@vellumai/assistant 0.6.5 → 0.6.6
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/AGENTS.md +9 -1
- package/ARCHITECTURE.md +15 -17
- package/Dockerfile +6 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +283 -0
- package/docs/architecture/integrations.md +32 -39
- package/docs/architecture/memory.md +25 -30
- package/docs/architecture/security.md +7 -6
- package/docs/browser-use-architecture-phase2.md +63 -20
- package/docs/plugins.md +761 -0
- package/examples/plugins/echo/README.md +132 -0
- package/examples/plugins/echo/package.json +17 -0
- package/examples/plugins/echo/register.ts +187 -0
- package/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
- package/openapi.yaml +212 -68
- package/package.json +1 -1
- package/src/__tests__/app-compiler.test.ts +57 -0
- package/src/__tests__/approval-cascade.test.ts +7 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +1 -0
- package/src/__tests__/avatar-generator.test.ts +4 -2
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/catalog-cache.test.ts +69 -0
- package/src/__tests__/checker.test.ts +459 -171
- package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
- package/src/__tests__/compaction-events.test.ts +501 -0
- package/src/__tests__/compaction-pipeline.test.ts +210 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +181 -0
- package/src/__tests__/compaction-timeout-recovery.test.ts +262 -0
- package/src/__tests__/config-model-image-provider.test.ts +110 -0
- package/src/__tests__/config-schema.test.ts +22 -9
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
- package/src/__tests__/contacts-tools.test.ts +26 -0
- package/src/__tests__/context-overflow-policy.test.ts +7 -7
- package/src/__tests__/context-window-manager.test.ts +355 -4
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +26 -30
- package/src/__tests__/conversation-agent-loop.test.ts +30 -141
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -1
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +2 -16
- package/src/__tests__/conversation-pairing.test.ts +174 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +4 -1
- package/src/__tests__/conversation-process-callsite.test.ts +3 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +16 -7
- package/src/__tests__/conversation-queue.test.ts +29 -14
- package/src/__tests__/conversation-routes-disk-view.test.ts +7 -6
- package/src/__tests__/conversation-runtime-assembly.test.ts +155 -110
- package/src/__tests__/conversation-runtime-workspace.test.ts +23 -38
- package/src/__tests__/conversation-seed-composer.test.ts +2 -2
- package/src/__tests__/conversation-slash-queue.test.ts +7 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +25 -2
- package/src/__tests__/conversation-speed-override.test.ts +6 -1
- package/src/__tests__/conversation-title-service.test.ts +116 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +41 -2
- package/src/__tests__/conversation-usage.test.ts +1 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +4 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +3 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -1
- package/src/__tests__/credential-health-service.test.ts +78 -9
- package/src/__tests__/credential-security-invariants.test.ts +2 -2
- package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
- package/src/__tests__/empty-response-pipeline.test.ts +305 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +3 -3
- package/src/__tests__/first-greeting.test.ts +247 -5
- package/src/__tests__/headless-browser-mode.test.ts +57 -0
- package/src/__tests__/history-repair-pipeline.test.ts +399 -0
- package/src/__tests__/host-browser-e2e-cloud.test.ts +307 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +3 -3
- package/src/__tests__/host-proxy-interface.test.ts +36 -2
- package/src/__tests__/image-credentials.test.ts +137 -0
- package/src/__tests__/image-service-dispatcher.test.ts +186 -0
- package/src/__tests__/injector-chain.test.ts +526 -0
- package/src/__tests__/intent-routing.test.ts +0 -26
- package/src/__tests__/llm-call-pipeline.test.ts +285 -0
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/media-generate-image.test.ts +119 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +401 -0
- package/src/__tests__/memory-upsert-concurrency.test.ts +1 -0
- package/src/__tests__/migration-import-from-url.test.ts +5 -68
- package/src/__tests__/model-intents.test.ts +4 -2
- package/src/__tests__/notification-broadcaster.test.ts +3 -3
- package/src/__tests__/notification-decision-strategy.test.ts +0 -11
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +108 -0
- package/src/__tests__/oauth-apps-routes.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +14 -12
- package/src/__tests__/oauth-connect-orchestrator.test.ts +4 -13
- package/src/__tests__/oauth-provider-serializer.test.ts +6 -4
- package/src/__tests__/oauth-provider-visibility.test.ts +3 -5
- package/src/__tests__/oauth-providers-routes.test.ts +3 -2
- package/src/__tests__/oauth-store.test.ts +41 -76
- package/src/__tests__/onboarding-template-contract.test.ts +16 -64
- package/src/__tests__/openai-image-service.test.ts +368 -0
- package/src/__tests__/overflow-reduce-pipeline.test.ts +676 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +0 -24
- package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
- package/src/__tests__/persistence-pipeline.test.ts +377 -0
- package/src/__tests__/pipeline-runner.test.ts +565 -0
- package/src/__tests__/platform.test.ts +5 -2
- package/src/__tests__/plugin-bootstrap.test.ts +483 -0
- package/src/__tests__/plugin-registry.test.ts +273 -0
- package/src/__tests__/plugin-route-contribution.test.ts +288 -0
- package/src/__tests__/plugin-skill-contribution.test.ts +367 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +286 -0
- package/src/__tests__/plugin-types.test.ts +320 -0
- package/src/__tests__/pricing.test.ts +44 -12
- package/src/__tests__/proxy-approval-callback.test.ts +69 -8
- package/src/__tests__/reaction-persistence.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +0 -2
- package/src/__tests__/schedule-routes.test.ts +131 -1
- package/src/__tests__/scheduler-recurrence.test.ts +14 -70
- package/src/__tests__/scheduler-reuse-conversation.test.ts +10 -50
- package/src/__tests__/secret-detection-handler.test.ts +0 -10
- package/src/__tests__/shell-identity.test.ts +0 -134
- package/src/__tests__/suggestion-routes.test.ts +103 -4
- package/src/__tests__/task-memory-cleanup.test.ts +1 -0
- package/src/__tests__/task-scheduler.test.ts +3 -15
- package/src/__tests__/test-preload.ts +11 -0
- package/src/__tests__/title-generate-pipeline.test.ts +224 -0
- package/src/__tests__/token-estimate-pipeline.test.ts +431 -0
- package/src/__tests__/tool-error-pipeline.test.ts +244 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +431 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -6
- package/src/__tests__/tool-executor-shell-integration.test.ts +7 -10
- package/src/__tests__/tool-executor.test.ts +141 -0
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -110
- package/src/__tests__/user-plugin-loader.test.ts +191 -0
- package/src/__tests__/workspace-migration-046-seed-conversation-starters-callsite.test.ts +185 -0
- package/src/__tests__/workspace-migration-049-release-notes-default-sonnet.test.ts +100 -0
- package/src/__tests__/workspace-migration-050-seed-main-agent-opus-callsite.test.ts +171 -0
- package/src/__tests__/workspace-migration-051-seed-conversation-summarization-callsite.test.ts +252 -0
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +99 -0
- package/src/__tests__/workspace-policy.test.ts +21 -3
- package/src/agent/loop.ts +340 -102
- package/src/approvals/__tests__/guardian-feed-event.test.ts +304 -0
- package/src/approvals/guardian-request-resolvers.ts +80 -0
- package/src/backup/__tests__/backup-worker.test.ts +2 -13
- package/src/backup/backup-worker.ts +3 -15
- package/src/bundler/app-compiler.ts +84 -1
- package/src/calls/call-state.ts +2 -2
- package/src/channels/__tests__/types.test.ts +3 -3
- package/src/channels/types.ts +6 -4
- package/src/cli/__tests__/notifications.test.ts +87 -211
- package/src/cli/commands/__tests__/backup.test.ts +1 -1
- package/src/cli/commands/__tests__/image-generation.test.ts +255 -35
- package/src/cli/commands/__tests__/inference-send.test.ts +12 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +12 -0
- package/src/cli/commands/backup.ts +2 -2
- package/src/cli/commands/clients.ts +138 -0
- package/src/cli/commands/completions.ts +2 -9
- package/src/cli/commands/conversations.ts +55 -7
- package/src/cli/commands/image-generation.ts +33 -34
- package/src/cli/commands/notifications.ts +68 -103
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
- package/src/cli/commands/oauth/connect.ts +2 -2
- package/src/cli/commands/oauth/providers.ts +176 -8
- package/src/cli/commands/oauth/status.ts +46 -36
- package/src/cli/commands/skills.ts +3 -4
- package/src/cli/program.ts +25 -29
- package/src/config/__tests__/backup-schema.test.ts +7 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +10 -10
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +66 -87
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +28 -51
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +22 -40
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -1
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +23 -39
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +207 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +12 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +58 -0
- package/src/config/bundled-skills/schedule/SKILL.md +8 -3
- package/src/config/bundled-skills/schedule/TOOLS.json +15 -7
- package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +59 -0
- package/src/config/bundled-tool-registry.ts +0 -15
- package/src/config/feature-flag-registry.json +17 -1
- package/src/config/schema.ts +19 -0
- package/src/config/schemas/backup.ts +1 -1
- package/src/config/schemas/conversations.ts +16 -0
- package/src/config/schemas/llm.ts +2 -3
- package/src/config/schemas/security.ts +6 -6
- package/src/config/schemas/tts.ts +11 -0
- package/src/config/skill-state.ts +6 -2
- package/src/config/skills.ts +94 -5
- package/src/context/__tests__/compact-prompt.test.ts +27 -9
- package/src/context/prompts/compact.md +26 -12
- package/src/context/tool-result-truncation.ts +3 -63
- package/src/context/window-manager.ts +190 -16
- package/src/credential-health/credential-health-service.ts +19 -6
- package/src/daemon/__tests__/conversation-feed-event.test.ts +317 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +4 -12
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +14 -15
- package/src/daemon/config-watcher.ts +0 -2
- package/src/daemon/context-overflow-policy.ts +4 -13
- package/src/daemon/conversation-agent-loop-handlers.ts +83 -22
- package/src/daemon/conversation-agent-loop.ts +984 -683
- package/src/daemon/conversation-history.ts +10 -19
- package/src/daemon/conversation-lifecycle.ts +37 -19
- package/src/daemon/conversation-notifiers.ts +2 -110
- package/src/daemon/conversation-process.ts +14 -7
- package/src/daemon/conversation-runtime-assembly.ts +532 -411
- package/src/daemon/conversation-tool-setup.ts +41 -4
- package/src/daemon/conversation.ts +80 -35
- package/src/daemon/external-plugins-bootstrap.ts +478 -0
- package/src/daemon/first-greeting.ts +191 -14
- package/src/daemon/handlers/config-model.ts +11 -0
- package/src/daemon/handlers/skills.ts +5 -1
- package/src/daemon/lifecycle.ts +33 -68
- package/src/daemon/message-types/computer-use.ts +2 -34
- package/src/daemon/message-types/conversations.ts +49 -0
- package/src/daemon/message-types/messages.ts +12 -0
- package/src/daemon/server.ts +5 -3
- package/src/daemon/shutdown-handlers.ts +2 -12
- package/src/daemon/tool-side-effects.ts +14 -56
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +160 -0
- package/src/heartbeat/heartbeat-service.ts +24 -1
- package/src/home/__tests__/feed-population-integration.test.ts +312 -0
- package/src/home/emit-feed-event.ts +7 -0
- package/src/home/feed-types.ts +41 -2
- package/src/home/rewrite-command-preview.ts +66 -0
- package/src/ipc/__tests__/socket-path.test.ts +11 -50
- package/src/ipc/cli-client.ts +1 -1
- package/src/ipc/cli-server.ts +3 -3
- package/src/ipc/gateway-client.ts +4 -1
- package/src/ipc/routes/browser-context.ts +2 -0
- package/src/ipc/routes/browser.ts +1 -0
- package/src/ipc/routes/get-contact.ts +16 -0
- package/src/ipc/routes/index.ts +14 -0
- package/src/ipc/routes/list-clients.ts +31 -0
- package/src/ipc/routes/merge-contacts.ts +17 -0
- package/src/ipc/routes/notification.ts +133 -0
- package/src/ipc/routes/rename-conversation.ts +59 -0
- package/src/ipc/routes/search-contacts.ts +19 -0
- package/src/ipc/routes/upsert-contact.ts +25 -0
- package/src/ipc/socket-path.ts +14 -38
- package/src/media/app-icon-generator.ts +23 -46
- package/src/media/avatar-router.ts +26 -41
- package/src/media/gemini-image-service.ts +8 -41
- package/src/media/image-credentials.ts +73 -0
- package/src/media/image-service.ts +85 -0
- package/src/media/openai-image-service.ts +131 -0
- package/src/media/types.ts +46 -0
- package/src/memory/conversation-crud.ts +48 -18
- package/src/memory/conversation-queries.ts +57 -4
- package/src/memory/conversation-title-service.ts +25 -0
- package/src/memory/db-init.ts +8 -0
- package/src/memory/embedding-gemini.test.ts +41 -2
- package/src/memory/embedding-gemini.ts +6 -1
- package/src/memory/graph/bootstrap.test.ts +282 -0
- package/src/memory/graph/bootstrap.ts +8 -5
- package/src/memory/graph/extraction.ts +10 -2
- package/src/memory/graph/graph-search.test.ts +1 -0
- package/src/memory/graph/inspect.ts +2 -2
- package/src/memory/graph/retriever.ts +10 -3
- package/src/memory/migrations/041-approval-prompt-ts-tracker.ts +26 -0
- package/src/memory/migrations/149-oauth-tables.ts +1 -0
- package/src/memory/migrations/223-schedule-script-column.ts +11 -0
- package/src/memory/migrations/224-oauth-providers-managed-service-is-paid.ts +24 -0
- package/src/memory/migrations/225-oauth-providers-available-scopes.ts +13 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/pkb/pkb-index.test.ts +1 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +1 -0
- package/src/memory/pkb/pkb-search.test.ts +65 -4
- package/src/memory/pkb/pkb-search.ts +40 -18
- package/src/memory/qdrant-client.test.ts +60 -0
- package/src/memory/qdrant-client.ts +25 -0
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/schema/oauth.ts +4 -1
- package/src/messaging/providers/slack/render-transcript.test.ts +77 -29
- package/src/messaging/providers/slack/render-transcript.ts +58 -0
- package/src/notifications/conversation-pairing.ts +78 -19
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/signal.ts +1 -2
- package/src/oauth/AGENTS.md +1 -1
- package/src/oauth/__tests__/identity-verifier.test.ts +2 -1
- package/src/oauth/connect-orchestrator.ts +8 -34
- package/src/oauth/connect-types.ts +6 -10
- package/src/oauth/manual-token-connection.ts +23 -0
- package/src/oauth/oauth-store.ts +30 -14
- package/src/oauth/provider-serializer.ts +6 -1
- package/src/oauth/seed-providers.ts +56 -108
- package/src/outbound-proxy/http-forwarder.ts +9 -0
- package/src/permissions/approval-policy.test.ts +293 -18
- package/src/permissions/approval-policy.ts +110 -58
- package/src/permissions/arg-parser.test.ts +161 -0
- package/src/permissions/arg-parser.ts +141 -0
- package/src/permissions/bash-risk-classifier.test.ts +414 -2
- package/src/permissions/bash-risk-classifier.ts +303 -60
- package/src/permissions/checker.ts +157 -29
- package/src/permissions/command-registry.test.ts +239 -0
- package/src/permissions/command-registry.ts +234 -54
- package/src/permissions/defaults.ts +5 -4
- package/src/permissions/gateway-threshold-reader.ts +196 -0
- package/src/permissions/prompter.ts +4 -0
- package/src/permissions/risk-types.ts +61 -4
- package/src/permissions/schedule-risk-classifier.test.ts +129 -0
- package/src/permissions/schedule-risk-classifier.ts +85 -0
- package/src/permissions/shell-identity.ts +2 -42
- package/src/permissions/types.ts +2 -0
- package/src/permissions/workspace-policy.ts +8 -3
- package/src/plugins/defaults/circuit-breaker.ts +146 -0
- package/src/plugins/defaults/compaction.ts +145 -0
- package/src/plugins/defaults/empty-response.ts +126 -0
- package/src/plugins/defaults/history-repair.ts +85 -0
- package/src/plugins/defaults/index.ts +116 -0
- package/src/plugins/defaults/injectors.ts +491 -0
- package/src/plugins/defaults/llm-call.ts +82 -0
- package/src/plugins/defaults/memory-retrieval.ts +226 -0
- package/src/plugins/defaults/overflow-reduce.ts +181 -0
- package/src/plugins/defaults/persistence.ts +129 -0
- package/src/plugins/defaults/title-generate.ts +95 -0
- package/src/plugins/defaults/token-estimate.ts +104 -0
- package/src/plugins/defaults/tool-error.ts +126 -0
- package/src/plugins/defaults/tool-execute.ts +89 -0
- package/src/plugins/defaults/tool-result-truncate.ts +88 -0
- package/src/plugins/pipeline.ts +316 -0
- package/src/plugins/plugin-skill-contributions.ts +292 -0
- package/src/plugins/registry.ts +241 -0
- package/src/plugins/types.ts +1134 -0
- package/src/plugins/user-loader.ts +177 -0
- package/src/prompts/templates/BOOTSTRAP.md +27 -77
- package/src/providers/model-catalog.ts +52 -29
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openrouter/client.ts +5 -1
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +61 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +57 -0
- package/src/providers/speech-to-text/xai-realtime.test.ts +72 -4
- package/src/providers/speech-to-text/xai-realtime.ts +39 -14
- package/src/runtime/AGENTS.md +25 -16
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +3 -3
- package/src/runtime/__tests__/client-registry.test.ts +293 -0
- package/src/runtime/client-registry.ts +261 -0
- package/src/runtime/http-server.ts +77 -8
- package/src/runtime/http-types.ts +0 -2
- package/src/runtime/migrations/vbundle-builder.ts +1 -22
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +51 -31
- package/src/runtime/routes/approval-routes.ts +17 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +27 -8
- package/src/runtime/routes/conversation-routes.ts +223 -116
- package/src/runtime/routes/inbound-message-handler.ts +88 -13
- package/src/runtime/routes/memory-item-routes.test.ts +1 -0
- package/src/runtime/routes/migration-routes.ts +0 -3
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +284 -0
- package/src/runtime/routes/playground/__tests__/guard.test.ts +80 -0
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +294 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +271 -0
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +202 -0
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +309 -0
- package/src/runtime/routes/playground/__tests__/state.test.ts +224 -0
- package/src/runtime/routes/playground/conversation-not-found.ts +29 -0
- package/src/runtime/routes/playground/deps.ts +56 -0
- package/src/runtime/routes/playground/force-compact.ts +73 -0
- package/src/runtime/routes/playground/guard.ts +37 -0
- package/src/runtime/routes/playground/index.ts +28 -0
- package/src/runtime/routes/playground/inject-failures.ts +159 -0
- package/src/runtime/routes/playground/reset-circuit.ts +115 -0
- package/src/runtime/routes/playground/seed-conversation.ts +139 -0
- package/src/runtime/routes/playground/seeded-conversations.ts +78 -0
- package/src/runtime/routes/playground/state.ts +78 -0
- package/src/runtime/routes/schedule-routes.ts +89 -8
- package/src/runtime/skill-route-registry.ts +75 -15
- package/src/schedule/run-script.ts +68 -0
- package/src/schedule/schedule-store.ts +7 -1
- package/src/schedule/scheduler.ts +48 -8
- package/src/skills/catalog-cache.ts +12 -5
- package/src/tools/browser/__tests__/browser-status.test.ts +189 -0
- package/src/tools/browser/browser-execution.ts +88 -19
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +230 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +146 -3
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +54 -3
- package/src/tools/browser/cdp-client/factory.ts +15 -4
- package/src/tools/executor.ts +126 -74
- package/src/tools/network/script-proxy/session-manager.ts +37 -1
- package/src/tools/permission-checker.ts +98 -49
- package/src/tools/policy-context.ts +4 -0
- package/src/tools/registry.ts +140 -3
- package/src/tools/schedule/create.ts +23 -8
- package/src/tools/schedule/update.ts +3 -1
- package/src/tools/secret-detection-handler.ts +0 -51
- package/src/tools/system/avatar-generator.ts +6 -2
- package/src/tools/types.ts +28 -2
- package/src/util/platform.ts +7 -2
- package/src/util/pricing.ts +26 -3
- package/src/workspace/migrations/006-services-config.ts +2 -4
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +2 -3
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +3 -4
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +108 -0
- package/src/workspace/migrations/047-remove-watch-callsites.ts +54 -0
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +81 -0
- package/src/workspace/migrations/049-release-notes-default-sonnet.ts +80 -0
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +86 -0
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +128 -0
- package/src/workspace/migrations/registry.ts +12 -0
- package/tsconfig.json +1 -1
- package/hook-templates/debug-prompt-logger/hook.json +0 -7
- package/hook-templates/debug-prompt-logger/run.sh +0 -66
- package/src/__tests__/compaction-circuit-breaker.test.ts +0 -336
- package/src/__tests__/context-overflow-approval.test.ts +0 -156
- package/src/__tests__/hooks-blocking.test.ts +0 -178
- package/src/__tests__/hooks-cli.test.ts +0 -182
- package/src/__tests__/hooks-config.test.ts +0 -108
- package/src/__tests__/hooks-discovery.test.ts +0 -211
- package/src/__tests__/hooks-integration.test.ts +0 -196
- package/src/__tests__/hooks-manager.test.ts +0 -226
- package/src/__tests__/hooks-runner.test.ts +0 -175
- package/src/__tests__/hooks-settings.test.ts +0 -160
- package/src/__tests__/hooks-templates.test.ts +0 -169
- package/src/__tests__/hooks-ts-runner.test.ts +0 -170
- package/src/__tests__/hooks-watch.test.ts +0 -112
- package/src/__tests__/notification-schedule-dedup.test.ts +0 -213
- package/src/__tests__/oauth-scope-policy.test.ts +0 -180
- package/src/__tests__/send-notification-tool.test.ts +0 -83
- package/src/cli/commands/shotgun.ts +0 -266
- package/src/config/bundled-skills/conversations/SKILL.md +0 -20
- package/src/config/bundled-skills/conversations/TOOLS.json +0 -23
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +0 -88
- package/src/config/bundled-skills/heartbeat/SKILL.md +0 -43
- package/src/config/bundled-skills/notifications/SKILL.md +0 -40
- package/src/config/bundled-skills/notifications/TOOLS.json +0 -80
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -152
- package/src/config/bundled-skills/notifications/tools/shared.ts +0 -13
- package/src/config/bundled-skills/screen-watch/SKILL.md +0 -27
- package/src/config/bundled-skills/screen-watch/TOOLS.json +0 -35
- package/src/config/bundled-skills/screen-watch/tools/start-screen-watch.ts +0 -12
- package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -84
- package/src/daemon/context-overflow-approval.ts +0 -52
- package/src/daemon/watch-handler.ts +0 -399
- package/src/hooks/cli.ts +0 -253
- package/src/hooks/config.ts +0 -100
- package/src/hooks/discovery.ts +0 -135
- package/src/hooks/manager.ts +0 -179
- package/src/hooks/runner.ts +0 -117
- package/src/hooks/templates.ts +0 -77
- package/src/hooks/types.ts +0 -75
- package/src/oauth/scope-policy.ts +0 -89
- package/src/runtime/gateway-internal-client.ts +0 -94
- package/src/runtime/routes/watch-routes.ts +0 -156
- package/src/signals/shotgun.ts +0 -203
- package/src/tools/watch/screen-watch.ts +0 -144
- package/src/tools/watch/watch-state.ts +0 -142
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
setServiceField,
|
|
9
9
|
} from "../../config/raw-config-utils.js";
|
|
10
10
|
import { VALID_INFERENCE_PROVIDERS } from "../../config/schemas/services.js";
|
|
11
|
+
import { providerForImageModelPrefix } from "../../media/types.js";
|
|
11
12
|
import type { ProviderCatalogEntry } from "../../providers/model-catalog.js";
|
|
12
13
|
import {
|
|
13
14
|
isModelInCatalog,
|
|
@@ -219,6 +220,16 @@ export async function setModel(
|
|
|
219
220
|
export function setImageGenModel(modelId: string, ctx: ModelSetContext): void {
|
|
220
221
|
const raw = loadRawConfig();
|
|
221
222
|
setServiceField(raw, "image-generation", "model", modelId);
|
|
223
|
+
// Keep the derived provider in sync with the selected model so downstream
|
|
224
|
+
// routing never sends a Gemini request to an OpenAI model (or vice versa).
|
|
225
|
+
// The prefix logic is shared with workspace migration 006-services-config
|
|
226
|
+
// via providerForImageModelPrefix().
|
|
227
|
+
setServiceField(
|
|
228
|
+
raw,
|
|
229
|
+
"image-generation",
|
|
230
|
+
"provider",
|
|
231
|
+
providerForImageModelPrefix(modelId),
|
|
232
|
+
);
|
|
222
233
|
|
|
223
234
|
const wasSuppressed = ctx.suppressConfigReload;
|
|
224
235
|
ctx.setSuppressConfigReload(true);
|
|
@@ -326,10 +326,14 @@ export function postInstallSkill(
|
|
|
326
326
|
|
|
327
327
|
/** Map the old `source` field to the new `kind` axis. */
|
|
328
328
|
function deriveKind(
|
|
329
|
-
source: "bundled" | "managed" | "workspace" | "extra" | "catalog",
|
|
329
|
+
source: "bundled" | "managed" | "workspace" | "extra" | "catalog" | "plugin",
|
|
330
330
|
): SlimSkillResponse["kind"] {
|
|
331
331
|
if (source === "bundled") return "bundled";
|
|
332
332
|
if (source === "catalog") return "catalog";
|
|
333
|
+
// Plugin-contributed skills are framework-provided like bundled skills —
|
|
334
|
+
// expose them under the same "bundled" kind so the UI doesn't invent a
|
|
335
|
+
// new category that existing clients don't know how to render.
|
|
336
|
+
if (source === "plugin") return "bundled";
|
|
333
337
|
return "installed"; // managed, workspace, extra
|
|
334
338
|
}
|
|
335
339
|
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -12,8 +12,6 @@ import { setVoiceBridgeDeps } from "../calls/voice-session-bridge.js";
|
|
|
12
12
|
import { initFeatureFlagOverrides } from "../config/assistant-feature-flags.js";
|
|
13
13
|
import {
|
|
14
14
|
getPlatformAssistantId,
|
|
15
|
-
getQdrantHttpPortEnv,
|
|
16
|
-
getQdrantUrlEnv,
|
|
17
15
|
getRuntimeHttpHost,
|
|
18
16
|
getRuntimeHttpPort,
|
|
19
17
|
setIngressPublicBaseUrl,
|
|
@@ -43,8 +41,6 @@ import {
|
|
|
43
41
|
startFeedScheduler,
|
|
44
42
|
} from "../home/feed-scheduler.js";
|
|
45
43
|
import { backfillRelationshipStateIfMissing } from "../home/relationship-state-writer.js";
|
|
46
|
-
import { getHookManager } from "../hooks/manager.js";
|
|
47
|
-
import { installTemplates } from "../hooks/templates.js";
|
|
48
44
|
import { closeSentry, initSentry, setSentryDeviceId } from "../instrument.js";
|
|
49
45
|
import { getMcpServerManager } from "../mcp/manager.js";
|
|
50
46
|
import * as attachmentsStore from "../memory/attachments-store.js";
|
|
@@ -63,7 +59,7 @@ import {
|
|
|
63
59
|
} from "../memory/embedding-backend.js";
|
|
64
60
|
import { enqueueMemoryJob } from "../memory/jobs-store.js";
|
|
65
61
|
import { startMemoryJobsWorker } from "../memory/jobs-worker.js";
|
|
66
|
-
import { initQdrantClient } from "../memory/qdrant-client.js";
|
|
62
|
+
import { initQdrantClient, resolveQdrantUrl } from "../memory/qdrant-client.js";
|
|
67
63
|
import { QdrantManager } from "../memory/qdrant-manager.js";
|
|
68
64
|
import { rotateToolInvocations } from "../memory/tool-usage-store.js";
|
|
69
65
|
import { deleteOldTraceEvents } from "../memory/trace-event-store.js";
|
|
@@ -73,6 +69,7 @@ import {
|
|
|
73
69
|
} from "../notifications/emit-signal.js";
|
|
74
70
|
import { backfillManualTokenConnections } from "../oauth/manual-token-connection.js";
|
|
75
71
|
import { seedOAuthProviders } from "../oauth/seed-providers.js";
|
|
72
|
+
import { loadUserPlugins } from "../plugins/user-loader.js";
|
|
76
73
|
import { ensurePromptFiles } from "../prompts/system-prompt.js";
|
|
77
74
|
import { resolveManagedProxyContext } from "../providers/managed-proxy/context.js";
|
|
78
75
|
import { buildAssistantEvent } from "../runtime/assistant-event.js";
|
|
@@ -107,6 +104,7 @@ import {
|
|
|
107
104
|
getInterfacesDir,
|
|
108
105
|
getWorkspaceDir,
|
|
109
106
|
} from "../util/platform.js";
|
|
107
|
+
import { APP_VERSION } from "../version.js";
|
|
110
108
|
import {
|
|
111
109
|
listWorkItems,
|
|
112
110
|
updateWorkItem,
|
|
@@ -124,6 +122,7 @@ import {
|
|
|
124
122
|
cleanupPidFileIfOwner,
|
|
125
123
|
writePid,
|
|
126
124
|
} from "./daemon-control.js";
|
|
125
|
+
import { bootstrapPlugins } from "./external-plugins-bootstrap.js";
|
|
127
126
|
import {
|
|
128
127
|
createGuardianActionCopyGenerator,
|
|
129
128
|
createGuardianFollowUpConversationGenerator,
|
|
@@ -148,7 +147,6 @@ import {
|
|
|
148
147
|
import { seedInterfaceFiles } from "./seed-files.js";
|
|
149
148
|
import { DaemonServer } from "./server.js";
|
|
150
149
|
import { installShutdownHandlers } from "./shutdown-handlers.js";
|
|
151
|
-
import { handleWatchObservation } from "./watch-handler.js";
|
|
152
150
|
|
|
153
151
|
// Re-export public API so existing consumers don't need to change imports
|
|
154
152
|
export type { StopResult } from "./daemon-control.js";
|
|
@@ -340,8 +338,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
340
338
|
|
|
341
339
|
seedInterfaceFiles();
|
|
342
340
|
|
|
343
|
-
log.info("Daemon startup:
|
|
344
|
-
installTemplates();
|
|
341
|
+
log.info("Daemon startup: initializing DB");
|
|
345
342
|
ensurePromptFiles();
|
|
346
343
|
|
|
347
344
|
// DB must be initialized before workspace migrations because some
|
|
@@ -699,6 +696,33 @@ export async function runDaemon(): Promise<void> {
|
|
|
699
696
|
}
|
|
700
697
|
}
|
|
701
698
|
|
|
699
|
+
// Populate the registry with user plugins from `~/.vellum/plugins/*`
|
|
700
|
+
// AFTER first-party plugins have already registered via their static
|
|
701
|
+
// side-effect imports. User plugins may fail to load individually; a
|
|
702
|
+
// failing user plugin is logged and skipped so one bad install can't
|
|
703
|
+
// prevent the daemon from starting. Ordering is load-bearing:
|
|
704
|
+
// first-party registrations → user registrations → bootstrap (init).
|
|
705
|
+
// Both groups are fully registered before any `init()` runs so plugins
|
|
706
|
+
// that depend on each other's registration observably see a stable
|
|
707
|
+
// registry at init time.
|
|
708
|
+
await loadUserPlugins();
|
|
709
|
+
|
|
710
|
+
// Bootstrap registered plugins. Runs after the plugin registry is
|
|
711
|
+
// populated (first-party static side-effect imports + user plugins
|
|
712
|
+
// loaded above) and before the DaemonServer starts handling
|
|
713
|
+
// conversations. Credential resolution + per-plugin storage directory
|
|
714
|
+
// creation happen here. Wrapped in try/catch so a failing plugin can't
|
|
715
|
+
// block daemon startup — bootstrapPlugins internally tears down any
|
|
716
|
+
// partially-initialized plugins before throwing.
|
|
717
|
+
try {
|
|
718
|
+
await bootstrapPlugins({ config, assistantVersion: APP_VERSION });
|
|
719
|
+
} catch (err) {
|
|
720
|
+
log.warn(
|
|
721
|
+
{ err },
|
|
722
|
+
"Plugin bootstrap failed — continuing startup with degraded plugin functionality",
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
|
|
702
726
|
// Start the DaemonServer (conversation manager) before Qdrant so HTTP
|
|
703
727
|
// routes can begin accepting requests while Qdrant initializes.
|
|
704
728
|
log.info("Daemon startup: starting DaemonServer");
|
|
@@ -741,13 +765,7 @@ export async function runDaemon(): Promise<void> {
|
|
|
741
765
|
// Initialize Qdrant vector store and memory worker in the background so the
|
|
742
766
|
// RuntimeHttpServer can start accepting requests without waiting for Qdrant.
|
|
743
767
|
async function initializeQdrantAndMemory(): Promise<void> {
|
|
744
|
-
|
|
745
|
-
// QDRANT_URL (external Qdrant instance) so the CLI can set the port without
|
|
746
|
-
// triggering QdrantManager's external mode which skips local process spawn.
|
|
747
|
-
const qdrantHttpPort = getQdrantHttpPortEnv();
|
|
748
|
-
const qdrantUrl = qdrantHttpPort
|
|
749
|
-
? `http://127.0.0.1:${qdrantHttpPort}`
|
|
750
|
-
: getQdrantUrlEnv() || config.memory.qdrant.url;
|
|
768
|
+
const qdrantUrl = resolveQdrantUrl(config);
|
|
751
769
|
log.info({ qdrantUrl }, "Daemon startup: initializing Qdrant");
|
|
752
770
|
const manager = new QdrantManager({ url: qdrantUrl });
|
|
753
771
|
bgRefs.qdrantManager = manager;
|
|
@@ -941,29 +959,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
941
959
|
throwOnError: true,
|
|
942
960
|
});
|
|
943
961
|
},
|
|
944
|
-
(schedule) => {
|
|
945
|
-
void emitNotificationSignal({
|
|
946
|
-
sourceEventName: "schedule.complete",
|
|
947
|
-
sourceChannel: "scheduler",
|
|
948
|
-
sourceContextId: schedule.id,
|
|
949
|
-
attentionHints: {
|
|
950
|
-
requiresAction: false,
|
|
951
|
-
urgency: "medium",
|
|
952
|
-
isAsyncBackground: true,
|
|
953
|
-
visibleInSourceNow: false,
|
|
954
|
-
},
|
|
955
|
-
contextPayload: {
|
|
956
|
-
scheduleId: schedule.id,
|
|
957
|
-
name: schedule.name,
|
|
958
|
-
},
|
|
959
|
-
conversationMetadata: {
|
|
960
|
-
groupId: "system:scheduled",
|
|
961
|
-
scheduleJobId: schedule.id,
|
|
962
|
-
source: "schedule",
|
|
963
|
-
},
|
|
964
|
-
dedupeKey: `schedule:complete:${schedule.id}:${Date.now()}`,
|
|
965
|
-
});
|
|
966
|
-
},
|
|
967
962
|
(notification) => {
|
|
968
963
|
void emitNotificationSignal({
|
|
969
964
|
sourceEventName: "watcher.notification",
|
|
@@ -1132,28 +1127,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
1132
1127
|
);
|
|
1133
1128
|
},
|
|
1134
1129
|
},
|
|
1135
|
-
getWatchDeps: () => {
|
|
1136
|
-
const ctx = server.getHandlerContext();
|
|
1137
|
-
return {
|
|
1138
|
-
handleWatchObservation: async (params) => {
|
|
1139
|
-
await handleWatchObservation(
|
|
1140
|
-
{
|
|
1141
|
-
type: "watch_observation",
|
|
1142
|
-
watchId: params.watchId,
|
|
1143
|
-
conversationId: params.conversationId,
|
|
1144
|
-
ocrText: params.ocrText,
|
|
1145
|
-
appName: params.appName,
|
|
1146
|
-
windowTitle: params.windowTitle,
|
|
1147
|
-
bundleIdentifier: params.bundleIdentifier,
|
|
1148
|
-
timestamp: params.timestamp,
|
|
1149
|
-
captureIndex: params.captureIndex,
|
|
1150
|
-
totalExpected: params.totalExpected,
|
|
1151
|
-
},
|
|
1152
|
-
ctx,
|
|
1153
|
-
);
|
|
1154
|
-
},
|
|
1155
|
-
};
|
|
1156
|
-
},
|
|
1157
1130
|
getRecordingDeps: () => ({
|
|
1158
1131
|
getHandlerContext: () => server.getHandlerContext(),
|
|
1159
1132
|
}),
|
|
@@ -1390,13 +1363,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
1390
1363
|
log.warn({ err }, "Assistant symlink installation failed — continuing");
|
|
1391
1364
|
}
|
|
1392
1365
|
|
|
1393
|
-
const hookManager = getHookManager();
|
|
1394
|
-
hookManager.watch();
|
|
1395
|
-
|
|
1396
|
-
void hookManager.trigger("daemon-start", {
|
|
1397
|
-
pid: process.pid,
|
|
1398
|
-
});
|
|
1399
|
-
|
|
1400
1366
|
// Download embedding runtime in background (non-blocking).
|
|
1401
1367
|
// If download fails, local embeddings gracefully fall back to cloud backends.
|
|
1402
1368
|
void (async () => {
|
|
@@ -1510,7 +1476,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
1510
1476
|
workspaceHeartbeat,
|
|
1511
1477
|
heartbeat,
|
|
1512
1478
|
filing,
|
|
1513
|
-
hookManager,
|
|
1514
1479
|
runtimeHttp,
|
|
1515
1480
|
scheduler,
|
|
1516
1481
|
feedScheduler,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Computer use and
|
|
1
|
+
// Computer use and recording types.
|
|
2
2
|
|
|
3
3
|
import type { CommandIntent, UserMessageAttachment } from "./shared.js";
|
|
4
4
|
|
|
@@ -15,19 +15,6 @@ export interface TaskSubmit {
|
|
|
15
15
|
commandIntent?: CommandIntent;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export interface WatchObservation {
|
|
19
|
-
type: "watch_observation";
|
|
20
|
-
watchId: string;
|
|
21
|
-
conversationId: string;
|
|
22
|
-
ocrText: string;
|
|
23
|
-
appName?: string;
|
|
24
|
-
windowTitle?: string;
|
|
25
|
-
bundleIdentifier?: string;
|
|
26
|
-
timestamp: number;
|
|
27
|
-
captureIndex: number;
|
|
28
|
-
totalExpected: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
18
|
// === Recording ===
|
|
32
19
|
|
|
33
20
|
/** Recording options shared across standalone and CU recording flows. */
|
|
@@ -89,30 +76,11 @@ export interface RecordingResume {
|
|
|
89
76
|
recordingId: string;
|
|
90
77
|
}
|
|
91
78
|
|
|
92
|
-
export interface WatchStarted {
|
|
93
|
-
type: "watch_started";
|
|
94
|
-
conversationId: string;
|
|
95
|
-
watchId: string;
|
|
96
|
-
durationSeconds: number;
|
|
97
|
-
intervalSeconds: number;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface WatchCompleteRequest {
|
|
101
|
-
type: "watch_complete_request";
|
|
102
|
-
conversationId: string;
|
|
103
|
-
watchId: string;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
79
|
// --- Domain-level union aliases (consumed by the barrel file) ---
|
|
107
80
|
|
|
108
|
-
export type _ComputerUseClientMessages =
|
|
109
|
-
| TaskSubmit
|
|
110
|
-
| WatchObservation
|
|
111
|
-
| RecordingStatus;
|
|
81
|
+
export type _ComputerUseClientMessages = TaskSubmit | RecordingStatus;
|
|
112
82
|
|
|
113
83
|
export type _ComputerUseServerMessages =
|
|
114
|
-
| WatchStarted
|
|
115
|
-
| WatchCompleteRequest
|
|
116
84
|
| RecordingStart
|
|
117
85
|
| RecordingStop
|
|
118
86
|
| RecordingPause
|
|
@@ -421,8 +421,16 @@ export interface UsageResponse {
|
|
|
421
421
|
model: string;
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
+
/**
|
|
425
|
+
* Emitted after a compaction turn completes (both auto-compaction and
|
|
426
|
+
* `/compact`). Carries the fresh `estimatedInputTokens` so clients can refresh
|
|
427
|
+
* the context-window indicator without waiting for the next `usage_update`.
|
|
428
|
+
*
|
|
429
|
+
* Scoped per-conversation — see `CompactionCircuitOpen` doc for why.
|
|
430
|
+
*/
|
|
424
431
|
export interface ContextCompacted {
|
|
425
432
|
type: "context_compacted";
|
|
433
|
+
conversationId: string;
|
|
426
434
|
previousEstimatedInputTokens: number;
|
|
427
435
|
estimatedInputTokens: number;
|
|
428
436
|
maxInputTokens: number;
|
|
@@ -432,6 +440,22 @@ export interface ContextCompacted {
|
|
|
432
440
|
summaryInputTokens: number;
|
|
433
441
|
summaryOutputTokens: number;
|
|
434
442
|
summaryModel: string;
|
|
443
|
+
/**
|
|
444
|
+
* Quality signals for the generated summary. Emitted for every
|
|
445
|
+
* compaction (including truncation-only paths where the summary text
|
|
446
|
+
* is unchanged from the prior pass). Consumers can use these to detect
|
|
447
|
+
* regressions without needing to read the summary text itself.
|
|
448
|
+
*
|
|
449
|
+
* - `summaryCharCount`: length of the produced summary text.
|
|
450
|
+
* - `summaryHeaderCount`: number of `## ` section headers in the summary.
|
|
451
|
+
* - `summaryHadMemoryEcho`: `true` if the summary contains any runtime
|
|
452
|
+
* injection tag (e.g. `<memory`, `<turn_context>`, `<workspace>`).
|
|
453
|
+
* Should always be `false` — `true` indicates the compaction strip
|
|
454
|
+
* logic failed to remove an injected block from the summarizer input.
|
|
455
|
+
*/
|
|
456
|
+
summaryCharCount?: number;
|
|
457
|
+
summaryHeaderCount?: number;
|
|
458
|
+
summaryHadMemoryEcho?: boolean;
|
|
435
459
|
}
|
|
436
460
|
|
|
437
461
|
/**
|
|
@@ -439,14 +463,38 @@ export interface ContextCompacted {
|
|
|
439
463
|
* summary-LLM failures (with local fallback covering each), auto-compaction is
|
|
440
464
|
* suspended until `openUntil` to avoid repeatedly hammering a broken provider.
|
|
441
465
|
* User-initiated compaction (`/compact`, `force: true`) bypasses the breaker.
|
|
466
|
+
*
|
|
467
|
+
* `conversationId` scopes the event so clients can ignore breaker trips from
|
|
468
|
+
* other conversations — `EventStreamClient` broadcasts every parsed server
|
|
469
|
+
* message to all subscribers, so without this field a breaker trip in one
|
|
470
|
+
* conversation would set the "auto-compaction paused" banner on every open
|
|
471
|
+
* `ChatViewModel`.
|
|
442
472
|
*/
|
|
443
473
|
export interface CompactionCircuitOpen {
|
|
444
474
|
type: "compaction_circuit_open";
|
|
475
|
+
conversationId: string;
|
|
445
476
|
reason: "3_consecutive_failures";
|
|
446
477
|
/** Timestamp (ms since epoch) when the breaker will allow auto-compaction again. */
|
|
447
478
|
openUntil: number;
|
|
448
479
|
}
|
|
449
480
|
|
|
481
|
+
/**
|
|
482
|
+
* Emitted when the compaction circuit breaker transitions from open → closed
|
|
483
|
+
* because a successful compaction reset
|
|
484
|
+
* `ctx.compactionCircuitOpenUntil`. The Swift client clears its banner state
|
|
485
|
+
* on receipt so the "auto-compaction paused" indicator dismisses immediately
|
|
486
|
+
* instead of lingering until the original `openUntil` deadline (up to 1h).
|
|
487
|
+
*
|
|
488
|
+
* Only fires on the open→closed transition — successful compactions while
|
|
489
|
+
* the breaker was already closed would be noise.
|
|
490
|
+
*
|
|
491
|
+
* Scoped per-conversation — see `CompactionCircuitOpen` doc for why.
|
|
492
|
+
*/
|
|
493
|
+
export interface CompactionCircuitClosed {
|
|
494
|
+
type: "compaction_circuit_closed";
|
|
495
|
+
conversationId: string;
|
|
496
|
+
}
|
|
497
|
+
|
|
450
498
|
export type ConversationErrorCode =
|
|
451
499
|
| "PROVIDER_NETWORK"
|
|
452
500
|
| "PROVIDER_RATE_LIMIT"
|
|
@@ -545,6 +593,7 @@ export type _ConversationsServerMessages =
|
|
|
545
593
|
| UsageResponse
|
|
546
594
|
| ContextCompacted
|
|
547
595
|
| CompactionCircuitOpen
|
|
596
|
+
| CompactionCircuitClosed
|
|
548
597
|
| ConversationErrorMessage
|
|
549
598
|
| ConversationInfo
|
|
550
599
|
| ConversationTitleUpdated
|
|
@@ -145,6 +145,14 @@ export interface ToolResult {
|
|
|
145
145
|
imageDataList?: string[];
|
|
146
146
|
/** The tool_use block ID for client-side correlation. */
|
|
147
147
|
toolUseId?: string;
|
|
148
|
+
/** Risk level from the classifier ("low" | "medium" | "high" | "unknown"). */
|
|
149
|
+
riskLevel?: string;
|
|
150
|
+
/** Human-readable reason for the risk classification. */
|
|
151
|
+
riskReason?: string;
|
|
152
|
+
/** Whether the daemon is running in a containerized (Docker) environment. */
|
|
153
|
+
isContainerized?: boolean;
|
|
154
|
+
/** Scope options ladder for the rule editor modal (narrowest to broadest). */
|
|
155
|
+
riskScopeOptions?: Array<{ pattern: string; label: string }>;
|
|
148
156
|
}
|
|
149
157
|
|
|
150
158
|
export interface ConfirmationRequest {
|
|
@@ -153,6 +161,10 @@ export interface ConfirmationRequest {
|
|
|
153
161
|
toolName: string;
|
|
154
162
|
input: Record<string, unknown>;
|
|
155
163
|
riskLevel: string;
|
|
164
|
+
/** Human-readable reason for the risk classification (e.g. "Modifies remote repository state"). */
|
|
165
|
+
riskReason?: string;
|
|
166
|
+
/** Whether the daemon is running in a containerized (Docker) environment. */
|
|
167
|
+
isContainerized?: boolean;
|
|
156
168
|
executionTarget?: "sandbox" | "host";
|
|
157
169
|
allowlistOptions: Array<{
|
|
158
170
|
label: string;
|
package/src/daemon/server.ts
CHANGED
|
@@ -886,6 +886,7 @@ export class DaemonServer {
|
|
|
886
886
|
trustClass: conversation.trustContext?.trustClass ?? "guardian",
|
|
887
887
|
hostBrowserProxy: conversation.hostBrowserProxy,
|
|
888
888
|
transportInterface: conversation.transportInterface,
|
|
889
|
+
hostBrowserRegistryRouted: !!conversation.hostBrowserSenderOverride,
|
|
889
890
|
};
|
|
890
891
|
});
|
|
891
892
|
|
|
@@ -1302,9 +1303,10 @@ export class DaemonServer {
|
|
|
1302
1303
|
// Chrome-extension host_browser wiring is intentionally not supported
|
|
1303
1304
|
// through this entry point. `prepareConversationForMessage` constructs
|
|
1304
1305
|
// host_browser proxies that capture `conversation.getCurrentSender()`
|
|
1305
|
-
// directly, which
|
|
1306
|
-
//
|
|
1307
|
-
//
|
|
1306
|
+
// directly, which routes browser frames through the daemon SSE channel.
|
|
1307
|
+
// This is correct for macOS (SSE-based host proxy), but chrome-extension
|
|
1308
|
+
// requires the `ChromeExtensionRegistry` WebSocket transport instead.
|
|
1309
|
+
// Chrome-extension flows reach host_browser exclusively through the
|
|
1308
1310
|
// `/v1/messages` flow in `conversation-routes.ts`, which wires a
|
|
1309
1311
|
// registry-aware sender and sets `hostBrowserSenderOverride`.
|
|
1310
1312
|
//
|
|
@@ -3,7 +3,6 @@ import * as Sentry from "@sentry/node";
|
|
|
3
3
|
import type { BackupWorkerHandle } from "../backup/backup-worker.js";
|
|
4
4
|
import type { FilingService } from "../filing/filing-service.js";
|
|
5
5
|
import type { HeartbeatService } from "../heartbeat/heartbeat-service.js";
|
|
6
|
-
import type { HookManager } from "../hooks/manager.js";
|
|
7
6
|
import type { McpServerManager } from "../mcp/manager.js";
|
|
8
7
|
import { getSqlite, resetDb } from "../memory/db.js";
|
|
9
8
|
import type { QdrantManager } from "../memory/qdrant-manager.js";
|
|
@@ -23,7 +22,6 @@ export interface ShutdownDeps {
|
|
|
23
22
|
workspaceHeartbeat: WorkspaceHeartbeatService;
|
|
24
23
|
heartbeat: HeartbeatService;
|
|
25
24
|
filing: FilingService;
|
|
26
|
-
hookManager: HookManager;
|
|
27
25
|
runtimeHttp: RuntimeHttpServer | null;
|
|
28
26
|
scheduler: { stop(): void };
|
|
29
27
|
feedScheduler: { stop(): void } | null;
|
|
@@ -44,11 +42,9 @@ export function installShutdownHandlers(deps: ShutdownDeps): void {
|
|
|
44
42
|
shuttingDown = true;
|
|
45
43
|
log.info("Shutting down daemon...");
|
|
46
44
|
|
|
47
|
-
deps.hookManager.stopWatching();
|
|
48
|
-
|
|
49
45
|
// Force exit if graceful shutdown takes too long.
|
|
50
|
-
// Set this BEFORE awaiting heartbeat stop
|
|
51
|
-
//
|
|
46
|
+
// Set this BEFORE awaiting heartbeat stop so it covers all
|
|
47
|
+
// potentially-blocking async shutdown work.
|
|
52
48
|
//
|
|
53
49
|
// 20s budget: 15s reserved for Meet session teardown
|
|
54
50
|
// (`MeetSessionManager.shutdownAll`), plus ~5s for the remaining
|
|
@@ -67,12 +63,6 @@ export function installShutdownHandlers(deps: ShutdownDeps): void {
|
|
|
67
63
|
await deps.heartbeat.stop();
|
|
68
64
|
await deps.filing.stop();
|
|
69
65
|
|
|
70
|
-
try {
|
|
71
|
-
await deps.hookManager.trigger("daemon-stop", { pid: process.pid });
|
|
72
|
-
} catch {
|
|
73
|
-
// Don't let hook failures block shutdown
|
|
74
|
-
}
|
|
75
|
-
|
|
76
66
|
// Run registered skill shutdown hooks (e.g. meet-join session teardown)
|
|
77
67
|
// before stopping the server so any HTTP round-trips and SSE emissions
|
|
78
68
|
// still have live transports.
|
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
* registry entry instead of another if/else branch.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { compileApp } from "../bundler/app-compiler.js";
|
|
11
10
|
import { generateAppIcon } from "../media/app-icon-generator.js";
|
|
12
|
-
import { getApp, getAppDirPath, isMultifileApp } from "../memory/app-store.js";
|
|
13
11
|
import { findActiveSession } from "../runtime/channel-verification-service.js";
|
|
14
12
|
import { deliverVerificationSlack } from "../runtime/verification-outbound-actions.js";
|
|
15
13
|
import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
|
|
@@ -39,41 +37,22 @@ export type PostExecutionHook = (
|
|
|
39
37
|
|
|
40
38
|
// ── Helpers ──────────────────────────────────────────────────────────
|
|
41
39
|
|
|
42
|
-
/**
|
|
43
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Propagate an app change to connected clients and the publish pipeline.
|
|
42
|
+
*
|
|
43
|
+
* Compilation is the responsibility of the tool executor (see
|
|
44
|
+
* `executeAppCreate`, `executeAppRefresh`): executors own the source→dist
|
|
45
|
+
* transform and surface `compile_errors` in their result when it fails.
|
|
46
|
+
* Post-execution hooks only observe the outcome and notify — they must
|
|
47
|
+
* not re-run a compile because `compileApp()` begins with `rm -rf dist/`
|
|
48
|
+
* and would race with the executor's own output (LUM-1153).
|
|
49
|
+
*/
|
|
50
|
+
function notifyAppChanged(
|
|
44
51
|
ctx: ToolSetupContext,
|
|
45
52
|
appId: string,
|
|
46
53
|
broadcastToAllClients: ((msg: ServerMessage) => void) | undefined,
|
|
47
54
|
opts?: { fileChange?: boolean; status?: string },
|
|
48
55
|
): void {
|
|
49
|
-
const app = getApp(appId);
|
|
50
|
-
|
|
51
|
-
// Multifile apps need a recompile before refreshing surfaces so the
|
|
52
|
-
// WebView picks up the latest compiled output.
|
|
53
|
-
if (app && isMultifileApp(app)) {
|
|
54
|
-
const appDir = getAppDirPath(appId);
|
|
55
|
-
void compileApp(appDir)
|
|
56
|
-
.then((result) => {
|
|
57
|
-
if (!result.ok) {
|
|
58
|
-
log.warn(
|
|
59
|
-
{ appId, errors: result.errors },
|
|
60
|
-
"Recompile failed on app change, serving stale dist/",
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
refreshSurfacesForApp(ctx, appId, opts);
|
|
64
|
-
broadcastToAllClients?.({ type: "app_files_changed", appId });
|
|
65
|
-
void updatePublishedAppDeployment(appId);
|
|
66
|
-
})
|
|
67
|
-
.catch((err) => {
|
|
68
|
-
log.warn({ appId, err }, "Recompile threw on app change");
|
|
69
|
-
// Still refresh surfaces with stale output
|
|
70
|
-
refreshSurfacesForApp(ctx, appId, opts);
|
|
71
|
-
broadcastToAllClients?.({ type: "app_files_changed", appId });
|
|
72
|
-
void updatePublishedAppDeployment(appId);
|
|
73
|
-
});
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
56
|
refreshSurfacesForApp(ctx, appId, opts);
|
|
78
57
|
broadcastToAllClients?.({ type: "app_files_changed", appId });
|
|
79
58
|
void updatePublishedAppDeployment(appId);
|
|
@@ -115,7 +94,7 @@ registerHook(
|
|
|
115
94
|
// trigger live reload.
|
|
116
95
|
ensureAppSourceWatcher();
|
|
117
96
|
|
|
118
|
-
|
|
97
|
+
notifyAppChanged(ctx, parsed.id, broadcastToAllClients);
|
|
119
98
|
|
|
120
99
|
// Fire-and-forget: generate an app icon in the background.
|
|
121
100
|
// When complete, broadcast again so clients pick up the new icon.
|
|
@@ -165,33 +144,12 @@ registerHook(
|
|
|
165
144
|
);
|
|
166
145
|
|
|
167
146
|
// Trigger surface refresh + broadcast when an app is refreshed.
|
|
168
|
-
// If the executor already compiled (multifile path), skip the redundant
|
|
169
|
-
// recompile and just refresh surfaces / broadcast / deploy directly.
|
|
170
147
|
registerHook(
|
|
171
148
|
"app_refresh",
|
|
172
|
-
(_name, input,
|
|
149
|
+
(_name, input, _result, { ctx, broadcastToAllClients }) => {
|
|
173
150
|
const appId = input.app_id as string | undefined;
|
|
174
151
|
if (!appId) return;
|
|
175
|
-
|
|
176
|
-
// executeAppRefresh already compiled multifile apps and included a
|
|
177
|
-
// "compiled" field in the result. Skip the expensive recompile and
|
|
178
|
-
// go straight to surface refresh + broadcast + deploy.
|
|
179
|
-
let alreadyCompiled = false;
|
|
180
|
-
try {
|
|
181
|
-
const parsed = JSON.parse(result.content) as { compiled?: boolean };
|
|
182
|
-
alreadyCompiled = parsed.compiled !== undefined;
|
|
183
|
-
} catch {
|
|
184
|
-
// Result wasn't valid JSON — fall through to handleAppChange.
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (alreadyCompiled) {
|
|
188
|
-
const opts = { fileChange: true };
|
|
189
|
-
refreshSurfacesForApp(ctx, appId, opts);
|
|
190
|
-
broadcastToAllClients?.({ type: "app_files_changed", appId });
|
|
191
|
-
void updatePublishedAppDeployment(appId);
|
|
192
|
-
} else {
|
|
193
|
-
handleAppChange(ctx, appId, broadcastToAllClients, { fileChange: true });
|
|
194
|
-
}
|
|
152
|
+
notifyAppChanged(ctx, appId, broadcastToAllClients, { fileChange: true });
|
|
195
153
|
},
|
|
196
154
|
);
|
|
197
155
|
|