@vellumai/assistant 0.8.7 → 0.8.8
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/Dockerfile +20 -4
- package/docker-entrypoint.sh +4 -2
- package/docker-init-apt-root.sh +3 -1
- package/docker-kata-apt-env.sh +3 -1
- package/docker-kata-runtime-family.sh +12 -0
- package/docs/architecture/memory.md +1 -1
- package/docs/plugins.md +75 -79
- package/examples/plugins/echo/README.md +6 -12
- package/examples/plugins/echo/register.ts +0 -41
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
- package/openapi.yaml +3381 -348
- package/package.json +1 -1
- package/scripts/generate-openapi.ts +68 -41
- package/src/__tests__/agent-loop-exit-reason.test.ts +34 -39
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +37 -87
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
- package/src/__tests__/annotate-risk-options.test.ts +2 -3
- package/src/__tests__/anthropic-provider.test.ts +95 -2
- package/src/__tests__/assistant-event-hub.test.ts +25 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
- package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
- package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
- package/src/__tests__/btw-routes.test.ts +62 -3
- package/src/__tests__/build-persisted-content.test.ts +184 -0
- package/src/__tests__/catalog-files.test.ts +1 -1
- package/src/__tests__/clawhub-files.test.ts +1 -1
- package/src/__tests__/compaction-pipeline.test.ts +1 -1
- package/src/__tests__/compaction.benchmark.test.ts +0 -30
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +313 -1136
- package/src/__tests__/conversation-agent-loop.test.ts +596 -1616
- package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
- package/src/__tests__/conversation-history-web-search.test.ts +11 -1
- package/src/__tests__/conversation-pairing.test.ts +4 -31
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +26 -5
- package/src/__tests__/conversation-queue.test.ts +2 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
- package/src/__tests__/conversation-runtime-assembly.test.ts +170 -229
- package/src/__tests__/conversation-runtime-workspace.test.ts +3 -24
- package/src/__tests__/conversation-slash-commands.test.ts +8 -42
- package/src/__tests__/conversation-slash-queue.test.ts +6 -1
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
- package/src/__tests__/conversation-sync-tags.test.ts +27 -15
- package/src/__tests__/conversation-title-service.test.ts +135 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
- package/src/__tests__/cross-provider-web-search.test.ts +214 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
- package/src/__tests__/dm-persistence.test.ts +5 -1
- package/src/__tests__/empty-response-hook.test.ts +304 -0
- package/src/__tests__/feature-flag-test-helpers.ts +2 -2
- package/src/__tests__/gemini-image-service.test.ts +13 -0
- package/src/__tests__/helpers/mock-provider.ts +110 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
- package/src/__tests__/history-repair-hook.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +12 -100
- package/src/__tests__/identity-routes.test.ts +248 -7
- package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
- package/src/__tests__/injector-background-turn.test.ts +2 -8
- package/src/__tests__/injector-chain.test.ts +106 -270
- package/src/__tests__/injector-disk-pressure.test.ts +3 -12
- package/src/__tests__/injector-document-comments.test.ts +2 -2
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
- package/src/__tests__/injector-v3-suppression.test.ts +31 -37
- package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
- package/src/__tests__/list-messages-page-latest.test.ts +60 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
- package/src/__tests__/llm-usage-store.test.ts +223 -1
- package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
- package/src/__tests__/native-web-search.test.ts +191 -0
- package/src/__tests__/onboarding-template-contract.test.ts +2 -0
- package/src/__tests__/openai-image-service.test.ts +17 -0
- package/src/__tests__/openai-provider.test.ts +31 -1
- package/src/__tests__/persist-unsendable-image.test.ts +215 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
- package/src/__tests__/pipeline-runner.test.ts +29 -39
- package/src/__tests__/pkb-autoinject.test.ts +2 -5
- package/src/__tests__/plugin-bootstrap.test.ts +13 -28
- package/src/__tests__/plugin-registry.test.ts +0 -27
- package/src/__tests__/plugin-types.test.ts +2 -125
- package/src/__tests__/process-message-display-content.test.ts +6 -2
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
- package/src/__tests__/resolve-trust-class.test.ts +4 -4
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
- package/src/__tests__/schedule-routes.test.ts +603 -2
- package/src/__tests__/schedule-store.test.ts +41 -0
- package/src/__tests__/schedule-tools.test.ts +35 -0
- package/src/__tests__/server-history-render.test.ts +314 -1
- package/src/__tests__/skillssh-files.test.ts +1 -1
- package/src/__tests__/system-prompt.test.ts +20 -0
- package/src/__tests__/task-scheduler.test.ts +162 -1
- package/src/__tests__/terminal-tools.test.ts +6 -1
- package/src/__tests__/title-generate-hook.test.ts +319 -0
- package/src/__tests__/tool-error-hook.test.ts +278 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -2
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
- package/src/__tests__/ui-work-result-surface.test.ts +159 -0
- package/src/__tests__/usage-routes.test.ts +285 -1
- package/src/__tests__/user-plugin-loader.test.ts +2 -2
- package/src/__tests__/voice-session-bridge.test.ts +6 -3
- package/src/__tests__/web-search-backend-failure.test.ts +166 -0
- package/src/agent/loop.ts +346 -442
- package/src/api/events/assistant-thinking-delta.ts +33 -0
- package/src/api/events/tool-output-chunk.ts +45 -0
- package/src/api/events/tool-use-preview-start.ts +32 -0
- package/src/api/events/trace-event.ts +69 -0
- package/src/api/index.ts +48 -13
- package/src/api/responses/conversation-message.ts +368 -0
- package/src/avatar/__tests__/avatar-store.test.ts +34 -29
- package/src/cli/commands/__tests__/notifications.test.ts +58 -14
- package/src/cli/commands/notifications.ts +112 -60
- package/src/config/assistant-feature-flags.ts +22 -11
- package/src/config/bundled-skills/app-builder/SKILL.md +3 -20
- package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
- package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
- package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
- package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
- package/src/config/bundled-skills/document-editor/SKILL.md +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +0 -7
- package/src/config/feature-flag-cache.ts +3 -3
- package/src/config/feature-flag-registry.json +35 -3
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-v2.ts +8 -0
- package/src/config/schemas/memory-v3.ts +8 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/seed-inference-profiles.ts +2 -2
- package/src/config/skills.ts +13 -0
- package/src/context/compactor.ts +1 -1
- package/src/context/strip-injections.ts +122 -0
- package/src/context/token-estimator.ts +23 -0
- package/src/context/tool-result-truncation.ts +0 -23
- package/src/context/window-manager.ts +3 -6
- package/src/credential-execution/executable-discovery.ts +16 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
- package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
- package/src/daemon/assistant-attachments.ts +1 -1
- package/src/daemon/config-watcher.ts +2 -2
- package/src/daemon/context-overflow-reducer.ts +0 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +605 -153
- package/src/daemon/conversation-agent-loop.ts +281 -760
- package/src/daemon/conversation-history.ts +5 -4
- package/src/daemon/conversation-lifecycle.ts +3 -4
- package/src/daemon/conversation-messaging.ts +7 -6
- package/src/daemon/conversation-process.ts +11 -16
- package/src/daemon/conversation-runtime-assembly.ts +130 -347
- package/src/daemon/conversation-slash.ts +6 -25
- package/src/daemon/conversation-surfaces.ts +222 -4
- package/src/daemon/conversation-tool-setup.ts +2 -29
- package/src/daemon/conversation.ts +32 -14
- package/src/daemon/external-plugins-bootstrap.ts +9 -10
- package/src/daemon/handlers/config-a2a.ts +51 -36
- package/src/daemon/handlers/config-slack-channel.ts +20 -14
- package/src/daemon/handlers/config-telegram.ts +16 -2
- package/src/daemon/handlers/shared.ts +156 -84
- package/src/daemon/handlers/skills.ts +39 -10
- package/src/daemon/lifecycle.ts +4 -0
- package/src/daemon/message-types/apps.ts +1 -29
- package/src/daemon/message-types/messages.ts +9 -57
- package/src/daemon/message-types/skills.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +136 -3
- package/src/daemon/now-scratchpad.ts +21 -0
- package/src/daemon/orphan-reaper.test.ts +210 -0
- package/src/daemon/orphan-reaper.ts +240 -0
- package/src/daemon/persist-unsendable-image.ts +117 -0
- package/src/daemon/process-message.ts +1 -3
- package/src/daemon/trace-emitter.ts +6 -4
- package/src/daemon/trust-context.ts +19 -0
- package/src/daemon/wake-target-adapter.ts +3 -1
- package/src/home/home-greeting-cache.ts +24 -1
- package/src/ipc/gateway-client.test.ts +2 -2
- package/src/ipc/gateway-client.ts +3 -3
- package/src/media/gemini-image-service.ts +15 -0
- package/src/media/openai-image-service.ts +14 -0
- package/src/media/types.ts +34 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
- package/src/memory/auth-fallback-events-store.ts +94 -0
- package/src/memory/conversation-title-service.ts +65 -41
- package/src/memory/db-init.ts +4 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
- package/src/memory/graph/conversation-graph-memory.ts +65 -0
- package/src/memory/jobs-store.ts +33 -0
- package/src/memory/jobs-worker.ts +31 -4
- package/src/memory/llm-usage-store.ts +224 -50
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
- package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
- package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/pkb/autoinject.ts +61 -0
- package/src/memory/pkb/context.ts +50 -0
- package/src/memory/pkb/types.ts +14 -0
- package/src/memory/schedule-attribution-sql.ts +104 -0
- package/src/memory/schema/infrastructure.ts +16 -0
- package/src/memory/usage-grouped-buckets.ts +6 -1
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -1
- package/src/memory/v2/consolidation-job.ts +1 -1
- package/src/memory/v3/__tests__/health.test.ts +16 -0
- package/src/memory/v3/__tests__/orchestrate.test.ts +45 -9
- package/src/memory/v3/__tests__/provider-blocks.test.ts +13 -0
- package/src/memory/v3/__tests__/router.test.ts +101 -29
- package/src/memory/v3/__tests__/selector.test.ts +93 -27
- package/src/memory/v3/__tests__/shadow-plugin.test.ts +23 -5
- package/src/memory/v3/health.ts +0 -0
- package/src/memory/v3/llm-retry.ts +32 -0
- package/src/memory/v3/orchestrate.ts +26 -14
- package/src/memory/v3/provider-blocks.ts +15 -5
- package/src/memory/v3/router.ts +48 -42
- package/src/memory/v3/selector.ts +57 -42
- package/src/memory/v3/shadow-plugin.ts +47 -15
- package/src/memory/v3/types.ts +8 -0
- package/src/notifications/conversation-pairing.ts +8 -15
- package/src/notifications/decision-engine.ts +6 -3
- package/src/notifications/home-feed-side-effect.ts +12 -1
- package/src/permissions/prompter.ts +4 -0
- package/src/plugin-api/constants.ts +4 -0
- package/src/plugin-api/index.ts +8 -1
- package/src/plugin-api/types.ts +151 -1
- package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
- package/src/plugins/defaults/empty-response/register.ts +8 -13
- package/src/plugins/defaults/index.ts +1 -15
- package/src/plugins/defaults/injectors/register.ts +243 -74
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +91 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
- package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
- package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/title-generate/package.json +1 -1
- package/src/plugins/defaults/title-generate/register.ts +18 -18
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
- package/src/plugins/defaults/tool-error/package.json +1 -1
- package/src/plugins/defaults/tool-error/register.ts +9 -21
- package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
- package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
- package/src/plugins/pipeline.ts +6 -18
- package/src/plugins/registry.ts +8 -25
- package/src/plugins/types.ts +43 -474
- package/src/proactive-artifact/aux-message-injector.ts +3 -3
- package/src/proactive-artifact/job.test.ts +7 -12
- package/src/prompts/__tests__/system-prompt.test.ts +36 -0
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +62 -0
- package/src/prompts/templates/BOOTSTRAP.md +2 -2
- package/src/prompts/templates/system-sections.ts +15 -0
- package/src/providers/anthropic/client.ts +37 -29
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
- package/src/providers/openai/chat-completions-provider.ts +44 -0
- package/src/providers/openrouter/client.ts +1 -0
- package/src/providers/placeholder-sentinels.ts +35 -0
- package/src/runtime/__tests__/agent-wake.test.ts +5 -1
- package/src/runtime/agent-wake.ts +2 -2
- package/src/runtime/assistant-event-hub.ts +36 -6
- package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
- package/src/runtime/http-router.ts +16 -21
- package/src/runtime/http-types.ts +16 -70
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/app-management-routes.ts +6 -117
- package/src/runtime/routes/app-routes.ts +13 -15
- package/src/runtime/routes/attachment-routes.ts +26 -15
- package/src/runtime/routes/avatar-routes.ts +26 -0
- package/src/runtime/routes/btw-routes.ts +29 -23
- package/src/runtime/routes/consolidation-routes.ts +120 -20
- package/src/runtime/routes/conversation-query-routes.ts +2 -0
- package/src/runtime/routes/conversation-routes.ts +358 -184
- package/src/runtime/routes/documents-routes.ts +4 -0
- package/src/runtime/routes/domain-routes.ts +51 -37
- package/src/runtime/routes/epoch-millis-range.ts +34 -0
- package/src/runtime/routes/events-routes.ts +28 -34
- package/src/runtime/routes/gateway-log-routes.ts +26 -4
- package/src/runtime/routes/heartbeat-routes.ts +32 -12
- package/src/runtime/routes/identity-intro-cache.ts +11 -34
- package/src/runtime/routes/identity-routes.ts +208 -17
- package/src/runtime/routes/image-generation-routes.ts +40 -2
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/a2a.ts +12 -10
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
- package/src/runtime/routes/integrations/slack/channel.ts +4 -0
- package/src/runtime/routes/integrations/slack/share.ts +27 -6
- package/src/runtime/routes/integrations/telegram.ts +6 -0
- package/src/runtime/routes/integrations/twilio.ts +42 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
- package/src/runtime/routes/log-export-routes.ts +8 -0
- package/src/runtime/routes/memory-v2-routes.ts +15 -8
- package/src/runtime/routes/memory-v3-routes.ts +50 -28
- package/src/runtime/routes/oauth-apps.ts +66 -12
- package/src/runtime/routes/oauth-providers.ts +44 -5
- package/src/runtime/routes/platform-routes.ts +81 -5
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
- package/src/runtime/routes/playground/force-compact.ts +1 -1
- package/src/runtime/routes/rename-conversation-routes.ts +5 -0
- package/src/runtime/routes/schedule-routes.ts +152 -42
- package/src/runtime/routes/secret-routes.ts +14 -2
- package/src/runtime/routes/skills-routes.ts +43 -14
- package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
- package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
- package/src/runtime/routes/trust-rules-routes.ts +26 -2
- package/src/runtime/routes/tts-routes.ts +35 -0
- package/src/runtime/routes/types.ts +66 -8
- package/src/runtime/routes/usage-routes.ts +47 -39
- package/src/runtime/routes/webhook-routes.ts +41 -2
- package/src/runtime/routes/workspace-routes.ts +4 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
- package/src/runtime/services/analyze-conversation.ts +2 -2
- package/src/schedule/schedule-store.ts +20 -1
- package/src/schedule/schedule-usage-store.ts +83 -0
- package/src/schedule/scheduler.ts +12 -5
- package/src/skills/catalog-files.ts +2 -2
- package/src/skills/catalog-install.ts +3 -0
- package/src/skills/categories-cache.ts +118 -0
- package/src/skills/clawhub-files.ts +1 -2
- package/src/skills/skillssh-files.ts +1 -2
- package/src/telemetry/types.ts +29 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
- package/src/telemetry/usage-telemetry-reporter.ts +57 -2
- package/src/tools/executor.ts +1 -53
- package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
- package/src/tools/network/__tests__/web-search.test.ts +11 -3
- package/src/tools/network/web-search-error.test.ts +248 -0
- package/src/tools/network/web-search-error.ts +267 -0
- package/src/tools/network/web-search.ts +207 -48
- package/src/tools/schedule/create.ts +2 -0
- package/src/tools/terminal/safe-env.ts +10 -1
- package/src/tools/ui-surface/definitions.ts +9 -1
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
- package/src/tts/provider-catalog.ts +76 -1
- package/src/util/mutex.ts +47 -0
- package/src/workspace/git-service.ts +1 -42
- package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
- package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +93 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
- package/src/__tests__/empty-response-pipeline.test.ts +0 -423
- package/src/__tests__/llm-call-pipeline.test.ts +0 -287
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
- package/src/__tests__/persistence-pipeline.test.ts +0 -503
- package/src/__tests__/title-generate-pipeline.test.ts +0 -211
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
- package/src/__tests__/tool-error-pipeline.test.ts +0 -241
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
- package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
- package/src/gallery/default-gallery.ts +0 -1359
- package/src/gallery/gallery-manifest.ts +0 -28
- package/src/home/feature-gate.ts +0 -22
- package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
- package/src/plugins/defaults/empty-response/terminal.ts +0 -106
- package/src/plugins/defaults/injectors/package.json +0 -15
- package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
- package/src/plugins/defaults/llm-call/package.json +0 -15
- package/src/plugins/defaults/llm-call/register.ts +0 -45
- package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
- package/src/plugins/defaults/memory-retrieval/package.json +0 -15
- package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
- package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
- package/src/plugins/defaults/persistence/package.json +0 -15
- package/src/plugins/defaults/persistence/register.ts +0 -38
- package/src/plugins/defaults/persistence/terminal.ts +0 -83
- package/src/plugins/defaults/title-generate/terminal.ts +0 -31
- package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
- package/src/plugins/defaults/token-estimate/package.json +0 -15
- package/src/plugins/defaults/token-estimate/register.ts +0 -34
- package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
- package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
- package/src/plugins/defaults/tool-error/terminal.ts +0 -47
- package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
- package/src/plugins/defaults/tool-execute/package.json +0 -15
- package/src/plugins/defaults/tool-execute/register.ts +0 -49
- package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
- package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
- package/src/skills/category-inference.ts +0 -111
|
@@ -38,10 +38,13 @@ import type { HostAppControlProxy } from "./host-app-control-proxy.js";
|
|
|
38
38
|
import type { HostCuProxy } from "./host-cu-proxy.js";
|
|
39
39
|
import type {
|
|
40
40
|
CardSurfaceData,
|
|
41
|
+
ChoiceSurfaceData,
|
|
41
42
|
ConfirmationSurfaceData,
|
|
43
|
+
CopyBlockSurfaceData,
|
|
42
44
|
DynamicPageSurfaceData,
|
|
43
45
|
FormSurfaceData,
|
|
44
46
|
ListSurfaceData,
|
|
47
|
+
OAuthConnectSurfaceData,
|
|
45
48
|
ServerMessage,
|
|
46
49
|
SurfaceData,
|
|
47
50
|
SurfaceType,
|
|
@@ -395,6 +398,107 @@ function normalizeTaskProgressCardPatch(
|
|
|
395
398
|
return normalizedPatch;
|
|
396
399
|
}
|
|
397
400
|
|
|
401
|
+
function normalizeChoiceShowData(
|
|
402
|
+
rawData: Record<string, unknown>,
|
|
403
|
+
): ChoiceSurfaceData {
|
|
404
|
+
const options = Array.isArray(rawData.options)
|
|
405
|
+
? rawData.options
|
|
406
|
+
.filter((option): option is Record<string, unknown> =>
|
|
407
|
+
isPlainObject(option),
|
|
408
|
+
)
|
|
409
|
+
.map((option) => {
|
|
410
|
+
const id = typeof option.id === "string" ? option.id.trim() : "";
|
|
411
|
+
const title =
|
|
412
|
+
typeof option.title === "string"
|
|
413
|
+
? option.title.trim()
|
|
414
|
+
: typeof option.label === "string"
|
|
415
|
+
? option.label.trim()
|
|
416
|
+
: "";
|
|
417
|
+
if (!id || !title) return null;
|
|
418
|
+
return {
|
|
419
|
+
id,
|
|
420
|
+
title,
|
|
421
|
+
...(typeof option.description === "string"
|
|
422
|
+
? { description: option.description }
|
|
423
|
+
: {}),
|
|
424
|
+
...(option.recommended === true ? { recommended: true } : {}),
|
|
425
|
+
...(isPlainObject(option.data)
|
|
426
|
+
? { data: option.data as Record<string, unknown> }
|
|
427
|
+
: {}),
|
|
428
|
+
};
|
|
429
|
+
})
|
|
430
|
+
.filter(
|
|
431
|
+
(option): option is NonNullable<typeof option> => option !== null,
|
|
432
|
+
)
|
|
433
|
+
: [];
|
|
434
|
+
|
|
435
|
+
return {
|
|
436
|
+
...(typeof rawData.description === "string"
|
|
437
|
+
? { description: rawData.description }
|
|
438
|
+
: {}),
|
|
439
|
+
options,
|
|
440
|
+
selectionMode: rawData.selectionMode === "multiple" ? "multiple" : "single",
|
|
441
|
+
...(typeof rawData.submitLabel === "string"
|
|
442
|
+
? { submitLabel: rawData.submitLabel }
|
|
443
|
+
: {}),
|
|
444
|
+
...(typeof rawData.commitOnSelect === "boolean"
|
|
445
|
+
? { commitOnSelect: rawData.commitOnSelect }
|
|
446
|
+
: {}),
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function normalizeCopyBlockShowData(
|
|
451
|
+
rawData: Record<string, unknown>,
|
|
452
|
+
): CopyBlockSurfaceData {
|
|
453
|
+
return {
|
|
454
|
+
text: typeof rawData.text === "string" ? rawData.text : "",
|
|
455
|
+
...(typeof rawData.label === "string" ? { label: rawData.label } : {}),
|
|
456
|
+
...(typeof rawData.language === "string"
|
|
457
|
+
? { language: rawData.language }
|
|
458
|
+
: {}),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function normalizeOAuthConnectShowData(
|
|
463
|
+
rawData: Record<string, unknown>,
|
|
464
|
+
): OAuthConnectSurfaceData {
|
|
465
|
+
return {
|
|
466
|
+
providerKey:
|
|
467
|
+
typeof rawData.providerKey === "string" ? rawData.providerKey.trim() : "",
|
|
468
|
+
...(typeof rawData.displayName === "string"
|
|
469
|
+
? { displayName: rawData.displayName }
|
|
470
|
+
: {}),
|
|
471
|
+
...(typeof rawData.description === "string"
|
|
472
|
+
? { description: rawData.description }
|
|
473
|
+
: {}),
|
|
474
|
+
...(typeof rawData.logoUrl === "string" || rawData.logoUrl === null
|
|
475
|
+
? { logoUrl: rawData.logoUrl }
|
|
476
|
+
: {}),
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function buildChoiceActions(data: ChoiceSurfaceData): Array<{
|
|
481
|
+
id: string;
|
|
482
|
+
label: string;
|
|
483
|
+
style?: string;
|
|
484
|
+
data?: Record<string, unknown>;
|
|
485
|
+
}> {
|
|
486
|
+
return data.options.map((option) => ({
|
|
487
|
+
id: option.id,
|
|
488
|
+
label: option.title,
|
|
489
|
+
style: option.recommended ? "primary" : "secondary",
|
|
490
|
+
data: {
|
|
491
|
+
choiceId: option.id,
|
|
492
|
+
choiceTitle: option.title,
|
|
493
|
+
selectedIds: [option.id],
|
|
494
|
+
selectedTitles: [option.title],
|
|
495
|
+
...(option.description ? { choiceDescription: option.description } : {}),
|
|
496
|
+
...(option.recommended ? { recommended: true } : {}),
|
|
497
|
+
...(option.data ?? {}),
|
|
498
|
+
},
|
|
499
|
+
}));
|
|
500
|
+
}
|
|
501
|
+
|
|
398
502
|
function isTaskProgressCardData(data: SurfaceData | Record<string, unknown>) {
|
|
399
503
|
return (data as Record<string, unknown>).template === "task_progress";
|
|
400
504
|
}
|
|
@@ -1699,6 +1803,8 @@ export async function handleSurfaceAction(
|
|
|
1699
1803
|
// been accepted. Deferred until after rejection check so the surface stays
|
|
1700
1804
|
// active and retryable if the queue was full.
|
|
1701
1805
|
const ONE_SHOT_SURFACE_TYPES = [
|
|
1806
|
+
"choice",
|
|
1807
|
+
"oauth_connect",
|
|
1702
1808
|
"form",
|
|
1703
1809
|
"confirmation",
|
|
1704
1810
|
"file_upload",
|
|
@@ -1860,6 +1966,12 @@ export function buildCompletionSummary(
|
|
|
1860
1966
|
data?: Record<string, unknown>,
|
|
1861
1967
|
surfaceData?: Record<string, unknown>,
|
|
1862
1968
|
): string {
|
|
1969
|
+
const selectedTitles = Array.isArray(data?.selectedTitles)
|
|
1970
|
+
? data.selectedTitles.filter(
|
|
1971
|
+
(title): title is string => typeof title === "string",
|
|
1972
|
+
)
|
|
1973
|
+
: [];
|
|
1974
|
+
|
|
1863
1975
|
if (surfaceType === "confirmation") {
|
|
1864
1976
|
if (actionId === "cancel") {
|
|
1865
1977
|
const cancelLabel =
|
|
@@ -1892,6 +2004,43 @@ export function buildCompletionSummary(
|
|
|
1892
2004
|
if (surfaceType === "form") {
|
|
1893
2005
|
return "Submitted";
|
|
1894
2006
|
}
|
|
2007
|
+
if (surfaceType === "choice" && data) {
|
|
2008
|
+
const choiceTitle =
|
|
2009
|
+
typeof data.choiceTitle === "string" ? data.choiceTitle : undefined;
|
|
2010
|
+
if (choiceTitle) return `User chose: "${choiceTitle}"`;
|
|
2011
|
+
if (selectedTitles.length === 1)
|
|
2012
|
+
return `User chose: "${selectedTitles[0]}"`;
|
|
2013
|
+
if (selectedTitles.length > 1) {
|
|
2014
|
+
return `User chose ${selectedTitles.length} options: ${selectedTitles
|
|
2015
|
+
.map((title) => `"${title}"`)
|
|
2016
|
+
.join(", ")}`;
|
|
2017
|
+
}
|
|
2018
|
+
return `User chose: ${actionId}`;
|
|
2019
|
+
}
|
|
2020
|
+
if (surfaceType === "oauth_connect") {
|
|
2021
|
+
const providerLabel =
|
|
2022
|
+
typeof data?.providerLabel === "string"
|
|
2023
|
+
? data.providerLabel
|
|
2024
|
+
: typeof data?.displayName === "string"
|
|
2025
|
+
? data.displayName
|
|
2026
|
+
: typeof data?.providerKey === "string"
|
|
2027
|
+
? data.providerKey
|
|
2028
|
+
: "OAuth";
|
|
2029
|
+
const accountLabel =
|
|
2030
|
+
typeof data?.accountLabel === "string" ? data.accountLabel : undefined;
|
|
2031
|
+
if (actionId === "connect" || data?.status === "connected") {
|
|
2032
|
+
return accountLabel
|
|
2033
|
+
? `Connected ${providerLabel}: ${accountLabel}`
|
|
2034
|
+
: `Connected ${providerLabel}`;
|
|
2035
|
+
}
|
|
2036
|
+
if (actionId === "cancel" || data?.status === "cancelled") {
|
|
2037
|
+
return `Cancelled ${providerLabel} connection`;
|
|
2038
|
+
}
|
|
2039
|
+
if (data?.status === "error") {
|
|
2040
|
+
return `${providerLabel} connection failed`;
|
|
2041
|
+
}
|
|
2042
|
+
return `${providerLabel} connection ${actionId}`;
|
|
2043
|
+
}
|
|
1895
2044
|
if (surfaceType === "list" && data) {
|
|
1896
2045
|
const selectedIds = data.selectedIds as string[] | undefined;
|
|
1897
2046
|
const actionSuffix = actionId ? ` (action: ${actionId})` : "";
|
|
@@ -1922,6 +2071,11 @@ function buildUserFacingLabel(
|
|
|
1922
2071
|
surfaceData?: Record<string, unknown>,
|
|
1923
2072
|
): string {
|
|
1924
2073
|
const count = (data?.selectedIds as string[] | undefined)?.length;
|
|
2074
|
+
const selectedTitles = Array.isArray(data?.selectedTitles)
|
|
2075
|
+
? data.selectedTitles.filter(
|
|
2076
|
+
(title): title is string => typeof title === "string",
|
|
2077
|
+
)
|
|
2078
|
+
: [];
|
|
1925
2079
|
|
|
1926
2080
|
if (surfaceType === "confirmation") {
|
|
1927
2081
|
if (actionId === "cancel") {
|
|
@@ -1948,6 +2102,39 @@ function buildUserFacingLabel(
|
|
|
1948
2102
|
return `Selected: ${actionId}`;
|
|
1949
2103
|
}
|
|
1950
2104
|
if (surfaceType === "form") return "Submitted";
|
|
2105
|
+
if (surfaceType === "choice") {
|
|
2106
|
+
const choiceTitle =
|
|
2107
|
+
typeof data?.choiceTitle === "string" ? data.choiceTitle : undefined;
|
|
2108
|
+
if (choiceTitle) return choiceTitle;
|
|
2109
|
+
if (selectedTitles.length === 1) return selectedTitles[0];
|
|
2110
|
+
if (selectedTitles.length > 1)
|
|
2111
|
+
return `Selected ${selectedTitles.length} options`;
|
|
2112
|
+
return "Selected";
|
|
2113
|
+
}
|
|
2114
|
+
if (surfaceType === "oauth_connect") {
|
|
2115
|
+
const providerLabel =
|
|
2116
|
+
typeof data?.providerLabel === "string"
|
|
2117
|
+
? data.providerLabel
|
|
2118
|
+
: typeof data?.displayName === "string"
|
|
2119
|
+
? data.displayName
|
|
2120
|
+
: typeof data?.providerKey === "string"
|
|
2121
|
+
? data.providerKey
|
|
2122
|
+
: "OAuth";
|
|
2123
|
+
const accountLabel =
|
|
2124
|
+
typeof data?.accountLabel === "string" ? data.accountLabel : undefined;
|
|
2125
|
+
if (actionId === "connect" || data?.status === "connected") {
|
|
2126
|
+
return accountLabel
|
|
2127
|
+
? `Connected ${providerLabel}: ${accountLabel}`
|
|
2128
|
+
: `Connected ${providerLabel}`;
|
|
2129
|
+
}
|
|
2130
|
+
if (actionId === "cancel" || data?.status === "cancelled") {
|
|
2131
|
+
return "Cancelled";
|
|
2132
|
+
}
|
|
2133
|
+
if (data?.status === "error") {
|
|
2134
|
+
return `${providerLabel} connection failed`;
|
|
2135
|
+
}
|
|
2136
|
+
return `Selected: ${actionId}`;
|
|
2137
|
+
}
|
|
1951
2138
|
|
|
1952
2139
|
// Table / list selection actions
|
|
1953
2140
|
if (count) {
|
|
@@ -2213,11 +2400,17 @@ export async function surfaceProxyResolver(
|
|
|
2213
2400
|
const data = (
|
|
2214
2401
|
surfaceType === "card"
|
|
2215
2402
|
? normalizeCardShowData(input, rawData)
|
|
2216
|
-
: surfaceType === "
|
|
2217
|
-
?
|
|
2218
|
-
:
|
|
2403
|
+
: surfaceType === "choice"
|
|
2404
|
+
? normalizeChoiceShowData(rawData)
|
|
2405
|
+
: surfaceType === "copy_block"
|
|
2406
|
+
? normalizeCopyBlockShowData(rawData)
|
|
2407
|
+
: surfaceType === "oauth_connect"
|
|
2408
|
+
? normalizeOAuthConnectShowData(rawData)
|
|
2409
|
+
: surfaceType === "dynamic_page"
|
|
2410
|
+
? normalizeDynamicPageShowData(input, rawData)
|
|
2411
|
+
: rawData
|
|
2219
2412
|
) as SurfaceData;
|
|
2220
|
-
const
|
|
2413
|
+
const inputActions = input.actions as
|
|
2221
2414
|
| Array<{
|
|
2222
2415
|
id: string;
|
|
2223
2416
|
label: string;
|
|
@@ -2225,8 +2418,33 @@ export async function surfaceProxyResolver(
|
|
|
2225
2418
|
data?: Record<string, unknown>;
|
|
2226
2419
|
}>
|
|
2227
2420
|
| undefined;
|
|
2421
|
+
const actions =
|
|
2422
|
+
surfaceType === "choice"
|
|
2423
|
+
? buildChoiceActions(data as ChoiceSurfaceData)
|
|
2424
|
+
: inputActions;
|
|
2228
2425
|
// Interactive surfaces default to awaiting user action.
|
|
2229
2426
|
const hasActions = Array.isArray(actions) && actions.length > 0;
|
|
2427
|
+
if (surfaceType === "choice" && !hasActions) {
|
|
2428
|
+
return {
|
|
2429
|
+
content:
|
|
2430
|
+
"choice surfaces require at least one option with both id and title.",
|
|
2431
|
+
isError: true,
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2434
|
+
const oauthProviderKey =
|
|
2435
|
+
surfaceType === "oauth_connect"
|
|
2436
|
+
? (data as unknown as Record<string, unknown>).providerKey
|
|
2437
|
+
: undefined;
|
|
2438
|
+
if (
|
|
2439
|
+
surfaceType === "oauth_connect" &&
|
|
2440
|
+
(typeof oauthProviderKey !== "string" ||
|
|
2441
|
+
oauthProviderKey.trim().length === 0)
|
|
2442
|
+
) {
|
|
2443
|
+
return {
|
|
2444
|
+
content: "oauth_connect surfaces require data.providerKey.",
|
|
2445
|
+
isError: true,
|
|
2446
|
+
};
|
|
2447
|
+
}
|
|
2230
2448
|
const isInteractive =
|
|
2231
2449
|
surfaceType === "card"
|
|
2232
2450
|
? hasActions
|
|
@@ -11,14 +11,12 @@ import {
|
|
|
11
11
|
type InterfaceId,
|
|
12
12
|
supportsHostProxy,
|
|
13
13
|
} from "../channels/types.js";
|
|
14
|
-
import { isHttpAuthDisabled } from "../config/env.js";
|
|
15
14
|
import { getIsPlatform } from "../config/env-registry.js";
|
|
16
15
|
import { getConfig } from "../config/loader.js";
|
|
17
16
|
import { getBindingByConversation } from "../memory/external-conversation-store.js";
|
|
18
17
|
import type { PermissionPrompter } from "../permissions/prompter.js";
|
|
19
18
|
import type { SecretPrompter } from "../permissions/secret-prompter.js";
|
|
20
19
|
import type { Message, ToolDefinition } from "../providers/types.js";
|
|
21
|
-
import type { TrustClass } from "../runtime/actor-trust-resolver.js";
|
|
22
20
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
23
21
|
import { registerConversationSender } from "../tools/browser/browser-screencast.js";
|
|
24
22
|
import type { ToolExecutor } from "../tools/executor.js";
|
|
@@ -48,27 +46,10 @@ import {
|
|
|
48
46
|
} from "./doordash-steps.js";
|
|
49
47
|
import type { ServerMessage, UiSurfaceShow } from "./message-protocol.js";
|
|
50
48
|
import { runPostExecutionSideEffects } from "./tool-side-effects.js";
|
|
51
|
-
import
|
|
49
|
+
import { resolveTrustClass } from "./trust-context.js";
|
|
52
50
|
|
|
53
51
|
const log = getLogger("conversation-tool-setup");
|
|
54
52
|
|
|
55
|
-
/**
|
|
56
|
-
* Resolve the effective trust class for tool execution.
|
|
57
|
-
*
|
|
58
|
-
* When HTTP auth is disabled (dev bypass), always returns `'guardian'`
|
|
59
|
-
* so that control-plane gates don't block local development.
|
|
60
|
-
*
|
|
61
|
-
* When no trust context is available (e.g. desktop-only conversations that
|
|
62
|
-
* don't go through channel trust resolution), defaults to `'unknown'`
|
|
63
|
-
* to fail-closed.
|
|
64
|
-
*/
|
|
65
|
-
export function resolveTrustClass(
|
|
66
|
-
trustContext: TrustContext | undefined,
|
|
67
|
-
): TrustClass {
|
|
68
|
-
if (isHttpAuthDisabled()) return "guardian";
|
|
69
|
-
return trustContext?.trustClass ?? "unknown";
|
|
70
|
-
}
|
|
71
|
-
|
|
72
53
|
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
73
54
|
import { AUTO_PROFILE_KEY } from "../config/seed-inference-profiles.js";
|
|
74
55
|
import {
|
|
@@ -97,7 +78,6 @@ export function createToolExecutor(
|
|
|
97
78
|
input: Record<string, unknown>,
|
|
98
79
|
onOutput?: (chunk: string) => void,
|
|
99
80
|
toolUseId?: string,
|
|
100
|
-
turnContext?: import("../plugins/types.js").TurnContext,
|
|
101
81
|
) => Promise<ToolExecutionResult> {
|
|
102
82
|
// Register the conversation's sendToClient for browser screencast surface messages
|
|
103
83
|
registerConversationSender(ctx.conversationId, (msg) =>
|
|
@@ -109,7 +89,6 @@ export function createToolExecutor(
|
|
|
109
89
|
input: Record<string, unknown>,
|
|
110
90
|
onOutput?: (chunk: string) => void,
|
|
111
91
|
toolUseId?: string,
|
|
112
|
-
turnContext?: import("../plugins/types.js").TurnContext,
|
|
113
92
|
) => {
|
|
114
93
|
const { name: executionName, input: executionInput } =
|
|
115
94
|
resolveToolInvocationAlias(name, input, ctx.allowedToolNames);
|
|
@@ -257,12 +236,7 @@ export function createToolExecutor(
|
|
|
257
236
|
};
|
|
258
237
|
}
|
|
259
238
|
|
|
260
|
-
const result = await executor.execute(
|
|
261
|
-
toolName,
|
|
262
|
-
toolInput,
|
|
263
|
-
toolContext,
|
|
264
|
-
turnContext,
|
|
265
|
-
);
|
|
239
|
+
const result = await executor.execute(toolName, toolInput, toolContext);
|
|
266
240
|
if (toolContext.approvedViaPrompt) {
|
|
267
241
|
ctx.approvedViaPromptThisTurn = true;
|
|
268
242
|
}
|
|
@@ -276,7 +250,6 @@ export function createToolExecutor(
|
|
|
276
250
|
executionName,
|
|
277
251
|
executionInput,
|
|
278
252
|
toolContext,
|
|
279
|
-
turnContext,
|
|
280
253
|
);
|
|
281
254
|
if (toolContext.approvedViaPrompt) {
|
|
282
255
|
ctx.approvedViaPromptThisTurn = true;
|
|
@@ -52,7 +52,6 @@ import { registerToolTraceListener } from "../events/tool-trace-listener.js";
|
|
|
52
52
|
import { resolveCanonicalGuardianRequest } from "../memory/canonical-guardian-store.js";
|
|
53
53
|
import {
|
|
54
54
|
getConversation,
|
|
55
|
-
getConversationOriginChannel,
|
|
56
55
|
getConversationOverrideProfileFromRow,
|
|
57
56
|
setConversationHistoryStrippedAt,
|
|
58
57
|
} from "../memory/conversation-crud.js";
|
|
@@ -68,6 +67,7 @@ import type { TrustClass } from "../runtime/actor-trust-resolver.js";
|
|
|
68
67
|
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
69
68
|
import type { AuthContext } from "../runtime/auth/types.js";
|
|
70
69
|
import type { InteractiveUiResult } from "../runtime/interactive-ui.js";
|
|
70
|
+
import { publishSyncInvalidation } from "../runtime/sync/sync-publisher.js";
|
|
71
71
|
import { ToolExecutor } from "../tools/executor.js";
|
|
72
72
|
import { getAllToolDefinitions } from "../tools/registry.js";
|
|
73
73
|
import type { ToolLifecycleEvent } from "../tools/types.js";
|
|
@@ -127,7 +127,6 @@ import type { ToolSetupContext } from "./conversation-tool-setup.js";
|
|
|
127
127
|
import {
|
|
128
128
|
createResolveToolsCallback,
|
|
129
129
|
createToolExecutor,
|
|
130
|
-
resolveTrustClass,
|
|
131
130
|
} from "./conversation-tool-setup.js";
|
|
132
131
|
import { refreshWorkspaceTopLevelContextIfNeeded as refreshWorkspaceImpl } from "./conversation-workspace.js";
|
|
133
132
|
import { canonicalizeTimeZone } from "./date-context.js";
|
|
@@ -143,6 +142,7 @@ import type {
|
|
|
143
142
|
import type { ConversationTransportMetadata } from "./message-types/conversations.js";
|
|
144
143
|
import { isHostProxyTransport } from "./message-types/conversations.js";
|
|
145
144
|
import type { ConfirmationStateChanged } from "./message-types/messages.js";
|
|
145
|
+
import { conversationMetadataSyncTag } from "./message-types/sync.js";
|
|
146
146
|
import { TraceEmitter } from "./trace-emitter.js";
|
|
147
147
|
|
|
148
148
|
const log = getLogger("conversation");
|
|
@@ -159,7 +159,7 @@ export type {
|
|
|
159
159
|
QueueDrainReason,
|
|
160
160
|
QueuePolicy,
|
|
161
161
|
} from "./conversation-queue-manager.js";
|
|
162
|
-
import type
|
|
162
|
+
import { resolveTrustClass, type TrustContext } from "./trust-context.js";
|
|
163
163
|
|
|
164
164
|
export interface ConversationConstructorOptions {
|
|
165
165
|
maxTokens?: number;
|
|
@@ -174,7 +174,7 @@ export class Conversation {
|
|
|
174
174
|
/** @internal */ provider: Provider;
|
|
175
175
|
/** @internal */ messages: Message[] = [];
|
|
176
176
|
/** @internal */ agentLoop: AgentLoop;
|
|
177
|
-
|
|
177
|
+
private _processing = false;
|
|
178
178
|
private stale = false;
|
|
179
179
|
/** @internal */ abortController: AbortController | null = null;
|
|
180
180
|
/** @internal */ prompter: PermissionPrompter;
|
|
@@ -733,7 +733,30 @@ export class Conversation {
|
|
|
733
733
|
}
|
|
734
734
|
|
|
735
735
|
isProcessing(): boolean {
|
|
736
|
-
return this.
|
|
736
|
+
return this._processing;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Mutate the server-authoritative `processing` flag. Web/Capacitor/CLI
|
|
741
|
+
* caches treat this flag as the source of truth for the avatar streaming
|
|
742
|
+
* ring and thinking indicator, so the `true → false` clear must announce
|
|
743
|
+
* itself: the daemon flips it in the agent-loop `finally` (after an awaited
|
|
744
|
+
* turn-boundary commit), which is later than the user-visible terminal SSE
|
|
745
|
+
* events, and a racing metadata refetch can otherwise re-read the
|
|
746
|
+
* not-yet-cleared `true` and clobber the client's optimistic `false`.
|
|
747
|
+
*
|
|
748
|
+
* Emitting a metadata invalidation on the clear lets every client GET the
|
|
749
|
+
* authoritative `false`, per the multi-client-sync contract in AGENTS.md
|
|
750
|
+
* ("emit the invalidation after the canonical state write succeeds").
|
|
751
|
+
*/
|
|
752
|
+
setProcessing(value: boolean): void {
|
|
753
|
+
const wasProcessing = this._processing;
|
|
754
|
+
this._processing = value;
|
|
755
|
+
if (wasProcessing && !value) {
|
|
756
|
+
void publishSyncInvalidation([
|
|
757
|
+
conversationMetadataSyncTag(this.conversationId),
|
|
758
|
+
]);
|
|
759
|
+
}
|
|
737
760
|
}
|
|
738
761
|
|
|
739
762
|
markStale(): void {
|
|
@@ -795,6 +818,7 @@ export class Conversation {
|
|
|
795
818
|
this.cesClient = undefined;
|
|
796
819
|
this.activeContextNodeIds = this.graphMemory.tracker.getActiveNodeIds();
|
|
797
820
|
this.graphMemory.persistState();
|
|
821
|
+
this.graphMemory.dispose();
|
|
798
822
|
disposeConversation(this);
|
|
799
823
|
}
|
|
800
824
|
|
|
@@ -836,7 +860,7 @@ export class Conversation {
|
|
|
836
860
|
}
|
|
837
861
|
|
|
838
862
|
canHandoffAtCheckpoint(): boolean {
|
|
839
|
-
return this.
|
|
863
|
+
return this._processing && this.hasQueuedMessages();
|
|
840
864
|
}
|
|
841
865
|
|
|
842
866
|
hasPendingConfirmation(requestId: string): boolean {
|
|
@@ -1020,9 +1044,7 @@ export class Conversation {
|
|
|
1020
1044
|
}
|
|
1021
1045
|
}
|
|
1022
1046
|
|
|
1023
|
-
async forceCompact(
|
|
1024
|
-
targetInputTokensOverride?: number;
|
|
1025
|
-
}): Promise<ContextWindowResult> {
|
|
1047
|
+
async forceCompact(): Promise<ContextWindowResult> {
|
|
1026
1048
|
const conversationRow = getConversation(this.conversationId);
|
|
1027
1049
|
const overrideProfile =
|
|
1028
1050
|
getConversationOverrideProfileFromRow(conversationRow) ?? null;
|
|
@@ -1066,11 +1088,7 @@ export class Conversation {
|
|
|
1066
1088
|
this.abortController?.signal ?? undefined,
|
|
1067
1089
|
{
|
|
1068
1090
|
force: true,
|
|
1069
|
-
lastCompactedAt: this.contextCompactedAt ?? undefined,
|
|
1070
|
-
conversationOriginChannel:
|
|
1071
|
-
getConversationOriginChannel(this.conversationId) ?? undefined,
|
|
1072
1091
|
overrideProfile,
|
|
1073
|
-
targetInputTokensOverride: options?.targetInputTokensOverride,
|
|
1074
1092
|
actorTrustClass: this.trustContext?.trustClass,
|
|
1075
1093
|
},
|
|
1076
1094
|
);
|
|
@@ -1251,7 +1269,7 @@ export class Conversation {
|
|
|
1251
1269
|
async persistUserMessage(
|
|
1252
1270
|
options: PersistMessageOptions,
|
|
1253
1271
|
): Promise<{ id: string; deduplicated: boolean }> {
|
|
1254
|
-
if (!this.
|
|
1272
|
+
if (!this._processing) {
|
|
1255
1273
|
await this.ensureActorScopedHistory();
|
|
1256
1274
|
}
|
|
1257
1275
|
return persistUserMessageImpl(this, options);
|
|
@@ -16,9 +16,8 @@
|
|
|
16
16
|
* the plugin is skipped wholesale — no `init()`, no tool/route/skill
|
|
17
17
|
* contributions, no entry in the shutdown hook, and the plugin is also
|
|
18
18
|
* dropped from the registry via {@link unregisterPlugin} so its middleware
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* plugins behind a feature flag.
|
|
19
|
+
* stops participating in pipeline runs. This is the primary mechanism for
|
|
20
|
+
* shipping experimental plugins behind a feature flag.
|
|
22
21
|
* 4. Resolves the plugin's `manifest.requiresCredential` entries via the
|
|
23
22
|
* credential store helper ({@link getSecureKeyAsync}). In Docker mode
|
|
24
23
|
* that helper goes through the CES HTTP API transparently; in local mode
|
|
@@ -190,8 +189,8 @@ function getDisabledPluginFlag(
|
|
|
190
189
|
* 1. Install the `globalThis.__vellumPluginRuntime` bridge so plugins can touch
|
|
191
190
|
* it from their module body (see `plugins/external-api.ts` — compiled-binary
|
|
192
191
|
* module identity).
|
|
193
|
-
* 2. Register the first-party defaults so their middleware
|
|
194
|
-
*
|
|
192
|
+
* 2. Register the first-party defaults so their middleware composes innermost,
|
|
193
|
+
* ahead of any user plugins.
|
|
195
194
|
* 3. Load user plugins from `<workspaceDir>/plugins/*`. A failing user plugin is
|
|
196
195
|
* logged and skipped; `loadUserPlugins()` closes the registration window
|
|
197
196
|
* when it returns, so the defaults must already be registered by then.
|
|
@@ -228,7 +227,7 @@ export async function initializePlugins(): Promise<void> {
|
|
|
228
227
|
*/
|
|
229
228
|
export async function bootstrapPlugins(): Promise<void> {
|
|
230
229
|
// Register first-party default plugins. Each default wraps one of the
|
|
231
|
-
// assistant's canonical pipelines (`
|
|
230
|
+
// assistant's canonical pipelines (`compaction`, `persistence`, ...) with a
|
|
232
231
|
// passthrough so the pipeline shape is explicit at boot even when no
|
|
233
232
|
// third-party plugins are loaded. Registration is idempotent via the
|
|
234
233
|
// already-registered guard so repeated calls (e.g. during integration
|
|
@@ -237,8 +236,8 @@ export async function bootstrapPlugins(): Promise<void> {
|
|
|
237
236
|
|
|
238
237
|
const plugins = getRegisteredPlugins();
|
|
239
238
|
if (plugins.length === 0) {
|
|
240
|
-
// No-op fast path. The default
|
|
241
|
-
//
|
|
239
|
+
// No-op fast path. The default plugins normally populate the registry, so
|
|
240
|
+
// this branch is primarily for tests that call
|
|
242
241
|
// `resetPluginRegistryForTests()` and stub the default registration.
|
|
243
242
|
log.debug("bootstrapPlugins: registry empty — skipping");
|
|
244
243
|
return;
|
|
@@ -263,8 +262,8 @@ export async function bootstrapPlugins(): Promise<void> {
|
|
|
263
262
|
// two steps always move together on the bootstrap failure path: the former
|
|
264
263
|
// clears tools/routes/skills (so they stop appearing to the model/HTTP
|
|
265
264
|
// server), the latter drops the plugin's entry from the Map (so
|
|
266
|
-
// `getMiddlewaresFor`
|
|
267
|
-
//
|
|
265
|
+
// `getMiddlewaresFor` doesn't re-enter an uninitialized plugin on the next
|
|
266
|
+
// pipeline invocation).
|
|
268
267
|
// Shutdown context is identical for every plugin in this boot — construct
|
|
269
268
|
// once and reuse across the bootstrap-failure rollback and the normal
|
|
270
269
|
// shutdown hook below. Only `assistantVersion` is exposed today; future
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* - acceptA2AInvite() — self-hosted broker: orchestrate complete + redeem across daemons
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
13
15
|
import {
|
|
14
16
|
getConfig,
|
|
15
17
|
invalidateConfigCache,
|
|
@@ -38,42 +40,55 @@ const log = getLogger("config-a2a");
|
|
|
38
40
|
|
|
39
41
|
// ── Result types ────────────────────────────────────────────────────
|
|
40
42
|
|
|
41
|
-
export
|
|
42
|
-
success: boolean
|
|
43
|
-
enabled: boolean
|
|
44
|
-
activeConnections: number
|
|
45
|
-
error
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
export
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
export
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
43
|
+
export const A2AConfigResultSchema = z.object({
|
|
44
|
+
success: z.boolean(),
|
|
45
|
+
enabled: z.boolean(),
|
|
46
|
+
activeConnections: z.number(),
|
|
47
|
+
error: z.string().optional(),
|
|
48
|
+
});
|
|
49
|
+
export type A2AConfigResult = z.infer<typeof A2AConfigResultSchema>;
|
|
50
|
+
|
|
51
|
+
export const CreateA2AInviteResultSchema = z.object({
|
|
52
|
+
success: z.boolean(),
|
|
53
|
+
inviteId: z.string().optional(),
|
|
54
|
+
token: z.string().optional(),
|
|
55
|
+
expiresAt: z.number().optional(),
|
|
56
|
+
senderGatewayUrl: z.string().optional(),
|
|
57
|
+
error: z.string().optional(),
|
|
58
|
+
});
|
|
59
|
+
export type CreateA2AInviteResult = z.infer<typeof CreateA2AInviteResultSchema>;
|
|
60
|
+
|
|
61
|
+
export const CompleteA2AInviteResultSchema = z.object({
|
|
62
|
+
success: z.boolean(),
|
|
63
|
+
sender: z
|
|
64
|
+
.object({
|
|
65
|
+
assistantId: z.string(),
|
|
66
|
+
displayName: z.string(),
|
|
67
|
+
gatewayUrl: z.string(),
|
|
68
|
+
})
|
|
69
|
+
.optional(),
|
|
70
|
+
error: z.string().optional(),
|
|
71
|
+
});
|
|
72
|
+
export type CompleteA2AInviteResult = z.infer<
|
|
73
|
+
typeof CompleteA2AInviteResultSchema
|
|
74
|
+
>;
|
|
75
|
+
|
|
76
|
+
export const RedeemA2AInviteResultSchema = z.object({
|
|
77
|
+
success: z.boolean(),
|
|
78
|
+
contactId: z.string().optional(),
|
|
79
|
+
alreadyConnected: z.boolean().optional(),
|
|
80
|
+
error: z.string().optional(),
|
|
81
|
+
});
|
|
82
|
+
export type RedeemA2AInviteResult = z.infer<typeof RedeemA2AInviteResultSchema>;
|
|
83
|
+
|
|
84
|
+
export const AcceptA2AInviteResultSchema = z.object({
|
|
85
|
+
success: z.boolean(),
|
|
86
|
+
contactId: z.string().optional(),
|
|
87
|
+
alreadyConnected: z.boolean().optional(),
|
|
88
|
+
error: z.string().optional(),
|
|
89
|
+
errorCode: z.string().optional(),
|
|
90
|
+
});
|
|
91
|
+
export type AcceptA2AInviteResult = z.infer<typeof AcceptA2AInviteResultSchema>;
|
|
77
92
|
|
|
78
93
|
// ── Config operations ───────────────────────────────────────────────
|
|
79
94
|
|