@vellumai/assistant 0.6.2 → 0.6.4
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 +273 -10
- package/Dockerfile +2 -3
- package/bun.lock +41 -49
- package/bunfig.toml +3 -0
- package/docs/architecture/memory.md +1 -1
- package/docs/backup-troubleshooting.md +52 -0
- package/docs/browser-use-architecture-phase2.md +174 -0
- package/docs/stt-provider-onboarding.md +120 -0
- package/knip.json +12 -2
- package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
- package/node_modules/@vellumai/ces-contracts/package.json +3 -3
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
- package/openapi.yaml +1111 -86
- package/package.json +40 -42
- package/scripts/generate-openapi.ts +0 -2
- package/scripts/test.sh +73 -18
- package/src/__tests__/acp-session.test.ts +43 -0
- package/src/__tests__/agent-image-optimize.test.ts +28 -0
- package/src/__tests__/agent-loop.test.ts +123 -0
- package/src/__tests__/anthropic-provider.test.ts +263 -10
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +1 -0
- package/src/__tests__/app-source-watcher.test.ts +37 -11
- package/src/__tests__/approval-routes-http.test.ts +178 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
- package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
- package/src/__tests__/browser-fill-credential.test.ts +240 -94
- package/src/__tests__/browser-manager.test.ts +40 -27
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/browser-skill-endstate.test.ts +31 -7
- package/src/__tests__/btw-routes.test.ts +7 -0
- package/src/__tests__/call-controller.test.ts +581 -20
- package/src/__tests__/catalog-files.test.ts +1000 -0
- package/src/__tests__/channel-approvals.test.ts +53 -0
- package/src/__tests__/channel-invite-transport.test.ts +2 -2
- package/src/__tests__/channel-readiness-routes.test.ts +16 -20
- package/src/__tests__/channel-readiness-service.test.ts +12 -7
- package/src/__tests__/checker.test.ts +157 -10
- package/src/__tests__/clawhub-files.test.ts +347 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
- package/src/__tests__/config-analysis.test.ts +100 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +1248 -224
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +43 -8
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
- package/src/__tests__/contact-store-user-file.test.ts +512 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- package/src/__tests__/context-overflow-approval.test.ts +16 -1
- package/src/__tests__/context-window-manager.test.ts +88 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop.test.ts +99 -3
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -2
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +290 -0
- package/src/__tests__/conversation-error.test.ts +70 -0
- package/src/__tests__/conversation-fork-crud.test.ts +17 -0
- package/src/__tests__/conversation-history-web-search.test.ts +12 -4
- package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
- package/src/__tests__/conversation-inject-context.test.ts +103 -0
- package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
- package/src/__tests__/conversation-list-source.test.ts +145 -0
- package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +946 -62
- package/src/__tests__/conversation-routes-disk-view.test.ts +275 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +324 -46
- package/src/__tests__/conversation-skill-tools.test.ts +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +33 -0
- package/src/__tests__/conversation-slash-queue.test.ts +89 -18
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-starter-routes.test.ts +126 -0
- package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
- package/src/__tests__/conversation-store.test.ts +195 -0
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -1
- package/src/__tests__/credential-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +6 -3
- package/src/__tests__/credential-vault-unit.test.ts +383 -7
- package/src/__tests__/credential-vault.test.ts +152 -13
- package/src/__tests__/credentials-cli.test.ts +42 -18
- package/src/__tests__/cross-provider-web-search.test.ts +146 -35
- package/src/__tests__/date-context.test.ts +4 -4
- package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
- package/src/__tests__/device-id.test.ts +112 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
- package/src/__tests__/email-html-renderer.test.ts +71 -0
- package/src/__tests__/email-invite-adapter.test.ts +36 -32
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
- package/src/__tests__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +222 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +386 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
- package/src/__tests__/gateway-only-guard.test.ts +2 -0
- package/src/__tests__/gemini-provider.test.ts +66 -2
- package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
- package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
- package/src/__tests__/gmail-archive-gate.test.ts +246 -0
- package/src/__tests__/gmail-preferences.test.ts +117 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
- package/src/__tests__/headless-browser-interactions.test.ts +738 -359
- package/src/__tests__/headless-browser-mode.test.ts +614 -0
- package/src/__tests__/headless-browser-navigate.test.ts +528 -49
- package/src/__tests__/headless-browser-read-tools.test.ts +274 -100
- package/src/__tests__/headless-browser-snapshot.test.ts +250 -77
- package/src/__tests__/heartbeat-service.test.ts +70 -17
- package/src/__tests__/home-state-routes.test.ts +162 -0
- package/src/__tests__/host-bash-proxy.test.ts +145 -1
- package/src/__tests__/host-browser-e2e-cloud.test.ts +596 -0
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
- package/src/__tests__/host-browser-event-routes.test.ts +350 -0
- package/src/__tests__/host-browser-proxy.test.ts +444 -0
- package/src/__tests__/host-browser-routes.test.ts +198 -0
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +423 -0
- package/src/__tests__/host-cu-proxy.test.ts +166 -1
- package/src/__tests__/host-file-proxy.test.ts +185 -1
- package/src/__tests__/host-file-read-tool.test.ts +52 -0
- package/src/__tests__/host-proxy-interface.test.ts +165 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -11
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/integration-status.test.ts +6 -7
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- package/src/__tests__/llm-context-normalization.test.ts +488 -0
- package/src/__tests__/llm-context-route-provider.test.ts +86 -5
- package/src/__tests__/llm-usage-store.test.ts +363 -0
- package/src/__tests__/mcp-client-auth.test.ts +40 -4
- package/src/__tests__/mcp-health-check.test.ts +10 -3
- package/src/__tests__/media-stream-output.test.ts +555 -0
- package/src/__tests__/media-stream-parser.test.ts +374 -0
- package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
- package/src/__tests__/media-stream-stt-session.test.ts +588 -0
- package/src/__tests__/media-turn-detector.test.ts +440 -0
- package/src/__tests__/message-queue.test.ts +125 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +67 -8
- package/src/__tests__/migration-export-streaming.test.ts +66 -0
- package/src/__tests__/migration-import-commit-http.test.ts +109 -7
- package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +151 -0
- package/src/__tests__/model-intents.test.ts +2 -2
- package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
- package/src/__tests__/oauth-apps-routes.test.ts +18 -12
- package/src/__tests__/oauth-cli.test.ts +709 -60
- package/src/__tests__/oauth-connect-orchestrator.test.ts +118 -24
- package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +147 -10
- package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
- package/src/__tests__/oauth-providers-routes.test.ts +52 -14
- package/src/__tests__/oauth-store.test.ts +1465 -176
- package/src/__tests__/oauth2-gateway-transport.test.ts +460 -26
- package/src/__tests__/onboarding-template-contract.test.ts +81 -70
- package/src/__tests__/openai-provider.test.ts +178 -2
- package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
- package/src/__tests__/openai-responses-provider.test.ts +1105 -0
- package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
- package/src/__tests__/outlook-categories.test.ts +1 -1
- package/src/__tests__/outlook-client-automation.test.ts +1 -1
- package/src/__tests__/outlook-compose-tools.test.ts +1 -1
- package/src/__tests__/outlook-email-watcher.test.ts +1 -1
- package/src/__tests__/outlook-follow-up.test.ts +1 -1
- package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
- package/src/__tests__/outlook-trash.test.ts +1 -1
- package/src/__tests__/outlook-unsubscribe.test.ts +32 -3
- package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
- package/src/__tests__/permission-mode.test.ts +28 -56
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
- package/src/__tests__/platform-callback-registration.test.ts +19 -0
- package/src/__tests__/platform.test.ts +92 -1
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +343 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
- package/src/__tests__/pricing.test.ts +174 -0
- package/src/__tests__/proxy-approval-callback.test.ts +18 -0
- package/src/__tests__/qdrant-manager.test.ts +29 -8
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
- package/src/__tests__/relationship-state-contract.test.ts +175 -0
- package/src/__tests__/relay-server.test.ts +423 -5
- package/src/__tests__/require-fresh-approval.test.ts +40 -1
- package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
- package/src/__tests__/schedule-routes.test.ts +162 -0
- package/src/__tests__/search-skills-unified.test.ts +118 -0
- package/src/__tests__/secret-detection-handler.test.ts +84 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/secret-scanner-executor.test.ts +4 -0
- package/src/__tests__/secure-keys.test.ts +107 -0
- package/src/__tests__/send-endpoint-busy.test.ts +8 -1
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +49 -0
- package/src/__tests__/set-permission-mode.test.ts +13 -250
- package/src/__tests__/settings-routes.test.ts +201 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +801 -0
- package/src/__tests__/skills-files-catalog-fallback.test.ts +738 -0
- package/src/__tests__/skills.test.ts +5 -2
- package/src/__tests__/skillssh-files.test.ts +446 -0
- package/src/__tests__/slack-block-formatting.test.ts +110 -0
- package/src/__tests__/slack-channel-config.test.ts +576 -16
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/subagent-detail.test.ts +44 -2
- package/src/__tests__/subagent-disposal.test.ts +1 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
- package/src/__tests__/subagent-manager-notify.test.ts +1 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/subagent-types.test.ts +1 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
- package/src/__tests__/system-prompt.test.ts +184 -27
- package/src/__tests__/task-scheduler.test.ts +32 -6
- package/src/__tests__/telegram-config.test.ts +10 -13
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +25 -5
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
- package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
- package/src/__tests__/tool-executor.test.ts +33 -24
- package/src/__tests__/tool-result-truncation.test.ts +36 -0
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
- package/src/__tests__/top-level-renderer.test.ts +73 -1
- package/src/__tests__/transport-hints-queue.test.ts +14 -29
- package/src/__tests__/trust-store.test.ts +7 -1
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/tts-catalog-parity.test.ts +345 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
- package/src/__tests__/twilio-routes.test.ts +376 -0
- package/src/__tests__/unicode.test.ts +293 -0
- package/src/__tests__/update-bulletin-format.test.ts +59 -0
- package/src/__tests__/update-bulletin.test.ts +206 -5
- package/src/__tests__/usage-routes.test.ts +25 -4
- package/src/__tests__/user-reference.test.ts +46 -61
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
- package/src/__tests__/voice-config-update.test.ts +403 -0
- package/src/__tests__/voice-quality.test.ts +434 -19
- package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
- package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
- package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
- package/src/__tests__/workspace-migration-meets.test.ts +244 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
- package/src/__tests__/workspace-policy.test.ts +2 -0
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +55 -9
- package/src/approvals/guardian-request-resolvers.ts +21 -15
- package/src/backup/__tests__/backup-key.test.ts +152 -0
- package/src/backup/__tests__/backup-worker.test.ts +767 -0
- package/src/backup/__tests__/list-snapshots.test.ts +87 -0
- package/src/backup/__tests__/local-writer.test.ts +218 -0
- package/src/backup/__tests__/offsite-writer.test.ts +641 -0
- package/src/backup/__tests__/paths.test.ts +300 -0
- package/src/backup/__tests__/restore.test.ts +498 -0
- package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
- package/src/backup/__tests__/stream-crypt.test.ts +228 -0
- package/src/backup/backup-key.ts +137 -0
- package/src/backup/backup-worker.ts +459 -0
- package/src/backup/list-snapshots.ts +147 -0
- package/src/backup/local-writer.ts +133 -0
- package/src/backup/offsite-writer.ts +222 -0
- package/src/backup/paths.ts +226 -0
- package/src/backup/restore.ts +322 -0
- package/src/backup/snapshot-lock.ts +431 -0
- package/src/backup/stream-crypt.ts +263 -0
- package/src/browser-session/__tests__/manager.test.ts +297 -0
- package/src/browser-session/backends/cdp-inspect.ts +30 -0
- package/src/browser-session/backends/extension.ts +26 -0
- package/src/browser-session/backends/local.ts +24 -0
- package/src/browser-session/events.ts +164 -0
- package/src/browser-session/index.ts +27 -0
- package/src/browser-session/manager.ts +159 -0
- package/src/browser-session/types.ts +28 -0
- package/src/bundler/package-resolver.ts +4 -0
- package/src/calls/audio-store.ts +11 -5
- package/src/calls/call-controller.ts +226 -71
- package/src/calls/call-domain.ts +9 -0
- package/src/calls/call-speech-output.ts +190 -0
- package/src/calls/call-transport.ts +77 -0
- package/src/calls/media-stream-audio-transcode.ts +173 -0
- package/src/calls/media-stream-output.ts +660 -0
- package/src/calls/media-stream-parser.ts +300 -0
- package/src/calls/media-stream-protocol.ts +166 -0
- package/src/calls/media-stream-server.ts +592 -0
- package/src/calls/media-stream-stt-session.ts +460 -0
- package/src/calls/media-turn-detector.ts +230 -0
- package/src/calls/relay-server.ts +90 -75
- package/src/calls/resolve-call-tts-provider.ts +136 -0
- package/src/calls/telephony-stt-routing.ts +145 -0
- package/src/calls/tts-call-strategy.ts +161 -0
- package/src/calls/tts-text-sanitizer.ts +32 -16
- package/src/calls/twilio-routes.ts +281 -17
- package/src/calls/voice-quality.ts +78 -35
- package/src/calls/voice-session-bridge.ts +8 -1
- package/src/channels/__tests__/types.test.ts +134 -0
- package/src/channels/types.ts +69 -3
- package/src/cli/__tests__/run-assistant-command.ts +11 -1
- package/src/cli/commands/__tests__/backup.test.ts +1165 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
- package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
- package/src/cli/commands/__tests__/email-download.test.ts +16 -1
- package/src/cli/commands/__tests__/email-list.test.ts +22 -4
- package/src/cli/commands/__tests__/email-register.test.ts +4 -4
- package/src/cli/commands/__tests__/email-send.test.ts +37 -4
- package/src/cli/commands/__tests__/email-status.test.ts +5 -1
- package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
- package/src/cli/commands/backup.ts +993 -0
- package/src/cli/commands/conversations.ts +77 -0
- package/src/cli/commands/credentials.ts +3 -4
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +273 -16
- package/src/cli/commands/mcp.ts +16 -4
- package/src/cli/commands/oauth/__tests__/connect.test.ts +56 -44
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
- package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
- package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +32 -33
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +330 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +117 -12
- package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
- package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
- package/src/cli/commands/oauth/apps.ts +7 -4
- package/src/cli/commands/oauth/connect.ts +6 -3
- package/src/cli/commands/oauth/disconnect.ts +1 -1
- package/src/cli/commands/oauth/mode.ts +12 -3
- package/src/cli/commands/oauth/providers.ts +215 -36
- package/src/cli/commands/oauth/shared.ts +7 -6
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +254 -0
- package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
- package/src/cli/commands/platform/index.ts +107 -10
- package/src/cli/commands/usage.ts +10 -9
- package/src/cli/lib/daemon-credential-client.ts +4 -0
- package/src/cli/program.ts +30 -4
- package/src/config/__tests__/backup-schema.test.ts +134 -0
- package/src/config/assistant-feature-flags.ts +61 -62
- package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +141 -0
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
- package/src/config/bundled-skills/browser/SKILL.md +30 -5
- package/src/config/bundled-skills/browser/TOOLS.json +123 -0
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
- package/src/config/bundled-skills/contacts/SKILL.md +5 -2
- package/src/config/bundled-skills/document/SKILL.md +4 -0
- package/src/config/bundled-skills/gmail/SKILL.md +54 -8
- package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
- package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
- package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
- package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
- package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
- package/src/config/bundled-skills/outlook/SKILL.md +9 -2
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
- package/src/config/bundled-skills/slack/SKILL.md +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +21 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
- package/src/config/bundled-skills/tasks/SKILL.md +5 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
- package/src/config/bundled-tool-registry.ts +8 -0
- package/src/config/env-registry.ts +38 -0
- package/src/config/env.ts +49 -4
- package/src/config/feature-flag-registry.json +85 -14
- package/src/config/loader.ts +82 -13
- package/src/config/sanitize-for-transfer.ts +47 -0
- package/src/config/schema.ts +81 -15
- package/src/config/schemas/__tests__/stt.test.ts +43 -0
- package/src/config/schemas/analysis.ts +51 -0
- package/src/config/schemas/backup.ts +72 -0
- package/src/config/schemas/calls.ts +1 -26
- package/src/config/schemas/elevenlabs.ts +0 -59
- package/src/config/schemas/filing.ts +47 -7
- package/src/config/schemas/heartbeat.ts +27 -5
- package/src/config/schemas/host-browser.ts +112 -0
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/memory-retrieval.ts +103 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +52 -0
- package/src/config/schemas/stt.ts +59 -0
- package/src/config/schemas/tts.ts +230 -0
- package/src/config/schemas/updates.ts +14 -0
- package/src/config/skills.ts +4 -0
- package/src/config/types.ts +4 -1
- package/src/contacts/contact-store.ts +56 -11
- package/src/contacts/contacts-write.ts +38 -1
- package/src/context/post-turn-tool-result-truncation.ts +177 -0
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +61 -10
- package/src/credential-execution/approval-bridge.ts +49 -15
- package/src/credential-execution/executable-discovery.ts +12 -2
- package/src/credential-execution/process-manager.ts +33 -2
- package/src/credential-health/credential-health-service.ts +366 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +195 -0
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/config-watcher.ts +99 -5
- package/src/daemon/context-overflow-approval.ts +5 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +23 -2
- package/src/daemon/conversation-agent-loop.ts +153 -42
- package/src/daemon/conversation-attachments.ts +40 -0
- package/src/daemon/conversation-error.ts +11 -0
- package/src/daemon/conversation-history.ts +40 -6
- package/src/daemon/conversation-launch.ts +220 -0
- package/src/daemon/conversation-lifecycle.ts +59 -9
- package/src/daemon/conversation-messaging.ts +37 -3
- package/src/daemon/conversation-notifiers.ts +5 -0
- package/src/daemon/conversation-process.ts +622 -13
- package/src/daemon/conversation-queue-manager.ts +24 -0
- package/src/daemon/conversation-runtime-assembly.ts +128 -36
- package/src/daemon/conversation-slash.ts +36 -0
- package/src/daemon/conversation-surfaces.ts +131 -40
- package/src/daemon/conversation-tool-setup.ts +99 -8
- package/src/daemon/conversation-usage.ts +7 -4
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +292 -16
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +13 -141
- package/src/daemon/handlers/shared.ts +80 -0
- package/src/daemon/handlers/skills.ts +483 -44
- package/src/daemon/host-bash-proxy.ts +48 -13
- package/src/daemon/host-browser-proxy.ts +192 -0
- package/src/daemon/host-cu-proxy.ts +36 -11
- package/src/daemon/host-file-proxy.ts +57 -9
- package/src/daemon/lifecycle.ts +179 -28
- package/src/daemon/message-protocol.ts +13 -0
- package/src/daemon/message-types/conversations.ts +89 -14
- package/src/daemon/message-types/home.ts +40 -0
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/meet.ts +143 -0
- package/src/daemon/message-types/messages.ts +19 -5
- package/src/daemon/message-types/schedules.ts +34 -2
- package/src/daemon/message-types/skills.ts +26 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/server.ts +439 -14
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +15 -0
- package/src/daemon/transport-hints.ts +5 -24
- package/src/email/html-renderer.ts +76 -0
- package/src/heartbeat/heartbeat-service.ts +93 -7
- package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
- package/src/home/__tests__/emit-feed-event.test.ts +169 -0
- package/src/home/__tests__/feed-scheduler.test.ts +194 -0
- package/src/home/__tests__/feed-types.test.ts +275 -0
- package/src/home/__tests__/feed-writer.test.ts +688 -0
- package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
- package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
- package/src/home/__tests__/progress-formula.test.ts +213 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
- package/src/home/__tests__/rollup-producer.test.ts +398 -0
- package/src/home/assistant-feed-authoring.ts +124 -0
- package/src/home/emit-feed-event.ts +158 -0
- package/src/home/feed-scheduler.ts +247 -0
- package/src/home/feed-types.ts +181 -0
- package/src/home/feed-writer.ts +469 -0
- package/src/home/platform-gmail-digest.ts +163 -0
- package/src/home/progress-formula.ts +86 -0
- package/src/home/relationship-state-writer.ts +824 -0
- package/src/home/relationship-state.ts +143 -0
- package/src/home/rollup-producer.ts +384 -0
- package/src/hooks/runner.ts +7 -0
- package/src/inbound/platform-callback-registration.ts +30 -20
- package/src/inbound/public-ingress-urls.ts +12 -0
- package/src/instrument.ts +1 -1
- package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
- package/src/ipc/cli-client.ts +151 -0
- package/src/ipc/cli-server.ts +234 -0
- package/src/ipc/gateway-client.ts +180 -0
- package/src/ipc/routes/index.ts +5 -0
- package/src/ipc/routes/wake-conversation.ts +19 -0
- package/src/mcp/client.ts +59 -24
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
- package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
- package/src/memory/app-store.ts +31 -1
- package/src/memory/attachments-store.ts +70 -0
- package/src/memory/auto-analysis-enqueue.ts +127 -0
- package/src/memory/auto-analysis-guard.ts +27 -0
- package/src/memory/cleanup-schedule-state.ts +37 -0
- package/src/memory/conversation-analyze-job.ts +73 -0
- package/src/memory/conversation-crud.ts +122 -0
- package/src/memory/conversation-disk-view.ts +7 -0
- package/src/memory/conversation-group-migration.ts +34 -2
- package/src/memory/conversation-queries.ts +6 -5
- package/src/memory/conversation-starters-cadence.ts +76 -0
- package/src/memory/conversation-title-service.ts +5 -2
- package/src/memory/db-init.ts +18 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/embedding-backend.test.ts +75 -0
- package/src/memory/embedding-backend.ts +131 -5
- package/src/memory/embedding-gemini.test.ts +54 -0
- package/src/memory/embedding-gemini.ts +20 -9
- package/src/memory/embedding-local.ts +176 -17
- package/src/memory/graph/consolidation.ts +10 -23
- package/src/memory/graph/conversation-graph-memory.ts +15 -0
- package/src/memory/graph/extraction-job.ts +15 -0
- package/src/memory/graph/extraction.test.ts +23 -0
- package/src/memory/graph/extraction.ts +8 -0
- package/src/memory/graph/retriever.ts +67 -40
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- package/src/memory/graph/store.test.ts +7 -3
- package/src/memory/graph/store.ts +47 -12
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/group-crud.ts +6 -1
- package/src/memory/indexer.ts +95 -16
- package/src/memory/job-handlers/cleanup.ts +11 -8
- package/src/memory/job-handlers/conversation-starters.ts +16 -10
- package/src/memory/jobs-store.ts +64 -4
- package/src/memory/jobs-worker.ts +22 -9
- package/src/memory/llm-usage-store.ts +137 -60
- package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
- package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
- package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
- package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
- package/src/memory/migrations/217-conversation-host-access.ts +40 -0
- package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
- package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
- package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
- package/src/memory/migrations/index.ts +12 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/qdrant-manager.ts +43 -16
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/oauth.ts +21 -13
- package/src/memory/usage-buckets.ts +396 -0
- package/src/messaging/providers/gmail/client.ts +57 -6
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
- package/src/messaging/providers/slack/adapter.ts +143 -38
- package/src/messaging/providers/slack/client.ts +16 -0
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/notifications/decision-engine.ts +3 -3
- package/src/notifications/signal.ts +5 -0
- package/src/oauth/AGENTS.md +76 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +25 -19
- package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
- package/src/oauth/byo-connection.test.ts +26 -9
- package/src/oauth/byo-connection.ts +10 -8
- package/src/oauth/connect-orchestrator.ts +25 -21
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/connection-resolver.test.ts +17 -4
- package/src/oauth/connection-resolver.ts +22 -18
- package/src/oauth/connection.ts +3 -1
- package/src/oauth/manual-token-connection.ts +13 -13
- package/src/oauth/oauth-store.ts +223 -100
- package/src/oauth/platform-connection.test.ts +101 -3
- package/src/oauth/platform-connection.ts +56 -35
- package/src/oauth/provider-serializer.ts +31 -5
- package/src/oauth/revoke.ts +76 -0
- package/src/oauth/seed-providers.ts +133 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +16 -6
- package/src/permissions/defaults.ts +49 -1
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -1
- package/src/permissions/trust-store.ts +3 -3
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/permissions/workspace-policy.ts +3 -0
- package/src/platform/client.test.ts +10 -0
- package/src/platform/sync-identity.ts +129 -0
- package/src/prompts/persona-resolver.ts +126 -2
- package/src/prompts/system-prompt.ts +76 -38
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -105
- package/src/prompts/templates/SOUL.md +3 -1
- package/src/prompts/templates/UPDATES.md +12 -0
- package/src/prompts/templates/channels/slack.md +20 -0
- package/src/prompts/update-bulletin-format.ts +26 -9
- package/src/prompts/update-bulletin.ts +34 -23
- package/src/prompts/user-reference.ts +20 -17
- package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
- package/src/providers/anthropic/client.ts +157 -60
- package/src/providers/fireworks/client.ts +2 -2
- package/src/providers/gemini/client.ts +9 -1
- package/src/providers/model-catalog.ts +6 -0
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/ollama/client.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +474 -0
- package/src/providers/openai/client.ts +25 -440
- package/src/providers/openai/responses-provider.ts +502 -0
- package/src/providers/openrouter/client.ts +101 -4
- package/src/providers/provider-secret-catalog.ts +139 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +14 -3
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
- package/src/providers/speech-to-text/deepgram.test.ts +332 -0
- package/src/providers/speech-to-text/deepgram.ts +115 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
- package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
- package/src/providers/speech-to-text/google-gemini.ts +101 -0
- package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
- package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
- package/src/providers/speech-to-text/openai-whisper.ts +63 -33
- package/src/providers/speech-to-text/provider-catalog.ts +306 -0
- package/src/providers/speech-to-text/resolve.ts +386 -6
- package/src/providers/types.ts +10 -1
- package/src/runtime/AGENTS.md +65 -0
- package/src/runtime/__tests__/agent-wake.test.ts +831 -0
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
- package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
- package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
- package/src/runtime/agent-wake.ts +512 -0
- package/src/runtime/assistant-event-hub.ts +2 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +48 -0
- package/src/runtime/auth/middleware.ts +98 -0
- package/src/runtime/auth/route-policy.ts +33 -9
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/capability-tokens.ts +414 -0
- package/src/runtime/channel-approvals.ts +18 -5
- package/src/runtime/channel-invite-transport.ts +1 -1
- package/src/runtime/channel-invite-transports/email.ts +14 -6
- package/src/runtime/channel-readiness-service.ts +12 -22
- package/src/runtime/chrome-extension-registry.ts +368 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
- package/src/runtime/guardian-decision-types.ts +7 -0
- package/src/runtime/http-server.ts +815 -75
- package/src/runtime/http-types.ts +6 -2
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +198 -0
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
- package/src/runtime/migrations/migration-transport.ts +7 -0
- package/src/runtime/migrations/migration-wizard.ts +23 -2
- package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
- package/src/runtime/migrations/vbundle-builder.ts +145 -38
- package/src/runtime/migrations/vbundle-import-analyzer.ts +96 -1
- package/src/runtime/migrations/vbundle-importer.ts +89 -5
- package/src/runtime/pending-interactions.ts +18 -13
- package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
- package/src/runtime/routes/app-management-routes.ts +12 -18
- package/src/runtime/routes/approval-routes.ts +90 -16
- package/src/runtime/routes/attachment-routes.test.ts +9 -3
- package/src/runtime/routes/attachment-routes.ts +216 -17
- package/src/runtime/routes/backup-routes.ts +519 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +556 -0
- package/src/runtime/routes/btw-routes.ts +8 -6
- package/src/runtime/routes/contact-routes.test.ts +298 -0
- package/src/runtime/routes/contact-routes.ts +132 -5
- package/src/runtime/routes/conversation-analysis-routes.ts +22 -141
- package/src/runtime/routes/conversation-management-routes.ts +223 -0
- package/src/runtime/routes/conversation-routes.ts +598 -103
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- package/src/runtime/routes/filing-routes.ts +93 -0
- package/src/runtime/routes/guardian-action-routes.ts +24 -13
- package/src/runtime/routes/home-feed-routes.ts +334 -0
- package/src/runtime/routes/home-state-routes.ts +138 -0
- package/src/runtime/routes/host-browser-routes.ts +268 -0
- package/src/runtime/routes/host-file-routes.ts +9 -1
- package/src/runtime/routes/identity-intro-cache.ts +7 -3
- package/src/runtime/routes/identity-routes.ts +262 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
- package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
- package/src/runtime/routes/integrations/slack/channel.ts +11 -3
- package/src/runtime/routes/integrations/slack/share.ts +45 -7
- package/src/runtime/routes/llm-context-normalization.ts +303 -0
- package/src/runtime/routes/log-export-routes.ts +42 -22
- package/src/runtime/routes/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/memory-item-routes.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +122 -2
- package/src/runtime/routes/oauth-apps.ts +15 -17
- package/src/runtime/routes/oauth-providers.ts +4 -0
- package/src/runtime/routes/schedule-routes.ts +24 -11
- package/src/runtime/routes/settings-routes.ts +31 -102
- package/src/runtime/routes/skills-routes.ts +128 -9
- package/src/runtime/routes/stt-routes.ts +233 -0
- package/src/runtime/routes/subagents-routes.ts +14 -10
- package/src/runtime/routes/surface-action-routes.ts +41 -2
- package/src/runtime/routes/tts-routes.ts +108 -24
- package/src/runtime/routes/usage-routes.ts +38 -9
- package/src/runtime/routes/user-route-dispatcher.ts +50 -5
- package/src/runtime/routes/user-routes.ts +13 -1
- package/src/runtime/routes/work-items-routes.ts +8 -1
- package/src/runtime/routes/workspace-routes.test.ts +22 -0
- package/src/runtime/routes/workspace-routes.ts +8 -1
- package/src/runtime/routes/workspace-utils.ts +2 -0
- package/src/runtime/runtime-mode.ts +33 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
- package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
- package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
- package/src/runtime/services/analyze-conversation.ts +344 -0
- package/src/runtime/services/analyze-deps-singleton.ts +32 -0
- package/src/runtime/services/auto-analysis-prompt.ts +55 -0
- package/src/runtime/skill-route-registry.ts +49 -0
- package/src/runtime/slack-block-formatting.ts +437 -10
- package/src/schedule/scheduler.ts +57 -5
- package/src/security/ces-credential-client.ts +20 -0
- package/src/security/ces-rpc-credential-backend.ts +17 -0
- package/src/security/credential-backend.ts +5 -0
- package/src/security/oauth2.ts +68 -29
- package/src/security/secure-keys.ts +143 -27
- package/src/security/token-manager.ts +31 -10
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-files.ts +554 -0
- package/src/skills/category-inference.ts +122 -0
- package/src/skills/clawhub-files.ts +213 -0
- package/src/skills/clawhub.ts +84 -23
- package/src/skills/skill-file-provider.ts +40 -0
- package/src/skills/skillssh-files.ts +395 -0
- package/src/skills/skillssh-registry.ts +4 -4
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
- package/src/stt/__tests__/types.test.ts +89 -0
- package/src/stt/daemon-batch-transcriber.ts +195 -0
- package/src/stt/stt-stream-session.ts +499 -0
- package/src/stt/types.ts +330 -0
- package/src/stt/wav-encoder.test.ts +373 -0
- package/src/stt/wav-encoder.ts +175 -0
- package/src/subagent/manager.ts +169 -40
- package/src/subagent/types.ts +19 -0
- package/src/tools/apps/executors.ts +11 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
- package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
- package/src/tools/browser/auth-detector.ts +43 -12
- package/src/tools/browser/browser-execution.ts +1787 -342
- package/src/tools/browser/browser-manager.ts +81 -12
- package/src/tools/browser/browser-mode-constants.ts +12 -0
- package/src/tools/browser/browser-mode.ts +92 -0
- package/src/tools/browser/browser-status-constants.ts +33 -0
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1263 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +359 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1993 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +1007 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +744 -0
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +868 -0
- package/src/tools/browser/cdp-client/errors.ts +49 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +148 -0
- package/src/tools/browser/cdp-client/factory.ts +914 -0
- package/src/tools/browser/cdp-client/index.ts +28 -0
- package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
- package/src/tools/browser/cdp-client/types.ts +120 -0
- package/src/tools/credentials/vault.ts +35 -6
- 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 +2 -1
- package/src/tools/host-filesystem/edit.ts +1 -1
- package/src/tools/host-filesystem/read.ts +12 -15
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +21 -16
- package/src/tools/network/web-fetch.ts +5 -2
- package/src/tools/network/web-search.ts +5 -2
- package/src/tools/permission-checker.ts +77 -82
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -0
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- package/src/tools/shared/shell-output.ts +3 -1
- package/src/tools/side-effects.ts +2 -0
- package/src/tools/skills/sandbox-runner.ts +3 -2
- package/src/tools/subagent/spawn.ts +47 -3
- package/src/tools/subagent/status.ts +2 -0
- package/src/tools/system/register.ts +2 -16
- package/src/tools/terminal/safe-env.ts +15 -0
- package/src/tools/terminal/shell.ts +36 -20
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/tool-manifest.ts +21 -0
- package/src/tools/types.ts +19 -0
- package/src/tools/ui-surface/definitions.ts +6 -1
- package/src/tts/__tests__/provider-adapters.test.ts +834 -0
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
- package/src/tts/__tests__/provider-catalog.test.ts +183 -0
- package/src/tts/__tests__/provider-registry.test.ts +90 -0
- package/src/tts/provider-catalog.ts +201 -0
- package/src/tts/provider-registry.ts +73 -0
- package/src/tts/providers/deepgram-provider.ts +219 -0
- package/src/tts/providers/elevenlabs-provider.ts +211 -0
- package/src/tts/providers/fish-audio-provider.ts +183 -0
- package/src/tts/providers/index.ts +42 -0
- package/src/tts/providers/register-builtins.ts +130 -0
- package/src/tts/synthesize-text.ts +110 -0
- package/src/tts/tts-config-resolver.ts +78 -0
- package/src/tts/types.ts +153 -0
- package/src/types/onboarding-context.ts +7 -0
- package/src/util/abort-reasons.ts +58 -0
- package/src/util/device-id.ts +32 -16
- package/src/util/errors.ts +9 -1
- package/src/util/platform.ts +63 -24
- package/src/util/pricing.ts +66 -3
- package/src/util/spawn.ts +1 -1
- package/src/util/truncate.ts +4 -2
- package/src/util/unicode.ts +201 -0
- package/src/version.ts +19 -24
- package/src/watcher/engine.ts +23 -0
- package/src/watcher/watcher-store.ts +31 -0
- package/src/workspace/migrations/003-seed-device-id.ts +9 -3
- package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
- package/src/workspace/migrations/029-seed-pkb.ts +1 -1
- package/src/workspace/migrations/031-drop-user-md.ts +317 -0
- package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
- package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
- package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
- package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
- package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
- package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
- package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/top-level-renderer.ts +31 -1
- package/src/workspace/turn-commit.ts +31 -0
- package/src/__tests__/chrome-cdp.test.ts +0 -419
- package/src/__tests__/email-cli.test.ts +0 -297
- package/src/__tests__/email-service-config-fallback.test.ts +0 -102
- package/src/__tests__/permission-mode-sse.test.ts +0 -418
- package/src/__tests__/permission-mode-store.test.ts +0 -277
- package/src/browser-extension-relay/protocol.ts +0 -63
- package/src/browser-extension-relay/server.ts +0 -203
- package/src/cli/commands/browser-relay.ts +0 -536
- package/src/config/schemas/sandbox.ts +0 -14
- package/src/email/guardrails.ts +0 -221
- package/src/email/provider.ts +0 -117
- package/src/email/providers/agentmail.ts +0 -361
- package/src/email/providers/index.ts +0 -65
- package/src/email/service.ts +0 -384
- package/src/email/types.ts +0 -126
- package/src/permissions/permission-mode-store.ts +0 -180
- package/src/prompts/templates/USER.md +0 -13
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/tools/browser/chrome-cdp.ts +0 -239
- package/src/tools/system/set-permission-mode.ts +0 -103
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
statSync,
|
|
10
10
|
} from "node:fs";
|
|
11
11
|
import { homedir } from "node:os";
|
|
12
|
-
import { join, relative } from "node:path";
|
|
12
|
+
import { basename, join, relative, sep } from "node:path";
|
|
13
13
|
|
|
14
14
|
import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
|
|
15
15
|
import {
|
|
@@ -31,13 +31,27 @@ import {
|
|
|
31
31
|
getConfiguredProvider,
|
|
32
32
|
userMessage,
|
|
33
33
|
} from "../../providers/provider-send-message.js";
|
|
34
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
isTextMimeType as isTextMime,
|
|
36
|
+
MAX_INLINE_TEXT_SIZE,
|
|
37
|
+
} from "../../runtime/routes/workspace-utils.js";
|
|
35
38
|
import { getCatalog } from "../../skills/catalog-cache.js";
|
|
36
39
|
import {
|
|
40
|
+
catalogSkillToSlim,
|
|
41
|
+
createVellumCatalogProvider,
|
|
42
|
+
hasHiddenOrSkippedSegment,
|
|
43
|
+
sanitizeRelativePath,
|
|
44
|
+
type SkillFileEntry,
|
|
45
|
+
SKIP_DIRS,
|
|
46
|
+
} from "../../skills/catalog-files.js";
|
|
47
|
+
import {
|
|
48
|
+
type CatalogSkill,
|
|
37
49
|
installSkillLocally,
|
|
38
50
|
upsertSkillsIndex,
|
|
39
51
|
} from "../../skills/catalog-install.js";
|
|
40
52
|
import { filterByQuery } from "../../skills/catalog-search.js";
|
|
53
|
+
import type { SkillCategory } from "../../skills/category-inference.js";
|
|
54
|
+
import { inferCategory } from "../../skills/category-inference.js";
|
|
41
55
|
import {
|
|
42
56
|
clawhubCheckUpdates,
|
|
43
57
|
clawhubInspect,
|
|
@@ -46,6 +60,7 @@ import {
|
|
|
46
60
|
clawhubSearch,
|
|
47
61
|
clawhubUpdate,
|
|
48
62
|
} from "../../skills/clawhub.js";
|
|
63
|
+
import { createClawhubProvider } from "../../skills/clawhub-files.js";
|
|
49
64
|
import {
|
|
50
65
|
readInstallMeta,
|
|
51
66
|
type SkillInstallMeta,
|
|
@@ -56,16 +71,25 @@ import {
|
|
|
56
71
|
removeSkillsIndexEntry,
|
|
57
72
|
validateManagedSkillId,
|
|
58
73
|
} from "../../skills/managed-store.js";
|
|
74
|
+
import type { SkillFileProvider } from "../../skills/skill-file-provider.js";
|
|
75
|
+
import { createSkillsShProvider } from "../../skills/skillssh-files.js";
|
|
59
76
|
import {
|
|
77
|
+
fetchSkillAudits,
|
|
60
78
|
installExternalSkill,
|
|
61
79
|
resolveSkillSource,
|
|
62
80
|
searchSkillsRegistry,
|
|
81
|
+
type SkillAuditData,
|
|
63
82
|
} from "../../skills/skillssh-registry.js";
|
|
64
83
|
import { getWorkspaceSkillsDir } from "../../util/platform.js";
|
|
65
84
|
import type {
|
|
66
85
|
SkillDetailResponse,
|
|
86
|
+
SkillFileContentResponse,
|
|
67
87
|
SlimSkillResponse,
|
|
68
88
|
} from "../message-types/skills.js";
|
|
89
|
+
|
|
90
|
+
// Re-export for use by route layer and future consumers.
|
|
91
|
+
export type { SkillCategory };
|
|
92
|
+
export { inferCategory };
|
|
69
93
|
import {
|
|
70
94
|
CONFIG_RELOAD_DEBOUNCE_MS,
|
|
71
95
|
ensureSkillEntry,
|
|
@@ -73,10 +97,6 @@ import {
|
|
|
73
97
|
log,
|
|
74
98
|
} from "./shared.js";
|
|
75
99
|
|
|
76
|
-
// ─── MIME detection helpers ───────────────────────────────────────────────────
|
|
77
|
-
|
|
78
|
-
const MAX_INLINE_SIZE = 2 * 1024 * 1024; // 2 MB
|
|
79
|
-
|
|
80
100
|
// ─── Shared context for standalone functions ─────────────────────────────────
|
|
81
101
|
|
|
82
102
|
/**
|
|
@@ -91,6 +111,62 @@ export interface SkillOperationContext {
|
|
|
91
111
|
broadcast: HandlerContext["broadcast"];
|
|
92
112
|
}
|
|
93
113
|
|
|
114
|
+
// ─── Provider chain for uninstalled skill file preview ───────────────────────
|
|
115
|
+
// Ordered by priority: vellum first (most common and cheapest to check),
|
|
116
|
+
// then skills.sh, then clawhub.
|
|
117
|
+
//
|
|
118
|
+
// Lazy-initialized on first access so that mock modules (in tests) can
|
|
119
|
+
// replace the factory functions before providers are constructed.
|
|
120
|
+
|
|
121
|
+
let _fileProviders: SkillFileProvider[] | null = null;
|
|
122
|
+
|
|
123
|
+
function getFileProviders(): SkillFileProvider[] {
|
|
124
|
+
if (!_fileProviders) {
|
|
125
|
+
_fileProviders = [
|
|
126
|
+
createVellumCatalogProvider(),
|
|
127
|
+
createSkillsShProvider(),
|
|
128
|
+
createClawhubProvider(),
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
return _fileProviders;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** @internal Exported for test use only — forces re-creation of providers. */
|
|
135
|
+
export function _resetFileProvidersForTest(): void {
|
|
136
|
+
_fileProviders = null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function resolveSkillFiles(skillId: string): Promise<{
|
|
140
|
+
handled: boolean;
|
|
141
|
+
skill: SlimSkillResponse | null;
|
|
142
|
+
files: SkillFileEntry[] | null;
|
|
143
|
+
}> {
|
|
144
|
+
for (const provider of getFileProviders()) {
|
|
145
|
+
if (!provider.canHandle(skillId)) continue;
|
|
146
|
+
// Commit to this provider — don't fall through to subsequent providers.
|
|
147
|
+
const files = await provider.listFiles(skillId);
|
|
148
|
+
if (files === null) return { handled: true, skill: null, files: null };
|
|
149
|
+
const skill = await provider.toSlimSkill(skillId);
|
|
150
|
+
if (skill === null) return { handled: true, skill: null, files: null };
|
|
151
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
152
|
+
return { handled: true, skill, files };
|
|
153
|
+
}
|
|
154
|
+
return { handled: false, skill: null, files: null };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function resolveSkillFileContent(
|
|
158
|
+
skillId: string,
|
|
159
|
+
sanitizedPath: string,
|
|
160
|
+
): Promise<{ handled: boolean; result: SkillFileEntry | null }> {
|
|
161
|
+
for (const provider of getFileProviders()) {
|
|
162
|
+
if (!provider.canHandle(skillId)) continue;
|
|
163
|
+
// Commit to this provider — don't fall through to subsequent providers.
|
|
164
|
+
const result = await provider.readFileContent(skillId, sanitizedPath);
|
|
165
|
+
return { handled: true, result };
|
|
166
|
+
}
|
|
167
|
+
return { handled: false, result: null };
|
|
168
|
+
}
|
|
169
|
+
|
|
94
170
|
// ─── Frontmatter parsing ─────────────────────────────────────────────────────
|
|
95
171
|
|
|
96
172
|
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -317,6 +393,7 @@ function toSlimSkillResponse(
|
|
|
317
393
|
stars: 0,
|
|
318
394
|
installs: 0,
|
|
319
395
|
reports: 0,
|
|
396
|
+
version: "",
|
|
320
397
|
};
|
|
321
398
|
}
|
|
322
399
|
case "skillssh": {
|
|
@@ -364,7 +441,7 @@ export async function listSkillsWithCatalog(
|
|
|
364
441
|
const installed = listSkills(ctx);
|
|
365
442
|
const installedIds = new Set(installed.map((s) => s.id));
|
|
366
443
|
|
|
367
|
-
let catalogSkills:
|
|
444
|
+
let catalogSkills: CatalogSkill[];
|
|
368
445
|
try {
|
|
369
446
|
catalogSkills = await getCatalog();
|
|
370
447
|
} catch {
|
|
@@ -376,15 +453,7 @@ export async function listSkillsWithCatalog(
|
|
|
376
453
|
// Create SlimSkillResponses for catalog skills not already installed.
|
|
377
454
|
const available: SlimSkillResponse[] = catalogSkills
|
|
378
455
|
.filter((cs) => !installedIds.has(cs.id))
|
|
379
|
-
.map((cs) => (
|
|
380
|
-
id: cs.id,
|
|
381
|
-
name: cs.metadata?.vellum?.["display-name"] ?? cs.name,
|
|
382
|
-
description: cs.description,
|
|
383
|
-
emoji: cs.emoji,
|
|
384
|
-
kind: "catalog" as const,
|
|
385
|
-
origin: "vellum" as const,
|
|
386
|
-
status: "available" as const,
|
|
387
|
-
}));
|
|
456
|
+
.map((cs) => catalogSkillToSlim(cs));
|
|
388
457
|
|
|
389
458
|
const merged = [...installed, ...available];
|
|
390
459
|
|
|
@@ -398,6 +467,138 @@ export async function listSkillsWithCatalog(
|
|
|
398
467
|
return merged;
|
|
399
468
|
}
|
|
400
469
|
|
|
470
|
+
// ─── Filtered skill listing ──────────────────────────────────────────────────
|
|
471
|
+
|
|
472
|
+
export interface SkillListFilter {
|
|
473
|
+
origin?: string;
|
|
474
|
+
kind?: string;
|
|
475
|
+
q?: string;
|
|
476
|
+
category?: string;
|
|
477
|
+
includeCatalog?: boolean;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/** Human-readable labels matching Swift's `sourceLabel`. */
|
|
481
|
+
export function originDisplayLabel(origin: string): string {
|
|
482
|
+
switch (origin) {
|
|
483
|
+
case "vellum":
|
|
484
|
+
return "Vellum";
|
|
485
|
+
case "clawhub":
|
|
486
|
+
return "Clawhub";
|
|
487
|
+
case "skillssh":
|
|
488
|
+
return "skills.sh";
|
|
489
|
+
case "custom":
|
|
490
|
+
return "Custom";
|
|
491
|
+
default:
|
|
492
|
+
return origin;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/** Check if a skill's origin matches a text query (matching Swift logic). */
|
|
497
|
+
export function originMatchesQuery(origin: string, query: string): boolean {
|
|
498
|
+
const label = originDisplayLabel(origin).toLowerCase();
|
|
499
|
+
if (label.includes(query)) return true;
|
|
500
|
+
// "community" umbrella matches clawhub and skillssh
|
|
501
|
+
if (
|
|
502
|
+
(origin === "clawhub" || origin === "skillssh") &&
|
|
503
|
+
"community".includes(query)
|
|
504
|
+
) {
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* List skills with filtering, category counts, and sorting.
|
|
512
|
+
* Calls listSkillsWithCatalog for the full merged list, then applies filters.
|
|
513
|
+
*/
|
|
514
|
+
export async function listSkillsFiltered(
|
|
515
|
+
filter: SkillListFilter,
|
|
516
|
+
ctx: SkillOperationContext,
|
|
517
|
+
): Promise<{
|
|
518
|
+
skills: SlimSkillResponse[];
|
|
519
|
+
categoryCounts: Record<string, number>;
|
|
520
|
+
totalCount: number;
|
|
521
|
+
}> {
|
|
522
|
+
let skills =
|
|
523
|
+
filter.includeCatalog !== false
|
|
524
|
+
? await listSkillsWithCatalog(ctx)
|
|
525
|
+
: listSkills(ctx);
|
|
526
|
+
|
|
527
|
+
// Apply origin filter
|
|
528
|
+
if (filter.origin) {
|
|
529
|
+
skills = skills.filter((s) => s.origin === filter.origin);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Apply kind/status filter
|
|
533
|
+
if (filter.kind) {
|
|
534
|
+
switch (filter.kind) {
|
|
535
|
+
case "installed":
|
|
536
|
+
skills = skills.filter(
|
|
537
|
+
(s) => s.kind === "installed" || s.kind === "bundled",
|
|
538
|
+
);
|
|
539
|
+
break;
|
|
540
|
+
case "available":
|
|
541
|
+
skills = skills.filter((s) => s.status === "available");
|
|
542
|
+
break;
|
|
543
|
+
default:
|
|
544
|
+
skills = skills.filter((s) => s.kind === filter.kind);
|
|
545
|
+
break;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Apply text search
|
|
550
|
+
if (filter.q) {
|
|
551
|
+
const query = filter.q.trim().toLowerCase();
|
|
552
|
+
if (query) {
|
|
553
|
+
skills = skills.filter((s) => {
|
|
554
|
+
if (s.name.toLowerCase().includes(query)) return true;
|
|
555
|
+
if (s.description.toLowerCase().includes(query)) return true;
|
|
556
|
+
if (s.id.toLowerCase().includes(query)) return true;
|
|
557
|
+
if (originMatchesQuery(s.origin, query)) return true;
|
|
558
|
+
return false;
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// Compute category counts BEFORE applying the category filter
|
|
564
|
+
const categoryCounts: Record<string, number> = {};
|
|
565
|
+
for (const s of skills) {
|
|
566
|
+
const cat = inferCategory(s.name, s.description);
|
|
567
|
+
categoryCounts[cat] = (categoryCounts[cat] ?? 0) + 1;
|
|
568
|
+
}
|
|
569
|
+
const totalCount = skills.length;
|
|
570
|
+
|
|
571
|
+
// Apply category filter
|
|
572
|
+
if (filter.category) {
|
|
573
|
+
skills = skills.filter(
|
|
574
|
+
(s) => inferCategory(s.name, s.description) === filter.category,
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Sort: installed first, community origins before core within installed,
|
|
579
|
+
// then alphabetical by name (matching Swift sorting logic)
|
|
580
|
+
skills.sort((a, b) => {
|
|
581
|
+
// Installed (bundled + installed) before catalog (available)
|
|
582
|
+
const aInstalled = a.kind === "installed" || a.kind === "bundled" ? 0 : 1;
|
|
583
|
+
const bInstalled = b.kind === "installed" || b.kind === "bundled" ? 0 : 1;
|
|
584
|
+
if (aInstalled !== bInstalled) return aInstalled - bInstalled;
|
|
585
|
+
|
|
586
|
+
// Within installed, community origins (clawhub, skillssh) before core (vellum)
|
|
587
|
+
if (aInstalled === 0 && bInstalled === 0) {
|
|
588
|
+
const aCommunity =
|
|
589
|
+
a.origin === "clawhub" || a.origin === "skillssh" ? 0 : 1;
|
|
590
|
+
const bCommunity =
|
|
591
|
+
b.origin === "clawhub" || b.origin === "skillssh" ? 0 : 1;
|
|
592
|
+
if (aCommunity !== bCommunity) return aCommunity - bCommunity;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Alphabetical by name
|
|
596
|
+
return a.name.localeCompare(b.name);
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
return { skills, categoryCounts, totalCount };
|
|
600
|
+
}
|
|
601
|
+
|
|
401
602
|
/** Look up a single skill by ID from the resolved catalog, returning its SlimSkillResponse. */
|
|
402
603
|
function findSkillById(
|
|
403
604
|
skillId: string,
|
|
@@ -419,6 +620,32 @@ export async function getSkill(
|
|
|
419
620
|
): Promise<{ skill: SkillDetailResponse } | { error: string; status: number }> {
|
|
420
621
|
const found = findSkillById(skillId);
|
|
421
622
|
if (!found) {
|
|
623
|
+
// Fallback: skill is not installed. Try all file providers.
|
|
624
|
+
for (const provider of getFileProviders()) {
|
|
625
|
+
if (!provider.canHandle(skillId)) continue;
|
|
626
|
+
// Commit to this provider — don't fall through to subsequent providers.
|
|
627
|
+
const slim = await provider.toSlimSkill(skillId);
|
|
628
|
+
if (slim) {
|
|
629
|
+
// Enrich uninstalled skills.sh skills with audit data (non-fatal)
|
|
630
|
+
if (slim.origin === "skillssh") {
|
|
631
|
+
try {
|
|
632
|
+
const sourceRepo = slim.sourceRepo;
|
|
633
|
+
const skillSlug = slim.slug.split("/").pop() ?? slim.slug;
|
|
634
|
+
const audits = await fetchSkillAudits(sourceRepo, [skillSlug]);
|
|
635
|
+
if (audits[skillSlug]) {
|
|
636
|
+
(slim as { audit?: SkillAuditData }).audit = audits[skillSlug];
|
|
637
|
+
}
|
|
638
|
+
} catch (err) {
|
|
639
|
+
log.warn(
|
|
640
|
+
{ err, skillId },
|
|
641
|
+
"Failed to enrich uninstalled skillssh skill with audit data",
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return { skill: slim as SkillDetailResponse };
|
|
646
|
+
}
|
|
647
|
+
return { error: `Skill "${skillId}" not found`, status: 404 };
|
|
648
|
+
}
|
|
422
649
|
return { error: `Skill "${skillId}" not found`, status: 404 };
|
|
423
650
|
}
|
|
424
651
|
|
|
@@ -442,6 +669,7 @@ export async function getSkill(
|
|
|
442
669
|
installs: slim.installs,
|
|
443
670
|
reports: slim.reports,
|
|
444
671
|
publishedAt: slim.publishedAt,
|
|
672
|
+
version: slim.version,
|
|
445
673
|
};
|
|
446
674
|
try {
|
|
447
675
|
const inspectResult = await clawhubInspect(slim.slug);
|
|
@@ -476,6 +704,20 @@ export async function getSkill(
|
|
|
476
704
|
sourceRepo: slim.sourceRepo,
|
|
477
705
|
installs: slim.installs,
|
|
478
706
|
};
|
|
707
|
+
// Enrich with audit data (non-fatal on failure)
|
|
708
|
+
try {
|
|
709
|
+
const sourceRepo = slim.sourceRepo;
|
|
710
|
+
const skillSlug = slim.slug.split("/").pop() ?? slim.slug;
|
|
711
|
+
const audits = await fetchSkillAudits(sourceRepo, [skillSlug]);
|
|
712
|
+
if (audits[skillSlug]) {
|
|
713
|
+
(detail as { audit?: SkillAuditData }).audit = audits[skillSlug];
|
|
714
|
+
}
|
|
715
|
+
} catch (err) {
|
|
716
|
+
log.warn(
|
|
717
|
+
{ err, skillId },
|
|
718
|
+
"Failed to enrich skillssh skill detail with audit data",
|
|
719
|
+
);
|
|
720
|
+
}
|
|
479
721
|
return { skill: detail };
|
|
480
722
|
}
|
|
481
723
|
|
|
@@ -494,16 +736,12 @@ export async function getSkill(
|
|
|
494
736
|
|
|
495
737
|
// ─── Skill file listing ──────────────────────────────────────────────────────
|
|
496
738
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
content: string | null; // inline text if ≤ 2 MB and text MIME, else null
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
const SKIP_DIRS = new Set(["node_modules", "__pycache__", ".git"]);
|
|
739
|
+
// `SkillFileEntry` lives in `../../skills/catalog-files.ts` to keep a single
|
|
740
|
+
// source of truth for the shape and avoid a circular import (catalog-files
|
|
741
|
+
// depends on `catalog-cache.ts`, which would otherwise be reachable via this
|
|
742
|
+
// handler module). Re-exported here so handlers can import it alongside
|
|
743
|
+
// the other skill handler exports.
|
|
744
|
+
export type { SkillFileEntry } from "../../skills/catalog-files.js";
|
|
507
745
|
|
|
508
746
|
/**
|
|
509
747
|
* Returns true if `filePath` is a symlink whose resolved real path escapes
|
|
@@ -550,7 +788,7 @@ function readDirRecursive(dir: string, rootDir: string): SkillFileEntry[] {
|
|
|
550
788
|
const mimeType = Bun.file(fullPath).type;
|
|
551
789
|
const isText = isTextMime(mimeType, dirent.name);
|
|
552
790
|
let content: string | null = null;
|
|
553
|
-
if (isText && stat.size <=
|
|
791
|
+
if (isText && stat.size <= MAX_INLINE_TEXT_SIZE) {
|
|
554
792
|
content = readFileSync(fullPath, "utf-8");
|
|
555
793
|
}
|
|
556
794
|
entries.push({
|
|
@@ -568,26 +806,180 @@ function readDirRecursive(dir: string, rootDir: string): SkillFileEntry[] {
|
|
|
568
806
|
return entries;
|
|
569
807
|
}
|
|
570
808
|
|
|
571
|
-
|
|
809
|
+
/**
|
|
810
|
+
* Read a single file's content from an installed or uninstalled skill.
|
|
811
|
+
*
|
|
812
|
+
* Installed-skill path (eager): reads the file directly from the skill's
|
|
813
|
+
* on-disk directory. Applies lexical containment, symlink rejection, and
|
|
814
|
+
* realpath containment checks for defense in depth.
|
|
815
|
+
*
|
|
816
|
+
* Provider chain fallback: when the skill id is not backed by a local
|
|
817
|
+
* directory, iterates the file-provider chain (vellum catalog,
|
|
818
|
+
* skills.sh, clawhub) until one returns content.
|
|
819
|
+
*/
|
|
820
|
+
export async function getSkillFileContent(
|
|
572
821
|
skillId: string,
|
|
822
|
+
relativePath: string,
|
|
573
823
|
_ctx: SkillOperationContext,
|
|
574
|
-
):
|
|
575
|
-
|
|
576
|
-
|
|
824
|
+
): Promise<SkillFileContentResponse | { error: string; status: number }> {
|
|
825
|
+
const sanitized = sanitizeRelativePath(relativePath);
|
|
826
|
+
if (!sanitized) {
|
|
827
|
+
return { error: "Invalid path", status: 400 };
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// Reject any sanitized path that references a hidden segment (dotfiles
|
|
831
|
+
// like `.env`, dot-dirs like `.git`) or a SKIP_DIRS segment (e.g.
|
|
832
|
+
// `node_modules`, `__pycache__`). Both file-listing endpoints (installed
|
|
833
|
+
// and catalog) intentionally omit these entries, so allowing the content
|
|
834
|
+
// endpoint to read them would create a data-exposure path and break
|
|
835
|
+
// parity with the visible file list. This check runs BEFORE both the
|
|
836
|
+
// installed-skill disk read and the catalog fallback so the rejection
|
|
837
|
+
// is uniform regardless of source.
|
|
838
|
+
if (hasHiddenOrSkippedSegment(sanitized)) {
|
|
839
|
+
return { error: "Invalid path", status: 400 };
|
|
840
|
+
}
|
|
841
|
+
|
|
577
842
|
const found = findSkillById(skillId);
|
|
578
|
-
if (
|
|
579
|
-
|
|
843
|
+
if (found) {
|
|
844
|
+
if (!existsSync(found.summary.directoryPath)) {
|
|
845
|
+
// Resolver lists the skill as installed but the directory is missing
|
|
846
|
+
// on disk (corrupted install, mid-delete race, external unmount, etc.).
|
|
847
|
+
// Return a distinct 404 instead of falling through to the catalog path
|
|
848
|
+
// so the content response stays consistent with `listSkillsWithCatalog`
|
|
849
|
+
// and `getSkillFiles`, which classify the same id as `kind: "installed"`.
|
|
850
|
+
return {
|
|
851
|
+
error: `Skill directory missing for "${skillId}"`,
|
|
852
|
+
status: 404,
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
const dir = found.summary.directoryPath;
|
|
856
|
+
const abs = join(dir, sanitized);
|
|
857
|
+
|
|
858
|
+
// Lexical containment: the resolved absolute path must stay inside the
|
|
859
|
+
// skill directory even after `join` normalization. Cheap short-circuit
|
|
860
|
+
// before any fs calls.
|
|
861
|
+
if (!(abs === dir || abs.startsWith(dir + sep))) {
|
|
862
|
+
return { error: "Invalid path", status: 400 };
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// Defense-in-depth symlink rejection: refuse to follow a symlinked file
|
|
866
|
+
// inside the skill dir that could point outside the root. Also catches
|
|
867
|
+
// symlinked parent directories via a realpath containment check.
|
|
868
|
+
let lstat;
|
|
869
|
+
try {
|
|
870
|
+
lstat = lstatSync(abs);
|
|
871
|
+
} catch {
|
|
872
|
+
return { error: "File not found", status: 404 };
|
|
873
|
+
}
|
|
874
|
+
if (lstat.isSymbolicLink()) {
|
|
875
|
+
return { error: "File not found", status: 404 };
|
|
876
|
+
}
|
|
877
|
+
if (!lstat.isFile()) {
|
|
878
|
+
return { error: "File not found", status: 404 };
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
let realAbs: string;
|
|
882
|
+
let realDir: string;
|
|
883
|
+
try {
|
|
884
|
+
realAbs = realpathSync(abs);
|
|
885
|
+
realDir = realpathSync(dir);
|
|
886
|
+
} catch {
|
|
887
|
+
return { error: "File not found", status: 404 };
|
|
888
|
+
}
|
|
889
|
+
if (!(realAbs === realDir || realAbs.startsWith(realDir + sep))) {
|
|
890
|
+
return { error: "File not found", status: 404 };
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
let stat;
|
|
894
|
+
try {
|
|
895
|
+
stat = statSync(abs);
|
|
896
|
+
} catch {
|
|
897
|
+
return { error: "File not found", status: 404 };
|
|
898
|
+
}
|
|
899
|
+
if (!stat.isFile()) {
|
|
900
|
+
return { error: "File not found", status: 404 };
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
const name = basename(sanitized);
|
|
904
|
+
const mimeType = Bun.file(abs).type;
|
|
905
|
+
const isText = isTextMime(mimeType, name);
|
|
906
|
+
const isBinary = !isText;
|
|
907
|
+
let content: string | null = null;
|
|
908
|
+
if (isText && stat.size <= MAX_INLINE_TEXT_SIZE) {
|
|
909
|
+
try {
|
|
910
|
+
content = readFileSync(abs, "utf-8");
|
|
911
|
+
} catch {
|
|
912
|
+
content = null;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
return {
|
|
916
|
+
path: sanitized,
|
|
917
|
+
name,
|
|
918
|
+
size: stat.size,
|
|
919
|
+
mimeType,
|
|
920
|
+
isBinary,
|
|
921
|
+
content,
|
|
922
|
+
};
|
|
580
923
|
}
|
|
581
924
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
925
|
+
// Fallback: skill is not installed. Try all file providers.
|
|
926
|
+
const { handled, result } = await resolveSkillFileContent(skillId, sanitized);
|
|
927
|
+
if (handled && result) {
|
|
928
|
+
return {
|
|
929
|
+
path: result.path,
|
|
930
|
+
name: result.name,
|
|
931
|
+
size: result.size,
|
|
932
|
+
mimeType: result.mimeType,
|
|
933
|
+
isBinary: result.isBinary,
|
|
934
|
+
content: result.content,
|
|
935
|
+
};
|
|
585
936
|
}
|
|
937
|
+
if (handled) {
|
|
938
|
+
// A provider claimed this skill but the specific file wasn't found.
|
|
939
|
+
return { error: "File not found", status: 404 };
|
|
940
|
+
}
|
|
941
|
+
return { error: "Skill not found", status: 404 };
|
|
942
|
+
}
|
|
586
943
|
|
|
587
|
-
|
|
588
|
-
|
|
944
|
+
export async function getSkillFiles(
|
|
945
|
+
skillId: string,
|
|
946
|
+
_ctx: SkillOperationContext,
|
|
947
|
+
): Promise<
|
|
948
|
+
| { skill: SlimSkillResponse; files: SkillFileEntry[] }
|
|
949
|
+
| { error: string; status: number }
|
|
950
|
+
> {
|
|
951
|
+
// Preferred path: the skill is resolved locally (bundled, managed,
|
|
952
|
+
// workspace, or extra) AND its directory exists on disk. Read files
|
|
953
|
+
// eagerly with inline content.
|
|
954
|
+
const found = findSkillById(skillId);
|
|
955
|
+
if (found) {
|
|
956
|
+
if (existsSync(found.summary.directoryPath)) {
|
|
957
|
+
const dirPath = found.summary.directoryPath;
|
|
958
|
+
const files = readDirRecursive(dirPath, dirPath);
|
|
959
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
960
|
+
return { skill: found.item, files };
|
|
961
|
+
}
|
|
962
|
+
// Resolver lists the skill as installed but the directory is missing
|
|
963
|
+
// on disk (corrupted install, mid-delete race, external unmount, etc.).
|
|
964
|
+
// Return a distinct 404 instead of falling through to the catalog path
|
|
965
|
+
// so the detail response stays consistent with `listSkillsWithCatalog`,
|
|
966
|
+
// which classifies the same id as `kind: "installed"`.
|
|
967
|
+
return {
|
|
968
|
+
error: `Skill directory missing for "${skillId}"`,
|
|
969
|
+
status: 404,
|
|
970
|
+
};
|
|
971
|
+
}
|
|
589
972
|
|
|
590
|
-
|
|
973
|
+
// Fallback: skill is not installed. Try all file providers.
|
|
974
|
+
const resolved = await resolveSkillFiles(skillId);
|
|
975
|
+
if (resolved.handled && resolved.skill && resolved.files) {
|
|
976
|
+
return { skill: resolved.skill, files: resolved.files };
|
|
977
|
+
}
|
|
978
|
+
if (resolved.handled) {
|
|
979
|
+
// A provider claimed this skill but couldn't produce files/metadata.
|
|
980
|
+
return { error: `Skill files unavailable for "${skillId}"`, status: 404 };
|
|
981
|
+
}
|
|
982
|
+
return { error: `Skill "${skillId}" not found`, status: 404 };
|
|
591
983
|
}
|
|
592
984
|
|
|
593
985
|
export function enableSkill(
|
|
@@ -676,7 +1068,9 @@ export async function installSkill(
|
|
|
676
1068
|
contactId?: string;
|
|
677
1069
|
},
|
|
678
1070
|
ctx: SkillOperationContext,
|
|
679
|
-
): Promise<
|
|
1071
|
+
): Promise<
|
|
1072
|
+
{ success: true; skillId: string } | { success: false; error: string }
|
|
1073
|
+
> {
|
|
680
1074
|
try {
|
|
681
1075
|
// Bundled skills are already available — no install needed
|
|
682
1076
|
const catalog = loadSkillCatalog();
|
|
@@ -721,7 +1115,7 @@ export async function installSkill(
|
|
|
721
1115
|
}
|
|
722
1116
|
seedSkillGraphNodes();
|
|
723
1117
|
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
724
|
-
return { success: true };
|
|
1118
|
+
return { success: true, skillId: spec.slug };
|
|
725
1119
|
}
|
|
726
1120
|
|
|
727
1121
|
// Check the Vellum catalog (first-party skills hosted on the platform).
|
|
@@ -742,7 +1136,7 @@ export async function installSkill(
|
|
|
742
1136
|
|
|
743
1137
|
const skillDir = join(getWorkspaceSkillsDir(), spec.slug);
|
|
744
1138
|
postInstallSkill(spec.slug, skillDir, ctx);
|
|
745
|
-
return { success: true };
|
|
1139
|
+
return { success: true, skillId: spec.slug };
|
|
746
1140
|
}
|
|
747
1141
|
} catch (err) {
|
|
748
1142
|
// If catalog lookup/install fails, fall through to community registries
|
|
@@ -770,7 +1164,7 @@ export async function installSkill(
|
|
|
770
1164
|
|
|
771
1165
|
const skillDir = join(getWorkspaceSkillsDir(), resolved.skillSlug);
|
|
772
1166
|
postInstallSkill(resolved.skillSlug, skillDir, ctx);
|
|
773
|
-
return { success: true };
|
|
1167
|
+
return { success: true, skillId: resolved.skillSlug };
|
|
774
1168
|
}
|
|
775
1169
|
|
|
776
1170
|
// Install from clawhub (community)
|
|
@@ -798,7 +1192,7 @@ export async function installSkill(
|
|
|
798
1192
|
upsertSkillsIndex(skillId);
|
|
799
1193
|
|
|
800
1194
|
postInstallSkill(skillId, skillDir, ctx);
|
|
801
|
-
return { success: true };
|
|
1195
|
+
return { success: true, skillId };
|
|
802
1196
|
} catch (err) {
|
|
803
1197
|
const message = err instanceof Error ? err.message : String(err);
|
|
804
1198
|
log.error({ err }, "Failed to install skill");
|
|
@@ -971,6 +1365,7 @@ export async function searchSkills(
|
|
|
971
1365
|
publishedAt: s.createdAt
|
|
972
1366
|
? new Date(s.createdAt * 1000).toISOString()
|
|
973
1367
|
: undefined,
|
|
1368
|
+
version: s.version,
|
|
974
1369
|
}));
|
|
975
1370
|
} else {
|
|
976
1371
|
log.warn(
|
|
@@ -992,6 +1387,50 @@ export async function searchSkills(
|
|
|
992
1387
|
sourceRepo: r.source,
|
|
993
1388
|
installs: r.installs,
|
|
994
1389
|
}));
|
|
1390
|
+
|
|
1391
|
+
// Batch-fetch audit data for skills.sh results, grouped by source repo.
|
|
1392
|
+
try {
|
|
1393
|
+
if (skillsshResult.value.length > 0) {
|
|
1394
|
+
const sourceToSlugs = new Map<string, string[]>();
|
|
1395
|
+
for (const r of skillsshResult.value) {
|
|
1396
|
+
const slugs = sourceToSlugs.get(r.source) ?? [];
|
|
1397
|
+
slugs.push(r.skillId);
|
|
1398
|
+
sourceToSlugs.set(r.source, slugs);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
const auditResults = await Promise.allSettled(
|
|
1402
|
+
[...sourceToSlugs.entries()].map(([source, slugs]) =>
|
|
1403
|
+
fetchSkillAudits(source, slugs).then((audits) => ({
|
|
1404
|
+
source,
|
|
1405
|
+
audits,
|
|
1406
|
+
})),
|
|
1407
|
+
),
|
|
1408
|
+
);
|
|
1409
|
+
|
|
1410
|
+
// Build a lookup map keyed by full skill ID (e.g. "owner/repo/skill-name")
|
|
1411
|
+
const auditMap = new Map<string, SkillAuditData>();
|
|
1412
|
+
for (const result of auditResults) {
|
|
1413
|
+
if (result.status !== "fulfilled") continue;
|
|
1414
|
+
const { source, audits } = result.value;
|
|
1415
|
+
for (const [skillSlug, auditData] of Object.entries(audits)) {
|
|
1416
|
+
auditMap.set(`${source}/${skillSlug}`, auditData);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
// Enrich each skills.sh skill with audit data
|
|
1421
|
+
skillsshSkills = skillsshSkills.map((skill) => {
|
|
1422
|
+
if (skill.origin !== "skillssh") return skill;
|
|
1423
|
+
const audit = auditMap.get(skill.id);
|
|
1424
|
+
if (!audit) return skill;
|
|
1425
|
+
return { ...skill, audit };
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
} catch (err) {
|
|
1429
|
+
log.warn(
|
|
1430
|
+
{ err },
|
|
1431
|
+
"Audit fetch failed for skills.sh results, continuing without audit data",
|
|
1432
|
+
);
|
|
1433
|
+
}
|
|
995
1434
|
} else {
|
|
996
1435
|
log.warn(
|
|
997
1436
|
{ err: skillsshResult.reason },
|