macro-agent 0.2.5 → 0.2.6
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/LICENSE +1 -1
- package/README.md +30 -56
- package/dist/acp/websocket-server.d.ts +6 -0
- package/dist/acp/websocket-server.d.ts.map +1 -1
- package/dist/acp/websocket-server.js +13 -0
- package/dist/acp/websocket-server.js.map +1 -1
- package/dist/acp/websocket-stream.d.ts +30 -0
- package/dist/acp/websocket-stream.d.ts.map +1 -0
- package/dist/acp/websocket-stream.js +118 -0
- package/dist/acp/websocket-stream.js.map +1 -0
- package/dist/activity/deduplication.d.ts +85 -0
- package/dist/activity/deduplication.d.ts.map +1 -0
- package/dist/activity/deduplication.js +149 -0
- package/dist/activity/deduplication.js.map +1 -0
- package/dist/activity/index.d.ts +16 -0
- package/dist/activity/index.d.ts.map +1 -0
- package/dist/activity/index.js +17 -0
- package/dist/activity/index.js.map +1 -0
- package/dist/activity/relevance.d.ts +81 -0
- package/dist/activity/relevance.d.ts.map +1 -0
- package/dist/activity/relevance.js +161 -0
- package/dist/activity/relevance.js.map +1 -0
- package/dist/activity/types.d.ts +169 -0
- package/dist/activity/types.d.ts.map +1 -0
- package/dist/activity/types.js +33 -0
- package/dist/activity/types.js.map +1 -0
- package/dist/activity/watcher.d.ts +64 -0
- package/dist/activity/watcher.d.ts.map +1 -0
- package/dist/activity/watcher.js +212 -0
- package/dist/activity/watcher.js.map +1 -0
- package/dist/adapters/federation.d.ts +8 -1
- package/dist/adapters/federation.d.ts.map +1 -1
- package/dist/adapters/federation.js +33 -2
- package/dist/adapters/federation.js.map +1 -1
- package/dist/agent/agent-manager-v2.d.ts.map +1 -1
- package/dist/agent/agent-manager-v2.js +7 -24
- package/dist/agent/agent-manager-v2.js.map +1 -1
- package/dist/agent/wake.d.ts +85 -0
- package/dist/agent/wake.d.ts.map +1 -0
- package/dist/agent/wake.js +278 -0
- package/dist/agent/wake.js.map +1 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +41 -25
- package/dist/api/server.js.map +1 -1
- package/dist/api/types.d.ts +6 -0
- package/dist/api/types.d.ts.map +1 -1
- package/dist/auth/server-auth.d.ts +43 -0
- package/dist/auth/server-auth.d.ts.map +1 -0
- package/dist/auth/server-auth.js +80 -0
- package/dist/auth/server-auth.js.map +1 -0
- package/dist/auth/token.d.ts +4 -0
- package/dist/auth/token.d.ts.map +1 -1
- package/dist/auth/token.js +7 -6
- package/dist/auth/token.js.map +1 -1
- package/dist/boot-v2.d.ts +6 -3
- package/dist/boot-v2.d.ts.map +1 -1
- package/dist/boot-v2.js +44 -25
- package/dist/boot-v2.js.map +1 -1
- package/dist/cognitive/team-lifecycle.d.ts +82 -0
- package/dist/cognitive/team-lifecycle.d.ts.map +1 -0
- package/dist/cognitive/team-lifecycle.js +121 -0
- package/dist/cognitive/team-lifecycle.js.map +1 -0
- package/dist/cognitive/trajectory-extractor.d.ts +25 -0
- package/dist/cognitive/trajectory-extractor.d.ts.map +1 -0
- package/dist/cognitive/trajectory-extractor.js +134 -0
- package/dist/cognitive/trajectory-extractor.js.map +1 -0
- package/dist/control/control-server.d.ts.map +1 -1
- package/dist/control/control-server.js +10 -0
- package/dist/control/control-server.js.map +1 -1
- package/dist/dispatch/mail-inbound-consumer.d.ts.map +1 -1
- package/dist/dispatch/mail-inbound-consumer.js +43 -10
- package/dist/dispatch/mail-inbound-consumer.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/handlers/generic.d.ts +27 -0
- package/dist/lifecycle/handlers/generic.d.ts.map +1 -0
- package/dist/lifecycle/handlers/generic.js +56 -0
- package/dist/lifecycle/handlers/generic.js.map +1 -0
- package/dist/lifecycle/handlers/index.d.ts +51 -0
- package/dist/lifecycle/handlers/index.d.ts.map +1 -0
- package/dist/lifecycle/handlers/index.js +110 -0
- package/dist/lifecycle/handlers/index.js.map +1 -0
- package/dist/lifecycle/handlers/integrator.d.ts +81 -0
- package/dist/lifecycle/handlers/integrator.d.ts.map +1 -0
- package/dist/lifecycle/handlers/integrator.js +451 -0
- package/dist/lifecycle/handlers/integrator.js.map +1 -0
- package/dist/lifecycle/handlers/monitor.d.ts +29 -0
- package/dist/lifecycle/handlers/monitor.d.ts.map +1 -0
- package/dist/lifecycle/handlers/monitor.js +79 -0
- package/dist/lifecycle/handlers/monitor.js.map +1 -0
- package/dist/lifecycle/handlers/worker.d.ts +56 -0
- package/dist/lifecycle/handlers/worker.d.ts.map +1 -0
- package/dist/lifecycle/handlers/worker.js +381 -0
- package/dist/lifecycle/handlers/worker.js.map +1 -0
- package/dist/lifecycle/handlers-v2.d.ts +0 -2
- package/dist/lifecycle/handlers-v2.d.ts.map +1 -1
- package/dist/lifecycle/handlers-v2.js +4 -55
- package/dist/lifecycle/handlers-v2.js.map +1 -1
- package/dist/mail/conversation-map.d.ts +33 -0
- package/dist/mail/conversation-map.d.ts.map +1 -0
- package/dist/mail/conversation-map.js +61 -0
- package/dist/mail/conversation-map.js.map +1 -0
- package/dist/mail/index.d.ts +11 -0
- package/dist/mail/index.d.ts.map +1 -0
- package/dist/mail/index.js +11 -0
- package/dist/mail/index.js.map +1 -0
- package/dist/mail/mail-service.d.ts +85 -0
- package/dist/mail/mail-service.d.ts.map +1 -0
- package/dist/mail/mail-service.js +121 -0
- package/dist/mail/mail-service.js.map +1 -0
- package/dist/mail/stores/eventstore-conversation-store.d.ts +40 -0
- package/dist/mail/stores/eventstore-conversation-store.d.ts.map +1 -0
- package/dist/mail/stores/eventstore-conversation-store.js +131 -0
- package/dist/mail/stores/eventstore-conversation-store.js.map +1 -0
- package/dist/mail/stores/eventstore-participant-store.d.ts +43 -0
- package/dist/mail/stores/eventstore-participant-store.d.ts.map +1 -0
- package/dist/mail/stores/eventstore-participant-store.js +145 -0
- package/dist/mail/stores/eventstore-participant-store.js.map +1 -0
- package/dist/mail/stores/eventstore-thread-store.d.ts +46 -0
- package/dist/mail/stores/eventstore-thread-store.d.ts.map +1 -0
- package/dist/mail/stores/eventstore-thread-store.js +118 -0
- package/dist/mail/stores/eventstore-thread-store.js.map +1 -0
- package/dist/mail/stores/eventstore-turn-store.d.ts +47 -0
- package/dist/mail/stores/eventstore-turn-store.d.ts.map +1 -0
- package/dist/mail/stores/eventstore-turn-store.js +153 -0
- package/dist/mail/stores/eventstore-turn-store.js.map +1 -0
- package/dist/mail/stores/index.d.ts +12 -0
- package/dist/mail/stores/index.d.ts.map +1 -0
- package/dist/mail/stores/index.js +12 -0
- package/dist/mail/stores/index.js.map +1 -0
- package/dist/mail/stores/types.d.ts +146 -0
- package/dist/mail/stores/types.d.ts.map +1 -0
- package/dist/mail/stores/types.js +13 -0
- package/dist/mail/stores/types.js.map +1 -0
- package/dist/mail/turn-recorder.d.ts +30 -0
- package/dist/mail/turn-recorder.d.ts.map +1 -0
- package/dist/mail/turn-recorder.js +98 -0
- package/dist/mail/turn-recorder.js.map +1 -0
- package/dist/map/adapter/acp-over-map.d.ts +115 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -0
- package/dist/map/adapter/acp-over-map.js +1024 -0
- package/dist/map/adapter/acp-over-map.js.map +1 -0
- package/dist/map/adapter/connection-manager.d.ts +150 -0
- package/dist/map/adapter/connection-manager.d.ts.map +1 -0
- package/dist/map/adapter/connection-manager.js +207 -0
- package/dist/map/adapter/connection-manager.js.map +1 -0
- package/dist/map/adapter/event-log.d.ts +87 -0
- package/dist/map/adapter/event-log.d.ts.map +1 -0
- package/dist/map/adapter/event-log.js +122 -0
- package/dist/map/adapter/event-log.js.map +1 -0
- package/dist/map/adapter/event-translator.d.ts +85 -0
- package/dist/map/adapter/event-translator.d.ts.map +1 -0
- package/dist/map/adapter/event-translator.js +295 -0
- package/dist/map/adapter/event-translator.js.map +1 -0
- package/dist/map/adapter/extensions/agent-detection.d.ts +49 -0
- package/dist/map/adapter/extensions/agent-detection.d.ts.map +1 -0
- package/dist/map/adapter/extensions/agent-detection.js +91 -0
- package/dist/map/adapter/extensions/agent-detection.js.map +1 -0
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
- package/dist/map/adapter/extensions/cognitive.d.ts +27 -0
- package/dist/map/adapter/extensions/cognitive.d.ts.map +1 -0
- package/dist/map/adapter/extensions/cognitive.js +158 -0
- package/dist/map/adapter/extensions/cognitive.js.map +1 -0
- package/dist/map/adapter/extensions/index.d.ts +95 -0
- package/dist/map/adapter/extensions/index.d.ts.map +1 -0
- package/dist/map/adapter/extensions/index.js +228 -0
- package/dist/map/adapter/extensions/index.js.map +1 -0
- package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
- package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
- package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
- package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
- package/dist/map/adapter/extensions/resume.d.ts +47 -0
- package/dist/map/adapter/extensions/resume.d.ts.map +1 -0
- package/dist/map/adapter/extensions/resume.js +59 -0
- package/dist/map/adapter/extensions/resume.js.map +1 -0
- package/dist/map/adapter/extensions/streams.d.ts +95 -0
- package/dist/map/adapter/extensions/streams.d.ts.map +1 -0
- package/dist/map/adapter/extensions/streams.js +515 -0
- package/dist/map/adapter/extensions/streams.js.map +1 -0
- package/dist/map/adapter/extensions/task.d.ts +40 -0
- package/dist/map/adapter/extensions/task.d.ts.map +1 -0
- package/dist/map/adapter/extensions/task.js +197 -0
- package/dist/map/adapter/extensions/task.js.map +1 -0
- package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
- package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
- package/dist/map/adapter/extensions/update-metadata.js +67 -0
- package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
- package/dist/map/adapter/extensions/wake.d.ts +60 -0
- package/dist/map/adapter/extensions/wake.d.ts.map +1 -0
- package/dist/map/adapter/extensions/wake.js +144 -0
- package/dist/map/adapter/extensions/wake.js.map +1 -0
- package/dist/map/adapter/extensions/workspace-files.d.ts +42 -0
- package/dist/map/adapter/extensions/workspace-files.d.ts.map +1 -0
- package/dist/map/adapter/extensions/workspace-files.js +338 -0
- package/dist/map/adapter/extensions/workspace-files.js.map +1 -0
- package/dist/map/adapter/extensions/workspace.d.ts +57 -0
- package/dist/map/adapter/extensions/workspace.d.ts.map +1 -0
- package/dist/map/adapter/extensions/workspace.js +81 -0
- package/dist/map/adapter/extensions/workspace.js.map +1 -0
- package/dist/map/adapter/index.d.ts +20 -0
- package/dist/map/adapter/index.d.ts.map +1 -0
- package/dist/map/adapter/index.js +40 -0
- package/dist/map/adapter/index.js.map +1 -0
- package/dist/map/adapter/interface.d.ts +450 -0
- package/dist/map/adapter/interface.d.ts.map +1 -0
- package/dist/map/adapter/interface.js +24 -0
- package/dist/map/adapter/interface.js.map +1 -0
- package/dist/map/adapter/mail-handler-adapter.d.ts +27 -0
- package/dist/map/adapter/mail-handler-adapter.d.ts.map +1 -0
- package/dist/map/adapter/mail-handler-adapter.js +292 -0
- package/dist/map/adapter/mail-handler-adapter.js.map +1 -0
- package/dist/map/adapter/map-adapter.d.ts +200 -0
- package/dist/map/adapter/map-adapter.d.ts.map +1 -0
- package/dist/map/adapter/map-adapter.js +1199 -0
- package/dist/map/adapter/map-adapter.js.map +1 -0
- package/dist/map/adapter/rpc-handler.d.ts +263 -0
- package/dist/map/adapter/rpc-handler.d.ts.map +1 -0
- package/dist/map/adapter/rpc-handler.js +365 -0
- package/dist/map/adapter/rpc-handler.js.map +1 -0
- package/dist/map/adapter/subscription-manager.d.ts +174 -0
- package/dist/map/adapter/subscription-manager.d.ts.map +1 -0
- package/dist/map/adapter/subscription-manager.js +248 -0
- package/dist/map/adapter/subscription-manager.js.map +1 -0
- package/dist/map/adapter/types.d.ts +194 -0
- package/dist/map/adapter/types.d.ts.map +1 -0
- package/dist/map/adapter/types.js +27 -0
- package/dist/map/adapter/types.js.map +1 -0
- package/dist/map/adapter/websocket-integration.d.ts +113 -0
- package/dist/map/adapter/websocket-integration.d.ts.map +1 -0
- package/dist/map/adapter/websocket-integration.js +134 -0
- package/dist/map/adapter/websocket-integration.js.map +1 -0
- package/dist/map/cascade-action-handler.d.ts.map +1 -1
- package/dist/map/cascade-action-handler.js +19 -5
- package/dist/map/cascade-action-handler.js.map +1 -1
- package/dist/map/federation/envelope.d.ts +98 -0
- package/dist/map/federation/envelope.d.ts.map +1 -0
- package/dist/map/federation/envelope.js +160 -0
- package/dist/map/federation/envelope.js.map +1 -0
- package/dist/map/federation/federation-handler.d.ts +50 -0
- package/dist/map/federation/federation-handler.d.ts.map +1 -0
- package/dist/map/federation/federation-handler.js +306 -0
- package/dist/map/federation/federation-handler.js.map +1 -0
- package/dist/map/federation/index.d.ts +14 -0
- package/dist/map/federation/index.d.ts.map +1 -0
- package/dist/map/federation/index.js +13 -0
- package/dist/map/federation/index.js.map +1 -0
- package/dist/map/federation/types.d.ts +239 -0
- package/dist/map/federation/types.d.ts.map +1 -0
- package/dist/map/federation/types.js +23 -0
- package/dist/map/federation/types.js.map +1 -0
- package/dist/map/server.d.ts.map +1 -1
- package/dist/map/server.js +17 -2
- package/dist/map/server.js.map +1 -1
- package/dist/map/types.d.ts +6 -0
- package/dist/map/types.d.ts.map +1 -1
- package/dist/mcp/map-client.d.ts +39 -0
- package/dist/mcp/map-client.d.ts.map +1 -0
- package/dist/mcp/map-client.js +129 -0
- package/dist/mcp/map-client.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +72 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -0
- package/dist/mcp/mcp-server.js +1027 -0
- package/dist/mcp/mcp-server.js.map +1 -0
- package/dist/mcp/tools/claim_task.d.ts +35 -0
- package/dist/mcp/tools/claim_task.d.ts.map +1 -0
- package/dist/mcp/tools/claim_task.js +58 -0
- package/dist/mcp/tools/claim_task.js.map +1 -0
- package/dist/mcp/tools/done-v2.d.ts +0 -1
- package/dist/mcp/tools/done-v2.d.ts.map +1 -1
- package/dist/mcp/tools/done-v2.js +0 -1
- package/dist/mcp/tools/done-v2.js.map +1 -1
- package/dist/mcp/tools/done.d.ts +102 -0
- package/dist/mcp/tools/done.d.ts.map +1 -0
- package/dist/mcp/tools/done.js +253 -0
- package/dist/mcp/tools/done.js.map +1 -0
- package/dist/mcp/tools/inject_context.d.ts +61 -0
- package/dist/mcp/tools/inject_context.d.ts.map +1 -0
- package/dist/mcp/tools/inject_context.js +123 -0
- package/dist/mcp/tools/inject_context.js.map +1 -0
- package/dist/mcp/tools/list_claimable_tasks.d.ts +38 -0
- package/dist/mcp/tools/list_claimable_tasks.d.ts.map +1 -0
- package/dist/mcp/tools/list_claimable_tasks.js +63 -0
- package/dist/mcp/tools/list_claimable_tasks.js.map +1 -0
- package/dist/mcp/tools/unclaim_task.d.ts +31 -0
- package/dist/mcp/tools/unclaim_task.d.ts.map +1 -0
- package/dist/mcp/tools/unclaim_task.js +47 -0
- package/dist/mcp/tools/unclaim_task.js.map +1 -0
- package/dist/mcp/tools/wait_for_activity.d.ts +60 -0
- package/dist/mcp/tools/wait_for_activity.d.ts.map +1 -0
- package/dist/mcp/tools/wait_for_activity.js +135 -0
- package/dist/mcp/tools/wait_for_activity.js.map +1 -0
- package/dist/monitor/health-check-service.d.ts +143 -0
- package/dist/monitor/health-check-service.d.ts.map +1 -0
- package/dist/monitor/health-check-service.js +240 -0
- package/dist/monitor/health-check-service.js.map +1 -0
- package/dist/monitor/index.d.ts +14 -0
- package/dist/monitor/index.d.ts.map +1 -0
- package/dist/monitor/index.js +14 -0
- package/dist/monitor/index.js.map +1 -0
- package/dist/monitor/stall-detector.d.ts +109 -0
- package/dist/monitor/stall-detector.d.ts.map +1 -0
- package/dist/monitor/stall-detector.js +152 -0
- package/dist/monitor/stall-detector.js.map +1 -0
- package/dist/peer/capability-manager.d.ts +56 -0
- package/dist/peer/capability-manager.d.ts.map +1 -0
- package/dist/peer/capability-manager.js +186 -0
- package/dist/peer/capability-manager.js.map +1 -0
- package/dist/peer/encapsulation-manager.d.ts +190 -0
- package/dist/peer/encapsulation-manager.d.ts.map +1 -0
- package/dist/peer/encapsulation-manager.js +486 -0
- package/dist/peer/encapsulation-manager.js.map +1 -0
- package/dist/peer/federation-manager.d.ts +223 -0
- package/dist/peer/federation-manager.d.ts.map +1 -0
- package/dist/peer/federation-manager.js +528 -0
- package/dist/peer/federation-manager.js.map +1 -0
- package/dist/peer/hierarchy-errors.d.ts +208 -0
- package/dist/peer/hierarchy-errors.d.ts.map +1 -0
- package/dist/peer/hierarchy-errors.js +268 -0
- package/dist/peer/hierarchy-errors.js.map +1 -0
- package/dist/peer/hierarchy-protocol.d.ts +159 -0
- package/dist/peer/hierarchy-protocol.d.ts.map +1 -0
- package/dist/peer/hierarchy-protocol.js +142 -0
- package/dist/peer/hierarchy-protocol.js.map +1 -0
- package/dist/peer/index.d.ts +15 -0
- package/dist/peer/index.d.ts.map +1 -0
- package/dist/peer/index.js +15 -0
- package/dist/peer/index.js.map +1 -0
- package/dist/peer/peer-manager.d.ts +99 -0
- package/dist/peer/peer-manager.d.ts.map +1 -0
- package/dist/peer/peer-manager.js +333 -0
- package/dist/peer/peer-manager.js.map +1 -0
- package/dist/peer/task-delegation.d.ts +189 -0
- package/dist/peer/task-delegation.d.ts.map +1 -0
- package/dist/peer/task-delegation.js +303 -0
- package/dist/peer/task-delegation.js.map +1 -0
- package/dist/peer/transports/index.d.ts +8 -0
- package/dist/peer/transports/index.d.ts.map +1 -0
- package/dist/peer/transports/index.js +8 -0
- package/dist/peer/transports/index.js.map +1 -0
- package/dist/peer/transports/local-transport.d.ts +56 -0
- package/dist/peer/transports/local-transport.d.ts.map +1 -0
- package/dist/peer/transports/local-transport.js +263 -0
- package/dist/peer/transports/local-transport.js.map +1 -0
- package/dist/peer/transports/websocket-transport.d.ts +86 -0
- package/dist/peer/transports/websocket-transport.d.ts.map +1 -0
- package/dist/peer/transports/websocket-transport.js +338 -0
- package/dist/peer/transports/websocket-transport.js.map +1 -0
- package/dist/peer/types.d.ts +268 -0
- package/dist/peer/types.d.ts.map +1 -0
- package/dist/peer/types.js +36 -0
- package/dist/peer/types.js.map +1 -0
- package/dist/router/address-resolver.d.ts +102 -0
- package/dist/router/address-resolver.d.ts.map +1 -0
- package/dist/router/address-resolver.js +198 -0
- package/dist/router/address-resolver.js.map +1 -0
- package/dist/router/broadcast.d.ts +53 -0
- package/dist/router/broadcast.d.ts.map +1 -0
- package/dist/router/broadcast.js +75 -0
- package/dist/router/broadcast.js.map +1 -0
- package/dist/router/channels.d.ts +148 -0
- package/dist/router/channels.d.ts.map +1 -0
- package/dist/router/channels.js +126 -0
- package/dist/router/channels.js.map +1 -0
- package/dist/router/index.d.ts +21 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +18 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/message-router.d.ts +197 -0
- package/dist/router/message-router.d.ts.map +1 -0
- package/dist/router/message-router.js +903 -0
- package/dist/router/message-router.js.map +1 -0
- package/dist/router/message-types.d.ts +183 -0
- package/dist/router/message-types.d.ts.map +1 -0
- package/dist/router/message-types.js +79 -0
- package/dist/router/message-types.js.map +1 -0
- package/dist/router/role-resolver.d.ts +67 -0
- package/dist/router/role-resolver.d.ts.map +1 -0
- package/dist/router/role-resolver.js +106 -0
- package/dist/router/role-resolver.js.map +1 -0
- package/dist/router/signals.d.ts +253 -0
- package/dist/router/signals.d.ts.map +1 -0
- package/dist/router/signals.js +53 -0
- package/dist/router/signals.js.map +1 -0
- package/dist/router/types.d.ts +191 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +34 -0
- package/dist/router/types.js.map +1 -0
- package/dist/router/wake.d.ts +111 -0
- package/dist/router/wake.d.ts.map +1 -0
- package/dist/router/wake.js +180 -0
- package/dist/router/wake.js.map +1 -0
- package/dist/server/combined-server.d.ts +95 -0
- package/dist/server/combined-server.d.ts.map +1 -0
- package/dist/server/combined-server.js +335 -0
- package/dist/server/combined-server.js.map +1 -0
- package/dist/steering/index.d.ts +11 -0
- package/dist/steering/index.d.ts.map +1 -0
- package/dist/steering/index.js +11 -0
- package/dist/steering/index.js.map +1 -0
- package/dist/steering/inject.d.ts +39 -0
- package/dist/steering/inject.d.ts.map +1 -0
- package/dist/steering/inject.js +197 -0
- package/dist/steering/inject.js.map +1 -0
- package/dist/steering/types.d.ts +100 -0
- package/dist/steering/types.d.ts.map +1 -0
- package/dist/steering/types.js +11 -0
- package/dist/steering/types.js.map +1 -0
- package/dist/store/backends/index.d.ts +11 -0
- package/dist/store/backends/index.d.ts.map +1 -0
- package/dist/store/backends/index.js +15 -0
- package/dist/store/backends/index.js.map +1 -0
- package/dist/store/backends/json-backend.d.ts +23 -0
- package/dist/store/backends/json-backend.d.ts.map +1 -0
- package/dist/store/backends/json-backend.js +220 -0
- package/dist/store/backends/json-backend.js.map +1 -0
- package/dist/store/backends/memory-backend.d.ts +12 -0
- package/dist/store/backends/memory-backend.d.ts.map +1 -0
- package/dist/store/backends/memory-backend.js +205 -0
- package/dist/store/backends/memory-backend.js.map +1 -0
- package/dist/store/backends/sqlite-backend.d.ts +27 -0
- package/dist/store/backends/sqlite-backend.d.ts.map +1 -0
- package/dist/store/backends/sqlite-backend.js +231 -0
- package/dist/store/backends/sqlite-backend.js.map +1 -0
- package/dist/store/backends/tinybase-backend.d.ts +22 -0
- package/dist/store/backends/tinybase-backend.d.ts.map +1 -0
- package/dist/store/backends/tinybase-backend.js +203 -0
- package/dist/store/backends/tinybase-backend.js.map +1 -0
- package/dist/store/backends/types.d.ts +175 -0
- package/dist/store/backends/types.d.ts.map +1 -0
- package/dist/store/backends/types.js +28 -0
- package/dist/store/backends/types.js.map +1 -0
- package/dist/store/event-store.d.ts +128 -0
- package/dist/store/event-store.d.ts.map +1 -0
- package/dist/store/event-store.js +1751 -0
- package/dist/store/event-store.js.map +1 -0
- package/dist/store/instance.d.ts +290 -0
- package/dist/store/instance.d.ts.map +1 -0
- package/dist/store/instance.js +363 -0
- package/dist/store/instance.js.map +1 -0
- package/dist/store/migrations.d.ts +41 -0
- package/dist/store/migrations.d.ts.map +1 -0
- package/dist/store/migrations.js +79 -0
- package/dist/store/migrations.js.map +1 -0
- package/dist/store/test-utils.d.ts +63 -0
- package/dist/store/test-utils.d.ts.map +1 -0
- package/dist/store/test-utils.js +63 -0
- package/dist/store/test-utils.js.map +1 -0
- package/dist/store/types/config.d.ts +16 -0
- package/dist/store/types/config.d.ts.map +1 -0
- package/dist/store/types/config.js +8 -0
- package/dist/store/types/config.js.map +1 -0
- package/dist/store/types/conversations.d.ts +91 -0
- package/dist/store/types/conversations.d.ts.map +1 -0
- package/dist/store/types/conversations.js +8 -0
- package/dist/store/types/conversations.js.map +1 -0
- package/dist/store/types/sessions.d.ts +44 -0
- package/dist/store/types/sessions.d.ts.map +1 -0
- package/dist/store/types/sessions.js +9 -0
- package/dist/store/types/sessions.js.map +1 -0
- package/dist/store/types.d.ts +115 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +6 -0
- package/dist/store/types.js.map +1 -0
- package/dist/task/backend/index.d.ts +93 -0
- package/dist/task/backend/index.d.ts.map +1 -0
- package/dist/task/backend/index.js +178 -0
- package/dist/task/backend/index.js.map +1 -0
- package/dist/task/backend/memory.d.ts +70 -0
- package/dist/task/backend/memory.d.ts.map +1 -0
- package/dist/task/backend/memory.js +621 -0
- package/dist/task/backend/memory.js.map +1 -0
- package/dist/task/backend/opentasks/backend.d.ts +140 -0
- package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
- package/dist/task/backend/opentasks/backend.js +1023 -0
- package/dist/task/backend/opentasks/backend.js.map +1 -0
- package/dist/task/backend/opentasks/client.d.ts +337 -0
- package/dist/task/backend/opentasks/client.d.ts.map +1 -0
- package/dist/task/backend/opentasks/client.js +225 -0
- package/dist/task/backend/opentasks/client.js.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.js +195 -0
- package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
- package/dist/task/backend/opentasks/index.d.ts +21 -0
- package/dist/task/backend/opentasks/index.d.ts.map +1 -0
- package/dist/task/backend/opentasks/index.js +21 -0
- package/dist/task/backend/opentasks/index.js.map +1 -0
- package/dist/task/backend/opentasks/mapping.d.ts +48 -0
- package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
- package/dist/task/backend/opentasks/mapping.js +77 -0
- package/dist/task/backend/opentasks/mapping.js.map +1 -0
- package/dist/task/backend/sudocode/__tests__/integration/test-utils.d.ts +54 -0
- package/dist/task/backend/sudocode/__tests__/integration/test-utils.d.ts.map +1 -0
- package/dist/task/backend/sudocode/__tests__/integration/test-utils.js +88 -0
- package/dist/task/backend/sudocode/__tests__/integration/test-utils.js.map +1 -0
- package/dist/task/backend/sudocode/backend.d.ts +155 -0
- package/dist/task/backend/sudocode/backend.d.ts.map +1 -0
- package/dist/task/backend/sudocode/backend.js +942 -0
- package/dist/task/backend/sudocode/backend.js.map +1 -0
- package/dist/task/backend/sudocode/client.d.ts +303 -0
- package/dist/task/backend/sudocode/client.d.ts.map +1 -0
- package/dist/task/backend/sudocode/client.js +101 -0
- package/dist/task/backend/sudocode/client.js.map +1 -0
- package/dist/task/backend/sudocode/index.d.ts +19 -0
- package/dist/task/backend/sudocode/index.d.ts.map +1 -0
- package/dist/task/backend/sudocode/index.js +17 -0
- package/dist/task/backend/sudocode/index.js.map +1 -0
- package/dist/task/backend/sudocode/mapping.d.ts +51 -0
- package/dist/task/backend/sudocode/mapping.d.ts.map +1 -0
- package/dist/task/backend/sudocode/mapping.js +86 -0
- package/dist/task/backend/sudocode/mapping.js.map +1 -0
- package/dist/task/backend/sudocode/server-client.d.ts +56 -0
- package/dist/task/backend/sudocode/server-client.d.ts.map +1 -0
- package/dist/task/backend/sudocode/server-client.js +367 -0
- package/dist/task/backend/sudocode/server-client.js.map +1 -0
- package/dist/task/backend/sudocode/standalone-client.d.ts +91 -0
- package/dist/task/backend/sudocode/standalone-client.d.ts.map +1 -0
- package/dist/task/backend/sudocode/standalone-client.js +476 -0
- package/dist/task/backend/sudocode/standalone-client.js.map +1 -0
- package/dist/task/backend/sudocode/sync-policy.d.ts +166 -0
- package/dist/task/backend/sudocode/sync-policy.d.ts.map +1 -0
- package/dist/task/backend/sudocode/sync-policy.js +221 -0
- package/dist/task/backend/sudocode/sync-policy.js.map +1 -0
- package/dist/task/backend/sudocode/tools.d.ts +87 -0
- package/dist/task/backend/sudocode/tools.d.ts.map +1 -0
- package/dist/task/backend/sudocode/tools.js +743 -0
- package/dist/task/backend/sudocode/tools.js.map +1 -0
- package/dist/task/backend/tool-provider.d.ts +56 -0
- package/dist/task/backend/tool-provider.d.ts.map +1 -0
- package/dist/task/backend/tool-provider.js +424 -0
- package/dist/task/backend/tool-provider.js.map +1 -0
- package/dist/task/backend/types.d.ts +297 -0
- package/dist/task/backend/types.d.ts.map +1 -0
- package/dist/task/backend/types.js +27 -0
- package/dist/task/backend/types.js.map +1 -0
- package/dist/task/backend/unified-tool-provider.d.ts +57 -0
- package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
- package/dist/task/backend/unified-tool-provider.js +623 -0
- package/dist/task/backend/unified-tool-provider.js.map +1 -0
- package/dist/task/index.d.ts +7 -0
- package/dist/task/index.d.ts.map +1 -0
- package/dist/task/index.js +7 -0
- package/dist/task/index.js.map +1 -0
- package/dist/task/retry-policy.d.ts +89 -0
- package/dist/task/retry-policy.d.ts.map +1 -0
- package/dist/task/retry-policy.js +160 -0
- package/dist/task/retry-policy.js.map +1 -0
- package/dist/task/task-manager.d.ts +70 -0
- package/dist/task/task-manager.d.ts.map +1 -0
- package/dist/task/task-manager.js +319 -0
- package/dist/task/task-manager.js.map +1 -0
- package/dist/task/types.d.ts +72 -0
- package/dist/task/types.d.ts.map +1 -0
- package/dist/task/types.js +33 -0
- package/dist/task/types.js.map +1 -0
- package/dist/teams/team-loader.d.ts +2 -1
- package/dist/teams/team-loader.d.ts.map +1 -1
- package/dist/teams/team-loader.js +2 -1
- package/dist/teams/team-loader.js.map +1 -1
- package/dist/teams/team-manager.d.ts +101 -0
- package/dist/teams/team-manager.d.ts.map +1 -0
- package/dist/teams/team-manager.js +260 -0
- package/dist/teams/team-manager.js.map +1 -0
- package/dist/teams/team-runtime-v2.d.ts +0 -3
- package/dist/teams/team-runtime-v2.d.ts.map +1 -1
- package/dist/teams/team-runtime-v2.js +8 -87
- package/dist/teams/team-runtime-v2.js.map +1 -1
- package/dist/teams/team-runtime.d.ts +245 -0
- package/dist/teams/team-runtime.d.ts.map +1 -0
- package/dist/teams/team-runtime.js +1023 -0
- package/dist/teams/team-runtime.js.map +1 -0
- package/dist/trigger/router/index.d.ts +11 -0
- package/dist/trigger/router/index.d.ts.map +1 -0
- package/dist/trigger/router/index.js +10 -0
- package/dist/trigger/router/index.js.map +1 -0
- package/dist/trigger/router/strategies/ai-router-strategy.d.ts +34 -0
- package/dist/trigger/router/strategies/ai-router-strategy.d.ts.map +1 -0
- package/dist/trigger/router/strategies/ai-router-strategy.js +359 -0
- package/dist/trigger/router/strategies/ai-router-strategy.js.map +1 -0
- package/dist/trigger/router/strategies/direct-strategy.d.ts +32 -0
- package/dist/trigger/router/strategies/direct-strategy.d.ts.map +1 -0
- package/dist/trigger/router/strategies/direct-strategy.js +119 -0
- package/dist/trigger/router/strategies/direct-strategy.js.map +1 -0
- package/dist/trigger/router/strategies/index.d.ts +11 -0
- package/dist/trigger/router/strategies/index.d.ts.map +1 -0
- package/dist/trigger/router/strategies/index.js +11 -0
- package/dist/trigger/router/strategies/index.js.map +1 -0
- package/dist/trigger/router/strategies/role-strategy.d.ts +39 -0
- package/dist/trigger/router/strategies/role-strategy.d.ts.map +1 -0
- package/dist/trigger/router/strategies/role-strategy.js +207 -0
- package/dist/trigger/router/strategies/role-strategy.js.map +1 -0
- package/dist/trigger/router/trigger-router.d.ts +54 -0
- package/dist/trigger/router/trigger-router.d.ts.map +1 -0
- package/dist/trigger/router/trigger-router.js +362 -0
- package/dist/trigger/router/trigger-router.js.map +1 -0
- package/dist/trigger/router/types.d.ts +225 -0
- package/dist/trigger/router/types.d.ts.map +1 -0
- package/dist/trigger/router/types.js +10 -0
- package/dist/trigger/router/types.js.map +1 -0
- package/dist/trigger/sources/cron/cron-service.d.ts.map +1 -1
- package/dist/trigger/sources/cron/cron-service.js +6 -3
- package/dist/trigger/sources/cron/cron-service.js.map +1 -1
- package/dist/trigger/trigger-system.d.ts +77 -0
- package/dist/trigger/trigger-system.d.ts.map +1 -0
- package/dist/trigger/trigger-system.js +84 -0
- package/dist/trigger/trigger-system.js.map +1 -0
- package/dist/util/git-safety.d.ts +33 -0
- package/dist/util/git-safety.d.ts.map +1 -0
- package/dist/util/git-safety.js +94 -0
- package/dist/util/git-safety.js.map +1 -0
- package/dist/workspace/dataplane-adapter.d.ts +260 -0
- package/dist/workspace/dataplane-adapter.d.ts.map +1 -0
- package/dist/workspace/dataplane-adapter.js +416 -0
- package/dist/workspace/dataplane-adapter.js.map +1 -0
- package/dist/workspace/index.d.ts +0 -1
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/index.js +0 -2
- package/dist/workspace/index.js.map +1 -1
- package/dist/workspace/landing/direct-push.d.ts.map +1 -1
- package/dist/workspace/landing/direct-push.js +22 -7
- package/dist/workspace/landing/direct-push.js.map +1 -1
- package/dist/workspace/landing/queue-to-branch.d.ts.map +1 -1
- package/dist/workspace/landing/queue-to-branch.js +1 -3
- package/dist/workspace/landing/queue-to-branch.js.map +1 -1
- package/dist/workspace/types.d.ts +0 -13
- package/dist/workspace/types.d.ts.map +1 -1
- package/dist/workspace/workspace-manager.d.ts +0 -11
- package/dist/workspace/workspace-manager.d.ts.map +1 -1
- package/dist/workspace/workspace-manager.js +0 -30
- package/dist/workspace/workspace-manager.js.map +1 -1
- package/package.json +28 -2
- package/templates/teams/self-driving/prompts/grinder.md +1 -0
- package/templates/teams/self-driving/prompts/judge.md +1 -0
- package/templates/teams/self-driving/prompts/planner.md +1 -0
- package/templates/teams/self-driving/roles/grinder.yaml +15 -0
- package/templates/teams/self-driving/roles/judge.yaml +10 -0
- package/templates/teams/self-driving/roles/planner.yaml +16 -0
- package/.claude/commands/openspec/apply.md +0 -23
- package/.claude/commands/openspec/archive.md +0 -27
- package/.claude/commands/openspec/proposal.md +0 -28
- package/.claude/settings.json +0 -133
- package/.gitattributes +0 -3
- package/.opentasks/config.json +0 -9
- package/.opentasks/graph.jsonl +0 -0
- package/.sessionlog/settings.json +0 -4
- package/.sudocode/issues.jsonl +0 -183
- package/.sudocode/specs.jsonl +0 -56
- package/AGENTS.md +0 -18
- package/CLAUDE.md +0 -923
- package/docs/architecture.md +0 -508
- package/docs/configuration.md +0 -323
- package/docs/conflict-recovery.md +0 -472
- package/docs/design/task-dispatcher.md +0 -880
- package/docs/design-subsystem-extraction.md +0 -627
- package/docs/git-cascade-integration-gaps.md +0 -678
- package/docs/implementation-details.md +0 -1127
- package/docs/implementation-summary.md +0 -448
- package/docs/lifecycle-events-design.md +0 -111
- package/docs/mail-integration.md +0 -608
- package/docs/openhive-capability-summary.md +0 -415
- package/docs/openhive-integration.md +0 -415
- package/docs/plan-self-driving-support.md +0 -433
- package/docs/roadmap-v2-gaps.md +0 -216
- package/docs/spec-self-driving-support.md +0 -462
- package/docs/team-templates.md +0 -860
- package/docs/teams.md +0 -306
- package/docs/trigger-system-design.md +0 -333
- package/docs/troubleshooting.md +0 -489
- package/docs/workspace-interfaces.md +0 -731
- package/docs/workspace-redesign-plan.md +0 -302
- package/examples/distributed-peer-communication.ts +0 -202
- package/examples/local-peer-communication.ts +0 -165
- package/index.js +0 -2
- package/mvp_docs/agent-execution-system.md +0 -347
- package/mvp_docs/agent-interface.md +0 -580
- package/mvp_docs/data-structures.md +0 -701
- package/mvp_docs/dynamic-meta-orchestration.md +0 -116
- package/mvp_docs/multi-agent-interaction-design.md +0 -779
- package/mvp_docs/mvp-implementation-plan.md +0 -1148
- package/renovate.json5 +0 -6
- package/scripts/test-acp-integration.ts +0 -422
- package/src/__tests__/boot-v2.test.ts +0 -631
- package/src/__tests__/e2e/acp-over-map-live.e2e.test.ts +0 -496
- package/src/__tests__/e2e/acp-over-map.e2e.test.ts +0 -457
- package/src/__tests__/e2e/agent-lifecycle.e2e.test.ts +0 -770
- package/src/__tests__/e2e/auto-sync.e2e.test.ts +0 -257
- package/src/__tests__/e2e/bootstrap.e2e.test.ts +0 -319
- package/src/__tests__/e2e/cascade-rebase.e2e.test.ts +0 -254
- package/src/__tests__/e2e/cc-swarm-bridge.e2e.test.ts +0 -253
- package/src/__tests__/e2e/cli-run.e2e.test.ts +0 -167
- package/src/__tests__/e2e/cognitive-workspace.e2e.test.ts +0 -282
- package/src/__tests__/e2e/dispatch-coordination.e2e.test.ts +0 -495
- package/src/__tests__/e2e/dispatch-live.e2e.test.ts +0 -564
- package/src/__tests__/e2e/dispatch-opentasks.e2e.test.ts +0 -496
- package/src/__tests__/e2e/dispatch-phase2-live.e2e.test.ts +0 -456
- package/src/__tests__/e2e/dispatch-phase2.e2e.test.ts +0 -386
- package/src/__tests__/e2e/dispatch.e2e.test.ts +0 -376
- package/src/__tests__/e2e/done-scenarios.e2e.test.ts +0 -322
- package/src/__tests__/e2e/live-agent.e2e.test.ts +0 -1330
- package/src/__tests__/e2e/map-server.e2e.test.ts +0 -128
- package/src/__tests__/e2e/map-sidecar.e2e.test.ts +0 -139
- package/src/__tests__/e2e/opentasks-integration.e2e.test.ts +0 -280
- package/src/__tests__/e2e/pull-mode.e2e.test.ts +0 -632
- package/src/__tests__/e2e/resume-continue.e2e.test.ts +0 -312
- package/src/__tests__/e2e/self-driving-v3.e2e.test.ts +0 -197
- package/src/__tests__/e2e/spawn-resolver.e2e.test.ts +0 -200
- package/src/__tests__/e2e/swarmkit-integration.e2e.test.ts +0 -562
- package/src/__tests__/e2e/swarmkit-live.e2e.test.ts +0 -1049
- package/src/__tests__/e2e/trajectory-tracking.e2e.test.ts +0 -258
- package/src/__tests__/e2e/trigger-wake.e2e.test.ts +0 -257
- package/src/__tests__/e2e/workspace-lifecycle.e2e.test.ts +0 -383
- package/src/__tests__/e2e/workspace-v3.e2e.test.ts +0 -413
- package/src/acp/__tests__/claude-code-replay.test.ts +0 -225
- package/src/acp/__tests__/macro-agent.test.ts +0 -387
- package/src/acp/__tests__/session-mapper.test.ts +0 -152
- package/src/acp/__tests__/websocket-server.test.ts +0 -194
- package/src/acp/claude-code-replay.ts +0 -208
- package/src/acp/index.ts +0 -32
- package/src/acp/macro-agent.ts +0 -995
- package/src/acp/map-bridge.ts +0 -193
- package/src/acp/session-mapper.ts +0 -116
- package/src/acp/types.ts +0 -99
- package/src/acp/websocket-server.ts +0 -213
- package/src/adapters/__tests__/federation.test.ts +0 -256
- package/src/adapters/__tests__/inbox-adapter.test.ts +0 -316
- package/src/adapters/__tests__/tasks-adapter.test.ts +0 -270
- package/src/adapters/federation.ts +0 -185
- package/src/adapters/inbox-adapter.ts +0 -292
- package/src/adapters/inbox-client-adapter.ts +0 -173
- package/src/adapters/index.ts +0 -44
- package/src/adapters/opentasks-daemon.ts +0 -252
- package/src/adapters/tasks-adapter.ts +0 -330
- package/src/adapters/types.ts +0 -286
- package/src/agent/__tests__/agent-manager-topology.test.ts +0 -73
- package/src/agent/__tests__/agent-manager-v2.completion-signal.test.ts +0 -284
- package/src/agent/__tests__/agent-manager-v2.permission-interception.test.ts +0 -296
- package/src/agent/__tests__/agent-manager-v2.permissions.test.ts +0 -233
- package/src/agent/__tests__/agent-manager-v2.test.ts +0 -614
- package/src/agent/__tests__/agent-store.test.ts +0 -465
- package/src/agent/__tests__/task-ref-resolution.test.ts +0 -231
- package/src/agent/agent-manager-v2.ts +0 -2187
- package/src/agent/agent-manager.ts +0 -403
- package/src/agent/agent-store.ts +0 -409
- package/src/agent/index.ts +0 -7
- package/src/agent/prompts/coordinator-signals.ts +0 -115
- package/src/agent/prompts/index.ts +0 -7
- package/src/agent/system-prompt.ts +0 -298
- package/src/agent/types.ts +0 -480
- package/src/agent-detection/__tests__/command-builder.test.ts +0 -336
- package/src/agent-detection/__tests__/detector.test.ts +0 -768
- package/src/agent-detection/__tests__/registry.test.ts +0 -254
- package/src/agent-detection/command-builder.ts +0 -90
- package/src/agent-detection/detector.ts +0 -307
- package/src/agent-detection/index.ts +0 -36
- package/src/agent-detection/registry.ts +0 -200
- package/src/agent-detection/types.ts +0 -184
- package/src/api/__tests__/server.test.ts +0 -292
- package/src/api/index.ts +0 -8
- package/src/api/server.ts +0 -380
- package/src/api/types.ts +0 -39
- package/src/auth/__tests__/token.test.ts +0 -100
- package/src/auth/index.ts +0 -1
- package/src/auth/token.ts +0 -82
- package/src/boot-v2.ts +0 -1343
- package/src/cli/__tests__/stable-instance-id.test.ts +0 -57
- package/src/cli/acp.ts +0 -101
- package/src/cli/inbox-mcp-proxy.ts +0 -56
- package/src/cli/index.ts +0 -566
- package/src/cli/mcp.ts +0 -305
- package/src/cli/parse-args.ts +0 -54
- package/src/cli/stable-instance-id.ts +0 -14
- package/src/cognitive/__tests__/macro-agent-backend.test.ts +0 -673
- package/src/cognitive/__tests__/session-converter.test.ts +0 -423
- package/src/cognitive/__tests__/workspace-handler.test.ts +0 -221
- package/src/cognitive/analyst-role.ts +0 -59
- package/src/cognitive/index.ts +0 -49
- package/src/cognitive/macro-agent-backend.ts +0 -402
- package/src/cognitive/session-converter.ts +0 -151
- package/src/cognitive/types.ts +0 -187
- package/src/cognitive/workspace-handler.ts +0 -163
- package/src/config/index.ts +0 -9
- package/src/config/project-config.ts +0 -294
- package/src/control/__tests__/control-resilience.test.ts +0 -251
- package/src/control/__tests__/control-socket.test.ts +0 -240
- package/src/control/control-client.ts +0 -337
- package/src/control/control-server.ts +0 -298
- package/src/control/index.ts +0 -17
- package/src/control/types.ts +0 -95
- package/src/dispatch/CLAUDE.md +0 -129
- package/src/dispatch/__tests__/loadout-translation.test.ts +0 -141
- package/src/dispatch/__tests__/mail-inbound-consumer.integration.test.ts +0 -519
- package/src/dispatch/__tests__/mail-inbound-consumer.test.ts +0 -800
- package/src/dispatch/__tests__/mail-inbound-reuse-consumer.test.ts +0 -575
- package/src/dispatch/__tests__/permission-evaluator.test.ts +0 -196
- package/src/dispatch/__tests__/permission-overlay.test.ts +0 -56
- package/src/dispatch/__tests__/permissions-handler.test.ts +0 -168
- package/src/dispatch/__tests__/spawn-agent-handler.test.ts +0 -282
- package/src/dispatch/loadout-translation.ts +0 -138
- package/src/dispatch/mail-inbound-consumer.ts +0 -560
- package/src/dispatch/mail-inbound-reuse-consumer.ts +0 -479
- package/src/dispatch/permission-evaluator.ts +0 -191
- package/src/dispatch/permission-overlay.ts +0 -89
- package/src/dispatch/permissions-handler.ts +0 -112
- package/src/dispatch/spawn-agent-handler.ts +0 -160
- package/src/index.ts +0 -117
- package/src/integrations/__tests__/context-builder.test.ts +0 -218
- package/src/integrations/__tests__/sessionlog.test.ts +0 -498
- package/src/integrations/__tests__/skilltree.test.ts +0 -136
- package/src/integrations/context-builder.ts +0 -280
- package/src/integrations/sessionlog.ts +0 -194
- package/src/integrations/skilltree.ts +0 -184
- package/src/lifecycle/__tests__/cascade-consolidation.test.ts +0 -240
- package/src/lifecycle/__tests__/handlers-v2.test.ts +0 -565
- package/src/lifecycle/cascade.ts +0 -335
- package/src/lifecycle/cleanup.ts +0 -373
- package/src/lifecycle/handlers-v2.ts +0 -508
- package/src/lifecycle/index.ts +0 -76
- package/src/lifecycle/types.ts +0 -260
- package/src/map/__tests__/cascade-bridge.test.ts +0 -229
- package/src/map/__tests__/cascade-diff-server.test.ts +0 -434
- package/src/map/__tests__/emit-event.test.ts +0 -71
- package/src/map/__tests__/lifecycle-bridge.test.ts +0 -430
- package/src/map/__tests__/mail-bridge.test.ts +0 -321
- package/src/map/__tests__/permission-forwarding.test.ts +0 -143
- package/src/map/__tests__/sidecar-diff-install-smoke.test.ts +0 -90
- package/src/map/__tests__/sidecar-integration.test.ts +0 -190
- package/src/map/__tests__/task-bridge.test.ts +0 -153
- package/src/map/__tests__/trajectory-reporter.test.ts +0 -173
- package/src/map/acp-bridge.ts +0 -293
- package/src/map/cascade-action-handler.ts +0 -205
- package/src/map/cascade-bridge.ts +0 -339
- package/src/map/cascade-diff-server.ts +0 -404
- package/src/map/cc-swarm-hooks.ts +0 -242
- package/src/map/coordination-handler.ts +0 -232
- package/src/map/index.ts +0 -18
- package/src/map/lifecycle-bridge.ts +0 -236
- package/src/map/mail-bridge.ts +0 -263
- package/src/map/repo-workspace.ts +0 -82
- package/src/map/server.ts +0 -758
- package/src/map/sidecar.ts +0 -826
- package/src/map/task-bridge.ts +0 -89
- package/src/map/trajectory-reporter.ts +0 -124
- package/src/map/types.ts +0 -304
- package/src/mcp/__tests__/mcp-server-v2.test.ts +0 -236
- package/src/mcp/index.ts +0 -6
- package/src/mcp/mcp-server-v2.ts +0 -485
- package/src/mcp/tools/done-v2.ts +0 -213
- package/src/mcp/types.ts +0 -432
- package/src/metrics/__tests__/metrics.test.ts +0 -205
- package/src/metrics/index.ts +0 -13
- package/src/metrics/metrics.ts +0 -151
- package/src/metrics/types.ts +0 -63
- package/src/roles/__tests__/config-loader.test.ts +0 -540
- package/src/roles/builtin/coordinator.ts +0 -75
- package/src/roles/builtin/generic.ts +0 -39
- package/src/roles/builtin/index.ts +0 -51
- package/src/roles/builtin/integrator.ts +0 -62
- package/src/roles/builtin/monitor.ts +0 -65
- package/src/roles/builtin/worker.ts +0 -134
- package/src/roles/capabilities.ts +0 -257
- package/src/roles/config-loader.ts +0 -405
- package/src/roles/index.ts +0 -141
- package/src/roles/registry.ts +0 -713
- package/src/roles/types.ts +0 -344
- package/src/store/index.ts +0 -8
- package/src/store/types/agents.ts +0 -69
- package/src/store/types/events.ts +0 -91
- package/src/store/types/index.ts +0 -9
- package/src/store/types/messages.ts +0 -32
- package/src/store/types/primitives.ts +0 -9
- package/src/store/types/tasks.ts +0 -124
- package/src/teams/__tests__/team-manager-v2.test.ts +0 -425
- package/src/teams/__tests__/team-runtime-v2.test.ts +0 -402
- package/src/teams/index.ts +0 -29
- package/src/teams/seed-defaults.ts +0 -83
- package/src/teams/team-loader.ts +0 -476
- package/src/teams/team-manager-v2.ts +0 -343
- package/src/teams/team-runtime-v2.ts +0 -943
- package/src/teams/types.ts +0 -276
- package/src/trigger/__tests__/cron-service.test.ts +0 -548
- package/src/trigger/__tests__/scheduler.test.ts +0 -371
- package/src/trigger/__tests__/system-event-queue.test.ts +0 -147
- package/src/trigger/__tests__/trigger-system-v2.test.ts +0 -257
- package/src/trigger/__tests__/wake-manager.test.ts +0 -356
- package/src/trigger/__tests__/webhook-handler.test.ts +0 -567
- package/src/trigger/index.ts +0 -110
- package/src/trigger/queue/index.ts +0 -21
- package/src/trigger/queue/system-event-queue.ts +0 -232
- package/src/trigger/queue/types.ts +0 -149
- package/src/trigger/sources/cron/cron-service.ts +0 -499
- package/src/trigger/sources/cron/index.ts +0 -41
- package/src/trigger/sources/cron/scheduler.ts +0 -344
- package/src/trigger/sources/cron/types.ts +0 -333
- package/src/trigger/sources/index.ts +0 -10
- package/src/trigger/sources/webhook/index.ts +0 -25
- package/src/trigger/sources/webhook/types.ts +0 -205
- package/src/trigger/sources/webhook/webhook-handler.ts +0 -410
- package/src/trigger/strategies/ai-router.ts +0 -170
- package/src/trigger/trigger-system-v2.ts +0 -536
- package/src/trigger/types.ts +0 -228
- package/src/trigger/wake/index.ts +0 -22
- package/src/trigger/wake/types.ts +0 -162
- package/src/trigger/wake/wake-manager.ts +0 -390
- package/src/workspace/__tests__/git-cascade-adapter.test.ts +0 -563
- package/src/workspace/__tests__/land-dispatch.test.ts +0 -214
- package/src/workspace/__tests__/self-driving-yaml.test.ts +0 -122
- package/src/workspace/__tests__/shared-worktree-refcount.test.ts +0 -154
- package/src/workspace/__tests__/standalone-mode.test.ts +0 -118
- package/src/workspace/__tests__/workspace-manager-v3.test.ts +0 -245
- package/src/workspace/__tests__/yaml-schema.test.ts +0 -210
- package/src/workspace/config.ts +0 -165
- package/src/workspace/git-cascade-adapter.ts +0 -1213
- package/src/workspace/index.ts +0 -110
- package/src/workspace/landing/__tests__/strategies.test.ts +0 -184
- package/src/workspace/landing/direct-push.ts +0 -91
- package/src/workspace/landing/index.ts +0 -40
- package/src/workspace/landing/merge-to-parent.ts +0 -229
- package/src/workspace/landing/optimistic-push.ts +0 -36
- package/src/workspace/landing/queue-to-branch.ts +0 -108
- package/src/workspace/merge-queue/__tests__/conflict-resolution-git.e2e.test.ts +0 -641
- package/src/workspace/merge-queue/__tests__/conflict-resolution.test.ts +0 -707
- package/src/workspace/merge-queue/__tests__/merge-queue-concurrent.test.ts +0 -628
- package/src/workspace/merge-queue/__tests__/merge-queue-edge-cases.test.ts +0 -1217
- package/src/workspace/merge-queue/__tests__/merge-queue.test.ts +0 -506
- package/src/workspace/merge-queue/__tests__/real-git-operations.e2e.test.ts +0 -556
- package/src/workspace/merge-queue/__tests__/resolver-flow.test.ts +0 -472
- package/src/workspace/merge-queue/index.ts +0 -38
- package/src/workspace/merge-queue/merge-queue.ts +0 -585
- package/src/workspace/merge-queue/schema.ts +0 -98
- package/src/workspace/merge-queue/types.ts +0 -316
- package/src/workspace/pool/__tests__/worktree-pool.integration.test.ts +0 -1281
- package/src/workspace/pool/__tests__/worktree-pool.test.ts +0 -590
- package/src/workspace/pool/index.ts +0 -26
- package/src/workspace/pool/types.ts +0 -276
- package/src/workspace/pool/worktree-pool.ts +0 -659
- package/src/workspace/recovery/__tests__/auto-resolve-integration.test.ts +0 -127
- package/src/workspace/recovery/__tests__/spawn-resolver.test.ts +0 -139
- package/src/workspace/recovery/__tests__/strategies.test.ts +0 -145
- package/src/workspace/recovery/abandon.ts +0 -51
- package/src/workspace/recovery/auto-resolve.ts +0 -119
- package/src/workspace/recovery/defer.ts +0 -23
- package/src/workspace/recovery/escalate.ts +0 -30
- package/src/workspace/recovery/index.ts +0 -58
- package/src/workspace/recovery/spawn-resolver.ts +0 -152
- package/src/workspace/recovery/types.ts +0 -54
- package/src/workspace/strategies/index.ts +0 -18
- package/src/workspace/strategies/optimistic.ts +0 -139
- package/src/workspace/strategies/queue.ts +0 -81
- package/src/workspace/strategies/registry.ts +0 -89
- package/src/workspace/strategies/trunk.ts +0 -123
- package/src/workspace/strategies/types.ts +0 -145
- package/src/workspace/topology/__tests__/yaml-driven.test.ts +0 -345
- package/src/workspace/topology/index.ts +0 -18
- package/src/workspace/topology/no-workspace.ts +0 -39
- package/src/workspace/topology/types.ts +0 -116
- package/src/workspace/topology/yaml-driven.ts +0 -316
- package/src/workspace/types-v3.ts +0 -162
- package/src/workspace/types.ts +0 -541
- package/src/workspace/workspace-manager.ts +0 -1577
- package/src/workspace/yaml-schema.ts +0 -216
- package/test_fixtures/README.md +0 -425
- package/test_fixtures/fixtures/behaviors/coordinators.ts +0 -196
- package/test_fixtures/fixtures/behaviors/index.ts +0 -62
- package/test_fixtures/fixtures/behaviors/integrators.ts +0 -143
- package/test_fixtures/fixtures/behaviors/monitors.ts +0 -199
- package/test_fixtures/fixtures/behaviors/workers.ts +0 -348
- package/test_fixtures/fixtures/index.ts +0 -7
- package/test_fixtures/fixtures/projects/index.ts +0 -23
- package/test_fixtures/fixtures/projects/project-with-specs.ts +0 -44
- package/test_fixtures/fixtures/projects/typescript-project.ts +0 -200
- package/test_fixtures/fixtures/repos/index.ts +0 -6
- package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -299
- package/test_fixtures/fixtures/repos/types.ts +0 -174
- package/test_fixtures/harness/assertions/harness-assertions.ts +0 -752
- package/test_fixtures/harness/assertions/index.ts +0 -8
- package/test_fixtures/harness/index.ts +0 -15
- package/test_fixtures/harness/simulator/agent-simulator.ts +0 -768
- package/test_fixtures/harness/simulator/behavior-executor.ts +0 -580
- package/test_fixtures/harness/simulator/index.ts +0 -14
- package/test_fixtures/harness/simulator/types.ts +0 -459
- package/test_fixtures/harness/test-harness.ts +0 -770
- package/test_fixtures/harness/timing/event-stepper.ts +0 -344
- package/test_fixtures/harness/timing/index.ts +0 -8
- package/tsconfig.json +0 -21
- package/vitest.config.ts +0 -30
- package/vitest.e2e.config.ts +0 -28
- package/vitest.setup.ts +0 -12
|
@@ -0,0 +1,1751 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Store implementation using TinyBase
|
|
3
|
+
*
|
|
4
|
+
* Provides an append-only event log with materialized views for:
|
|
5
|
+
* - Agents
|
|
6
|
+
* - Tasks
|
|
7
|
+
* - Messages (per-agent queues)
|
|
8
|
+
* - Subscriptions
|
|
9
|
+
*/
|
|
10
|
+
import { createStore } from 'tinybase';
|
|
11
|
+
import { createCustomPersister, createCustomSqlitePersister } from 'tinybase/persisters';
|
|
12
|
+
import Database from 'better-sqlite3';
|
|
13
|
+
import { nanoid } from 'nanoid';
|
|
14
|
+
import * as path from 'path';
|
|
15
|
+
import * as os from 'os';
|
|
16
|
+
import * as fs from 'fs';
|
|
17
|
+
import { CURRENT_EVENT_VERSION } from './types/events.js';
|
|
18
|
+
import { migrateEvent } from './migrations.js';
|
|
19
|
+
import { resolveInstancePath, ensureInstanceDir, createInstanceMeta, writeInstanceMeta, touchInstance, registerInstance, DEFAULT_PEER_VISIBILITY, filterEventsForPeer, } from './instance.js';
|
|
20
|
+
import { createTinyBaseBackend } from './backends/tinybase-backend.js';
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
// Tabular better-sqlite3 Persister
|
|
23
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
/**
|
|
25
|
+
* Build tabular config for the 10 TinyBase tables.
|
|
26
|
+
* Identity mapping: TinyBase table name === SQLite table name.
|
|
27
|
+
*/
|
|
28
|
+
function getTabularConfig() {
|
|
29
|
+
const tableNames = [
|
|
30
|
+
'events', 'agents', 'tasks', 'messages',
|
|
31
|
+
'sessions', 'conversations', 'turns',
|
|
32
|
+
'threads', 'subscriptions', 'participants',
|
|
33
|
+
];
|
|
34
|
+
const load = {};
|
|
35
|
+
const save = {};
|
|
36
|
+
for (const t of tableNames) {
|
|
37
|
+
load[t] = t; // SQLite table -> TinyBase table (same name)
|
|
38
|
+
save[t] = t; // TinyBase table -> SQLite table (same name)
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
mode: 'tabular',
|
|
42
|
+
tables: { load, save },
|
|
43
|
+
autoLoadIntervalSeconds: 1,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates a tabular TinyBase persister backed by better-sqlite3.
|
|
48
|
+
*
|
|
49
|
+
* Unlike the old JSON blob approach (entire store as one JSON string in a
|
|
50
|
+
* single row), tabular mode maps each TinyBase table to a real SQLite table
|
|
51
|
+
* and only writes changed rows on autoSave — making persistence O(delta)
|
|
52
|
+
* instead of O(total).
|
|
53
|
+
*/
|
|
54
|
+
function createTabularBetterSqlite3Persister(store, db) {
|
|
55
|
+
// Wrap better-sqlite3's sync API as the async DatabaseExecuteCommand.
|
|
56
|
+
// TinyBase generates SQL with $1, $2, ... placeholders (PostgreSQL-style),
|
|
57
|
+
// but better-sqlite3 uses ? for positional array binding. Convert them.
|
|
58
|
+
const executeCommand = async (sql, params) => {
|
|
59
|
+
const convertedSql = sql.replace(/\$\d+/g, '?');
|
|
60
|
+
const trimmed = convertedSql.trimStart().toUpperCase();
|
|
61
|
+
const stmt = db.prepare(convertedSql);
|
|
62
|
+
if (trimmed.startsWith('SELECT') || trimmed.startsWith('PRAGMA')) {
|
|
63
|
+
return (params ? stmt.all(...params) : stmt.all());
|
|
64
|
+
}
|
|
65
|
+
params ? stmt.run(...params) : stmt.run();
|
|
66
|
+
return [];
|
|
67
|
+
};
|
|
68
|
+
return createCustomSqlitePersister(store, getTabularConfig(), executeCommand,
|
|
69
|
+
// addChangeListener — better-sqlite3 has no native change events
|
|
70
|
+
(_listener) => null,
|
|
71
|
+
// delChangeListener — no-op
|
|
72
|
+
(_handle) => { },
|
|
73
|
+
// onSqlCommand
|
|
74
|
+
undefined,
|
|
75
|
+
// onIgnoredError
|
|
76
|
+
(error) => console.warn('[EventStore] Persister error:', error),
|
|
77
|
+
// destroy — do NOT close DB here; close() handles it after the persister drains
|
|
78
|
+
() => { },
|
|
79
|
+
// persist mode (1 = StoreOnly)
|
|
80
|
+
1,
|
|
81
|
+
// thing (the db instance)
|
|
82
|
+
db,
|
|
83
|
+
// getThing accessor name
|
|
84
|
+
'getDb');
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parse a duration string (e.g., "30d", "7d") to milliseconds
|
|
88
|
+
*/
|
|
89
|
+
export function parseDuration(duration) {
|
|
90
|
+
const match = duration.match(/^(\d+)([dhms])$/);
|
|
91
|
+
if (!match) {
|
|
92
|
+
throw new Error(`Invalid duration format: "${duration}". Use format like "30d", "7d", "24h", "60m", "30s".`);
|
|
93
|
+
}
|
|
94
|
+
const value = parseInt(match[1], 10);
|
|
95
|
+
const unit = match[2];
|
|
96
|
+
const multipliers = {
|
|
97
|
+
s: 1000,
|
|
98
|
+
m: 60 * 1000,
|
|
99
|
+
h: 60 * 60 * 1000,
|
|
100
|
+
d: 24 * 60 * 60 * 1000,
|
|
101
|
+
};
|
|
102
|
+
return value * multipliers[unit];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Create an Event Store instance
|
|
106
|
+
*/
|
|
107
|
+
export async function createEventStore(config = {}) {
|
|
108
|
+
// Resolve instance configuration
|
|
109
|
+
const resolved = resolveInstancePath(config);
|
|
110
|
+
const { instanceId, instancePath, namespace, isNew, backendType } = resolved;
|
|
111
|
+
// Reject deprecated legacy path option
|
|
112
|
+
if (config.path) {
|
|
113
|
+
throw new Error('[macro-agent] The `path` option has been removed. ' +
|
|
114
|
+
'Use `instanceId` and `baseDir` instead for per-instance isolation.');
|
|
115
|
+
}
|
|
116
|
+
// Track baseDir for MCP subprocess communication
|
|
117
|
+
const baseDir = config.baseDir ?? path.join(os.homedir(), '.multiagent');
|
|
118
|
+
// Get peer visibility config (default is restrictive)
|
|
119
|
+
const peerVisibility = config.peerVisibility ?? DEFAULT_PEER_VISIBILITY;
|
|
120
|
+
// Emit warning for in-memory mode (only in non-test environments)
|
|
121
|
+
if (config.inMemory && process.env.NODE_ENV !== 'test') {
|
|
122
|
+
console.warn('[macro-agent] WARNING: Using in-memory EventStore. MCP tools (done, spawn_agent, etc.) will not work ' +
|
|
123
|
+
'because MCP servers run as separate subprocesses that cannot access in-memory data. ' +
|
|
124
|
+
'Use file-based storage (remove inMemory option) for real agent workflows.');
|
|
125
|
+
}
|
|
126
|
+
const store = createStore();
|
|
127
|
+
// Set up persister based on backend type
|
|
128
|
+
let persister = null;
|
|
129
|
+
let db = null;
|
|
130
|
+
if (!config.inMemory) {
|
|
131
|
+
ensureInstanceDir(instancePath);
|
|
132
|
+
const dbPath = path.join(instancePath, 'store.sqlite');
|
|
133
|
+
db = new Database(dbPath);
|
|
134
|
+
db.pragma('journal_mode = WAL');
|
|
135
|
+
db.pragma('busy_timeout = 5000');
|
|
136
|
+
// Migration: if old JSON blob table exists, load data from it first
|
|
137
|
+
const oldTableExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tinybase_store'").get();
|
|
138
|
+
if (oldTableExists) {
|
|
139
|
+
const oldPersister = createCustomPersister(store, async () => {
|
|
140
|
+
const row = db.prepare("SELECT store FROM tinybase_store WHERE _id = '_'").get();
|
|
141
|
+
return row ? JSON.parse(row.store) : undefined;
|
|
142
|
+
}, async () => { }, (listener) => setInterval(listener, 1000), (interval) => clearInterval(interval));
|
|
143
|
+
await oldPersister.load();
|
|
144
|
+
oldPersister.destroy();
|
|
145
|
+
}
|
|
146
|
+
persister = createTabularBetterSqlite3Persister(store, db);
|
|
147
|
+
if (oldTableExists) {
|
|
148
|
+
// Save migrated data to new tabular format, then drop old table
|
|
149
|
+
await persister.save();
|
|
150
|
+
db.exec('DROP TABLE IF EXISTS tinybase_store');
|
|
151
|
+
}
|
|
152
|
+
await persister.load();
|
|
153
|
+
// Auto-save: persist to disk whenever the in-memory store changes.
|
|
154
|
+
// Without this, emit() only writes to TinyBase's in-memory store and
|
|
155
|
+
// data is lost if the server is killed before an explicit persist().
|
|
156
|
+
// Disabled for secondary instances (e.g., MCP subprocesses) to prevent
|
|
157
|
+
// cross-process data corruption from concurrent TinyBase save operations.
|
|
158
|
+
if (!config.disableAutoSave) {
|
|
159
|
+
await persister.startAutoSave();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Initialize/update instance metadata
|
|
163
|
+
if (!config.inMemory) {
|
|
164
|
+
if (isNew) {
|
|
165
|
+
const meta = createInstanceMeta(resolved, config);
|
|
166
|
+
writeInstanceMeta(instancePath, meta);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
touchInstance(instancePath);
|
|
170
|
+
}
|
|
171
|
+
// Register in namespace for discovery
|
|
172
|
+
registerInstance(config.baseDir ?? path.join(os.homedir(), '.multiagent'), namespace, instanceId, { label: config.label });
|
|
173
|
+
}
|
|
174
|
+
// Initialize tables if they don't exist
|
|
175
|
+
initializeTables(store);
|
|
176
|
+
// Rebuild materialized views from events
|
|
177
|
+
rebuildViews(store);
|
|
178
|
+
// Listener registries
|
|
179
|
+
const agentListeners = new Set();
|
|
180
|
+
const agentIdListeners = new Map();
|
|
181
|
+
const taskListeners = new Set();
|
|
182
|
+
const sessionListeners = new Set();
|
|
183
|
+
const messageListeners = new Map();
|
|
184
|
+
const conversationListeners = new Set();
|
|
185
|
+
const turnListeners = new Set();
|
|
186
|
+
/**
|
|
187
|
+
* Emit a new event to the store
|
|
188
|
+
*/
|
|
189
|
+
function emit(input) {
|
|
190
|
+
const event = {
|
|
191
|
+
...input,
|
|
192
|
+
id: `evt_${nanoid(12)}`,
|
|
193
|
+
version: CURRENT_EVENT_VERSION,
|
|
194
|
+
timestamp: Date.now(),
|
|
195
|
+
};
|
|
196
|
+
// Store the event
|
|
197
|
+
// Note: Use empty object for undefined source to avoid JSON.parse errors in query
|
|
198
|
+
store.setRow('events', event.id, {
|
|
199
|
+
id: event.id,
|
|
200
|
+
version: event.version,
|
|
201
|
+
timestamp: event.timestamp,
|
|
202
|
+
type: event.type,
|
|
203
|
+
source: JSON.stringify(event.source ?? {}),
|
|
204
|
+
target: event.target ? JSON.stringify(event.target) : '',
|
|
205
|
+
payload: JSON.stringify(event.payload),
|
|
206
|
+
metadata: event.metadata ? JSON.stringify(event.metadata) : '',
|
|
207
|
+
});
|
|
208
|
+
// Update materialized views
|
|
209
|
+
applyEventToViews(store, event, notifyAgentChange, notifyTaskChange, notifyMessageChange, notifySessionChange, notifyConversationChange, notifyTurnChange);
|
|
210
|
+
return event;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Query events with filters
|
|
214
|
+
*/
|
|
215
|
+
function query(filter) {
|
|
216
|
+
const events = [];
|
|
217
|
+
const rowIds = store.getRowIds('events');
|
|
218
|
+
for (const rowId of rowIds) {
|
|
219
|
+
const row = store.getRow('events', rowId);
|
|
220
|
+
if (!row.id)
|
|
221
|
+
continue;
|
|
222
|
+
// Parse raw event data
|
|
223
|
+
// Handle legacy data where source might be stored as "undefined" string
|
|
224
|
+
const sourceStr = row.source;
|
|
225
|
+
const parsedSource = sourceStr && sourceStr !== 'undefined'
|
|
226
|
+
? JSON.parse(sourceStr)
|
|
227
|
+
: {};
|
|
228
|
+
const rawEvent = {
|
|
229
|
+
id: row.id,
|
|
230
|
+
version: row.version,
|
|
231
|
+
timestamp: row.timestamp,
|
|
232
|
+
type: row.type,
|
|
233
|
+
source: parsedSource,
|
|
234
|
+
target: row.target ? JSON.parse(row.target) : undefined,
|
|
235
|
+
payload: JSON.parse(row.payload),
|
|
236
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
237
|
+
};
|
|
238
|
+
// Migrate event to current version if needed
|
|
239
|
+
const event = migrateEvent(rawEvent);
|
|
240
|
+
// Apply filters
|
|
241
|
+
if (filter) {
|
|
242
|
+
if (filter.type && event.type !== filter.type)
|
|
243
|
+
continue;
|
|
244
|
+
if (filter.source_agent_id && event.source.agent_id !== filter.source_agent_id)
|
|
245
|
+
continue;
|
|
246
|
+
if (filter.target_agent_id && event.target?.agent_id !== filter.target_agent_id)
|
|
247
|
+
continue;
|
|
248
|
+
if (filter.after && event.timestamp <= filter.after)
|
|
249
|
+
continue;
|
|
250
|
+
if (filter.before && event.timestamp >= filter.before)
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
events.push(event);
|
|
254
|
+
}
|
|
255
|
+
// Sort by timestamp
|
|
256
|
+
events.sort((a, b) => a.timestamp - b.timestamp);
|
|
257
|
+
// Apply limit
|
|
258
|
+
if (filter?.limit) {
|
|
259
|
+
return events.slice(0, filter.limit);
|
|
260
|
+
}
|
|
261
|
+
return events;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Get agent by ID
|
|
265
|
+
*/
|
|
266
|
+
function getAgent(agentId) {
|
|
267
|
+
const row = store.getRow('agents', agentId);
|
|
268
|
+
if (!row.id)
|
|
269
|
+
return null;
|
|
270
|
+
return rowToAgent(row);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* List agents with optional filter
|
|
274
|
+
*/
|
|
275
|
+
function listAgents(filter) {
|
|
276
|
+
const agents = [];
|
|
277
|
+
const rowIds = store.getRowIds('agents');
|
|
278
|
+
for (const rowId of rowIds) {
|
|
279
|
+
const row = store.getRow('agents', rowId);
|
|
280
|
+
if (!row.id)
|
|
281
|
+
continue;
|
|
282
|
+
const agent = rowToAgent(row);
|
|
283
|
+
if (filter) {
|
|
284
|
+
if (filter.state && agent.state !== filter.state)
|
|
285
|
+
continue;
|
|
286
|
+
if (filter.parent !== undefined && agent.parent !== filter.parent)
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
agents.push(agent);
|
|
290
|
+
}
|
|
291
|
+
return agents;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Update agent metadata fields (name, plan, metadata).
|
|
295
|
+
* Only provided fields are updated. Metadata is shallow-merged with existing.
|
|
296
|
+
*/
|
|
297
|
+
function updateAgentMetadata(agentId, updates) {
|
|
298
|
+
const row = store.getRow('agents', agentId);
|
|
299
|
+
if (!row.id)
|
|
300
|
+
return;
|
|
301
|
+
const partial = {
|
|
302
|
+
last_activity_at: Date.now(),
|
|
303
|
+
};
|
|
304
|
+
if (updates.name !== undefined) {
|
|
305
|
+
partial.name = updates.name;
|
|
306
|
+
}
|
|
307
|
+
if (updates.plan !== undefined) {
|
|
308
|
+
partial.plan = JSON.stringify(updates.plan);
|
|
309
|
+
}
|
|
310
|
+
if (updates.metadata !== undefined) {
|
|
311
|
+
// Shallow merge with existing metadata
|
|
312
|
+
const existing = row.metadata ? JSON.parse(row.metadata) : {};
|
|
313
|
+
partial.metadata = JSON.stringify({ ...existing, ...updates.metadata });
|
|
314
|
+
}
|
|
315
|
+
if (updates.team_instance !== undefined) {
|
|
316
|
+
partial.team_instance = updates.team_instance;
|
|
317
|
+
}
|
|
318
|
+
if (updates.cwd !== undefined) {
|
|
319
|
+
partial.cwd = updates.cwd;
|
|
320
|
+
}
|
|
321
|
+
store.setPartialRow('agents', agentId, partial);
|
|
322
|
+
const agent = rowToAgent(store.getRow('agents', agentId));
|
|
323
|
+
notifyAgentChange(agentId, agent);
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Update an agent's plan entries (persisted to SQLite via TinyBase).
|
|
327
|
+
* Convenience wrapper around updateAgentMetadata.
|
|
328
|
+
*/
|
|
329
|
+
function updateAgentPlan(agentId, plan) {
|
|
330
|
+
updateAgentMetadata(agentId, { plan });
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Get task by ID
|
|
334
|
+
*/
|
|
335
|
+
function getTask(taskId) {
|
|
336
|
+
const row = store.getRow('tasks', taskId);
|
|
337
|
+
if (!row.id)
|
|
338
|
+
return null;
|
|
339
|
+
return rowToTask(row);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* List tasks with optional filter
|
|
343
|
+
*/
|
|
344
|
+
function listTasks(filter) {
|
|
345
|
+
const tasks = [];
|
|
346
|
+
const rowIds = store.getRowIds('tasks');
|
|
347
|
+
for (const rowId of rowIds) {
|
|
348
|
+
const row = store.getRow('tasks', rowId);
|
|
349
|
+
if (!row.id)
|
|
350
|
+
continue;
|
|
351
|
+
const task = rowToTask(row);
|
|
352
|
+
if (filter) {
|
|
353
|
+
if (filter.status && task.status !== filter.status)
|
|
354
|
+
continue;
|
|
355
|
+
if (filter.assigned_agent && task.assigned_agent !== filter.assigned_agent)
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
tasks.push(task);
|
|
359
|
+
}
|
|
360
|
+
return tasks;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Get pending messages for an agent
|
|
364
|
+
*/
|
|
365
|
+
function getMessages(agentId, limit) {
|
|
366
|
+
const messages = [];
|
|
367
|
+
const rowIds = store.getRowIds('messages');
|
|
368
|
+
for (const rowId of rowIds) {
|
|
369
|
+
const row = store.getRow('messages', rowId);
|
|
370
|
+
if (!row.id || row.recipient !== agentId)
|
|
371
|
+
continue;
|
|
372
|
+
messages.push({
|
|
373
|
+
id: row.id,
|
|
374
|
+
from: JSON.parse(row.from),
|
|
375
|
+
content: row.content,
|
|
376
|
+
timestamp: row.timestamp,
|
|
377
|
+
truncated: row.truncated,
|
|
378
|
+
correlation_id: row.correlation_id,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
// Sort by timestamp
|
|
382
|
+
messages.sort((a, b) => a.timestamp - b.timestamp);
|
|
383
|
+
if (limit) {
|
|
384
|
+
return messages.slice(0, limit);
|
|
385
|
+
}
|
|
386
|
+
return messages;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get full message content by ID
|
|
390
|
+
*/
|
|
391
|
+
function getFullMessage(messageId) {
|
|
392
|
+
// Look up the original event
|
|
393
|
+
const row = store.getRow('events', messageId);
|
|
394
|
+
if (!row.id || row.type !== 'message')
|
|
395
|
+
return null;
|
|
396
|
+
const payload = JSON.parse(row.payload);
|
|
397
|
+
return payload.content ?? null;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Add a subscription for an agent
|
|
401
|
+
*/
|
|
402
|
+
function addSubscription(agentId, subscription) {
|
|
403
|
+
const subId = `${agentId}:${subscription.type}:${subscription.target}`;
|
|
404
|
+
store.setRow('subscriptions', subId, {
|
|
405
|
+
id: subId,
|
|
406
|
+
agent_id: agentId,
|
|
407
|
+
type: subscription.type,
|
|
408
|
+
target: subscription.target,
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Remove a subscription for an agent
|
|
413
|
+
*/
|
|
414
|
+
function removeSubscription(agentId, subscription) {
|
|
415
|
+
const subId = `${agentId}:${subscription.type}:${subscription.target}`;
|
|
416
|
+
store.delRow('subscriptions', subId);
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Get all subscriptions for an agent
|
|
420
|
+
*/
|
|
421
|
+
function getSubscriptions(agentId) {
|
|
422
|
+
const subscriptions = [];
|
|
423
|
+
const rowIds = store.getRowIds('subscriptions');
|
|
424
|
+
for (const rowId of rowIds) {
|
|
425
|
+
const row = store.getRow('subscriptions', rowId);
|
|
426
|
+
if (row.agent_id !== agentId)
|
|
427
|
+
continue;
|
|
428
|
+
subscriptions.push({
|
|
429
|
+
type: row.type,
|
|
430
|
+
target: row.target,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
return subscriptions;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Get all agents subscribed to a given subscription
|
|
437
|
+
*/
|
|
438
|
+
function getSubscribers(subscription) {
|
|
439
|
+
const subscribers = [];
|
|
440
|
+
const rowIds = store.getRowIds('subscriptions');
|
|
441
|
+
for (const rowId of rowIds) {
|
|
442
|
+
const row = store.getRow('subscriptions', rowId);
|
|
443
|
+
if (row.type !== subscription.type || row.target !== subscription.target)
|
|
444
|
+
continue;
|
|
445
|
+
subscribers.push(row.agent_id);
|
|
446
|
+
}
|
|
447
|
+
return subscribers;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Notify agent change listeners
|
|
451
|
+
*/
|
|
452
|
+
function notifyAgentChange(agentId, agent) {
|
|
453
|
+
// Global listeners
|
|
454
|
+
for (const callback of agentListeners) {
|
|
455
|
+
callback(agentId, agent);
|
|
456
|
+
}
|
|
457
|
+
// Specific agent listeners
|
|
458
|
+
const specificListeners = agentIdListeners.get(agentId);
|
|
459
|
+
if (specificListeners) {
|
|
460
|
+
for (const callback of specificListeners) {
|
|
461
|
+
callback(agentId, agent);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Notify task change listeners
|
|
467
|
+
*/
|
|
468
|
+
function notifyTaskChange(taskId, task) {
|
|
469
|
+
for (const callback of taskListeners) {
|
|
470
|
+
callback(taskId, task);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Notify message change listeners
|
|
475
|
+
*/
|
|
476
|
+
function notifyMessageChange(agentId) {
|
|
477
|
+
const listeners = messageListeners.get(agentId);
|
|
478
|
+
if (listeners) {
|
|
479
|
+
const messages = getMessages(agentId);
|
|
480
|
+
for (const callback of listeners) {
|
|
481
|
+
callback(agentId, messages);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Subscribe to agent changes (all agents or specific agent)
|
|
487
|
+
*/
|
|
488
|
+
function onAgentChange(callbackOrId, callback) {
|
|
489
|
+
if (typeof callbackOrId === 'function') {
|
|
490
|
+
// Global subscription
|
|
491
|
+
agentListeners.add(callbackOrId);
|
|
492
|
+
return () => agentListeners.delete(callbackOrId);
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
// Specific agent subscription
|
|
496
|
+
const agentId = callbackOrId;
|
|
497
|
+
const cb = callback;
|
|
498
|
+
if (!agentIdListeners.has(agentId)) {
|
|
499
|
+
agentIdListeners.set(agentId, new Set());
|
|
500
|
+
}
|
|
501
|
+
agentIdListeners.get(agentId).add(cb);
|
|
502
|
+
return () => agentIdListeners.get(agentId)?.delete(cb);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Subscribe to task changes
|
|
507
|
+
*/
|
|
508
|
+
function onTaskChange(callback) {
|
|
509
|
+
taskListeners.add(callback);
|
|
510
|
+
return () => taskListeners.delete(callback);
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Subscribe to message changes for an agent
|
|
514
|
+
*/
|
|
515
|
+
function onMessageChange(agentId, callback) {
|
|
516
|
+
if (!messageListeners.has(agentId)) {
|
|
517
|
+
messageListeners.set(agentId, new Set());
|
|
518
|
+
}
|
|
519
|
+
messageListeners.get(agentId).add(callback);
|
|
520
|
+
return () => messageListeners.get(agentId)?.delete(callback);
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Notify conversation change listeners
|
|
524
|
+
*/
|
|
525
|
+
function notifyConversationChange(conversationId, conversation) {
|
|
526
|
+
for (const callback of conversationListeners) {
|
|
527
|
+
callback(conversationId, conversation);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Notify turn change listeners
|
|
532
|
+
*/
|
|
533
|
+
function notifyTurnChange(conversationId, turn) {
|
|
534
|
+
for (const callback of turnListeners) {
|
|
535
|
+
callback(conversationId, turn);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Subscribe to conversation changes
|
|
540
|
+
*/
|
|
541
|
+
function onConversationChange(callback) {
|
|
542
|
+
conversationListeners.add(callback);
|
|
543
|
+
return () => conversationListeners.delete(callback);
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Subscribe to turn changes
|
|
547
|
+
*/
|
|
548
|
+
function onTurnChange(callback) {
|
|
549
|
+
turnListeners.add(callback);
|
|
550
|
+
return () => turnListeners.delete(callback);
|
|
551
|
+
}
|
|
552
|
+
// ─── Session View Queries ───
|
|
553
|
+
function getSession(sessionId) {
|
|
554
|
+
const row = store.getRow('sessions', sessionId);
|
|
555
|
+
if (!row.id)
|
|
556
|
+
return null;
|
|
557
|
+
return rowToSession(row);
|
|
558
|
+
}
|
|
559
|
+
function listSessions(filter) {
|
|
560
|
+
const sessions = [];
|
|
561
|
+
const rowIds = store.getRowIds('sessions');
|
|
562
|
+
for (const rowId of rowIds) {
|
|
563
|
+
const row = store.getRow('sessions', rowId);
|
|
564
|
+
if (!row.id)
|
|
565
|
+
continue;
|
|
566
|
+
const session = rowToSession(row);
|
|
567
|
+
if (filter) {
|
|
568
|
+
if (filter.state && session.state !== filter.state)
|
|
569
|
+
continue;
|
|
570
|
+
if (filter.agent_id && session.current_agent_id !== filter.agent_id && session.head_manager_id !== filter.agent_id)
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
sessions.push(session);
|
|
574
|
+
}
|
|
575
|
+
return sessions;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Notify session change listeners
|
|
579
|
+
*/
|
|
580
|
+
function notifySessionChange(sessionId, session) {
|
|
581
|
+
for (const callback of sessionListeners) {
|
|
582
|
+
callback(sessionId, session);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Subscribe to session changes
|
|
587
|
+
*/
|
|
588
|
+
function onSessionChange(callback) {
|
|
589
|
+
sessionListeners.add(callback);
|
|
590
|
+
return () => sessionListeners.delete(callback);
|
|
591
|
+
}
|
|
592
|
+
// ─── Conversation View Queries ───
|
|
593
|
+
function getConversation(conversationId) {
|
|
594
|
+
const row = store.getRow('conversations', conversationId);
|
|
595
|
+
if (!row.id)
|
|
596
|
+
return null;
|
|
597
|
+
return rowToConversation(row);
|
|
598
|
+
}
|
|
599
|
+
function listConversations(filter) {
|
|
600
|
+
const conversations = [];
|
|
601
|
+
const rowIds = store.getRowIds('conversations');
|
|
602
|
+
for (const rowId of rowIds) {
|
|
603
|
+
const row = store.getRow('conversations', rowId);
|
|
604
|
+
if (!row.id)
|
|
605
|
+
continue;
|
|
606
|
+
const conversation = rowToConversation(row);
|
|
607
|
+
if (filter) {
|
|
608
|
+
if (filter.type && conversation.type !== filter.type)
|
|
609
|
+
continue;
|
|
610
|
+
if (filter.status && conversation.status !== filter.status)
|
|
611
|
+
continue;
|
|
612
|
+
if (filter.parentConversationId && conversation.parentConversationId !== filter.parentConversationId)
|
|
613
|
+
continue;
|
|
614
|
+
if (filter.participantId) {
|
|
615
|
+
// Check participants table for membership
|
|
616
|
+
const partRow = store.getRow('participants', `${conversation.id}:${filter.participantId}`);
|
|
617
|
+
if (!partRow.id)
|
|
618
|
+
continue;
|
|
619
|
+
// Skip if participant has left
|
|
620
|
+
if (partRow.left_at && partRow.left_at > 0)
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
conversations.push(conversation);
|
|
625
|
+
}
|
|
626
|
+
return conversations;
|
|
627
|
+
}
|
|
628
|
+
function listTurns(filter) {
|
|
629
|
+
const turns = [];
|
|
630
|
+
const rowIds = store.getRowIds('turns');
|
|
631
|
+
for (const rowId of rowIds) {
|
|
632
|
+
const row = store.getRow('turns', rowId);
|
|
633
|
+
if (!row.id)
|
|
634
|
+
continue;
|
|
635
|
+
const turn = rowToTurn(row);
|
|
636
|
+
// Filter by conversation (required)
|
|
637
|
+
if (turn.conversationId !== filter.conversationId)
|
|
638
|
+
continue;
|
|
639
|
+
// Optional filters
|
|
640
|
+
if (filter.threadId && turn.threadId !== filter.threadId)
|
|
641
|
+
continue;
|
|
642
|
+
if (filter.contentType && turn.contentType !== filter.contentType)
|
|
643
|
+
continue;
|
|
644
|
+
if (filter.participantId && turn.participant !== filter.participantId)
|
|
645
|
+
continue;
|
|
646
|
+
turns.push(turn);
|
|
647
|
+
}
|
|
648
|
+
// Sort
|
|
649
|
+
const order = filter.order ?? 'asc';
|
|
650
|
+
turns.sort((a, b) => order === 'asc' ? a.timestamp - b.timestamp : b.timestamp - a.timestamp);
|
|
651
|
+
// Limit
|
|
652
|
+
if (filter.limit) {
|
|
653
|
+
return turns.slice(0, filter.limit);
|
|
654
|
+
}
|
|
655
|
+
return turns;
|
|
656
|
+
}
|
|
657
|
+
function listParticipants(conversationId, active) {
|
|
658
|
+
const participants = [];
|
|
659
|
+
const rowIds = store.getRowIds('participants');
|
|
660
|
+
for (const rowId of rowIds) {
|
|
661
|
+
const row = store.getRow('participants', rowId);
|
|
662
|
+
if (!row.id)
|
|
663
|
+
continue;
|
|
664
|
+
if (row.conversation_id !== conversationId)
|
|
665
|
+
continue;
|
|
666
|
+
const participant = rowToParticipant(row);
|
|
667
|
+
if (active && participant.leftAt)
|
|
668
|
+
continue;
|
|
669
|
+
participants.push(participant);
|
|
670
|
+
}
|
|
671
|
+
return participants;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Persist store to disk
|
|
675
|
+
*/
|
|
676
|
+
async function persist() {
|
|
677
|
+
if (persister) {
|
|
678
|
+
await persister.save();
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Reload store from disk (refresh data from SQLite)
|
|
683
|
+
*/
|
|
684
|
+
async function reload() {
|
|
685
|
+
if (persister) {
|
|
686
|
+
await persister.load();
|
|
687
|
+
// Rebuild materialized views from freshly loaded events
|
|
688
|
+
rebuildViews(store);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Close the store
|
|
693
|
+
*/
|
|
694
|
+
async function close() {
|
|
695
|
+
if (persister) {
|
|
696
|
+
// Stop auto-save first to prevent race conditions between
|
|
697
|
+
// auto-save callbacks and the explicit save/destroy sequence.
|
|
698
|
+
await persister.stopAutoSave();
|
|
699
|
+
await persister.save();
|
|
700
|
+
// Destroy the persister (removes store listeners) BEFORE closing the DB.
|
|
701
|
+
// The destroy callback is a no-op — we close the DB ourselves below
|
|
702
|
+
// after giving TinyBase's internal async queues time to drain.
|
|
703
|
+
persister.destroy();
|
|
704
|
+
// Allow any in-flight TinyBase microtasks to settle before closing
|
|
705
|
+
// the database connection. Without this, pending writes from store
|
|
706
|
+
// change listeners can race against db.close().
|
|
707
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
708
|
+
}
|
|
709
|
+
if (db) {
|
|
710
|
+
db.close();
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Get archives directory path
|
|
715
|
+
*/
|
|
716
|
+
function getArchivesDir() {
|
|
717
|
+
return path.join(instancePath, 'archives');
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Get manifest file path
|
|
721
|
+
*/
|
|
722
|
+
function getManifestPath() {
|
|
723
|
+
return path.join(getArchivesDir(), 'manifest.json');
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Read archive manifest
|
|
727
|
+
*/
|
|
728
|
+
function readManifest() {
|
|
729
|
+
const manifestPath = getManifestPath();
|
|
730
|
+
if (fs.existsSync(manifestPath)) {
|
|
731
|
+
return JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
732
|
+
}
|
|
733
|
+
return { version: 1, archives: [] };
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Write archive manifest
|
|
737
|
+
*/
|
|
738
|
+
function writeManifest(manifest) {
|
|
739
|
+
const manifestPath = getManifestPath();
|
|
740
|
+
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Archive old events to prevent unbounded store growth
|
|
744
|
+
*/
|
|
745
|
+
async function archive(options = {}) {
|
|
746
|
+
// Calculate cutoff timestamp
|
|
747
|
+
let cutoff;
|
|
748
|
+
if (options.before !== undefined) {
|
|
749
|
+
cutoff = options.before;
|
|
750
|
+
}
|
|
751
|
+
else if (options.olderThan) {
|
|
752
|
+
cutoff = Date.now() - parseDuration(options.olderThan);
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
// Default to 30 days
|
|
756
|
+
cutoff = Date.now() - parseDuration('30d');
|
|
757
|
+
}
|
|
758
|
+
// Query events older than cutoff
|
|
759
|
+
const allEvents = query();
|
|
760
|
+
const eventsToArchive = allEvents.filter((e) => e.timestamp < cutoff);
|
|
761
|
+
const eventsToRetain = allEvents.filter((e) => e.timestamp >= cutoff);
|
|
762
|
+
if (eventsToArchive.length === 0) {
|
|
763
|
+
return {
|
|
764
|
+
archivedCount: 0,
|
|
765
|
+
archivePath: '',
|
|
766
|
+
oldestRetained: eventsToRetain.length > 0 ? eventsToRetain[0].timestamp : Date.now(),
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
// Ensure archives directory exists
|
|
770
|
+
const archivesDir = getArchivesDir();
|
|
771
|
+
if (!fs.existsSync(archivesDir)) {
|
|
772
|
+
fs.mkdirSync(archivesDir, { recursive: true });
|
|
773
|
+
}
|
|
774
|
+
// Group events by month
|
|
775
|
+
const eventsByMonth = new Map();
|
|
776
|
+
for (const event of eventsToArchive) {
|
|
777
|
+
const date = new Date(event.timestamp);
|
|
778
|
+
const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
|
|
779
|
+
if (!eventsByMonth.has(monthKey)) {
|
|
780
|
+
eventsByMonth.set(monthKey, []);
|
|
781
|
+
}
|
|
782
|
+
eventsByMonth.get(monthKey).push(event);
|
|
783
|
+
}
|
|
784
|
+
// Read existing manifest
|
|
785
|
+
const manifest = readManifest();
|
|
786
|
+
// Write archive files and update manifest
|
|
787
|
+
let lastArchivePath = '';
|
|
788
|
+
for (const [monthKey, monthEvents] of eventsByMonth) {
|
|
789
|
+
const archivePath = path.join(archivesDir, `${monthKey}.json`);
|
|
790
|
+
lastArchivePath = archivePath;
|
|
791
|
+
// Read existing archive if it exists and merge
|
|
792
|
+
let existingEvents = [];
|
|
793
|
+
if (fs.existsSync(archivePath)) {
|
|
794
|
+
existingEvents = JSON.parse(fs.readFileSync(archivePath, 'utf-8'));
|
|
795
|
+
}
|
|
796
|
+
// Merge and deduplicate by event ID
|
|
797
|
+
const mergedEvents = [...existingEvents, ...monthEvents];
|
|
798
|
+
const uniqueEvents = Array.from(new Map(mergedEvents.map((e) => [e.id, e])).values());
|
|
799
|
+
uniqueEvents.sort((a, b) => a.timestamp - b.timestamp);
|
|
800
|
+
// Write archive file
|
|
801
|
+
fs.writeFileSync(archivePath, JSON.stringify(uniqueEvents, null, 2));
|
|
802
|
+
// Update manifest entry
|
|
803
|
+
const existingIndex = manifest.archives.findIndex((a) => a.path === archivePath);
|
|
804
|
+
const archiveEntry = {
|
|
805
|
+
path: archivePath,
|
|
806
|
+
from: uniqueEvents[0].timestamp,
|
|
807
|
+
to: uniqueEvents[uniqueEvents.length - 1].timestamp,
|
|
808
|
+
eventCount: uniqueEvents.length,
|
|
809
|
+
};
|
|
810
|
+
if (existingIndex >= 0) {
|
|
811
|
+
manifest.archives[existingIndex] = archiveEntry;
|
|
812
|
+
}
|
|
813
|
+
else {
|
|
814
|
+
manifest.archives.push(archiveEntry);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
// Sort manifest archives by date
|
|
818
|
+
manifest.archives.sort((a, b) => a.from - b.from);
|
|
819
|
+
// Write updated manifest
|
|
820
|
+
writeManifest(manifest);
|
|
821
|
+
// Remove archived events from active store
|
|
822
|
+
for (const event of eventsToArchive) {
|
|
823
|
+
store.delRow('events', event.id);
|
|
824
|
+
}
|
|
825
|
+
// Persist the updated store
|
|
826
|
+
await persist();
|
|
827
|
+
return {
|
|
828
|
+
archivedCount: eventsToArchive.length,
|
|
829
|
+
archivePath: lastArchivePath,
|
|
830
|
+
oldestRetained: eventsToRetain.length > 0 ? eventsToRetain[0].timestamp : Date.now(),
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Load archived events by date range
|
|
835
|
+
*/
|
|
836
|
+
async function loadArchive(options = {}) {
|
|
837
|
+
const manifest = readManifest();
|
|
838
|
+
const events = [];
|
|
839
|
+
for (const archive of manifest.archives) {
|
|
840
|
+
// Skip archives outside the requested range
|
|
841
|
+
if (options.from !== undefined && archive.to < options.from)
|
|
842
|
+
continue;
|
|
843
|
+
if (options.to !== undefined && archive.from > options.to)
|
|
844
|
+
continue;
|
|
845
|
+
// Read archive file
|
|
846
|
+
if (!fs.existsSync(archive.path))
|
|
847
|
+
continue;
|
|
848
|
+
const archiveEvents = JSON.parse(fs.readFileSync(archive.path, 'utf-8'));
|
|
849
|
+
// Filter by date range
|
|
850
|
+
for (const event of archiveEvents) {
|
|
851
|
+
if (options.from !== undefined && event.timestamp < options.from)
|
|
852
|
+
continue;
|
|
853
|
+
if (options.to !== undefined && event.timestamp > options.to)
|
|
854
|
+
continue;
|
|
855
|
+
events.push(event);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
// Sort by timestamp
|
|
859
|
+
events.sort((a, b) => a.timestamp - b.timestamp);
|
|
860
|
+
return events;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Get information about available archives
|
|
864
|
+
*/
|
|
865
|
+
async function getArchiveInfo() {
|
|
866
|
+
const manifest = readManifest();
|
|
867
|
+
const totalArchivedEvents = manifest.archives.reduce((sum, a) => sum + a.eventCount, 0);
|
|
868
|
+
return {
|
|
869
|
+
archives: manifest.archives,
|
|
870
|
+
totalArchivedEvents,
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Export events for peer sync
|
|
875
|
+
* @param filter Optional event filter
|
|
876
|
+
* @param options Export options
|
|
877
|
+
* @param options.forPeer If true, filter by peerVisibility config
|
|
878
|
+
*/
|
|
879
|
+
function exportEvents(filter, options) {
|
|
880
|
+
let events = query(filter);
|
|
881
|
+
// If exporting for peer, apply visibility filter
|
|
882
|
+
if (options?.forPeer) {
|
|
883
|
+
events = filterEventsForPeer(events, peerVisibility);
|
|
884
|
+
}
|
|
885
|
+
return events.map((event) => ({
|
|
886
|
+
...event,
|
|
887
|
+
sourceInstance: instanceId,
|
|
888
|
+
}));
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Import events from peer
|
|
892
|
+
*/
|
|
893
|
+
function importEvents(events) {
|
|
894
|
+
for (const event of events) {
|
|
895
|
+
// Skip if event already exists
|
|
896
|
+
const existing = store.getRow('events', event.id);
|
|
897
|
+
if (existing.id)
|
|
898
|
+
continue;
|
|
899
|
+
// Store the event
|
|
900
|
+
store.setRow('events', event.id, {
|
|
901
|
+
id: event.id,
|
|
902
|
+
version: event.version,
|
|
903
|
+
timestamp: event.timestamp,
|
|
904
|
+
type: event.type,
|
|
905
|
+
source: JSON.stringify(event.source),
|
|
906
|
+
target: event.target ? JSON.stringify(event.target) : '',
|
|
907
|
+
payload: JSON.stringify(event.payload),
|
|
908
|
+
metadata: event.metadata ? JSON.stringify(event.metadata) : '',
|
|
909
|
+
});
|
|
910
|
+
// Update materialized views
|
|
911
|
+
applyEventToViews(store, event, notifyAgentChange, notifyTaskChange, notifyMessageChange, notifySessionChange, notifyConversationChange, notifyTurnChange);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Get underlying storage backend (for advanced use)
|
|
916
|
+
*/
|
|
917
|
+
function getBackend() {
|
|
918
|
+
return createTinyBaseBackend(store, {
|
|
919
|
+
onFlush: async () => {
|
|
920
|
+
if (persister) {
|
|
921
|
+
await persister.save();
|
|
922
|
+
}
|
|
923
|
+
},
|
|
924
|
+
onClose: async () => {
|
|
925
|
+
if (persister) {
|
|
926
|
+
await persister.save();
|
|
927
|
+
persister.destroy();
|
|
928
|
+
}
|
|
929
|
+
if (db) {
|
|
930
|
+
db.close();
|
|
931
|
+
}
|
|
932
|
+
},
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
return {
|
|
936
|
+
// Instance info
|
|
937
|
+
instanceId,
|
|
938
|
+
namespace,
|
|
939
|
+
instancePath,
|
|
940
|
+
baseDir,
|
|
941
|
+
backendType,
|
|
942
|
+
peerVisibility,
|
|
943
|
+
// Event operations
|
|
944
|
+
emit,
|
|
945
|
+
query,
|
|
946
|
+
// Views
|
|
947
|
+
getAgent,
|
|
948
|
+
listAgents,
|
|
949
|
+
updateAgentPlan,
|
|
950
|
+
updateAgentMetadata,
|
|
951
|
+
getTask,
|
|
952
|
+
listTasks,
|
|
953
|
+
getMessages,
|
|
954
|
+
getFullMessage,
|
|
955
|
+
getSession,
|
|
956
|
+
listSessions,
|
|
957
|
+
getConversation,
|
|
958
|
+
listConversations,
|
|
959
|
+
listTurns,
|
|
960
|
+
listParticipants,
|
|
961
|
+
// Subscriptions
|
|
962
|
+
addSubscription,
|
|
963
|
+
removeSubscription,
|
|
964
|
+
getSubscriptions,
|
|
965
|
+
getSubscribers,
|
|
966
|
+
// Reactive updates
|
|
967
|
+
onAgentChange,
|
|
968
|
+
onTaskChange,
|
|
969
|
+
onMessageChange,
|
|
970
|
+
onSessionChange,
|
|
971
|
+
onConversationChange,
|
|
972
|
+
onTurnChange,
|
|
973
|
+
// Lifecycle
|
|
974
|
+
persist,
|
|
975
|
+
reload,
|
|
976
|
+
close,
|
|
977
|
+
// Archival
|
|
978
|
+
archive,
|
|
979
|
+
loadArchive,
|
|
980
|
+
getArchiveInfo,
|
|
981
|
+
// Export/Import
|
|
982
|
+
exportEvents,
|
|
983
|
+
importEvents,
|
|
984
|
+
// Advanced
|
|
985
|
+
getBackend,
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Initialize empty tables in the store
|
|
990
|
+
*/
|
|
991
|
+
function initializeTables(store) {
|
|
992
|
+
// Events table is created implicitly when rows are added
|
|
993
|
+
// We just ensure the tables exist by checking row IDs
|
|
994
|
+
store.getRowIds('events');
|
|
995
|
+
store.getRowIds('agents');
|
|
996
|
+
store.getRowIds('tasks');
|
|
997
|
+
store.getRowIds('messages');
|
|
998
|
+
store.getRowIds('subscriptions');
|
|
999
|
+
store.getRowIds('sessions');
|
|
1000
|
+
store.getRowIds('conversations');
|
|
1001
|
+
store.getRowIds('turns');
|
|
1002
|
+
store.getRowIds('threads');
|
|
1003
|
+
store.getRowIds('participants');
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Rebuild materialized views from the event log
|
|
1007
|
+
*/
|
|
1008
|
+
function rebuildViews(store) {
|
|
1009
|
+
// Preserve out-of-band agent fields that aren't derived from events.
|
|
1010
|
+
// These fields are written directly (not through events),
|
|
1011
|
+
// so they would be lost when we clear and replay.
|
|
1012
|
+
const OUT_OF_BAND_FIELDS = ['plan', 'name', 'metadata', 'cwd', 'team_instance'];
|
|
1013
|
+
const savedOutOfBand = new Map();
|
|
1014
|
+
for (const rowId of store.getRowIds('agents')) {
|
|
1015
|
+
const row = store.getRow('agents', rowId);
|
|
1016
|
+
const saved = {};
|
|
1017
|
+
for (const field of OUT_OF_BAND_FIELDS) {
|
|
1018
|
+
const val = row[field];
|
|
1019
|
+
if (val && val !== '' && val !== '[]') {
|
|
1020
|
+
saved[field] = val;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
if (Object.keys(saved).length > 0) {
|
|
1024
|
+
savedOutOfBand.set(rowId, saved);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
// Clear existing views
|
|
1028
|
+
for (const rowId of store.getRowIds('agents')) {
|
|
1029
|
+
store.delRow('agents', rowId);
|
|
1030
|
+
}
|
|
1031
|
+
for (const rowId of store.getRowIds('tasks')) {
|
|
1032
|
+
store.delRow('tasks', rowId);
|
|
1033
|
+
}
|
|
1034
|
+
for (const rowId of store.getRowIds('messages')) {
|
|
1035
|
+
store.delRow('messages', rowId);
|
|
1036
|
+
}
|
|
1037
|
+
for (const rowId of store.getRowIds('sessions')) {
|
|
1038
|
+
store.delRow('sessions', rowId);
|
|
1039
|
+
}
|
|
1040
|
+
for (const rowId of store.getRowIds('conversations')) {
|
|
1041
|
+
store.delRow('conversations', rowId);
|
|
1042
|
+
}
|
|
1043
|
+
for (const rowId of store.getRowIds('turns')) {
|
|
1044
|
+
store.delRow('turns', rowId);
|
|
1045
|
+
}
|
|
1046
|
+
for (const rowId of store.getRowIds('threads')) {
|
|
1047
|
+
store.delRow('threads', rowId);
|
|
1048
|
+
}
|
|
1049
|
+
for (const rowId of store.getRowIds('participants')) {
|
|
1050
|
+
store.delRow('participants', rowId);
|
|
1051
|
+
}
|
|
1052
|
+
// Replay all events to rebuild views
|
|
1053
|
+
const events = [];
|
|
1054
|
+
for (const rowId of store.getRowIds('events')) {
|
|
1055
|
+
const row = store.getRow('events', rowId);
|
|
1056
|
+
if (!row.id)
|
|
1057
|
+
continue;
|
|
1058
|
+
// Parse raw event and migrate to current version
|
|
1059
|
+
const rawEvent = {
|
|
1060
|
+
id: row.id,
|
|
1061
|
+
version: row.version,
|
|
1062
|
+
timestamp: row.timestamp,
|
|
1063
|
+
type: row.type,
|
|
1064
|
+
source: JSON.parse(row.source),
|
|
1065
|
+
target: row.target ? JSON.parse(row.target) : undefined,
|
|
1066
|
+
payload: JSON.parse(row.payload),
|
|
1067
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
1068
|
+
};
|
|
1069
|
+
events.push(migrateEvent(rawEvent));
|
|
1070
|
+
}
|
|
1071
|
+
// Sort by timestamp
|
|
1072
|
+
events.sort((a, b) => a.timestamp - b.timestamp);
|
|
1073
|
+
// Apply each event (no-op callbacks since we're rebuilding)
|
|
1074
|
+
const noop = () => { };
|
|
1075
|
+
for (const event of events) {
|
|
1076
|
+
applyEventToViews(store, event, noop, noop, noop, noop, noop, noop);
|
|
1077
|
+
}
|
|
1078
|
+
// Restore out-of-band agent fields preserved before the wipe
|
|
1079
|
+
for (const [agentId, fields] of savedOutOfBand) {
|
|
1080
|
+
const row = store.getRow('agents', agentId);
|
|
1081
|
+
if (row.id) {
|
|
1082
|
+
store.setPartialRow('agents', agentId, fields);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Apply a single event to materialized views
|
|
1088
|
+
*/
|
|
1089
|
+
function applyEventToViews(store, event, notifyAgentChange, notifyTaskChange, notifyMessageChange, notifySessionChange, notifyConversationChange, notifyTurnChange) {
|
|
1090
|
+
switch (event.type) {
|
|
1091
|
+
case 'spawn':
|
|
1092
|
+
applySpawnEvent(store, event, notifyAgentChange);
|
|
1093
|
+
break;
|
|
1094
|
+
case 'stop':
|
|
1095
|
+
applyStopEvent(store, event, notifyAgentChange);
|
|
1096
|
+
break;
|
|
1097
|
+
case 'status':
|
|
1098
|
+
applyStatusEvent(store, event, notifyAgentChange);
|
|
1099
|
+
break;
|
|
1100
|
+
case 'message':
|
|
1101
|
+
applyMessageEvent(store, event, notifyMessageChange);
|
|
1102
|
+
break;
|
|
1103
|
+
case 'task':
|
|
1104
|
+
applyTaskEvent(store, event, notifyTaskChange);
|
|
1105
|
+
break;
|
|
1106
|
+
case 'session':
|
|
1107
|
+
applySessionEvent(store, event, notifySessionChange);
|
|
1108
|
+
break;
|
|
1109
|
+
case 'conversation':
|
|
1110
|
+
applyConversationEvent(store, event, notifyConversationChange);
|
|
1111
|
+
break;
|
|
1112
|
+
case 'turn':
|
|
1113
|
+
applyTurnEvent(store, event, notifyTurnChange);
|
|
1114
|
+
break;
|
|
1115
|
+
case 'thread':
|
|
1116
|
+
applyThreadEvent(store, event);
|
|
1117
|
+
break;
|
|
1118
|
+
case 'peer_message':
|
|
1119
|
+
case 'peer_request':
|
|
1120
|
+
// Peer events are stored in the event log for audit trail
|
|
1121
|
+
// but not materialized into views since PeerManager handles
|
|
1122
|
+
// in-memory queues. Events can be queried via eventStore.query().
|
|
1123
|
+
break;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Apply spawn event to agents view
|
|
1128
|
+
*/
|
|
1129
|
+
function applySpawnEvent(store, event, notify) {
|
|
1130
|
+
const payload = event.payload;
|
|
1131
|
+
const agentId = payload.agent_id;
|
|
1132
|
+
const parent = payload.parent ?? null;
|
|
1133
|
+
// Compute lineage
|
|
1134
|
+
let lineage = [];
|
|
1135
|
+
if (parent) {
|
|
1136
|
+
const parentRow = store.getRow('agents', parent);
|
|
1137
|
+
if (parentRow.lineage) {
|
|
1138
|
+
lineage = [...JSON.parse(parentRow.lineage), parent];
|
|
1139
|
+
}
|
|
1140
|
+
else {
|
|
1141
|
+
lineage = [parent];
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
store.setRow('agents', agentId, {
|
|
1145
|
+
id: agentId,
|
|
1146
|
+
name: '',
|
|
1147
|
+
session_id: payload.session_id,
|
|
1148
|
+
provider_session_id: '',
|
|
1149
|
+
parent: parent ?? '',
|
|
1150
|
+
lineage: JSON.stringify(lineage),
|
|
1151
|
+
state: 'spawning',
|
|
1152
|
+
stop_reason: '',
|
|
1153
|
+
task: payload.task,
|
|
1154
|
+
task_id: payload.task_id ?? '',
|
|
1155
|
+
role: payload.role ?? '',
|
|
1156
|
+
team_instance: payload.team_instance ?? '',
|
|
1157
|
+
config: JSON.stringify(payload.config ?? {}),
|
|
1158
|
+
cwd: payload.cwd ?? process.cwd(),
|
|
1159
|
+
plan: '[]',
|
|
1160
|
+
metadata: '',
|
|
1161
|
+
created_at: event.timestamp,
|
|
1162
|
+
started_at: 0,
|
|
1163
|
+
stopped_at: 0,
|
|
1164
|
+
last_activity_at: event.timestamp,
|
|
1165
|
+
});
|
|
1166
|
+
const agent = rowToAgent(store.getRow('agents', agentId));
|
|
1167
|
+
notify(agentId, agent);
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Apply stop event to agents view
|
|
1171
|
+
*/
|
|
1172
|
+
function applyStopEvent(store, event, notify) {
|
|
1173
|
+
const agentId = event.source.agent_id;
|
|
1174
|
+
if (!agentId)
|
|
1175
|
+
return;
|
|
1176
|
+
const payload = event.payload;
|
|
1177
|
+
store.setPartialRow('agents', agentId, {
|
|
1178
|
+
state: 'stopped',
|
|
1179
|
+
stop_reason: payload.reason,
|
|
1180
|
+
stopped_at: event.timestamp,
|
|
1181
|
+
last_activity_at: event.timestamp,
|
|
1182
|
+
});
|
|
1183
|
+
const agent = rowToAgent(store.getRow('agents', agentId));
|
|
1184
|
+
notify(agentId, agent);
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Apply status event to agents view
|
|
1188
|
+
*/
|
|
1189
|
+
function applyStatusEvent(store, event, notify) {
|
|
1190
|
+
const agentId = event.source.agent_id;
|
|
1191
|
+
if (!agentId)
|
|
1192
|
+
return;
|
|
1193
|
+
const payload = event.payload;
|
|
1194
|
+
// Handle specific status types
|
|
1195
|
+
if (payload.status_type === 'started') {
|
|
1196
|
+
const updates = {
|
|
1197
|
+
state: 'running',
|
|
1198
|
+
started_at: event.timestamp,
|
|
1199
|
+
last_activity_at: event.timestamp,
|
|
1200
|
+
};
|
|
1201
|
+
// Store the provider's session ID (e.g., Claude Code UUID for --resume)
|
|
1202
|
+
if (payload.provider_session_id) {
|
|
1203
|
+
updates.provider_session_id = payload.provider_session_id;
|
|
1204
|
+
}
|
|
1205
|
+
store.setPartialRow('agents', agentId, updates);
|
|
1206
|
+
}
|
|
1207
|
+
else {
|
|
1208
|
+
// Always update last_activity_at on any status event
|
|
1209
|
+
store.setPartialRow('agents', agentId, {
|
|
1210
|
+
last_activity_at: event.timestamp,
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1213
|
+
const agent = rowToAgent(store.getRow('agents', agentId));
|
|
1214
|
+
notify(agentId, agent);
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Apply message event to messages view
|
|
1218
|
+
*/
|
|
1219
|
+
function applyMessageEvent(store, event, notify) {
|
|
1220
|
+
const target = event.target;
|
|
1221
|
+
if (!target)
|
|
1222
|
+
return;
|
|
1223
|
+
const payload = event.payload;
|
|
1224
|
+
// Handle various payload formats - content may be a string, object, or missing
|
|
1225
|
+
const rawContent = payload.content;
|
|
1226
|
+
const content = typeof rawContent === 'string'
|
|
1227
|
+
? rawContent
|
|
1228
|
+
: rawContent != null
|
|
1229
|
+
? JSON.stringify(rawContent)
|
|
1230
|
+
: '[no content]';
|
|
1231
|
+
// Truncate if needed (1000 chars limit)
|
|
1232
|
+
const MAX_CONTENT_LENGTH = 1000;
|
|
1233
|
+
const truncated = content.length > MAX_CONTENT_LENGTH;
|
|
1234
|
+
const displayContent = truncated ? content.slice(0, MAX_CONTENT_LENGTH) + '...' : content;
|
|
1235
|
+
// Route to direct agent target
|
|
1236
|
+
if (target.agent_id) {
|
|
1237
|
+
const messageId = `${event.id}:${target.agent_id}`;
|
|
1238
|
+
store.setRow('messages', messageId, {
|
|
1239
|
+
id: event.id,
|
|
1240
|
+
recipient: target.agent_id,
|
|
1241
|
+
from: JSON.stringify(event.source),
|
|
1242
|
+
content: displayContent,
|
|
1243
|
+
timestamp: event.timestamp,
|
|
1244
|
+
truncated,
|
|
1245
|
+
correlation_id: payload.correlation_id ?? '',
|
|
1246
|
+
});
|
|
1247
|
+
notify(target.agent_id);
|
|
1248
|
+
}
|
|
1249
|
+
// Route to topic subscribers
|
|
1250
|
+
if (target.topic) {
|
|
1251
|
+
const rowIds = store.getRowIds('subscriptions');
|
|
1252
|
+
for (const rowId of rowIds) {
|
|
1253
|
+
const row = store.getRow('subscriptions', rowId);
|
|
1254
|
+
if (row.type === 'topic' && row.target === target.topic) {
|
|
1255
|
+
const recipientId = row.agent_id;
|
|
1256
|
+
const messageId = `${event.id}:${recipientId}`;
|
|
1257
|
+
store.setRow('messages', messageId, {
|
|
1258
|
+
id: event.id,
|
|
1259
|
+
recipient: recipientId,
|
|
1260
|
+
from: JSON.stringify(event.source),
|
|
1261
|
+
content: displayContent,
|
|
1262
|
+
timestamp: event.timestamp,
|
|
1263
|
+
truncated,
|
|
1264
|
+
correlation_id: payload.correlation_id ?? '',
|
|
1265
|
+
});
|
|
1266
|
+
notify(recipientId);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Apply task event to tasks view
|
|
1273
|
+
*/
|
|
1274
|
+
function applyTaskEvent(store, event, notify) {
|
|
1275
|
+
const payload = event.payload;
|
|
1276
|
+
const taskId = payload.task_id;
|
|
1277
|
+
switch (payload.action) {
|
|
1278
|
+
case 'created': {
|
|
1279
|
+
const details = payload.details;
|
|
1280
|
+
store.setRow('tasks', taskId, {
|
|
1281
|
+
id: taskId,
|
|
1282
|
+
description: details.description,
|
|
1283
|
+
status: 'pending',
|
|
1284
|
+
assigned_agent: '',
|
|
1285
|
+
parent_task: details.parent_task ?? '',
|
|
1286
|
+
subtasks: JSON.stringify([]),
|
|
1287
|
+
blockers: JSON.stringify([]),
|
|
1288
|
+
tags: details.tags ? JSON.stringify(details.tags) : '',
|
|
1289
|
+
created_at: event.timestamp,
|
|
1290
|
+
started_at: 0,
|
|
1291
|
+
completed_at: 0,
|
|
1292
|
+
created_by: event.source.agent_id ?? '',
|
|
1293
|
+
inputs: JSON.stringify(details.inputs ?? {}),
|
|
1294
|
+
outputs: JSON.stringify({}),
|
|
1295
|
+
artifacts: JSON.stringify([]),
|
|
1296
|
+
agent_history: JSON.stringify([]),
|
|
1297
|
+
retry_policy: details.retryPolicy
|
|
1298
|
+
? JSON.stringify(details.retryPolicy)
|
|
1299
|
+
: '',
|
|
1300
|
+
retry_state: '',
|
|
1301
|
+
});
|
|
1302
|
+
break;
|
|
1303
|
+
}
|
|
1304
|
+
case 'assigned': {
|
|
1305
|
+
const details = payload.details;
|
|
1306
|
+
const existing = store.getRow('tasks', taskId);
|
|
1307
|
+
const history = existing.agent_history
|
|
1308
|
+
? JSON.parse(existing.agent_history)
|
|
1309
|
+
: [];
|
|
1310
|
+
history.push({
|
|
1311
|
+
agent_id: details.agent_id,
|
|
1312
|
+
role: details.role,
|
|
1313
|
+
assigned_at: event.timestamp,
|
|
1314
|
+
});
|
|
1315
|
+
store.setPartialRow('tasks', taskId, {
|
|
1316
|
+
status: 'assigned',
|
|
1317
|
+
assigned_agent: details.agent_id,
|
|
1318
|
+
agent_history: JSON.stringify(history),
|
|
1319
|
+
});
|
|
1320
|
+
break;
|
|
1321
|
+
}
|
|
1322
|
+
case 'unassigned': {
|
|
1323
|
+
const details = payload.details;
|
|
1324
|
+
const existing = store.getRow('tasks', taskId);
|
|
1325
|
+
const history = existing.agent_history
|
|
1326
|
+
? JSON.parse(existing.agent_history)
|
|
1327
|
+
: [];
|
|
1328
|
+
// Update the last entry for this agent with ended_at
|
|
1329
|
+
for (let i = history.length - 1; i >= 0; i--) {
|
|
1330
|
+
if (history[i].agent_id === details.agent_id && !history[i].ended_at) {
|
|
1331
|
+
history[i].ended_at = event.timestamp;
|
|
1332
|
+
break;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
const updates = {
|
|
1336
|
+
assigned_agent: '',
|
|
1337
|
+
agent_history: JSON.stringify(history),
|
|
1338
|
+
};
|
|
1339
|
+
// Reset to pending if task was only assigned (not yet started)
|
|
1340
|
+
if (existing.status === 'assigned') {
|
|
1341
|
+
updates.status = 'pending';
|
|
1342
|
+
}
|
|
1343
|
+
store.setPartialRow('tasks', taskId, updates);
|
|
1344
|
+
break;
|
|
1345
|
+
}
|
|
1346
|
+
case 'status_change': {
|
|
1347
|
+
const details = payload.details;
|
|
1348
|
+
const updates = {};
|
|
1349
|
+
if (details.status) {
|
|
1350
|
+
updates.status = details.status;
|
|
1351
|
+
if (details.status === 'in_progress') {
|
|
1352
|
+
const existing = store.getRow('tasks', taskId);
|
|
1353
|
+
if (!existing.started_at) {
|
|
1354
|
+
updates.started_at = event.timestamp;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
if (details.outputs !== undefined) {
|
|
1359
|
+
updates.outputs = JSON.stringify(details.outputs);
|
|
1360
|
+
}
|
|
1361
|
+
if (details.artifacts !== undefined) {
|
|
1362
|
+
const existing = store.getRow('tasks', taskId);
|
|
1363
|
+
const currentArtifacts = existing.artifacts
|
|
1364
|
+
? JSON.parse(existing.artifacts)
|
|
1365
|
+
: [];
|
|
1366
|
+
updates.artifacts = JSON.stringify([
|
|
1367
|
+
...currentArtifacts,
|
|
1368
|
+
...details.artifacts,
|
|
1369
|
+
]);
|
|
1370
|
+
}
|
|
1371
|
+
if (details.description !== undefined) {
|
|
1372
|
+
updates.description = details.description;
|
|
1373
|
+
}
|
|
1374
|
+
if (details.subtask_added) {
|
|
1375
|
+
const existing = store.getRow('tasks', taskId);
|
|
1376
|
+
const subtasks = existing.subtasks
|
|
1377
|
+
? JSON.parse(existing.subtasks)
|
|
1378
|
+
: [];
|
|
1379
|
+
subtasks.push(details.subtask_added);
|
|
1380
|
+
updates.subtasks = JSON.stringify(subtasks);
|
|
1381
|
+
}
|
|
1382
|
+
if (details.retryState !== undefined) {
|
|
1383
|
+
updates.retry_state = JSON.stringify(details.retryState);
|
|
1384
|
+
}
|
|
1385
|
+
// Allow clearing the assigned agent (for retry)
|
|
1386
|
+
if (details.agent_id === null) {
|
|
1387
|
+
updates.assigned_agent = '';
|
|
1388
|
+
}
|
|
1389
|
+
if (Object.keys(updates).length > 0) {
|
|
1390
|
+
store.setPartialRow('tasks', taskId, updates);
|
|
1391
|
+
}
|
|
1392
|
+
break;
|
|
1393
|
+
}
|
|
1394
|
+
case 'completed': {
|
|
1395
|
+
store.setPartialRow('tasks', taskId, {
|
|
1396
|
+
status: 'completed',
|
|
1397
|
+
completed_at: event.timestamp,
|
|
1398
|
+
});
|
|
1399
|
+
break;
|
|
1400
|
+
}
|
|
1401
|
+
case 'failed': {
|
|
1402
|
+
store.setPartialRow('tasks', taskId, {
|
|
1403
|
+
status: 'failed',
|
|
1404
|
+
completed_at: event.timestamp,
|
|
1405
|
+
});
|
|
1406
|
+
break;
|
|
1407
|
+
}
|
|
1408
|
+
case 'blocker_added': {
|
|
1409
|
+
const details = payload.details;
|
|
1410
|
+
const existing = store.getRow('tasks', taskId);
|
|
1411
|
+
const blockers = existing.blockers
|
|
1412
|
+
? JSON.parse(existing.blockers)
|
|
1413
|
+
: [];
|
|
1414
|
+
if (!blockers.includes(details.blocker_id)) {
|
|
1415
|
+
blockers.push(details.blocker_id);
|
|
1416
|
+
store.setPartialRow('tasks', taskId, {
|
|
1417
|
+
blockers: JSON.stringify(blockers),
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
break;
|
|
1421
|
+
}
|
|
1422
|
+
case 'blocker_removed': {
|
|
1423
|
+
const details = payload.details;
|
|
1424
|
+
const existing = store.getRow('tasks', taskId);
|
|
1425
|
+
const blockers = existing.blockers
|
|
1426
|
+
? JSON.parse(existing.blockers)
|
|
1427
|
+
: [];
|
|
1428
|
+
const idx = blockers.indexOf(details.blocker_id);
|
|
1429
|
+
if (idx >= 0) {
|
|
1430
|
+
blockers.splice(idx, 1);
|
|
1431
|
+
store.setPartialRow('tasks', taskId, {
|
|
1432
|
+
blockers: JSON.stringify(blockers),
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
break;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
const task = rowToTask(store.getRow('tasks', taskId));
|
|
1439
|
+
notify(taskId, task);
|
|
1440
|
+
}
|
|
1441
|
+
/**
|
|
1442
|
+
* Convert a TinyBase row to an Agent object
|
|
1443
|
+
*/
|
|
1444
|
+
function rowToAgent(row) {
|
|
1445
|
+
const stopReason = row.stop_reason;
|
|
1446
|
+
return {
|
|
1447
|
+
id: row.id,
|
|
1448
|
+
name: row.name || undefined,
|
|
1449
|
+
session_id: row.session_id,
|
|
1450
|
+
provider_session_id: row.provider_session_id || undefined,
|
|
1451
|
+
parent: row.parent || null,
|
|
1452
|
+
lineage: row.lineage ? JSON.parse(row.lineage) : [],
|
|
1453
|
+
state: row.state,
|
|
1454
|
+
stop_reason: stopReason ? stopReason : undefined,
|
|
1455
|
+
task: row.task,
|
|
1456
|
+
task_id: row.task_id || undefined,
|
|
1457
|
+
role: row.role || undefined,
|
|
1458
|
+
team_instance: row.team_instance || undefined,
|
|
1459
|
+
config: row.config ? JSON.parse(row.config) : {},
|
|
1460
|
+
cwd: row.cwd || process.cwd(),
|
|
1461
|
+
plan: row.plan ? JSON.parse(row.plan) : [],
|
|
1462
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
1463
|
+
created_at: row.created_at,
|
|
1464
|
+
started_at: row.started_at || undefined,
|
|
1465
|
+
stopped_at: row.stopped_at || undefined,
|
|
1466
|
+
last_activity_at: row.last_activity_at || undefined,
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
/**
|
|
1470
|
+
* Convert a TinyBase row to a Task object
|
|
1471
|
+
*/
|
|
1472
|
+
function rowToTask(row) {
|
|
1473
|
+
return {
|
|
1474
|
+
id: row.id,
|
|
1475
|
+
description: row.description,
|
|
1476
|
+
status: row.status,
|
|
1477
|
+
assigned_agent: row.assigned_agent || undefined,
|
|
1478
|
+
parent_task: row.parent_task || undefined,
|
|
1479
|
+
subtasks: row.subtasks ? JSON.parse(row.subtasks) : undefined,
|
|
1480
|
+
blockers: row.blockers ? JSON.parse(row.blockers) : undefined,
|
|
1481
|
+
created_at: row.created_at,
|
|
1482
|
+
started_at: row.started_at || undefined,
|
|
1483
|
+
completed_at: row.completed_at || undefined,
|
|
1484
|
+
created_by: row.created_by,
|
|
1485
|
+
inputs: row.inputs ? JSON.parse(row.inputs) : undefined,
|
|
1486
|
+
outputs: row.outputs ? JSON.parse(row.outputs) : undefined,
|
|
1487
|
+
artifacts: row.artifacts ? JSON.parse(row.artifacts) : undefined,
|
|
1488
|
+
agent_history: row.agent_history ? JSON.parse(row.agent_history) : undefined,
|
|
1489
|
+
tags: row.tags ? JSON.parse(row.tags) : undefined,
|
|
1490
|
+
retryPolicy: row.retry_policy ? JSON.parse(row.retry_policy) : undefined,
|
|
1491
|
+
retryState: row.retry_state ? JSON.parse(row.retry_state) : undefined,
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1495
|
+
// Session Event Handlers
|
|
1496
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1497
|
+
/**
|
|
1498
|
+
* Apply session event to sessions view
|
|
1499
|
+
*/
|
|
1500
|
+
function applySessionEvent(store, event, notify) {
|
|
1501
|
+
const payload = event.payload;
|
|
1502
|
+
const sessionId = payload.session_id;
|
|
1503
|
+
switch (payload.action) {
|
|
1504
|
+
case 'created': {
|
|
1505
|
+
store.setRow('sessions', sessionId, {
|
|
1506
|
+
id: sessionId,
|
|
1507
|
+
head_manager_id: payload.head_manager_id ?? '',
|
|
1508
|
+
current_agent_id: payload.head_manager_id ?? '',
|
|
1509
|
+
state: 'active',
|
|
1510
|
+
created_at: event.timestamp,
|
|
1511
|
+
updated_at: event.timestamp,
|
|
1512
|
+
closed_at: 0,
|
|
1513
|
+
});
|
|
1514
|
+
break;
|
|
1515
|
+
}
|
|
1516
|
+
case 'mounted': {
|
|
1517
|
+
store.setPartialRow('sessions', sessionId, {
|
|
1518
|
+
current_agent_id: payload.target_agent_id ?? '',
|
|
1519
|
+
state: 'mounted',
|
|
1520
|
+
updated_at: event.timestamp,
|
|
1521
|
+
});
|
|
1522
|
+
break;
|
|
1523
|
+
}
|
|
1524
|
+
case 'unmounted': {
|
|
1525
|
+
const existing = store.getRow('sessions', sessionId);
|
|
1526
|
+
store.setPartialRow('sessions', sessionId, {
|
|
1527
|
+
current_agent_id: existing.head_manager_id,
|
|
1528
|
+
state: 'active',
|
|
1529
|
+
updated_at: event.timestamp,
|
|
1530
|
+
});
|
|
1531
|
+
break;
|
|
1532
|
+
}
|
|
1533
|
+
case 'closed': {
|
|
1534
|
+
store.setPartialRow('sessions', sessionId, {
|
|
1535
|
+
state: 'closed',
|
|
1536
|
+
updated_at: event.timestamp,
|
|
1537
|
+
closed_at: event.timestamp,
|
|
1538
|
+
});
|
|
1539
|
+
break;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
const session = rowToSession(store.getRow('sessions', sessionId));
|
|
1543
|
+
notify(sessionId, session);
|
|
1544
|
+
}
|
|
1545
|
+
/**
|
|
1546
|
+
* Convert a TinyBase row to a Session object
|
|
1547
|
+
*/
|
|
1548
|
+
function rowToSession(row) {
|
|
1549
|
+
return {
|
|
1550
|
+
id: row.id,
|
|
1551
|
+
head_manager_id: row.head_manager_id,
|
|
1552
|
+
current_agent_id: row.current_agent_id,
|
|
1553
|
+
state: row.state,
|
|
1554
|
+
created_at: row.created_at,
|
|
1555
|
+
updated_at: row.updated_at,
|
|
1556
|
+
closed_at: row.closed_at || undefined,
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1560
|
+
// Conversation Event Handlers
|
|
1561
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1562
|
+
/**
|
|
1563
|
+
* Apply conversation event to conversations view
|
|
1564
|
+
*/
|
|
1565
|
+
function applyConversationEvent(store, event, notify) {
|
|
1566
|
+
const payload = event.payload;
|
|
1567
|
+
const conversationId = payload.conversation_id;
|
|
1568
|
+
switch (payload.action) {
|
|
1569
|
+
case 'created': {
|
|
1570
|
+
store.setRow('conversations', conversationId, {
|
|
1571
|
+
id: conversationId,
|
|
1572
|
+
type: payload.conversation_type,
|
|
1573
|
+
status: 'active',
|
|
1574
|
+
subject: payload.subject ?? '',
|
|
1575
|
+
parent_conversation_id: payload.parent_conversation_id ?? '',
|
|
1576
|
+
created_by: event.source.agent_id ?? 'unknown',
|
|
1577
|
+
created_at: event.timestamp,
|
|
1578
|
+
updated_at: event.timestamp,
|
|
1579
|
+
closed_at: 0,
|
|
1580
|
+
closed_by: '',
|
|
1581
|
+
close_reason: '',
|
|
1582
|
+
participant_count: 0,
|
|
1583
|
+
metadata: payload.metadata ? JSON.stringify(payload.metadata) : '',
|
|
1584
|
+
});
|
|
1585
|
+
break;
|
|
1586
|
+
}
|
|
1587
|
+
case 'closed': {
|
|
1588
|
+
const closeReason = payload.close_reason ?? '';
|
|
1589
|
+
// Map close_reason to valid ConversationStatus
|
|
1590
|
+
const validStatuses = new Set(['completed', 'failed', 'archived']);
|
|
1591
|
+
const closedStatus = validStatuses.has(closeReason) ? closeReason : 'completed';
|
|
1592
|
+
store.setPartialRow('conversations', conversationId, {
|
|
1593
|
+
status: closedStatus,
|
|
1594
|
+
closed_at: event.timestamp,
|
|
1595
|
+
updated_at: event.timestamp,
|
|
1596
|
+
closed_by: payload.closed_by ?? event.source.agent_id ?? '',
|
|
1597
|
+
close_reason: closeReason,
|
|
1598
|
+
});
|
|
1599
|
+
break;
|
|
1600
|
+
}
|
|
1601
|
+
case 'participant_joined': {
|
|
1602
|
+
const participantId = payload.participant_id;
|
|
1603
|
+
const partId = `${conversationId}:${participantId}`;
|
|
1604
|
+
store.setRow('participants', partId, {
|
|
1605
|
+
id: participantId,
|
|
1606
|
+
conversation_id: conversationId,
|
|
1607
|
+
type: payload.participant_type ?? 'agent',
|
|
1608
|
+
role: payload.participant_role ?? 'worker',
|
|
1609
|
+
joined_at: event.timestamp,
|
|
1610
|
+
left_at: 0,
|
|
1611
|
+
agent_id: payload.agent_id ?? '',
|
|
1612
|
+
});
|
|
1613
|
+
// Increment participant count
|
|
1614
|
+
const existing = store.getRow('conversations', conversationId);
|
|
1615
|
+
if (existing.id) {
|
|
1616
|
+
const count = existing.participant_count || 0;
|
|
1617
|
+
store.setPartialRow('conversations', conversationId, {
|
|
1618
|
+
participant_count: count + 1,
|
|
1619
|
+
updated_at: event.timestamp,
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1622
|
+
break;
|
|
1623
|
+
}
|
|
1624
|
+
case 'participant_left': {
|
|
1625
|
+
const leftParticipantId = payload.participant_id;
|
|
1626
|
+
const partId = `${conversationId}:${leftParticipantId}`;
|
|
1627
|
+
store.setPartialRow('participants', partId, {
|
|
1628
|
+
left_at: event.timestamp,
|
|
1629
|
+
});
|
|
1630
|
+
// Decrement participant count
|
|
1631
|
+
const existing = store.getRow('conversations', conversationId);
|
|
1632
|
+
if (existing.id) {
|
|
1633
|
+
const count = existing.participant_count || 0;
|
|
1634
|
+
store.setPartialRow('conversations', conversationId, {
|
|
1635
|
+
participant_count: Math.max(0, count - 1),
|
|
1636
|
+
updated_at: event.timestamp,
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
break;
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
const conversation = rowToConversation(store.getRow('conversations', conversationId));
|
|
1643
|
+
notify(conversationId, conversation);
|
|
1644
|
+
}
|
|
1645
|
+
/**
|
|
1646
|
+
* Apply turn event to turns view
|
|
1647
|
+
*/
|
|
1648
|
+
function applyTurnEvent(store, event, notify) {
|
|
1649
|
+
const payload = event.payload;
|
|
1650
|
+
if (payload.action !== 'recorded')
|
|
1651
|
+
return;
|
|
1652
|
+
const turnId = payload.turn_id;
|
|
1653
|
+
const conversationId = payload.conversation_id;
|
|
1654
|
+
const content = payload.content;
|
|
1655
|
+
store.setRow('turns', turnId, {
|
|
1656
|
+
id: turnId,
|
|
1657
|
+
conversation_id: conversationId,
|
|
1658
|
+
participant: payload.participant ?? event.source.agent_id ?? '',
|
|
1659
|
+
timestamp: event.timestamp,
|
|
1660
|
+
content_type: payload.content_type ?? 'text',
|
|
1661
|
+
content: typeof content === 'string' ? content : JSON.stringify(content),
|
|
1662
|
+
thread_id: payload.thread_id ?? '',
|
|
1663
|
+
in_reply_to: payload.in_reply_to ?? '',
|
|
1664
|
+
source_type: payload.source_type ?? 'explicit',
|
|
1665
|
+
source_message_id: payload.source_message_id ?? '',
|
|
1666
|
+
metadata: payload.metadata ? JSON.stringify(payload.metadata) : '',
|
|
1667
|
+
});
|
|
1668
|
+
// Update conversation's updatedAt
|
|
1669
|
+
const convRow = store.getRow('conversations', conversationId);
|
|
1670
|
+
if (convRow.id) {
|
|
1671
|
+
store.setPartialRow('conversations', conversationId, {
|
|
1672
|
+
updated_at: event.timestamp,
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
const turn = rowToTurn(store.getRow('turns', turnId));
|
|
1676
|
+
notify(conversationId, turn);
|
|
1677
|
+
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Apply thread event to threads view
|
|
1680
|
+
*/
|
|
1681
|
+
function applyThreadEvent(store, event) {
|
|
1682
|
+
const payload = event.payload;
|
|
1683
|
+
if (payload.action !== 'created')
|
|
1684
|
+
return;
|
|
1685
|
+
const threadId = payload.thread_id;
|
|
1686
|
+
store.setRow('threads', threadId, {
|
|
1687
|
+
id: threadId,
|
|
1688
|
+
conversation_id: payload.conversation_id ?? '',
|
|
1689
|
+
root_turn_id: payload.root_turn_id ?? '',
|
|
1690
|
+
subject: payload.subject ?? '',
|
|
1691
|
+
parent_thread_id: payload.parent_thread_id ?? '',
|
|
1692
|
+
created_by: event.source.agent_id ?? 'unknown',
|
|
1693
|
+
created_at: event.timestamp,
|
|
1694
|
+
turn_count: 0,
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1697
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1698
|
+
// Conversation Row Conversion Functions
|
|
1699
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1700
|
+
function rowToConversation(row) {
|
|
1701
|
+
return {
|
|
1702
|
+
id: row.id,
|
|
1703
|
+
type: row.type,
|
|
1704
|
+
status: row.status,
|
|
1705
|
+
subject: row.subject || undefined,
|
|
1706
|
+
parentConversationId: row.parent_conversation_id || undefined,
|
|
1707
|
+
createdBy: row.created_by,
|
|
1708
|
+
createdAt: row.created_at,
|
|
1709
|
+
updatedAt: row.updated_at,
|
|
1710
|
+
closedAt: row.closed_at || undefined,
|
|
1711
|
+
closedBy: row.closed_by || undefined,
|
|
1712
|
+
closeReason: row.close_reason || undefined,
|
|
1713
|
+
participantCount: row.participant_count || 0,
|
|
1714
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
1715
|
+
};
|
|
1716
|
+
}
|
|
1717
|
+
function rowToTurn(row) {
|
|
1718
|
+
const rawContent = row.content;
|
|
1719
|
+
let content;
|
|
1720
|
+
try {
|
|
1721
|
+
content = JSON.parse(rawContent);
|
|
1722
|
+
}
|
|
1723
|
+
catch {
|
|
1724
|
+
content = rawContent;
|
|
1725
|
+
}
|
|
1726
|
+
return {
|
|
1727
|
+
id: row.id,
|
|
1728
|
+
conversationId: row.conversation_id,
|
|
1729
|
+
participant: row.participant,
|
|
1730
|
+
timestamp: row.timestamp,
|
|
1731
|
+
contentType: row.content_type,
|
|
1732
|
+
content,
|
|
1733
|
+
threadId: row.thread_id || undefined,
|
|
1734
|
+
inReplyTo: row.in_reply_to || undefined,
|
|
1735
|
+
sourceType: row.source_type,
|
|
1736
|
+
sourceMessageId: row.source_message_id || undefined,
|
|
1737
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
1740
|
+
function rowToParticipant(row) {
|
|
1741
|
+
return {
|
|
1742
|
+
id: row.id,
|
|
1743
|
+
conversationId: row.conversation_id,
|
|
1744
|
+
type: row.type,
|
|
1745
|
+
role: row.role,
|
|
1746
|
+
joinedAt: row.joined_at,
|
|
1747
|
+
leftAt: row.left_at || undefined,
|
|
1748
|
+
agentId: row.agent_id || undefined,
|
|
1749
|
+
};
|
|
1750
|
+
}
|
|
1751
|
+
//# sourceMappingURL=event-store.js.map
|