@vellumai/assistant 0.8.3 → 0.8.4
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/docker-entrypoint.sh +0 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +610 -16
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +272 -0
- package/src/__tests__/approval-cascade.test.ts +1 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/channel-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/compaction-events.test.ts +1 -1
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/context-token-estimator.test.ts +91 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +54 -3
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +31 -6
- package/src/__tests__/conversation-agent-loop.test.ts +25 -7
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +161 -0
- package/src/__tests__/conversation-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-load-cleaned-at.test.ts +279 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +6 -0
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/first-greeting.test.ts +23 -2
- package/src/__tests__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/injector-chain.test.ts +2 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +17 -16
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-resolver.test.ts +85 -1
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/openai-provider.test.ts +105 -0
- package/src/__tests__/openai-responses-provider.test.ts +4 -4
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +190 -0
- package/src/__tests__/platform.test.ts +0 -3
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- package/src/__tests__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- package/src/__tests__/server-history-render.test.ts +83 -4
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/system-prompt.test.ts +51 -28
- package/src/__tests__/terminal-tools.test.ts +11 -1
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- package/src/__tests__/tool-executor.test.ts +90 -1
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +88 -5
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +57 -20
- package/src/background-wake/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/browser/operations.ts +15 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +9 -12
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/inference-providers.ts +147 -1
- package/src/cli/commands/memory-v2.ts +308 -0
- package/src/cli/commands/notifications.ts +24 -2
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/SKILL.md +115 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +240 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
- package/src/config/bundled-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +22 -12
- package/src/config/call-site-defaults.ts +19 -0
- package/src/config/feature-flag-registry.json +99 -3
- package/src/config/llm-resolver.ts +16 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +4 -0
- package/src/config/schemas/call-site-catalog.ts +21 -0
- package/src/config/schemas/llm.ts +3 -0
- package/src/config/schemas/memory-v2.ts +48 -1
- package/src/context/compactor.ts +8 -1
- package/src/context/token-estimator.ts +47 -4
- package/src/context/window-manager.ts +25 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +153 -23
- package/src/daemon/conversation-agent-loop.ts +223 -54
- package/src/daemon/conversation-lifecycle.ts +142 -116
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +135 -75
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +7 -0
- package/src/daemon/conversation.ts +42 -5
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/config-a2a.ts +160 -0
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +79 -0
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-transfer-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +18 -4
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +8 -0
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/messages.ts +68 -1
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +69 -12
- package/src/daemon/query-complexity-router.ts +75 -0
- package/src/daemon/trust-context.ts +6 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +6 -1
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +94 -0
- package/src/home/suggested-prompts.ts +177 -9
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +320 -6
- package/src/memory/conversation-crud.ts +133 -43
- package/src/memory/db-init.ts +16 -0
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- package/src/memory/jobs-worker.ts +21 -1
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +3 -2
- package/src/memory/memory-retrospective-job.ts +408 -18
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +26 -8
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- package/src/memory/migrations/index.ts +17 -0
- package/src/memory/migrations/registry.ts +25 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +31 -14
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/router.test.ts +489 -1
- package/src/memory/v2/consolidation-job.ts +14 -0
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +21 -10
- package/src/memory/v2/page-index.ts +209 -7
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/router.ts +209 -55
- package/src/messaging/providers/index.ts +7 -1
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/emit-signal.ts +9 -1
- package/src/notifications/home-feed-side-effect.ts +60 -30
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +4 -1
- package/src/plugins/defaults/injectors.ts +82 -9
- package/src/prompts/__tests__/system-prompt.test.ts +46 -2
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/sections.ts +32 -14
- package/src/prompts/system-prompt.ts +105 -68
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +8 -0
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +53 -3
- package/src/providers/anthropic/client.ts +132 -5
- package/src/providers/fireworks/client.ts +20 -2
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/adapter-factory.ts +15 -1
- package/src/providers/inference/auth.ts +3 -3
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/resolve-auth.ts +49 -6
- package/src/providers/model-catalog.ts +48 -1
- package/src/providers/openai/chat-completions-provider.ts +57 -20
- package/src/providers/openai/responses-provider.ts +9 -3
- package/src/providers/openrouter/client.ts +5 -1
- package/src/providers/types.ts +25 -0
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +151 -56
- package/src/runtime/auth/route-policy.ts +7 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-types.ts +7 -4
- package/src/runtime/pending-interactions.ts +51 -8
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +55 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +271 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/approval-routes.ts +4 -1
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +146 -1
- package/src/runtime/routes/conversation-query-routes.ts +60 -1
- package/src/runtime/routes/conversation-routes.ts +281 -76
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +8 -1
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +12 -4
- package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
- package/src/runtime/routes/integrations/a2a.ts +60 -1
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-v2-routes.ts +217 -0
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/sanity-routes.ts +159 -0
- package/src/runtime/routes/slack-channel-routes.ts +187 -0
- package/src/runtime/services/conversation-serializer.ts +30 -4
- package/src/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +80 -0
- package/src/tools/browser/browser-execution.ts +93 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +1 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +10 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +15 -1
- package/src/tools/browser/cdp-client/factory.ts +87 -3
- package/src/tools/browser/cdp-client/local-cdp-client.ts +9 -0
- package/src/tools/browser/cdp-client/types.ts +36 -0
- package/src/tools/browser/pinned-tabs.ts +90 -0
- package/src/tools/document/document-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +128 -2
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +213 -64
- package/src/tools/network/web-search.ts +191 -66
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/types.ts +4 -0
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/types/onboarding-context.ts +4 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/platform.ts +0 -5
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
"description": "Automatically trigger conversation analysis on the same cadence as memory extraction (batch threshold, idle debounce, end-of-conversation). The analysis agent has full tool access and writes back to memory and skills without user approval.",
|
|
10
10
|
"defaultEnabled": false
|
|
11
11
|
},
|
|
12
|
+
{
|
|
13
|
+
"id": "memory-retrospective-fork",
|
|
14
|
+
"scope": "assistant",
|
|
15
|
+
"key": "memory-retrospective-fork",
|
|
16
|
+
"label": "Fork-based memory retrospective",
|
|
17
|
+
"description": "Fork the source conversation through its latest message for memory retrospectives, instead of rendering the slice into a transcript and waking an empty background conversation. Lets the retrospective hit the provider prompt cache and read compaction summary + tail messages natively.",
|
|
18
|
+
"defaultEnabled": false
|
|
19
|
+
},
|
|
12
20
|
{
|
|
13
21
|
"id": "user-hosted-enabled",
|
|
14
22
|
"scope": "client",
|
|
@@ -43,7 +51,7 @@
|
|
|
43
51
|
},
|
|
44
52
|
{
|
|
45
53
|
"id": "settings-developer-nav",
|
|
46
|
-
"scope": "
|
|
54
|
+
"scope": "assistant",
|
|
47
55
|
"key": "settings-developer-nav",
|
|
48
56
|
"label": "Settings Developer Nav",
|
|
49
57
|
"description": "Control Developer nav visibility in macOS settings",
|
|
@@ -89,6 +97,14 @@
|
|
|
89
97
|
"description": "Surface credential grant and audit inspection endpoints for reviewing active grants and access logs",
|
|
90
98
|
"defaultEnabled": false
|
|
91
99
|
},
|
|
100
|
+
{
|
|
101
|
+
"id": "chatgpt-subscription-auth",
|
|
102
|
+
"scope": "assistant",
|
|
103
|
+
"key": "chatgpt-subscription-auth",
|
|
104
|
+
"label": "ChatGPT Subscription Auth",
|
|
105
|
+
"description": "Enable ChatGPT subscription OAuth as a provider auth type for OpenAI models, using the Codex device-code flow.",
|
|
106
|
+
"defaultEnabled": false
|
|
107
|
+
},
|
|
92
108
|
{
|
|
93
109
|
"id": "deploy-to-vercel",
|
|
94
110
|
"scope": "assistant",
|
|
@@ -275,7 +291,7 @@
|
|
|
275
291
|
},
|
|
276
292
|
{
|
|
277
293
|
"id": "account-deletion",
|
|
278
|
-
"scope": "
|
|
294
|
+
"scope": "assistant",
|
|
279
295
|
"key": "account-deletion",
|
|
280
296
|
"label": "Account Deletion",
|
|
281
297
|
"description": "Surfaces the user-initiated account deletion flow in client settings.",
|
|
@@ -299,7 +315,7 @@
|
|
|
299
315
|
},
|
|
300
316
|
{
|
|
301
317
|
"id": "pro-plan-adjust",
|
|
302
|
-
"scope": "
|
|
318
|
+
"scope": "client",
|
|
303
319
|
"key": "pro-plan-adjust",
|
|
304
320
|
"label": "Pro Plan Adjust",
|
|
305
321
|
"description": "Show the rich Plan card (current plan, features, Manage/Upgrade CTA) at the top of the macOS Settings \u2192 Billing tab.",
|
|
@@ -328,6 +344,86 @@
|
|
|
328
344
|
"label": "Velvet Theme",
|
|
329
345
|
"description": "Show the Velvet theme option in the macOS appearance settings. Velvet is a dark-mode variant with red/pink accent colors.",
|
|
330
346
|
"defaultEnabled": false
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"id": "query-complexity-routing",
|
|
350
|
+
"scope": "assistant",
|
|
351
|
+
"key": "query-complexity-routing",
|
|
352
|
+
"label": "Query Complexity Routing",
|
|
353
|
+
"description": "Automatically route user messages to the most appropriate inference profile based on query complexity. Simple queries use the speed profile, complex queries escalate to the quality profile. The user is notified of each switch and can opt out by pinning a profile on the conversation.",
|
|
354
|
+
"defaultEnabled": false
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
"id": "queue-steering",
|
|
358
|
+
"scope": "assistant",
|
|
359
|
+
"key": "queue-steering",
|
|
360
|
+
"label": "Queue Steering",
|
|
361
|
+
"description": "Enable the 'Push to agent' button on queued messages, allowing users to steer the assistant to a specific queued message by aborting the current generation and promoting the message to the head of the queue.",
|
|
362
|
+
"defaultEnabled": false
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"id": "chat-pull-to-refresh-enabled",
|
|
366
|
+
"scope": "client",
|
|
367
|
+
"key": "chat-pull-to-refresh-enabled",
|
|
368
|
+
"label": "Chat Pull to Refresh",
|
|
369
|
+
"description": "Enable pull-to-refresh gesture in the chat view.",
|
|
370
|
+
"defaultEnabled": false
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"id": "doctor",
|
|
374
|
+
"scope": "client",
|
|
375
|
+
"key": "doctor",
|
|
376
|
+
"label": "Doctor",
|
|
377
|
+
"description": "Enable the Doctor diagnostic tab in Debug settings.",
|
|
378
|
+
"defaultEnabled": false
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
"id": "home-page",
|
|
382
|
+
"scope": "client",
|
|
383
|
+
"key": "home-page",
|
|
384
|
+
"label": "Home Page",
|
|
385
|
+
"description": "Enable the Home page as the default landing view.",
|
|
386
|
+
"defaultEnabled": false
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"id": "platform-notifications",
|
|
390
|
+
"scope": "client",
|
|
391
|
+
"key": "platform-notifications",
|
|
392
|
+
"label": "Platform Notifications",
|
|
393
|
+
"description": "Enable the Notifications tab in settings.",
|
|
394
|
+
"defaultEnabled": false
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
"id": "rollback-enabled",
|
|
398
|
+
"scope": "assistant",
|
|
399
|
+
"key": "rollback-enabled",
|
|
400
|
+
"label": "Rollback Enabled",
|
|
401
|
+
"description": "Show older versions in the version picker, allowing rollback to previous releases.",
|
|
402
|
+
"defaultEnabled": false
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
"id": "self-hosted-assistant",
|
|
406
|
+
"scope": "client",
|
|
407
|
+
"key": "self-hosted-assistant",
|
|
408
|
+
"label": "Self-Hosted Assistant",
|
|
409
|
+
"description": "Enable self-hosted assistant configuration.",
|
|
410
|
+
"defaultEnabled": false
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"id": "settings-sleep-policy",
|
|
414
|
+
"scope": "assistant",
|
|
415
|
+
"key": "settings-sleep-policy",
|
|
416
|
+
"label": "Settings Sleep Policy",
|
|
417
|
+
"description": "Enable sleep policy settings.",
|
|
418
|
+
"defaultEnabled": false
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
"id": "velvet",
|
|
422
|
+
"scope": "client",
|
|
423
|
+
"key": "velvet",
|
|
424
|
+
"label": "Velvet",
|
|
425
|
+
"description": "Enable the Velvet design theme.",
|
|
426
|
+
"defaultEnabled": false
|
|
331
427
|
}
|
|
332
428
|
]
|
|
333
429
|
}
|
|
@@ -81,13 +81,27 @@ export function resolveCallSiteConfig(
|
|
|
81
81
|
type Mergeable = Record<string, unknown>;
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* Returns the
|
|
85
|
-
*
|
|
84
|
+
* Returns the effective default profile key the resolver would actually
|
|
85
|
+
* select for a call site when no per-turn `overrideProfile` is supplied.
|
|
86
|
+
*
|
|
87
|
+
* Mirrors the layering in `resolveCallSiteConfig`:
|
|
88
|
+
* - For `mainAgent`, the workspace's `activeProfile` sits ABOVE the
|
|
89
|
+
* call-site catalog default (and above any static `llm.callSites.mainAgent`
|
|
90
|
+
* override), so a non-disabled `activeProfile` wins.
|
|
91
|
+
* - For other call sites, the catalog default sits ABOVE `activeProfile`,
|
|
92
|
+
* so the catalog default (with `custom-*` fallback) wins.
|
|
86
93
|
*/
|
|
87
94
|
export function resolveDefaultProfileKey(
|
|
88
95
|
callSite: LLMCallSite,
|
|
89
96
|
llm: z.infer<typeof LLMSchema>,
|
|
90
97
|
): string | undefined {
|
|
98
|
+
if (callSite === "mainAgent" && llm.activeProfile != null) {
|
|
99
|
+
const active = llm.profiles?.[llm.activeProfile];
|
|
100
|
+
if (active != null && active.status !== "disabled") {
|
|
101
|
+
return llm.activeProfile;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
91
105
|
const dflt = CALL_SITE_DEFAULTS[callSite];
|
|
92
106
|
if (dflt?.profile == null) return undefined;
|
|
93
107
|
const target = llm.profiles?.[dflt.profile];
|
|
@@ -23,6 +23,7 @@ describe("MemoryV2ConfigSchema", () => {
|
|
|
23
23
|
bm25_k1: 1.2,
|
|
24
24
|
bm25_b: 0.4,
|
|
25
25
|
consolidation_interval_hours: 4,
|
|
26
|
+
consolidation_max_buffer_lines: 100,
|
|
26
27
|
max_page_chars: 5000,
|
|
27
28
|
consolidation_prompt_path: null,
|
|
28
29
|
rerank: {
|
|
@@ -36,6 +37,9 @@ describe("MemoryV2ConfigSchema", () => {
|
|
|
36
37
|
enabled: true,
|
|
37
38
|
max_page_ids: 25,
|
|
38
39
|
router_prompt_path: null,
|
|
40
|
+
batch_size: null,
|
|
41
|
+
tier1_size: null,
|
|
42
|
+
tier2_size: null,
|
|
39
43
|
},
|
|
40
44
|
});
|
|
41
45
|
});
|
|
@@ -300,6 +300,27 @@ const CATALOG_RECORD: CatalogRecord = {
|
|
|
300
300
|
"Builds the personalized artifact in a background conversation with tool access.",
|
|
301
301
|
domain: "agentLoop",
|
|
302
302
|
},
|
|
303
|
+
homeGreeting: {
|
|
304
|
+
id: "homeGreeting",
|
|
305
|
+
displayName: "Home Greeting",
|
|
306
|
+
description:
|
|
307
|
+
"Generates the personalized greeting shown on the Home page in the assistant's tone/persona.",
|
|
308
|
+
domain: "ui",
|
|
309
|
+
},
|
|
310
|
+
homeSuggestedPrompts: {
|
|
311
|
+
id: "homeSuggestedPrompts",
|
|
312
|
+
displayName: "Home Suggested Prompts",
|
|
313
|
+
description:
|
|
314
|
+
"Generates contextual conversation-starter suggestions for the Home page.",
|
|
315
|
+
domain: "ui",
|
|
316
|
+
},
|
|
317
|
+
queryComplexityRouter: {
|
|
318
|
+
id: "queryComplexityRouter",
|
|
319
|
+
displayName: "Query Complexity Router",
|
|
320
|
+
description:
|
|
321
|
+
"Classifies user message complexity to route to the appropriate inference profile.",
|
|
322
|
+
domain: "agentLoop",
|
|
323
|
+
},
|
|
303
324
|
};
|
|
304
325
|
|
|
305
326
|
// Source of truth for call-site display metadata. API responses and usage
|
|
@@ -76,6 +76,9 @@ export const LLMCallSiteEnum = z.enum([
|
|
|
76
76
|
"trustRuleSuggestion",
|
|
77
77
|
"proactiveArtifactDecision",
|
|
78
78
|
"proactiveArtifactBuild",
|
|
79
|
+
"homeGreeting",
|
|
80
|
+
"homeSuggestedPrompts",
|
|
81
|
+
"queryComplexityRouter",
|
|
79
82
|
]);
|
|
80
83
|
export type LLMCallSite = z.infer<typeof LLMCallSiteEnum>;
|
|
81
84
|
|
|
@@ -194,6 +194,19 @@ export const MemoryV2ConfigSchema = z
|
|
|
194
194
|
.describe(
|
|
195
195
|
"Hours between scheduled consolidation runs that synthesize buffered memories into concept pages",
|
|
196
196
|
),
|
|
197
|
+
consolidation_max_buffer_lines: z
|
|
198
|
+
.number({
|
|
199
|
+
error: "memory.v2.consolidation_max_buffer_lines must be a number",
|
|
200
|
+
})
|
|
201
|
+
.int("memory.v2.consolidation_max_buffer_lines must be an integer")
|
|
202
|
+
.positive(
|
|
203
|
+
"memory.v2.consolidation_max_buffer_lines must be a positive integer",
|
|
204
|
+
)
|
|
205
|
+
.nullable()
|
|
206
|
+
.default(100)
|
|
207
|
+
.describe(
|
|
208
|
+
"Size-based trigger for consolidation. When `memory/buffer.md` reaches this many non-empty lines, consolidation runs even if the time-based interval hasn't elapsed. Defaults to 100. Set to `null` to disable the size trigger and rely solely on `consolidation_interval_hours`.",
|
|
209
|
+
),
|
|
197
210
|
max_page_chars: z
|
|
198
211
|
.number({ error: "memory.v2.max_page_chars must be a number" })
|
|
199
212
|
.int("memory.v2.max_page_chars must be an integer")
|
|
@@ -282,8 +295,42 @@ export const MemoryV2ConfigSchema = z
|
|
|
282
295
|
.describe(
|
|
283
296
|
"Optional path to a file whose contents replace the bundled router prompt. Absolute paths are used as-is, a leading `~/` is expanded to the home directory, otherwise the path is resolved under the workspace root. The loaded contents may include `{{ASSISTANT_NAME}}`, `{{USER_NAME}}`, and `{{PAGE_INDEX}}`, which are substituted at runtime. If the file is missing, unreadable, or empty, the bundled prompt is used and a warning is logged.",
|
|
284
297
|
),
|
|
298
|
+
batch_size: z
|
|
299
|
+
.number()
|
|
300
|
+
.int()
|
|
301
|
+
.min(1)
|
|
302
|
+
.nullable()
|
|
303
|
+
.default(null)
|
|
304
|
+
.describe(
|
|
305
|
+
"Target batch size for parallel page-index routing. `null` (default) sends the entire page index in one call — identical to v3 behavior. When set, pages are split into `ceil(N / batch_size)` batches by stable FNV-1a hash on slug (so adding/removing a single page only invalidates one batch's KV cache), routed in parallel, and the selected slugs are unioned. A failure in one batch does not abort the turn as long as at least one batch succeeds.",
|
|
306
|
+
),
|
|
307
|
+
tier1_size: z
|
|
308
|
+
.number()
|
|
309
|
+
.int()
|
|
310
|
+
.min(1)
|
|
311
|
+
.nullable()
|
|
312
|
+
.default(null)
|
|
313
|
+
.describe(
|
|
314
|
+
"Pool size for the tier-1 'recently modified' batch. `null` (default) disables tier 1 entirely — all pages flow through tier 3 batching. When set, the top-N concept pages by file mtime become their own dedicated parallel batch with mtime-desc ordering; everything else is partitioned into tier 3 batches by `batch_size`. Synthetic entries (skills, CLI commands) have mtime=0 and naturally rank below real concept pages so they don't crowd tier 1.",
|
|
315
|
+
),
|
|
316
|
+
tier2_size: z
|
|
317
|
+
.number()
|
|
318
|
+
.int()
|
|
319
|
+
.min(1)
|
|
320
|
+
.nullable()
|
|
321
|
+
.default(null)
|
|
322
|
+
.describe(
|
|
323
|
+
"Pool size for the tier-2 'useful' batch. `null` (default) disables tier 2 — pages skip straight from tier 1 to tier 3. When set, the top-M pages by injection-frequency EMA (excluding tier 1) become their own parallel batch ordered by score desc. Pages with score 0 (never selected since EMA tracking began) are ineligible for tier 2 and stay in tier 3 regardless of `tier2_size`. Score is the time-decayed sum `Σ exp(-λ(now - tᵢ))` with 3-day half-life, computed on read from `memory_v2_injection_events`.",
|
|
324
|
+
),
|
|
325
|
+
})
|
|
326
|
+
.default({
|
|
327
|
+
enabled: true,
|
|
328
|
+
max_page_ids: 25,
|
|
329
|
+
router_prompt_path: null,
|
|
330
|
+
batch_size: null,
|
|
331
|
+
tier1_size: null,
|
|
332
|
+
tier2_size: null,
|
|
285
333
|
})
|
|
286
|
-
.default({ enabled: true, max_page_ids: 25, router_prompt_path: null })
|
|
287
334
|
.describe(
|
|
288
335
|
"LLM router configuration. When enabled, a single router LLM call replaces spreading activation for per-turn page selection.",
|
|
289
336
|
),
|
package/src/context/compactor.ts
CHANGED
|
@@ -155,6 +155,11 @@ export interface CompactionRunResult {
|
|
|
155
155
|
thresholdTokens: number;
|
|
156
156
|
compactedMessages: number;
|
|
157
157
|
compactedPersistedMessages: number;
|
|
158
|
+
/**
|
|
159
|
+
* Number of recent ("tail") messages preserved verbatim alongside the
|
|
160
|
+
* summary. Omitted on no-op / skipped results — defaults to 0 at render.
|
|
161
|
+
*/
|
|
162
|
+
preservedTailMessages?: number;
|
|
158
163
|
summaryCalls: number;
|
|
159
164
|
summaryInputTokens: number;
|
|
160
165
|
summaryOutputTokens: number;
|
|
@@ -327,7 +332,7 @@ export function renderImageManifest(entries: ManifestEntry[]): string {
|
|
|
327
332
|
* runtime emitted — typically
|
|
328
333
|
* `2026-04-02 (Thursday) 01:52:33 -05:00 (America/Chicago)`).
|
|
329
334
|
*/
|
|
330
|
-
function extractTurnContextTimestamp(message: Message): string | null {
|
|
335
|
+
export function extractTurnContextTimestamp(message: Message): string | null {
|
|
331
336
|
if (message.role !== "user") return null;
|
|
332
337
|
for (const block of message.content) {
|
|
333
338
|
if (block.type !== "text") continue;
|
|
@@ -841,6 +846,7 @@ export async function runAssistantDrivenCompaction(
|
|
|
841
846
|
thresholdTokens,
|
|
842
847
|
compactedMessages: compactableMessages.length,
|
|
843
848
|
compactedPersistedMessages,
|
|
849
|
+
preservedTailMessages: args.messages.length - tailIndex,
|
|
844
850
|
summaryCalls: 1,
|
|
845
851
|
summaryInputTokens: response.usage.inputTokens,
|
|
846
852
|
summaryOutputTokens: response.usage.outputTokens,
|
|
@@ -1090,6 +1096,7 @@ export async function runEmergencyCompaction(
|
|
|
1090
1096
|
thresholdTokens,
|
|
1091
1097
|
compactedMessages: compactedCount,
|
|
1092
1098
|
compactedPersistedMessages: Math.max(0, compactedCount - nonPersistedAway),
|
|
1099
|
+
preservedTailMessages: keptTail.length,
|
|
1093
1100
|
summaryCalls: 1,
|
|
1094
1101
|
summaryInputTokens: response.usage.inputTokens,
|
|
1095
1102
|
summaryOutputTokens: response.usage.outputTokens,
|
|
@@ -52,6 +52,24 @@ const IMAGE_MAX_PIXELS = 1_200_000;
|
|
|
52
52
|
const IMAGE_TOKENS_PER_PIXEL = 1 / 750;
|
|
53
53
|
const IMAGE_MAX_TOKENS = 1_600;
|
|
54
54
|
|
|
55
|
+
// Gemini prices images differently: any side ≤384px counts as a single 258-token
|
|
56
|
+
// tile; anything larger is resized so the longest side is ≤3072px and then
|
|
57
|
+
// split into 768x768 tiles at 258 tokens each. A 4000x4000 image clamps to
|
|
58
|
+
// 3072x3072 → ceil(3072/768)^2 = 16 tiles = 4,128 tokens. Without the clamp
|
|
59
|
+
// we'd over-count it as 36 tiles (~9,288 tokens) and trigger spurious
|
|
60
|
+
// compaction. The clamped 16-tile, 4,128-token figure is also the per-image
|
|
61
|
+
// ceiling we fall back to when dimensions are unparseable (e.g. HEIC/HEIF
|
|
62
|
+
// from iOS attachments) — the generic 1,600 cap can under-count Gemini
|
|
63
|
+
// images by ~2.5x.
|
|
64
|
+
// See: https://ai.google.dev/gemini-api/docs/tokens#multimodal-tokens
|
|
65
|
+
const GEMINI_IMAGE_SMALL_THRESHOLD = 384;
|
|
66
|
+
const GEMINI_IMAGE_TILE_SIZE = 768;
|
|
67
|
+
const GEMINI_IMAGE_TOKENS_PER_TILE = 258;
|
|
68
|
+
const GEMINI_IMAGE_MAX_DIMENSION = 3072;
|
|
69
|
+
const GEMINI_IMAGE_MAX_TOKENS =
|
|
70
|
+
Math.ceil(GEMINI_IMAGE_MAX_DIMENSION / GEMINI_IMAGE_TILE_SIZE) ** 2 *
|
|
71
|
+
GEMINI_IMAGE_TOKENS_PER_TILE;
|
|
72
|
+
|
|
55
73
|
// Anthropic renders each PDF page as an image (~1,568 tokens at standard
|
|
56
74
|
// resolution) plus any extracted text. Typical PDF pages are 50-150 KB.
|
|
57
75
|
// Using ~100 KB/page and ~1,600 tokens/page gives ~0.016 tokens/byte.
|
|
@@ -129,16 +147,41 @@ function estimateImageTokensByDimensions(
|
|
|
129
147
|
return Math.ceil(scaledWidth * scaledHeight * IMAGE_TOKENS_PER_PIXEL);
|
|
130
148
|
}
|
|
131
149
|
|
|
150
|
+
function estimateGeminiImageTokens(width: number, height: number): number {
|
|
151
|
+
if (
|
|
152
|
+
width <= GEMINI_IMAGE_SMALL_THRESHOLD &&
|
|
153
|
+
height <= GEMINI_IMAGE_SMALL_THRESHOLD
|
|
154
|
+
) {
|
|
155
|
+
return GEMINI_IMAGE_TOKENS_PER_TILE;
|
|
156
|
+
}
|
|
157
|
+
// Gemini resizes images so the longest side is ≤3072px before tiling.
|
|
158
|
+
const clampedWidth = Math.min(width, GEMINI_IMAGE_MAX_DIMENSION);
|
|
159
|
+
const clampedHeight = Math.min(height, GEMINI_IMAGE_MAX_DIMENSION);
|
|
160
|
+
const tilesWide = Math.ceil(clampedWidth / GEMINI_IMAGE_TILE_SIZE);
|
|
161
|
+
const tilesHigh = Math.ceil(clampedHeight / GEMINI_IMAGE_TILE_SIZE);
|
|
162
|
+
return tilesWide * tilesHigh * GEMINI_IMAGE_TOKENS_PER_TILE;
|
|
163
|
+
}
|
|
164
|
+
|
|
132
165
|
function estimateImageTokens(
|
|
133
166
|
block: Extract<ContentBlock, { type: "image" }>,
|
|
167
|
+
options?: TokenEstimatorOptions,
|
|
134
168
|
): number {
|
|
135
169
|
const dims = parseImageDimensions(block.source.data, block.source.media_type);
|
|
136
170
|
if (dims) {
|
|
171
|
+
if (options?.providerName === "gemini") {
|
|
172
|
+
return estimateGeminiImageTokens(dims.width, dims.height);
|
|
173
|
+
}
|
|
137
174
|
return estimateImageTokensByDimensions(dims.width, dims.height);
|
|
138
175
|
}
|
|
139
|
-
// Dimensions unparseable (corrupt header,
|
|
140
|
-
//
|
|
141
|
-
//
|
|
176
|
+
// Dimensions unparseable (corrupt header, or formats parseImageDimensions
|
|
177
|
+
// doesn't recognize like HEIC/HEIF coming from iOS attachments). Fall back
|
|
178
|
+
// to the per-provider per-image ceiling rather than the raw base64 length,
|
|
179
|
+
// which over-counts by 30-100x. Gemini's tile pricing tops out well above
|
|
180
|
+
// the universal 1,600-token cap, so use its max-tile budget instead to
|
|
181
|
+
// avoid under-counting large iPhone screenshots.
|
|
182
|
+
if (options?.providerName === "gemini") {
|
|
183
|
+
return GEMINI_IMAGE_MAX_TOKENS;
|
|
184
|
+
}
|
|
142
185
|
return IMAGE_MAX_TOKENS;
|
|
143
186
|
}
|
|
144
187
|
|
|
@@ -186,7 +229,7 @@ export function estimateContentBlockTokens(
|
|
|
186
229
|
return (
|
|
187
230
|
IMAGE_BLOCK_OVERHEAD_TOKENS +
|
|
188
231
|
estimateTextTokens(block.source.media_type) +
|
|
189
|
-
estimateImageTokens(block)
|
|
232
|
+
estimateImageTokens(block, options)
|
|
190
233
|
);
|
|
191
234
|
case "file":
|
|
192
235
|
return (
|
|
@@ -51,6 +51,11 @@ export interface ContextWindowResult {
|
|
|
51
51
|
thresholdTokens: number;
|
|
52
52
|
compactedMessages: number;
|
|
53
53
|
compactedPersistedMessages: number;
|
|
54
|
+
/**
|
|
55
|
+
* Number of recent ("tail") messages preserved verbatim alongside the
|
|
56
|
+
* summary. Omitted on no-op / skipped results — defaults to 0 at render.
|
|
57
|
+
*/
|
|
58
|
+
preservedTailMessages?: number;
|
|
54
59
|
summaryCalls: number;
|
|
55
60
|
summaryInputTokens: number;
|
|
56
61
|
summaryOutputTokens: number;
|
|
@@ -216,6 +221,26 @@ export class ContextWindowManager {
|
|
|
216
221
|
return getConfig().compaction;
|
|
217
222
|
}
|
|
218
223
|
|
|
224
|
+
get maxInputTokens(): number {
|
|
225
|
+
return this.config.maxInputTokens;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Estimate the prompt-token cost of `messages` using the same path as the
|
|
230
|
+
* auto-compaction pre-check. Clears the system-prompt cache so the next
|
|
231
|
+
* turn re-resolves it (the system prompt is lazy and may have changed).
|
|
232
|
+
*/
|
|
233
|
+
estimateInputTokens(messages: Message[]): number {
|
|
234
|
+
try {
|
|
235
|
+
return estimatePromptTokens(messages, this.systemPrompt, {
|
|
236
|
+
providerName: this.estimationProviderName,
|
|
237
|
+
toolTokenBudget: this.toolTokenBudget,
|
|
238
|
+
});
|
|
239
|
+
} finally {
|
|
240
|
+
this.clearSystemPromptCache();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
219
244
|
/**
|
|
220
245
|
* Cheap pre-check — estimate the current token count and compare against
|
|
221
246
|
* `compaction.autoThreshold`. Callers pass the estimate back through
|
|
@@ -315,9 +315,11 @@ async function checkManagedProvider(
|
|
|
315
315
|
const client = await VellumPlatformClient.create();
|
|
316
316
|
if (!client?.platformAssistantId) return results;
|
|
317
317
|
|
|
318
|
+
// Query without a status filter so we can distinguish "never
|
|
319
|
+
// connected" (empty result) from "previously connected but now
|
|
320
|
+
// inactive" (non-empty result with no ACTIVE entries).
|
|
318
321
|
const params = new URLSearchParams();
|
|
319
322
|
params.set("provider", providerRow.provider);
|
|
320
|
-
params.set("status", "ACTIVE");
|
|
321
323
|
|
|
322
324
|
const path = `/v1/assistants/${encodeURIComponent(client.platformAssistantId)}/oauth/connections/?${params.toString()}`;
|
|
323
325
|
const response = await client.fetch(path);
|
|
@@ -331,19 +333,30 @@ async function checkManagedProvider(
|
|
|
331
333
|
}
|
|
332
334
|
|
|
333
335
|
const body = (await response.json()) as unknown;
|
|
334
|
-
const
|
|
336
|
+
const allConnections = (
|
|
335
337
|
Array.isArray(body)
|
|
336
338
|
? body
|
|
337
339
|
: ((body as Record<string, unknown>).results ?? [])
|
|
338
|
-
) as Array<{ id: string; account_label?: string }>;
|
|
340
|
+
) as Array<{ id: string; account_label?: string; status?: string }>;
|
|
341
|
+
|
|
342
|
+
if (allConnections.length === 0) {
|
|
343
|
+
// No connections of any status — the user has never connected this
|
|
344
|
+
// provider. The suggested-prompts system handles prompting them to
|
|
345
|
+
// connect; this is not a health issue.
|
|
346
|
+
return results;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const connections = allConnections.filter(
|
|
350
|
+
(c) => (c.status ?? "ACTIVE").toUpperCase() === "ACTIVE",
|
|
351
|
+
);
|
|
339
352
|
|
|
340
353
|
if (connections.length === 0) {
|
|
341
|
-
//
|
|
342
|
-
//
|
|
354
|
+
// Connections exist but none are active — the user previously
|
|
355
|
+
// connected and the connection was revoked/deactivated.
|
|
343
356
|
results.push({
|
|
344
357
|
connectionId: `managed:${providerRow.provider}`,
|
|
345
358
|
provider: providerRow.provider,
|
|
346
|
-
accountInfo: null,
|
|
359
|
+
accountInfo: allConnections[0]?.account_label ?? null,
|
|
347
360
|
status: "missing_token",
|
|
348
361
|
details: `No active managed connection for ${providerRow.provider}. Reconnect on the Vellum platform.`,
|
|
349
362
|
missingScopes: [],
|
|
@@ -550,9 +563,20 @@ export async function checkAllCredentials(): Promise<CredentialHealthReport> {
|
|
|
550
563
|
for (const providerRow of providers) {
|
|
551
564
|
if (!(await isManagedProvider(providerRow))) continue;
|
|
552
565
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
566
|
+
let managedResults: CredentialHealthResult[] = [];
|
|
567
|
+
try {
|
|
568
|
+
managedResults = await checkManagedProvider(providerRow);
|
|
569
|
+
} catch (err) {
|
|
570
|
+
log.warn(
|
|
571
|
+
{ err, provider: providerRow.provider },
|
|
572
|
+
"Failed to check managed provider health",
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// Only replace BYO results with managed results when the managed
|
|
577
|
+
// check returned something. If managed returned empty (user never
|
|
578
|
+
// connected via managed mode), keep any existing BYO results.
|
|
579
|
+
if (managedResults.length > 0 && byoProviders.has(providerRow.provider)) {
|
|
556
580
|
const beforeLen = results.length;
|
|
557
581
|
const filtered = results.filter(
|
|
558
582
|
(r) => r.provider !== providerRow.provider,
|
|
@@ -562,16 +586,7 @@ export async function checkAllCredentials(): Promise<CredentialHealthReport> {
|
|
|
562
586
|
results.push(...filtered);
|
|
563
587
|
}
|
|
564
588
|
}
|
|
565
|
-
|
|
566
|
-
try {
|
|
567
|
-
const managedResults = await checkManagedProvider(providerRow);
|
|
568
|
-
results.push(...managedResults);
|
|
569
|
-
} catch (err) {
|
|
570
|
-
log.warn(
|
|
571
|
-
{ err, provider: providerRow.provider },
|
|
572
|
-
"Failed to check managed provider health",
|
|
573
|
-
);
|
|
574
|
-
}
|
|
589
|
+
results.push(...managedResults);
|
|
575
590
|
}
|
|
576
591
|
|
|
577
592
|
const unhealthy = results.filter((r) => r.status !== "healthy");
|
|
@@ -49,11 +49,8 @@ mock.module("../../runtime/assistant-event-hub.js", () => ({
|
|
|
49
49
|
|
|
50
50
|
// Dynamic imports after mock.module calls so the stubs take effect
|
|
51
51
|
// before the modules under test are loaded.
|
|
52
|
-
const {
|
|
53
|
-
|
|
54
|
-
HOST_TOOL_TO_CAPABILITY,
|
|
55
|
-
isToolActiveForContext,
|
|
56
|
-
} = await import("../conversation-tool-setup.js");
|
|
52
|
+
const { HOST_TOOL_NAMES, HOST_TOOL_TO_CAPABILITY, isToolActiveForContext } =
|
|
53
|
+
await import("../conversation-tool-setup.js");
|
|
57
54
|
type SkillProjectionContext =
|
|
58
55
|
import("../conversation-tool-setup.js").SkillProjectionContext;
|
|
59
56
|
type SkillProjectionCache =
|
|
@@ -75,6 +72,66 @@ beforeEach(() => {
|
|
|
75
72
|
mockClientCountByCapability.clear();
|
|
76
73
|
});
|
|
77
74
|
|
|
75
|
+
describe("isToolActiveForContext — Slack task_progress UI exception", () => {
|
|
76
|
+
test("ui_show and ui_update are active for Slack task_progress turns", () => {
|
|
77
|
+
const ctx = makeCtx({
|
|
78
|
+
hasNoClient: false,
|
|
79
|
+
channelCapabilities: {
|
|
80
|
+
channel: "slack",
|
|
81
|
+
supportsDynamicUi: false,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(isToolActiveForContext("ui_show", ctx)).toBe(true);
|
|
86
|
+
expect(isToolActiveForContext("ui_update", ctx)).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("ui_dismiss remains hidden for Slack without dynamic UI support", () => {
|
|
90
|
+
expect(
|
|
91
|
+
isToolActiveForContext(
|
|
92
|
+
"ui_dismiss",
|
|
93
|
+
makeCtx({
|
|
94
|
+
hasNoClient: false,
|
|
95
|
+
channelCapabilities: {
|
|
96
|
+
channel: "slack",
|
|
97
|
+
supportsDynamicUi: false,
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
100
|
+
),
|
|
101
|
+
).toBe(false);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("Slack task_progress UI tools still require a connected client path", () => {
|
|
105
|
+
expect(
|
|
106
|
+
isToolActiveForContext(
|
|
107
|
+
"ui_show",
|
|
108
|
+
makeCtx({
|
|
109
|
+
hasNoClient: true,
|
|
110
|
+
channelCapabilities: {
|
|
111
|
+
channel: "slack",
|
|
112
|
+
supportsDynamicUi: false,
|
|
113
|
+
},
|
|
114
|
+
}),
|
|
115
|
+
),
|
|
116
|
+
).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("other non-dynamic channels still hide UI surface tools", () => {
|
|
120
|
+
expect(
|
|
121
|
+
isToolActiveForContext(
|
|
122
|
+
"ui_show",
|
|
123
|
+
makeCtx({
|
|
124
|
+
hasNoClient: false,
|
|
125
|
+
channelCapabilities: {
|
|
126
|
+
channel: "telegram",
|
|
127
|
+
supportsDynamicUi: false,
|
|
128
|
+
},
|
|
129
|
+
}),
|
|
130
|
+
),
|
|
131
|
+
).toBe(false);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
78
135
|
describe("isToolActiveForContext — host tool capability gating", () => {
|
|
79
136
|
// macOS transport: SSE-based interactive approval required.
|
|
80
137
|
test("host_bash is active for macOS with a connected client", () => {
|
|
@@ -331,7 +388,10 @@ describe("isToolActiveForContext — cross-client exposure for host_file_*", ()
|
|
|
331
388
|
expect(
|
|
332
389
|
isToolActiveForContext(
|
|
333
390
|
tool,
|
|
334
|
-
makeCtx({
|
|
391
|
+
makeCtx({
|
|
392
|
+
hasNoClient: true,
|
|
393
|
+
transportInterface: "chrome-extension",
|
|
394
|
+
}),
|
|
335
395
|
),
|
|
336
396
|
).toBe(false);
|
|
337
397
|
});
|