@vellumai/assistant 0.5.10 → 0.5.12
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/AGENTS.md +8 -0
- package/ARCHITECTURE.md +43 -43
- package/Dockerfile +3 -0
- package/docs/architecture/integrations.md +37 -42
- package/docs/architecture/memory.md +7 -12
- package/docs/credential-execution-service.md +9 -9
- package/docs/skills.md +1 -1
- package/node_modules/@vellumai/ces-contracts/src/__tests__/grants.test.ts +7 -7
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +5 -4
- package/node_modules/@vellumai/credential-storage/src/index.ts +3 -3
- package/node_modules/@vellumai/credential-storage/src/static-credentials.ts +1 -1
- package/openapi.yaml +7208 -0
- package/package.json +2 -1
- package/scripts/generate-openapi.ts +562 -0
- package/src/__tests__/acp-session.test.ts +239 -44
- package/src/__tests__/assistant-feature-flag-guard.test.ts +8 -8
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +5 -86
- package/src/__tests__/assistant-feature-flags-integration.test.ts +7 -14
- package/src/__tests__/browser-skill-endstate.test.ts +1 -1
- package/src/__tests__/btw-routes.test.ts +8 -0
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +10 -10
- package/src/__tests__/catalog-cache.test.ts +164 -0
- package/src/__tests__/catalog-search.test.ts +61 -0
- package/src/__tests__/channel-approvals.test.ts +7 -7
- package/src/__tests__/channel-readiness-service.test.ts +41 -0
- package/src/__tests__/cli-command-risk-guard.test.ts +181 -6
- package/src/__tests__/config-schema.test.ts +10 -2
- package/src/__tests__/context-memory-e2e.test.ts +2 -6
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +396 -0
- package/src/__tests__/conversation-error.test.ts +3 -2
- package/src/__tests__/conversation-skill-tools.test.ts +1 -3
- package/src/__tests__/conversation-title-service.test.ts +2 -15
- package/src/__tests__/credential-execution-feature-gates.test.ts +4 -8
- package/src/__tests__/credential-execution-managed-contract.test.ts +8 -8
- package/src/__tests__/credential-security-e2e.test.ts +4 -4
- package/src/__tests__/credential-security-invariants.test.ts +12 -18
- package/src/__tests__/credential-vault-unit.test.ts +32 -34
- package/src/__tests__/credential-vault.test.ts +25 -33
- package/src/__tests__/credentials-cli.test.ts +3 -3
- package/src/__tests__/daemon-credential-client.test.ts +2 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -0
- package/src/__tests__/heartbeat-service.test.ts +35 -0
- package/src/__tests__/host-bash-proxy.test.ts +79 -0
- package/src/__tests__/host-cu-proxy.test.ts +90 -0
- package/src/__tests__/host-file-proxy.test.ts +89 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +3 -3
- package/src/__tests__/integration-status.test.ts +5 -5
- package/src/__tests__/list-messages-attachments.test.ts +171 -0
- package/src/__tests__/llm-request-log-turn-query.test.ts +64 -0
- package/src/__tests__/log-export-workspace.test.ts +1 -1
- package/src/__tests__/mcp-abort-signal.test.ts +205 -0
- package/src/__tests__/mcp-client-auth.test.ts +1 -1
- package/src/__tests__/memory-lifecycle-e2e.test.ts +2 -2
- package/src/__tests__/memory-recall-log-store.test.ts +182 -0
- package/src/__tests__/memory-recall-quality.test.ts +6 -8
- package/src/__tests__/memory-regressions.test.ts +53 -42
- package/src/__tests__/memory-retrieval.benchmark.test.ts +5 -9
- package/src/__tests__/messaging-send-tool.test.ts +5 -5
- package/src/__tests__/messaging-skill-split.test.ts +2 -17
- package/src/__tests__/notification-telegram-adapter.test.ts +125 -0
- package/src/__tests__/oauth-cli.test.ts +203 -649
- package/src/__tests__/oauth-provider-profiles.test.ts +55 -20
- package/src/__tests__/oauth-scope-policy.test.ts +4 -6
- package/src/__tests__/onboarding-template-contract.test.ts +2 -2
- package/src/__tests__/platform-callback-registration.test.ts +119 -0
- package/src/__tests__/secret-ingress-channel.test.ts +261 -0
- package/src/__tests__/secret-ingress-cli.test.ts +201 -0
- package/src/__tests__/secret-ingress-http.test.ts +312 -0
- package/src/__tests__/secret-ingress.test.ts +283 -0
- package/src/__tests__/secret-onetime-send.test.ts +4 -4
- package/src/__tests__/secret-routes-managed-proxy.test.ts +78 -0
- package/src/__tests__/secure-keys-managed-failover.test.ts +73 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +4 -4
- package/src/__tests__/skill-feature-flags.test.ts +11 -19
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -1
- package/src/__tests__/skill-load-inline-command.test.ts +3 -3
- package/src/__tests__/skill-load-inline-includes.test.ts +2 -2
- package/src/__tests__/skill-memory.test.ts +2 -4
- package/src/__tests__/skill-projection-feature-flag.test.ts +2 -4
- package/src/__tests__/skill-projection.benchmark.test.ts +1 -3
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +16 -2
- package/src/__tests__/slack-channel-config.test.ts +1 -1
- package/src/__tests__/slack-messaging-token-resolution.test.ts +22 -24
- package/src/__tests__/slack-share-routes.test.ts +5 -5
- package/src/__tests__/slack-skill.test.ts +5 -69
- package/src/__tests__/system-prompt.test.ts +39 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -1
- package/src/__tests__/workspace-migration-018-rekey-compound-credential-keys.test.ts +181 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +5 -4
- package/src/acp/client-handler.ts +113 -31
- package/src/acp/session-manager.ts +29 -27
- package/src/approvals/guardian-request-resolvers.ts +1 -1
- package/src/cli/AGENTS.md +113 -0
- package/src/cli/commands/autonomy.ts +3 -5
- package/src/cli/commands/browser-relay.ts +2 -17
- package/src/cli/commands/contacts.ts +6 -4
- package/src/cli/commands/conversations.ts +13 -1
- package/src/cli/commands/credential-execution.ts +17 -3
- package/src/cli/commands/credentials.ts +2 -8
- package/src/cli/commands/memory.ts +2 -3
- package/src/cli/commands/oauth/__tests__/connect.test.ts +706 -0
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +686 -0
- package/src/cli/commands/oauth/__tests__/mode.test.ts +625 -0
- package/src/cli/commands/oauth/__tests__/ping.test.ts +631 -0
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +574 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +416 -0
- package/src/cli/commands/oauth/__tests__/status.test.ts +551 -0
- package/src/cli/commands/oauth/__tests__/token.test.ts +420 -0
- package/src/cli/commands/oauth/apps.ts +87 -50
- package/src/cli/commands/oauth/connect.ts +405 -0
- package/src/cli/commands/oauth/disconnect.ts +285 -0
- package/src/cli/commands/oauth/index.ts +62 -20
- package/src/cli/commands/oauth/mode.ts +251 -0
- package/src/cli/commands/oauth/ping.ts +196 -0
- package/src/cli/commands/oauth/providers.ts +589 -55
- package/src/cli/commands/oauth/request.ts +564 -0
- package/src/cli/commands/oauth/shared.ts +114 -0
- package/src/cli/commands/oauth/status.ts +191 -0
- package/src/cli/commands/oauth/token.ts +150 -0
- package/src/cli/commands/platform/connect.ts +104 -0
- package/src/cli/commands/platform/disconnect.ts +118 -0
- package/src/cli/commands/platform/index.ts +252 -0
- package/src/cli/commands/sequence.ts +5 -4
- package/src/cli/commands/shotgun.ts +16 -0
- package/src/cli/commands/skills.ts +173 -41
- package/src/cli/commands/usage.ts +5 -11
- package/src/cli/lib/daemon-credential-client.ts +22 -38
- package/src/cli/program.ts +1 -1
- package/src/cli.ts +82 -17
- package/src/config/assistant-feature-flags.ts +77 -18
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -1
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +1 -1
- package/src/config/bundled-skills/conversations/SKILL.md +20 -0
- package/src/config/bundled-skills/conversations/TOOLS.json +23 -0
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +66 -0
- package/src/config/bundled-skills/gmail/SKILL.md +13 -13
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +3 -3
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +2 -2
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +2 -2
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +1 -1
- package/src/config/bundled-skills/google-calendar/SKILL.md +10 -4
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +19 -42
- package/src/config/bundled-skills/messaging/TOOLS.json +9 -9
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +1 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +5 -6
- package/src/config/bundled-skills/notifications/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +2 -2
- package/src/config/bundled-skills/settings/SKILL.md +5 -3
- package/src/config/bundled-skills/settings/TOOLS.json +17 -0
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +50 -0
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +7 -0
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +6 -1
- package/src/config/bundled-skills/settings/tools/identity-avatar.ts +55 -0
- package/src/config/bundled-skills/skills-catalog/SKILL.md +3 -3
- package/src/config/bundled-skills/slack/SKILL.md +58 -44
- package/src/config/bundled-tool-registry.ts +7 -19
- package/src/config/env.ts +5 -1
- package/src/config/feature-flag-registry.json +58 -42
- package/src/config/loader.ts +4 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/security.ts +9 -1
- package/src/config/schemas/services.ts +1 -1
- package/src/config/skill-state.ts +1 -3
- package/src/config/skills.ts +2 -4
- package/src/credential-execution/client.ts +1 -1
- package/src/credential-execution/feature-gates.ts +9 -16
- package/src/credential-execution/process-manager.ts +12 -0
- package/src/daemon/config-watcher.ts +4 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +10 -0
- package/src/daemon/conversation-agent-loop.ts +51 -2
- package/src/daemon/conversation-error.ts +36 -6
- package/src/daemon/conversation-memory.ts +0 -1
- package/src/daemon/conversation-messaging.ts +9 -0
- package/src/daemon/conversation-runtime-assembly.ts +33 -0
- package/src/daemon/conversation-surfaces.ts +120 -14
- package/src/daemon/conversation.ts +5 -0
- package/src/daemon/handlers/config-slack-channel.ts +43 -1
- package/src/daemon/handlers/conversations.ts +41 -33
- package/src/daemon/handlers/skills.ts +148 -3
- package/src/daemon/host-bash-proxy.ts +16 -0
- package/src/daemon/host-cu-proxy.ts +16 -0
- package/src/daemon/host-file-proxy.ts +16 -0
- package/src/daemon/lifecycle.ts +73 -3
- package/src/daemon/message-types/acp.ts +0 -15
- package/src/daemon/message-types/conversations.ts +1 -0
- package/src/daemon/message-types/guardian-actions.ts +2 -0
- package/src/daemon/message-types/host-bash.ts +6 -1
- package/src/daemon/message-types/host-cu.ts +6 -1
- package/src/daemon/message-types/host-file.ts +6 -1
- package/src/daemon/message-types/integrations.ts +0 -1
- package/src/daemon/message-types/memory.ts +0 -1
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/schedules.ts +9 -0
- package/src/daemon/server.ts +48 -9
- package/src/email/feature-gate.ts +3 -3
- package/src/heartbeat/heartbeat-service.ts +48 -0
- package/src/hooks/cli.ts +74 -0
- package/src/inbound/platform-callback-registration.ts +68 -19
- package/src/mcp/client.ts +6 -1
- package/src/mcp/manager.ts +2 -1
- package/src/mcp/mcp-oauth-provider.ts +3 -3
- package/src/memory/app-store.ts +3 -3
- package/src/memory/conversation-crud.ts +213 -0
- package/src/memory/conversation-key-store.ts +26 -0
- package/src/memory/conversation-title-service.ts +7 -17
- package/src/memory/db-init.ts +24 -0
- package/src/memory/embedding-local.ts +47 -2
- package/src/memory/indexer.ts +13 -10
- package/src/memory/items-extractor.ts +12 -4
- package/src/memory/job-utils.ts +5 -0
- package/src/memory/jobs-store.ts +10 -2
- package/src/memory/journal-memory.ts +6 -2
- package/src/memory/llm-request-log-store.ts +88 -21
- package/src/memory/memory-recall-log-store.ts +128 -0
- package/src/memory/migrations/194-memory-recall-logs.ts +50 -0
- package/src/memory/migrations/195-oauth-providers-ping-config.ts +23 -0
- package/src/memory/migrations/196-messages-conversation-created-at-index.ts +9 -0
- package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +186 -0
- package/src/memory/migrations/197-oauth-providers-behavior-columns.ts +29 -0
- package/src/memory/migrations/198-drop-setup-skill-id-column.ts +11 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/retriever.test.ts +4 -5
- package/src/memory/schema/infrastructure.ts +31 -0
- package/src/memory/schema/oauth.ts +14 -0
- package/src/messaging/provider.ts +13 -12
- package/src/messaging/providers/gmail/adapter.ts +44 -35
- package/src/messaging/providers/slack/adapter.ts +63 -33
- package/src/messaging/providers/telegram-bot/adapter.ts +7 -9
- package/src/messaging/providers/whatsapp/adapter.ts +6 -8
- package/src/notifications/adapters/telegram.ts +78 -2
- package/src/oauth/__tests__/identity-verifier.test.ts +464 -0
- package/src/oauth/byo-connection.test.ts +22 -24
- package/src/oauth/connect-orchestrator.ts +79 -64
- package/src/oauth/connect-types.ts +7 -65
- package/src/oauth/connection-resolver.test.ts +13 -13
- package/src/oauth/connection-resolver.ts +3 -4
- package/src/oauth/identity-verifier.ts +177 -0
- package/src/oauth/manual-token-connection.ts +5 -5
- package/src/oauth/oauth-store.ts +251 -5
- package/src/oauth/platform-connection.test.ts +56 -6
- package/src/oauth/platform-connection.ts +8 -1
- package/src/oauth/seed-providers.ts +256 -34
- package/src/permissions/checker.ts +129 -3
- package/src/permissions/trust-client.ts +2 -2
- package/src/platform/client.ts +2 -2
- package/src/prompts/journal-context.ts +6 -1
- package/src/prompts/system-prompt.ts +43 -9
- package/src/prompts/templates/BOOTSTRAP.md +16 -5
- package/src/providers/anthropic/client.ts +139 -28
- package/src/runtime/auth/__tests__/middleware.test.ts +19 -0
- package/src/runtime/auth/route-policy.ts +0 -1
- package/src/runtime/btw-sidechain.ts +7 -1
- package/src/runtime/channel-approvals.ts +2 -2
- package/src/runtime/channel-readiness-service.ts +30 -7
- package/src/runtime/guardian-action-service.ts +7 -2
- package/src/runtime/http-router.ts +31 -0
- package/src/runtime/http-server.ts +26 -7
- package/src/runtime/http-types.ts +9 -0
- package/src/runtime/pending-interactions.ts +21 -3
- package/src/runtime/routes/acp-routes.ts +46 -28
- package/src/runtime/routes/app-management-routes.ts +123 -0
- package/src/runtime/routes/app-routes.ts +31 -0
- package/src/runtime/routes/approval-routes.ts +108 -3
- package/src/runtime/routes/attachment-routes.ts +45 -0
- package/src/runtime/routes/avatar-routes.ts +16 -0
- package/src/runtime/routes/brain-graph-routes.ts +18 -0
- package/src/runtime/routes/btw-routes.ts +20 -0
- package/src/runtime/routes/call-routes.ts +81 -0
- package/src/runtime/routes/channel-readiness-routes.ts +48 -7
- package/src/runtime/routes/channel-routes.ts +18 -0
- package/src/runtime/routes/channel-verification-routes.ts +49 -1
- package/src/runtime/routes/contact-routes.ts +77 -0
- package/src/runtime/routes/conversation-attention-routes.ts +37 -0
- package/src/runtime/routes/conversation-management-routes.ts +125 -0
- package/src/runtime/routes/conversation-query-routes.ts +78 -0
- package/src/runtime/routes/conversation-routes.ts +191 -39
- package/src/runtime/routes/conversation-starter-routes.ts +29 -0
- package/src/runtime/routes/debug-routes.ts +23 -0
- package/src/runtime/routes/diagnostics-routes.ts +30 -0
- package/src/runtime/routes/documents-routes.ts +42 -0
- package/src/runtime/routes/events-routes.ts +10 -0
- package/src/runtime/routes/global-search-routes.ts +35 -0
- package/src/runtime/routes/guardian-action-routes.ts +61 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +77 -2
- package/src/runtime/routes/heartbeat-routes.ts +278 -0
- package/src/runtime/routes/host-bash-routes.ts +16 -1
- package/src/runtime/routes/host-cu-routes.ts +23 -1
- package/src/runtime/routes/host-file-routes.ts +18 -1
- package/src/runtime/routes/identity-routes.ts +35 -0
- package/src/runtime/routes/inbound-message-handler.ts +46 -25
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -8
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +30 -2
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +1 -2
- package/src/runtime/routes/integrations/slack/share.ts +1 -1
- package/src/runtime/routes/integrations/twilio.ts +32 -22
- package/src/runtime/routes/invite-routes.ts +83 -0
- package/src/runtime/routes/log-export-routes.ts +14 -0
- package/src/runtime/routes/memory-item-routes.ts +99 -1
- package/src/runtime/routes/migration-rollback-routes.ts +25 -0
- package/src/runtime/routes/migration-routes.ts +40 -0
- package/src/runtime/routes/notification-routes.ts +20 -0
- package/src/runtime/routes/oauth-apps.ts +13 -4
- package/src/runtime/routes/pairing-routes.ts +15 -0
- package/src/runtime/routes/recording-routes.ts +72 -0
- package/src/runtime/routes/schedule-routes.ts +77 -5
- package/src/runtime/routes/secret-routes.ts +99 -14
- package/src/runtime/routes/settings-routes.ts +102 -19
- package/src/runtime/routes/skills-routes.ts +141 -18
- package/src/runtime/routes/subagents-routes.ts +38 -3
- package/src/runtime/routes/surface-action-routes.ts +66 -24
- package/src/runtime/routes/surface-content-routes.ts +20 -0
- package/src/runtime/routes/telemetry-routes.ts +12 -0
- package/src/runtime/routes/trace-event-routes.ts +25 -0
- package/src/runtime/routes/trust-rules-routes.ts +46 -0
- package/src/runtime/routes/tts-routes.ts +15 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +38 -0
- package/src/runtime/routes/usage-routes.ts +59 -0
- package/src/runtime/routes/watch-routes.ts +28 -0
- package/src/runtime/routes/work-items-routes.ts +59 -0
- package/src/runtime/routes/workspace-commit-routes.ts +12 -0
- package/src/runtime/routes/workspace-routes.ts +102 -0
- package/src/schedule/integration-status.ts +2 -2
- package/src/schedule/scheduler.ts +7 -1
- package/src/security/AGENTS.md +7 -0
- package/src/security/ces-rpc-credential-backend.ts +19 -16
- package/src/security/credential-backend.ts +1 -1
- package/src/security/encrypted-store.ts +3 -3
- package/src/security/oauth-completion-page.ts +153 -0
- package/src/security/oauth2.ts +58 -17
- package/src/security/secret-ingress.ts +174 -0
- package/src/security/secret-patterns.ts +133 -0
- package/src/security/secret-scanner.ts +28 -117
- package/src/security/secure-keys.ts +207 -7
- package/src/security/token-manager.ts +3 -6
- package/src/signals/bash.ts +6 -1
- package/src/signals/confirm.ts +12 -8
- package/src/signals/user-message.ts +18 -3
- package/src/skills/catalog-cache.ts +44 -0
- package/src/skills/catalog-search.ts +18 -0
- package/src/skills/skill-memory.ts +1 -2
- package/src/tasks/task-runner.ts +7 -1
- package/src/tools/credentials/broker.ts +1 -1
- package/src/tools/credentials/metadata-store.ts +1 -1
- package/src/tools/credentials/post-connect-hooks.ts +1 -1
- package/src/tools/credentials/vault.ts +36 -48
- package/src/tools/host-terminal/host-shell.ts +16 -3
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/memory/definitions.ts +1 -1
- package/src/tools/memory/handlers.test.ts +2 -4
- package/src/tools/skills/load.ts +1 -1
- package/src/tools/skills/sandbox-runner.ts +16 -3
- package/src/tools/terminal/safe-env.ts +7 -0
- package/src/tools/terminal/shell.ts +16 -3
- package/src/tools/tool-manifest.ts +1 -1
- package/src/util/log-redact.ts +9 -34
- package/src/util/logger.ts +11 -1
- package/src/util/sentry-log-stream.ts +51 -0
- package/src/watcher/providers/github.ts +2 -2
- package/src/watcher/providers/gmail.ts +1 -1
- package/src/watcher/providers/google-calendar.ts +1 -1
- package/src/watcher/providers/linear.ts +2 -2
- package/src/workspace/migrations/011-backfill-installation-id.ts +5 -3
- package/src/workspace/migrations/020-rename-oauth-skill-dirs.ts +119 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/docs/architecture/keychain-broker.md +0 -68
- package/src/cli/commands/oauth/connections.ts +0 -734
- package/src/cli/commands/oauth/platform.ts +0 -525
- package/src/cli/commands/platform.ts +0 -176
- package/src/config/bundled-skills/slack/TOOLS.json +0 -272
- package/src/config/bundled-skills/slack/tools/shared.ts +0 -34
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +0 -27
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +0 -38
- package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +0 -146
- package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +0 -105
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +0 -26
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +0 -27
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +0 -25
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +0 -372
- package/src/oauth/provider-behaviors.ts +0 -634
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
import { readFileSync } from "node:fs";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
13
15
|
import {
|
|
14
16
|
getPlatformBaseUrl,
|
|
15
17
|
setIngressPublicBaseUrl,
|
|
@@ -28,10 +30,6 @@ import {
|
|
|
28
30
|
getMostRecentAppByProvider,
|
|
29
31
|
getProvider,
|
|
30
32
|
} from "../../oauth/oauth-store.js";
|
|
31
|
-
import {
|
|
32
|
-
getProviderBehavior,
|
|
33
|
-
resolveService,
|
|
34
|
-
} from "../../oauth/provider-behaviors.js";
|
|
35
33
|
import {
|
|
36
34
|
check,
|
|
37
35
|
classifyRisk,
|
|
@@ -168,14 +166,14 @@ async function handleOAuthConnectStart(body: {
|
|
|
168
166
|
return httpError("BAD_REQUEST", "Missing required field: service", 400);
|
|
169
167
|
}
|
|
170
168
|
|
|
171
|
-
const
|
|
169
|
+
const service = body.service;
|
|
172
170
|
|
|
173
171
|
// Resolve client_id and client_secret from oauth-store.
|
|
174
172
|
let clientId: string | undefined;
|
|
175
173
|
let clientSecret: string | undefined;
|
|
176
174
|
|
|
177
175
|
// Try existing connection first (re-auth flow)
|
|
178
|
-
const conn = getConnectionByProvider(
|
|
176
|
+
const conn = getConnectionByProvider(service);
|
|
179
177
|
if (conn) {
|
|
180
178
|
const app = getApp(conn.oauthAppId);
|
|
181
179
|
if (app) {
|
|
@@ -186,7 +184,7 @@ async function handleOAuthConnectStart(body: {
|
|
|
186
184
|
|
|
187
185
|
// Fall back to most recent app for this provider (first-time connect with stored app)
|
|
188
186
|
if (!clientId) {
|
|
189
|
-
const dbApp = getMostRecentAppByProvider(
|
|
187
|
+
const dbApp = getMostRecentAppByProvider(service);
|
|
190
188
|
if (dbApp) {
|
|
191
189
|
clientId = dbApp.clientId;
|
|
192
190
|
if (!clientSecret) {
|
|
@@ -200,20 +198,17 @@ async function handleOAuthConnectStart(body: {
|
|
|
200
198
|
if (!clientId) {
|
|
201
199
|
return httpError(
|
|
202
200
|
"BAD_REQUEST",
|
|
203
|
-
`No client_id found for "${
|
|
201
|
+
`No client_id found for "${service}". Store it first via the credential vault.`,
|
|
204
202
|
400,
|
|
205
203
|
);
|
|
206
204
|
}
|
|
207
205
|
|
|
208
|
-
const
|
|
209
|
-
const
|
|
210
|
-
const requiresSecret =
|
|
211
|
-
behavior?.setup?.requiresClientSecret ??
|
|
212
|
-
!!(providerRow?.tokenEndpointAuthMethod || providerRow?.extraParams);
|
|
206
|
+
const providerRow = getProvider(service);
|
|
207
|
+
const requiresSecret = !!providerRow?.requiresClientSecret;
|
|
213
208
|
if (requiresSecret && !clientSecret) {
|
|
214
209
|
return httpError(
|
|
215
210
|
"BAD_REQUEST",
|
|
216
|
-
`client_secret is required for "${
|
|
211
|
+
`client_secret is required for "${service}" but not found in the credential store. Store it first via the credential vault.`,
|
|
217
212
|
400,
|
|
218
213
|
);
|
|
219
214
|
}
|
|
@@ -224,7 +219,7 @@ async function handleOAuthConnectStart(body: {
|
|
|
224
219
|
let authUrl: string | undefined;
|
|
225
220
|
|
|
226
221
|
const result = await orchestrateOAuthConnect({
|
|
227
|
-
service
|
|
222
|
+
service,
|
|
228
223
|
requestedScopes: body.requestedScopes,
|
|
229
224
|
clientId,
|
|
230
225
|
clientSecret,
|
|
@@ -236,7 +231,7 @@ async function handleOAuthConnectStart(body: {
|
|
|
236
231
|
// Prefer accountInfo from oauth-store when available.
|
|
237
232
|
let accountInfo = deferredResult.accountInfo;
|
|
238
233
|
try {
|
|
239
|
-
const conn = getConnectionByProvider(
|
|
234
|
+
const conn = getConnectionByProvider(service);
|
|
240
235
|
if (conn?.accountInfo) accountInfo = conn.accountInfo;
|
|
241
236
|
} catch {
|
|
242
237
|
// DB not ready — use orchestrator value
|
|
@@ -275,7 +270,7 @@ async function handleOAuthConnectStart(body: {
|
|
|
275
270
|
|
|
276
271
|
if (!result.success) {
|
|
277
272
|
log.error(
|
|
278
|
-
{ err: result.error, service
|
|
273
|
+
{ err: result.error, service },
|
|
279
274
|
"OAuth connect orchestrator returned error",
|
|
280
275
|
);
|
|
281
276
|
return httpError(
|
|
@@ -296,7 +291,7 @@ async function handleOAuthConnectStart(body: {
|
|
|
296
291
|
// Prefer accountInfo from oauth-store when available.
|
|
297
292
|
let responseAccountInfo = result.accountInfo;
|
|
298
293
|
try {
|
|
299
|
-
const conn = getConnectionByProvider(
|
|
294
|
+
const conn = getConnectionByProvider(service);
|
|
300
295
|
if (conn?.accountInfo) responseAccountInfo = conn.accountInfo;
|
|
301
296
|
} catch {
|
|
302
297
|
// DB not ready — use orchestrator value
|
|
@@ -310,7 +305,7 @@ async function handleOAuthConnectStart(body: {
|
|
|
310
305
|
});
|
|
311
306
|
} catch (err) {
|
|
312
307
|
const message = err instanceof Error ? err.message : String(err);
|
|
313
|
-
log.error({ err, service
|
|
308
|
+
log.error({ err, service }, "OAuth connect flow failed");
|
|
314
309
|
return httpError("INTERNAL_ERROR", sanitizeOAuthError(message), 500);
|
|
315
310
|
}
|
|
316
311
|
}
|
|
@@ -612,6 +607,12 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
612
607
|
endpoint: "settings/voice",
|
|
613
608
|
method: "PUT",
|
|
614
609
|
policyKey: "settings/voice",
|
|
610
|
+
summary: "Update voice activation key",
|
|
611
|
+
description: "Validate and normalize a voice activation key.",
|
|
612
|
+
tags: ["settings"],
|
|
613
|
+
requestBody: z.object({
|
|
614
|
+
activationKey: z.string(),
|
|
615
|
+
}),
|
|
615
616
|
handler: async ({ req }) => {
|
|
616
617
|
const body = (await req.json()) as { activationKey?: string };
|
|
617
618
|
if (!body.activationKey) {
|
|
@@ -626,6 +627,12 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
626
627
|
endpoint: "settings/avatar/generate",
|
|
627
628
|
method: "POST",
|
|
628
629
|
policyKey: "settings/avatar/generate",
|
|
630
|
+
summary: "Generate avatar",
|
|
631
|
+
description: "Generate an AI avatar image from a text description.",
|
|
632
|
+
tags: ["settings"],
|
|
633
|
+
requestBody: z.object({
|
|
634
|
+
description: z.string(),
|
|
635
|
+
}),
|
|
629
636
|
handler: async ({ req }) => {
|
|
630
637
|
const body = (await req.json()) as { description?: string };
|
|
631
638
|
return handleGenerateAvatar(body.description ?? "");
|
|
@@ -637,6 +644,13 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
637
644
|
endpoint: "settings/client",
|
|
638
645
|
method: "PUT",
|
|
639
646
|
policyKey: "settings/client",
|
|
647
|
+
summary: "Update client setting",
|
|
648
|
+
description: "Set a single client-side setting key/value pair.",
|
|
649
|
+
tags: ["settings"],
|
|
650
|
+
requestBody: z.object({
|
|
651
|
+
key: z.string(),
|
|
652
|
+
value: z.string(),
|
|
653
|
+
}),
|
|
640
654
|
handler: async ({ req }) => {
|
|
641
655
|
const body = (await req.json()) as { key?: string; value?: string };
|
|
642
656
|
if (!body.key || body.value === undefined) {
|
|
@@ -651,6 +665,14 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
651
665
|
endpoint: "oauth/start",
|
|
652
666
|
method: "POST",
|
|
653
667
|
policyKey: "oauth/start",
|
|
668
|
+
summary: "Start OAuth flow",
|
|
669
|
+
description:
|
|
670
|
+
"Initiate an OAuth authorization flow for a third-party service.",
|
|
671
|
+
tags: ["oauth"],
|
|
672
|
+
requestBody: z.object({
|
|
673
|
+
service: z.string(),
|
|
674
|
+
requestedScopes: z.array(z.unknown()),
|
|
675
|
+
}),
|
|
654
676
|
handler: async ({ req }) => {
|
|
655
677
|
const body = (await req.json()) as {
|
|
656
678
|
service?: string;
|
|
@@ -665,6 +687,13 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
665
687
|
endpoint: "integrations/oauth/start",
|
|
666
688
|
method: "POST",
|
|
667
689
|
policyKey: "integrations/oauth/start",
|
|
690
|
+
summary: "Start OAuth flow (legacy)",
|
|
691
|
+
description: "Legacy alias for oauth/start.",
|
|
692
|
+
tags: ["oauth"],
|
|
693
|
+
requestBody: z.object({
|
|
694
|
+
service: z.string(),
|
|
695
|
+
requestedScopes: z.array(z.unknown()),
|
|
696
|
+
}),
|
|
668
697
|
handler: async ({ req }) => {
|
|
669
698
|
const body = (await req.json()) as {
|
|
670
699
|
service?: string;
|
|
@@ -679,12 +708,18 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
679
708
|
endpoint: "workspace-files",
|
|
680
709
|
method: "GET",
|
|
681
710
|
policyKey: "workspace-files",
|
|
711
|
+
summary: "List workspace files",
|
|
712
|
+
description: "Return an array of files in the workspace directory.",
|
|
713
|
+
tags: ["workspace"],
|
|
682
714
|
handler: () => handleWorkspaceFilesList(),
|
|
683
715
|
},
|
|
684
716
|
{
|
|
685
717
|
endpoint: "workspace-files/read",
|
|
686
718
|
method: "GET",
|
|
687
719
|
policyKey: "workspace-files/read",
|
|
720
|
+
summary: "Read a workspace file",
|
|
721
|
+
description: "Return the contents of a single file by path.",
|
|
722
|
+
tags: ["workspace"],
|
|
688
723
|
handler: ({ url }) => {
|
|
689
724
|
const filePath = url.searchParams.get("path") ?? "";
|
|
690
725
|
if (!filePath) {
|
|
@@ -703,6 +738,10 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
703
738
|
endpoint: "tools",
|
|
704
739
|
method: "GET",
|
|
705
740
|
policyKey: "tools",
|
|
741
|
+
summary: "List tools",
|
|
742
|
+
description:
|
|
743
|
+
"Return available tool names with their descriptions, risk levels, and categories.",
|
|
744
|
+
tags: ["tools"],
|
|
706
745
|
handler: () => handleToolNamesList(),
|
|
707
746
|
},
|
|
708
747
|
|
|
@@ -711,6 +750,17 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
711
750
|
endpoint: "tools/simulate-permission",
|
|
712
751
|
method: "POST",
|
|
713
752
|
policyKey: "tools/simulate-permission",
|
|
753
|
+
summary: "Simulate tool permission check",
|
|
754
|
+
description:
|
|
755
|
+
"Dry-run a permission check for a tool invocation without executing it.",
|
|
756
|
+
tags: ["tools"],
|
|
757
|
+
requestBody: z.object({
|
|
758
|
+
toolName: z.string(),
|
|
759
|
+
input: z.object({}).passthrough(),
|
|
760
|
+
workingDir: z.string(),
|
|
761
|
+
forcePromptSideEffects: z.boolean(),
|
|
762
|
+
isInteractive: z.boolean(),
|
|
763
|
+
}),
|
|
714
764
|
handler: async ({ req }) => {
|
|
715
765
|
const body = (await req.json()) as {
|
|
716
766
|
toolName?: string;
|
|
@@ -728,6 +778,10 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
728
778
|
endpoint: "diagnostics/env-vars",
|
|
729
779
|
method: "GET",
|
|
730
780
|
policyKey: "diagnostics/env-vars",
|
|
781
|
+
summary: "List safe environment variables",
|
|
782
|
+
description:
|
|
783
|
+
"Return environment variable names and values that are safe to expose (no secrets).",
|
|
784
|
+
tags: ["diagnostics"],
|
|
731
785
|
handler: () => handleEnvVars(),
|
|
732
786
|
},
|
|
733
787
|
|
|
@@ -736,6 +790,13 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
736
790
|
endpoint: "config/platform",
|
|
737
791
|
method: "GET",
|
|
738
792
|
policyKey: "config/platform:GET",
|
|
793
|
+
summary: "Get platform config",
|
|
794
|
+
description: "Return the platform base URL configuration.",
|
|
795
|
+
tags: ["config"],
|
|
796
|
+
responseBody: z.object({
|
|
797
|
+
baseUrl: z.string(),
|
|
798
|
+
success: z.boolean(),
|
|
799
|
+
}),
|
|
739
800
|
handler: () => {
|
|
740
801
|
const raw = loadRawConfig();
|
|
741
802
|
const platform = (raw?.platform ?? {}) as Record<string, unknown>;
|
|
@@ -748,6 +809,12 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
748
809
|
endpoint: "config/platform",
|
|
749
810
|
method: "PUT",
|
|
750
811
|
policyKey: "config/platform",
|
|
812
|
+
summary: "Update platform config",
|
|
813
|
+
description: "Set the platform base URL.",
|
|
814
|
+
tags: ["config"],
|
|
815
|
+
requestBody: z.object({
|
|
816
|
+
baseUrl: z.string(),
|
|
817
|
+
}),
|
|
751
818
|
handler: async ({ req }) => {
|
|
752
819
|
try {
|
|
753
820
|
const body = (await req.json()) as { baseUrl?: string };
|
|
@@ -773,12 +840,28 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
773
840
|
endpoint: "integrations/ingress/config",
|
|
774
841
|
method: "GET",
|
|
775
842
|
policyKey: "integrations/ingress/config:GET",
|
|
843
|
+
summary: "Get ingress config",
|
|
844
|
+
description: "Return the current ingress tunnel configuration.",
|
|
845
|
+
tags: ["config"],
|
|
776
846
|
handler: () => Response.json(getIngressConfigResult()),
|
|
777
847
|
},
|
|
778
848
|
{
|
|
779
849
|
endpoint: "integrations/ingress/config",
|
|
780
850
|
method: "PUT",
|
|
781
851
|
policyKey: "integrations/ingress/config",
|
|
852
|
+
summary: "Update ingress config",
|
|
853
|
+
description: "Set the ingress public base URL and enabled state.",
|
|
854
|
+
tags: ["config"],
|
|
855
|
+
requestBody: z.object({
|
|
856
|
+
publicBaseUrl: z.string(),
|
|
857
|
+
enabled: z.boolean(),
|
|
858
|
+
}),
|
|
859
|
+
responseBody: z.object({
|
|
860
|
+
enabled: z.boolean(),
|
|
861
|
+
publicBaseUrl: z.string(),
|
|
862
|
+
localGatewayTarget: z.string(),
|
|
863
|
+
success: z.boolean(),
|
|
864
|
+
}),
|
|
782
865
|
handler: async ({ req }) => {
|
|
783
866
|
try {
|
|
784
867
|
const body = (await req.json()) as {
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* using the standalone functions extracted in `../../daemon/handlers/skills.ts`.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
8
10
|
import type {
|
|
9
11
|
CreateSkillParams,
|
|
10
12
|
SkillOperationContext,
|
|
@@ -21,6 +23,7 @@ import {
|
|
|
21
23
|
inspectSkill,
|
|
22
24
|
installSkill,
|
|
23
25
|
listSkills,
|
|
26
|
+
listSkillsWithCatalog,
|
|
24
27
|
searchSkills,
|
|
25
28
|
uninstallSkill,
|
|
26
29
|
updateSkill,
|
|
@@ -40,22 +43,69 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
40
43
|
const ctx = () => deps.getSkillContext();
|
|
41
44
|
|
|
42
45
|
return [
|
|
43
|
-
// GET /v1/skills — list all skills
|
|
44
46
|
{
|
|
45
47
|
endpoint: "skills",
|
|
46
48
|
method: "GET",
|
|
47
49
|
policyKey: "skills",
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
summary: "List all skills",
|
|
51
|
+
description:
|
|
52
|
+
"Return all installed skills. Pass ?include=catalog to also include available catalog skills.",
|
|
53
|
+
tags: ["skills"],
|
|
54
|
+
queryParams: [
|
|
55
|
+
{
|
|
56
|
+
name: "include",
|
|
57
|
+
schema: { type: "string", enum: ["catalog"] },
|
|
58
|
+
description:
|
|
59
|
+
"Optional inclusion flag. Use 'catalog' to merge available Vellum catalog skills into the response.",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
responseBody: z.object({
|
|
63
|
+
skills: z
|
|
64
|
+
.array(
|
|
65
|
+
z.object({
|
|
66
|
+
id: z.string(),
|
|
67
|
+
name: z.string(),
|
|
68
|
+
description: z.string(),
|
|
69
|
+
emoji: z.string().optional(),
|
|
70
|
+
homepage: z.string().optional(),
|
|
71
|
+
source: z.enum([
|
|
72
|
+
"bundled",
|
|
73
|
+
"managed",
|
|
74
|
+
"workspace",
|
|
75
|
+
"clawhub",
|
|
76
|
+
"extra",
|
|
77
|
+
"catalog",
|
|
78
|
+
]),
|
|
79
|
+
state: z.enum(["enabled", "disabled"]),
|
|
80
|
+
installStatus: z.enum(["bundled", "installed", "available"]),
|
|
81
|
+
updateAvailable: z.boolean(),
|
|
82
|
+
provenance: z.object({
|
|
83
|
+
kind: z.enum(["first-party", "third-party", "local"]),
|
|
84
|
+
provider: z.string().optional(),
|
|
85
|
+
originId: z.string().optional(),
|
|
86
|
+
sourceUrl: z.string().optional(),
|
|
87
|
+
}),
|
|
88
|
+
}),
|
|
89
|
+
)
|
|
90
|
+
.describe("Skill objects"),
|
|
91
|
+
}),
|
|
92
|
+
handler: async ({ url }) => {
|
|
93
|
+
const include = url.searchParams.get("include");
|
|
94
|
+
const skills =
|
|
95
|
+
include === "catalog"
|
|
96
|
+
? await listSkillsWithCatalog(ctx())
|
|
97
|
+
: listSkills(ctx());
|
|
50
98
|
return Response.json({ skills });
|
|
51
99
|
},
|
|
52
100
|
},
|
|
53
101
|
|
|
54
|
-
// GET /v1/skills/:id/files — skill metadata + directory contents
|
|
55
102
|
{
|
|
56
103
|
endpoint: "skills/:id/files",
|
|
57
104
|
method: "GET",
|
|
58
105
|
policyKey: "skills",
|
|
106
|
+
summary: "Get skill files",
|
|
107
|
+
description: "Return skill metadata and directory contents.",
|
|
108
|
+
tags: ["skills"],
|
|
59
109
|
handler: ({ params }) => {
|
|
60
110
|
const result = getSkillFiles(params.id, ctx());
|
|
61
111
|
if ("error" in result) {
|
|
@@ -68,11 +118,16 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
68
118
|
},
|
|
69
119
|
},
|
|
70
120
|
|
|
71
|
-
// POST /v1/skills/:id/enable — enable skill
|
|
72
121
|
{
|
|
73
122
|
endpoint: "skills/:id/enable",
|
|
74
123
|
method: "POST",
|
|
75
124
|
policyKey: "skills",
|
|
125
|
+
summary: "Enable skill",
|
|
126
|
+
description: "Enable an installed skill.",
|
|
127
|
+
tags: ["skills"],
|
|
128
|
+
responseBody: z.object({
|
|
129
|
+
ok: z.boolean(),
|
|
130
|
+
}),
|
|
76
131
|
handler: ({ params }) => {
|
|
77
132
|
const result = enableSkill(params.id, ctx());
|
|
78
133
|
if (!result.success) {
|
|
@@ -82,11 +137,16 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
82
137
|
},
|
|
83
138
|
},
|
|
84
139
|
|
|
85
|
-
// POST /v1/skills/:id/disable — disable skill
|
|
86
140
|
{
|
|
87
141
|
endpoint: "skills/:id/disable",
|
|
88
142
|
method: "POST",
|
|
89
143
|
policyKey: "skills",
|
|
144
|
+
summary: "Disable skill",
|
|
145
|
+
description: "Disable an installed skill.",
|
|
146
|
+
tags: ["skills"],
|
|
147
|
+
responseBody: z.object({
|
|
148
|
+
ok: z.boolean(),
|
|
149
|
+
}),
|
|
90
150
|
handler: ({ params }) => {
|
|
91
151
|
const result = disableSkill(params.id, ctx());
|
|
92
152
|
if (!result.success) {
|
|
@@ -96,11 +156,21 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
96
156
|
},
|
|
97
157
|
},
|
|
98
158
|
|
|
99
|
-
// PATCH /v1/skills/:id/config — configure skill
|
|
100
159
|
{
|
|
101
160
|
endpoint: "skills/:id/config",
|
|
102
161
|
method: "PATCH",
|
|
103
162
|
policyKey: "skills",
|
|
163
|
+
summary: "Configure skill",
|
|
164
|
+
description: "Update skill configuration (env, apiKey, config).",
|
|
165
|
+
tags: ["skills"],
|
|
166
|
+
requestBody: z.object({
|
|
167
|
+
env: z.object({}).passthrough().describe("Environment variables"),
|
|
168
|
+
apiKey: z.string(),
|
|
169
|
+
config: z.object({}).passthrough().describe("Arbitrary config"),
|
|
170
|
+
}),
|
|
171
|
+
responseBody: z.object({
|
|
172
|
+
ok: z.boolean(),
|
|
173
|
+
}),
|
|
104
174
|
handler: async ({ req, params }) => {
|
|
105
175
|
const body = (await req.json()) as {
|
|
106
176
|
env?: Record<string, string>;
|
|
@@ -119,11 +189,22 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
119
189
|
},
|
|
120
190
|
},
|
|
121
191
|
|
|
122
|
-
// POST /v1/skills/install — install skill
|
|
123
192
|
{
|
|
124
193
|
endpoint: "skills/install",
|
|
125
194
|
method: "POST",
|
|
126
195
|
policyKey: "skills",
|
|
196
|
+
summary: "Install skill",
|
|
197
|
+
description: "Install a skill by slug, URL, or spec.",
|
|
198
|
+
tags: ["skills"],
|
|
199
|
+
requestBody: z.object({
|
|
200
|
+
slug: z.string().describe("Skill slug"),
|
|
201
|
+
url: z.string().describe("Skill URL"),
|
|
202
|
+
spec: z.string().describe("Skill spec"),
|
|
203
|
+
version: z.string(),
|
|
204
|
+
}),
|
|
205
|
+
responseBody: z.object({
|
|
206
|
+
ok: z.boolean(),
|
|
207
|
+
}),
|
|
127
208
|
handler: async ({ req }) => {
|
|
128
209
|
const body = (await req.json()) as {
|
|
129
210
|
slug?: string;
|
|
@@ -150,11 +231,16 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
150
231
|
},
|
|
151
232
|
},
|
|
152
233
|
|
|
153
|
-
// POST /v1/skills/check-updates — check for updates
|
|
154
234
|
{
|
|
155
235
|
endpoint: "skills/check-updates",
|
|
156
236
|
method: "POST",
|
|
157
237
|
policyKey: "skills",
|
|
238
|
+
summary: "Check skill updates",
|
|
239
|
+
description: "Check for available updates to installed skills.",
|
|
240
|
+
tags: ["skills"],
|
|
241
|
+
responseBody: z.object({
|
|
242
|
+
data: z.object({}).passthrough().describe("Update availability info"),
|
|
243
|
+
}),
|
|
158
244
|
handler: async () => {
|
|
159
245
|
const result = await checkSkillUpdates(ctx());
|
|
160
246
|
if (!result.success) {
|
|
@@ -164,11 +250,23 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
164
250
|
},
|
|
165
251
|
},
|
|
166
252
|
|
|
167
|
-
// GET /v1/skills/search — search catalog
|
|
168
253
|
{
|
|
169
254
|
endpoint: "skills/search",
|
|
170
255
|
method: "GET",
|
|
171
256
|
policyKey: "skills",
|
|
257
|
+
summary: "Search skill catalog",
|
|
258
|
+
description: "Search the skill catalog by query string.",
|
|
259
|
+
tags: ["skills"],
|
|
260
|
+
queryParams: [
|
|
261
|
+
{
|
|
262
|
+
name: "q",
|
|
263
|
+
schema: { type: "string" },
|
|
264
|
+
description: "Search query (required)",
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
responseBody: z.object({
|
|
268
|
+
data: z.object({}).passthrough().describe("Search results"),
|
|
269
|
+
}),
|
|
172
270
|
handler: async ({ url }) => {
|
|
173
271
|
const query = url.searchParams.get("q") ?? "";
|
|
174
272
|
if (!query) {
|
|
@@ -182,11 +280,16 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
182
280
|
},
|
|
183
281
|
},
|
|
184
282
|
|
|
185
|
-
// POST /v1/skills/draft — draft new skill
|
|
186
283
|
{
|
|
187
284
|
endpoint: "skills/draft",
|
|
188
285
|
method: "POST",
|
|
189
286
|
policyKey: "skills",
|
|
287
|
+
summary: "Draft a skill",
|
|
288
|
+
description: "Generate a skill draft from source text.",
|
|
289
|
+
tags: ["skills"],
|
|
290
|
+
requestBody: z.object({
|
|
291
|
+
sourceText: z.string().describe("Source text for drafting"),
|
|
292
|
+
}),
|
|
190
293
|
handler: async ({ req }) => {
|
|
191
294
|
const body = (await req.json()) as { sourceText?: string };
|
|
192
295
|
if (!body.sourceText || typeof body.sourceText !== "string") {
|
|
@@ -204,11 +307,22 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
204
307
|
},
|
|
205
308
|
},
|
|
206
309
|
|
|
207
|
-
// POST /v1/skills — create skill
|
|
208
310
|
{
|
|
209
311
|
endpoint: "skills",
|
|
210
312
|
method: "POST",
|
|
211
313
|
policyKey: "skills",
|
|
314
|
+
summary: "Create skill",
|
|
315
|
+
description: "Create a new skill.",
|
|
316
|
+
tags: ["skills"],
|
|
317
|
+
requestBody: z.object({
|
|
318
|
+
skillId: z.string(),
|
|
319
|
+
name: z.string(),
|
|
320
|
+
description: z.string(),
|
|
321
|
+
bodyMarkdown: z.string(),
|
|
322
|
+
}),
|
|
323
|
+
responseBody: z.object({
|
|
324
|
+
ok: z.boolean(),
|
|
325
|
+
}),
|
|
212
326
|
handler: async ({ req }) => {
|
|
213
327
|
const body = (await req.json()) as CreateSkillParams;
|
|
214
328
|
if (
|
|
@@ -231,11 +345,16 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
231
345
|
},
|
|
232
346
|
},
|
|
233
347
|
|
|
234
|
-
// POST /v1/skills/:id/update — update skill
|
|
235
348
|
{
|
|
236
349
|
endpoint: "skills/:id/update",
|
|
237
350
|
method: "POST",
|
|
238
351
|
policyKey: "skills",
|
|
352
|
+
summary: "Update skill",
|
|
353
|
+
description: "Update an installed skill to the latest version.",
|
|
354
|
+
tags: ["skills"],
|
|
355
|
+
responseBody: z.object({
|
|
356
|
+
ok: z.boolean(),
|
|
357
|
+
}),
|
|
239
358
|
handler: async ({ params }) => {
|
|
240
359
|
const result = await updateSkill(params.id, ctx());
|
|
241
360
|
if (!result.success) {
|
|
@@ -245,11 +364,13 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
245
364
|
},
|
|
246
365
|
},
|
|
247
366
|
|
|
248
|
-
// GET /v1/skills/:id/inspect — inspect skill details
|
|
249
367
|
{
|
|
250
368
|
endpoint: "skills/:id/inspect",
|
|
251
369
|
method: "GET",
|
|
252
370
|
policyKey: "skills",
|
|
371
|
+
summary: "Inspect skill",
|
|
372
|
+
description: "Return detailed skill information.",
|
|
373
|
+
tags: ["skills"],
|
|
253
374
|
handler: async ({ params }) => {
|
|
254
375
|
const result = await inspectSkill(params.id, ctx());
|
|
255
376
|
if (result.error && !result.data) {
|
|
@@ -269,13 +390,13 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
269
390
|
},
|
|
270
391
|
},
|
|
271
392
|
|
|
272
|
-
// GET /v1/skills/:id — single skill metadata
|
|
273
|
-
// Registered after all literal-segment GET routes (search, inspect, files)
|
|
274
|
-
// to avoid shadowing them with the parametric :id match.
|
|
275
393
|
{
|
|
276
394
|
endpoint: "skills/:id",
|
|
277
395
|
method: "GET",
|
|
278
396
|
policyKey: "skills",
|
|
397
|
+
summary: "Get skill",
|
|
398
|
+
description: "Return a single skill by ID.",
|
|
399
|
+
tags: ["skills"],
|
|
279
400
|
handler: ({ params }) => {
|
|
280
401
|
const result = getSkill(params.id, ctx());
|
|
281
402
|
if ("error" in result) {
|
|
@@ -288,11 +409,13 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
288
409
|
},
|
|
289
410
|
},
|
|
290
411
|
|
|
291
|
-
// DELETE /v1/skills/:id — uninstall skill
|
|
292
412
|
{
|
|
293
413
|
endpoint: "skills/:id",
|
|
294
414
|
method: "DELETE",
|
|
295
415
|
policyKey: "skills",
|
|
416
|
+
summary: "Uninstall skill",
|
|
417
|
+
description: "Remove an installed skill.",
|
|
418
|
+
tags: ["skills"],
|
|
296
419
|
handler: async ({ params }) => {
|
|
297
420
|
const result = await uninstallSkill(params.id, ctx());
|
|
298
421
|
if (!result.success) {
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* sharing business logic with the handlers in
|
|
6
6
|
* `daemon/handlers/subagents.ts`.
|
|
7
7
|
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
8
10
|
import { getMessages } from "../../memory/conversation-crud.js";
|
|
9
11
|
import { getSubagentManager } from "../../subagent/index.js";
|
|
10
12
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -121,11 +123,25 @@ export function getSubagentDetail(
|
|
|
121
123
|
|
|
122
124
|
export function subagentRouteDefinitions(): RouteDefinition[] {
|
|
123
125
|
return [
|
|
124
|
-
// GET /v1/subagents/:id — get subagent detail
|
|
125
126
|
{
|
|
126
127
|
endpoint: "subagents/:id",
|
|
127
128
|
method: "GET",
|
|
128
129
|
policyKey: "subagents",
|
|
130
|
+
summary: "Get subagent detail",
|
|
131
|
+
description: "Return subagent objective and event history.",
|
|
132
|
+
tags: ["subagents"],
|
|
133
|
+
queryParams: [
|
|
134
|
+
{
|
|
135
|
+
name: "conversationId",
|
|
136
|
+
schema: { type: "string" },
|
|
137
|
+
description: "Parent conversation ID (required)",
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
responseBody: z.object({
|
|
141
|
+
subagentId: z.string(),
|
|
142
|
+
objective: z.string(),
|
|
143
|
+
events: z.array(z.unknown()).describe("Subagent event objects"),
|
|
144
|
+
}),
|
|
129
145
|
handler: ({ url, params }) => {
|
|
130
146
|
const conversationId = url.searchParams.get("conversationId");
|
|
131
147
|
if (!conversationId) {
|
|
@@ -152,11 +168,20 @@ export function subagentRouteDefinitions(): RouteDefinition[] {
|
|
|
152
168
|
},
|
|
153
169
|
},
|
|
154
170
|
|
|
155
|
-
// POST /v1/subagents/:id/abort — abort subagent
|
|
156
171
|
{
|
|
157
172
|
endpoint: "subagents/:id/abort",
|
|
158
173
|
method: "POST",
|
|
159
174
|
policyKey: "subagents/abort",
|
|
175
|
+
summary: "Abort subagent",
|
|
176
|
+
description: "Abort a running subagent.",
|
|
177
|
+
tags: ["subagents"],
|
|
178
|
+
requestBody: z.object({
|
|
179
|
+
conversationId: z.string(),
|
|
180
|
+
}),
|
|
181
|
+
responseBody: z.object({
|
|
182
|
+
subagentId: z.string(),
|
|
183
|
+
aborted: z.boolean(),
|
|
184
|
+
}),
|
|
160
185
|
handler: async ({ req, params }) => {
|
|
161
186
|
const body = (await req.json()) as { conversationId?: string };
|
|
162
187
|
const conversationId = body.conversationId;
|
|
@@ -187,11 +212,21 @@ export function subagentRouteDefinitions(): RouteDefinition[] {
|
|
|
187
212
|
},
|
|
188
213
|
},
|
|
189
214
|
|
|
190
|
-
// POST /v1/subagents/:id/message — send message to subagent
|
|
191
215
|
{
|
|
192
216
|
endpoint: "subagents/:id/message",
|
|
193
217
|
method: "POST",
|
|
194
218
|
policyKey: "subagents/message",
|
|
219
|
+
summary: "Send message to subagent",
|
|
220
|
+
description: "Send a text message to a running subagent.",
|
|
221
|
+
tags: ["subagents"],
|
|
222
|
+
requestBody: z.object({
|
|
223
|
+
conversationId: z.string(),
|
|
224
|
+
content: z.string(),
|
|
225
|
+
}),
|
|
226
|
+
responseBody: z.object({
|
|
227
|
+
subagentId: z.string(),
|
|
228
|
+
sent: z.boolean(),
|
|
229
|
+
}),
|
|
195
230
|
handler: async ({ req, params }) => {
|
|
196
231
|
const body = (await req.json()) as {
|
|
197
232
|
conversationId?: string;
|