@vellumai/assistant 0.8.12 → 0.9.0-staging.2
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/AGENTS.md +0 -14
- package/ARCHITECTURE.md +45 -45
- package/README.md +1 -1
- package/bun.lock +200 -154
- package/docs/architecture/integrations.md +3 -3
- package/docs/architecture/memory.md +2 -2
- package/docs/architecture/security.md +10 -10
- package/docs/runbook-trusted-contacts.md +12 -12
- package/docs/skills.md +6 -6
- package/docs/workflows-testing.md +221 -0
- package/docs/workflows.md +510 -0
- package/examples/plugins/echo/README.md +5 -5
- package/knip.json +2 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +105 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +12 -0
- package/openapi.yaml +7197 -5708
- package/package.json +8 -4
- package/scripts/generate-openapi.ts +66 -114
- package/src/__tests__/access-request-seed-content-blocks.test.ts +213 -0
- package/src/__tests__/adaptive-thinking-repair.test.ts +32 -3
- package/src/__tests__/agent-loop-output-hooks.test.ts +183 -0
- package/src/__tests__/agent-loop-regrowth-guard.test.ts +506 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +77 -0
- package/src/__tests__/app-compiler.test.ts +7 -1
- package/src/__tests__/app-dir-path-guard.test.ts +27 -3
- package/src/__tests__/app-executors.test.ts +43 -0
- package/src/__tests__/approval-cascade.test.ts +0 -5
- package/src/__tests__/approval-routes-http.test.ts +91 -0
- package/src/__tests__/assistant-stream-state.test.ts +107 -0
- package/src/__tests__/browser-fill-credential.test.ts +3 -3
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +63 -7
- package/src/__tests__/compaction-trail-store.test.ts +74 -1
- package/src/__tests__/compaction.benchmark.test.ts +63 -41
- package/src/__tests__/compactor-low-watermark-cut.test.ts +349 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +64 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -5
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -5
- package/src/__tests__/conversation-history-web-search.test.ts +7 -0
- package/src/__tests__/conversation-process-callsite.test.ts +0 -5
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -5
- package/src/__tests__/conversation-queue.test.ts +0 -5
- package/src/__tests__/conversation-slash-queue.test.ts +0 -5
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -5
- package/src/__tests__/conversation-speed-override.test.ts +0 -5
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +97 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
- package/src/__tests__/conversation-usage.test.ts +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -5
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -5
- package/src/__tests__/credential-broker-browser-fill.test.ts +2 -2
- package/src/__tests__/credential-broker-server-use.test.ts +2 -2
- package/src/__tests__/credential-broker.test.ts +1 -1
- package/src/__tests__/credential-prompt-route.test.ts +417 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault.test.ts +37 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +24 -0
- package/src/__tests__/dynamic-page-surface.test.ts +219 -0
- package/src/__tests__/empty-state-greeting-cache.test.ts +94 -0
- package/src/__tests__/gateway-flag-listener.test.ts +24 -7
- package/src/__tests__/guardian-action-sweep.test.ts +56 -219
- package/src/__tests__/guardian-routing-invariants.test.ts +138 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/list-messages-hidden-metadata.test.ts +99 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +87 -1
- package/src/__tests__/llm-resolver.test.ts +115 -0
- package/src/__tests__/managed-profile-guard.test.ts +6 -5
- package/src/__tests__/max-tokens-continue-hook.test.ts +184 -0
- package/src/__tests__/media-generate-image.test.ts +20 -9
- package/src/__tests__/mock-gateway-ipc.ts +23 -0
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/normalize-onboarding.test.ts +26 -0
- package/src/__tests__/notification-decision-strategy.test.ts +4 -2
- package/src/__tests__/notification-telegram-adapter.test.ts +21 -3
- package/src/__tests__/pending-interactions-resolved-event.test.ts +62 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +72 -18
- package/src/__tests__/require-fresh-approval.test.ts +425 -1
- package/src/__tests__/resolve-app-id.test.ts +56 -0
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -0
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +408 -0
- package/src/__tests__/schedule-routes.test.ts +257 -4
- package/src/__tests__/schedule-store.test.ts +60 -0
- package/src/__tests__/schedule-tools.test.ts +247 -2
- package/src/__tests__/skill-execute-input.test.ts +85 -0
- package/src/__tests__/skill-secret-handling-guard.test.ts +21 -20
- package/src/__tests__/skills.test.ts +3 -3
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +1 -1
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +547 -0
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/task-progress-nudge-hook.test.ts +372 -0
- package/src/__tests__/task-scheduler.test.ts +299 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +209 -0
- package/src/__tests__/tool-result-spool.test.ts +3 -1
- package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +181 -0
- package/src/__tests__/workspace-migration-103-upgrade-quality-profile-to-opus-4-8.test.ts +174 -0
- package/src/agent/compaction-circuit.ts +11 -0
- package/src/agent/loop.ts +181 -12
- package/src/api/constants/call-sites.ts +12 -0
- package/src/api/events/assistant-thinking-delta.ts +10 -0
- package/src/api/events/usage-update.ts +7 -0
- package/src/api/index.ts +4 -1
- package/src/api/responses/memory-v3-selection-log.ts +18 -11
- package/src/approvals/approval-primitive.ts +2 -2
- package/src/background-wake/background-wake-routes.test.ts +5 -2
- package/src/bundler/compiler-tools.ts +1 -1
- package/src/bundler/package-resolver.ts +0 -1
- package/src/calls/call-domain.ts +1 -1
- package/src/calls/guardian-action-sweep.ts +16 -93
- package/src/cli/AGENTS.md +4 -0
- package/src/cli/commands/__tests__/schedules.test.ts +430 -1
- package/src/cli/commands/credentials.ts +28 -24
- package/src/cli/commands/image-generation.ts +23 -9
- package/src/cli/commands/notifications.ts +1 -1
- package/src/cli/commands/plugins.ts +89 -46
- package/src/cli/commands/schedules.ts +384 -11
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +69 -5
- package/src/cli/lib/__tests__/install-from-github.test.ts +15 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +81 -4
- package/src/cli/lib/inspect-plugin.ts +62 -1
- package/src/cli/lib/install-from-github.ts +52 -5
- package/src/cli/lib/upgrade-plugin.ts +18 -0
- package/src/config/__tests__/workflows-schema.test.ts +60 -0
- package/src/config/bundled-skills/acp/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +6 -1
- package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +7 -1
- package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +7 -1
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +10 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +66 -19
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -6
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +22 -3
- package/src/config/bundled-skills/personal-page/SKILL.md +57 -0
- package/src/config/bundled-skills/personal-page/TOOLS.json +27 -0
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +17 -0
- package/src/config/bundled-skills/schedule/SKILL.md +7 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +48 -4
- package/src/config/bundled-skills/workflows/SKILL.md +214 -0
- package/src/config/bundled-skills/workflows/TOOLS.json +84 -0
- package/src/config/bundled-skills/workflows/tools/manage-workflows.ts +12 -0
- package/src/config/bundled-skills/workflows/tools/run-workflow.ts +12 -0
- package/src/config/bundled-tool-registry.ts +14 -2
- package/src/config/call-site-defaults.ts +5 -0
- package/src/config/feature-flag-registry.json +12 -4
- package/src/config/llm-context-resolution.ts +8 -0
- package/src/config/llm-resolver.ts +30 -0
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +22 -0
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +16 -0
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +77 -0
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +57 -0
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +28 -0
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +234 -0
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +48 -0
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +16 -0
- package/src/config/preloaded-apps/personal-page/src/index.html +20 -0
- package/src/config/preloaded-apps/personal-page/src/main.tsx +7 -0
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +82 -0
- package/src/config/preloaded-apps/personal-page/src/styles.css +759 -0
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/heartbeat.ts +4 -1
- package/src/config/schemas/llm.ts +33 -26
- package/src/config/schemas/memory-retrospective.ts +19 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/services.ts +5 -2
- package/src/config/schemas/workflows.ts +42 -0
- package/src/config/skills.ts +3 -3
- package/src/context/compactor.ts +273 -39
- package/src/context/post-turn-tool-result-truncation.ts +23 -6
- package/src/context/tool-result-spool.ts +12 -17
- package/src/credential-execution/executable-discovery.ts +1 -1
- package/src/credential-execution/process-manager.ts +37 -3
- package/src/credential-execution/prompted-credential.ts +205 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +14 -0
- package/src/daemon/conversation-process.ts +11 -2
- package/src/daemon/conversation-surfaces.ts +167 -3
- package/src/daemon/conversation-tool-setup.ts +103 -26
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +115 -11
- package/src/daemon/handlers/shared.ts +26 -14
- package/src/daemon/host-cu-proxy.ts +15 -12
- package/src/daemon/host-file-proxy.ts +15 -12
- package/src/daemon/host-transfer-proxy.ts +30 -24
- package/src/daemon/lifecycle.ts +40 -3
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/messages.ts +2 -10
- package/src/daemon/message-types/workflows.ts +49 -0
- package/src/daemon/parse-actual-tokens-from-error.test.ts +62 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +43 -4
- package/src/daemon/process-message.ts +6 -0
- package/src/daemon/tool-setup-types.ts +57 -0
- package/src/daemon/wake-conversation-ops.ts +18 -0
- package/src/heartbeat/heartbeat-run-store.ts +8 -2
- package/src/home/feed-types.ts +1 -1
- package/src/ipc/gateway-flag-listener.ts +28 -6
- package/src/mcp/mcp-auth-state.ts +8 -20
- package/src/media/__tests__/image-models.test.ts +57 -0
- package/src/media/image-models.ts +66 -0
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +38 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +12 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +911 -34
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +227 -5
- package/src/memory/__tests__/memory-retrospective-state.test.ts +195 -0
- package/src/memory/__tests__/preloaded-apps.test.ts +85 -0
- package/src/memory/auto-analysis-enqueue.ts +14 -1
- package/src/memory/compaction-log-store-clickhouse.ts +6 -4
- package/src/memory/conversation-crud.ts +9 -2
- package/src/memory/conversation-disk-view.ts +1 -1
- package/src/memory/conversation-queries.ts +22 -7
- package/src/memory/db-init.ts +20 -0
- package/src/memory/db-maintenance.ts +16 -0
- package/src/memory/embedding-runtime-manager.ts +1 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +112 -14
- package/src/memory/llm-request-log-source-local.ts +19 -1
- package/src/memory/llm-request-log-source.ts +35 -6
- package/src/memory/llm-request-log-store.ts +90 -2
- package/src/memory/memory-retrospective-constants.ts +9 -0
- package/src/memory/memory-retrospective-enqueue.ts +3 -6
- package/src/memory/memory-retrospective-fork-boundary.ts +94 -0
- package/src/memory/memory-retrospective-job.ts +500 -208
- package/src/memory/memory-retrospective-startup-cleanup.ts +97 -19
- package/src/memory/memory-retrospective-state.ts +85 -2
- package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +40 -0
- package/src/memory/migrations/282-schedule-inference-profile.test.ts +77 -0
- package/src/memory/migrations/282-schedule-inference-profile.ts +26 -0
- package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.test.ts +102 -0
- package/src/memory/migrations/283-memory-v3-selections-message-id-and-sections.ts +53 -0
- package/src/memory/migrations/284-workflow-runs.ts +51 -0
- package/src/memory/migrations/285-schedule-workflow-mode.ts +26 -0
- package/src/memory/migrations/286-workflow-run-trust.ts +27 -0
- package/src/memory/migrations/287-conversation-origin-channel-index.ts +15 -0
- package/src/memory/migrations/288-backfill-origin-channel-from-bindings.ts +43 -0
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +115 -0
- package/src/memory/migrations/290-schedule-capabilities.test.ts +77 -0
- package/src/memory/migrations/290-schedule-capabilities.ts +25 -0
- package/src/memory/migrations/__tests__/281-memory-retrospective-remembered-log.test.ts +96 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +571 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/preloaded-apps.ts +116 -0
- package/src/memory/schema/infrastructure.ts +4 -0
- package/src/memory/schema/memory-core.ts +4 -0
- package/src/memory/v2/__tests__/concept-page-frontmatter-schema.test.ts +45 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +11 -7
- package/src/memory/v2/__tests__/page-store.test.ts +13 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +24 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -6
- package/src/memory/v2/page-store.ts +4 -3
- package/src/memory/v2/qdrant.ts +42 -3
- package/src/memory/v2/types.ts +16 -10
- package/src/messaging/draft-store.ts +1 -1
- package/src/notifications/access-request-copy.ts +200 -113
- package/src/notifications/adapters/slack.ts +250 -111
- package/src/notifications/adapters/telegram.ts +7 -44
- package/src/notifications/approval-card-builder.ts +93 -0
- package/src/notifications/broadcaster.ts +74 -0
- package/src/notifications/conversation-pairing.ts +8 -6
- package/src/notifications/copy-composer.ts +32 -26
- package/src/notifications/decision-engine.ts +59 -7
- package/src/notifications/guardian-question-mode.ts +145 -155
- package/src/notifications/home-feed-side-effect.ts +28 -11
- package/src/notifications/notification-utils.ts +66 -0
- package/src/notifications/signal.ts +6 -0
- package/src/notifications/tool-approval-copy.ts +142 -0
- package/src/notifications/types.ts +19 -0
- package/src/permissions/threshold.ts +11 -0
- package/src/plugin-api/types.ts +16 -4
- package/src/plugins/defaults/compaction/window-manager.ts +44 -0
- package/src/plugins/defaults/index.ts +46 -0
- package/src/plugins/defaults/max-tokens-continue/continue-state-store.ts +53 -0
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +80 -0
- package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +20 -0
- package/src/plugins/defaults/max-tokens-continue/package.json +14 -0
- package/src/plugins/defaults/memory-retrieval/hooks/__tests__/user-prompt-submit.test.ts +37 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +29 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +8 -3
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +4 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +28 -18
- package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +67 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +122 -22
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +2 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +63 -1
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +61 -18
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +1 -1
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +39 -10
- package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +34 -1
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +112 -47
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +78 -15
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +206 -0
- package/src/plugins/defaults/task-progress-nudge/package.json +15 -0
- package/src/prompts/__tests__/system-prompt.test.ts +100 -1
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +5 -7
- package/src/prompts/normalize-onboarding.ts +2 -0
- package/src/prompts/persona-resolver.ts +3 -0
- package/src/prompts/system-prompt.ts +51 -2
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +3 -1
- package/src/prompts/templates/system-sections.ts +8 -3
- package/src/providers/call-site-routing.ts +6 -3
- package/src/providers/fireworks/client.ts +3 -0
- package/src/providers/inference/auth.ts +52 -46
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/openai/__tests__/coerce-object-args.test.ts +105 -0
- package/src/providers/openai/chat-completions-provider.ts +47 -9
- package/src/providers/openai/coerce-object-args.ts +104 -0
- package/src/providers/retry.ts +8 -5
- package/src/providers/types.ts +10 -0
- package/src/runtime/__tests__/agent-wake.test.ts +629 -7
- package/src/runtime/access-request-helper.ts +16 -9
- package/src/runtime/agent-wake.ts +302 -51
- package/src/runtime/assistant-stream-state.ts +141 -8
- package/src/runtime/background-job-runner.ts +9 -0
- package/src/runtime/channel-approval-types.ts +1 -0
- package/src/runtime/channel-invite-transports/telegram.ts +6 -5
- package/src/runtime/channel-invite-transports/voice.ts +2 -2
- package/src/runtime/channel-invite-types.ts +4 -2
- package/src/runtime/channel-retry-sweep.ts +19 -41
- package/src/runtime/finalize-event-delivery.ts +72 -0
- package/src/runtime/guardian-action-message-composer.ts +0 -54
- package/src/runtime/http-server.ts +6 -14
- package/src/runtime/http-types.ts +0 -1
- package/src/runtime/message-composer-types.ts +0 -9
- package/src/runtime/middleware/__tests__/rate-limiter.test.ts +63 -0
- package/src/runtime/middleware/auth.ts +27 -3
- package/src/runtime/middleware/rate-limiter.ts +28 -1
- package/src/runtime/migrations/vbundle-builder.ts +6 -5
- package/src/runtime/pending-interactions.ts +20 -1
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +232 -173
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +18 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +436 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +11 -0
- package/src/runtime/routes/approval-routes.ts +35 -8
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -1
- package/src/runtime/routes/btw-routes.ts +37 -1
- package/src/runtime/routes/channel-delivery-routes.ts +11 -7
- package/src/runtime/routes/channel-route-definitions.ts +3 -0
- package/src/runtime/routes/channel-route-shared.ts +3 -1
- package/src/runtime/routes/consolidation-routes.ts +17 -13
- package/src/runtime/routes/conversation-compaction-routes.ts +159 -119
- package/src/runtime/routes/conversation-list-routes.ts +41 -4
- package/src/runtime/routes/conversation-query-routes.ts +196 -11
- package/src/runtime/routes/conversation-routes.ts +15 -1
- package/src/runtime/routes/credential-prompt-routes.ts +39 -17
- package/src/runtime/routes/empty-state-greeting-cache.ts +65 -0
- package/src/runtime/routes/heartbeat-routes.ts +18 -13
- package/src/runtime/routes/image-generation-routes.ts +20 -2
- package/src/runtime/routes/inbound-message-handler.ts +13 -12
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +32 -31
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +7 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -21
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +5 -5
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +6 -15
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +1 -1
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/log-export/AGENTS.md +1 -1
- package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
- package/src/runtime/routes/migration-routes.ts +5 -9
- package/src/runtime/routes/plugins-routes.ts +26 -0
- package/src/runtime/routes/ps-routes.ts +10 -8
- package/src/runtime/routes/retrospective-routes.ts +235 -0
- package/src/runtime/routes/runs-pagination.ts +75 -0
- package/src/runtime/routes/schedule-routes.ts +367 -59
- package/src/runtime/routes/sounds-config-routes.ts +239 -0
- package/src/runtime/routes/surface-action-routes.ts +84 -4
- package/src/runtime/routes/workflow-routes.test.ts +372 -0
- package/src/runtime/routes/workflow-routes.ts +363 -0
- package/src/runtime/routes/workspace-routes.test.ts +61 -1
- package/src/runtime/routes/workspace-routes.ts +26 -1
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +38 -0
- package/src/runtime/services/analyze-conversation.ts +26 -13
- package/src/schedule/inference-profile.ts +28 -0
- package/src/schedule/schedule-store.ts +152 -4
- package/src/schedule/scheduler-types.ts +6 -0
- package/src/schedule/scheduler.ts +96 -0
- package/src/security/secret-allowlist.ts +1 -1
- package/src/skills/path-classifier.ts +1 -1
- package/src/tools/apps/executors.ts +23 -0
- package/src/tools/apps/resolve-app-id.ts +42 -0
- package/src/tools/browser/browser-execution.ts +9 -11
- package/src/tools/credentials/broker.ts +4 -4
- package/src/tools/credentials/vault.ts +26 -137
- package/src/tools/executor.ts +69 -0
- package/src/tools/flag-gated-tools.test.ts +76 -0
- package/src/tools/permission-checker.ts +8 -1
- package/src/tools/registry.ts +51 -0
- package/src/tools/schedule/create.ts +77 -1
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +73 -1
- package/src/tools/skills/execute.ts +56 -0
- package/src/tools/terminal/shell.ts +1 -1
- package/src/tools/ui-surface/definitions.ts +91 -2
- package/src/tools/workflows/manage-workflows.ts +183 -0
- package/src/tools/workflows/run-workflow.test.ts +442 -0
- package/src/tools/workflows/run-workflow.ts +88 -0
- package/src/types/onboarding-context.ts +2 -0
- package/src/usage/attribution.ts +24 -0
- package/src/util/canonicalize-identity.ts +12 -3
- package/src/util/platform.ts +17 -17
- package/src/watcher/__tests__/engine.test.ts +24 -0
- package/src/watcher/__tests__/telemetry.test.ts +135 -0
- package/src/watcher/engine.ts +7 -0
- package/src/watcher/telemetry.ts +74 -0
- package/src/workflows/capabilities.test.ts +365 -0
- package/src/workflows/capabilities.ts +359 -0
- package/src/workflows/deterministic-stringify.ts +27 -0
- package/src/workflows/engine-integration.test.ts +656 -0
- package/src/workflows/engine.test.ts +1144 -0
- package/src/workflows/engine.ts +1078 -0
- package/src/workflows/fanout-load.test.ts +168 -0
- package/src/workflows/journal-store.test.ts +369 -0
- package/src/workflows/journal-store.ts +470 -0
- package/src/workflows/leaf-runner.test.ts +704 -0
- package/src/workflows/leaf-runner.ts +589 -0
- package/src/workflows/library.test.ts +134 -0
- package/src/workflows/library.ts +124 -0
- package/src/workflows/run-manager.test.ts +711 -0
- package/src/workflows/run-manager.ts +593 -0
- package/src/workflows/sandbox-escape.test.ts +339 -0
- package/src/workflows/sandbox.test.ts +251 -0
- package/src/workflows/sandbox.ts +447 -0
- package/src/workspace/adaptive-thinking-repair.ts +33 -11
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +1 -1
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +1 -1
- package/src/workspace/migrations/026-backfill-install-meta.ts +1 -1
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +2 -1
- package/src/workspace/migrations/031-drop-user-md.ts +1 -4
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +1 -1
- package/src/workspace/migrations/056-release-notes-inference-profile-reordering.ts +5 -2
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +1 -1
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +8 -2
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +41 -14
- package/src/workspace/migrations/102-preserve-heartbeat-enabled-for-existing-workspaces.ts +69 -0
- package/src/workspace/migrations/103-upgrade-quality-profile-to-opus-4-8.ts +83 -0
- package/src/workspace/migrations/104-recheck-adaptive-thinking-model-implied-anthropic.ts +133 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/migrations/runner.ts +1 -1
- package/tsconfig.json +1 -1
- package/src/__tests__/guardian-action-copy-generator.test.ts +0 -200
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -579
- package/src/__tests__/guardian-action-store.test.ts +0 -106
- package/src/daemon/guardian-action-generators.ts +0 -71
- package/src/memory/guardian-action-store.ts +0 -484
- package/src/runtime/guardian-action-grant-minter.ts +0 -150
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed persistence for the workflow orchestration engine.
|
|
3
|
+
*
|
|
4
|
+
* Two tables (created by migration 282):
|
|
5
|
+
*
|
|
6
|
+
* - `workflow_runs` — one row per orchestration run (a sandboxed script that
|
|
7
|
+
* spawns parallel leaf agents), tracking lifecycle status and token usage.
|
|
8
|
+
* - `workflow_journal` — append-only `(run_id, seq)` log of every leaf call
|
|
9
|
+
* (agent / host function / nested workflow). On resume after a daemon
|
|
10
|
+
* restart, the engine replays cached results for the unchanged call prefix
|
|
11
|
+
* instead of re-spawning agents.
|
|
12
|
+
*
|
|
13
|
+
* This module is pure persistence — no `workflows` feature-flag logic. Callers
|
|
14
|
+
* (the engine, a later PR) own gating.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { rawAll, rawGet, rawRun } from "../memory/raw-query.js";
|
|
18
|
+
|
|
19
|
+
export type WorkflowRunStatus =
|
|
20
|
+
| "running"
|
|
21
|
+
| "completed"
|
|
22
|
+
| "failed"
|
|
23
|
+
| "aborted"
|
|
24
|
+
| "cap_exceeded"
|
|
25
|
+
| "interrupted";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The journal records leaf-agent calls (`"agent"`) and nested `workflow()`
|
|
29
|
+
* resolutions (`"workflow"`). A `"workflow"` entry snapshots the resolved child
|
|
30
|
+
* source under its own `seq` so a resumed run re-executes the SAME child code
|
|
31
|
+
* the original launch did, even if the saved workflow was since edited or
|
|
32
|
+
* deleted. The column stays TEXT so adding kinds later needs no migration.
|
|
33
|
+
*/
|
|
34
|
+
export type WorkflowJournalKind = "agent" | "workflow";
|
|
35
|
+
|
|
36
|
+
/** A persisted workflow run row, with JSON columns parsed into values. */
|
|
37
|
+
export interface WorkflowRun {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string | null;
|
|
40
|
+
scriptSource: string;
|
|
41
|
+
scriptHash: string;
|
|
42
|
+
args: unknown;
|
|
43
|
+
capabilities: unknown;
|
|
44
|
+
status: WorkflowRunStatus;
|
|
45
|
+
conversationId: string | null;
|
|
46
|
+
/**
|
|
47
|
+
* Originating trust context (parsed), or null for legacy rows written before
|
|
48
|
+
* the column existed. Reconstructed on resume so a run never resumes with more
|
|
49
|
+
* trust than it started under — see {@link CreateRunInput.trust}.
|
|
50
|
+
*/
|
|
51
|
+
trust: unknown;
|
|
52
|
+
agentsSpawned: number;
|
|
53
|
+
inputTokens: number;
|
|
54
|
+
outputTokens: number;
|
|
55
|
+
result: unknown;
|
|
56
|
+
error: string | null;
|
|
57
|
+
createdAt: number | null;
|
|
58
|
+
updatedAt: number | null;
|
|
59
|
+
finishedAt: number | null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** A persisted journal entry, with JSON columns parsed into values. */
|
|
63
|
+
export interface WorkflowJournalEntry {
|
|
64
|
+
runId: string;
|
|
65
|
+
seq: number;
|
|
66
|
+
callHash: string;
|
|
67
|
+
kind: WorkflowJournalKind;
|
|
68
|
+
request: unknown;
|
|
69
|
+
result: unknown;
|
|
70
|
+
status: string;
|
|
71
|
+
createdAt: number | null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface CreateRunInput {
|
|
75
|
+
id: string;
|
|
76
|
+
name?: string | null;
|
|
77
|
+
scriptSource: string;
|
|
78
|
+
scriptHash: string;
|
|
79
|
+
args?: unknown;
|
|
80
|
+
capabilities?: unknown;
|
|
81
|
+
status?: WorkflowRunStatus;
|
|
82
|
+
conversationId?: string | null;
|
|
83
|
+
/**
|
|
84
|
+
* Originating trust context (trust metadata — `{ sourceChannel, trustClass,
|
|
85
|
+
* ... }`, no secret material), serialized so a crash-orphaned run can
|
|
86
|
+
* reconstruct the exact trust class it started under when resumed. Omit on
|
|
87
|
+
* legacy callers; resume then falls back to low trust, never guardian.
|
|
88
|
+
*/
|
|
89
|
+
trust?: unknown;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface UpdateRunInput {
|
|
93
|
+
status?: WorkflowRunStatus;
|
|
94
|
+
agentsSpawned?: number;
|
|
95
|
+
inputTokens?: number;
|
|
96
|
+
outputTokens?: number;
|
|
97
|
+
conversationId?: string | null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface FinishRunInput {
|
|
101
|
+
status: WorkflowRunStatus;
|
|
102
|
+
result?: unknown;
|
|
103
|
+
error?: string | null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface AppendJournalEntryInput {
|
|
107
|
+
runId: string;
|
|
108
|
+
seq: number;
|
|
109
|
+
callHash: string;
|
|
110
|
+
kind: WorkflowJournalKind;
|
|
111
|
+
request?: unknown;
|
|
112
|
+
result?: unknown;
|
|
113
|
+
status: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Row shapes + mappers
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
|
|
120
|
+
interface WorkflowRunRow {
|
|
121
|
+
id: string;
|
|
122
|
+
name: string | null;
|
|
123
|
+
script_source: string;
|
|
124
|
+
script_hash: string;
|
|
125
|
+
args_json: string | null;
|
|
126
|
+
capabilities_json: string | null;
|
|
127
|
+
status: string;
|
|
128
|
+
conversation_id: string | null;
|
|
129
|
+
trust_json: string | null;
|
|
130
|
+
agents_spawned: number;
|
|
131
|
+
input_tokens: number;
|
|
132
|
+
output_tokens: number;
|
|
133
|
+
result_json: string | null;
|
|
134
|
+
error: string | null;
|
|
135
|
+
created_at: number | null;
|
|
136
|
+
updated_at: number | null;
|
|
137
|
+
finished_at: number | null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
interface WorkflowJournalRow {
|
|
141
|
+
run_id: string;
|
|
142
|
+
seq: number;
|
|
143
|
+
call_hash: string;
|
|
144
|
+
kind: string;
|
|
145
|
+
request_json: string | null;
|
|
146
|
+
result_json: string | null;
|
|
147
|
+
status: string;
|
|
148
|
+
created_at: number | null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Parse a nullable JSON column; malformed values collapse to null. */
|
|
152
|
+
function parseJsonColumn(value: string | null): unknown {
|
|
153
|
+
if (value === null) return null;
|
|
154
|
+
try {
|
|
155
|
+
return JSON.parse(value);
|
|
156
|
+
} catch {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Serialize a value for a nullable JSON column. `undefined` stores as null. */
|
|
162
|
+
function serializeJsonColumn(value: unknown): string | null {
|
|
163
|
+
return value === undefined || value === null ? null : JSON.stringify(value);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function rowToRun(row: WorkflowRunRow): WorkflowRun {
|
|
167
|
+
return {
|
|
168
|
+
id: row.id,
|
|
169
|
+
name: row.name,
|
|
170
|
+
scriptSource: row.script_source,
|
|
171
|
+
scriptHash: row.script_hash,
|
|
172
|
+
args: parseJsonColumn(row.args_json),
|
|
173
|
+
capabilities: parseJsonColumn(row.capabilities_json),
|
|
174
|
+
status: row.status as WorkflowRunStatus,
|
|
175
|
+
conversationId: row.conversation_id,
|
|
176
|
+
trust: parseJsonColumn(row.trust_json),
|
|
177
|
+
agentsSpawned: row.agents_spawned,
|
|
178
|
+
inputTokens: row.input_tokens,
|
|
179
|
+
outputTokens: row.output_tokens,
|
|
180
|
+
result: parseJsonColumn(row.result_json),
|
|
181
|
+
error: row.error,
|
|
182
|
+
createdAt: row.created_at,
|
|
183
|
+
updatedAt: row.updated_at,
|
|
184
|
+
finishedAt: row.finished_at,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function rowToJournalEntry(row: WorkflowJournalRow): WorkflowJournalEntry {
|
|
189
|
+
return {
|
|
190
|
+
runId: row.run_id,
|
|
191
|
+
seq: row.seq,
|
|
192
|
+
callHash: row.call_hash,
|
|
193
|
+
kind: row.kind as WorkflowJournalKind,
|
|
194
|
+
request: parseJsonColumn(row.request_json),
|
|
195
|
+
result: parseJsonColumn(row.result_json),
|
|
196
|
+
status: row.status,
|
|
197
|
+
createdAt: row.created_at,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ---------------------------------------------------------------------------
|
|
202
|
+
// Runs — write
|
|
203
|
+
// ---------------------------------------------------------------------------
|
|
204
|
+
|
|
205
|
+
/** Insert a new workflow run. Defaults status to `running`. */
|
|
206
|
+
export function createRun(input: CreateRunInput): WorkflowRun {
|
|
207
|
+
const now = Date.now();
|
|
208
|
+
const status = input.status ?? "running";
|
|
209
|
+
rawRun(
|
|
210
|
+
/*sql*/ `
|
|
211
|
+
INSERT INTO workflow_runs (
|
|
212
|
+
id, name, script_source, script_hash, args_json, capabilities_json,
|
|
213
|
+
status, conversation_id, trust_json, agents_spawned, input_tokens,
|
|
214
|
+
output_tokens, result_json, error, created_at, updated_at, finished_at
|
|
215
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, 0, NULL, NULL, ?, ?, NULL)
|
|
216
|
+
`,
|
|
217
|
+
input.id,
|
|
218
|
+
input.name ?? null,
|
|
219
|
+
input.scriptSource,
|
|
220
|
+
input.scriptHash,
|
|
221
|
+
serializeJsonColumn(input.args),
|
|
222
|
+
serializeJsonColumn(input.capabilities),
|
|
223
|
+
status,
|
|
224
|
+
input.conversationId ?? null,
|
|
225
|
+
serializeJsonColumn(input.trust),
|
|
226
|
+
now,
|
|
227
|
+
now,
|
|
228
|
+
);
|
|
229
|
+
return getRun(input.id)!;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Patch mutable fields on a run and bump `updated_at`. Only the fields present
|
|
234
|
+
* in `input` are written. Returns the updated run, or null if it doesn't exist.
|
|
235
|
+
*/
|
|
236
|
+
export function updateRun(
|
|
237
|
+
runId: string,
|
|
238
|
+
input: UpdateRunInput,
|
|
239
|
+
): WorkflowRun | null {
|
|
240
|
+
const sets: string[] = [];
|
|
241
|
+
const params: (string | number | null)[] = [];
|
|
242
|
+
|
|
243
|
+
if (input.status !== undefined) {
|
|
244
|
+
sets.push("status = ?");
|
|
245
|
+
params.push(input.status);
|
|
246
|
+
}
|
|
247
|
+
if (input.agentsSpawned !== undefined) {
|
|
248
|
+
sets.push("agents_spawned = ?");
|
|
249
|
+
params.push(input.agentsSpawned);
|
|
250
|
+
}
|
|
251
|
+
if (input.inputTokens !== undefined) {
|
|
252
|
+
sets.push("input_tokens = ?");
|
|
253
|
+
params.push(input.inputTokens);
|
|
254
|
+
}
|
|
255
|
+
if (input.outputTokens !== undefined) {
|
|
256
|
+
sets.push("output_tokens = ?");
|
|
257
|
+
params.push(input.outputTokens);
|
|
258
|
+
}
|
|
259
|
+
if (input.conversationId !== undefined) {
|
|
260
|
+
sets.push("conversation_id = ?");
|
|
261
|
+
params.push(input.conversationId);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
sets.push("updated_at = ?");
|
|
265
|
+
params.push(Date.now());
|
|
266
|
+
params.push(runId);
|
|
267
|
+
|
|
268
|
+
rawRun(`UPDATE workflow_runs SET ${sets.join(", ")} WHERE id = ?`, ...params);
|
|
269
|
+
return getRun(runId);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Mark a run terminal: set its final status, result/error payload, and stamp
|
|
274
|
+
* both `updated_at` and `finished_at`. Returns the updated run, or null if it
|
|
275
|
+
* doesn't exist.
|
|
276
|
+
*/
|
|
277
|
+
export function finishRun(
|
|
278
|
+
runId: string,
|
|
279
|
+
input: FinishRunInput,
|
|
280
|
+
): WorkflowRun | null {
|
|
281
|
+
const now = Date.now();
|
|
282
|
+
rawRun(
|
|
283
|
+
/*sql*/ `
|
|
284
|
+
UPDATE workflow_runs
|
|
285
|
+
SET status = ?, result_json = ?, error = ?, updated_at = ?, finished_at = ?
|
|
286
|
+
WHERE id = ?
|
|
287
|
+
`,
|
|
288
|
+
input.status,
|
|
289
|
+
serializeJsonColumn(input.result),
|
|
290
|
+
input.error ?? null,
|
|
291
|
+
now,
|
|
292
|
+
now,
|
|
293
|
+
runId,
|
|
294
|
+
);
|
|
295
|
+
return getRun(runId);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
299
|
+
// Journal — write
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Append a leaf-call entry to a run's journal, upserting on `(run_id, seq)`.
|
|
304
|
+
*
|
|
305
|
+
* A genuine duplicate re-append (same hash/result — the crash-recovery case
|
|
306
|
+
* where a write replays after a crash between the call and its journal write)
|
|
307
|
+
* is idempotent: the conflicting row is overwritten with identical values.
|
|
308
|
+
*
|
|
309
|
+
* On resume, a leaf whose input CHANGED re-runs and produces a new
|
|
310
|
+
* hash/result/status at the same `seq`; the UPSERT rewrites the stale first-run
|
|
311
|
+
* row so the persisted journal agrees with the value the engine returned (and
|
|
312
|
+
* the call doesn't re-run on every future resume). `created_at` is left at its
|
|
313
|
+
* original value on conflict so the row keeps its first-write timestamp.
|
|
314
|
+
*/
|
|
315
|
+
export function appendJournalEntry(
|
|
316
|
+
input: AppendJournalEntryInput,
|
|
317
|
+
): WorkflowJournalEntry {
|
|
318
|
+
rawRun(
|
|
319
|
+
/*sql*/ `
|
|
320
|
+
INSERT INTO workflow_journal (
|
|
321
|
+
run_id, seq, call_hash, kind, request_json, result_json, status, created_at
|
|
322
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
323
|
+
ON CONFLICT(run_id, seq) DO UPDATE SET
|
|
324
|
+
call_hash = excluded.call_hash,
|
|
325
|
+
kind = excluded.kind,
|
|
326
|
+
request_json = excluded.request_json,
|
|
327
|
+
result_json = excluded.result_json,
|
|
328
|
+
status = excluded.status
|
|
329
|
+
`,
|
|
330
|
+
input.runId,
|
|
331
|
+
input.seq,
|
|
332
|
+
input.callHash,
|
|
333
|
+
input.kind,
|
|
334
|
+
serializeJsonColumn(input.request),
|
|
335
|
+
serializeJsonColumn(input.result),
|
|
336
|
+
input.status,
|
|
337
|
+
Date.now(),
|
|
338
|
+
);
|
|
339
|
+
return getJournalEntry(input.runId, input.seq)!;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ---------------------------------------------------------------------------
|
|
343
|
+
// Runs + journal — read
|
|
344
|
+
// ---------------------------------------------------------------------------
|
|
345
|
+
|
|
346
|
+
/** Fetch a single run by id, or null if it doesn't exist. */
|
|
347
|
+
export function getRun(runId: string): WorkflowRun | null {
|
|
348
|
+
const row = rawGet<WorkflowRunRow>(
|
|
349
|
+
`SELECT * FROM workflow_runs WHERE id = ?`,
|
|
350
|
+
runId,
|
|
351
|
+
);
|
|
352
|
+
return row ? rowToRun(row) : null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** Fetch a run's full journal in sequence order for resume replay. */
|
|
356
|
+
export function getJournal(runId: string): WorkflowJournalEntry[] {
|
|
357
|
+
const rows = rawAll<WorkflowJournalRow>(
|
|
358
|
+
`SELECT * FROM workflow_journal WHERE run_id = ? ORDER BY seq ASC`,
|
|
359
|
+
runId,
|
|
360
|
+
);
|
|
361
|
+
return rows.map(rowToJournalEntry);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** Fetch a single journal entry by its `(run_id, seq)` key, or null. */
|
|
365
|
+
export function getJournalEntry(
|
|
366
|
+
runId: string,
|
|
367
|
+
seq: number,
|
|
368
|
+
): WorkflowJournalEntry | null {
|
|
369
|
+
const row = rawGet<WorkflowJournalRow>(
|
|
370
|
+
`SELECT * FROM workflow_journal WHERE run_id = ? AND seq = ?`,
|
|
371
|
+
runId,
|
|
372
|
+
seq,
|
|
373
|
+
);
|
|
374
|
+
return row ? rowToJournalEntry(row) : null;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export interface ListRunsOptions {
|
|
378
|
+
limit: number;
|
|
379
|
+
status?: WorkflowRunStatus;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** List runs newest-first, optionally filtered by status. */
|
|
383
|
+
export function listRuns(options: ListRunsOptions): WorkflowRun[] {
|
|
384
|
+
const rows = options.status
|
|
385
|
+
? rawAll<WorkflowRunRow>(
|
|
386
|
+
`SELECT * FROM workflow_runs WHERE status = ? ORDER BY created_at DESC LIMIT ?`,
|
|
387
|
+
options.status,
|
|
388
|
+
options.limit,
|
|
389
|
+
)
|
|
390
|
+
: rawAll<WorkflowRunRow>(
|
|
391
|
+
`SELECT * FROM workflow_runs ORDER BY created_at DESC LIMIT ?`,
|
|
392
|
+
options.limit,
|
|
393
|
+
);
|
|
394
|
+
return rows.map(rowToRun);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// ---------------------------------------------------------------------------
|
|
398
|
+
// Startup reconciliation
|
|
399
|
+
// ---------------------------------------------------------------------------
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Flip every `running` run to `interrupted`. Called once at daemon startup: a
|
|
403
|
+
* row left in `running` means the process died mid-run (nothing else can leave
|
|
404
|
+
* a row `running` after the engine exits, which always finishes it). Marking it
|
|
405
|
+
* `interrupted` makes it eligible for an explicit resume.
|
|
406
|
+
*
|
|
407
|
+
* STATUS ONLY — `agents_spawned`/`input_tokens`/`output_tokens` are NOT touched.
|
|
408
|
+
* The run row is the source of truth for ACCOUNTING (it seeds the resumed run's
|
|
409
|
+
* cap counters) while the journal is the source of truth for REPLAY; rewriting
|
|
410
|
+
* the counters here would drift the cap accounting. Returns the number of rows
|
|
411
|
+
* reconciled.
|
|
412
|
+
*/
|
|
413
|
+
export function markRunningAsInterrupted(): number {
|
|
414
|
+
return rawRun(
|
|
415
|
+
/*sql*/ `UPDATE workflow_runs SET status = 'interrupted', updated_at = ? WHERE status = 'running'`,
|
|
416
|
+
Date.now(),
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// ---------------------------------------------------------------------------
|
|
421
|
+
// Retention
|
|
422
|
+
// ---------------------------------------------------------------------------
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Set of genuinely TERMINAL run statuses — the only rows `pruneRuns` may reap.
|
|
426
|
+
* A run is non-terminal (and therefore retained regardless of age) when it is
|
|
427
|
+
* still `running` OR `interrupted`: an `interrupted` run is a crash-orphaned
|
|
428
|
+
* row awaiting an explicit resume, so pruning it would destroy resumability.
|
|
429
|
+
*/
|
|
430
|
+
const TERMINAL_RUN_STATUSES: readonly WorkflowRunStatus[] = [
|
|
431
|
+
"completed",
|
|
432
|
+
"failed",
|
|
433
|
+
"aborted",
|
|
434
|
+
"cap_exceeded",
|
|
435
|
+
];
|
|
436
|
+
|
|
437
|
+
/** SQL list literal of the terminal statuses, e.g. `'completed','failed',...`. */
|
|
438
|
+
const TERMINAL_RUN_STATUS_SQL = TERMINAL_RUN_STATUSES.map((s) => `'${s}'`).join(
|
|
439
|
+
", ",
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Delete TERMINAL runs older than `retentionDays` (by `created_at`) and their
|
|
444
|
+
* journal entries. Non-terminal runs are never pruned, regardless of age:
|
|
445
|
+
* `running` rows could be reaped out from under the engine, and `interrupted`
|
|
446
|
+
* rows are crash-orphaned and still resumable — deleting either would destroy
|
|
447
|
+
* an in-flight or resumable run. Returns the number of runs deleted.
|
|
448
|
+
*/
|
|
449
|
+
export function pruneRuns(retentionDays: number): number {
|
|
450
|
+
const cutoff = Date.now() - retentionDays * 24 * 60 * 60 * 1000;
|
|
451
|
+
rawRun(
|
|
452
|
+
/*sql*/ `
|
|
453
|
+
DELETE FROM workflow_journal
|
|
454
|
+
WHERE run_id IN (
|
|
455
|
+
SELECT id FROM workflow_runs
|
|
456
|
+
WHERE status IN (${TERMINAL_RUN_STATUS_SQL})
|
|
457
|
+
AND created_at IS NOT NULL AND created_at < ?
|
|
458
|
+
)
|
|
459
|
+
`,
|
|
460
|
+
cutoff,
|
|
461
|
+
);
|
|
462
|
+
return rawRun(
|
|
463
|
+
/*sql*/ `
|
|
464
|
+
DELETE FROM workflow_runs
|
|
465
|
+
WHERE status IN (${TERMINAL_RUN_STATUS_SQL})
|
|
466
|
+
AND created_at IS NOT NULL AND created_at < ?
|
|
467
|
+
`,
|
|
468
|
+
cutoff,
|
|
469
|
+
);
|
|
470
|
+
}
|