@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
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
|
|
3
|
+
import type { DrizzleDb } from "../memory/db-connection.js";
|
|
4
|
+
import { getDb } from "../memory/db-connection.js";
|
|
5
|
+
import { rawChanges } from "../memory/raw-query.js";
|
|
6
|
+
import { a2aTasks } from "../memory/schema.js";
|
|
7
|
+
import { TERMINAL_TASK_STATES } from "./protocol-constants.js";
|
|
8
|
+
import type {
|
|
9
|
+
A2AMessage,
|
|
10
|
+
A2ATask,
|
|
11
|
+
Artifact,
|
|
12
|
+
TaskState,
|
|
13
|
+
} from "./protocol-types.js";
|
|
14
|
+
|
|
15
|
+
// ── Internal types ──────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
/** Raw database row shape for a2a_tasks. */
|
|
18
|
+
type A2ATaskRow = typeof a2aTasks.$inferSelect;
|
|
19
|
+
|
|
20
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
/** Throw if the task doesn't exist or is in a terminal state. */
|
|
23
|
+
function assertNonTerminal(
|
|
24
|
+
db: DrizzleDb,
|
|
25
|
+
taskId: string,
|
|
26
|
+
targetState: TaskState,
|
|
27
|
+
): void {
|
|
28
|
+
const current = db
|
|
29
|
+
.select({ state: a2aTasks.state })
|
|
30
|
+
.from(a2aTasks)
|
|
31
|
+
.where(eq(a2aTasks.id, taskId))
|
|
32
|
+
.get();
|
|
33
|
+
|
|
34
|
+
if (!current) {
|
|
35
|
+
throw new Error(`A2A task not found: ${taskId}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (TERMINAL_TASK_STATES.has(current.state as TaskState)) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Cannot transition task ${taskId} from terminal state "${current.state}" to "${targetState}"`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function rowToTask(row: A2ATaskRow): A2ATask {
|
|
46
|
+
return {
|
|
47
|
+
id: row.id,
|
|
48
|
+
context_id: row.contextId ?? undefined,
|
|
49
|
+
status: {
|
|
50
|
+
state: row.state as TaskState,
|
|
51
|
+
message: row.statusMessage
|
|
52
|
+
? {
|
|
53
|
+
message_id: crypto.randomUUID(),
|
|
54
|
+
role: "agent",
|
|
55
|
+
parts: [{ kind: "text", text: row.statusMessage }],
|
|
56
|
+
}
|
|
57
|
+
: undefined,
|
|
58
|
+
timestamp: new Date(row.updatedAt).toISOString(),
|
|
59
|
+
},
|
|
60
|
+
artifacts: row.artifactsJson
|
|
61
|
+
? (JSON.parse(row.artifactsJson) as Artifact[])
|
|
62
|
+
: undefined,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── Store functions ─────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
export function createTask(params: {
|
|
69
|
+
contextId?: string;
|
|
70
|
+
senderAssistantId: string;
|
|
71
|
+
requestMessage: A2AMessage;
|
|
72
|
+
pushUrl?: string;
|
|
73
|
+
}): A2ATask {
|
|
74
|
+
const db = getDb();
|
|
75
|
+
const now = Date.now();
|
|
76
|
+
|
|
77
|
+
const row: A2ATaskRow = {
|
|
78
|
+
id: crypto.randomUUID(),
|
|
79
|
+
contextId: params.contextId ?? null,
|
|
80
|
+
conversationId: null,
|
|
81
|
+
state: "submitted",
|
|
82
|
+
statusMessage: null,
|
|
83
|
+
requestMessageJson: JSON.stringify(params.requestMessage),
|
|
84
|
+
artifactsJson: null,
|
|
85
|
+
pushUrl: params.pushUrl ?? null,
|
|
86
|
+
senderAssistantId: params.senderAssistantId,
|
|
87
|
+
createdAt: now,
|
|
88
|
+
updatedAt: now,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
db.insert(a2aTasks).values(row).run();
|
|
92
|
+
|
|
93
|
+
return rowToTask(row);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getTask(taskId: string): A2ATask | null {
|
|
97
|
+
const db = getDb();
|
|
98
|
+
const row = db.select().from(a2aTasks).where(eq(a2aTasks.id, taskId)).get();
|
|
99
|
+
return row ? rowToTask(row) : null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function updateState(
|
|
103
|
+
taskId: string,
|
|
104
|
+
state: TaskState,
|
|
105
|
+
statusMessage?: string,
|
|
106
|
+
): A2ATask {
|
|
107
|
+
const db = getDb();
|
|
108
|
+
assertNonTerminal(db, taskId, state);
|
|
109
|
+
|
|
110
|
+
db.update(a2aTasks)
|
|
111
|
+
.set({
|
|
112
|
+
state,
|
|
113
|
+
statusMessage: statusMessage ?? null,
|
|
114
|
+
updatedAt: Date.now(),
|
|
115
|
+
})
|
|
116
|
+
.where(eq(a2aTasks.id, taskId))
|
|
117
|
+
.run();
|
|
118
|
+
|
|
119
|
+
return rowToTask(
|
|
120
|
+
db.select().from(a2aTasks).where(eq(a2aTasks.id, taskId)).get()!,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function completeWithArtifacts(
|
|
125
|
+
taskId: string,
|
|
126
|
+
artifacts: Artifact[],
|
|
127
|
+
): A2ATask {
|
|
128
|
+
const db = getDb();
|
|
129
|
+
assertNonTerminal(db, taskId, "completed");
|
|
130
|
+
|
|
131
|
+
db.update(a2aTasks)
|
|
132
|
+
.set({
|
|
133
|
+
state: "completed",
|
|
134
|
+
statusMessage: null,
|
|
135
|
+
artifactsJson: JSON.stringify(artifacts),
|
|
136
|
+
updatedAt: Date.now(),
|
|
137
|
+
})
|
|
138
|
+
.where(eq(a2aTasks.id, taskId))
|
|
139
|
+
.run();
|
|
140
|
+
|
|
141
|
+
return rowToTask(
|
|
142
|
+
db.select().from(a2aTasks).where(eq(a2aTasks.id, taskId)).get()!,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function linkConversation(taskId: string, conversationId: string): void {
|
|
147
|
+
const db = getDb();
|
|
148
|
+
const now = Date.now();
|
|
149
|
+
|
|
150
|
+
db.update(a2aTasks)
|
|
151
|
+
.set({ conversationId, updatedAt: now })
|
|
152
|
+
.where(eq(a2aTasks.id, taskId))
|
|
153
|
+
.run();
|
|
154
|
+
|
|
155
|
+
if (rawChanges() === 0) {
|
|
156
|
+
throw new Error(`A2A task not found: ${taskId}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function getPushUrl(taskId: string): string | null {
|
|
161
|
+
const db = getDb();
|
|
162
|
+
const row = db
|
|
163
|
+
.select({ pushUrl: a2aTasks.pushUrl })
|
|
164
|
+
.from(a2aTasks)
|
|
165
|
+
.where(eq(a2aTasks.id, taskId))
|
|
166
|
+
.get();
|
|
167
|
+
return row?.pushUrl ?? null;
|
|
168
|
+
}
|
package/src/acp/resolve-agent.ts
CHANGED
|
@@ -73,7 +73,7 @@ function installHintFor(command: string): string {
|
|
|
73
73
|
*/
|
|
74
74
|
function findAgentBinary(agent: AcpAgentConfig): string | null {
|
|
75
75
|
const PATH = agent.env?.PATH ?? process.env.PATH;
|
|
76
|
-
return Bun.which(agent.command, PATH ? { PATH } : undefined);
|
|
76
|
+
return Bun.which(agent.command, PATH != null ? { PATH } : undefined);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/**
|
|
@@ -21,6 +21,11 @@ const MAX_DIMENSION = 1568;
|
|
|
21
21
|
// Threshold below which we skip optimization — small images don't need it.
|
|
22
22
|
const OPTIMIZE_THRESHOLD_BYTES = 300 * 1024; // 300 KB
|
|
23
23
|
|
|
24
|
+
// Anthropic rejects any single image whose source payload exceeds 5 MB,
|
|
25
|
+
// regardless of pixel dimensions. Cap at ~3.5 MB raw so the base64-encoded
|
|
26
|
+
// form (raw * 4/3) stays comfortably under 5 MB even after re-encoding.
|
|
27
|
+
const MAX_TRANSPORT_BYTES = Math.floor(3.5 * 1024 * 1024); // ~3.5 MB raw
|
|
28
|
+
|
|
24
29
|
const JPEG_QUALITY = 80;
|
|
25
30
|
|
|
26
31
|
// Content-addressed disk cache to avoid re-running sips on the same image.
|
|
@@ -130,10 +135,13 @@ function runSips(inputBytes: Buffer): Buffer | null {
|
|
|
130
135
|
/**
|
|
131
136
|
* Decide whether an image needs to be rescaled before sending.
|
|
132
137
|
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
138
|
+
* Two independent gates apply:
|
|
139
|
+
* 1. Pixel dimensions — Anthropic rejects many-image requests when any
|
|
140
|
+
* image exceeds 2000 px on a side. A sparse screenshot can be under
|
|
141
|
+
* 300 KB while still being 3000+ px wide.
|
|
142
|
+
* 2. Byte size — Anthropic rejects any image whose source payload
|
|
143
|
+
* exceeds 5 MB. A 1500×1500 high-color screenshot can produce a >5 MB
|
|
144
|
+
* payload while staying well under the dimension cap.
|
|
137
145
|
*
|
|
138
146
|
* Exported for unit testing.
|
|
139
147
|
*/
|
|
@@ -141,8 +149,8 @@ export function shouldRescaleImage(
|
|
|
141
149
|
dims: { width: number; height: number } | null,
|
|
142
150
|
byteLength: number,
|
|
143
151
|
): boolean {
|
|
152
|
+
if (byteLength > MAX_TRANSPORT_BYTES) return true;
|
|
144
153
|
if (dims) {
|
|
145
|
-
// Dimensions known — they are the authoritative check.
|
|
146
154
|
return dims.width > MAX_DIMENSION || dims.height > MAX_DIMENSION;
|
|
147
155
|
}
|
|
148
156
|
// Dimensions unparseable — fall back to file size as a rough proxy.
|
package/src/agent/loop.ts
CHANGED
|
@@ -67,6 +67,43 @@ export interface CheckpointInfo {
|
|
|
67
67
|
|
|
68
68
|
export type CheckpointDecision = "continue" | "yield";
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Why an {@link AgentLoop.run} invocation exited its `while (true)` body.
|
|
72
|
+
*
|
|
73
|
+
* Emitted exactly once per run as part of an {@link AgentEvent} of type
|
|
74
|
+
* `agent_loop_exit`, then persisted onto the **final** `llm_request_logs`
|
|
75
|
+
* row of the run. Rows from intermediate turns keep a NULL
|
|
76
|
+
* `agent_loop_exit_reason`, which is how downstream tooling (and the LLM
|
|
77
|
+
* Context Inspector) distinguishes "loop kept going" from "loop is done".
|
|
78
|
+
*
|
|
79
|
+
* Values are stable wire/DB strings — they are written to SQLite and
|
|
80
|
+
* surfaced over the inspector wire format, so renaming any of them is a
|
|
81
|
+
* breaking change.
|
|
82
|
+
*
|
|
83
|
+
* Cardinality matches the nine `break;`/`throw` sites currently inside the
|
|
84
|
+
* loop body. Keep in sync with `emitExit` call sites in
|
|
85
|
+
* {@link AgentLoop.run}.
|
|
86
|
+
*/
|
|
87
|
+
export type AgentLoopExitReason =
|
|
88
|
+
/** `if (signal?.aborted) break;` at the top of the loop. */
|
|
89
|
+
| "aborted_pre_call"
|
|
90
|
+
/** Empty assistant response after the configured retry budget. */
|
|
91
|
+
| "empty_response_exhausted"
|
|
92
|
+
/** Assistant message has no tool-use blocks (or no tool executor). */
|
|
93
|
+
| "no_tool_calls"
|
|
94
|
+
/** Signal aborted while building the user-side tool-results message. */
|
|
95
|
+
| "aborted_post_response"
|
|
96
|
+
/** Signal aborted mid-tool-execution; completed results were pushed. */
|
|
97
|
+
| "aborted_during_tools"
|
|
98
|
+
/** A tool result requested handing back to the user. */
|
|
99
|
+
| "yield_to_user"
|
|
100
|
+
/** The orchestrator's `onCheckpoint` callback returned `"yield"`. */
|
|
101
|
+
| "checkpoint_yield"
|
|
102
|
+
/** Signal aborted while the catch handler was synthesizing an error turn. */
|
|
103
|
+
| "aborted_via_error"
|
|
104
|
+
/** Catch-block fallback: an unhandled error broke the loop. */
|
|
105
|
+
| "error";
|
|
106
|
+
|
|
70
107
|
export type AgentEvent =
|
|
71
108
|
| { type: "text_delta"; text: string }
|
|
72
109
|
| { type: "thinking_delta"; thinking: string }
|
|
@@ -126,6 +163,32 @@ export type AgentEvent =
|
|
|
126
163
|
content?: unknown[];
|
|
127
164
|
}
|
|
128
165
|
| { type: "error"; error: Error }
|
|
166
|
+
| {
|
|
167
|
+
/**
|
|
168
|
+
* Emitted when the `llmCall` pipeline throws — i.e. the provider
|
|
169
|
+
* rejected the request before returning a usable response. Carries
|
|
170
|
+
* the loop-level raw request we attempted to send (messages, tools,
|
|
171
|
+
* system prompt, provider-agnostic config) plus the thrown error.
|
|
172
|
+
* Consumers (`handleProviderError` in the daemon handlers, the
|
|
173
|
+
* `onEvent` in `agent-wake`) persist these as `llm_request_logs`
|
|
174
|
+
* rows so failed calls are queryable in the LLM inspector instead
|
|
175
|
+
* of only surfacing in pino logs.
|
|
176
|
+
*
|
|
177
|
+
* `rawRequest` is the loop-level abstract shape rather than the
|
|
178
|
+
* provider-specific payload (which the provider builds internally
|
|
179
|
+
* and never returns when it throws). `actualProvider` echoes the
|
|
180
|
+
* `ProviderError.provider` tag when available so the persisted row
|
|
181
|
+
* has the same `provider` column value as a successful `usage` row.
|
|
182
|
+
*
|
|
183
|
+
* Re-thrown by the inner LLM-call try/catch after emission so the
|
|
184
|
+
* outer agent-loop catch still handles abort, Sentry capture, the
|
|
185
|
+
* existing `error` event, and the loop break.
|
|
186
|
+
*/
|
|
187
|
+
type: "provider_error";
|
|
188
|
+
rawRequest: unknown;
|
|
189
|
+
error: Error;
|
|
190
|
+
actualProvider?: string;
|
|
191
|
+
}
|
|
129
192
|
| {
|
|
130
193
|
type: "usage";
|
|
131
194
|
inputTokens: number;
|
|
@@ -144,6 +207,18 @@ export type AgentEvent =
|
|
|
144
207
|
* for this call (e.g. legacy/stubbed code paths).
|
|
145
208
|
*/
|
|
146
209
|
estimatedInputTokens?: number;
|
|
210
|
+
}
|
|
211
|
+
| {
|
|
212
|
+
/**
|
|
213
|
+
* Emitted exactly once at the end of {@link AgentLoop.run}, after the
|
|
214
|
+
* loop body has exited (whether via `break;`, an unhandled error in
|
|
215
|
+
* the catch block, or the empty-response throw path). Consumers
|
|
216
|
+
* persist `reason` onto the final `llm_request_logs` row for the run;
|
|
217
|
+
* intermediate rows keep `agent_loop_exit_reason = NULL`, which is the
|
|
218
|
+
* canonical "loop kept going" signal.
|
|
219
|
+
*/
|
|
220
|
+
type: "agent_loop_exit";
|
|
221
|
+
reason: AgentLoopExitReason;
|
|
147
222
|
};
|
|
148
223
|
|
|
149
224
|
const DEFAULT_CONFIG: AgentLoopConfig = {
|
|
@@ -398,8 +473,24 @@ export class AgentLoop {
|
|
|
398
473
|
const substitutionMap = new Map<string, string>();
|
|
399
474
|
let streamingPending = "";
|
|
400
475
|
|
|
476
|
+
// Idempotency guard for `emitExit`. Used so the throw path in the
|
|
477
|
+
// empty-response branch can stamp its reason ("empty_response_exhausted")
|
|
478
|
+
// before throwing — the catch handler that observes the rethrow will
|
|
479
|
+
// then attempt to stamp "error" and harmlessly no-op, preserving the
|
|
480
|
+
// more specific reason. Also defends against accidental future
|
|
481
|
+
// double-emits if a new break site is added without checking this.
|
|
482
|
+
let exitReasonEmitted = false;
|
|
483
|
+
const emitExit = async (reason: AgentLoopExitReason): Promise<void> => {
|
|
484
|
+
if (exitReasonEmitted) return;
|
|
485
|
+
exitReasonEmitted = true;
|
|
486
|
+
await onEvent({ type: "agent_loop_exit", reason });
|
|
487
|
+
};
|
|
488
|
+
|
|
401
489
|
while (true) {
|
|
402
|
-
if (signal?.aborted)
|
|
490
|
+
if (signal?.aborted) {
|
|
491
|
+
await emitExit("aborted_pre_call");
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
403
494
|
|
|
404
495
|
rlog.info(
|
|
405
496
|
{ turn: toolUseTurns, messageCount: history.length },
|
|
@@ -618,23 +709,64 @@ export class AgentLoop {
|
|
|
618
709
|
toolUseTurns,
|
|
619
710
|
);
|
|
620
711
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
712
|
+
// Inner try/catch narrows error-recording scope to the provider
|
|
713
|
+
// call itself. The outer agent-loop catch (below) wraps the entire
|
|
714
|
+
// turn body (tool execution, plugin pipelines, checkpoints), so
|
|
715
|
+
// recording there would risk mis-attributing tool/plugin throws as
|
|
716
|
+
// provider rejections. On provider failure we emit `provider_error`
|
|
717
|
+
// with the loop-level raw request so consumers can persist it as an
|
|
718
|
+
// `llm_request_logs` row, then re-throw so the existing outer catch
|
|
719
|
+
// continues to handle abort sync, Sentry capture, the `error` event,
|
|
720
|
+
// and the loop break unchanged.
|
|
721
|
+
let response: LLMCallResult;
|
|
722
|
+
try {
|
|
723
|
+
response = await runPipeline<LLMCallArgs, LLMCallResult>(
|
|
724
|
+
"llmCall",
|
|
725
|
+
getMiddlewaresFor("llmCall"),
|
|
726
|
+
(args) =>
|
|
727
|
+
args.provider.sendMessage(
|
|
728
|
+
args.messages,
|
|
729
|
+
args.tools,
|
|
730
|
+
args.systemPrompt,
|
|
731
|
+
args.options,
|
|
732
|
+
),
|
|
733
|
+
llmCallArgs,
|
|
734
|
+
turnCtx,
|
|
735
|
+
DEFAULT_TIMEOUTS.llmCall,
|
|
736
|
+
);
|
|
737
|
+
} catch (llmCallError) {
|
|
738
|
+
// Skip recording on abort — the user cancelled the request and
|
|
739
|
+
// there's no provider rejection worth a log row. The outer catch
|
|
740
|
+
// still synthesizes cancellation tool_results.
|
|
741
|
+
if (!signal?.aborted) {
|
|
742
|
+
const errInstance =
|
|
743
|
+
llmCallError instanceof Error
|
|
744
|
+
? llmCallError
|
|
745
|
+
: new Error(String(llmCallError));
|
|
746
|
+
// Strip non-serializable / runtime-only fields from `options`
|
|
747
|
+
// before snapshotting. `onEvent` is a closure with side effects
|
|
748
|
+
// and `signal` is an AbortSignal — neither is meaningful in a
|
|
749
|
+
// persisted log row, and `JSON.stringify` would silently drop or
|
|
750
|
+
// misrepresent both.
|
|
751
|
+
const rawRequest = {
|
|
752
|
+
provider: this.provider.name,
|
|
753
|
+
messages: llmCallArgs.messages,
|
|
754
|
+
tools: llmCallArgs.tools,
|
|
755
|
+
systemPrompt: llmCallArgs.systemPrompt,
|
|
756
|
+
config: llmCallArgs.options?.config,
|
|
757
|
+
};
|
|
758
|
+
onEvent({
|
|
759
|
+
type: "provider_error",
|
|
760
|
+
rawRequest,
|
|
761
|
+
error: errInstance,
|
|
762
|
+
actualProvider:
|
|
763
|
+
errInstance instanceof ProviderError
|
|
764
|
+
? errInstance.provider
|
|
765
|
+
: this.provider.name,
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
throw llmCallError;
|
|
769
|
+
}
|
|
638
770
|
|
|
639
771
|
const providerDurationMs = Date.now() - providerStart;
|
|
640
772
|
|
|
@@ -785,6 +917,11 @@ export class AgentLoop {
|
|
|
785
917
|
{ turn: toolUseTurns, retries: emptyResponseRetries },
|
|
786
918
|
"emptyResponse pipeline requested error surface",
|
|
787
919
|
);
|
|
920
|
+
// Stamp the specific exit reason *before* throwing. The catch
|
|
921
|
+
// handler below will see the rethrown error and attempt to stamp
|
|
922
|
+
// "error" — guarded by `exitReasonEmitted`, that becomes a no-op
|
|
923
|
+
// and the more specific reason wins.
|
|
924
|
+
await emitExit("empty_response_exhausted");
|
|
788
925
|
throw new AssistantError(
|
|
789
926
|
"Model returned empty response after tool results",
|
|
790
927
|
ErrorCode.INTERNAL_ERROR,
|
|
@@ -811,6 +948,7 @@ export class AgentLoop {
|
|
|
811
948
|
await onEvent({ type: "message_complete", message: assistantMessage });
|
|
812
949
|
|
|
813
950
|
if (toolUseBlocks.length === 0 || !this.toolExecutor) {
|
|
951
|
+
await emitExit("no_tool_calls");
|
|
814
952
|
break;
|
|
815
953
|
}
|
|
816
954
|
|
|
@@ -835,6 +973,7 @@ export class AgentLoop {
|
|
|
835
973
|
}),
|
|
836
974
|
);
|
|
837
975
|
history.push({ role: "user", content: cancelledBlocks });
|
|
976
|
+
await emitExit("aborted_post_response");
|
|
838
977
|
break;
|
|
839
978
|
}
|
|
840
979
|
|
|
@@ -1022,6 +1161,7 @@ export class AgentLoop {
|
|
|
1022
1161
|
// If cancelled during execution, push completed results and stop
|
|
1023
1162
|
if (signal?.aborted) {
|
|
1024
1163
|
history.push({ role: "user", content: resultBlocks });
|
|
1164
|
+
await emitExit("aborted_during_tools");
|
|
1025
1165
|
break;
|
|
1026
1166
|
}
|
|
1027
1167
|
|
|
@@ -1029,6 +1169,7 @@ export class AgentLoop {
|
|
|
1029
1169
|
// surface awaiting a button click), push results and stop the loop.
|
|
1030
1170
|
if (toolResults.some(({ result }) => result.yieldToUser)) {
|
|
1031
1171
|
history.push({ role: "user", content: resultBlocks });
|
|
1172
|
+
await emitExit("yield_to_user");
|
|
1032
1173
|
break;
|
|
1033
1174
|
}
|
|
1034
1175
|
|
|
@@ -1095,6 +1236,7 @@ export class AgentLoop {
|
|
|
1095
1236
|
history,
|
|
1096
1237
|
});
|
|
1097
1238
|
if (decision === "yield") {
|
|
1239
|
+
await emitExit("checkpoint_yield");
|
|
1098
1240
|
break;
|
|
1099
1241
|
}
|
|
1100
1242
|
}
|
|
@@ -1114,6 +1256,7 @@ export class AgentLoop {
|
|
|
1114
1256
|
);
|
|
1115
1257
|
history.push({ role: "user", content: cancelledBlocks });
|
|
1116
1258
|
}
|
|
1259
|
+
await emitExit("aborted_via_error");
|
|
1117
1260
|
break;
|
|
1118
1261
|
}
|
|
1119
1262
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
@@ -1125,6 +1268,12 @@ export class AgentLoop {
|
|
|
1125
1268
|
Sentry.captureException(err);
|
|
1126
1269
|
}
|
|
1127
1270
|
onEvent({ type: "error", error: err });
|
|
1271
|
+
// Catch-block fallback. If the rethrow came from the
|
|
1272
|
+
// empty-response throw path above, `emitExit("error")` no-ops
|
|
1273
|
+
// because `emitExit("empty_response_exhausted")` already ran
|
|
1274
|
+
// before the throw. Otherwise, this is the genuine
|
|
1275
|
+
// unhandled-error exit.
|
|
1276
|
+
await emitExit("error");
|
|
1128
1277
|
break;
|
|
1129
1278
|
}
|
|
1130
1279
|
}
|
|
@@ -318,8 +318,9 @@ export async function startVoiceTurn(
|
|
|
318
318
|
|
|
319
319
|
// Phone voice has no interactive permission/secret UI, so apply explicit
|
|
320
320
|
// per-role policies by default. Local live voice opts into the normal
|
|
321
|
-
// client approval path instead. Side-effect double-defense
|
|
322
|
-
//
|
|
321
|
+
// client approval path instead. Side-effect double-defense
|
|
322
|
+
// (forcePromptSideEffects) is wired inside the agent-loop IIFE so it
|
|
323
|
+
// is always paired with cleanup() in the IIFE's finally.
|
|
323
324
|
const trustClass = opts.trustContext?.trustClass;
|
|
324
325
|
const isGuardian = trustClass === "guardian";
|
|
325
326
|
const approvalMode = opts.approvalMode ?? "phone-call";
|
|
@@ -391,34 +392,57 @@ export async function startVoiceTurn(
|
|
|
391
392
|
}
|
|
392
393
|
}
|
|
393
394
|
|
|
394
|
-
//
|
|
395
|
-
//
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
395
|
+
// Hoisted so the catch below can clear partially-applied turn state
|
|
396
|
+
// when a setter or `persistUserMessage` throws — otherwise `trustContext`,
|
|
397
|
+
// `callSessionId`, etc. leak into subsequent non-voice turns on the same
|
|
398
|
+
// conversation. The client callback is only reset when this turn actually
|
|
399
|
+
// installed it (tracked via `clientCallbackInstalled`); otherwise cleanup
|
|
400
|
+
// would detach an active sender installed by a prior turn.
|
|
401
|
+
let clientCallbackInstalled = false;
|
|
402
|
+
const cleanup = () => {
|
|
403
|
+
conversation.setChannelCapabilities(null);
|
|
404
|
+
conversation.setTrustContext(null);
|
|
405
|
+
conversation.setCommandIntent(null);
|
|
406
|
+
conversation.setAssistantId("self");
|
|
407
|
+
conversation.setVoiceCallControlPrompt(null);
|
|
408
|
+
conversation.callSessionId = undefined;
|
|
409
|
+
conversation.forcePromptSideEffects = false;
|
|
410
|
+
if (clientCallbackInstalled) {
|
|
411
|
+
// Reset the client callback to a no-op so the stale closure doesn't
|
|
412
|
+
// intercept events from future turns on the same conversation.
|
|
413
|
+
conversation.updateClient(() => {}, true);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
414
416
|
|
|
415
417
|
const requestId = crypto.randomUUID();
|
|
416
418
|
const turnId = crypto.randomUUID();
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
419
|
+
let messageId: string;
|
|
420
|
+
try {
|
|
421
|
+
conversation.setAssistantId(
|
|
422
|
+
opts.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID,
|
|
423
|
+
);
|
|
424
|
+
conversation.callSessionId = voiceSessionId;
|
|
425
|
+
conversation.setTrustContext(opts.trustContext ?? null);
|
|
426
|
+
conversation.setCommandIntent(null);
|
|
427
|
+
conversation.setTurnChannelContext(turnChannelContext);
|
|
428
|
+
conversation.setTurnInterfaceContext?.(turnInterfaceContext);
|
|
429
|
+
conversation.setChannelCapabilities(
|
|
430
|
+
resolveChannelCapabilities(
|
|
431
|
+
turnChannelContext.userMessageChannel,
|
|
432
|
+
turnInterfaceContext.userMessageInterface,
|
|
433
|
+
),
|
|
434
|
+
);
|
|
435
|
+
conversation.setVoiceCallControlPrompt(voiceCallControlPrompt);
|
|
436
|
+
|
|
437
|
+
messageId = await conversation.persistUserMessage(
|
|
438
|
+
persistedContent,
|
|
439
|
+
[],
|
|
440
|
+
requestId,
|
|
441
|
+
);
|
|
442
|
+
} catch (err) {
|
|
443
|
+
cleanup();
|
|
444
|
+
throw err;
|
|
445
|
+
}
|
|
422
446
|
try {
|
|
423
447
|
opts.callbacks?.persisted_user_message_id?.(messageId);
|
|
424
448
|
} catch (err) {
|
|
@@ -556,25 +580,20 @@ export async function startVoiceTurn(
|
|
|
556
580
|
}
|
|
557
581
|
broadcastMessage(msg);
|
|
558
582
|
});
|
|
583
|
+
clientCallbackInstalled = true;
|
|
559
584
|
|
|
560
585
|
// Fire-and-forget the agent loop
|
|
561
|
-
const cleanup = () => {
|
|
562
|
-
// Reset channel capabilities so a subsequent desktop session on the
|
|
563
|
-
// same conversation is not incorrectly treated as a voice client.
|
|
564
|
-
conversation.setChannelCapabilities(null);
|
|
565
|
-
conversation.setTrustContext(null);
|
|
566
|
-
conversation.setCommandIntent(null);
|
|
567
|
-
conversation.setAssistantId("self");
|
|
568
|
-
conversation.setVoiceCallControlPrompt(null);
|
|
569
|
-
conversation.callSessionId = undefined;
|
|
570
|
-
conversation.forcePromptSideEffects = false;
|
|
571
|
-
// Reset the conversation's client callback to a no-op so the stale
|
|
572
|
-
// closure doesn't intercept events from future turns on the same conversation.
|
|
573
|
-
conversation.updateClient(() => {}, true);
|
|
574
|
-
};
|
|
575
|
-
|
|
576
586
|
void (async () => {
|
|
577
587
|
try {
|
|
588
|
+
// Non-guardian phone voice forces side-effect tools to prompt so the
|
|
589
|
+
// auto-deny handler above reliably sees a confirmation_request. Without
|
|
590
|
+
// this, a broad allow trust rule (e.g. wildcard bash) would let
|
|
591
|
+
// side-effect tools execute without ever emitting an event for the
|
|
592
|
+
// auto-deny / scoped-grant handler to intercept. Set inside the
|
|
593
|
+
// try/finally so a failed setup before this point cannot leak the
|
|
594
|
+
// flag into subsequent non-voice turns on the same conversation.
|
|
595
|
+
conversation.forcePromptSideEffects =
|
|
596
|
+
!isGuardian && !usesLocalInteractiveApprovals;
|
|
578
597
|
await conversation.runAgentLoop(
|
|
579
598
|
persistedContent,
|
|
580
599
|
messageId,
|
package/src/channels/config.ts
CHANGED
|
@@ -94,6 +94,15 @@ const CHANNEL_POLICIES = {
|
|
|
94
94
|
codeRedemptionEnabled: false,
|
|
95
95
|
},
|
|
96
96
|
},
|
|
97
|
+
a2a: {
|
|
98
|
+
notification: {
|
|
99
|
+
deliveryEnabled: false,
|
|
100
|
+
conversationStrategy: "continue_existing_conversation",
|
|
101
|
+
},
|
|
102
|
+
invite: {
|
|
103
|
+
codeRedemptionEnabled: false,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
97
106
|
} as const satisfies Record<ChannelId, ChannelNotificationPolicy>;
|
|
98
107
|
|
|
99
108
|
export type ChannelPolicies = typeof CHANNEL_POLICIES;
|