@vellumai/assistant 0.8.1 → 0.8.2
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 +2 -7
- package/Dockerfile +75 -1
- package/bun.lock +11 -1
- package/docker-entrypoint.sh +5 -0
- package/docker-init-apt-root.sh +94 -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 +325 -3
- 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-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 +41 -0
- 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 +1 -0
- 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 +2 -0
- 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-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 +76 -9
- 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__/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 +60 -36
- package/src/__tests__/filing-service.test.ts +140 -0
- package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
- 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 +266 -10
- 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-chain.test.ts +10 -8
- package/src/__tests__/install-skill-routing.test.ts +155 -37
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +92 -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-catalog-parity.test.ts +55 -13
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +34 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
- package/src/__tests__/llm-usage-store.test.ts +114 -0
- package/src/__tests__/managed-profile-guard.test.ts +31 -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__/oauth-commands-routes.test.ts +168 -16
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
- package/src/__tests__/openai-provider.test.ts +24 -0
- package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
- 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} +1 -1
- 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 +142 -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} +8 -8
- 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__/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 +737 -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-remove-legacy-skills-index.test.ts +309 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
- package/src/acp/resolve-agent.ts +1 -1
- package/src/agent/image-optimize.ts +13 -5
- package/src/calls/voice-session-bridge.ts +61 -42
- package/src/channels/types.ts +108 -0
- package/src/cli/__tests__/unknown-command.test.ts +24 -0
- package/src/cli/commands/__tests__/changelog.test.ts +304 -319
- package/src/cli/commands/__tests__/schedules.test.ts +491 -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 +329 -317
- package/src/cli/commands/plugins.ts +185 -0
- package/src/cli/commands/schedules.ts +391 -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__/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 +304 -0
- package/src/cli/lib/list-installed-plugins.ts +137 -0
- package/src/cli/lib/uninstall-plugin.ts +82 -0
- package/src/cli/lib/unknown-command.ts +111 -0
- package/src/cli/program.ts +38 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
- 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/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/feature-flag-registry.json +41 -1
- package/src/config/loader.ts +64 -38
- package/src/config/schema.ts +7 -10
- package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
- package/src/config/schemas/channels.ts +8 -0
- package/src/config/schemas/compaction.ts +28 -0
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm-request-logs.ts +31 -7
- package/src/config/schemas/llm.ts +3 -0
- package/src/config/schemas/memory-retrieval.ts +18 -0
- package/src/config/schemas/tools.ts +14 -0
- package/src/config/skills.ts +3 -96
- package/src/context/compactor.ts +1047 -0
- package/src/context/token-estimator.ts +2 -2
- 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 +34 -0
- 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.ts +169 -9
- 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 +16 -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 -1
- package/src/daemon/external-plugins-bootstrap.ts +217 -181
- package/src/daemon/first-greeting.ts +22 -2
- package/src/daemon/handlers/config-model.ts +6 -5
- package/src/daemon/handlers/config-slack-channel.ts +15 -3
- 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 +98 -23
- package/src/daemon/lifecycle.ts +45 -35
- package/src/daemon/meet-host-supervisor.ts +5 -4
- package/src/daemon/memory-v2-startup.ts +49 -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/subagents.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pkb-reminder-builder.test.ts +1 -1
- package/src/daemon/pkb-reminder-builder.ts +1 -1
- package/src/daemon/plugin-source-watcher.ts +146 -0
- package/src/daemon/process-message.ts +21 -3
- package/src/daemon/server.ts +11 -2
- package/src/daemon/skill-memory-refresh.ts +29 -0
- package/src/documents/document-store.ts +221 -3
- package/src/embedded/plugin-api.ts +40 -0
- package/src/filing/filing-service.ts +39 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +91 -6
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +41 -0
- package/src/home/__tests__/feed-types.test.ts +40 -0
- package/src/home/feed-types.ts +22 -0
- package/src/home/post-connect-feed.ts +1 -0
- package/src/index.ts +18 -1
- 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 +263 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
- 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 +110 -10
- package/src/memory/db-init.ts +6 -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 +66 -9
- package/src/memory/graph/conversation-graph-memory.ts +31 -15
- package/src/memory/graph/tools.ts +3 -3
- package/src/memory/indexer.ts +34 -29
- 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 +17 -10
- package/src/memory/llm-request-log-source.ts +19 -52
- package/src/memory/llm-usage-store.ts +125 -5
- 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/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/onboarding-events-store.ts +106 -0
- package/src/memory/schema/bookmarks.ts +0 -2
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/inference.ts +1 -3
- package/src/memory/schema/infrastructure.ts +12 -0
- package/src/memory/turn-events-store.ts +127 -2
- package/src/memory/v2/__tests__/activation.test.ts +0 -8
- package/src/memory/v2/__tests__/injection.test.ts +98 -8
- 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/injection.ts +32 -6
- package/src/memory/v2/migration.ts +49 -19
- package/src/memory/v2/page-index.ts +35 -5
- 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/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/conversation-pairing.ts +2 -1
- package/src/notifications/decision-engine.ts +2 -1
- package/src/notifications/emit-signal.ts +20 -1
- package/src/notifications/home-feed-side-effect.ts +54 -0
- package/src/notifications/signal.ts +3 -1
- package/src/oauth/connection-resolver.ts +8 -4
- package/src/oauth/platform-connection.ts +6 -2
- 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 +36 -3
- 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 +105 -32
- 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 +31 -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 +12 -0
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
- package/src/prompts/normalize-onboarding.ts +27 -0
- package/src/prompts/sections.ts +302 -0
- package/src/prompts/system-prompt.ts +63 -166
- package/src/prompts/templates/BOOTSTRAP.md +17 -1
- package/src/prompts/templates/system-sections.ts +173 -0
- package/src/providers/__tests__/inference.test.ts +22 -7
- package/src/providers/anthropic/client.ts +28 -28
- package/src/providers/connection-resolution.ts +7 -0
- package/src/providers/inference/adapter-factory.ts +41 -4
- package/src/providers/inference/connections.ts +74 -29
- package/src/providers/inference/resolve-auth.ts +12 -4
- package/src/providers/model-catalog.ts +294 -12
- package/src/providers/openai/chat-completions-provider.ts +10 -2
- package/src/providers/openrouter/client.ts +7 -0
- package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
- 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 +36 -0
- package/src/providers/registry.ts +22 -14
- package/src/providers/retry.ts +47 -1
- package/src/runtime/__tests__/agent-wake.test.ts +152 -0
- package/src/runtime/agent-wake.ts +42 -14
- package/src/runtime/auth/route-policy.ts +8 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/http-types.ts +19 -0
- 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__/conversation-management-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +107 -20
- 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 +121 -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 +40 -35
- package/src/runtime/routes/conversation-routes.ts +90 -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 +6 -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 +65 -21
- 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/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 +57 -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 +15 -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/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 +72 -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/registry.ts +8 -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/context/__tests__/compact-prompt.test.ts +0 -63
- package/src/context/prompts/compact.md +0 -26
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
- /package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +0 -0
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
|
});
|
|
@@ -330,7 +330,7 @@ function classifyWakeDiskPressurePolicy(opts: WakeOptions): {
|
|
|
330
330
|
const status = getDiskPressureStatus();
|
|
331
331
|
const decision = classifyDiskPressureTurnPolicy(status, {
|
|
332
332
|
conversationSource: opts.source,
|
|
333
|
-
callSite: "mainAgent",
|
|
333
|
+
callSite: opts.callSite ?? "mainAgent",
|
|
334
334
|
isDirectWake: true,
|
|
335
335
|
sourceChannel: opts.sourceChannel ?? opts.trustContext?.sourceChannel,
|
|
336
336
|
sourceInterface: opts.sourceInterface,
|
|
@@ -537,6 +537,33 @@ export async function wakeAgentForOpportunity(
|
|
|
537
537
|
// only after `agentLoop.run()` returns.
|
|
538
538
|
let mode: "buffering" | "live" = "buffering";
|
|
539
539
|
const buffered: AgentEvent[] = [];
|
|
540
|
+
// LLM request logs accumulated while buffering. Persisted only if the
|
|
541
|
+
// wake transitions to live (i.e. produced output). A silent no-op wake
|
|
542
|
+
// drops them — otherwise the next user-turn's `backfillMessageIdOnLogs`
|
|
543
|
+
// sweep would misattach these NULL-messageId rows to an unrelated
|
|
544
|
+
// future assistant message, contaminating inspector context.
|
|
545
|
+
type PendingLog = {
|
|
546
|
+
rawRequest: unknown;
|
|
547
|
+
rawResponse: unknown;
|
|
548
|
+
provider?: string;
|
|
549
|
+
};
|
|
550
|
+
const pendingLogs: PendingLog[] = [];
|
|
551
|
+
const persistLog = (record: PendingLog): void => {
|
|
552
|
+
try {
|
|
553
|
+
recordRequestLog(
|
|
554
|
+
conversationId,
|
|
555
|
+
JSON.stringify(record.rawRequest),
|
|
556
|
+
JSON.stringify(record.rawResponse),
|
|
557
|
+
undefined,
|
|
558
|
+
record.provider,
|
|
559
|
+
);
|
|
560
|
+
} catch (err) {
|
|
561
|
+
log.warn(
|
|
562
|
+
{ err, conversationId, source },
|
|
563
|
+
"agent-wake: failed to persist LLM request log (non-fatal)",
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
};
|
|
540
567
|
const safeEmit = (event: AgentEvent): void => {
|
|
541
568
|
try {
|
|
542
569
|
target.emitAgentEvent(event);
|
|
@@ -550,20 +577,17 @@ export async function wakeAgentForOpportunity(
|
|
|
550
577
|
const onEvent = (event: AgentEvent): void => {
|
|
551
578
|
// Replicates the recordRequestLog side-effect in `handleUsage` because
|
|
552
579
|
// wakes own their own onEvent and never reach `dispatchAgentEvent`.
|
|
580
|
+
// Defer persistence while buffering — see `pendingLogs` above.
|
|
553
581
|
if (event.type === "usage" && event.rawRequest && event.rawResponse) {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
log.warn(
|
|
564
|
-
{ err, conversationId, source },
|
|
565
|
-
"agent-wake: failed to persist LLM request log (non-fatal)",
|
|
566
|
-
);
|
|
582
|
+
const record = {
|
|
583
|
+
rawRequest: event.rawRequest,
|
|
584
|
+
rawResponse: event.rawResponse,
|
|
585
|
+
provider: event.actualProvider,
|
|
586
|
+
};
|
|
587
|
+
if (mode === "buffering") {
|
|
588
|
+
pendingLogs.push(record);
|
|
589
|
+
} else {
|
|
590
|
+
persistLog(record);
|
|
567
591
|
}
|
|
568
592
|
}
|
|
569
593
|
if (mode === "buffering") {
|
|
@@ -620,6 +644,10 @@ export async function wakeAgentForOpportunity(
|
|
|
620
644
|
safeEmit(event);
|
|
621
645
|
}
|
|
622
646
|
buffered.length = 0;
|
|
647
|
+
for (const record of pendingLogs) {
|
|
648
|
+
persistLog(record);
|
|
649
|
+
}
|
|
650
|
+
pendingLogs.length = 0;
|
|
623
651
|
mode = "live";
|
|
624
652
|
};
|
|
625
653
|
|
|
@@ -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"] },
|
|
@@ -285,7 +286,8 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
285
286
|
{ endpoint: "slack/channels", scopes: ["settings.read"] },
|
|
286
287
|
{ endpoint: "slack/share", scopes: ["settings.write"] },
|
|
287
288
|
|
|
288
|
-
// Channel readiness
|
|
289
|
+
// Channel availability + readiness
|
|
290
|
+
{ endpoint: "channels/available", scopes: ["settings.read"] },
|
|
289
291
|
{ endpoint: "channels/readiness", scopes: ["settings.read"] },
|
|
290
292
|
{ endpoint: "channels/readiness/refresh", scopes: ["settings.write"] },
|
|
291
293
|
|
|
@@ -342,6 +344,7 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
342
344
|
|
|
343
345
|
// Lifecycle telemetry
|
|
344
346
|
{ endpoint: "telemetry/lifecycle", scopes: ["settings.write"] },
|
|
347
|
+
{ endpoint: "telemetry/flush", scopes: ["settings.write"] },
|
|
345
348
|
|
|
346
349
|
// Debug / introspection
|
|
347
350
|
{ endpoint: "clients", scopes: ["settings.read"] },
|
|
@@ -1079,6 +1082,10 @@ registerPolicy("oauth/mode.set", {
|
|
|
1079
1082
|
requiredScopes: ["settings.write"],
|
|
1080
1083
|
allowedPrincipalTypes: ["local"],
|
|
1081
1084
|
});
|
|
1085
|
+
registerPolicy("oauth/connection-changed", {
|
|
1086
|
+
requiredScopes: ["settings.write"],
|
|
1087
|
+
allowedPrincipalTypes: ["local"],
|
|
1088
|
+
});
|
|
1082
1089
|
registerPolicy("oauth/status", {
|
|
1083
1090
|
requiredScopes: ["settings.read"],
|
|
1084
1091
|
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
|
|
@@ -115,6 +115,11 @@ export interface RuntimeMessageConversationOptions {
|
|
|
115
115
|
commandIntent?: { type: string; payload?: string; languageCode?: string };
|
|
116
116
|
/** Slack-only non-persisted notice injected into the active model turn. */
|
|
117
117
|
slackRuntimeContextNotice?: string;
|
|
118
|
+
/**
|
|
119
|
+
* Persisted user-facing content. When present, storage/UI use this value
|
|
120
|
+
* while the model-facing turn continues to use `content`.
|
|
121
|
+
*/
|
|
122
|
+
displayContent?: string;
|
|
118
123
|
/** Optional callback to receive real-time agent loop events (text deltas, tool starts, etc.). */
|
|
119
124
|
onEvent?: (msg: ServerMessage) => void;
|
|
120
125
|
/**
|
|
@@ -227,5 +232,19 @@ export interface RuntimeMessagePayload {
|
|
|
227
232
|
status: string;
|
|
228
233
|
error?: string;
|
|
229
234
|
conversationId?: string;
|
|
235
|
+
objective?: string;
|
|
236
|
+
};
|
|
237
|
+
slackMessage?: {
|
|
238
|
+
channelId: string;
|
|
239
|
+
channelTs: string;
|
|
240
|
+
threadTs?: string;
|
|
241
|
+
messageLink?: {
|
|
242
|
+
appUrl?: string;
|
|
243
|
+
webUrl?: string;
|
|
244
|
+
};
|
|
245
|
+
threadLink?: {
|
|
246
|
+
appUrl?: string;
|
|
247
|
+
webUrl?: string;
|
|
248
|
+
};
|
|
230
249
|
};
|
|
231
250
|
}
|
|
@@ -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" },
|
|
@@ -23,6 +23,7 @@ mock.module("../../assistant-event-hub.js", () => ({
|
|
|
23
23
|
publish: async () => {},
|
|
24
24
|
subscribe: () => () => {},
|
|
25
25
|
},
|
|
26
|
+
broadcastMessage: () => {},
|
|
26
27
|
}));
|
|
27
28
|
|
|
28
29
|
import { getDb } from "../../../memory/db-connection.js";
|
|
@@ -114,7 +115,10 @@ function seedConversation(id: string): void {
|
|
|
114
115
|
describe("PUT /v1/conversations/:id/inference-profile", () => {
|
|
115
116
|
beforeEach(() => {
|
|
116
117
|
clearConversations();
|
|
117
|
-
configLlmProfiles = {
|
|
118
|
+
configLlmProfiles = {
|
|
119
|
+
fast: { model: "model-a" },
|
|
120
|
+
slow: { model: "model-b" },
|
|
121
|
+
};
|
|
118
122
|
});
|
|
119
123
|
|
|
120
124
|
test("PUT with ttlSeconds=600 → response includes sessionId (UUID), expiresAt, ttlSeconds=600", async () => {
|