@vellumai/assistant 0.10.1 → 0.10.2-dev.202606241651.2d2b40d
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/docs/workspace-tools.md +42 -33
- package/eslint-rules/cli-no-daemon-internals.js +6 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +31 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +17 -0
- package/openapi.yaml +74 -1
- package/package.json +1 -1
- package/scripts/test.sh +36 -15
- package/src/__tests__/actor-token-service.test.ts +36 -14
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
- package/src/__tests__/annotate-activity-metadata.test.ts +2 -0
- package/src/__tests__/annotate-risk-options.test.ts +2 -0
- package/src/__tests__/approval-cascade.test.ts +2 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -0
- package/src/__tests__/btw-routes.test.ts +2 -0
- package/src/__tests__/build-persisted-content.test.ts +2 -0
- package/src/__tests__/call-controller.test.ts +19 -0
- package/src/__tests__/channel-guardian.test.ts +94 -58
- package/src/__tests__/channel-reply-delivery.test.ts +2 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +2 -0
- package/src/__tests__/compactor-low-watermark-cut.test.ts +2 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +2 -0
- package/src/__tests__/compactor-summary-call-truncation.test.ts +2 -0
- package/src/__tests__/compactor-web-search-strip.test.ts +2 -0
- package/src/__tests__/computer-use-tools.test.ts +13 -0
- package/src/__tests__/config-loader-backfill.test.ts +5 -1
- package/src/__tests__/config-schema.test.ts +1 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +31 -29
- package/src/__tests__/contacts-relay-reads.test.ts +13 -15
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +7 -0
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +2 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -0
- package/src/__tests__/conversation-history-web-search.test.ts +2 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -0
- package/src/__tests__/conversation-load-history-stripped.test.ts +2 -0
- package/src/__tests__/conversation-pairing.test.ts +2 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
- package/src/__tests__/conversation-process-callsite.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +91 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +14 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +14 -0
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +2 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +65 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -0
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
- package/src/__tests__/conversation-usage.test.ts +2 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/db-migration-rollback.test.ts +205 -171
- package/src/__tests__/db-test-helpers.ts +5 -4
- package/src/__tests__/deterministic-verification-control-plane.test.ts +4 -2
- package/src/__tests__/disk-pressure-guard.test.ts +41 -0
- package/src/__tests__/dm-persistence.test.ts +2 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +10 -5
- package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
- package/src/__tests__/filing-service.test.ts +2 -0
- package/src/__tests__/guardian-binding-drift-heal.test.ts +75 -10
- package/src/__tests__/guardian-dispatch.test.ts +95 -1
- package/src/__tests__/guardian-outbound-http.test.ts +13 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
- package/src/__tests__/heartbeat-service.test.ts +2 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +1 -7
- package/src/__tests__/host-app-control-routes.test.ts +24 -30
- package/src/__tests__/host-bash-routes.test.ts +31 -41
- package/src/__tests__/host-browser-routes.test.ts +26 -32
- package/src/__tests__/host-cu-proxy.test.ts +299 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
- package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
- package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
- package/src/__tests__/http-user-message-parity.test.ts +167 -8
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/invite-redemption-service.test.ts +43 -0
- package/src/__tests__/llm-context-normalization.test.ts +105 -0
- package/src/__tests__/llm-usage-store.test.ts +25 -0
- package/src/__tests__/media-stream-server-integration.test.ts +127 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +2 -0
- package/src/__tests__/messaging-send-tool.test.ts +2 -0
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/native-web-search.test.ts +2 -0
- package/src/__tests__/non-member-access-request.test.ts +189 -17
- package/src/__tests__/notification-broadcaster.test.ts +4 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
- package/src/__tests__/notification-deep-link.test.ts +6 -0
- package/src/__tests__/notification-guardian-path.test.ts +19 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
- package/src/__tests__/plugin-bootstrap.test.ts +3 -73
- package/src/__tests__/plugin-route-contribution.test.ts +4 -17
- package/src/__tests__/plugin-tool-contribution.test.ts +3 -18
- package/src/__tests__/plugin-types.test.ts +0 -2
- package/src/__tests__/process-message-background-slack.test.ts +2 -0
- package/src/__tests__/process-message-display-content.test.ts +2 -0
- package/src/__tests__/provider-usage-tracking.test.ts +39 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +2 -0
- package/src/__tests__/registry.test.ts +3 -0
- package/src/__tests__/relay-server.test.ts +694 -25
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/secret-ingress-http.test.ts +14 -0
- package/src/__tests__/send-endpoint-busy.test.ts +30 -8
- package/src/__tests__/skills.test.ts +44 -0
- package/src/__tests__/slack-inbound-verification.test.ts +47 -2
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +102 -0
- package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
- package/src/__tests__/stt-hints.test.ts +44 -13
- package/src/__tests__/subagent-detail.test.ts +27 -0
- package/src/__tests__/subagent-disposal.test.ts +65 -0
- package/src/__tests__/subagent-notify-parent.test.ts +2 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +2 -0
- package/src/__tests__/subagent-tools.test.ts +2 -0
- package/src/__tests__/suggestion-routes.test.ts +2 -0
- package/src/__tests__/title-generate-hook.test.ts +2 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -0
- package/src/__tests__/tool-executor.test.ts +16 -11
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +2 -0
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
- package/src/__tests__/twilio-routes.test.ts +96 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -0
- package/src/__tests__/web-search-backend-failure.test.ts +2 -0
- package/src/__tests__/workspace-tool-loader.test.ts +195 -2
- package/src/agent/loop-exclusive-tool.test.ts +150 -0
- package/src/agent/loop.ts +56 -0
- package/src/api/constants/sse-replay.ts +41 -0
- package/src/api/index.ts +6 -0
- package/src/api/responses/llm-request-log-entry.ts +25 -0
- package/src/api/responses/subagent-detail.ts +17 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +262 -4
- package/src/calls/call-domain.ts +3 -3
- package/src/calls/guardian-dispatch.ts +10 -8
- package/src/calls/inbound-trust-reader.ts +17 -1
- package/src/calls/media-stream-server.ts +21 -0
- package/src/calls/relay-server.ts +167 -50
- package/src/calls/relay-setup-router.ts +37 -7
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/stt-hints.ts +9 -12
- package/src/calls/twilio-routes.ts +14 -4
- package/src/cli/commands/__tests__/cache.test.ts +8 -1
- package/src/cli/commands/cache.ts +194 -181
- package/src/cli/commands/db/__tests__/repair.test.ts +6 -5
- package/src/cli/commands/db/status.ts +37 -1
- package/src/cli/commands/mcp.ts +252 -218
- package/src/cli/commands/memory/__tests__/worker.test.ts +302 -0
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/worker.ts +175 -0
- package/src/cli/commands/plugins.ts +75 -3
- package/src/cli/lib/__tests__/install-from-github.test.ts +102 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
- package/src/cli/lib/list-installed-plugins.ts +179 -1
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +6 -1
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +27 -17
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +13 -3
- package/src/config/feature-flag-registry.json +0 -8
- package/src/config/loader.ts +36 -5
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/memory-v3.ts +7 -0
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/timeouts.ts +8 -0
- package/src/config/seed-inference-profiles.ts +14 -5
- package/src/config/skills.ts +27 -5
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
- package/src/contacts/contacts-write.ts +3 -0
- package/src/contacts/guardian-delivery-reader.ts +223 -0
- package/src/daemon/conversation-agent-loop.ts +9 -0
- package/src/daemon/conversation-process.ts +39 -17
- package/src/daemon/conversation-surfaces.ts +8 -0
- package/src/daemon/conversation-tool-setup.ts +49 -16
- package/src/daemon/conversation.ts +21 -2
- package/src/daemon/disk-pressure-guard.ts +12 -2
- package/src/daemon/event-loop-watchdog.ts +28 -1
- package/src/daemon/external-plugins-bootstrap.ts +4 -34
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +25 -0
- package/src/daemon/handlers/__tests__/config-channels.test.ts +225 -0
- package/src/daemon/handlers/config-a2a.ts +6 -14
- package/src/daemon/handlers/config-channels.ts +78 -22
- package/src/daemon/handlers/conversations.ts +77 -0
- package/src/daemon/host-cu-proxy.ts +102 -11
- package/src/daemon/lifecycle.ts +4 -0
- package/src/daemon/memory-v2-startup.test.ts +72 -0
- package/src/daemon/memory-v2-startup.ts +87 -19
- package/src/daemon/server.ts +0 -4
- package/src/daemon/shutdown-handlers.ts +20 -0
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/assistant-server.ts +2 -2
- package/src/memory/__tests__/301-create-watchdog-events.test.ts +110 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
- package/src/memory/__tests__/prompt-override.test.ts +192 -0
- package/src/memory/__tests__/watchdog-events-store.test.ts +161 -0
- package/src/memory/conversation-crud.ts +38 -0
- package/src/memory/db-connection.ts +22 -3
- package/src/memory/db-init.ts +36 -502
- package/src/memory/db-singleton.ts +6 -4
- package/src/memory/jobs-worker.ts +58 -0
- package/src/memory/llm-usage-store.ts +48 -20
- package/src/memory/memory-retrospective-job.ts +9 -8
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +13 -3
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -27
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +130 -56
- package/src/memory/migrations/300-add-processing-started-at.ts +30 -0
- package/src/memory/migrations/301-create-watchdog-events.ts +45 -0
- package/src/memory/migrations/__tests__/014-backfill-inbox-thread-state.test.ts +108 -0
- package/src/memory/migrations/__tests__/136-drop-assistant-id-columns.test.ts +82 -0
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +224 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
- package/src/memory/migrations/run-migrations.ts +90 -6
- package/src/memory/migrations/schema-introspection.ts +14 -0
- package/src/memory/migrations/validate-migration-state.ts +101 -66
- package/src/memory/prompt-override.ts +129 -0
- package/src/memory/schema/conversations.ts +9 -0
- package/src/memory/schema/infrastructure.ts +20 -0
- package/src/memory/steps.ts +573 -0
- package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
- package/src/memory/v2/cli-command-store.ts +75 -38
- package/src/memory/v2/prompts/consolidation.ts +13 -82
- package/src/memory/v2/prompts/router.ts +21 -93
- package/src/memory/v2/skill-store.ts +68 -31
- package/src/memory/watchdog-events-store.ts +87 -0
- package/src/memory/worker-control.ts +118 -0
- package/src/memory/worker-process.ts +72 -0
- package/src/notifications/__tests__/broadcaster.test.ts +16 -8
- package/src/notifications/__tests__/connected-channels.test.ts +114 -0
- package/src/notifications/__tests__/decision-engine.test.ts +78 -9
- package/src/notifications/__tests__/destination-resolver.test.ts +256 -0
- package/src/notifications/broadcaster.ts +8 -1
- package/src/notifications/decision-engine.ts +15 -7
- package/src/notifications/destination-resolver.ts +68 -24
- package/src/notifications/emit-signal.ts +39 -14
- package/src/onboarding/checkin-event.test.ts +220 -0
- package/src/onboarding/checkin-event.ts +321 -0
- package/src/onboarding/schedule-checkin.ts +190 -0
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +7 -4
- package/src/plugin-api/index.ts +6 -6
- package/src/plugin-api/types.ts +3 -5
- package/src/plugin-api/vision-support.test.ts +28 -4
- package/src/plugin-api/vision-support.ts +66 -31
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +161 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +106 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +60 -0
- package/src/plugins/defaults/advisor/consult.ts +110 -6
- package/src/plugins/defaults/advisor/context-pack.ts +288 -0
- package/src/plugins/defaults/advisor/steering.ts +14 -2
- package/src/plugins/defaults/advisor/tools/advisor.ts +32 -5
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +47 -7
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +10 -11
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +12 -20
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +42 -11
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +29 -1
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +8 -1
- package/src/plugins/mtime-cache.ts +7 -2
- package/src/plugins/types.ts +0 -2
- package/src/providers/anthropic/client.ts +5 -0
- package/src/providers/call-site-routing.ts +4 -0
- package/src/providers/model-catalog.ts +16 -0
- package/src/providers/openai/responses-provider.ts +5 -0
- package/src/providers/openrouter/client.ts +5 -0
- package/src/providers/provider-send-message.ts +4 -0
- package/src/providers/ratelimit.ts +4 -0
- package/src/providers/retry.ts +4 -0
- package/src/providers/types.ts +9 -0
- package/src/providers/usage-tracking.ts +4 -0
- package/src/runtime/__tests__/channel-verification-service.test.ts +133 -0
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +181 -0
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +66 -0
- package/src/runtime/__tests__/local-principal-trust.test.ts +164 -0
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +335 -3
- package/src/runtime/access-request-helper.ts +19 -39
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/anchored-guardian.test.ts +156 -0
- package/src/runtime/anchored-guardian.ts +135 -0
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/assistant-stream-state.ts +9 -2
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
- package/src/runtime/auth/require-bound-guardian.ts +21 -11
- package/src/runtime/channel-verification-service.ts +56 -31
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
- package/src/runtime/guardian-vellum-migration.ts +66 -7
- package/src/runtime/invite-redemption-service.ts +50 -18
- package/src/runtime/local-actor-identity.ts +76 -11
- package/src/runtime/local-principal-trust.ts +52 -0
- package/src/runtime/pending-interactions.ts +11 -1
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +56 -5
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/contact-routes.test.ts +212 -0
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +93 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +215 -1
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/channel-verification-routes.ts +3 -3
- package/src/runtime/routes/contact-routes.ts +8 -32
- package/src/runtime/routes/conversation-cli-routes.ts +4 -5
- package/src/runtime/routes/conversation-list-routes.ts +4 -7
- package/src/runtime/routes/conversation-routes.ts +74 -81
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +3 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -5
- package/src/runtime/routes/host-app-control-routes.ts +5 -4
- package/src/runtime/routes/host-bash-routes.ts +5 -4
- package/src/runtime/routes/host-browser-routes.ts +9 -11
- package/src/runtime/routes/host-cu-routes.ts +5 -4
- package/src/runtime/routes/host-file-routes.ts +5 -4
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +3 -2
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +97 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +61 -49
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +16 -4
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/llm-context-normalization.ts +71 -0
- package/src/runtime/routes/mcp-auth-routes.ts +38 -15
- package/src/runtime/routes/migration-rollback-routes.ts +4 -3
- package/src/runtime/routes/migration-routes.ts +4 -1
- package/src/runtime/routes/onboarding-checkin-routes.ts +86 -0
- package/src/runtime/routes/subagents-routes.ts +5 -0
- package/src/runtime/routes/surface-action-routes.ts +51 -55
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
- package/src/runtime/services/conversation-serializer.ts +7 -9
- package/src/runtime/tool-grant-request-helper.ts +3 -3
- package/src/runtime/trust-verdict-consumer.ts +85 -9
- package/src/runtime/verification-outbound-actions.ts +18 -18
- package/src/signals/user-message.ts +16 -0
- package/src/subagent/manager.ts +9 -0
- package/src/telemetry/types.ts +34 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
- package/src/telemetry/usage-telemetry-reporter.ts +87 -3
- package/src/tools/ask-question/ask-question-tool.test.ts +29 -0
- package/src/tools/ask-question/ask-question-tool.ts +13 -0
- package/src/tools/computer-use/definitions.ts +8 -2
- package/src/tools/executor.ts +4 -4
- package/src/tools/registry.ts +18 -0
- package/src/tools/tool-approval-handler.ts +1 -1
- package/src/tools/tool-defaults.ts +9 -2
- package/src/tools/types.ts +17 -2
- package/src/tools/workspace-tools/loader.ts +348 -244
- package/src/util/platform.ts +5 -0
- package/src/util/telemetry-db-path.ts +24 -0
- package/src/workspace/migrations/017-seed-persona-dirs.ts +3 -34
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +3 -24
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +0 -70
- package/src/daemon/workspace-tools-watcher.ts +0 -328
- package/src/memory/migrations/registry.ts +0 -573
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
updateCallSession,
|
|
56
56
|
} from "./call-store.js";
|
|
57
57
|
import { getChannelAdmissionPolicy } from "./channel-admission-reader.js";
|
|
58
|
+
import { getPhoneCallerVerdict } from "./inbound-trust-reader.js";
|
|
58
59
|
import { routeSetup } from "./relay-setup-router.js";
|
|
59
60
|
import { resolveCallHints } from "./stt-hints.js";
|
|
60
61
|
import { resolveTelephonySttRouting } from "./telephony-stt-routing.js";
|
|
@@ -298,7 +299,7 @@ async function processVoiceWebhook(
|
|
|
298
299
|
"Inbound voice webhook — creating/reusing session",
|
|
299
300
|
);
|
|
300
301
|
|
|
301
|
-
const { session } = createInboundVoiceSession({
|
|
302
|
+
const { session } = await createInboundVoiceSession({
|
|
302
303
|
callSid,
|
|
303
304
|
fromNumber: callerFrom,
|
|
304
305
|
toNumber: callerTo,
|
|
@@ -484,12 +485,21 @@ async function buildVoiceWebhookTwiml(
|
|
|
484
485
|
// admits the caller.
|
|
485
486
|
const admissionPolicy = await getChannelAdmissionPolicy("phone");
|
|
486
487
|
|
|
488
|
+
// Verdict-first caller trust so this preflight matches handleSetup's ACL.
|
|
489
|
+
// routeSetup uses it when present and not resolutionFailed, else falls back
|
|
490
|
+
// to local resolution. The reader returns null on failure, keeping the
|
|
491
|
+
// local path on a gateway blip.
|
|
492
|
+
const isInbound = sessionContext?.direction !== "outbound";
|
|
493
|
+
const otherPartyNumber = isInbound ? from : to;
|
|
494
|
+
const verdict = await getPhoneCallerVerdict(otherPartyNumber);
|
|
495
|
+
|
|
487
496
|
const { outcome } = routeSetup({
|
|
488
497
|
callSessionId,
|
|
489
498
|
session: session ?? null,
|
|
490
499
|
from,
|
|
491
500
|
to,
|
|
492
501
|
admissionPolicy,
|
|
502
|
+
verdict,
|
|
493
503
|
});
|
|
494
504
|
|
|
495
505
|
// The media-stream transport supports normal_call and deny (which speaks
|
|
@@ -522,7 +532,7 @@ async function buildVoiceWebhookTwiml(
|
|
|
522
532
|
/**
|
|
523
533
|
* Build ConversationRelay TwiML for Twilio-native STT providers.
|
|
524
534
|
*/
|
|
525
|
-
function buildConversationRelayTwiml(
|
|
535
|
+
async function buildConversationRelayTwiml(
|
|
526
536
|
callSessionId: string,
|
|
527
537
|
profile: ReturnType<typeof resolveVoiceQualityProfile>,
|
|
528
538
|
sessionContext: {
|
|
@@ -535,8 +545,8 @@ function buildConversationRelayTwiml(
|
|
|
535
545
|
} | null,
|
|
536
546
|
verificationSessionId: string | null | undefined,
|
|
537
547
|
sttAttrs: { transcriptionProvider: string; speechModel: string | undefined },
|
|
538
|
-
): string {
|
|
539
|
-
const rawHints = resolveCallHints(sessionContext, profile.hints);
|
|
548
|
+
): Promise<string> {
|
|
549
|
+
const rawHints = await resolveCallHints(sessionContext, profile.hints);
|
|
540
550
|
|
|
541
551
|
const speechConfig: TwilioRelaySpeechConfig = {
|
|
542
552
|
transcriptionProvider: sttAttrs.transcriptionProvider,
|
|
@@ -88,8 +88,15 @@ mock.module("../../../util/logger.js", () => ({
|
|
|
88
88
|
}));
|
|
89
89
|
|
|
90
90
|
mock.module("../../lib/cache-fs.js", () => ({
|
|
91
|
-
readFileSync: (path: string, encoding?: BufferEncoding) => {
|
|
91
|
+
readFileSync: (path: string | number, encoding?: BufferEncoding) => {
|
|
92
|
+
// Stdin must be read via fd 0, not by reopening "/dev/stdin": a spawned
|
|
93
|
+
// subprocess whose stdin is a pipe (Bun.spawn stdin:"pipe") cannot reopen
|
|
94
|
+
// its read-end by path — open("/dev/stdin") fails ENXIO. Throwing here on
|
|
95
|
+
// the path makes any regression to path-based reading fail loudly.
|
|
92
96
|
if (path === "/dev/stdin") {
|
|
97
|
+
throw new Error("ENXIO: no such device or address, open '/dev/stdin'");
|
|
98
|
+
}
|
|
99
|
+
if (path === 0) {
|
|
93
100
|
if (mockStdinContent === null) {
|
|
94
101
|
throw new Error("EAGAIN: resource temporarily unavailable");
|
|
95
102
|
}
|
|
@@ -17,6 +17,9 @@ import { log } from "../logger.js";
|
|
|
17
17
|
/** Warn (stderr) when a raw payload exceeds this byte count. */
|
|
18
18
|
const MAX_PAYLOAD_BYTES = 1_000_000; // 1 MB
|
|
19
19
|
|
|
20
|
+
/** Standard input file descriptor. */
|
|
21
|
+
const STDIN_FD = 0;
|
|
22
|
+
|
|
20
23
|
// ── TTL parsing ───────────────────────────────────────────────────────
|
|
21
24
|
|
|
22
25
|
const TTL_PATTERN = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h)$/;
|
|
@@ -99,6 +102,11 @@ function parseJsonPayload(raw: string, source: string): unknown {
|
|
|
99
102
|
* Read JSON payload from stdin when piped. Throws when stdin is a TTY
|
|
100
103
|
* (no piped input) or when the input is empty/invalid JSON, so the CLI
|
|
101
104
|
* can surface actionable parse errors.
|
|
105
|
+
*
|
|
106
|
+
* Reads file descriptor 0 directly rather than reopening the `/dev/stdin`
|
|
107
|
+
* path. When the caller is a spawned subprocess whose stdin is a pipe (e.g.
|
|
108
|
+
* `Bun.spawn(..., { stdin: "pipe" })`), `open("/dev/stdin")` fails with ENXIO
|
|
109
|
+
* because a pipe read-end cannot be reopened by path; the fd is readable.
|
|
102
110
|
*/
|
|
103
111
|
function readPayloadFromStdin(): unknown {
|
|
104
112
|
if (process.stdin.isTTY) {
|
|
@@ -111,7 +119,7 @@ function readPayloadFromStdin(): unknown {
|
|
|
111
119
|
|
|
112
120
|
let raw: string;
|
|
113
121
|
try {
|
|
114
|
-
raw = readFileSync(
|
|
122
|
+
raw = readFileSync(STDIN_FD, "utf-8");
|
|
115
123
|
} catch (err) {
|
|
116
124
|
throw new Error(
|
|
117
125
|
`Failed to read stdin: ${err instanceof Error ? err.message : String(err)}.\n` +
|
|
@@ -173,10 +181,9 @@ export function registerCacheCommand(program: Command): void {
|
|
|
173
181
|
transport: "ipc",
|
|
174
182
|
description: "Interact with the assistant's in-memory key/value cache",
|
|
175
183
|
build: (cache) => {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
`
|
|
184
|
+
cache.addHelpText(
|
|
185
|
+
"after",
|
|
186
|
+
`
|
|
180
187
|
The cache is a TTL-aware, LRU-evicting in-memory store managed by the
|
|
181
188
|
running assistant. Data is scoped to the assistant process lifetime and
|
|
182
189
|
is not persisted across restarts.
|
|
@@ -190,33 +197,33 @@ Examples:
|
|
|
190
197
|
$ echo '{"result": [1,2,3]}' | assistant cache set --ttl 5m
|
|
191
198
|
$ assistant cache get my-key
|
|
192
199
|
$ assistant cache delete my-key`,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// ── set ───────────────────────────────────────────────────────────
|
|
203
|
+
|
|
204
|
+
cache
|
|
205
|
+
.command("set")
|
|
206
|
+
.description("Store a JSON value in the cache")
|
|
207
|
+
.option(
|
|
208
|
+
"--key <key>",
|
|
209
|
+
"Cache key for idempotent upsert. Omit to auto-generate.",
|
|
210
|
+
)
|
|
211
|
+
.option(
|
|
212
|
+
"--ttl <duration>",
|
|
213
|
+
"Time-to-live (minimum 1s). Units: ms, s, m, h (e.g. 1000ms, 30s, 5m, 2h). Defaults to 30m if omitted.",
|
|
214
|
+
)
|
|
215
|
+
.option(
|
|
216
|
+
"--value <json>",
|
|
217
|
+
"JSON payload to store. Alternative to piping via stdin.",
|
|
218
|
+
)
|
|
219
|
+
.option(
|
|
220
|
+
"--file <path>",
|
|
221
|
+
"Path to a file containing the JSON payload. Alternative to piping via stdin.",
|
|
222
|
+
)
|
|
223
|
+
.option("--json", "Output result as machine-readable JSON.")
|
|
224
|
+
.addHelpText(
|
|
225
|
+
"after",
|
|
226
|
+
`
|
|
220
227
|
Stores a JSON payload in the cache and prints the assigned key. The payload
|
|
221
228
|
can be provided via --value, --file, or piped through stdin. If --key is
|
|
222
229
|
provided, the entry is upserted (created or replaced). If omitted, a new
|
|
@@ -240,86 +247,86 @@ Examples:
|
|
|
240
247
|
$ assistant cache set --file /tmp/payload.json --key scores --ttl 10m
|
|
241
248
|
$ echo '{"scores":[98,85,72]}' | assistant cache set
|
|
242
249
|
$ echo '"simple string"' | assistant cache set --ttl 1h --json`,
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
250
|
+
)
|
|
251
|
+
.action(
|
|
252
|
+
async (opts: {
|
|
253
|
+
key?: string;
|
|
254
|
+
ttl?: string;
|
|
255
|
+
value?: string;
|
|
256
|
+
file?: string;
|
|
257
|
+
json?: boolean;
|
|
258
|
+
}) => {
|
|
259
|
+
let data: unknown;
|
|
260
|
+
try {
|
|
261
|
+
data = resolvePayload(opts);
|
|
262
|
+
} catch (err) {
|
|
263
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
264
|
+
if (opts.json) {
|
|
265
|
+
process.stdout.write(
|
|
266
|
+
JSON.stringify({ ok: false, error: msg }) + "\n",
|
|
267
|
+
);
|
|
268
|
+
} else {
|
|
269
|
+
log.error(msg);
|
|
270
|
+
}
|
|
271
|
+
process.exitCode = 1;
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
let ttl_ms: number | undefined;
|
|
276
|
+
try {
|
|
277
|
+
ttl_ms = parseTtl(opts.ttl);
|
|
278
|
+
} catch (err) {
|
|
279
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
280
|
+
if (opts.json) {
|
|
281
|
+
process.stdout.write(
|
|
282
|
+
JSON.stringify({ ok: false, error: msg }) + "\n",
|
|
283
|
+
);
|
|
284
|
+
} else {
|
|
285
|
+
log.error(msg);
|
|
286
|
+
}
|
|
287
|
+
process.exitCode = 1;
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const params: Record<string, unknown> = { data };
|
|
292
|
+
if (ttl_ms !== undefined) params.ttl_ms = ttl_ms;
|
|
293
|
+
if (opts.key) params.key = opts.key;
|
|
294
|
+
|
|
295
|
+
const result = await cliIpcCall<{ key: string }>("cache_set", {
|
|
296
|
+
body: params,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
if (!result.ok) {
|
|
300
|
+
if (opts.json) {
|
|
301
|
+
process.stdout.write(
|
|
302
|
+
JSON.stringify({ ok: false, error: result.error }) + "\n",
|
|
303
|
+
);
|
|
304
|
+
} else {
|
|
305
|
+
log.error(`Error: ${result.error}`);
|
|
306
|
+
}
|
|
307
|
+
process.exitCode = 1;
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (opts.json) {
|
|
312
|
+
process.stdout.write(
|
|
313
|
+
JSON.stringify({ ok: true, key: result.result!.key }) + "\n",
|
|
314
|
+
);
|
|
315
|
+
} else {
|
|
316
|
+
log.info(`Cached with key: ${result.result!.key}`);
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
);
|
|
313
320
|
|
|
314
|
-
|
|
321
|
+
// ── get ───────────────────────────────────────────────────────────
|
|
315
322
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
+
cache
|
|
324
|
+
.command("get <key>")
|
|
325
|
+
.description("Retrieve a cached value by key")
|
|
326
|
+
.option("--json", "Output result as machine-readable JSON.")
|
|
327
|
+
.addHelpText(
|
|
328
|
+
"after",
|
|
329
|
+
`
|
|
323
330
|
Arguments:
|
|
324
331
|
key The cache key to look up. Run 'assistant cache set' to store a
|
|
325
332
|
value and receive its key.
|
|
@@ -331,49 +338,52 @@ exist or has expired, reports not-found. In --json mode, a miss returns
|
|
|
331
338
|
Examples:
|
|
332
339
|
$ assistant cache get my-key
|
|
333
340
|
$ assistant cache get my-key --json`,
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
if (opts.json) {
|
|
342
|
-
process.stdout.write(
|
|
343
|
-
JSON.stringify({ ok: false, error: result.error }) + "\n",
|
|
341
|
+
)
|
|
342
|
+
.action(async (key: string, opts: { json?: boolean }) => {
|
|
343
|
+
const result = await cliIpcCall<{ data: unknown } | null>(
|
|
344
|
+
"cache_get",
|
|
345
|
+
{
|
|
346
|
+
body: { key },
|
|
347
|
+
},
|
|
344
348
|
);
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
349
|
+
|
|
350
|
+
if (!result.ok) {
|
|
351
|
+
if (opts.json) {
|
|
352
|
+
process.stdout.write(
|
|
353
|
+
JSON.stringify({ ok: false, error: result.error }) + "\n",
|
|
354
|
+
);
|
|
355
|
+
} else {
|
|
356
|
+
log.error(`Error: ${result.error}`);
|
|
357
|
+
}
|
|
358
|
+
process.exitCode = 1;
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (opts.json) {
|
|
363
|
+
process.stdout.write(
|
|
364
|
+
JSON.stringify({
|
|
365
|
+
ok: true,
|
|
366
|
+
data: result.result ? result.result.data : null,
|
|
367
|
+
}) + "\n",
|
|
368
|
+
);
|
|
369
|
+
} else {
|
|
370
|
+
if (result.result == null) {
|
|
371
|
+
log.info(`No cache entry found for key "${key}".`);
|
|
372
|
+
} else {
|
|
373
|
+
log.info(JSON.stringify(result.result.data, null, 2));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// ── delete ────────────────────────────────────────────────────────
|
|
379
|
+
|
|
380
|
+
cache
|
|
381
|
+
.command("delete <key>")
|
|
382
|
+
.description("Remove a cached entry by key")
|
|
383
|
+
.option("--json", "Output result as machine-readable JSON.")
|
|
384
|
+
.addHelpText(
|
|
385
|
+
"after",
|
|
386
|
+
`
|
|
377
387
|
Arguments:
|
|
378
388
|
key The cache key to remove. Run 'assistant cache get <key>' to
|
|
379
389
|
verify a key exists before deleting.
|
|
@@ -384,36 +394,39 @@ existed or not, but reports whether an entry was actually removed.
|
|
|
384
394
|
Examples:
|
|
385
395
|
$ assistant cache delete my-key
|
|
386
396
|
$ assistant cache delete my-key --json`,
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (opts.json) {
|
|
395
|
-
process.stdout.write(
|
|
396
|
-
JSON.stringify({ ok: false, error: result.error }) + "\n",
|
|
397
|
+
)
|
|
398
|
+
.action(async (key: string, opts: { json?: boolean }) => {
|
|
399
|
+
const result = await cliIpcCall<{ deleted: boolean }>(
|
|
400
|
+
"cache_delete",
|
|
401
|
+
{
|
|
402
|
+
body: { key },
|
|
403
|
+
},
|
|
397
404
|
);
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
405
|
+
|
|
406
|
+
if (!result.ok) {
|
|
407
|
+
if (opts.json) {
|
|
408
|
+
process.stdout.write(
|
|
409
|
+
JSON.stringify({ ok: false, error: result.error }) + "\n",
|
|
410
|
+
);
|
|
411
|
+
} else {
|
|
412
|
+
log.error(`Error: ${result.error}`);
|
|
413
|
+
}
|
|
414
|
+
process.exitCode = 1;
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const deleted = result.result!.deleted;
|
|
419
|
+
|
|
420
|
+
if (opts.json) {
|
|
421
|
+
process.stdout.write(JSON.stringify({ ok: true, deleted }) + "\n");
|
|
422
|
+
} else {
|
|
423
|
+
if (deleted) {
|
|
424
|
+
log.info(`Deleted cache entry "${key}".`);
|
|
425
|
+
} else {
|
|
426
|
+
log.info(`No cache entry "${key}" (nothing to delete).`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
});
|
|
417
430
|
},
|
|
418
431
|
});
|
|
419
432
|
}
|
|
@@ -456,6 +456,9 @@ async function initSchema(): Promise<void> {
|
|
|
456
456
|
clearStoredDb("memory");
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
+
// Every test here runs initSchema(), which replays the full production
|
|
460
|
+
// migration suite, plus at least one repair pass. On a loaded machine that
|
|
461
|
+
// comfortably exceeds bun's 5s per-test default, so each gets a 30s ceiling.
|
|
459
462
|
describe("assistant db repair — conversation-backfill step", () => {
|
|
460
463
|
test("backfills a disk-only conversation into SQLite", async () => {
|
|
461
464
|
await initSchema();
|
|
@@ -499,7 +502,7 @@ describe("assistant db repair — conversation-backfill step", () => {
|
|
|
499
502
|
} finally {
|
|
500
503
|
verify.close();
|
|
501
504
|
}
|
|
502
|
-
});
|
|
505
|
+
}, 30_000);
|
|
503
506
|
|
|
504
507
|
test("skips conversations already present (idempotent)", async () => {
|
|
505
508
|
await initSchema();
|
|
@@ -516,8 +519,6 @@ describe("assistant db repair — conversation-backfill step", () => {
|
|
|
516
519
|
expect(parsed.steps[1].result.data.recovered).toBe(0);
|
|
517
520
|
expect(parsed.steps[1].result.data.skipped).toBe(1);
|
|
518
521
|
expect(parsed.steps[1].result.status).toBe("ok");
|
|
519
|
-
// Two full repair passes (each walks the DB via integrity-check) exceed
|
|
520
|
-
// bun's 5s per-test default, so raise the ceiling to keep CI stable.
|
|
521
522
|
}, 30_000);
|
|
522
523
|
|
|
523
524
|
test("reports nothing-to-backfill on an empty conversations dir", async () => {
|
|
@@ -529,7 +530,7 @@ describe("assistant db repair — conversation-backfill step", () => {
|
|
|
529
530
|
expect(parsed.steps[1].result.status).toBe("ok");
|
|
530
531
|
expect(parsed.steps[1].result.summary).toContain("nothing to backfill");
|
|
531
532
|
expect(parsed.steps[1].result.data.recovered).toBe(0);
|
|
532
|
-
});
|
|
533
|
+
}, 30_000);
|
|
533
534
|
|
|
534
535
|
test("surfaces warnings for malformed meta.json without erroring the step", async () => {
|
|
535
536
|
await initSchema();
|
|
@@ -547,5 +548,5 @@ describe("assistant db repair — conversation-backfill step", () => {
|
|
|
547
548
|
w.includes("malformed meta.json"),
|
|
548
549
|
),
|
|
549
550
|
).toBe(true);
|
|
550
|
-
});
|
|
551
|
+
}, 30_000);
|
|
551
552
|
});
|
|
@@ -31,6 +31,7 @@ import type { Command } from "commander";
|
|
|
31
31
|
import { getLogsDbPath } from "../../../util/logs-db-path.js";
|
|
32
32
|
import { getMemoryDbPath } from "../../../util/memory-db-path.js";
|
|
33
33
|
import { getDbPath } from "../../../util/platform.js";
|
|
34
|
+
import { getTelemetryDbPath } from "../../../util/telemetry-db-path.js";
|
|
34
35
|
import { red } from "../../lib/cli-colors.js";
|
|
35
36
|
import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
36
37
|
import {
|
|
@@ -99,6 +100,15 @@ interface StatusReport {
|
|
|
99
100
|
*/
|
|
100
101
|
memoryFile?: FileFacts;
|
|
101
102
|
memoryDb?: DbFacts | null;
|
|
103
|
+
/**
|
|
104
|
+
* The dedicated telemetry database (`assistant-telemetry.db`). Like
|
|
105
|
+
* `logsFile` and `memoryFile`, it is omitted from the report until the file
|
|
106
|
+
* exists on disk — it is created the first time the daemon opens its
|
|
107
|
+
* connection, so a fresh install that has never run the daemon won't have
|
|
108
|
+
* one.
|
|
109
|
+
*/
|
|
110
|
+
telemetryFile?: FileFacts;
|
|
111
|
+
telemetryDb?: DbFacts | null;
|
|
102
112
|
}
|
|
103
113
|
|
|
104
114
|
interface MigrationSummary {
|
|
@@ -327,6 +337,13 @@ function renderHuman(report: StatusReport): string {
|
|
|
327
337
|
out += renderDbBlock(report.memoryFile, report.memoryDb ?? null);
|
|
328
338
|
}
|
|
329
339
|
|
|
340
|
+
// The secondary telemetry file is likewise only reported once it exists.
|
|
341
|
+
if (report.telemetryFile?.exists) {
|
|
342
|
+
out += "\n";
|
|
343
|
+
out += "Telemetry database (telemetry event tables)\n";
|
|
344
|
+
out += renderDbBlock(report.telemetryFile, report.telemetryDb ?? null);
|
|
345
|
+
}
|
|
346
|
+
|
|
330
347
|
// Cross-database migration summary — the checkpoint ledger lives only in
|
|
331
348
|
// the main DB, so this is a single block at the end covering all three.
|
|
332
349
|
out += renderSummary(report.migration);
|
|
@@ -409,7 +426,13 @@ function readMigrationSummary(mainDbPath: string): MigrationSummary | null {
|
|
|
409
426
|
// No table yet.
|
|
410
427
|
}
|
|
411
428
|
|
|
412
|
-
return {
|
|
429
|
+
return {
|
|
430
|
+
latestKey,
|
|
431
|
+
latestUpdatedAtMs,
|
|
432
|
+
appliedSteps,
|
|
433
|
+
appliedRegistry,
|
|
434
|
+
crashed,
|
|
435
|
+
};
|
|
413
436
|
} finally {
|
|
414
437
|
db.close();
|
|
415
438
|
}
|
|
@@ -519,6 +542,17 @@ export function registerDbStatus(parent: Command): void {
|
|
|
519
542
|
}
|
|
520
543
|
}
|
|
521
544
|
|
|
545
|
+
// Same best-effort probe for the dedicated telemetry DB.
|
|
546
|
+
const telemetryFile = readFileFacts(getTelemetryDbPath());
|
|
547
|
+
let telemetryDb: DbFacts | null = null;
|
|
548
|
+
if (telemetryFile.exists) {
|
|
549
|
+
try {
|
|
550
|
+
telemetryDb = readDbFacts(telemetryFile.path);
|
|
551
|
+
} catch {
|
|
552
|
+
telemetryDb = null;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
522
556
|
// Cross-database migration summary from the main DB's checkpoint ledger.
|
|
523
557
|
let migration: MigrationSummary | null = null;
|
|
524
558
|
try {
|
|
@@ -535,6 +569,8 @@ export function registerDbStatus(parent: Command): void {
|
|
|
535
569
|
logsDb,
|
|
536
570
|
memoryFile,
|
|
537
571
|
memoryDb,
|
|
572
|
+
telemetryFile,
|
|
573
|
+
telemetryDb,
|
|
538
574
|
};
|
|
539
575
|
if (shouldOutputJson(this)) {
|
|
540
576
|
writeOutput(this, report);
|