@vellumai/assistant 0.12.3-staging.1 → 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/ARCHITECTURE.md +43 -29
- package/Dockerfile +63 -0
- package/docs/architecture/security.md +10 -5
- package/docs/architecture/turn-actor.md +2 -0
- package/docs/desktop-browser-cli.md +45 -4
- 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/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/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- 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/src/gateway-ipc-contracts.ts +20 -0
- 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/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
- package/openapi.yaml +665 -14
- package/package.json +1 -1
- package/scripts/smoke-desktop-browser-cli.ts +10 -26
- package/scripts/smoke-desktop-window-theme.ts +2 -3
- 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__/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__/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__/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-retry-sweep.test.ts +9 -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-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.test.ts +546 -16
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
- package/src/__tests__/conversation-evictor.test.ts +62 -37
- 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-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 +6 -6
- package/src/__tests__/credential-prompt-route.test.ts +35 -3
- package/src/__tests__/cu-unified-flow.test.ts +82 -1
- 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 +25 -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__/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 +1 -1
- package/src/__tests__/interrupt-on-send.test.ts +57 -43
- package/src/__tests__/interrupt-turn-note.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +2 -2
- 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-provider-serializer.test.ts +12 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -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 -0
- 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__/runtime-events-sse-reconnect.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__/secure-keys.test.ts +43 -1
- package/src/__tests__/send-endpoint-busy.test.ts +163 -1
- package/src/__tests__/server-history-render.test.ts +91 -1
- package/src/__tests__/settings-routes.test.ts +50 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
- 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__/surface-completion-in-flight-snapshot.test.ts +2 -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-metadata-plumbing.test.ts +3 -1
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/twilio-routes.test.ts +1 -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 +99 -41
- package/src/api/events/assistant-turn-start.ts +3 -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/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 +31 -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 +6 -0
- package/src/approvals/AGENTS.md +4 -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 -8
- 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__/notifications.test.ts +35 -10
- package/src/cli/commands/browser.help.ts +4 -5
- 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 +6 -1
- package/src/cli/commands/notifications.help.ts +16 -2
- package/src/cli/commands/notifications.ts +30 -8
- package/src/cli/commands/roadmap.help.ts +18 -21
- package/src/cli/commands/roadmap.ts +4 -21
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
- package/src/cli/lib/bundled-marketplace.json +84 -34
- package/src/cli/lib/plugin-marketplace.ts +8 -0
- package/src/cli/lib/publish-plugin.ts +1 -2
- package/src/config/__tests__/default-provider.test.ts +3 -1
- 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/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/profile-text-generation.test.ts +2 -2
- 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 +3 -1
- package/src/config/schemas/mcp.ts +2 -1
- package/src/config/schemas/memory-retrospective.ts +11 -2
- 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 +1 -11
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
- package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
- package/src/daemon/browser-mode-session.test.ts +402 -0
- package/src/daemon/browser-mode-session.ts +186 -0
- 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 +58 -10
- package/src/daemon/conversation-agent-loop.ts +219 -25
- 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 +8 -3
- package/src/daemon/conversation.ts +143 -41
- 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/message-protocol.ts +0 -1
- package/src/daemon/message-provenance.ts +28 -4
- package/src/daemon/mode-session-startup-recovery.ts +23 -0
- package/src/daemon/mode-session-tracking.ts +54 -0
- package/src/daemon/process-message.ts +13 -4
- package/src/daemon/virtual-desktop-context.ts +21 -0
- 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 +76 -68
- package/src/desktop/desktop-automation-lease.ts +41 -50
- 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-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 +11 -122
- package/src/desktop/desktop-stream-bridge.ts +6 -8
- package/src/desktop/desktop-window-theme.ts +5 -25
- package/src/desktop/virtual-desktop-feature.ts +52 -2
- 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 +63 -18
- package/src/mcp/__tests__/tool-caps.test.ts +28 -1
- package/src/mcp/manager.ts +3 -0
- package/src/mcp/tool-caps.ts +12 -4
- 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/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 +1 -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 +0 -23
- 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/signal.ts +4 -19
- package/src/notifications/types.ts +15 -0
- package/src/oauth/connection-resolver.ts +1 -2
- package/src/oauth/oauth-store.ts +1 -3
- package/src/oauth/provider-serializer.ts +7 -0
- package/src/oauth/seed-providers.ts +30 -0
- package/src/onboarding/onboarding-events-store.ts +99 -12
- package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
- package/src/persistence/client-connection-events-store.ts +377 -0
- package/src/persistence/conversation-crud.ts +55 -6
- package/src/persistence/conversation-mode-sessions.test.ts +424 -0
- package/src/persistence/conversation-mode-sessions.ts +460 -0
- package/src/persistence/conversation-queries.ts +6 -19
- package/src/persistence/llm-usage-store.ts +3 -9
- package/src/persistence/message-metadata.ts +25 -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/conversations.ts +67 -0
- package/src/persistence/schema/infrastructure.ts +29 -0
- package/src/persistence/steps.ts +17 -0
- package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
- package/src/plugin-api/effective-context-window.ts +33 -0
- package/src/plugin-api/index.ts +24 -5
- 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/__tests__/archive-removal-framing.test.ts +64 -0
- package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
- package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +78 -22
- package/src/plugins/defaults/memory/context-search/format.ts +51 -7
- 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/types.ts +1 -11
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +12 -21
- package/src/plugins/defaults/memory/graph/tools.ts +35 -64
- package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +5 -0
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +2 -2
- package/src/plugins/defaults/memory/tools.test.ts +124 -9
- package/src/plugins/defaults/memory/tools.ts +38 -11
- package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +165 -27
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +46 -27
- package/src/plugins/defaults/memory/v3/orchestrate.ts +78 -38
- package/src/plugins/defaults/memory/v3/pool-log-store.ts +65 -79
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +14 -5
- package/src/plugins/defaults/memory/v3/pool-select.ts +683 -44
- 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/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 +1 -1
- package/src/providers/jev/client.test.ts +10 -0
- package/src/providers/jev/client.ts +20 -4
- package/src/providers/model-catalog.ts +4 -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/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 +4 -2
- package/src/runtime/actor-trust-resolver.ts +3 -3
- package/src/runtime/agent-wake.ts +1 -1
- 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-reply-router.ts +28 -32
- 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/vbundle-builder.ts +24 -1
- package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +10 -0
- 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 +1 -1
- 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/client-routes.ts +108 -0
- package/src/runtime/routes/conversation-management-routes.ts +4 -1
- package/src/runtime/routes/conversation-routes.ts +113 -27
- 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 +4 -6
- 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/identity-routes.ts +1 -5
- package/src/runtime/routes/image-generation-routes.ts +8 -14
- package/src/runtime/routes/inbound-message-handler.ts +35 -38
- 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 +38 -9
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +2 -5
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -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-providers.ts +7 -0
- package/src/runtime/routes/plugins-routes.ts +6 -0
- package/src/runtime/routes/roadmap-routes.ts +47 -8
- package/src/runtime/routes/secret-routes.ts +1 -1
- 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/worker-control.ts +15 -5
- package/src/security/secure-keys.ts +53 -103
- 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.ts +6 -4
- package/src/tools/browser/browser-execution.ts +22 -59
- 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 +4 -1
- 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/skills/load.ts +2 -1
- package/src/tools/skills/sandbox-runner.ts +11 -2
- 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 +11 -0
- package/src/tools/terminal/safe-env.ts +4 -0
- package/src/tools/terminal/shell.ts +2 -0
- 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/canonicalize-identity.test.ts +21 -0
- package/src/util/canonicalize-identity.ts +16 -0
- package/src/util/errors.ts +13 -3
- package/src/util/provider-error-patterns.ts +3 -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
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 382 creates `client_connection_events`, the durable hub
|
|
3
|
+
* subscribe/dispose ledger used by `assistant clients history`.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Database } from "bun:sqlite";
|
|
7
|
+
import { describe, expect, test } from "bun:test";
|
|
8
|
+
|
|
9
|
+
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
10
|
+
|
|
11
|
+
import { getSqliteFrom } from "../../db-connection.js";
|
|
12
|
+
import * as schema from "../../schema.js";
|
|
13
|
+
import { migrateCreateClientConnectionEvents } from "../382-create-client-connection-events.js";
|
|
14
|
+
|
|
15
|
+
function createTestDb() {
|
|
16
|
+
const sqlite = new Database(":memory:");
|
|
17
|
+
sqlite.exec("PRAGMA journal_mode=WAL");
|
|
18
|
+
return drizzle(sqlite, { schema });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function tableNames(db: ReturnType<typeof createTestDb>): string[] {
|
|
22
|
+
const rows = getSqliteFrom(db)
|
|
23
|
+
.prepare("SELECT name FROM sqlite_master WHERE type = 'table'")
|
|
24
|
+
.all() as { name: string }[];
|
|
25
|
+
return rows.map((row) => row.name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function indexNames(db: ReturnType<typeof createTestDb>): string[] {
|
|
29
|
+
const rows = getSqliteFrom(db)
|
|
30
|
+
.prepare("SELECT name FROM sqlite_master WHERE type = 'index'")
|
|
31
|
+
.all() as { name: string }[];
|
|
32
|
+
return rows.map((row) => row.name);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe("migrateCreateClientConnectionEvents", () => {
|
|
36
|
+
test("creates the table and its lookup indexes", () => {
|
|
37
|
+
const db = createTestDb();
|
|
38
|
+
|
|
39
|
+
migrateCreateClientConnectionEvents(db);
|
|
40
|
+
|
|
41
|
+
expect(tableNames(db)).toContain("client_connection_events");
|
|
42
|
+
expect(indexNames(db)).toContain(
|
|
43
|
+
"idx_client_connection_events_client_occurred",
|
|
44
|
+
);
|
|
45
|
+
expect(indexNames(db)).toContain("idx_client_connection_events_occurred");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("re-running is a no-op", () => {
|
|
49
|
+
const db = createTestDb();
|
|
50
|
+
|
|
51
|
+
migrateCreateClientConnectionEvents(db);
|
|
52
|
+
migrateCreateClientConnectionEvents(db);
|
|
53
|
+
|
|
54
|
+
expect(tableNames(db)).toContain("client_connection_events");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { sql } from "drizzle-orm";
|
|
2
2
|
import {
|
|
3
|
+
check,
|
|
3
4
|
index,
|
|
4
5
|
integer,
|
|
5
6
|
primaryKey,
|
|
@@ -141,6 +142,72 @@ export const conversations = sqliteTable(
|
|
|
141
142
|
],
|
|
142
143
|
);
|
|
143
144
|
|
|
145
|
+
export const conversationModeSessions = sqliteTable(
|
|
146
|
+
"conversation_mode_sessions",
|
|
147
|
+
{
|
|
148
|
+
id: text("id").primaryKey(),
|
|
149
|
+
conversationId: text("conversation_id")
|
|
150
|
+
.notNull()
|
|
151
|
+
.references(() => conversations.id, { onDelete: "cascade" }),
|
|
152
|
+
mode: text("mode", {
|
|
153
|
+
enum: ["computer_use", "browser", "live_vision", "ambient"],
|
|
154
|
+
}).notNull(),
|
|
155
|
+
status: text("status", {
|
|
156
|
+
enum: ["active", "completed", "interrupted"],
|
|
157
|
+
}).notNull(),
|
|
158
|
+
sourceStartedAt: integer("source_started_at").notNull(),
|
|
159
|
+
firstIncludedAt: integer("first_included_at"),
|
|
160
|
+
firstIncludedMessageId: text("first_included_message_id"),
|
|
161
|
+
lastActivityAt: integer("last_activity_at").notNull(),
|
|
162
|
+
lastOwnedMessageId: text("last_owned_message_id"),
|
|
163
|
+
endedAt: integer("ended_at"),
|
|
164
|
+
endReason: text("end_reason"),
|
|
165
|
+
revision: integer("revision").notNull().default(1),
|
|
166
|
+
},
|
|
167
|
+
(table) => [
|
|
168
|
+
check(
|
|
169
|
+
"conversation_mode_sessions_mode_check",
|
|
170
|
+
sql`${table.mode} IN ('computer_use', 'browser', 'live_vision', 'ambient')`,
|
|
171
|
+
),
|
|
172
|
+
check(
|
|
173
|
+
"conversation_mode_sessions_status_check",
|
|
174
|
+
sql`${table.status} IN ('active', 'completed', 'interrupted')`,
|
|
175
|
+
),
|
|
176
|
+
check(
|
|
177
|
+
"conversation_mode_sessions_revision_check",
|
|
178
|
+
sql`${table.revision} > 0`,
|
|
179
|
+
),
|
|
180
|
+
check(
|
|
181
|
+
"conversation_mode_sessions_first_included_boundary_check",
|
|
182
|
+
sql`(${table.firstIncludedAt} IS NULL) = (${table.firstIncludedMessageId} IS NULL)`,
|
|
183
|
+
),
|
|
184
|
+
check(
|
|
185
|
+
"conversation_mode_sessions_terminal_fields_check",
|
|
186
|
+
sql`(
|
|
187
|
+
(${table.status} = 'active' AND ${table.endedAt} IS NULL AND ${table.endReason} IS NULL)
|
|
188
|
+
OR (${table.status} = 'completed' AND ${table.endedAt} IS NOT NULL AND ${table.endReason} IS NOT NULL AND length(${table.endReason}) > 0)
|
|
189
|
+
OR (${table.status} = 'interrupted' AND ${table.endReason} IS NOT NULL AND length(${table.endReason}) > 0)
|
|
190
|
+
)`,
|
|
191
|
+
),
|
|
192
|
+
check(
|
|
193
|
+
"conversation_mode_sessions_end_after_activity_check",
|
|
194
|
+
sql`${table.endedAt} IS NULL OR ${table.endedAt} >= ${table.lastActivityAt}`,
|
|
195
|
+
),
|
|
196
|
+
check(
|
|
197
|
+
"conversation_mode_sessions_activity_after_source_check",
|
|
198
|
+
sql`${table.lastActivityAt} >= ${table.sourceStartedAt}`,
|
|
199
|
+
),
|
|
200
|
+
check(
|
|
201
|
+
"conversation_mode_sessions_first_included_before_activity_check",
|
|
202
|
+
sql`${table.firstIncludedAt} IS NULL OR ${table.firstIncludedAt} <= ${table.lastActivityAt}`,
|
|
203
|
+
),
|
|
204
|
+
index("idx_conversation_mode_sessions_conversation_status").on(
|
|
205
|
+
table.conversationId,
|
|
206
|
+
table.status,
|
|
207
|
+
),
|
|
208
|
+
],
|
|
209
|
+
);
|
|
210
|
+
|
|
144
211
|
export const messages = sqliteTable(
|
|
145
212
|
"messages",
|
|
146
213
|
{
|
|
@@ -359,3 +359,32 @@ export const telemetryEvents = sqliteTable(
|
|
|
359
359
|
index("idx_telemetry_events_conversation_id").on(table.conversationId),
|
|
360
360
|
],
|
|
361
361
|
);
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Append-only hub subscribe/dispose ledger. Support reconstructs client
|
|
365
|
+
* uptime and reconnect flaps from these rows. No message bodies or page
|
|
366
|
+
* URLs: client UUID, interface, close reason, and optional build
|
|
367
|
+
* fingerprint only.
|
|
368
|
+
*/
|
|
369
|
+
export const clientConnectionEvents = sqliteTable(
|
|
370
|
+
"client_connection_events",
|
|
371
|
+
{
|
|
372
|
+
id: text("id").primaryKey(),
|
|
373
|
+
clientId: text("client_id").notNull(),
|
|
374
|
+
interfaceId: text("interface_id").notNull(),
|
|
375
|
+
connectionId: text("connection_id").notNull(),
|
|
376
|
+
reason: text("reason").notNull(),
|
|
377
|
+
occurredAt: integer("occurred_at").notNull(),
|
|
378
|
+
actorPrincipalId: text("actor_principal_id"),
|
|
379
|
+
clientVersion: text("client_version"),
|
|
380
|
+
sseWatchdog: integer("sse_watchdog", { mode: "boolean" }),
|
|
381
|
+
machineName: text("machine_name"),
|
|
382
|
+
},
|
|
383
|
+
(table) => [
|
|
384
|
+
index("idx_client_connection_events_client_occurred").on(
|
|
385
|
+
table.clientId,
|
|
386
|
+
table.occurredAt,
|
|
387
|
+
),
|
|
388
|
+
index("idx_client_connection_events_occurred").on(table.occurredAt),
|
|
389
|
+
],
|
|
390
|
+
);
|
package/src/persistence/steps.ts
CHANGED
|
@@ -488,6 +488,11 @@ import { migrateAddSubagentBudgetStopReason } from "./migrations/377-add-subagen
|
|
|
488
488
|
import { migrateCreateConversationToolSurfaces } from "./migrations/378-create-conversation-tool-surfaces.js";
|
|
489
489
|
import { migrateOAuthProvidersResponseOkField } from "./migrations/379-oauth-providers-response-ok-field.js";
|
|
490
490
|
import { migrateConversationToolSurfacesDelegateIndependentTasks } from "./migrations/380-conversation-tool-surfaces-delegate-independent-tasks.js";
|
|
491
|
+
import {
|
|
492
|
+
downCreateConversationModeSessions,
|
|
493
|
+
migrateCreateConversationModeSessions,
|
|
494
|
+
} from "./migrations/381-create-conversation-mode-sessions.js";
|
|
495
|
+
import { migrateCreateClientConnectionEvents } from "./migrations/382-create-client-connection-events.js";
|
|
491
496
|
import type { MigrationStep } from "./migrations/run-migrations.js";
|
|
492
497
|
|
|
493
498
|
export const migrationSteps: MigrationStep[] = [
|
|
@@ -1632,4 +1637,16 @@ export const migrationSteps: MigrationStep[] = [
|
|
|
1632
1637
|
// step must be checkpointed first.
|
|
1633
1638
|
dependsOn: ["migrateCreateConversationToolSurfaces"],
|
|
1634
1639
|
},
|
|
1640
|
+
{
|
|
1641
|
+
name: "migrateCreateConversationModeSessions",
|
|
1642
|
+
run: migrateCreateConversationModeSessions,
|
|
1643
|
+
rollback: [
|
|
1644
|
+
{
|
|
1645
|
+
version: 58,
|
|
1646
|
+
description: "Create conversation-owned mode session lifecycle records",
|
|
1647
|
+
down: downCreateConversationModeSessions,
|
|
1648
|
+
},
|
|
1649
|
+
],
|
|
1650
|
+
},
|
|
1651
|
+
migrateCreateClientConnectionEvents,
|
|
1635
1652
|
];
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
5
|
+
|
|
6
|
+
import { runInPluginContext } from "../../plugins/plugin-execution-context.js";
|
|
7
|
+
import {
|
|
8
|
+
derivePluginNameFromProcess,
|
|
9
|
+
derivePluginNameFromSkillScriptPath,
|
|
10
|
+
PLUGIN_NAME_ENV,
|
|
11
|
+
readPluginNameFromEnv,
|
|
12
|
+
resolveCallingPluginName,
|
|
13
|
+
} from "../plugin-name-env.js";
|
|
14
|
+
|
|
15
|
+
const pluginsDir = "/tmp/vellum-workspace/plugins";
|
|
16
|
+
|
|
17
|
+
describe("readPluginNameFromEnv", () => {
|
|
18
|
+
test("returns a trimmed install name", () => {
|
|
19
|
+
expect(readPluginNameFromEnv({ [PLUGIN_NAME_ENV]: " sms " })).toBe("sms");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("ignores empty or whitespace-only values", () => {
|
|
23
|
+
expect(readPluginNameFromEnv({ [PLUGIN_NAME_ENV]: "" })).toBeUndefined();
|
|
24
|
+
expect(readPluginNameFromEnv({ [PLUGIN_NAME_ENV]: " " })).toBeUndefined();
|
|
25
|
+
expect(readPluginNameFromEnv({})).toBeUndefined();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("derivePluginNameFromSkillScriptPath", () => {
|
|
30
|
+
test("returns the plugin install name for a scripts path", () => {
|
|
31
|
+
expect(
|
|
32
|
+
derivePluginNameFromSkillScriptPath(
|
|
33
|
+
join(pluginsDir, "sms/skills/sms-setup/scripts/twilio-numbers.ts"),
|
|
34
|
+
pluginsDir,
|
|
35
|
+
),
|
|
36
|
+
).toBe("sms");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("returns the plugin install name for a tools path", () => {
|
|
40
|
+
expect(
|
|
41
|
+
derivePluginNameFromSkillScriptPath(
|
|
42
|
+
join(pluginsDir, "sms/skills/sms-setup/tools/list.ts"),
|
|
43
|
+
pluginsDir,
|
|
44
|
+
),
|
|
45
|
+
).toBe("sms");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("accepts a file URL", () => {
|
|
49
|
+
const filePath = join(
|
|
50
|
+
pluginsDir,
|
|
51
|
+
"sms/skills/sms-setup/scripts/twilio-numbers.ts",
|
|
52
|
+
);
|
|
53
|
+
expect(
|
|
54
|
+
derivePluginNameFromSkillScriptPath(`file://${filePath}`, pluginsDir),
|
|
55
|
+
).toBe("sms");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("rejects a path outside plugins/", () => {
|
|
59
|
+
expect(
|
|
60
|
+
derivePluginNameFromSkillScriptPath(
|
|
61
|
+
"/tmp/other/skills/sms-setup/scripts/twilio-numbers.ts",
|
|
62
|
+
pluginsDir,
|
|
63
|
+
),
|
|
64
|
+
).toBeUndefined();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("rejects a plugin file that is not under scripts/ or tools/", () => {
|
|
68
|
+
expect(
|
|
69
|
+
derivePluginNameFromSkillScriptPath(
|
|
70
|
+
join(pluginsDir, "sms/skills/sms-setup/SKILL.md"),
|
|
71
|
+
pluginsDir,
|
|
72
|
+
),
|
|
73
|
+
).toBeUndefined();
|
|
74
|
+
expect(
|
|
75
|
+
derivePluginNameFromSkillScriptPath(
|
|
76
|
+
join(pluginsDir, "sms/register.ts"),
|
|
77
|
+
pluginsDir,
|
|
78
|
+
),
|
|
79
|
+
).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("rejects a truncated plugins path", () => {
|
|
83
|
+
expect(
|
|
84
|
+
derivePluginNameFromSkillScriptPath(
|
|
85
|
+
join(pluginsDir, "sms/skills/scripts/too-short.ts"),
|
|
86
|
+
pluginsDir,
|
|
87
|
+
),
|
|
88
|
+
).toBeUndefined();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe("derivePluginNameFromProcess", () => {
|
|
93
|
+
test("scans argv for a plugin-resident skill script", () => {
|
|
94
|
+
expect(
|
|
95
|
+
derivePluginNameFromProcess(
|
|
96
|
+
["bun", join(pluginsDir, "sms/skills/sms-setup/scripts/twilio-numbers.ts")],
|
|
97
|
+
"/tmp",
|
|
98
|
+
pluginsDir,
|
|
99
|
+
),
|
|
100
|
+
).toBe("sms");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("resolves a relative argv path against cwd", () => {
|
|
104
|
+
expect(
|
|
105
|
+
derivePluginNameFromProcess(
|
|
106
|
+
["bun", "sms/skills/sms-setup/scripts/twilio-numbers.ts"],
|
|
107
|
+
pluginsDir,
|
|
108
|
+
pluginsDir,
|
|
109
|
+
),
|
|
110
|
+
).toBe("sms");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("skips flags", () => {
|
|
114
|
+
expect(
|
|
115
|
+
derivePluginNameFromProcess(
|
|
116
|
+
["bun", "--hot", join(pluginsDir, "sms/skills/sms-setup/scripts/twilio-numbers.ts")],
|
|
117
|
+
"/tmp",
|
|
118
|
+
pluginsDir,
|
|
119
|
+
),
|
|
120
|
+
).toBe("sms");
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe("resolveCallingPluginName", () => {
|
|
125
|
+
const prior = process.env[PLUGIN_NAME_ENV];
|
|
126
|
+
|
|
127
|
+
afterEach(() => {
|
|
128
|
+
if (prior === undefined) {
|
|
129
|
+
delete process.env[PLUGIN_NAME_ENV];
|
|
130
|
+
} else {
|
|
131
|
+
process.env[PLUGIN_NAME_ENV] = prior;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("prefers AsyncLocalStorage over env", () => {
|
|
136
|
+
process.env[PLUGIN_NAME_ENV] = "from-env";
|
|
137
|
+
const name = runInPluginContext("from-als", () =>
|
|
138
|
+
resolveCallingPluginName(process.env, [], "/tmp"),
|
|
139
|
+
);
|
|
140
|
+
expect(name).toBe("from-als");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("uses VELLUM_PLUGIN_NAME when ALS is empty", () => {
|
|
144
|
+
expect(
|
|
145
|
+
resolveCallingPluginName({ [PLUGIN_NAME_ENV]: "sms" }, [], "/tmp"),
|
|
146
|
+
).toBe("sms");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("falls back to the process entry path", () => {
|
|
150
|
+
expect(
|
|
151
|
+
resolveCallingPluginName(
|
|
152
|
+
{},
|
|
153
|
+
["bun", join(pluginsDir, "sms/skills/sms-setup/scripts/twilio-numbers.ts")],
|
|
154
|
+
"/tmp",
|
|
155
|
+
pluginsDir,
|
|
156
|
+
),
|
|
157
|
+
).toBe("sms");
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe("resolveCallingPluginName real child", () => {
|
|
162
|
+
test("recovers the plugin name from a scripts path without env", async () => {
|
|
163
|
+
const workspace = mkdtempSync(join(tmpdir(), "plugin-name-child-"));
|
|
164
|
+
const scriptDir = join(
|
|
165
|
+
workspace,
|
|
166
|
+
"plugins/sms/skills/sms-setup/scripts",
|
|
167
|
+
);
|
|
168
|
+
mkdirSync(scriptDir, { recursive: true });
|
|
169
|
+
const helper = join(
|
|
170
|
+
import.meta.dir,
|
|
171
|
+
"..",
|
|
172
|
+
"plugin-name-env.ts",
|
|
173
|
+
);
|
|
174
|
+
const scriptPath = join(scriptDir, "echo-plugin-name.ts");
|
|
175
|
+
writeFileSync(
|
|
176
|
+
scriptPath,
|
|
177
|
+
`import { resolveCallingPluginName } from ${JSON.stringify(helper)};
|
|
178
|
+
console.log(JSON.stringify({ name: resolveCallingPluginName() ?? null }));
|
|
179
|
+
`,
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
const child = Bun.spawn(
|
|
184
|
+
["bun", scriptPath],
|
|
185
|
+
{
|
|
186
|
+
cwd: scriptDir,
|
|
187
|
+
env: {
|
|
188
|
+
PATH: process.env.PATH,
|
|
189
|
+
HOME: process.env.HOME,
|
|
190
|
+
VELLUM_WORKSPACE_DIR: workspace,
|
|
191
|
+
},
|
|
192
|
+
stdout: "pipe",
|
|
193
|
+
stderr: "pipe",
|
|
194
|
+
},
|
|
195
|
+
);
|
|
196
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
197
|
+
new Response(child.stdout).text(),
|
|
198
|
+
new Response(child.stderr).text(),
|
|
199
|
+
child.exited,
|
|
200
|
+
]);
|
|
201
|
+
expect(stderr).toBe("");
|
|
202
|
+
expect(exitCode).toBe(0);
|
|
203
|
+
expect(JSON.parse(stdout.trim())).toEqual({ name: "sms" });
|
|
204
|
+
} finally {
|
|
205
|
+
rmSync(workspace, { recursive: true, force: true });
|
|
206
|
+
}
|
|
207
|
+
}, 15_000);
|
|
208
|
+
|
|
209
|
+
test("recovers the plugin name from VELLUM_PLUGIN_NAME without a plugin path", async () => {
|
|
210
|
+
const workspace = mkdtempSync(join(tmpdir(), "plugin-name-env-child-"));
|
|
211
|
+
const scriptDir = join(workspace, "scratch");
|
|
212
|
+
mkdirSync(scriptDir, { recursive: true });
|
|
213
|
+
const helper = join(import.meta.dir, "..", "plugin-name-env.ts");
|
|
214
|
+
const scriptPath = join(scriptDir, "echo-plugin-name.ts");
|
|
215
|
+
writeFileSync(
|
|
216
|
+
scriptPath,
|
|
217
|
+
`import { resolveCallingPluginName } from ${JSON.stringify(helper)};
|
|
218
|
+
console.log(JSON.stringify({ name: resolveCallingPluginName() ?? null }));
|
|
219
|
+
`,
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
const child = Bun.spawn(
|
|
224
|
+
["bun", scriptPath],
|
|
225
|
+
{
|
|
226
|
+
cwd: scriptDir,
|
|
227
|
+
env: {
|
|
228
|
+
PATH: process.env.PATH,
|
|
229
|
+
HOME: process.env.HOME,
|
|
230
|
+
VELLUM_WORKSPACE_DIR: workspace,
|
|
231
|
+
VELLUM_PLUGIN_NAME: "sms",
|
|
232
|
+
},
|
|
233
|
+
stdout: "pipe",
|
|
234
|
+
stderr: "pipe",
|
|
235
|
+
},
|
|
236
|
+
);
|
|
237
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
238
|
+
new Response(child.stdout).text(),
|
|
239
|
+
new Response(child.stderr).text(),
|
|
240
|
+
child.exited,
|
|
241
|
+
]);
|
|
242
|
+
expect(stderr).toBe("");
|
|
243
|
+
expect(exitCode).toBe(0);
|
|
244
|
+
expect(JSON.parse(stdout.trim())).toEqual({ name: "sms" });
|
|
245
|
+
} finally {
|
|
246
|
+
rmSync(workspace, { recursive: true, force: true });
|
|
247
|
+
}
|
|
248
|
+
}, 15_000);
|
|
249
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { resolveEffectiveContextWindow } from "../config/llm-context-resolution.js";
|
|
2
|
+
import type { ResolveCallSiteOpts } from "../config/llm-resolver.js";
|
|
3
|
+
import { getConfig } from "../config/loader.js";
|
|
4
|
+
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
5
|
+
|
|
6
|
+
export interface EffectiveContextWindowInfo {
|
|
7
|
+
provider: string;
|
|
8
|
+
model: string;
|
|
9
|
+
maxInputTokens: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type EffectiveContextWindowOptions = Pick<
|
|
13
|
+
ResolveCallSiteOpts,
|
|
14
|
+
"overrideProfile" | "forceOverrideProfile" | "selectionSeed"
|
|
15
|
+
>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the provider, model, and effective input limit for one configured
|
|
19
|
+
* call site. The result applies both the workspace override and the selected
|
|
20
|
+
* model's catalog limit, using the same profile-selection options accepted by
|
|
21
|
+
* {@link getConfiguredProvider}.
|
|
22
|
+
*/
|
|
23
|
+
export function getEffectiveContextWindow(
|
|
24
|
+
callSite: LLMCallSite,
|
|
25
|
+
options: EffectiveContextWindowOptions = {},
|
|
26
|
+
): EffectiveContextWindowInfo {
|
|
27
|
+
const { provider, model, maxInputTokens } = resolveEffectiveContextWindow({
|
|
28
|
+
llm: getConfig().llm,
|
|
29
|
+
callSite,
|
|
30
|
+
...options,
|
|
31
|
+
});
|
|
32
|
+
return { provider, model, maxInputTokens };
|
|
33
|
+
}
|
package/src/plugin-api/index.ts
CHANGED
|
@@ -33,9 +33,11 @@
|
|
|
33
33
|
* - {@link assistantEventHub} — the assistant's pub/sub hub for runtime events
|
|
34
34
|
* - {@link getModelProfiles} — list the workspace inference profiles a plugin
|
|
35
35
|
* can route to (e.g. a model router building its category → profile map)
|
|
36
|
-
* - {@link getConfiguredProvider}
|
|
36
|
+
* - {@link getConfiguredProvider}: resolve a {@link Provider} for a call site
|
|
37
37
|
* (optionally overriding the profile) and run inference through the
|
|
38
|
-
* workspace's configured profiles and credentials
|
|
38
|
+
* workspace's configured profiles and credentials, with no plugin-supplied API key
|
|
39
|
+
* - {@link getEffectiveContextWindow}: resolve that call site's provider,
|
|
40
|
+
* model, and effective maximum input size
|
|
39
41
|
*
|
|
40
42
|
* - {@link InitContext} — passed to `init` hook at bootstrap
|
|
41
43
|
* - {@link ShutdownContext} — passed to `shutdown` hook at teardown
|
|
@@ -169,10 +171,12 @@ export { publishEvent } from "./publish-event.js";
|
|
|
169
171
|
// `inputModalities.image` override winning when set (mix profiles are
|
|
170
172
|
// vision-capable if any arm is). Returns false when nothing resolves.
|
|
171
173
|
export { doesSupportVision } from "./vision-support.js";
|
|
172
|
-
// Resolve a stored credential to its plaintext value
|
|
173
|
-
// `assistant credentials reveal` prints
|
|
174
|
+
// Resolve a stored credential to its plaintext value (the same value
|
|
175
|
+
// `assistant credentials reveal` prints) from a UUID or a "service/field"
|
|
174
176
|
// reference. When a plugin is in context, resolution is scoped to credentials
|
|
175
|
-
// whose service matches the plugin's
|
|
177
|
+
// whose service matches the plugin's runtime name. A plugin-resident skill
|
|
178
|
+
// script or skill-tool child presents a daemon-issued invocation grant and is
|
|
179
|
+
// scoped the same way. Outside any plugin context or grant the resolver is
|
|
176
180
|
// unscoped. Throws CredentialResolutionError when the ref does not resolve, the
|
|
177
181
|
// store is unreachable, or the credential is out of the plugin's scope.
|
|
178
182
|
export {
|
|
@@ -218,6 +222,11 @@ export { resolveOauthCallbackUrl } from "../inbound/oauth-callback-url.js";
|
|
|
218
222
|
// float the chosen profile above the call-site layers when the plugin must
|
|
219
223
|
// run on a specific profile regardless of workspace tuning.
|
|
220
224
|
export { getConfiguredProvider } from "../providers/provider-send-message.js";
|
|
225
|
+
export type {
|
|
226
|
+
EffectiveContextWindowInfo,
|
|
227
|
+
EffectiveContextWindowOptions,
|
|
228
|
+
} from "./effective-context-window.js";
|
|
229
|
+
export { getEffectiveContextWindow } from "./effective-context-window.js";
|
|
221
230
|
// Resolve an image/file block's media `source` to its bytes as inline base64,
|
|
222
231
|
// whether the source is inline base64 or a persisted workspace reference
|
|
223
232
|
// (attachment-store row or a file on disk). Returns null when a reference can no
|
|
@@ -401,6 +410,16 @@ export { persistSystemCard } from "./system-card.js";
|
|
|
401
410
|
// what makes that true. Host tools and plugin tools share this one guard.
|
|
402
411
|
export type { CancellableToolContext } from "./tool-cancellation.js";
|
|
403
412
|
export { throwIfCancelled } from "./tool-cancellation.js";
|
|
413
|
+
// Tool input from a Zod schema: derive the advertised `input_schema` from the
|
|
414
|
+
// schema the tool parses its input with, so what the model is told and what
|
|
415
|
+
// the tool accepts share one source. The host validates built-in tools'
|
|
416
|
+
// input centrally; a plugin tool parses its own, and answers a failed parse
|
|
417
|
+
// with `invalidToolInputResult` so its message reads the same as the host's.
|
|
418
|
+
export {
|
|
419
|
+
invalidToolInputResult,
|
|
420
|
+
nullAsOmitted,
|
|
421
|
+
toToolInputSchema,
|
|
422
|
+
} from "../tools/shared/zod-tool-schema.js";
|
|
404
423
|
// Synthesize text to speech through the assistant's globally configured TTS
|
|
405
424
|
// provider (ElevenLabs, Fish Audio, etc.). Plugins that need voice output —
|
|
406
425
|
// e.g. a meeting bot speaking into a live call — use this instead of managing
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a child process learns which plugin it is running as.
|
|
3
|
+
*
|
|
4
|
+
* In-process plugin hooks, tools, and routes use AsyncLocalStorage
|
|
5
|
+
* ({@link getCurrentPluginName}). A bash or skill-sandbox child does not
|
|
6
|
+
* inherit that store. Those children recover the install-directory basename
|
|
7
|
+
* from `VELLUM_PLUGIN_NAME` (injected after env sanitization) or from the
|
|
8
|
+
* entry script path under `plugins/<service>/skills/<skill>/{scripts,tools}/`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
|
|
14
|
+
import { getCurrentPluginName } from "../plugins/plugin-execution-context.js";
|
|
15
|
+
import { getWorkspacePluginsDir } from "../util/platform.js";
|
|
16
|
+
|
|
17
|
+
export const PLUGIN_NAME_ENV = "VELLUM_PLUGIN_NAME";
|
|
18
|
+
|
|
19
|
+
const SKILL_SCRIPT_ROOTS = new Set(["scripts", "tools"]);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Read a plugin install-directory name from the process environment.
|
|
23
|
+
* Empty or whitespace-only values are ignored.
|
|
24
|
+
*/
|
|
25
|
+
export function readPluginNameFromEnv(
|
|
26
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
27
|
+
): string | undefined {
|
|
28
|
+
const raw = env[PLUGIN_NAME_ENV];
|
|
29
|
+
if (typeof raw !== "string") {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const trimmed = raw.trim();
|
|
33
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* If `filePath` is a skill script or tool under an installed plugin, return
|
|
38
|
+
* that plugin's install-directory basename (the runtime service name).
|
|
39
|
+
*
|
|
40
|
+
* Expected layout:
|
|
41
|
+
* `plugins/<service>/skills/<skill-id>/scripts|tools/<file>`.
|
|
42
|
+
*/
|
|
43
|
+
export function derivePluginNameFromSkillScriptPath(
|
|
44
|
+
filePath: string,
|
|
45
|
+
pluginsDir: string = getWorkspacePluginsDir(),
|
|
46
|
+
): string | undefined {
|
|
47
|
+
if (filePath.length === 0) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
let resolved = filePath;
|
|
51
|
+
if (filePath.startsWith("file:")) {
|
|
52
|
+
try {
|
|
53
|
+
resolved = fileURLToPath(filePath);
|
|
54
|
+
} catch {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!isAbsolute(resolved)) {
|
|
59
|
+
resolved = resolve(process.cwd(), resolved);
|
|
60
|
+
}
|
|
61
|
+
const pluginsRoot = resolve(pluginsDir);
|
|
62
|
+
const rel = relative(pluginsRoot, resolved);
|
|
63
|
+
if (rel.length === 0 || rel.startsWith("..") || isAbsolute(rel)) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const parts = rel.split(sep).filter((part) => part.length > 0);
|
|
67
|
+
if (parts.length < 5) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
const [service, skillsSeg, skillId, root] = parts;
|
|
71
|
+
if (
|
|
72
|
+
service === undefined ||
|
|
73
|
+
skillsSeg !== "skills" ||
|
|
74
|
+
skillId === undefined ||
|
|
75
|
+
root === undefined ||
|
|
76
|
+
!SKILL_SCRIPT_ROOTS.has(root)
|
|
77
|
+
) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
return service;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Scan argv for a plugin-resident skill script path, resolving relative
|
|
85
|
+
* entries against `cwd`.
|
|
86
|
+
*/
|
|
87
|
+
export function derivePluginNameFromProcess(
|
|
88
|
+
argv: readonly string[] = process.argv,
|
|
89
|
+
cwd: string = process.cwd(),
|
|
90
|
+
pluginsDir: string = getWorkspacePluginsDir(),
|
|
91
|
+
): string | undefined {
|
|
92
|
+
for (const candidate of argv.slice(1)) {
|
|
93
|
+
if (typeof candidate !== "string" || candidate.length === 0) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (candidate.startsWith("-")) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const absolute = isAbsolute(candidate)
|
|
100
|
+
? candidate
|
|
101
|
+
: resolve(cwd, candidate);
|
|
102
|
+
const name = derivePluginNameFromSkillScriptPath(absolute, pluginsDir);
|
|
103
|
+
if (name !== undefined) {
|
|
104
|
+
return name;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Plugin identity for credential scoping: in-process AsyncLocalStorage,
|
|
112
|
+
* then the injected env var, then the process entry script path.
|
|
113
|
+
*/
|
|
114
|
+
export function resolveCallingPluginName(
|
|
115
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
116
|
+
argv: readonly string[] = process.argv,
|
|
117
|
+
cwd: string = process.cwd(),
|
|
118
|
+
pluginsDir: string = getWorkspacePluginsDir(),
|
|
119
|
+
): string | undefined {
|
|
120
|
+
return (
|
|
121
|
+
getCurrentPluginName() ??
|
|
122
|
+
readPluginNameFromEnv(env) ??
|
|
123
|
+
derivePluginNameFromProcess(argv, cwd, pluginsDir)
|
|
124
|
+
);
|
|
125
|
+
}
|