@vellumai/assistant 0.6.3 → 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 +5 -13
- 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/openapi.yaml +982 -72
- package/package.json +4 -6
- package/scripts/generate-openapi.ts +0 -1
- package/scripts/test.sh +73 -18
- 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__/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 +11 -0
- 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 +138 -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-schema.test.ts +1013 -66
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +43 -8
- package/src/__tests__/contact-store-user-file.test.ts +512 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- 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 +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +98 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +135 -0
- package/src/__tests__/conversation-error.test.ts +70 -0
- package/src/__tests__/conversation-history-web-search.test.ts +11 -4
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
- 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 +901 -60
- package/src/__tests__/conversation-routes-disk-view.test.ts +270 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +55 -0
- 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-tool-setup-batch-authorized.test.ts +226 -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-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +5 -3
- package/src/__tests__/credential-vault-unit.test.ts +379 -3
- package/src/__tests__/credentials-cli.test.ts +40 -16
- package/src/__tests__/cross-provider-web-search.test.ts +146 -35
- 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__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +75 -8
- package/src/__tests__/fixtures/mock-chrome-extension.ts +11 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +64 -0
- 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__/headless-browser-interactions.test.ts +43 -0
- package/src/__tests__/headless-browser-mode.test.ts +614 -0
- package/src/__tests__/headless-browser-navigate.test.ts +142 -5
- package/src/__tests__/headless-browser-read-tools.test.ts +11 -0
- package/src/__tests__/headless-browser-snapshot.test.ts +10 -0
- 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 +0 -5
- package/src/__tests__/host-browser-e2e-cloud.test.ts +138 -4
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +4 -4
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +103 -0
- package/src/__tests__/host-cu-proxy.test.ts +0 -5
- package/src/__tests__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- 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__/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-export-http.test.ts +6 -6
- package/src/__tests__/migration-import-commit-http.test.ts +8 -6
- 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__/oauth-apps-routes.test.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +2 -0
- package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +1 -0
- package/src/__tests__/oauth-providers-routes.test.ts +2 -0
- package/src/__tests__/oauth-store.test.ts +85 -0
- package/src/__tests__/oauth2-gateway-transport.test.ts +249 -6
- package/src/__tests__/onboarding-template-contract.test.ts +6 -13
- package/src/__tests__/openai-provider.test.ts +176 -0
- 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-unsubscribe.test.ts +31 -2
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
- package/src/__tests__/platform.test.ts +92 -1
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
- package/src/__tests__/pricing.test.ts +174 -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__/search-skills-unified.test.ts +118 -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 +5 -1
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +49 -0
- 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 +276 -145
- package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
- 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 +564 -1
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/system-prompt.test.ts +112 -26
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +18 -7
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
- 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__/trust-store.test.ts +7 -1
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
- 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__/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/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +43 -3
- 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/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/types.ts +16 -0
- 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 +0 -1
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +255 -3
- package/src/cli/commands/oauth/__tests__/connect.test.ts +12 -0
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +1 -0
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -0
- package/src/cli/commands/oauth/mode.ts +12 -3
- package/src/cli/commands/oauth/providers.ts +15 -0
- package/src/cli/commands/oauth/shared.ts +2 -1
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +4 -9
- 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/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/references/CUSTOM_ROUTES.md +37 -1
- 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 +2 -2
- package/src/config/bundled-skills/gmail/SKILL.md +53 -7
- 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 +2 -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/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 +24 -0
- package/src/config/env.ts +34 -10
- package/src/config/feature-flag-registry.json +46 -14
- package/src/config/loader.ts +26 -12
- package/src/config/schema.ts +35 -10
- 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 +47 -1
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/services.ts +44 -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 -0
- 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 +3 -2
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +45 -12
- 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 +17 -8
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/config-watcher.ts +99 -5
- package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
- package/src/daemon/conversation-agent-loop.ts +101 -24
- 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 +581 -19
- package/src/daemon/conversation-queue-manager.ts +24 -0
- package/src/daemon/conversation-runtime-assembly.ts +11 -1
- package/src/daemon/conversation-slash.ts +36 -0
- package/src/daemon/conversation-surfaces.ts +94 -4
- package/src/daemon/conversation-tool-setup.ts +25 -0
- package/src/daemon/conversation-usage.ts +7 -4
- package/src/daemon/conversation.ts +86 -28
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +4 -1
- package/src/daemon/handlers/shared.ts +22 -0
- package/src/daemon/handlers/skills.ts +321 -77
- package/src/daemon/host-browser-proxy.ts +2 -1
- package/src/daemon/lifecycle.ts +122 -25
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/conversations.ts +34 -1
- package/src/daemon/message-types/home.ts +40 -0
- package/src/daemon/message-types/meet.ts +143 -0
- package/src/daemon/message-types/messages.ts +14 -0
- package/src/daemon/message-types/schedules.ts +34 -2
- package/src/daemon/message-types/skills.ts +16 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/server.ts +347 -2
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +9 -0
- 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 +12 -3
- 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/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 +1 -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 +99 -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/db-init.ts +6 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/graph/conversation-graph-memory.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 +27 -18
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- 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 +92 -56
- 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 +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/qdrant-manager.ts +43 -16
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/oauth.ts +3 -0
- 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/__tests__/identity-verifier.test.ts +1 -0
- package/src/oauth/byo-connection.test.ts +18 -1
- package/src/oauth/byo-connection.ts +3 -1
- package/src/oauth/connect-orchestrator.ts +2 -0
- package/src/oauth/connection-resolver.ts +6 -2
- package/src/oauth/connection.ts +2 -0
- package/src/oauth/oauth-store.ts +9 -0
- package/src/oauth/platform-connection.test.ts +98 -0
- package/src/oauth/platform-connection.ts +52 -31
- package/src/oauth/seed-providers.ts +7 -0
- package/src/permissions/checker.ts +16 -6
- package/src/permissions/defaults.ts +49 -1
- package/src/permissions/trust-store.ts +3 -3
- 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 +59 -18
- package/src/prompts/templates/BOOTSTRAP.md +5 -5
- 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 -61
- 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 +9 -0
- package/src/runtime/AGENTS.md +43 -1
- package/src/runtime/__tests__/agent-wake.test.ts +831 -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/auth/__tests__/route-policy.test.ts +40 -0
- package/src/runtime/auth/route-policy.ts +30 -5
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/capability-tokens.ts +10 -10
- 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 +38 -2
- package/src/runtime/http-server.ts +395 -10
- package/src/runtime/http-types.ts +6 -2
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +36 -0
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
- package/src/runtime/migrations/migration-transport.ts +1 -0
- package/src/runtime/migrations/migration-wizard.ts +1 -0
- package/src/runtime/migrations/vbundle-import-analyzer.ts +77 -1
- package/src/runtime/migrations/vbundle-importer.ts +34 -0
- package/src/runtime/pending-interactions.ts +0 -11
- 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/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 +82 -23
- 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 -142
- package/src/runtime/routes/conversation-management-routes.ts +115 -0
- package/src/runtime/routes/conversation-routes.ts +367 -146
- package/src/runtime/routes/filing-routes.ts +93 -0
- 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 +3 -14
- package/src/runtime/routes/identity-intro-cache.ts +7 -3
- package/src/runtime/routes/identity-routes.ts +3 -17
- 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/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/migration-routes.ts +40 -5
- package/src/runtime/routes/settings-routes.ts +22 -5
- package/src/runtime/routes/skills-routes.ts +76 -7
- package/src/runtime/routes/stt-routes.ts +233 -0
- 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 +30 -2
- 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/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 +50 -0
- package/src/security/oauth2.ts +26 -4
- package/src/security/secure-keys.ts +25 -2
- package/src/security/token-manager.ts +8 -0
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-files.ts +64 -2
- 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 +38 -14
- 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/browser-execution.ts +1163 -23
- package/src/tools/browser/browser-manager.ts +45 -0
- 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__/cdp-inspect-client.test.ts +393 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +29 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1648 -32
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +264 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +183 -17
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +254 -21
- package/src/tools/browser/cdp-client/errors.ts +15 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +39 -16
- package/src/tools/browser/cdp-client/factory.ts +797 -87
- package/src/tools/browser/cdp-client/index.ts +16 -2
- package/src/tools/browser/cdp-client/types.ts +68 -0
- package/src/tools/credentials/vault.ts +35 -6
- package/src/tools/network/web-fetch.ts +5 -2
- package/src/tools/network/web-search.ts +5 -2
- 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/terminal/safe-env.ts +10 -2
- package/src/tools/terminal/shell.ts +15 -4
- package/src/tools/tool-manifest.ts +21 -0
- package/src/tools/types.ts +17 -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 +54 -10
- 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 +13 -1
- package/src/workspace/turn-commit.ts +31 -0
- package/src/__tests__/email-cli.test.ts +0 -297
- package/src/__tests__/email-service-config-fallback.test.ts +0 -102
- package/src/cli/commands/browser-relay.ts +0 -466
- 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/prompts/templates/USER.md +0 -13
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/runtime/routes/browser-cdp-routes.ts +0 -229
|
@@ -112,6 +112,168 @@ export function normalizeLlmContextPayloads(
|
|
|
112
112
|
function normalizeOpenAiRequestPayload(
|
|
113
113
|
requestPayload: unknown,
|
|
114
114
|
allowPlainText = false,
|
|
115
|
+
): NormalizedPayloadCandidate | null {
|
|
116
|
+
// Try Responses API shape first, then fall back to chat-completions.
|
|
117
|
+
return (
|
|
118
|
+
normalizeOpenAiResponsesRequestPayload(requestPayload, allowPlainText) ??
|
|
119
|
+
normalizeOpenAiChatCompletionsRequestPayload(requestPayload, allowPlainText)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Detect and normalize OpenAI Responses API request payloads.
|
|
125
|
+
*
|
|
126
|
+
* Responses requests use `input` (array) instead of `messages`, may have a
|
|
127
|
+
* top-level `instructions` string, and tools have `type: "function"` at the
|
|
128
|
+
* top level with the function fields inlined (no nested `function` wrapper).
|
|
129
|
+
*/
|
|
130
|
+
function normalizeOpenAiResponsesRequestPayload(
|
|
131
|
+
requestPayload: unknown,
|
|
132
|
+
allowPlainText = false,
|
|
133
|
+
): NormalizedPayloadCandidate | null {
|
|
134
|
+
const request = asRecord(requestPayload);
|
|
135
|
+
if (!request) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const input = asRecordArray(request.input);
|
|
140
|
+
if (!input) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Require at least one Responses-specific signal to avoid matching generic
|
|
145
|
+
// arrays. `instructions` is the strongest signal; otherwise look for
|
|
146
|
+
// Responses-shaped input items or tool objects.
|
|
147
|
+
const hasResponsesSignal =
|
|
148
|
+
typeof request.instructions === "string" ||
|
|
149
|
+
hasOpenAiModelPrefix(asString(request.model)) ||
|
|
150
|
+
input.some(
|
|
151
|
+
(item) =>
|
|
152
|
+
asString(item.type) === "function_call" ||
|
|
153
|
+
asString(item.type) === "function_call_output",
|
|
154
|
+
) ||
|
|
155
|
+
extractOpenAiResponsesRequestToolNames(request.tools).length > 0;
|
|
156
|
+
|
|
157
|
+
if (!allowPlainText && !hasResponsesSignal) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const requestSections: LlmContextSection[] = [];
|
|
162
|
+
|
|
163
|
+
// System-level instructions
|
|
164
|
+
const instructions = asString(request.instructions);
|
|
165
|
+
if (instructions && hasMeaningfulText(instructions)) {
|
|
166
|
+
requestSections.push({
|
|
167
|
+
kind: "system",
|
|
168
|
+
label: "System prompt",
|
|
169
|
+
role: "system",
|
|
170
|
+
text: instructions,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Input items
|
|
175
|
+
let messageIndex = 0;
|
|
176
|
+
for (const item of input) {
|
|
177
|
+
const itemType = asString(item.type);
|
|
178
|
+
|
|
179
|
+
if (itemType === "message") {
|
|
180
|
+
messageIndex++;
|
|
181
|
+
const role = asString(item.role) ?? "unknown";
|
|
182
|
+
const messageText = extractOpenAiContentText(item.content);
|
|
183
|
+
if (messageText !== undefined) {
|
|
184
|
+
requestSections.push({
|
|
185
|
+
kind: "message",
|
|
186
|
+
label: buildMessageLabel(role, messageIndex),
|
|
187
|
+
role,
|
|
188
|
+
text: messageText,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (itemType === "function_call") {
|
|
195
|
+
const name = asString(item.name);
|
|
196
|
+
const args = parseJsonValue(asString(item.arguments));
|
|
197
|
+
requestSections.push({
|
|
198
|
+
kind: "function_call",
|
|
199
|
+
label: `Request tool call${name ? ` (${name})` : ""}`,
|
|
200
|
+
role: "assistant",
|
|
201
|
+
toolName: name,
|
|
202
|
+
data: args,
|
|
203
|
+
text: previewStructuredValue(args),
|
|
204
|
+
});
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (itemType === "function_call_output") {
|
|
209
|
+
const output = asString(item.output);
|
|
210
|
+
requestSections.push({
|
|
211
|
+
kind: "tool_result",
|
|
212
|
+
label: `Tool result${asString(item.call_id) ? ` (${asString(item.call_id)})` : ""}`,
|
|
213
|
+
role: "tool",
|
|
214
|
+
toolName: asString(item.call_id),
|
|
215
|
+
text: output,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Tool definitions (Responses shape: top-level type/name/parameters)
|
|
221
|
+
const requestToolNames = extractOpenAiResponsesRequestToolNames(
|
|
222
|
+
request.tools,
|
|
223
|
+
);
|
|
224
|
+
if (requestToolNames.length > 0) {
|
|
225
|
+
requestSections.push({
|
|
226
|
+
kind: "tool_definitions",
|
|
227
|
+
label: "Available tools",
|
|
228
|
+
data: {
|
|
229
|
+
tools: asRecordArray(request.tools) ?? request.tools,
|
|
230
|
+
},
|
|
231
|
+
language: "json",
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const requestSettings = omitRecordKeys(request, [
|
|
236
|
+
"instructions",
|
|
237
|
+
"input",
|
|
238
|
+
"tools",
|
|
239
|
+
]);
|
|
240
|
+
if (hasMeaningfulRequestSettings(requestSettings)) {
|
|
241
|
+
requestSections.push(
|
|
242
|
+
structuredJsonSection("settings", "Request settings", requestSettings),
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Count all input items for the message count (includes messages, function
|
|
247
|
+
// calls, and function call outputs — mirrors how chat-completions counts
|
|
248
|
+
// all messages regardless of role).
|
|
249
|
+
return {
|
|
250
|
+
provider: "openai",
|
|
251
|
+
summary: {
|
|
252
|
+
provider: "openai",
|
|
253
|
+
model: asString(request.model),
|
|
254
|
+
inputTokens: undefined,
|
|
255
|
+
outputTokens: undefined,
|
|
256
|
+
cacheCreationInputTokens: undefined,
|
|
257
|
+
cacheReadInputTokens: undefined,
|
|
258
|
+
stopReason: undefined,
|
|
259
|
+
requestMessageCount: input.length,
|
|
260
|
+
requestToolCount: requestToolNames.length,
|
|
261
|
+
responseMessageCount: undefined,
|
|
262
|
+
responseToolCallCount: undefined,
|
|
263
|
+
responsePreview: undefined,
|
|
264
|
+
toolCallNames: undefined,
|
|
265
|
+
},
|
|
266
|
+
requestSections: requestSections.length > 0 ? requestSections : undefined,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Normalize a legacy OpenAI Chat Completions request payload.
|
|
272
|
+
* Requires `messages` array in the request.
|
|
273
|
+
*/
|
|
274
|
+
function normalizeOpenAiChatCompletionsRequestPayload(
|
|
275
|
+
requestPayload: unknown,
|
|
276
|
+
allowPlainText = false,
|
|
115
277
|
): NormalizedPayloadCandidate | null {
|
|
116
278
|
const request = asRecord(requestPayload);
|
|
117
279
|
if (!request) {
|
|
@@ -202,6 +364,130 @@ function normalizeOpenAiRequestPayload(
|
|
|
202
364
|
|
|
203
365
|
function normalizeOpenAiResponsePayload(
|
|
204
366
|
responsePayload: unknown,
|
|
367
|
+
): NormalizedPayloadCandidate | null {
|
|
368
|
+
// Try Responses API shape first, then fall back to chat-completions.
|
|
369
|
+
return (
|
|
370
|
+
normalizeOpenAiResponsesResponsePayload(responsePayload) ??
|
|
371
|
+
normalizeOpenAiChatCompletionsResponsePayload(responsePayload)
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Detect and normalize OpenAI Responses API response payloads.
|
|
377
|
+
*
|
|
378
|
+
* Responses responses have an `output` array of items instead of `choices`.
|
|
379
|
+
* Tool calls are top-level items with `type: "function_call"`.
|
|
380
|
+
* Usage uses `input_tokens`/`output_tokens` (not `prompt_tokens`/`completion_tokens`).
|
|
381
|
+
* `status` replaces `choices[0].finish_reason`.
|
|
382
|
+
*/
|
|
383
|
+
function normalizeOpenAiResponsesResponsePayload(
|
|
384
|
+
responsePayload: unknown,
|
|
385
|
+
): NormalizedPayloadCandidate | null {
|
|
386
|
+
const response = asRecord(responsePayload);
|
|
387
|
+
if (!response) {
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const output = asRecordArray(response.output);
|
|
392
|
+
if (!output) {
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Require at least one Responses-specific signal
|
|
397
|
+
const hasResponsesSignal =
|
|
398
|
+
typeof response.status === "string" ||
|
|
399
|
+
hasOpenAiModelPrefix(asString(response.model)) ||
|
|
400
|
+
output.some(
|
|
401
|
+
(item) =>
|
|
402
|
+
asString(item.type) === "message" ||
|
|
403
|
+
asString(item.type) === "function_call",
|
|
404
|
+
);
|
|
405
|
+
if (!hasResponsesSignal) {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const responseSections: LlmContextSection[] = [];
|
|
410
|
+
let responseText: string | undefined;
|
|
411
|
+
const toolCallSections: LlmContextSection[] = [];
|
|
412
|
+
let toolCallIndex = 0;
|
|
413
|
+
|
|
414
|
+
for (const item of output) {
|
|
415
|
+
const itemType = asString(item.type);
|
|
416
|
+
|
|
417
|
+
if (itemType === "message") {
|
|
418
|
+
const role = asString(item.role) ?? "assistant";
|
|
419
|
+
const content = asRecordArray(item.content);
|
|
420
|
+
const text = content ? extractOpenAiContentText(content) : undefined;
|
|
421
|
+
if (text !== undefined) {
|
|
422
|
+
responseText = text;
|
|
423
|
+
responseSections.push({
|
|
424
|
+
kind: "message",
|
|
425
|
+
label: "Assistant response",
|
|
426
|
+
role,
|
|
427
|
+
text,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (itemType === "function_call") {
|
|
434
|
+
toolCallIndex++;
|
|
435
|
+
const name = asString(item.name);
|
|
436
|
+
const args = parseJsonValue(asString(item.arguments));
|
|
437
|
+
const section: LlmContextSection = {
|
|
438
|
+
kind: "function_call",
|
|
439
|
+
label: `Response tool call ${toolCallIndex}`,
|
|
440
|
+
role: "assistant",
|
|
441
|
+
toolName: name,
|
|
442
|
+
data: args,
|
|
443
|
+
text: previewStructuredValue(args),
|
|
444
|
+
};
|
|
445
|
+
toolCallSections.push(section);
|
|
446
|
+
responseSections.push(section);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const usage = asRecord(response.usage);
|
|
451
|
+
const toolCallNames = toolCallSections
|
|
452
|
+
.map((section) => section.toolName)
|
|
453
|
+
.filter((name): name is string => typeof name === "string");
|
|
454
|
+
|
|
455
|
+
// Map Responses API status to a stop reason string.
|
|
456
|
+
const status = asString(response.status);
|
|
457
|
+
const stopReason = status === "completed" ? "stop" : status;
|
|
458
|
+
|
|
459
|
+
return {
|
|
460
|
+
provider: "openai",
|
|
461
|
+
summary: {
|
|
462
|
+
provider: "openai",
|
|
463
|
+
model: asString(response.model),
|
|
464
|
+
inputTokens: asNumber(usage?.input_tokens),
|
|
465
|
+
outputTokens: asNumber(usage?.output_tokens),
|
|
466
|
+
cacheCreationInputTokens: undefined,
|
|
467
|
+
cacheReadInputTokens: undefined,
|
|
468
|
+
stopReason,
|
|
469
|
+
requestMessageCount: undefined,
|
|
470
|
+
requestToolCount: undefined,
|
|
471
|
+
responseMessageCount:
|
|
472
|
+
responseText !== undefined || toolCallSections.length > 0
|
|
473
|
+
? 1
|
|
474
|
+
: undefined,
|
|
475
|
+
responseToolCallCount:
|
|
476
|
+
toolCallSections.length > 0 ? toolCallSections.length : undefined,
|
|
477
|
+
responsePreview: responseText ? truncateText(responseText) : undefined,
|
|
478
|
+
toolCallNames: toolCallNames.length > 0 ? toolCallNames : undefined,
|
|
479
|
+
},
|
|
480
|
+
responseSections:
|
|
481
|
+
responseSections.length > 0 ? responseSections : undefined,
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Normalize a legacy OpenAI Chat Completions response payload.
|
|
487
|
+
* Requires `choices` array in the response.
|
|
488
|
+
*/
|
|
489
|
+
function normalizeOpenAiChatCompletionsResponsePayload(
|
|
490
|
+
responsePayload: unknown,
|
|
205
491
|
): NormalizedPayloadCandidate | null {
|
|
206
492
|
const response = asRecord(responsePayload);
|
|
207
493
|
if (!response) {
|
|
@@ -739,6 +1025,23 @@ function extractOpenAiRequestToolNames(tools: unknown): string[] {
|
|
|
739
1025
|
.filter((name): name is string => typeof name === "string");
|
|
740
1026
|
}
|
|
741
1027
|
|
|
1028
|
+
/**
|
|
1029
|
+
* Extract tool names from Responses API tool definitions.
|
|
1030
|
+
* Responses tools have `type: "function"` at the top level with `name`
|
|
1031
|
+
* directly on the tool object (no nested `function` wrapper).
|
|
1032
|
+
*/
|
|
1033
|
+
function extractOpenAiResponsesRequestToolNames(tools: unknown): string[] {
|
|
1034
|
+
return (asRecordArray(tools) ?? [])
|
|
1035
|
+
.map((tool) => {
|
|
1036
|
+
// Responses shape: { type: "function", name: "...", ... }
|
|
1037
|
+
if (asString(tool.type) === "function" && asString(tool.name)) {
|
|
1038
|
+
return asString(tool.name);
|
|
1039
|
+
}
|
|
1040
|
+
return undefined;
|
|
1041
|
+
})
|
|
1042
|
+
.filter((name): name is string => typeof name === "string");
|
|
1043
|
+
}
|
|
1044
|
+
|
|
742
1045
|
function extractAnthropicToolNames(tools: unknown): string[] {
|
|
743
1046
|
return (asRecordArray(tools) ?? [])
|
|
744
1047
|
.map((tool) => asString(tool.name))
|
|
@@ -868,14 +868,15 @@ describe("Memory Item Routes", () => {
|
|
|
868
868
|
const res = await handler(ctx);
|
|
869
869
|
expect(res.status).toBe(204);
|
|
870
870
|
|
|
871
|
-
// Verify the node is gone
|
|
871
|
+
// Verify the node is soft-deleted (fidelity='gone')
|
|
872
872
|
const db = getDb();
|
|
873
873
|
const node = db
|
|
874
874
|
.select()
|
|
875
875
|
.from(memoryGraphNodes)
|
|
876
876
|
.where(eq(memoryGraphNodes.id, "i1"))
|
|
877
877
|
.get();
|
|
878
|
-
expect(node).
|
|
878
|
+
expect(node).toBeDefined();
|
|
879
|
+
expect(node?.fidelity).toBe("gone");
|
|
879
880
|
});
|
|
880
881
|
|
|
881
882
|
test("returns 404 for non-existent item", async () => {
|
|
@@ -45,6 +45,9 @@ import {
|
|
|
45
45
|
} from "../migrations/vbundle-importer.js";
|
|
46
46
|
import { validateVBundle } from "../migrations/vbundle-validator.js";
|
|
47
47
|
|
|
48
|
+
/** Credentials with this prefix are platform-identity keys and must not be imported. */
|
|
49
|
+
const PLATFORM_CREDENTIAL_PREFIX = "vellum:";
|
|
50
|
+
|
|
48
51
|
const log = getLogger("migration-routes");
|
|
49
52
|
|
|
50
53
|
/**
|
|
@@ -483,6 +486,7 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
|
|
|
483
486
|
succeeded: number;
|
|
484
487
|
failed: number;
|
|
485
488
|
failedAccounts: string[];
|
|
489
|
+
skippedPlatform: number;
|
|
486
490
|
}
|
|
487
491
|
| undefined;
|
|
488
492
|
|
|
@@ -491,9 +495,22 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
|
|
|
491
495
|
validation.entries,
|
|
492
496
|
validation.manifest!,
|
|
493
497
|
);
|
|
494
|
-
|
|
498
|
+
|
|
499
|
+
// Filter out platform-identity credentials (vellum:*) — these are
|
|
500
|
+
// environment-specific and must not overwrite the target's own identity.
|
|
501
|
+
const userCredentials = bundleCredentials.filter(
|
|
502
|
+
(c) => !c.account.startsWith(PLATFORM_CREDENTIAL_PREFIX),
|
|
503
|
+
);
|
|
504
|
+
const skippedPlatform = bundleCredentials.length - userCredentials.length;
|
|
505
|
+
if (skippedPlatform > 0) {
|
|
506
|
+
log.info(
|
|
507
|
+
`Skipped ${skippedPlatform} platform credential(s) from import`,
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (userCredentials.length > 0) {
|
|
495
512
|
try {
|
|
496
|
-
const credResults = await bulkSetSecureKeysAsync(
|
|
513
|
+
const credResults = await bulkSetSecureKeysAsync(userCredentials);
|
|
497
514
|
const failedResults = credResults.filter((r) => !r.ok);
|
|
498
515
|
if (failedResults.length > 0) {
|
|
499
516
|
log.warn(
|
|
@@ -502,15 +519,16 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
|
|
|
502
519
|
);
|
|
503
520
|
}
|
|
504
521
|
log.info(
|
|
505
|
-
{ total:
|
|
522
|
+
{ total: userCredentials.length, failed: failedResults.length },
|
|
506
523
|
"Credential import complete",
|
|
507
524
|
);
|
|
508
|
-
const succeeded =
|
|
525
|
+
const succeeded = userCredentials.length - failedResults.length;
|
|
509
526
|
credentialsImported = {
|
|
510
|
-
total:
|
|
527
|
+
total: userCredentials.length,
|
|
511
528
|
succeeded,
|
|
512
529
|
failed: failedResults.length,
|
|
513
530
|
failedAccounts: failedResults.map((f) => f.account),
|
|
531
|
+
skippedPlatform,
|
|
514
532
|
};
|
|
515
533
|
if (failedResults.length > 0) {
|
|
516
534
|
result.report.warnings.push(
|
|
@@ -522,7 +540,24 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
|
|
|
522
540
|
result.report.warnings.push(
|
|
523
541
|
`Credential import failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
524
542
|
);
|
|
543
|
+
credentialsImported = {
|
|
544
|
+
total: userCredentials.length,
|
|
545
|
+
succeeded: 0,
|
|
546
|
+
failed: userCredentials.length,
|
|
547
|
+
failedAccounts: userCredentials.map((c) => c.account),
|
|
548
|
+
skippedPlatform,
|
|
549
|
+
};
|
|
525
550
|
}
|
|
551
|
+
} else if (skippedPlatform > 0) {
|
|
552
|
+
// All credentials in the bundle were platform credentials — report
|
|
553
|
+
// the skip count even though nothing was sent to CES.
|
|
554
|
+
credentialsImported = {
|
|
555
|
+
total: userCredentials.length,
|
|
556
|
+
succeeded: 0,
|
|
557
|
+
failed: 0,
|
|
558
|
+
failedAccounts: [],
|
|
559
|
+
skippedPlatform,
|
|
560
|
+
};
|
|
526
561
|
}
|
|
527
562
|
}
|
|
528
563
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { readFileSync } from "node:fs";
|
|
11
|
-
import { join } from "node:path";
|
|
11
|
+
import { basename, join } from "node:path";
|
|
12
12
|
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
|
|
@@ -36,6 +36,8 @@ import {
|
|
|
36
36
|
generateAllowlistOptions,
|
|
37
37
|
generateScopeOptions,
|
|
38
38
|
} from "../../permissions/checker.js";
|
|
39
|
+
import { resolveGuardianPersonaPath } from "../../prompts/persona-resolver.js";
|
|
40
|
+
import type { ToolDefinition } from "../../providers/types.js";
|
|
39
41
|
import { getSecureKeyAsync } from "../../security/secure-keys.js";
|
|
40
42
|
import { parseToolManifestFile } from "../../skills/tool-manifest.js";
|
|
41
43
|
import {
|
|
@@ -314,16 +316,31 @@ async function handleOAuthConnectStart(body: {
|
|
|
314
316
|
// Workspace files (list/read)
|
|
315
317
|
// ---------------------------------------------------------------------------
|
|
316
318
|
|
|
317
|
-
|
|
319
|
+
/**
|
|
320
|
+
* Build the list of workspace files exposed via the workspace-files endpoint.
|
|
321
|
+
*
|
|
322
|
+
* Returns the static identity/soul files and skills directory plus the
|
|
323
|
+
* guardian's resolved per-user persona file at `users/<slug>.md` when a
|
|
324
|
+
* guardian exists. Callers should invoke this per-request instead of
|
|
325
|
+
* caching, since the guardian can change over the lifetime of the daemon.
|
|
326
|
+
*/
|
|
327
|
+
function getWorkspaceFiles(): string[] {
|
|
328
|
+
const files = ["IDENTITY.md", "SOUL.md", "skills/"];
|
|
329
|
+
const guardianPath = resolveGuardianPersonaPath();
|
|
330
|
+
if (guardianPath) {
|
|
331
|
+
files.push(`users/${basename(guardianPath)}`);
|
|
332
|
+
}
|
|
333
|
+
return files;
|
|
334
|
+
}
|
|
318
335
|
|
|
319
336
|
function handleWorkspaceFilesList(): Response {
|
|
320
337
|
const base = getWorkspaceDir();
|
|
321
|
-
const files =
|
|
338
|
+
const files = getWorkspaceFiles().map((name) => ({
|
|
322
339
|
path: name,
|
|
323
340
|
name,
|
|
324
341
|
exists: pathExists(join(base, name)),
|
|
325
342
|
}));
|
|
326
|
-
return Response.json({ files });
|
|
343
|
+
return Response.json({ type: "workspace_files_list_response", files });
|
|
327
344
|
}
|
|
328
345
|
|
|
329
346
|
function handleWorkspaceFileRead(requestedPath: string): Response {
|
|
@@ -389,7 +406,7 @@ function handleToolNamesList(): Response {
|
|
|
389
406
|
const schemas: Record<string, SchemaShape> = {};
|
|
390
407
|
|
|
391
408
|
// Collect raw definitions from the registry so we can transform them.
|
|
392
|
-
const rawDefs:
|
|
409
|
+
const rawDefs: ToolDefinition[] = [];
|
|
393
410
|
for (const tool of tools) {
|
|
394
411
|
try {
|
|
395
412
|
rawDefs.push(tool.getDefinition());
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
inspectSkill,
|
|
25
25
|
installSkill,
|
|
26
26
|
listSkills,
|
|
27
|
-
|
|
27
|
+
listSkillsFiltered,
|
|
28
28
|
searchSkills,
|
|
29
29
|
uninstallSkill,
|
|
30
30
|
updateSkill,
|
|
@@ -40,6 +40,13 @@ export interface SkillRouteDeps {
|
|
|
40
40
|
getSkillContext: () => SkillOperationContext;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
const partnerAuditSchema = z.object({
|
|
44
|
+
risk: z.enum(["safe", "low", "medium", "high", "critical", "unknown"]),
|
|
45
|
+
alerts: z.number().optional(),
|
|
46
|
+
score: z.number().optional(),
|
|
47
|
+
analyzedAt: z.string(),
|
|
48
|
+
});
|
|
49
|
+
|
|
43
50
|
const slimSkillBase = {
|
|
44
51
|
id: z.string(),
|
|
45
52
|
name: z.string(),
|
|
@@ -60,6 +67,7 @@ const slimSkillSchema = z.discriminatedUnion("origin", [
|
|
|
60
67
|
installs: z.number(),
|
|
61
68
|
reports: z.number(),
|
|
62
69
|
publishedAt: z.string().optional(),
|
|
70
|
+
version: z.string(),
|
|
63
71
|
}),
|
|
64
72
|
z.object({
|
|
65
73
|
...slimSkillBase,
|
|
@@ -67,6 +75,7 @@ const slimSkillSchema = z.discriminatedUnion("origin", [
|
|
|
67
75
|
slug: z.string(),
|
|
68
76
|
sourceRepo: z.string(),
|
|
69
77
|
installs: z.number(),
|
|
78
|
+
audit: z.record(z.string(), partnerAuditSchema).optional(),
|
|
70
79
|
}),
|
|
71
80
|
z.object({ ...slimSkillBase, origin: z.literal("custom") }),
|
|
72
81
|
]);
|
|
@@ -82,6 +91,7 @@ const skillDetailSchema = z.discriminatedUnion("origin", [
|
|
|
82
91
|
installs: z.number(),
|
|
83
92
|
reports: z.number(),
|
|
84
93
|
publishedAt: z.string().optional(),
|
|
94
|
+
version: z.string(),
|
|
85
95
|
owner: z
|
|
86
96
|
.object({
|
|
87
97
|
handle: z.string(),
|
|
@@ -115,6 +125,7 @@ const skillDetailSchema = z.discriminatedUnion("origin", [
|
|
|
115
125
|
slug: z.string(),
|
|
116
126
|
sourceRepo: z.string(),
|
|
117
127
|
installs: z.number(),
|
|
128
|
+
audit: z.record(z.string(), partnerAuditSchema).optional(),
|
|
118
129
|
}),
|
|
119
130
|
z.object({ ...slimSkillBase, origin: z.literal("custom") }),
|
|
120
131
|
]);
|
|
@@ -129,7 +140,7 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
129
140
|
policyKey: "skills",
|
|
130
141
|
summary: "List all skills",
|
|
131
142
|
description:
|
|
132
|
-
"Return all installed skills. Pass ?include=catalog to also include available catalog skills.",
|
|
143
|
+
"Return all installed skills. Pass ?include=catalog to also include available catalog skills. Supports optional filter params: origin, kind, q, category.",
|
|
133
144
|
tags: ["skills"],
|
|
134
145
|
queryParams: [
|
|
135
146
|
{
|
|
@@ -138,16 +149,73 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
138
149
|
description:
|
|
139
150
|
"Optional inclusion flag. Use 'catalog' to merge available Vellum catalog skills into the response.",
|
|
140
151
|
},
|
|
152
|
+
{
|
|
153
|
+
name: "origin",
|
|
154
|
+
schema: { type: "string" },
|
|
155
|
+
description:
|
|
156
|
+
"Filter by skill origin (e.g. 'vellum', 'clawhub', 'skillssh', 'custom').",
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: "kind",
|
|
160
|
+
schema: { type: "string" },
|
|
161
|
+
description:
|
|
162
|
+
"Filter by kind: 'installed' (includes bundled), 'available', or pass through as skill.kind.",
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: "q",
|
|
166
|
+
schema: { type: "string" },
|
|
167
|
+
description:
|
|
168
|
+
"Text search across skill name, description, id, and origin label.",
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: "category",
|
|
172
|
+
schema: { type: "string" },
|
|
173
|
+
description:
|
|
174
|
+
"Filter by inferred category (e.g. 'communication', 'productivity').",
|
|
175
|
+
},
|
|
141
176
|
],
|
|
142
177
|
responseBody: z.object({
|
|
143
178
|
skills: z.array(slimSkillSchema).describe("Skill objects"),
|
|
179
|
+
categoryCounts: z
|
|
180
|
+
.record(z.string(), z.number())
|
|
181
|
+
.optional()
|
|
182
|
+
.describe(
|
|
183
|
+
"Count of skills per category (before category filter is applied)",
|
|
184
|
+
),
|
|
185
|
+
totalCount: z
|
|
186
|
+
.number()
|
|
187
|
+
.optional()
|
|
188
|
+
.describe("Total number of skills matching non-category filters"),
|
|
144
189
|
}),
|
|
145
190
|
handler: async ({ url }) => {
|
|
146
191
|
const include = url.searchParams.get("include");
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
192
|
+
const origin = url.searchParams.get("origin");
|
|
193
|
+
const kind = url.searchParams.get("kind");
|
|
194
|
+
const q = url.searchParams.get("q");
|
|
195
|
+
const category = url.searchParams.get("category");
|
|
196
|
+
|
|
197
|
+
const hasFilter = !!(origin || kind || q || category);
|
|
198
|
+
|
|
199
|
+
if (hasFilter || include === "catalog") {
|
|
200
|
+
const result = await listSkillsFiltered(
|
|
201
|
+
{
|
|
202
|
+
...(origin ? { origin } : {}),
|
|
203
|
+
...(kind ? { kind } : {}),
|
|
204
|
+
...(q ? { q } : {}),
|
|
205
|
+
...(category ? { category } : {}),
|
|
206
|
+
includeCatalog: include === "catalog",
|
|
207
|
+
},
|
|
208
|
+
ctx(),
|
|
209
|
+
);
|
|
210
|
+
return Response.json({
|
|
211
|
+
skills: result.skills,
|
|
212
|
+
categoryCounts: result.categoryCounts,
|
|
213
|
+
totalCount: result.totalCount,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// No filter params and include !== catalog: preserve existing behavior
|
|
218
|
+
const skills = listSkills(ctx());
|
|
151
219
|
return Response.json({ skills });
|
|
152
220
|
},
|
|
153
221
|
},
|
|
@@ -312,6 +380,7 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
312
380
|
}),
|
|
313
381
|
responseBody: z.object({
|
|
314
382
|
ok: z.boolean(),
|
|
383
|
+
skillId: z.string().optional(),
|
|
315
384
|
}),
|
|
316
385
|
handler: async ({ req, authContext }) => {
|
|
317
386
|
const body = (await req.json()) as {
|
|
@@ -337,7 +406,7 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
337
406
|
if (!result.success) {
|
|
338
407
|
return httpError("INTERNAL_ERROR", result.error, 500);
|
|
339
408
|
}
|
|
340
|
-
return Response.json({ ok: true });
|
|
409
|
+
return Response.json({ ok: true, skillId: result.skillId });
|
|
341
410
|
},
|
|
342
411
|
},
|
|
343
412
|
|