@vellumai/assistant 0.8.4 → 0.8.5
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 +2 -2
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/knip.json +2 -1
- package/openapi.yaml +809 -11
- package/package.json +1 -1
- package/src/__tests__/anthropic-provider.test.ts +34 -37
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
- package/src/__tests__/audit-log-rotation.test.ts +70 -16
- package/src/__tests__/background-workers-disk-pressure.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +2 -3
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +3 -3
- package/src/__tests__/checker.test.ts +6 -15
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
- package/src/__tests__/computer-use-tools.test.ts +2 -4
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +197 -2
- package/src/__tests__/conversation-agent-loop.test.ts +163 -122
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-fork-crud.test.ts +178 -15
- package/src/__tests__/conversation-lifecycle.test.ts +52 -11
- package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +13 -13
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
- package/src/__tests__/conversation-skill-tools.test.ts +2 -5
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-sync-tags.test.ts +99 -32
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
- package/src/__tests__/credential-execution-tools.test.ts +6 -6
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +2 -2
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/gateway-flag-listener.test.ts +237 -0
- package/src/__tests__/gemini-provider.test.ts +78 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -5
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +4 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
- package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
- package/src/__tests__/llm-resolver.test.ts +77 -9
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/logger.test.ts +89 -0
- package/src/__tests__/mcp-abort-signal.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +31 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
- package/src/__tests__/model-intents.test.ts +2 -4
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/onboarding-template-contract.test.ts +1 -1
- package/src/__tests__/openai-provider.test.ts +46 -0
- package/src/__tests__/openai-responses-provider.test.ts +114 -12
- package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -2
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +2 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
- package/src/__tests__/plugin-types.test.ts +3 -2
- package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
- package/src/__tests__/pricing.test.ts +12 -0
- package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
- package/src/__tests__/registry.test.ts +2 -8
- package/src/__tests__/require-fresh-approval.test.ts +2 -2
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
- package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
- package/src/__tests__/skill-tool-factory.test.ts +1 -1
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/sync-message-contract.test.ts +59 -0
- package/src/__tests__/system-prompt.test.ts +145 -131
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/tool-approval-handler.test.ts +1 -5
- package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
- package/src/__tests__/tool-executor.test.ts +9 -62
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
- package/src/__tests__/usage-routes.test.ts +3 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +6 -5
- package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
- package/src/acp/prepare-agent-env.ts +78 -0
- package/src/acp/session-manager.ts +1 -1
- package/src/agent/loop.ts +8 -0
- package/src/api/README.md +5 -0
- package/src/api/index.ts +4 -0
- package/src/api/package.json +10 -0
- package/src/background-wake/background-wake-routes.test.ts +233 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
- package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
- package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference.ts +93 -40
- package/src/cli/commands/memory-v2-compare-render.ts +115 -0
- package/src/cli/commands/memory-v2.ts +176 -1
- package/src/cli/commands/memory-v3-render.ts +344 -0
- package/src/cli/commands/memory-v3.ts +316 -0
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +21 -9
- package/src/config/bundled-skills/document-editor/SKILL.md +11 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/call-site-defaults.ts +7 -6
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +213 -1
- package/src/config/schemas/call-site-catalog.ts +21 -7
- package/src/config/schemas/llm.ts +12 -1
- package/src/config/schemas/memory-v2.ts +246 -0
- package/src/config/schemas/memory.ts +2 -1
- package/src/context/compactor.ts +52 -0
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -13
- package/src/daemon/conversation-agent-loop.ts +126 -76
- package/src/daemon/conversation-error.ts +31 -1
- package/src/daemon/conversation-lifecycle.ts +27 -22
- package/src/daemon/conversation-runtime-assembly.ts +10 -9
- package/src/daemon/conversation-tool-setup.ts +63 -3
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +14 -29
- package/src/daemon/disk-pressure-guard.ts +14 -2
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +11 -3
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +4 -4
- package/src/daemon/host-file-proxy.ts +4 -4
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +10 -10
- package/src/daemon/lifecycle.ts +23 -20
- package/src/daemon/meet-manifest-loader.ts +1 -7
- package/src/daemon/message-types/conversations.ts +6 -9
- package/src/daemon/message-types/home.ts +1 -13
- package/src/daemon/message-types/messages.ts +6 -14
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/shutdown-handlers.ts +24 -5
- package/src/daemon/switch-inference-profile-tool.ts +52 -0
- package/src/daemon/tool-setup-types.ts +13 -0
- package/src/events/relationship-state-updated.ts +25 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -1
- package/src/home/home-greeting.ts +0 -9
- package/src/home/suggested-prompts.ts +0 -9
- package/src/ipc/gateway-flag-listener.ts +123 -0
- package/src/ipc/skill-routes/registries.ts +8 -12
- package/src/memory/__tests__/db-async-query.test.ts +165 -0
- package/src/memory/__tests__/db-maintenance.test.ts +115 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
- package/src/memory/__tests__/memory-retrospective-job.test.ts +7 -0
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-crud.ts +71 -70
- package/src/memory/conversation-starters-cadence.ts +3 -1
- package/src/memory/conversation-title-service.ts +19 -3
- package/src/memory/db-async-query.ts +214 -0
- package/src/memory/db-init.ts +10 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/graph/bootstrap.ts +8 -1
- package/src/memory/graph/capability-seed.ts +7 -3
- package/src/memory/graph/conversation-graph-memory.ts +100 -17
- package/src/memory/graph/extraction.ts +1 -5
- package/src/memory/graph/graph-search.ts +7 -1
- package/src/memory/indexer.ts +28 -18
- package/src/memory/job-handlers/cleanup.ts +76 -18
- package/src/memory/job-handlers/conversation-starters.ts +1 -4
- package/src/memory/jobs/embed-pkb-file.ts +6 -1
- package/src/memory/jobs-store.ts +14 -0
- package/src/memory/jobs-worker.ts +55 -22
- package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
- package/src/memory/llm-request-log-source-local.ts +7 -0
- package/src/memory/llm-request-log-source.ts +9 -2
- package/src/memory/llm-request-log-store.ts +43 -1
- package/src/memory/llm-usage-store.ts +24 -0
- package/src/memory/memory-retrospective-enqueue.ts +8 -1
- package/src/memory/memory-retrospective-job.ts +5 -0
- package/src/memory/memory-v2-activation-log-store.ts +15 -6
- package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
- package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
- package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
- package/src/memory/migrations/index.ts +17 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/schema/conversations.ts +1 -1
- package/src/memory/schema/infrastructure.ts +21 -0
- package/src/memory/tool-usage-store.ts +36 -8
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
- package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
- package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
- package/src/memory/v2/__tests__/injection.test.ts +127 -98
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +171 -3
- package/src/memory/v2/harness/compare.ts +57 -0
- package/src/memory/v2/harness/metrics.ts +124 -0
- package/src/memory/v2/harness/oracle.ts +145 -0
- package/src/memory/v2/harness/replay-input.ts +224 -0
- package/src/memory/v2/harness/retriever.ts +74 -0
- package/src/memory/v2/harness/router-retriever.ts +43 -0
- package/src/memory/v2/harness/runner.ts +106 -0
- package/src/memory/v2/harness/trace.ts +58 -0
- package/src/memory/v2/injection.ts +21 -15
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +171 -18
- package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
- package/src/memory/v3/__tests__/edges.test.ts +563 -0
- package/src/memory/v3/__tests__/filter.test.ts +512 -0
- package/src/memory/v3/__tests__/gate.test.ts +574 -0
- package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
- package/src/memory/v3/__tests__/loop.test.ts +530 -0
- package/src/memory/v3/__tests__/retriever.test.ts +226 -0
- package/src/memory/v3/__tests__/scouts.test.ts +440 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
- package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
- package/src/memory/v3/__tests__/traversal.test.ts +469 -0
- package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
- package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
- package/src/memory/v3/__tests__/validate.test.ts +245 -0
- package/src/memory/v3/auto-edges.ts +223 -0
- package/src/memory/v3/coactivation-store.ts +124 -0
- package/src/memory/v3/consolidation-job.ts +323 -0
- package/src/memory/v3/edge-learning-job.ts +160 -0
- package/src/memory/v3/edges.ts +249 -0
- package/src/memory/v3/filter.ts +281 -0
- package/src/memory/v3/gate.ts +334 -0
- package/src/memory/v3/index-composition.ts +113 -0
- package/src/memory/v3/llm-capture.ts +46 -0
- package/src/memory/v3/loop.ts +382 -0
- package/src/memory/v3/maintenance.ts +144 -0
- package/src/memory/v3/prompt-context.ts +33 -0
- package/src/memory/v3/prompts/consolidation.ts +458 -0
- package/src/memory/v3/prompts/system-prompts.ts +196 -0
- package/src/memory/v3/retriever.ts +33 -0
- package/src/memory/v3/scouts.ts +420 -0
- package/src/memory/v3/shadow-middleware.ts +305 -0
- package/src/memory/v3/traversal.ts +206 -0
- package/src/memory/v3/tree-index.ts +237 -0
- package/src/memory/v3/tree-store.ts +394 -0
- package/src/memory/v3/tree-walk.ts +351 -0
- package/src/memory/v3/types.ts +65 -0
- package/src/memory/v3/validate.ts +300 -0
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/emit-signal.ts +29 -49
- package/src/permissions/prompter.ts +3 -3
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +2 -2
- package/src/plugin-api/index.ts +4 -0
- package/src/plugin-api/types.ts +7 -33
- package/src/plugins/defaults/index.ts +6 -0
- package/src/plugins/defaults/injectors.ts +18 -11
- package/src/plugins/external-plugin-loader.ts +5 -68
- package/src/plugins/types.ts +11 -16
- package/src/proactive-artifact/aux-message-injector.ts +17 -4
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +39 -7
- package/src/prompts/system-prompt.ts +50 -185
- package/src/prompts/templates/BOOTSTRAP.md +2 -2
- package/src/prompts/templates/system-sections.ts +230 -8
- package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
- package/src/providers/__tests__/retry-callsite.test.ts +85 -5
- package/src/providers/anthropic/client.ts +32 -66
- package/src/providers/call-site-routing.ts +14 -2
- package/src/providers/connection-model-compat.ts +38 -0
- package/src/providers/connection-resolution.ts +16 -2
- package/src/providers/gemini/client.ts +49 -6
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +43 -0
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openai/chat-completions-provider.ts +6 -3
- package/src/providers/openai/codex-models.ts +18 -0
- package/src/providers/openai/responses-provider.ts +78 -21
- package/src/providers/provider-send-message.ts +7 -1
- package/src/providers/retry.ts +34 -3
- package/src/providers/thinking-config.ts +26 -1
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/agent-wake.ts +1 -0
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +36 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/http-types.ts +0 -2
- package/src/runtime/migrations/vbundle-builder.ts +10 -3
- package/src/runtime/pending-interactions.ts +0 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +106 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +25 -6
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/avatar-routes.ts +10 -10
- package/src/runtime/routes/background-wake-routes.ts +188 -0
- package/src/runtime/routes/browser-tabs-routes.ts +200 -0
- package/src/runtime/routes/btw-routes.ts +0 -6
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +12 -4
- package/src/runtime/routes/conversation-management-routes.ts +77 -20
- package/src/runtime/routes/conversation-query-routes.ts +142 -36
- package/src/runtime/routes/conversation-routes.ts +252 -410
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/domain-routes.ts +60 -10
- package/src/runtime/routes/email-routes.ts +5 -2
- package/src/runtime/routes/events-routes.ts +54 -10
- package/src/runtime/routes/group-routes.ts +24 -8
- package/src/runtime/routes/host-browser-routes.ts +10 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
- package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +215 -5
- package/src/runtime/routes/memory-v3-routes.ts +316 -0
- package/src/runtime/routes/migration-routes.ts +21 -24
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/secret-routes.ts +25 -5
- package/src/runtime/routes/settings-routes.ts +12 -11
- package/src/runtime/routes/slack-channel-routes.ts +5 -4
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/sync/resource-sync-events.ts +106 -38
- package/src/runtime/sync/sync-publisher.test.ts +49 -0
- package/src/runtime/sync/sync-publisher.ts +2 -1
- package/src/runtime/verification-outbound-actions.ts +73 -1
- package/src/telemetry/types.ts +12 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/acp/spawn.test.ts +119 -0
- package/src/tools/acp/spawn.ts +15 -2
- package/src/tools/apps/definitions.ts +2 -8
- package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
- package/src/tools/ask-question/ask-question-tool.ts +38 -45
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
- package/src/tools/browser/browser-execution.ts +16 -3
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
- package/src/tools/browser/cdp-client/factory.ts +100 -17
- package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
- package/src/tools/browser/cdp-client/types.ts +65 -0
- package/src/tools/browser/pinned-tabs.ts +96 -40
- package/src/tools/computer-use/definitions.ts +22 -78
- package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
- package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
- package/src/tools/credentials/vault.ts +3 -9
- package/src/tools/document/document-tool.ts +59 -0
- package/src/tools/execution-target.ts +21 -23
- package/src/tools/executor.ts +6 -1
- package/src/tools/filesystem/edit.ts +3 -9
- package/src/tools/filesystem/list.ts +3 -9
- package/src/tools/filesystem/read.ts +3 -9
- package/src/tools/filesystem/write.ts +3 -9
- package/src/tools/host-filesystem/edit.ts +3 -9
- package/src/tools/host-filesystem/read.ts +3 -9
- package/src/tools/host-filesystem/transfer.ts +3 -9
- package/src/tools/host-filesystem/write.ts +3 -9
- package/src/tools/host-terminal/host-shell.ts +3 -9
- package/src/tools/mcp/mcp-tool-factory.ts +1 -8
- package/src/tools/memory/register.test.ts +1 -1
- package/src/tools/memory/register.ts +4 -9
- package/src/tools/network/web-fetch.ts +3 -9
- package/src/tools/network/web-search.ts +25 -32
- package/src/tools/registry.ts +7 -23
- package/src/tools/schema-transforms.ts +1 -1
- package/src/tools/skills/execute.ts +3 -9
- package/src/tools/skills/load.ts +3 -9
- package/src/tools/skills/skill-tool-factory.ts +1 -8
- package/src/tools/subagent/notify-parent.ts +3 -9
- package/src/tools/system/request-permission.ts +3 -9
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/types.ts +27 -98
- package/src/tools/ui-surface/definitions.ts +6 -22
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -2
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
- package/src/__tests__/message-complete-display-id.test.ts +0 -175
- package/src/daemon/query-complexity-router.ts +0 -75
- package/src/prompts/cache-boundary.ts +0 -8
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for the defaults applied when a `ToolDefinition`
|
|
3
|
+
* omits one of the normally-required fields, plus the `finalizeTool`
|
|
4
|
+
* helper that lifts a `ToolDefinition` into a `LoadedTool`.
|
|
5
|
+
*
|
|
6
|
+
* Plugins, external loaders, and any other registration boundary that
|
|
7
|
+
* accepts loose `ToolDefinition` objects from authors must run them
|
|
8
|
+
* through `finalizeTool` before handing the result to a `registerXxxTools`
|
|
9
|
+
* call. The registry types make this a hard rule: every registered tool
|
|
10
|
+
* is a `LoadedTool` (`Required<ToolDefinition> & { name }`).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type {
|
|
14
|
+
LoadedTool,
|
|
15
|
+
RiskLevel,
|
|
16
|
+
ToolDefinition,
|
|
17
|
+
ToolExecutionResult,
|
|
18
|
+
} from "./types.js";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Default values applied by `finalizeTool` when the author omits a field.
|
|
22
|
+
*
|
|
23
|
+
* - `description` defaults to empty — the model sees the tool name only
|
|
24
|
+
* for un-documented tools, which is the correct minimal-info signal.
|
|
25
|
+
* - `defaultRiskLevel` defaults to `medium` — the safe middle band that
|
|
26
|
+
* forces explicit approval for risky calls without spamming approval
|
|
27
|
+
* prompts on no-op tools.
|
|
28
|
+
* - `input_schema` defaults to an empty closed object — the model is
|
|
29
|
+
* allowed to call the tool with no arguments, and unknown arguments
|
|
30
|
+
* are rejected at the JSON-schema layer.
|
|
31
|
+
* - `executionTarget` defaults to `sandbox` — author-supplied tool code
|
|
32
|
+
* runs in the assistant container by default; opt in to `host` when
|
|
33
|
+
* the tool proxies work to the connected client.
|
|
34
|
+
*
|
|
35
|
+
* `execute` has no constant default because the default closure needs to
|
|
36
|
+
* close over the tool's name to produce a useful error message; see
|
|
37
|
+
* `finalizeTool` below.
|
|
38
|
+
*/
|
|
39
|
+
export const TOOL_DEFAULTS = Object.freeze({
|
|
40
|
+
description: "",
|
|
41
|
+
defaultRiskLevel: "medium" as RiskLevel,
|
|
42
|
+
input_schema: Object.freeze({
|
|
43
|
+
type: "object",
|
|
44
|
+
properties: {},
|
|
45
|
+
additionalProperties: false,
|
|
46
|
+
}) as object,
|
|
47
|
+
executionTarget: "sandbox" as const,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Fill the four normally-required `ToolDefinition` fields with documented
|
|
52
|
+
* defaults when the author omitted them, attach the registration-time
|
|
53
|
+
* `name`, and return a `LoadedTool` that is safe to hand to a
|
|
54
|
+
* `registerXxxTools` call.
|
|
55
|
+
*
|
|
56
|
+
* The default `execute` returns an error result so the model sees a clear
|
|
57
|
+
* "this tool isn't wired up" signal at call time. The owning loader still
|
|
58
|
+
* registers the tool cleanly — a broken individual tool must never block
|
|
59
|
+
* the registration batch.
|
|
60
|
+
*/
|
|
61
|
+
export function finalizeTool(
|
|
62
|
+
tool: ToolDefinition,
|
|
63
|
+
name: string,
|
|
64
|
+
): LoadedTool {
|
|
65
|
+
const description =
|
|
66
|
+
typeof tool.description === "string"
|
|
67
|
+
? tool.description
|
|
68
|
+
: TOOL_DEFAULTS.description;
|
|
69
|
+
const defaultRiskLevel =
|
|
70
|
+
typeof tool.defaultRiskLevel === "string"
|
|
71
|
+
? tool.defaultRiskLevel
|
|
72
|
+
: TOOL_DEFAULTS.defaultRiskLevel;
|
|
73
|
+
const input_schema =
|
|
74
|
+
tool.input_schema !== null && typeof tool.input_schema === "object"
|
|
75
|
+
? tool.input_schema
|
|
76
|
+
: TOOL_DEFAULTS.input_schema;
|
|
77
|
+
const execute =
|
|
78
|
+
typeof tool.execute === "function"
|
|
79
|
+
? tool.execute
|
|
80
|
+
: async (): Promise<ToolExecutionResult> => ({
|
|
81
|
+
content: `tool ${name} has no execute implementation`,
|
|
82
|
+
isError: true,
|
|
83
|
+
});
|
|
84
|
+
const executionTarget = tool.executionTarget ?? TOOL_DEFAULTS.executionTarget;
|
|
85
|
+
return {
|
|
86
|
+
...tool,
|
|
87
|
+
name,
|
|
88
|
+
description,
|
|
89
|
+
defaultRiskLevel,
|
|
90
|
+
input_schema,
|
|
91
|
+
executionTarget,
|
|
92
|
+
execute,
|
|
93
|
+
};
|
|
94
|
+
}
|
package/src/tools/types.ts
CHANGED
|
@@ -5,7 +5,6 @@ import type {
|
|
|
5
5
|
ProxyApprovalCallback,
|
|
6
6
|
RiskLevel,
|
|
7
7
|
SensitiveOutputBinding,
|
|
8
|
-
ToolDefinition,
|
|
9
8
|
ToolExecutionErrorEvent,
|
|
10
9
|
ToolExecutionStartEvent,
|
|
11
10
|
ToolPermissionDeniedEvent,
|
|
@@ -64,7 +63,6 @@ export type {
|
|
|
64
63
|
ProxyEnvVars,
|
|
65
64
|
SensitiveOutputBinding,
|
|
66
65
|
SensitiveOutputKind,
|
|
67
|
-
ToolDefinition,
|
|
68
66
|
ToolExecutionErrorEvent,
|
|
69
67
|
ToolExecutionStartEvent,
|
|
70
68
|
ToolPermissionDeniedEvent,
|
|
@@ -76,19 +74,7 @@ export { RiskLevel } from "@vellumai/skill-host-contracts";
|
|
|
76
74
|
// Assistant-side concrete overlays
|
|
77
75
|
// ---------------------------------------------------------------------------
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
* Public, narrow subset of {@link ToolExecutionResult} that plugin-authored
|
|
81
|
-
* tools are responsible for producing. Re-exported from
|
|
82
|
-
* `@vellumai/plugin-api` as `ToolExecutionResult` — the type name plugin
|
|
83
|
-
* authors actually import. The daemon-internal version below extends
|
|
84
|
-
* this and adds runtime-only fields (risk metadata, approval
|
|
85
|
-
* bookkeeping, sensitive-output bindings, etc.) that the executor
|
|
86
|
-
* populates around the call — plugins MUST NOT set those.
|
|
87
|
-
*
|
|
88
|
-
* Adding fields here is a non-breaking change; renaming or removing
|
|
89
|
-
* fields is breaking and gated on a major bump of `@vellumai/plugin-api`.
|
|
90
|
-
*/
|
|
91
|
-
export interface PluginToolExecutionResult {
|
|
77
|
+
export interface ToolExecutionResult {
|
|
92
78
|
/** Textual result shown to the model in the tool-result block. Empty string is valid. */
|
|
93
79
|
content: string;
|
|
94
80
|
/** When true, the agent loop treats `content` as an error and may surface it / retry. */
|
|
@@ -105,9 +91,6 @@ export interface PluginToolExecutionResult {
|
|
|
105
91
|
* the LLM voluntarily end its turn.
|
|
106
92
|
*/
|
|
107
93
|
yieldToUser?: boolean;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export interface ToolExecutionResult extends PluginToolExecutionResult {
|
|
111
94
|
diff?: DiffInfo;
|
|
112
95
|
/** Optional rich content blocks (e.g. images) to include alongside text in the tool result. */
|
|
113
96
|
contentBlocks?: ContentBlock[];
|
|
@@ -211,20 +194,7 @@ export type ToolLifecycleEventHandler = (
|
|
|
211
194
|
event: ToolLifecycleEvent,
|
|
212
195
|
) => void | Promise<void>;
|
|
213
196
|
|
|
214
|
-
|
|
215
|
-
* Public, narrow subset of {@link ToolContext} handed to plugin-authored
|
|
216
|
-
* tools. Re-exported from `@vellumai/plugin-api` as `ToolContext` — the
|
|
217
|
-
* type name plugin authors actually import. The daemon-internal version
|
|
218
|
-
* below extends this and adds host-only fields (CES client, trust class,
|
|
219
|
-
* lifecycle handlers, requester metadata, host-bash proxy, etc.). Plugin
|
|
220
|
-
* tools see this shape only — the runtime still hands them the full
|
|
221
|
-
* {@link ToolContext} value, but the structural extension here guarantees
|
|
222
|
-
* the assignment without a manual cast.
|
|
223
|
-
*
|
|
224
|
-
* Adding fields here is a non-breaking change; renaming or removing
|
|
225
|
-
* fields is breaking and gated on a major bump of `@vellumai/plugin-api`.
|
|
226
|
-
*/
|
|
227
|
-
export interface PluginToolContext {
|
|
197
|
+
export interface ToolContext {
|
|
228
198
|
/** Identifier of the conversation this tool invocation belongs to. */
|
|
229
199
|
conversationId: string;
|
|
230
200
|
/** Working directory the daemon was launched from. */
|
|
@@ -235,9 +205,6 @@ export interface PluginToolContext {
|
|
|
235
205
|
signal?: AbortSignal;
|
|
236
206
|
/** Optional incremental-output callback for streaming tools. Streaming tools should fall back to returning the full result in `content` when this is absent. */
|
|
237
207
|
onOutput?: (chunk: string) => void;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export interface ToolContext extends PluginToolContext {
|
|
241
208
|
/** Logical assistant scope for multi-assistant routing. */
|
|
242
209
|
assistantId?: string;
|
|
243
210
|
/** When set, the tool execution is part of a task run. Used to retrieve ephemeral permission rules. */
|
|
@@ -349,11 +316,32 @@ export interface ToolContext extends PluginToolContext {
|
|
|
349
316
|
sourceActorPrincipalId?: string;
|
|
350
317
|
}
|
|
351
318
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
319
|
+
/**
|
|
320
|
+
* Author-facing tool spec — re-exported from `@vellumai/plugin-api`.
|
|
321
|
+
* Loaders fill documented defaults for omitted fields via `finalizeTool`
|
|
322
|
+
* in `tool-defaults.ts`.
|
|
323
|
+
*/
|
|
324
|
+
export interface ToolDefinition {
|
|
325
|
+
/** Human-readable description shown to the model in the tool catalog. */
|
|
326
|
+
description?: string;
|
|
327
|
+
/** Author-asserted risk band — low / medium / high. Drives default permission gating. */
|
|
328
|
+
defaultRiskLevel?: RiskLevel;
|
|
329
|
+
/** JSON schema describing the tool's input arguments. */
|
|
330
|
+
input_schema?: object;
|
|
331
|
+
/** Where the tool runs — sandbox (assistant container) or host (guardian device via proxy). Resolved by `resolveExecutionTarget` if omitted. */
|
|
332
|
+
executionTarget?: ExecutionTarget;
|
|
333
|
+
/** Implementation invoked when the model calls the tool. */
|
|
334
|
+
execute?: (
|
|
335
|
+
input: Record<string, unknown>,
|
|
336
|
+
context: ToolContext,
|
|
337
|
+
) => Promise<ToolExecutionResult>;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/** Tool after the loader has derived its name and filled defaults. */
|
|
341
|
+
export type LoadedTool = Required<ToolDefinition> & { name: string };
|
|
342
|
+
|
|
343
|
+
export interface Tool extends LoadedTool {
|
|
355
344
|
category: string;
|
|
356
|
-
defaultRiskLevel: RiskLevel;
|
|
357
345
|
/** When set to 'proxy', the tool is forwarded to a connected client rather than executed locally. */
|
|
358
346
|
executionMode?: "local" | "proxy";
|
|
359
347
|
/** Whether this tool is a core built-in, provided by a skill, contributed by a plugin, or from an MCP server. */
|
|
@@ -368,63 +356,4 @@ export interface Tool {
|
|
|
368
356
|
ownerSkillVersionHash?: string;
|
|
369
357
|
/** Whether the owning skill is bundled with the daemon (trusted first-party). */
|
|
370
358
|
ownerSkillBundled?: boolean;
|
|
371
|
-
/** Declared execution target from the skill manifest. Used by resolveExecutionTarget
|
|
372
|
-
* to accurately label lifecycle events for skill-provided tools. */
|
|
373
|
-
executionTarget?: ExecutionTarget;
|
|
374
|
-
getDefinition(): ToolDefinition;
|
|
375
|
-
execute(
|
|
376
|
-
input: Record<string, unknown>,
|
|
377
|
-
context: ToolContext,
|
|
378
|
-
): Promise<ToolExecutionResult>;
|
|
379
359
|
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Plugin-facing tool shape. The narrow surface plugin authors implement;
|
|
383
|
-
* differs from {@link Tool} in four ways:
|
|
384
|
-
* - Plugins declare `input_schema` as a top-level field instead of
|
|
385
|
-
* implementing `getDefinition()`. The registration boundary synthesizes
|
|
386
|
-
* `getDefinition()` from `{name, description, input_schema}` before the
|
|
387
|
-
* tool enters the internal registry.
|
|
388
|
-
* - `name` is derived from the tool file's basename by the external plugin
|
|
389
|
-
* loader.
|
|
390
|
-
* - `category` is registry-owned and stamped to `"plugin"` when the tool is
|
|
391
|
-
* registered.
|
|
392
|
-
* - All ownership stamps (`origin`, `ownerPluginId`, etc.) are set
|
|
393
|
-
* authoritatively by the bootstrap; plugin authors leave them blank.
|
|
394
|
-
*
|
|
395
|
-
* Every author-visible field is optional. The loader fills the four
|
|
396
|
-
* normally-required slots (`description`, `defaultRiskLevel`,
|
|
397
|
-
* `input_schema`, `execute`) with documented defaults when a plugin omits
|
|
398
|
-
* them — see `applyPluginToolDefaults` in `external-plugin-loader.ts`.
|
|
399
|
-
* A nameless, body-less `export default {}` is a valid (if useless) tool;
|
|
400
|
-
* misconfigured tools surface at call time rather than blocking plugin
|
|
401
|
-
* load.
|
|
402
|
-
*/
|
|
403
|
-
export type PluginTool = Omit<
|
|
404
|
-
Tool,
|
|
405
|
-
"category" | "getDefinition" | "name" | "description" | "defaultRiskLevel"
|
|
406
|
-
> & {
|
|
407
|
-
description?: string;
|
|
408
|
-
defaultRiskLevel?: RiskLevel;
|
|
409
|
-
input_schema?: object;
|
|
410
|
-
execute?: (
|
|
411
|
-
input: Record<string, unknown>,
|
|
412
|
-
context: ToolContext,
|
|
413
|
-
) => Promise<ToolExecutionResult>;
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Plugin tool after the external loader has derived its registry name and
|
|
418
|
-
* filled defaults for any author-omitted fields. All four normally-required
|
|
419
|
-
* slots are guaranteed present.
|
|
420
|
-
*/
|
|
421
|
-
export type LoadedPluginTool = PluginTool & {
|
|
422
|
-
name: string;
|
|
423
|
-
description: string;
|
|
424
|
-
defaultRiskLevel: RiskLevel;
|
|
425
|
-
input_schema: object;
|
|
426
|
-
execute: (
|
|
427
|
-
input: Record<string, unknown>,
|
|
428
|
-
context: ToolContext,
|
|
429
|
-
) => Promise<ToolExecutionResult>;
|
|
430
|
-
};
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { RiskLevel } from "../../permissions/types.js";
|
|
11
|
-
import type { ToolDefinition } from "../../providers/types.js";
|
|
12
11
|
import type { Tool, ToolExecutionResult } from "../types.js";
|
|
13
12
|
|
|
14
13
|
// ---------------------------------------------------------------------------
|
|
@@ -42,12 +41,9 @@ export const uiShowTool: Tool = {
|
|
|
42
41
|
category: "ui-surface",
|
|
43
42
|
defaultRiskLevel: RiskLevel.Low,
|
|
44
43
|
executionMode: "proxy",
|
|
44
|
+
executionTarget: "host",
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
name: this.name,
|
|
49
|
-
description: this.description,
|
|
50
|
-
input_schema: {
|
|
46
|
+
input_schema: {
|
|
51
47
|
type: "object",
|
|
52
48
|
properties: {
|
|
53
49
|
surface_type: {
|
|
@@ -109,8 +105,6 @@ export const uiShowTool: Tool = {
|
|
|
109
105
|
},
|
|
110
106
|
required: ["surface_type", "data"],
|
|
111
107
|
},
|
|
112
|
-
};
|
|
113
|
-
},
|
|
114
108
|
|
|
115
109
|
execute: proxyExecute,
|
|
116
110
|
};
|
|
@@ -127,12 +121,9 @@ const uiUpdateTool: Tool = {
|
|
|
127
121
|
category: "ui-surface",
|
|
128
122
|
defaultRiskLevel: RiskLevel.Low,
|
|
129
123
|
executionMode: "proxy",
|
|
124
|
+
executionTarget: "host",
|
|
130
125
|
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
name: this.name,
|
|
134
|
-
description: this.description,
|
|
135
|
-
input_schema: {
|
|
126
|
+
input_schema: {
|
|
136
127
|
type: "object",
|
|
137
128
|
properties: {
|
|
138
129
|
surface_id: {
|
|
@@ -146,8 +137,6 @@ const uiUpdateTool: Tool = {
|
|
|
146
137
|
},
|
|
147
138
|
required: ["surface_id", "data"],
|
|
148
139
|
},
|
|
149
|
-
};
|
|
150
|
-
},
|
|
151
140
|
|
|
152
141
|
execute: proxyExecute,
|
|
153
142
|
};
|
|
@@ -162,12 +151,9 @@ const uiDismissTool: Tool = {
|
|
|
162
151
|
category: "ui-surface",
|
|
163
152
|
defaultRiskLevel: RiskLevel.Low,
|
|
164
153
|
executionMode: "proxy",
|
|
154
|
+
executionTarget: "host",
|
|
165
155
|
|
|
166
|
-
|
|
167
|
-
return {
|
|
168
|
-
name: this.name,
|
|
169
|
-
description: this.description,
|
|
170
|
-
input_schema: {
|
|
156
|
+
input_schema: {
|
|
171
157
|
type: "object",
|
|
172
158
|
properties: {
|
|
173
159
|
surface_id: {
|
|
@@ -177,8 +163,6 @@ const uiDismissTool: Tool = {
|
|
|
177
163
|
},
|
|
178
164
|
required: ["surface_id"],
|
|
179
165
|
},
|
|
180
|
-
};
|
|
181
|
-
},
|
|
182
166
|
|
|
183
167
|
execute: proxyExecute,
|
|
184
168
|
};
|
package/src/usage/pricing.ts
CHANGED
|
@@ -20,9 +20,32 @@ function normalizeTokenCount(value: number | null | undefined): number {
|
|
|
20
20
|
|
|
21
21
|
function asRecord(value: unknown): Record<string, unknown> | null {
|
|
22
22
|
if (typeof value !== "object" || value == null) return null;
|
|
23
|
+
if (Array.isArray(value)) return null;
|
|
23
24
|
return value as Record<string, unknown>;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Extract the provider's untouched `usage` block from a `rawResponse`
|
|
29
|
+
* payload for opaque end-to-end forwarding (the `raw_usage` column /
|
|
30
|
+
* telemetry field).
|
|
31
|
+
*
|
|
32
|
+
* Returns `null` when there is no usage object to surface. For streaming
|
|
33
|
+
* providers that pass `rawResponse` as an accumulated array of chunks,
|
|
34
|
+
* the final element's `usage` is preferred — Anthropic and OpenAI both
|
|
35
|
+
* stamp the complete tally on the terminal chunk, so taking the last
|
|
36
|
+
* element captures the post-completion state without re-aggregating.
|
|
37
|
+
*/
|
|
38
|
+
export function extractRawUsage(
|
|
39
|
+
rawResponse: unknown,
|
|
40
|
+
): Record<string, unknown> | null {
|
|
41
|
+
if (rawResponse == null) return null;
|
|
42
|
+
const candidate = Array.isArray(rawResponse)
|
|
43
|
+
? rawResponse[rawResponse.length - 1]
|
|
44
|
+
: rawResponse;
|
|
45
|
+
const record = asRecord(candidate);
|
|
46
|
+
return asRecord(record?.usage);
|
|
47
|
+
}
|
|
48
|
+
|
|
26
49
|
function extractAnthropicCacheCreationFromResponse(
|
|
27
50
|
response: unknown,
|
|
28
51
|
): AnthropicCacheCreationTokenDetails | null {
|
package/src/usage/types.ts
CHANGED
|
@@ -42,6 +42,18 @@ export interface UsageEventInput {
|
|
|
42
42
|
outputTokens: number;
|
|
43
43
|
cacheCreationInputTokens: number | null;
|
|
44
44
|
cacheReadInputTokens: number | null;
|
|
45
|
+
/**
|
|
46
|
+
* The provider's untouched `usage` block (the literal object returned in
|
|
47
|
+
* the API response), preserved as JSON so downstream consumers can
|
|
48
|
+
* extract any provider-specific detail without requiring a schema
|
|
49
|
+
* change. Anthropic nests its TTL breakdown under
|
|
50
|
+
* `cache_creation.ephemeral_{5m,1h}_input_tokens`; OpenAI nests cached
|
|
51
|
+
* read counts under `prompt_tokens_details.cached_tokens`; both shapes
|
|
52
|
+
* are stored as-is. `null` when the provider did not return a usage
|
|
53
|
+
* block and for rows persisted before the
|
|
54
|
+
* `260-llm-usage-add-raw-usage` migration.
|
|
55
|
+
*/
|
|
56
|
+
rawUsage: Record<string, unknown> | null;
|
|
45
57
|
actor: UsageActor;
|
|
46
58
|
conversationId: string | null;
|
|
47
59
|
runId: string | null;
|
package/src/util/logger.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
getIsContainerized,
|
|
18
18
|
} from "../config/env-registry.js";
|
|
19
19
|
import { logSerializers } from "./log-redact.js";
|
|
20
|
-
import {
|
|
20
|
+
import { getLogsDir } from "./platform.js";
|
|
21
21
|
import { createSentryLogStream } from "./sentry-log-stream.js";
|
|
22
22
|
|
|
23
23
|
/** Common pino-pretty options that inline [module] into the message prefix. */
|
|
@@ -87,7 +87,7 @@ function resolveLogDir(config: LogFileConfig): string | undefined {
|
|
|
87
87
|
if (getIsContainerized()) {
|
|
88
88
|
// Config has a host-specific path that can't be created inside the
|
|
89
89
|
// container (e.g. /Users/…). Fall back to the default log directory.
|
|
90
|
-
const fallback =
|
|
90
|
+
const fallback = getLogsDir();
|
|
91
91
|
console.warn(
|
|
92
92
|
`[logger] Configured logFile.dir "${config.dir}" cannot be created ` +
|
|
93
93
|
`in container (${(err as Error).message}). Falling back to "${fallback}".`,
|
|
@@ -210,7 +210,8 @@ function getRootLogger(): pino.Logger {
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
try {
|
|
213
|
-
const
|
|
213
|
+
const logDir = getLogsDir();
|
|
214
|
+
const logPath = logFilePathForDate(logDir, new Date());
|
|
214
215
|
// Use sync: true so the fd is opened immediately. This prevents
|
|
215
216
|
// "sonic boom is not ready yet" errors when commander calls
|
|
216
217
|
// process.exit(0) for --help/--version before the async fd is ready.
|
|
@@ -247,6 +248,10 @@ function getRootLogger(): pino.Logger {
|
|
|
247
248
|
fileStream,
|
|
248
249
|
);
|
|
249
250
|
}
|
|
251
|
+
|
|
252
|
+
// Register state so ensureCurrentDate() rebuilds across UTC midnight.
|
|
253
|
+
activeLogFileConfig = { dir: logDir, retentionDays: 0 };
|
|
254
|
+
activeLogDate = formatDate(new Date());
|
|
250
255
|
} catch {
|
|
251
256
|
rootLogger = pino(
|
|
252
257
|
{
|
|
@@ -274,16 +279,20 @@ export function truncateForLog(value: string, maxLen = 500): string {
|
|
|
274
279
|
/**
|
|
275
280
|
* Returns a lazy logger that only initializes pino when a log method is called.
|
|
276
281
|
* This avoids "sonic boom is not ready yet" errors when the process exits
|
|
277
|
-
* quickly (e.g. `assistant --help`).
|
|
282
|
+
* quickly (e.g. `assistant --help`). The child is rebuilt whenever the
|
|
283
|
+
* underlying root logger changes (e.g. day rollover, late initLogger()).
|
|
278
284
|
*/
|
|
279
285
|
export function getLogger(name: string): pino.Logger {
|
|
286
|
+
let cachedRoot: pino.Logger | null = null;
|
|
280
287
|
let child: pino.Logger | null = null;
|
|
281
288
|
const handler: ProxyHandler<pino.Logger> = {
|
|
282
289
|
get(_target, prop, receiver) {
|
|
283
|
-
|
|
284
|
-
|
|
290
|
+
const root = getRootLogger();
|
|
291
|
+
if (root !== cachedRoot) {
|
|
292
|
+
cachedRoot = root;
|
|
293
|
+
child = root.child({ module: name });
|
|
285
294
|
}
|
|
286
|
-
const val = Reflect.get(child
|
|
295
|
+
const val = Reflect.get(child!, prop, receiver);
|
|
287
296
|
if (typeof val === "function") {
|
|
288
297
|
return val.bind(child);
|
|
289
298
|
}
|
package/src/util/platform.ts
CHANGED
|
@@ -158,8 +158,13 @@ export function getDbPath(): string {
|
|
|
158
158
|
return join(getDataDir(), "db", "assistant.db");
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Returns the directory where logs live: `<dataDir>/logs/`. Files rotate
|
|
163
|
+
* daily (`assistant-YYYY-MM-DD.log`), so callers ask for the directory and
|
|
164
|
+
* let the logger own the filename.
|
|
165
|
+
*/
|
|
166
|
+
export function getLogsDir(): string {
|
|
167
|
+
return join(getDataDir(), "logs");
|
|
163
168
|
}
|
|
164
169
|
|
|
165
170
|
export function getHistoryPath(): string {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper for locating a `sqlite3` CLI binary on the host.
|
|
3
|
+
*
|
|
4
|
+
* Used by `memory/db-async-query.ts` so slow statements (`VACUUM`,
|
|
5
|
+
* `PRAGMA optimize`, large bulk deletes) can be shelled out to a
|
|
6
|
+
* subprocess and run without blocking the daemon's main event loop.
|
|
7
|
+
*
|
|
8
|
+
* Resolution order (matches the spirit of `bun-runtime.ts#findBun()`):
|
|
9
|
+
* 1. Common system install locations
|
|
10
|
+
* 2. `Bun.which("sqlite3")` (PATH lookup)
|
|
11
|
+
*
|
|
12
|
+
* Unlike `bun-runtime.ts`, this module does **not** download `sqlite3`
|
|
13
|
+
* when missing. The async path is opt-out (callers fall back to the
|
|
14
|
+
* synchronous in-process `bun:sqlite` connection); if a user wants the
|
|
15
|
+
* non-blocking behavior they install one package.
|
|
16
|
+
*
|
|
17
|
+
* On platform (k8s assistant container) `sqlite3` is installed in the
|
|
18
|
+
* Dockerfile, so the primary path is always available there. On macOS
|
|
19
|
+
* `sqlite3` ships with the OS. On most Linux distros it's available via
|
|
20
|
+
* the system package manager.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { existsSync } from "node:fs";
|
|
24
|
+
|
|
25
|
+
let cachedSqlite3Path: string | undefined | null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Synchronous lookup for a usable `sqlite3` CLI binary.
|
|
29
|
+
* Returns the path if found, `undefined` otherwise. Result is cached
|
|
30
|
+
* per-process so the filesystem checks only happen once.
|
|
31
|
+
*/
|
|
32
|
+
export function findSqlite3(): string | undefined {
|
|
33
|
+
if (cachedSqlite3Path !== undefined) {
|
|
34
|
+
return cachedSqlite3Path ?? undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 1. Common install locations. We check these before `Bun.which` so we
|
|
38
|
+
// pick a deterministic, predictable binary even when PATH is
|
|
39
|
+
// unusual (e.g. a daemon launched with a stripped env).
|
|
40
|
+
for (const p of [
|
|
41
|
+
"/usr/bin/sqlite3",
|
|
42
|
+
"/usr/local/bin/sqlite3",
|
|
43
|
+
"/opt/homebrew/bin/sqlite3",
|
|
44
|
+
]) {
|
|
45
|
+
if (existsSync(p)) {
|
|
46
|
+
cachedSqlite3Path = p;
|
|
47
|
+
return p;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 2. PATH lookup.
|
|
52
|
+
const which = Bun.which("sqlite3");
|
|
53
|
+
if (which) {
|
|
54
|
+
cachedSqlite3Path = which;
|
|
55
|
+
return which;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
cachedSqlite3Path = null;
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Reset the cached lookup. Test-only. */
|
|
63
|
+
export function _resetSqlite3Cache(): void {
|
|
64
|
+
cachedSqlite3Path = undefined;
|
|
65
|
+
}
|
|
@@ -140,6 +140,7 @@ const GEMINI_CATALOG_MODELS = new Set<string>([
|
|
|
140
140
|
"gemini-3.1-pro-preview-customtools",
|
|
141
141
|
"gemini-3-flash-preview",
|
|
142
142
|
"gemini-3.1-flash-lite-preview",
|
|
143
|
+
"gemini-3.1-flash-lite",
|
|
143
144
|
"gemini-2.5-flash",
|
|
144
145
|
"gemini-2.5-flash-lite",
|
|
145
146
|
"gemini-2.5-pro",
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { getLogger } from "../../util/logger.js";
|
|
5
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
6
|
+
|
|
7
|
+
const log = getLogger("workspace-migration-089-move-memory-tree-out-of-v3");
|
|
8
|
+
|
|
9
|
+
function isNotFoundError(err: unknown): boolean {
|
|
10
|
+
return (
|
|
11
|
+
typeof err === "object" &&
|
|
12
|
+
err !== null &&
|
|
13
|
+
"code" in err &&
|
|
14
|
+
err.code === "ENOENT"
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Move `<workspace>/memory/<fromRel>` to `<workspace>/memory/<toRel>` when the
|
|
20
|
+
* source exists and the destination does not. Idempotent: a missing source is a
|
|
21
|
+
* no-op (already migrated, or never created), and an existing destination is
|
|
22
|
+
* left untouched (we never clobber). Both directions go through here so `run`
|
|
23
|
+
* and `down` share the same safety checks.
|
|
24
|
+
*/
|
|
25
|
+
function moveMemorySubdir(
|
|
26
|
+
workspaceDir: string,
|
|
27
|
+
fromRel: string,
|
|
28
|
+
toRel: string,
|
|
29
|
+
): void {
|
|
30
|
+
const memoryDir = join(workspaceDir, "memory");
|
|
31
|
+
const src = join(memoryDir, fromRel);
|
|
32
|
+
const dest = join(memoryDir, toRel);
|
|
33
|
+
try {
|
|
34
|
+
if (!fs.existsSync(src)) return;
|
|
35
|
+
if (fs.existsSync(dest)) {
|
|
36
|
+
log.warn(
|
|
37
|
+
{ src, dest },
|
|
38
|
+
"Both source and destination tree dirs exist; leaving in place for manual resolution",
|
|
39
|
+
);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
fs.mkdirSync(dirname(dest), { recursive: true });
|
|
43
|
+
fs.renameSync(src, dest);
|
|
44
|
+
log.info({ src, dest }, "Moved memory tree directory");
|
|
45
|
+
} catch (err) {
|
|
46
|
+
if (isNotFoundError(err)) return;
|
|
47
|
+
log.warn({ err, src, dest }, "Failed to move memory tree directory");
|
|
48
|
+
throw err;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Remove `<workspace>/memory/v3` if it is now an empty wrapper (the tree was
|
|
53
|
+
* its only child). Best-effort — a non-empty or missing dir is left alone. */
|
|
54
|
+
function removeEmptyV3Wrapper(workspaceDir: string): void {
|
|
55
|
+
const v3Dir = join(workspaceDir, "memory", "v3");
|
|
56
|
+
try {
|
|
57
|
+
if (fs.existsSync(v3Dir) && fs.readdirSync(v3Dir).length === 0) {
|
|
58
|
+
fs.rmdirSync(v3Dir);
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
// Non-fatal: leaving an empty memory/v3 wrapper is harmless.
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Relocate the v3 memory tree from `memory/v3/tree` to `memory/tree`.
|
|
67
|
+
*
|
|
68
|
+
* The tree is a DAG overlay over the flat `memory/concepts/` pages and is now a
|
|
69
|
+
* top-level sibling of `concepts/` (matching the storage design), no longer
|
|
70
|
+
* nested under a `v3/` wrapper. `getTreeDir` reads `memory/tree` after this
|
|
71
|
+
* change, so any pre-existing hand-authored tree must move with it.
|
|
72
|
+
*/
|
|
73
|
+
export const moveMemoryTreeOutOfV3Migration: WorkspaceMigration = {
|
|
74
|
+
id: "089-move-memory-tree-out-of-v3",
|
|
75
|
+
description: "Relocate the v3 memory tree from memory/v3/tree to memory/tree",
|
|
76
|
+
retryFailedCheckpoint: true,
|
|
77
|
+
|
|
78
|
+
run(workspaceDir: string): void {
|
|
79
|
+
moveMemorySubdir(workspaceDir, join("v3", "tree"), "tree");
|
|
80
|
+
removeEmptyV3Wrapper(workspaceDir);
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
down(workspaceDir: string): void {
|
|
84
|
+
moveMemorySubdir(workspaceDir, "tree", join("v3", "tree"));
|
|
85
|
+
},
|
|
86
|
+
};
|
|
@@ -86,6 +86,7 @@ import { memoryV2Bm25BReembedDisabledV2PagesMigration } from "./085-memory-v2-bm
|
|
|
86
86
|
import { revertStaleGeminiMisRewritesMigration } from "./086-revert-stale-gemini-mis-rewrites.js";
|
|
87
87
|
import { memoryRouterBalancedProfileMigration } from "./087-memory-router-balanced-profile.js";
|
|
88
88
|
import { deprecateBackgroundConversationOverrideMigration } from "./088-deprecate-background-conversation-override.js";
|
|
89
|
+
import { moveMemoryTreeOutOfV3Migration } from "./089-move-memory-tree-out-of-v3.js";
|
|
89
90
|
import { migrateToWorkspaceVolumeMigration } from "./migrate-to-workspace-volume.js";
|
|
90
91
|
import type { WorkspaceMigration } from "./types.js";
|
|
91
92
|
|
|
@@ -183,4 +184,5 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
|
|
|
183
184
|
revertStaleGeminiMisRewritesMigration,
|
|
184
185
|
memoryRouterBalancedProfileMigration,
|
|
185
186
|
deprecateBackgroundConversationOverrideMigration,
|
|
187
|
+
moveMemoryTreeOutOfV3Migration,
|
|
186
188
|
];
|