@vellumai/assistant 0.8.5 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +33 -1
- package/ARCHITECTURE.md +1 -1
- package/bunfig.toml +6 -1
- package/docs/credential-execution-service.md +6 -6
- package/docs/plugins.md +4 -3
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
- package/openapi.yaml +1900 -166
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +3 -2
- package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
- package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/annotate-risk-options.test.ts +1 -0
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +9 -13
- package/src/__tests__/assert-not-live-db.ts +79 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +9 -25
- package/src/__tests__/audit-log-rotation.test.ts +2 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
- package/src/__tests__/background-workers-disk-pressure.test.ts +5 -8
- package/src/__tests__/browser-skill-endstate.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +3 -2
- package/src/__tests__/call-controller.test.ts +3 -2
- package/src/__tests__/channel-approval-routes.test.ts +3 -2
- package/src/__tests__/channel-guardian.test.ts +3 -2
- package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
- package/src/__tests__/channel-reply-delivery.test.ts +35 -0
- package/src/__tests__/channel-retry-sweep.test.ts +320 -3
- package/src/__tests__/checker.test.ts +12 -12
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compaction-trail-store.test.ts +264 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +1 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +7 -5
- package/src/__tests__/computer-use-tools.test.ts +12 -14
- package/src/__tests__/config-loader-backfill.test.ts +13 -28
- package/src/__tests__/config-loader-corrupt.test.ts +5 -5
- package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
- package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
- package/src/__tests__/config-schema.test.ts +10 -10
- package/src/__tests__/connection-model-compat.test.ts +83 -0
- package/src/__tests__/contacts-tools.test.ts +3 -2
- package/src/__tests__/context-token-estimator.test.ts +22 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +34 -0
- package/src/__tests__/conversation-agent-loop.test.ts +488 -2
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
- package/src/__tests__/conversation-app-control-instantiation.test.ts +29 -19
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-attention-store.test.ts +101 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-error.test.ts +30 -0
- package/src/__tests__/conversation-fork-crud.test.ts +69 -8
- package/src/__tests__/conversation-fork-route.test.ts +3 -2
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
- package/src/__tests__/conversation-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -0
- package/src/__tests__/conversation-pairing.test.ts +53 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -0
- package/src/__tests__/conversation-queue.test.ts +333 -291
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -18
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
- package/src/__tests__/conversation-routes-slash-commands.test.ts +33 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
- package/src/__tests__/conversation-skill-tools.test.ts +38 -142
- package/src/__tests__/conversation-slash-queue.test.ts +84 -32
- package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
- package/src/__tests__/conversation-sync-tags.test.ts +128 -12
- package/src/__tests__/conversation-title-service.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
- package/src/__tests__/conversation-usage.test.ts +1 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
- package/src/__tests__/credential-broker-server-use.test.ts +5 -5
- package/src/__tests__/credential-execution-client.test.ts +72 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +10 -12
- package/src/__tests__/credential-health-service.test.ts +252 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -5
- package/src/__tests__/credential-vault-unit.test.ts +19 -19
- package/src/__tests__/credential-vault.test.ts +5 -5
- package/src/__tests__/cross-provider-web-search.test.ts +56 -2
- package/src/__tests__/db-connection-isolation.test.ts +7 -6
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
- package/src/__tests__/db-test-helpers.ts +58 -0
- package/src/__tests__/disk-pressure-guard.test.ts +58 -41
- package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
- package/src/__tests__/disk-pressure-routes.test.ts +0 -33
- package/src/__tests__/disk-pressure-tools.test.ts +0 -4
- package/src/__tests__/dm-persistence.test.ts +26 -40
- package/src/__tests__/document-create-dedupe.test.ts +189 -0
- package/src/__tests__/document-find-replace.test.ts +3 -2
- package/src/__tests__/document-tool-security.test.ts +81 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
- package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
- package/src/__tests__/encrypted-store.test.ts +11 -9
- package/src/__tests__/feature-flag-test-helpers.ts +53 -0
- package/src/__tests__/filing-service.test.ts +1 -0
- package/src/__tests__/first-greeting.test.ts +62 -12
- package/src/__tests__/gateway-flag-listener.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +26 -0
- package/src/__tests__/guardian-action-sweep.test.ts +3 -2
- package/src/__tests__/guardian-outbound-http.test.ts +3 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/mock-logger.ts +26 -0
- package/src/__tests__/host-bash-routes.test.ts +1 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-shell-tool.test.ts +5 -4
- package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
- package/src/__tests__/http-conversation-lineage.test.ts +3 -2
- package/src/__tests__/http-user-message-parity.test.ts +29 -7
- package/src/__tests__/identity-intro-cache.test.ts +133 -22
- package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
- package/src/__tests__/inference-profile-reaper.test.ts +3 -2
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
- package/src/__tests__/injector-disk-pressure.test.ts +3 -17
- package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
- package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
- package/src/__tests__/llm-context-normalization.test.ts +42 -0
- package/src/__tests__/llm-resolver.test.ts +331 -0
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
- package/src/__tests__/mcp-abort-signal.test.ts +14 -0
- package/src/__tests__/mcp-client-auth.test.ts +14 -0
- package/src/__tests__/messaging-send-tool.test.ts +1 -0
- package/src/__tests__/migration-import-from-url.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +18 -2
- package/src/__tests__/model-intents.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +30 -2
- package/src/__tests__/notification-deep-link.test.ts +62 -0
- package/src/__tests__/oauth-commands-routes.test.ts +37 -0
- package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
- package/src/__tests__/oauth-store.test.ts +3 -2
- package/src/__tests__/onboarding-template-contract.test.ts +3 -2
- package/src/__tests__/openai-provider.test.ts +8 -9
- package/src/__tests__/openai-responses-provider.test.ts +70 -10
- package/src/__tests__/openrouter-provider-only.test.ts +27 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
- package/src/__tests__/persistence-pipeline.test.ts +139 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
- package/src/__tests__/plugin-bootstrap.test.ts +9 -11
- package/src/__tests__/plugin-tool-contribution.test.ts +41 -38
- package/src/__tests__/process-message-background-slack.test.ts +21 -16
- package/src/__tests__/process-message-display-content.test.ts +19 -22
- package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
- package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
- package/src/__tests__/provider-registry-ollama.test.ts +45 -22
- package/src/__tests__/recording-handler.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +82 -76
- package/src/__tests__/relay-server.test.ts +10 -10
- package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
- package/src/__tests__/schedule-store.test.ts +16 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
- package/src/__tests__/secret-ingress-http.test.ts +5 -1
- package/src/__tests__/secure-keys.test.ts +3 -3
- package/src/__tests__/send-endpoint-busy.test.ts +81 -42
- package/src/__tests__/server-history-render.test.ts +4 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
- package/src/__tests__/skill-feature-flags.test.ts +14 -16
- package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
- package/src/__tests__/skill-projection-feature-flag.test.ts +44 -30
- package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
- package/src/__tests__/skill-tool-factory.test.ts +96 -95
- package/src/__tests__/slack-channel-config.test.ts +3 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
- package/src/__tests__/subagent-disposal.test.ts +27 -8
- package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
- package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
- package/src/__tests__/subagent-manager-notify.test.ts +20 -8
- package/src/__tests__/subagent-notify-parent.test.ts +5 -4
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
- package/src/__tests__/subagent-tools.test.ts +2 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/system-prompt.test.ts +38 -0
- package/src/__tests__/test-preload-verifier.ts +68 -0
- package/src/__tests__/test-preload.ts +32 -39
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +20 -7
- package/src/__tests__/tool-executor.test.ts +55 -10
- package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/twilio-routes.test.ts +3 -2
- package/src/__tests__/validate-input.test.ts +381 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
- package/src/__tests__/voice-session-bridge.test.ts +37 -28
- package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
- package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
- package/src/acp/session-manager.ts +5 -6
- package/src/agent/loop.ts +80 -0
- package/src/api/README.md +124 -2
- package/src/api/constants/call-sites.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +51 -0
- package/src/api/events/assistant-text-delta.ts +32 -0
- package/src/api/events/assistant-turn-start.ts +33 -0
- package/src/api/events/document-comment-created.ts +48 -0
- package/src/api/events/document-comment-deleted.ts +24 -0
- package/src/api/events/document-comment-reopened.ts +25 -0
- package/src/api/events/document-comment-resolved.ts +27 -0
- package/src/api/events/generation-cancelled.ts +24 -0
- package/src/api/events/generation-handoff.ts +41 -0
- package/src/api/events/message-complete.ts +42 -0
- package/src/api/events/open-url.ts +30 -0
- package/src/{events → api/events}/relationship-state-updated.ts +3 -3
- package/src/api/events/tool-use-start.ts +32 -0
- package/src/api/index.ts +128 -3
- package/src/api/responses/llm-context-response.ts +39 -0
- package/src/api/responses/llm-request-log-entry.ts +93 -0
- package/src/api/responses/memory-recall-log.ts +65 -0
- package/src/api/responses/memory-v2-activation-log.ts +78 -0
- package/src/background-wake/background-wake-routes.test.ts +687 -52
- package/src/background-wake/platform-client.test.ts +308 -0
- package/src/background-wake/platform-client.ts +167 -0
- package/src/background-wake/publisher.ts +91 -0
- package/src/background-wake/runtime-registry.ts +2 -2
- package/src/background-wake/wake-intent-hooks.test.ts +282 -0
- package/src/calls/guardian-dispatch.ts +1 -0
- package/src/calls/voice-session-bridge.ts +4 -4
- package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
- package/src/cli/commands/__tests__/notifications.test.ts +184 -40
- package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
- package/src/cli/commands/channels/index.ts +229 -0
- package/src/cli/commands/memory-v3-render.ts +147 -0
- package/src/cli/commands/memory-v3.ts +255 -4
- package/src/cli/commands/notifications.ts +365 -55
- package/src/cli/lib/open-browser.ts +7 -2
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +23 -42
- package/src/config/bundled-skills/document-editor/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
- package/src/config/call-site-defaults.ts +1 -1
- package/src/config/feature-flag-cache.ts +86 -0
- package/src/config/feature-flag-registry.json +17 -17
- package/src/config/llm-context-resolution.ts +10 -1
- package/src/config/llm-resolver.ts +121 -15
- package/src/config/loader.ts +4 -5
- package/src/config/schemas/__tests__/memory-v2.test.ts +15 -0
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +90 -1
- package/src/config/schemas/memory-v2.ts +26 -0
- package/src/config/schemas/services.ts +6 -2
- package/src/config/seed-inference-profiles.ts +36 -16
- package/src/context/token-estimator.ts +10 -5
- package/src/credential-execution/executable-discovery.ts +40 -0
- package/src/credential-execution/process-manager.ts +6 -2
- package/src/credential-health/credential-health-service.ts +125 -40
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -2
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +389 -68
- package/src/daemon/conversation-agent-loop.ts +132 -28
- package/src/daemon/conversation-error.ts +33 -5
- package/src/daemon/conversation-messaging.ts +84 -43
- package/src/daemon/conversation-process.ts +74 -37
- package/src/daemon/conversation-runtime-assembly.ts +29 -9
- package/src/daemon/conversation-skill-tools.ts +14 -30
- package/src/daemon/conversation-surfaces.ts +69 -34
- package/src/daemon/conversation-tool-setup.ts +33 -48
- package/src/daemon/conversation.ts +26 -46
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/daemon-skill-host.ts +9 -2
- package/src/daemon/disk-pressure-guard.ts +27 -29
- package/src/daemon/first-greeting.ts +31 -13
- package/src/daemon/handlers/shared.ts +6 -1
- package/src/daemon/lifecycle.ts +12 -12
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/meet-manifest-loader.ts +10 -17
- package/src/daemon/message-types/conversations.ts +20 -22
- package/src/daemon/message-types/document-comments.ts +8 -44
- package/src/daemon/message-types/home.ts +2 -2
- package/src/daemon/message-types/integrations.ts +2 -7
- package/src/daemon/message-types/messages.ts +23 -38
- package/src/daemon/message-types/subagents.ts +6 -0
- package/src/daemon/process-message.ts +9 -9
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +16 -0
- package/src/daemon/switch-inference-profile-tool.ts +13 -3
- package/src/daemon/tool-setup-types.ts +0 -6
- package/src/daemon/wake-target-adapter.ts +10 -0
- package/src/documents/document-store.ts +38 -0
- package/src/export/__tests__/transcript-formatter.test.ts +1 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -0
- package/src/heartbeat/heartbeat-service.ts +63 -0
- package/src/home/__tests__/feed-writer.test.ts +161 -0
- package/src/home/__tests__/post-connect-feed.test.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +55 -59
- package/src/home/feed-writer.ts +146 -7
- package/src/home/suggested-prompts.ts +27 -145
- package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
- package/src/ipc/gateway-client.test.ts +4 -1
- package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
- package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
- package/src/ipc/skill-routes/memory.ts +4 -3
- package/src/ipc/skill-routes/registries.ts +28 -29
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +1 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
- package/src/memory/conversation-attention-store.ts +17 -3
- package/src/memory/conversation-crud.ts +352 -112
- package/src/memory/db-connection.ts +29 -19
- package/src/memory/db-init.ts +4 -0
- package/src/memory/db-singleton.ts +77 -0
- package/src/memory/delivery-channels.ts +82 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
- package/src/memory/graph/retriever.test.ts +3 -3
- package/src/memory/job-handlers/embedding.test.ts +3 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
- package/src/memory/jobs-worker.ts +12 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +80 -0
- package/src/memory/llm-request-log-source-local.ts +24 -0
- package/src/memory/llm-request-log-source.ts +31 -0
- package/src/memory/llm-request-log-store.ts +188 -3
- package/src/memory/memory-v2-activation-log-store.ts +95 -1
- package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
- package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/schema/conversations.ts +9 -1
- package/src/memory/schema/inference.ts +0 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
- package/src/memory/v2/__tests__/harness-metrics.test.ts +9 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +9 -4
- package/src/memory/v2/__tests__/harness-runner.test.ts +26 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
- package/src/memory/v2/harness/metrics.ts +5 -1
- package/src/memory/v2/harness/replay-input.ts +19 -3
- package/src/memory/v2/harness/runner.ts +6 -0
- package/src/memory/v2/harness/trace.ts +6 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +2 -4
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
- package/src/memory/v3/__tests__/edges.test.ts +144 -1
- package/src/memory/v3/__tests__/filter.test.ts +48 -0
- package/src/memory/v3/__tests__/gate.test.ts +96 -33
- package/src/memory/v3/__tests__/index-composition.test.ts +58 -0
- package/src/memory/v3/__tests__/loop.test.ts +250 -5
- package/src/memory/v3/__tests__/scouts.test.ts +49 -0
- package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +88 -2
- package/src/memory/v3/__tests__/traversal.test.ts +39 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +77 -0
- package/src/memory/v3/__tests__/validate.test.ts +32 -0
- package/src/memory/v3/coretrieval-seed.ts +240 -0
- package/src/memory/v3/edges.ts +58 -21
- package/src/memory/v3/filter.ts +27 -22
- package/src/memory/v3/gate.ts +51 -36
- package/src/memory/v3/index-composition.ts +18 -5
- package/src/memory/v3/loop.ts +65 -17
- package/src/memory/v3/scouts.ts +15 -4
- package/src/memory/v3/shadow-diff.ts +287 -0
- package/src/memory/v3/shadow-middleware.ts +44 -2
- package/src/memory/v3/traversal.ts +6 -1
- package/src/memory/v3/tree-walk.ts +6 -1
- package/src/memory/v3/validate.ts +56 -33
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
- package/src/notifications/adapters/slack.ts +45 -11
- package/src/notifications/broadcaster.ts +114 -63
- package/src/notifications/conversation-pairing.ts +23 -3
- package/src/notifications/decisions-store.ts +32 -1
- package/src/notifications/deliveries-store.ts +45 -0
- package/src/notifications/edit-notification.ts +201 -0
- package/src/notifications/emit-signal.ts +11 -1
- package/src/notifications/signal.ts +10 -0
- package/src/notifications/types.ts +37 -0
- package/src/oauth/byo-connection.test.ts +67 -3
- package/src/oauth/byo-connection.ts +32 -5
- package/src/oauth/connect-orchestrator.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +76 -0
- package/src/oauth/connection-resolver.ts +49 -10
- package/src/oauth/manual-token-connection.ts +51 -3
- package/src/oauth/seed-providers.ts +3 -0
- package/src/permissions/approval-policy.test.ts +19 -5
- package/src/permissions/approval-policy.ts +14 -3
- package/src/permissions/checker.ts +21 -8
- package/src/platform/client.test.ts +24 -1
- package/src/platform/client.ts +8 -0
- package/src/platform/feature-gate.ts +15 -0
- package/src/plugins/defaults/injectors.ts +2 -8
- package/src/plugins/defaults/persistence.ts +25 -6
- package/src/plugins/types.ts +57 -13
- package/src/proactive-artifact/job.test.ts +1 -0
- package/src/prompts/__tests__/system-prompt.test.ts +4 -4
- package/src/prompts/system-prompt.ts +38 -40
- package/src/prompts/template-detection.ts +10 -4
- package/src/prompts/templates/BOOTSTRAP.md +7 -11
- package/src/prompts/templates/IDENTITY.md +0 -2
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -4
- package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
- package/src/providers/call-site-routing.ts +33 -9
- package/src/providers/connection-model-compat.ts +23 -0
- package/src/providers/connection-resolution.ts +39 -20
- package/src/providers/fireworks/client.ts +1 -0
- package/src/providers/gemini/client.ts +24 -3
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
- package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
- package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
- package/src/providers/inference/auth.ts +0 -8
- package/src/providers/inference/connections.ts +3 -66
- package/src/providers/inference/resolve-auth.ts +2 -3
- package/src/providers/model-catalog.ts +35 -1
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
- package/src/providers/openai/chat-completions-provider.ts +110 -12
- package/src/providers/openai/codex-models.ts +2 -0
- package/src/providers/openai/responses-provider.ts +53 -53
- package/src/providers/openrouter/client.ts +13 -8
- package/src/providers/provider-send-message.ts +18 -9
- package/src/providers/registry.ts +48 -8
- package/src/providers/retry.ts +16 -4
- package/src/providers/search-provider-catalog.ts +17 -9
- package/src/providers/types.ts +9 -0
- package/src/runtime/__tests__/agent-wake.test.ts +1 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
- package/src/runtime/access-request-helper.ts +1 -0
- package/src/runtime/auth/route-policy.ts +10 -0
- package/src/runtime/channel-readiness-service.ts +68 -0
- package/src/runtime/channel-reply-delivery.ts +23 -0
- package/src/runtime/channel-retry-sweep.ts +47 -14
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/migrations/vbundle-builder.ts +3 -2
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +51 -3
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
- package/src/runtime/routes/acp-routes-list.test.ts +3 -0
- package/src/runtime/routes/app-management-routes.ts +111 -4
- package/src/runtime/routes/background-wake-routes.ts +188 -20
- package/src/runtime/routes/btw-routes.ts +4 -4
- package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
- package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
- package/src/runtime/routes/conversation-list-routes.ts +147 -0
- package/src/runtime/routes/conversation-management-routes.ts +39 -14
- package/src/runtime/routes/conversation-query-routes.ts +60 -10
- package/src/runtime/routes/conversation-routes.ts +186 -140
- package/src/runtime/routes/conversations-import-routes.ts +19 -6
- package/src/runtime/routes/documents-routes.ts +10 -1
- package/src/runtime/routes/group-routes.ts +11 -0
- package/src/runtime/routes/home-feed-routes.ts +129 -0
- package/src/runtime/routes/identity-intro-cache.ts +61 -16
- package/src/runtime/routes/identity-routes.ts +30 -9
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
- package/src/runtime/routes/integrations/vercel.ts +15 -0
- package/src/runtime/routes/llm-context-normalization.ts +7 -2
- package/src/runtime/routes/memory-v3-routes.ts +160 -2
- package/src/runtime/routes/migration-routes.ts +20 -13
- package/src/runtime/routes/notification-routes.ts +63 -1
- package/src/runtime/routes/oauth-commands-routes.ts +6 -1
- package/src/runtime/routes/surface-action-routes.ts +1 -38
- package/src/runtime/routes/surface-content-routes.ts +12 -5
- package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
- package/src/runtime/slack-dm-text-delivery.ts +177 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -1
- package/src/runtime/tool-grant-request-helper.ts +1 -0
- package/src/schedule/schedule-store.ts +8 -1
- package/src/schedule/scheduler.ts +111 -15
- package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
- package/src/security/encrypted-store.ts +7 -16
- package/src/security/store-path-override.ts +61 -0
- package/src/signals/user-message.ts +5 -8
- package/src/skills/validate-input.ts +177 -0
- package/src/subagent/manager.ts +13 -13
- package/src/subagent/types.ts +6 -0
- package/src/tasks/tool-sanitizer.ts +2 -2
- package/src/tools/apps/definitions.ts +35 -21
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
- package/src/tools/computer-use/definitions.ts +268 -266
- package/src/tools/document/document-tool.ts +131 -8
- package/src/tools/execution-target.ts +2 -5
- package/src/tools/executor.ts +18 -55
- package/src/tools/host-filesystem/edit.test.ts +1 -0
- package/src/tools/host-filesystem/read.test.ts +1 -0
- package/src/tools/host-filesystem/transfer.test.ts +31 -6
- package/src/tools/host-filesystem/write.test.ts +1 -0
- package/src/tools/mcp/mcp-tool-factory.ts +0 -2
- package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
- package/src/tools/network/__tests__/web-search.test.ts +211 -3
- package/src/tools/network/managed-search-proxy.ts +183 -0
- package/src/tools/network/web-search.ts +199 -44
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/registry.ts +146 -103
- package/src/tools/schedule/create.ts +1 -1
- package/src/tools/skills/skill-tool-factory.ts +17 -36
- package/src/tools/subagent/spawn.ts +3 -0
- package/src/tools/tool-approval-handler.ts +10 -4
- package/src/tools/tool-name-aliases.ts +72 -14
- package/src/tools/types.ts +17 -15
- package/src/tools/ui-surface/definitions.ts +98 -86
- package/src/types/onboarding-context.ts +6 -0
- package/src/usage/attribution.ts +32 -1
- package/src/util/browser.ts +7 -2
- package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
- package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
- package/src/workspace/migrations/registry.ts +4 -0
|
@@ -1,19 +1,77 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
type ToolInputNormalizer = (
|
|
2
|
+
input: Record<string, unknown>,
|
|
3
|
+
) => Record<string, unknown>;
|
|
4
|
+
|
|
5
|
+
const TOOL_NAME_ALIASES = new Map<
|
|
6
|
+
string,
|
|
7
|
+
{ canonicalName: string; normalizeInput?: ToolInputNormalizer }
|
|
8
|
+
>([
|
|
9
|
+
["create_app", { canonicalName: "app_create" }],
|
|
10
|
+
[
|
|
11
|
+
"computer_use_press_key",
|
|
12
|
+
{
|
|
13
|
+
canonicalName: "computer_use_key",
|
|
14
|
+
normalizeInput: normalizeLegacyComputerUsePressKeyInput,
|
|
15
|
+
},
|
|
16
|
+
],
|
|
3
17
|
]);
|
|
4
18
|
|
|
5
|
-
|
|
6
|
-
* Resolve high-confidence compatibility aliases before active-tool gating.
|
|
7
|
-
* Keep this list narrow: aliases should only cover observed model drift where
|
|
8
|
-
* the canonical target is active for the turn.
|
|
9
|
-
*/
|
|
10
|
-
export function resolveToolNameAlias(
|
|
19
|
+
export function resolveToolInvocationAlias(
|
|
11
20
|
name: string,
|
|
21
|
+
input: Record<string, unknown>,
|
|
12
22
|
allowedToolNames?: ReadonlySet<string>,
|
|
13
|
-
): string {
|
|
14
|
-
if (allowedToolNames?.has(name)) return name;
|
|
15
|
-
const
|
|
16
|
-
if (!
|
|
17
|
-
if (allowedToolNames && !allowedToolNames.has(
|
|
18
|
-
|
|
23
|
+
): { name: string; input: Record<string, unknown> } {
|
|
24
|
+
if (allowedToolNames?.has(name)) return { name, input };
|
|
25
|
+
const alias = TOOL_NAME_ALIASES.get(name);
|
|
26
|
+
if (!alias) return { name, input };
|
|
27
|
+
if (allowedToolNames && !allowedToolNames.has(alias.canonicalName)) {
|
|
28
|
+
return { name, input };
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
name: alias.canonicalName,
|
|
32
|
+
input: alias.normalizeInput ? alias.normalizeInput(input) : input,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizeLegacyComputerUsePressKeyInput(
|
|
37
|
+
input: Record<string, unknown>,
|
|
38
|
+
): Record<string, unknown> {
|
|
39
|
+
const normalized = { ...input };
|
|
40
|
+
const key = typeof normalized.key === "string" ? normalized.key.trim() : "";
|
|
41
|
+
const modifiers = Array.isArray(normalized.modifiers)
|
|
42
|
+
? normalized.modifiers.flatMap((modifier) => {
|
|
43
|
+
if (typeof modifier !== "string") return [];
|
|
44
|
+
const normalizedModifier = normalizeKeyModifier(modifier);
|
|
45
|
+
return normalizedModifier ? [normalizedModifier] : [];
|
|
46
|
+
})
|
|
47
|
+
: [];
|
|
48
|
+
|
|
49
|
+
delete normalized.modifiers;
|
|
50
|
+
|
|
51
|
+
if (key && modifiers.length > 0 && !key.includes("+")) {
|
|
52
|
+
normalized.key = [...new Set(modifiers), key.toLowerCase()].join("+");
|
|
53
|
+
} else if (key && !key.includes("+")) {
|
|
54
|
+
normalized.key = key.toLowerCase();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return normalized;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function normalizeKeyModifier(modifier: string): string | undefined {
|
|
61
|
+
switch (modifier.trim().toLowerCase()) {
|
|
62
|
+
case "cmd":
|
|
63
|
+
case "command":
|
|
64
|
+
case "meta":
|
|
65
|
+
return "cmd";
|
|
66
|
+
case "ctrl":
|
|
67
|
+
case "control":
|
|
68
|
+
return "ctrl";
|
|
69
|
+
case "option":
|
|
70
|
+
case "alt":
|
|
71
|
+
return "option";
|
|
72
|
+
case "shift":
|
|
73
|
+
return "shift";
|
|
74
|
+
default:
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
19
77
|
}
|
package/src/tools/types.ts
CHANGED
|
@@ -338,22 +338,24 @@ export interface ToolDefinition {
|
|
|
338
338
|
}
|
|
339
339
|
|
|
340
340
|
/** Tool after the loader has derived its name and filled defaults. */
|
|
341
|
-
export type LoadedTool = Required<ToolDefinition> & {
|
|
341
|
+
export type LoadedTool = Required<ToolDefinition> & {
|
|
342
|
+
name: string;
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
/** The kind of extension that owns a tool. Core tools have no owner. */
|
|
346
|
+
export type OwnerKind = "skill" | "mcp" | "plugin";
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Identifies which extension owns a tool (skill / plugin / MCP server).
|
|
350
|
+
* Tracked by the tool registry keyed by tool name, not stored on the `Tool`
|
|
351
|
+
* object itself — query via {@link ../tools/registry.getToolOwner}.
|
|
352
|
+
*/
|
|
353
|
+
export interface OwnerInfo {
|
|
354
|
+
kind: OwnerKind;
|
|
355
|
+
/** ID of the owning extension (skill id / plugin name / MCP server id). */
|
|
356
|
+
id: string;
|
|
357
|
+
}
|
|
342
358
|
|
|
343
359
|
export interface Tool extends LoadedTool {
|
|
344
360
|
category: string;
|
|
345
|
-
/** When set to 'proxy', the tool is forwarded to a connected client rather than executed locally. */
|
|
346
|
-
executionMode?: "local" | "proxy";
|
|
347
|
-
/** Whether this tool is a core built-in, provided by a skill, contributed by a plugin, or from an MCP server. */
|
|
348
|
-
origin?: "core" | "skill" | "mcp" | "plugin";
|
|
349
|
-
/** If origin is 'skill', the ID of the owning skill. */
|
|
350
|
-
ownerSkillId?: string;
|
|
351
|
-
/** If origin is 'mcp', the ID of the owning MCP server. */
|
|
352
|
-
ownerMcpServerId?: string;
|
|
353
|
-
/** If origin is 'plugin', the name of the owning plugin. */
|
|
354
|
-
ownerPluginId?: string;
|
|
355
|
-
/** Content-hash of the owning skill's source at registration time. */
|
|
356
|
-
ownerSkillVersionHash?: string;
|
|
357
|
-
/** Whether the owning skill is bundled with the daemon (trusted first-party). */
|
|
358
|
-
ownerSkillBundled?: boolean;
|
|
359
361
|
}
|
|
@@ -8,16 +8,31 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { RiskLevel } from "../../permissions/types.js";
|
|
11
|
-
import type { Tool, ToolExecutionResult } from "../types.js";
|
|
11
|
+
import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
|
|
12
12
|
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
// Helpers
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Forward execution to the connected macOS client via the request-bound
|
|
19
|
+
* `proxyToolResolver`. Returns a structured error when no resolver is
|
|
20
|
+
* configured (e.g. no client connected) so callers see a normal tool
|
|
21
|
+
* failure rather than an unhandled throw.
|
|
22
|
+
*/
|
|
23
|
+
function proxyExecute(toolName: string) {
|
|
24
|
+
return async (
|
|
25
|
+
input: Record<string, unknown>,
|
|
26
|
+
context: ToolContext,
|
|
27
|
+
): Promise<ToolExecutionResult> => {
|
|
28
|
+
if (!context.proxyToolResolver) {
|
|
29
|
+
return {
|
|
30
|
+
content: `No proxy resolver configured for proxy tool "${toolName}". This tool requires an external resolver (e.g. a connected macOS client).`,
|
|
31
|
+
isError: true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return context.proxyToolResolver(toolName, input);
|
|
35
|
+
};
|
|
21
36
|
}
|
|
22
37
|
|
|
23
38
|
// ---------------------------------------------------------------------------
|
|
@@ -40,73 +55,72 @@ export const uiShowTool: Tool = {
|
|
|
40
55
|
"Proactively show a task_progress card before multi-step or long-running work (web searches, file operations, research). Show it before your first tool call, then update steps as work progresses.",
|
|
41
56
|
category: "ui-surface",
|
|
42
57
|
defaultRiskLevel: RiskLevel.Low,
|
|
43
|
-
executionMode: "proxy",
|
|
44
58
|
executionTarget: "host",
|
|
45
59
|
|
|
46
60
|
input_schema: {
|
|
61
|
+
type: "object",
|
|
62
|
+
properties: {
|
|
63
|
+
surface_type: {
|
|
64
|
+
type: "string",
|
|
65
|
+
enum: [
|
|
66
|
+
"card",
|
|
67
|
+
"form",
|
|
68
|
+
"list",
|
|
69
|
+
"table",
|
|
70
|
+
"confirmation",
|
|
71
|
+
"dynamic_page",
|
|
72
|
+
"file_upload",
|
|
73
|
+
"task_preferences",
|
|
74
|
+
],
|
|
75
|
+
description: "The type of surface to display",
|
|
76
|
+
},
|
|
77
|
+
title: {
|
|
78
|
+
type: "string",
|
|
79
|
+
description: "Optional title for the surface window",
|
|
80
|
+
},
|
|
81
|
+
data: {
|
|
47
82
|
type: "object",
|
|
48
|
-
|
|
49
|
-
surface_type
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
title: {
|
|
64
|
-
type: "string",
|
|
65
|
-
description: "Optional title for the surface window",
|
|
66
|
-
},
|
|
67
|
-
data: {
|
|
68
|
-
type: "object",
|
|
69
|
-
description:
|
|
70
|
-
"Surface data; structure depends on surface_type (see tool description)",
|
|
71
|
-
},
|
|
72
|
-
actions: {
|
|
73
|
-
type: "array",
|
|
74
|
-
items: {
|
|
75
|
-
type: "object",
|
|
76
|
-
properties: {
|
|
77
|
-
id: { type: "string", description: "Unique action identifier" },
|
|
78
|
-
label: { type: "string", description: "Button label text" },
|
|
79
|
-
style: {
|
|
80
|
-
type: "string",
|
|
81
|
-
enum: ["primary", "secondary", "destructive"],
|
|
82
|
-
description: "Visual style of the button",
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
required: ["id", "label"],
|
|
83
|
+
description:
|
|
84
|
+
"Surface data; structure depends on surface_type (see tool description)",
|
|
85
|
+
},
|
|
86
|
+
actions: {
|
|
87
|
+
type: "array",
|
|
88
|
+
items: {
|
|
89
|
+
type: "object",
|
|
90
|
+
properties: {
|
|
91
|
+
id: { type: "string", description: "Unique action identifier" },
|
|
92
|
+
label: { type: "string", description: "Button label text" },
|
|
93
|
+
style: {
|
|
94
|
+
type: "string",
|
|
95
|
+
enum: ["primary", "secondary", "destructive"],
|
|
96
|
+
description: "Visual style of the button",
|
|
86
97
|
},
|
|
87
|
-
description: "Optional action buttons to display on the surface",
|
|
88
|
-
},
|
|
89
|
-
display: {
|
|
90
|
-
type: "string",
|
|
91
|
-
enum: ["inline", "panel"],
|
|
92
|
-
description:
|
|
93
|
-
'Where to render the surface. "inline" embeds it in the chat message. "panel" shows a floating window. Defaults to "inline". Prefer inline — only use panel when a separate window is explicitly requested.',
|
|
94
|
-
},
|
|
95
|
-
await_action: {
|
|
96
|
-
type: "boolean",
|
|
97
|
-
description:
|
|
98
|
-
"Whether to block until an action is selected. Defaults to true when actions are provided.",
|
|
99
|
-
},
|
|
100
|
-
persistent: {
|
|
101
|
-
type: "boolean",
|
|
102
|
-
description:
|
|
103
|
-
"When true, clicking an action does not dismiss the surface — the card stays visible and only the clicked action is marked as spent. Use for launcher or menu-style cards where multiple buttons may be clicked. Defaults to false.",
|
|
104
98
|
},
|
|
99
|
+
required: ["id", "label"],
|
|
105
100
|
},
|
|
106
|
-
|
|
101
|
+
description: "Optional action buttons to display on the surface",
|
|
107
102
|
},
|
|
103
|
+
display: {
|
|
104
|
+
type: "string",
|
|
105
|
+
enum: ["inline", "panel"],
|
|
106
|
+
description:
|
|
107
|
+
'Where to render the surface. "inline" embeds it in the chat message. "panel" shows a floating window. Defaults to "inline". Prefer inline — only use panel when a separate window is explicitly requested.',
|
|
108
|
+
},
|
|
109
|
+
await_action: {
|
|
110
|
+
type: "boolean",
|
|
111
|
+
description:
|
|
112
|
+
"Whether to block until an action is selected. Defaults to true when actions are provided.",
|
|
113
|
+
},
|
|
114
|
+
persistent: {
|
|
115
|
+
type: "boolean",
|
|
116
|
+
description:
|
|
117
|
+
"When true, clicking an action does not dismiss the surface — the card stays visible and only the clicked action is marked as spent. Use for launcher or menu-style cards where multiple buttons may be clicked. Defaults to false.",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
required: ["surface_type", "data"],
|
|
121
|
+
},
|
|
108
122
|
|
|
109
|
-
execute: proxyExecute,
|
|
123
|
+
execute: proxyExecute("ui_show"),
|
|
110
124
|
};
|
|
111
125
|
|
|
112
126
|
// ---------------------------------------------------------------------------
|
|
@@ -120,25 +134,24 @@ const uiUpdateTool: Tool = {
|
|
|
120
134
|
"For card templates (for example `task_progress`), update nested fields under `data.templateData` rather than sending template fields at the top level.",
|
|
121
135
|
category: "ui-surface",
|
|
122
136
|
defaultRiskLevel: RiskLevel.Low,
|
|
123
|
-
executionMode: "proxy",
|
|
124
137
|
executionTarget: "host",
|
|
125
138
|
|
|
126
139
|
input_schema: {
|
|
140
|
+
type: "object",
|
|
141
|
+
properties: {
|
|
142
|
+
surface_id: {
|
|
143
|
+
type: "string",
|
|
144
|
+
description: "The ID of the surface to update",
|
|
145
|
+
},
|
|
146
|
+
data: {
|
|
127
147
|
type: "object",
|
|
128
|
-
|
|
129
|
-
surface_id: {
|
|
130
|
-
type: "string",
|
|
131
|
-
description: "The ID of the surface to update",
|
|
132
|
-
},
|
|
133
|
-
data: {
|
|
134
|
-
type: "object",
|
|
135
|
-
description: "Partial data to merge into the existing surface data",
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
required: ["surface_id", "data"],
|
|
148
|
+
description: "Partial data to merge into the existing surface data",
|
|
139
149
|
},
|
|
150
|
+
},
|
|
151
|
+
required: ["surface_id", "data"],
|
|
152
|
+
},
|
|
140
153
|
|
|
141
|
-
execute: proxyExecute,
|
|
154
|
+
execute: proxyExecute("ui_update"),
|
|
142
155
|
};
|
|
143
156
|
|
|
144
157
|
// ---------------------------------------------------------------------------
|
|
@@ -150,21 +163,20 @@ const uiDismissTool: Tool = {
|
|
|
150
163
|
description: "Dismiss a currently displayed surface.",
|
|
151
164
|
category: "ui-surface",
|
|
152
165
|
defaultRiskLevel: RiskLevel.Low,
|
|
153
|
-
executionMode: "proxy",
|
|
154
166
|
executionTarget: "host",
|
|
155
167
|
|
|
156
168
|
input_schema: {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
required: ["surface_id"],
|
|
169
|
+
type: "object",
|
|
170
|
+
properties: {
|
|
171
|
+
surface_id: {
|
|
172
|
+
type: "string",
|
|
173
|
+
description: "The ID of the surface to dismiss",
|
|
165
174
|
},
|
|
175
|
+
},
|
|
176
|
+
required: ["surface_id"],
|
|
177
|
+
},
|
|
166
178
|
|
|
167
|
-
execute: proxyExecute,
|
|
179
|
+
execute: proxyExecute("ui_dismiss"),
|
|
168
180
|
};
|
|
169
181
|
|
|
170
182
|
export const allUiSurfaceTools: Tool[] = [
|
|
@@ -10,4 +10,10 @@ export interface OnboardingContext {
|
|
|
10
10
|
cohort?: string;
|
|
11
11
|
websiteUrl?: string;
|
|
12
12
|
contentSourceUrl?: string;
|
|
13
|
+
/** Filename of the bootstrap template to use (e.g. "BOOTSTRAP-CONTENT-AUTOMATION.md"). When set, replaces generic BOOTSTRAP.md if still pristine. */
|
|
14
|
+
bootstrapTemplate?: string;
|
|
15
|
+
/** Override the first user message content. When set during a wake-up greeting, this replaces the canned greeting. */
|
|
16
|
+
initialMessage?: string;
|
|
17
|
+
/** Skills to eagerly load on first turn (e.g. ["geo-writing", "document-editor"]). Informational — the bootstrap template drives actual loading. */
|
|
18
|
+
skills?: string[];
|
|
13
19
|
}
|
package/src/usage/attribution.ts
CHANGED
|
@@ -15,6 +15,14 @@ export type UsageAttributionProfileSource =
|
|
|
15
15
|
export interface UsageAttributionInput {
|
|
16
16
|
callSite: LLMCallSite | null;
|
|
17
17
|
overrideProfile?: string | null;
|
|
18
|
+
/**
|
|
19
|
+
* Per-conversation seed for `mix`-profile expansion (the conversation id).
|
|
20
|
+
* When the applied profile is a mix, threading the same seed the dispatch
|
|
21
|
+
* path uses ensures `resolvedModel`/`resolvedMixArm` reflect the arm the
|
|
22
|
+
* request actually ran on. Omitted by one-shot callers (the snapshot's
|
|
23
|
+
* `resolvedMixArm` is then null even if a mix was involved).
|
|
24
|
+
*/
|
|
25
|
+
selectionSeed?: string;
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
export interface UsageAttributionSnapshot {
|
|
@@ -26,6 +34,12 @@ export interface UsageAttributionSnapshot {
|
|
|
26
34
|
profileSource: UsageAttributionProfileSource;
|
|
27
35
|
resolvedProvider: string;
|
|
28
36
|
resolvedModel: string;
|
|
37
|
+
/**
|
|
38
|
+
* When `appliedProfile` is a mix profile, the constituent arm chosen for
|
|
39
|
+
* this request; null otherwise. Lets A/B analysis attribute usage to the
|
|
40
|
+
* specific arm (mix name lives in `appliedProfile`).
|
|
41
|
+
*/
|
|
42
|
+
resolvedMixArm: string | null;
|
|
29
43
|
}
|
|
30
44
|
|
|
31
45
|
/**
|
|
@@ -51,7 +65,11 @@ export function resolveUsageAttribution(
|
|
|
51
65
|
const overrideProfile = normalizeProfileId(input.overrideProfile);
|
|
52
66
|
|
|
53
67
|
if (callSite == null) {
|
|
54
|
-
const resolvedMainAgent = resolveCallSiteConfig("mainAgent", llm
|
|
68
|
+
const resolvedMainAgent = resolveCallSiteConfig("mainAgent", llm, {
|
|
69
|
+
...(input.selectionSeed != null
|
|
70
|
+
? { selectionSeed: input.selectionSeed }
|
|
71
|
+
: {}),
|
|
72
|
+
});
|
|
55
73
|
return {
|
|
56
74
|
callSite: null,
|
|
57
75
|
activeProfile: normalizeProfileId(llm.activeProfile),
|
|
@@ -61,11 +79,20 @@ export function resolveUsageAttribution(
|
|
|
61
79
|
profileSource: "unknown",
|
|
62
80
|
resolvedProvider: resolvedMainAgent.provider,
|
|
63
81
|
resolvedModel: resolvedMainAgent.model,
|
|
82
|
+
resolvedMixArm: null,
|
|
64
83
|
};
|
|
65
84
|
}
|
|
66
85
|
|
|
86
|
+
// Capture which arm each expanded mix resolved to so we can attribute usage
|
|
87
|
+
// to the arm behind the applied (mix) profile below.
|
|
88
|
+
const mixSelections = new Map<string, string>();
|
|
67
89
|
const resolved = resolveCallSiteConfig(callSite, llm, {
|
|
68
90
|
...(overrideProfile != null ? { overrideProfile } : {}),
|
|
91
|
+
...(input.selectionSeed != null
|
|
92
|
+
? { selectionSeed: input.selectionSeed }
|
|
93
|
+
: {}),
|
|
94
|
+
onMixSelected: ({ mixProfile, chosenProfile }) =>
|
|
95
|
+
mixSelections.set(mixProfile, chosenProfile),
|
|
69
96
|
});
|
|
70
97
|
const activeProfile = normalizeProfileId(llm.activeProfile);
|
|
71
98
|
const callSiteProfile = normalizeProfileId(
|
|
@@ -88,6 +115,10 @@ export function resolveUsageAttribution(
|
|
|
88
115
|
profileSource: profile.profileSource,
|
|
89
116
|
resolvedProvider: resolved.provider,
|
|
90
117
|
resolvedModel: resolved.model,
|
|
118
|
+
resolvedMixArm:
|
|
119
|
+
profile.appliedProfile != null
|
|
120
|
+
? (mixSelections.get(profile.appliedProfile) ?? null)
|
|
121
|
+
: null,
|
|
91
122
|
};
|
|
92
123
|
}
|
|
93
124
|
|
package/src/util/browser.ts
CHANGED
|
@@ -10,8 +10,13 @@ const log = getLogger("browser");
|
|
|
10
10
|
* Open a URL on the user's host machine.
|
|
11
11
|
*
|
|
12
12
|
* Writes an `open_url` event to the `signals/emit-event` file so that the
|
|
13
|
-
*
|
|
14
|
-
* (e.g. the Swift macOS app) via the assistant event hub.
|
|
13
|
+
* assistant's ConfigWatcher picks it up and publishes it to connected
|
|
14
|
+
* clients (e.g. the Swift macOS app) via the assistant event hub.
|
|
15
|
+
*
|
|
16
|
+
* CLI-initiated emit — no conversation context available, so the inner
|
|
17
|
+
* message has no `conversationId`. That's fine: `OpenUrlEventSchema`
|
|
18
|
+
* declares `conversationId` as optional, so this payload parses
|
|
19
|
+
* cleanly on the web side as well as in the Swift macOS app.
|
|
15
20
|
*/
|
|
16
21
|
export async function openInHostBrowser(url: string): Promise<void> {
|
|
17
22
|
try {
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
5
|
+
|
|
6
|
+
// Flip callSites.memoryRouter from { profile: "balanced" } (the shape that
|
|
7
|
+
// migration 087 wrote) to the shipped cost-optimized default so the router
|
|
8
|
+
// rides the workspace's cheaper/faster managed profile.
|
|
9
|
+
//
|
|
10
|
+
// The migrated entry must mirror the shipped default in call-site-defaults.ts
|
|
11
|
+
// EXACTLY — { profile: "cost-optimized", contextWindow: { maxInputTokens:
|
|
12
|
+
// 1_000_000 } } — because the resolver prefers an explicit
|
|
13
|
+
// llm.callSites.memoryRouter entry over CALL_SITE_DEFAULTS. Writing a bare
|
|
14
|
+
// { profile: "cost-optimized" } would drop the 1M input window and regress
|
|
15
|
+
// migrated users to the profile's normal ~200k window.
|
|
16
|
+
//
|
|
17
|
+
// The shipped default in call-site-defaults.ts also moves to cost-optimized
|
|
18
|
+
// in the same change; this migration is what gets existing users — who carry
|
|
19
|
+
// an explicit { profile: "balanced" } in their config.json — onto the new
|
|
20
|
+
// default. Workspaces with no memoryRouter entry already pick up the shipped
|
|
21
|
+
// default automatically (e.g. BYOK installs that skipped 077/087, or fresh
|
|
22
|
+
// installs), so this migration only touches the 087-seeded balanced shape and
|
|
23
|
+
// the bare { profile: "cost-optimized" } shape an earlier (pre-fix) run of
|
|
24
|
+
// this migration may have written — the latter so those users also recover
|
|
25
|
+
// the 1M window.
|
|
26
|
+
//
|
|
27
|
+
// Two skip conditions, mirroring 087:
|
|
28
|
+
//
|
|
29
|
+
// 1. BYOK / non-Anthropic workspaces. `cost-optimized` is a managed
|
|
30
|
+
// Anthropic profile, which off-platform installs disable. Forcing it
|
|
31
|
+
// there would make getConfiguredProvider("memoryRouter") return null
|
|
32
|
+
// and silently disable memory injection. Detect via llm.default.provider.
|
|
33
|
+
//
|
|
34
|
+
// 2. User-customized memoryRouter config. If the existing entry carries any
|
|
35
|
+
// key beyond a bare balanced/cost-optimized profile reference, the user —
|
|
36
|
+
// or a platform overlay — chose those values deliberately. Preserve them.
|
|
37
|
+
const MEMORY_ROUTER_COST_OPTIMIZED = {
|
|
38
|
+
profile: "cost-optimized",
|
|
39
|
+
contextWindow: { maxInputTokens: 1_000_000 },
|
|
40
|
+
} as const;
|
|
41
|
+
|
|
42
|
+
export const memoryRouterCostOptimizedProfileMigration: WorkspaceMigration = {
|
|
43
|
+
id: "090-memory-router-cost-optimized-profile",
|
|
44
|
+
description:
|
|
45
|
+
"Set callSites.memoryRouter to the shipped cost-optimized default (with 1M context) for workspaces still carrying the 087-seeded balanced profile",
|
|
46
|
+
run(workspaceDir: string): void {
|
|
47
|
+
if (process.env.VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH) return;
|
|
48
|
+
|
|
49
|
+
const configPath = join(workspaceDir, "config.json");
|
|
50
|
+
if (!existsSync(configPath)) return;
|
|
51
|
+
|
|
52
|
+
let config: Record<string, unknown> = {};
|
|
53
|
+
try {
|
|
54
|
+
const raw = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
55
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
|
|
56
|
+
config = raw as Record<string, unknown>;
|
|
57
|
+
} catch {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const llm = readObject(config.llm);
|
|
62
|
+
if (llm === null) return;
|
|
63
|
+
|
|
64
|
+
const explicitProvider = readString(readObject(llm.default)?.provider);
|
|
65
|
+
if (explicitProvider !== undefined && explicitProvider !== "anthropic") {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const callSites = readObject(llm.callSites);
|
|
70
|
+
if (callSites === null) return;
|
|
71
|
+
|
|
72
|
+
const existing = readObject(callSites.memoryRouter);
|
|
73
|
+
if (existing === null || !needsCostOptimizedUpgrade(existing)) return;
|
|
74
|
+
|
|
75
|
+
callSites.memoryRouter = { ...MEMORY_ROUTER_COST_OPTIMIZED };
|
|
76
|
+
llm.callSites = callSites;
|
|
77
|
+
config.llm = llm;
|
|
78
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
79
|
+
},
|
|
80
|
+
down(_workspaceDir: string): void {
|
|
81
|
+
// Forward-only.
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// True when the entry is a bare single-key profile reference we own:
|
|
86
|
+
// - { profile: "balanced" } — what migration 087 wrote
|
|
87
|
+
// - { profile: "cost-optimized" } — what a pre-fix run of THIS migration
|
|
88
|
+
// wrote (no contextWindow), so those users
|
|
89
|
+
// still recover the 1M window
|
|
90
|
+
// Any extra keys (model pins, tuning fields, an already-present contextWindow)
|
|
91
|
+
// mean the user/platform customized it — preserve and skip. This keeps the
|
|
92
|
+
// migration idempotent: once it writes the full cost-optimized + contextWindow
|
|
93
|
+
// shape, the two-key entry no longer matches.
|
|
94
|
+
function needsCostOptimizedUpgrade(entry: Record<string, unknown>): boolean {
|
|
95
|
+
const keys = Object.keys(entry);
|
|
96
|
+
if (keys.length !== 1) return false;
|
|
97
|
+
return entry.profile === "balanced" || entry.profile === "cost-optimized";
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function readObject(value: unknown): Record<string, unknown> | null {
|
|
101
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return value as Record<string, unknown>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function readString(value: unknown): string | undefined {
|
|
108
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
109
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import type { MigrationRunContext, WorkspaceMigration } from "./types.js";
|
|
5
|
+
|
|
6
|
+
// The exact onboarding bullet seeded by 069-seed-onboarding-threads for the
|
|
7
|
+
// assistant-migration step. Inlined here (not imported) to keep this migration
|
|
8
|
+
// self-contained and decoupled from 069.
|
|
9
|
+
const OLD_BULLET =
|
|
10
|
+
"- Ask your user if they use ChatGPT, Claude or another AI tool and offer to help them import memories from there.";
|
|
11
|
+
|
|
12
|
+
// The tightened replacement: help-first, an early light one-time offer, naming
|
|
13
|
+
// the common prior assistants. Keeps the literal "ChatGPT, Claude" substring.
|
|
14
|
+
const NEW_BULLET =
|
|
15
|
+
"- After helping with the user's first real task, offer early — at the first natural opening — to port their context, memories, prompts, skills, or workflows from a prior assistant (ChatGPT, Claude, OpenClaw, Hermes, or another tool). Keep it a light one-time offer, not a push; if they decline, drop it.";
|
|
16
|
+
|
|
17
|
+
export const retightenMigrationOnboardingThreadMigration: WorkspaceMigration = {
|
|
18
|
+
id: "091-retighten-migration-onboarding-thread",
|
|
19
|
+
description:
|
|
20
|
+
"Retighten the assistant-migration onboarding bullet in memory/threads.md for brand new assistants",
|
|
21
|
+
|
|
22
|
+
run(workspaceDir: string, ctx?: MigrationRunContext): void {
|
|
23
|
+
// Only rewrite onboarding tasks for newly-created workspaces. An existing
|
|
24
|
+
// assistant whose user has edited threads.md must not have its content
|
|
25
|
+
// rewritten on upgrade. When invoked without a context (e.g. from older
|
|
26
|
+
// callers), default to the safe path and skip — the runner always supplies
|
|
27
|
+
// one in production.
|
|
28
|
+
if (!ctx?.isNewWorkspace) return;
|
|
29
|
+
const filePath = join(workspaceDir, "memory", "threads.md");
|
|
30
|
+
if (!existsSync(filePath)) return;
|
|
31
|
+
const content = readFileSync(filePath, "utf-8");
|
|
32
|
+
// Idempotent: if the old bullet is absent (already replaced, or the user
|
|
33
|
+
// edited it away), there is nothing to do.
|
|
34
|
+
if (!content.includes(OLD_BULLET)) return;
|
|
35
|
+
writeFileSync(filePath, content.replace(OLD_BULLET, NEW_BULLET), "utf-8");
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
down(_workspaceDir: string): void {
|
|
39
|
+
// Forward-only: never rewrite user-visible memory content on rollback.
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -87,6 +87,8 @@ import { revertStaleGeminiMisRewritesMigration } from "./086-revert-stale-gemini
|
|
|
87
87
|
import { memoryRouterBalancedProfileMigration } from "./087-memory-router-balanced-profile.js";
|
|
88
88
|
import { deprecateBackgroundConversationOverrideMigration } from "./088-deprecate-background-conversation-override.js";
|
|
89
89
|
import { moveMemoryTreeOutOfV3Migration } from "./089-move-memory-tree-out-of-v3.js";
|
|
90
|
+
import { memoryRouterCostOptimizedProfileMigration } from "./090-memory-router-cost-optimized-profile.js";
|
|
91
|
+
import { retightenMigrationOnboardingThreadMigration } from "./091-retighten-migration-onboarding-thread.js";
|
|
90
92
|
import { migrateToWorkspaceVolumeMigration } from "./migrate-to-workspace-volume.js";
|
|
91
93
|
import type { WorkspaceMigration } from "./types.js";
|
|
92
94
|
|
|
@@ -185,4 +187,6 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
|
|
|
185
187
|
memoryRouterBalancedProfileMigration,
|
|
186
188
|
deprecateBackgroundConversationOverrideMigration,
|
|
187
189
|
moveMemoryTreeOutOfV3Migration,
|
|
190
|
+
memoryRouterCostOptimizedProfileMigration,
|
|
191
|
+
retightenMigrationOnboardingThreadMigration,
|
|
188
192
|
];
|