@vellumai/assistant 0.9.0 → 0.10.0-dev.202606192226.8ed8a6a
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/ARCHITECTURE.md +19 -35
- package/bun.lock +7 -8
- package/docs/activation-funnel-telemetry.md +28 -22
- package/docs/architecture/security.md +29 -28
- package/docs/stt-provider-onboarding.md +3 -5
- package/docs/workflows-testing.md +13 -44
- package/docs/workflows.md +3 -5
- package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
- package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
- package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
- package/openapi.yaml +1128 -119
- package/package.json +2 -1
- package/scripts/sync-llm-catalog.ts +6 -15
- package/scripts/sync-web-search-catalog.ts +3 -11
- package/src/__tests__/access-request-card-view.test.ts +98 -0
- package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
- package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
- package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
- package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
- package/src/__tests__/app-compiler.test.ts +15 -1
- package/src/__tests__/app-dir-path-guard.test.ts +0 -1
- package/src/__tests__/approval-cascade.test.ts +6 -0
- package/src/__tests__/approval-routes-http.test.ts +128 -0
- package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
- package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
- package/src/__tests__/avatar-identity-sync.test.ts +2 -27
- package/src/__tests__/btw-routes.test.ts +6 -8
- package/src/__tests__/call-pointer-messages.test.ts +28 -0
- package/src/__tests__/cancel-clears-processing.test.ts +89 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -4
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
- package/src/__tests__/checker.test.ts +0 -3
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
- package/src/__tests__/compaction-events.test.ts +6 -0
- package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
- package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
- package/src/__tests__/config-loader-backfill.test.ts +268 -27
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/config-watcher.test.ts +0 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +0 -6
- package/src/__tests__/contacts-tools.test.ts +29 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +58 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
- package/src/__tests__/conversation-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-process-callsite.test.ts +6 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-queue.test.ts +6 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-slash-queue.test.ts +6 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +6 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/credential-broker.test.ts +449 -1
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
- package/src/__tests__/credential-execution-tools.test.ts +0 -1
- package/src/__tests__/credential-prompt-route.test.ts +4 -4
- package/src/__tests__/credential-routes.test.ts +360 -0
- package/src/__tests__/credential-security-invariants.test.ts +4 -13
- package/src/__tests__/disk-pressure-policy.test.ts +12 -0
- package/src/__tests__/disk-pressure-tools.test.ts +41 -1
- package/src/__tests__/disk-usage.test.ts +65 -0
- package/src/__tests__/document-tool-security.test.ts +9 -6
- package/src/__tests__/document-update-default-surface.test.ts +202 -0
- package/src/__tests__/dynamic-page-surface.test.ts +152 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
- package/src/__tests__/gateway-flag-listener.test.ts +110 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -7
- package/src/__tests__/gemini-count-tokens.test.ts +70 -0
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
- package/src/__tests__/guardian-grant-minting.test.ts +3 -35
- package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/headless-browser-mode.test.ts +10 -0
- package/src/__tests__/headless-browser-navigate.test.ts +8 -3
- package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
- package/src/__tests__/host-browser-proxy.test.ts +87 -0
- package/src/__tests__/identity-routes.test.ts +0 -189
- package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
- package/src/__tests__/injector-disk-pressure.test.ts +10 -5
- package/src/__tests__/injector-v3-suppression.test.ts +27 -20
- package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
- package/src/__tests__/invite-redemption-service.test.ts +4 -7
- package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +30 -23
- package/src/__tests__/llm-resolver.test.ts +70 -24
- package/src/__tests__/llm-schema.test.ts +1 -0
- package/src/__tests__/managed-profile-guard.test.ts +163 -4
- package/src/__tests__/mcp-health-check.test.ts +6 -7
- package/src/__tests__/media-stream-server-integration.test.ts +317 -13
- package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
- package/src/__tests__/onboarding-persona-write.test.ts +1 -1
- package/src/__tests__/path-policy.test.ts +34 -0
- package/src/__tests__/persona-resolver.test.ts +49 -14
- package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
- package/src/__tests__/plugin-api-provider.test.ts +24 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
- package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
- package/src/__tests__/reaction-persistence.test.ts +150 -29
- package/src/__tests__/registry.test.ts +2 -7
- package/src/__tests__/relay-server.test.ts +285 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
- package/src/__tests__/schedule-routes.test.ts +0 -30
- package/src/__tests__/schedule-tools.test.ts +2 -18
- package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
- package/src/__tests__/secret-response-routing.test.ts +35 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +16 -2
- package/src/__tests__/skill-execute-input.test.ts +177 -1
- package/src/__tests__/skill-load-tool.test.ts +72 -0
- package/src/__tests__/skill-runtime-path.test.ts +2 -3
- package/src/__tests__/skills.test.ts +51 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
- package/src/__tests__/subagent-tools.test.ts +266 -0
- package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
- package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
- package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
- package/src/__tests__/title-generate-hook.test.ts +100 -3
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
- package/src/__tests__/token-manager.test.ts +519 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
- package/src/__tests__/tool-audit-listener.test.ts +7 -7
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
- package/src/__tests__/tool-executor.test.ts +0 -79
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
- package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
- package/src/__tests__/trusted-contact-verification.test.ts +8 -10
- package/src/__tests__/twilio-routes.test.ts +81 -1
- package/src/__tests__/voice-invite-redemption.test.ts +2 -3
- package/src/__tests__/weak-open-model.test.ts +30 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
- package/src/__tests__/workspace-greetings.test.ts +152 -0
- package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
- package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
- package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
- package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
- package/src/agent/loop.ts +75 -29
- package/src/api/README.md +6 -6
- package/src/api/events/tool-result.ts +6 -0
- package/src/api/events/workflow-completed.ts +53 -0
- package/src/api/events/workflow-leaf-finished.ts +38 -0
- package/src/api/events/workflow-leaf-started.ts +35 -0
- package/src/api/events/workflow-progress.ts +32 -0
- package/src/api/events/workflow-started.ts +31 -0
- package/src/api/index.ts +40 -0
- package/src/api/responses/conversation-message.ts +28 -4
- package/src/api/responses/home.ts +26 -4
- package/src/api/responses/workflow-journal.ts +53 -0
- package/src/approvals/guardian-card-withdrawal.ts +145 -0
- package/src/approvals/guardian-decision-primitive.ts +26 -3
- package/src/approvals/guardian-request-resolvers.ts +183 -80
- package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
- package/src/calls/call-pointer-messages.ts +10 -4
- package/src/calls/channel-admission-reader.ts +104 -0
- package/src/calls/guardian-dispatch.ts +17 -45
- package/src/calls/media-stream-server.ts +84 -2
- package/src/calls/relay-access-wait.ts +1 -1
- package/src/calls/relay-server.ts +66 -0
- package/src/calls/relay-setup-router.ts +82 -1
- package/src/calls/twilio-routes.ts +17 -8
- package/src/calls/voice-session-bridge.ts +2 -2
- package/src/cli/commands/clients.ts +3 -0
- package/src/cli/commands/db/status.ts +37 -3
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
- package/src/cli/commands/memory/index.ts +30 -0
- package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
- package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
- package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
- package/src/cli/commands/oauth/status.test.ts +36 -0
- package/src/cli/commands/oauth/status.ts +23 -3
- package/src/cli/commands/plugins.ts +400 -14
- package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +31 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
- package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
- package/src/cli/lib/diff-plugin.ts +346 -0
- package/src/cli/lib/inspect-plugin.ts +12 -1
- package/src/cli/lib/install-from-github.ts +128 -19
- package/src/cli/lib/merge-plugin-tree.ts +328 -0
- package/src/cli/lib/plugin-fingerprint.ts +14 -0
- package/src/cli/lib/plugin-marketplace.ts +11 -0
- package/src/cli/lib/plugin-pin-history.ts +257 -0
- package/src/cli/lib/plugin-surfaces.ts +104 -0
- package/src/cli/lib/upgrade-plugin.ts +298 -10
- package/src/cli/program.ts +2 -6
- package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
- package/src/config/assistant-feature-flags.ts +22 -7
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
- package/src/config/bundled-skills/document-editor/SKILL.md +3 -3
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- package/src/config/bundled-skills/messaging/SKILL.md +6 -4
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
- package/src/config/bundled-skills/subagent/SKILL.md +4 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
- package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
- package/src/config/bundled-skills/workflows/SKILL.md +14 -8
- package/src/config/bundled-tool-registry.ts +2 -7
- package/src/config/call-site-defaults.ts +15 -2
- package/src/config/feature-flag-registry.json +46 -31
- package/src/config/inference-profile-validation.ts +26 -0
- package/src/config/llm-resolver.ts +3 -0
- package/src/config/loader.ts +4 -0
- package/src/config/memory-v3-gate.ts +11 -0
- package/src/config/profile-order.ts +28 -0
- package/src/config/schema.ts +8 -6
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/channels.ts +11 -0
- package/src/config/schemas/elevenlabs.ts +0 -1
- package/src/config/schemas/llm.ts +31 -0
- package/src/config/schemas/memory-lifecycle.ts +3 -7
- package/src/config/schemas/memory-v3.ts +6 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/services.ts +18 -0
- package/src/config/seed-inference-profiles.ts +109 -44
- package/src/config/skills.ts +21 -0
- package/src/config/sync-gated-profiles.ts +220 -0
- package/src/contacts/contact-store.ts +89 -106
- package/src/contacts/contacts-write.ts +5 -22
- package/src/contacts/types.ts +0 -1
- package/src/context/compactor.ts +88 -54
- package/src/context/strip-injections.ts +58 -10
- package/src/context/token-estimator.ts +1 -1
- package/src/credential-execution/process-manager.ts +55 -14
- package/src/credential-execution/prompted-credential.ts +2 -3
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
- package/src/daemon/config-watcher.ts +0 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
- package/src/daemon/conversation-agent-loop.ts +114 -22
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +3 -5
- package/src/daemon/conversation-process.ts +13 -5
- package/src/daemon/conversation-runtime-assembly.ts +13 -15
- package/src/daemon/conversation-slash.ts +2 -23
- package/src/daemon/conversation-surfaces.ts +26 -0
- package/src/daemon/conversation-tool-setup.ts +53 -19
- package/src/daemon/conversation.ts +131 -20
- package/src/daemon/disk-pressure-policy.ts +5 -3
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
- package/src/daemon/handlers/config-a2a.ts +0 -2
- package/src/daemon/handlers/config-channels.ts +15 -16
- package/src/daemon/handlers/config-slack-channel.ts +22 -3
- package/src/daemon/handlers/conversations.ts +107 -0
- package/src/daemon/host-browser-proxy.ts +41 -0
- package/src/daemon/lifecycle.ts +55 -27
- package/src/daemon/memory-v2-startup.test.ts +131 -0
- package/src/daemon/memory-v2-startup.ts +100 -1
- package/src/daemon/message-provenance.ts +2 -0
- package/src/daemon/message-types/contacts.ts +0 -1
- package/src/daemon/message-types/conversations.ts +3 -3
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/message-types/web-activity.ts +7 -1
- package/src/daemon/message-types/workflows.ts +83 -1
- package/src/daemon/orphan-reaper.test.ts +0 -19
- package/src/daemon/orphan-reaper.ts +2 -24
- package/src/daemon/server.ts +0 -10
- package/src/daemon/tool-setup-types.ts +4 -0
- package/src/daemon/trust-context.ts +1 -1
- package/src/daemon/wake-conversation-ops.ts +1 -0
- package/src/events/tool-audit-listener.ts +2 -2
- package/src/home/feed-source-enrichment.test.ts +151 -0
- package/src/home/feed-source-enrichment.ts +176 -0
- package/src/home/relationship-state.ts +2 -4
- package/src/instrument.ts +18 -6
- package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
- package/src/ipc/assistant-server.ts +37 -4
- package/src/ipc/gateway-flag-listener.ts +18 -2
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
- package/src/memory/__tests__/db-logs-attach.test.ts +122 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
- package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
- package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
- package/src/memory/auth-fallback-events-store.ts +2 -2
- package/src/memory/auto-analysis-enqueue.ts +3 -5
- package/src/memory/bookmark-crud.ts +1 -2
- package/src/memory/canonical-guardian-store.ts +39 -1
- package/src/memory/conversation-crud.ts +9 -4
- package/src/memory/conversation-key-store.ts +17 -2
- package/src/memory/conversation-title-service.ts +64 -7
- package/src/memory/db-async-query.ts +20 -2
- package/src/memory/db-connection.ts +49 -5
- package/src/memory/db-init.ts +17 -17
- package/src/memory/embedding-backend.ts +38 -1
- package/src/memory/embedding-billing-breaker.ts +96 -0
- package/src/memory/jobs-store.ts +25 -13
- package/src/memory/jobs-worker.ts +54 -1
- package/src/memory/lifecycle-events-store.ts +2 -2
- package/src/memory/memory-retrospective-constants.ts +4 -4
- package/src/memory/memory-retrospective-enqueue.ts +31 -6
- package/src/memory/memory-retrospective-job.ts +28 -227
- package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
- package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
- package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
- package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
- package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
- package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
- package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
- package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/run-migrations.ts +41 -0
- package/src/memory/migrations/validate-migration-state.ts +1 -1
- package/src/memory/onboarding-events-store.ts +3 -3
- package/src/memory/schema/contacts.ts +0 -5
- package/src/memory/skill-loaded-events-store.test.ts +7 -15
- package/src/memory/skill-loaded-events-store.ts +2 -2
- package/src/memory/tool-executed-events-store.test.ts +7 -7
- package/src/memory/turn-trace-store.test.ts +736 -0
- package/src/memory/turn-trace-store.ts +364 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
- package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
- package/src/memory/v2/consolidation-job.ts +2 -2
- package/src/memory/v2/skill-content.ts +25 -7
- package/src/memory/v2/skill-store.ts +7 -1
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
- package/src/memory/v3-eval/eval-packets.ts +546 -0
- package/src/messaging/providers/slack/adapter.ts +1 -1
- package/src/messaging/providers/slack/api.ts +31 -0
- package/src/messaging/providers/slack/send.test.ts +114 -2
- package/src/messaging/providers/slack/send.ts +30 -7
- package/src/messaging/providers/slack/withdraw.test.ts +200 -0
- package/src/messaging/providers/slack/withdraw.ts +161 -0
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/access-request-copy.ts +72 -59
- package/src/notifications/adapters/shared.ts +29 -0
- package/src/notifications/adapters/slack.ts +58 -103
- package/src/notifications/adapters/telegram.ts +2 -20
- package/src/notifications/approval-card-data.ts +333 -0
- package/src/notifications/broadcaster.ts +16 -3
- package/src/notifications/canonical-delivery-recorder.ts +139 -0
- package/src/notifications/copy-composer.ts +3 -3
- package/src/notifications/decision-engine.ts +4 -2
- package/src/notifications/destination-resolver.ts +4 -6
- package/src/notifications/guardian-question-mode.ts +10 -0
- package/src/notifications/home-feed-side-effect.ts +7 -16
- package/src/notifications/notification-utils.ts +19 -20
- package/src/notifications/signal.ts +79 -43
- package/src/notifications/types.ts +98 -121
- package/src/oauth/AGENTS.md +5 -24
- package/src/permissions/checker.test.ts +51 -0
- package/src/permissions/checker.ts +185 -26
- package/src/permissions/ipc-risk-types.ts +24 -0
- package/src/permissions/question-prompter.test.ts +27 -0
- package/src/permissions/question-prompter.ts +4 -0
- package/src/permissions/secret-prompter.ts +15 -1
- package/src/platform/client.test.ts +119 -0
- package/src/platform/client.ts +66 -0
- package/src/platform/consent-cache.test.ts +267 -0
- package/src/platform/consent-cache.ts +174 -0
- package/src/plugin-api/constants.ts +1 -1
- package/src/plugin-api/index.ts +33 -1
- package/src/plugin-api/model-profiles.ts +33 -0
- package/src/plugin-api/types.ts +50 -2
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
- package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
- package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
- package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
- package/src/plugins/defaults/advisor/config.ts +21 -0
- package/src/plugins/defaults/advisor/consult.ts +93 -0
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/advisor/package.json +14 -0
- package/src/plugins/defaults/advisor/steering.ts +67 -0
- package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
- package/src/plugins/defaults/advisor/transcript.ts +76 -0
- package/src/plugins/defaults/compaction/window-manager.ts +18 -0
- package/src/plugins/defaults/index.ts +60 -0
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
- package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
- package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
- package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
- package/src/prompts/persona-resolver.ts +14 -4
- package/src/prompts/templates/system-sections.ts +7 -2
- package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
- package/src/providers/__tests__/retry-callsite.test.ts +176 -0
- package/src/providers/anthropic/client.ts +230 -175
- package/src/providers/atlascloud/client.ts +85 -0
- package/src/providers/call-site-routing.ts +10 -0
- package/src/providers/fetch-provider-catalog.ts +85 -0
- package/src/providers/gemini/client.ts +43 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/model-catalog.ts +58 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
- package/src/providers/openai/chat-completions-provider.ts +7 -0
- package/src/providers/openai/responses-provider.ts +10 -0
- package/src/providers/provider-send-message.ts +11 -3
- package/src/providers/ratelimit.ts +9 -0
- package/src/providers/retry.ts +62 -12
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/types.ts +16 -0
- package/src/providers/usage-tracking.ts +7 -0
- package/src/providers/weak-open-model.ts +22 -0
- package/src/runtime/AGENTS.md +0 -1
- package/src/runtime/__tests__/agent-wake.test.ts +227 -0
- package/src/runtime/__tests__/client-health.test.ts +44 -0
- package/src/runtime/access-request-helper.ts +21 -53
- package/src/runtime/actor-trust-resolver.ts +59 -63
- package/src/runtime/agent-wake.ts +71 -0
- package/src/runtime/assistant-event-hub.ts +18 -4
- package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -6
- package/src/runtime/capabilities.test.ts +120 -0
- package/src/runtime/capabilities.ts +197 -0
- package/src/runtime/channel-approval-types.ts +22 -45
- package/src/runtime/channel-invite-transports/telegram.ts +4 -4
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/channel-verification-service.ts +3 -3
- package/src/runtime/client-health.ts +26 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
- package/src/runtime/effective-capabilities.test.ts +128 -0
- package/src/runtime/effective-capabilities.ts +84 -0
- package/src/runtime/guardian-reply-router.ts +106 -21
- package/src/runtime/invite-redemption-service.ts +9 -25
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +126 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +35 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +383 -1
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/approval-routes.ts +40 -9
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
- package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
- package/src/runtime/routes/browser-tabs-routes.ts +9 -0
- package/src/runtime/routes/btw-routes.ts +1 -27
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
- package/src/runtime/routes/client-routes.ts +10 -0
- package/src/runtime/routes/contact-routes.ts +31 -8
- package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
- package/src/runtime/routes/conversation-management-routes.ts +80 -1
- package/src/runtime/routes/conversation-query-routes.ts +68 -22
- package/src/runtime/routes/conversation-routes.ts +39 -14
- package/src/runtime/routes/credential-routes.ts +40 -16
- package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
- package/src/runtime/routes/events-routes.ts +1 -3
- package/src/runtime/routes/guardian-approval-interception.ts +14 -73
- package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
- package/src/runtime/routes/home-feed-routes.ts +8 -3
- package/src/runtime/routes/identity-routes.ts +1 -296
- package/src/runtime/routes/inbound-message-handler.ts +214 -228
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
- package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
- package/src/runtime/routes/integrations/slack/channel.ts +36 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
- package/src/runtime/routes/mcp-auth-routes.ts +233 -41
- package/src/runtime/routes/memory-eval-routes.ts +87 -0
- package/src/runtime/routes/notification-routes.ts +122 -133
- package/src/runtime/routes/platform-routes.ts +2 -2
- package/src/runtime/routes/plugins-routes.ts +366 -11
- package/src/runtime/routes/schedule-routes.ts +0 -22
- package/src/runtime/routes/secret-routes.ts +15 -0
- package/src/runtime/routes/surface-action-routes.ts +2 -1
- package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
- package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
- package/src/runtime/routes/workflow-routes.test.ts +229 -44
- package/src/runtime/routes/workflow-routes.ts +131 -29
- package/src/runtime/routes/workspace-greetings.ts +55 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -11
- package/src/runtime/tool-grant-request-helper.ts +18 -16
- package/src/runtime/trust-context-resolver.ts +8 -5
- package/src/schedule/inference-profile.ts +2 -14
- package/src/schedule/schedule-store.ts +1 -1
- package/src/schedule/scheduler-types.ts +5 -1
- package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
- package/src/security/secret-patterns.ts +3 -0
- package/src/subagent/manager.ts +17 -4
- package/src/subagent/types.ts +6 -0
- package/src/telemetry/trace-collection-policy.test.ts +28 -0
- package/src/telemetry/trace-collection-policy.ts +30 -0
- package/src/telemetry/types.ts +89 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
- package/src/telemetry/usage-telemetry-reporter.ts +148 -41
- package/src/tools/AGENTS.md +3 -3
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
- package/src/tools/browser/browser-execution.ts +30 -19
- package/src/tools/document/document-tool.ts +30 -6
- package/src/tools/executor.ts +5 -3
- package/src/tools/host-terminal/host-shell.ts +5 -4
- package/src/tools/memory/register.ts +2 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
- package/src/tools/network/__tests__/web-search.test.ts +143 -0
- package/src/tools/network/web-fetch.ts +372 -1
- package/src/tools/network/web-search-error.ts +1 -1
- package/src/tools/network/web-search.ts +213 -10
- package/src/tools/permission-checker.ts +4 -3
- package/src/tools/registry.ts +20 -0
- package/src/tools/schedule/create.ts +7 -12
- package/src/tools/schedule/update.ts +4 -11
- package/src/tools/shared/filesystem/path-policy.ts +39 -13
- package/src/tools/side-effects.ts +2 -17
- package/src/tools/skills/execute.ts +99 -2
- package/src/tools/skills/load.ts +43 -2
- package/src/tools/subagent/spawn.ts +64 -15
- package/src/tools/terminal/shell.ts +10 -4
- package/src/tools/tool-approval-handler.ts +18 -13
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/types.ts +10 -0
- package/src/tools/ui-surface/definitions.ts +64 -3
- package/src/tools/verification-control-plane-policy.ts +3 -1
- package/src/tools/workflows/run-workflow.test.ts +8 -18
- package/src/tools/workflows/run-workflow.ts +1 -0
- package/src/util/disk-usage.ts +78 -23
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/platform.ts +10 -3
- package/src/watcher/telemetry.ts +2 -2
- package/src/workflows/capabilities.ts +2 -3
- package/src/workflows/engine.test.ts +175 -1
- package/src/workflows/engine.ts +82 -0
- package/src/workflows/journal-store.test.ts +70 -0
- package/src/workflows/journal-store.ts +18 -3
- package/src/workflows/run-manager.test.ts +171 -28
- package/src/workflows/run-manager.ts +66 -24
- package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
- package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
- package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
- package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
- package/src/__tests__/credential-security-e2e.test.ts +0 -362
- package/src/__tests__/credential-vault-unit.test.ts +0 -1528
- package/src/__tests__/credential-vault.test.ts +0 -1706
- package/src/__tests__/identity-intro-cache.test.ts +0 -315
- package/src/__tests__/secret-onetime-send.test.ts +0 -182
- package/src/cli/commands/__tests__/task.test.ts +0 -914
- package/src/cli/commands/task.ts +0 -771
- package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
- package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
- package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
- package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
- package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
- package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
- package/src/memory/preloaded-apps.ts +0 -116
- package/src/notifications/tool-approval-copy.ts +0 -142
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
- package/src/runtime/routes/identity-intro-cache.ts +0 -172
- package/src/tools/credentials/vault.ts +0 -712
|
@@ -11,11 +11,9 @@ mock.module("../../util/logger.js", () => ({
|
|
|
11
11
|
}));
|
|
12
12
|
|
|
13
13
|
// ── Mutable mock state ────────────────────────────────────────────────
|
|
14
|
-
// `
|
|
15
|
-
//
|
|
16
|
-
// records the args of the last `start()` call for assertion.
|
|
14
|
+
// `configThrows` simulates config not yet loaded (test-setup race). The
|
|
15
|
+
// run-manager mock records the args of the last `start()` call for assertion.
|
|
17
16
|
|
|
18
|
-
let flagEnabled = true;
|
|
19
17
|
let configThrows = false;
|
|
20
18
|
|
|
21
19
|
const realLoader = await import("../../config/loader.js");
|
|
@@ -35,13 +33,6 @@ mock.module("../../config/loader.js", () => ({
|
|
|
35
33
|
}) as unknown as ReturnType<typeof realLoader.loadConfig>,
|
|
36
34
|
}));
|
|
37
35
|
|
|
38
|
-
const realFlags = await import("../../config/assistant-feature-flags.js");
|
|
39
|
-
mock.module("../../config/assistant-feature-flags.js", () => ({
|
|
40
|
-
...realFlags,
|
|
41
|
-
isAssistantFeatureFlagEnabled: (key: string) =>
|
|
42
|
-
key === "workflows" ? flagEnabled : false,
|
|
43
|
-
}));
|
|
44
|
-
|
|
45
36
|
// No live conversation in tests — the tool falls back to a synthetic trust
|
|
46
37
|
// context built from the tool context's trustClass.
|
|
47
38
|
const realRegistry = await import("../../daemon/conversation-registry.js");
|
|
@@ -92,7 +83,6 @@ function makeContext(): Parameters<typeof executeRunWorkflow>[1] {
|
|
|
92
83
|
}
|
|
93
84
|
|
|
94
85
|
beforeEach(() => {
|
|
95
|
-
flagEnabled = true;
|
|
96
86
|
configThrows = false;
|
|
97
87
|
startThrows = null;
|
|
98
88
|
lastStartArgs = null;
|
|
@@ -105,10 +95,10 @@ beforeEach(() => {
|
|
|
105
95
|
});
|
|
106
96
|
|
|
107
97
|
describe("workflow tools are served by the workflows skill", () => {
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
98
|
+
// run_workflow / manage_workflows are served by the `workflows` bundled skill
|
|
99
|
+
// (loaded via skill_load, invoked via skill_execute), not the always-on tool
|
|
100
|
+
// manifest. The skill manifest is the source of truth; assert it declares both
|
|
101
|
+
// as in-process host tools.
|
|
112
102
|
test("the workflows skill TOOLS.json declares both host-executed tools", async () => {
|
|
113
103
|
const { readFileSync } = await import("node:fs");
|
|
114
104
|
const { join } = await import("node:path");
|
|
@@ -211,13 +201,13 @@ describe("run_workflow launch", () => {
|
|
|
211
201
|
});
|
|
212
202
|
|
|
213
203
|
test("surfaces a run-manager start error as a tool error", async () => {
|
|
214
|
-
startThrows = new Error("
|
|
204
|
+
startThrows = new Error("run manager exploded");
|
|
215
205
|
const res = await executeRunWorkflow(
|
|
216
206
|
{ script: "export const meta = {};" },
|
|
217
207
|
makeContext(),
|
|
218
208
|
);
|
|
219
209
|
expect(res.isError).toBe(true);
|
|
220
|
-
expect(res.content).toContain("
|
|
210
|
+
expect(res.content).toContain("run manager exploded");
|
|
221
211
|
});
|
|
222
212
|
});
|
|
223
213
|
|
package/src/util/disk-usage.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { existsSync, statfsSync } from "node:fs";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
getIsContainerized,
|
|
6
|
+
getIsPlatform,
|
|
7
|
+
getMinikubeStorageSize,
|
|
8
|
+
} from "../config/env-registry.js";
|
|
5
9
|
import { getWorkspaceDir } from "./platform.js";
|
|
6
10
|
|
|
7
11
|
export interface DiskUsageInfo {
|
|
@@ -58,6 +62,57 @@ export function __resetDiskUsageCacheForTests(): void {
|
|
|
58
62
|
duCachePaths = null;
|
|
59
63
|
}
|
|
60
64
|
|
|
65
|
+
/**
|
|
66
|
+
* How the workspace volume's capacity should be reported when statfsSync
|
|
67
|
+
* cannot see the volume directly.
|
|
68
|
+
*
|
|
69
|
+
* - `fixed-cap`: minikube hostPath PVC — the PVC request is the hard
|
|
70
|
+
* capacity, so usage is measured with `du` and free space is whatever
|
|
71
|
+
* remains within the quota.
|
|
72
|
+
* - `host-free`: local Docker named volume — the volume is backed by the
|
|
73
|
+
* host (or Colima VM) filesystem and can grow into its free space, so
|
|
74
|
+
* usage is measured with `du` and the effective capacity is current usage
|
|
75
|
+
* plus the host's remaining headroom.
|
|
76
|
+
* - `none`: statfsSync already reports the volume accurately (bare metal, or
|
|
77
|
+
* a platform-managed instance on a CSI-backed PVC), so use it directly.
|
|
78
|
+
*/
|
|
79
|
+
type WorkspaceVolumeReporting =
|
|
80
|
+
| { kind: "none" }
|
|
81
|
+
| { kind: "fixed-cap"; totalBytes: number }
|
|
82
|
+
| { kind: "host-free" };
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Decide how to report the workspace volume's capacity. Both minikube
|
|
86
|
+
* hostPath PVCs and local Docker named volumes are backed by the host
|
|
87
|
+
* filesystem, so statfsSync reports the host's entire disk rather than the
|
|
88
|
+
* workspace volume — in both cases we measure actual usage with `du` instead.
|
|
89
|
+
*/
|
|
90
|
+
function classifyWorkspaceVolume(
|
|
91
|
+
fsTotalBytes: number,
|
|
92
|
+
): WorkspaceVolumeReporting {
|
|
93
|
+
// Minikube mode: the platform passes the PVC storage size so we can report
|
|
94
|
+
// accurate capacity. Detect the hostPath case by comparing filesystem size
|
|
95
|
+
// against the PVC size — if the filesystem is larger, statfsSync is seeing
|
|
96
|
+
// the host disk and we should measure the directory instead.
|
|
97
|
+
const storageSizeRaw = getMinikubeStorageSize();
|
|
98
|
+
if (storageSizeRaw) {
|
|
99
|
+
const pvcTotalBytes = parseK8sMemoryBytes(storageSizeRaw);
|
|
100
|
+
if (pvcTotalBytes !== null && fsTotalBytes > pvcTotalBytes * 1.1) {
|
|
101
|
+
return { kind: "fixed-cap", totalBytes: pvcTotalBytes };
|
|
102
|
+
}
|
|
103
|
+
return { kind: "none" };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Local Docker hatch: the workspace is a Docker named volume backed by the
|
|
107
|
+
// host filesystem. Platform-managed remote instances run on CSI-backed PVCs
|
|
108
|
+
// where statfsSync already reports the volume, so they are excluded.
|
|
109
|
+
if (getIsContainerized() && !getIsPlatform()) {
|
|
110
|
+
return { kind: "host-free" };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return { kind: "none" };
|
|
114
|
+
}
|
|
115
|
+
|
|
61
116
|
export function getDiskUsageInfo(): DiskUsageInfo | null {
|
|
62
117
|
try {
|
|
63
118
|
const wsDir = getWorkspaceDir();
|
|
@@ -68,28 +123,28 @@ export function getDiskUsageInfo(): DiskUsageInfo | null {
|
|
|
68
123
|
const bytesToMb = (b: number) =>
|
|
69
124
|
Math.round((b / (1024 * 1024)) * 100) / 100;
|
|
70
125
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
126
|
+
const reporting = classifyWorkspaceVolume(fsTotalBytes);
|
|
127
|
+
if (reporting.kind !== "none") {
|
|
128
|
+
const volumePaths = [diskPath];
|
|
129
|
+
if (diskPath !== "/data" && existsSync("/data")) {
|
|
130
|
+
volumePaths.push("/data");
|
|
131
|
+
}
|
|
132
|
+
const usedBytes = getCachedDirectorySizeBytes(volumePaths);
|
|
133
|
+
if (usedBytes !== null) {
|
|
134
|
+
const totalBytes =
|
|
135
|
+
reporting.kind === "fixed-cap"
|
|
136
|
+
? reporting.totalBytes
|
|
137
|
+
: usedBytes + fsFreeBytes;
|
|
138
|
+
const freeBytes =
|
|
139
|
+
reporting.kind === "fixed-cap"
|
|
140
|
+
? Math.max(0, reporting.totalBytes - usedBytes)
|
|
141
|
+
: fsFreeBytes;
|
|
142
|
+
return {
|
|
143
|
+
path: diskPath,
|
|
144
|
+
totalMb: bytesToMb(totalBytes),
|
|
145
|
+
usedMb: bytesToMb(usedBytes),
|
|
146
|
+
freeMb: bytesToMb(freeBytes),
|
|
147
|
+
};
|
|
93
148
|
}
|
|
94
149
|
}
|
|
95
150
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
|
|
3
|
+
import { getDataDir } from "./platform.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Path to the secondary SQLite file that houses heavy append-only tables
|
|
7
|
+
* (LLM request logs, and other log/event tables over time). It lives in the
|
|
8
|
+
* same `data/db` directory as the main DB and is ATTACHed to the daemon's
|
|
9
|
+
* connection as the `logs` schema (see `memory/db-connection.ts`). Splitting
|
|
10
|
+
* these tables into their own file keeps the main DB — and its WAL — small and
|
|
11
|
+
* lets the two files VACUUM/checkpoint independently.
|
|
12
|
+
*
|
|
13
|
+
* Kept in its own leaf module rather than alongside `getDbPath()` in
|
|
14
|
+
* `platform.ts`: `platform.ts` is imported very early and widely, and adding an
|
|
15
|
+
* export to it that low-level consumers (e.g. `db-connection.ts`) pull in
|
|
16
|
+
* across the daemon's large, cyclic import graph trips a Bun link-order bug
|
|
17
|
+
* ("Export named 'getLogsDbPath' not found"). Isolating it here keeps
|
|
18
|
+
* `platform.ts`'s module shape stable.
|
|
19
|
+
*/
|
|
20
|
+
export function getLogsDbPath(): string {
|
|
21
|
+
return join(getDataDir(), "db", "assistant-logs.db");
|
|
22
|
+
}
|
package/src/util/platform.ts
CHANGED
|
@@ -314,7 +314,14 @@ export function getWorkspaceToolsDir(): string {
|
|
|
314
314
|
return join(getWorkspaceDir(), "tools");
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
-
/**
|
|
317
|
+
/**
|
|
318
|
+
* Returns $VELLUM_WORKSPACE_DIR/routes — user-defined HTTP route handlers.
|
|
319
|
+
*
|
|
320
|
+
* Handler modules under this directory are dynamic-imported by the user-route
|
|
321
|
+
* dispatcher and their exported HTTP-method functions are executed on the
|
|
322
|
+
* next matching request, so the file risk classifier escalates writes under
|
|
323
|
+
* this path to High for the same reason `plugins/` and `tools/` are escalated.
|
|
324
|
+
*/
|
|
318
325
|
export function getWorkspaceRoutesDir(): string {
|
|
319
326
|
return join(getWorkspaceDir(), "routes");
|
|
320
327
|
}
|
|
@@ -402,8 +409,8 @@ export function getSkillRuntimePath(
|
|
|
402
409
|
*
|
|
403
410
|
* Resolution order:
|
|
404
411
|
*
|
|
405
|
-
* 1. macOS `.app` bundle: `Contents/Resources/bun` —
|
|
406
|
-
*
|
|
412
|
+
* 1. macOS `.app` bundle: `Contents/Resources/bun` — bundled at a version
|
|
413
|
+
* that matches `.tool-versions`.
|
|
407
414
|
* 2. Next-to-binary: `<execDir>/bun` for Docker/generic compiled layouts
|
|
408
415
|
* that stage a bun binary alongside the daemon (PR 29 wires this up).
|
|
409
416
|
*
|
package/src/watcher/telemetry.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* ahead of the planned watcher → skills-and-schedules migration.
|
|
5
5
|
*
|
|
6
6
|
* Both event shapes ship through the existing lifecycle-event telemetry
|
|
7
|
-
* pipeline, so they inherit its `
|
|
8
|
-
* no wire-contract or platform-side changes:
|
|
7
|
+
* pipeline, so they inherit its platform `share_analytics` consent gate and
|
|
8
|
+
* need no wire-contract or platform-side changes:
|
|
9
9
|
*
|
|
10
10
|
* - `watcher_enabled:<providerId>` — one per enabled watcher, at most
|
|
11
11
|
* once per 24h per daemon. Counts devices that have watchers
|
|
@@ -29,9 +29,8 @@
|
|
|
29
29
|
* (If host execution is ever wanted, the deliberate path is to thread the
|
|
30
30
|
* originating tool context through the engine — not to relax this gate.)
|
|
31
31
|
*
|
|
32
|
-
* This module is pure logic: it performs no
|
|
33
|
-
*
|
|
34
|
-
* callers, not this code.
|
|
32
|
+
* This module is pure logic: it performs no I/O beyond the synchronous
|
|
33
|
+
* tool-registry lookup.
|
|
35
34
|
*/
|
|
36
35
|
|
|
37
36
|
import { z } from "zod";
|
|
@@ -16,7 +16,11 @@ import type { TrustContext } from "../daemon/trust-context.js";
|
|
|
16
16
|
import { getSqlite } from "../memory/db-connection.js";
|
|
17
17
|
import { initializeDb } from "../memory/db-init.js";
|
|
18
18
|
import type { ResolvedCapabilities } from "./capabilities.js";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
executeWorkflow,
|
|
21
|
+
extractWorkflowMeta,
|
|
22
|
+
type WorkflowLeafEvent,
|
|
23
|
+
} from "./engine.js";
|
|
20
24
|
import * as journalStore from "./journal-store.js";
|
|
21
25
|
import type { LeafResult, RunLeafOptions } from "./leaf-runner.js";
|
|
22
26
|
|
|
@@ -677,6 +681,21 @@ describe("executeWorkflow — resume", () => {
|
|
|
677
681
|
);
|
|
678
682
|
expect(journalA.map((e) => e.seq)).toEqual([0, 1, 2]);
|
|
679
683
|
});
|
|
684
|
+
|
|
685
|
+
test("a completed leaf persists its per-leaf token usage in the journal", async () => {
|
|
686
|
+
const runner = makeFakeRunner();
|
|
687
|
+
await execute("wf-leaf-tokens", `return agent("alpha");`, runner.runner);
|
|
688
|
+
|
|
689
|
+
const journal = journalStore.getJournal("wf-leaf-tokens");
|
|
690
|
+
expect(journal).toHaveLength(1);
|
|
691
|
+
// The fake runner reports 10/5 per leaf; the completed entry carries them.
|
|
692
|
+
expect(journal[0]).toMatchObject({
|
|
693
|
+
seq: 0,
|
|
694
|
+
status: "completed",
|
|
695
|
+
inputTokens: 10,
|
|
696
|
+
outputTokens: 5,
|
|
697
|
+
});
|
|
698
|
+
});
|
|
680
699
|
});
|
|
681
700
|
|
|
682
701
|
describe("executeWorkflow — schema vs tool leaf tool forwarding", () => {
|
|
@@ -1142,3 +1161,158 @@ describe("executeWorkflow — nested workflow()", () => {
|
|
|
1142
1161
|
expect(second.prompts).toEqual([]);
|
|
1143
1162
|
});
|
|
1144
1163
|
});
|
|
1164
|
+
|
|
1165
|
+
describe("executeWorkflow — onLeaf observe-only hook", () => {
|
|
1166
|
+
beforeEach(resetTables);
|
|
1167
|
+
|
|
1168
|
+
/** Run a workflow, collecting every onLeaf event. */
|
|
1169
|
+
function executeWithLeafEvents(
|
|
1170
|
+
runId: string,
|
|
1171
|
+
scriptSource: string,
|
|
1172
|
+
runner: typeof import("./leaf-runner.js").runLeaf,
|
|
1173
|
+
config: WorkflowsConfig = configWith(),
|
|
1174
|
+
signal?: AbortSignal,
|
|
1175
|
+
): {
|
|
1176
|
+
promise: ReturnType<typeof executeWorkflow>;
|
|
1177
|
+
events: WorkflowLeafEvent[];
|
|
1178
|
+
} {
|
|
1179
|
+
const events: WorkflowLeafEvent[] = [];
|
|
1180
|
+
const promise = executeWorkflow({
|
|
1181
|
+
runId,
|
|
1182
|
+
scriptSource: META + scriptSource,
|
|
1183
|
+
args: null,
|
|
1184
|
+
capabilities: CAPABILITIES,
|
|
1185
|
+
config,
|
|
1186
|
+
journal: journalStore,
|
|
1187
|
+
leafRunner: runner,
|
|
1188
|
+
trustContext: TRUST,
|
|
1189
|
+
onLeaf: (e) => events.push(e),
|
|
1190
|
+
...(signal ? { signal } : {}),
|
|
1191
|
+
});
|
|
1192
|
+
return { promise, events };
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
test("a single agent() emits leaf_started then leaf_finished:completed at seq 0", async () => {
|
|
1196
|
+
const fake = makeFakeRunner();
|
|
1197
|
+
const { promise, events } = executeWithLeafEvents(
|
|
1198
|
+
"wf-leaf-single",
|
|
1199
|
+
`return agent("solo");`,
|
|
1200
|
+
fake.runner,
|
|
1201
|
+
);
|
|
1202
|
+
const res = await promise;
|
|
1203
|
+
expect(res.status).toBe("completed");
|
|
1204
|
+
|
|
1205
|
+
expect(events).toEqual([
|
|
1206
|
+
{ type: "leaf_started", seq: 0, promptSummary: "solo" },
|
|
1207
|
+
{
|
|
1208
|
+
type: "leaf_finished",
|
|
1209
|
+
seq: 0,
|
|
1210
|
+
status: "completed",
|
|
1211
|
+
inputTokens: 10,
|
|
1212
|
+
outputTokens: 5,
|
|
1213
|
+
resultSummary: "out:solo",
|
|
1214
|
+
},
|
|
1215
|
+
]);
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1218
|
+
test("a 3-spec parallel() emits 3 started + 3 finished across seqs 0,1,2", async () => {
|
|
1219
|
+
const fake = makeFakeRunner();
|
|
1220
|
+
const { promise, events } = executeWithLeafEvents(
|
|
1221
|
+
"wf-leaf-parallel",
|
|
1222
|
+
`return parallel([leaf("a"), leaf("b"), leaf("c")]);`,
|
|
1223
|
+
fake.runner,
|
|
1224
|
+
);
|
|
1225
|
+
const res = await promise;
|
|
1226
|
+
expect(res.status).toBe("completed");
|
|
1227
|
+
|
|
1228
|
+
const started = events.filter((e) => e.type === "leaf_started");
|
|
1229
|
+
const finished = events.filter((e) => e.type === "leaf_finished");
|
|
1230
|
+
expect(started.map((e) => e.seq).sort((a, b) => a - b)).toEqual([0, 1, 2]);
|
|
1231
|
+
expect(finished.map((e) => e.seq).sort((a, b) => a - b)).toEqual([0, 1, 2]);
|
|
1232
|
+
expect(finished.every((e) => e.status === "completed")).toBe(true);
|
|
1233
|
+
});
|
|
1234
|
+
|
|
1235
|
+
test("a throwing (non-abort) leaf emits leaf_started then leaf_finished:failed", async () => {
|
|
1236
|
+
const fake = makeFakeRunner({ failOn: (p) => p === "boom" });
|
|
1237
|
+
const { promise, events } = executeWithLeafEvents(
|
|
1238
|
+
"wf-leaf-fail",
|
|
1239
|
+
`return parallel([leaf("boom")]);`,
|
|
1240
|
+
fake.runner,
|
|
1241
|
+
);
|
|
1242
|
+
await promise;
|
|
1243
|
+
|
|
1244
|
+
expect(events).toEqual([
|
|
1245
|
+
{ type: "leaf_started", seq: 0, promptSummary: "boom" },
|
|
1246
|
+
{
|
|
1247
|
+
type: "leaf_finished",
|
|
1248
|
+
seq: 0,
|
|
1249
|
+
status: "failed",
|
|
1250
|
+
inputTokens: 0,
|
|
1251
|
+
outputTokens: 0,
|
|
1252
|
+
resultSummary: "leaf failed: boom",
|
|
1253
|
+
},
|
|
1254
|
+
]);
|
|
1255
|
+
});
|
|
1256
|
+
|
|
1257
|
+
test("an aborted in-flight leaf emits leaf_started but NO leaf_finished", async () => {
|
|
1258
|
+
const controller = new AbortController();
|
|
1259
|
+
let started = false;
|
|
1260
|
+
const runner = (async (): Promise<
|
|
1261
|
+
import("./leaf-runner.js").LeafResult
|
|
1262
|
+
> => {
|
|
1263
|
+
started = true;
|
|
1264
|
+
await new Promise<void>((resolve) => {
|
|
1265
|
+
if (controller.signal.aborted) return resolve();
|
|
1266
|
+
controller.signal.addEventListener("abort", () => resolve(), {
|
|
1267
|
+
once: true,
|
|
1268
|
+
});
|
|
1269
|
+
});
|
|
1270
|
+
const err = new Error("The operation was aborted");
|
|
1271
|
+
err.name = "AbortError";
|
|
1272
|
+
throw err;
|
|
1273
|
+
}) as unknown as typeof import("./leaf-runner.js").runLeaf;
|
|
1274
|
+
|
|
1275
|
+
const { promise, events } = executeWithLeafEvents(
|
|
1276
|
+
"wf-leaf-abort",
|
|
1277
|
+
`return agent("long-running");`,
|
|
1278
|
+
runner,
|
|
1279
|
+
configWith(),
|
|
1280
|
+
controller.signal,
|
|
1281
|
+
);
|
|
1282
|
+
|
|
1283
|
+
await waitUntil(() => started);
|
|
1284
|
+
controller.abort();
|
|
1285
|
+
|
|
1286
|
+
const res = await promise;
|
|
1287
|
+
expect(res.status).toBe("aborted");
|
|
1288
|
+
expect(events).toEqual([
|
|
1289
|
+
{ type: "leaf_started", seq: 0, promptSummary: "long-running" },
|
|
1290
|
+
]);
|
|
1291
|
+
});
|
|
1292
|
+
|
|
1293
|
+
test("a journal-replayed leaf emits neither leaf_started nor leaf_finished", async () => {
|
|
1294
|
+
const script = `return agent("alpha");`;
|
|
1295
|
+
|
|
1296
|
+
// First run journals the leaf as completed.
|
|
1297
|
+
const first = makeFakeRunner();
|
|
1298
|
+
const res1 = await executeWithLeafEvents(
|
|
1299
|
+
"wf-leaf-replay",
|
|
1300
|
+
script,
|
|
1301
|
+
first.runner,
|
|
1302
|
+
).promise;
|
|
1303
|
+
expect(res1.status).toBe("completed");
|
|
1304
|
+
expect(first.prompts).toEqual(["alpha"]);
|
|
1305
|
+
|
|
1306
|
+
// Resume: the leaf replays from the journal, so no onLeaf events fire.
|
|
1307
|
+
const second = makeFakeRunner();
|
|
1308
|
+
const { promise, events } = executeWithLeafEvents(
|
|
1309
|
+
"wf-leaf-replay",
|
|
1310
|
+
script,
|
|
1311
|
+
second.runner,
|
|
1312
|
+
);
|
|
1313
|
+
const res2 = await promise;
|
|
1314
|
+
expect(res2.status).toBe("completed");
|
|
1315
|
+
expect(second.prompts).toEqual([]);
|
|
1316
|
+
expect(events).toEqual([]);
|
|
1317
|
+
});
|
|
1318
|
+
});
|
package/src/workflows/engine.ts
CHANGED
|
@@ -73,6 +73,30 @@ export type WorkflowProgressEvent =
|
|
|
73
73
|
| { type: "phase"; title: string }
|
|
74
74
|
| { type: "log"; message: string };
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* An observe-only lifecycle event for a single leaf — the source of a live leaf
|
|
78
|
+
* tree. Emitted once when a leaf STARTS (after the cap check + spawn increment)
|
|
79
|
+
* and once when it FINISHES (completed or failed). A journal-replayed leaf and
|
|
80
|
+
* an aborted in-flight leaf emit neither.
|
|
81
|
+
*/
|
|
82
|
+
export type WorkflowLeafEvent =
|
|
83
|
+
| {
|
|
84
|
+
type: "leaf_started";
|
|
85
|
+
seq: number;
|
|
86
|
+
label?: string;
|
|
87
|
+
phase?: string;
|
|
88
|
+
promptSummary: string;
|
|
89
|
+
}
|
|
90
|
+
| {
|
|
91
|
+
type: "leaf_finished";
|
|
92
|
+
seq: number;
|
|
93
|
+
status: "completed" | "failed";
|
|
94
|
+
label?: string;
|
|
95
|
+
inputTokens: number;
|
|
96
|
+
outputTokens: number;
|
|
97
|
+
resultSummary: string;
|
|
98
|
+
};
|
|
99
|
+
|
|
76
100
|
/** The journal-store surface the engine depends on (injectable for tests). */
|
|
77
101
|
export interface WorkflowJournal {
|
|
78
102
|
appendJournalEntry: typeof JournalStore.appendJournalEntry;
|
|
@@ -108,6 +132,13 @@ export interface ExecuteWorkflowOptions {
|
|
|
108
132
|
trustContext: TrustContext;
|
|
109
133
|
/** Receives `phase`/`log` progress events from the script. */
|
|
110
134
|
onProgress?: (event: WorkflowProgressEvent) => void;
|
|
135
|
+
/**
|
|
136
|
+
* Observe-only per-leaf lifecycle hook. Emits once on START (after the cap
|
|
137
|
+
* check + spawn increment; NEVER on a journal-replay short-circuit) and once
|
|
138
|
+
* on FINISH (completed or failed). An aborted in-flight leaf emits NEITHER a
|
|
139
|
+
* finish nor a spurious failed.
|
|
140
|
+
*/
|
|
141
|
+
onLeaf?: (event: WorkflowLeafEvent) => void;
|
|
111
142
|
/** Cooperative cancellation for the whole run. */
|
|
112
143
|
signal?: AbortSignal;
|
|
113
144
|
}
|
|
@@ -451,6 +482,26 @@ function skipRegexLiteral(source: string, start: number): number {
|
|
|
451
482
|
return source.length - 1;
|
|
452
483
|
}
|
|
453
484
|
|
|
485
|
+
/**
|
|
486
|
+
* A bounded string summary of a leaf prompt or result, for an observe-only
|
|
487
|
+
* {@link WorkflowLeafEvent}. Strings pass through; everything else is
|
|
488
|
+
* JSON-serialized (falling back to `String(value)` if it cannot be). Truncated
|
|
489
|
+
* to `max` chars with a trailing ellipsis.
|
|
490
|
+
*/
|
|
491
|
+
function summarizeForLeafEvent(value: unknown, max = 200): string {
|
|
492
|
+
let text: string;
|
|
493
|
+
if (typeof value === "string") {
|
|
494
|
+
text = value;
|
|
495
|
+
} else {
|
|
496
|
+
try {
|
|
497
|
+
text = JSON.stringify(value);
|
|
498
|
+
} catch {
|
|
499
|
+
text = String(value);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return text.length > max ? `${text.slice(0, max)}…` : text;
|
|
503
|
+
}
|
|
504
|
+
|
|
454
505
|
function callHashOf(prompt: string, opts: LeafCallOptions): string {
|
|
455
506
|
return createHash("sha256")
|
|
456
507
|
.update(deterministicStringify({ prompt, opts }))
|
|
@@ -542,6 +593,7 @@ export async function executeWorkflow(
|
|
|
542
593
|
leafRunner,
|
|
543
594
|
trustContext,
|
|
544
595
|
onProgress,
|
|
596
|
+
onLeaf,
|
|
545
597
|
signal,
|
|
546
598
|
} = opts;
|
|
547
599
|
|
|
@@ -630,6 +682,14 @@ export async function executeWorkflow(
|
|
|
630
682
|
}
|
|
631
683
|
agentsSpawned += 1;
|
|
632
684
|
|
|
685
|
+
onLeaf?.({
|
|
686
|
+
type: "leaf_started",
|
|
687
|
+
seq,
|
|
688
|
+
...(leafOpts.label !== undefined ? { label: leafOpts.label } : {}),
|
|
689
|
+
...(leafOpts.phase !== undefined ? { phase: leafOpts.phase } : {}),
|
|
690
|
+
promptSummary: summarizeForLeafEvent(prompt),
|
|
691
|
+
});
|
|
692
|
+
|
|
633
693
|
try {
|
|
634
694
|
// A leaf is EITHER a schema leaf (structured output via forced
|
|
635
695
|
// tool-choice — `schema` set, no tools) OR a tool leaf (free-form with
|
|
@@ -666,6 +726,17 @@ export async function executeWorkflow(
|
|
|
666
726
|
request: { prompt, opts: leafOpts },
|
|
667
727
|
result: result.output,
|
|
668
728
|
status: "completed",
|
|
729
|
+
inputTokens: result.inputTokens,
|
|
730
|
+
outputTokens: result.outputTokens,
|
|
731
|
+
});
|
|
732
|
+
onLeaf?.({
|
|
733
|
+
type: "leaf_finished",
|
|
734
|
+
seq,
|
|
735
|
+
status: "completed",
|
|
736
|
+
...(leafOpts.label !== undefined ? { label: leafOpts.label } : {}),
|
|
737
|
+
inputTokens: result.inputTokens,
|
|
738
|
+
outputTokens: result.outputTokens,
|
|
739
|
+
resultSummary: summarizeForLeafEvent(result.output),
|
|
669
740
|
});
|
|
670
741
|
return { output: result.output, failed: false };
|
|
671
742
|
} catch (err) {
|
|
@@ -693,6 +764,17 @@ export async function executeWorkflow(
|
|
|
693
764
|
{ err, runId, seq, label: leafOpts.label },
|
|
694
765
|
"Workflow leaf failed",
|
|
695
766
|
);
|
|
767
|
+
onLeaf?.({
|
|
768
|
+
type: "leaf_finished",
|
|
769
|
+
seq,
|
|
770
|
+
status: "failed",
|
|
771
|
+
...(leafOpts.label !== undefined ? { label: leafOpts.label } : {}),
|
|
772
|
+
inputTokens: 0,
|
|
773
|
+
outputTokens: 0,
|
|
774
|
+
resultSummary: summarizeForLeafEvent(
|
|
775
|
+
err instanceof Error ? err.message : String(err),
|
|
776
|
+
),
|
|
777
|
+
});
|
|
696
778
|
return { output: null, failed: true };
|
|
697
779
|
}
|
|
698
780
|
};
|
|
@@ -197,6 +197,76 @@ describe("workflow journal store", () => {
|
|
|
197
197
|
});
|
|
198
198
|
});
|
|
199
199
|
|
|
200
|
+
test("appendJournalEntry round-trips per-leaf token usage", () => {
|
|
201
|
+
createRun({ id: "wf-tok", scriptSource: "s", scriptHash: "h" });
|
|
202
|
+
|
|
203
|
+
appendJournalEntry({
|
|
204
|
+
runId: "wf-tok",
|
|
205
|
+
seq: 0,
|
|
206
|
+
callHash: "c0",
|
|
207
|
+
kind: "agent",
|
|
208
|
+
request: { prompt: "with tokens" },
|
|
209
|
+
result: { text: "r" },
|
|
210
|
+
status: "completed",
|
|
211
|
+
inputTokens: 120,
|
|
212
|
+
outputTokens: 45,
|
|
213
|
+
});
|
|
214
|
+
// A leaf with no recorded usage stores NULL → reads back as undefined.
|
|
215
|
+
appendJournalEntry({
|
|
216
|
+
runId: "wf-tok",
|
|
217
|
+
seq: 1,
|
|
218
|
+
callHash: "c1",
|
|
219
|
+
kind: "agent",
|
|
220
|
+
request: { prompt: "no tokens" },
|
|
221
|
+
result: { error: "boom" },
|
|
222
|
+
status: "failed",
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const journal = getJournal("wf-tok");
|
|
226
|
+
expect(journal[0]).toMatchObject({
|
|
227
|
+
seq: 0,
|
|
228
|
+
inputTokens: 120,
|
|
229
|
+
outputTokens: 45,
|
|
230
|
+
});
|
|
231
|
+
expect(journal[1].inputTokens).toBeUndefined();
|
|
232
|
+
expect(journal[1].outputTokens).toBeUndefined();
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test("appendJournalEntry upserts token usage on a changed-hash re-run", () => {
|
|
236
|
+
createRun({ id: "wf-tok-resume", scriptSource: "s", scriptHash: "h" });
|
|
237
|
+
|
|
238
|
+
appendJournalEntry({
|
|
239
|
+
runId: "wf-tok-resume",
|
|
240
|
+
seq: 0,
|
|
241
|
+
callHash: "hash-old",
|
|
242
|
+
kind: "agent",
|
|
243
|
+
result: { text: "old" },
|
|
244
|
+
status: "completed",
|
|
245
|
+
inputTokens: 10,
|
|
246
|
+
outputTokens: 5,
|
|
247
|
+
});
|
|
248
|
+
// Resume re-runs the leaf with new usage; the upsert overwrites the tokens.
|
|
249
|
+
appendJournalEntry({
|
|
250
|
+
runId: "wf-tok-resume",
|
|
251
|
+
seq: 0,
|
|
252
|
+
callHash: "hash-new",
|
|
253
|
+
kind: "agent",
|
|
254
|
+
result: { text: "new" },
|
|
255
|
+
status: "completed",
|
|
256
|
+
inputTokens: 30,
|
|
257
|
+
outputTokens: 12,
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
const journal = getJournal("wf-tok-resume");
|
|
261
|
+
expect(journal).toHaveLength(1);
|
|
262
|
+
expect(journal[0]).toMatchObject({
|
|
263
|
+
seq: 0,
|
|
264
|
+
callHash: "hash-new",
|
|
265
|
+
inputTokens: 30,
|
|
266
|
+
outputTokens: 12,
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
200
270
|
test("appendJournalEntry is idempotent on (run_id, seq)", () => {
|
|
201
271
|
createRun({ id: "wf-dup", scriptSource: "s", scriptHash: "h" });
|
|
202
272
|
|