claude-code-swarm 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +22 -1
- package/.claude-plugin/run-agent-inbox-mcp.sh +76 -0
- package/.claude-plugin/run-minimem-mcp.sh +98 -0
- package/.claude-plugin/run-opentasks-mcp.sh +65 -0
- package/CLAUDE.md +200 -36
- package/README.md +65 -0
- package/e2e/helpers/cleanup.mjs +17 -3
- package/e2e/helpers/map-mock-server.mjs +201 -25
- package/e2e/helpers/sidecar.mjs +222 -0
- package/e2e/helpers/workspace.mjs +2 -1
- package/e2e/tier5-sidecar-inbox.test.mjs +900 -0
- package/e2e/tier6-inbox-mcp.test.mjs +173 -0
- package/e2e/tier6-live-agent.test.mjs +759 -0
- package/e2e/vitest.config.e2e.mjs +1 -1
- package/hooks/hooks.json +15 -8
- package/package.json +13 -1
- package/references/agent-inbox/CLAUDE.md +151 -0
- package/references/agent-inbox/README.md +238 -0
- package/references/agent-inbox/docs/CLAUDE-CODE-SWARM-PROPOSAL.md +137 -0
- package/references/agent-inbox/docs/DESIGN.md +1156 -0
- package/references/agent-inbox/hooks/inbox-hook.mjs +119 -0
- package/references/agent-inbox/hooks/register-hook.mjs +69 -0
- package/references/agent-inbox/package-lock.json +3347 -0
- package/references/agent-inbox/package.json +58 -0
- package/references/agent-inbox/rules/agent-inbox.md +78 -0
- package/references/agent-inbox/src/federation/address.ts +61 -0
- package/references/agent-inbox/src/federation/connection-manager.ts +573 -0
- package/references/agent-inbox/src/federation/delivery-queue.ts +222 -0
- package/references/agent-inbox/src/federation/index.ts +6 -0
- package/references/agent-inbox/src/federation/routing-engine.ts +188 -0
- package/references/agent-inbox/src/federation/trust.ts +71 -0
- package/references/agent-inbox/src/index.ts +390 -0
- package/references/agent-inbox/src/ipc/ipc-server.ts +207 -0
- package/references/agent-inbox/src/jsonrpc/mail-server.ts +382 -0
- package/references/agent-inbox/src/map/map-client.ts +414 -0
- package/references/agent-inbox/src/mcp/mcp-server.ts +272 -0
- package/references/agent-inbox/src/mesh/delivery-bridge.ts +110 -0
- package/references/agent-inbox/src/mesh/mesh-connector.ts +41 -0
- package/references/agent-inbox/src/mesh/mesh-transport.ts +157 -0
- package/references/agent-inbox/src/mesh/type-mapper.ts +239 -0
- package/references/agent-inbox/src/push/notifier.ts +233 -0
- package/references/agent-inbox/src/registry/warm-registry.ts +255 -0
- package/references/agent-inbox/src/router/message-router.ts +175 -0
- package/references/agent-inbox/src/storage/interface.ts +48 -0
- package/references/agent-inbox/src/storage/memory.ts +145 -0
- package/references/agent-inbox/src/storage/sqlite.ts +671 -0
- package/references/agent-inbox/src/traceability/traceability.ts +183 -0
- package/references/agent-inbox/src/types.ts +303 -0
- package/references/agent-inbox/test/federation/address.test.ts +101 -0
- package/references/agent-inbox/test/federation/connection-manager.test.ts +546 -0
- package/references/agent-inbox/test/federation/delivery-queue.test.ts +159 -0
- package/references/agent-inbox/test/federation/integration.test.ts +857 -0
- package/references/agent-inbox/test/federation/routing-engine.test.ts +117 -0
- package/references/agent-inbox/test/federation/sdk-integration.test.ts +744 -0
- package/references/agent-inbox/test/federation/trust.test.ts +89 -0
- package/references/agent-inbox/test/ipc-jsonrpc.test.ts +113 -0
- package/references/agent-inbox/test/ipc-server.test.ts +197 -0
- package/references/agent-inbox/test/mail-server.test.ts +285 -0
- package/references/agent-inbox/test/map-client.test.ts +408 -0
- package/references/agent-inbox/test/mesh/delivery-bridge.test.ts +178 -0
- package/references/agent-inbox/test/mesh/e2e-mesh.test.ts +527 -0
- package/references/agent-inbox/test/mesh/e2e-real-meshpeer.test.ts +629 -0
- package/references/agent-inbox/test/mesh/federation-mesh.test.ts +269 -0
- package/references/agent-inbox/test/mesh/mesh-connector.test.ts +66 -0
- package/references/agent-inbox/test/mesh/mesh-transport.test.ts +191 -0
- package/references/agent-inbox/test/mesh/meshpeer-integration.test.ts +442 -0
- package/references/agent-inbox/test/mesh/mock-mesh.ts +125 -0
- package/references/agent-inbox/test/mesh/mock-meshpeer.ts +266 -0
- package/references/agent-inbox/test/mesh/type-mapper.test.ts +226 -0
- package/references/agent-inbox/test/message-router.test.ts +184 -0
- package/references/agent-inbox/test/push-notifier.test.ts +139 -0
- package/references/agent-inbox/test/registry/warm-registry.test.ts +171 -0
- package/references/agent-inbox/test/sqlite-prefix.test.ts +192 -0
- package/references/agent-inbox/test/sqlite-storage.test.ts +243 -0
- package/references/agent-inbox/test/storage.test.ts +196 -0
- package/references/agent-inbox/test/traceability.test.ts +123 -0
- package/references/agent-inbox/test/wake.test.ts +330 -0
- package/references/agent-inbox/tsconfig.json +20 -0
- package/references/agent-inbox/tsup.config.ts +10 -0
- package/references/agent-inbox/vitest.config.ts +8 -0
- package/references/minimem/.claude/settings.json +7 -0
- package/references/minimem/.sudocode/issues.jsonl +18 -0
- package/references/minimem/.sudocode/specs.jsonl +1 -0
- package/references/minimem/CLAUDE.md +329 -0
- package/references/minimem/README.md +565 -0
- package/references/minimem/claude-plugin/.claude-plugin/plugin.json +10 -0
- package/references/minimem/claude-plugin/.mcp.json +7 -0
- package/references/minimem/claude-plugin/README.md +158 -0
- package/references/minimem/claude-plugin/commands/recall.md +47 -0
- package/references/minimem/claude-plugin/commands/remember.md +41 -0
- package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +272 -0
- package/references/minimem/claude-plugin/hooks/hooks.json +27 -0
- package/references/minimem/claude-plugin/hooks/session-end.sh +86 -0
- package/references/minimem/claude-plugin/hooks/session-start.sh +85 -0
- package/references/minimem/claude-plugin/skills/memory/SKILL.md +108 -0
- package/references/minimem/media/banner.png +0 -0
- package/references/minimem/package-lock.json +5373 -0
- package/references/minimem/package.json +76 -0
- package/references/minimem/scripts/postbuild.js +49 -0
- package/references/minimem/src/__tests__/edge-cases.test.ts +371 -0
- package/references/minimem/src/__tests__/errors.test.ts +265 -0
- package/references/minimem/src/__tests__/helpers.ts +199 -0
- package/references/minimem/src/__tests__/internal.test.ts +407 -0
- package/references/minimem/src/__tests__/knowledge-frontmatter.test.ts +148 -0
- package/references/minimem/src/__tests__/knowledge.test.ts +148 -0
- package/references/minimem/src/__tests__/minimem.integration.test.ts +1127 -0
- package/references/minimem/src/__tests__/session.test.ts +190 -0
- package/references/minimem/src/cli/__tests__/commands.test.ts +760 -0
- package/references/minimem/src/cli/__tests__/contained-layout.test.ts +286 -0
- package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +141 -0
- package/references/minimem/src/cli/commands/append.ts +76 -0
- package/references/minimem/src/cli/commands/config.ts +262 -0
- package/references/minimem/src/cli/commands/conflicts.ts +415 -0
- package/references/minimem/src/cli/commands/daemon.ts +169 -0
- package/references/minimem/src/cli/commands/index.ts +12 -0
- package/references/minimem/src/cli/commands/init.ts +166 -0
- package/references/minimem/src/cli/commands/mcp.ts +221 -0
- package/references/minimem/src/cli/commands/push-pull.ts +213 -0
- package/references/minimem/src/cli/commands/search.ts +223 -0
- package/references/minimem/src/cli/commands/status.ts +84 -0
- package/references/minimem/src/cli/commands/store.ts +189 -0
- package/references/minimem/src/cli/commands/sync-init.ts +290 -0
- package/references/minimem/src/cli/commands/sync.ts +70 -0
- package/references/minimem/src/cli/commands/upsert.ts +197 -0
- package/references/minimem/src/cli/config.ts +611 -0
- package/references/minimem/src/cli/index.ts +299 -0
- package/references/minimem/src/cli/shared.ts +189 -0
- package/references/minimem/src/cli/sync/__tests__/central.test.ts +152 -0
- package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +209 -0
- package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +118 -0
- package/references/minimem/src/cli/sync/__tests__/detection.test.ts +207 -0
- package/references/minimem/src/cli/sync/__tests__/integration.test.ts +476 -0
- package/references/minimem/src/cli/sync/__tests__/registry.test.ts +363 -0
- package/references/minimem/src/cli/sync/__tests__/state.test.ts +255 -0
- package/references/minimem/src/cli/sync/__tests__/validation.test.ts +193 -0
- package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +178 -0
- package/references/minimem/src/cli/sync/central.ts +292 -0
- package/references/minimem/src/cli/sync/conflicts.ts +205 -0
- package/references/minimem/src/cli/sync/daemon.ts +407 -0
- package/references/minimem/src/cli/sync/detection.ts +138 -0
- package/references/minimem/src/cli/sync/index.ts +107 -0
- package/references/minimem/src/cli/sync/operations.ts +373 -0
- package/references/minimem/src/cli/sync/registry.ts +279 -0
- package/references/minimem/src/cli/sync/state.ts +358 -0
- package/references/minimem/src/cli/sync/validation.ts +206 -0
- package/references/minimem/src/cli/sync/watcher.ts +237 -0
- package/references/minimem/src/cli/version.ts +34 -0
- package/references/minimem/src/core/index.ts +9 -0
- package/references/minimem/src/core/indexer.ts +628 -0
- package/references/minimem/src/core/searcher.ts +221 -0
- package/references/minimem/src/db/schema.ts +183 -0
- package/references/minimem/src/db/sqlite-vec.ts +24 -0
- package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +431 -0
- package/references/minimem/src/embeddings/batch-gemini.ts +392 -0
- package/references/minimem/src/embeddings/batch-openai.ts +409 -0
- package/references/minimem/src/embeddings/embeddings.ts +434 -0
- package/references/minimem/src/index.ts +132 -0
- package/references/minimem/src/internal.ts +299 -0
- package/references/minimem/src/minimem.ts +1291 -0
- package/references/minimem/src/search/__tests__/hybrid.test.ts +247 -0
- package/references/minimem/src/search/graph.ts +234 -0
- package/references/minimem/src/search/hybrid.ts +151 -0
- package/references/minimem/src/search/search.ts +256 -0
- package/references/minimem/src/server/__tests__/mcp.test.ts +347 -0
- package/references/minimem/src/server/__tests__/tools.test.ts +364 -0
- package/references/minimem/src/server/mcp.ts +326 -0
- package/references/minimem/src/server/tools.ts +720 -0
- package/references/minimem/src/session.ts +460 -0
- package/references/minimem/src/store/__tests__/manifest.test.ts +177 -0
- package/references/minimem/src/store/__tests__/materialize.test.ts +52 -0
- package/references/minimem/src/store/__tests__/store-graph.test.ts +228 -0
- package/references/minimem/src/store/index.ts +27 -0
- package/references/minimem/src/store/manifest.ts +203 -0
- package/references/minimem/src/store/materialize.ts +185 -0
- package/references/minimem/src/store/store-graph.ts +252 -0
- package/references/minimem/tsconfig.json +19 -0
- package/references/minimem/tsup.config.ts +26 -0
- package/references/minimem/vitest.config.ts +29 -0
- package/references/openteams/src/cli/generate.ts +23 -1
- package/references/openteams/src/generators/agent-prompt-generator.test.ts +94 -0
- package/references/openteams/src/generators/agent-prompt-generator.ts +42 -13
- package/references/openteams/src/generators/package-generator.ts +9 -1
- package/references/openteams/src/generators/skill-generator.test.ts +28 -0
- package/references/openteams/src/generators/skill-generator.ts +10 -4
- package/references/skill-tree/.claude/settings.json +6 -0
- package/references/skill-tree/.sudocode/issues.jsonl +19 -0
- package/references/skill-tree/.sudocode/specs.jsonl +3 -0
- package/references/skill-tree/CLAUDE.md +132 -0
- package/references/skill-tree/README.md +396 -0
- package/references/skill-tree/docs/GAPS_v1.md +221 -0
- package/references/skill-tree/docs/INTEGRATION_PLAN.md +467 -0
- package/references/skill-tree/docs/TODOS.md +91 -0
- package/references/skill-tree/docs/anthropic_skill_guide.md +1364 -0
- package/references/skill-tree/docs/design/federated-skill-trees.md +524 -0
- package/references/skill-tree/docs/design/multi-agent-sync.md +759 -0
- package/references/skill-tree/docs/scraper/BRAINSTORM.md +583 -0
- package/references/skill-tree/docs/scraper/POC_PLAN.md +420 -0
- package/references/skill-tree/docs/scraper/README.md +170 -0
- package/references/skill-tree/examples/basic-usage.ts +157 -0
- package/references/skill-tree/package-lock.json +1852 -0
- package/references/skill-tree/package.json +66 -0
- package/references/skill-tree/plan.md +78 -0
- package/references/skill-tree/scraper/README.md +123 -0
- package/references/skill-tree/scraper/docs/DESIGN.md +683 -0
- package/references/skill-tree/scraper/docs/PLAN.md +336 -0
- package/references/skill-tree/scraper/drizzle.config.ts +10 -0
- package/references/skill-tree/scraper/package-lock.json +6329 -0
- package/references/skill-tree/scraper/package.json +68 -0
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +7 -0
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +7 -0
- package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +27 -0
- package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +21 -0
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +54 -0
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +24 -0
- package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +93 -0
- package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +22 -0
- package/references/skill-tree/scraper/tsup.config.ts +14 -0
- package/references/skill-tree/scraper/vitest.config.ts +17 -0
- package/references/skill-tree/scripts/convert-to-vitest.ts +166 -0
- package/references/skill-tree/skills/skill-writer/SKILL.md +339 -0
- package/references/skill-tree/skills/skill-writer/references/examples.md +326 -0
- package/references/skill-tree/skills/skill-writer/references/patterns.md +210 -0
- package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +123 -0
- package/references/skill-tree/test/run-all.ts +106 -0
- package/references/skill-tree/test/utils.ts +128 -0
- package/references/skill-tree/vitest.config.ts +16 -0
- package/references/swarmkit/src/commands/init/phases/configure.ts +0 -22
- package/references/swarmkit/src/commands/init/phases/global-setup.ts +5 -3
- package/references/swarmkit/src/commands/init/wizard.ts +2 -2
- package/references/swarmkit/src/packages/setup.test.ts +53 -7
- package/references/swarmkit/src/packages/setup.ts +37 -1
- package/scripts/bootstrap.mjs +26 -1
- package/scripts/generate-agents.mjs +5 -1
- package/scripts/map-hook.mjs +97 -64
- package/scripts/map-sidecar.mjs +179 -25
- package/scripts/team-loader.mjs +12 -41
- package/skills/swarm/SKILL.md +89 -25
- package/src/__tests__/agent-generator.test.mjs +6 -13
- package/src/__tests__/bootstrap.test.mjs +124 -1
- package/src/__tests__/config.test.mjs +200 -27
- package/src/__tests__/e2e-live-map.test.mjs +536 -0
- package/src/__tests__/e2e-mesh-sidecar.test.mjs +570 -0
- package/src/__tests__/e2e-native-task-hooks.test.mjs +376 -0
- package/src/__tests__/e2e-sidecar-bridge.test.mjs +477 -0
- package/src/__tests__/helpers.mjs +13 -0
- package/src/__tests__/inbox.test.mjs +22 -89
- package/src/__tests__/index.test.mjs +35 -9
- package/src/__tests__/integration.test.mjs +513 -0
- package/src/__tests__/map-events.test.mjs +514 -150
- package/src/__tests__/mesh-connection.test.mjs +308 -0
- package/src/__tests__/opentasks-client.test.mjs +517 -0
- package/src/__tests__/paths.test.mjs +185 -41
- package/src/__tests__/sidecar-client.test.mjs +35 -0
- package/src/__tests__/sidecar-server.test.mjs +124 -0
- package/src/__tests__/skilltree-client.test.mjs +80 -0
- package/src/agent-generator.mjs +104 -33
- package/src/bootstrap.mjs +150 -10
- package/src/config.mjs +81 -17
- package/src/context-output.mjs +58 -8
- package/src/inbox.mjs +9 -54
- package/src/index.mjs +39 -8
- package/src/map-connection.mjs +4 -3
- package/src/map-events.mjs +350 -80
- package/src/mesh-connection.mjs +148 -0
- package/src/opentasks-client.mjs +269 -0
- package/src/paths.mjs +182 -27
- package/src/sessionlog.mjs +14 -9
- package/src/sidecar-client.mjs +81 -27
- package/src/sidecar-server.mjs +175 -16
- package/src/skilltree-client.mjs +173 -0
- package/src/template.mjs +68 -4
- package/vitest.config.mjs +1 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import { InMemoryStorage } from "./storage/memory.js";
|
|
5
|
+
import { SqliteStorage } from "./storage/sqlite.js";
|
|
6
|
+
import { MessageRouter } from "./router/message-router.js";
|
|
7
|
+
import { TraceabilityLayer } from "./traceability/traceability.js";
|
|
8
|
+
import { IpcServer } from "./ipc/ipc-server.js";
|
|
9
|
+
import { MapClient } from "./map/map-client.js";
|
|
10
|
+
import { InboxMcpServer } from "./mcp/mcp-server.js";
|
|
11
|
+
import { MailJsonRpcServer } from "./jsonrpc/mail-server.js";
|
|
12
|
+
import { PushNotifier } from "./push/notifier.js";
|
|
13
|
+
import { ConnectionManager } from "./federation/connection-manager.js";
|
|
14
|
+
import { MeshConnector } from "./mesh/mesh-connector.js";
|
|
15
|
+
import { DeliveryBridge } from "./mesh/delivery-bridge.js";
|
|
16
|
+
import type { MeshContextLike } from "./mesh/mesh-transport.js";
|
|
17
|
+
import type { MeshPeerLike, MeshMapServer } from "./map/map-client.js";
|
|
18
|
+
import { WarmRegistry } from "./registry/warm-registry.js";
|
|
19
|
+
import type { InboxConfig } from "./types.js";
|
|
20
|
+
import type { Storage } from "./storage/interface.js";
|
|
21
|
+
|
|
22
|
+
export { InMemoryStorage } from "./storage/memory.js";
|
|
23
|
+
export { SqliteStorage } from "./storage/sqlite.js";
|
|
24
|
+
export { MessageRouter, normalizeContent } from "./router/message-router.js";
|
|
25
|
+
export { TraceabilityLayer } from "./traceability/traceability.js";
|
|
26
|
+
export { IpcServer } from "./ipc/ipc-server.js";
|
|
27
|
+
export { MapClient } from "./map/map-client.js";
|
|
28
|
+
export { InboxMcpServer } from "./mcp/mcp-server.js";
|
|
29
|
+
export { MailJsonRpcServer } from "./jsonrpc/mail-server.js";
|
|
30
|
+
export { PushNotifier, formatInboxMarkdown, parseCommand } from "./push/notifier.js";
|
|
31
|
+
export type { InboxMessageEvent, NotifierConfig, InboxFileEntry } from "./push/notifier.js";
|
|
32
|
+
export { ConnectionManager } from "./federation/connection-manager.js";
|
|
33
|
+
export type { DeliveryResult, IncomingMessageHandler } from "./federation/connection-manager.js";
|
|
34
|
+
export type { MapConnection, MapAgentConnectionClass, IncomingMapMessage } from "./map/map-client.js";
|
|
35
|
+
export { WarmRegistry } from "./registry/warm-registry.js";
|
|
36
|
+
export { RoutingEngine } from "./federation/routing-engine.js";
|
|
37
|
+
export { DeliveryQueue } from "./federation/delivery-queue.js";
|
|
38
|
+
export { TrustManager } from "./federation/trust.js";
|
|
39
|
+
export {
|
|
40
|
+
parseAddress,
|
|
41
|
+
formatAddress,
|
|
42
|
+
isRemoteAddress,
|
|
43
|
+
isBroadcastAddress,
|
|
44
|
+
} from "./federation/address.js";
|
|
45
|
+
export { MeshTransport, DEFAULT_CHANNEL_NAME } from "./mesh/mesh-transport.js";
|
|
46
|
+
export type { MeshContextLike, MeshChannel, MeshPeerInfo, InboxWireMessage } from "./mesh/mesh-transport.js";
|
|
47
|
+
export { MeshConnector } from "./mesh/mesh-connector.js";
|
|
48
|
+
export { DeliveryBridge } from "./mesh/delivery-bridge.js";
|
|
49
|
+
export type { MeshDeliveryHandler } from "./mesh/delivery-bridge.js";
|
|
50
|
+
export { mapMessageToInbox, inboxMessageToMap } from "./mesh/type-mapper.js";
|
|
51
|
+
export type { MapMessage as MeshMapMessage, MapAddress as MeshMapAddress } from "./mesh/type-mapper.js";
|
|
52
|
+
export type { MeshPeerLike, MeshAgentConnection, MeshMapServer } from "./map/map-client.js";
|
|
53
|
+
export type * from "./types.js";
|
|
54
|
+
export type { Storage, InboxQuery, ThreadQuery } from "./storage/interface.js";
|
|
55
|
+
|
|
56
|
+
function defaultSocketPath(): string {
|
|
57
|
+
const home = os.homedir();
|
|
58
|
+
return path.join(home, ".claude", "agent-inbox", "inbox.sock");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function defaultInboxDir(): string {
|
|
62
|
+
const home = os.homedir();
|
|
63
|
+
return path.join(home, ".claude", "agent-inbox", "inboxes");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function defaultSqlitePath(): string {
|
|
67
|
+
const home = os.homedir();
|
|
68
|
+
return path.join(home, ".claude", "agent-inbox", "inbox.db");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function loadConfig(): InboxConfig {
|
|
72
|
+
return {
|
|
73
|
+
socketPath: process.env.INBOX_SOCKET_PATH ?? defaultSocketPath(),
|
|
74
|
+
scope: process.env.INBOX_SCOPE ?? "default",
|
|
75
|
+
map: {
|
|
76
|
+
enabled: process.env.INBOX_MAP_ENABLED === "true",
|
|
77
|
+
server: process.env.INBOX_MAP_SERVER,
|
|
78
|
+
scope: process.env.INBOX_MAP_SCOPE ?? process.env.INBOX_SCOPE ?? "default",
|
|
79
|
+
systemId: process.env.INBOX_MAP_SYSTEM_ID ?? "agent-inbox",
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface AgentInbox {
|
|
85
|
+
storage: Storage;
|
|
86
|
+
router: MessageRouter;
|
|
87
|
+
traceability: TraceabilityLayer;
|
|
88
|
+
ipcServer: IpcServer;
|
|
89
|
+
mapClient: MapClient;
|
|
90
|
+
jsonRpc: MailJsonRpcServer;
|
|
91
|
+
notifier: PushNotifier;
|
|
92
|
+
federation: ConnectionManager | null;
|
|
93
|
+
registry: WarmRegistry | null;
|
|
94
|
+
events: EventEmitter;
|
|
95
|
+
stop(): Promise<void>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface CreateOptions {
|
|
99
|
+
config?: Partial<InboxConfig>;
|
|
100
|
+
/** Use SQLite storage at this path (":memory:" for in-memory SQLite) */
|
|
101
|
+
sqlitePath?: string;
|
|
102
|
+
/** Use an external better-sqlite3 Database handle (co-locate tables in another DB) */
|
|
103
|
+
sqliteDb?: import("better-sqlite3").Database;
|
|
104
|
+
/** Table name prefix when co-locating in an external DB (e.g. "inbox_") */
|
|
105
|
+
sqlitePrefix?: string;
|
|
106
|
+
/** HTTP port for JSON-RPC endpoint (0 = disabled) */
|
|
107
|
+
httpPort?: number;
|
|
108
|
+
/** Webhook URLs for push notifications */
|
|
109
|
+
webhooks?: string[];
|
|
110
|
+
/** Enable federation with peer systems */
|
|
111
|
+
enableFederation?: boolean;
|
|
112
|
+
/** Use an externally-managed MAP connection instead of creating one.
|
|
113
|
+
* When provided, Agent Inbox borrows this connection for messaging
|
|
114
|
+
* but does not own its lifecycle (won't disconnect it on stop()). */
|
|
115
|
+
connection?: import("./map/map-client.js").MapConnection;
|
|
116
|
+
/** Phase 1: agentic-mesh context for P2P federation transport.
|
|
117
|
+
* When provided, federation peers with meshPeerId use encrypted
|
|
118
|
+
* mesh channels instead of WebSocket MAP connections. */
|
|
119
|
+
mesh?: {
|
|
120
|
+
context: MeshContextLike;
|
|
121
|
+
localPeerId: string;
|
|
122
|
+
channelName?: string;
|
|
123
|
+
};
|
|
124
|
+
/** Phase 2: Full MeshPeer integration.
|
|
125
|
+
* When provided, agent-inbox registers as an agent on the MeshPeer's
|
|
126
|
+
* MapServer, uses FederationGateway for cross-mesh routing, and
|
|
127
|
+
* installs a DeliveryHandler bridge for incoming messages.
|
|
128
|
+
* Supersedes `mesh` option — if both are set, meshPeer takes priority. */
|
|
129
|
+
meshPeer?: MeshPeerLike;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export async function createAgentInbox(
|
|
133
|
+
opts: CreateOptions = {}
|
|
134
|
+
): Promise<AgentInbox> {
|
|
135
|
+
const config = { ...loadConfig(), ...opts.config };
|
|
136
|
+
|
|
137
|
+
// 1. Storage — SQLite (own file, external DB, or in-memory fallback)
|
|
138
|
+
let storage: Storage;
|
|
139
|
+
if (opts.sqliteDb) {
|
|
140
|
+
storage = new SqliteStorage({
|
|
141
|
+
db: opts.sqliteDb,
|
|
142
|
+
prefix: opts.sqlitePrefix,
|
|
143
|
+
});
|
|
144
|
+
} else if (opts.sqlitePath) {
|
|
145
|
+
storage = new SqliteStorage({
|
|
146
|
+
path: opts.sqlitePath,
|
|
147
|
+
prefix: opts.sqlitePrefix,
|
|
148
|
+
});
|
|
149
|
+
} else {
|
|
150
|
+
storage = new InMemoryStorage();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 2. Event bus (internal)
|
|
154
|
+
const events = new EventEmitter();
|
|
155
|
+
|
|
156
|
+
// 3. Message router
|
|
157
|
+
const router = new MessageRouter(storage, events, config.scope);
|
|
158
|
+
|
|
159
|
+
// 4. Traceability layer (subscribes to message.created events)
|
|
160
|
+
const traceability = new TraceabilityLayer(storage, events);
|
|
161
|
+
|
|
162
|
+
// 5. Push notifier (per-agent inbox files + webhooks + event emission)
|
|
163
|
+
const notifier = new PushNotifier(
|
|
164
|
+
{ inboxDir: defaultInboxDir(), webhooks: opts.webhooks },
|
|
165
|
+
storage,
|
|
166
|
+
events
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// 6. MAP client (connects first to obtain SDK class for federation)
|
|
170
|
+
const mapClient = new MapClient(
|
|
171
|
+
storage,
|
|
172
|
+
router,
|
|
173
|
+
events,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// Phase 2: MeshPeer integration (if provided)
|
|
177
|
+
if (opts.meshPeer) {
|
|
178
|
+
const meshSystemId = await mapClient.connectViaMesh(opts.meshPeer);
|
|
179
|
+
|
|
180
|
+
// Install DeliveryHandler bridge on the MeshPeer's MapServer
|
|
181
|
+
const server = opts.meshPeer.server as MeshMapServer & {
|
|
182
|
+
setDeliveryHandler?(handler: unknown): unknown;
|
|
183
|
+
};
|
|
184
|
+
if (typeof server.setDeliveryHandler === "function") {
|
|
185
|
+
// Get the current handler, then replace with our bridge that delegates back
|
|
186
|
+
const prev = server.setDeliveryHandler(
|
|
187
|
+
new DeliveryBridge(storage, events, config.scope)
|
|
188
|
+
);
|
|
189
|
+
if (prev) {
|
|
190
|
+
// Re-install with the previous handler as fallback
|
|
191
|
+
server.setDeliveryHandler(
|
|
192
|
+
new DeliveryBridge(
|
|
193
|
+
storage,
|
|
194
|
+
events,
|
|
195
|
+
config.scope,
|
|
196
|
+
prev as import("./mesh/delivery-bridge.js").MeshDeliveryHandler
|
|
197
|
+
)
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
console.error(`Connected to MeshPeer (systemId: ${meshSystemId})`);
|
|
203
|
+
} else if (opts.connection) {
|
|
204
|
+
// External connection — borrow it, don't manage its lifecycle
|
|
205
|
+
mapClient.useConnection(opts.connection);
|
|
206
|
+
} else if (config.map?.enabled) {
|
|
207
|
+
const connected = await mapClient.connect(config.map);
|
|
208
|
+
if (connected) {
|
|
209
|
+
// Replay missed messages from MAP server
|
|
210
|
+
const replayed = await mapClient.replayMissed();
|
|
211
|
+
if (replayed > 0) {
|
|
212
|
+
console.error(`Replayed ${replayed} missed messages from MAP server`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// 7. Registry + Federation (optional)
|
|
218
|
+
let federation: ConnectionManager | null = null;
|
|
219
|
+
let registry: WarmRegistry | null = null;
|
|
220
|
+
|
|
221
|
+
const needsRegistry = opts.enableFederation || config.federation?.peers?.length;
|
|
222
|
+
|
|
223
|
+
if (needsRegistry) {
|
|
224
|
+
registry = new WarmRegistry(storage, events, config.federation?.registry);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (opts.enableFederation || config.federation?.peers?.length) {
|
|
228
|
+
const sdkClass = mapClient.getAgentConnectionClass() ?? undefined;
|
|
229
|
+
|
|
230
|
+
let meshConnector: MeshConnector | undefined;
|
|
231
|
+
if (opts.mesh) {
|
|
232
|
+
meshConnector = new MeshConnector(
|
|
233
|
+
opts.mesh.context,
|
|
234
|
+
opts.mesh.localPeerId,
|
|
235
|
+
opts.mesh.channelName
|
|
236
|
+
);
|
|
237
|
+
} else if (opts.meshPeer) {
|
|
238
|
+
// Phase 2: Derive mesh context from MeshPeer if available
|
|
239
|
+
const peerObj = opts.meshPeer as MeshPeerLike & { mesh?: MeshContextLike };
|
|
240
|
+
if (peerObj.mesh) {
|
|
241
|
+
meshConnector = new MeshConnector(
|
|
242
|
+
peerObj.mesh,
|
|
243
|
+
opts.meshPeer.peerId
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
federation = new ConnectionManager(events, config.federation, {
|
|
249
|
+
sdkClass,
|
|
250
|
+
meshConnector,
|
|
251
|
+
meshPeer: opts.meshPeer,
|
|
252
|
+
onIncomingMessage: ({ from, peerId, payload, meta }) => {
|
|
253
|
+
// Delegate incoming federation messages to the router.
|
|
254
|
+
// The targetAgent in meta tells us which local agent this is for.
|
|
255
|
+
const targetAgent = (meta?.targetAgent as string) ?? from;
|
|
256
|
+
router.routeMessage({
|
|
257
|
+
from: `${from}@${peerId}`,
|
|
258
|
+
to: targetAgent,
|
|
259
|
+
payload,
|
|
260
|
+
scope: meta?.scope as string | undefined,
|
|
261
|
+
subject: meta?.subject as string | undefined,
|
|
262
|
+
importance: meta?.importance as "high" | "normal" | undefined,
|
|
263
|
+
threadTag: meta?.threadTag as string | undefined,
|
|
264
|
+
inReplyTo: meta?.inReplyTo as string | undefined,
|
|
265
|
+
metadata: meta,
|
|
266
|
+
}).catch((err) => {
|
|
267
|
+
console.error(
|
|
268
|
+
`Failed to route incoming federation message from ${from}@${peerId}: ${err instanceof Error ? err.message : err}`
|
|
269
|
+
);
|
|
270
|
+
});
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
router.setFederation(federation);
|
|
274
|
+
|
|
275
|
+
// Tier 2 system ID resolution: update from MAP or MeshPeer systemInfo
|
|
276
|
+
const mapSystemName = mapClient.getSystemName();
|
|
277
|
+
if (mapSystemName) {
|
|
278
|
+
federation.updateSystemIdFromMap(mapSystemName);
|
|
279
|
+
} else if (opts.meshPeer) {
|
|
280
|
+
federation.updateSystemIdFromMap(opts.meshPeer.server.systemId);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Connect to configured federation peers
|
|
284
|
+
if (config.federation?.peers) {
|
|
285
|
+
for (const peer of config.federation.peers) {
|
|
286
|
+
try {
|
|
287
|
+
await federation.federate(peer);
|
|
288
|
+
const via = peer.meshPeerId ? `mesh:${peer.meshPeerId}` : peer.url;
|
|
289
|
+
console.error(`Federated with peer: ${peer.systemId} (${via})`);
|
|
290
|
+
} catch (err) {
|
|
291
|
+
console.error(
|
|
292
|
+
`Failed to federate with ${peer.systemId}: ${err instanceof Error ? err.message : err}`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Start delivery queue tick timer
|
|
299
|
+
federation.queue.startTicking();
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// 8. JSON-RPC server (mail/* methods)
|
|
303
|
+
const jsonRpc = new MailJsonRpcServer(storage, router, events);
|
|
304
|
+
if (opts.httpPort && opts.httpPort > 0) {
|
|
305
|
+
await jsonRpc.startHttp(opts.httpPort);
|
|
306
|
+
console.error(`JSON-RPC HTTP server listening on port ${opts.httpPort}`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// 9. IPC server (UNIX socket — handles both NDJSON commands and JSON-RPC inline)
|
|
310
|
+
const socketPath = config.socketPath ?? defaultSocketPath();
|
|
311
|
+
const ipcServer = new IpcServer(socketPath, router, storage, jsonRpc);
|
|
312
|
+
await ipcServer.start();
|
|
313
|
+
|
|
314
|
+
const stop = async () => {
|
|
315
|
+
await ipcServer.stop();
|
|
316
|
+
await jsonRpc.stopHttp();
|
|
317
|
+
await mapClient.disconnect();
|
|
318
|
+
if (federation) await federation.destroy();
|
|
319
|
+
if (registry) registry.destroy();
|
|
320
|
+
if ("close" in storage && typeof storage.close === "function") {
|
|
321
|
+
(storage as SqliteStorage).close();
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
return {
|
|
326
|
+
storage,
|
|
327
|
+
router,
|
|
328
|
+
traceability,
|
|
329
|
+
ipcServer,
|
|
330
|
+
mapClient,
|
|
331
|
+
jsonRpc,
|
|
332
|
+
notifier,
|
|
333
|
+
federation,
|
|
334
|
+
registry,
|
|
335
|
+
events,
|
|
336
|
+
stop,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// CLI entry point
|
|
341
|
+
const isMainModule =
|
|
342
|
+
process.argv[1] &&
|
|
343
|
+
(process.argv[1].endsWith("/index.js") ||
|
|
344
|
+
process.argv[1].endsWith("/index.ts"));
|
|
345
|
+
|
|
346
|
+
if (isMainModule) {
|
|
347
|
+
const mode = process.argv[2] ?? "ipc";
|
|
348
|
+
|
|
349
|
+
if (mode === "mcp") {
|
|
350
|
+
// MCP-only mode (stdio transport for Claude Code integration)
|
|
351
|
+
const config = loadConfig();
|
|
352
|
+
const sqlitePath = process.env.INBOX_SQLITE_PATH;
|
|
353
|
+
const storage: Storage = sqlitePath
|
|
354
|
+
? new SqliteStorage({ path: sqlitePath })
|
|
355
|
+
: new InMemoryStorage();
|
|
356
|
+
const events = new EventEmitter();
|
|
357
|
+
const router = new MessageRouter(storage, events, config.scope);
|
|
358
|
+
const _traceability = new TraceabilityLayer(storage, events);
|
|
359
|
+
const mcpServer = new InboxMcpServer(router, storage, config.scope);
|
|
360
|
+
mcpServer.start().catch((err) => {
|
|
361
|
+
console.error("MCP server failed:", err);
|
|
362
|
+
process.exit(1);
|
|
363
|
+
});
|
|
364
|
+
} else {
|
|
365
|
+
// IPC server mode (default)
|
|
366
|
+
const httpPort = process.env.INBOX_HTTP_PORT
|
|
367
|
+
? parseInt(process.env.INBOX_HTTP_PORT, 10)
|
|
368
|
+
: 0;
|
|
369
|
+
const sqlitePath = process.env.INBOX_SQLITE_PATH;
|
|
370
|
+
|
|
371
|
+
createAgentInbox({ httpPort, sqlitePath })
|
|
372
|
+
.then((inbox) => {
|
|
373
|
+
console.error(
|
|
374
|
+
`Agent Inbox IPC server listening on ${process.env.INBOX_SOCKET_PATH ?? defaultSocketPath()}`
|
|
375
|
+
);
|
|
376
|
+
process.on("SIGINT", async () => {
|
|
377
|
+
await inbox.stop();
|
|
378
|
+
process.exit(0);
|
|
379
|
+
});
|
|
380
|
+
process.on("SIGTERM", async () => {
|
|
381
|
+
await inbox.stop();
|
|
382
|
+
process.exit(0);
|
|
383
|
+
});
|
|
384
|
+
})
|
|
385
|
+
.catch((err) => {
|
|
386
|
+
console.error("Failed to start Agent Inbox:", err);
|
|
387
|
+
process.exit(1);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import * as net from "node:net";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import type {
|
|
5
|
+
IpcCommand,
|
|
6
|
+
IpcResponse,
|
|
7
|
+
Agent,
|
|
8
|
+
} from "../types.js";
|
|
9
|
+
import type { Storage } from "../storage/interface.js";
|
|
10
|
+
import type { MessageRouter } from "../router/message-router.js";
|
|
11
|
+
import type { MailJsonRpcServer } from "../jsonrpc/mail-server.js";
|
|
12
|
+
|
|
13
|
+
export class IpcServer {
|
|
14
|
+
private server: net.Server | null = null;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
private socketPath: string,
|
|
18
|
+
private router: MessageRouter,
|
|
19
|
+
private storage: Storage,
|
|
20
|
+
private jsonRpc?: MailJsonRpcServer
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
async start(): Promise<void> {
|
|
24
|
+
// Clean up stale socket file
|
|
25
|
+
try {
|
|
26
|
+
fs.unlinkSync(this.socketPath);
|
|
27
|
+
} catch {
|
|
28
|
+
// Doesn't exist, fine
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Ensure directory exists
|
|
32
|
+
const dir = path.dirname(this.socketPath);
|
|
33
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
34
|
+
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
this.server = net.createServer((conn) => this.handleConnection(conn));
|
|
37
|
+
this.server.on("error", reject);
|
|
38
|
+
this.server.listen(this.socketPath, () => resolve());
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async stop(): Promise<void> {
|
|
43
|
+
return new Promise((resolve) => {
|
|
44
|
+
if (!this.server) return resolve();
|
|
45
|
+
this.server.close(() => {
|
|
46
|
+
try {
|
|
47
|
+
fs.unlinkSync(this.socketPath);
|
|
48
|
+
} catch {
|
|
49
|
+
// Already gone
|
|
50
|
+
}
|
|
51
|
+
resolve();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private handleConnection(conn: net.Socket): void {
|
|
57
|
+
let buffer = "";
|
|
58
|
+
|
|
59
|
+
conn.on("data", (data) => {
|
|
60
|
+
buffer += data.toString();
|
|
61
|
+
// Process complete lines (NDJSON)
|
|
62
|
+
let newlineIdx: number;
|
|
63
|
+
while ((newlineIdx = buffer.indexOf("\n")) !== -1) {
|
|
64
|
+
const line = buffer.slice(0, newlineIdx).trim();
|
|
65
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
66
|
+
if (!line) continue;
|
|
67
|
+
|
|
68
|
+
this.processLine(line)
|
|
69
|
+
.then((response) => {
|
|
70
|
+
conn.write(JSON.stringify(response) + "\n");
|
|
71
|
+
})
|
|
72
|
+
.catch((err) => {
|
|
73
|
+
conn.write(
|
|
74
|
+
JSON.stringify({ ok: false, error: String(err) }) + "\n"
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
conn.on("error", () => {
|
|
81
|
+
// Client disconnected, ignore
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private async processLine(line: string): Promise<IpcResponse | object> {
|
|
86
|
+
let parsed: Record<string, unknown>;
|
|
87
|
+
try {
|
|
88
|
+
parsed = JSON.parse(line) as Record<string, unknown>;
|
|
89
|
+
} catch {
|
|
90
|
+
return { ok: false, error: "Invalid JSON" };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Detect JSON-RPC requests (have "jsonrpc" field) vs IPC commands (have "action" field)
|
|
94
|
+
if (parsed.jsonrpc === "2.0" && typeof parsed.method === "string") {
|
|
95
|
+
if (this.jsonRpc) {
|
|
96
|
+
return this.jsonRpc.handleRequest(
|
|
97
|
+
parsed as { jsonrpc: "2.0"; id?: string | number | null; method: string; params?: Record<string, unknown> }
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return { jsonrpc: "2.0", id: parsed.id ?? null, error: { code: -32603, message: "JSON-RPC not configured" } };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return this.handleCommand(parsed as unknown as IpcCommand);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async handleCommand(command: IpcCommand): Promise<IpcResponse> {
|
|
107
|
+
switch (command.action) {
|
|
108
|
+
case "ping":
|
|
109
|
+
return { ok: true, pid: process.pid };
|
|
110
|
+
|
|
111
|
+
case "send":
|
|
112
|
+
return this.handleSend(command);
|
|
113
|
+
|
|
114
|
+
case "notify":
|
|
115
|
+
return this.handleNotify(command);
|
|
116
|
+
|
|
117
|
+
case "check_inbox":
|
|
118
|
+
return this.handleCheckInbox(command);
|
|
119
|
+
|
|
120
|
+
case "emit":
|
|
121
|
+
// For Phase 1, emit is acknowledged but not forwarded to MAP
|
|
122
|
+
return { ok: true };
|
|
123
|
+
|
|
124
|
+
default:
|
|
125
|
+
return { ok: false, error: `Unknown action: ${(command as { action: string }).action}` };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private async handleSend(
|
|
130
|
+
command: Extract<IpcCommand, { action: "send" }>
|
|
131
|
+
): Promise<IpcResponse> {
|
|
132
|
+
try {
|
|
133
|
+
const message = await this.router.routeMessage({
|
|
134
|
+
from: command.from,
|
|
135
|
+
to: command.to,
|
|
136
|
+
payload: command.payload,
|
|
137
|
+
scope: command.scope,
|
|
138
|
+
threadTag: command.threadTag,
|
|
139
|
+
inReplyTo: command.inReplyTo,
|
|
140
|
+
importance: command.importance,
|
|
141
|
+
metadata: command.meta,
|
|
142
|
+
});
|
|
143
|
+
return { ok: true, messageId: message.id };
|
|
144
|
+
} catch (err) {
|
|
145
|
+
return { ok: false, error: String(err) };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private handleCheckInbox(
|
|
150
|
+
command: Extract<IpcCommand, { action: "check_inbox" }>
|
|
151
|
+
): IpcResponse {
|
|
152
|
+
const agentId = command.agentId ?? command.scope ?? "default";
|
|
153
|
+
const messages = this.storage.getInbox(agentId, {
|
|
154
|
+
unreadOnly: command.unreadOnly,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Mark messages as read
|
|
158
|
+
if (command.clear) {
|
|
159
|
+
const now = new Date().toISOString();
|
|
160
|
+
for (const msg of messages) {
|
|
161
|
+
for (const r of msg.recipients) {
|
|
162
|
+
if (r.agent_id === agentId && !r.read_at) {
|
|
163
|
+
r.read_at = now;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
this.storage.putMessage(msg);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return { ok: true, messages };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private handleNotify(
|
|
174
|
+
command: Extract<IpcCommand, { action: "notify" }>
|
|
175
|
+
): IpcResponse {
|
|
176
|
+
const event = command.event;
|
|
177
|
+
|
|
178
|
+
if (event.type === "agent.spawn" && event.agent) {
|
|
179
|
+
const now = new Date().toISOString();
|
|
180
|
+
const agent: Agent = {
|
|
181
|
+
agent_id: event.agent.agentId,
|
|
182
|
+
display_name: event.agent.name,
|
|
183
|
+
scope: event.agent.scopes?.[0] ?? "default",
|
|
184
|
+
status: "active",
|
|
185
|
+
metadata: event.agent.metadata ?? {},
|
|
186
|
+
registered_at: now,
|
|
187
|
+
last_active_at: now,
|
|
188
|
+
};
|
|
189
|
+
this.storage.putAgent(agent);
|
|
190
|
+
return { ok: true };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (event.type === "agent.done") {
|
|
194
|
+
const agentId = event.agentId ?? event.agent?.agentId;
|
|
195
|
+
if (agentId) {
|
|
196
|
+
const agent = this.storage.getAgent(agentId);
|
|
197
|
+
if (agent) {
|
|
198
|
+
agent.status = "offline";
|
|
199
|
+
this.storage.putAgent(agent);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return { ok: true };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return { ok: true };
|
|
206
|
+
}
|
|
207
|
+
}
|