@vellumai/assistant 0.6.4 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +5 -0
- package/AGENTS.md +9 -1
- package/ARCHITECTURE.md +43 -49
- package/Dockerfile +17 -3
- package/README.md +3 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +283 -0
- package/bun.lock +8 -3
- package/docs/architecture/integrations.md +33 -59
- package/docs/architecture/memory.md +25 -30
- package/docs/architecture/security.md +19 -18
- package/docs/browser-use-architecture-phase2.md +63 -20
- package/docs/error-handling.md +111 -0
- package/docs/plugins.md +761 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +2 -1
- package/examples/plugins/echo/README.md +132 -0
- package/examples/plugins/echo/package.json +17 -0
- package/examples/plugins/echo/register.ts +187 -0
- package/knip.json +9 -2
- package/node_modules/@vellumai/ces-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
- package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
- package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
- package/node_modules/@vellumai/credential-storage/package.json +2 -2
- package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
- package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
- package/node_modules/@vellumai/egress-proxy/package.json +2 -2
- package/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
- package/openapi.yaml +334 -78
- package/package.json +6 -3
- package/scripts/generate-openapi.ts +50 -11
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
- package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
- package/src/__tests__/agent-loop.test.ts +112 -1
- package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
- package/src/__tests__/anthropic-provider.test.ts +171 -2
- package/src/__tests__/app-compiler.test.ts +57 -0
- package/src/__tests__/approval-cascade.test.ts +36 -10
- package/src/__tests__/approval-routes-http.test.ts +134 -10
- package/src/__tests__/assistant-attachments.test.ts +44 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +1 -0
- package/src/__tests__/avatar-generator.test.ts +4 -2
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
- package/src/__tests__/browser-skill-endstate.test.ts +51 -182
- package/src/__tests__/btw-routes.test.ts +47 -1
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/call-controller.test.ts +1 -2
- package/src/__tests__/call-site-routing-provider.test.ts +214 -0
- package/src/__tests__/catalog-cache.test.ts +96 -4
- package/src/__tests__/channel-approval-routes.test.ts +4 -4
- package/src/__tests__/channel-reply-delivery.test.ts +300 -2
- package/src/__tests__/checker.test.ts +870 -655
- package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/compaction-events.test.ts +501 -0
- package/src/__tests__/compaction-pipeline.test.ts +210 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +181 -0
- package/src/__tests__/compaction-timeout-recovery.test.ts +262 -0
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/config-analysis.test.ts +11 -28
- package/src/__tests__/config-loader-backfill.test.ts +174 -0
- package/src/__tests__/config-loader-corrupt.test.ts +183 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
- package/src/__tests__/config-model-image-provider.test.ts +110 -0
- package/src/__tests__/config-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +440 -114
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +72 -73
- package/src/__tests__/contacts-tools.test.ts +26 -0
- package/src/__tests__/contacts-write.test.ts +4 -4
- package/src/__tests__/context-overflow-policy.test.ts +7 -7
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +883 -4
- package/src/__tests__/conversation-abort-tool-results.test.ts +32 -15
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +86 -46
- package/src/__tests__/conversation-agent-loop.test.ts +435 -216
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +36 -10
- package/src/__tests__/conversation-error.test.ts +37 -6
- package/src/__tests__/conversation-history-web-search.test.ts +7 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +34 -12
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pairing.test.ts +174 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +32 -15
- package/src/__tests__/conversation-process-callsite.test.ts +309 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +44 -21
- package/src/__tests__/conversation-queue.test.ts +68 -38
- package/src/__tests__/conversation-routes-disk-view.test.ts +36 -7
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2877 -152
- package/src/__tests__/conversation-runtime-workspace.test.ts +35 -50
- package/src/__tests__/conversation-seed-composer.test.ts +2 -2
- package/src/__tests__/conversation-skill-tools.test.ts +12 -146
- package/src/__tests__/conversation-slash-queue.test.ts +39 -19
- package/src/__tests__/conversation-slash-unknown.test.ts +53 -16
- package/src/__tests__/conversation-speed-override.test.ts +36 -12
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
- package/src/__tests__/conversation-title-service.test.ts +118 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +41 -2
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
- package/src/__tests__/conversation-unread-route.test.ts +2 -2
- package/src/__tests__/conversation-usage.test.ts +4 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +33 -9
- package/src/__tests__/conversation-workspace-injection.test.ts +46 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +46 -15
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-health-service.test.ts +78 -9
- package/src/__tests__/credential-security-invariants.test.ts +5 -2
- package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
- package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
- package/src/__tests__/credential-vault-unit.test.ts +135 -19
- package/src/__tests__/credentials-cli.test.ts +1 -9
- package/src/__tests__/cross-provider-web-search.test.ts +84 -0
- package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
- package/src/__tests__/delete-propagation.test.ts +437 -0
- package/src/__tests__/dm-backfill.test.ts +417 -0
- package/src/__tests__/dm-persistence.test.ts +227 -0
- package/src/__tests__/edit-propagation.test.ts +280 -0
- package/src/__tests__/empty-response-pipeline.test.ts +305 -0
- package/src/__tests__/ephemeral-permissions.test.ts +93 -3
- package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
- package/src/__tests__/estimator-calibration.test.ts +213 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +29 -10
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- package/src/__tests__/first-greeting.test.ts +247 -5
- package/src/__tests__/gemini-provider.test.ts +0 -3
- package/src/__tests__/guardian-grant-minting.test.ts +8 -0
- package/src/__tests__/headless-browser-interactions.test.ts +1 -1
- package/src/__tests__/headless-browser-mode.test.ts +57 -0
- package/src/__tests__/heartbeat-service.test.ts +96 -15
- package/src/__tests__/history-repair-pipeline.test.ts +399 -0
- package/src/__tests__/host-browser-e2e-cloud.test.ts +307 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +3 -3
- package/src/__tests__/host-proxy-interface.test.ts +36 -2
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/image-credentials.test.ts +137 -0
- package/src/__tests__/image-service-dispatcher.test.ts +186 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/injector-chain.test.ts +526 -0
- package/src/__tests__/intent-routing.test.ts +1 -66
- package/src/__tests__/llm-call-pipeline.test.ts +285 -0
- package/src/__tests__/llm-catalog-parity.test.ts +174 -0
- package/src/__tests__/llm-context-normalization.test.ts +121 -0
- package/src/__tests__/llm-resolver.test.ts +214 -0
- package/src/__tests__/llm-schema.test.ts +223 -0
- package/src/__tests__/managed-proxy-context.test.ts +6 -2
- package/src/__tests__/media-generate-image.test.ts +119 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +401 -0
- package/src/__tests__/memory-upsert-concurrency.test.ts +1 -0
- package/src/__tests__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-import-from-url.test.ts +621 -0
- package/src/__tests__/model-intents.test.ts +11 -83
- package/src/__tests__/notification-broadcaster.test.ts +3 -3
- package/src/__tests__/notification-decision-fallback.test.ts +0 -10
- package/src/__tests__/notification-decision-identity.test.ts +0 -9
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
- package/src/__tests__/notification-decision-strategy.test.ts +0 -11
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +108 -0
- package/src/__tests__/oauth-apps-routes.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +14 -12
- package/src/__tests__/oauth-connect-orchestrator.test.ts +4 -13
- package/src/__tests__/oauth-provider-serializer.test.ts +6 -4
- package/src/__tests__/oauth-provider-visibility.test.ts +3 -5
- package/src/__tests__/oauth-providers-routes.test.ts +3 -2
- package/src/__tests__/oauth-store.test.ts +46 -78
- package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
- package/src/__tests__/onboarding-template-contract.test.ts +16 -64
- package/src/__tests__/openai-image-service.test.ts +368 -0
- package/src/__tests__/openai-provider.test.ts +7 -0
- package/src/__tests__/openai-responses-provider.test.ts +396 -0
- package/src/__tests__/openrouter-provider-only.test.ts +135 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
- package/src/__tests__/overflow-reduce-pipeline.test.ts +676 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +1 -25
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
- package/src/__tests__/persistence-pipeline.test.ts +377 -0
- package/src/__tests__/persona-resolver.test.ts +13 -13
- package/src/__tests__/pipeline-runner.test.ts +565 -0
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/platform.test.ts +5 -2
- package/src/__tests__/plugin-bootstrap.test.ts +483 -0
- package/src/__tests__/plugin-registry.test.ts +273 -0
- package/src/__tests__/plugin-route-contribution.test.ts +288 -0
- package/src/__tests__/plugin-skill-contribution.test.ts +367 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +286 -0
- package/src/__tests__/plugin-types.test.ts +320 -0
- package/src/__tests__/pricing.test.ts +93 -14
- package/src/__tests__/profiler-routes.test.ts +1 -1
- package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
- package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
- package/src/__tests__/provider-error-scenarios.test.ts +135 -6
- package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
- package/src/__tests__/provider-registry-ollama.test.ts +1 -2
- package/src/__tests__/proxy-approval-callback.test.ts +69 -9
- package/src/__tests__/reaction-persistence.test.ts +561 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +0 -2
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
- package/src/__tests__/risk-classifier-parity.test.ts +230 -0
- package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
- package/src/__tests__/schedule-routes.test.ts +131 -1
- package/src/__tests__/scheduler-recurrence.test.ts +14 -70
- package/src/__tests__/scheduler-reuse-conversation.test.ts +10 -50
- package/src/__tests__/secret-detection-handler.test.ts +0 -10
- package/src/__tests__/secret-ingress-http.test.ts +28 -0
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
- package/src/__tests__/secret-scanner-executor.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +29 -1
- package/src/__tests__/server-history-render.test.ts +31 -0
- package/src/__tests__/shell-identity.test.ts +0 -134
- package/src/__tests__/shell-parser-property.test.ts +13 -13
- package/src/__tests__/skill-cache-store.test.ts +182 -0
- package/src/__tests__/skills.test.ts +19 -33
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-skill.test.ts +3 -8
- package/src/__tests__/starter-bundle.test.ts +35 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
- package/src/__tests__/suggestion-routes.test.ts +259 -3
- package/src/__tests__/system-prompt.test.ts +22 -35
- package/src/__tests__/task-memory-cleanup.test.ts +1 -0
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/task-scheduler.test.ts +3 -15
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/test-preload.ts +11 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/title-generate-pipeline.test.ts +224 -0
- package/src/__tests__/token-estimate-pipeline.test.ts +431 -0
- package/src/__tests__/tool-error-pipeline.test.ts +244 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +431 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -8
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
- package/src/__tests__/tool-executor-shell-integration.test.ts +7 -10
- package/src/__tests__/tool-executor.test.ts +201 -94
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -110
- package/src/__tests__/trust-store.test.ts +442 -109
- package/src/__tests__/update-bulletin-job.test.ts +389 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
- package/src/__tests__/user-plugin-loader.test.ts +191 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
- package/src/__tests__/voice-session-bridge.test.ts +39 -0
- package/src/__tests__/volume-security-guard.test.ts +3 -2
- package/src/__tests__/web-search-history.test.ts +337 -0
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
- package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
- package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
- package/src/__tests__/workspace-migration-046-seed-conversation-starters-callsite.test.ts +185 -0
- package/src/__tests__/workspace-migration-049-release-notes-default-sonnet.test.ts +100 -0
- package/src/__tests__/workspace-migration-050-seed-main-agent-opus-callsite.test.ts +171 -0
- package/src/__tests__/workspace-migration-051-seed-conversation-summarization-callsite.test.ts +252 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +99 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +22 -16
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/loop.ts +545 -115
- package/src/approvals/__tests__/guardian-feed-event.test.ts +304 -0
- package/src/approvals/guardian-request-resolvers.ts +80 -0
- package/src/avatar/resvg-lazy.test.ts +136 -0
- package/src/avatar/resvg-lazy.ts +82 -9
- package/src/avatar/traits-png-sync.ts +21 -1
- package/src/backup/__tests__/backup-worker.test.ts +2 -13
- package/src/backup/backup-worker.ts +3 -15
- package/src/browser/__tests__/operations.test.ts +163 -0
- package/src/browser/identifiers.ts +51 -0
- package/src/browser/operations.ts +660 -0
- package/src/browser/types.ts +81 -0
- package/src/bundler/app-compiler.ts +84 -1
- package/src/calls/call-state.ts +2 -2
- package/src/calls/guardian-question-copy.ts +2 -2
- package/src/calls/telephony-stt-routing.ts +1 -1
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/channels/__tests__/types.test.ts +3 -3
- package/src/channels/types.ts +6 -4
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/__tests__/notifications.test.ts +87 -211
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- package/src/cli/commands/__tests__/backup.test.ts +1 -1
- package/src/cli/commands/__tests__/browser.test.ts +554 -0
- package/src/cli/commands/__tests__/cache.test.ts +623 -0
- package/src/cli/commands/__tests__/email-list.test.ts +6 -0
- package/src/cli/commands/__tests__/email-send.test.ts +93 -1
- package/src/cli/commands/__tests__/image-generation.test.ts +886 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +463 -0
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
- package/src/cli/commands/__tests__/task.test.ts +913 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +606 -0
- package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
- package/src/cli/commands/__tests__/ui.test.ts +1215 -0
- package/src/cli/commands/__tests__/watchers.test.ts +716 -0
- package/src/cli/commands/attachment.ts +182 -0
- package/src/cli/commands/backup.ts +2 -2
- package/src/cli/commands/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/clients.ts +138 -0
- package/src/cli/commands/completions.ts +2 -12
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +69 -8
- package/src/cli/commands/email.ts +234 -194
- package/src/cli/commands/image-generation.ts +299 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- package/src/cli/commands/notifications.ts +68 -103
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
- package/src/cli/commands/oauth/connect.ts +2 -2
- package/src/cli/commands/oauth/providers.ts +176 -8
- package/src/cli/commands/oauth/status.ts +46 -36
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
- package/src/cli/commands/skills.ts +3 -4
- package/src/cli/commands/stt.ts +339 -0
- package/src/cli/commands/task.ts +795 -0
- package/src/cli/commands/trust.ts +50 -19
- package/src/cli/commands/tts.ts +273 -0
- package/src/cli/commands/ui.ts +670 -0
- package/src/cli/commands/watchers.ts +509 -0
- package/src/cli/lib/daemon-credential-client.ts +0 -19
- package/src/cli/program.ts +39 -24
- package/src/cli.ts +0 -37
- package/src/config/__tests__/backup-schema.test.ts +7 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +10 -10
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +66 -87
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +28 -51
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +22 -40
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -1
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +23 -39
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +207 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +20 -1
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +69 -12
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
- package/src/config/bundled-skills/schedule/SKILL.md +8 -3
- package/src/config/bundled-skills/schedule/TOOLS.json +15 -7
- package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +59 -0
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-tool-registry.ts +0 -190
- package/src/config/env.ts +7 -2
- package/src/config/feature-flag-registry.json +42 -10
- package/src/config/llm-resolver.ts +128 -0
- package/src/config/loader.ts +194 -10
- package/src/config/raw-config-utils.ts +30 -2
- package/src/config/sanitize-for-transfer.ts +35 -0
- package/src/config/schema.ts +49 -41
- package/src/config/schemas/analysis.ts +3 -22
- package/src/config/schemas/backup.ts +1 -1
- package/src/config/schemas/calls.ts +0 -4
- package/src/config/schemas/conversations.ts +16 -0
- package/src/config/schemas/filing.ts +2 -7
- package/src/config/schemas/heartbeat.ts +0 -5
- package/src/config/schemas/inference.ts +3 -23
- package/src/config/schemas/llm.ts +317 -0
- package/src/config/schemas/memory-processing.ts +1 -9
- package/src/config/schemas/notifications.ts +4 -11
- package/src/config/schemas/platform.ts +3 -9
- package/src/config/schemas/security.ts +33 -0
- package/src/config/schemas/services.ts +9 -4
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/schemas/tts.ts +64 -0
- package/src/config/schemas/updates.ts +1 -1
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skill-state.ts +6 -2
- package/src/config/skills.ts +96 -7
- package/src/context/__tests__/compact-prompt.test.ts +63 -0
- package/src/context/__tests__/microcompact.test.ts +805 -0
- package/src/context/estimator-calibration.ts +136 -0
- package/src/context/microcompact.ts +443 -0
- package/src/context/prompts/compact.md +26 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/tool-result-truncation.ts +3 -63
- package/src/context/window-manager.ts +417 -39
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/executable-discovery.ts +19 -8
- package/src/credential-execution/process-manager.test.ts +109 -0
- package/src/credential-execution/process-manager.ts +65 -2
- package/src/credential-health/credential-health-service.ts +19 -6
- package/src/daemon/__tests__/conversation-feed-event.test.ts +317 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +4 -12
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +14 -15
- package/src/daemon/approval-generators.ts +29 -4
- package/src/daemon/assistant-attachments.ts +24 -13
- package/src/daemon/classifier.ts +2 -2
- package/src/daemon/config-watcher.ts +0 -3
- package/src/daemon/context-overflow-policy.ts +4 -13
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +162 -34
- package/src/daemon/conversation-agent-loop.ts +1282 -599
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +36 -1
- package/src/daemon/conversation-history.ts +10 -19
- package/src/daemon/conversation-lifecycle.ts +59 -17
- package/src/daemon/conversation-messaging.ts +73 -4
- package/src/daemon/conversation-notifiers.ts +2 -110
- package/src/daemon/conversation-process.ts +24 -11
- package/src/daemon/conversation-queue-manager.ts +3 -0
- package/src/daemon/conversation-runtime-assembly.ts +1063 -211
- package/src/daemon/conversation-slash.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +389 -1
- package/src/daemon/conversation-tool-setup.ts +51 -9
- package/src/daemon/conversation-usage.ts +1 -1
- package/src/daemon/conversation.ts +197 -64
- package/src/daemon/external-plugins-bootstrap.ts +478 -0
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- package/src/daemon/first-greeting.ts +191 -14
- package/src/daemon/guardian-action-generators.ts +34 -14
- package/src/daemon/handlers/config-model.test.ts +86 -0
- package/src/daemon/handlers/config-model.ts +65 -12
- package/src/daemon/handlers/conversations.ts +9 -2
- package/src/daemon/handlers/shared.ts +39 -11
- package/src/daemon/handlers/skills.ts +7 -3
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/lifecycle.ts +109 -82
- package/src/daemon/message-types/computer-use.ts +2 -34
- package/src/daemon/message-types/conversations.ts +63 -0
- package/src/daemon/message-types/messages.ts +21 -1
- package/src/daemon/message-types/trust.ts +0 -2
- package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
- package/src/daemon/pkb-context-tracker.test.ts +169 -0
- package/src/daemon/pkb-context-tracker.ts +125 -0
- package/src/daemon/pkb-reminder-builder.test.ts +70 -0
- package/src/daemon/pkb-reminder-builder.ts +31 -0
- package/src/daemon/providers-setup.ts +6 -0
- package/src/daemon/server.ts +122 -12
- package/src/daemon/shutdown-handlers.ts +2 -12
- package/src/daemon/tool-side-effects.ts +14 -65
- package/src/daemon/web-search-history.ts +126 -0
- package/src/events/domain-events.ts +0 -1
- package/src/filing/filing-service.ts +9 -10
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +160 -0
- package/src/heartbeat/heartbeat-service.ts +99 -28
- package/src/home/__tests__/feed-population-integration.test.ts +312 -0
- package/src/home/__tests__/feed-scheduler.test.ts +39 -11
- package/src/home/__tests__/rollup-producer.test.ts +44 -0
- package/src/home/assistant-feed-authoring.ts +4 -0
- package/src/home/emit-feed-event.ts +11 -0
- package/src/home/feed-scheduler.ts +20 -4
- package/src/home/feed-types.ts +97 -4
- package/src/home/relationship-state-writer.ts +2 -2
- package/src/home/rewrite-command-preview.ts +66 -0
- package/src/home/rollup-producer.ts +34 -5
- package/src/home/suggested-prompts.ts +101 -0
- package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
- package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
- package/src/ipc/__tests__/socket-path.test.ts +34 -0
- package/src/ipc/__tests__/task-ipc.test.ts +577 -0
- package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
- package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
- package/src/ipc/cli-client.ts +2 -1
- package/src/ipc/cli-server.ts +26 -8
- package/src/ipc/gateway-client.ts +6 -3
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +63 -0
- package/src/ipc/routes/browser.ts +97 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/get-contact.ts +16 -0
- package/src/ipc/routes/index.ts +31 -1
- package/src/ipc/routes/list-clients.ts +31 -0
- package/src/ipc/routes/merge-contacts.ts +17 -0
- package/src/ipc/routes/notification.ts +133 -0
- package/src/ipc/routes/rename-conversation.ts +59 -0
- package/src/ipc/routes/search-contacts.ts +19 -0
- package/src/ipc/routes/task-queue.ts +226 -0
- package/src/ipc/routes/task.ts +173 -0
- package/src/ipc/routes/ui-request.ts +50 -0
- package/src/ipc/routes/upsert-contact.ts +25 -0
- package/src/ipc/routes/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +76 -0
- package/src/media/app-icon-generator.ts +23 -46
- package/src/media/avatar-router.ts +26 -41
- package/src/media/gemini-image-service.ts +8 -41
- package/src/media/image-credentials.ts +73 -0
- package/src/media/image-service.ts +85 -0
- package/src/media/openai-image-service.ts +131 -0
- package/src/media/types.ts +46 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
- package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
- package/src/memory/admin.ts +18 -0
- package/src/memory/conversation-analyze-job.ts +14 -13
- package/src/memory/conversation-attention-store.ts +13 -6
- package/src/memory/conversation-crud.ts +133 -3
- package/src/memory/conversation-group-migration.ts +38 -6
- package/src/memory/conversation-queries.ts +57 -4
- package/src/memory/conversation-title-service.ts +32 -4
- package/src/memory/db-init.ts +10 -0
- package/src/memory/embedding-backend.ts +1 -1
- package/src/memory/embedding-gemini.test.ts +41 -2
- package/src/memory/embedding-gemini.ts +6 -1
- package/src/memory/graph/bootstrap.test.ts +282 -0
- package/src/memory/graph/bootstrap.ts +8 -5
- package/src/memory/graph/compaction.ts +299 -0
- package/src/memory/graph/consolidation.ts +4 -4
- package/src/memory/graph/conversation-graph-memory.ts +89 -29
- package/src/memory/graph/extraction.test.ts +272 -2
- package/src/memory/graph/extraction.ts +183 -53
- package/src/memory/graph/graph-search.test.ts +93 -0
- package/src/memory/graph/graph-search.ts +4 -1
- package/src/memory/graph/inspect.ts +2 -2
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.test.ts +459 -0
- package/src/memory/graph/retriever.ts +237 -48
- package/src/memory/graph/store.ts +41 -0
- package/src/memory/graph/tool-handlers.ts +27 -0
- package/src/memory/graph/tools.ts +6 -1
- package/src/memory/indexer.ts +5 -5
- package/src/memory/job-handlers/conversation-starters.ts +23 -20
- package/src/memory/job-handlers/summarization.ts +2 -2
- package/src/memory/job-utils.ts +7 -1
- package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
- package/src/memory/jobs/embed-pkb-file.ts +54 -0
- package/src/memory/jobs-store.ts +44 -3
- package/src/memory/jobs-worker.ts +4 -0
- package/src/memory/migrations/041-approval-prompt-ts-tracker.ts +26 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
- package/src/memory/migrations/149-oauth-tables.ts +1 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
- package/src/memory/migrations/223-schedule-script-column.ts +11 -0
- package/src/memory/migrations/224-oauth-providers-managed-service-is-paid.ts +24 -0
- package/src/memory/migrations/225-oauth-providers-available-scopes.ts +13 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/pkb/pkb-index.test.ts +369 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +252 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +499 -0
- package/src/memory/pkb/pkb-search.ts +159 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.test.ts +60 -0
- package/src/memory/qdrant-client.ts +147 -1
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/schema/oauth.ts +4 -1
- package/src/memory/slack-thread-store.ts +37 -0
- package/src/messaging/providers/gmail/adapter.ts +6 -16
- package/src/messaging/providers/gmail/client.ts +22 -0
- package/src/messaging/providers/gmail/types.ts +7 -0
- package/src/messaging/providers/slack/adapter.ts +14 -2
- package/src/messaging/providers/slack/backfill.test.ts +257 -0
- package/src/messaging/providers/slack/backfill.ts +101 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
- package/src/messaging/providers/slack/message-metadata.ts +123 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1421 -0
- package/src/messaging/providers/slack/render-transcript.ts +501 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/conversation-pairing.ts +78 -19
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/decision-engine.ts +3 -9
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/notifications/signal.ts +1 -2
- package/src/oauth/AGENTS.md +1 -1
- package/src/oauth/__tests__/identity-verifier.test.ts +2 -1
- package/src/oauth/connect-orchestrator.ts +8 -34
- package/src/oauth/connect-types.ts +6 -10
- package/src/oauth/manual-token-connection.ts +23 -0
- package/src/oauth/oauth-store.ts +31 -14
- package/src/oauth/platform-connection.test.ts +47 -0
- package/src/oauth/platform-connection.ts +15 -5
- package/src/oauth/provider-serializer.ts +6 -1
- package/src/oauth/seed-providers.ts +56 -106
- package/src/outbound-proxy/http-forwarder.ts +9 -0
- package/src/permissions/approval-policy.test.ts +1223 -0
- package/src/permissions/approval-policy.ts +309 -0
- package/src/permissions/arg-parser.test.ts +161 -0
- package/src/permissions/arg-parser.ts +141 -0
- package/src/permissions/bash-risk-classifier.test.ts +1620 -0
- package/src/permissions/bash-risk-classifier.ts +950 -0
- package/src/permissions/checker.ts +348 -711
- package/src/permissions/command-registry.test.ts +774 -0
- package/src/permissions/command-registry.ts +1005 -0
- package/src/permissions/defaults.ts +28 -79
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/gateway-threshold-reader.ts +196 -0
- package/src/permissions/prompter.ts +4 -0
- package/src/permissions/risk-types.ts +262 -0
- package/src/permissions/schedule-risk-classifier.test.ts +129 -0
- package/src/permissions/schedule-risk-classifier.ts +85 -0
- package/src/permissions/secret-prompter.ts +53 -2
- package/src/permissions/shell-identity.ts +2 -42
- package/src/permissions/skill-risk-classifier.test.ts +311 -0
- package/src/permissions/skill-risk-classifier.ts +214 -0
- package/src/permissions/trust-client.ts +52 -25
- package/src/permissions/trust-store-interface.ts +1 -6
- package/src/permissions/trust-store.ts +161 -62
- package/src/permissions/types.ts +25 -14
- package/src/permissions/web-risk-classifier.test.ts +170 -0
- package/src/permissions/web-risk-classifier.ts +89 -0
- package/src/permissions/workspace-policy.ts +9 -19
- package/src/platform/client.ts +19 -1
- package/src/plugins/defaults/circuit-breaker.ts +146 -0
- package/src/plugins/defaults/compaction.ts +145 -0
- package/src/plugins/defaults/empty-response.ts +126 -0
- package/src/plugins/defaults/history-repair.ts +85 -0
- package/src/plugins/defaults/index.ts +116 -0
- package/src/plugins/defaults/injectors.ts +491 -0
- package/src/plugins/defaults/llm-call.ts +82 -0
- package/src/plugins/defaults/memory-retrieval.ts +226 -0
- package/src/plugins/defaults/overflow-reduce.ts +181 -0
- package/src/plugins/defaults/persistence.ts +129 -0
- package/src/plugins/defaults/title-generate.ts +95 -0
- package/src/plugins/defaults/token-estimate.ts +104 -0
- package/src/plugins/defaults/tool-error.ts +126 -0
- package/src/plugins/defaults/tool-execute.ts +89 -0
- package/src/plugins/defaults/tool-result-truncate.ts +88 -0
- package/src/plugins/pipeline.ts +316 -0
- package/src/plugins/plugin-skill-contributions.ts +292 -0
- package/src/plugins/registry.ts +241 -0
- package/src/plugins/types.ts +1134 -0
- package/src/plugins/user-loader.ts +177 -0
- package/src/prompts/persona-resolver.ts +3 -3
- package/src/prompts/system-prompt.ts +19 -20
- package/src/prompts/templates/BOOTSTRAP.md +27 -77
- package/src/prompts/templates/SOUL.md +2 -2
- package/src/prompts/update-bulletin-job.ts +190 -0
- package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
- package/src/providers/__tests__/retry-callsite.test.ts +424 -0
- package/src/providers/anthropic/client.ts +183 -14
- package/src/providers/call-site-routing.ts +71 -0
- package/src/providers/gemini/client.ts +65 -2
- package/src/providers/managed-proxy/constants.ts +2 -1
- package/src/providers/model-catalog.ts +524 -33
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/openai/chat-completions-provider.ts +57 -1
- package/src/providers/openai/responses-provider.ts +86 -9
- package/src/providers/openrouter/client.ts +80 -9
- package/src/providers/provider-env-vars.ts +56 -0
- package/src/providers/provider-send-message.ts +22 -5
- package/src/providers/ratelimit.ts +4 -0
- package/src/providers/registry.ts +19 -8
- package/src/providers/retry.ts +174 -39
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +61 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +57 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
- package/src/providers/speech-to-text/provider-catalog.ts +17 -0
- package/src/providers/speech-to-text/resolve.ts +7 -0
- package/src/providers/speech-to-text/xai-realtime.test.ts +646 -0
- package/src/providers/speech-to-text/xai-realtime.ts +821 -0
- package/src/providers/speech-to-text/xai.test.ts +155 -0
- package/src/providers/speech-to-text/xai.ts +97 -0
- package/src/providers/types.ts +93 -3
- package/src/runtime/AGENTS.md +27 -18
- package/src/runtime/__tests__/agent-wake.test.ts +43 -2
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +3 -3
- package/src/runtime/__tests__/client-registry.test.ts +293 -0
- package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
- package/src/runtime/agent-wake.ts +63 -22
- package/src/runtime/auth/route-policy.ts +4 -0
- package/src/runtime/btw-sidechain.ts +13 -3
- package/src/runtime/channel-reply-delivery.ts +106 -2
- package/src/runtime/client-registry.ts +261 -0
- package/src/runtime/decision-token.ts +116 -0
- package/src/runtime/gateway-client.ts +2 -2
- package/src/runtime/http-router.ts +32 -0
- package/src/runtime/http-server.ts +129 -9
- package/src/runtime/http-types.ts +23 -3
- package/src/runtime/interactive-ui.ts +362 -0
- package/src/runtime/invite-instruction-generator.ts +2 -2
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
- package/src/runtime/migrations/gcs-signed-url.ts +162 -0
- package/src/runtime/migrations/vbundle-builder.ts +1 -22
- package/src/runtime/migrations/vbundle-importer.ts +154 -9
- package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
- package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
- package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
- package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
- package/src/runtime/migrations/vbundle-validator.ts +15 -6
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +78 -0
- package/src/runtime/routes/approval-routes.ts +29 -17
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
- package/src/runtime/routes/avatar-routes.ts +20 -4
- package/src/runtime/routes/browser-extension-pair-routes.ts +27 -8
- package/src/runtime/routes/btw-routes.ts +1 -4
- package/src/runtime/routes/conversation-management-routes.ts +20 -2
- package/src/runtime/routes/conversation-routes.ts +351 -138
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +6 -4
- package/src/runtime/routes/events-routes.ts +16 -0
- package/src/runtime/routes/guardian-approval-interception.ts +33 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
- package/src/runtime/routes/home-feed-routes.ts +120 -2
- package/src/runtime/routes/inbound-message-handler.ts +987 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
- package/src/runtime/routes/integrations/slack/channel.ts +25 -3
- package/src/runtime/routes/llm-context-normalization.ts +23 -1
- package/src/runtime/routes/memory-item-routes.test.ts +1 -0
- package/src/runtime/routes/migration-routes.ts +720 -127
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +284 -0
- package/src/runtime/routes/playground/__tests__/guard.test.ts +80 -0
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +294 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +271 -0
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +202 -0
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +309 -0
- package/src/runtime/routes/playground/__tests__/state.test.ts +224 -0
- package/src/runtime/routes/playground/conversation-not-found.ts +29 -0
- package/src/runtime/routes/playground/deps.ts +56 -0
- package/src/runtime/routes/playground/force-compact.ts +73 -0
- package/src/runtime/routes/playground/guard.ts +37 -0
- package/src/runtime/routes/playground/index.ts +28 -0
- package/src/runtime/routes/playground/inject-failures.ts +159 -0
- package/src/runtime/routes/playground/reset-circuit.ts +115 -0
- package/src/runtime/routes/playground/seed-conversation.ts +139 -0
- package/src/runtime/routes/playground/seeded-conversations.ts +78 -0
- package/src/runtime/routes/playground/state.ts +78 -0
- package/src/runtime/routes/schedule-routes.ts +89 -8
- package/src/runtime/routes/settings-routes.ts +4 -2
- package/src/runtime/routes/trust-rules-routes.ts +30 -14
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/routes/work-items-routes.ts +3 -2
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
- package/src/runtime/services/analyze-conversation.ts +12 -16
- package/src/runtime/skill-route-registry.ts +97 -15
- package/src/schedule/run-script.ts +68 -0
- package/src/schedule/schedule-store.ts +7 -1
- package/src/schedule/scheduler.ts +56 -8
- package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
- package/src/security/__tests__/untrusted-content.test.ts +109 -0
- package/src/security/oauth2.ts +98 -35
- package/src/security/secure-keys.ts +7 -8
- package/src/security/token-manager.ts +27 -13
- package/src/security/untrusted-content.ts +102 -0
- package/src/skills/catalog-cache.ts +35 -9
- package/src/skills/catalog-install.ts +31 -3
- package/src/skills/skill-cache-store.ts +97 -0
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
- package/src/stt/daemon-batch-transcriber.ts +33 -0
- package/src/stt/stt-stream-session.ts +8 -1
- package/src/stt/types.ts +5 -1
- package/src/subagent/manager.ts +41 -13
- package/src/tasks/ephemeral-permissions.ts +9 -4
- package/src/telemetry/usage-telemetry-reporter.ts +27 -5
- package/src/tools/browser/__tests__/browser-status.test.ts +234 -2
- package/src/tools/browser/browser-execution.ts +150 -54
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +230 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +146 -3
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +54 -3
- package/src/tools/browser/cdp-client/factory.ts +15 -4
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +9 -4
- package/src/tools/executor.ts +129 -73
- package/src/tools/filesystem/write.ts +52 -0
- package/src/tools/host-terminal/host-shell.ts +45 -5
- package/src/tools/memory/register.test.ts +185 -0
- package/src/tools/memory/register.ts +3 -1
- package/src/tools/network/script-proxy/session-manager.ts +37 -1
- package/src/tools/network/web-fetch.ts +20 -10
- package/src/tools/network/web-search.ts +19 -4
- package/src/tools/permission-checker.ts +116 -46
- package/src/tools/policy-context.ts +29 -8
- package/src/tools/registry.ts +195 -6
- package/src/tools/schedule/create.ts +23 -8
- package/src/tools/schedule/update.ts +3 -1
- package/src/tools/secret-detection-handler.ts +0 -51
- package/src/tools/side-effects.ts +0 -11
- package/src/tools/skills/execute.ts +2 -2
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/system/avatar-generator.ts +6 -2
- package/src/tools/terminal/backends/native.ts +51 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +1 -0
- package/src/tools/tool-manifest.ts +6 -21
- package/src/tools/types.ts +40 -5
- package/src/tools/verification-control-plane-policy.ts +1 -1
- package/src/tts/__tests__/provider-adapters.test.ts +240 -13
- package/src/tts/provider-catalog.ts +18 -0
- package/src/tts/providers/index.ts +2 -0
- package/src/tts/providers/xai-provider.ts +224 -0
- package/src/tts/types.ts +46 -0
- package/src/types/tar-stream.d.ts +66 -0
- package/src/util/json.ts +17 -0
- package/src/util/platform.ts +9 -4
- package/src/util/pricing.ts +41 -8
- package/src/watcher/engine.ts +1 -1
- package/src/watcher/providers/google-calendar.ts +134 -8
- package/src/watcher/providers/outlook-calendar.ts +42 -2
- package/src/workspace/git-service.ts +23 -4
- package/src/workspace/migrations/006-services-config.ts +2 -4
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +2 -3
- package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
- package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +56 -0
- package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
- package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
- package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
- package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +108 -0
- package/src/workspace/migrations/047-remove-watch-callsites.ts +54 -0
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +81 -0
- package/src/workspace/migrations/049-release-notes-default-sonnet.ts +80 -0
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +86 -0
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +128 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +28 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- package/tsconfig.json +1 -1
- package/hook-templates/debug-prompt-logger/hook.json +0 -7
- package/hook-templates/debug-prompt-logger/run.sh +0 -66
- package/src/__tests__/context-overflow-approval.test.ts +0 -156
- package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
- package/src/__tests__/gmail-archive-gate.test.ts +0 -246
- package/src/__tests__/gmail-preferences.test.ts +0 -117
- package/src/__tests__/hooks-blocking.test.ts +0 -178
- package/src/__tests__/hooks-cli.test.ts +0 -182
- package/src/__tests__/hooks-config.test.ts +0 -108
- package/src/__tests__/hooks-discovery.test.ts +0 -211
- package/src/__tests__/hooks-integration.test.ts +0 -196
- package/src/__tests__/hooks-manager.test.ts +0 -226
- package/src/__tests__/hooks-runner.test.ts +0 -175
- package/src/__tests__/hooks-settings.test.ts +0 -160
- package/src/__tests__/hooks-templates.test.ts +0 -169
- package/src/__tests__/hooks-ts-runner.test.ts +0 -170
- package/src/__tests__/hooks-watch.test.ts +0 -112
- package/src/__tests__/notification-schedule-dedup.test.ts +0 -213
- package/src/__tests__/oauth-scope-policy.test.ts +0 -180
- package/src/__tests__/outlook-attachments.test.ts +0 -301
- package/src/__tests__/outlook-automation-tools.test.ts +0 -425
- package/src/__tests__/outlook-categories.test.ts +0 -212
- package/src/__tests__/outlook-compose-tools.test.ts +0 -325
- package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
- package/src/__tests__/outlook-follow-up.test.ts +0 -196
- package/src/__tests__/outlook-trash.test.ts +0 -77
- package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
- package/src/__tests__/send-notification-tool.test.ts +0 -83
- package/src/__tests__/update-bulletin-format.test.ts +0 -181
- package/src/__tests__/update-bulletin-state.test.ts +0 -135
- package/src/__tests__/update-bulletin.test.ts +0 -478
- package/src/__tests__/update-template-contract.test.ts +0 -29
- package/src/cli/commands/doctor.ts +0 -341
- package/src/cli/commands/shotgun.ts +0 -266
- package/src/config/bundled-skills/browser/SKILL.md +0 -88
- package/src/config/bundled-skills/browser/TOOLS.json +0 -516
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
- package/src/config/bundled-skills/conversations/SKILL.md +0 -20
- package/src/config/bundled-skills/conversations/TOOLS.json +0 -23
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +0 -66
- package/src/config/bundled-skills/gmail/SKILL.md +0 -221
- package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
- package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
- package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
- package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/google-calendar/types.ts +0 -97
- package/src/config/bundled-skills/heartbeat/SKILL.md +0 -43
- package/src/config/bundled-skills/notifications/SKILL.md +0 -40
- package/src/config/bundled-skills/notifications/TOOLS.json +0 -80
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -152
- package/src/config/bundled-skills/notifications/tools/shared.ts +0 -13
- package/src/config/bundled-skills/outlook/SKILL.md +0 -196
- package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
- package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
- package/src/config/bundled-skills/screen-watch/SKILL.md +0 -27
- package/src/config/bundled-skills/screen-watch/TOOLS.json +0 -35
- package/src/config/bundled-skills/screen-watch/tools/start-screen-watch.ts +0 -12
- package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -84
- package/src/config/bundled-skills/slack/SKILL.md +0 -108
- package/src/config/bundled-skills/tasks/SKILL.md +0 -37
- package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
- package/src/config/bundled-skills/tasks/icon.svg +0 -34
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
- package/src/config/bundled-skills/watcher/SKILL.md +0 -31
- package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
- package/src/daemon/context-overflow-approval.ts +0 -52
- package/src/daemon/watch-handler.ts +0 -399
- package/src/hooks/cli.ts +0 -253
- package/src/hooks/config.ts +0 -100
- package/src/hooks/discovery.ts +0 -135
- package/src/hooks/manager.ts +0 -179
- package/src/hooks/runner.ts +0 -117
- package/src/hooks/templates.ts +0 -77
- package/src/hooks/types.ts +0 -75
- package/src/oauth/scope-policy.ts +0 -89
- package/src/prompts/templates/UPDATES.md +0 -50
- package/src/prompts/update-bulletin-format.ts +0 -85
- package/src/prompts/update-bulletin-state.ts +0 -58
- package/src/prompts/update-bulletin-template-path.ts +0 -13
- package/src/prompts/update-bulletin.ts +0 -139
- package/src/runtime/gateway-internal-client.ts +0 -94
- package/src/runtime/routes/watch-routes.ts +0 -156
- package/src/shared/provider-env-vars.ts +0 -19
- package/src/signals/shotgun.ts +0 -203
- package/src/tools/watch/screen-watch.ts +0 -144
- package/src/tools/watch/watch-state.ts +0 -142
- package/src/tools/watcher/create.ts +0 -86
- package/src/tools/watcher/delete.ts +0 -36
- package/src/tools/watcher/digest.ts +0 -54
- package/src/tools/watcher/list.ts +0 -83
- package/src/tools/watcher/update.ts +0 -71
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin pipeline runner.
|
|
3
|
+
*
|
|
4
|
+
* A "pipeline" is a named chain of {@link Middleware}s wrapped around a
|
|
5
|
+
* terminal handler (the original behavior that existed before plugins). The
|
|
6
|
+
* runner composes the chain in onion order, runs it under an optional
|
|
7
|
+
* per-pipeline timeout, and emits one structured log record per invocation
|
|
8
|
+
* covering success, error, and timeout uniformly.
|
|
9
|
+
*
|
|
10
|
+
* Design doc: `.private/plans/agent-plugin-system.md` (PR 12 notes).
|
|
11
|
+
*
|
|
12
|
+
* Semantics:
|
|
13
|
+
* - Onion composition — the first element of `middlewares` is the outermost
|
|
14
|
+
* wrapper; it sees the request first and the response last. Terminal runs
|
|
15
|
+
* in the middle.
|
|
16
|
+
* - Strict-fail — there is NO `try/catch` around user middleware. Errors,
|
|
17
|
+
* including `PluginTimeoutError` from a breached budget, propagate to the
|
|
18
|
+
* caller. The `finally` block only handles logging, never error recovery.
|
|
19
|
+
* - Timeout — when `timeoutMs` is a finite number, the invocation races a
|
|
20
|
+
* timer. A timeout rejection is a `PluginTimeoutError` carrying the
|
|
21
|
+
* pipeline name, the best-known offending plugin (from `ctx.pluginName`),
|
|
22
|
+
* and elapsed ms. When `timeoutMs` is `null`/`undefined`, no timer is
|
|
23
|
+
* armed — pipelines like `llmCall` and `toolExecute` rely on downstream
|
|
24
|
+
* timeouts instead.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import type { Logger } from "pino";
|
|
28
|
+
|
|
29
|
+
import { getLogger } from "../util/logger.js";
|
|
30
|
+
import {
|
|
31
|
+
type Middleware,
|
|
32
|
+
type PipelineName,
|
|
33
|
+
PluginTimeoutError,
|
|
34
|
+
type TurnContext,
|
|
35
|
+
} from "./types.js";
|
|
36
|
+
|
|
37
|
+
// Side-effect import: register every first-party default plugin at module
|
|
38
|
+
// load so downstream consumers (production bootstrap AND tests that skip
|
|
39
|
+
// `bootstrapPlugins()`) observe a fully-populated registry by default.
|
|
40
|
+
// Every code path that calls `runPipeline` imports this module, so by the
|
|
41
|
+
// time the first pipeline runs the defaults are already in place. User
|
|
42
|
+
// plugins load via `loadUserPlugins()` inside `bootstrapPlugins()` (which
|
|
43
|
+
// runs AFTER all static side-effect imports), so the onion ordering
|
|
44
|
+
// (defaults inner, user middleware outer) across all 14 pipelines is
|
|
45
|
+
// preserved in production.
|
|
46
|
+
import "./defaults/index.js";
|
|
47
|
+
|
|
48
|
+
const moduleLogger = getLogger("plugin-pipeline");
|
|
49
|
+
|
|
50
|
+
// ─── Default timeouts ───────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Default per-pipeline timeout budgets in milliseconds. A value of `null`
|
|
54
|
+
* means the runner does NOT arm a timer — the pipeline relies on its
|
|
55
|
+
* downstream for budgeting (e.g. `llmCall` defers to provider-level HTTP
|
|
56
|
+
* timeouts; `toolExecute` defers to the per-tool timeout already enforced
|
|
57
|
+
* by `ToolExecutor`).
|
|
58
|
+
*
|
|
59
|
+
* Callers pass the appropriate entry as `runPipeline`'s `timeoutMs` argument.
|
|
60
|
+
* The design doc locks these numbers in; do not tweak without coordinating
|
|
61
|
+
* a design update.
|
|
62
|
+
*/
|
|
63
|
+
export const DEFAULT_TIMEOUTS: Record<PipelineName, number | null> = {
|
|
64
|
+
turn: null,
|
|
65
|
+
llmCall: null,
|
|
66
|
+
toolExecute: null,
|
|
67
|
+
memoryRetrieval: null,
|
|
68
|
+
historyRepair: null,
|
|
69
|
+
tokenEstimate: null,
|
|
70
|
+
compaction: null,
|
|
71
|
+
overflowReduce: null,
|
|
72
|
+
persistence: null,
|
|
73
|
+
titleGenerate: null,
|
|
74
|
+
toolResultTruncate: null,
|
|
75
|
+
emptyResponse: null,
|
|
76
|
+
toolError: null,
|
|
77
|
+
circuitBreaker: null,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// ─── Composition ────────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Compose an ordered list of {@link Middleware}s around a terminal handler
|
|
84
|
+
* using onion semantics. The first element of `middlewares` is the outermost
|
|
85
|
+
* layer.
|
|
86
|
+
*
|
|
87
|
+
* The returned function accepts `(args, ctx)` and runs the entire chain:
|
|
88
|
+
* ```
|
|
89
|
+
* middlewares[0] → middlewares[1] → ... → terminal → ... → middlewares[1] → middlewares[0]
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* Middlewares that never call `next` short-circuit the chain — the terminal
|
|
93
|
+
* and any deeper middleware are never invoked. Middlewares that throw abort
|
|
94
|
+
* the chain; the error flows back out through any outer middleware unchanged
|
|
95
|
+
* (no internal try/catch).
|
|
96
|
+
*/
|
|
97
|
+
export function composeMiddleware<A, R>(
|
|
98
|
+
middlewares: ReadonlyArray<Middleware<A, R>>,
|
|
99
|
+
terminal: (args: A) => Promise<R>,
|
|
100
|
+
): (args: A, ctx: TurnContext) => Promise<R> {
|
|
101
|
+
return (args, ctx) => {
|
|
102
|
+
// Walk back-to-front, wrapping each middleware around `next`. The last
|
|
103
|
+
// middleware in the array wraps `terminal`; earlier entries wrap the
|
|
104
|
+
// accumulated chain so they execute first.
|
|
105
|
+
let next: (args: A) => Promise<R> = terminal;
|
|
106
|
+
for (let i = middlewares.length - 1; i >= 0; i--) {
|
|
107
|
+
const mw = middlewares[i]!;
|
|
108
|
+
const downstream = next;
|
|
109
|
+
next = (innerArgs: A) => mw(innerArgs, downstream, ctx);
|
|
110
|
+
}
|
|
111
|
+
return next(args);
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ─── Abort-signal linking ───────────────────────────────────────────────────
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Return a shallow-cloned `args` object where every `AbortSignal`-typed
|
|
119
|
+
* top-level property is swapped for a signal linked to `internalController`.
|
|
120
|
+
*
|
|
121
|
+
* "Linked" here means: the returned signal aborts when either the caller's
|
|
122
|
+
* original signal aborts OR `internalController` aborts (e.g. the pipeline
|
|
123
|
+
* timer fires). The caller's args are never mutated.
|
|
124
|
+
*
|
|
125
|
+
* When `args` carries no `AbortSignal` property, the original object is
|
|
126
|
+
* returned unchanged — pipelines whose terminals don't consume a signal
|
|
127
|
+
* (e.g. `persistence`, `tokenEstimate`) see identical behavior to before.
|
|
128
|
+
* The return value's `cleanup()` tears down any `addEventListener("abort",
|
|
129
|
+
* ...)` handlers attached to the caller's signal so a pipeline that
|
|
130
|
+
* completes successfully doesn't leak listeners on the caller's controller.
|
|
131
|
+
*/
|
|
132
|
+
function linkAbortSignal<A>(
|
|
133
|
+
args: A,
|
|
134
|
+
internalController: AbortController,
|
|
135
|
+
): { args: A; cleanup: () => void } {
|
|
136
|
+
if (args === null || typeof args !== "object") {
|
|
137
|
+
return { args, cleanup: () => {} };
|
|
138
|
+
}
|
|
139
|
+
const abortListeners: Array<{
|
|
140
|
+
signal: AbortSignal;
|
|
141
|
+
listener: () => void;
|
|
142
|
+
}> = [];
|
|
143
|
+
const record = args as Record<string, unknown>;
|
|
144
|
+
const patched: Record<string, unknown> = { ...record };
|
|
145
|
+
let swappedAny = false;
|
|
146
|
+
for (const key of Object.keys(record)) {
|
|
147
|
+
const value = record[key];
|
|
148
|
+
if (value instanceof AbortSignal) {
|
|
149
|
+
swappedAny = true;
|
|
150
|
+
if (value.aborted) {
|
|
151
|
+
// Caller already aborted — propagate immediately so the inner call
|
|
152
|
+
// sees the abort without waiting for the listener to fire.
|
|
153
|
+
internalController.abort();
|
|
154
|
+
} else {
|
|
155
|
+
const listener = () => internalController.abort();
|
|
156
|
+
value.addEventListener("abort", listener, { once: true });
|
|
157
|
+
abortListeners.push({ signal: value, listener });
|
|
158
|
+
}
|
|
159
|
+
patched[key] = internalController.signal;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const cleanup = () => {
|
|
163
|
+
for (const { signal, listener } of abortListeners) {
|
|
164
|
+
signal.removeEventListener("abort", listener);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
return { args: (swappedAny ? patched : args) as A, cleanup };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ─── Runner ─────────────────────────────────────────────────────────────────
|
|
171
|
+
|
|
172
|
+
type PipelineLogRecord = {
|
|
173
|
+
event: "plugin.pipeline";
|
|
174
|
+
pipeline: PipelineName;
|
|
175
|
+
chain: ReadonlyArray<string>;
|
|
176
|
+
durationMs: number;
|
|
177
|
+
outcome: "success" | "error" | "timeout";
|
|
178
|
+
pluginName?: string;
|
|
179
|
+
errorName?: string;
|
|
180
|
+
errorMessage?: string;
|
|
181
|
+
errorStack?: string;
|
|
182
|
+
timeoutMs?: number;
|
|
183
|
+
requestId: string;
|
|
184
|
+
conversationId: string;
|
|
185
|
+
turnIndex?: number;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Best-effort detection of a pino-compatible logger on the `TurnContext`.
|
|
190
|
+
*
|
|
191
|
+
* `TurnContext` intentionally doesn't require a logger slot — most code paths
|
|
192
|
+
* use the module-level logger. Some callers (notably plugin-scoped pipelines
|
|
193
|
+
* in later PRs) may attach a child logger via `(ctx as any).logger`. We type
|
|
194
|
+
* the field loosely to avoid coupling `TurnContext` to pino.
|
|
195
|
+
*/
|
|
196
|
+
function selectLogger(ctx: TurnContext): Logger {
|
|
197
|
+
const maybe = (ctx as { logger?: unknown }).logger;
|
|
198
|
+
if (maybe && typeof maybe === "object" && "info" in maybe) {
|
|
199
|
+
return maybe as Logger;
|
|
200
|
+
}
|
|
201
|
+
return moduleLogger;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Execute a named pipeline: compose middleware, run it under an optional
|
|
206
|
+
* timeout, and emit one structured log record covering success, error, or
|
|
207
|
+
* timeout uniformly.
|
|
208
|
+
*
|
|
209
|
+
* @param name The pipeline identifier. Used for telemetry and error
|
|
210
|
+
* attribution.
|
|
211
|
+
* @param middlewares Ordered list of middlewares to wrap around `terminal`.
|
|
212
|
+
* Names for the log `chain` are pulled from `Function.name`
|
|
213
|
+
* (empty strings are kept so length always matches).
|
|
214
|
+
* @param terminal The original behavior. Runs when all middlewares call
|
|
215
|
+
* `next`.
|
|
216
|
+
* @param args Pipeline-specific input payload.
|
|
217
|
+
* @param ctx Per-turn context. May carry an optional `logger` slot;
|
|
218
|
+
* otherwise the module logger is used.
|
|
219
|
+
* @param timeoutMs Deadline in milliseconds. `null`/`undefined` disables
|
|
220
|
+
* the timer entirely (inherits downstream timeouts).
|
|
221
|
+
*
|
|
222
|
+
* @throws {PluginTimeoutError} When `timeoutMs` is non-null and the chain
|
|
223
|
+
* exceeds the budget. `ctx.pluginName` (if set) is attached as the
|
|
224
|
+
* offending plugin.
|
|
225
|
+
* @throws Any error produced by user middleware or the terminal — flows
|
|
226
|
+
* through unchanged.
|
|
227
|
+
*/
|
|
228
|
+
export async function runPipeline<A, R>(
|
|
229
|
+
name: PipelineName,
|
|
230
|
+
middlewares: ReadonlyArray<Middleware<A, R>>,
|
|
231
|
+
terminal: (args: A) => Promise<R>,
|
|
232
|
+
args: A,
|
|
233
|
+
ctx: TurnContext,
|
|
234
|
+
timeoutMs?: number | null,
|
|
235
|
+
): Promise<R> {
|
|
236
|
+
const logger = selectLogger(ctx);
|
|
237
|
+
const chain = middlewares.map((m) => m.name || "anonymous");
|
|
238
|
+
const composed = composeMiddleware(middlewares, terminal);
|
|
239
|
+
const start = performance.now();
|
|
240
|
+
|
|
241
|
+
let outcome: "success" | "error" | "timeout" = "success";
|
|
242
|
+
let thrown: unknown = undefined;
|
|
243
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
if (typeof timeoutMs === "number" && Number.isFinite(timeoutMs)) {
|
|
247
|
+
const budget = timeoutMs;
|
|
248
|
+
// Internal controller: fires on either (a) the timer, so the inner call
|
|
249
|
+
// actually observes the budget breach instead of running forever after
|
|
250
|
+
// `Promise.race` rejects; or (b) the caller's own signal, so external
|
|
251
|
+
// cancellation still reaches the inner call transparently. Any
|
|
252
|
+
// `AbortSignal`-typed property on `args` (e.g. `signal` on
|
|
253
|
+
// `CompactionArgs`, `abortSignal` on `OverflowReduceArgs`) is swapped
|
|
254
|
+
// for this linked signal on a shallow-cloned args object — we never
|
|
255
|
+
// mutate the caller's args.
|
|
256
|
+
const internalController = new AbortController();
|
|
257
|
+
const { args: effectiveArgs, cleanup } = linkAbortSignal(
|
|
258
|
+
args,
|
|
259
|
+
internalController,
|
|
260
|
+
);
|
|
261
|
+
const timeoutPromise = new Promise<never>((_resolve, reject) => {
|
|
262
|
+
timer = setTimeout(() => {
|
|
263
|
+
internalController.abort();
|
|
264
|
+
reject(
|
|
265
|
+
new PluginTimeoutError(
|
|
266
|
+
name,
|
|
267
|
+
ctx.pluginName,
|
|
268
|
+
Math.round(performance.now() - start),
|
|
269
|
+
),
|
|
270
|
+
);
|
|
271
|
+
}, budget);
|
|
272
|
+
});
|
|
273
|
+
try {
|
|
274
|
+
return await Promise.race([
|
|
275
|
+
composed(effectiveArgs, ctx),
|
|
276
|
+
timeoutPromise,
|
|
277
|
+
]);
|
|
278
|
+
} finally {
|
|
279
|
+
cleanup();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return await composed(args, ctx);
|
|
283
|
+
} catch (err) {
|
|
284
|
+
thrown = err;
|
|
285
|
+
outcome = err instanceof PluginTimeoutError ? "timeout" : "error";
|
|
286
|
+
throw err;
|
|
287
|
+
} finally {
|
|
288
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
289
|
+
const durationMs = Math.round(performance.now() - start);
|
|
290
|
+
const record: PipelineLogRecord = {
|
|
291
|
+
event: "plugin.pipeline",
|
|
292
|
+
pipeline: name,
|
|
293
|
+
chain,
|
|
294
|
+
durationMs,
|
|
295
|
+
outcome,
|
|
296
|
+
requestId: ctx.requestId,
|
|
297
|
+
conversationId: ctx.conversationId,
|
|
298
|
+
};
|
|
299
|
+
if (ctx.turnIndex !== undefined) record.turnIndex = ctx.turnIndex;
|
|
300
|
+
if (ctx.pluginName !== undefined) record.pluginName = ctx.pluginName;
|
|
301
|
+
if (typeof timeoutMs === "number" && Number.isFinite(timeoutMs)) {
|
|
302
|
+
record.timeoutMs = timeoutMs;
|
|
303
|
+
}
|
|
304
|
+
if (thrown !== undefined) {
|
|
305
|
+
if (thrown instanceof Error) {
|
|
306
|
+
record.errorName = thrown.name;
|
|
307
|
+
record.errorMessage = thrown.message;
|
|
308
|
+
if (thrown.stack) record.errorStack = thrown.stack;
|
|
309
|
+
} else {
|
|
310
|
+
record.errorName = "NonError";
|
|
311
|
+
record.errorMessage = String(thrown);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
logger.info(record, "plugin.pipeline");
|
|
315
|
+
}
|
|
316
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory registry of plugin-contributed skills.
|
|
3
|
+
*
|
|
4
|
+
* Plugins with `manifest.skills` (or {@link Plugin.skills}) declared in their
|
|
5
|
+
* {@link PluginSkillRegistration} list get their entries indexed here during
|
|
6
|
+
* bootstrap (PR 14 -> PR 33). {@link loadSkillCatalog} in
|
|
7
|
+
* `config/skills.ts` merges these entries into the regular catalog so the
|
|
8
|
+
* model's `skill_load` / `skill_execute` flow can resolve them under
|
|
9
|
+
* `source: "plugin"`.
|
|
10
|
+
*
|
|
11
|
+
* ## Ref-counted lifecycle
|
|
12
|
+
*
|
|
13
|
+
* Registration is per-plugin — a plugin declares zero or more skills and the
|
|
14
|
+
* registry stores them keyed by plugin name. Several tests and hot-reload
|
|
15
|
+
* flows may call {@link registerPluginSkills} more than once for the same
|
|
16
|
+
* plugin (same skills, same body). Each call bumps a reference counter;
|
|
17
|
+
* {@link unregisterPluginSkills} decrements it and only tears the entry down
|
|
18
|
+
* when the counter reaches zero. This mirrors the ref-counted teardown
|
|
19
|
+
* semantics of `registerSkillTools` / `unregisterSkillTools` in the tool
|
|
20
|
+
* registry, so the plugin layer's lifecycle matches the skill layer's.
|
|
21
|
+
*
|
|
22
|
+
* Collision rules:
|
|
23
|
+
*
|
|
24
|
+
* - A plugin cannot register two skills with the same id in a single call —
|
|
25
|
+
* the duplicate is rejected at registration time.
|
|
26
|
+
* - Two different plugins cannot contribute skills with the same id. The
|
|
27
|
+
* second registration throws so the operator notices, rather than silently
|
|
28
|
+
* shadowing the first plugin's contribution.
|
|
29
|
+
* - The catalog merge logic in {@link loadSkillCatalog} decides how plugin
|
|
30
|
+
* skills interact with filesystem skills (bundled/managed/workspace) —
|
|
31
|
+
* this module just owns the in-memory set.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import type {
|
|
35
|
+
SkillDefinition,
|
|
36
|
+
SkillSummary,
|
|
37
|
+
SkillToolManifestMeta,
|
|
38
|
+
} from "../config/skills.js";
|
|
39
|
+
import { getLogger } from "../util/logger.js";
|
|
40
|
+
import { PluginExecutionError, type PluginSkillRegistration } from "./types.js";
|
|
41
|
+
|
|
42
|
+
// This module imports ONLY types from `config/skills.js`. `config/skills.ts`
|
|
43
|
+
// in turn imports values from here to merge plugin-contributed skills into
|
|
44
|
+
// the catalog output. TypeScript / ESM handles the type-only edge of the
|
|
45
|
+
// cycle cleanly; converting any of the imports above to value imports would
|
|
46
|
+
// introduce a runtime cycle and a load-order hazard with `loadSkillCatalog`.
|
|
47
|
+
|
|
48
|
+
const log = getLogger("plugin-skills");
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Virtual directory path prefix for plugin-contributed skills. `SkillSummary`
|
|
52
|
+
* requires a `directoryPath` — plugin skills aren't on disk, so we synthesize
|
|
53
|
+
* a stable, recognizable path that encodes the plugin name. Downstream code
|
|
54
|
+
* that reads from disk (inline-command rendering, reference-file listing,
|
|
55
|
+
* icon caching) gates on `source` so these paths are never stat'd.
|
|
56
|
+
*/
|
|
57
|
+
const PLUGIN_VIRTUAL_PATH_PREFIX = "<plugin>/";
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* One stored plugin skill. Keeps the original registration for re-exposure
|
|
61
|
+
* and a pre-built {@link SkillDefinition} so the catalog / loader paths can
|
|
62
|
+
* return summary/definition objects without re-synthesizing them on every
|
|
63
|
+
* lookup.
|
|
64
|
+
*/
|
|
65
|
+
interface StoredPluginSkill {
|
|
66
|
+
/** Name of the plugin that contributed the skill. */
|
|
67
|
+
pluginName: string;
|
|
68
|
+
/** Pre-built definition (includes the body) returned to `skill_load`. */
|
|
69
|
+
definition: SkillDefinition;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** All skills contributed by plugins, keyed by skill id. */
|
|
73
|
+
const pluginSkillsById = new Map<string, StoredPluginSkill>();
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Ref-count of active registrations per plugin name. Bumped on
|
|
77
|
+
* {@link registerPluginSkills}, decremented on {@link unregisterPluginSkills}.
|
|
78
|
+
* Only when the counter hits zero do we actually remove the plugin's
|
|
79
|
+
* contributed skills from {@link pluginSkillsById}.
|
|
80
|
+
*/
|
|
81
|
+
const pluginRefCount = new Map<string, number>();
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Skill-id -> owning plugin name. Maintained alongside
|
|
85
|
+
* {@link pluginSkillsById} so {@link unregisterPluginSkills} can drop exactly
|
|
86
|
+
* the entries the plugin owns without scanning the full id map.
|
|
87
|
+
*/
|
|
88
|
+
const pluginSkillIdsByPlugin = new Map<string, Set<string>>();
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Build the {@link SkillDefinition} object that {@link loadSkillCatalog} and
|
|
92
|
+
* {@link loadSkillBySelector} hand back to consumers. Kept in one place so
|
|
93
|
+
* summary and definition stay in lockstep — any field added to
|
|
94
|
+
* {@link PluginSkillRegistration} shows up in both.
|
|
95
|
+
*/
|
|
96
|
+
function buildDefinition(
|
|
97
|
+
pluginName: string,
|
|
98
|
+
reg: PluginSkillRegistration,
|
|
99
|
+
): SkillDefinition {
|
|
100
|
+
// Synthetic directory path. Using a non-filesystem prefix keeps the path
|
|
101
|
+
// recognizable in logs while preventing accidental `fs.existsSync` loops
|
|
102
|
+
// elsewhere in the catalog (all such loops live behind source !== "plugin"
|
|
103
|
+
// guards).
|
|
104
|
+
const directoryPath = `${PLUGIN_VIRTUAL_PATH_PREFIX}${pluginName}/${reg.id}`;
|
|
105
|
+
const skillFilePath = `${directoryPath}/SKILL.md`;
|
|
106
|
+
|
|
107
|
+
// toolManifest stays undefined for plugin skills — plugin tool contributions
|
|
108
|
+
// flow through `Plugin.tools` (PR 31), not through a synthetic TOOLS.json.
|
|
109
|
+
const toolManifest: SkillToolManifestMeta | undefined = undefined;
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
id: reg.id,
|
|
113
|
+
name: reg.name,
|
|
114
|
+
displayName: reg.displayName ?? reg.name,
|
|
115
|
+
description: reg.description,
|
|
116
|
+
directoryPath,
|
|
117
|
+
skillFilePath,
|
|
118
|
+
body: reg.body,
|
|
119
|
+
emoji: reg.emoji,
|
|
120
|
+
source: "plugin",
|
|
121
|
+
toolManifest,
|
|
122
|
+
includes: reg.includes,
|
|
123
|
+
featureFlag: reg.featureFlag,
|
|
124
|
+
activationHints: reg.activationHints,
|
|
125
|
+
avoidWhen: reg.avoidWhen,
|
|
126
|
+
// Plugin skills do not support inline command expansion in this PR.
|
|
127
|
+
inlineCommandExpansions: undefined,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Register every skill declared by a plugin's `Plugin.skills` list.
|
|
133
|
+
*
|
|
134
|
+
* Must be called after the plugin's `init()` completes successfully (see
|
|
135
|
+
* `external-plugins-bootstrap.ts`). Throws {@link PluginExecutionError} if a
|
|
136
|
+
* skill id collides with another plugin's skill or with an id already
|
|
137
|
+
* registered in an earlier successful registration from the same plugin
|
|
138
|
+
* that hasn't been torn down.
|
|
139
|
+
*
|
|
140
|
+
* Ref-count semantics: each call bumps the plugin-level ref counter.
|
|
141
|
+
* Duplicate registrations of the *same* plugin's skills are accepted and
|
|
142
|
+
* treated as a no-op past the first call — the second invocation increments
|
|
143
|
+
* the counter without re-inserting entries.
|
|
144
|
+
*/
|
|
145
|
+
export function registerPluginSkills(
|
|
146
|
+
pluginName: string,
|
|
147
|
+
skills: readonly PluginSkillRegistration[],
|
|
148
|
+
): void {
|
|
149
|
+
const currentCount = pluginRefCount.get(pluginName) ?? 0;
|
|
150
|
+
|
|
151
|
+
if (currentCount > 0) {
|
|
152
|
+
// The plugin already has skills registered — bump the counter without
|
|
153
|
+
// re-adding. Duplicate register calls for the same plugin are legitimate
|
|
154
|
+
// (hot-reload, re-bootstrap) so we accept them rather than throw.
|
|
155
|
+
pluginRefCount.set(pluginName, currentCount + 1);
|
|
156
|
+
log.debug(
|
|
157
|
+
{ pluginName, refCount: currentCount + 1 },
|
|
158
|
+
"Bumped plugin-skills ref count (skills kept)",
|
|
159
|
+
);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// First-time registration for this plugin — validate and insert.
|
|
164
|
+
//
|
|
165
|
+
// We validate intra-batch uniqueness first so a plugin that accidentally
|
|
166
|
+
// declares the same skill twice gets a clear error at registration,
|
|
167
|
+
// rather than the second declaration silently overwriting the first
|
|
168
|
+
// inside the map.
|
|
169
|
+
const seenInBatch = new Set<string>();
|
|
170
|
+
for (const reg of skills) {
|
|
171
|
+
if (seenInBatch.has(reg.id)) {
|
|
172
|
+
throw new PluginExecutionError(
|
|
173
|
+
`plugin ${pluginName} declared skill "${reg.id}" more than once`,
|
|
174
|
+
pluginName,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
seenInBatch.add(reg.id);
|
|
178
|
+
|
|
179
|
+
const existing = pluginSkillsById.get(reg.id);
|
|
180
|
+
if (existing) {
|
|
181
|
+
throw new PluginExecutionError(
|
|
182
|
+
`plugin ${pluginName} cannot contribute skill "${reg.id}" — ` +
|
|
183
|
+
`already registered by plugin "${existing.pluginName}"`,
|
|
184
|
+
pluginName,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const ownedIds = new Set<string>();
|
|
190
|
+
for (const reg of skills) {
|
|
191
|
+
pluginSkillsById.set(reg.id, {
|
|
192
|
+
pluginName,
|
|
193
|
+
definition: buildDefinition(pluginName, reg),
|
|
194
|
+
});
|
|
195
|
+
ownedIds.add(reg.id);
|
|
196
|
+
log.info({ pluginName, skillId: reg.id }, "Plugin skill registered");
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
pluginSkillIdsByPlugin.set(pluginName, ownedIds);
|
|
200
|
+
pluginRefCount.set(pluginName, 1);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Decrement the ref count for a plugin's skills. When the count hits zero
|
|
205
|
+
* the plugin's contributed skills are removed from the in-memory catalog.
|
|
206
|
+
*
|
|
207
|
+
* Idempotent — calling on a plugin that was never registered is a no-op
|
|
208
|
+
* (logged at debug level).
|
|
209
|
+
*/
|
|
210
|
+
export function unregisterPluginSkills(pluginName: string): void {
|
|
211
|
+
const current = pluginRefCount.get(pluginName) ?? 0;
|
|
212
|
+
if (current === 0) {
|
|
213
|
+
log.debug(
|
|
214
|
+
{ pluginName },
|
|
215
|
+
"unregisterPluginSkills called on unregistered plugin (no-op)",
|
|
216
|
+
);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (current > 1) {
|
|
221
|
+
pluginRefCount.set(pluginName, current - 1);
|
|
222
|
+
log.info(
|
|
223
|
+
{ pluginName, remaining: current - 1 },
|
|
224
|
+
"Decremented plugin-skills ref count, skills kept",
|
|
225
|
+
);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Last reference — actually remove the skills.
|
|
230
|
+
pluginRefCount.delete(pluginName);
|
|
231
|
+
const ownedIds = pluginSkillIdsByPlugin.get(pluginName);
|
|
232
|
+
if (ownedIds) {
|
|
233
|
+
for (const id of ownedIds) {
|
|
234
|
+
pluginSkillsById.delete(id);
|
|
235
|
+
log.info({ pluginName, skillId: id }, "Plugin skill unregistered");
|
|
236
|
+
}
|
|
237
|
+
pluginSkillIdsByPlugin.delete(pluginName);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Return a shallow-copied list of {@link SkillSummary} entries for every
|
|
243
|
+
* plugin-contributed skill. Consumers (the catalog loader) treat the return
|
|
244
|
+
* value as a read-only snapshot — mutating it does not mutate the registry.
|
|
245
|
+
*/
|
|
246
|
+
export function getPluginContributedSkillSummaries(): SkillSummary[] {
|
|
247
|
+
const out: SkillSummary[] = [];
|
|
248
|
+
for (const stored of pluginSkillsById.values()) {
|
|
249
|
+
// Strip `body` so we hand out a SkillSummary, not a SkillDefinition —
|
|
250
|
+
// the catalog merge function in config/skills.ts pushes summaries.
|
|
251
|
+
const { body: _body, ...summary } = stored.definition;
|
|
252
|
+
out.push(summary);
|
|
253
|
+
}
|
|
254
|
+
return out;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Look up the full {@link SkillDefinition} for a plugin-contributed skill by
|
|
259
|
+
* id. Used by the catalog loader to satisfy `skill_load` without a disk
|
|
260
|
+
* read.
|
|
261
|
+
*/
|
|
262
|
+
export function getPluginContributedSkillDefinition(
|
|
263
|
+
skillId: string,
|
|
264
|
+
): SkillDefinition | undefined {
|
|
265
|
+
return pluginSkillsById.get(skillId)?.definition;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Return the current ref count for a plugin's skills. Exposed for tests.
|
|
270
|
+
*/
|
|
271
|
+
export function getPluginSkillRefCount(pluginName: string): number {
|
|
272
|
+
return pluginRefCount.get(pluginName) ?? 0;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Clear every registered plugin skill. Test-only — throws when invoked
|
|
277
|
+
* outside a test environment. Guard mirrors
|
|
278
|
+
* {@link resetPluginRegistryForTests}.
|
|
279
|
+
*/
|
|
280
|
+
export function resetPluginSkillContributionsForTests(): void {
|
|
281
|
+
const isTest =
|
|
282
|
+
process.env.BUN_TEST === "1" || process.env.NODE_ENV === "test";
|
|
283
|
+
if (!isTest) {
|
|
284
|
+
throw new PluginExecutionError(
|
|
285
|
+
"resetPluginSkillContributionsForTests may only be called in test environments",
|
|
286
|
+
undefined,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
pluginSkillsById.clear();
|
|
290
|
+
pluginRefCount.clear();
|
|
291
|
+
pluginSkillIdsByPlugin.clear();
|
|
292
|
+
}
|