@vellumai/assistant 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +2 -7
- package/Dockerfile +75 -1
- package/bun.lock +11 -1
- package/docker-entrypoint.sh +5 -0
- package/docker-init-apt-root.sh +94 -0
- package/docker-kata-apt-env.sh +39 -0
- package/docs/plugins.md +88 -47
- package/docs/skills.md +9 -7
- package/examples/plugins/echo/README.md +27 -27
- package/examples/plugins/echo/package.json +3 -0
- package/examples/plugins/echo/register.ts +31 -31
- package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
- package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
- package/openapi.yaml +325 -3
- package/package.json +3 -1
- package/scripts/generate-openapi.ts +83 -10
- package/scripts/sync-llm-catalog.ts +2 -2
- package/scripts/sync-web-search-catalog.ts +47 -25
- package/src/__tests__/agent-image-optimize.test.ts +11 -3
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
- package/src/__tests__/anthropic-provider.test.ts +45 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
- package/src/__tests__/app-executors.test.ts +220 -4
- package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/channel-availability-routes.test.ts +206 -0
- package/src/__tests__/channel-delivery-store.test.ts +289 -1
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
- package/src/__tests__/clawhub.test.ts +75 -16
- package/src/__tests__/compactor-tail-resolution.test.ts +41 -0
- package/src/__tests__/config-schema.test.ts +21 -0
- package/src/__tests__/config-set-route.test.ts +80 -0
- package/src/__tests__/config-sounds-sync.test.ts +97 -0
- package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
- package/src/__tests__/context-search-conversations-source.test.ts +117 -2
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +7 -0
- package/src/__tests__/context-token-estimator.test.ts +1 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
- package/src/__tests__/conversation-agent-loop.test.ts +2 -0
- package/src/__tests__/conversation-error.test.ts +42 -3
- package/src/__tests__/conversation-fork-crud.test.ts +82 -0
- package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
- package/src/__tests__/conversation-lifecycle.test.ts +173 -0
- package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
- package/src/__tests__/conversation-pairing.test.ts +54 -0
- package/src/__tests__/conversation-process-callsite.test.ts +4 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
- package/src/__tests__/conversation-queue.test.ts +4 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +76 -9
- package/src/__tests__/conversation-slash-queue.test.ts +59 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
- package/src/__tests__/conversation-sync-tags.test.ts +235 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +3 -2
- package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
- package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
- package/src/__tests__/disk-pressure-tools.test.ts +1 -0
- package/src/__tests__/dm-backfill.test.ts +121 -10
- package/src/__tests__/document-tool-security.test.ts +258 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/edit-propagation.test.ts +33 -0
- package/src/__tests__/empty-response-pipeline.test.ts +0 -4
- package/src/__tests__/external-plugin-loader.test.ts +60 -36
- package/src/__tests__/filing-service.test.ts +140 -0
- package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
- package/src/__tests__/helpers/tar-fixtures.ts +39 -0
- package/src/__tests__/helpers/wait-for.ts +21 -0
- package/src/__tests__/history-repair-pipeline.test.ts +0 -3
- package/src/__tests__/history-repair.test.ts +73 -0
- package/src/__tests__/host-app-control-proxy.test.ts +266 -10
- package/src/__tests__/image-credentials.test.ts +1 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
- package/src/__tests__/inference-profile-reaper.test.ts +4 -2
- package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
- package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
- package/src/__tests__/injector-chain.test.ts +10 -8
- package/src/__tests__/install-skill-routing.test.ts +155 -37
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +92 -3
- package/src/__tests__/list-messages-page-latest.test.ts +55 -0
- package/src/__tests__/llm-call-pipeline.test.ts +0 -3
- package/src/__tests__/llm-catalog-parity.test.ts +55 -13
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +34 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
- package/src/__tests__/llm-usage-store.test.ts +114 -0
- package/src/__tests__/managed-profile-guard.test.ts +31 -29
- package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
- package/src/__tests__/managed-store.test.ts +84 -192
- package/src/__tests__/media-generate-image.test.ts +1 -1
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
- package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
- package/src/__tests__/oauth-commands-routes.test.ts +168 -16
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
- package/src/__tests__/openai-provider.test.ts +24 -0
- package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
- package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
- package/src/__tests__/persistence-pipeline.test.ts +0 -2
- package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
- package/src/__tests__/platform.test.ts +2 -0
- package/src/__tests__/plugin-api-shim.test.ts +125 -0
- package/src/__tests__/plugin-bootstrap.test.ts +10 -36
- package/src/__tests__/plugin-external-api.test.ts +68 -0
- package/src/__tests__/plugin-registry.test.ts +0 -77
- package/src/__tests__/plugin-route-contribution.test.ts +0 -1
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
- package/src/__tests__/plugin-types.test.ts +3 -13
- package/src/__tests__/process-message-background-slack.test.ts +8 -1
- package/src/__tests__/process-message-display-content.test.ts +421 -0
- package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
- package/src/__tests__/provider-error-scenarios.test.ts +111 -0
- package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +8 -8
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
- package/src/__tests__/schedule-routes.test.ts +50 -3
- package/src/__tests__/schedule-store.test.ts +94 -0
- package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
- package/src/__tests__/schema-transforms.test.ts +20 -0
- package/src/__tests__/search-skills-unified.test.ts +0 -5
- package/src/__tests__/server-history-render.test.ts +43 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
- package/src/__tests__/skill-load-tool.test.ts +27 -89
- package/src/__tests__/skill-memory.test.ts +23 -3
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
- package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
- package/src/__tests__/skills-install-extract.test.ts +49 -38
- package/src/__tests__/skills-install-staging.test.ts +159 -0
- package/src/__tests__/skills-uninstall.test.ts +9 -41
- package/src/__tests__/skills.test.ts +51 -58
- package/src/__tests__/slack-channel-config.test.ts +9 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/system-prompt.test.ts +737 -63
- package/src/__tests__/terminal-tools.test.ts +28 -1
- package/src/__tests__/thread-backfill.test.ts +557 -27
- package/src/__tests__/title-generate-pipeline.test.ts +0 -13
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
- package/src/__tests__/tool-error-pipeline.test.ts +0 -3
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +16 -4
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
- package/src/__tests__/turn-events-store.test.ts +256 -0
- package/src/__tests__/twilio-routes.test.ts +4 -0
- package/src/__tests__/user-plugin-loader.test.ts +0 -7
- package/src/__tests__/voice-session-bridge.test.ts +198 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
- package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
- package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
- package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
- package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
- package/src/acp/resolve-agent.ts +1 -1
- package/src/agent/image-optimize.ts +13 -5
- package/src/calls/voice-session-bridge.ts +61 -42
- package/src/channels/types.ts +108 -0
- package/src/cli/__tests__/unknown-command.test.ts +24 -0
- package/src/cli/commands/__tests__/changelog.test.ts +304 -319
- package/src/cli/commands/__tests__/schedules.test.ts +491 -0
- package/src/cli/commands/changelog.ts +106 -42
- package/src/cli/commands/conversations.ts +102 -17
- package/src/cli/commands/default-action.ts +10 -53
- package/src/cli/commands/notifications.ts +329 -317
- package/src/cli/commands/plugins.ts +185 -0
- package/src/cli/commands/schedules.ts +391 -0
- package/src/cli/commands/telemetry.ts +40 -0
- package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
- package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
- package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
- package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
- package/src/cli/lib/cli-colors.ts +12 -0
- package/src/cli/lib/confirm-prompt.ts +79 -0
- package/src/cli/lib/install-from-github.ts +304 -0
- package/src/cli/lib/list-installed-plugins.ts +137 -0
- package/src/cli/lib/uninstall-plugin.ts +82 -0
- package/src/cli/lib/unknown-command.ts +111 -0
- package/src/cli/program.ts +38 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
- package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
- package/src/config/bundled-skills/document/SKILL.md +23 -3
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
- package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
- package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
- package/src/config/bundled-tool-registry.ts +6 -0
- package/src/config/feature-flag-registry.json +41 -1
- package/src/config/loader.ts +64 -38
- package/src/config/schema.ts +7 -10
- package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
- package/src/config/schemas/channels.ts +8 -0
- package/src/config/schemas/compaction.ts +28 -0
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm-request-logs.ts +31 -7
- package/src/config/schemas/llm.ts +3 -0
- package/src/config/schemas/memory-retrieval.ts +18 -0
- package/src/config/schemas/tools.ts +14 -0
- package/src/config/skills.ts +3 -96
- package/src/context/compactor.ts +1047 -0
- package/src/context/token-estimator.ts +2 -2
- package/src/context/window-manager.ts +197 -1520
- package/src/credential-execution/managed-catalog.ts +37 -0
- package/src/credential-health/credential-health-service.ts +280 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +34 -0
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
- package/src/daemon/approval-generators.ts +8 -6
- package/src/daemon/config-watcher.ts +94 -31
- package/src/daemon/conversation-agent-loop.ts +169 -9
- package/src/daemon/conversation-error.ts +171 -37
- package/src/daemon/conversation-lifecycle.ts +53 -40
- package/src/daemon/conversation-messaging.ts +25 -6
- package/src/daemon/conversation-process.ts +49 -12
- package/src/daemon/conversation-runtime-assembly.ts +16 -1
- package/src/daemon/conversation-slash.ts +12 -5
- package/src/daemon/conversation-store.ts +11 -4
- package/src/daemon/conversation-tool-setup.ts +39 -7
- package/src/daemon/conversation.ts +33 -1
- package/src/daemon/external-plugins-bootstrap.ts +217 -181
- package/src/daemon/first-greeting.ts +22 -2
- package/src/daemon/handlers/config-model.ts +6 -5
- package/src/daemon/handlers/config-slack-channel.ts +15 -3
- package/src/daemon/handlers/shared.ts +14 -5
- package/src/daemon/handlers/skills.ts +111 -108
- package/src/daemon/history-repair.ts +28 -1
- package/src/daemon/host-app-control-proxy.ts +98 -23
- package/src/daemon/lifecycle.ts +45 -35
- package/src/daemon/meet-host-supervisor.ts +5 -4
- package/src/daemon/memory-v2-startup.ts +49 -0
- package/src/daemon/message-protocol.ts +1 -0
- package/src/daemon/message-types/conversations.ts +25 -0
- package/src/daemon/message-types/messages.ts +61 -0
- package/src/daemon/message-types/subagents.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pkb-reminder-builder.test.ts +1 -1
- package/src/daemon/pkb-reminder-builder.ts +1 -1
- package/src/daemon/plugin-source-watcher.ts +146 -0
- package/src/daemon/process-message.ts +21 -3
- package/src/daemon/server.ts +11 -2
- package/src/daemon/skill-memory-refresh.ts +29 -0
- package/src/documents/document-store.ts +221 -3
- package/src/embedded/plugin-api.ts +40 -0
- package/src/filing/filing-service.ts +39 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +91 -6
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +41 -0
- package/src/home/__tests__/feed-types.test.ts +40 -0
- package/src/home/feed-types.ts +22 -0
- package/src/home/post-connect-feed.ts +1 -0
- package/src/index.ts +18 -1
- package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
- package/src/mcp/client.ts +20 -4
- package/src/media/image-credentials.ts +3 -3
- package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
- package/src/memory/__tests__/conversation-queries.test.ts +263 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
- package/src/memory/__tests__/message-content.test.ts +35 -0
- package/src/memory/bookmark-crud.ts +42 -10
- package/src/memory/context-search/sources/conversations.ts +62 -2
- package/src/memory/context-search/sources/workspace.ts +4 -0
- package/src/memory/conversation-crud.ts +63 -19
- package/src/memory/conversation-queries.ts +110 -10
- package/src/memory/db-init.ts +6 -0
- package/src/memory/delivery-crud.ts +152 -5
- package/src/memory/embedding-backend.ts +4 -4
- package/src/memory/external-conversation-store.ts +66 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
- package/src/memory/graph/conversation-graph-memory.ts +31 -15
- package/src/memory/graph/tools.ts +3 -3
- package/src/memory/indexer.ts +34 -29
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
- package/src/memory/jobs/embed-concept-page.ts +20 -11
- package/src/memory/jobs-worker.ts +6 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +17 -10
- package/src/memory/llm-request-log-source.ts +19 -52
- package/src/memory/llm-usage-store.ts +125 -5
- package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
- package/src/memory/message-content.ts +1 -1
- package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
- package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
- package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
- package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
- package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/onboarding-events-store.ts +106 -0
- package/src/memory/schema/bookmarks.ts +0 -2
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/inference.ts +1 -3
- package/src/memory/schema/infrastructure.ts +12 -0
- package/src/memory/turn-events-store.ts +127 -2
- package/src/memory/v2/__tests__/activation.test.ts +0 -8
- package/src/memory/v2/__tests__/injection.test.ts +98 -8
- package/src/memory/v2/__tests__/migration.test.ts +87 -0
- package/src/memory/v2/__tests__/page-index.test.ts +83 -0
- package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
- package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
- package/src/memory/v2/__tests__/router.test.ts +15 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
- package/src/memory/v2/injection.ts +32 -6
- package/src/memory/v2/migration.ts +49 -19
- package/src/memory/v2/page-index.ts +35 -5
- package/src/memory/v2/prompts/router.ts +11 -8
- package/src/memory/v2/prompts/sweep.ts +2 -2
- package/src/memory/v2/qdrant.ts +135 -7
- package/src/memory/v2/router.ts +9 -8
- package/src/memory/v2/skill-store.ts +120 -35
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
- package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
- package/src/messaging/providers/slack/adapter.ts +43 -5
- package/src/messaging/providers/slack/client.ts +27 -0
- package/src/messaging/providers/slack/deep-link.ts +65 -0
- package/src/messaging/providers/slack/download.ts +104 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
- package/src/messaging/providers/slack/message-metadata.ts +27 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
- package/src/messaging/providers/slack/render-transcript.ts +69 -5
- package/src/messaging/providers/slack/types.ts +20 -1
- package/src/notifications/conversation-pairing.ts +2 -1
- package/src/notifications/decision-engine.ts +2 -1
- package/src/notifications/emit-signal.ts +20 -1
- package/src/notifications/home-feed-side-effect.ts +54 -0
- package/src/notifications/signal.ts +3 -1
- package/src/oauth/connection-resolver.ts +8 -4
- package/src/oauth/platform-connection.ts +6 -2
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/checker.ts +2 -0
- package/src/permissions/ipc-risk-types.ts +1 -0
- package/src/permissions/question-prompter.test.ts +416 -0
- package/src/permissions/question-prompter.ts +294 -0
- package/src/platform/client.test.ts +1 -1
- package/src/platform/client.ts +1 -1
- package/src/plugin-api/constants.ts +26 -0
- package/src/plugin-api/index.ts +34 -1
- package/src/plugin-api/types.ts +104 -22
- package/src/plugins/defaults/circuit-breaker.ts +0 -5
- package/src/plugins/defaults/compaction.ts +0 -4
- package/src/plugins/defaults/empty-response.ts +0 -2
- package/src/plugins/defaults/history-repair.ts +0 -2
- package/src/plugins/defaults/injectors.ts +36 -3
- package/src/plugins/defaults/llm-call.ts +0 -2
- package/src/plugins/defaults/memory-retrieval.ts +0 -1
- package/src/plugins/defaults/overflow-reduce.ts +0 -1
- package/src/plugins/defaults/persistence.ts +0 -2
- package/src/plugins/defaults/title-generate.ts +0 -5
- package/src/plugins/defaults/token-estimate.ts +0 -2
- package/src/plugins/defaults/tool-error.ts +0 -7
- package/src/plugins/defaults/tool-execute.ts +0 -2
- package/src/plugins/defaults/tool-result-truncate.ts +0 -4
- package/src/plugins/ensure-plugin-api-shim.ts +96 -0
- package/src/plugins/external-api.ts +104 -0
- package/src/plugins/external-plugin-loader.ts +105 -32
- package/src/plugins/feature-gate.ts +22 -0
- package/src/plugins/pipeline.ts +37 -0
- package/src/plugins/registry.ts +48 -80
- package/src/plugins/types.ts +31 -26
- package/src/plugins/user-loader.ts +21 -2
- package/src/proactive-artifact/aux-message-injector.ts +11 -0
- package/src/proactive-artifact/job.test.ts +37 -5
- package/src/prompts/__tests__/system-prompt.test.ts +12 -0
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
- package/src/prompts/normalize-onboarding.ts +27 -0
- package/src/prompts/sections.ts +302 -0
- package/src/prompts/system-prompt.ts +63 -166
- package/src/prompts/templates/BOOTSTRAP.md +17 -1
- package/src/prompts/templates/system-sections.ts +173 -0
- package/src/providers/__tests__/inference.test.ts +22 -7
- package/src/providers/anthropic/client.ts +28 -28
- package/src/providers/connection-resolution.ts +7 -0
- package/src/providers/inference/adapter-factory.ts +41 -4
- package/src/providers/inference/connections.ts +74 -29
- package/src/providers/inference/resolve-auth.ts +12 -4
- package/src/providers/model-catalog.ts +294 -12
- package/src/providers/openai/chat-completions-provider.ts +10 -2
- package/src/providers/openrouter/client.ts +7 -0
- package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
- package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
- package/src/providers/provider-availability.ts +17 -2
- package/src/providers/provider-catalog-visibility.ts +36 -0
- package/src/providers/registry.ts +22 -14
- package/src/providers/retry.ts +47 -1
- package/src/runtime/__tests__/agent-wake.test.ts +152 -0
- package/src/runtime/agent-wake.ts +42 -14
- package/src/runtime/auth/route-policy.ts +8 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/http-types.ts +19 -0
- package/src/runtime/migrations/origin-mode.ts +1 -1
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +107 -20
- package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
- package/src/runtime/routes/acp-routes-list.test.ts +143 -0
- package/src/runtime/routes/acp-routes.ts +5 -3
- package/src/runtime/routes/auth-routes.ts +1 -1
- package/src/runtime/routes/bookmark-routes.ts +5 -3
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/channel-availability-routes.ts +121 -0
- package/src/runtime/routes/conversation-cli-routes.ts +44 -3
- package/src/runtime/routes/conversation-list-routes.ts +3 -20
- package/src/runtime/routes/conversation-management-routes.ts +17 -42
- package/src/runtime/routes/conversation-query-routes.ts +40 -35
- package/src/runtime/routes/conversation-routes.ts +90 -11
- package/src/runtime/routes/documents-routes.ts +25 -86
- package/src/runtime/routes/group-routes.ts +5 -0
- package/src/runtime/routes/inbound-conversation.ts +28 -8
- package/src/runtime/routes/inbound-message-handler.ts +236 -41
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
- package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
- package/src/runtime/routes/inference-provider-connection-routes.ts +65 -21
- package/src/runtime/routes/integrations/slack/share.ts +4 -52
- package/src/runtime/routes/integrations/slack/token.ts +43 -0
- package/src/runtime/routes/integrations/twilio.ts +6 -13
- package/src/runtime/routes/notification-routes.ts +1 -1
- package/src/runtime/routes/oauth-commands-routes.ts +105 -15
- package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
- package/src/runtime/routes/question-routes.ts +259 -0
- package/src/runtime/routes/rename-conversation-routes.ts +2 -33
- package/src/runtime/routes/schedule-routes.ts +4 -7
- package/src/runtime/routes/subagents-routes.ts +57 -18
- package/src/runtime/routes/telemetry-routes.ts +27 -0
- package/src/runtime/routes/tts-routes.ts +27 -2
- package/src/runtime/routes/workspace-routes.test.ts +43 -0
- package/src/runtime/routes/workspace-routes.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +39 -7
- package/src/runtime/sync/resource-sync-events.ts +93 -1
- package/src/schedule/schedule-store.ts +27 -2
- package/src/schedule/scheduler.ts +9 -1
- package/src/security/__tests__/untrusted-content.test.ts +86 -0
- package/src/security/untrusted-content.ts +93 -8
- package/src/skills/catalog-files.ts +1 -1
- package/src/skills/catalog-install.ts +233 -116
- package/src/skills/clawhub.ts +70 -13
- package/src/skills/managed-store.ts +4 -119
- package/src/skills/skillssh-registry.ts +27 -48
- package/src/subagent/manager.ts +15 -7
- package/src/telemetry/types.ts +113 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
- package/src/telemetry/usage-telemetry-reporter.ts +113 -7
- package/src/tools/apps/executors.ts +58 -7
- package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
- package/src/tools/ask-question/ask-question-tool.ts +304 -0
- package/src/tools/browser/browser-execution.ts +15 -11
- package/src/tools/computer-use/definitions.ts +3 -3
- package/src/tools/credentials/vault.ts +1 -1
- package/src/tools/document/document-tool.ts +124 -1
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +5 -2
- package/src/tools/host-filesystem/transfer.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +1 -1
- package/src/tools/permission-checker.ts +1 -1
- package/src/tools/registry.ts +17 -7
- package/src/tools/schedule/create.ts +2 -2
- package/src/tools/schema-transforms.ts +7 -2
- package/src/tools/side-effects.ts +1 -0
- package/src/tools/skills/delete-managed.ts +4 -4
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/scaffold-managed.ts +3 -2
- package/src/tools/subagent/notify-parent.ts +1 -1
- package/src/tools/system/request-permission.ts +2 -2
- package/src/tools/terminal/safe-env.ts +60 -1
- package/src/tools/tool-manifest.ts +2 -0
- package/src/tools/types.ts +72 -21
- package/src/tools/ui-surface/definitions.ts +6 -5
- package/src/tts/__tests__/provider-adapters.test.ts +76 -2
- package/src/tts/providers/elevenlabs-provider.ts +75 -1
- package/src/types/onboarding-context.ts +2 -0
- package/src/util/errors.ts +17 -0
- package/src/util/platform.ts +10 -0
- package/src/watcher/__tests__/engine.test.ts +22 -0
- package/src/watcher/engine.ts +6 -2
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
- package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
- package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
- package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/migrations/runner.ts +39 -9
- package/src/workspace/migrations/types.ts +4 -0
- package/examples/plugins/echo/bun.lock +0 -25
- package/src/__tests__/context-window-manager.test.ts +0 -2481
- package/src/context/__tests__/compact-prompt.test.ts +0 -63
- package/src/context/prompts/compact.md +0 -26
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
- /package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +0 -0
package/src/tools/registry.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { hostFileWriteTool } from "./host-filesystem/write.js";
|
|
|
10
10
|
import { hostShellTool } from "./host-terminal/host-shell.js";
|
|
11
11
|
import { toProviderSafeToolName } from "./provider-tool-name.js";
|
|
12
12
|
import { registerSystemTools } from "./system/register.js";
|
|
13
|
-
import type { Tool } from "./types.js";
|
|
13
|
+
import type { PluginTool, Tool } from "./types.js";
|
|
14
14
|
import { allUiSurfaceTools } from "./ui-surface/definitions.js";
|
|
15
15
|
import { registerUiSurfaceTools } from "./ui-surface/registry.js";
|
|
16
16
|
|
|
@@ -193,19 +193,29 @@ export function registerSkillTools(newTools: Tool[]): Tool[] {
|
|
|
193
193
|
*/
|
|
194
194
|
export function registerPluginTools(
|
|
195
195
|
pluginName: string,
|
|
196
|
-
newTools:
|
|
196
|
+
newTools: PluginTool[],
|
|
197
197
|
): Tool[] {
|
|
198
|
-
const stamped: Tool[] = newTools.map((
|
|
199
|
-
|
|
200
|
-
|
|
198
|
+
const stamped: Tool[] = newTools.map((pluginTool) => {
|
|
199
|
+
const { input_schema, ...rest } = pluginTool;
|
|
200
|
+
const tool: Tool = {
|
|
201
|
+
...rest,
|
|
202
|
+
category: "plugin",
|
|
201
203
|
origin: "plugin" as const,
|
|
202
204
|
ownerPluginId: pluginName,
|
|
203
205
|
ownerSkillId: undefined,
|
|
204
206
|
ownerMcpServerId: undefined,
|
|
205
207
|
ownerSkillBundled: undefined,
|
|
206
208
|
ownerSkillVersionHash: undefined,
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
getDefinition(): ToolDefinition {
|
|
210
|
+
return {
|
|
211
|
+
name: pluginTool.name,
|
|
212
|
+
description: pluginTool.description,
|
|
213
|
+
input_schema,
|
|
214
|
+
};
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
return withProviderSafeToolName(tool);
|
|
218
|
+
});
|
|
209
219
|
|
|
210
220
|
const accepted: Tool[] = [];
|
|
211
221
|
for (const tool of stamped) {
|
|
@@ -150,7 +150,7 @@ export async function executeScheduleCreate(
|
|
|
150
150
|
` Status: ${job.status}`,
|
|
151
151
|
``,
|
|
152
152
|
`Integrations: ${integrations}`,
|
|
153
|
-
`\u26a0 If this schedule requires an integration that isn't connected, it will fail at runtime. Warn
|
|
153
|
+
`\u26a0 If this schedule requires an integration that isn't connected, it will fail at runtime. Warn about any missing capabilities before confirming the schedule is ready.`,
|
|
154
154
|
].join("\n"),
|
|
155
155
|
isError: false,
|
|
156
156
|
};
|
|
@@ -239,7 +239,7 @@ export async function executeScheduleCreate(
|
|
|
239
239
|
` Next run: ${nextRunDate}`,
|
|
240
240
|
``,
|
|
241
241
|
`Integrations: ${integrations}`,
|
|
242
|
-
`\u26a0 If this schedule requires an integration that isn't connected, it will fail at runtime. Warn
|
|
242
|
+
`\u26a0 If this schedule requires an integration that isn't connected, it will fail at runtime. Warn about any missing capabilities before confirming the schedule is ready.`,
|
|
243
243
|
].join("\n"),
|
|
244
244
|
isError: false,
|
|
245
245
|
};
|
|
@@ -23,8 +23,13 @@ export function injectActivityField(
|
|
|
23
23
|
return def;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
const schema = def.input_schema as Record<string, unknown
|
|
27
|
-
if (
|
|
26
|
+
const schema = def.input_schema as Record<string, unknown> | undefined;
|
|
27
|
+
if (
|
|
28
|
+
schema == null ||
|
|
29
|
+
typeof schema !== "object" ||
|
|
30
|
+
schema.type !== "object" ||
|
|
31
|
+
!schema.properties
|
|
32
|
+
) {
|
|
28
33
|
return def;
|
|
29
34
|
}
|
|
30
35
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { refreshSkillCapabilityMemories } from "../../daemon/skill-memory-refresh.js";
|
|
1
2
|
import { deleteManagedSkill } from "../../skills/managed-store.js";
|
|
2
3
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
3
4
|
|
|
@@ -17,19 +18,18 @@ export async function executeDeleteManagedSkill(
|
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
const result = deleteManagedSkill(skillId.trim(), removeFromIndex);
|
|
21
|
+
const result = deleteManagedSkill(skillId.trim());
|
|
23
22
|
|
|
24
23
|
if (!result.deleted) {
|
|
25
24
|
return { content: `Error: ${result.error}`, isError: true };
|
|
26
25
|
}
|
|
27
26
|
|
|
27
|
+
refreshSkillCapabilityMemories();
|
|
28
|
+
|
|
28
29
|
return {
|
|
29
30
|
content: JSON.stringify({
|
|
30
31
|
deleted: true,
|
|
31
32
|
skill_id: skillId.trim(),
|
|
32
|
-
index_updated: result.indexUpdated,
|
|
33
33
|
}),
|
|
34
34
|
isError: false,
|
|
35
35
|
};
|
|
@@ -30,7 +30,7 @@ class SkillExecuteTool implements Tool {
|
|
|
30
30
|
activity: {
|
|
31
31
|
type: "string",
|
|
32
32
|
description:
|
|
33
|
-
"Brief non-technical explanation of what you are doing and why, shown
|
|
33
|
+
"Brief non-technical explanation of what you are doing and why, shown as a progress update.",
|
|
34
34
|
},
|
|
35
35
|
},
|
|
36
36
|
required: ["tool", "input", "activity"],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { refreshSkillCapabilityMemories } from "../../daemon/skill-memory-refresh.js";
|
|
1
2
|
import { createManagedSkill } from "../../skills/managed-store.js";
|
|
2
3
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
3
4
|
|
|
@@ -93,7 +94,6 @@ export async function executeScaffoldManagedSkill(
|
|
|
93
94
|
? sanitizeFrontmatterValue(input.emoji)
|
|
94
95
|
: undefined,
|
|
95
96
|
overwrite: input.overwrite === true,
|
|
96
|
-
addToIndex: input.add_to_index !== false,
|
|
97
97
|
includes,
|
|
98
98
|
});
|
|
99
99
|
|
|
@@ -101,12 +101,13 @@ export async function executeScaffoldManagedSkill(
|
|
|
101
101
|
return { content: `Error: ${result.error}`, isError: true };
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
refreshSkillCapabilityMemories();
|
|
105
|
+
|
|
104
106
|
return {
|
|
105
107
|
content: JSON.stringify({
|
|
106
108
|
created: true,
|
|
107
109
|
skill_id: skillId.trim(),
|
|
108
110
|
path: result.path,
|
|
109
|
-
index_updated: result.indexUpdated,
|
|
110
111
|
}),
|
|
111
112
|
isError: false,
|
|
112
113
|
};
|
|
@@ -59,7 +59,7 @@ class NotifyParentTool implements Tool {
|
|
|
59
59
|
activity: {
|
|
60
60
|
type: "string",
|
|
61
61
|
description:
|
|
62
|
-
"Brief non-technical explanation of what you are doing and why, shown
|
|
62
|
+
"Brief non-technical explanation of what you are doing and why, shown as a status update.",
|
|
63
63
|
},
|
|
64
64
|
},
|
|
65
65
|
required: ["message", "activity"],
|
|
@@ -53,7 +53,7 @@ const FRIENDLY_NAMES: Record<PermissionType, string> = {
|
|
|
53
53
|
class RequestSystemPermissionTool implements Tool {
|
|
54
54
|
name = "request_system_permission";
|
|
55
55
|
description =
|
|
56
|
-
"
|
|
56
|
+
"Request a macOS system permission via System Settings. " +
|
|
57
57
|
"Use when a tool fails with a permission/access error (e.g. 'Operation not permitted', 'EACCES', sandbox denial). " +
|
|
58
58
|
"Do not explain how to open System Settings manually - this tool handles it with a clickable button.";
|
|
59
59
|
category = "system";
|
|
@@ -74,7 +74,7 @@ class RequestSystemPermissionTool implements Tool {
|
|
|
74
74
|
activity: {
|
|
75
75
|
type: "string",
|
|
76
76
|
description:
|
|
77
|
-
"Short explanation of why this permission is needed (shown
|
|
77
|
+
"Short explanation of why this permission is needed (shown in the prompt)",
|
|
78
78
|
},
|
|
79
79
|
},
|
|
80
80
|
required: ["permission_type", "activity"],
|
|
@@ -46,6 +46,7 @@ export const SAFE_ENV_VARS = [
|
|
|
46
46
|
"IS_CONTAINERIZED",
|
|
47
47
|
"IS_PLATFORM",
|
|
48
48
|
"VELLUM_CLOUD",
|
|
49
|
+
"VELLUM_SANDBOX_RUNTIME",
|
|
49
50
|
"CES_SERVICE_TOKEN",
|
|
50
51
|
"VELLUM_PROFILER_RUN_ID",
|
|
51
52
|
"VELLUM_PROFILER_MODE",
|
|
@@ -59,6 +60,37 @@ export const SAFE_ENV_VARS = [
|
|
|
59
60
|
"VELLUM_BACKUP_KEY_PATH",
|
|
60
61
|
] as const;
|
|
61
62
|
|
|
63
|
+
export const KATA_SAFE_ENV_VARS = [
|
|
64
|
+
"LD_LIBRARY_PATH",
|
|
65
|
+
"VELLUM_APT_DATA_ROOT",
|
|
66
|
+
"VELLUM_APT_DATA_SUITE",
|
|
67
|
+
"VELLUM_APT_DATA_MIRROR",
|
|
68
|
+
] as const;
|
|
69
|
+
|
|
70
|
+
const KATA_APT_DATA_ROOT = "/data/system";
|
|
71
|
+
|
|
72
|
+
function kataAptPaths(dataRoot: string): string[] {
|
|
73
|
+
return [
|
|
74
|
+
`${dataRoot}/bin`,
|
|
75
|
+
`${dataRoot}/usr/local/sbin`,
|
|
76
|
+
`${dataRoot}/usr/local/bin`,
|
|
77
|
+
`${dataRoot}/usr/sbin`,
|
|
78
|
+
`${dataRoot}/usr/bin`,
|
|
79
|
+
`${dataRoot}/sbin`,
|
|
80
|
+
`${dataRoot}/usr/games`,
|
|
81
|
+
`${dataRoot}/games`,
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function kataAptLibraryPaths(dataRoot: string): string[] {
|
|
86
|
+
return [
|
|
87
|
+
`${dataRoot}/usr/local/lib`,
|
|
88
|
+
`${dataRoot}/usr/lib`,
|
|
89
|
+
`${dataRoot}/usr/lib/x86_64-linux-gnu`,
|
|
90
|
+
`${dataRoot}/usr/lib/aarch64-linux-gnu`,
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
62
94
|
/**
|
|
63
95
|
* Keys that buildSanitizedEnv always injects into the returned env,
|
|
64
96
|
* independent of what is present in process.env.
|
|
@@ -70,13 +102,40 @@ export const ALWAYS_INJECTED_ENV_VARS = [
|
|
|
70
102
|
"VELLUM_WORKSPACE_DIR",
|
|
71
103
|
] as const;
|
|
72
104
|
|
|
105
|
+
function appendUniquePathEntries(
|
|
106
|
+
value: string | undefined,
|
|
107
|
+
entries: readonly string[],
|
|
108
|
+
): string {
|
|
109
|
+
const parts = value ? value.split(":").filter(Boolean) : [];
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
if (!parts.includes(entry)) {
|
|
112
|
+
parts.push(entry);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return parts.join(":");
|
|
116
|
+
}
|
|
117
|
+
|
|
73
118
|
export function buildSanitizedEnv(): Record<string, string> {
|
|
74
119
|
const env: Record<string, string> = {};
|
|
75
|
-
|
|
120
|
+
const isKataRuntime = process.env.VELLUM_SANDBOX_RUNTIME === "kata";
|
|
121
|
+
const safeEnvVars = isKataRuntime
|
|
122
|
+
? [...SAFE_ENV_VARS, ...KATA_SAFE_ENV_VARS]
|
|
123
|
+
: SAFE_ENV_VARS;
|
|
124
|
+
|
|
125
|
+
for (const key of safeEnvVars) {
|
|
76
126
|
if (process.env[key] != null) {
|
|
77
127
|
env[key] = process.env[key]!;
|
|
78
128
|
}
|
|
79
129
|
}
|
|
130
|
+
if (isKataRuntime) {
|
|
131
|
+
const kataAptDataRoot = env.VELLUM_APT_DATA_ROOT ?? KATA_APT_DATA_ROOT;
|
|
132
|
+
env.VELLUM_APT_DATA_ROOT = kataAptDataRoot;
|
|
133
|
+
env.PATH = appendUniquePathEntries(env.PATH, kataAptPaths(kataAptDataRoot));
|
|
134
|
+
env.LD_LIBRARY_PATH = appendUniquePathEntries(
|
|
135
|
+
env.LD_LIBRARY_PATH,
|
|
136
|
+
kataAptLibraryPaths(kataAptDataRoot),
|
|
137
|
+
);
|
|
138
|
+
}
|
|
80
139
|
// Always inject an internal gateway base for local control-plane/API calls.
|
|
81
140
|
const internalGatewayBase = getGatewayInternalBaseUrl();
|
|
82
141
|
env.INTERNAL_GATEWAY_BASE_URL = internalGatewayBase;
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
isCesSecureInstallEnabled,
|
|
12
12
|
isCesToolsEnabled,
|
|
13
13
|
} from "../credential-execution/feature-gates.js";
|
|
14
|
+
import { askQuestionTool } from "./ask-question/ask-question-tool.js";
|
|
14
15
|
import { makeAuthenticatedRequestTool } from "./credential-execution/make-authenticated-request.js";
|
|
15
16
|
import { manageSecureCommandTool } from "./credential-execution/manage-secure-command-tool.js";
|
|
16
17
|
import { runAuthenticatedCommandTool } from "./credential-execution/run-authenticated-command.js";
|
|
@@ -91,6 +92,7 @@ export const explicitTools: Tool[] = [
|
|
|
91
92
|
recallTool,
|
|
92
93
|
credentialStoreTool,
|
|
93
94
|
notifyParentTool,
|
|
95
|
+
askQuestionTool,
|
|
94
96
|
// NOTE: external skill tools (registered via registerExternalTools in
|
|
95
97
|
// registry.ts) are intentionally NOT included here. `explicitTools` is a
|
|
96
98
|
// module-level const whose value is fixed at first evaluation, so
|
package/src/tools/types.ts
CHANGED
|
@@ -75,22 +75,25 @@ export { RiskLevel } from "@vellumai/skill-host-contracts";
|
|
|
75
75
|
// Assistant-side concrete overlays
|
|
76
76
|
// ---------------------------------------------------------------------------
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Public, narrow subset of {@link ToolExecutionResult} that plugin-authored
|
|
80
|
+
* tools are responsible for producing. Re-exported from
|
|
81
|
+
* `@vellumai/plugin-api` as `ToolExecutionResult` — the type name plugin
|
|
82
|
+
* authors actually import. The daemon-internal version below extends
|
|
83
|
+
* this and adds runtime-only fields (risk metadata, approval
|
|
84
|
+
* bookkeeping, sensitive-output bindings, etc.) that the executor
|
|
85
|
+
* populates around the call — plugins MUST NOT set those.
|
|
86
|
+
*
|
|
87
|
+
* Adding fields here is a non-breaking change; renaming or removing
|
|
88
|
+
* fields is breaking and gated on a major bump of `@vellumai/plugin-api`.
|
|
89
|
+
*/
|
|
90
|
+
export interface PluginToolExecutionResult {
|
|
91
|
+
/** Textual result shown to the model in the tool-result block. Empty string is valid. */
|
|
79
92
|
content: string;
|
|
93
|
+
/** When true, the agent loop treats `content` as an error and may surface it / retry. */
|
|
80
94
|
isError: boolean;
|
|
81
|
-
|
|
82
|
-
/** Optional status message for display (e.g. timeout, truncation). */
|
|
95
|
+
/** Optional short status message for client display (e.g. `"truncated"`, `"timed out"`). */
|
|
83
96
|
status?: string;
|
|
84
|
-
/** Optional rich content blocks (e.g. images) to include alongside text in the tool result. */
|
|
85
|
-
contentBlocks?: ContentBlock[];
|
|
86
|
-
/**
|
|
87
|
-
* Runtime-internal sensitive output bindings (placeholder -> real value).
|
|
88
|
-
* Populated by the executor when tool output contains
|
|
89
|
-
* `<vellum-sensitive-output>` directives. The agent loop merges these
|
|
90
|
-
* into a per-run substitution map for deterministic post-generation
|
|
91
|
-
* replacement. MUST NOT be emitted in client-facing events or logs.
|
|
92
|
-
*/
|
|
93
|
-
sensitiveBindings?: SensitiveOutputBinding[];
|
|
94
97
|
/**
|
|
95
98
|
* When true, the agent loop should yield control back to the user after
|
|
96
99
|
* returning this result — tool results are pushed to history and the loop
|
|
@@ -101,6 +104,20 @@ export interface ToolExecutionResult {
|
|
|
101
104
|
* the LLM voluntarily end its turn.
|
|
102
105
|
*/
|
|
103
106
|
yieldToUser?: boolean;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface ToolExecutionResult extends PluginToolExecutionResult {
|
|
110
|
+
diff?: DiffInfo;
|
|
111
|
+
/** Optional rich content blocks (e.g. images) to include alongside text in the tool result. */
|
|
112
|
+
contentBlocks?: ContentBlock[];
|
|
113
|
+
/**
|
|
114
|
+
* Runtime-internal sensitive output bindings (placeholder -> real value).
|
|
115
|
+
* Populated by the executor when tool output contains
|
|
116
|
+
* `<vellum-sensitive-output>` directives. The agent loop merges these
|
|
117
|
+
* into a per-run substitution map for deterministic post-generation
|
|
118
|
+
* replacement. MUST NOT be emitted in client-facing events or logs.
|
|
119
|
+
*/
|
|
120
|
+
sensitiveBindings?: SensitiveOutputBinding[];
|
|
104
121
|
/** Risk level from the classifier (populated during permission check). */
|
|
105
122
|
riskLevel?: string;
|
|
106
123
|
/** Human-readable reason for the risk classification. */
|
|
@@ -190,19 +207,37 @@ export type ToolLifecycleEventHandler = (
|
|
|
190
207
|
event: ToolLifecycleEvent,
|
|
191
208
|
) => void | Promise<void>;
|
|
192
209
|
|
|
193
|
-
|
|
194
|
-
|
|
210
|
+
/**
|
|
211
|
+
* Public, narrow subset of {@link ToolContext} handed to plugin-authored
|
|
212
|
+
* tools. Re-exported from `@vellumai/plugin-api` as `ToolContext` — the
|
|
213
|
+
* type name plugin authors actually import. The daemon-internal version
|
|
214
|
+
* below extends this and adds host-only fields (CES client, trust class,
|
|
215
|
+
* lifecycle handlers, requester metadata, host-bash proxy, etc.). Plugin
|
|
216
|
+
* tools see this shape only — the runtime still hands them the full
|
|
217
|
+
* {@link ToolContext} value, but the structural extension here guarantees
|
|
218
|
+
* the assignment without a manual cast.
|
|
219
|
+
*
|
|
220
|
+
* Adding fields here is a non-breaking change; renaming or removing
|
|
221
|
+
* fields is breaking and gated on a major bump of `@vellumai/plugin-api`.
|
|
222
|
+
*/
|
|
223
|
+
export interface PluginToolContext {
|
|
224
|
+
/** Identifier of the conversation this tool invocation belongs to. */
|
|
195
225
|
conversationId: string;
|
|
226
|
+
/** Working directory the daemon was launched from. */
|
|
227
|
+
workingDir: string;
|
|
228
|
+
/** Per-turn request id for cross-component log correlation. */
|
|
229
|
+
requestId?: string;
|
|
230
|
+
/** Cooperative cancellation signal for long-running tools. Tools should check `signal.aborted` periodically (or forward `signal` to fetch / child-process options). */
|
|
231
|
+
signal?: AbortSignal;
|
|
232
|
+
/** Optional incremental-output callback for streaming tools. Streaming tools should fall back to returning the full result in `content` when this is absent. */
|
|
233
|
+
onOutput?: (chunk: string) => void;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface ToolContext extends PluginToolContext {
|
|
196
237
|
/** Logical assistant scope for multi-assistant routing. */
|
|
197
238
|
assistantId?: string;
|
|
198
239
|
/** When set, the tool execution is part of a task run. Used to retrieve ephemeral permission rules. */
|
|
199
240
|
taskRunId?: string;
|
|
200
|
-
/** Per-message request ID for log correlation across conversation/connection boundaries. */
|
|
201
|
-
requestId?: string;
|
|
202
|
-
/** Optional callback for streaming incremental output to the client. */
|
|
203
|
-
onOutput?: (chunk: string) => void;
|
|
204
|
-
/** Abort signal for cooperative cancellation. Tools should check this periodically. */
|
|
205
|
-
signal?: AbortSignal;
|
|
206
241
|
/** Optional callback for tool lifecycle events (start/prompt/deny/execute/error). */
|
|
207
242
|
onToolLifecycleEvent?: ToolLifecycleEventHandler;
|
|
208
243
|
/** Optional resolver for proxy tools - delegates execution to an external client. */
|
|
@@ -338,3 +373,19 @@ export interface Tool {
|
|
|
338
373
|
context: ToolContext,
|
|
339
374
|
): Promise<ToolExecutionResult>;
|
|
340
375
|
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Plugin-facing tool shape. The narrow surface plugin authors implement;
|
|
379
|
+
* differs from {@link Tool} in three ways:
|
|
380
|
+
* - Plugins declare `input_schema` as a top-level field instead of
|
|
381
|
+
* implementing `getDefinition()`. The registration boundary synthesizes
|
|
382
|
+
* `getDefinition()` from `{name, description, input_schema}` before the
|
|
383
|
+
* tool enters the internal registry.
|
|
384
|
+
* - `category` is registry-owned and stamped to `"plugin"` when the tool is
|
|
385
|
+
* registered.
|
|
386
|
+
* - All ownership stamps (`origin`, `ownerPluginId`, etc.) are set
|
|
387
|
+
* authoritatively by the bootstrap; plugin authors leave them blank.
|
|
388
|
+
*/
|
|
389
|
+
export type PluginTool = Omit<Tool, "category" | "getDefinition"> & {
|
|
390
|
+
input_schema: object;
|
|
391
|
+
};
|
|
@@ -28,7 +28,7 @@ function proxyExecute(): Promise<ToolExecutionResult> {
|
|
|
28
28
|
export const uiShowTool: Tool = {
|
|
29
29
|
name: "ui_show",
|
|
30
30
|
description:
|
|
31
|
-
"
|
|
31
|
+
"Surface structured data or UI in the conversation. For long-form writing use the document skill; for interactive apps use the app-builder skill.\n\n" +
|
|
32
32
|
"Surface types (data shapes):\n" +
|
|
33
33
|
'- card: { title, subtitle?, body, metadata?: [{ label, value }], template?, templateData? }. Templates: "weather_forecast" (native weather widget), "task_progress" (live step tracker - update via ui_update on data.templateData; shape: { title, status: "in_progress"|"completed"|"failed", steps: [{ label, status: "pending"|"in_progress"|"completed"|"failed", detail? }] })\n' +
|
|
34
34
|
'- table: { columns: [{ id, label }], rows: [{ id, cells: Record<id, string | { text, icon?, iconColor?: "success"|"warning"|"error"|"muted" }>, selectable?, selected? }], selectionMode?: "none"|"single"|"multiple", caption? }\n' +
|
|
@@ -36,7 +36,8 @@ export const uiShowTool: Tool = {
|
|
|
36
36
|
'- list: { items: [{ id, title, subtitle?, icon?, selected? }], selectionMode: "single"|"multiple"|"none" }\n' +
|
|
37
37
|
"- confirmation: { message, detail?, confirmLabel?, confirmedLabel?, cancelLabel?, destructive? }\n" +
|
|
38
38
|
"- dynamic_page: { html, width?, height?, preview?: { title, subtitle?, description?, icon?, metrics?: [{ label, value }] } }\n" +
|
|
39
|
-
"- file_upload: { prompt, acceptedTypes?, maxFiles? }"
|
|
39
|
+
"- file_upload: { prompt, acceptedTypes?, maxFiles? }\n\n" +
|
|
40
|
+
"Proactively show a task_progress card before multi-step or long-running work (web searches, file operations, research). Show it before your first tool call, then update steps as work progresses.",
|
|
40
41
|
category: "ui-surface",
|
|
41
42
|
defaultRiskLevel: RiskLevel.Low,
|
|
42
43
|
executionMode: "proxy",
|
|
@@ -91,17 +92,17 @@ export const uiShowTool: Tool = {
|
|
|
91
92
|
type: "string",
|
|
92
93
|
enum: ["inline", "panel"],
|
|
93
94
|
description:
|
|
94
|
-
'Where to render the surface. "inline" embeds it in the chat message. "panel" shows a floating window. Defaults to "inline". Prefer inline — only use panel when
|
|
95
|
+
'Where to render the surface. "inline" embeds it in the chat message. "panel" shows a floating window. Defaults to "inline". Prefer inline — only use panel when a separate window is explicitly requested.',
|
|
95
96
|
},
|
|
96
97
|
await_action: {
|
|
97
98
|
type: "boolean",
|
|
98
99
|
description:
|
|
99
|
-
"Whether to block until
|
|
100
|
+
"Whether to block until an action is selected. Defaults to true when actions are provided.",
|
|
100
101
|
},
|
|
101
102
|
persistent: {
|
|
102
103
|
type: "boolean",
|
|
103
104
|
description:
|
|
104
|
-
"When true, clicking an action does not dismiss the surface — the card stays visible and only the clicked action is marked as spent. Use for launcher or menu-style cards where
|
|
105
|
+
"When true, clicking an action does not dismiss the surface — the card stays visible and only the clicked action is marked as spent. Use for launcher or menu-style cards where multiple buttons may be clicked. Defaults to false.",
|
|
105
106
|
},
|
|
106
107
|
},
|
|
107
108
|
required: ["surface_type", "data"],
|
|
@@ -114,8 +114,11 @@ import {
|
|
|
114
114
|
createDeepgramProvider,
|
|
115
115
|
DeepgramTtsError,
|
|
116
116
|
} from "../providers/deepgram-provider.js";
|
|
117
|
-
import {
|
|
118
|
-
|
|
117
|
+
import {
|
|
118
|
+
createElevenLabsProvider,
|
|
119
|
+
ElevenLabsTtsError,
|
|
120
|
+
extractElevenLabsErrorMessage,
|
|
121
|
+
} from "../providers/elevenlabs-provider.js";
|
|
119
122
|
import { createFishAudioProvider } from "../providers/fish-audio-provider.js";
|
|
120
123
|
import { FishAudioTtsError } from "../providers/fish-audio-provider.js";
|
|
121
124
|
import { providerFactories } from "../providers/index.js";
|
|
@@ -396,6 +399,77 @@ describe("ElevenLabs TTS provider adapter", () => {
|
|
|
396
399
|
);
|
|
397
400
|
}
|
|
398
401
|
});
|
|
402
|
+
|
|
403
|
+
// -- Upstream error-body extraction --------------------------------------
|
|
404
|
+
|
|
405
|
+
describe("extractElevenLabsErrorMessage", () => {
|
|
406
|
+
test("extracts message from standard { detail: { message } } shape", () => {
|
|
407
|
+
const body = JSON.stringify({
|
|
408
|
+
detail: {
|
|
409
|
+
type: "payment_required",
|
|
410
|
+
code: "paid_plan_required",
|
|
411
|
+
message:
|
|
412
|
+
"Free users cannot use library voices via the API. Please upgrade your subscription to use this voice.",
|
|
413
|
+
status: "payment_required",
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
expect(extractElevenLabsErrorMessage(body)).toBe(
|
|
417
|
+
"Free users cannot use library voices via the API. Please upgrade your subscription to use this voice.",
|
|
418
|
+
);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
test("falls back to { detail: '...' } when detail is a string", () => {
|
|
422
|
+
const body = JSON.stringify({ detail: "Voice not found" });
|
|
423
|
+
expect(extractElevenLabsErrorMessage(body)).toBe("Voice not found");
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
test("falls back to { message: '...' } when present", () => {
|
|
427
|
+
const body = JSON.stringify({ message: "Quota exceeded" });
|
|
428
|
+
expect(extractElevenLabsErrorMessage(body)).toBe("Quota exceeded");
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
test("returns trimmed raw body when not JSON", () => {
|
|
432
|
+
expect(extractElevenLabsErrorMessage(" upstream timeout ")).toBe(
|
|
433
|
+
"upstream timeout",
|
|
434
|
+
);
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
test("truncates oversized raw bodies", () => {
|
|
438
|
+
const long = "x".repeat(1000);
|
|
439
|
+
const result = extractElevenLabsErrorMessage(long);
|
|
440
|
+
expect(result).not.toBeUndefined();
|
|
441
|
+
// 200-char limit plus an ellipsis character.
|
|
442
|
+
expect(result!.length).toBeLessThanOrEqual(201);
|
|
443
|
+
expect(result!.endsWith("…")).toBe(true);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
test("returns undefined for empty input", () => {
|
|
447
|
+
expect(extractElevenLabsErrorMessage("")).toBeUndefined();
|
|
448
|
+
expect(extractElevenLabsErrorMessage(" \n ")).toBeUndefined();
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
test("returns truncated raw body when JSON is malformed", () => {
|
|
452
|
+
// Not valid JSON despite the leading `{` — falls through to raw fallback.
|
|
453
|
+
const body = "{not really json}";
|
|
454
|
+
expect(extractElevenLabsErrorMessage(body)).toBe("{not really json}");
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
test("ignores empty-string message fields", () => {
|
|
458
|
+
const body = JSON.stringify({ detail: { message: " " } });
|
|
459
|
+
// Falls through to top-level message — also absent — then to raw body.
|
|
460
|
+
const result = extractElevenLabsErrorMessage(body);
|
|
461
|
+
expect(result).not.toBeUndefined();
|
|
462
|
+
// Raw body fallback contains the JSON text itself.
|
|
463
|
+
expect(result).toContain("detail");
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
test("trims whitespace from extracted messages", () => {
|
|
467
|
+
const body = JSON.stringify({
|
|
468
|
+
detail: { message: " hello world " },
|
|
469
|
+
});
|
|
470
|
+
expect(extractElevenLabsErrorMessage(body)).toBe("hello world");
|
|
471
|
+
});
|
|
472
|
+
});
|
|
399
473
|
});
|
|
400
474
|
|
|
401
475
|
// ===========================================================================
|
|
@@ -49,6 +49,73 @@ export class ElevenLabsTtsError extends Error {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Error-body parser
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
/** Maximum number of characters of a fallback raw body to surface in an error message. */
|
|
57
|
+
const MAX_RAW_ERROR_BODY_CHARS = 200;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Best-effort extraction of a user-facing error message from an ElevenLabs
|
|
61
|
+
* error response body.
|
|
62
|
+
*
|
|
63
|
+
* ElevenLabs returns structured errors in the shape:
|
|
64
|
+
* ```json
|
|
65
|
+
* { "detail": { "status": "...", "code": "...", "message": "..." } }
|
|
66
|
+
* ```
|
|
67
|
+
* but also occasionally returns `{ "message": "..." }`, `{ "detail": "..." }`,
|
|
68
|
+
* HTML pages (502/503 from their CDN), or free-form text. We try the
|
|
69
|
+
* structured shapes first, fall back to a trimmed/truncated raw body, and
|
|
70
|
+
* return `undefined` when nothing useful is present.
|
|
71
|
+
*
|
|
72
|
+
* Exported for unit testing.
|
|
73
|
+
*/
|
|
74
|
+
export function extractElevenLabsErrorMessage(
|
|
75
|
+
body: string,
|
|
76
|
+
): string | undefined {
|
|
77
|
+
if (!body) return undefined;
|
|
78
|
+
const trimmed = body.trim();
|
|
79
|
+
if (!trimmed) return undefined;
|
|
80
|
+
|
|
81
|
+
// Try JSON envelopes first.
|
|
82
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(trimmed) as unknown;
|
|
85
|
+
if (parsed && typeof parsed === "object") {
|
|
86
|
+
const root = parsed as { detail?: unknown; message?: unknown };
|
|
87
|
+
|
|
88
|
+
// Standard ElevenLabs shape: { detail: { message } }
|
|
89
|
+
if (root.detail && typeof root.detail === "object") {
|
|
90
|
+
const detailMessage = (root.detail as { message?: unknown }).message;
|
|
91
|
+
if (typeof detailMessage === "string" && detailMessage.trim()) {
|
|
92
|
+
return detailMessage.trim();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Fallback shape: { detail: "..." }
|
|
97
|
+
if (typeof root.detail === "string" && root.detail.trim()) {
|
|
98
|
+
return root.detail.trim();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Fallback shape: { message: "..." }
|
|
102
|
+
if (typeof root.message === "string" && root.message.trim()) {
|
|
103
|
+
return root.message.trim();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
} catch {
|
|
107
|
+
// Not valid JSON — fall through to the raw-body fallback.
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Raw body fallback (HTML pages, plain text). Truncate to keep error
|
|
112
|
+
// messages reasonable when surfaced to UI clients.
|
|
113
|
+
if (trimmed.length > MAX_RAW_ERROR_BODY_CHARS) {
|
|
114
|
+
return `${trimmed.slice(0, MAX_RAW_ERROR_BODY_CHARS)}…`;
|
|
115
|
+
}
|
|
116
|
+
return trimmed;
|
|
117
|
+
}
|
|
118
|
+
|
|
52
119
|
// ---------------------------------------------------------------------------
|
|
53
120
|
// Constants
|
|
54
121
|
// ---------------------------------------------------------------------------
|
|
@@ -180,9 +247,16 @@ export function createElevenLabsProvider(): TtsProvider {
|
|
|
180
247
|
|
|
181
248
|
if (!response.ok) {
|
|
182
249
|
const errorText = await response.text().catch(() => "");
|
|
250
|
+
// Surface the upstream provider message verbatim when extractable —
|
|
251
|
+
// the daemon route wraps it with a single "TTS synthesis failed:"
|
|
252
|
+
// prefix on the way out. The HTTP status is preserved on `statusCode`
|
|
253
|
+
// and logged by the daemon, so we don't embed it in the message text.
|
|
254
|
+
const message =
|
|
255
|
+
extractElevenLabsErrorMessage(errorText) ??
|
|
256
|
+
`ElevenLabs returned HTTP ${response.status}`;
|
|
183
257
|
throw new ElevenLabsTtsError(
|
|
184
258
|
"ELEVENLABS_TTS_HTTP_ERROR",
|
|
185
|
-
|
|
259
|
+
message,
|
|
186
260
|
response.status,
|
|
187
261
|
);
|
|
188
262
|
}
|