@vellumai/assistant 0.12.2 → 0.12.3-staging.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/.env.example +2 -0
- package/AGENTS.md +1 -1
- package/ARCHITECTURE.md +43 -29
- package/Dockerfile +63 -0
- package/docs/architecture/integrations.md +7 -0
- package/docs/architecture/memory.md +17 -2
- package/docs/architecture/security.md +10 -5
- package/docs/architecture/turn-actor.md +2 -0
- package/docs/credential-execution-service.md +1 -1
- package/docs/desktop-browser-cli.md +50 -5
- package/docs/live-voice-task-outcomes.md +100 -0
- package/docs/mode-sessions.md +183 -0
- package/docs/voice-input-diagnostics.md +58 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
- package/node_modules/@vellumai/environments/src/shell.ts +24 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -2
- package/node_modules/@vellumai/gateway-client/src/index.ts +4 -1
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +38 -7
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +5 -6
- package/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
- package/openapi.yaml +716 -16
- package/package.json +1 -1
- package/scripts/smoke-desktop-browser-cli.ts +11 -26
- package/scripts/smoke-desktop-window-theme.ts +2 -3
- package/scripts/sync-llm-catalog.ts +3 -0
- package/scripts/voice-ttft-spike.ts +2 -2
- package/src/__tests__/agent-loop-output-hooks.test.ts +150 -1
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +87 -19
- package/src/__tests__/agent-loop.test.ts +259 -0
- package/src/__tests__/agent-wake-delegation-prompt.test.ts +64 -2
- package/src/__tests__/annotate-activity-metadata.test.ts +3 -1
- package/src/__tests__/annotate-risk-options.test.ts +2 -0
- package/src/__tests__/answered-question-persistence.test.ts +2 -0
- package/src/__tests__/anthropic-gateway-shared.test.ts +22 -0
- package/src/__tests__/anthropic-provider.test.ts +55 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
- package/src/__tests__/approval-message-composer.test.ts +1 -118
- package/src/__tests__/approval-routes-http.test.ts +3 -0
- package/src/__tests__/assistant-event-hub-connection-history.test.ts +111 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +50 -0
- package/src/__tests__/assistant-event-targeting.test.ts +186 -0
- package/src/__tests__/assistant-stream-state.test.ts +29 -9
- package/src/__tests__/attachments-store.test.ts +22 -3
- package/src/__tests__/browser-fill-credential.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +4 -1
- package/src/__tests__/build-persisted-content.test.ts +1 -1
- package/src/__tests__/call-conversation-messages.test.ts +5 -0
- package/src/__tests__/call-recovery.test.ts +7 -2
- package/src/__tests__/call-routes-http.test.ts +12 -0
- package/src/__tests__/call-store.test.ts +7 -2
- package/src/__tests__/channel-approval.test.ts +9 -14
- package/src/__tests__/channel-reply-delivery.test.ts +56 -0
- package/src/__tests__/channel-retry-sweep.test.ts +9 -0
- package/src/__tests__/chat-credential-redaction.test.ts +23 -0
- package/src/__tests__/chat-reveal-guard-priming.test.ts +2 -0
- package/src/__tests__/checker.test.ts +11 -3
- package/src/__tests__/client-os-metadata-persistence.test.ts +35 -1
- package/src/__tests__/computer-use-screenshot-attachments.test.ts +411 -0
- package/src/__tests__/computer-use-screenshot-selection.test.ts +50 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -25
- package/src/__tests__/computer-use-tools.test.ts +1 -233
- package/src/__tests__/config-model-image-provider.test.ts +39 -0
- package/src/__tests__/config-schema.test.ts +16 -0
- package/src/__tests__/config-watcher.test.ts +24 -0
- package/src/__tests__/context-search-agent-runner.test.ts +260 -1
- package/src/__tests__/context-search-fanout.test.ts +1 -1
- package/src/__tests__/context-search-types.test.ts +7 -7
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +8 -2
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +797 -16
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
- package/src/__tests__/conversation-attachments.test.ts +106 -0
- package/src/__tests__/conversation-evictor.test.ts +62 -37
- package/src/__tests__/conversation-fork-crud.test.ts +191 -0
- package/src/__tests__/conversation-history-boundary-repair-failure.test.ts +174 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +2 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
- package/src/__tests__/conversation-rendered-delegation-state.test.ts +276 -0
- package/src/__tests__/conversation-retry-route.test.ts +22 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +2 -0
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +2 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +10 -0
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +2 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +29 -0
- package/src/__tests__/conversation-surface-snapshots.test.ts +543 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +151 -0
- package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +63 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +23 -0
- package/src/__tests__/conversation-undo.test.ts +61 -0
- package/src/__tests__/credential-execution-client.test.ts +72 -55
- package/src/__tests__/credential-prompt-route.test.ts +35 -3
- package/src/__tests__/cu-unified-flow.test.ts +82 -1
- package/src/__tests__/db-conversation-tool-surface.test.ts +221 -0
- package/src/__tests__/db-mode-sessions-migration.test.ts +175 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -0
- package/src/__tests__/dm-backfill.test.ts +91 -1
- package/src/__tests__/document-create-route.test.ts +88 -0
- package/src/__tests__/document-sync-tags.test.ts +27 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +142 -2
- package/src/__tests__/events-tail-route.test.ts +58 -0
- package/src/__tests__/evict-conversations-for-reload.test.ts +57 -8
- package/src/__tests__/guardian-action-sweep.test.ts +16 -0
- package/src/__tests__/guardian-dispatch.test.ts +13 -0
- package/src/__tests__/headless-browser-interactions.test.ts +64 -20
- package/src/__tests__/heartbeat-service.test.ts +2 -59
- package/src/__tests__/helpers/mock-conversation.ts +21 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +2 -0
- package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +5 -0
- package/src/__tests__/history-repair.test.ts +53 -0
- package/src/__tests__/host-cu-proxy.test.ts +46 -2
- package/src/__tests__/http-user-message-parity.test.ts +2 -0
- package/src/__tests__/image-credentials.test.ts +49 -0
- package/src/__tests__/image-service-dispatcher.test.ts +45 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +26 -0
- package/src/__tests__/interrupt-on-send.test.ts +57 -43
- package/src/__tests__/interrupt-turn-note.test.ts +5 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +85 -1
- package/src/__tests__/llm-catalog-parity.test.ts +27 -4
- package/src/__tests__/media-generate-image.test.ts +49 -1
- package/src/__tests__/message-provenance-contact-id.test.ts +69 -0
- package/src/__tests__/migration-export-to-gcs.test.ts +142 -0
- package/src/__tests__/mode-session-history.test.ts +245 -0
- package/src/__tests__/mode-session-recovery.test.ts +222 -0
- package/src/__tests__/mode-session-wire.test.ts +141 -0
- package/src/__tests__/notification-guardian-path.test.ts +7 -0
- package/src/__tests__/notification-telegram-adapter.test.ts +2 -2
- package/src/__tests__/notification-vellum-adapter.test.ts +34 -0
- package/src/__tests__/oauth-apps-routes.test.ts +1 -0
- package/src/__tests__/oauth-commands-routes.test.ts +114 -101
- package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +13 -0
- package/src/__tests__/oauth-providers-routes.test.ts +3 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/persist-media-references.test.ts +50 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
- package/src/__tests__/plugin-api-provider.test.ts +5 -0
- package/src/__tests__/plugin-api-resolve-credential.test.ts +97 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +9 -1
- package/src/__tests__/process-message-display-content.test.ts +56 -0
- package/src/__tests__/reaction-persistence.test.ts +5 -0
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +25 -9
- package/src/__tests__/run-conversation-turn-persistence.test.ts +138 -1
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +20 -0
- package/src/__tests__/scheduler-result-notification.test.ts +23 -4
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/scripted-turn-metadata-persistence.test.ts +73 -0
- package/src/__tests__/secret-ingress-http.test.ts +2 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +86 -31
- package/src/__tests__/secret-routes-scrub.test.ts +22 -27
- package/src/__tests__/secret-scanner.test.ts +20 -0
- package/src/__tests__/secure-keys-managed-failover.test.ts +8 -0
- package/src/__tests__/secure-keys.test.ts +50 -4
- package/src/__tests__/send-endpoint-busy.test.ts +163 -1
- package/src/__tests__/server-history-render.test.ts +91 -1
- package/src/__tests__/server-tool-pairing.test.ts +107 -0
- package/src/__tests__/settings-routes.test.ts +50 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
- package/src/__tests__/skills.test.ts +5 -4
- package/src/__tests__/subagent-fork-notifications.test.ts +1 -2
- package/src/__tests__/subagent-manager-notify.test.ts +1 -2
- package/src/__tests__/subagent-notify-parent.test.ts +146 -39
- package/src/__tests__/subagent-notify-stale-rebuild.test.ts +2 -4
- package/src/__tests__/subagent-tool-gate-mode.test.ts +226 -0
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +2 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/thread-backfill.test.ts +53 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
- package/src/__tests__/tool-result-follow-up.test.ts +99 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +66 -1
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/twilio-routes.test.ts +1 -0
- package/src/__tests__/unicode.test.ts +36 -0
- package/src/__tests__/web-search-backend-failure.test.ts +1 -1
- package/src/activation/progress-store.test.ts +12 -7
- package/src/agent/loop.ts +136 -53
- package/src/agent/tool-result-follow-up.ts +70 -0
- package/src/api/attachment-provenance.test.ts +68 -0
- package/src/api/computer-use-tool.test.ts +55 -0
- package/src/api/computer-use-tool.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +3 -0
- package/src/api/events/assistant-turn-start.ts +3 -0
- package/src/api/events/desktop-activity-changed.ts +10 -0
- package/src/api/events/generation-handoff.ts +2 -0
- package/src/api/events/message-complete.ts +2 -0
- package/src/api/events/notification-conversation-created.ts +14 -16
- package/src/api/events/notification-intent.ts +4 -2
- package/src/api/events/question-request.ts +1 -0
- package/src/api/events/tool-result.ts +85 -0
- package/src/api/events/tool-use-start.ts +3 -0
- package/src/api/events/user-message-echo.ts +3 -0
- package/src/api/index.ts +42 -6
- package/src/api/mode-session.test.ts +131 -0
- package/src/api/mode-session.ts +148 -0
- package/src/api/remember-tool.ts +15 -0
- package/src/api/responses/conversation-message.ts +9 -0
- package/src/approvals/AGENTS.md +4 -2
- package/src/approvals/approval-primitive.ts +5 -2
- package/src/approvals/scoped-approval-grants.ts +6 -2
- package/src/browser/__tests__/operations.test.ts +29 -0
- package/src/browser/operation-meta.ts +2 -1
- package/src/browser/operations.ts +29 -0
- package/src/browser/virtual-desktop-target.ts +2 -9
- package/src/bundler/bundle-signer.ts +1 -3
- package/src/calls/__tests__/barge-in-guard.test.ts +3 -0
- package/src/calls/__tests__/call-controller.test.ts +94 -0
- package/src/calls/__tests__/call-funnel-telemetry.test.ts +204 -0
- package/src/calls/__tests__/voice-control-protocol.test.ts +15 -0
- package/src/calls/__tests__/voice-escalation-judge.test.ts +209 -0
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +168 -0
- package/src/{live-voice/__tests__/live-voice-metrics.test.ts → calls/__tests__/voice-metrics.test.ts} +32 -38
- package/src/calls/__tests__/voice-session-bridge.test.ts +576 -122
- package/src/calls/barge-in-guard.ts +5 -0
- package/src/calls/call-controller.ts +196 -1
- package/src/calls/call-domain.ts +4 -0
- package/src/calls/call-store.ts +87 -2
- package/src/calls/guardian-action-sweep.ts +22 -8
- package/src/calls/media-stream-audio-transcode.ts +1 -3
- package/src/calls/typesafe-noul.ts +156 -0
- package/src/calls/voice-control-protocol.ts +6 -0
- package/src/calls/voice-escalation-judge.ts +145 -0
- package/src/calls/voice-escalation-target.ts +10 -0
- package/src/calls/voice-leg-coordinator.ts +121 -3
- package/src/{live-voice/live-voice-metrics.ts → calls/voice-metrics.ts} +94 -87
- package/src/calls/voice-session-bridge.ts +256 -112
- package/src/calls/voice-triage-escalate.ts +7 -0
- package/src/cli/__tests__/roadmap-cli.test.ts +4 -41
- package/src/cli/commands/__tests__/cli-test-harness.ts +21 -3
- package/src/cli/commands/__tests__/notifications.test.ts +35 -10
- package/src/cli/commands/__tests__/plugins.test.ts +20 -1
- package/src/cli/commands/__tests__/schedules.test.ts +14 -0
- package/src/cli/commands/bash.help.ts +4 -3
- package/src/cli/commands/browser.help.ts +9 -6
- package/src/cli/commands/browser.ts +0 -1
- package/src/cli/commands/clients.help.ts +46 -0
- package/src/cli/commands/clients.ts +116 -0
- package/src/cli/commands/credentials.help.ts +9 -4
- package/src/cli/commands/notifications.help.ts +16 -2
- package/src/cli/commands/notifications.ts +30 -8
- package/src/cli/commands/oauth/index.help.ts +10 -0
- package/src/cli/commands/oauth/providers.ts +12 -0
- package/src/cli/commands/oauth/request.test.ts +179 -2
- package/src/cli/commands/oauth/request.ts +41 -10
- package/src/cli/commands/plugins.ts +12 -5
- package/src/cli/commands/roadmap.help.ts +18 -21
- package/src/cli/commands/roadmap.ts +4 -21
- package/src/cli/commands/schedules.ts +2 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +41 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
- package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +133 -51
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +8 -2
- package/src/cli/lib/bundled-marketplace.json +906 -1
- package/src/cli/lib/bundled-plugin-packages.json +783 -1
- package/src/cli/lib/inspect-plugin.ts +11 -4
- package/src/cli/lib/plugin-marketplace.ts +8 -0
- package/src/cli/lib/publish-plugin.ts +1 -2
- package/src/cli/lib/upgrade-plugin.ts +19 -11
- package/src/cli/output.ts +18 -4
- package/src/config/__tests__/default-provider.test.ts +6 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +14 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +1 -1
- package/src/config/bundled-skills/computer-use/TOOLS.json +89 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +17 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -11
- package/src/config/bundled-skills/schedule/SKILL.md +6 -6
- package/src/config/bundled-skills/sequences/TOOLS.json +1 -5
- package/src/config/call-site-defaults.ts +9 -0
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/loader.ts +9 -17
- package/src/config/platform-identity.ts +8 -8
- package/src/config/profile-text-generation.test.ts +51 -0
- package/src/config/profile-text-generation.ts +51 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +12 -0
- package/src/config/schemas/__tests__/tools.test.ts +31 -0
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/channels.ts +0 -18
- package/src/config/schemas/llm.ts +9 -2
- package/src/config/schemas/mcp.ts +6 -1
- package/src/config/schemas/memory-retrospective.ts +11 -2
- package/src/config/schemas/memory-v3.ts +12 -0
- package/src/config/schemas/services.ts +15 -6
- package/src/config/schemas/tools.ts +10 -0
- package/src/config/session-groups-gate.ts +21 -0
- package/src/config/skills.ts +2 -6
- package/src/conversations/__tests__/message-consolidation.test.ts +149 -0
- package/src/conversations/message-consolidation.ts +102 -5
- package/src/credential-execution/ces-connect.test.ts +69 -0
- package/src/credential-execution/ces-connect.ts +115 -0
- package/src/credential-execution/ces-runtime.ts +55 -93
- package/src/credential-execution/executable-discovery.ts +34 -142
- package/src/credential-execution/process-manager.test.ts +20 -24
- package/src/credential-execution/process-manager.ts +24 -19
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +43 -0
- package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
- package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +36 -0
- package/src/daemon/assistant-attachments.ts +20 -12
- package/src/daemon/browser-mode-session.test.ts +402 -0
- package/src/daemon/browser-mode-session.ts +186 -0
- package/src/daemon/chat-credential-redaction.ts +16 -1
- package/src/daemon/computer-use-mode-session.test.ts +210 -0
- package/src/daemon/computer-use-mode-session.ts +105 -0
- package/src/daemon/config-watcher.ts +10 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +132 -13
- package/src/daemon/conversation-agent-loop.ts +231 -25
- package/src/daemon/conversation-attachments.ts +93 -12
- package/src/daemon/conversation-evictor.ts +5 -24
- package/src/daemon/conversation-history.ts +10 -0
- package/src/daemon/conversation-interrupt-repair.ts +4 -43
- package/src/daemon/conversation-interrupt.ts +7 -11
- package/src/daemon/conversation-messaging.ts +58 -5
- package/src/daemon/conversation-mode-session.test.ts +1667 -0
- package/src/daemon/conversation-mode-session.ts +1008 -0
- package/src/daemon/conversation-process.ts +5 -0
- package/src/daemon/conversation-runtime-assembly.ts +10 -20
- package/src/daemon/conversation-skill-tools.ts +1 -0
- package/src/daemon/conversation-store.ts +4 -4
- package/src/daemon/conversation-surface-snapshots.ts +135 -0
- package/src/daemon/conversation-surfaces.ts +113 -5
- package/src/daemon/conversation-tool-setup.ts +79 -6
- package/src/daemon/conversation-turn-finalize.ts +26 -13
- package/src/daemon/conversation.ts +215 -58
- package/src/daemon/daemon-control.ts +3 -7
- package/src/daemon/handlers/config-model.ts +7 -5
- package/src/daemon/handlers/shared.ts +55 -16
- package/src/daemon/host-cu-proxy.ts +51 -22
- package/src/daemon/lifecycle.ts +30 -13
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/message-protocol.ts +0 -1
- package/src/daemon/message-provenance.ts +28 -4
- package/src/daemon/message-types/shared.ts +1 -0
- package/src/daemon/mode-session-startup-recovery.ts +23 -0
- package/src/daemon/mode-session-tracking.ts +54 -0
- package/src/daemon/orphan-reaper.ts +4 -3
- package/src/daemon/persist-media-references.ts +20 -3
- package/src/daemon/process-message.ts +13 -4
- package/src/daemon/tool-setup-types.ts +6 -0
- package/src/daemon/virtual-desktop-context.ts +21 -0
- package/src/daemon/wake-conversation-ops.ts +50 -15
- package/src/desktop/__tests__/fake-desktop.ts +1 -0
- package/src/desktop/desktop-accessibility-script.ts +88 -0
- package/src/desktop/desktop-accessibility.test.ts +160 -0
- package/src/desktop/desktop-accessibility.ts +169 -0
- package/src/desktop/desktop-automation-lease.test.ts +302 -64
- package/src/desktop/desktop-automation-lease.ts +129 -54
- package/src/desktop/desktop-browser-endpoint.ts +4 -0
- package/src/desktop/desktop-computer-use-routing.test.ts +330 -0
- package/src/desktop/desktop-computer-use.test.ts +449 -0
- package/src/desktop/desktop-computer-use.ts +502 -0
- package/src/desktop/desktop-dependencies.ts +47 -293
- package/src/desktop/desktop-display.ts +2 -2
- package/src/desktop/desktop-help.ts +15 -0
- package/src/desktop/desktop-panel-config.test.ts +13 -3
- package/src/desktop/desktop-panel-config.ts +109 -15
- package/src/desktop/desktop-session-manager.test.ts +69 -21
- package/src/desktop/desktop-session-manager.ts +76 -22
- package/src/desktop/desktop-stream-bridge.test.ts +76 -132
- package/src/desktop/desktop-stream-bridge.ts +9 -11
- package/src/desktop/desktop-wallpaper-renderer.ts +132 -0
- package/src/desktop/desktop-wallpaper-worker.ts +17 -0
- package/src/desktop/desktop-wallpaper.test.ts +48 -7
- package/src/desktop/desktop-wallpaper.ts +34 -102
- package/src/desktop/desktop-window-theme.ts +5 -25
- package/src/desktop/virtual-desktop-feature.ts +53 -3
- package/src/desktop/virtual-desktop-platform.test.ts +5 -9
- package/src/documents/document-store.ts +23 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +22 -26
- package/src/heartbeat/heartbeat-service.ts +5 -33
- package/src/ipc/__tests__/browser-ipc.test.ts +215 -6
- package/src/ipc/assistant-server.ts +2 -0
- package/src/ipc/routes/__tests__/channel-reply-ipc-routes.test.ts +111 -0
- package/src/ipc/routes/channel-reply-ipc-routes.ts +73 -0
- package/src/live-voice/__tests__/continuation-judge.test.ts +151 -0
- package/src/live-voice/__tests__/live-activity-reporter.test.ts +154 -15
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +743 -31
- package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +191 -10
- package/src/live-voice/__tests__/live-voice-session-groups-gate.test.ts +87 -0
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +5 -1
- package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +41 -0
- package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +1017 -9
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +224 -1
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +101 -0
- package/src/live-voice/__tests__/live-voice-tts.test.ts +44 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +939 -75
- package/src/live-voice/__tests__/microphone-idle-gate.test.ts +87 -0
- package/src/live-voice/__tests__/session-controls.test.ts +23 -0
- package/src/live-voice/__tests__/task-outcomes.test.ts +117 -0
- package/src/live-voice/__tests__/voice-input-diagnostics.test.ts +117 -0
- package/src/live-voice/camera-mode-session.test.ts +265 -0
- package/src/live-voice/camera-mode-session.ts +277 -0
- package/src/live-voice/continuation-judge.ts +123 -0
- package/src/live-voice/live-activity-reporter.ts +115 -6
- package/src/live-voice/live-voice-manager.ts +36 -1
- package/src/live-voice/live-voice-photo.ts +88 -7
- package/src/live-voice/live-voice-session-manager.ts +15 -0
- package/src/live-voice/live-voice-session.ts +1443 -747
- package/src/live-voice/live-voice-tts.ts +22 -4
- package/src/live-voice/microphone-idle-gate.ts +56 -0
- package/src/live-voice/protocol.ts +171 -4
- package/src/live-voice/session-controls.ts +11 -3
- package/src/live-voice/task-outcomes.ts +131 -0
- package/src/live-voice/voice-input-diagnostics.ts +117 -0
- package/src/mcp/__tests__/manager-tool-caps.test.ts +156 -0
- package/src/mcp/__tests__/startup.test.ts +30 -7
- package/src/mcp/__tests__/tool-caps.test.ts +134 -0
- package/src/mcp/manager.ts +171 -101
- package/src/mcp/startup.ts +33 -13
- package/src/mcp/tool-caps.ts +184 -0
- package/src/media/__tests__/image-models.test.ts +58 -0
- package/src/media/image-credentials.ts +5 -0
- package/src/media/image-models.ts +52 -0
- package/src/media/image-service.ts +8 -0
- package/src/media/openrouter-image-service.test.ts +133 -0
- package/src/media/openrouter-image-service.ts +153 -0
- package/src/media/types.ts +1 -1
- package/src/messaging/provider-message-metadata.ts +3 -3
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +65 -11
- package/src/messaging/providers/discord/send.ts +4 -17
- package/src/messaging/providers/discord/transport.ts +2 -2
- package/src/messaging/providers/outlook/client.ts +16 -22
- package/src/messaging/providers/telegram-bot/send.test.ts +236 -1
- package/src/messaging/providers/telegram-bot/send.ts +10 -7
- package/src/messaging/providers/telegram-bot/transport.ts +3 -10
- package/src/messaging/providers/whatsapp/send.test.ts +169 -4
- package/src/monitoring/__tests__/control.test.ts +17 -5
- package/src/monitoring/control.ts +15 -5
- package/src/notifications/AGENTS.md +1 -1
- package/src/notifications/README.md +83 -99
- package/src/notifications/__tests__/broadcaster.test.ts +1 -1
- package/src/notifications/__tests__/channel-allowlist.test.ts +39 -0
- package/src/notifications/__tests__/copy-composer.test.ts +71 -1
- package/src/notifications/__tests__/decision-engine.test.ts +79 -2
- package/src/notifications/__tests__/deterministic-checks.test.ts +10 -10
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +93 -4
- package/src/notifications/__tests__/notification-utils.test.ts +18 -0
- package/src/notifications/adapters/macos.ts +37 -46
- package/src/notifications/broadcaster.ts +5 -6
- package/src/notifications/channel-allowlist.ts +44 -0
- package/src/notifications/copy-composer.ts +11 -26
- package/src/notifications/decision-engine.ts +24 -14
- package/src/notifications/deterministic-checks.ts +1 -1
- package/src/notifications/emit-signal.ts +123 -37
- package/src/notifications/home-feed-side-effect.ts +9 -7
- package/src/notifications/notification-utils.ts +19 -0
- package/src/notifications/schedule-result-producer.ts +4 -6
- package/src/notifications/signal.ts +4 -19
- package/src/notifications/types.ts +15 -0
- package/src/oauth/AGENTS.md +2 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +36 -1
- package/src/oauth/connection-resolver.ts +1 -2
- package/src/oauth/identity-verifier.ts +24 -0
- package/src/oauth/oauth-store.ts +12 -4
- package/src/oauth/provider-serializer.ts +8 -0
- package/src/oauth/seed-providers.ts +42 -0
- package/src/onboarding/onboarding-events-store.ts +99 -12
- package/src/permissions/confirmation-guardian-request.test.ts +16 -0
- package/src/permissions/confirmation-guardian-request.ts +2 -3
- package/src/permissions/question-prompter.test.ts +31 -0
- package/src/permissions/question-prompter.ts +2 -0
- package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
- package/src/persistence/attachments-store.ts +84 -44
- package/src/persistence/client-connection-events-store.ts +377 -0
- package/src/persistence/conversation-crud.ts +166 -26
- package/src/persistence/conversation-mode-sessions.test.ts +424 -0
- package/src/persistence/conversation-mode-sessions.ts +460 -0
- package/src/persistence/conversation-plugin-facade.ts +30 -0
- package/src/persistence/conversation-queries.ts +6 -19
- package/src/persistence/conversation-tool-surface.ts +135 -0
- package/src/persistence/conversation-types.test.ts +32 -0
- package/src/persistence/conversation-types.ts +26 -4
- package/src/persistence/llm-usage-store.ts +3 -9
- package/src/persistence/message-metadata.ts +25 -0
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.test.ts +78 -0
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.ts +29 -0
- package/src/persistence/migrations/379-oauth-providers-response-ok-field.test.ts +92 -0
- package/src/persistence/migrations/379-oauth-providers-response-ok-field.ts +32 -0
- package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.test.ts +90 -0
- package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.ts +34 -0
- package/src/persistence/migrations/381-create-conversation-mode-sessions.ts +41 -0
- package/src/persistence/migrations/382-create-client-connection-events.ts +40 -0
- package/src/persistence/migrations/__tests__/382-create-client-connection-events.test.ts +56 -0
- package/src/persistence/schema/conversation-tool-surfaces.ts +32 -0
- package/src/persistence/schema/conversations.ts +67 -0
- package/src/persistence/schema/index.ts +1 -0
- package/src/persistence/schema/infrastructure.ts +29 -0
- package/src/persistence/schema/oauth.ts +1 -0
- package/src/persistence/steps.ts +41 -3
- package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
- package/src/plugin-api/conversation-turn.ts +31 -7
- package/src/plugin-api/effective-context-window.ts +33 -0
- package/src/plugin-api/index.ts +35 -6
- package/src/plugin-api/plugin-channel-turn-trust.test.ts +133 -0
- package/src/plugin-api/plugin-channel-turn-trust.ts +71 -0
- package/src/plugin-api/plugin-name-env.ts +125 -0
- package/src/plugin-api/resolve-credential.ts +79 -20
- package/src/plugin-api/vision-support.test.ts +22 -0
- package/src/plugin-api/vision-support.ts +17 -5
- package/src/plugins/__tests__/active-plugin-env.test.ts +136 -0
- package/src/plugins/active-plugin-env.ts +51 -0
- package/src/plugins/defaults/index.ts +24 -0
- package/src/plugins/defaults/memory/AGENTS.md +39 -5
- package/src/plugins/defaults/memory/__tests__/archive-removal-framing.test.ts +64 -0
- package/src/plugins/defaults/memory/__tests__/buffer-file.test.ts +365 -0
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +43 -0
- package/src/plugins/defaults/memory/__tests__/conversation-memory-purge.test.ts +1 -0
- package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +2 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/buffer-appender.ts +17 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +74 -0
- package/src/plugins/defaults/memory/__tests__/memory-run-evidence.test.ts +161 -0
- package/src/plugins/defaults/memory/__tests__/relocated-memory-test-rows.ts +10 -0
- package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
- package/src/plugins/defaults/memory/buffer-file.ts +354 -0
- package/src/plugins/defaults/memory/buffer-format.ts +40 -0
- package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +77 -22
- package/src/plugins/defaults/memory/context-search/format.ts +53 -8
- package/src/plugins/defaults/memory/context-search/limits.ts +10 -12
- package/src/plugins/defaults/memory/context-search/recall-input.ts +38 -0
- package/src/plugins/defaults/memory/context-search/search.ts +8 -14
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +1 -0
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +2 -1
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +2 -1
- package/src/plugins/defaults/memory/context-search/types.ts +1 -11
- package/src/plugins/defaults/memory/conversation-memory-purge.ts +4 -0
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
- package/src/plugins/defaults/memory/graph/capability-seed.ts +1 -2
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +13 -63
- package/src/plugins/defaults/memory/graph/tools.ts +35 -64
- package/src/plugins/defaults/memory/host-utils.ts +0 -10
- package/src/plugins/defaults/memory/injectors.ts +4 -3
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +72 -183
- package/src/plugins/defaults/memory/memory-run-evidence.ts +213 -0
- package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +6 -1
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +407 -99
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +10 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +107 -7
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +307 -86
- package/src/plugins/defaults/memory/substrate/consolidation-tool-surface.ts +34 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +2 -1
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +91 -51
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +1 -1
- package/src/plugins/defaults/memory/tools.test.ts +124 -9
- package/src/plugins/defaults/memory/tools.ts +38 -11
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +2 -2
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +2 -1
- package/src/plugins/defaults/memory/v1/graph/retriever.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +5 -0
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +5 -2
- package/src/plugins/defaults/memory/v2/reranker.ts +2 -1
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +81 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +87 -0
- package/src/plugins/defaults/memory/v3/__tests__/plugin-schema.test.ts +12 -0
- package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +332 -15
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +148 -28
- package/src/plugins/defaults/memory/v3/card.ts +2 -1
- package/src/plugins/defaults/memory/v3/injector.ts +212 -178
- package/src/plugins/defaults/memory/v3/orchestrate.ts +159 -32
- package/src/plugins/defaults/memory/v3/plugin-schema.ts +54 -4
- package/src/plugins/defaults/memory/v3/pool-log-store.ts +275 -37
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +47 -5
- package/src/plugins/defaults/memory/v3/pool-select.ts +710 -59
- package/src/plugins/defaults/memory/v3/sections.ts +2 -1
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +41 -14
- package/src/plugins/defaults/memory/worker-control.ts +15 -5
- package/src/plugins/defaults/task-progress/__tests__/registration.test.ts +70 -0
- package/src/plugins/defaults/task-progress/__tests__/task-progress-context.test.ts +380 -0
- package/src/plugins/defaults/task-progress/hooks/post-compact.ts +19 -0
- package/src/plugins/defaults/task-progress/hooks/user-prompt-submit.ts +24 -0
- package/src/plugins/defaults/task-progress/package.json +14 -0
- package/src/plugins/defaults/task-progress/src/apply-task-progress-context.ts +93 -0
- package/src/plugins/defaults/task-progress/src/format-task-progress-context.ts +67 -0
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +4 -1
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +1 -46
- package/src/prompts/__tests__/parallel-tasks-section.test.ts +25 -0
- package/src/prompts/delegation-gate.ts +57 -0
- package/src/prompts/system-prompt.ts +14 -32
- package/src/providers/__tests__/context-overflow-error.test.ts +10 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +18 -0
- package/src/providers/anthropic/client.ts +10 -1
- package/src/providers/anthropic-gateway-shared.ts +6 -0
- package/src/providers/fetch-provider-catalog.ts +11 -0
- package/src/providers/gemini/client.ts +25 -8
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/jev/client.test.ts +270 -0
- package/src/providers/jev/client.ts +534 -0
- package/src/providers/model-catalog.ts +59 -3
- package/src/providers/openai/__tests__/chat-completions-extra-body.test.ts +94 -1
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +106 -1
- package/src/providers/openai/__tests__/chat-template-flatten.test.ts +24 -0
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +1 -2
- package/src/providers/openai/chat-completions-provider.ts +100 -29
- package/src/providers/openai/google-thought-signature.ts +0 -6
- package/src/providers/openai/responses-provider.ts +23 -1
- package/src/providers/ratelimit.ts +1 -3
- package/src/providers/search-provider-catalog.ts +24 -0
- package/src/providers/server-tool-pairing.ts +16 -7
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +24 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +7 -1
- package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +50 -1
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +11 -0
- package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +13 -0
- package/src/providers/types.ts +5 -0
- package/src/routes/control.ts +7 -5
- package/src/runtime/AGENTS.md +6 -4
- package/src/runtime/__tests__/agent-wake.test.ts +94 -1
- package/src/runtime/actor-trust-resolver.ts +3 -3
- package/src/runtime/agent-wake.ts +32 -5
- package/src/runtime/approval-message-composer.ts +3 -69
- package/src/runtime/assistant-event-hub.ts +73 -75
- package/src/runtime/assistant-event-publish-options.ts +7 -0
- package/src/runtime/assistant-event-targeting.ts +79 -0
- package/src/runtime/assistant-stream-state.ts +13 -100
- package/src/runtime/background-job-runner.ts +5 -5
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/guardian-action-message-composer.ts +8 -161
- package/src/runtime/guardian-action-service.ts +2 -17
- package/src/runtime/guardian-reply-router.ts +29 -40
- package/src/runtime/http-server.ts +2 -2
- package/src/runtime/http-types.ts +6 -0
- package/src/runtime/message-composer-types.ts +3 -61
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +67 -1
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +89 -0
- package/src/runtime/migrations/vbundle-builder.ts +24 -1
- package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +43 -11
- package/src/runtime/migrations/vbundle-importer.ts +4 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +4 -1
- package/src/runtime/migrations/vbundle-validator.ts +1 -0
- package/src/runtime/pending-interactions-mode-session.test.ts +62 -0
- package/src/runtime/pending-interactions.ts +29 -0
- package/src/runtime/routes/__tests__/client-history-routes.test.ts +104 -0
- package/src/runtime/routes/__tests__/image-generation-routes.test.ts +97 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +24 -2
- package/src/runtime/routes/__tests__/roadmap-routes.test.ts +29 -6
- package/src/runtime/routes/browser-context.ts +31 -11
- package/src/runtime/routes/browser-routes.ts +43 -4
- package/src/runtime/routes/btw-routes.ts +9 -4
- package/src/runtime/routes/channel-route-shared.ts +1 -9
- package/src/runtime/routes/client-routes.ts +108 -0
- package/src/runtime/routes/conversation-management-routes.ts +4 -1
- package/src/runtime/routes/conversation-routes.ts +125 -14
- package/src/runtime/routes/credential-prompt-routes.ts +4 -3
- package/src/runtime/routes/credential-routes.ts +1 -2
- package/src/runtime/routes/desktop-setup-routes.test.ts +9 -18
- package/src/runtime/routes/desktop-setup-routes.ts +8 -7
- package/src/runtime/routes/documents-routes.ts +51 -0
- package/src/runtime/routes/email-routes.ts +3 -7
- package/src/runtime/routes/events-routes.ts +75 -54
- package/src/runtime/routes/guardian-approval-interception.ts +24 -0
- package/src/runtime/routes/identity-routes.ts +1 -5
- package/src/runtime/routes/image-generation-routes.ts +8 -14
- package/src/runtime/routes/inbound-message-handler.ts +37 -41
- package/src/runtime/routes/inbound-stages/backfill-sender-provenance.test.ts +168 -0
- package/src/runtime/routes/inbound-stages/backfill-sender-provenance.ts +96 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +39 -10
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +9 -9
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +11 -1
- package/src/runtime/routes/inference-profiles-routes.ts +9 -0
- package/src/runtime/routes/llm-context-normalization.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +73 -2
- package/src/runtime/routes/notification-routes.ts +10 -0
- package/src/runtime/routes/oauth-commands-routes.ts +57 -54
- package/src/runtime/routes/oauth-providers.ts +11 -0
- package/src/runtime/routes/oauth-request-hints.test.ts +246 -0
- package/src/runtime/routes/oauth-request-hints.ts +149 -0
- package/src/runtime/routes/plugins-routes.ts +6 -0
- package/src/runtime/routes/roadmap-routes.ts +47 -8
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/secret-routes.ts +99 -119
- package/src/runtime/routes/settings-routes.ts +10 -4
- package/src/runtime/routes/watcher-routes.ts +1 -3
- package/src/runtime/trust-class.test.ts +7 -6
- package/src/runtime/trust-class.ts +9 -17
- package/src/schedule/__tests__/worker-control.test.ts +36 -5
- package/src/schedule/__tests__/worker-mcp-bootstrap.test.ts +107 -0
- package/src/schedule/__tests__/worker-mcp-readiness.test.ts +173 -0
- package/src/schedule/__tests__/worker-mcp-tools.test.ts +13 -47
- package/src/schedule/run-script.ts +2 -2
- package/src/schedule/scheduler.ts +47 -11
- package/src/schedule/tool-surface-readiness.ts +65 -0
- package/src/schedule/worker-control.ts +15 -5
- package/src/schedule/worker-mcp.ts +85 -0
- package/src/schedule/worker.ts +9 -31
- package/src/security/secure-keys.ts +74 -112
- package/src/skills/clawhub.ts +3 -8
- package/src/skills/managed-store.ts +1 -5
- package/src/stt/types.ts +4 -0
- package/src/subagent/notify.ts +54 -34
- package/src/subagent/parent-notification.ts +6 -0
- package/src/telemetry/__tests__/phone-call-funnel.test.ts +72 -0
- package/src/telemetry/phone-call-funnel.ts +144 -0
- package/src/tools/__tests__/tool-schema-root-combinator-guard.test.ts +81 -0
- package/src/tools/ask-question/ask-question-tool.test.ts +167 -5
- package/src/tools/ask-question/ask-question-tool.ts +120 -22
- package/src/tools/browser/browser-execution.ts +29 -60
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +561 -39
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +435 -39
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +1 -8
- package/src/tools/client-os.ts +15 -0
- package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
- package/src/tools/computer-use/target.ts +42 -0
- package/src/tools/document/document-tool.ts +13 -18
- package/src/tools/execution-target.ts +14 -16
- package/src/tools/host-terminal/host-shell.ts +16 -7
- package/src/tools/network/__tests__/web-fetch-tinyfish.test.ts +250 -0
- package/src/tools/network/__tests__/web-search.test.ts +203 -0
- package/src/tools/network/web-fetch.ts +274 -7
- package/src/tools/network/web-search.ts +468 -6
- package/src/tools/permission-checker.ts +3 -3
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +1 -31
- package/src/tools/shared/shell-output.test.ts +10 -0
- package/src/tools/shared/shell-output.ts +14 -2
- package/src/tools/skills/load.ts +2 -1
- package/src/tools/skills/sandbox-runner.ts +24 -4
- package/src/tools/skills/scaffold-managed.ts +2 -1
- package/src/tools/skills/skill-script-runner.ts +7 -0
- package/src/tools/skills/skill-tool-factory.ts +15 -1
- package/src/tools/terminal/__tests__/safe-env.test.ts +44 -4
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -14
- package/src/tools/terminal/safe-env.ts +39 -24
- package/src/tools/terminal/sanitized-bash.ts +15 -2
- package/src/tools/terminal/shell-launch.test.ts +162 -0
- package/src/tools/terminal/shell.test.ts +29 -0
- package/src/tools/terminal/shell.ts +15 -7
- package/src/tools/tool-approval-handler.ts +5 -1
- package/src/tools/tool-types.ts +3 -3
- package/src/tools/types.ts +8 -2
- package/src/util/__tests__/worker-process-command.test.ts +5 -4
- package/src/util/abort-reasons.ts +18 -26
- package/src/util/browser-human-verification.ts +14 -0
- package/src/util/canonicalize-identity.test.ts +21 -0
- package/src/util/canonicalize-identity.ts +16 -0
- package/src/util/errors.ts +13 -3
- package/src/util/host-process.test.ts +17 -1
- package/src/util/host-process.ts +24 -0
- package/src/util/provider-error-patterns.ts +3 -0
- package/src/util/unicode.ts +29 -0
- package/src/util/worker-process.ts +77 -35
- package/src/workspace/migrations/157-add-desktop-files-launcher.ts +94 -0
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +4 -10
- package/src/workspace/migrations/__tests__/157-add-desktop-files-launcher.test.ts +113 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/computer-use-window-schema.test.ts +0 -24
- package/src/api/events/heartbeat-alert.ts +0 -20
- package/src/daemon/message-types/web-activity.ts +0 -65
- package/src/desktop/desktop-dependencies.test.ts +0 -131
- package/src/tools/computer-use/definitions.ts +0 -607
|
@@ -32,6 +32,16 @@ interface ListHomeFeedPayload {
|
|
|
32
32
|
updatedAt: string;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
function parseCommaSeparatedList(raw: string): string[] | undefined {
|
|
36
|
+
const items = raw
|
|
37
|
+
.split(",")
|
|
38
|
+
.map((item) => item.trim())
|
|
39
|
+
.filter((item) => {
|
|
40
|
+
return item.length > 0;
|
|
41
|
+
});
|
|
42
|
+
return items.length > 0 ? items : undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
35
45
|
function parseBoundedInt(
|
|
36
46
|
raw: string | undefined,
|
|
37
47
|
label: string,
|
|
@@ -142,6 +152,7 @@ export function registerNotificationsCommand(program: Command): void {
|
|
|
142
152
|
visibleInSourceNow: boolean;
|
|
143
153
|
deadlineAt?: string;
|
|
144
154
|
preferredChannels?: string;
|
|
155
|
+
channels?: string;
|
|
145
156
|
sessionId?: string;
|
|
146
157
|
dedupeKey?: string;
|
|
147
158
|
deepLinkMetadata?: string;
|
|
@@ -220,14 +231,12 @@ export function registerNotificationsCommand(program: Command): void {
|
|
|
220
231
|
deadlineAt = parsed;
|
|
221
232
|
}
|
|
222
233
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
.filter((ch) => ch.length > 0);
|
|
230
|
-
}
|
|
234
|
+
const preferredChannels = opts.preferredChannels
|
|
235
|
+
? parseCommaSeparatedList(opts.preferredChannels)
|
|
236
|
+
: undefined;
|
|
237
|
+
const channelAllowlist = opts.channels
|
|
238
|
+
? parseCommaSeparatedList(opts.channels)
|
|
239
|
+
: undefined;
|
|
231
240
|
|
|
232
241
|
// Parse --deep-link-metadata
|
|
233
242
|
let deepLinkMetadata: Record<string, unknown> | undefined;
|
|
@@ -283,6 +292,9 @@ export function registerNotificationsCommand(program: Command): void {
|
|
|
283
292
|
dispatched: boolean;
|
|
284
293
|
deduplicated: boolean;
|
|
285
294
|
reason: string;
|
|
295
|
+
selectedChannels?: string[];
|
|
296
|
+
deliveryResults?: unknown[];
|
|
297
|
+
receiptClass?: string;
|
|
286
298
|
}>("emit_notification_signal", {
|
|
287
299
|
body: {
|
|
288
300
|
sourceChannel,
|
|
@@ -300,6 +312,7 @@ export function registerNotificationsCommand(program: Command): void {
|
|
|
300
312
|
requestedBySource: sourceChannel,
|
|
301
313
|
...(opts.title ? { requestedTitle: opts.title } : {}),
|
|
302
314
|
...(preferredChannels?.length ? { preferredChannels } : {}),
|
|
315
|
+
...(channelAllowlist?.length ? { channelAllowlist } : {}),
|
|
303
316
|
...(deepLinkMetadata ? { deepLinkMetadata } : {}),
|
|
304
317
|
},
|
|
305
318
|
...(opts.dedupeKey ? { dedupeKey: opts.dedupeKey } : {}),
|
|
@@ -326,6 +339,9 @@ export function registerNotificationsCommand(program: Command): void {
|
|
|
326
339
|
signalId: signal.signalId,
|
|
327
340
|
dispatched: signal.dispatched,
|
|
328
341
|
reason: signal.reason,
|
|
342
|
+
selectedChannels: signal.selectedChannels ?? [],
|
|
343
|
+
deliveryResults: signal.deliveryResults ?? [],
|
|
344
|
+
receiptClass: signal.receiptClass ?? "unknown",
|
|
329
345
|
});
|
|
330
346
|
|
|
331
347
|
if (!shouldOutputJson(cmd)) {
|
|
@@ -335,6 +351,12 @@ export function registerNotificationsCommand(program: Command): void {
|
|
|
335
351
|
if (signal.reason) {
|
|
336
352
|
log.info(` Reason: ${signal.reason}`);
|
|
337
353
|
}
|
|
354
|
+
if (signal.selectedChannels && signal.selectedChannels.length > 0) {
|
|
355
|
+
log.info(` Channels: ${signal.selectedChannels.join(", ")}`);
|
|
356
|
+
}
|
|
357
|
+
if (signal.receiptClass) {
|
|
358
|
+
log.info(` Receipt: ${signal.receiptClass}`);
|
|
359
|
+
}
|
|
338
360
|
}
|
|
339
361
|
} catch (err) {
|
|
340
362
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -258,6 +258,11 @@ Examples:
|
|
|
258
258
|
description:
|
|
259
259
|
"Dot-notation path to a boolean field that must be truthy for the response to be valid",
|
|
260
260
|
},
|
|
261
|
+
{
|
|
262
|
+
flags: "--response-ok-field <field>",
|
|
263
|
+
description:
|
|
264
|
+
"Dot-notation path to the boolean every response body carries to report success (Slack: ok); an explicit false under a 2xx fails the request",
|
|
265
|
+
},
|
|
261
266
|
{
|
|
262
267
|
flags: "--setup-notes <json>",
|
|
263
268
|
description:
|
|
@@ -430,6 +435,11 @@ Examples:
|
|
|
430
435
|
flags: "--identity-ok-field <field>",
|
|
431
436
|
description: "Dot-notation path to a boolean ok field",
|
|
432
437
|
},
|
|
438
|
+
{
|
|
439
|
+
flags: "--response-ok-field <field>",
|
|
440
|
+
description:
|
|
441
|
+
"Dot-notation path to the boolean every response body carries to report success",
|
|
442
|
+
},
|
|
433
443
|
{
|
|
434
444
|
flags: "--setup-notes <json>",
|
|
435
445
|
description: "JSON array of setup instruction notes",
|
|
@@ -49,6 +49,7 @@ interface SerializedProvider {
|
|
|
49
49
|
identityResponsePaths?: string[] | null;
|
|
50
50
|
identityFormat?: string | null;
|
|
51
51
|
identityOkField?: string | null;
|
|
52
|
+
responseOkField?: string | null;
|
|
52
53
|
availableScopes?: unknown;
|
|
53
54
|
setupNotes?: string[] | unknown;
|
|
54
55
|
featureFlag?: string | null;
|
|
@@ -217,6 +218,9 @@ function formatProviderDetail(p: SerializedProvider): string {
|
|
|
217
218
|
if (p.identityOkField) {
|
|
218
219
|
lines.push(` Identity ok field: ${p.identityOkField}`);
|
|
219
220
|
}
|
|
221
|
+
if (p.responseOkField) {
|
|
222
|
+
lines.push(` Response ok field: ${p.responseOkField}`);
|
|
223
|
+
}
|
|
220
224
|
if (p.setupNotes) {
|
|
221
225
|
if (Array.isArray(p.setupNotes)) {
|
|
222
226
|
lines.push(
|
|
@@ -403,6 +407,7 @@ export function registerProviderCommands(oauth: Command): void {
|
|
|
403
407
|
identityResponsePaths?: string;
|
|
404
408
|
identityFormat?: string;
|
|
405
409
|
identityOkField?: string;
|
|
410
|
+
responseOkField?: string;
|
|
406
411
|
setupNotes?: string;
|
|
407
412
|
availableScopes?: string;
|
|
408
413
|
},
|
|
@@ -505,6 +510,9 @@ export function registerProviderCommands(oauth: Command): void {
|
|
|
505
510
|
if (opts.identityOkField !== undefined) {
|
|
506
511
|
body.identity_ok_field = opts.identityOkField;
|
|
507
512
|
}
|
|
513
|
+
if (opts.responseOkField !== undefined) {
|
|
514
|
+
body.response_ok_field = opts.responseOkField;
|
|
515
|
+
}
|
|
508
516
|
if (opts.setupNotes !== undefined) {
|
|
509
517
|
body.setup_notes = JSON.parse(opts.setupNotes);
|
|
510
518
|
}
|
|
@@ -578,6 +586,7 @@ export function registerProviderCommands(oauth: Command): void {
|
|
|
578
586
|
identityResponsePaths?: string;
|
|
579
587
|
identityFormat?: string;
|
|
580
588
|
identityOkField?: string;
|
|
589
|
+
responseOkField?: string;
|
|
581
590
|
setupNotes?: string;
|
|
582
591
|
availableScopes?: string;
|
|
583
592
|
},
|
|
@@ -686,6 +695,9 @@ export function registerProviderCommands(oauth: Command): void {
|
|
|
686
695
|
if (opts.identityOkField !== undefined) {
|
|
687
696
|
body.identity_ok_field = opts.identityOkField;
|
|
688
697
|
}
|
|
698
|
+
if (opts.responseOkField !== undefined) {
|
|
699
|
+
body.response_ok_field = opts.responseOkField;
|
|
700
|
+
}
|
|
689
701
|
if (opts.setupNotes !== undefined) {
|
|
690
702
|
body.setup_notes = JSON.parse(opts.setupNotes);
|
|
691
703
|
}
|
|
@@ -17,6 +17,7 @@ let handleRequestResult: {
|
|
|
17
17
|
body: unknown;
|
|
18
18
|
bodyEncoding?: "base64";
|
|
19
19
|
account?: string | null;
|
|
20
|
+
hint?: string;
|
|
20
21
|
} = {
|
|
21
22
|
ok: true,
|
|
22
23
|
status: 200,
|
|
@@ -71,18 +72,71 @@ afterEach(() => {
|
|
|
71
72
|
process.exitCode = 0;
|
|
72
73
|
});
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Runs the command with both streams captured and `process.exit` recorded.
|
|
77
|
+
* The stream stubs honour a write callback the way the real streams do, so an
|
|
78
|
+
* exit that rides the last write lands in `exitCalls`, and only after every
|
|
79
|
+
* chunk written before it has been captured. `holdStderr` keeps stderr
|
|
80
|
+
* callbacks back and returns them, for the case where stderr is still in
|
|
81
|
+
* flight when stdout has drained.
|
|
82
|
+
*/
|
|
83
|
+
async function runRequestCommand(
|
|
84
|
+
args: string[],
|
|
85
|
+
options: { holdStderr?: boolean } = {},
|
|
86
|
+
): Promise<{
|
|
75
87
|
stdout: Buffer;
|
|
88
|
+
stderr: string;
|
|
76
89
|
exitCode: number;
|
|
90
|
+
exitCalls: number[];
|
|
91
|
+
heldStderrCallbacks: Array<() => void>;
|
|
77
92
|
}> {
|
|
78
93
|
const chunks: Buffer[] = [];
|
|
94
|
+
const stderrChunks: string[] = [];
|
|
95
|
+
const exitCalls: number[] = [];
|
|
96
|
+
const heldStderrCallbacks: Array<() => void> = [];
|
|
79
97
|
const originalWrite = process.stdout.write;
|
|
80
|
-
process.
|
|
98
|
+
const originalStderrWrite = process.stderr.write;
|
|
99
|
+
const originalExit = process.exit;
|
|
100
|
+
const callbackOf = (rest: unknown[]): (() => void) | undefined =>
|
|
101
|
+
rest.find((arg) => typeof arg === "function") as (() => void) | undefined;
|
|
102
|
+
process.stdout.write = ((chunk: string | Uint8Array, ...rest: unknown[]) => {
|
|
81
103
|
chunks.push(
|
|
82
104
|
typeof chunk === "string" ? Buffer.from(chunk) : Buffer.from(chunk),
|
|
83
105
|
);
|
|
106
|
+
callbackOf(rest)?.();
|
|
84
107
|
return true;
|
|
85
108
|
}) as typeof process.stdout.write;
|
|
109
|
+
process.stderr.write = ((chunk: string | Uint8Array, ...rest: unknown[]) => {
|
|
110
|
+
stderrChunks.push(String(chunk));
|
|
111
|
+
const callback = callbackOf(rest);
|
|
112
|
+
if (callback) {
|
|
113
|
+
if (options.holdStderr) {
|
|
114
|
+
heldStderrCallbacks.push(holdCallback(callback));
|
|
115
|
+
} else {
|
|
116
|
+
callback();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}) as typeof process.stderr.write;
|
|
121
|
+
const recordExit = ((code?: number) => {
|
|
122
|
+
exitCalls.push(code ?? Number(process.exitCode ?? 0));
|
|
123
|
+
}) as typeof process.exit;
|
|
124
|
+
process.exit = recordExit;
|
|
125
|
+
// A held callback runs after this function has restored the real
|
|
126
|
+
// `process.exit`, so it reinstalls the recorder for the duration of the
|
|
127
|
+
// call; the exit it triggers must land in `exitCalls`, never end the test
|
|
128
|
+
// process.
|
|
129
|
+
const holdCallback = (callback: () => void): (() => void) => {
|
|
130
|
+
return () => {
|
|
131
|
+
const current = process.exit;
|
|
132
|
+
process.exit = recordExit;
|
|
133
|
+
try {
|
|
134
|
+
callback();
|
|
135
|
+
} finally {
|
|
136
|
+
process.exit = current;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
};
|
|
86
140
|
|
|
87
141
|
try {
|
|
88
142
|
const program = new Command();
|
|
@@ -101,11 +155,16 @@ async function runRequestCommand(args: string[]): Promise<{
|
|
|
101
155
|
// Commander may throw under exitOverride for parse errors.
|
|
102
156
|
} finally {
|
|
103
157
|
process.stdout.write = originalWrite;
|
|
158
|
+
process.stderr.write = originalStderrWrite;
|
|
159
|
+
process.exit = originalExit;
|
|
104
160
|
}
|
|
105
161
|
|
|
106
162
|
return {
|
|
107
163
|
stdout: Buffer.concat(chunks),
|
|
164
|
+
stderr: stderrChunks.join(""),
|
|
108
165
|
exitCode: Number(process.exitCode ?? 0),
|
|
166
|
+
exitCalls,
|
|
167
|
+
heldStderrCallbacks,
|
|
109
168
|
};
|
|
110
169
|
}
|
|
111
170
|
|
|
@@ -308,6 +367,124 @@ describe("oauth request body output", () => {
|
|
|
308
367
|
expect(parsed.bodyEncoding).toBe("base64");
|
|
309
368
|
});
|
|
310
369
|
|
|
370
|
+
test("exits non-zero when the route reports failure inside a 2xx", async () => {
|
|
371
|
+
// The exit code follows the route's verdict, so a caller that only checks
|
|
372
|
+
// the exit code sees a refused call as a failure; the body still prints,
|
|
373
|
+
// since it carries the provider's own error code.
|
|
374
|
+
handleRequestResult = {
|
|
375
|
+
ok: false,
|
|
376
|
+
status: 200,
|
|
377
|
+
headers: { "content-type": "application/json" },
|
|
378
|
+
body: { ok: false, error: "not_in_channel" },
|
|
379
|
+
account: "user@example.com",
|
|
380
|
+
};
|
|
381
|
+
const { stdout, exitCode } = await runRequestCommand([
|
|
382
|
+
"--provider",
|
|
383
|
+
"slack_channel",
|
|
384
|
+
"-s",
|
|
385
|
+
"/chat.postMessage",
|
|
386
|
+
]);
|
|
387
|
+
|
|
388
|
+
expect(exitCode).toBe(1);
|
|
389
|
+
expect(stdout.toString("utf8")).toContain("not_in_channel");
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
test("exits itself once the whole body has drained", async () => {
|
|
393
|
+
// The in-process route leaves handles open, so the command has to exit;
|
|
394
|
+
// and it must do so on the write callback, because a bare exit after a
|
|
395
|
+
// large piped write drops everything past the first 64 KB.
|
|
396
|
+
const body = "x".repeat(200_000);
|
|
397
|
+
handleRequestResult = {
|
|
398
|
+
ok: true,
|
|
399
|
+
status: 200,
|
|
400
|
+
headers: { "content-type": "text/plain" },
|
|
401
|
+
body,
|
|
402
|
+
account: "user@example.com",
|
|
403
|
+
};
|
|
404
|
+
const { stdout, exitCode, exitCalls } = await runRequestCommand([
|
|
405
|
+
"--provider",
|
|
406
|
+
"google",
|
|
407
|
+
"-s",
|
|
408
|
+
"https://api.google.com/v1/big",
|
|
409
|
+
]);
|
|
410
|
+
|
|
411
|
+
expect(stdout.toString("utf8")).toBe(body + "\n");
|
|
412
|
+
expect(exitCode).toBe(0);
|
|
413
|
+
expect(exitCalls).toEqual([0]);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
test("exits after writing an empty body to a file", async () => {
|
|
417
|
+
const target = join(tempDir, "empty.bin");
|
|
418
|
+
handleRequestResult = {
|
|
419
|
+
ok: true,
|
|
420
|
+
status: 204,
|
|
421
|
+
headers: {},
|
|
422
|
+
body: null,
|
|
423
|
+
account: "user@example.com",
|
|
424
|
+
};
|
|
425
|
+
const { exitCalls } = await runRequestCommand([
|
|
426
|
+
"--provider",
|
|
427
|
+
"google",
|
|
428
|
+
"-s",
|
|
429
|
+
"-o",
|
|
430
|
+
target,
|
|
431
|
+
"https://api.google.com/v1/none",
|
|
432
|
+
]);
|
|
433
|
+
|
|
434
|
+
expect(readFileSync(target)).toHaveLength(0);
|
|
435
|
+
expect(exitCalls).toEqual([0]);
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
test("waits for stderr to drain before exiting when stdout carried nothing", async () => {
|
|
439
|
+
// With `-o`, stdout carries nothing, so the exit cannot ride a stdout
|
|
440
|
+
// write, and the diagnostics on stderr (the account line, a hint) may
|
|
441
|
+
// still be in flight. The exit waits for the last of them.
|
|
442
|
+
const target = join(tempDir, "body.json");
|
|
443
|
+
handleRequestResult = {
|
|
444
|
+
ok: false,
|
|
445
|
+
status: 200,
|
|
446
|
+
headers: { "content-type": "application/json" },
|
|
447
|
+
body: { ok: false, error: "not_in_channel" },
|
|
448
|
+
account: "user@example.com",
|
|
449
|
+
hint: "slack_channel answered HTTP 200 but reported ok: false",
|
|
450
|
+
};
|
|
451
|
+
const { stderr, exitCalls, heldStderrCallbacks } = await runRequestCommand(
|
|
452
|
+
["--provider", "slack_channel", "-o", target, "/chat.postMessage"],
|
|
453
|
+
{ holdStderr: true },
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
expect(stderr).toContain("Account: user@example.com");
|
|
457
|
+
expect(stderr).toContain("ok: false");
|
|
458
|
+
expect(heldStderrCallbacks).toHaveLength(2);
|
|
459
|
+
expect(exitCalls).toEqual([]);
|
|
460
|
+
|
|
461
|
+
heldStderrCallbacks[0]();
|
|
462
|
+
expect(exitCalls).toEqual([]);
|
|
463
|
+
heldStderrCallbacks[1]();
|
|
464
|
+
expect(exitCalls).toEqual([1]);
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
test("a stdout body waits for stderr diagnostics written before it", async () => {
|
|
468
|
+
handleRequestResult = {
|
|
469
|
+
ok: true,
|
|
470
|
+
status: 200,
|
|
471
|
+
headers: { "content-type": "application/json" },
|
|
472
|
+
body: { hello: "world" },
|
|
473
|
+
account: "user@example.com",
|
|
474
|
+
};
|
|
475
|
+
const { stdout, exitCalls, heldStderrCallbacks } = await runRequestCommand(
|
|
476
|
+
["--provider", "google", "https://api.google.com/v1/me"],
|
|
477
|
+
{ holdStderr: true },
|
|
478
|
+
);
|
|
479
|
+
|
|
480
|
+
expect(stdout.toString("utf8")).toContain("hello");
|
|
481
|
+
expect(heldStderrCallbacks).toHaveLength(1);
|
|
482
|
+
expect(exitCalls).toEqual([]);
|
|
483
|
+
|
|
484
|
+
heldStderrCallbacks[0]();
|
|
485
|
+
expect(exitCalls).toEqual([0]);
|
|
486
|
+
});
|
|
487
|
+
|
|
311
488
|
test("writes text bodies as UTF-8 and appends a newline on stdout", async () => {
|
|
312
489
|
handleRequestResult = {
|
|
313
490
|
ok: true,
|
|
@@ -142,11 +142,38 @@ export async function runAuthenticatedRequest(params: {
|
|
|
142
142
|
const { providerKey, url, opts, cmd } = params;
|
|
143
143
|
const jsonMode = shouldOutputJson(cmd);
|
|
144
144
|
|
|
145
|
+
// The command exits itself, once its last write on either stream has
|
|
146
|
+
// drained. Running the route in-process leaves handles open that the event
|
|
147
|
+
// loop waits on (the lazy CES connection the credential resolves through is
|
|
148
|
+
// never closed by the CLI), so returning from the action would leave the
|
|
149
|
+
// process alive after a complete response. A bare `process.exit()` is not
|
|
150
|
+
// the answer either: with a pipe on the other end, Bun flushes what the
|
|
151
|
+
// pipe accepts and drops the rest, so the exit rides write callbacks, which
|
|
152
|
+
// fire when the bytes are out. Stdout's last write carries `exit` itself;
|
|
153
|
+
// stderr's writes are counted, so an exit requested while one is still in
|
|
154
|
+
// flight waits for it. The pipe's capacity is not a bound to lean on: a
|
|
155
|
+
// busy host can shrink an unprivileged pipe to a single page.
|
|
156
|
+
let stderrInFlight = 0;
|
|
157
|
+
let exitRequested = false;
|
|
158
|
+
const exit = (): void => {
|
|
159
|
+
exitRequested = true;
|
|
160
|
+
if (stderrInFlight === 0) {
|
|
161
|
+
process.exit(Number(process.exitCode ?? 0));
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
145
165
|
// Helper: write info to stderr (respects -s)
|
|
146
166
|
const writeInfo = (msg: string): void => {
|
|
147
|
-
if (
|
|
148
|
-
|
|
167
|
+
if (opts.silent) {
|
|
168
|
+
return;
|
|
149
169
|
}
|
|
170
|
+
stderrInFlight += 1;
|
|
171
|
+
process.stderr.write(msg + "\n", () => {
|
|
172
|
+
stderrInFlight -= 1;
|
|
173
|
+
if (exitRequested) {
|
|
174
|
+
exit();
|
|
175
|
+
}
|
|
176
|
+
});
|
|
150
177
|
};
|
|
151
178
|
|
|
152
179
|
try {
|
|
@@ -232,17 +259,18 @@ export async function runAuthenticatedRequest(params: {
|
|
|
232
259
|
// reported the way every other failure here is, so `--json` gets its
|
|
233
260
|
// envelope and the caller's diagnostics hint is not lost; only the
|
|
234
261
|
// exit code comes from the route's status.
|
|
235
|
-
writeError(cmd, `${err.message}\n\n${params.diagnosticsHint}`);
|
|
236
262
|
process.exitCode = exitCodeFromIpcResult({
|
|
237
263
|
statusCode: err.statusCode,
|
|
238
264
|
});
|
|
265
|
+
writeError(cmd, `${err.message}\n\n${params.diagnosticsHint}`, exit);
|
|
239
266
|
return;
|
|
240
267
|
}
|
|
241
268
|
throw err;
|
|
242
269
|
}
|
|
243
270
|
|
|
244
|
-
//
|
|
245
|
-
|
|
271
|
+
// The route's verdict, not the status code: a provider that reports
|
|
272
|
+
// failure inside a 2xx (Slack's `ok: false`) is a failed request.
|
|
273
|
+
if (!result.ok) {
|
|
246
274
|
process.exitCode = 1;
|
|
247
275
|
}
|
|
248
276
|
|
|
@@ -261,7 +289,7 @@ export async function runAuthenticatedRequest(params: {
|
|
|
261
289
|
|
|
262
290
|
// JSON output mode
|
|
263
291
|
if (jsonMode) {
|
|
264
|
-
writeOutput(cmd, result);
|
|
292
|
+
writeOutput(cmd, result, exit);
|
|
265
293
|
return;
|
|
266
294
|
}
|
|
267
295
|
|
|
@@ -282,20 +310,23 @@ export async function runAuthenticatedRequest(params: {
|
|
|
282
310
|
if (output) {
|
|
283
311
|
if (opts.output) {
|
|
284
312
|
writeFileSync(opts.output, output.bytes);
|
|
313
|
+
} else if (output.isBinary) {
|
|
314
|
+
process.stdout.write(output.bytes, exit);
|
|
315
|
+
return;
|
|
285
316
|
} else {
|
|
286
317
|
process.stdout.write(output.bytes);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
318
|
+
process.stdout.write("\n", exit);
|
|
319
|
+
return;
|
|
290
320
|
}
|
|
291
321
|
}
|
|
292
322
|
} else if (opts.output) {
|
|
293
323
|
writeFileSync(opts.output, Buffer.alloc(0));
|
|
294
324
|
}
|
|
325
|
+
exit();
|
|
295
326
|
} catch (err) {
|
|
296
327
|
const message = err instanceof Error ? err.message : String(err);
|
|
297
|
-
writeError(cmd, `${message}\n\n${params.diagnosticsHint}`);
|
|
298
328
|
process.exitCode = 1;
|
|
329
|
+
writeError(cmd, `${message}\n\n${params.diagnosticsHint}`, exit);
|
|
299
330
|
}
|
|
300
331
|
}
|
|
301
332
|
|
|
@@ -238,11 +238,18 @@ export function registerPluginsCommand(program: Command): void {
|
|
|
238
238
|
const platformEnabled =
|
|
239
239
|
libs.catalogLocal.arePlatformFeaturesEnabled();
|
|
240
240
|
if (platformEnabled) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
241
|
+
let match;
|
|
242
|
+
try {
|
|
243
|
+
match = (
|
|
244
|
+
await libs.catalogCache.getPluginCatalog(
|
|
245
|
+
DEFAULT_PLUGIN_REF,
|
|
246
|
+
{ fetch: globalThis.fetch.bind(globalThis) },
|
|
247
|
+
)
|
|
248
|
+
).matches.find((candidate) => candidate.name === nameOrUrl);
|
|
249
|
+
} catch {
|
|
250
|
+
// The install endpoint remains authoritative and can succeed
|
|
251
|
+
// independently when catalog discovery is unavailable.
|
|
252
|
+
}
|
|
246
253
|
if (match?.source.kind === "local") {
|
|
247
254
|
result = await libs.installGitHub.installPlugin(
|
|
248
255
|
{
|
|
@@ -25,7 +25,7 @@ no verb to post one.
|
|
|
25
25
|
Examples:
|
|
26
26
|
$ assistant roadmap list --sort upvotes --limit 10
|
|
27
27
|
$ assistant roadmap get scheduled-messages
|
|
28
|
-
$ assistant roadmap create --title "Add dark mode" --tag
|
|
28
|
+
$ assistant roadmap create --title "Add dark mode" --tag area-interface
|
|
29
29
|
$ assistant roadmap upvote scheduled-messages`,
|
|
30
30
|
subcommands: [
|
|
31
31
|
{
|
|
@@ -79,10 +79,13 @@ Examples:
|
|
|
79
79
|
options: [
|
|
80
80
|
{
|
|
81
81
|
flags: "--title <title>",
|
|
82
|
-
description: "Item title (required)",
|
|
82
|
+
description: "Item title, 1 to 200 characters (required)",
|
|
83
83
|
required: true,
|
|
84
84
|
},
|
|
85
|
-
{
|
|
85
|
+
{
|
|
86
|
+
flags: "--description <desc>",
|
|
87
|
+
description: "Item description, up to 5000 characters",
|
|
88
|
+
},
|
|
86
89
|
{
|
|
87
90
|
flags: "--tag <slug>",
|
|
88
91
|
description:
|
|
@@ -97,41 +100,35 @@ accepted, since status is assigned by Vellum.
|
|
|
97
100
|
Examples:
|
|
98
101
|
$ assistant roadmap create --title "Add dark mode"
|
|
99
102
|
$ assistant roadmap create --title "Recurring reminders" \\
|
|
100
|
-
--description "Repeat a scheduled message weekly" --tag
|
|
103
|
+
--description "Repeat a scheduled message weekly" --tag area-assistant`,
|
|
101
104
|
},
|
|
102
105
|
{
|
|
103
106
|
name: "update",
|
|
104
107
|
args: "<slug>",
|
|
105
|
-
description:
|
|
108
|
+
description:
|
|
109
|
+
"Edit the title or description of an item the assistant filed",
|
|
106
110
|
options: [
|
|
107
|
-
{ flags: "--title <title>", description: "New title" },
|
|
108
|
-
{ flags: "--description <desc>", description: "New description" },
|
|
109
111
|
{
|
|
110
|
-
flags: "--
|
|
111
|
-
description: "New
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
flags: "--tag <slug>",
|
|
115
|
-
description: "Replacement tag slug, repeatable",
|
|
112
|
+
flags: "--title <title>",
|
|
113
|
+
description: "New title, 1 to 200 characters",
|
|
116
114
|
},
|
|
117
115
|
{
|
|
118
|
-
flags: "--
|
|
119
|
-
description: "
|
|
116
|
+
flags: "--description <desc>",
|
|
117
|
+
description: "New description, up to 5000 characters",
|
|
120
118
|
},
|
|
121
119
|
],
|
|
122
120
|
helpText: `
|
|
123
121
|
Arguments:
|
|
124
122
|
<slug> Item slug, as printed in the URL by 'assistant roadmap list'
|
|
125
123
|
|
|
126
|
-
At least one
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
At least one of --title or --description is required. Only items this
|
|
125
|
+
assistant filed can be edited, and only while their status is still open.
|
|
126
|
+
Status and tags are set by Vellum staff, so an item's tags are chosen once,
|
|
127
|
+
on 'roadmap create'.
|
|
130
128
|
|
|
131
129
|
Examples:
|
|
132
130
|
$ assistant roadmap update dark-mode --description "Follow the OS setting"
|
|
133
|
-
$ assistant roadmap update dark-mode --
|
|
134
|
-
$ assistant roadmap update dark-mode --clear-tags`,
|
|
131
|
+
$ assistant roadmap update dark-mode --title "Dark mode that follows the OS"`,
|
|
135
132
|
},
|
|
136
133
|
{
|
|
137
134
|
name: "delete",
|
|
@@ -14,7 +14,7 @@ import { stripAnsiAndControlChars as sanitize } from "../../util/ansi.js";
|
|
|
14
14
|
import { applyCommandHelp, subcommand } from "../lib/cli-command-help.js";
|
|
15
15
|
import { registerCommand } from "../lib/register-command.js";
|
|
16
16
|
import { log } from "../logger.js";
|
|
17
|
-
import { shouldOutputJson,
|
|
17
|
+
import { shouldOutputJson, writeOutput } from "../output.js";
|
|
18
18
|
import { roadmapHelp } from "./roadmap.help.js";
|
|
19
19
|
|
|
20
20
|
// ---------------------------------------------------------------------------
|
|
@@ -227,9 +227,6 @@ async function runCreate(cmd: Command, opts: CreateOpts): Promise<void> {
|
|
|
227
227
|
interface UpdateOpts {
|
|
228
228
|
title?: string;
|
|
229
229
|
description?: string;
|
|
230
|
-
status?: string;
|
|
231
|
-
tag?: string[];
|
|
232
|
-
clearTags?: boolean;
|
|
233
230
|
}
|
|
234
231
|
|
|
235
232
|
async function runUpdate(
|
|
@@ -237,24 +234,11 @@ async function runUpdate(
|
|
|
237
234
|
slug: string,
|
|
238
235
|
opts: UpdateOpts,
|
|
239
236
|
): Promise<void> {
|
|
240
|
-
if (opts.clearTags && opts.tag) {
|
|
241
|
-
writeError(
|
|
242
|
-
cmd,
|
|
243
|
-
"--clear-tags and --tag conflict. Drop --clear-tags to set tags, or drop --tag to remove them all.",
|
|
244
|
-
);
|
|
245
|
-
process.exitCode = 1;
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
237
|
const item = await call<MutatedRoadmapItem>("roadmap_update", {
|
|
250
238
|
pathParams: { slug },
|
|
251
239
|
body: {
|
|
252
240
|
title: opts.title,
|
|
253
241
|
description: opts.description,
|
|
254
|
-
status: opts.status,
|
|
255
|
-
// `--tag` always carries a value, so an empty set is only reachable
|
|
256
|
-
// through `--clear-tags`.
|
|
257
|
-
tags: opts.clearTags ? [] : opts.tag,
|
|
258
242
|
},
|
|
259
243
|
});
|
|
260
244
|
|
|
@@ -334,10 +318,9 @@ export function registerRoadmapCommand(program: Command): void {
|
|
|
334
318
|
makeTagRepeatable(create);
|
|
335
319
|
create.action((opts: CreateOpts, cmd: Command) => runCreate(cmd, opts));
|
|
336
320
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
runUpdate(cmd, slug, opts),
|
|
321
|
+
subcommand(roadmap, "update").action(
|
|
322
|
+
(slug: string, opts: UpdateOpts, cmd: Command) =>
|
|
323
|
+
runUpdate(cmd, slug, opts),
|
|
341
324
|
);
|
|
342
325
|
|
|
343
326
|
subcommand(roadmap, "delete").action(
|
|
@@ -35,6 +35,7 @@ interface ScheduleRecord {
|
|
|
35
35
|
mode: string;
|
|
36
36
|
status: string;
|
|
37
37
|
routingIntent: string;
|
|
38
|
+
quiet: boolean;
|
|
38
39
|
reuseConversation: boolean;
|
|
39
40
|
wakeConversationId: string | null;
|
|
40
41
|
sourceKey: string | null;
|
|
@@ -268,6 +269,7 @@ export function registerSchedulesCommand(program: Command): void {
|
|
|
268
269
|
formatScheduleInferenceProfile(schedule.inferenceProfile),
|
|
269
270
|
],
|
|
270
271
|
["Routing intent", schedule.routingIntent],
|
|
272
|
+
["Quiet", schedule.quiet ? "yes" : "no"],
|
|
271
273
|
["Reuse conversation", schedule.reuseConversation ? "yes" : "no"],
|
|
272
274
|
["Wake conversation", schedule.wakeConversationId ?? "—"],
|
|
273
275
|
["Retry count", String(schedule.retryCount)],
|