@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
|
@@ -17,9 +17,16 @@
|
|
|
17
17
|
* targets the user's actual desktop application, which is a host-wide
|
|
18
18
|
* resource. It is acquired optimistically when `app_control_start` is
|
|
19
19
|
* dispatched (storing `(conversationId, app)`) so that the synchronous
|
|
20
|
-
* guard and the asynchronous host round-trip cannot race
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* guard and the asynchronous host round-trip cannot race. A separate
|
|
21
|
+
* `confirmedAppControlSession` tracks the last session the host reported
|
|
22
|
+
* `running`; the rollback path on a failed `start` restores from the
|
|
23
|
+
* current confirmed pointer (not from a per-call snapshot of a sibling
|
|
24
|
+
* optimistic write), so two overlapping starts that both fail cannot
|
|
25
|
+
* leave a phantom lock. Each session carries a monotonic `dispatchedAt`
|
|
26
|
+
* counter so out-of-order `running` responses promote in dispatch order:
|
|
27
|
+
* the latest-dispatched start that the host confirms becomes the
|
|
28
|
+
* confirmed baseline, regardless of which response arrived last. The
|
|
29
|
+
* lock is released outright when the owning proxy's `dispose()` fires.
|
|
23
30
|
*
|
|
24
31
|
* `app_control_start` is the only tool that can acquire the lock — the
|
|
25
32
|
* user's medium-risk approval at start time is the consent boundary. All
|
|
@@ -78,37 +85,78 @@ export interface ActiveAppControlSession {
|
|
|
78
85
|
* the `app` of subsequent non-start tool calls.
|
|
79
86
|
*/
|
|
80
87
|
app: string;
|
|
88
|
+
/**
|
|
89
|
+
* Strictly monotonic counter assigned when the session is created (in
|
|
90
|
+
* `request()` for a `start`). Used by {@link promoteStartIfCurrent} to
|
|
91
|
+
* tell which of two confirmations from overlapping starts is newer when
|
|
92
|
+
* host responses arrive out of order. Larger values are newer.
|
|
93
|
+
*/
|
|
94
|
+
dispatchedAt: number;
|
|
81
95
|
}
|
|
82
96
|
|
|
83
97
|
/**
|
|
84
|
-
*
|
|
98
|
+
* Monotonic counter that stamps each `start`'s {@link
|
|
99
|
+
* ActiveAppControlSession.dispatchedAt}. Process-lifetime monotonic; the
|
|
100
|
+
* absolute value is meaningless — only ordering matters.
|
|
101
|
+
*/
|
|
102
|
+
let nextDispatchedAt = 1;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Currently active session, or `undefined` when no session is held. This
|
|
106
|
+
* is the optimistic value: it is set the moment a `start` is dispatched
|
|
107
|
+
* and only promoted to {@link confirmedAppControlSession} when the host
|
|
108
|
+
* returns `running`.
|
|
85
109
|
*
|
|
86
110
|
* Exported for test inspection only. Production code paths must not read
|
|
87
111
|
* or mutate this directly — use the proxy methods.
|
|
88
112
|
*/
|
|
89
113
|
let activeAppControlSession: ActiveAppControlSession | undefined;
|
|
90
114
|
|
|
91
|
-
/**
|
|
115
|
+
/**
|
|
116
|
+
* Last session whose `start` was confirmed by the host (`payload.state ===
|
|
117
|
+
* "running"`). Used as the rollback baseline so a failed start never
|
|
118
|
+
* restores a sibling in-flight optimistic write — only a session that was
|
|
119
|
+
* actually running can re-emerge from a rollback.
|
|
120
|
+
*/
|
|
121
|
+
let confirmedAppControlSession: ActiveAppControlSession | undefined;
|
|
122
|
+
|
|
123
|
+
/** Test-only helper: read current (optimistic) session. */
|
|
92
124
|
export function _getActiveAppControlSession():
|
|
93
125
|
| ActiveAppControlSession
|
|
94
126
|
| undefined {
|
|
95
127
|
return activeAppControlSession;
|
|
96
128
|
}
|
|
97
129
|
|
|
98
|
-
/** Test-only helper:
|
|
130
|
+
/** Test-only helper: read the last host-confirmed session. */
|
|
131
|
+
export function _getConfirmedAppControlSession():
|
|
132
|
+
| ActiveAppControlSession
|
|
133
|
+
| undefined {
|
|
134
|
+
return confirmedAppControlSession;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Test-only helper: clear both session pointers between test cases. */
|
|
99
138
|
export function _resetActiveAppControlSession(): void {
|
|
100
139
|
activeAppControlSession = undefined;
|
|
140
|
+
confirmedAppControlSession = undefined;
|
|
101
141
|
}
|
|
102
142
|
|
|
103
143
|
/**
|
|
104
|
-
* Test-only helper: prime
|
|
105
|
-
* Useful for tests that exercise non-start tool paths and
|
|
106
|
-
* verify the start flow itself.
|
|
144
|
+
* Test-only helper: prime both session pointers without a full `start`
|
|
145
|
+
* round-trip. Useful for tests that exercise non-start tool paths and
|
|
146
|
+
* don't need to verify the start flow itself.
|
|
107
147
|
*/
|
|
108
|
-
export function _setActiveAppControlSession(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
148
|
+
export function _setActiveAppControlSession(session: {
|
|
149
|
+
conversationId: string;
|
|
150
|
+
app: string;
|
|
151
|
+
dispatchedAt?: number;
|
|
152
|
+
}): void {
|
|
153
|
+
const full: ActiveAppControlSession = {
|
|
154
|
+
conversationId: session.conversationId,
|
|
155
|
+
app: session.app,
|
|
156
|
+
dispatchedAt: session.dispatchedAt ?? nextDispatchedAt++,
|
|
157
|
+
};
|
|
158
|
+
activeAppControlSession = full;
|
|
159
|
+
confirmedAppControlSession = full;
|
|
112
160
|
}
|
|
113
161
|
|
|
114
162
|
/**
|
|
@@ -236,6 +284,7 @@ export class HostAppControlProxy extends HostProxyBase<
|
|
|
236
284
|
// belong to the active session and target the same `app`. Without this
|
|
237
285
|
// gate, prompt-injected calls would bypass the start-time approval and
|
|
238
286
|
// send raw input to arbitrary apps.
|
|
287
|
+
let attemptedSession: ActiveAppControlSession | undefined;
|
|
239
288
|
if (input.tool === "start") {
|
|
240
289
|
if (
|
|
241
290
|
activeAppControlSession != null &&
|
|
@@ -253,12 +302,16 @@ export class HostAppControlProxy extends HostProxyBase<
|
|
|
253
302
|
// synchronous guard and the asynchronous `dispatchRequest` below. Two
|
|
254
303
|
// concurrent starts from different conversations would otherwise both
|
|
255
304
|
// see `activeAppControlSession == null` and both pass the guard. The
|
|
256
|
-
// lock is
|
|
257
|
-
// non-running state
|
|
258
|
-
|
|
305
|
+
// lock is rolled back below if dispatch fails or the host returns a
|
|
306
|
+
// non-running state — keyed on object identity so that a later
|
|
307
|
+
// overlapping start that has already replaced our write is not
|
|
308
|
+
// clobbered by a stale rollback.
|
|
309
|
+
attemptedSession = {
|
|
259
310
|
conversationId: this.conversationId,
|
|
260
311
|
app: input.app,
|
|
312
|
+
dispatchedAt: nextDispatchedAt++,
|
|
261
313
|
};
|
|
314
|
+
activeAppControlSession = attemptedSession;
|
|
262
315
|
} else {
|
|
263
316
|
const sessionError = checkNonStartAuthorization(
|
|
264
317
|
input,
|
|
@@ -278,10 +331,17 @@ export class HostAppControlProxy extends HostProxyBase<
|
|
|
278
331
|
undefined,
|
|
279
332
|
targetClientId,
|
|
280
333
|
);
|
|
281
|
-
|
|
334
|
+
if (input.tool === "start") {
|
|
335
|
+
if (payload.state === "running") {
|
|
336
|
+
this.promoteStartIfCurrent(attemptedSession);
|
|
337
|
+
} else {
|
|
338
|
+
this.rollbackStartIfCurrent(attemptedSession);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return this.handleSuccess(payload);
|
|
282
342
|
} catch (err) {
|
|
283
343
|
if (input.tool === "start") {
|
|
284
|
-
this.
|
|
344
|
+
this.rollbackStartIfCurrent(attemptedSession);
|
|
285
345
|
}
|
|
286
346
|
if (err instanceof HostProxyRequestError) {
|
|
287
347
|
if (err.reason === "timeout") {
|
|
@@ -301,10 +361,85 @@ export class HostAppControlProxy extends HostProxyBase<
|
|
|
301
361
|
}
|
|
302
362
|
}
|
|
303
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Roll back the optimistic overwrite performed by a `start` when the
|
|
366
|
+
* dispatch fails or the host returns non-running. Keyed on the
|
|
367
|
+
* `attempted` reference, not just `conversationId`, so that an
|
|
368
|
+
* out-of-order failure does not clobber a newer overlapping start that
|
|
369
|
+
* already replaced our write — e.g. start A → start B (pending) →
|
|
370
|
+
* start C (success); when B later fails, the live session is C and the
|
|
371
|
+
* identity check makes our rollback a no-op rather than restoring A.
|
|
372
|
+
*
|
|
373
|
+
* Restores from the *current* `confirmedAppControlSession`, not a
|
|
374
|
+
* per-call snapshot of it. This matters when a late-arriving `running`
|
|
375
|
+
* for an older overlapping start has updated `confirmedAppControlSession`
|
|
376
|
+
* in the meantime: if A is dispatched, then C is dispatched (overwriting
|
|
377
|
+
* active), then A returns `running` (confirming A), then C returns
|
|
378
|
+
* non-running, the rollback must restore active to A — not undefined.
|
|
379
|
+
*/
|
|
380
|
+
private rollbackStartIfCurrent(
|
|
381
|
+
attempted: ActiveAppControlSession | undefined,
|
|
382
|
+
): void {
|
|
383
|
+
if (attempted != null && activeAppControlSession === attempted) {
|
|
384
|
+
activeAppControlSession = confirmedAppControlSession;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Promote this start's session to the confirmed pointer when the host
|
|
390
|
+
* returns `running`. Two gates:
|
|
391
|
+
*
|
|
392
|
+
* 1. The live optimistic write must still belong to this conversation —
|
|
393
|
+
* if `dispose()` cleared the lock or another conversation acquired
|
|
394
|
+
* it, this confirmation must not resurrect a stale session.
|
|
395
|
+
* 2. The confirming session must be at least as recent as the currently
|
|
396
|
+
* confirmed one, compared via {@link
|
|
397
|
+
* ActiveAppControlSession.dispatchedAt}. The dispatch counter is
|
|
398
|
+
* assigned synchronously in `request()`, so it captures dispatch
|
|
399
|
+
* order even when host responses arrive out of order. The latest
|
|
400
|
+
* dispatched start that confirms wins, which is the right baseline
|
|
401
|
+
* for the rollback path: if a newer start later fails, rollback
|
|
402
|
+
* restores the most recently confirmed session, not an older one.
|
|
403
|
+
*
|
|
404
|
+
* Also advance the active pointer when it is strictly older than the
|
|
405
|
+
* newly-confirmed session. This handles the case where an even newer
|
|
406
|
+
* optimistic write has already failed and rolled active back to the
|
|
407
|
+
* previous confirmed session; without this, observe/actions for the
|
|
408
|
+
* newly-confirmed session would target the older app. A newer
|
|
409
|
+
* in-flight optimistic write (higher `dispatchedAt`) is preserved.
|
|
410
|
+
*/
|
|
411
|
+
private promoteStartIfCurrent(
|
|
412
|
+
attempted: ActiveAppControlSession | undefined,
|
|
413
|
+
): void {
|
|
414
|
+
if (attempted == null) return;
|
|
415
|
+
if (activeAppControlSession?.conversationId !== attempted.conversationId) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (
|
|
419
|
+
confirmedAppControlSession != null &&
|
|
420
|
+
attempted.dispatchedAt <= confirmedAppControlSession.dispatchedAt
|
|
421
|
+
) {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
confirmedAppControlSession = attempted;
|
|
425
|
+
if (activeAppControlSession.dispatchedAt < attempted.dispatchedAt) {
|
|
426
|
+
activeAppControlSession = attempted;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Release both the optimistic and confirmed module-level session
|
|
432
|
+
* pointers if this proxy is the current holder. Used by `dispose()` —
|
|
433
|
+
* distinct from `rollbackStartIfCurrent` because dispose is keyed on
|
|
434
|
+
* ownership (conversationId) rather than on a specific in-flight start.
|
|
435
|
+
*/
|
|
304
436
|
private releaseSessionIfHeld(): void {
|
|
305
437
|
if (activeAppControlSession?.conversationId === this.conversationId) {
|
|
306
438
|
activeAppControlSession = undefined;
|
|
307
439
|
}
|
|
440
|
+
if (confirmedAppControlSession?.conversationId === this.conversationId) {
|
|
441
|
+
confirmedAppControlSession = undefined;
|
|
442
|
+
}
|
|
308
443
|
}
|
|
309
444
|
|
|
310
445
|
// ---------------------------------------------------------------------------
|
|
@@ -312,7 +447,6 @@ export class HostAppControlProxy extends HostProxyBase<
|
|
|
312
447
|
// ---------------------------------------------------------------------------
|
|
313
448
|
|
|
314
449
|
private handleSuccess(
|
|
315
|
-
input: HostAppControlInput,
|
|
316
450
|
payload: HostAppControlResultPayload,
|
|
317
451
|
): ToolExecutionResult {
|
|
318
452
|
// Update PNG-hash loop tracking only for the "running" state — other
|
|
@@ -332,14 +466,6 @@ export class HostAppControlProxy extends HostProxyBase<
|
|
|
332
466
|
}
|
|
333
467
|
}
|
|
334
468
|
|
|
335
|
-
// The optimistic lock acquired in `request()` for `start` stays held
|
|
336
|
-
// only when the host confirms the session is running. Non-running
|
|
337
|
-
// outcomes (missing/minimized) release it so a retry or another
|
|
338
|
-
// conversation can acquire.
|
|
339
|
-
if (input.tool === "start" && payload.state !== "running") {
|
|
340
|
-
this.releaseSessionIfHeld();
|
|
341
|
-
}
|
|
342
|
-
|
|
343
469
|
return this.formatResult(payload, stuck);
|
|
344
470
|
}
|
|
345
471
|
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
import type { HostProxyCapability, InterfaceId } from "../channels/types.js";
|
|
30
30
|
import { supportsHostProxy } from "../channels/types.js";
|
|
31
31
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
32
|
+
import { getLogger } from "../util/logger.js";
|
|
33
|
+
|
|
34
|
+
const log = getLogger("host-proxy-preactivation");
|
|
32
35
|
|
|
33
36
|
/**
|
|
34
37
|
* Subset of Conversation/ProcessConversationContext that
|
|
@@ -36,9 +39,29 @@ import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
|
36
39
|
* `ProcessConversationContext` satisfy this structurally.
|
|
37
40
|
*/
|
|
38
41
|
export interface HostProxyPreactivationTarget {
|
|
42
|
+
readonly conversationId: string;
|
|
39
43
|
addPreactivatedSkillId(id: string): void;
|
|
40
44
|
}
|
|
41
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Why an attachment decision went the way it did. Logged per turn so that
|
|
48
|
+
* silent-gate failures (e.g. ATL-609: computer-use never reaches the LLM
|
|
49
|
+
* surface for a macOS user) can be diagnosed from production logs without
|
|
50
|
+
* extra instrumentation.
|
|
51
|
+
*/
|
|
52
|
+
export type HostProxyAttachmentReason =
|
|
53
|
+
| "native_support"
|
|
54
|
+
| "cross_client"
|
|
55
|
+
| "denied_no_interface"
|
|
56
|
+
| "denied_chrome_extension"
|
|
57
|
+
| "denied_no_clients";
|
|
58
|
+
|
|
59
|
+
export interface HostProxyAttachmentDecision {
|
|
60
|
+
shouldAttach: boolean;
|
|
61
|
+
reason: HostProxyAttachmentReason;
|
|
62
|
+
clientCount?: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
42
65
|
/**
|
|
43
66
|
* Registry mapping each host-proxy capability to the skill that must be
|
|
44
67
|
* preactivated when that capability is supported by the source interface.
|
|
@@ -62,45 +85,89 @@ export const HOST_PROXY_SKILL_PREACTIVATIONS: ReadonlyArray<{
|
|
|
62
85
|
];
|
|
63
86
|
|
|
64
87
|
/**
|
|
65
|
-
* Returns
|
|
66
|
-
*
|
|
88
|
+
* Returns the full attachment decision for a host-proxy capability — used both
|
|
89
|
+
* to gate proxy instantiation and to feed the structured preactivation log so
|
|
90
|
+
* silent gates can be diagnosed without re-instrumenting after the fact.
|
|
67
91
|
*
|
|
68
|
-
* 1.
|
|
69
|
-
* 2.
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
92
|
+
* 1. No source interface → `denied_no_interface`.
|
|
93
|
+
* 2. Source interface natively supports the capability → `native_support`.
|
|
94
|
+
* 3. `chrome-extension` source can never broker cross-client routing to a
|
|
95
|
+
* macOS client (security boundary) → `denied_chrome_extension`.
|
|
96
|
+
* 4. At least one connected client advertises the capability →
|
|
97
|
+
* `cross_client` with `clientCount`.
|
|
98
|
+
* 5. Otherwise → `denied_no_clients` with `clientCount: 0`.
|
|
73
99
|
*
|
|
74
|
-
*
|
|
75
|
-
|
|
100
|
+
* Single source of truth for preactivation and proxy instantiation.
|
|
101
|
+
*/
|
|
102
|
+
export function evaluateHostProxyAttachment(
|
|
103
|
+
capability: HostProxyCapability,
|
|
104
|
+
sourceInterface: InterfaceId | undefined,
|
|
105
|
+
): HostProxyAttachmentDecision {
|
|
106
|
+
if (!sourceInterface) {
|
|
107
|
+
return { shouldAttach: false, reason: "denied_no_interface" };
|
|
108
|
+
}
|
|
109
|
+
if (supportsHostProxy(sourceInterface, capability)) {
|
|
110
|
+
return { shouldAttach: true, reason: "native_support" };
|
|
111
|
+
}
|
|
112
|
+
if (sourceInterface === "chrome-extension") {
|
|
113
|
+
return { shouldAttach: false, reason: "denied_chrome_extension" };
|
|
114
|
+
}
|
|
115
|
+
const clientCount =
|
|
116
|
+
assistantEventHub.listClientsByCapability(capability).length;
|
|
117
|
+
if (clientCount > 0) {
|
|
118
|
+
return { shouldAttach: true, reason: "cross_client", clientCount };
|
|
119
|
+
}
|
|
120
|
+
return { shouldAttach: false, reason: "denied_no_clients", clientCount: 0 };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Boolean wrapper retained for the proxy-instantiation call sites that only
|
|
125
|
+
* need the gate result. Prefer `evaluateHostProxyAttachment` when the reason
|
|
126
|
+
* is also useful (e.g. for logging or telemetry).
|
|
76
127
|
*/
|
|
77
128
|
export function shouldAttachHostProxyForCapability(
|
|
78
129
|
capability: HostProxyCapability,
|
|
79
130
|
sourceInterface: InterfaceId | undefined,
|
|
80
131
|
): boolean {
|
|
81
|
-
|
|
82
|
-
if (supportsHostProxy(sourceInterface, capability)) return true;
|
|
83
|
-
if (sourceInterface === "chrome-extension") return false;
|
|
84
|
-
return assistantEventHub.listClientsByCapability(capability).length > 0;
|
|
132
|
+
return evaluateHostProxyAttachment(capability, sourceInterface).shouldAttach;
|
|
85
133
|
}
|
|
86
134
|
|
|
87
135
|
/**
|
|
88
136
|
* Preactivate every host-proxy-backed skill that the given source interface
|
|
89
|
-
* supports
|
|
137
|
+
* supports, and emit one structured `log.info` line per turn capturing each
|
|
138
|
+
* capability's decision + the final preactivated skill IDs.
|
|
139
|
+
*
|
|
140
|
+
* The log line fires unconditionally — even when `sourceInterface` is
|
|
141
|
+
* undefined — because "preactivation never ran because no interface" is
|
|
142
|
+
* itself the diagnostic signal we want visible in production.
|
|
90
143
|
*
|
|
91
144
|
* Callers are responsible for any additional gating (e.g. only preactivating
|
|
92
145
|
* when the conversation is idle vs. when re-adding after dequeue), since
|
|
93
|
-
* those constraints differ across create vs. drain paths.
|
|
94
|
-
* iterates the registry and dispatches.
|
|
146
|
+
* those constraints differ across create vs. drain paths.
|
|
95
147
|
*/
|
|
96
148
|
export function preactivateHostProxySkills(
|
|
97
149
|
conversation: HostProxyPreactivationTarget,
|
|
98
150
|
sourceInterface: InterfaceId | undefined,
|
|
99
151
|
): void {
|
|
100
|
-
|
|
152
|
+
const decisions: Record<string, HostProxyAttachmentDecision> = {};
|
|
153
|
+
const preactivatedSkillIds: string[] = [];
|
|
154
|
+
|
|
101
155
|
for (const { capability, skillId } of HOST_PROXY_SKILL_PREACTIVATIONS) {
|
|
102
|
-
|
|
156
|
+
const decision = evaluateHostProxyAttachment(capability, sourceInterface);
|
|
157
|
+
decisions[capability] = decision;
|
|
158
|
+
if (decision.shouldAttach) {
|
|
103
159
|
conversation.addPreactivatedSkillId(skillId);
|
|
160
|
+
preactivatedSkillIds.push(skillId);
|
|
104
161
|
}
|
|
105
162
|
}
|
|
163
|
+
|
|
164
|
+
log.info(
|
|
165
|
+
{
|
|
166
|
+
conversationId: conversation.conversationId,
|
|
167
|
+
sourceInterface,
|
|
168
|
+
decisions,
|
|
169
|
+
preactivatedSkillIds,
|
|
170
|
+
},
|
|
171
|
+
"host-proxy preactivation decision",
|
|
172
|
+
);
|
|
106
173
|
}
|