Reduce swarm local persistence

This commit is contained in:
2026-04-04 03:37:55 +08:00
parent eb96764770
commit f65baebb3c
7 changed files with 83 additions and 334 deletions

View File

@@ -15,7 +15,6 @@ import { PermissionModeSchema } from '../entrypoints/sdk/coreSchemas.js'
import { SEND_MESSAGE_TOOL_NAME } from '../tools/SendMessageTool/constants.js'
import type { Message } from '../types/message.js'
import { generateRequestId } from './agentId.js'
import { count } from './array.js'
import { logForDebugging } from './debug.js'
import { getTeamsDir } from './envUtils.js'
import { getErrnoCode } from './errors.js'
@@ -192,8 +191,8 @@ export async function writeToMailbox(
}
/**
* Mark a specific message in a teammate's inbox as read by index
* Uses file locking to prevent race conditions
* Remove a specific processed message from a teammate's inbox by index.
* Uses file locking to prevent race conditions.
* @param agentName - The agent name to mark message as read for
* @param teamName - Optional team name
* @param messageIndex - Index of the message to mark as read
@@ -242,11 +241,17 @@ export async function markMessageAsReadByIndex(
return
}
messages[messageIndex] = { ...message, read: true }
const updatedMessages = messages.filter(
(currentMessage, index) => index !== messageIndex && !currentMessage.read,
)
await writeFile(inboxPath, jsonStringify(messages, null, 2), 'utf-8')
await writeFile(
inboxPath,
jsonStringify(updatedMessages, null, 2),
'utf-8',
)
logForDebugging(
`[TeammateMailbox] markMessageAsReadByIndex: marked message at index ${messageIndex} as read`,
`[TeammateMailbox] markMessageAsReadByIndex: removed message at index ${messageIndex} from inbox`,
)
} catch (error) {
const code = getErrnoCode(error)
@@ -270,77 +275,6 @@ export async function markMessageAsReadByIndex(
}
}
/**
* Mark all messages in a teammate's inbox as read
* Uses file locking to prevent race conditions
* @param agentName - The agent name to mark messages as read for
* @param teamName - Optional team name
*/
export async function markMessagesAsRead(
agentName: string,
teamName?: string,
): Promise<void> {
const inboxPath = getInboxPath(agentName, teamName)
logForDebugging(
`[TeammateMailbox] markMessagesAsRead called: agentName=${agentName}, teamName=${teamName}, path=${inboxPath}`,
)
const lockFilePath = `${inboxPath}.lock`
let release: (() => Promise<void>) | undefined
try {
logForDebugging(`[TeammateMailbox] markMessagesAsRead: acquiring lock...`)
release = await lockfile.lock(inboxPath, {
lockfilePath: lockFilePath,
...LOCK_OPTIONS,
})
logForDebugging(`[TeammateMailbox] markMessagesAsRead: lock acquired`)
// Re-read messages after acquiring lock to get the latest state
const messages = await readMailbox(agentName, teamName)
logForDebugging(
`[TeammateMailbox] markMessagesAsRead: read ${messages.length} messages after lock`,
)
if (messages.length === 0) {
logForDebugging(
`[TeammateMailbox] markMessagesAsRead: no messages to mark`,
)
return
}
const unreadCount = count(messages, m => !m.read)
logForDebugging(
`[TeammateMailbox] markMessagesAsRead: ${unreadCount} unread of ${messages.length} total`,
)
// messages comes from jsonParse — fresh, unshared objects safe to mutate
for (const m of messages) m.read = true
await writeFile(inboxPath, jsonStringify(messages, null, 2), 'utf-8')
logForDebugging(
`[TeammateMailbox] markMessagesAsRead: WROTE ${unreadCount} message(s) as read to ${inboxPath}`,
)
} catch (error) {
const code = getErrnoCode(error)
if (code === 'ENOENT') {
logForDebugging(
`[TeammateMailbox] markMessagesAsRead: file does not exist at ${inboxPath}`,
)
return
}
logForDebugging(
`[TeammateMailbox] markMessagesAsRead FAILED for ${agentName}: ${error}`,
)
logError(error)
} finally {
if (release) {
await release()
logForDebugging(`[TeammateMailbox] markMessagesAsRead: lock released`)
}
}
}
/**
* Clear a teammate's inbox (delete all messages)
* @param agentName - The agent name to clear inbox for
@@ -1095,8 +1029,8 @@ export function isStructuredProtocolMessage(messageText: string): boolean {
}
/**
* Marks only messages matching a predicate as read, leaving others unread.
* Uses the same file-locking mechanism as markMessagesAsRead.
* Removes only messages matching a predicate, leaving the rest unread.
* Uses the same file-locking mechanism as the other mailbox update helpers.
*/
export async function markMessagesAsReadByPredicate(
agentName: string,
@@ -1119,8 +1053,8 @@ export async function markMessagesAsReadByPredicate(
return
}
const updatedMessages = messages.map(m =>
!m.read && predicate(m) ? { ...m, read: true } : m,
const updatedMessages = messages.filter(
m => !m.read && !predicate(m),
)
await writeFile(inboxPath, jsonStringify(updatedMessages, null, 2), 'utf-8')