@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
package/src/providers/retry.ts
CHANGED
|
@@ -72,6 +72,40 @@ const RETRYABLE_STREAM_PATTERNS = [
|
|
|
72
72
|
*/
|
|
73
73
|
const RETRYABLE_PROVIDER_MESSAGE_PATTERNS = [/overloaded/i];
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Patterns that indicate the Anthropic provider SDK reported a transport-level
|
|
77
|
+
* abort (TCP close mid-stream, edge LB idle cutoff, Bun fetch deadline) rather
|
|
78
|
+
* than a caller-initiated cancellation or inner-timeout deadline. The SDK
|
|
79
|
+
* surfaces all three cases as ``Request was aborted`` with ``error.status ===
|
|
80
|
+
* undefined``; the catch-site in ``providers/anthropic/client.ts`` separates
|
|
81
|
+
* them by:
|
|
82
|
+
* - tagging caller cancellations with ``abortReason`` (short-circuits in
|
|
83
|
+
* {@link isRetryableError} before reaching this predicate)
|
|
84
|
+
* - rewriting the inner-timeout message to ``"Anthropic stream timed out
|
|
85
|
+
* after Xs (inner streamTimeoutMs)"`` (doesn't start with ``Anthropic API
|
|
86
|
+
* error:`` so it falls through to network-error classification)
|
|
87
|
+
* - leaving the transport-abort message verbatim as
|
|
88
|
+
* ``"Anthropic API error: Request was aborted."``
|
|
89
|
+
*
|
|
90
|
+
* Pattern is intentionally anchored to the Anthropic-specific message prefix.
|
|
91
|
+
* The OpenAI / Gemini / OpenRouter catch-sites format their errors as
|
|
92
|
+
* ``"<Provider> API error (undefined): Request was aborted."`` (note the
|
|
93
|
+
* ``(undefined)`` parenthetical) and — crucially — do **not** rewrite
|
|
94
|
+
* inner-timeout failures, so a provider-agnostic ``/request was aborted/i``
|
|
95
|
+
* predicate would erroneously retry their 30-minute deadline failures three
|
|
96
|
+
* additional times. Once those catch-sites grow the same
|
|
97
|
+
* ``innerTimeoutFired`` distinction the Anthropic one has, the pattern set
|
|
98
|
+
* here can be expanded to cover them too.
|
|
99
|
+
*
|
|
100
|
+
* This is the daemon-side counterpart to the vembda graceful-close behavior
|
|
101
|
+
* for upstream disconnects (LUM-1536) — together they collapse the 45 s
|
|
102
|
+
* silent-stall window the web client used to observe whenever Anthropic's
|
|
103
|
+
* stream was cut mid-token.
|
|
104
|
+
*/
|
|
105
|
+
const RETRYABLE_TRANSPORT_ABORT_PATTERNS = [
|
|
106
|
+
/^anthropic api error:\s*request was aborted/i,
|
|
107
|
+
];
|
|
108
|
+
|
|
75
109
|
function isRetryableStreamError(error: unknown): boolean {
|
|
76
110
|
if (!(error instanceof ProviderError)) return false;
|
|
77
111
|
if (error.statusCode !== undefined) return false; // has a real HTTP status — not a stream error
|
|
@@ -84,6 +118,15 @@ function isRetryableProviderMessage(error: unknown): boolean {
|
|
|
84
118
|
return RETRYABLE_PROVIDER_MESSAGE_PATTERNS.some((p) => p.test(error.message));
|
|
85
119
|
}
|
|
86
120
|
|
|
121
|
+
function isRetryableTransportAbort(error: unknown): boolean {
|
|
122
|
+
if (!(error instanceof ProviderError)) return false;
|
|
123
|
+
// Transport aborts surface with ``status === undefined`` (the SDK never
|
|
124
|
+
// saw an HTTP response). A real HTTP status here means a server error,
|
|
125
|
+
// which is handled by the status check.
|
|
126
|
+
if (error.statusCode !== undefined) return false;
|
|
127
|
+
return RETRYABLE_TRANSPORT_ABORT_PATTERNS.some((p) => p.test(error.message));
|
|
128
|
+
}
|
|
129
|
+
|
|
87
130
|
function isRetryableError(error: unknown): boolean {
|
|
88
131
|
// Context overflow is deterministic — retrying the same oversized prompt
|
|
89
132
|
// will never succeed. Short-circuit before the generic 429/5xx check so
|
|
@@ -103,6 +146,7 @@ function isRetryableError(error: unknown): boolean {
|
|
|
103
146
|
}
|
|
104
147
|
if (isRetryableProviderMessage(error)) return true;
|
|
105
148
|
if (isRetryableStreamError(error)) return true;
|
|
149
|
+
if (isRetryableTransportAbort(error)) return true;
|
|
106
150
|
return isRetryableNetworkError(error);
|
|
107
151
|
}
|
|
108
152
|
|
|
@@ -482,7 +526,9 @@ export class RetryProvider implements Provider {
|
|
|
482
526
|
? "provider_overloaded"
|
|
483
527
|
: isRetryableStreamError(error)
|
|
484
528
|
? "stream_corruption"
|
|
485
|
-
:
|
|
529
|
+
: isRetryableTransportAbort(error)
|
|
530
|
+
? "transport_abort"
|
|
531
|
+
: "network_error";
|
|
486
532
|
log.warn(
|
|
487
533
|
{
|
|
488
534
|
attempt: attempt + 1,
|
|
@@ -68,6 +68,33 @@ mock.module("../../daemon/disk-pressure-guard.js", () => ({
|
|
|
68
68
|
getDiskPressureStatus: () => mockDiskPressureStatus,
|
|
69
69
|
}));
|
|
70
70
|
|
|
71
|
+
const recordRequestLogCalls: Array<{
|
|
72
|
+
conversationId: string;
|
|
73
|
+
requestPayload: string;
|
|
74
|
+
responsePayload: string;
|
|
75
|
+
messageId?: string;
|
|
76
|
+
provider?: string;
|
|
77
|
+
}> = [];
|
|
78
|
+
mock.module("../../memory/llm-request-log-store.js", () => ({
|
|
79
|
+
recordRequestLog: (
|
|
80
|
+
conversationId: string,
|
|
81
|
+
requestPayload: string,
|
|
82
|
+
responsePayload: string,
|
|
83
|
+
messageId?: string,
|
|
84
|
+
provider?: string,
|
|
85
|
+
) => {
|
|
86
|
+
recordRequestLogCalls.push({
|
|
87
|
+
conversationId,
|
|
88
|
+
requestPayload,
|
|
89
|
+
responsePayload,
|
|
90
|
+
messageId,
|
|
91
|
+
provider,
|
|
92
|
+
});
|
|
93
|
+
return "log-id-test";
|
|
94
|
+
},
|
|
95
|
+
backfillMessageIdOnLogs: () => {},
|
|
96
|
+
}));
|
|
97
|
+
|
|
71
98
|
import type { AgentEvent } from "../../agent/loop.js";
|
|
72
99
|
import type { Message } from "../../providers/types.js";
|
|
73
100
|
import {
|
|
@@ -220,6 +247,7 @@ function makeTarget(options: {
|
|
|
220
247
|
|
|
221
248
|
beforeEach(() => {
|
|
222
249
|
__resetWakeChainForTests();
|
|
250
|
+
recordRequestLogCalls.length = 0;
|
|
223
251
|
mockDiskPressureStatus = {
|
|
224
252
|
enabled: false,
|
|
225
253
|
state: "disabled",
|
|
@@ -1435,4 +1463,128 @@ describe("wakeAgentForOpportunity", () => {
|
|
|
1435
1463
|
expect(uiBlock!.surfaceId).toBe(wakeProducedOutputCalls[0]);
|
|
1436
1464
|
},
|
|
1437
1465
|
);
|
|
1466
|
+
|
|
1467
|
+
test(
|
|
1468
|
+
"silent no-op wake drops LLM request logs so a future backfillMessageIdOnLogs " +
|
|
1469
|
+
"sweep cannot misattach them to an unrelated assistant reply",
|
|
1470
|
+
async () => {
|
|
1471
|
+
const usageEvent: AgentEvent = {
|
|
1472
|
+
type: "usage",
|
|
1473
|
+
inputTokens: 100,
|
|
1474
|
+
outputTokens: 5,
|
|
1475
|
+
model: "test-model",
|
|
1476
|
+
actualProvider: "test-provider",
|
|
1477
|
+
providerDurationMs: 10,
|
|
1478
|
+
rawRequest: { request: "no-op wake" },
|
|
1479
|
+
rawResponse: { response: "no output" },
|
|
1480
|
+
};
|
|
1481
|
+
const target = makeTarget({
|
|
1482
|
+
baseline: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
|
|
1483
|
+
scriptedEvents: [usageEvent],
|
|
1484
|
+
// Empty assistant text → silent no-op.
|
|
1485
|
+
scriptedAssistant: {
|
|
1486
|
+
role: "assistant",
|
|
1487
|
+
content: [{ type: "text", text: "" }],
|
|
1488
|
+
},
|
|
1489
|
+
});
|
|
1490
|
+
|
|
1491
|
+
const result = await wakeAgentForOpportunity(
|
|
1492
|
+
{
|
|
1493
|
+
conversationId: target.conversationId,
|
|
1494
|
+
hint: "consider doing nothing",
|
|
1495
|
+
source: "unit-test",
|
|
1496
|
+
},
|
|
1497
|
+
{ resolveTarget: async () => target },
|
|
1498
|
+
);
|
|
1499
|
+
|
|
1500
|
+
expect(result).toEqual({ invoked: true, producedToolCalls: false });
|
|
1501
|
+
// Nothing emitted, nothing persisted to the conversation.
|
|
1502
|
+
expect(target.emittedEvents).toHaveLength(0);
|
|
1503
|
+
expect(target.persistedTailCalls).toHaveLength(0);
|
|
1504
|
+
// Critical: the LLM request log must NOT be inserted with messageId=NULL,
|
|
1505
|
+
// otherwise the next user turn's backfillMessageIdOnLogs sweep would
|
|
1506
|
+
// misattach this row to an unrelated future assistant reply.
|
|
1507
|
+
expect(recordRequestLogCalls).toHaveLength(0);
|
|
1508
|
+
},
|
|
1509
|
+
);
|
|
1510
|
+
|
|
1511
|
+
test("wake that produces output persists buffered LLM request logs", async () => {
|
|
1512
|
+
const usageEvent: AgentEvent = {
|
|
1513
|
+
type: "usage",
|
|
1514
|
+
inputTokens: 100,
|
|
1515
|
+
outputTokens: 5,
|
|
1516
|
+
model: "test-model",
|
|
1517
|
+
actualProvider: "test-provider",
|
|
1518
|
+
providerDurationMs: 10,
|
|
1519
|
+
rawRequest: { request: "produced wake" },
|
|
1520
|
+
rawResponse: { response: "real reply" },
|
|
1521
|
+
};
|
|
1522
|
+
const target = makeTarget({
|
|
1523
|
+
baseline: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
|
|
1524
|
+
scriptedEvents: [usageEvent],
|
|
1525
|
+
scriptedAssistant: {
|
|
1526
|
+
role: "assistant",
|
|
1527
|
+
content: [{ type: "text", text: "real reply" }],
|
|
1528
|
+
},
|
|
1529
|
+
});
|
|
1530
|
+
|
|
1531
|
+
const result = await wakeAgentForOpportunity(
|
|
1532
|
+
{
|
|
1533
|
+
conversationId: target.conversationId,
|
|
1534
|
+
hint: "do reply",
|
|
1535
|
+
source: "unit-test",
|
|
1536
|
+
},
|
|
1537
|
+
{ resolveTarget: async () => target },
|
|
1538
|
+
);
|
|
1539
|
+
|
|
1540
|
+
expect(result).toEqual({ invoked: true, producedToolCalls: false });
|
|
1541
|
+
expect(recordRequestLogCalls).toHaveLength(1);
|
|
1542
|
+
expect(recordRequestLogCalls[0]).toMatchObject({
|
|
1543
|
+
conversationId: target.conversationId,
|
|
1544
|
+
provider: "test-provider",
|
|
1545
|
+
messageId: undefined,
|
|
1546
|
+
});
|
|
1547
|
+
});
|
|
1548
|
+
|
|
1549
|
+
test("non-serializable usage payload does not abort the wake", async () => {
|
|
1550
|
+
// Circular reference in rawRequest — JSON.stringify throws on this.
|
|
1551
|
+
// Serialization must happen inside persistLog's try/catch so the
|
|
1552
|
+
// failure is swallowed as a non-fatal log warning rather than
|
|
1553
|
+
// escaping and aborting the wake.
|
|
1554
|
+
const circular: Record<string, unknown> = { request: "produced wake" };
|
|
1555
|
+
circular.self = circular;
|
|
1556
|
+
const usageEvent: AgentEvent = {
|
|
1557
|
+
type: "usage",
|
|
1558
|
+
inputTokens: 100,
|
|
1559
|
+
outputTokens: 5,
|
|
1560
|
+
model: "test-model",
|
|
1561
|
+
actualProvider: "test-provider",
|
|
1562
|
+
providerDurationMs: 10,
|
|
1563
|
+
rawRequest: circular,
|
|
1564
|
+
rawResponse: { response: "real reply" },
|
|
1565
|
+
};
|
|
1566
|
+
const target = makeTarget({
|
|
1567
|
+
baseline: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
|
|
1568
|
+
scriptedEvents: [usageEvent],
|
|
1569
|
+
scriptedAssistant: {
|
|
1570
|
+
role: "assistant",
|
|
1571
|
+
content: [{ type: "text", text: "real reply" }],
|
|
1572
|
+
},
|
|
1573
|
+
});
|
|
1574
|
+
|
|
1575
|
+
const result = await wakeAgentForOpportunity(
|
|
1576
|
+
{
|
|
1577
|
+
conversationId: target.conversationId,
|
|
1578
|
+
hint: "do reply",
|
|
1579
|
+
source: "unit-test",
|
|
1580
|
+
},
|
|
1581
|
+
{ resolveTarget: async () => target },
|
|
1582
|
+
);
|
|
1583
|
+
|
|
1584
|
+
expect(result).toEqual({ invoked: true, producedToolCalls: false });
|
|
1585
|
+
// Wake still produced output even though logging failed.
|
|
1586
|
+
expect(target.persistedTailCalls).toHaveLength(1);
|
|
1587
|
+
// No log row was inserted because JSON.stringify threw.
|
|
1588
|
+
expect(recordRequestLogCalls).toHaveLength(0);
|
|
1589
|
+
});
|
|
1438
1590
|
});
|
|
@@ -57,7 +57,11 @@ import {
|
|
|
57
57
|
} from "../daemon/disk-pressure-policy.js";
|
|
58
58
|
import type { TrustContext } from "../daemon/trust-context.js";
|
|
59
59
|
import { getConversationOverrideProfile } from "../memory/conversation-crud.js";
|
|
60
|
-
import {
|
|
60
|
+
import {
|
|
61
|
+
buildProviderErrorResponsePayload,
|
|
62
|
+
recordRequestLog,
|
|
63
|
+
setAgentLoopExitReasonOnLatestLog,
|
|
64
|
+
} from "../memory/llm-request-log-store.js";
|
|
61
65
|
import type { TurnContext } from "../plugins/types.js";
|
|
62
66
|
import type { Message } from "../providers/types.js";
|
|
63
67
|
import { getLogger } from "../util/logger.js";
|
|
@@ -330,7 +334,7 @@ function classifyWakeDiskPressurePolicy(opts: WakeOptions): {
|
|
|
330
334
|
const status = getDiskPressureStatus();
|
|
331
335
|
const decision = classifyDiskPressureTurnPolicy(status, {
|
|
332
336
|
conversationSource: opts.source,
|
|
333
|
-
callSite: "mainAgent",
|
|
337
|
+
callSite: opts.callSite ?? "mainAgent",
|
|
334
338
|
isDirectWake: true,
|
|
335
339
|
sourceChannel: opts.sourceChannel ?? opts.trustContext?.sourceChannel,
|
|
336
340
|
sourceInterface: opts.sourceInterface,
|
|
@@ -537,6 +541,49 @@ export async function wakeAgentForOpportunity(
|
|
|
537
541
|
// only after `agentLoop.run()` returns.
|
|
538
542
|
let mode: "buffering" | "live" = "buffering";
|
|
539
543
|
const buffered: AgentEvent[] = [];
|
|
544
|
+
// LLM request logs accumulated while buffering. Persisted only if the
|
|
545
|
+
// wake transitions to live (i.e. produced output). A silent no-op wake
|
|
546
|
+
// drops them — otherwise the next user-turn's `backfillMessageIdOnLogs`
|
|
547
|
+
// sweep would misattach these NULL-messageId rows to an unrelated
|
|
548
|
+
// future assistant message, contaminating inspector context.
|
|
549
|
+
type PendingLog = {
|
|
550
|
+
rawRequest: unknown;
|
|
551
|
+
rawResponse: unknown;
|
|
552
|
+
provider?: string;
|
|
553
|
+
};
|
|
554
|
+
const pendingLogs: PendingLog[] = [];
|
|
555
|
+
// Exit reason deferred alongside pendingLogs. Same drop-on-silent-
|
|
556
|
+
// wake guarantee: if the wake never goes live, this stays null and
|
|
557
|
+
// no DB row is touched. Applied after pendingLogs flush in goLive
|
|
558
|
+
// so the latest-row lookup in `setAgentLoopExitReasonOnLatestLog`
|
|
559
|
+
// can see the freshly-persisted final usage row.
|
|
560
|
+
let pendingExitReason: string | null = null;
|
|
561
|
+
const persistLog = (record: PendingLog): void => {
|
|
562
|
+
try {
|
|
563
|
+
recordRequestLog(
|
|
564
|
+
conversationId,
|
|
565
|
+
JSON.stringify(record.rawRequest),
|
|
566
|
+
JSON.stringify(record.rawResponse),
|
|
567
|
+
undefined,
|
|
568
|
+
record.provider,
|
|
569
|
+
);
|
|
570
|
+
} catch (err) {
|
|
571
|
+
log.warn(
|
|
572
|
+
{ err, conversationId, source },
|
|
573
|
+
"agent-wake: failed to persist LLM request log (non-fatal)",
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
const persistExitReason = (reason: string): void => {
|
|
578
|
+
try {
|
|
579
|
+
setAgentLoopExitReasonOnLatestLog(conversationId, reason);
|
|
580
|
+
} catch (err) {
|
|
581
|
+
log.warn(
|
|
582
|
+
{ err, conversationId, source, reason },
|
|
583
|
+
"agent-wake: failed to persist agent_loop_exit_reason (non-fatal)",
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
};
|
|
540
587
|
const safeEmit = (event: AgentEvent): void => {
|
|
541
588
|
try {
|
|
542
589
|
target.emitAgentEvent(event);
|
|
@@ -550,20 +597,49 @@ export async function wakeAgentForOpportunity(
|
|
|
550
597
|
const onEvent = (event: AgentEvent): void => {
|
|
551
598
|
// Replicates the recordRequestLog side-effect in `handleUsage` because
|
|
552
599
|
// wakes own their own onEvent and never reach `dispatchAgentEvent`.
|
|
600
|
+
// Defer persistence while buffering — see `pendingLogs` above.
|
|
553
601
|
if (event.type === "usage" && event.rawRequest && event.rawResponse) {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
602
|
+
const record = {
|
|
603
|
+
rawRequest: event.rawRequest,
|
|
604
|
+
rawResponse: event.rawResponse,
|
|
605
|
+
provider: event.actualProvider,
|
|
606
|
+
};
|
|
607
|
+
if (mode === "buffering") {
|
|
608
|
+
pendingLogs.push(record);
|
|
609
|
+
} else {
|
|
610
|
+
persistLog(record);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
// Mirror the same recording side-effect for provider-rejected calls.
|
|
614
|
+
// `handleProviderError` in the daemon dispatcher persists these on the
|
|
615
|
+
// normal turn path; the wake path owns its own onEvent and bypasses
|
|
616
|
+
// that dispatcher entirely, so we replicate here. Buffering rules
|
|
617
|
+
// match the success path: if the wake never goes live (silent no-op),
|
|
618
|
+
// the rows are dropped so a stale `messageId IS NULL` row doesn't get
|
|
619
|
+
// mis-backfilled onto an unrelated future assistant message.
|
|
620
|
+
if (event.type === "provider_error") {
|
|
621
|
+
const record: PendingLog = {
|
|
622
|
+
rawRequest: event.rawRequest,
|
|
623
|
+
rawResponse: buildProviderErrorResponsePayload(event.error),
|
|
624
|
+
provider: event.actualProvider,
|
|
625
|
+
};
|
|
626
|
+
if (mode === "buffering") {
|
|
627
|
+
pendingLogs.push(record);
|
|
628
|
+
} else {
|
|
629
|
+
persistLog(record);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
// Replicates the setAgentLoopExitReasonOnLatestLog side-effect that
|
|
633
|
+
// `dispatchAgentEvent` does for the normal path. In live mode the
|
|
634
|
+
// final usage event of the run has already landed its row, so the
|
|
635
|
+
// latest-row lookup hits the right target. In buffering mode the
|
|
636
|
+
// reason is stashed and applied in `goLive` after pendingLogs are
|
|
637
|
+
// persisted, preserving the same ordering guarantee.
|
|
638
|
+
if (event.type === "agent_loop_exit") {
|
|
639
|
+
if (mode === "buffering") {
|
|
640
|
+
pendingExitReason = event.reason;
|
|
641
|
+
} else {
|
|
642
|
+
persistExitReason(event.reason);
|
|
567
643
|
}
|
|
568
644
|
}
|
|
569
645
|
if (mode === "buffering") {
|
|
@@ -620,6 +696,18 @@ export async function wakeAgentForOpportunity(
|
|
|
620
696
|
safeEmit(event);
|
|
621
697
|
}
|
|
622
698
|
buffered.length = 0;
|
|
699
|
+
for (const record of pendingLogs) {
|
|
700
|
+
persistLog(record);
|
|
701
|
+
}
|
|
702
|
+
pendingLogs.length = 0;
|
|
703
|
+
// Apply the deferred exit reason after pendingLogs are persisted —
|
|
704
|
+
// the latest-row lookup in `setAgentLoopExitReasonOnLatestLog`
|
|
705
|
+
// needs the final usage row to already exist. Cleared after use so
|
|
706
|
+
// an extremely unlikely double-goLive can't double-stamp.
|
|
707
|
+
if (pendingExitReason !== null) {
|
|
708
|
+
persistExitReason(pendingExitReason);
|
|
709
|
+
pendingExitReason = null;
|
|
710
|
+
}
|
|
623
711
|
mode = "live";
|
|
624
712
|
};
|
|
625
713
|
|
|
@@ -164,6 +164,7 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
164
164
|
{ endpoint: "confirm", scopes: ["approval.write"] },
|
|
165
165
|
{ endpoint: "secret", scopes: ["approval.write"] },
|
|
166
166
|
{ endpoint: "trust-rules", scopes: ["approval.write"] },
|
|
167
|
+
{ endpoint: "question-response", scopes: ["approval.write"] },
|
|
167
168
|
{ endpoint: "host-app-control-result", scopes: ["approval.write"] },
|
|
168
169
|
{ endpoint: "host-bash-result", scopes: ["approval.write"] },
|
|
169
170
|
{ endpoint: "host-browser-result", scopes: ["approval.write"] },
|
|
@@ -242,6 +243,7 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
242
243
|
endpoint: "integrations/slack/channel/config:DELETE",
|
|
243
244
|
scopes: ["settings.write"],
|
|
244
245
|
},
|
|
246
|
+
{ endpoint: "integrations/a2a/invite", scopes: ["settings.write"] },
|
|
245
247
|
{ endpoint: "channel-verification-sessions", scopes: ["settings.write"] },
|
|
246
248
|
{
|
|
247
249
|
endpoint: "channel-verification-sessions:DELETE",
|
|
@@ -285,7 +287,8 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
285
287
|
{ endpoint: "slack/channels", scopes: ["settings.read"] },
|
|
286
288
|
{ endpoint: "slack/share", scopes: ["settings.write"] },
|
|
287
289
|
|
|
288
|
-
// Channel readiness
|
|
290
|
+
// Channel availability + readiness
|
|
291
|
+
{ endpoint: "channels/available", scopes: ["settings.read"] },
|
|
289
292
|
{ endpoint: "channels/readiness", scopes: ["settings.read"] },
|
|
290
293
|
{ endpoint: "channels/readiness/refresh", scopes: ["settings.write"] },
|
|
291
294
|
|
|
@@ -342,6 +345,7 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
342
345
|
|
|
343
346
|
// Lifecycle telemetry
|
|
344
347
|
{ endpoint: "telemetry/lifecycle", scopes: ["settings.write"] },
|
|
348
|
+
{ endpoint: "telemetry/flush", scopes: ["settings.write"] },
|
|
345
349
|
|
|
346
350
|
// Debug / introspection
|
|
347
351
|
{ endpoint: "clients", scopes: ["settings.read"] },
|
|
@@ -683,6 +687,18 @@ for (const endpoint of INTERNAL_ENDPOINTS) {
|
|
|
683
687
|
});
|
|
684
688
|
}
|
|
685
689
|
|
|
690
|
+
// A2A invite completion: gateway-only (platform-orchestrated)
|
|
691
|
+
registerPolicy("integrations/a2a/invite/complete", {
|
|
692
|
+
requiredScopes: ["internal.write"],
|
|
693
|
+
allowedPrincipalTypes: ["svc_gateway"],
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
// A2A invite redemption: gateway-only (platform-orchestrated)
|
|
697
|
+
registerPolicy("integrations/a2a/invite/redeem", {
|
|
698
|
+
requiredScopes: ["internal.write"],
|
|
699
|
+
allowedPrincipalTypes: ["svc_gateway"],
|
|
700
|
+
});
|
|
701
|
+
|
|
686
702
|
// Admin control-plane endpoints: gateway-only
|
|
687
703
|
registerPolicy("admin/upgrade-broadcast", {
|
|
688
704
|
requiredScopes: ["internal.write"],
|
|
@@ -1079,6 +1095,10 @@ registerPolicy("oauth/mode.set", {
|
|
|
1079
1095
|
requiredScopes: ["settings.write"],
|
|
1080
1096
|
allowedPrincipalTypes: ["local"],
|
|
1081
1097
|
});
|
|
1098
|
+
registerPolicy("oauth/connection-changed", {
|
|
1099
|
+
requiredScopes: ["settings.write"],
|
|
1100
|
+
allowedPrincipalTypes: ["local"],
|
|
1101
|
+
});
|
|
1082
1102
|
registerPolicy("oauth/status", {
|
|
1083
1103
|
requiredScopes: ["settings.read"],
|
|
1084
1104
|
allowedPrincipalTypes: ["local"],
|
|
@@ -70,6 +70,8 @@ export async function runBtwSidechain(
|
|
|
70
70
|
const tools = params.tools;
|
|
71
71
|
const history = params.messages ?? params.conversation?.getMessages() ?? [];
|
|
72
72
|
const messages = [...history, userMessage(trimmedContent)];
|
|
73
|
+
// Side-chains force `tool_choice: { type: "none" }` below, so tool usage
|
|
74
|
+
// guidance must stay in tool descriptions rather than this system prompt.
|
|
73
75
|
const systemPrompt =
|
|
74
76
|
params.systemPrompt ??
|
|
75
77
|
(params.conversation?.hasSystemPromptOverride
|
|
@@ -28,6 +28,8 @@ import {
|
|
|
28
28
|
import { isHttpAuthDisabled } from "../config/env.js";
|
|
29
29
|
import { getIsPlatform } from "../config/env-registry.js";
|
|
30
30
|
import { getConfig } from "../config/loader.js";
|
|
31
|
+
import { createApprovalCopyGenerator } from "../daemon/approval-generators.js";
|
|
32
|
+
import { createGuardianActionCopyGenerator } from "../daemon/guardian-action-generators.js";
|
|
31
33
|
import { processMessage } from "../daemon/process-message.js";
|
|
32
34
|
import { createLiveVoiceSession } from "../live-voice/live-voice-session.js";
|
|
33
35
|
import { LiveVoiceSessionManager } from "../live-voice/live-voice-session-manager.js";
|
|
@@ -96,10 +98,8 @@ import { matchSkillRoute } from "./skill-route-registry.js";
|
|
|
96
98
|
export { isPrivateAddress } from "./middleware/auth.js";
|
|
97
99
|
|
|
98
100
|
import type {
|
|
99
|
-
ApprovalConversationGenerator,
|
|
100
101
|
ApprovalCopyGenerator,
|
|
101
102
|
GuardianActionCopyGenerator,
|
|
102
|
-
GuardianFollowUpConversationGenerator,
|
|
103
103
|
RuntimeHttpServerOptions,
|
|
104
104
|
} from "./http-types.js";
|
|
105
105
|
|
|
@@ -161,10 +161,8 @@ export class RuntimeHttpServer {
|
|
|
161
161
|
private port: number;
|
|
162
162
|
private hostname: string;
|
|
163
163
|
|
|
164
|
-
private approvalCopyGenerator
|
|
165
|
-
private
|
|
166
|
-
private guardianActionCopyGenerator?: GuardianActionCopyGenerator;
|
|
167
|
-
private guardianFollowUpConversationGenerator?: GuardianFollowUpConversationGenerator;
|
|
164
|
+
private readonly approvalCopyGenerator: ApprovalCopyGenerator;
|
|
165
|
+
private readonly guardianActionCopyGenerator: GuardianActionCopyGenerator;
|
|
168
166
|
private retrySweepTimer: ReturnType<typeof setInterval> | null = null;
|
|
169
167
|
private sweepInProgress = false;
|
|
170
168
|
|
|
@@ -175,11 +173,8 @@ export class RuntimeHttpServer {
|
|
|
175
173
|
this.port = options.port ?? DEFAULT_PORT;
|
|
176
174
|
this.hostname = options.hostname ?? DEFAULT_HOSTNAME;
|
|
177
175
|
|
|
178
|
-
this.approvalCopyGenerator =
|
|
179
|
-
this.
|
|
180
|
-
this.guardianActionCopyGenerator = options.guardianActionCopyGenerator;
|
|
181
|
-
this.guardianFollowUpConversationGenerator =
|
|
182
|
-
options.guardianFollowUpConversationGenerator;
|
|
176
|
+
this.approvalCopyGenerator = createApprovalCopyGenerator();
|
|
177
|
+
this.guardianActionCopyGenerator = createGuardianActionCopyGenerator();
|
|
183
178
|
this.liveVoiceSessionManager = new LiveVoiceSessionManager({
|
|
184
179
|
createSession: (context) => createLiveVoiceSession(context),
|
|
185
180
|
});
|
|
@@ -560,11 +555,7 @@ export class RuntimeHttpServer {
|
|
|
560
555
|
const endpoint = url.pathname.slice("/v1/".length).replace(/\/$/, "");
|
|
561
556
|
meta = this.router.findLoggingMetadata(req.method, endpoint) ?? undefined;
|
|
562
557
|
}
|
|
563
|
-
return withRequestLogging(
|
|
564
|
-
req,
|
|
565
|
-
() => this.routeRequest(req, server),
|
|
566
|
-
meta,
|
|
567
|
-
);
|
|
558
|
+
return withRequestLogging(req, () => this.routeRequest(req, server), meta);
|
|
568
559
|
}
|
|
569
560
|
|
|
570
561
|
private async routeRequest(
|
|
@@ -14,10 +14,6 @@ import type {
|
|
|
14
14
|
export type { SlackInboundMessageMetadata };
|
|
15
15
|
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
16
16
|
import type { AssistantEventHub } from "./assistant-event-hub.js";
|
|
17
|
-
import type {
|
|
18
|
-
ApprovalCopyGenerator,
|
|
19
|
-
GuardianActionCopyGenerator,
|
|
20
|
-
} from "./message-composer-types.js";
|
|
21
17
|
|
|
22
18
|
export type {
|
|
23
19
|
ApprovalCopyGenerator,
|
|
@@ -61,41 +57,6 @@ export type ApprovalConversationGenerator = (
|
|
|
61
57
|
context: ApprovalConversationContext,
|
|
62
58
|
) => Promise<ApprovalConversationResult>;
|
|
63
59
|
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
|
-
// Guardian follow-up conversation flow types
|
|
66
|
-
// ---------------------------------------------------------------------------
|
|
67
|
-
|
|
68
|
-
/** The disposition returned by the guardian follow-up conversation engine. */
|
|
69
|
-
export type GuardianFollowUpDisposition =
|
|
70
|
-
| "call_back"
|
|
71
|
-
| "decline"
|
|
72
|
-
| "keep_pending";
|
|
73
|
-
|
|
74
|
-
/** Structured result from a single turn of the guardian follow-up conversation. */
|
|
75
|
-
export interface GuardianFollowUpTurnResult {
|
|
76
|
-
disposition: GuardianFollowUpDisposition;
|
|
77
|
-
replyText: string;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/** Input context for the guardian follow-up conversation engine. */
|
|
81
|
-
export interface GuardianFollowUpConversationContext {
|
|
82
|
-
/** The original question that was asked during the voice call. */
|
|
83
|
-
questionText: string;
|
|
84
|
-
/** The guardian's late answer text that initiated the follow-up. */
|
|
85
|
-
lateAnswerText: string;
|
|
86
|
-
/** The guardian's latest reply in the follow-up conversation. */
|
|
87
|
-
guardianReply: string;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Daemon-injected function that processes one turn of a guardian follow-up
|
|
92
|
-
* conversation. Classifies the guardian's intent into a structured disposition
|
|
93
|
-
* and produces a natural reply.
|
|
94
|
-
*/
|
|
95
|
-
export type GuardianFollowUpConversationGenerator = (
|
|
96
|
-
context: GuardianFollowUpConversationContext,
|
|
97
|
-
) => Promise<GuardianFollowUpTurnResult>;
|
|
98
|
-
|
|
99
60
|
export interface RuntimeMessageConversationOptions {
|
|
100
61
|
transport?: {
|
|
101
62
|
channelId: ChannelId;
|
|
@@ -115,6 +76,11 @@ export interface RuntimeMessageConversationOptions {
|
|
|
115
76
|
commandIntent?: { type: string; payload?: string; languageCode?: string };
|
|
116
77
|
/** Slack-only non-persisted notice injected into the active model turn. */
|
|
117
78
|
slackRuntimeContextNotice?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Persisted user-facing content. When present, storage/UI use this value
|
|
81
|
+
* while the model-facing turn continues to use `content`.
|
|
82
|
+
*/
|
|
83
|
+
displayContent?: string;
|
|
118
84
|
/** Optional callback to receive real-time agent loop events (text deltas, tool starts, etc.). */
|
|
119
85
|
onEvent?: (msg: ServerMessage) => void;
|
|
120
86
|
/**
|
|
@@ -168,14 +134,6 @@ export interface RuntimeHttpServerOptions {
|
|
|
168
134
|
port?: number;
|
|
169
135
|
/** Hostname / IP to bind to. Defaults to '127.0.0.1' (loopback-only). */
|
|
170
136
|
hostname?: string;
|
|
171
|
-
/** Daemon-injected generator for approval copy (provider-backed). */
|
|
172
|
-
approvalCopyGenerator?: ApprovalCopyGenerator;
|
|
173
|
-
/** Daemon-injected generator for conversational approval flow (provider-backed). */
|
|
174
|
-
approvalConversationGenerator?: ApprovalConversationGenerator;
|
|
175
|
-
/** Daemon-injected generator for guardian action copy (provider-backed). */
|
|
176
|
-
guardianActionCopyGenerator?: GuardianActionCopyGenerator;
|
|
177
|
-
/** Daemon-injected generator for guardian follow-up conversation (provider-backed). */
|
|
178
|
-
guardianFollowUpConversationGenerator?: GuardianFollowUpConversationGenerator;
|
|
179
137
|
}
|
|
180
138
|
|
|
181
139
|
export interface RuntimeAttachmentMetadata {
|
|
@@ -227,5 +185,19 @@ export interface RuntimeMessagePayload {
|
|
|
227
185
|
status: string;
|
|
228
186
|
error?: string;
|
|
229
187
|
conversationId?: string;
|
|
188
|
+
objective?: string;
|
|
189
|
+
};
|
|
190
|
+
slackMessage?: {
|
|
191
|
+
channelId: string;
|
|
192
|
+
channelTs: string;
|
|
193
|
+
threadTs?: string;
|
|
194
|
+
messageLink?: {
|
|
195
|
+
appUrl?: string;
|
|
196
|
+
webUrl?: string;
|
|
197
|
+
};
|
|
198
|
+
threadLink?: {
|
|
199
|
+
appUrl?: string;
|
|
200
|
+
webUrl?: string;
|
|
201
|
+
};
|
|
230
202
|
};
|
|
231
203
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* combination logic.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { hasManagedProxyPrereqs } from "../../providers/
|
|
17
|
+
import { hasManagedProxyPrereqs } from "../../providers/platform-proxy/context.js";
|
|
18
18
|
import { getDaemonRuntimeMode } from "../runtime-mode.js";
|
|
19
19
|
|
|
20
20
|
export type VBundleOriginMode =
|
|
@@ -241,6 +241,23 @@ describe("bookmark routes", () => {
|
|
|
241
241
|
).toBe("msg-6");
|
|
242
242
|
});
|
|
243
243
|
|
|
244
|
+
test("duplicate POSTs only broadcast one bookmark.created event", async () => {
|
|
245
|
+
seedConversationAndMessage({
|
|
246
|
+
conversationId: "conv-dup",
|
|
247
|
+
messageId: "msg-dup",
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
await call(createHandler, {
|
|
251
|
+
body: { messageId: "msg-dup", conversationId: "conv-dup" },
|
|
252
|
+
});
|
|
253
|
+
await call(createHandler, {
|
|
254
|
+
body: { messageId: "msg-dup", conversationId: "conv-dup" },
|
|
255
|
+
});
|
|
256
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
257
|
+
|
|
258
|
+
expect(publishedTypes()).toEqual(["bookmark.created"]);
|
|
259
|
+
});
|
|
260
|
+
|
|
244
261
|
test("DELETE on a non-existent messageId does not publish", async () => {
|
|
245
262
|
await call(deleteByMessageHandler, {
|
|
246
263
|
pathParams: { messageId: "does-not-exist" },
|