@vellumai/assistant 0.8.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +13 -19
- package/Dockerfile +75 -1
- package/bun.lock +11 -1
- package/docker-entrypoint.sh +17 -0
- package/docker-init-apt-root.sh +167 -0
- package/docker-kata-apt-env.sh +39 -0
- package/docs/plugins.md +88 -47
- package/docs/skills.md +9 -7
- package/examples/plugins/echo/README.md +27 -27
- package/examples/plugins/echo/package.json +3 -0
- package/examples/plugins/echo/register.ts +31 -31
- package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
- package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
- package/openapi.yaml +642 -5
- package/package.json +3 -1
- package/scripts/generate-openapi.ts +83 -10
- package/scripts/sync-llm-catalog.ts +2 -2
- package/scripts/sync-web-search-catalog.ts +47 -25
- package/src/__tests__/agent-image-optimize.test.ts +11 -3
- package/src/__tests__/agent-loop-exit-reason.test.ts +272 -0
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
- package/src/__tests__/anthropic-provider.test.ts +45 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
- package/src/__tests__/app-executors.test.ts +220 -4
- package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/channel-availability-routes.test.ts +206 -0
- package/src/__tests__/channel-delivery-store.test.ts +289 -1
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
- package/src/__tests__/clawhub.test.ts +75 -16
- package/src/__tests__/compactor-tail-resolution.test.ts +147 -0
- package/src/__tests__/config-get-vision-flag.test.ts +136 -0
- package/src/__tests__/config-loader-backfill.test.ts +115 -18
- package/src/__tests__/config-schema.test.ts +21 -0
- package/src/__tests__/config-set-route.test.ts +80 -0
- package/src/__tests__/config-sounds-sync.test.ts +97 -0
- package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
- package/src/__tests__/context-search-conversations-source.test.ts +117 -2
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +7 -0
- package/src/__tests__/context-token-estimator.test.ts +31 -65
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
- package/src/__tests__/conversation-agent-loop.test.ts +59 -1
- package/src/__tests__/conversation-error.test.ts +42 -3
- package/src/__tests__/conversation-fork-crud.test.ts +82 -0
- package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
- package/src/__tests__/conversation-lifecycle.test.ts +173 -0
- package/src/__tests__/conversation-media-retry.test.ts +19 -8
- package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
- package/src/__tests__/conversation-pairing.test.ts +54 -0
- package/src/__tests__/conversation-process-callsite.test.ts +4 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
- package/src/__tests__/conversation-queue.test.ts +4 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +102 -13
- package/src/__tests__/conversation-slash-queue.test.ts +59 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
- package/src/__tests__/conversation-sync-tags.test.ts +235 -0
- 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 +3 -2
- package/src/__tests__/date-context.test.ts +45 -0
- package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
- package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
- package/src/__tests__/disk-pressure-tools.test.ts +1 -0
- package/src/__tests__/dm-backfill.test.ts +121 -10
- package/src/__tests__/document-tool-security.test.ts +258 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/edit-propagation.test.ts +33 -0
- package/src/__tests__/empty-response-pipeline.test.ts +0 -4
- package/src/__tests__/external-plugin-loader.test.ts +151 -55
- package/src/__tests__/filing-service.test.ts +140 -0
- package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
- package/src/__tests__/heartbeat-service.test.ts +24 -164
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/helpers/tar-fixtures.ts +39 -0
- package/src/__tests__/helpers/wait-for.ts +21 -0
- package/src/__tests__/history-repair-pipeline.test.ts +0 -3
- package/src/__tests__/history-repair.test.ts +73 -0
- package/src/__tests__/host-app-control-proxy.test.ts +507 -10
- package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
- package/src/__tests__/image-credentials.test.ts +1 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
- package/src/__tests__/inference-profile-reaper.test.ts +4 -2
- package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
- package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
- package/src/__tests__/injector-background-turn.test.ts +153 -0
- package/src/__tests__/injector-chain.test.ts +15 -8
- package/src/__tests__/install-skill-routing.test.ts +155 -37
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +99 -3
- package/src/__tests__/list-messages-page-latest.test.ts +55 -0
- package/src/__tests__/llm-call-pipeline.test.ts +0 -3
- package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
- package/src/__tests__/llm-catalog-parity.test.ts +58 -13
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +36 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
- package/src/__tests__/llm-resolver.test.ts +255 -2
- package/src/__tests__/llm-usage-store.test.ts +114 -0
- package/src/__tests__/managed-profile-guard.test.ts +41 -29
- package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
- package/src/__tests__/managed-store.test.ts +84 -192
- package/src/__tests__/media-generate-image.test.ts +1 -1
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
- package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
- package/src/__tests__/notification-decision-fallback.test.ts +0 -91
- package/src/__tests__/notification-decision-strategy.test.ts +14 -31
- package/src/__tests__/notification-deep-link.test.ts +15 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -2
- package/src/__tests__/notification-platform-adapter.test.ts +5 -4
- package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
- package/src/__tests__/oauth-commands-routes.test.ts +168 -16
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
- package/src/__tests__/openai-provider.test.ts +242 -3
- package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
- package/src/__tests__/openrouter-provider-only.test.ts +51 -3
- package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
- package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
- package/src/__tests__/persistence-pipeline.test.ts +0 -2
- package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +7 -2
- package/src/__tests__/platform.test.ts +2 -0
- package/src/__tests__/plugin-api-shim.test.ts +125 -0
- package/src/__tests__/plugin-bootstrap.test.ts +10 -36
- package/src/__tests__/plugin-external-api.test.ts +68 -0
- package/src/__tests__/plugin-registry.test.ts +0 -77
- package/src/__tests__/plugin-route-contribution.test.ts +0 -1
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
- package/src/__tests__/plugin-types.test.ts +3 -13
- package/src/__tests__/process-message-background-slack.test.ts +8 -1
- package/src/__tests__/process-message-display-content.test.ts +421 -0
- package/src/__tests__/provider-catalog-visibility.test.ts +158 -0
- package/src/__tests__/provider-error-scenarios.test.ts +111 -0
- package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +33 -31
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
- package/src/__tests__/schedule-routes.test.ts +50 -3
- package/src/__tests__/schedule-store.test.ts +94 -0
- package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
- package/src/__tests__/schema-transforms.test.ts +20 -0
- package/src/__tests__/search-skills-unified.test.ts +0 -5
- package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +1 -1
- package/src/__tests__/server-history-render.test.ts +43 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
- package/src/__tests__/skill-load-tool.test.ts +27 -89
- package/src/__tests__/skill-memory.test.ts +23 -3
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
- package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
- package/src/__tests__/skills-install-extract.test.ts +49 -38
- package/src/__tests__/skills-install-staging.test.ts +159 -0
- package/src/__tests__/skills-uninstall.test.ts +9 -41
- package/src/__tests__/skills.test.ts +51 -58
- package/src/__tests__/slack-channel-config.test.ts +9 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/system-prompt.test.ts +670 -63
- package/src/__tests__/terminal-tools.test.ts +28 -1
- package/src/__tests__/thread-backfill.test.ts +557 -27
- package/src/__tests__/title-generate-pipeline.test.ts +0 -13
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
- package/src/__tests__/tool-error-pipeline.test.ts +0 -3
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +16 -4
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
- package/src/__tests__/turn-events-store.test.ts +256 -0
- package/src/__tests__/twilio-routes.test.ts +4 -0
- package/src/__tests__/user-plugin-loader.test.ts +0 -7
- package/src/__tests__/voice-session-bridge.test.ts +198 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
- package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
- package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
- package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
- package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
- package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
- package/src/a2a/__tests__/agent-card.test.ts +98 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
- package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
- package/src/a2a/__tests__/task-store.test.ts +246 -0
- package/src/a2a/agent-card.ts +58 -0
- package/src/a2a/feature-gate.ts +8 -0
- package/src/a2a/protocol-constants.ts +21 -0
- package/src/a2a/protocol-errors.ts +50 -0
- package/src/a2a/protocol-types.ts +162 -0
- package/src/a2a/task-store.ts +168 -0
- package/src/acp/resolve-agent.ts +1 -1
- package/src/agent/image-optimize.ts +13 -5
- package/src/agent/loop.ts +167 -18
- package/src/calls/voice-session-bridge.ts +61 -42
- package/src/channels/config.ts +9 -0
- package/src/channels/types.ts +122 -0
- package/src/cli/__tests__/unknown-command.test.ts +24 -0
- package/src/cli/commands/__tests__/changelog.test.ts +304 -319
- package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
- package/src/cli/commands/__tests__/schedules.test.ts +960 -0
- package/src/cli/commands/changelog.ts +106 -42
- package/src/cli/commands/conversations.ts +102 -17
- package/src/cli/commands/default-action.ts +10 -53
- package/src/cli/commands/notifications.ts +388 -346
- package/src/cli/commands/plugins.ts +252 -0
- package/src/cli/commands/schedules.ts +683 -0
- package/src/cli/commands/telemetry.ts +40 -0
- package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
- package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
- package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
- package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
- package/src/cli/lib/cli-colors.ts +12 -0
- package/src/cli/lib/confirm-prompt.ts +79 -0
- package/src/cli/lib/install-from-github.ts +303 -0
- package/src/cli/lib/list-installed-plugins.ts +137 -0
- package/src/cli/lib/search-plugins.ts +163 -0
- package/src/cli/lib/uninstall-plugin.ts +82 -0
- package/src/cli/lib/unknown-command.ts +111 -0
- package/src/cli/program.ts +52 -2
- package/src/config/assistant-feature-flags.ts +24 -54
- package/src/config/bundled-skills/app-builder/SKILL.md +140 -22
- package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
- package/src/config/bundled-skills/document/SKILL.md +23 -3
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
- package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
- package/src/config/bundled-tool-registry.ts +6 -0
- package/src/config/call-site-defaults.ts +105 -0
- package/src/config/feature-flag-registry.json +41 -9
- package/src/config/llm-resolver.ts +52 -1
- package/src/config/loader.ts +64 -38
- package/src/config/schema.ts +9 -10
- package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +3 -3
- package/src/config/schemas/channels.ts +17 -0
- package/src/config/schemas/compaction.ts +28 -0
- package/src/config/schemas/conversations.ts +10 -0
- package/src/config/schemas/heartbeat.ts +23 -0
- package/src/config/schemas/llm-request-logs.ts +31 -7
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-retrieval.ts +18 -0
- package/src/config/schemas/memory-retrospective.ts +1 -1
- package/src/config/schemas/memory-v2.ts +4 -4
- package/src/config/schemas/memory.ts +3 -1
- package/src/config/schemas/tools.ts +14 -0
- package/src/config/seed-inference-profiles.ts +99 -29
- package/src/config/skills.ts +3 -96
- package/src/context/compactor.ts +1107 -0
- package/src/context/token-estimator.ts +34 -36
- package/src/context/window-manager.ts +197 -1520
- package/src/credential-execution/managed-catalog.ts +37 -0
- package/src/credential-health/credential-health-service.ts +280 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +33 -18
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
- package/src/daemon/approval-generators.ts +8 -6
- package/src/daemon/config-watcher.ts +94 -31
- package/src/daemon/conversation-agent-loop-handlers.ts +78 -0
- package/src/daemon/conversation-agent-loop.ts +198 -11
- package/src/daemon/conversation-error.ts +171 -37
- package/src/daemon/conversation-lifecycle.ts +53 -40
- package/src/daemon/conversation-messaging.ts +25 -6
- package/src/daemon/conversation-process.ts +49 -12
- package/src/daemon/conversation-runtime-assembly.ts +25 -1
- package/src/daemon/conversation-slash.ts +12 -5
- package/src/daemon/conversation-store.ts +11 -4
- package/src/daemon/conversation-tool-setup.ts +39 -7
- package/src/daemon/conversation.ts +33 -8
- package/src/daemon/date-context.ts +40 -0
- package/src/daemon/external-plugins-bootstrap.ts +217 -181
- package/src/daemon/first-greeting.ts +22 -2
- package/src/daemon/guardian-action-generators.ts +1 -125
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
- package/src/daemon/handlers/config-a2a.ts +289 -0
- package/src/daemon/handlers/config-model.ts +6 -5
- package/src/daemon/handlers/config-slack-channel.ts +15 -3
- package/src/daemon/handlers/conversations.ts +1 -0
- package/src/daemon/handlers/shared.ts +14 -5
- package/src/daemon/handlers/skills.ts +111 -108
- package/src/daemon/history-repair.ts +28 -1
- package/src/daemon/host-app-control-proxy.ts +153 -27
- package/src/daemon/host-proxy-preactivation.ts +85 -18
- package/src/daemon/lifecycle.ts +89 -91
- package/src/daemon/meet-host-supervisor.ts +5 -4
- package/src/daemon/memory-v2-startup.ts +85 -0
- package/src/daemon/message-protocol.ts +1 -0
- package/src/daemon/message-types/conversations.ts +25 -0
- package/src/daemon/message-types/messages.ts +61 -0
- package/src/daemon/message-types/notifications.ts +21 -0
- package/src/daemon/message-types/subagents.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pkb-reminder-builder.test.ts +11 -54
- package/src/daemon/pkb-reminder-builder.ts +5 -20
- package/src/daemon/plugin-source-watcher.ts +146 -0
- package/src/daemon/process-message.ts +24 -3
- package/src/daemon/server.ts +11 -2
- package/src/daemon/skill-memory-refresh.ts +33 -0
- package/src/daemon/wake-target-adapter.ts +2 -0
- package/src/documents/document-store.ts +221 -3
- package/src/embedded/plugin-api.ts +40 -0
- package/src/export/__tests__/transcript-formatter.test.ts +121 -0
- package/src/export/transcript-formatter.ts +54 -20
- package/src/filing/filing-service.ts +39 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +135 -6
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +73 -189
- package/src/home/__tests__/feed-types.test.ts +80 -0
- package/src/home/feed-types.ts +36 -2
- package/src/home/post-connect-feed.ts +1 -0
- package/src/index.ts +18 -1
- package/src/ipc/cli-client.ts +147 -45
- package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
- package/src/mcp/client.ts +20 -4
- package/src/media/image-credentials.ts +3 -3
- package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
- package/src/memory/__tests__/conversation-queries.test.ts +483 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
- package/src/memory/__tests__/memory-retrospective-job.test.ts +87 -4
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
- package/src/memory/__tests__/message-content.test.ts +35 -0
- package/src/memory/bookmark-crud.ts +42 -10
- package/src/memory/context-search/sources/conversations.ts +62 -2
- package/src/memory/context-search/sources/workspace.ts +4 -0
- package/src/memory/conversation-crud.ts +63 -19
- package/src/memory/conversation-queries.ts +197 -11
- package/src/memory/conversation-title-service.ts +26 -4
- package/src/memory/db-init.ts +12 -0
- package/src/memory/delivery-crud.ts +152 -5
- package/src/memory/embedding-backend.ts +4 -4
- package/src/memory/external-conversation-store.ts +66 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +150 -12
- package/src/memory/graph/conversation-graph-memory.ts +49 -21
- package/src/memory/graph/tools.ts +9 -40
- package/src/memory/indexer.ts +34 -29
- package/src/memory/invite-store.ts +53 -0
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
- package/src/memory/jobs/embed-concept-page.ts +20 -11
- package/src/memory/jobs-worker.ts +6 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +24 -12
- package/src/memory/llm-request-log-source.ts +19 -52
- package/src/memory/llm-request-log-store.ts +92 -1
- package/src/memory/llm-usage-store.ts +125 -5
- package/src/memory/memory-retrospective-enqueue.ts +1 -20
- package/src/memory/memory-retrospective-job.ts +33 -6
- package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
- package/src/memory/message-content.ts +1 -1
- package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
- package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
- package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
- package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
- package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
- package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
- package/src/memory/migrations/251-a2a-tasks.ts +49 -0
- package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
- package/src/memory/migrations/index.ts +9 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/onboarding-events-store.ts +106 -0
- package/src/memory/schema/a2a.ts +15 -0
- package/src/memory/schema/bookmarks.ts +0 -2
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/inference.ts +3 -3
- package/src/memory/schema/infrastructure.ts +13 -0
- package/src/memory/turn-events-store.ts +127 -2
- package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
- package/src/memory/v2/__tests__/activation.test.ts +0 -8
- package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
- package/src/memory/v2/__tests__/injection.test.ts +288 -11
- package/src/memory/v2/__tests__/migration.test.ts +87 -0
- package/src/memory/v2/__tests__/page-index.test.ts +83 -0
- package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
- package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
- package/src/memory/v2/__tests__/router.test.ts +15 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
- package/src/memory/v2/__tests__/static-context.test.ts +12 -1
- package/src/memory/v2/activation-store.ts +14 -16
- package/src/memory/v2/cli-command-content.ts +19 -0
- package/src/memory/v2/cli-command-store.ts +304 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -1
- package/src/memory/v2/injection.ts +81 -26
- package/src/memory/v2/migration.ts +49 -19
- package/src/memory/v2/page-index.ts +63 -8
- package/src/memory/v2/prompts/router.ts +11 -8
- package/src/memory/v2/prompts/sweep.ts +2 -2
- package/src/memory/v2/qdrant.ts +135 -7
- package/src/memory/v2/router.ts +9 -8
- package/src/memory/v2/skill-store.ts +120 -35
- package/src/memory/v2/static-context.ts +4 -4
- package/src/memory/v2/types.ts +23 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
- package/src/messaging/providers/a2a/deliver.ts +156 -0
- package/src/messaging/providers/gmail/client.ts +9 -2
- package/src/messaging/providers/index.ts +11 -2
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
- package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
- package/src/messaging/providers/slack/adapter.ts +43 -5
- package/src/messaging/providers/slack/client.ts +27 -0
- package/src/messaging/providers/slack/deep-link.ts +65 -0
- package/src/messaging/providers/slack/download.ts +104 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
- package/src/messaging/providers/slack/message-metadata.ts +27 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
- package/src/messaging/providers/slack/render-transcript.ts +69 -5
- package/src/messaging/providers/slack/types.ts +20 -1
- package/src/notifications/__tests__/broadcaster.test.ts +203 -0
- package/src/notifications/__tests__/decision-engine.test.ts +283 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +430 -7
- package/src/notifications/adapters/macos.ts +12 -2
- package/src/notifications/broadcaster.ts +29 -4
- package/src/notifications/conversation-pairing.ts +2 -1
- package/src/notifications/copy-composer.ts +17 -64
- package/src/notifications/decision-engine.ts +113 -45
- package/src/notifications/deterministic-checks.ts +96 -0
- package/src/notifications/emit-signal.ts +21 -1
- package/src/notifications/home-feed-side-effect.ts +138 -5
- package/src/notifications/signal.ts +3 -5
- package/src/notifications/types.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -4
- package/src/oauth/platform-connection.test.ts +43 -3
- package/src/oauth/platform-connection.ts +19 -6
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/checker.ts +2 -0
- package/src/permissions/ipc-risk-types.ts +1 -0
- package/src/permissions/question-prompter.test.ts +416 -0
- package/src/permissions/question-prompter.ts +294 -0
- package/src/platform/client.test.ts +1 -1
- package/src/platform/client.ts +1 -1
- package/src/plugin-api/constants.ts +26 -0
- package/src/plugin-api/index.ts +34 -1
- package/src/plugin-api/types.ts +104 -22
- package/src/plugins/defaults/circuit-breaker.ts +0 -5
- package/src/plugins/defaults/compaction.ts +0 -4
- package/src/plugins/defaults/empty-response.ts +0 -2
- package/src/plugins/defaults/history-repair.ts +0 -2
- package/src/plugins/defaults/injectors.ts +74 -22
- package/src/plugins/defaults/llm-call.ts +0 -2
- package/src/plugins/defaults/memory-retrieval.ts +0 -1
- package/src/plugins/defaults/overflow-reduce.ts +0 -1
- package/src/plugins/defaults/persistence.ts +0 -2
- package/src/plugins/defaults/title-generate.ts +0 -5
- package/src/plugins/defaults/token-estimate.ts +0 -2
- package/src/plugins/defaults/tool-error.ts +0 -7
- package/src/plugins/defaults/tool-execute.ts +0 -2
- package/src/plugins/defaults/tool-result-truncate.ts +0 -4
- package/src/plugins/ensure-plugin-api-shim.ts +96 -0
- package/src/plugins/external-api.ts +104 -0
- package/src/plugins/external-plugin-loader.ts +187 -42
- package/src/plugins/feature-gate.ts +22 -0
- package/src/plugins/pipeline.ts +37 -0
- package/src/plugins/registry.ts +48 -80
- package/src/plugins/types.ts +40 -26
- package/src/plugins/user-loader.ts +21 -2
- package/src/proactive-artifact/aux-message-injector.ts +11 -0
- package/src/proactive-artifact/job.test.ts +37 -5
- package/src/prompts/__tests__/system-prompt.test.ts +10 -43
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +95 -0
- package/src/prompts/normalize-onboarding.ts +27 -0
- package/src/prompts/sections.ts +302 -0
- package/src/prompts/system-prompt.ts +63 -174
- package/src/prompts/templates/BOOTSTRAP.md +17 -1
- package/src/prompts/templates/system-sections.ts +164 -0
- package/src/providers/__tests__/inference.test.ts +24 -7
- package/src/providers/anthropic/client.ts +28 -28
- package/src/providers/call-site-routing.ts +24 -6
- package/src/providers/connection-resolution.ts +68 -11
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
- package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
- package/src/providers/inference/adapter-factory.ts +32 -6
- package/src/providers/inference/auth.ts +12 -0
- package/src/providers/inference/backfill.ts +14 -1
- package/src/providers/inference/connections.ts +159 -34
- package/src/providers/inference/resolve-auth.ts +14 -4
- package/src/providers/model-catalog.ts +249 -12
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
- package/src/providers/openai/chat-completions-provider.ts +169 -8
- package/src/providers/openrouter/client.ts +49 -4
- package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -2
- package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
- package/src/providers/provider-availability.ts +17 -2
- package/src/providers/provider-catalog-visibility.ts +38 -0
- package/src/providers/provider-send-message.ts +27 -12
- package/src/providers/registry.ts +52 -15
- package/src/providers/retry.ts +47 -1
- package/src/runtime/__tests__/agent-wake.test.ts +152 -0
- package/src/runtime/agent-wake.ts +103 -15
- package/src/runtime/auth/route-policy.ts +21 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/http-server.ts +7 -16
- package/src/runtime/http-types.ts +19 -47
- package/src/runtime/migrations/origin-mode.ts +1 -1
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +172 -23
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
- package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
- package/src/runtime/routes/acp-routes-list.test.ts +143 -0
- package/src/runtime/routes/acp-routes.ts +5 -3
- package/src/runtime/routes/auth-routes.ts +1 -1
- package/src/runtime/routes/bookmark-routes.ts +5 -3
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/channel-availability-routes.ts +126 -0
- package/src/runtime/routes/consolidation-routes.ts +100 -0
- package/src/runtime/routes/conversation-cli-routes.ts +44 -3
- package/src/runtime/routes/conversation-list-routes.ts +3 -20
- package/src/runtime/routes/conversation-management-routes.ts +17 -42
- package/src/runtime/routes/conversation-query-routes.ts +99 -35
- package/src/runtime/routes/conversation-routes.ts +97 -11
- package/src/runtime/routes/documents-routes.ts +25 -86
- package/src/runtime/routes/group-routes.ts +5 -0
- package/src/runtime/routes/inbound-conversation.ts +28 -8
- package/src/runtime/routes/inbound-message-handler.ts +236 -41
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
- package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
- package/src/runtime/routes/inference-provider-connection-routes.ts +199 -22
- package/src/runtime/routes/integrations/a2a.ts +235 -0
- package/src/runtime/routes/integrations/slack/share.ts +4 -52
- package/src/runtime/routes/integrations/slack/token.ts +43 -0
- package/src/runtime/routes/integrations/twilio.ts +6 -13
- package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
- package/src/runtime/routes/notification-routes.ts +1 -1
- package/src/runtime/routes/oauth-commands-routes.ts +105 -15
- package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
- package/src/runtime/routes/question-routes.ts +259 -0
- package/src/runtime/routes/rename-conversation-routes.ts +2 -33
- package/src/runtime/routes/schedule-routes.ts +4 -7
- package/src/runtime/routes/subagents-routes.ts +98 -18
- package/src/runtime/routes/telemetry-routes.ts +27 -0
- package/src/runtime/routes/tts-routes.ts +27 -2
- package/src/runtime/routes/workspace-routes.test.ts +43 -0
- package/src/runtime/routes/workspace-routes.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +39 -7
- package/src/runtime/sync/resource-sync-events.ts +93 -1
- package/src/schedule/schedule-store.ts +27 -2
- package/src/schedule/scheduler.ts +9 -1
- package/src/security/__tests__/untrusted-content.test.ts +86 -0
- package/src/security/untrusted-content.ts +93 -8
- package/src/skills/catalog-files.ts +1 -1
- package/src/skills/catalog-install.ts +233 -116
- package/src/skills/clawhub.ts +70 -13
- package/src/skills/managed-store.ts +4 -119
- package/src/skills/skillssh-registry.ts +27 -48
- package/src/subagent/manager.ts +17 -7
- package/src/telemetry/types.ts +113 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
- package/src/telemetry/usage-telemetry-reporter.ts +113 -7
- package/src/tools/apps/executors.ts +58 -7
- package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
- package/src/tools/ask-question/ask-question-tool.ts +304 -0
- package/src/tools/browser/browser-execution.ts +15 -11
- package/src/tools/computer-use/definitions.ts +3 -3
- package/src/tools/credentials/vault.ts +1 -1
- package/src/tools/document/document-tool.ts +124 -1
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +5 -2
- package/src/tools/host-filesystem/transfer.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +1 -1
- package/src/tools/memory/register.ts +1 -9
- package/src/tools/permission-checker.ts +1 -1
- package/src/tools/registry.ts +17 -7
- package/src/tools/schedule/create.ts +2 -2
- package/src/tools/schema-transforms.ts +7 -2
- package/src/tools/side-effects.ts +1 -0
- package/src/tools/skills/delete-managed.ts +4 -4
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/scaffold-managed.ts +3 -2
- package/src/tools/subagent/notify-parent.ts +1 -1
- package/src/tools/system/request-permission.ts +2 -2
- package/src/tools/terminal/safe-env.ts +60 -1
- package/src/tools/tool-manifest.ts +2 -0
- package/src/tools/types.ts +107 -21
- package/src/tools/ui-surface/definitions.ts +6 -5
- package/src/tts/__tests__/provider-adapters.test.ts +76 -2
- package/src/tts/providers/elevenlabs-provider.ts +75 -1
- package/src/types/onboarding-context.ts +2 -0
- package/src/util/errors.ts +17 -0
- package/src/util/platform.ts +10 -0
- package/src/watcher/__tests__/engine.test.ts +22 -0
- package/src/watcher/engine.ts +6 -2
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
- package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
- package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
- package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
- package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/migrations/runner.ts +39 -9
- package/src/workspace/migrations/types.ts +4 -0
- package/examples/plugins/echo/bun.lock +0 -25
- package/src/__tests__/context-window-manager.test.ts +0 -2481
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
- package/src/context/__tests__/compact-prompt.test.ts +0 -63
- package/src/context/prompts/compact.md +0 -26
- package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
- package/src/runtime/guardian-action-conversation-turn.ts +0 -99
|
@@ -16,6 +16,35 @@ export interface ClassifiedConversationError {
|
|
|
16
16
|
debugDetails?: string;
|
|
17
17
|
/** Machine-readable error category for log report metadata and triage. */
|
|
18
18
|
errorCategory: string;
|
|
19
|
+
/**
|
|
20
|
+
* Name of the `provider_connections` row in play when the error
|
|
21
|
+
* occurred. Forwarded to the wire `ConversationErrorMessage` so chat
|
|
22
|
+
* banners can point users at the specific slot to fix. Only set by
|
|
23
|
+
* classifiers / callers that have the resolved connection in scope —
|
|
24
|
+
* generic regex fallbacks leave it undefined.
|
|
25
|
+
*/
|
|
26
|
+
connectionName?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Name of the resolved profile (`llm.activeProfile` / per-call override)
|
|
29
|
+
* in play when the error occurred. Forwarded to the wire message so
|
|
30
|
+
* banners can name the profile when the connection identifier is
|
|
31
|
+
* generic (e.g. the canonical managed connection). Optional for the
|
|
32
|
+
* same reason as `connectionName`.
|
|
33
|
+
*/
|
|
34
|
+
profileName?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Optional resolved-config context that callers can attach to error
|
|
39
|
+
* classification so the resulting `ConversationErrorMessage` can name the
|
|
40
|
+
* exact connection / profile in play. Used in particular by the chat
|
|
41
|
+
* dispatch sites to make `PROVIDER_INVALID_KEY` and `PROVIDER_NOT_CONFIGURED`
|
|
42
|
+
* actionable (the macOS banner reads these to render "Invalid API key for
|
|
43
|
+
* profile X" instead of a generic "API key required").
|
|
44
|
+
*/
|
|
45
|
+
export interface ConversationErrorAttribution {
|
|
46
|
+
connectionName?: string;
|
|
47
|
+
profileName?: string;
|
|
19
48
|
}
|
|
20
49
|
|
|
21
50
|
// Network-level error patterns (connection refused, timeout, DNS, reset)
|
|
@@ -137,6 +166,20 @@ export interface ErrorContext {
|
|
|
137
166
|
phase: "agent_loop" | "regenerate" | "handler" | "persist";
|
|
138
167
|
/** Whether the abort signal was active when the error occurred. */
|
|
139
168
|
aborted?: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* Optional name of the `provider_connections` row in play. Plumbed by
|
|
171
|
+
* dispatch sites that know the resolved connection (chat agent loop)
|
|
172
|
+
* so credential-related classifications (`PROVIDER_INVALID_KEY`,
|
|
173
|
+
* `PROVIDER_NOT_CONFIGURED`) can name the exact slot to fix.
|
|
174
|
+
*/
|
|
175
|
+
connectionName?: string;
|
|
176
|
+
/**
|
|
177
|
+
* Optional name of the resolved profile in play. Plumbed alongside
|
|
178
|
+
* `connectionName` by dispatch sites; surfaces in the wire message so
|
|
179
|
+
* the macOS chat banner can reference the profile even when the
|
|
180
|
+
* underlying connection name is generic.
|
|
181
|
+
*/
|
|
182
|
+
profileName?: string;
|
|
140
183
|
}
|
|
141
184
|
|
|
142
185
|
/**
|
|
@@ -195,32 +238,43 @@ export function classifyConversationError(
|
|
|
195
238
|
(error instanceof Error ? error.stack : undefined) ?? message;
|
|
196
239
|
const debugDetails = truncateDebugDetails(rawDetails);
|
|
197
240
|
|
|
241
|
+
// Extract optional attribution (connection / profile names) so
|
|
242
|
+
// credential-related classifications can name the exact slot to fix.
|
|
243
|
+
// A `ProviderNotConfiguredError` instance carries its own attribution
|
|
244
|
+
// (from the throw site) which takes priority over context when present.
|
|
245
|
+
const attribution: ConversationErrorAttribution = {
|
|
246
|
+
...(ctx.connectionName ? { connectionName: ctx.connectionName } : {}),
|
|
247
|
+
...(ctx.profileName ? { profileName: ctx.profileName } : {}),
|
|
248
|
+
};
|
|
249
|
+
|
|
198
250
|
// Dedicated classification for missing provider API key
|
|
199
251
|
if (error instanceof ProviderNotConfiguredError) {
|
|
200
252
|
return {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
253
|
+
...providerNotConfiguredClassification({
|
|
254
|
+
connectionName:
|
|
255
|
+
error.connectionName ?? attribution.connectionName,
|
|
256
|
+
profileName: error.profileName ?? attribution.profileName,
|
|
257
|
+
}),
|
|
206
258
|
debugDetails,
|
|
207
259
|
};
|
|
208
260
|
}
|
|
209
261
|
|
|
210
262
|
// Phase-specific overrides
|
|
211
263
|
if (ctx.phase === "regenerate") {
|
|
212
|
-
const base = classifyCore(error, message);
|
|
264
|
+
const base = classifyCore(error, message, attribution);
|
|
213
265
|
return {
|
|
214
266
|
code: "REGENERATE_FAILED",
|
|
215
267
|
userMessage: `Could not regenerate the response. ${base.userMessage}`,
|
|
216
268
|
retryable: true,
|
|
217
269
|
debugDetails,
|
|
218
270
|
errorCategory: `regenerate:${base.errorCategory}`,
|
|
271
|
+
...(base.connectionName ? { connectionName: base.connectionName } : {}),
|
|
272
|
+
...(base.profileName ? { profileName: base.profileName } : {}),
|
|
219
273
|
};
|
|
220
274
|
}
|
|
221
275
|
|
|
222
276
|
// Classify using statusCode (if ProviderError) then regex fallback
|
|
223
|
-
const classified = classifyCore(error, message);
|
|
277
|
+
const classified = classifyCore(error, message, attribution);
|
|
224
278
|
return {
|
|
225
279
|
...classified,
|
|
226
280
|
debugDetails,
|
|
@@ -230,10 +284,16 @@ export function classifyConversationError(
|
|
|
230
284
|
/**
|
|
231
285
|
* Core classification: check ProviderError.statusCode first for
|
|
232
286
|
* deterministic classification, then fall back to regex patterns.
|
|
287
|
+
*
|
|
288
|
+
* `attribution` carries the resolved connection / profile names (when the
|
|
289
|
+
* caller knows them) so credential-related results can name the exact
|
|
290
|
+
* slot for the user to fix. Pass an empty object when no attribution is
|
|
291
|
+
* available — the classifier falls back to a generic message.
|
|
233
292
|
*/
|
|
234
293
|
function classifyCore(
|
|
235
294
|
error: unknown,
|
|
236
295
|
message: string,
|
|
296
|
+
attribution: ConversationErrorAttribution = {},
|
|
237
297
|
): Omit<ClassifiedConversationError, "debugDetails"> {
|
|
238
298
|
// ProviderError with statusCode — deterministic classification
|
|
239
299
|
if (error instanceof ProviderError && error.statusCode !== undefined) {
|
|
@@ -247,39 +307,33 @@ function classifyCore(
|
|
|
247
307
|
};
|
|
248
308
|
}
|
|
249
309
|
if (error.statusCode === 401 || error.statusCode === 403) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
code: "MANAGED_KEY_INVALID",
|
|
261
|
-
userMessage:
|
|
262
|
-
"The assistant API key is invalid. Attempting to re-provision…",
|
|
263
|
-
retryable: true,
|
|
264
|
-
errorCategory: "managed_key_invalid",
|
|
265
|
-
};
|
|
266
|
-
}
|
|
310
|
+
// Both managed-proxy and user-key 401/403s reach this branch.
|
|
311
|
+
// Managed-proxy routes through the assistant API key (stale → re-
|
|
312
|
+
// provision) and emits `MANAGED_KEY_INVALID`; everything else is a
|
|
313
|
+
// user-set credential that the upstream provider rejected → emit
|
|
314
|
+
// `PROVIDER_INVALID_KEY` so the macOS chat banner renders an
|
|
315
|
+
// "Invalid API key" surface (distinct from "API key required"
|
|
316
|
+
// which only fires when the key is genuinely missing — see
|
|
317
|
+
// `providerNotConfiguredClassification`).
|
|
318
|
+
const providerName = error.provider;
|
|
319
|
+
if (getProviderRoutingSource(providerName) === "managed-proxy") {
|
|
267
320
|
return {
|
|
268
|
-
code: "
|
|
321
|
+
code: "MANAGED_KEY_INVALID",
|
|
269
322
|
userMessage:
|
|
270
|
-
"
|
|
271
|
-
retryable:
|
|
272
|
-
errorCategory: "
|
|
323
|
+
"The assistant API key is invalid. Attempting to re-provision…",
|
|
324
|
+
retryable: true,
|
|
325
|
+
errorCategory: "managed_key_invalid",
|
|
273
326
|
};
|
|
274
327
|
}
|
|
328
|
+
return invalidApiKeyClassification(attribution);
|
|
275
329
|
}
|
|
276
330
|
if (error.statusCode === 401) {
|
|
277
331
|
return {
|
|
278
|
-
code: "
|
|
332
|
+
code: "PROVIDER_INVALID_KEY",
|
|
279
333
|
userMessage:
|
|
280
334
|
"Your API key is invalid or expired. Update it in Settings or switch to managed mode.",
|
|
281
335
|
retryable: false,
|
|
282
|
-
errorCategory: "
|
|
336
|
+
errorCategory: "provider_invalid_key",
|
|
283
337
|
};
|
|
284
338
|
}
|
|
285
339
|
if (error.statusCode === 402) {
|
|
@@ -369,13 +423,10 @@ function classifyCore(
|
|
|
369
423
|
message,
|
|
370
424
|
)
|
|
371
425
|
) {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
retryable: false,
|
|
377
|
-
errorCategory: "provider_not_configured",
|
|
378
|
-
};
|
|
426
|
+
// Mirror the 401/403 branch: a credential-shaped 4xx is an
|
|
427
|
+
// "invalid key" surface (banner: "Invalid API key"), distinct
|
|
428
|
+
// from "no key configured" (banner: "API key required").
|
|
429
|
+
return invalidApiKeyClassification(attribution);
|
|
379
430
|
}
|
|
380
431
|
if (isImageDimensionsTooLarge(message)) {
|
|
381
432
|
return {
|
|
@@ -477,6 +528,80 @@ function providerBillingClassification(): Omit<
|
|
|
477
528
|
};
|
|
478
529
|
}
|
|
479
530
|
|
|
531
|
+
/**
|
|
532
|
+
* Build a user-facing message that names the exact profile / connection
|
|
533
|
+
* to fix when one is known, falling back to a generic phrase otherwise.
|
|
534
|
+
* Profile is preferred because that's the entity the user picks in the
|
|
535
|
+
* chat picker; connection is shown when no profile is in play (e.g.
|
|
536
|
+
* `llm.default` direct dispatch) or as a parenthetical when both differ.
|
|
537
|
+
*/
|
|
538
|
+
function describeAttribution(
|
|
539
|
+
attribution: ConversationErrorAttribution | undefined,
|
|
540
|
+
): string {
|
|
541
|
+
if (!attribution) return "";
|
|
542
|
+
const { profileName, connectionName } = attribution;
|
|
543
|
+
if (profileName && connectionName && profileName !== connectionName) {
|
|
544
|
+
return ` for profile "${profileName}" (connection "${connectionName}")`;
|
|
545
|
+
}
|
|
546
|
+
if (profileName) return ` for profile "${profileName}"`;
|
|
547
|
+
if (connectionName) return ` for connection "${connectionName}"`;
|
|
548
|
+
return "";
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Classification for an invalid (rejected by the upstream provider, e.g.
|
|
553
|
+
* Anthropic 401/403) API key. Distinct from `PROVIDER_NOT_CONFIGURED`
|
|
554
|
+
* (which is for a key that was never set) so the macOS chat banner can
|
|
555
|
+
* render "Invalid API key" rather than "API key required" — they have
|
|
556
|
+
* different recovery actions (update vs. add).
|
|
557
|
+
*/
|
|
558
|
+
function invalidApiKeyClassification(
|
|
559
|
+
attribution?: ConversationErrorAttribution,
|
|
560
|
+
): Omit<ClassifiedConversationError, "debugDetails"> {
|
|
561
|
+
const target = describeAttribution(attribution);
|
|
562
|
+
return {
|
|
563
|
+
code: "PROVIDER_INVALID_KEY",
|
|
564
|
+
userMessage: target
|
|
565
|
+
? `The API key${target} was rejected by the provider. Update it in Settings.`
|
|
566
|
+
: "Your API key was rejected by the provider. Update it in Settings.",
|
|
567
|
+
retryable: false,
|
|
568
|
+
errorCategory: "provider_invalid_key",
|
|
569
|
+
...(attribution?.connectionName
|
|
570
|
+
? { connectionName: attribution.connectionName }
|
|
571
|
+
: {}),
|
|
572
|
+
...(attribution?.profileName
|
|
573
|
+
? { profileName: attribution.profileName }
|
|
574
|
+
: {}),
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Classification for a genuinely-missing provider credential — vault has
|
|
580
|
+
* no entry for the resolved connection's `auth.credential`, or no
|
|
581
|
+
* provider is registered at all. The macOS chat banner renders this as
|
|
582
|
+
* "API key required" with an "Open Settings" CTA. Distinct from
|
|
583
|
+
* `PROVIDER_INVALID_KEY` (where a key exists but was rejected).
|
|
584
|
+
*/
|
|
585
|
+
function providerNotConfiguredClassification(
|
|
586
|
+
attribution?: ConversationErrorAttribution,
|
|
587
|
+
): Omit<ClassifiedConversationError, "debugDetails"> {
|
|
588
|
+
const target = describeAttribution(attribution);
|
|
589
|
+
return {
|
|
590
|
+
code: "PROVIDER_NOT_CONFIGURED",
|
|
591
|
+
userMessage: target
|
|
592
|
+
? `No API key configured${target}. Add one in Settings to start chatting.`
|
|
593
|
+
: "No API key configured for inference. Add one in Settings to start chatting.",
|
|
594
|
+
retryable: true,
|
|
595
|
+
errorCategory: "provider_not_configured",
|
|
596
|
+
...(attribution?.connectionName
|
|
597
|
+
? { connectionName: attribution.connectionName }
|
|
598
|
+
: {}),
|
|
599
|
+
...(attribution?.profileName
|
|
600
|
+
? { profileName: attribution.profileName }
|
|
601
|
+
: {}),
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
|
|
480
605
|
function classifyByMessage(
|
|
481
606
|
error: unknown,
|
|
482
607
|
message: string,
|
|
@@ -650,5 +775,14 @@ export function buildConversationErrorMessage(
|
|
|
650
775
|
retryable: classified.retryable,
|
|
651
776
|
debugDetails: classified.debugDetails,
|
|
652
777
|
errorCategory: classified.errorCategory,
|
|
778
|
+
// Optional attribution — only forwarded when the classifier was able
|
|
779
|
+
// to pin the failure to a specific provider connection / profile.
|
|
780
|
+
// The macOS chat banner reads these to render targeted CTAs.
|
|
781
|
+
...(classified.connectionName
|
|
782
|
+
? { connectionName: classified.connectionName }
|
|
783
|
+
: {}),
|
|
784
|
+
...(classified.profileName
|
|
785
|
+
? { profileName: classified.profileName }
|
|
786
|
+
: {}),
|
|
653
787
|
};
|
|
654
788
|
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from "../memory/conversation-crud.js";
|
|
19
19
|
import { enqueueMemoryJob } from "../memory/jobs-store.js";
|
|
20
20
|
import { enqueueMemoryRetrospectiveIfEnabled } from "../memory/memory-retrospective-enqueue.js";
|
|
21
|
+
import { shouldExposePersonalMemory } from "../memory/v2/static-context.js";
|
|
21
22
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
22
23
|
import type { SecretPrompter } from "../permissions/secret-prompter.js";
|
|
23
24
|
import type { ContentBlock, Message } from "../providers/types.js";
|
|
@@ -31,12 +32,14 @@ import { getLogger } from "../util/logger.js";
|
|
|
31
32
|
import { unregisterCallNotifiers } from "./conversation-notifiers.js";
|
|
32
33
|
import type { MessageQueue } from "./conversation-queue-manager.js";
|
|
33
34
|
import { resetSkillToolProjection } from "./conversation-skill-tools.js";
|
|
35
|
+
import { resolveTrustClass } from "./conversation-tool-setup.js";
|
|
34
36
|
import { repairHistory } from "./history-repair.js";
|
|
35
37
|
import type {
|
|
36
38
|
SurfaceData,
|
|
37
39
|
SurfaceType,
|
|
38
40
|
UsageStats,
|
|
39
41
|
} from "./message-protocol.js";
|
|
42
|
+
import type { TrustContext } from "./trust-context.js";
|
|
40
43
|
|
|
41
44
|
const log = getLogger("conversation-lifecycle");
|
|
42
45
|
|
|
@@ -113,8 +116,9 @@ export interface LoadFromDbContext {
|
|
|
113
116
|
usageStats: UsageStats;
|
|
114
117
|
contextCompactedMessageCount: number;
|
|
115
118
|
contextCompactedAt: number | null;
|
|
116
|
-
trustContext?:
|
|
119
|
+
trustContext?: TrustContext;
|
|
117
120
|
loadedHistoryTrustClass?: TrustClass;
|
|
121
|
+
loadedHistoryPersonalMemoryAllowed?: boolean;
|
|
118
122
|
}
|
|
119
123
|
|
|
120
124
|
export interface AbortContext {
|
|
@@ -184,7 +188,16 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
|
184
188
|
ctx.contextCompactedAt = conv?.contextCompactedAt ?? null;
|
|
185
189
|
}
|
|
186
190
|
|
|
187
|
-
|
|
191
|
+
// Mirror the injection-time gate (`shouldExposePersonalMemory` in
|
|
192
|
+
// `conversation-agent-loop.ts`) so background/local conversations
|
|
193
|
+
// (sourceChannel `undefined` or `"vellum"`) can rehydrate the persisted
|
|
194
|
+
// v2 static memory block. Use `resolveTrustClass` for parity with the
|
|
195
|
+
// agent loop — it folds in the HTTP-auth-disabled dev bypass so
|
|
196
|
+
// rehydration and injection agree on the effective trust class.
|
|
197
|
+
const personalMemoryAllowed = shouldExposePersonalMemory({
|
|
198
|
+
sourceChannel: ctx.trustContext?.sourceChannel,
|
|
199
|
+
isTrustedActor: resolveTrustClass(ctx.trustContext) === "guardian",
|
|
200
|
+
});
|
|
188
201
|
const parsedMessages: Message[] = dbMessages
|
|
189
202
|
.slice(ctx.contextCompactedMessageCount)
|
|
190
203
|
.map((m, index, arr) => {
|
|
@@ -212,21 +225,19 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
|
212
225
|
const meta = JSON.parse(m.metadata);
|
|
213
226
|
const isTail = index === arr.length - 1;
|
|
214
227
|
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
//
|
|
224
|
-
// prefix cache keeps matching msg[0]
|
|
225
|
-
// conversation eviction. The tail
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
// cannot reconstruct (currently just `memoryInjectedBlock`, which
|
|
229
|
-
// is not always re-injected on the next turn).
|
|
228
|
+
// Rehydrate in reverse injection order (innermost block first)
|
|
229
|
+
// so the resulting layout matches `applyRuntimeInjections`'s
|
|
230
|
+
// after-memory-prefix splices in ascending injector order
|
|
231
|
+
// (pkb-context 30, pkb-reminder 35, memory-v2-static 38,
|
|
232
|
+
// now-md 40 — the v2 static block lands inside the memory
|
|
233
|
+
// prefix, so now-md splices *after* it):
|
|
234
|
+
// [<workspace>, <turn_context>, <memory __injected>,
|
|
235
|
+
// <memory>\n…</memory>, <NOW.md>, <system_reminder>,
|
|
236
|
+
// <knowledge_base>, ...original]
|
|
237
|
+
// Required so Anthropic's prefix cache keeps matching msg[0]
|
|
238
|
+
// across daemon restart and conversation eviction. The tail
|
|
239
|
+
// row only rehydrates `memoryInjectedBlock` — the next turn
|
|
240
|
+
// re-injects the rest fresh.
|
|
230
241
|
if (!isTail && typeof meta.pkbContextBlock === "string") {
|
|
231
242
|
content = [
|
|
232
243
|
{ type: "text" as const, text: meta.pkbContextBlock },
|
|
@@ -241,6 +252,13 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
|
241
252
|
];
|
|
242
253
|
}
|
|
243
254
|
|
|
255
|
+
if (!isTail && typeof meta.nowScratchpadBlock === "string") {
|
|
256
|
+
content = [
|
|
257
|
+
{ type: "text" as const, text: meta.nowScratchpadBlock },
|
|
258
|
+
...content,
|
|
259
|
+
];
|
|
260
|
+
}
|
|
261
|
+
|
|
244
262
|
// The v2 static memory block (essentials/threads/recent/buffer
|
|
245
263
|
// wrapped in `<memory>…</memory>`) carries personal user memory.
|
|
246
264
|
// Trust-gated to mirror `shouldExposePersonalMemory` at injection
|
|
@@ -281,13 +299,6 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
|
281
299
|
];
|
|
282
300
|
}
|
|
283
301
|
|
|
284
|
-
if (!isTail && typeof meta.nowScratchpadBlock === "string") {
|
|
285
|
-
content = [
|
|
286
|
-
{ type: "text" as const, text: meta.nowScratchpadBlock },
|
|
287
|
-
...content,
|
|
288
|
-
];
|
|
289
|
-
}
|
|
290
|
-
|
|
291
302
|
if (!isTail && typeof meta.turnContextBlock === "string") {
|
|
292
303
|
content = [
|
|
293
304
|
{ type: "text" as const, text: meta.turnContextBlock },
|
|
@@ -336,6 +347,7 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
|
|
|
336
347
|
}
|
|
337
348
|
|
|
338
349
|
ctx.loadedHistoryTrustClass = trustClass;
|
|
350
|
+
ctx.loadedHistoryPersonalMemoryAllowed = personalMemoryAllowed;
|
|
339
351
|
|
|
340
352
|
log.info(
|
|
341
353
|
{ conversationId: ctx.conversationId, count: ctx.messages.length },
|
|
@@ -423,6 +435,23 @@ export function disposeConversation(ctx: DisposeContext): void {
|
|
|
423
435
|
// Best-effort — don't block conversation disposal
|
|
424
436
|
}
|
|
425
437
|
}
|
|
438
|
+
|
|
439
|
+
try {
|
|
440
|
+
// Memory-retrospective lifecycle safety-net. The periodic triggers
|
|
441
|
+
// (interval / message_count / pre-compaction) handle the common
|
|
442
|
+
// path; lifecycle catches the gap between the last interval fire
|
|
443
|
+
// and conversation eviction. The job's `no_new_messages` early
|
|
444
|
+
// return makes this a cheap no-op when the periodic path already
|
|
445
|
+
// covered things. Lives inside the `!isAutoAnalysis` guard so
|
|
446
|
+
// auto-analysis conversations don't trigger retrospective enqueues
|
|
447
|
+
// on disposal — mirrors the indexer-time gate in `indexer.ts`.
|
|
448
|
+
enqueueMemoryRetrospectiveIfEnabled({
|
|
449
|
+
conversationId: ctx.conversationId,
|
|
450
|
+
trigger: "lifecycle",
|
|
451
|
+
});
|
|
452
|
+
} catch {
|
|
453
|
+
// Best-effort — don't block conversation disposal
|
|
454
|
+
}
|
|
426
455
|
}
|
|
427
456
|
|
|
428
457
|
try {
|
|
@@ -436,22 +465,6 @@ export function disposeConversation(ctx: DisposeContext): void {
|
|
|
436
465
|
} catch {
|
|
437
466
|
// Best-effort — don't block conversation disposal
|
|
438
467
|
}
|
|
439
|
-
|
|
440
|
-
try {
|
|
441
|
-
// Memory-retrospective lifecycle safety-net. The periodic triggers
|
|
442
|
-
// (interval / message_count / pre-compaction) handle the common
|
|
443
|
-
// path; lifecycle catches the gap between the last interval fire
|
|
444
|
-
// and conversation eviction. The job's `no_new_messages` early
|
|
445
|
-
// return makes this a cheap no-op when the periodic path already
|
|
446
|
-
// covered things. `enqueueMemoryRetrospectiveIfEnabled` has its
|
|
447
|
-
// own internal recursion guard.
|
|
448
|
-
enqueueMemoryRetrospectiveIfEnabled({
|
|
449
|
-
conversationId: ctx.conversationId,
|
|
450
|
-
trigger: "lifecycle",
|
|
451
|
-
});
|
|
452
|
-
} catch {
|
|
453
|
-
// Best-effort — don't block conversation disposal
|
|
454
|
-
}
|
|
455
468
|
}
|
|
456
469
|
|
|
457
470
|
abortConversation(
|
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
import { v4 as uuid } from "uuid";
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
enrichMessageWithSourcePaths,
|
|
12
|
+
type MessageAttachmentInput,
|
|
13
|
+
} from "../agent/attachments.js";
|
|
11
14
|
import { createUserMessage } from "../agent/message-types.js";
|
|
12
15
|
import type {
|
|
13
16
|
TurnChannelContext,
|
|
@@ -191,6 +194,19 @@ export interface MessagingConversationContext {
|
|
|
191
194
|
getTurnInterfaceContext(): TurnInterfaceContext | null;
|
|
192
195
|
}
|
|
193
196
|
|
|
197
|
+
export function serializePersistedUserMessageContent(
|
|
198
|
+
content: string,
|
|
199
|
+
attachments: MessageAttachmentInput[],
|
|
200
|
+
displayContent: string | undefined,
|
|
201
|
+
): string {
|
|
202
|
+
return JSON.stringify(
|
|
203
|
+
createUserMessage(
|
|
204
|
+
displayContent !== undefined ? displayContent : content,
|
|
205
|
+
attachments,
|
|
206
|
+
).content,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
194
210
|
function extractTurnChannelContext(
|
|
195
211
|
metadata?: Record<string, unknown>,
|
|
196
212
|
): TurnChannelContext | null {
|
|
@@ -258,6 +274,9 @@ export function buildSlackMetaForPersistence(params: {
|
|
|
258
274
|
eventKind: "message",
|
|
259
275
|
...(candidate.threadTs ? { threadTs: candidate.threadTs } : {}),
|
|
260
276
|
...(candidate.displayName ? { displayName: candidate.displayName } : {}),
|
|
277
|
+
...(candidate.actorExternalUserId
|
|
278
|
+
? { actorExternalUserId: candidate.actorExternalUserId }
|
|
279
|
+
: {}),
|
|
261
280
|
};
|
|
262
281
|
return writeSlackMetadata(slackMeta);
|
|
263
282
|
}
|
|
@@ -454,11 +473,11 @@ export async function persistQueuedMessageBody(
|
|
|
454
473
|
// intent stripping), persist that to DB so users see the full message
|
|
455
474
|
// after restart. The in-memory userMessage (sent to the LLM) still uses
|
|
456
475
|
// the stripped content.
|
|
457
|
-
const contentToPersist =
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
476
|
+
const contentToPersist = serializePersistedUserMessageContent(
|
|
477
|
+
content,
|
|
478
|
+
attachmentInputs,
|
|
479
|
+
displayContent,
|
|
480
|
+
);
|
|
462
481
|
const persistedUserMessage = await addMessage(
|
|
463
482
|
ctx.conversationId,
|
|
464
483
|
"user",
|