@graychennpm/codebridge 0.0.0-stage → 0.1.0
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/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +217 -2
- package/README.zh-CN.md +222 -0
- package/apps/web/public/brand/agent-logo-carbon.svg +1 -0
- package/apps/web/public/brand/agent-logo.svg +1 -0
- package/docs/zh-CN/npm-release.md +77 -0
- package/node_modules/@codebridge/agent-registry/dist/index.d.ts +32 -0
- package/node_modules/@codebridge/agent-registry/dist/index.js +177 -0
- package/node_modules/@codebridge/agent-registry/dist/setup.d.ts +9 -0
- package/node_modules/@codebridge/agent-registry/dist/setup.js +115 -0
- package/node_modules/@codebridge/agent-registry/package.json +17 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-active-session.d.ts +12 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-active-session.js +57 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-claude-activity.d.ts +9 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-claude-activity.js +49 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-config-options.d.ts +46 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-config-options.js +220 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-doctor.d.ts +3 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-doctor.js +18 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-event-mapper.d.ts +5 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-event-mapper.js +136 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-kill.d.ts +10 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-kill.js +24 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-race.d.ts +6 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-race.js +29 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-session-list.d.ts +32 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-session-list.js +218 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-session-pool.d.ts +85 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-session-pool.js +165 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-session-runner.d.ts +78 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-session-runner.js +550 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-spawn-profiles.d.ts +9 -0
- package/node_modules/@codebridge/backends/dist/acp/acp-spawn-profiles.js +28 -0
- package/node_modules/@codebridge/backends/dist/acp/headless-client.d.ts +19 -0
- package/node_modules/@codebridge/backends/dist/acp/headless-client.js +47 -0
- package/node_modules/@codebridge/backends/dist/acp/index.d.ts +9 -0
- package/node_modules/@codebridge/backends/dist/acp/index.js +9 -0
- package/node_modules/@codebridge/backends/dist/agent-setup.d.ts +60 -0
- package/node_modules/@codebridge/backends/dist/agent-setup.js +504 -0
- package/node_modules/@codebridge/backends/dist/attachment-prompt.d.ts +8 -0
- package/node_modules/@codebridge/backends/dist/attachment-prompt.js +28 -0
- package/node_modules/@codebridge/backends/dist/auth-error-hints.d.ts +8 -0
- package/node_modules/@codebridge/backends/dist/auth-error-hints.js +33 -0
- package/node_modules/@codebridge/backends/dist/codex-skill-commands.d.ts +3 -0
- package/node_modules/@codebridge/backends/dist/codex-skill-commands.js +88 -0
- package/node_modules/@codebridge/backends/dist/index.d.ts +18 -0
- package/node_modules/@codebridge/backends/dist/index.js +34 -0
- package/node_modules/@codebridge/backends/dist/pi-providers.d.ts +45 -0
- package/node_modules/@codebridge/backends/dist/pi-providers.js +148 -0
- package/node_modules/@codebridge/backends/dist/pi-session-runner.d.ts +85 -0
- package/node_modules/@codebridge/backends/dist/pi-session-runner.js +460 -0
- package/node_modules/@codebridge/backends/dist/provider-connection.d.ts +17 -0
- package/node_modules/@codebridge/backends/dist/provider-connection.js +99 -0
- package/node_modules/@codebridge/backends/dist/session-discovery.d.ts +23 -0
- package/node_modules/@codebridge/backends/dist/session-discovery.js +340 -0
- package/node_modules/@codebridge/backends/dist/skill-control-plane.d.ts +147 -0
- package/node_modules/@codebridge/backends/dist/skill-control-plane.js +832 -0
- package/node_modules/@codebridge/backends/package.json +22 -0
- package/node_modules/@codebridge/bridge/dist/alert-notification-rules.d.ts +14 -0
- package/node_modules/@codebridge/bridge/dist/alert-notification-rules.js +37 -0
- package/node_modules/@codebridge/bridge/dist/channel-config.d.ts +4 -0
- package/node_modules/@codebridge/bridge/dist/channel-config.js +9 -0
- package/node_modules/@codebridge/bridge/dist/channel-ingress.d.ts +5 -0
- package/node_modules/@codebridge/bridge/dist/channel-ingress.js +403 -0
- package/node_modules/@codebridge/bridge/dist/cli.d.ts +3 -0
- package/node_modules/@codebridge/bridge/dist/cli.js +581 -0
- package/node_modules/@codebridge/bridge/dist/deployment.d.ts +46 -0
- package/node_modules/@codebridge/bridge/dist/deployment.js +174 -0
- package/node_modules/@codebridge/bridge/dist/event-loop-lag.d.ts +19 -0
- package/node_modules/@codebridge/bridge/dist/event-loop-lag.js +33 -0
- package/node_modules/@codebridge/bridge/dist/feishu-alert-monitor.d.ts +70 -0
- package/node_modules/@codebridge/bridge/dist/feishu-alert-monitor.js +591 -0
- package/node_modules/@codebridge/bridge/dist/init-wizard.d.ts +52 -0
- package/node_modules/@codebridge/bridge/dist/init-wizard.js +571 -0
- package/node_modules/@codebridge/bridge/dist/mcp-api.d.ts +4 -0
- package/node_modules/@codebridge/bridge/dist/mcp-api.js +100 -0
- package/node_modules/@codebridge/bridge/dist/outbound-api.d.ts +31 -0
- package/node_modules/@codebridge/bridge/dist/outbound-api.js +184 -0
- package/node_modules/@codebridge/bridge/dist/outbound-publishers.d.ts +54 -0
- package/node_modules/@codebridge/bridge/dist/outbound-publishers.js +213 -0
- package/node_modules/@codebridge/bridge/dist/project-api.d.ts +4 -0
- package/node_modules/@codebridge/bridge/dist/project-api.js +161 -0
- package/node_modules/@codebridge/bridge/dist/secrets-command.d.ts +13 -0
- package/node_modules/@codebridge/bridge/dist/secrets-command.js +34 -0
- package/node_modules/@codebridge/bridge/dist/session-api.d.ts +26 -0
- package/node_modules/@codebridge/bridge/dist/session-api.js +1378 -0
- package/node_modules/@codebridge/bridge/dist/session-history-import.d.ts +24 -0
- package/node_modules/@codebridge/bridge/dist/session-history-import.js +82 -0
- package/node_modules/@codebridge/bridge/dist/session-runtime-api.d.ts +19 -0
- package/node_modules/@codebridge/bridge/dist/session-runtime-api.js +453 -0
- package/node_modules/@codebridge/bridge/dist/session-runtime-migration.d.ts +21 -0
- package/node_modules/@codebridge/bridge/dist/session-runtime-migration.js +43 -0
- package/node_modules/@codebridge/bridge/dist/session-runtime-types.d.ts +85 -0
- package/node_modules/@codebridge/bridge/dist/session-runtime-types.js +98 -0
- package/node_modules/@codebridge/bridge/dist/skill-api.d.ts +28 -0
- package/node_modules/@codebridge/bridge/dist/skill-api.js +129 -0
- package/node_modules/@codebridge/bridge/dist/startup-surfaces.d.ts +15 -0
- package/node_modules/@codebridge/bridge/dist/startup-surfaces.js +13 -0
- package/node_modules/@codebridge/bridge/dist/web-frontend.d.ts +8 -0
- package/node_modules/@codebridge/bridge/dist/web-frontend.js +76 -0
- package/node_modules/@codebridge/bridge/dist/work-item-api.d.ts +6 -0
- package/node_modules/@codebridge/bridge/dist/work-item-api.js +414 -0
- package/node_modules/@codebridge/bridge/package.json +28 -0
- package/node_modules/@codebridge/channel-feishu/dist/alert-reactions.d.ts +6 -0
- package/node_modules/@codebridge/channel-feishu/dist/alert-reactions.js +58 -0
- package/node_modules/@codebridge/channel-feishu/dist/alert-types.d.ts +35 -0
- package/node_modules/@codebridge/channel-feishu/dist/alert-types.js +2 -0
- package/node_modules/@codebridge/channel-feishu/dist/bridge.d.ts +130 -0
- package/node_modules/@codebridge/channel-feishu/dist/bridge.js +1231 -0
- package/node_modules/@codebridge/channel-feishu/dist/cardkit-writer.d.ts +48 -0
- package/node_modules/@codebridge/channel-feishu/dist/cardkit-writer.js +153 -0
- package/node_modules/@codebridge/channel-feishu/dist/chain-topics.d.ts +20 -0
- package/node_modules/@codebridge/channel-feishu/dist/chain-topics.js +35 -0
- package/node_modules/@codebridge/channel-feishu/dist/coalescing-card-writer.d.ts +12 -0
- package/node_modules/@codebridge/channel-feishu/dist/coalescing-card-writer.js +53 -0
- package/node_modules/@codebridge/channel-feishu/dist/delivery-reconciler.d.ts +19 -0
- package/node_modules/@codebridge/channel-feishu/dist/delivery-reconciler.js +53 -0
- package/node_modules/@codebridge/channel-feishu/dist/durable-markdown-card.d.ts +19 -0
- package/node_modules/@codebridge/channel-feishu/dist/durable-markdown-card.js +77 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-extra-events.d.ts +27 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-extra-events.js +24 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-http.d.ts +4 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-http.js +25 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-context.d.ts +13 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-context.js +45 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-media.d.ts +22 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-media.js +273 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-mention-gate.d.ts +13 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-mention-gate.js +22 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-outbound-file.d.ts +12 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-outbound-file.js +38 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-quoted-message.d.ts +30 -0
- package/node_modules/@codebridge/channel-feishu/dist/feishu-quoted-message.js +183 -0
- package/node_modules/@codebridge/channel-feishu/dist/index.d.ts +7 -0
- package/node_modules/@codebridge/channel-feishu/dist/index.js +3 -0
- package/node_modules/@codebridge/channel-feishu/dist/redacting-logger.d.ts +17 -0
- package/node_modules/@codebridge/channel-feishu/dist/redacting-logger.js +41 -0
- package/node_modules/@codebridge/channel-feishu/dist/run-status.d.ts +39 -0
- package/node_modules/@codebridge/channel-feishu/dist/run-status.js +166 -0
- package/node_modules/@codebridge/channel-feishu/dist/session-watcher.d.ts +98 -0
- package/node_modules/@codebridge/channel-feishu/dist/session-watcher.js +655 -0
- package/node_modules/@codebridge/channel-feishu/package.json +19 -0
- package/node_modules/@codebridge/channel-telegram/dist/coalescing-message-writer.d.ts +14 -0
- package/node_modules/@codebridge/channel-telegram/dist/coalescing-message-writer.js +56 -0
- package/node_modules/@codebridge/channel-telegram/dist/index.d.ts +3 -0
- package/node_modules/@codebridge/channel-telegram/dist/index.js +3 -0
- package/node_modules/@codebridge/channel-telegram/dist/telegram-api.d.ts +62 -0
- package/node_modules/@codebridge/channel-telegram/dist/telegram-api.js +72 -0
- package/node_modules/@codebridge/channel-telegram/dist/telegram-bridge.d.ts +64 -0
- package/node_modules/@codebridge/channel-telegram/dist/telegram-bridge.js +469 -0
- package/node_modules/@codebridge/channel-telegram/dist/telegram-session-watcher.d.ts +41 -0
- package/node_modules/@codebridge/channel-telegram/dist/telegram-session-watcher.js +184 -0
- package/node_modules/@codebridge/channel-telegram/package.json +18 -0
- package/node_modules/@codebridge/core/dist/config-schema.d.ts +1195 -0
- package/node_modules/@codebridge/core/dist/config-schema.js +293 -0
- package/node_modules/@codebridge/core/dist/config-store.d.ts +48 -0
- package/node_modules/@codebridge/core/dist/config-store.js +207 -0
- package/node_modules/@codebridge/core/dist/index.d.ts +11 -0
- package/node_modules/@codebridge/core/dist/index.js +10 -0
- package/node_modules/@codebridge/core/dist/json-file-store.d.ts +16 -0
- package/node_modules/@codebridge/core/dist/json-file-store.js +46 -0
- package/node_modules/@codebridge/core/dist/mcp-types.d.ts +7 -0
- package/node_modules/@codebridge/core/dist/mcp-types.js +2 -0
- package/node_modules/@codebridge/core/dist/mentions.d.ts +36 -0
- package/node_modules/@codebridge/core/dist/mentions.js +138 -0
- package/node_modules/@codebridge/core/dist/secret-migration.d.ts +14 -0
- package/node_modules/@codebridge/core/dist/secret-migration.js +55 -0
- package/node_modules/@codebridge/core/dist/secret-refs.d.ts +34 -0
- package/node_modules/@codebridge/core/dist/secret-refs.js +142 -0
- package/node_modules/@codebridge/core/dist/session-event-wire.d.ts +17 -0
- package/node_modules/@codebridge/core/dist/session-event-wire.js +28 -0
- package/node_modules/@codebridge/core/dist/types.d.ts +363 -0
- package/node_modules/@codebridge/core/dist/types.js +22 -0
- package/node_modules/@codebridge/core/dist/workspace-key.d.ts +11 -0
- package/node_modules/@codebridge/core/dist/workspace-key.js +25 -0
- package/node_modules/@codebridge/core/package.json +22 -0
- package/node_modules/@codebridge/mcp-runtime/dist/.tsbuildinfo +1 -0
- package/node_modules/@codebridge/mcp-runtime/dist/index.d.ts +92 -0
- package/node_modules/@codebridge/mcp-runtime/dist/index.js +377 -0
- package/node_modules/@codebridge/mcp-runtime/package.json +19 -0
- package/node_modules/@codebridge/policy/dist/capability-runtime.d.ts +123 -0
- package/node_modules/@codebridge/policy/dist/capability-runtime.js +195 -0
- package/node_modules/@codebridge/policy/dist/demo-capabilities.d.ts +4 -0
- package/node_modules/@codebridge/policy/dist/demo-capabilities.js +134 -0
- package/node_modules/@codebridge/policy/dist/equity-capabilities.d.ts +8 -0
- package/node_modules/@codebridge/policy/dist/equity-capabilities.js +35 -0
- package/node_modules/@codebridge/policy/dist/index.d.ts +107 -0
- package/node_modules/@codebridge/policy/dist/index.js +317 -0
- package/node_modules/@codebridge/policy/package.json +17 -0
- package/node_modules/@codebridge/project-catalog/dist/index.d.ts +145 -0
- package/node_modules/@codebridge/project-catalog/dist/index.js +699 -0
- package/node_modules/@codebridge/project-catalog/package.json +18 -0
- package/node_modules/@codebridge/router/dist/channel-stream-projector.d.ts +19 -0
- package/node_modules/@codebridge/router/dist/channel-stream-projector.js +68 -0
- package/node_modules/@codebridge/router/dist/command-help.d.ts +14 -0
- package/node_modules/@codebridge/router/dist/command-help.js +151 -0
- package/node_modules/@codebridge/router/dist/feishu-stream-presenter.d.ts +18 -0
- package/node_modules/@codebridge/router/dist/feishu-stream-presenter.js +193 -0
- package/node_modules/@codebridge/router/dist/index.d.ts +9 -0
- package/node_modules/@codebridge/router/dist/index.js +9 -0
- package/node_modules/@codebridge/router/dist/model-effort.d.ts +5 -0
- package/node_modules/@codebridge/router/dist/model-effort.js +33 -0
- package/node_modules/@codebridge/router/dist/orchestrator.d.ts +56 -0
- package/node_modules/@codebridge/router/dist/orchestrator.js +290 -0
- package/node_modules/@codebridge/router/dist/session-list-format.d.ts +19 -0
- package/node_modules/@codebridge/router/dist/session-list-format.js +97 -0
- package/node_modules/@codebridge/router/dist/session-rotation.d.ts +9 -0
- package/node_modules/@codebridge/router/dist/session-rotation.js +31 -0
- package/node_modules/@codebridge/router/dist/session-router.d.ts +59 -0
- package/node_modules/@codebridge/router/dist/session-router.js +182 -0
- package/node_modules/@codebridge/router/dist/slash-commands.d.ts +78 -0
- package/node_modules/@codebridge/router/dist/slash-commands.js +874 -0
- package/node_modules/@codebridge/router/package.json +18 -0
- package/node_modules/@codebridge/run-executor/dist/agent-event-aggregator.d.ts +18 -0
- package/node_modules/@codebridge/run-executor/dist/agent-event-aggregator.js +88 -0
- package/node_modules/@codebridge/run-executor/dist/index.d.ts +55 -0
- package/node_modules/@codebridge/run-executor/dist/index.js +754 -0
- package/node_modules/@codebridge/run-executor/dist/run-heartbeat.d.ts +14 -0
- package/node_modules/@codebridge/run-executor/dist/run-heartbeat.js +24 -0
- package/node_modules/@codebridge/run-executor/package.json +20 -0
- package/node_modules/@codebridge/runner-client/dist/index.d.ts +142 -0
- package/node_modules/@codebridge/runner-client/dist/index.js +439 -0
- package/node_modules/@codebridge/runner-client/package.json +18 -0
- package/node_modules/@codebridge/runner-host/dist/cli.d.ts +3 -0
- package/node_modules/@codebridge/runner-host/dist/cli.js +58 -0
- package/node_modules/@codebridge/runner-host/dist/codex-session-ownership.d.ts +13 -0
- package/node_modules/@codebridge/runner-host/dist/codex-session-ownership.js +79 -0
- package/node_modules/@codebridge/runner-host/dist/deployment-mcp-server.d.ts +10 -0
- package/node_modules/@codebridge/runner-host/dist/deployment-mcp-server.js +54 -0
- package/node_modules/@codebridge/runner-host/dist/fcb-script.d.ts +3 -0
- package/node_modules/@codebridge/runner-host/dist/fcb-script.js +99 -0
- package/node_modules/@codebridge/runner-host/dist/index.d.ts +3 -0
- package/node_modules/@codebridge/runner-host/dist/index.js +2 -0
- package/node_modules/@codebridge/runner-host/dist/materialize-attachments.d.ts +4 -0
- package/node_modules/@codebridge/runner-host/dist/materialize-attachments.js +62 -0
- package/node_modules/@codebridge/runner-host/dist/server.d.ts +150 -0
- package/node_modules/@codebridge/runner-host/dist/server.js +1295 -0
- package/node_modules/@codebridge/runner-host/dist/session-lease.d.ts +12 -0
- package/node_modules/@codebridge/runner-host/dist/session-lease.js +146 -0
- package/node_modules/@codebridge/runner-host/package.json +26 -0
- package/node_modules/@codebridge/session-catalog/dist/index.d.ts +124 -0
- package/node_modules/@codebridge/session-catalog/dist/index.js +411 -0
- package/node_modules/@codebridge/session-catalog/package.json +17 -0
- package/node_modules/@codebridge/session-coordinator/dist/coordinator.d.ts +111 -0
- package/node_modules/@codebridge/session-coordinator/dist/coordinator.js +364 -0
- package/node_modules/@codebridge/session-coordinator/dist/index.d.ts +5 -0
- package/node_modules/@codebridge/session-coordinator/dist/index.js +5 -0
- package/node_modules/@codebridge/session-coordinator/dist/lease.d.ts +14 -0
- package/node_modules/@codebridge/session-coordinator/dist/lease.js +26 -0
- package/node_modules/@codebridge/session-coordinator/dist/queued-claim.d.ts +20 -0
- package/node_modules/@codebridge/session-coordinator/dist/queued-claim.js +45 -0
- package/node_modules/@codebridge/session-coordinator/dist/recovery.d.ts +31 -0
- package/node_modules/@codebridge/session-coordinator/dist/recovery.js +114 -0
- package/node_modules/@codebridge/session-coordinator/package.json +17 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/node_modules/@codebridge/web/dist/assets/abnfDiagram-N423BO3Z-C-JdFv0U.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/arc-DsNROjzU.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/architecture-TIHT7OUA-ZEBHG2JZ.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/architectureDiagram-T3A2C74G-OsrxcwPM.js +36 -0
- package/node_modules/@codebridge/web/dist/assets/array-BifhSqXX.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/blockDiagram-VBNYF7ZC-DRgfNeNW.js +132 -0
- package/node_modules/@codebridge/web/dist/assets/c4Diagram-5PPSVZJV-BtOGKTh8.js +10 -0
- package/node_modules/@codebridge/web/dist/assets/channel-MhXyjxUS.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-2GRJ4B5K-Dy1gJ7sY.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-4I5QYGJK-1pOLR_SG.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-5RXB4S5H-CP43rgsO.js +231 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-6Q2QTUOP-Bi3Xrp6W.js +88 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-7Z6QIM7H-CILAW2Nk.js +10 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-GF5L2VYU-CAp09yhq.js +206 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-I66GZJ75-B_rJXmNu.js +128 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-JQJVKLGR-OVeOJFCx.js +156 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-KBJHAD2P-uaupp0k5.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-KEIR6QF5-BICK3FdT.js +161 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-NSK5VX7P-fIHF5wwn.js +2 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-QR6OTTB3-DxkJuF2b.js +62 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-RYQCIY6F-CC5j3u-X.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-UBXNYLIW-DB35O-6R.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-W5SLKNZC-bkRBsbq-.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-WRU74C26-DwvEoD-1.js +70 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-XXDRQBXY-DRyYA-HY.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/classDiagram-JCYQIIEL-B8r7z8ii.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/classDiagram-v2-OCEON4UE-B8r7z8ii.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/cose-bilkent-JH36ORCC-CLkwlrX7.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/cynefin-VYW2F7L2-C3_Llw02.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/cynefinDiagram-MW4NZA55-D5v7UnJy.js +62 -0
- package/node_modules/@codebridge/web/dist/assets/cytoscape.esm-B-NFISlW.js +321 -0
- package/node_modules/@codebridge/web/dist/assets/dagre-Buvkdvvj.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/dagre-VZM6K2ZE-Cr0IibwW.js +4 -0
- package/node_modules/@codebridge/web/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/diagram-7IWD3JNH-CpQXDIzA.js +30 -0
- package/node_modules/@codebridge/web/dist/assets/diagram-B4RE2ZJO-VaOkH0Ya.js +3 -0
- package/node_modules/@codebridge/web/dist/assets/diagram-LBJQPF4R-D0iXyNks.js +24 -0
- package/node_modules/@codebridge/web/dist/assets/diagram-Q27KOJAE-CtqYk01P.js +24 -0
- package/node_modules/@codebridge/web/dist/assets/diagram-UB23O5K3-CFnd3H1_.js +41 -0
- package/node_modules/@codebridge/web/dist/assets/dist-D2L7nRdk.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/ebnfDiagram-BXEA7PRR-B0GIbJYt.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/erDiagram-JOGREHBK-BApaLGVA.js +85 -0
- package/node_modules/@codebridge/web/dist/assets/eventmodeling-45OFAUF4-DqGGjcld.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/flowDiagram-UKHOOZJN-I_qlizLH.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/ganttDiagram-PKOTCBZU-B-QZ-J82.js +292 -0
- package/node_modules/@codebridge/web/dist/assets/gitGraph-TEB2WS4Q-DK2SJ2Ne.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/gitGraphDiagram-DS77QQ5N-B6Z-pu0D.js +106 -0
- package/node_modules/@codebridge/web/dist/assets/graphlib-DS17s2tU.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/index-8BzpyygS.js +559 -0
- package/node_modules/@codebridge/web/dist/assets/index-Bzaz89LE.css +1 -0
- package/node_modules/@codebridge/web/dist/assets/info-DKCQHKI2-CGWxt_Py.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/infoDiagram-6WML65LV-77XjrPZs.js +2 -0
- package/node_modules/@codebridge/web/dist/assets/init-C-OQMol4.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/ishikawaDiagram-WSZJBQD7-P1bZAz2x.js +70 -0
- package/node_modules/@codebridge/web/dist/assets/journeyDiagram-NVQOT4AX-C4rwMcBY.js +139 -0
- package/node_modules/@codebridge/web/dist/assets/kanban-definition-27J2QSJJ-mtw4a9bc.js +89 -0
- package/node_modules/@codebridge/web/dist/assets/line-DP4RkYqm.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/linear-DMg3PPio.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/map-BaFkSB1l.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/mermaid-parser.core-HY84kHw1.js +7 -0
- package/node_modules/@codebridge/web/dist/assets/mermaid.core-DdgCdsnM.js +42 -0
- package/node_modules/@codebridge/web/dist/assets/mindmap-definition-FAOFIHXS-Cw1EnbhZ.js +96 -0
- package/node_modules/@codebridge/web/dist/assets/ordinal-BDEzSJ7C.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/packet-7NZHBO7P-CEbrbJH3.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/path-fybaL0A-.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/pegDiagram-VL7TDLO6-CEc1Gedb.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/pie-RZYD4A2V-DPXVs-IW.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/pieDiagram-7S7Q4E2Y-hoQeGMFH.js +39 -0
- package/node_modules/@codebridge/web/dist/assets/quadrantDiagram-CIZ2JOQS-C-Nmxx0f.js +7 -0
- package/node_modules/@codebridge/web/dist/assets/radar-I7S5WNFK-BVd3X3Pd.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/railroad-3IZDKUUU-CxLxzr_v.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/railroad-abnf-AHOZXSZD-MA1zPI84.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/railroad-ebnf-EBAXGLYW-Bqug_umD.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/railroad-peg-LSFZ7HO6-DRcRFwpq.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/railroadDiagram-AXF67PYL-B007ZkL9.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/requirementDiagram-LRYGKXZP-LrTCcEi5.js +84 -0
- package/node_modules/@codebridge/web/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/sankeyDiagram-W5VNT64P-Ch4mzHck.js +40 -0
- package/node_modules/@codebridge/web/dist/assets/sequenceDiagram-SI44F4Z6-CHg4OzLX.js +162 -0
- package/node_modules/@codebridge/web/dist/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/src-BrO6_odD.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/stateDiagram-OKZ733FA-7cVkr5nR.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/stateDiagram-v2-UEYNNEHI-CTy_mAXb.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/swimlanes-SLNWSIFB-BwSVF5qy.js +2 -0
- package/node_modules/@codebridge/web/dist/assets/swimlanesDiagram-ULZ7WXOC-BBQnfZ1j.js +8 -0
- package/node_modules/@codebridge/web/dist/assets/timeline-definition-Z64GVDOM-BaHEkVDV.js +120 -0
- package/node_modules/@codebridge/web/dist/assets/treeView-QDETBFTQ-CF0kLN62.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/treemap-6X3UGDF4-BB8A8uux.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/vennDiagram-T6HMQDX7-BFK12Iro.js +34 -0
- package/node_modules/@codebridge/web/dist/assets/wardley-OPB4EBWU-C_3y61zk.js +1 -0
- package/node_modules/@codebridge/web/dist/assets/wardleyDiagram-T6FBY63Y-W2oGu4WK.js +78 -0
- package/node_modules/@codebridge/web/dist/assets/xychartDiagram-ELKLHX3M-BiVRnbvz.js +7 -0
- package/node_modules/@codebridge/web/dist/brand/agent-logo-carbon.svg +1 -0
- package/node_modules/@codebridge/web/dist/brand/agent-logo.svg +1 -0
- package/node_modules/@codebridge/web/dist/brand/agnet-logo-carbon.svg +1 -0
- package/node_modules/@codebridge/web/dist/brand/agnet-logo.svg +1 -0
- package/node_modules/@codebridge/web/dist/brand/agnet-mark-carbon.svg +1 -0
- package/node_modules/@codebridge/web/dist/brand/agnet-mark.svg +1 -0
- package/node_modules/@codebridge/web/dist/fonts/CommitMono-400-Regular.otf +0 -0
- package/node_modules/@codebridge/web/dist/fonts/CommitMono-700-Regular.otf +0 -0
- package/node_modules/@codebridge/web/dist/fonts/CommitMono-OFL.txt +21 -0
- package/node_modules/@codebridge/web/dist/fonts/DepartureMono-OFL.txt +21 -0
- package/node_modules/@codebridge/web/dist/fonts/DepartureMono-Regular.woff2 +0 -0
- package/node_modules/@codebridge/web/dist/index.html +25 -0
- package/node_modules/@codebridge/web/package.json +7 -0
- package/node_modules/@codebridge/work-items/dist/index.d.ts +371 -0
- package/node_modules/@codebridge/work-items/dist/index.js +1784 -0
- package/node_modules/@codebridge/work-items/dist/session-projector.d.ts +4 -0
- package/node_modules/@codebridge/work-items/dist/session-projector.js +506 -0
- package/node_modules/@codebridge/work-items/dist/session-runtime.d.ts +274 -0
- package/node_modules/@codebridge/work-items/dist/session-runtime.js +1103 -0
- package/node_modules/@codebridge/work-items/dist/session-schema.d.ts +9 -0
- package/node_modules/@codebridge/work-items/dist/session-schema.js +292 -0
- package/node_modules/@codebridge/work-items/package.json +20 -0
- package/package.json +75 -4
|
@@ -0,0 +1,1784 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { initializeSessionRuntimeSchema } from "./session-schema.js";
|
|
6
|
+
import { projectSessionEvent } from "./session-projector.js";
|
|
7
|
+
import { appendSessionEventInTransaction, createSqliteSessionRuntimeTransaction, importProviderHistory, parseSessionTurnMessage, resolveRunExecutionKind, } from "./session-runtime.js";
|
|
8
|
+
const { DatabaseSync } = createRequire(import.meta.url)("node:sqlite");
|
|
9
|
+
const STATUS_BY_EVENT = {
|
|
10
|
+
PLAN_PROPOSED: "planned",
|
|
11
|
+
APPROVAL_REQUESTED: "awaiting_approval",
|
|
12
|
+
RUN_CANCELLED: "cancelled",
|
|
13
|
+
STEP_STARTED: "executing",
|
|
14
|
+
VERIFICATION_COMPLETED: "verifying",
|
|
15
|
+
STEP_FAILED: "failed",
|
|
16
|
+
WORK_ITEM_COMPLETED: "completed",
|
|
17
|
+
};
|
|
18
|
+
export class SqliteEventStore {
|
|
19
|
+
database;
|
|
20
|
+
transactionDepth = 0;
|
|
21
|
+
constructor(databasePath) {
|
|
22
|
+
if (databasePath !== ":memory:") {
|
|
23
|
+
fs.mkdirSync(path.dirname(databasePath), { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
this.database = new DatabaseSync(databasePath);
|
|
26
|
+
this.database.exec("PRAGMA busy_timeout = 5000;");
|
|
27
|
+
if (databasePath !== ":memory:") {
|
|
28
|
+
this.database.exec("PRAGMA journal_mode = WAL;");
|
|
29
|
+
}
|
|
30
|
+
this.database.exec(`
|
|
31
|
+
PRAGMA foreign_keys = ON;
|
|
32
|
+
|
|
33
|
+
CREATE TABLE IF NOT EXISTS work_items (
|
|
34
|
+
id TEXT PRIMARY KEY,
|
|
35
|
+
schema_version INTEGER NOT NULL,
|
|
36
|
+
title TEXT NOT NULL,
|
|
37
|
+
status TEXT NOT NULL,
|
|
38
|
+
mode TEXT NOT NULL,
|
|
39
|
+
conversation_id TEXT NOT NULL,
|
|
40
|
+
agent_id TEXT,
|
|
41
|
+
workflow_id TEXT,
|
|
42
|
+
workflow_revision TEXT,
|
|
43
|
+
workspace_scope TEXT NOT NULL,
|
|
44
|
+
identifiers TEXT NOT NULL,
|
|
45
|
+
context_revision INTEGER NOT NULL,
|
|
46
|
+
risk_level TEXT NOT NULL,
|
|
47
|
+
created_at TEXT NOT NULL,
|
|
48
|
+
updated_at TEXT NOT NULL
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE TABLE IF NOT EXISTS domain_events (
|
|
52
|
+
event_id TEXT PRIMARY KEY,
|
|
53
|
+
schema_version INTEGER NOT NULL,
|
|
54
|
+
sequence INTEGER NOT NULL,
|
|
55
|
+
work_item_id TEXT NOT NULL,
|
|
56
|
+
run_id TEXT,
|
|
57
|
+
execution_kind TEXT CHECK (execution_kind IN ('agent', 'flow') OR execution_kind IS NULL),
|
|
58
|
+
type TEXT NOT NULL,
|
|
59
|
+
occurred_at TEXT NOT NULL,
|
|
60
|
+
actor TEXT NOT NULL,
|
|
61
|
+
target TEXT,
|
|
62
|
+
input_hash TEXT,
|
|
63
|
+
result_ref TEXT,
|
|
64
|
+
payload TEXT NOT NULL,
|
|
65
|
+
FOREIGN KEY (work_item_id) REFERENCES work_items(id),
|
|
66
|
+
UNIQUE (work_item_id, sequence)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
CREATE INDEX IF NOT EXISTS domain_events_work_item_sequence
|
|
70
|
+
ON domain_events (work_item_id, sequence);
|
|
71
|
+
|
|
72
|
+
CREATE INDEX IF NOT EXISTS domain_events_target_sequence
|
|
73
|
+
ON domain_events (target, sequence);
|
|
74
|
+
|
|
75
|
+
CREATE TABLE IF NOT EXISTS runs (
|
|
76
|
+
id TEXT PRIMARY KEY,
|
|
77
|
+
schema_version INTEGER NOT NULL,
|
|
78
|
+
work_item_id TEXT NOT NULL,
|
|
79
|
+
mode TEXT NOT NULL,
|
|
80
|
+
status TEXT NOT NULL,
|
|
81
|
+
execution_kind TEXT NOT NULL DEFAULT 'agent'
|
|
82
|
+
CHECK (execution_kind IN ('agent', 'flow')),
|
|
83
|
+
agent_id TEXT,
|
|
84
|
+
plan_id TEXT,
|
|
85
|
+
workflow_revision TEXT,
|
|
86
|
+
created_at TEXT NOT NULL,
|
|
87
|
+
updated_at TEXT NOT NULL,
|
|
88
|
+
FOREIGN KEY (work_item_id) REFERENCES work_items(id)
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
CREATE INDEX IF NOT EXISTS runs_work_item_created
|
|
92
|
+
ON runs (work_item_id, created_at);
|
|
93
|
+
|
|
94
|
+
CREATE TABLE IF NOT EXISTS message_attachments (
|
|
95
|
+
id TEXT PRIMARY KEY,
|
|
96
|
+
schema_version INTEGER NOT NULL,
|
|
97
|
+
work_item_id TEXT NOT NULL,
|
|
98
|
+
name TEXT NOT NULL,
|
|
99
|
+
mime_type TEXT NOT NULL,
|
|
100
|
+
data_base64 TEXT NOT NULL,
|
|
101
|
+
byte_size INTEGER NOT NULL,
|
|
102
|
+
content_hash TEXT NOT NULL,
|
|
103
|
+
created_at TEXT NOT NULL,
|
|
104
|
+
FOREIGN KEY (work_item_id) REFERENCES work_items(id) ON DELETE CASCADE
|
|
105
|
+
);
|
|
106
|
+
CREATE INDEX IF NOT EXISTS message_attachments_work_item_created
|
|
107
|
+
ON message_attachments (work_item_id, created_at);
|
|
108
|
+
|
|
109
|
+
CREATE TABLE IF NOT EXISTS plans (
|
|
110
|
+
plan_id TEXT PRIMARY KEY,
|
|
111
|
+
schema_version INTEGER NOT NULL,
|
|
112
|
+
source TEXT NOT NULL,
|
|
113
|
+
workflow_id TEXT NOT NULL,
|
|
114
|
+
definition_revision TEXT,
|
|
115
|
+
session_id TEXT,
|
|
116
|
+
run_id TEXT UNIQUE,
|
|
117
|
+
steps TEXT NOT NULL,
|
|
118
|
+
created_at TEXT NOT NULL
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
CREATE TABLE IF NOT EXISTS idempotency_responses (
|
|
122
|
+
namespace TEXT NOT NULL,
|
|
123
|
+
idempotency_key TEXT NOT NULL,
|
|
124
|
+
response TEXT NOT NULL,
|
|
125
|
+
created_at TEXT NOT NULL,
|
|
126
|
+
PRIMARY KEY (namespace, idempotency_key)
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
CREATE TABLE IF NOT EXISTS artifacts (
|
|
130
|
+
id TEXT PRIMARY KEY,
|
|
131
|
+
work_item_id TEXT NOT NULL,
|
|
132
|
+
run_id TEXT NOT NULL,
|
|
133
|
+
step_id TEXT,
|
|
134
|
+
kind TEXT NOT NULL,
|
|
135
|
+
name TEXT NOT NULL,
|
|
136
|
+
mime_type TEXT NOT NULL,
|
|
137
|
+
content TEXT NOT NULL,
|
|
138
|
+
content_hash TEXT NOT NULL,
|
|
139
|
+
metadata TEXT NOT NULL,
|
|
140
|
+
created_at TEXT NOT NULL,
|
|
141
|
+
FOREIGN KEY (work_item_id) REFERENCES work_items(id),
|
|
142
|
+
FOREIGN KEY (run_id) REFERENCES runs(id)
|
|
143
|
+
);
|
|
144
|
+
CREATE INDEX IF NOT EXISTS artifacts_run_created ON artifacts (run_id, created_at);
|
|
145
|
+
|
|
146
|
+
CREATE TABLE IF NOT EXISTS verifications (
|
|
147
|
+
id TEXT PRIMARY KEY,
|
|
148
|
+
work_item_id TEXT NOT NULL,
|
|
149
|
+
run_id TEXT NOT NULL,
|
|
150
|
+
step_id TEXT,
|
|
151
|
+
validator TEXT NOT NULL,
|
|
152
|
+
status TEXT NOT NULL,
|
|
153
|
+
summary TEXT NOT NULL,
|
|
154
|
+
artifact_ids TEXT NOT NULL,
|
|
155
|
+
created_at TEXT NOT NULL,
|
|
156
|
+
FOREIGN KEY (work_item_id) REFERENCES work_items(id),
|
|
157
|
+
FOREIGN KEY (run_id) REFERENCES runs(id)
|
|
158
|
+
);
|
|
159
|
+
CREATE INDEX IF NOT EXISTS verifications_run_created ON verifications (run_id, created_at);
|
|
160
|
+
`);
|
|
161
|
+
for (const statement of [
|
|
162
|
+
"ALTER TABLE runs ADD COLUMN workflow_revision TEXT",
|
|
163
|
+
"ALTER TABLE plans ADD COLUMN plan_ir_hash TEXT",
|
|
164
|
+
"ALTER TABLE runs ADD COLUMN plan_ir_hash TEXT",
|
|
165
|
+
]) {
|
|
166
|
+
try {
|
|
167
|
+
this.database.exec(statement);
|
|
168
|
+
}
|
|
169
|
+
catch { /* Existing databases already contain the column. */ }
|
|
170
|
+
}
|
|
171
|
+
initializeSessionRuntimeSchema(this.database);
|
|
172
|
+
}
|
|
173
|
+
createWorkItem(input) {
|
|
174
|
+
const now = new Date().toISOString();
|
|
175
|
+
const workItem = {
|
|
176
|
+
schemaVersion: 1,
|
|
177
|
+
id: input.id ?? createId("wi"),
|
|
178
|
+
title: input.title,
|
|
179
|
+
status: "created",
|
|
180
|
+
mode: input.mode,
|
|
181
|
+
conversationId: input.conversationId,
|
|
182
|
+
sessionId: input.sessionId ?? null,
|
|
183
|
+
agentId: input.agentId ?? null,
|
|
184
|
+
workflowId: input.workflowId ?? null,
|
|
185
|
+
workflowRevision: input.workflowRevision ?? null,
|
|
186
|
+
workspaceScope: [...(input.workspaceScope ?? [])],
|
|
187
|
+
identifiers: { ...(input.identifiers ?? {}) },
|
|
188
|
+
contextRevision: input.contextRevision ?? 1,
|
|
189
|
+
riskLevel: input.riskLevel,
|
|
190
|
+
createdAt: now,
|
|
191
|
+
updatedAt: now,
|
|
192
|
+
};
|
|
193
|
+
this.withTransaction(() => {
|
|
194
|
+
this.database
|
|
195
|
+
.prepare(`INSERT INTO work_items (
|
|
196
|
+
id, schema_version, title, status, mode, conversation_id,
|
|
197
|
+
session_id, agent_id, workflow_id, workflow_revision, workspace_scope,
|
|
198
|
+
identifiers, context_revision, risk_level, created_at, updated_at
|
|
199
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
200
|
+
.run(workItem.id, workItem.schemaVersion, workItem.title, workItem.status, workItem.mode, workItem.conversationId, workItem.sessionId, workItem.agentId, workItem.workflowId, workItem.workflowRevision, JSON.stringify(workItem.workspaceScope), JSON.stringify(workItem.identifiers), workItem.contextRevision, workItem.riskLevel, workItem.createdAt, workItem.updatedAt);
|
|
201
|
+
if (workItem.sessionId) {
|
|
202
|
+
this.database
|
|
203
|
+
.prepare(`INSERT INTO session_runtime (
|
|
204
|
+
session_id, active_run_id, queue_state, queue_pause_reason,
|
|
205
|
+
last_event_sequence, version, updated_at
|
|
206
|
+
) VALUES (?, NULL, 'ready', NULL, 0, 1, ?)`)
|
|
207
|
+
.run(workItem.sessionId, workItem.createdAt);
|
|
208
|
+
}
|
|
209
|
+
this.appendEventInTransaction({
|
|
210
|
+
workItemId: workItem.id,
|
|
211
|
+
type: "WORK_ITEM_CREATED",
|
|
212
|
+
actor: "system",
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
return workItem;
|
|
216
|
+
}
|
|
217
|
+
getWorkItem(workItemId) {
|
|
218
|
+
const row = this.database
|
|
219
|
+
.prepare("SELECT * FROM work_items WHERE id = ?")
|
|
220
|
+
.get(workItemId);
|
|
221
|
+
return row ? toWorkItem(row) : undefined;
|
|
222
|
+
}
|
|
223
|
+
getWorkItemBySessionId(sessionId) {
|
|
224
|
+
const row = this.database
|
|
225
|
+
.prepare("SELECT * FROM work_items WHERE session_id = ?")
|
|
226
|
+
.get(sessionId);
|
|
227
|
+
return row ? toWorkItem(row) : undefined;
|
|
228
|
+
}
|
|
229
|
+
getSessionRuntime(sessionId) {
|
|
230
|
+
const row = this.database
|
|
231
|
+
.prepare("SELECT * FROM session_runtime WHERE session_id = ?")
|
|
232
|
+
.get(sessionId);
|
|
233
|
+
return row ? toSessionRuntime(row) : undefined;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* First and latest ACP usage_update persisted for a session (context tokens in use / model window).
|
|
237
|
+
* INDEXED BY: without ANALYZE stats SQLite picks the (target, sequence) index and scans every
|
|
238
|
+
* session's usage rows; this keeps the lookup inside one work item.
|
|
239
|
+
*/
|
|
240
|
+
getContextUsage(sessionId) {
|
|
241
|
+
const workItemId = this.getWorkItemBySessionId(sessionId)?.id;
|
|
242
|
+
if (!workItemId)
|
|
243
|
+
return undefined;
|
|
244
|
+
const read = (order) => {
|
|
245
|
+
const row = this.database
|
|
246
|
+
.prepare(`SELECT payload FROM domain_events INDEXED BY domain_events_work_item_sequence
|
|
247
|
+
WHERE work_item_id = ? AND target = 'usage_update'
|
|
248
|
+
ORDER BY sequence ${order} LIMIT 1`)
|
|
249
|
+
.get(workItemId);
|
|
250
|
+
const event = row?.payload
|
|
251
|
+
? JSON.parse(row.payload).event
|
|
252
|
+
: undefined;
|
|
253
|
+
return typeof event?.used === "number" && typeof event.size === "number"
|
|
254
|
+
? { used: event.used, size: event.size }
|
|
255
|
+
: undefined;
|
|
256
|
+
};
|
|
257
|
+
const latest = read("DESC");
|
|
258
|
+
const first = latest && read("ASC");
|
|
259
|
+
return latest && first ? { first, latest } : undefined;
|
|
260
|
+
}
|
|
261
|
+
getTurn(turnId) {
|
|
262
|
+
const row = this.database
|
|
263
|
+
.prepare("SELECT * FROM session_turns WHERE turn_id = ?")
|
|
264
|
+
.get(turnId);
|
|
265
|
+
return row ? toSessionTurn(row) : undefined;
|
|
266
|
+
}
|
|
267
|
+
listQueuedTurns(sessionId, options) {
|
|
268
|
+
const afterPosition = Math.max(0, Math.floor(options.afterPosition ?? 0));
|
|
269
|
+
const limit = Math.max(1, Math.min(100, Math.floor(options.limit)));
|
|
270
|
+
const rows = this.database
|
|
271
|
+
.prepare(`SELECT * FROM session_turns
|
|
272
|
+
WHERE session_id = ? AND status = 'queued' AND queue_position > ?
|
|
273
|
+
ORDER BY queue_position ASC
|
|
274
|
+
LIMIT ?`)
|
|
275
|
+
.all(sessionId, afterPosition, limit + 1);
|
|
276
|
+
const totalRow = this.database
|
|
277
|
+
.prepare(`SELECT COUNT(*) AS total FROM session_turns
|
|
278
|
+
WHERE session_id = ? AND status = 'queued'`)
|
|
279
|
+
.get(sessionId);
|
|
280
|
+
const hasMore = rows.length > limit;
|
|
281
|
+
const turns = rows.slice(0, limit).map(toSessionTurn);
|
|
282
|
+
return {
|
|
283
|
+
turns,
|
|
284
|
+
total: Number(totalRow?.total ?? 0),
|
|
285
|
+
nextCursor: hasMore
|
|
286
|
+
? turns.at(-1)?.queuePosition ?? null
|
|
287
|
+
: null,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
listTimelineTurns(sessionId, options) {
|
|
291
|
+
const limit = Math.max(1, Math.min(50, Math.floor(options.limit)));
|
|
292
|
+
const before = Number.isFinite(options.before)
|
|
293
|
+
? Math.max(1, Math.floor(options.before))
|
|
294
|
+
: Number.MAX_SAFE_INTEGER;
|
|
295
|
+
const contentBudget = Math.max(1, Math.min(1_048_576, Math.floor(options.contentBudgetBytes ?? 1_048_576)));
|
|
296
|
+
const rows = this.database
|
|
297
|
+
.prepare(`SELECT * FROM session_timeline_turns
|
|
298
|
+
WHERE session_id = ? AND timeline_index < ?
|
|
299
|
+
ORDER BY timeline_index DESC
|
|
300
|
+
LIMIT ?`)
|
|
301
|
+
.all(sessionId, before, limit + 1);
|
|
302
|
+
const hasEarlier = rows.length > limit;
|
|
303
|
+
const selectedRows = rows.slice(0, limit).reverse();
|
|
304
|
+
const truncatedBlockIds = [];
|
|
305
|
+
let usedBytes = 0;
|
|
306
|
+
const turns = selectedRows.map((turnRow) => {
|
|
307
|
+
const blockRows = this.database
|
|
308
|
+
.prepare(`SELECT * FROM session_timeline_blocks
|
|
309
|
+
WHERE turn_id = ?
|
|
310
|
+
ORDER BY block_index ASC`)
|
|
311
|
+
.all(String(turnRow.turn_id));
|
|
312
|
+
const blocks = blockRows.map((blockRow) => {
|
|
313
|
+
const segmentRows = this.database
|
|
314
|
+
.prepare(`SELECT * FROM session_output_segments
|
|
315
|
+
WHERE block_id = ?
|
|
316
|
+
ORDER BY segment_index ASC
|
|
317
|
+
LIMIT 101`)
|
|
318
|
+
.all(String(blockRow.block_id));
|
|
319
|
+
const segments = [];
|
|
320
|
+
for (const segmentRow of segmentRows.slice(0, 100)) {
|
|
321
|
+
const byteLength = Number(segmentRow.byte_length);
|
|
322
|
+
if (usedBytes + byteLength > contentBudget)
|
|
323
|
+
break;
|
|
324
|
+
segments.push(toTimelineSegment(segmentRow));
|
|
325
|
+
usedBytes += byteLength;
|
|
326
|
+
}
|
|
327
|
+
const hasMore = segments.length < segmentRows.length;
|
|
328
|
+
if (hasMore)
|
|
329
|
+
truncatedBlockIds.push(String(blockRow.block_id));
|
|
330
|
+
return {
|
|
331
|
+
...toTimelineBlock(blockRow),
|
|
332
|
+
segments,
|
|
333
|
+
nextSegmentCursor: hasMore
|
|
334
|
+
? segments.at(-1)?.segmentIndex ?? -1
|
|
335
|
+
: null,
|
|
336
|
+
};
|
|
337
|
+
});
|
|
338
|
+
return {
|
|
339
|
+
...toTimelineTurn(turnRow),
|
|
340
|
+
blocks,
|
|
341
|
+
};
|
|
342
|
+
});
|
|
343
|
+
return {
|
|
344
|
+
turns,
|
|
345
|
+
previousCursor: hasEarlier
|
|
346
|
+
? turns[0]?.timelineIndex ?? null
|
|
347
|
+
: null,
|
|
348
|
+
truncatedBlockIds,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
listTimelineSegments(blockId, options) {
|
|
352
|
+
const after = Number.isFinite(options.after)
|
|
353
|
+
? Math.floor(options.after)
|
|
354
|
+
: -1;
|
|
355
|
+
const limit = Math.max(1, Math.min(100, Math.floor(options.limit)));
|
|
356
|
+
const rows = this.database
|
|
357
|
+
.prepare(`SELECT * FROM session_output_segments
|
|
358
|
+
WHERE block_id = ? AND segment_index > ?
|
|
359
|
+
ORDER BY segment_index ASC
|
|
360
|
+
LIMIT ?`)
|
|
361
|
+
.all(blockId, after, limit + 1);
|
|
362
|
+
const hasMore = rows.length > limit;
|
|
363
|
+
const segments = rows.slice(0, limit).map(toTimelineSegment);
|
|
364
|
+
return {
|
|
365
|
+
segments,
|
|
366
|
+
nextCursor: hasMore
|
|
367
|
+
? segments.at(-1)?.segmentIndex ?? null
|
|
368
|
+
: null,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
listSessionCommands(sessionId) {
|
|
372
|
+
const rows = this.database
|
|
373
|
+
.prepare(`SELECT name, description, input_json
|
|
374
|
+
FROM session_commands
|
|
375
|
+
WHERE session_id = ?
|
|
376
|
+
ORDER BY name ASC`)
|
|
377
|
+
.all(sessionId);
|
|
378
|
+
return rows.map((row) => {
|
|
379
|
+
const input = row.input_json === null || row.input_json === undefined
|
|
380
|
+
? undefined
|
|
381
|
+
: JSON.parse(String(row.input_json));
|
|
382
|
+
return {
|
|
383
|
+
name: String(row.name),
|
|
384
|
+
description: String(row.description),
|
|
385
|
+
...(input ? { input } : {}),
|
|
386
|
+
};
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
countAllChanges() {
|
|
390
|
+
const row = this.database
|
|
391
|
+
.prepare("SELECT total_changes() AS value")
|
|
392
|
+
.get();
|
|
393
|
+
return Number(row?.value ?? 0);
|
|
394
|
+
}
|
|
395
|
+
getProviderHistoryImport(sessionId, providerSessionId) {
|
|
396
|
+
const row = this.database
|
|
397
|
+
.prepare(`SELECT provider_digest, imported_position, imported_at
|
|
398
|
+
FROM provider_history_imports
|
|
399
|
+
WHERE session_id = ? AND provider_session_id = ?`)
|
|
400
|
+
.get(sessionId, providerSessionId);
|
|
401
|
+
return row
|
|
402
|
+
? {
|
|
403
|
+
providerDigest: String(row.provider_digest),
|
|
404
|
+
importedPosition: Number(row.imported_position),
|
|
405
|
+
importedAt: String(row.imported_at),
|
|
406
|
+
}
|
|
407
|
+
: undefined;
|
|
408
|
+
}
|
|
409
|
+
importProviderHistory(input) {
|
|
410
|
+
return this.withSessionTransaction((tx) => importProviderHistory(tx, input));
|
|
411
|
+
}
|
|
412
|
+
withSessionTransaction(operation) {
|
|
413
|
+
return this.withTransaction(() => {
|
|
414
|
+
const { transaction, deactivate } = createSqliteSessionRuntimeTransaction(this.database);
|
|
415
|
+
try {
|
|
416
|
+
return operation(transaction);
|
|
417
|
+
}
|
|
418
|
+
finally {
|
|
419
|
+
deactivate();
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
withTransaction(operation) {
|
|
424
|
+
if (this.transactionDepth > 0) {
|
|
425
|
+
throw new Error("nested transaction is not supported");
|
|
426
|
+
}
|
|
427
|
+
this.database.exec("BEGIN IMMEDIATE;");
|
|
428
|
+
this.transactionDepth = 1;
|
|
429
|
+
try {
|
|
430
|
+
const result = operation();
|
|
431
|
+
this.database.exec("COMMIT;");
|
|
432
|
+
return result;
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
this.database.exec("ROLLBACK;");
|
|
436
|
+
throw error;
|
|
437
|
+
}
|
|
438
|
+
finally {
|
|
439
|
+
this.transactionDepth = 0;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
previewSessionRuntimeMigration(bindings) {
|
|
443
|
+
const conflicts = [];
|
|
444
|
+
for (const binding of bindings) {
|
|
445
|
+
const activeRuns = this.database
|
|
446
|
+
.prepare(`SELECT id
|
|
447
|
+
FROM runs
|
|
448
|
+
WHERE work_item_id = ?
|
|
449
|
+
AND status IN ('queued', 'running', 'waiting')
|
|
450
|
+
ORDER BY created_at ASC, id ASC`)
|
|
451
|
+
.all(binding.workItemId);
|
|
452
|
+
const activeRunIds = activeRuns.map((row) => String(row.id));
|
|
453
|
+
if (activeRunIds.length > 1) {
|
|
454
|
+
conflicts.push({
|
|
455
|
+
sessionId: binding.sessionId,
|
|
456
|
+
activeRunIds,
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return { conflicts };
|
|
461
|
+
}
|
|
462
|
+
bindWorkItemToSession(sessionId, workItemId) {
|
|
463
|
+
this.withTransaction(() => {
|
|
464
|
+
const workItem = this.database
|
|
465
|
+
.prepare("SELECT session_id FROM work_items WHERE id = ?")
|
|
466
|
+
.get(workItemId);
|
|
467
|
+
if (!workItem) {
|
|
468
|
+
throw new Error(`WorkItem not found: ${workItemId}`);
|
|
469
|
+
}
|
|
470
|
+
const existingBinding = this.database
|
|
471
|
+
.prepare("SELECT id FROM work_items WHERE session_id = ? AND id != ? LIMIT 1")
|
|
472
|
+
.get(sessionId, workItemId);
|
|
473
|
+
if (existingBinding) {
|
|
474
|
+
throw new Error(`Session already bound to another WorkItem: ${sessionId}`);
|
|
475
|
+
}
|
|
476
|
+
if (workItem.session_id !== null
|
|
477
|
+
&& workItem.session_id !== undefined
|
|
478
|
+
&& String(workItem.session_id) !== sessionId) {
|
|
479
|
+
throw new Error(`WorkItem already bound to another Session: ${workItemId}`);
|
|
480
|
+
}
|
|
481
|
+
const now = new Date().toISOString();
|
|
482
|
+
this.database
|
|
483
|
+
.prepare("UPDATE work_items SET session_id = ?, updated_at = ? WHERE id = ?")
|
|
484
|
+
.run(sessionId, now, workItemId);
|
|
485
|
+
this.database
|
|
486
|
+
.prepare(`INSERT INTO session_runtime (
|
|
487
|
+
session_id, active_run_id, queue_state, queue_pause_reason,
|
|
488
|
+
last_event_sequence, version, updated_at
|
|
489
|
+
) VALUES (?, NULL, 'ready', NULL, 0, 1, ?)
|
|
490
|
+
ON CONFLICT(session_id) DO NOTHING`)
|
|
491
|
+
.run(sessionId, now);
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
backfillRunTurns(sessionId, workItemId) {
|
|
495
|
+
return this.withTransaction(() => {
|
|
496
|
+
const runs = this.database
|
|
497
|
+
.prepare(`SELECT *
|
|
498
|
+
FROM runs
|
|
499
|
+
WHERE work_item_id = ?
|
|
500
|
+
ORDER BY created_at ASC, id ASC`)
|
|
501
|
+
.all(workItemId);
|
|
502
|
+
if (runs.length === 0) {
|
|
503
|
+
const events = this.database
|
|
504
|
+
.prepare(`SELECT *
|
|
505
|
+
FROM domain_events
|
|
506
|
+
WHERE work_item_id = ?
|
|
507
|
+
AND type IN ('MESSAGE_RECEIVED', 'AGENT_EVENT')
|
|
508
|
+
ORDER BY sequence ASC`)
|
|
509
|
+
.all(workItemId);
|
|
510
|
+
let activeGroup = false;
|
|
511
|
+
let syntheticCount = 0;
|
|
512
|
+
for (const row of events) {
|
|
513
|
+
const event = toDomainEvent(row);
|
|
514
|
+
if (event.type !== "MESSAGE_RECEIVED" && activeGroup)
|
|
515
|
+
continue;
|
|
516
|
+
const seed = event.type === "MESSAGE_RECEIVED"
|
|
517
|
+
? `message:${event.sequence}`
|
|
518
|
+
: `agent:${event.sequence}`;
|
|
519
|
+
const turnId = createMigrationId("turn", sessionId, seed);
|
|
520
|
+
const runId = createMigrationId("run", sessionId, seed);
|
|
521
|
+
const message = event.type === "MESSAGE_RECEIVED"
|
|
522
|
+
? legacyTurnMessageFromEvent(event)
|
|
523
|
+
: emptyLegacyTurnMessage();
|
|
524
|
+
const run = createLegacySyntheticRun({
|
|
525
|
+
runId,
|
|
526
|
+
turnId,
|
|
527
|
+
workItemId,
|
|
528
|
+
sessionId,
|
|
529
|
+
occurredAt: event.occurredAt,
|
|
530
|
+
});
|
|
531
|
+
upsertLegacyRunTurn(this.database, {
|
|
532
|
+
sessionId,
|
|
533
|
+
workItemId,
|
|
534
|
+
runId,
|
|
535
|
+
turnId,
|
|
536
|
+
queuePosition: syntheticCount + 1,
|
|
537
|
+
message,
|
|
538
|
+
createdAt: event.occurredAt,
|
|
539
|
+
}, run, event.occurredAt);
|
|
540
|
+
syntheticCount += 1;
|
|
541
|
+
activeGroup = true;
|
|
542
|
+
}
|
|
543
|
+
return syntheticCount;
|
|
544
|
+
}
|
|
545
|
+
const messageRows = this.database
|
|
546
|
+
.prepare(`SELECT *
|
|
547
|
+
FROM domain_events
|
|
548
|
+
WHERE work_item_id = ? AND type = 'MESSAGE_RECEIVED'
|
|
549
|
+
ORDER BY sequence ASC`)
|
|
550
|
+
.all(workItemId);
|
|
551
|
+
const explicitMessagesByRunId = new Map();
|
|
552
|
+
const unscopedMessages = [];
|
|
553
|
+
for (const row of messageRows) {
|
|
554
|
+
const message = toDomainEvent(row);
|
|
555
|
+
if (message.runId) {
|
|
556
|
+
explicitMessagesByRunId.set(message.runId, message);
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
unscopedMessages.push(message);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
let unscopedIndex = 0;
|
|
563
|
+
let boundCount = 0;
|
|
564
|
+
for (const [index, row] of runs.entries()) {
|
|
565
|
+
const run = toRun(row);
|
|
566
|
+
const turnEvent = this.database
|
|
567
|
+
.prepare(`SELECT *
|
|
568
|
+
FROM domain_events
|
|
569
|
+
WHERE work_item_id = ? AND run_id = ? AND type = 'TURN_DISPATCHED'
|
|
570
|
+
ORDER BY sequence ASC
|
|
571
|
+
LIMIT 1`)
|
|
572
|
+
.get(workItemId, run.id);
|
|
573
|
+
const messageEvent = explicitMessagesByRunId.get(run.id)
|
|
574
|
+
?? unscopedMessages.at(unscopedIndex++)
|
|
575
|
+
?? undefined;
|
|
576
|
+
const turnId = turnEvent
|
|
577
|
+
? legacyTurnIdFromEvent(sessionId, turnEvent, run.id)
|
|
578
|
+
: run.turnId
|
|
579
|
+
?? (messageEvent
|
|
580
|
+
? createMigrationId("turn", sessionId, `message:${messageEvent.sequence}`)
|
|
581
|
+
: createMigrationId("turn", sessionId, `run:${run.id}`));
|
|
582
|
+
const queuePosition = index + 1;
|
|
583
|
+
const message = messageEvent
|
|
584
|
+
? legacyTurnMessageFromEvent(messageEvent)
|
|
585
|
+
: emptyLegacyTurnMessage();
|
|
586
|
+
upsertLegacyRunTurn(this.database, {
|
|
587
|
+
sessionId,
|
|
588
|
+
workItemId,
|
|
589
|
+
runId: run.id,
|
|
590
|
+
turnId,
|
|
591
|
+
queuePosition,
|
|
592
|
+
message,
|
|
593
|
+
createdAt: messageEvent?.occurredAt === undefined
|
|
594
|
+
? run.createdAt
|
|
595
|
+
: String(messageEvent.occurredAt),
|
|
596
|
+
}, run, turnEvent ? String(turnEvent.occurred_at) : undefined);
|
|
597
|
+
boundCount += 1;
|
|
598
|
+
}
|
|
599
|
+
return boundCount;
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
ensureRuntimeFromRuns(sessionId) {
|
|
603
|
+
return this.withTransaction(() => {
|
|
604
|
+
const current = this.getSessionRuntime(sessionId);
|
|
605
|
+
const runs = this.database
|
|
606
|
+
.prepare(`SELECT *
|
|
607
|
+
FROM runs
|
|
608
|
+
WHERE session_id = ? OR work_item_id IN (
|
|
609
|
+
SELECT id FROM work_items WHERE session_id = ?
|
|
610
|
+
)
|
|
611
|
+
ORDER BY created_at ASC, id ASC`)
|
|
612
|
+
.all(sessionId, sessionId);
|
|
613
|
+
const activeRuns = runs
|
|
614
|
+
.map(toRun)
|
|
615
|
+
.filter((run) => isActiveRunStatus(run.status));
|
|
616
|
+
if (activeRuns.length > 1) {
|
|
617
|
+
const error = new Error("session_runtime_migration_conflict");
|
|
618
|
+
error.conflicts = [{
|
|
619
|
+
sessionId,
|
|
620
|
+
activeRunIds: activeRuns.map((run) => run.id),
|
|
621
|
+
}];
|
|
622
|
+
throw error;
|
|
623
|
+
}
|
|
624
|
+
const latestRun = runs.length > 0
|
|
625
|
+
? toRun(runs.at(-1))
|
|
626
|
+
: undefined;
|
|
627
|
+
const next = activeRuns[0]
|
|
628
|
+
? {
|
|
629
|
+
activeRunId: activeRuns[0].id,
|
|
630
|
+
queueState: "ready",
|
|
631
|
+
queuePauseReason: null,
|
|
632
|
+
}
|
|
633
|
+
: latestRun && (latestRun.status === "failed"
|
|
634
|
+
|| latestRun.status === "cancelled"
|
|
635
|
+
|| latestRun.status === "interrupted")
|
|
636
|
+
? {
|
|
637
|
+
activeRunId: null,
|
|
638
|
+
queueState: "paused",
|
|
639
|
+
queuePauseReason: latestRun.status,
|
|
640
|
+
}
|
|
641
|
+
: {
|
|
642
|
+
activeRunId: current?.activeRunId ?? null,
|
|
643
|
+
queueState: current?.queueState ?? "ready",
|
|
644
|
+
queuePauseReason: current?.queuePauseReason ?? null,
|
|
645
|
+
};
|
|
646
|
+
const now = new Date().toISOString();
|
|
647
|
+
if (current) {
|
|
648
|
+
this.database
|
|
649
|
+
.prepare(`UPDATE session_runtime
|
|
650
|
+
SET active_run_id = ?, queue_state = ?, queue_pause_reason = ?,
|
|
651
|
+
updated_at = ?
|
|
652
|
+
WHERE session_id = ?`)
|
|
653
|
+
.run(next.activeRunId, next.queueState, next.queuePauseReason, now, sessionId);
|
|
654
|
+
}
|
|
655
|
+
else {
|
|
656
|
+
this.database
|
|
657
|
+
.prepare(`INSERT INTO session_runtime (
|
|
658
|
+
session_id, active_run_id, queue_state, queue_pause_reason,
|
|
659
|
+
last_event_sequence, version, updated_at
|
|
660
|
+
) VALUES (?, ?, ?, ?, 0, 1, ?)`)
|
|
661
|
+
.run(sessionId, next.activeRunId, next.queueState, next.queuePauseReason, now);
|
|
662
|
+
}
|
|
663
|
+
return this.getSessionRuntime(sessionId);
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
getProjectionCursor(sessionId) {
|
|
667
|
+
const row = this.database
|
|
668
|
+
.prepare("SELECT last_projected_sequence FROM session_projection_cursors WHERE session_id = ?")
|
|
669
|
+
.get(sessionId);
|
|
670
|
+
return row ? Number(row.last_projected_sequence) : 0;
|
|
671
|
+
}
|
|
672
|
+
backfillSessionProjection(sessionId, workItemId, batchSize) {
|
|
673
|
+
return this.withTransaction(() => {
|
|
674
|
+
const cursor = this.getProjectionCursor(sessionId);
|
|
675
|
+
const boundedBatchSize = Math.max(1, Math.min(1_000, Math.floor(batchSize)));
|
|
676
|
+
const projectionBindings = this.database
|
|
677
|
+
.prepare(`SELECT st.turn_id, st.dispatched_run_id
|
|
678
|
+
FROM session_turns st
|
|
679
|
+
WHERE st.session_id = ?
|
|
680
|
+
AND NOT EXISTS (
|
|
681
|
+
SELECT 1
|
|
682
|
+
FROM domain_events de
|
|
683
|
+
WHERE de.run_id = st.dispatched_run_id
|
|
684
|
+
AND de.type = 'MESSAGE_RECEIVED'
|
|
685
|
+
)
|
|
686
|
+
ORDER BY queue_position ASC, turn_id ASC`)
|
|
687
|
+
.all(sessionId);
|
|
688
|
+
const priorUnscopedMessages = this.database
|
|
689
|
+
.prepare(`SELECT COUNT(*) AS count
|
|
690
|
+
FROM domain_events
|
|
691
|
+
WHERE work_item_id = ? AND type = 'MESSAGE_RECEIVED'
|
|
692
|
+
AND run_id IS NULL AND sequence <= ?`)
|
|
693
|
+
.get(workItemId, cursor);
|
|
694
|
+
const bindings = projectionBindings.map((row) => ({
|
|
695
|
+
turnId: String(row.turn_id),
|
|
696
|
+
runId: String(row.dispatched_run_id),
|
|
697
|
+
}));
|
|
698
|
+
const bindingIndex = Number(priorUnscopedMessages?.count ?? 0);
|
|
699
|
+
const bindingState = {
|
|
700
|
+
index: bindingIndex,
|
|
701
|
+
bindings,
|
|
702
|
+
};
|
|
703
|
+
const priorUnscopedMessageRow = bindingIndex > 0
|
|
704
|
+
? this.database
|
|
705
|
+
.prepare(`SELECT *
|
|
706
|
+
FROM domain_events
|
|
707
|
+
WHERE work_item_id = ? AND type = 'MESSAGE_RECEIVED'
|
|
708
|
+
AND run_id IS NULL AND sequence <= ?
|
|
709
|
+
ORDER BY sequence DESC
|
|
710
|
+
LIMIT 1`)
|
|
711
|
+
.get(workItemId, cursor)
|
|
712
|
+
: undefined;
|
|
713
|
+
const rows = this.database
|
|
714
|
+
.prepare(`SELECT *
|
|
715
|
+
FROM domain_events
|
|
716
|
+
WHERE work_item_id = ? AND sequence > ?
|
|
717
|
+
ORDER BY sequence ASC
|
|
718
|
+
LIMIT ?`)
|
|
719
|
+
.all(workItemId, cursor, boundedBatchSize);
|
|
720
|
+
if (!rows.length) {
|
|
721
|
+
return 0;
|
|
722
|
+
}
|
|
723
|
+
const priorBinding = bindingIndex > 0
|
|
724
|
+
? bindings.at(bindingIndex - 1)
|
|
725
|
+
: undefined;
|
|
726
|
+
const priorMessage = priorUnscopedMessageRow
|
|
727
|
+
? toDomainEvent(priorUnscopedMessageRow)
|
|
728
|
+
: undefined;
|
|
729
|
+
let currentSynthetic = priorBinding
|
|
730
|
+
? {
|
|
731
|
+
...priorBinding,
|
|
732
|
+
queuePosition: bindingIndex,
|
|
733
|
+
}
|
|
734
|
+
: priorMessage
|
|
735
|
+
? {
|
|
736
|
+
runId: createMigrationId("run", sessionId, `message:${priorMessage.sequence}`),
|
|
737
|
+
turnId: createMigrationId("turn", sessionId, `message:${priorMessage.sequence}`),
|
|
738
|
+
queuePosition: bindingIndex,
|
|
739
|
+
}
|
|
740
|
+
: null;
|
|
741
|
+
let projected = 0;
|
|
742
|
+
for (const row of rows) {
|
|
743
|
+
const event = toDomainEvent(row);
|
|
744
|
+
const projectedEvent = normalizeLegacyProjectionEvent(this.database, sessionId, event, currentSynthetic, bindingState);
|
|
745
|
+
currentSynthetic = projectedEvent.syntheticGroup ?? currentSynthetic;
|
|
746
|
+
projectSessionEvent(this.database, sessionId, projectedEvent.event);
|
|
747
|
+
projected += 1;
|
|
748
|
+
}
|
|
749
|
+
return projected;
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
listWorkItems() {
|
|
753
|
+
const rows = this.database
|
|
754
|
+
.prepare("SELECT * FROM work_items ORDER BY updated_at DESC, rowid ASC")
|
|
755
|
+
.all();
|
|
756
|
+
return rows.map(toWorkItem);
|
|
757
|
+
}
|
|
758
|
+
appendEvent(input) {
|
|
759
|
+
if (!this.getWorkItem(input.workItemId)) {
|
|
760
|
+
throw new Error(`WorkItem not found: ${input.workItemId}`);
|
|
761
|
+
}
|
|
762
|
+
return this.withTransaction(() => {
|
|
763
|
+
const event = this.appendEventInTransaction(input);
|
|
764
|
+
return event;
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
appendLeasedRunEvent(owner, input) {
|
|
768
|
+
return this.withTransaction(() => {
|
|
769
|
+
const lease = this.database
|
|
770
|
+
.prepare(`SELECT 1 FROM runs
|
|
771
|
+
WHERE id = ? AND session_id = ? AND status = 'running'
|
|
772
|
+
AND lease_owner = ? AND lease_expires_at >= ?`)
|
|
773
|
+
.get(input.runId, input.sessionId, owner, new Date().toISOString());
|
|
774
|
+
if (!lease)
|
|
775
|
+
throw new Error("run_lease_lost");
|
|
776
|
+
const event = appendSessionEventInTransaction(this.database, input);
|
|
777
|
+
return event;
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
appendEventOnce(input) {
|
|
781
|
+
if (!this.getWorkItem(input.workItemId)) {
|
|
782
|
+
throw new Error(`WorkItem not found: ${input.workItemId}`);
|
|
783
|
+
}
|
|
784
|
+
return this.withTransaction(() => {
|
|
785
|
+
const existing = this.database
|
|
786
|
+
.prepare("SELECT * FROM domain_events WHERE work_item_id = ? AND input_hash = ? LIMIT 1")
|
|
787
|
+
.get(input.workItemId, input.inputHash);
|
|
788
|
+
const event = existing ? toDomainEvent(existing) : this.appendEventInTransaction(input);
|
|
789
|
+
return event;
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
listEvents(workItemId, afterSequence = 0) {
|
|
793
|
+
const rows = this.database
|
|
794
|
+
.prepare(`SELECT * FROM domain_events
|
|
795
|
+
WHERE work_item_id = ? AND sequence > ?
|
|
796
|
+
ORDER BY sequence ASC`)
|
|
797
|
+
.all(workItemId, afterSequence);
|
|
798
|
+
return rows.map(toDomainEvent);
|
|
799
|
+
}
|
|
800
|
+
listEventsByTarget(target) {
|
|
801
|
+
const rows = this.database
|
|
802
|
+
.prepare(`SELECT * FROM domain_events
|
|
803
|
+
WHERE target = ?
|
|
804
|
+
ORDER BY sequence ASC`)
|
|
805
|
+
.all(target);
|
|
806
|
+
return rows.map(toDomainEvent);
|
|
807
|
+
}
|
|
808
|
+
listEventsPage(workItemId, afterSequence, limit) {
|
|
809
|
+
const boundedLimit = Math.max(1, Math.min(501, Math.floor(limit)));
|
|
810
|
+
const rows = this.database
|
|
811
|
+
.prepare(`SELECT * FROM domain_events
|
|
812
|
+
WHERE work_item_id = ? AND sequence > ?
|
|
813
|
+
ORDER BY sequence ASC
|
|
814
|
+
LIMIT ?`)
|
|
815
|
+
.all(workItemId, afterSequence, boundedLimit);
|
|
816
|
+
return rows.map(toDomainEvent);
|
|
817
|
+
}
|
|
818
|
+
listRecentEvents(workItemId, limit) {
|
|
819
|
+
const boundedLimit = Math.max(1, Math.min(10_000, Math.floor(limit)));
|
|
820
|
+
const rows = this.database
|
|
821
|
+
.prepare(`SELECT * FROM domain_events
|
|
822
|
+
WHERE work_item_id = ?
|
|
823
|
+
ORDER BY sequence DESC
|
|
824
|
+
LIMIT ?`)
|
|
825
|
+
.all(workItemId, boundedLimit);
|
|
826
|
+
return rows.reverse().map(toDomainEvent);
|
|
827
|
+
}
|
|
828
|
+
listEventInputHashes(workItemId) {
|
|
829
|
+
const rows = this.database
|
|
830
|
+
.prepare(`SELECT input_hash FROM domain_events
|
|
831
|
+
WHERE work_item_id = ? AND input_hash IS NOT NULL`)
|
|
832
|
+
.all(workItemId);
|
|
833
|
+
return new Set(rows.map((row) => String(row.input_hash)));
|
|
834
|
+
}
|
|
835
|
+
sequenceForEventId(workItemId, eventId) {
|
|
836
|
+
const row = this.database
|
|
837
|
+
.prepare("SELECT sequence FROM domain_events WHERE work_item_id = ? AND event_id = ?")
|
|
838
|
+
.get(workItemId, eventId);
|
|
839
|
+
return row?.sequence ? Number(row.sequence) : 0;
|
|
840
|
+
}
|
|
841
|
+
savePlan(input) {
|
|
842
|
+
const plan = {
|
|
843
|
+
schemaVersion: 1,
|
|
844
|
+
planId: input.planId,
|
|
845
|
+
source: input.source,
|
|
846
|
+
workflowId: input.workflowId,
|
|
847
|
+
definitionRevision: input.definitionRevision,
|
|
848
|
+
planIrHash: input.planIrHash ?? null,
|
|
849
|
+
sessionId: input.sessionId ?? null,
|
|
850
|
+
runId: input.runId ?? null,
|
|
851
|
+
steps: input.steps.map(clonePlanStep),
|
|
852
|
+
createdAt: new Date().toISOString(),
|
|
853
|
+
};
|
|
854
|
+
this.database
|
|
855
|
+
.prepare(`INSERT INTO plans (
|
|
856
|
+
plan_id, schema_version, source, workflow_id, definition_revision,
|
|
857
|
+
plan_ir_hash, session_id, run_id, steps, created_at
|
|
858
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
859
|
+
ON CONFLICT(plan_id) DO UPDATE SET
|
|
860
|
+
source = excluded.source,
|
|
861
|
+
workflow_id = excluded.workflow_id,
|
|
862
|
+
definition_revision = excluded.definition_revision,
|
|
863
|
+
plan_ir_hash = excluded.plan_ir_hash,
|
|
864
|
+
session_id = excluded.session_id,
|
|
865
|
+
run_id = excluded.run_id,
|
|
866
|
+
steps = excluded.steps`)
|
|
867
|
+
.run(plan.planId, plan.schemaVersion, plan.source, plan.workflowId, plan.definitionRevision, plan.planIrHash, plan.sessionId, plan.runId, JSON.stringify(plan.steps), plan.createdAt);
|
|
868
|
+
return this.getPlan(plan.planId);
|
|
869
|
+
}
|
|
870
|
+
getPlan(planId) {
|
|
871
|
+
const row = this.database.prepare("SELECT * FROM plans WHERE plan_id = ?").get(planId);
|
|
872
|
+
return row ? toPlan(row) : undefined;
|
|
873
|
+
}
|
|
874
|
+
getPlanForRun(runId) {
|
|
875
|
+
const row = this.database.prepare("SELECT * FROM plans WHERE run_id = ?").get(runId);
|
|
876
|
+
return row ? toPlan(row) : undefined;
|
|
877
|
+
}
|
|
878
|
+
createRun(input) {
|
|
879
|
+
const workItem = this.getWorkItem(input.workItemId);
|
|
880
|
+
if (!workItem) {
|
|
881
|
+
throw new Error(`WorkItem not found: ${input.workItemId}`);
|
|
882
|
+
}
|
|
883
|
+
const plan = input.planId ? this.getPlan(input.planId) : undefined;
|
|
884
|
+
if (input.planId && !plan) {
|
|
885
|
+
throw new Error(`Plan not found: ${input.planId}`);
|
|
886
|
+
}
|
|
887
|
+
if (plan?.runId && input.id && plan.runId !== input.id) {
|
|
888
|
+
throw new Error(`Plan ${plan.planId} is bound to another Run`);
|
|
889
|
+
}
|
|
890
|
+
const now = new Date().toISOString();
|
|
891
|
+
const run = {
|
|
892
|
+
schemaVersion: 1,
|
|
893
|
+
id: input.id ?? createId("run"),
|
|
894
|
+
workItemId: input.workItemId,
|
|
895
|
+
sessionId: input.sessionId ?? workItem.sessionId,
|
|
896
|
+
turnId: input.turnId ?? null,
|
|
897
|
+
mode: input.mode,
|
|
898
|
+
status: "queued",
|
|
899
|
+
executionKind: input.executionKind,
|
|
900
|
+
agentId: input.agentId ?? workItem.agentId,
|
|
901
|
+
planId: input.planId ?? null,
|
|
902
|
+
planIrHash: input.planIrHash ?? plan?.planIrHash ?? null,
|
|
903
|
+
workflowRevision: input.workflowRevision ?? plan?.definitionRevision ?? workItem.workflowRevision,
|
|
904
|
+
terminalReason: null,
|
|
905
|
+
replaySafety: "safe",
|
|
906
|
+
leaseOwner: null,
|
|
907
|
+
leaseExpiresAt: null,
|
|
908
|
+
cancelRequestedAt: null,
|
|
909
|
+
cancelDeadlineAt: null,
|
|
910
|
+
providerSessionId: input.providerSessionId ?? null,
|
|
911
|
+
createdAt: now,
|
|
912
|
+
updatedAt: now,
|
|
913
|
+
};
|
|
914
|
+
this.withTransaction(() => {
|
|
915
|
+
this.database
|
|
916
|
+
.prepare(`INSERT INTO runs (
|
|
917
|
+
id, schema_version, work_item_id, session_id, turn_id, mode, status,
|
|
918
|
+
execution_kind, agent_id, plan_id, plan_ir_hash, workflow_revision, terminal_reason,
|
|
919
|
+
replay_safety, lease_owner, lease_expires_at, cancel_requested_at,
|
|
920
|
+
cancel_deadline_at, provider_session_id, created_at, updated_at
|
|
921
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
922
|
+
.run(run.id, run.schemaVersion, run.workItemId, run.sessionId, run.turnId, run.mode, run.status, run.executionKind, run.agentId, run.planId, run.planIrHash, run.workflowRevision, run.terminalReason, run.replaySafety, run.leaseOwner, run.leaseExpiresAt, run.cancelRequestedAt, run.cancelDeadlineAt, run.providerSessionId ?? null, run.createdAt, run.updatedAt);
|
|
923
|
+
this.appendEventInTransaction({
|
|
924
|
+
workItemId: run.workItemId,
|
|
925
|
+
runId: run.id,
|
|
926
|
+
type: "RUN_CREATED",
|
|
927
|
+
actor: "system",
|
|
928
|
+
target: run.id,
|
|
929
|
+
payload: {
|
|
930
|
+
mode: run.mode,
|
|
931
|
+
agent_id: run.agentId,
|
|
932
|
+
plan_id: run.planId,
|
|
933
|
+
workflow_revision: run.workflowRevision,
|
|
934
|
+
execution_kind: run.executionKind,
|
|
935
|
+
},
|
|
936
|
+
});
|
|
937
|
+
if (plan) {
|
|
938
|
+
this.appendEventInTransaction({
|
|
939
|
+
workItemId: run.workItemId,
|
|
940
|
+
runId: run.id,
|
|
941
|
+
type: "PLAN_VALIDATED",
|
|
942
|
+
actor: "system",
|
|
943
|
+
target: plan.planId,
|
|
944
|
+
payload: {
|
|
945
|
+
workflow_id: plan.workflowId,
|
|
946
|
+
definition_revision: plan.definitionRevision,
|
|
947
|
+
source: plan.source,
|
|
948
|
+
step_count: plan.steps.length,
|
|
949
|
+
},
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
return run;
|
|
954
|
+
}
|
|
955
|
+
getRun(runId) {
|
|
956
|
+
const row = this.database.prepare("SELECT * FROM runs WHERE id = ?").get(runId);
|
|
957
|
+
return row ? toRun(row) : undefined;
|
|
958
|
+
}
|
|
959
|
+
listRuns(workItemId) {
|
|
960
|
+
const rows = this.database
|
|
961
|
+
.prepare("SELECT * FROM runs WHERE work_item_id = ? ORDER BY created_at ASC")
|
|
962
|
+
.all(workItemId);
|
|
963
|
+
return rows.map(toRun);
|
|
964
|
+
}
|
|
965
|
+
listRunsByStatus(statuses) {
|
|
966
|
+
if (!statuses.length)
|
|
967
|
+
return [];
|
|
968
|
+
const placeholders = statuses.map(() => "?").join(", ");
|
|
969
|
+
const rows = this.database
|
|
970
|
+
.prepare(`SELECT * FROM runs WHERE status IN (${placeholders}) ORDER BY created_at ASC`)
|
|
971
|
+
.all(...statuses);
|
|
972
|
+
return rows.map(toRun);
|
|
973
|
+
}
|
|
974
|
+
updateRunStatus(runId, status) {
|
|
975
|
+
const now = new Date().toISOString();
|
|
976
|
+
const result = this.database
|
|
977
|
+
.prepare("UPDATE runs SET status = ?, updated_at = ? WHERE id = ?")
|
|
978
|
+
.run(status, now, runId);
|
|
979
|
+
if (Number(result.changes) !== 1)
|
|
980
|
+
throw new Error(`Run not found: ${runId}`);
|
|
981
|
+
return this.getRun(runId);
|
|
982
|
+
}
|
|
983
|
+
updateRunControl(runId, patch) {
|
|
984
|
+
const current = this.getRun(runId);
|
|
985
|
+
if (!current)
|
|
986
|
+
throw new Error(`Run not found: ${runId}`);
|
|
987
|
+
const next = {
|
|
988
|
+
...current,
|
|
989
|
+
...patch,
|
|
990
|
+
updatedAt: new Date().toISOString(),
|
|
991
|
+
};
|
|
992
|
+
this.database
|
|
993
|
+
.prepare(`UPDATE runs
|
|
994
|
+
SET status = ?, terminal_reason = ?, replay_safety = ?,
|
|
995
|
+
lease_owner = ?, lease_expires_at = ?, cancel_requested_at = ?,
|
|
996
|
+
cancel_deadline_at = ?, updated_at = ?
|
|
997
|
+
WHERE id = ?`)
|
|
998
|
+
.run(next.status, next.terminalReason, next.replaySafety, next.leaseOwner, next.leaseExpiresAt, next.cancelRequestedAt, next.cancelDeadlineAt, next.updatedAt, runId);
|
|
999
|
+
return this.getRun(runId);
|
|
1000
|
+
}
|
|
1001
|
+
claimRun(runId, owner, now, expiresAt) {
|
|
1002
|
+
return this.withSessionTransaction((tx) => tx.claimRun(runId, owner, now, expiresAt));
|
|
1003
|
+
}
|
|
1004
|
+
renewRunLease(runId, owner, now, expiresAt) {
|
|
1005
|
+
return this.withSessionTransaction((tx) => tx.renewRunLease(runId, owner, now, expiresAt));
|
|
1006
|
+
}
|
|
1007
|
+
reclaimRunLease(runId, owner, expiresAt) {
|
|
1008
|
+
return this.withSessionTransaction((tx) => tx.reclaimRunLease(runId, owner, expiresAt));
|
|
1009
|
+
}
|
|
1010
|
+
updateLeasedRunReplaySafety(runId, owner, replaySafety) {
|
|
1011
|
+
const now = new Date().toISOString();
|
|
1012
|
+
const result = this.database
|
|
1013
|
+
.prepare(`UPDATE runs
|
|
1014
|
+
SET replay_safety = ?, updated_at = ?
|
|
1015
|
+
WHERE id = ? AND status = 'running' AND lease_owner = ?
|
|
1016
|
+
AND lease_expires_at >= ?`)
|
|
1017
|
+
.run(replaySafety, now, runId, owner, now);
|
|
1018
|
+
if (Number(result.changes) !== 1) {
|
|
1019
|
+
throw new Error("run_lease_lost");
|
|
1020
|
+
}
|
|
1021
|
+
return this.getRun(runId);
|
|
1022
|
+
}
|
|
1023
|
+
listExpiredRunningRuns(now, limit) {
|
|
1024
|
+
return createSqliteSessionRuntimeTransaction(this.database)
|
|
1025
|
+
.transaction.listExpiredRunningRuns(now, limit);
|
|
1026
|
+
}
|
|
1027
|
+
listCancellationDeadlineRuns(now, limit) {
|
|
1028
|
+
return createSqliteSessionRuntimeTransaction(this.database)
|
|
1029
|
+
.transaction.listCancellationDeadlineRuns(now, limit);
|
|
1030
|
+
}
|
|
1031
|
+
listDeliveries(channel, surfaceMessageId) {
|
|
1032
|
+
return createSqliteSessionRuntimeTransaction(this.database)
|
|
1033
|
+
.transaction.listDeliveries(channel, surfaceMessageId);
|
|
1034
|
+
}
|
|
1035
|
+
claimProviderSession(input) {
|
|
1036
|
+
return this.withSessionTransaction((tx) => tx.claimProviderSession(input));
|
|
1037
|
+
}
|
|
1038
|
+
renewProviderSession(input) {
|
|
1039
|
+
return this.withSessionTransaction((tx) => tx.renewProviderSession(input));
|
|
1040
|
+
}
|
|
1041
|
+
releaseProviderSession(input) {
|
|
1042
|
+
return this.withSessionTransaction((tx) => tx.releaseProviderSession(input));
|
|
1043
|
+
}
|
|
1044
|
+
findLiveProviderLease(agentId, providerSessionId, now) {
|
|
1045
|
+
return createSqliteSessionRuntimeTransaction(this.database)
|
|
1046
|
+
.transaction.findLiveProviderLease(agentId, providerSessionId, now);
|
|
1047
|
+
}
|
|
1048
|
+
setSessionProviderSessionId(sessionId, providerSessionId) {
|
|
1049
|
+
this.withSessionTransaction((tx) => tx.setSessionProviderSessionId(sessionId, providerSessionId));
|
|
1050
|
+
}
|
|
1051
|
+
startRunAttempt(runId) {
|
|
1052
|
+
if (!this.getRun(runId))
|
|
1053
|
+
throw new Error(`Run not found: ${runId}`);
|
|
1054
|
+
return this.withTransaction(() => {
|
|
1055
|
+
const row = this.database
|
|
1056
|
+
.prepare(`SELECT COALESCE(MAX(attempt_number), 0) + 1 AS next_attempt
|
|
1057
|
+
FROM run_attempts WHERE run_id = ?`)
|
|
1058
|
+
.get(runId);
|
|
1059
|
+
const attemptId = `attempt_${randomUUID().replaceAll("-", "")}`;
|
|
1060
|
+
this.database
|
|
1061
|
+
.prepare(`INSERT INTO run_attempts (
|
|
1062
|
+
attempt_id, run_id, attempt_number, started_at, ended_at,
|
|
1063
|
+
provider_error, side_effect_boundary
|
|
1064
|
+
) VALUES (?, ?, ?, ?, NULL, NULL, 'safe')`)
|
|
1065
|
+
.run(attemptId, runId, Number(row?.next_attempt ?? 1), new Date().toISOString());
|
|
1066
|
+
const attempt = this.database
|
|
1067
|
+
.prepare("SELECT * FROM run_attempts WHERE attempt_id = ?")
|
|
1068
|
+
.get(attemptId);
|
|
1069
|
+
return toRunAttempt(attempt);
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
finishRunAttempt(attemptId, input) {
|
|
1073
|
+
const result = this.database
|
|
1074
|
+
.prepare(`UPDATE run_attempts
|
|
1075
|
+
SET ended_at = ?, provider_error = ?,
|
|
1076
|
+
side_effect_boundary = ?
|
|
1077
|
+
WHERE attempt_id = ? AND ended_at IS NULL`)
|
|
1078
|
+
.run(new Date().toISOString(), input.providerError, input.sideEffectBoundary, attemptId);
|
|
1079
|
+
if (Number(result.changes) !== 1) {
|
|
1080
|
+
throw new Error(`Open Run attempt not found: ${attemptId}`);
|
|
1081
|
+
}
|
|
1082
|
+
const row = this.database
|
|
1083
|
+
.prepare("SELECT * FROM run_attempts WHERE attempt_id = ?")
|
|
1084
|
+
.get(attemptId);
|
|
1085
|
+
return toRunAttempt(row);
|
|
1086
|
+
}
|
|
1087
|
+
listRunAttempts(runId) {
|
|
1088
|
+
const rows = this.database
|
|
1089
|
+
.prepare(`SELECT * FROM run_attempts
|
|
1090
|
+
WHERE run_id = ? ORDER BY attempt_number ASC`)
|
|
1091
|
+
.all(runId);
|
|
1092
|
+
return rows.map(toRunAttempt);
|
|
1093
|
+
}
|
|
1094
|
+
findTerminalEventForRun(runId) {
|
|
1095
|
+
const row = this.database
|
|
1096
|
+
.prepare(`SELECT * FROM domain_events
|
|
1097
|
+
WHERE run_id = ?
|
|
1098
|
+
AND type IN (
|
|
1099
|
+
'RUN_SUCCEEDED', 'RUN_FAILED',
|
|
1100
|
+
'RUN_CANCELLED', 'RUN_INTERRUPTED'
|
|
1101
|
+
)
|
|
1102
|
+
ORDER BY sequence DESC
|
|
1103
|
+
LIMIT 1`)
|
|
1104
|
+
.get(runId);
|
|
1105
|
+
return row ? toDomainEvent(row) : undefined;
|
|
1106
|
+
}
|
|
1107
|
+
requeueRun(runId) {
|
|
1108
|
+
return this.updateRunStatus(runId, "queued");
|
|
1109
|
+
}
|
|
1110
|
+
putIdempotencyResponse(namespace, key, response, createdAt) {
|
|
1111
|
+
this.database
|
|
1112
|
+
.prepare(`INSERT OR IGNORE INTO idempotency_responses
|
|
1113
|
+
(namespace, idempotency_key, response, created_at) VALUES (?, ?, ?, ?)`)
|
|
1114
|
+
.run(namespace, key, JSON.stringify(response), createdAt ?? new Date().toISOString());
|
|
1115
|
+
}
|
|
1116
|
+
getIdempotencyRecord(namespace, key) {
|
|
1117
|
+
const row = this.database
|
|
1118
|
+
.prepare("SELECT response, created_at FROM idempotency_responses WHERE namespace = ? AND idempotency_key = ?")
|
|
1119
|
+
.get(namespace, key);
|
|
1120
|
+
if (!row?.response)
|
|
1121
|
+
return undefined;
|
|
1122
|
+
return { response: JSON.parse(row.response), createdAt: row.created_at ?? "" };
|
|
1123
|
+
}
|
|
1124
|
+
getIdempotencyResponse(namespace, key) {
|
|
1125
|
+
return this.getIdempotencyRecord(namespace, key)?.response;
|
|
1126
|
+
}
|
|
1127
|
+
deleteIdempotencyResponse(namespace, key) {
|
|
1128
|
+
this.database
|
|
1129
|
+
.prepare("DELETE FROM idempotency_responses WHERE namespace = ? AND idempotency_key = ?")
|
|
1130
|
+
.run(namespace, key);
|
|
1131
|
+
}
|
|
1132
|
+
createMessageAttachment(input) {
|
|
1133
|
+
if (!this.getWorkItem(input.workItemId))
|
|
1134
|
+
throw new Error(`WorkItem not found: ${input.workItemId}`);
|
|
1135
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(input.dataBase64) || input.dataBase64.length % 4 === 1) {
|
|
1136
|
+
throw new Error("attachment data must be valid base64");
|
|
1137
|
+
}
|
|
1138
|
+
const bytes = Buffer.from(input.dataBase64, "base64");
|
|
1139
|
+
if (bytes.length === 0)
|
|
1140
|
+
throw new Error("attachment data cannot be empty");
|
|
1141
|
+
if (bytes.length > 10_000_000)
|
|
1142
|
+
throw new Error("attachment content exceeds 10 MB");
|
|
1143
|
+
const record = {
|
|
1144
|
+
schemaVersion: 1,
|
|
1145
|
+
id: input.id ?? createId("attachment"),
|
|
1146
|
+
workItemId: input.workItemId,
|
|
1147
|
+
name: path.basename(input.name || "attachment"),
|
|
1148
|
+
mimeType: input.mimeType || "application/octet-stream",
|
|
1149
|
+
dataBase64: input.dataBase64,
|
|
1150
|
+
byteSize: bytes.length,
|
|
1151
|
+
contentHash: `sha256:${createHash("sha256").update(bytes).digest("hex")}`,
|
|
1152
|
+
createdAt: new Date().toISOString(),
|
|
1153
|
+
};
|
|
1154
|
+
this.database
|
|
1155
|
+
.prepare(`INSERT INTO message_attachments (
|
|
1156
|
+
id, schema_version, work_item_id, name, mime_type, data_base64,
|
|
1157
|
+
byte_size, content_hash, created_at
|
|
1158
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
1159
|
+
.run(record.id, record.schemaVersion, record.workItemId, record.name, record.mimeType, record.dataBase64, record.byteSize, record.contentHash, record.createdAt);
|
|
1160
|
+
return record;
|
|
1161
|
+
}
|
|
1162
|
+
getMessageAttachment(id) {
|
|
1163
|
+
const row = this.database.prepare("SELECT * FROM message_attachments WHERE id = ?").get(id);
|
|
1164
|
+
return row ? toMessageAttachment(row) : undefined;
|
|
1165
|
+
}
|
|
1166
|
+
listMessageAttachments(workItemId, ids) {
|
|
1167
|
+
const rows = this.database
|
|
1168
|
+
.prepare("SELECT * FROM message_attachments WHERE work_item_id = ? ORDER BY created_at ASC")
|
|
1169
|
+
.all(workItemId);
|
|
1170
|
+
const attachments = rows.map(toMessageAttachment);
|
|
1171
|
+
if (!ids)
|
|
1172
|
+
return attachments;
|
|
1173
|
+
const byId = new Map(attachments.map((attachment) => [attachment.id, attachment]));
|
|
1174
|
+
return ids.flatMap((id) => {
|
|
1175
|
+
const attachment = byId.get(id);
|
|
1176
|
+
return attachment ? [attachment] : [];
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
createArtifact(input) {
|
|
1180
|
+
if (!this.getWorkItem(input.workItemId))
|
|
1181
|
+
throw new Error(`WorkItem not found: ${input.workItemId}`);
|
|
1182
|
+
if (!this.getRun(input.runId))
|
|
1183
|
+
throw new Error(`Run not found: ${input.runId}`);
|
|
1184
|
+
if (input.content.length > 10_000_000)
|
|
1185
|
+
throw new Error("artifact content exceeds 10 MB");
|
|
1186
|
+
const record = {
|
|
1187
|
+
id: input.id ?? createId("artifact"),
|
|
1188
|
+
workItemId: input.workItemId,
|
|
1189
|
+
runId: input.runId,
|
|
1190
|
+
stepId: input.stepId ?? null,
|
|
1191
|
+
kind: input.kind ?? "output",
|
|
1192
|
+
name: input.name,
|
|
1193
|
+
mimeType: input.mimeType ?? "text/plain",
|
|
1194
|
+
content: input.content,
|
|
1195
|
+
contentHash: `sha256:${createHash("sha256").update(input.content).digest("hex")}`,
|
|
1196
|
+
metadata: { ...(input.metadata ?? {}) },
|
|
1197
|
+
createdAt: new Date().toISOString(),
|
|
1198
|
+
};
|
|
1199
|
+
this.database
|
|
1200
|
+
.prepare(`INSERT INTO artifacts (
|
|
1201
|
+
id, work_item_id, run_id, step_id, kind, name, mime_type, content,
|
|
1202
|
+
content_hash, metadata, created_at
|
|
1203
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
1204
|
+
.run(record.id, record.workItemId, record.runId, record.stepId, record.kind, record.name, record.mimeType, record.content, record.contentHash, JSON.stringify(record.metadata), record.createdAt);
|
|
1205
|
+
this.appendEvent({
|
|
1206
|
+
workItemId: record.workItemId,
|
|
1207
|
+
runId: record.runId,
|
|
1208
|
+
type: "ARTIFACT_CREATED",
|
|
1209
|
+
actor: input.actor ?? "adapter",
|
|
1210
|
+
target: record.id,
|
|
1211
|
+
resultRef: `artifact://${record.id}`,
|
|
1212
|
+
payload: {
|
|
1213
|
+
artifact_id: record.id,
|
|
1214
|
+
step_id: record.stepId,
|
|
1215
|
+
kind: record.kind,
|
|
1216
|
+
name: record.name,
|
|
1217
|
+
mime_type: record.mimeType,
|
|
1218
|
+
content_hash: record.contentHash,
|
|
1219
|
+
},
|
|
1220
|
+
});
|
|
1221
|
+
return record;
|
|
1222
|
+
}
|
|
1223
|
+
getArtifact(id) {
|
|
1224
|
+
const row = this.database.prepare("SELECT * FROM artifacts WHERE id = ?").get(id);
|
|
1225
|
+
return row ? toArtifact(row) : undefined;
|
|
1226
|
+
}
|
|
1227
|
+
listArtifacts(runId) {
|
|
1228
|
+
return this.database.prepare("SELECT * FROM artifacts WHERE run_id = ? ORDER BY created_at ASC").all(runId).map(toArtifact);
|
|
1229
|
+
}
|
|
1230
|
+
recordVerification(input) {
|
|
1231
|
+
if (!this.getWorkItem(input.workItemId))
|
|
1232
|
+
throw new Error(`WorkItem not found: ${input.workItemId}`);
|
|
1233
|
+
if (!this.getRun(input.runId))
|
|
1234
|
+
throw new Error(`Run not found: ${input.runId}`);
|
|
1235
|
+
const record = {
|
|
1236
|
+
id: input.id ?? createId("verification"),
|
|
1237
|
+
workItemId: input.workItemId,
|
|
1238
|
+
runId: input.runId,
|
|
1239
|
+
stepId: input.stepId ?? null,
|
|
1240
|
+
validator: input.validator,
|
|
1241
|
+
status: input.status,
|
|
1242
|
+
summary: input.summary,
|
|
1243
|
+
artifactIds: [...(input.artifactIds ?? [])],
|
|
1244
|
+
createdAt: new Date().toISOString(),
|
|
1245
|
+
};
|
|
1246
|
+
this.database
|
|
1247
|
+
.prepare(`INSERT INTO verifications (
|
|
1248
|
+
id, work_item_id, run_id, step_id, validator, status, summary,
|
|
1249
|
+
artifact_ids, created_at
|
|
1250
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
1251
|
+
.run(record.id, record.workItemId, record.runId, record.stepId, record.validator, record.status, record.summary, JSON.stringify(record.artifactIds), record.createdAt);
|
|
1252
|
+
this.appendEvent({
|
|
1253
|
+
workItemId: record.workItemId,
|
|
1254
|
+
runId: record.runId,
|
|
1255
|
+
type: "VERIFICATION_COMPLETED",
|
|
1256
|
+
actor: "adapter",
|
|
1257
|
+
target: record.stepId ?? record.runId,
|
|
1258
|
+
resultRef: record.artifactIds[0] ? `artifact://${record.artifactIds[0]}` : null,
|
|
1259
|
+
payload: {
|
|
1260
|
+
verification_id: record.id,
|
|
1261
|
+
step_id: record.stepId,
|
|
1262
|
+
validator: record.validator,
|
|
1263
|
+
status: record.status,
|
|
1264
|
+
summary: record.summary,
|
|
1265
|
+
artifact_ids: record.artifactIds,
|
|
1266
|
+
},
|
|
1267
|
+
});
|
|
1268
|
+
return record;
|
|
1269
|
+
}
|
|
1270
|
+
listVerifications(runId) {
|
|
1271
|
+
return this.database.prepare("SELECT * FROM verifications WHERE run_id = ? ORDER BY created_at ASC").all(runId).map(toVerification);
|
|
1272
|
+
}
|
|
1273
|
+
close() {
|
|
1274
|
+
if (this.database.isOpen)
|
|
1275
|
+
this.database.close();
|
|
1276
|
+
}
|
|
1277
|
+
appendEventInTransaction(input) {
|
|
1278
|
+
const workItem = this.database
|
|
1279
|
+
.prepare("SELECT session_id FROM work_items WHERE id = ?")
|
|
1280
|
+
.get(input.workItemId);
|
|
1281
|
+
if (workItem?.session_id) {
|
|
1282
|
+
return appendSessionEventInTransaction(this.database, {
|
|
1283
|
+
...input,
|
|
1284
|
+
sessionId: String(workItem.session_id),
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
const sequenceRow = this.database
|
|
1288
|
+
.prepare("SELECT COALESCE(MAX(sequence), 0) + 1 AS next_sequence FROM domain_events WHERE work_item_id = ?")
|
|
1289
|
+
.get(input.workItemId);
|
|
1290
|
+
const sequence = Number(sequenceRow?.next_sequence ?? 1);
|
|
1291
|
+
const event = {
|
|
1292
|
+
schemaVersion: 1,
|
|
1293
|
+
eventId: createId("evt"),
|
|
1294
|
+
sequence,
|
|
1295
|
+
workItemId: input.workItemId,
|
|
1296
|
+
runId: input.runId ?? null,
|
|
1297
|
+
executionKind: resolveRunExecutionKind(this.database, input.runId ?? null),
|
|
1298
|
+
type: input.type,
|
|
1299
|
+
occurredAt: new Date().toISOString(),
|
|
1300
|
+
actor: input.actor,
|
|
1301
|
+
target: input.target ?? null,
|
|
1302
|
+
inputHash: input.inputHash ?? null,
|
|
1303
|
+
resultRef: input.resultRef ?? null,
|
|
1304
|
+
payload: { ...(input.payload ?? {}) },
|
|
1305
|
+
};
|
|
1306
|
+
this.database
|
|
1307
|
+
.prepare(`INSERT INTO domain_events (
|
|
1308
|
+
event_id, schema_version, sequence, work_item_id, run_id, execution_kind, type,
|
|
1309
|
+
occurred_at, actor, target, input_hash, result_ref, payload
|
|
1310
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
1311
|
+
.run(event.eventId, event.schemaVersion, event.sequence, event.workItemId, event.runId, event.executionKind, event.type, event.occurredAt, event.actor, event.target, event.inputHash, event.resultRef, JSON.stringify(event.payload));
|
|
1312
|
+
this.database
|
|
1313
|
+
.prepare(`UPDATE session_runtime
|
|
1314
|
+
SET last_event_sequence = ?, updated_at = ?
|
|
1315
|
+
WHERE session_id = (
|
|
1316
|
+
SELECT session_id FROM work_items WHERE id = ?
|
|
1317
|
+
)`)
|
|
1318
|
+
.run(event.sequence, event.occurredAt, event.workItemId);
|
|
1319
|
+
const nextStatus = STATUS_BY_EVENT[event.type];
|
|
1320
|
+
if (nextStatus) {
|
|
1321
|
+
this.database
|
|
1322
|
+
.prepare("UPDATE work_items SET status = ?, updated_at = ? WHERE id = ?")
|
|
1323
|
+
.run(nextStatus, event.occurredAt, event.workItemId);
|
|
1324
|
+
}
|
|
1325
|
+
return event;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
function createId(prefix) {
|
|
1329
|
+
return `${prefix}_${randomUUID().replaceAll("-", "")}`;
|
|
1330
|
+
}
|
|
1331
|
+
function createMigrationId(prefix, sessionId, seed) {
|
|
1332
|
+
return `${prefix}_mig_${createHash("sha256")
|
|
1333
|
+
.update(`${sessionId}\0${seed}`)
|
|
1334
|
+
.digest("hex")
|
|
1335
|
+
.slice(0, 24)}`;
|
|
1336
|
+
}
|
|
1337
|
+
function createLegacySyntheticRun(input) {
|
|
1338
|
+
return {
|
|
1339
|
+
schemaVersion: 1,
|
|
1340
|
+
id: input.runId,
|
|
1341
|
+
workItemId: input.workItemId,
|
|
1342
|
+
sessionId: input.sessionId,
|
|
1343
|
+
turnId: input.turnId,
|
|
1344
|
+
mode: "auto",
|
|
1345
|
+
status: "succeeded",
|
|
1346
|
+
executionKind: "agent",
|
|
1347
|
+
agentId: null,
|
|
1348
|
+
planId: null,
|
|
1349
|
+
planIrHash: null,
|
|
1350
|
+
workflowRevision: null,
|
|
1351
|
+
terminalReason: "legacy_history_import",
|
|
1352
|
+
replaySafety: "safe",
|
|
1353
|
+
leaseOwner: null,
|
|
1354
|
+
leaseExpiresAt: null,
|
|
1355
|
+
cancelRequestedAt: null,
|
|
1356
|
+
cancelDeadlineAt: null,
|
|
1357
|
+
createdAt: input.occurredAt,
|
|
1358
|
+
updatedAt: input.occurredAt,
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
function isActiveRunStatus(status) {
|
|
1362
|
+
return status === "queued" || status === "running" || status === "waiting";
|
|
1363
|
+
}
|
|
1364
|
+
function legacyTurnMessageFromEvent(event) {
|
|
1365
|
+
const payload = event.payload;
|
|
1366
|
+
return {
|
|
1367
|
+
text: typeof payload.message === "string" ? payload.message : "",
|
|
1368
|
+
attachmentIds: Array.isArray(payload.attachment_ids)
|
|
1369
|
+
? payload.attachment_ids.map((value) => String(value))
|
|
1370
|
+
: [],
|
|
1371
|
+
executionKind: "agent",
|
|
1372
|
+
model: null,
|
|
1373
|
+
effort: null,
|
|
1374
|
+
permissionMode: null,
|
|
1375
|
+
plan: null,
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1378
|
+
function emptyLegacyTurnMessage() {
|
|
1379
|
+
return {
|
|
1380
|
+
text: "",
|
|
1381
|
+
attachmentIds: [],
|
|
1382
|
+
executionKind: "agent",
|
|
1383
|
+
model: null,
|
|
1384
|
+
effort: null,
|
|
1385
|
+
permissionMode: null,
|
|
1386
|
+
plan: null,
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
function legacyTurnIdFromEvent(sessionId, event, runId) {
|
|
1390
|
+
const target = event.target === null || event.target === undefined
|
|
1391
|
+
? null
|
|
1392
|
+
: String(event.target);
|
|
1393
|
+
if (target)
|
|
1394
|
+
return target;
|
|
1395
|
+
return createMigrationId("turn", sessionId, `run:${runId}`);
|
|
1396
|
+
}
|
|
1397
|
+
function nextLegacyQueuePosition(database, sessionId) {
|
|
1398
|
+
const row = database
|
|
1399
|
+
.prepare(`SELECT COALESCE(MAX(queue_position), 0) + 1 AS next_position
|
|
1400
|
+
FROM session_turns
|
|
1401
|
+
WHERE session_id = ?`)
|
|
1402
|
+
.get(sessionId);
|
|
1403
|
+
return Number(row?.next_position ?? 1);
|
|
1404
|
+
}
|
|
1405
|
+
function ensureSyntheticTimelineTurn(database, sessionId, turnId, runId, startedSequence, occurredAt) {
|
|
1406
|
+
const existing = database
|
|
1407
|
+
.prepare(`SELECT 1 FROM session_timeline_turns
|
|
1408
|
+
WHERE turn_id = ? OR run_id = ?`)
|
|
1409
|
+
.get(turnId, runId);
|
|
1410
|
+
if (existing)
|
|
1411
|
+
return;
|
|
1412
|
+
const row = database
|
|
1413
|
+
.prepare(`SELECT COALESCE(MAX(timeline_index), 0) + 1 AS next_index
|
|
1414
|
+
FROM session_timeline_turns
|
|
1415
|
+
WHERE session_id = ?`)
|
|
1416
|
+
.get(sessionId);
|
|
1417
|
+
database
|
|
1418
|
+
.prepare(`INSERT INTO session_timeline_turns (
|
|
1419
|
+
session_id, timeline_index, turn_id, run_id, started_sequence,
|
|
1420
|
+
ended_sequence, status, updated_at
|
|
1421
|
+
) VALUES (?, ?, ?, ?, ?, NULL, 'dispatched', ?)`)
|
|
1422
|
+
.run(sessionId, Number(row?.next_index ?? 1), turnId, runId, startedSequence, occurredAt);
|
|
1423
|
+
}
|
|
1424
|
+
function upsertLegacyRunTurn(database, input, run, dispatchOccurredAt) {
|
|
1425
|
+
database
|
|
1426
|
+
.prepare(`INSERT INTO runs (
|
|
1427
|
+
id, schema_version, work_item_id, session_id, turn_id, mode, status,
|
|
1428
|
+
execution_kind, agent_id, plan_id, plan_ir_hash, workflow_revision, terminal_reason,
|
|
1429
|
+
replay_safety, lease_owner, lease_expires_at, cancel_requested_at,
|
|
1430
|
+
cancel_deadline_at, created_at, updated_at
|
|
1431
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1432
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
1433
|
+
work_item_id = excluded.work_item_id,
|
|
1434
|
+
session_id = excluded.session_id,
|
|
1435
|
+
turn_id = excluded.turn_id`)
|
|
1436
|
+
.run(input.runId, run.schemaVersion, input.workItemId, input.sessionId, input.turnId, run.mode, run.status, run.executionKind, run.agentId, run.planId, run.planIrHash, run.workflowRevision, run.terminalReason, run.replaySafety, run.leaseOwner, run.leaseExpiresAt, run.cancelRequestedAt, run.cancelDeadlineAt, run.createdAt, run.updatedAt);
|
|
1437
|
+
upsertSessionTurnBinding(database, {
|
|
1438
|
+
turnId: input.turnId,
|
|
1439
|
+
sessionId: input.sessionId,
|
|
1440
|
+
queuePosition: input.queuePosition,
|
|
1441
|
+
message: input.message,
|
|
1442
|
+
dispatchedRunId: input.runId,
|
|
1443
|
+
createdAt: input.createdAt,
|
|
1444
|
+
dispatchedAt: dispatchOccurredAt ?? input.createdAt,
|
|
1445
|
+
});
|
|
1446
|
+
}
|
|
1447
|
+
function upsertSessionTurnBinding(database, input) {
|
|
1448
|
+
const existingTurn = database
|
|
1449
|
+
.prepare(`SELECT turn_id, queue_position
|
|
1450
|
+
FROM session_turns
|
|
1451
|
+
WHERE turn_id = ? OR dispatched_run_id = ? OR (
|
|
1452
|
+
session_id = ? AND queue_position = ?
|
|
1453
|
+
)
|
|
1454
|
+
ORDER BY
|
|
1455
|
+
CASE
|
|
1456
|
+
WHEN turn_id = ? THEN 0
|
|
1457
|
+
WHEN dispatched_run_id = ? THEN 1
|
|
1458
|
+
ELSE 2
|
|
1459
|
+
END,
|
|
1460
|
+
queue_position ASC
|
|
1461
|
+
LIMIT 1`)
|
|
1462
|
+
.get(input.turnId, input.dispatchedRunId, input.sessionId, input.queuePosition, input.turnId, input.dispatchedRunId);
|
|
1463
|
+
if (existingTurn?.turn_id) {
|
|
1464
|
+
database
|
|
1465
|
+
.prepare(`UPDATE session_turns
|
|
1466
|
+
SET session_id = ?, status = 'dispatched',
|
|
1467
|
+
message_json = ?, dispatched_run_id = ?, created_at = ?,
|
|
1468
|
+
dispatched_at = ?, cancelled_at = NULL
|
|
1469
|
+
WHERE turn_id = ?`)
|
|
1470
|
+
.run(input.sessionId, JSON.stringify(input.message), input.dispatchedRunId, input.createdAt, input.dispatchedAt, String(existingTurn.turn_id));
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
database
|
|
1474
|
+
.prepare(`INSERT INTO session_turns (
|
|
1475
|
+
turn_id, session_id, queue_position, status, message_json, version,
|
|
1476
|
+
dispatched_run_id, created_at, dispatched_at, cancelled_at
|
|
1477
|
+
) VALUES (?, ?, ?, 'dispatched', ?, 2, ?, ?, ?, NULL)`)
|
|
1478
|
+
.run(input.turnId, input.sessionId, input.queuePosition, JSON.stringify(input.message), input.dispatchedRunId, input.createdAt, input.dispatchedAt);
|
|
1479
|
+
}
|
|
1480
|
+
function normalizeLegacyProjectionEvent(database, sessionId, event, currentSynthetic, bindingState) {
|
|
1481
|
+
if (event.runId) {
|
|
1482
|
+
if (event.type === "MESSAGE_RECEIVED"
|
|
1483
|
+
|| event.type === "AGENT_EVENT"
|
|
1484
|
+
|| event.type === "APPROVAL_REQUESTED") {
|
|
1485
|
+
ensureSyntheticProjectionTurnForRun(database, sessionId, event);
|
|
1486
|
+
}
|
|
1487
|
+
return { event, syntheticGroup: currentSynthetic };
|
|
1488
|
+
}
|
|
1489
|
+
let syntheticGroup = currentSynthetic;
|
|
1490
|
+
if (event.type !== "MESSAGE_RECEIVED" && event.type !== "AGENT_EVENT") {
|
|
1491
|
+
return { event, syntheticGroup };
|
|
1492
|
+
}
|
|
1493
|
+
if (event.type === "MESSAGE_RECEIVED" || !syntheticGroup) {
|
|
1494
|
+
const binding = bindingState && bindingState.index < bindingState.bindings.length
|
|
1495
|
+
? bindingState.bindings[bindingState.index++]
|
|
1496
|
+
: undefined;
|
|
1497
|
+
if (binding) {
|
|
1498
|
+
syntheticGroup = {
|
|
1499
|
+
runId: binding.runId,
|
|
1500
|
+
turnId: binding.turnId,
|
|
1501
|
+
queuePosition: bindingState ? bindingState.index : nextLegacyQueuePosition(database, sessionId),
|
|
1502
|
+
};
|
|
1503
|
+
ensureSyntheticTimelineTurn(database, sessionId, binding.turnId, binding.runId, event.sequence, event.occurredAt);
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
const seed = event.type === "MESSAGE_RECEIVED"
|
|
1507
|
+
? `message:${event.sequence}`
|
|
1508
|
+
: `agent:${event.sequence}`;
|
|
1509
|
+
syntheticGroup = {
|
|
1510
|
+
runId: createMigrationId("run", sessionId, seed),
|
|
1511
|
+
turnId: createMigrationId("turn", sessionId, seed),
|
|
1512
|
+
queuePosition: nextLegacyQueuePosition(database, sessionId),
|
|
1513
|
+
};
|
|
1514
|
+
ensureSyntheticTimelineTurn(database, sessionId, syntheticGroup.turnId, syntheticGroup.runId, event.sequence, event.occurredAt);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
else {
|
|
1518
|
+
ensureSyntheticTimelineTurn(database, sessionId, syntheticGroup.turnId, syntheticGroup.runId, event.sequence, event.occurredAt);
|
|
1519
|
+
}
|
|
1520
|
+
if (!syntheticGroup) {
|
|
1521
|
+
throw new Error("legacy synthetic projection group missing");
|
|
1522
|
+
}
|
|
1523
|
+
return {
|
|
1524
|
+
event: {
|
|
1525
|
+
...event,
|
|
1526
|
+
runId: syntheticGroup.runId,
|
|
1527
|
+
target: event.target ?? syntheticGroup.turnId,
|
|
1528
|
+
},
|
|
1529
|
+
syntheticGroup,
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
function ensureSyntheticProjectionTurnForRun(database, sessionId, event) {
|
|
1533
|
+
const run = database
|
|
1534
|
+
.prepare("SELECT * FROM runs WHERE id = ?")
|
|
1535
|
+
.get(event.runId);
|
|
1536
|
+
if (!run)
|
|
1537
|
+
return;
|
|
1538
|
+
const turnId = run.turn_id === null || run.turn_id === undefined
|
|
1539
|
+
? legacyTurnIdFromEvent(sessionId, event, event.runId)
|
|
1540
|
+
: String(run.turn_id);
|
|
1541
|
+
ensureSyntheticTimelineTurn(database, sessionId, turnId, event.runId, event.sequence, event.occurredAt);
|
|
1542
|
+
}
|
|
1543
|
+
function toWorkItem(row) {
|
|
1544
|
+
return {
|
|
1545
|
+
schemaVersion: Number(row.schema_version),
|
|
1546
|
+
id: String(row.id),
|
|
1547
|
+
title: String(row.title),
|
|
1548
|
+
status: String(row.status),
|
|
1549
|
+
mode: String(row.mode),
|
|
1550
|
+
conversationId: String(row.conversation_id),
|
|
1551
|
+
sessionId: row.session_id === null || row.session_id === undefined
|
|
1552
|
+
? null
|
|
1553
|
+
: String(row.session_id),
|
|
1554
|
+
agentId: row.agent_id === null ? null : String(row.agent_id),
|
|
1555
|
+
workflowId: row.workflow_id === null ? null : String(row.workflow_id),
|
|
1556
|
+
workflowRevision: row.workflow_revision === null ? null : String(row.workflow_revision),
|
|
1557
|
+
workspaceScope: JSON.parse(String(row.workspace_scope)),
|
|
1558
|
+
identifiers: JSON.parse(String(row.identifiers)),
|
|
1559
|
+
contextRevision: Number(row.context_revision),
|
|
1560
|
+
riskLevel: String(row.risk_level),
|
|
1561
|
+
createdAt: String(row.created_at),
|
|
1562
|
+
updatedAt: String(row.updated_at),
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
function toDomainEvent(row) {
|
|
1566
|
+
const runId = row.run_id === null ? null : String(row.run_id);
|
|
1567
|
+
return {
|
|
1568
|
+
schemaVersion: Number(row.schema_version),
|
|
1569
|
+
eventId: String(row.event_id),
|
|
1570
|
+
sequence: Number(row.sequence),
|
|
1571
|
+
workItemId: String(row.work_item_id),
|
|
1572
|
+
runId,
|
|
1573
|
+
executionKind: executionKindValue(row.execution_kind, runId),
|
|
1574
|
+
type: String(row.type),
|
|
1575
|
+
occurredAt: String(row.occurred_at),
|
|
1576
|
+
actor: String(row.actor),
|
|
1577
|
+
target: row.target === null ? null : String(row.target),
|
|
1578
|
+
inputHash: row.input_hash === null ? null : String(row.input_hash),
|
|
1579
|
+
resultRef: row.result_ref === null ? null : String(row.result_ref),
|
|
1580
|
+
payload: JSON.parse(String(row.payload)),
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
function toRun(row) {
|
|
1584
|
+
return {
|
|
1585
|
+
schemaVersion: Number(row.schema_version),
|
|
1586
|
+
id: String(row.id),
|
|
1587
|
+
workItemId: String(row.work_item_id),
|
|
1588
|
+
sessionId: row.session_id === null || row.session_id === undefined
|
|
1589
|
+
? null
|
|
1590
|
+
: String(row.session_id),
|
|
1591
|
+
turnId: row.turn_id === null || row.turn_id === undefined
|
|
1592
|
+
? null
|
|
1593
|
+
: String(row.turn_id),
|
|
1594
|
+
mode: String(row.mode),
|
|
1595
|
+
status: String(row.status),
|
|
1596
|
+
executionKind: executionKindValue(row.execution_kind, String(row.id)),
|
|
1597
|
+
agentId: row.agent_id === null ? null : String(row.agent_id),
|
|
1598
|
+
planId: row.plan_id === null ? null : String(row.plan_id),
|
|
1599
|
+
planIrHash: row.plan_ir_hash === null || row.plan_ir_hash === undefined ? null : String(row.plan_ir_hash),
|
|
1600
|
+
workflowRevision: row.workflow_revision === null || row.workflow_revision === undefined
|
|
1601
|
+
? null
|
|
1602
|
+
: String(row.workflow_revision),
|
|
1603
|
+
terminalReason: row.terminal_reason === null || row.terminal_reason === undefined
|
|
1604
|
+
? null
|
|
1605
|
+
: String(row.terminal_reason),
|
|
1606
|
+
replaySafety: String(row.replay_safety ?? "safe"),
|
|
1607
|
+
leaseOwner: row.lease_owner === null || row.lease_owner === undefined
|
|
1608
|
+
? null
|
|
1609
|
+
: String(row.lease_owner),
|
|
1610
|
+
leaseExpiresAt: row.lease_expires_at === null || row.lease_expires_at === undefined
|
|
1611
|
+
? null
|
|
1612
|
+
: String(row.lease_expires_at),
|
|
1613
|
+
cancelRequestedAt: row.cancel_requested_at === null || row.cancel_requested_at === undefined
|
|
1614
|
+
? null
|
|
1615
|
+
: String(row.cancel_requested_at),
|
|
1616
|
+
cancelDeadlineAt: row.cancel_deadline_at === null || row.cancel_deadline_at === undefined
|
|
1617
|
+
? null
|
|
1618
|
+
: String(row.cancel_deadline_at),
|
|
1619
|
+
providerSessionId: row.provider_session_id === null || row.provider_session_id === undefined
|
|
1620
|
+
? null
|
|
1621
|
+
: String(row.provider_session_id),
|
|
1622
|
+
createdAt: String(row.created_at),
|
|
1623
|
+
updatedAt: String(row.updated_at),
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
function executionKindValue(value, runId) {
|
|
1627
|
+
if (runId === null) {
|
|
1628
|
+
if (value === null || value === undefined)
|
|
1629
|
+
return null;
|
|
1630
|
+
throw new Error("Runless event cannot have an execution kind");
|
|
1631
|
+
}
|
|
1632
|
+
if (value === "agent" || value === "flow")
|
|
1633
|
+
return value;
|
|
1634
|
+
throw new Error(`Invalid Run execution kind: ${runId}`);
|
|
1635
|
+
}
|
|
1636
|
+
function toSessionRuntime(row) {
|
|
1637
|
+
return {
|
|
1638
|
+
sessionId: String(row.session_id),
|
|
1639
|
+
activeRunId: row.active_run_id === null || row.active_run_id === undefined
|
|
1640
|
+
? null
|
|
1641
|
+
: String(row.active_run_id),
|
|
1642
|
+
queueState: String(row.queue_state),
|
|
1643
|
+
queuePauseReason: row.queue_pause_reason === null || row.queue_pause_reason === undefined
|
|
1644
|
+
? null
|
|
1645
|
+
: String(row.queue_pause_reason),
|
|
1646
|
+
lastEventSequence: Number(row.last_event_sequence),
|
|
1647
|
+
version: Number(row.version),
|
|
1648
|
+
updatedAt: String(row.updated_at),
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1651
|
+
function toSessionTurn(row) {
|
|
1652
|
+
return {
|
|
1653
|
+
turnId: String(row.turn_id),
|
|
1654
|
+
sessionId: String(row.session_id),
|
|
1655
|
+
queuePosition: Number(row.queue_position),
|
|
1656
|
+
status: String(row.status),
|
|
1657
|
+
message: parseSessionTurnMessage(String(row.message_json)),
|
|
1658
|
+
version: Number(row.version),
|
|
1659
|
+
dispatchedRunId: row.dispatched_run_id === null || row.dispatched_run_id === undefined
|
|
1660
|
+
? null
|
|
1661
|
+
: String(row.dispatched_run_id),
|
|
1662
|
+
createdAt: String(row.created_at),
|
|
1663
|
+
dispatchedAt: row.dispatched_at === null || row.dispatched_at === undefined
|
|
1664
|
+
? null
|
|
1665
|
+
: String(row.dispatched_at),
|
|
1666
|
+
cancelledAt: row.cancelled_at === null || row.cancelled_at === undefined
|
|
1667
|
+
? null
|
|
1668
|
+
: String(row.cancelled_at),
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
function toRunAttempt(row) {
|
|
1672
|
+
return {
|
|
1673
|
+
attemptId: String(row.attempt_id),
|
|
1674
|
+
runId: String(row.run_id),
|
|
1675
|
+
attemptNumber: Number(row.attempt_number),
|
|
1676
|
+
startedAt: String(row.started_at),
|
|
1677
|
+
endedAt: row.ended_at === null
|
|
1678
|
+
? null
|
|
1679
|
+
: String(row.ended_at),
|
|
1680
|
+
providerError: row.provider_error === null
|
|
1681
|
+
? null
|
|
1682
|
+
: String(row.provider_error),
|
|
1683
|
+
sideEffectBoundary: String(row.side_effect_boundary),
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
function toTimelineSegment(row) {
|
|
1687
|
+
return {
|
|
1688
|
+
segmentId: String(row.segment_id),
|
|
1689
|
+
blockId: String(row.block_id),
|
|
1690
|
+
segmentIndex: Number(row.segment_index),
|
|
1691
|
+
content: String(row.content),
|
|
1692
|
+
byteLength: Number(row.byte_length),
|
|
1693
|
+
sealed: Number(row.sealed) === 1,
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
function toTimelineBlock(row) {
|
|
1697
|
+
return {
|
|
1698
|
+
blockId: String(row.block_id),
|
|
1699
|
+
sessionId: String(row.session_id),
|
|
1700
|
+
turnId: String(row.turn_id),
|
|
1701
|
+
runId: String(row.run_id),
|
|
1702
|
+
blockIndex: Number(row.block_index),
|
|
1703
|
+
kind: String(row.kind),
|
|
1704
|
+
status: String(row.status),
|
|
1705
|
+
metadata: JSON.parse(String(row.metadata_json ?? "{}")),
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
function toTimelineTurn(row) {
|
|
1709
|
+
return {
|
|
1710
|
+
sessionId: String(row.session_id),
|
|
1711
|
+
timelineIndex: Number(row.timeline_index),
|
|
1712
|
+
turnId: String(row.turn_id),
|
|
1713
|
+
runId: String(row.run_id),
|
|
1714
|
+
startedSequence: Number(row.started_sequence),
|
|
1715
|
+
endedSequence: row.ended_sequence === null || row.ended_sequence === undefined
|
|
1716
|
+
? null
|
|
1717
|
+
: Number(row.ended_sequence),
|
|
1718
|
+
status: String(row.status),
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1721
|
+
function toPlan(row) {
|
|
1722
|
+
return {
|
|
1723
|
+
schemaVersion: Number(row.schema_version),
|
|
1724
|
+
planId: String(row.plan_id),
|
|
1725
|
+
source: String(row.source),
|
|
1726
|
+
workflowId: String(row.workflow_id),
|
|
1727
|
+
definitionRevision: row.definition_revision === null ? null : String(row.definition_revision),
|
|
1728
|
+
planIrHash: row.plan_ir_hash === null || row.plan_ir_hash === undefined ? null : String(row.plan_ir_hash),
|
|
1729
|
+
sessionId: row.session_id === null ? null : String(row.session_id),
|
|
1730
|
+
runId: row.run_id === null ? null : String(row.run_id),
|
|
1731
|
+
steps: JSON.parse(String(row.steps)).map(clonePlanStep),
|
|
1732
|
+
createdAt: String(row.created_at),
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
function toArtifact(row) {
|
|
1736
|
+
return {
|
|
1737
|
+
id: String(row.id),
|
|
1738
|
+
workItemId: String(row.work_item_id),
|
|
1739
|
+
runId: String(row.run_id),
|
|
1740
|
+
stepId: row.step_id === null ? null : String(row.step_id),
|
|
1741
|
+
kind: String(row.kind),
|
|
1742
|
+
name: String(row.name),
|
|
1743
|
+
mimeType: String(row.mime_type),
|
|
1744
|
+
content: String(row.content),
|
|
1745
|
+
contentHash: String(row.content_hash),
|
|
1746
|
+
metadata: JSON.parse(String(row.metadata)),
|
|
1747
|
+
createdAt: String(row.created_at),
|
|
1748
|
+
};
|
|
1749
|
+
}
|
|
1750
|
+
function toMessageAttachment(row) {
|
|
1751
|
+
return {
|
|
1752
|
+
schemaVersion: Number(row.schema_version),
|
|
1753
|
+
id: String(row.id),
|
|
1754
|
+
workItemId: String(row.work_item_id),
|
|
1755
|
+
name: String(row.name),
|
|
1756
|
+
mimeType: String(row.mime_type),
|
|
1757
|
+
dataBase64: String(row.data_base64),
|
|
1758
|
+
byteSize: Number(row.byte_size),
|
|
1759
|
+
contentHash: String(row.content_hash),
|
|
1760
|
+
createdAt: String(row.created_at),
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
function toVerification(row) {
|
|
1764
|
+
return {
|
|
1765
|
+
id: String(row.id),
|
|
1766
|
+
workItemId: String(row.work_item_id),
|
|
1767
|
+
runId: String(row.run_id),
|
|
1768
|
+
stepId: row.step_id === null ? null : String(row.step_id),
|
|
1769
|
+
validator: String(row.validator),
|
|
1770
|
+
status: String(row.status),
|
|
1771
|
+
summary: String(row.summary),
|
|
1772
|
+
artifactIds: JSON.parse(String(row.artifact_ids)),
|
|
1773
|
+
createdAt: String(row.created_at),
|
|
1774
|
+
};
|
|
1775
|
+
}
|
|
1776
|
+
function clonePlanStep(step) {
|
|
1777
|
+
return {
|
|
1778
|
+
...step,
|
|
1779
|
+
dependsOn: [...step.dependsOn],
|
|
1780
|
+
branches: step.branches.map((branch) => ({ ...branch })),
|
|
1781
|
+
retry: step.retry ? { ...step.retry } : null,
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
//# sourceMappingURL=index.js.map
|