@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
package/src/agent/loop.ts
CHANGED
|
@@ -103,6 +103,14 @@ export type AgentLoopExitReason =
|
|
|
103
103
|
| "checkpoint_handoff"
|
|
104
104
|
/** Context-window recovery exhausted and the turn ended with an error. */
|
|
105
105
|
| "context_too_large"
|
|
106
|
+
/**
|
|
107
|
+
* Auto-compress rerun (post-emergency-compaction, post-tier reducer)
|
|
108
|
+
* still yielded at the mid-loop budget checkpoint — the turn silently
|
|
109
|
+
* terminated with no further recovery layer to re-enter. Pure
|
|
110
|
+
* observability signal so the silent stall is attributable instead of
|
|
111
|
+
* leaving `agent_loop_exit_reason` NULL.
|
|
112
|
+
*/
|
|
113
|
+
| "budget_yield_unrecovered"
|
|
106
114
|
/** User cancellation landed after a non-terminal checkpoint yield. */
|
|
107
115
|
| "aborted_after_checkpoint"
|
|
108
116
|
/** Signal aborted while the catch handler was synthesizing an error turn. */
|
package/src/api/index.ts
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import type { BackgroundWakeIntent } from "./next-wake.js";
|
|
4
|
+
import {
|
|
5
|
+
clearBackgroundWakeRuntime,
|
|
6
|
+
registerBackgroundWakeRuntime,
|
|
7
|
+
} from "./runtime-registry.js";
|
|
8
|
+
|
|
9
|
+
type MockIntent = BackgroundWakeIntent;
|
|
10
|
+
|
|
11
|
+
let computedIntent: MockIntent | null;
|
|
12
|
+
let computeCalls: number;
|
|
13
|
+
|
|
14
|
+
const { ROUTES, setBackgroundWakeIntentComputerForTest } =
|
|
15
|
+
await import("../runtime/routes/background-wake-routes.js");
|
|
16
|
+
|
|
17
|
+
function findHandler(operationId: string) {
|
|
18
|
+
const route = ROUTES.find(
|
|
19
|
+
(candidate) => candidate.operationId === operationId,
|
|
20
|
+
);
|
|
21
|
+
if (!route) throw new Error(`Route ${operationId} not found`);
|
|
22
|
+
return route.handler;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const NOW = 1_800_000_000_000;
|
|
26
|
+
|
|
27
|
+
describe("background wake runtime routes", () => {
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
clearBackgroundWakeRuntime();
|
|
30
|
+
computeCalls = 0;
|
|
31
|
+
computedIntent = intentFixture({ nextWakeAt: Date.now() + 10 * 60_000 });
|
|
32
|
+
setBackgroundWakeIntentComputerForTest(() => {
|
|
33
|
+
computeCalls += 1;
|
|
34
|
+
return computedIntent;
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
setBackgroundWakeIntentComputerForTest(null);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("intent route returns the current computed wake intent", async () => {
|
|
43
|
+
const handler = findHandler("getBackgroundWakeIntent");
|
|
44
|
+
|
|
45
|
+
expect(await handler({})).toEqual({ intent: computedIntent });
|
|
46
|
+
expect(computeCalls).toBe(1);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("intent route returns null when no wake intent exists", async () => {
|
|
50
|
+
computedIntent = null;
|
|
51
|
+
const handler = findHandler("getBackgroundWakeIntent");
|
|
52
|
+
|
|
53
|
+
expect(await handler({})).toEqual({ intent: null });
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("prepare-sleep defers when the next wake is inside the local window", async () => {
|
|
57
|
+
computedIntent = intentFixture({ nextWakeAt: Date.now() + 30_000 });
|
|
58
|
+
const handler = findHandler("prepareBackgroundWakeSleep");
|
|
59
|
+
|
|
60
|
+
expect(await handler({})).toEqual({
|
|
61
|
+
intent: computedIntent,
|
|
62
|
+
deferSleep: true,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("prepare-sleep allows sleep when the next wake is outside the local window", async () => {
|
|
67
|
+
computedIntent = intentFixture({ nextWakeAt: Date.now() + 5 * 60_000 });
|
|
68
|
+
const handler = findHandler("prepareBackgroundWakeSleep");
|
|
69
|
+
|
|
70
|
+
expect(await handler({})).toEqual({
|
|
71
|
+
intent: computedIntent,
|
|
72
|
+
deferSleep: false,
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("drain-due fails when the runtime registry is missing", async () => {
|
|
77
|
+
const handler = findHandler("drainDueBackgroundWake");
|
|
78
|
+
|
|
79
|
+
await expect(handler({ body: drainBodyFixture() })).rejects.toThrow(
|
|
80
|
+
"Background wake runtime is not registered",
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("drain-due invokes due heartbeat and scheduler work", async () => {
|
|
85
|
+
const heartbeatRunOnce = mock(async () => true);
|
|
86
|
+
const schedulerRunOnce = mock(async () => 2);
|
|
87
|
+
registerBackgroundWakeRuntime({
|
|
88
|
+
heartbeat: {
|
|
89
|
+
nextRunAt: Date.now() - 1,
|
|
90
|
+
runOnce: heartbeatRunOnce,
|
|
91
|
+
},
|
|
92
|
+
scheduler: {
|
|
93
|
+
runOnce: schedulerRunOnce,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
computedIntent = intentFixture({
|
|
97
|
+
nextWakeAt: NOW + 60_000,
|
|
98
|
+
sourceGeneration: "next-generation",
|
|
99
|
+
});
|
|
100
|
+
const handler = findHandler("drainDueBackgroundWake");
|
|
101
|
+
|
|
102
|
+
const response = await handler({ body: drainBodyFixture() });
|
|
103
|
+
|
|
104
|
+
expect(heartbeatRunOnce).toHaveBeenCalledTimes(1);
|
|
105
|
+
expect(heartbeatRunOnce).toHaveBeenCalledWith();
|
|
106
|
+
expect(schedulerRunOnce).toHaveBeenCalledTimes(1);
|
|
107
|
+
expect(response).toEqual({
|
|
108
|
+
leaseId: "lease-123",
|
|
109
|
+
reason: "schedule",
|
|
110
|
+
sourceGeneration: "source-generation",
|
|
111
|
+
startedAt: NOW,
|
|
112
|
+
deadlineAt: NOW + 30_000,
|
|
113
|
+
counts: {
|
|
114
|
+
heartbeat: 1,
|
|
115
|
+
scheduler: 2,
|
|
116
|
+
total: 3,
|
|
117
|
+
},
|
|
118
|
+
nextIntent: computedIntent,
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("drain-due skips heartbeat when it is not due and reports no scheduler work", async () => {
|
|
123
|
+
const heartbeatRunOnce = mock(async () => true);
|
|
124
|
+
const schedulerRunOnce = mock(async () => 0);
|
|
125
|
+
registerBackgroundWakeRuntime({
|
|
126
|
+
heartbeat: {
|
|
127
|
+
nextRunAt: Date.now() + 5 * 60_000,
|
|
128
|
+
runOnce: heartbeatRunOnce,
|
|
129
|
+
},
|
|
130
|
+
scheduler: {
|
|
131
|
+
runOnce: schedulerRunOnce,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
const handler = findHandler("drainDueBackgroundWake");
|
|
135
|
+
|
|
136
|
+
const response = (await handler({ body: drainBodyFixture() })) as {
|
|
137
|
+
counts: { heartbeat: number; scheduler: number; total: number };
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
expect(heartbeatRunOnce).not.toHaveBeenCalled();
|
|
141
|
+
expect(schedulerRunOnce).toHaveBeenCalledTimes(1);
|
|
142
|
+
expect(response.counts).toEqual({
|
|
143
|
+
heartbeat: 0,
|
|
144
|
+
scheduler: 0,
|
|
145
|
+
total: 0,
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("drain-due recomputes the next intent after due work drains", async () => {
|
|
150
|
+
const recomputedIntent = intentFixture({
|
|
151
|
+
nextWakeAt: NOW + 2 * 60_000,
|
|
152
|
+
sourceGeneration: "after-drain",
|
|
153
|
+
});
|
|
154
|
+
const schedulerRunOnce = mock(async () => {
|
|
155
|
+
computedIntent = recomputedIntent;
|
|
156
|
+
return 1;
|
|
157
|
+
});
|
|
158
|
+
registerBackgroundWakeRuntime({
|
|
159
|
+
heartbeat: {
|
|
160
|
+
nextRunAt: null,
|
|
161
|
+
runOnce: mock(async () => true),
|
|
162
|
+
},
|
|
163
|
+
scheduler: {
|
|
164
|
+
runOnce: schedulerRunOnce,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
const handler = findHandler("drainDueBackgroundWake");
|
|
168
|
+
|
|
169
|
+
const response = (await handler({ body: drainBodyFixture() })) as {
|
|
170
|
+
nextIntent: MockIntent | null;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
expect(response.nextIntent).toEqual(recomputedIntent);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test("drain-due accepts vembda snake_case payload aliases", async () => {
|
|
177
|
+
const schedulerRunOnce = mock(async () => 0);
|
|
178
|
+
registerBackgroundWakeRuntime({
|
|
179
|
+
heartbeat: {
|
|
180
|
+
nextRunAt: null,
|
|
181
|
+
runOnce: mock(async () => false),
|
|
182
|
+
},
|
|
183
|
+
scheduler: {
|
|
184
|
+
runOnce: schedulerRunOnce,
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
const handler = findHandler("drainDueBackgroundWake");
|
|
188
|
+
|
|
189
|
+
const response = await handler({
|
|
190
|
+
body: {
|
|
191
|
+
lease_id: "lease-snake",
|
|
192
|
+
reason: "refresh",
|
|
193
|
+
source_generation: "generation-snake",
|
|
194
|
+
started_at: new Date(NOW).toISOString(),
|
|
195
|
+
deadline_at: String(NOW + 30_000),
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
expect(response).toMatchObject({
|
|
200
|
+
leaseId: "lease-snake",
|
|
201
|
+
reason: "refresh",
|
|
202
|
+
sourceGeneration: "generation-snake",
|
|
203
|
+
startedAt: NOW,
|
|
204
|
+
deadlineAt: NOW + 30_000,
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
function drainBodyFixture() {
|
|
210
|
+
return {
|
|
211
|
+
leaseId: "lease-123",
|
|
212
|
+
reason: "schedule",
|
|
213
|
+
sourceGeneration: "source-generation",
|
|
214
|
+
startedAt: NOW,
|
|
215
|
+
deadlineAt: NOW + 30_000,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function intentFixture(overrides: Partial<MockIntent>): MockIntent {
|
|
220
|
+
const nextWakeAt = overrides.nextWakeAt ?? NOW + 60_000;
|
|
221
|
+
return {
|
|
222
|
+
nextWakeAt,
|
|
223
|
+
actualNextDueAt: nextWakeAt,
|
|
224
|
+
reason: "schedule",
|
|
225
|
+
sourceGeneration: "source-generation",
|
|
226
|
+
computedAt: NOW - 1_000,
|
|
227
|
+
sourcePayload: {
|
|
228
|
+
heartbeat: null,
|
|
229
|
+
schedules: [],
|
|
230
|
+
},
|
|
231
|
+
...overrides,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { HeartbeatService } from "../heartbeat/heartbeat-service.js";
|
|
2
|
+
import type { SchedulerHandle } from "../schedule/scheduler.js";
|
|
3
|
+
|
|
4
|
+
export interface BackgroundWakeRuntime {
|
|
5
|
+
scheduler: Pick<SchedulerHandle, "runOnce">;
|
|
6
|
+
heartbeat: Pick<HeartbeatService, "nextRunAt" | "runOnce">;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let runtime: BackgroundWakeRuntime | null = null;
|
|
10
|
+
|
|
11
|
+
export function registerBackgroundWakeRuntime(
|
|
12
|
+
nextRuntime: BackgroundWakeRuntime,
|
|
13
|
+
): void {
|
|
14
|
+
runtime = nextRuntime;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getBackgroundWakeRuntime(): BackgroundWakeRuntime | null {
|
|
18
|
+
return runtime;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** @internal Test helper for module-level route state. */
|
|
22
|
+
export function clearBackgroundWakeRuntime(): void {
|
|
23
|
+
runtime = null;
|
|
24
|
+
}
|
|
@@ -131,26 +131,44 @@ beforeEach(() => {
|
|
|
131
131
|
// ---------------------------------------------------------------------------
|
|
132
132
|
|
|
133
133
|
describe("subcommand registration", () => {
|
|
134
|
-
test("registers
|
|
134
|
+
test("registers one direct subcommand per BROWSER_OPERATIONS entry plus 'tabs' group", () => {
|
|
135
135
|
const program = new Command();
|
|
136
136
|
registerBrowserCommand(program);
|
|
137
137
|
const browser = program.commands.find((c) => c.name() === "browser");
|
|
138
138
|
expect(browser).toBeDefined();
|
|
139
|
-
|
|
140
|
-
expect(
|
|
139
|
+
// 17 operation commands + 1 'tabs' grouping subcommand
|
|
140
|
+
expect(browser!.commands).toHaveLength(BROWSER_OPERATIONS.length + 1);
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
-
test("subcommand names match kebab-cased BROWSER_OPERATIONS", () => {
|
|
143
|
+
test("operation subcommand names match kebab-cased BROWSER_OPERATIONS", () => {
|
|
144
144
|
const program = new Command();
|
|
145
145
|
registerBrowserCommand(program);
|
|
146
146
|
const browser = program.commands.find((c) => c.name() === "browser");
|
|
147
|
-
|
|
147
|
+
// Filter out the 'tabs' grouping subcommand — it's not a BROWSER_OPERATIONS entry.
|
|
148
|
+
const subcommandNames = browser!.commands
|
|
149
|
+
.filter((c) => c.name() !== "tabs")
|
|
150
|
+
.map((c) => c.name())
|
|
151
|
+
.sort();
|
|
148
152
|
const expectedNames = BROWSER_OPERATIONS.map((op) =>
|
|
149
153
|
op.replace(/_/g, "-"),
|
|
150
154
|
).sort();
|
|
151
155
|
expect(subcommandNames).toEqual(expectedNames);
|
|
152
156
|
});
|
|
153
157
|
|
|
158
|
+
test("registers 'tabs' subcommand group with list/select/new/close", () => {
|
|
159
|
+
const program = new Command();
|
|
160
|
+
registerBrowserCommand(program);
|
|
161
|
+
const browser = program.commands.find((c) => c.name() === "browser");
|
|
162
|
+
const tabs = browser!.commands.find((c) => c.name() === "tabs");
|
|
163
|
+
expect(tabs).toBeDefined();
|
|
164
|
+
expect(tabs!.commands.map((c) => c.name()).sort()).toEqual([
|
|
165
|
+
"close",
|
|
166
|
+
"list",
|
|
167
|
+
"new",
|
|
168
|
+
"select",
|
|
169
|
+
]);
|
|
170
|
+
});
|
|
171
|
+
|
|
154
172
|
test("all 17 operations from BROWSER_OPERATIONS are covered", () => {
|
|
155
173
|
expect(BROWSER_OPERATIONS).toHaveLength(17);
|
|
156
174
|
expect(BROWSER_OPERATION_META).toHaveLength(17);
|
|
@@ -204,4 +204,114 @@ describe("assistant domain register", () => {
|
|
|
204
204
|
await runDomainCommand("domain", "register", "velly");
|
|
205
205
|
expect(process.exitCode).not.toBe(0);
|
|
206
206
|
});
|
|
207
|
+
|
|
208
|
+
test("--email-username is included in IPC body", async () => {
|
|
209
|
+
mockIpcCallFn = mock(() =>
|
|
210
|
+
Promise.resolve({
|
|
211
|
+
ok: true,
|
|
212
|
+
result: {
|
|
213
|
+
id: "550e8400-e29b-41d4-a716-446655440000",
|
|
214
|
+
domain: "velly.vellum.me",
|
|
215
|
+
status: "active",
|
|
216
|
+
verified: true,
|
|
217
|
+
},
|
|
218
|
+
}),
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
await runDomainCommand(
|
|
222
|
+
"domain",
|
|
223
|
+
"register",
|
|
224
|
+
"velly",
|
|
225
|
+
"--email-username",
|
|
226
|
+
"hello",
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
expect(mockIpcCallFn).toHaveBeenCalledWith("domain_register", {
|
|
230
|
+
body: { subdomain: "velly", email_username: "hello" },
|
|
231
|
+
});
|
|
232
|
+
expect(process.exitCode).toBe(0);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test("email error in response is surfaced as warning", async () => {
|
|
236
|
+
mockIpcCallFn = mock(() =>
|
|
237
|
+
Promise.resolve({
|
|
238
|
+
ok: true,
|
|
239
|
+
result: {
|
|
240
|
+
id: "550e8400-e29b-41d4-a716-446655440000",
|
|
241
|
+
domain: "velly.vellum.me",
|
|
242
|
+
status: "active",
|
|
243
|
+
verified: true,
|
|
244
|
+
email_error: {
|
|
245
|
+
detail: "MX records not ready",
|
|
246
|
+
code: "email_setup_failed",
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
}),
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
await runDomainCommand(
|
|
253
|
+
"domain",
|
|
254
|
+
"register",
|
|
255
|
+
"velly",
|
|
256
|
+
"--email-username",
|
|
257
|
+
"hello",
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
expect(process.exitCode).toBe(0);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("--json includes email_error in output", async () => {
|
|
264
|
+
mockIpcCallFn = mock(() =>
|
|
265
|
+
Promise.resolve({
|
|
266
|
+
ok: true,
|
|
267
|
+
result: {
|
|
268
|
+
id: "550e8400-e29b-41d4-a716-446655440000",
|
|
269
|
+
domain: "velly.vellum.me",
|
|
270
|
+
status: "active",
|
|
271
|
+
verified: true,
|
|
272
|
+
email_error: {
|
|
273
|
+
detail: "MX records not ready",
|
|
274
|
+
code: "email_setup_failed",
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
}),
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
const output = await runDomainCommand(
|
|
281
|
+
"domain",
|
|
282
|
+
"--json",
|
|
283
|
+
"register",
|
|
284
|
+
"velly",
|
|
285
|
+
"--email-username",
|
|
286
|
+
"hello",
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
const parsed = JSON.parse(output.trim());
|
|
290
|
+
expect(parsed.email_error).toEqual({
|
|
291
|
+
detail: "MX records not ready",
|
|
292
|
+
code: "email_setup_failed",
|
|
293
|
+
});
|
|
294
|
+
expect(process.exitCode).toBe(0);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test("without --email-username behavior is unchanged", async () => {
|
|
298
|
+
mockIpcCallFn = mock(() =>
|
|
299
|
+
Promise.resolve({
|
|
300
|
+
ok: true,
|
|
301
|
+
result: {
|
|
302
|
+
id: "550e8400-e29b-41d4-a716-446655440000",
|
|
303
|
+
domain: "velly.vellum.me",
|
|
304
|
+
status: "active",
|
|
305
|
+
verified: true,
|
|
306
|
+
},
|
|
307
|
+
}),
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
await runDomainCommand("domain", "register", "velly");
|
|
311
|
+
|
|
312
|
+
expect(mockIpcCallFn).toHaveBeenCalledWith("domain_register", {
|
|
313
|
+
body: { subdomain: "velly" },
|
|
314
|
+
});
|
|
315
|
+
expect(process.exitCode).toBe(0);
|
|
316
|
+
});
|
|
207
317
|
});
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Tests for the domain status CLI subcommand (thin IPC wrapper).
|
|
3
3
|
*
|
|
4
4
|
* Validates:
|
|
5
|
-
* - status calls domain_status
|
|
5
|
+
* - status calls domain_status then domain_verification_status
|
|
6
6
|
* - --json outputs structured response
|
|
7
|
-
* -
|
|
7
|
+
* - unknown subdomain shows helpful message
|
|
8
8
|
* - error responses are surfaced correctly
|
|
9
9
|
*/
|
|
10
10
|
|
|
@@ -99,15 +99,16 @@ async function runDomainCommand(...args: string[]) {
|
|
|
99
99
|
// status
|
|
100
100
|
// ---------------------------------------------------------------------------
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
Promise.resolve({
|
|
102
|
+
function mockDomainStatusWithVerification() {
|
|
103
|
+
mockIpcCallFn = mock((method: string) => {
|
|
104
|
+
if (method === "domain_status") {
|
|
105
|
+
return Promise.resolve({
|
|
106
106
|
ok: true,
|
|
107
107
|
result: {
|
|
108
108
|
results: [
|
|
109
109
|
{
|
|
110
110
|
id: "550e8400-e29b-41d4-a716-446655440000",
|
|
111
|
+
subdomain: "becky",
|
|
111
112
|
domain: "becky.vellum.me",
|
|
112
113
|
status: "active",
|
|
113
114
|
verified: true,
|
|
@@ -115,38 +116,37 @@ describe("assistant domain status", () => {
|
|
|
115
116
|
},
|
|
116
117
|
],
|
|
117
118
|
},
|
|
118
|
-
})
|
|
119
|
-
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return Promise.resolve({
|
|
122
|
+
ok: true,
|
|
123
|
+
result: {
|
|
124
|
+
domain: "becky.vellum.me",
|
|
125
|
+
status: "verified",
|
|
126
|
+
message: "DNS records have been verified.",
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}) as unknown as typeof mockIpcCallFn;
|
|
130
|
+
}
|
|
120
131
|
|
|
121
|
-
|
|
132
|
+
describe("assistant domain status", () => {
|
|
133
|
+
test("calls domain_status and domain_verification_status", async () => {
|
|
134
|
+
mockDomainStatusWithVerification();
|
|
122
135
|
|
|
123
|
-
|
|
136
|
+
await runDomainCommand("domain", "status", "becky");
|
|
137
|
+
|
|
138
|
+
expect(mockIpcCallFn).toHaveBeenCalledTimes(2);
|
|
124
139
|
expect(process.exitCode).toBe(0);
|
|
125
140
|
});
|
|
126
141
|
|
|
127
142
|
test("--json outputs structured response", async () => {
|
|
128
|
-
|
|
129
|
-
Promise.resolve({
|
|
130
|
-
ok: true,
|
|
131
|
-
result: {
|
|
132
|
-
results: [
|
|
133
|
-
{
|
|
134
|
-
id: "550e8400-e29b-41d4-a716-446655440000",
|
|
135
|
-
domain: "becky.vellum.me",
|
|
136
|
-
status: "active",
|
|
137
|
-
verified: true,
|
|
138
|
-
created_at: "2026-04-15T19:00:00Z",
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
},
|
|
142
|
-
}),
|
|
143
|
-
);
|
|
143
|
+
mockDomainStatusWithVerification();
|
|
144
144
|
|
|
145
|
-
const output = await runDomainCommand("domain", "--json", "status");
|
|
145
|
+
const output = await runDomainCommand("domain", "--json", "status", "becky");
|
|
146
146
|
|
|
147
147
|
const parsed = JSON.parse(output.trim());
|
|
148
|
-
expect(parsed.
|
|
149
|
-
expect(parsed.
|
|
148
|
+
expect(parsed.domain.domain).toBe("becky.vellum.me");
|
|
149
|
+
expect(parsed.verification.status).toBe("verified");
|
|
150
150
|
expect(process.exitCode).toBe(0);
|
|
151
151
|
});
|
|
152
152
|
|
|
@@ -158,8 +158,8 @@ describe("assistant domain status", () => {
|
|
|
158
158
|
}),
|
|
159
159
|
);
|
|
160
160
|
|
|
161
|
-
await runDomainCommand("domain", "status");
|
|
162
|
-
expect(process.exitCode).toBe(
|
|
161
|
+
await runDomainCommand("domain", "status", "becky");
|
|
162
|
+
expect(process.exitCode).toBe(1);
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
test("IPC error with --json outputs error envelope", async () => {
|
|
@@ -171,7 +171,7 @@ describe("assistant domain status", () => {
|
|
|
171
171
|
}),
|
|
172
172
|
) as unknown as typeof mockIpcCallFn;
|
|
173
173
|
|
|
174
|
-
const output = await runDomainCommand("domain", "--json", "status");
|
|
174
|
+
const output = await runDomainCommand("domain", "--json", "status", "becky");
|
|
175
175
|
|
|
176
176
|
expect(process.exitCode).not.toBe(0);
|
|
177
177
|
const parsed = JSON.parse(output.trim());
|
|
@@ -187,7 +187,7 @@ describe("assistant domain status", () => {
|
|
|
187
187
|
}),
|
|
188
188
|
) as unknown as typeof mockIpcCallFn;
|
|
189
189
|
|
|
190
|
-
await runDomainCommand("domain", "status");
|
|
190
|
+
await runDomainCommand("domain", "status", "becky");
|
|
191
191
|
expect(process.exitCode).not.toBe(0);
|
|
192
192
|
});
|
|
193
193
|
});
|