( agentName: string, predicate: (msg: TeammateMessage) => boolean, teamName?: string, )
| 1099 | * Uses the same file-locking mechanism as markMessagesAsRead. |
| 1100 | */ |
| 1101 | export async function markMessagesAsReadByPredicate( |
| 1102 | agentName: string, |
| 1103 | predicate: (msg: TeammateMessage) => boolean, |
| 1104 | teamName?: string, |
| 1105 | ): Promise<void> { |
| 1106 | const inboxPath = getInboxPath(agentName, teamName) |
| 1107 | |
| 1108 | const lockFilePath = `${inboxPath}.lock` |
| 1109 | let release: (() => Promise<void>) | undefined |
| 1110 | |
| 1111 | try { |
| 1112 | release = await lockfile.lock(inboxPath, { |
| 1113 | lockfilePath: lockFilePath, |
| 1114 | ...LOCK_OPTIONS, |
| 1115 | }) |
| 1116 | |
| 1117 | const messages = await readMailbox(agentName, teamName) |
| 1118 | if (messages.length === 0) { |
| 1119 | return |
| 1120 | } |
| 1121 | |
| 1122 | const updatedMessages = messages.map(m => |
| 1123 | !m.read && predicate(m) ? { ...m, read: true } : m, |
| 1124 | ) |
| 1125 | |
| 1126 | await writeFile(inboxPath, jsonStringify(updatedMessages, null, 2), 'utf-8') |
| 1127 | } catch (error) { |
| 1128 | const code = getErrnoCode(error) |
| 1129 | if (code === 'ENOENT') { |
| 1130 | return |
| 1131 | } |
| 1132 | logError(error) |
| 1133 | } finally { |
| 1134 | if (release) { |
| 1135 | try { |
| 1136 | await release() |
| 1137 | } catch { |
| 1138 | // Lock may have already been released |
| 1139 | } |
| 1140 | } |
| 1141 | } |
| 1142 | } |
| 1143 | |
| 1144 | /** |
| 1145 | * Extracts a "[to {name}] {summary}" string from the last assistant message |
no test coverage detected