@vellumai/assistant 0.5.16 → 0.6.1
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 +4 -0
- package/ARCHITECTURE.md +69 -16
- package/Dockerfile +2 -5
- package/bun.lock +6 -2
- package/docker-entrypoint.sh +32 -1
- package/docs/architecture/integrations.md +1 -1
- package/docs/architecture/memory.md +21 -24
- package/knip.json +2 -1
- package/openapi.yaml +1198 -83
- package/package.json +5 -1
- package/src/__tests__/actor-token-service.test.ts +68 -0
- package/src/__tests__/agent-loop.test.ts +0 -32
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/anthropic-provider.test.ts +217 -98
- package/src/__tests__/app-compiler.test.ts +120 -0
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +47 -1
- package/src/__tests__/app-source-watcher.test.ts +159 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/call-conversation-messages.test.ts +2 -6
- package/src/__tests__/call-domain.test.ts +2 -6
- package/src/__tests__/call-pointer-messages.test.ts +2 -14
- package/src/__tests__/call-recovery.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +2 -6
- package/src/__tests__/call-store.test.ts +2 -6
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
- package/src/__tests__/canonical-guardian-store.test.ts +2 -6
- package/src/__tests__/channel-delivery-store.test.ts +2 -6
- package/src/__tests__/channel-retry-sweep.test.ts +2 -6
- package/src/__tests__/checker.test.ts +63 -9
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
- package/src/__tests__/config-schema.test.ts +6 -1
- package/src/__tests__/config-set-platform-guard.test.ts +302 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
- package/src/__tests__/contacts-tools.test.ts +31 -0
- package/src/__tests__/context-overflow-reducer.test.ts +86 -0
- package/src/__tests__/context-token-estimator.test.ts +175 -10
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +13 -6
- package/src/__tests__/conversation-agent-loop.test.ts +13 -51
- package/src/__tests__/conversation-attachments.test.ts +2 -6
- package/src/__tests__/conversation-attention-store.test.ts +2 -6
- package/src/__tests__/conversation-clear-safety.test.ts +2 -6
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
- package/src/__tests__/conversation-disk-view.test.ts +2 -6
- package/src/__tests__/conversation-error.test.ts +33 -2
- package/src/__tests__/conversation-fork-crud.test.ts +2 -6
- package/src/__tests__/conversation-history-web-search.test.ts +6 -1
- package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
- package/src/__tests__/conversation-media-retry.test.ts +91 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
- package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
- package/src/__tests__/conversation-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
- package/src/__tests__/conversation-usage.test.ts +2 -6
- package/src/__tests__/conversation-wipe.test.ts +13 -414
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
- package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
- package/src/__tests__/credential-security-e2e.test.ts +2 -0
- package/src/__tests__/date-context.test.ts +76 -210
- package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
- package/src/__tests__/file-list-tool.test.ts +219 -0
- package/src/__tests__/first-greeting.test.ts +1 -1
- package/src/__tests__/followup-tools.test.ts +2 -6
- package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
- package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
- package/src/__tests__/guardian-action-store.test.ts +2 -6
- package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
- package/src/__tests__/guardian-dispatch.test.ts +2 -6
- package/src/__tests__/guardian-grant-minting.test.ts +2 -14
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
- package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
- package/src/__tests__/guardian-routing-state.test.ts +2 -6
- package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
- package/src/__tests__/heartbeat-service.test.ts +180 -3
- package/src/__tests__/identity-routes.test.ts +328 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
- package/src/__tests__/injection-block.test.ts +178 -0
- package/src/__tests__/install-meta.test.ts +506 -0
- package/src/__tests__/install-skill-routing.test.ts +293 -0
- package/src/__tests__/invite-redemption-service.test.ts +2 -6
- package/src/__tests__/invite-routes-http.test.ts +2 -6
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +17 -28
- package/src/__tests__/list-messages-attachments.test.ts +2 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
- package/src/__tests__/llm-context-normalization.test.ts +18 -18
- package/src/__tests__/llm-context-route-provider.test.ts +103 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +164 -6
- package/src/__tests__/llm-usage-store.test.ts +2 -6
- package/src/__tests__/log-export-workspace.test.ts +74 -111
- package/src/__tests__/managed-store.test.ts +38 -11
- package/src/__tests__/mcp-abort-signal.test.ts +5 -0
- package/src/__tests__/mcp-client-auth.test.ts +5 -0
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
- package/src/__tests__/memory-recall-log-store.test.ts +134 -6
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
- package/src/__tests__/migration-export-streaming.test.ts +304 -0
- package/src/__tests__/migration-import-commit-http.test.ts +11 -10
- package/src/__tests__/mock-fetch.ts +87 -0
- package/src/__tests__/non-member-access-request.test.ts +2 -6
- package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
- package/src/__tests__/notification-guardian-path.test.ts +2 -6
- package/src/__tests__/oauth-cli.test.ts +364 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
- package/src/__tests__/onboarding-template-contract.test.ts +62 -14
- package/src/__tests__/outlook-attachments.test.ts +301 -0
- package/src/__tests__/outlook-automation-tools.test.ts +425 -0
- package/src/__tests__/outlook-categories.test.ts +212 -0
- package/src/__tests__/outlook-client-automation.test.ts +246 -0
- package/src/__tests__/outlook-compose-tools.test.ts +325 -0
- package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
- package/src/__tests__/outlook-email-watcher.test.ts +322 -0
- package/src/__tests__/outlook-follow-up.test.ts +196 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
- package/src/__tests__/outlook-trash.test.ts +77 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
- package/src/__tests__/parser.test.ts +32 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
- package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
- package/src/__tests__/permission-mode-sse.test.ts +418 -0
- package/src/__tests__/permission-mode-store.test.ts +277 -0
- package/src/__tests__/permission-mode.test.ts +101 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
- package/src/__tests__/platform-callback-registration.test.ts +4 -4
- package/src/__tests__/playbook-execution.test.ts +76 -80
- package/src/__tests__/playbook-tools.test.ts +5 -7
- package/src/__tests__/profiler-routes.test.ts +502 -0
- package/src/__tests__/profiler-run-store.test.ts +441 -0
- package/src/__tests__/provider-error-scenarios.test.ts +21 -0
- package/src/__tests__/proxy-approval-callback.test.ts +4 -75
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
- package/src/__tests__/registry.test.ts +3 -3
- package/src/__tests__/require-fresh-approval.test.ts +64 -2
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
- package/src/__tests__/runtime-events-sse.test.ts +2 -6
- package/src/__tests__/sandbox-host-parity.test.ts +5 -4
- package/src/__tests__/schedule-store.test.ts +2 -6
- package/src/__tests__/schedule-tools.test.ts +2 -6
- package/src/__tests__/scheduler-recurrence.test.ts +1 -5
- package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
- package/src/__tests__/scoped-approval-grants.test.ts +2 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
- package/src/__tests__/search-skills-unified.test.ts +422 -0
- package/src/__tests__/secret-onetime-send.test.ts +2 -0
- package/src/__tests__/send-endpoint-busy.test.ts +44 -9
- package/src/__tests__/sequence-store.test.ts +2 -6
- package/src/__tests__/server-history-render.test.ts +2 -6
- package/src/__tests__/set-permission-mode.test.ts +274 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +23 -11
- package/src/__tests__/skill-memory.test.ts +2 -741
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +1 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -6
- package/src/__tests__/strip-memory-injections.test.ts +187 -0
- package/src/__tests__/subagent-detail.test.ts +84 -0
- package/src/__tests__/subagent-disposal.test.ts +308 -0
- package/src/__tests__/subagent-manager-notify.test.ts +19 -10
- package/src/__tests__/subagent-notify-parent.test.ts +390 -0
- package/src/__tests__/subagent-role-registry.test.ts +108 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
- package/src/__tests__/subagent-tools.test.ts +464 -4
- package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
- package/src/__tests__/task-compiler.test.ts +2 -6
- package/src/__tests__/task-management-tools.test.ts +2 -6
- package/src/__tests__/task-memory-cleanup.test.ts +185 -241
- package/src/__tests__/task-runner.test.ts +2 -6
- package/src/__tests__/task-scheduler.test.ts +2 -6
- package/src/__tests__/terminal-tools.test.ts +17 -27
- package/src/__tests__/test-preload.ts +7 -0
- package/src/__tests__/tool-approval-handler.test.ts +2 -6
- package/src/__tests__/tool-executor.test.ts +4 -26
- package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +277 -0
- package/src/__tests__/top-level-renderer.test.ts +10 -13
- package/src/__tests__/trust-store.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +118 -8
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
- package/src/__tests__/trusted-contact-verification.test.ts +2 -6
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
- package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
- package/src/__tests__/usage-routes.test.ts +2 -6
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +2 -6
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
- package/src/__tests__/voice-session-bridge.test.ts +2 -6
- package/src/__tests__/volume-security-guard.test.ts +2 -0
- package/src/__tests__/workspace-lifecycle.test.ts +29 -1
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
- package/src/__tests__/workspace-policy.test.ts +1 -1
- package/src/agent/attachments.ts +7 -2
- package/src/agent/image-optimize.ts +165 -0
- package/src/agent/loop.ts +7 -15
- package/src/approvals/guardian-request-resolvers.ts +24 -0
- package/src/avatar/traits-png-sync.ts +3 -3
- package/src/bundler/app-compiler.ts +179 -2
- package/src/bundler/package-resolver.ts +3 -5
- package/src/cli/__tests__/notifications.test.ts +1 -2
- package/src/cli/__tests__/run-assistant-command.ts +29 -0
- package/src/cli/commands/__tests__/email-download.test.ts +245 -0
- package/src/cli/commands/__tests__/email-list.test.ts +192 -0
- package/src/cli/commands/__tests__/email-register.test.ts +186 -0
- package/src/cli/commands/__tests__/email-send.test.ts +291 -0
- package/src/cli/commands/__tests__/email-status.test.ts +181 -0
- package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
- package/src/cli/commands/__tests__/routes.test.ts +562 -0
- package/src/cli/commands/avatar.ts +3 -3
- package/src/cli/commands/config.ts +26 -13
- package/src/cli/commands/conversations.ts +1 -8
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/email.ts +584 -835
- package/src/cli/commands/memory.ts +37 -84
- package/src/cli/commands/notifications.ts +7 -2
- package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
- package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +25 -11
- package/src/cli/commands/oauth/mode.ts +7 -0
- package/src/cli/commands/oauth/shared.ts +39 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
- package/src/cli/commands/platform/index.ts +16 -16
- package/src/cli/commands/routes.ts +396 -0
- package/src/cli/commands/skills.ts +218 -36
- package/src/cli/commands/trust.ts +2 -2
- package/src/cli/lib/daemon-credential-client.ts +2 -3
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +1 -120
- package/src/config/bundled-skills/acp/TOOLS.json +1 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +4 -1
- package/src/config/bundled-skills/contacts/SKILL.md +0 -1
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
- package/src/config/bundled-skills/gmail/SKILL.md +4 -12
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
- package/src/config/bundled-skills/messaging/SKILL.md +17 -18
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
- package/src/config/bundled-skills/outlook/SKILL.md +189 -0
- package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
- package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
- package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
- package/src/config/bundled-skills/schedule/SKILL.md +22 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
- package/src/config/bundled-skills/slack/SKILL.md +3 -7
- package/src/config/bundled-skills/subagent/SKILL.md +43 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
- package/src/config/bundled-tool-registry.ts +56 -4
- package/src/config/env-registry.ts +78 -8
- package/src/config/feature-flag-registry.json +38 -125
- package/src/config/schema.ts +8 -0
- package/src/config/schemas/filing.ts +51 -0
- package/src/config/schemas/heartbeat.ts +15 -12
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/security.ts +14 -0
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/config/skills.ts +18 -7
- package/src/context/token-estimator.ts +25 -18
- package/src/context/window-manager.ts +6 -2
- package/src/credential-execution/process-manager.ts +3 -1
- package/src/daemon/app-source-watcher.ts +93 -0
- package/src/daemon/config-watcher.ts +79 -1
- package/src/daemon/context-overflow-reducer.ts +46 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +143 -82
- package/src/daemon/conversation-agent-loop.ts +236 -108
- package/src/daemon/conversation-error.ts +31 -8
- package/src/daemon/conversation-history.ts +4 -19
- package/src/daemon/conversation-lifecycle.ts +36 -9
- package/src/daemon/conversation-media-retry.ts +85 -7
- package/src/daemon/conversation-notifiers.ts +4 -1
- package/src/daemon/conversation-process.ts +13 -7
- package/src/daemon/conversation-runtime-assembly.ts +305 -306
- package/src/daemon/conversation-tool-setup.ts +44 -14
- package/src/daemon/conversation-workspace.ts +1 -2
- package/src/daemon/conversation.ts +59 -2
- package/src/daemon/daemon-control.ts +8 -2
- package/src/daemon/date-context.ts +26 -53
- package/src/daemon/first-greeting.ts +1 -1
- package/src/daemon/handlers/conversations.ts +4 -7
- package/src/daemon/handlers/shared.test.ts +143 -0
- package/src/daemon/handlers/shared.ts +85 -17
- package/src/daemon/handlers/skills.ts +416 -209
- package/src/daemon/lifecycle.ts +212 -131
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +29 -7
- package/src/daemon/message-types/messages.ts +12 -2
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/settings.ts +6 -0
- package/src/daemon/message-types/skills.ts +97 -36
- package/src/daemon/profiler-run-store.ts +557 -0
- package/src/daemon/providers-setup.ts +5 -0
- package/src/daemon/server.ts +100 -11
- package/src/daemon/shutdown-handlers.ts +5 -0
- package/src/daemon/tool-side-effects.ts +50 -8
- package/src/export/transcript-formatter.ts +148 -0
- package/src/filing/filing-service.ts +228 -0
- package/src/heartbeat/heartbeat-service.ts +97 -7
- package/src/hooks/cli.ts +2 -2
- package/src/hooks/runner.ts +15 -38
- package/src/inbound/platform-callback-registration.ts +14 -14
- package/src/mcp/client.ts +6 -0
- package/src/mcp/mcp-oauth-provider.ts +149 -27
- package/src/memory/admin.ts +42 -75
- package/src/memory/app-store.ts +69 -0
- package/src/memory/conversation-bootstrap.ts +3 -1
- package/src/memory/conversation-crud.ts +211 -288
- package/src/memory/conversation-group-migration.ts +157 -0
- package/src/memory/conversation-queries.ts +61 -13
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/db-init.ts +194 -361
- package/src/memory/embed.ts +73 -0
- package/src/memory/embedding-backend.ts +8 -14
- package/src/memory/embedding-runtime-manager.ts +12 -114
- package/src/memory/fingerprint.ts +2 -2
- package/src/memory/graph/bootstrap.ts +521 -0
- package/src/memory/graph/capability-seed.ts +449 -0
- package/src/memory/graph/consolidation.ts +725 -0
- package/src/memory/graph/conversation-graph-memory.ts +659 -0
- package/src/memory/graph/decay.test.ts +208 -0
- package/src/memory/graph/decay.ts +195 -0
- package/src/memory/graph/extraction-job.ts +74 -0
- package/src/memory/graph/extraction.test.ts +936 -0
- package/src/memory/graph/extraction.ts +1297 -0
- package/src/memory/graph/graph-memory-state-store.ts +37 -0
- package/src/memory/graph/graph-search.ts +280 -0
- package/src/memory/graph/image-ref-utils.ts +29 -0
- package/src/memory/graph/injection.test.ts +513 -0
- package/src/memory/graph/injection.ts +469 -0
- package/src/memory/graph/inspect.ts +543 -0
- package/src/memory/graph/narrative.ts +267 -0
- package/src/memory/graph/pattern-scan.ts +269 -0
- package/src/memory/graph/retriever.ts +1111 -0
- package/src/memory/graph/scoring.test.ts +548 -0
- package/src/memory/graph/scoring.ts +232 -0
- package/src/memory/graph/serendipity.ts +65 -0
- package/src/memory/graph/store.test.ts +1098 -0
- package/src/memory/graph/store.ts +838 -0
- package/src/memory/graph/tool-handlers.ts +301 -0
- package/src/memory/graph/tools.ts +97 -0
- package/src/memory/graph/triggers.test.ts +487 -0
- package/src/memory/graph/triggers.ts +223 -0
- package/src/memory/graph/types.ts +295 -0
- package/src/memory/group-crud.ts +191 -0
- package/src/memory/indexer.ts +37 -19
- package/src/memory/job-handlers/cleanup.ts +32 -42
- package/src/memory/job-handlers/conversation-starters.ts +91 -53
- package/src/memory/job-handlers/embedding.ts +5 -31
- package/src/memory/job-handlers/index-maintenance.ts +23 -11
- package/src/memory/job-handlers/summarization.ts +32 -17
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +21 -31
- package/src/memory/jobs-worker.ts +180 -129
- package/src/memory/llm-request-log-store.ts +96 -12
- package/src/memory/memory-recall-log-store.ts +49 -5
- package/src/memory/message-content.ts +1 -0
- package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
- package/src/memory/migrations/203-drop-memory-items-tables.ts +55 -0
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
- package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
- package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
- package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
- package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
- package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
- package/src/memory/migrations/index.ts +12 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/schema/conversations.ts +14 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/infrastructure.ts +8 -1
- package/src/memory/schema/memory-core.ts +0 -51
- package/src/memory/schema/memory-graph.ts +154 -0
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/task-memory-cleanup.ts +58 -61
- package/src/messaging/providers/outlook/adapter.ts +8 -1
- package/src/messaging/providers/outlook/client.ts +299 -0
- package/src/messaging/providers/outlook/types.ts +118 -0
- package/src/notifications/adapters/macos.ts +1 -0
- package/src/notifications/copy-composer.ts +95 -0
- package/src/notifications/decision-engine.ts +35 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/seed-providers.ts +2 -1
- package/src/permissions/checker.ts +36 -4
- package/src/permissions/defaults.ts +4 -4
- package/src/permissions/permission-mode-store.ts +180 -0
- package/src/permissions/permission-mode.ts +31 -0
- package/src/permissions/workspace-policy.ts +10 -1
- package/src/playbooks/playbook-compiler.ts +19 -18
- package/src/playbooks/types.ts +4 -3
- package/src/prompts/system-prompt.ts +62 -36
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
- package/src/prompts/templates/BOOTSTRAP.md +70 -165
- package/src/prompts/templates/HEARTBEAT.md +3 -1
- package/src/prompts/templates/SOUL.md +25 -4
- package/src/prompts/templates/UPDATES.md +8 -0
- package/src/providers/anthropic/client.ts +136 -220
- package/src/providers/gemini/client.ts +1 -1
- package/src/providers/openai/client.ts +1 -1
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +19 -3
- package/src/runtime/actor-trust-resolver.ts +5 -1
- package/src/runtime/auth/route-policy.ts +30 -0
- package/src/runtime/guardian-reply-router.ts +5 -1
- package/src/runtime/http-server.ts +55 -5
- package/src/runtime/http-types.ts +12 -1
- package/src/runtime/middleware/auth.ts +20 -0
- package/src/runtime/migrations/vbundle-builder.ts +389 -3
- package/src/runtime/migrations/vbundle-importer.ts +8 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
- package/src/runtime/routes/app-management-routes.ts +1 -11
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
- package/src/runtime/routes/archive-utils.ts +29 -0
- package/src/runtime/routes/attachment-routes.test.ts +106 -0
- package/src/runtime/routes/attachment-routes.ts +106 -16
- package/src/runtime/routes/avatar-routes.ts +2 -9
- package/src/runtime/routes/brain-graph-routes.ts +21 -22
- package/src/runtime/routes/btw-routes.ts +22 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +173 -0
- package/src/runtime/routes/conversation-management-routes.ts +3 -14
- package/src/runtime/routes/conversation-query-routes.ts +49 -3
- package/src/runtime/routes/conversation-routes.ts +264 -44
- package/src/runtime/routes/conversation-starter-routes.ts +2 -2
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/global-search-routes.ts +21 -19
- package/src/runtime/routes/group-routes.ts +207 -0
- package/src/runtime/routes/guardian-action-routes.ts +21 -10
- package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
- package/src/runtime/routes/heartbeat-routes.ts +4 -10
- package/src/runtime/routes/identity-routes.ts +53 -18
- package/src/runtime/routes/inbound-message-handler.ts +19 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
- package/src/runtime/routes/llm-context-normalization.ts +14 -10
- package/src/runtime/routes/log-export-routes.ts +23 -275
- package/src/runtime/routes/memory-item-routes.test.ts +170 -247
- package/src/runtime/routes/memory-item-routes.ts +341 -388
- package/src/runtime/routes/migration-routes.ts +18 -7
- package/src/runtime/routes/profiler-routes.ts +350 -0
- package/src/runtime/routes/schedule-routes.ts +28 -11
- package/src/runtime/routes/settings-routes.ts +95 -8
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/subagents-routes.ts +28 -7
- package/src/runtime/routes/user-route-dispatcher.ts +223 -0
- package/src/runtime/routes/user-routes.ts +41 -0
- package/src/runtime/routes/work-items-routes.test.ts +2 -6
- package/src/runtime/routes/workspace-routes.ts +0 -1
- package/src/schedule/schedule-store.ts +30 -0
- package/src/schedule/scheduler.ts +52 -18
- package/src/security/oauth2.ts +1 -1
- package/src/security/secure-keys.ts +4 -8
- package/src/shared/provider-env-vars.ts +19 -0
- package/src/skills/catalog-cache.ts +5 -0
- package/src/skills/catalog-install.ts +25 -16
- package/src/skills/clawhub.ts +134 -154
- package/src/skills/install-meta.ts +208 -0
- package/src/skills/managed-store.ts +29 -18
- package/src/skills/skill-memory.ts +12 -229
- package/src/skills/skillssh-registry.ts +19 -17
- package/src/subagent/index.ts +13 -3
- package/src/subagent/manager.ts +308 -29
- package/src/subagent/types.ts +68 -0
- package/src/tasks/task-runner.ts +7 -5
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
- package/src/tools/apps/executors.ts +29 -4
- package/src/tools/browser/runtime-check.ts +3 -1
- package/src/tools/filesystem/list.ts +93 -0
- package/src/tools/memory/register.ts +63 -46
- package/src/tools/permission-checker.ts +85 -1
- package/src/tools/registry.ts +4 -0
- package/src/tools/schedule/create.ts +3 -0
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +6 -0
- package/src/tools/shared/filesystem/errors.ts +5 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- package/src/tools/shared/filesystem/types.ts +17 -0
- package/src/tools/shared/shell-output.ts +31 -2
- package/src/tools/subagent/abort.ts +12 -2
- package/src/tools/subagent/message.ts +9 -2
- package/src/tools/subagent/notify-parent.ts +79 -0
- package/src/tools/subagent/read.ts +29 -8
- package/src/tools/subagent/resolve.ts +21 -0
- package/src/tools/subagent/spawn.ts +2 -0
- package/src/tools/subagent/status.ts +11 -1
- package/src/tools/system/avatar-generator.ts +3 -3
- package/src/tools/system/register.ts +23 -0
- package/src/tools/system/set-permission-mode.ts +103 -0
- package/src/tools/terminal/parser.ts +30 -5
- package/src/tools/terminal/safe-env.ts +17 -1
- package/src/tools/tool-manifest.ts +9 -3
- package/src/tools/types.ts +2 -0
- package/src/util/browser.ts +25 -10
- package/src/util/bun-runtime.ts +172 -0
- package/src/util/logger.ts +1 -1
- package/src/util/platform.ts +50 -17
- package/src/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
- package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
- package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
- package/src/workspace/migrations/029-seed-pkb.ts +84 -0
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/top-level-renderer.ts +5 -9
- package/src/__tests__/cli-memory.test.ts +0 -372
- package/src/__tests__/clipboard.test.ts +0 -88
- package/src/__tests__/context-memory-e2e.test.ts +0 -415
- package/src/__tests__/journal-context.test.ts +0 -268
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
- package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
- package/src/__tests__/memory-query-builder.test.ts +0 -59
- package/src/__tests__/memory-recall-quality.test.ts +0 -1046
- package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
- package/src/__tests__/memory-regressions.test.ts +0 -3696
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
- package/src/cli/cli-memory.ts +0 -176
- package/src/daemon/conversation-memory.ts +0 -207
- package/src/memory/conversation-starters-cadence.ts +0 -74
- package/src/memory/items-extractor.ts +0 -860
- package/src/memory/job-handlers/batch-extraction.ts +0 -753
- package/src/memory/job-handlers/extraction.ts +0 -40
- package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
- package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
- package/src/memory/journal-memory.ts +0 -224
- package/src/memory/query-builder.ts +0 -47
- package/src/memory/query-expansion.ts +0 -83
- package/src/memory/retriever.test.ts +0 -1592
- package/src/memory/retriever.ts +0 -1331
- package/src/memory/search/formatting.test.ts +0 -140
- package/src/memory/search/formatting.ts +0 -262
- package/src/memory/search/mmr.ts +0 -139
- package/src/memory/search/ranking.ts +0 -15
- package/src/memory/search/staleness.ts +0 -40
- package/src/memory/search/tier-classifier.ts +0 -18
- package/src/memory/search/types.ts +0 -121
- package/src/prompts/journal-context.ts +0 -154
- package/src/tools/memory/definitions.ts +0 -69
- package/src/tools/memory/handlers.test.ts +0 -562
- package/src/tools/memory/handlers.ts +0 -434
- package/src/util/clipboard.ts +0 -34
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
1
2
|
import {
|
|
2
3
|
existsSync,
|
|
3
4
|
lstatSync,
|
|
@@ -7,6 +8,7 @@ import {
|
|
|
7
8
|
rmSync,
|
|
8
9
|
statSync,
|
|
9
10
|
} from "node:fs";
|
|
11
|
+
import { homedir } from "node:os";
|
|
10
12
|
import { join, relative } from "node:path";
|
|
11
13
|
|
|
12
14
|
import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
|
|
@@ -18,6 +20,11 @@ import {
|
|
|
18
20
|
} from "../../config/loader.js";
|
|
19
21
|
import { resolveSkillStates, skillFlagKey } from "../../config/skill-state.js";
|
|
20
22
|
import { loadSkillCatalog, type SkillSummary } from "../../config/skills.js";
|
|
23
|
+
import {
|
|
24
|
+
deleteSkillCapabilityNode,
|
|
25
|
+
seedSkillGraphNodes,
|
|
26
|
+
seedUninstalledCatalogSkillMemories,
|
|
27
|
+
} from "../../memory/graph/capability-seed.js";
|
|
21
28
|
import {
|
|
22
29
|
createTimeout,
|
|
23
30
|
extractText,
|
|
@@ -26,7 +33,10 @@ import {
|
|
|
26
33
|
} from "../../providers/provider-send-message.js";
|
|
27
34
|
import { isTextMimeType as isTextMime } from "../../runtime/routes/workspace-utils.js";
|
|
28
35
|
import { getCatalog } from "../../skills/catalog-cache.js";
|
|
29
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
installSkillLocally,
|
|
38
|
+
upsertSkillsIndex,
|
|
39
|
+
} from "../../skills/catalog-install.js";
|
|
30
40
|
import { filterByQuery } from "../../skills/catalog-search.js";
|
|
31
41
|
import {
|
|
32
42
|
clawhubCheckUpdates,
|
|
@@ -36,6 +46,10 @@ import {
|
|
|
36
46
|
clawhubSearch,
|
|
37
47
|
clawhubUpdate,
|
|
38
48
|
} from "../../skills/clawhub.js";
|
|
49
|
+
import {
|
|
50
|
+
readInstallMeta,
|
|
51
|
+
type SkillInstallMeta,
|
|
52
|
+
} from "../../skills/install-meta.js";
|
|
39
53
|
import {
|
|
40
54
|
createManagedSkill,
|
|
41
55
|
deleteManagedSkill,
|
|
@@ -43,10 +57,15 @@ import {
|
|
|
43
57
|
validateManagedSkillId,
|
|
44
58
|
} from "../../skills/managed-store.js";
|
|
45
59
|
import {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
60
|
+
installExternalSkill,
|
|
61
|
+
resolveSkillSource,
|
|
62
|
+
searchSkillsRegistry,
|
|
63
|
+
} from "../../skills/skillssh-registry.js";
|
|
49
64
|
import { getWorkspaceSkillsDir } from "../../util/platform.js";
|
|
65
|
+
import type {
|
|
66
|
+
SkillDetailResponse,
|
|
67
|
+
SlimSkillResponse,
|
|
68
|
+
} from "../message-types/skills.js";
|
|
50
69
|
import {
|
|
51
70
|
CONFIG_RELOAD_DEBOUNCE_MS,
|
|
52
71
|
ensureSkillEntry,
|
|
@@ -72,52 +91,6 @@ export interface SkillOperationContext {
|
|
|
72
91
|
broadcast: HandlerContext["broadcast"];
|
|
73
92
|
}
|
|
74
93
|
|
|
75
|
-
// ─── Provenance resolution ──────────────────────────────────────────────────
|
|
76
|
-
|
|
77
|
-
interface SkillProvenance {
|
|
78
|
-
kind: "first-party" | "third-party" | "local";
|
|
79
|
-
provider?: string;
|
|
80
|
-
originId?: string;
|
|
81
|
-
sourceUrl?: string;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const CLAWHUB_BASE_URL = "https://skills.sh";
|
|
85
|
-
|
|
86
|
-
function resolveProvenance(summary: SkillSummary): SkillProvenance {
|
|
87
|
-
// Bundled skills are always first-party (shipped with Vellum)
|
|
88
|
-
if (summary.source === "bundled") {
|
|
89
|
-
return { kind: "first-party", provider: "Vellum" };
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Managed skills are third-party (installed from clawhub). The homepage field
|
|
93
|
-
// confirms provenance.
|
|
94
|
-
if (summary.source === "managed") {
|
|
95
|
-
if (
|
|
96
|
-
summary.homepage?.includes("skills.sh") ||
|
|
97
|
-
summary.homepage?.includes("clawhub")
|
|
98
|
-
) {
|
|
99
|
-
return {
|
|
100
|
-
kind: "third-party",
|
|
101
|
-
provider: "skills.sh",
|
|
102
|
-
originId: summary.id,
|
|
103
|
-
sourceUrl:
|
|
104
|
-
summary.homepage ??
|
|
105
|
-
`${CLAWHUB_BASE_URL}/skills/${encodeURIComponent(summary.id)}`,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
// No positive evidence of clawhub origin -- likely user-authored.
|
|
109
|
-
// Default to "local" to avoid mislabeling.
|
|
110
|
-
return { kind: "local" };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Workspace and extra skills are user-provided
|
|
114
|
-
if (summary.source === "workspace" || summary.source === "extra") {
|
|
115
|
-
return { kind: "local" };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return { kind: "local" };
|
|
119
|
-
}
|
|
120
|
-
|
|
121
94
|
// ─── Frontmatter parsing ─────────────────────────────────────────────────────
|
|
122
95
|
|
|
123
96
|
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -232,52 +205,148 @@ function saveConfigWithSuppression(
|
|
|
232
205
|
ctx.updateConfigFingerprint();
|
|
233
206
|
}
|
|
234
207
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Shared post-install logic for catalog, skillssh, and clawhub install paths
|
|
210
|
+
* in the daemon. Handles catalog reload, auto-enable, broadcast, and memory
|
|
211
|
+
* seeding.
|
|
212
|
+
*
|
|
213
|
+
* SKILLS.md indexing and dependency installation are handled separately:
|
|
214
|
+
* `installSkillLocally` and `installExternalSkill` handle them internally
|
|
215
|
+
* (so both CLI and daemon callers get correct behavior), while the clawhub
|
|
216
|
+
* path handles them inline in `installSkill()` since `clawhubInstall` only
|
|
217
|
+
* runs the clawhub CLI and writes metadata.
|
|
218
|
+
*
|
|
219
|
+
* NOT used for bundled skills — those have a simpler inline path in
|
|
220
|
+
* `installSkill()` that only auto-enables, broadcasts, and seeds memories.
|
|
221
|
+
*/
|
|
222
|
+
export function postInstallSkill(
|
|
223
|
+
skillId: string,
|
|
224
|
+
_skillDir: string,
|
|
225
|
+
ctx: SkillOperationContext,
|
|
226
|
+
): void {
|
|
227
|
+
// Reload skill catalog so the newly installed skill is picked up
|
|
228
|
+
loadSkillCatalog();
|
|
229
|
+
|
|
230
|
+
// Auto-enable the skill in config
|
|
231
|
+
try {
|
|
232
|
+
const raw = loadRawConfig();
|
|
233
|
+
ensureSkillEntry(raw, skillId).enabled = true;
|
|
234
|
+
saveConfigWithSuppression(raw, ctx);
|
|
235
|
+
ctx.broadcast({
|
|
236
|
+
type: "skills_state_changed",
|
|
237
|
+
name: skillId,
|
|
238
|
+
state: "enabled",
|
|
239
|
+
});
|
|
240
|
+
} catch (err) {
|
|
241
|
+
log.warn({ err, skillId }, "Failed to auto-enable installed skill");
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Seed skill memories
|
|
245
|
+
seedSkillGraphNodes();
|
|
246
|
+
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ─── Kind / origin / status derivation ───────────────────────────────────────
|
|
250
|
+
|
|
251
|
+
/** Map the old `source` field to the new `kind` axis. */
|
|
252
|
+
function deriveKind(
|
|
253
|
+
source: "bundled" | "managed" | "workspace" | "extra" | "catalog",
|
|
254
|
+
): SlimSkillResponse["kind"] {
|
|
255
|
+
if (source === "bundled") return "bundled";
|
|
256
|
+
if (source === "catalog") return "catalog";
|
|
257
|
+
return "installed"; // managed, workspace, extra
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Map a resolved skill to its `origin`, using install-meta.json when available. */
|
|
261
|
+
function deriveOrigin(
|
|
262
|
+
kind: SlimSkillResponse["kind"],
|
|
263
|
+
directoryPath: string,
|
|
264
|
+
installMeta?: SkillInstallMeta | null,
|
|
265
|
+
): SlimSkillResponse["origin"] {
|
|
266
|
+
if (kind === "bundled") return "vellum";
|
|
267
|
+
if (kind === "catalog") return "vellum";
|
|
268
|
+
// For installed skills, use provided install-meta or read from disk.
|
|
269
|
+
// null means "already read, nothing found" — don't re-read.
|
|
270
|
+
const meta =
|
|
271
|
+
installMeta !== undefined ? installMeta : readInstallMeta(directoryPath);
|
|
272
|
+
return meta?.origin ?? "custom";
|
|
246
273
|
}
|
|
247
274
|
|
|
248
|
-
/**
|
|
249
|
-
function
|
|
250
|
-
if (
|
|
251
|
-
if (
|
|
252
|
-
|
|
253
|
-
return 3; // local
|
|
275
|
+
/** Sort rank by kind: bundled first, then catalog, then installed. */
|
|
276
|
+
function kindSortRank(kind: SlimSkillResponse["kind"]): number {
|
|
277
|
+
if (kind === "bundled") return 0;
|
|
278
|
+
if (kind === "catalog") return 1;
|
|
279
|
+
return 2; // installed
|
|
254
280
|
}
|
|
255
281
|
|
|
256
|
-
|
|
282
|
+
/** Convert a resolved skill to a SlimSkillResponse. */
|
|
283
|
+
function toSlimSkillResponse(
|
|
284
|
+
summary: SkillSummary,
|
|
285
|
+
state: "enabled" | "disabled",
|
|
286
|
+
): SlimSkillResponse {
|
|
287
|
+
const kind = deriveKind(summary.source);
|
|
288
|
+
// Read install-meta once and pass it through to avoid redundant file I/O.
|
|
289
|
+
// Use undefined to mean "not yet read"; null means "read but no metadata found".
|
|
290
|
+
const installMeta =
|
|
291
|
+
kind === "installed" ? readInstallMeta(summary.directoryPath) : undefined;
|
|
292
|
+
const origin = deriveOrigin(kind, summary.directoryPath, installMeta);
|
|
293
|
+
const status: SlimSkillResponse["status"] = state;
|
|
294
|
+
|
|
295
|
+
const base = {
|
|
296
|
+
id: summary.id,
|
|
297
|
+
name: summary.displayName,
|
|
298
|
+
description: summary.description,
|
|
299
|
+
emoji: summary.emoji,
|
|
300
|
+
kind,
|
|
301
|
+
status,
|
|
302
|
+
} as const;
|
|
303
|
+
|
|
304
|
+
switch (origin) {
|
|
305
|
+
case "vellum":
|
|
306
|
+
return { ...base, origin };
|
|
307
|
+
case "clawhub": {
|
|
308
|
+
const meta =
|
|
309
|
+
installMeta !== undefined
|
|
310
|
+
? installMeta
|
|
311
|
+
: readInstallMeta(summary.directoryPath);
|
|
312
|
+
return {
|
|
313
|
+
...base,
|
|
314
|
+
origin,
|
|
315
|
+
slug: meta?.slug ?? summary.id,
|
|
316
|
+
author: "",
|
|
317
|
+
stars: 0,
|
|
318
|
+
installs: 0,
|
|
319
|
+
reports: 0,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
case "skillssh": {
|
|
323
|
+
const meta =
|
|
324
|
+
installMeta !== undefined
|
|
325
|
+
? installMeta
|
|
326
|
+
: readInstallMeta(summary.directoryPath);
|
|
327
|
+
return {
|
|
328
|
+
...base,
|
|
329
|
+
origin,
|
|
330
|
+
slug: meta?.slug ?? summary.id,
|
|
331
|
+
sourceRepo: meta?.sourceRepo ?? "",
|
|
332
|
+
installs: 0,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
case "custom":
|
|
336
|
+
return { ...base, origin };
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function listSkills(_ctx: SkillOperationContext): SlimSkillResponse[] {
|
|
257
341
|
const config = getConfig();
|
|
258
342
|
const catalog = loadSkillCatalog();
|
|
259
343
|
const resolved = resolveSkillStates(catalog, config);
|
|
260
344
|
|
|
261
|
-
const items = resolved.map((r) => (
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
description: r.summary.description,
|
|
265
|
-
emoji: r.summary.emoji,
|
|
266
|
-
homepage: r.summary.homepage,
|
|
267
|
-
source: r.summary.source,
|
|
268
|
-
state: r.state,
|
|
269
|
-
installStatus: (r.summary.source === "bundled"
|
|
270
|
-
? "bundled"
|
|
271
|
-
: "installed") as SkillListItem["installStatus"],
|
|
272
|
-
updateAvailable: false,
|
|
273
|
-
provenance: resolveProvenance(r.summary),
|
|
274
|
-
}));
|
|
275
|
-
|
|
276
|
-
// Sort: first-party > third-party with provider > third-party without > local,
|
|
277
|
-
// alphabetical by name within each tier.
|
|
345
|
+
const items = resolved.map((r) => toSlimSkillResponse(r.summary, r.state));
|
|
346
|
+
|
|
347
|
+
// Sort by kind rank, then alphabetical by name within each tier.
|
|
278
348
|
items.sort((a, b) => {
|
|
279
|
-
const rankDiff =
|
|
280
|
-
provenanceSortRank(a.provenance) - provenanceSortRank(b.provenance);
|
|
349
|
+
const rankDiff = kindSortRank(a.kind) - kindSortRank(b.kind);
|
|
281
350
|
if (rankDiff !== 0) return rankDiff;
|
|
282
351
|
return a.name.localeCompare(b.name);
|
|
283
352
|
});
|
|
@@ -291,7 +360,7 @@ export function listSkills(_ctx: SkillOperationContext): SkillListItem[] {
|
|
|
291
360
|
*/
|
|
292
361
|
export async function listSkillsWithCatalog(
|
|
293
362
|
ctx: SkillOperationContext,
|
|
294
|
-
): Promise<
|
|
363
|
+
): Promise<SlimSkillResponse[]> {
|
|
295
364
|
const installed = listSkills(ctx);
|
|
296
365
|
const installedIds = new Set(installed.map((s) => s.id));
|
|
297
366
|
|
|
@@ -304,28 +373,24 @@ export async function listSkillsWithCatalog(
|
|
|
304
373
|
}
|
|
305
374
|
|
|
306
375
|
// All entries from the Vellum platform API are first-party.
|
|
307
|
-
// Create
|
|
308
|
-
const available:
|
|
376
|
+
// Create SlimSkillResponses for catalog skills not already installed.
|
|
377
|
+
const available: SlimSkillResponse[] = catalogSkills
|
|
309
378
|
.filter((cs) => !installedIds.has(cs.id))
|
|
310
379
|
.map((cs) => ({
|
|
311
380
|
id: cs.id,
|
|
312
381
|
name: cs.metadata?.vellum?.["display-name"] ?? cs.name,
|
|
313
382
|
description: cs.description,
|
|
314
383
|
emoji: cs.emoji,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
installStatus: "available" as const,
|
|
319
|
-
updateAvailable: false,
|
|
320
|
-
provenance: { kind: "first-party" as const, provider: "Vellum" },
|
|
384
|
+
kind: "catalog" as const,
|
|
385
|
+
origin: "vellum" as const,
|
|
386
|
+
status: "available" as const,
|
|
321
387
|
}));
|
|
322
388
|
|
|
323
389
|
const merged = [...installed, ...available];
|
|
324
390
|
|
|
325
|
-
// Sort
|
|
391
|
+
// Sort by kind rank, then alphabetical by name
|
|
326
392
|
merged.sort((a, b) => {
|
|
327
|
-
const rankDiff =
|
|
328
|
-
provenanceSortRank(a.provenance) - provenanceSortRank(b.provenance);
|
|
393
|
+
const rankDiff = kindSortRank(a.kind) - kindSortRank(b.kind);
|
|
329
394
|
if (rankDiff !== 0) return rankDiff;
|
|
330
395
|
return a.name.localeCompare(b.name);
|
|
331
396
|
});
|
|
@@ -333,10 +398,10 @@ export async function listSkillsWithCatalog(
|
|
|
333
398
|
return merged;
|
|
334
399
|
}
|
|
335
400
|
|
|
336
|
-
/** Look up a single skill by ID from the resolved catalog, returning its
|
|
401
|
+
/** Look up a single skill by ID from the resolved catalog, returning its SlimSkillResponse. */
|
|
337
402
|
function findSkillById(
|
|
338
403
|
skillId: string,
|
|
339
|
-
): { item:
|
|
404
|
+
): { item: SlimSkillResponse; summary: SkillSummary } | undefined {
|
|
340
405
|
const config = getConfig();
|
|
341
406
|
const catalog = loadSkillCatalog();
|
|
342
407
|
const resolved = resolveSkillStates(catalog, config);
|
|
@@ -344,30 +409,87 @@ function findSkillById(
|
|
|
344
409
|
if (!match) return undefined;
|
|
345
410
|
|
|
346
411
|
const r = match;
|
|
347
|
-
const item
|
|
348
|
-
id: r.summary.id,
|
|
349
|
-
name: r.summary.displayName,
|
|
350
|
-
description: r.summary.description,
|
|
351
|
-
emoji: r.summary.emoji,
|
|
352
|
-
homepage: r.summary.homepage,
|
|
353
|
-
source: r.summary.source,
|
|
354
|
-
state: r.state,
|
|
355
|
-
installStatus: r.summary.source === "bundled" ? "bundled" : "installed",
|
|
356
|
-
updateAvailable: false,
|
|
357
|
-
provenance: resolveProvenance(r.summary),
|
|
358
|
-
};
|
|
412
|
+
const item = toSlimSkillResponse(r.summary, r.state);
|
|
359
413
|
return { item, summary: r.summary };
|
|
360
414
|
}
|
|
361
415
|
|
|
362
|
-
export function getSkill(
|
|
416
|
+
export async function getSkill(
|
|
363
417
|
skillId: string,
|
|
364
418
|
_ctx: SkillOperationContext,
|
|
365
|
-
): { skill:
|
|
419
|
+
): Promise<{ skill: SkillDetailResponse } | { error: string; status: number }> {
|
|
366
420
|
const found = findSkillById(skillId);
|
|
367
421
|
if (!found) {
|
|
368
422
|
return { error: `Skill "${skillId}" not found`, status: 404 };
|
|
369
423
|
}
|
|
370
|
-
|
|
424
|
+
|
|
425
|
+
const slim = found.item;
|
|
426
|
+
|
|
427
|
+
// Build the detail response as a flat discriminated union on origin.
|
|
428
|
+
// Origin-specific fields are spread directly at the top level.
|
|
429
|
+
if (slim.origin === "clawhub") {
|
|
430
|
+
// Start with slim clawhub fields, then enrich with inspect data.
|
|
431
|
+
const detail: SkillDetailResponse = {
|
|
432
|
+
id: slim.id,
|
|
433
|
+
name: slim.name,
|
|
434
|
+
description: slim.description,
|
|
435
|
+
emoji: slim.emoji,
|
|
436
|
+
kind: slim.kind,
|
|
437
|
+
origin: slim.origin,
|
|
438
|
+
status: slim.status,
|
|
439
|
+
slug: slim.slug,
|
|
440
|
+
author: slim.author,
|
|
441
|
+
stars: slim.stars,
|
|
442
|
+
installs: slim.installs,
|
|
443
|
+
reports: slim.reports,
|
|
444
|
+
publishedAt: slim.publishedAt,
|
|
445
|
+
};
|
|
446
|
+
try {
|
|
447
|
+
const inspectResult = await clawhubInspect(slim.slug);
|
|
448
|
+
if (inspectResult.data) {
|
|
449
|
+
const data = inspectResult.data;
|
|
450
|
+
(detail as { owner?: typeof data.owner }).owner = data.owner;
|
|
451
|
+
(detail as { stats?: typeof data.stats }).stats = data.stats;
|
|
452
|
+
(
|
|
453
|
+
detail as { latestVersion?: typeof data.latestVersion }
|
|
454
|
+
).latestVersion = data.latestVersion;
|
|
455
|
+
(detail as { createdAt?: typeof data.createdAt }).createdAt =
|
|
456
|
+
data.createdAt;
|
|
457
|
+
(detail as { updatedAt?: typeof data.updatedAt }).updatedAt =
|
|
458
|
+
data.updatedAt;
|
|
459
|
+
}
|
|
460
|
+
} catch (err) {
|
|
461
|
+
log.warn({ err, skillId }, "Failed to enrich clawhub skill detail");
|
|
462
|
+
}
|
|
463
|
+
return { skill: detail };
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
if (slim.origin === "skillssh") {
|
|
467
|
+
const detail: SkillDetailResponse = {
|
|
468
|
+
id: slim.id,
|
|
469
|
+
name: slim.name,
|
|
470
|
+
description: slim.description,
|
|
471
|
+
emoji: slim.emoji,
|
|
472
|
+
kind: slim.kind,
|
|
473
|
+
origin: slim.origin,
|
|
474
|
+
status: slim.status,
|
|
475
|
+
slug: slim.slug,
|
|
476
|
+
sourceRepo: slim.sourceRepo,
|
|
477
|
+
installs: slim.installs,
|
|
478
|
+
};
|
|
479
|
+
return { skill: detail };
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// vellum or custom origin — base fields only
|
|
483
|
+
const detail: SkillDetailResponse = {
|
|
484
|
+
id: slim.id,
|
|
485
|
+
name: slim.name,
|
|
486
|
+
description: slim.description,
|
|
487
|
+
emoji: slim.emoji,
|
|
488
|
+
kind: slim.kind,
|
|
489
|
+
origin: slim.origin,
|
|
490
|
+
status: slim.status,
|
|
491
|
+
};
|
|
492
|
+
return { skill: detail };
|
|
371
493
|
}
|
|
372
494
|
|
|
373
495
|
// ─── Skill file listing ──────────────────────────────────────────────────────
|
|
@@ -450,7 +572,7 @@ export function getSkillFiles(
|
|
|
450
572
|
skillId: string,
|
|
451
573
|
_ctx: SkillOperationContext,
|
|
452
574
|
):
|
|
453
|
-
| { skill:
|
|
575
|
+
| { skill: SlimSkillResponse; files: SkillFileEntry[] }
|
|
454
576
|
| { error: string; status: number } {
|
|
455
577
|
const found = findSkillById(skillId);
|
|
456
578
|
if (!found) {
|
|
@@ -481,7 +603,8 @@ export function enableSkill(
|
|
|
481
603
|
name: skillId,
|
|
482
604
|
state: "enabled",
|
|
483
605
|
});
|
|
484
|
-
|
|
606
|
+
seedSkillGraphNodes();
|
|
607
|
+
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
485
608
|
return { success: true };
|
|
486
609
|
} catch (err) {
|
|
487
610
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -503,6 +626,8 @@ export function disableSkill(
|
|
|
503
626
|
name: skillId,
|
|
504
627
|
state: "disabled",
|
|
505
628
|
});
|
|
629
|
+
seedSkillGraphNodes();
|
|
630
|
+
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
506
631
|
return { success: true };
|
|
507
632
|
} catch (err) {
|
|
508
633
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -535,8 +660,21 @@ export function configureSkill(
|
|
|
535
660
|
}
|
|
536
661
|
}
|
|
537
662
|
|
|
663
|
+
/**
|
|
664
|
+
* Check whether a slug looks like a skills.sh multi-segment format
|
|
665
|
+
* (e.g. `owner/repo/skill-name` — three or more `/`-separated segments).
|
|
666
|
+
*/
|
|
667
|
+
function looksLikeSkillsShSlug(slug: string): boolean {
|
|
668
|
+
return slug.split("/").length >= 3;
|
|
669
|
+
}
|
|
670
|
+
|
|
538
671
|
export async function installSkill(
|
|
539
|
-
spec: {
|
|
672
|
+
spec: {
|
|
673
|
+
slug: string;
|
|
674
|
+
version?: string;
|
|
675
|
+
origin?: "clawhub" | "skillssh";
|
|
676
|
+
contactId?: string;
|
|
677
|
+
},
|
|
540
678
|
ctx: SkillOperationContext,
|
|
541
679
|
): Promise<{ success: true } | { success: false; error: string }> {
|
|
542
680
|
try {
|
|
@@ -560,7 +698,12 @@ export async function installSkill(
|
|
|
560
698
|
(s) => s.id === spec.slug && s.source === "bundled",
|
|
561
699
|
);
|
|
562
700
|
if (bundled) {
|
|
563
|
-
//
|
|
701
|
+
// Intentional divergence from postInstallSkill(): bundled skills are
|
|
702
|
+
// shipped with the assistant binary and are already on disk. They skip
|
|
703
|
+
// SKILLS.md indexing (they're discovered via the bundled catalog, not
|
|
704
|
+
// the workspace index), dependency installation (deps are pre-bundled),
|
|
705
|
+
// and catalog reload (the catalog already includes them). Only
|
|
706
|
+
// auto-enable, broadcast, and seed memories are needed.
|
|
564
707
|
try {
|
|
565
708
|
const raw = loadRawConfig();
|
|
566
709
|
ensureSkillEntry(raw, spec.slug).enabled = true;
|
|
@@ -576,74 +719,85 @@ export async function installSkill(
|
|
|
576
719
|
"Failed to auto-enable bundled skill",
|
|
577
720
|
);
|
|
578
721
|
}
|
|
579
|
-
|
|
722
|
+
seedSkillGraphNodes();
|
|
723
|
+
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
580
724
|
return { success: true };
|
|
581
725
|
}
|
|
582
726
|
|
|
583
|
-
// Check the Vellum catalog (first-party skills hosted on the platform)
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
saveConfigWithSuppression(raw, ctx);
|
|
598
|
-
ctx.broadcast({
|
|
599
|
-
type: "skills_state_changed",
|
|
600
|
-
name: spec.slug,
|
|
601
|
-
state: "enabled",
|
|
602
|
-
});
|
|
603
|
-
} catch (err) {
|
|
604
|
-
log.warn(
|
|
605
|
-
{ err, skillId: spec.slug },
|
|
606
|
-
"Failed to auto-enable installed catalog skill",
|
|
727
|
+
// Check the Vellum catalog (first-party skills hosted on the platform).
|
|
728
|
+
// Skip when the caller explicitly specified a community origin — this
|
|
729
|
+
// prevents slug collisions where a catalog skill shadows a community
|
|
730
|
+
// skill the user selected from search results.
|
|
731
|
+
if (spec.origin !== "clawhub" && spec.origin !== "skillssh")
|
|
732
|
+
try {
|
|
733
|
+
const vellumCatalog = await getCatalog();
|
|
734
|
+
const catalogEntry = vellumCatalog.find((s) => s.id === spec.slug);
|
|
735
|
+
if (catalogEntry) {
|
|
736
|
+
await installSkillLocally(
|
|
737
|
+
spec.slug,
|
|
738
|
+
catalogEntry,
|
|
739
|
+
true,
|
|
740
|
+
spec.contactId,
|
|
607
741
|
);
|
|
608
|
-
}
|
|
609
742
|
|
|
610
|
-
|
|
611
|
-
|
|
743
|
+
const skillDir = join(getWorkspaceSkillsDir(), spec.slug);
|
|
744
|
+
postInstallSkill(spec.slug, skillDir, ctx);
|
|
745
|
+
return { success: true };
|
|
746
|
+
}
|
|
747
|
+
} catch (err) {
|
|
748
|
+
// If catalog lookup/install fails, fall through to community registries
|
|
749
|
+
log.warn(
|
|
750
|
+
{ err, skillId: spec.slug },
|
|
751
|
+
"Vellum catalog install failed, falling back to community registry",
|
|
752
|
+
);
|
|
612
753
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
754
|
+
|
|
755
|
+
// skills.sh install path: route here when origin is explicitly "skillssh"
|
|
756
|
+
// or when the slug looks like a skills.sh multi-segment format (owner/repo/skill)
|
|
757
|
+
if (
|
|
758
|
+
spec.origin === "skillssh" ||
|
|
759
|
+
(spec.origin !== "clawhub" && looksLikeSkillsShSlug(spec.slug))
|
|
760
|
+
) {
|
|
761
|
+
const resolved = resolveSkillSource(spec.slug);
|
|
762
|
+
await installExternalSkill(
|
|
763
|
+
resolved.owner,
|
|
764
|
+
resolved.repo,
|
|
765
|
+
resolved.skillSlug,
|
|
766
|
+
true /* overwrite */,
|
|
767
|
+
resolved.ref ?? spec.version,
|
|
768
|
+
spec.contactId,
|
|
618
769
|
);
|
|
770
|
+
|
|
771
|
+
const skillDir = join(getWorkspaceSkillsDir(), resolved.skillSlug);
|
|
772
|
+
postInstallSkill(resolved.skillSlug, skillDir, ctx);
|
|
773
|
+
return { success: true };
|
|
619
774
|
}
|
|
620
775
|
|
|
621
776
|
// Install from clawhub (community)
|
|
622
|
-
const result = await clawhubInstall(spec.slug, {
|
|
777
|
+
const result = await clawhubInstall(spec.slug, {
|
|
778
|
+
version: spec.version,
|
|
779
|
+
contactId: spec.contactId,
|
|
780
|
+
});
|
|
623
781
|
if (!result.success) {
|
|
624
782
|
return { success: false, error: result.error ?? "Unknown error" };
|
|
625
783
|
}
|
|
626
784
|
const rawId = result.skillName ?? spec.slug;
|
|
627
785
|
const skillId = rawId.includes("/") ? rawId.split("/").pop()! : rawId;
|
|
628
786
|
|
|
629
|
-
//
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
type: "skills_state_changed",
|
|
639
|
-
name: skillId,
|
|
640
|
-
state: "enabled",
|
|
787
|
+
// clawhubInstall uses the clawhub CLI which doesn't handle bun install
|
|
788
|
+
// or SKILLS.md indexing, so we do those here before post-install.
|
|
789
|
+
const skillDir = join(getWorkspaceSkillsDir(), skillId);
|
|
790
|
+
if (existsSync(join(skillDir, "package.json"))) {
|
|
791
|
+
const bunPath = `${homedir()}/.bun/bin`;
|
|
792
|
+
execSync("bun install", {
|
|
793
|
+
cwd: skillDir,
|
|
794
|
+
stdio: "inherit",
|
|
795
|
+
env: { ...process.env, PATH: `${bunPath}:${process.env.PATH}` },
|
|
641
796
|
});
|
|
642
|
-
} catch (err) {
|
|
643
|
-
log.warn({ err, skillId }, "Failed to auto-enable installed skill");
|
|
644
797
|
}
|
|
798
|
+
upsertSkillsIndex(skillId);
|
|
645
799
|
|
|
646
|
-
|
|
800
|
+
postInstallSkill(skillId, skillDir, ctx);
|
|
647
801
|
return { success: true };
|
|
648
802
|
} catch (err) {
|
|
649
803
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -693,7 +847,7 @@ export async function uninstallSkill(
|
|
|
693
847
|
}
|
|
694
848
|
// Best-effort cleanup of capability memory for uninstalled skill
|
|
695
849
|
// (managed path handles this internally via deleteManagedSkill)
|
|
696
|
-
|
|
850
|
+
deleteSkillCapabilityNode(skillId);
|
|
697
851
|
}
|
|
698
852
|
|
|
699
853
|
// Clean config entry
|
|
@@ -757,62 +911,112 @@ export async function searchSkills(
|
|
|
757
911
|
query: string,
|
|
758
912
|
_ctx: SkillOperationContext,
|
|
759
913
|
): Promise<
|
|
760
|
-
|
|
914
|
+
| { success: true; skills: SlimSkillResponse[] }
|
|
915
|
+
| { success: false; error: string }
|
|
761
916
|
> {
|
|
762
917
|
try {
|
|
763
|
-
// Search the loaded skill catalog (bundled + installed) for matches
|
|
918
|
+
// Search the loaded skill catalog (bundled + installed) for matches.
|
|
919
|
+
// Use resolveSkillStates + toSlimSkillResponse so that already-installed
|
|
920
|
+
// or bundled skills get their correct kind/origin/status instead of being
|
|
921
|
+
// hard-coded as catalog/available.
|
|
764
922
|
const catalog = loadSkillCatalog();
|
|
923
|
+
const config = getConfig();
|
|
924
|
+
const resolved = resolveSkillStates(catalog, config);
|
|
925
|
+
const resolvedById = new Map(resolved.map((r) => [r.summary.id, r]));
|
|
926
|
+
|
|
765
927
|
const catalogMatches = filterByQuery(catalog, query, [
|
|
766
928
|
(s) => s.id,
|
|
767
929
|
(s) => s.displayName,
|
|
768
930
|
(s) => s.description,
|
|
769
931
|
]);
|
|
770
932
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
933
|
+
const catalogItems: SlimSkillResponse[] = catalogMatches.map((s) => {
|
|
934
|
+
const r = resolvedById.get(s.id);
|
|
935
|
+
if (r) {
|
|
936
|
+
return toSlimSkillResponse(r.summary, r.state);
|
|
937
|
+
}
|
|
938
|
+
// Fallback for catalog entries not in resolvedSkillStates (shouldn't
|
|
939
|
+
// normally happen, but defensive)
|
|
940
|
+
return {
|
|
941
|
+
id: s.id,
|
|
942
|
+
name: s.displayName,
|
|
943
|
+
description: s.description,
|
|
944
|
+
emoji: s.emoji,
|
|
945
|
+
kind: "catalog" as const,
|
|
946
|
+
origin: "vellum" as const,
|
|
947
|
+
status: "available" as const,
|
|
948
|
+
};
|
|
949
|
+
});
|
|
784
950
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
stars: 0,
|
|
791
|
-
installs: 0,
|
|
792
|
-
version: "",
|
|
793
|
-
createdAt: 0,
|
|
794
|
-
source: "vellum" as const,
|
|
795
|
-
}));
|
|
951
|
+
// Search both community registries in parallel (non-fatal on failure)
|
|
952
|
+
const [clawhubResult, skillsshResult] = await Promise.allSettled([
|
|
953
|
+
clawhubSearch(query),
|
|
954
|
+
searchSkillsRegistry(query, 25),
|
|
955
|
+
]);
|
|
796
956
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
957
|
+
let clawhubSkills: SlimSkillResponse[] = [];
|
|
958
|
+
if (clawhubResult.status === "fulfilled") {
|
|
959
|
+
clawhubSkills = clawhubResult.value.skills.map((s) => ({
|
|
960
|
+
id: s.slug,
|
|
961
|
+
name: s.name,
|
|
962
|
+
description: s.description,
|
|
963
|
+
kind: "catalog" as const,
|
|
964
|
+
origin: "clawhub" as const,
|
|
965
|
+
status: "available" as const,
|
|
966
|
+
slug: s.slug,
|
|
967
|
+
author: s.author,
|
|
968
|
+
stars: s.stars,
|
|
969
|
+
installs: s.installs,
|
|
970
|
+
reports: 0,
|
|
971
|
+
publishedAt: s.createdAt
|
|
972
|
+
? new Date(s.createdAt * 1000).toISOString()
|
|
973
|
+
: undefined,
|
|
974
|
+
}));
|
|
975
|
+
} else {
|
|
803
976
|
log.warn(
|
|
804
|
-
{ err },
|
|
805
|
-
"clawhub search failed,
|
|
977
|
+
{ err: clawhubResult.reason },
|
|
978
|
+
"clawhub search failed, continuing without clawhub results",
|
|
806
979
|
);
|
|
807
980
|
}
|
|
808
981
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
982
|
+
let skillsshSkills: SlimSkillResponse[] = [];
|
|
983
|
+
if (skillsshResult.status === "fulfilled") {
|
|
984
|
+
skillsshSkills = skillsshResult.value.map((r) => ({
|
|
985
|
+
id: r.id,
|
|
986
|
+
name: r.name,
|
|
987
|
+
description: "",
|
|
988
|
+
kind: "catalog" as const,
|
|
989
|
+
origin: "skillssh" as const,
|
|
990
|
+
status: "available" as const,
|
|
991
|
+
slug: r.id,
|
|
992
|
+
sourceRepo: r.source,
|
|
993
|
+
installs: r.installs,
|
|
994
|
+
}));
|
|
995
|
+
} else {
|
|
996
|
+
log.warn(
|
|
997
|
+
{ err: skillsshResult.reason },
|
|
998
|
+
"skills.sh search failed, continuing without skills.sh results",
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
// Deduplicate: catalog > clawhub > skills.sh (first occurrence wins)
|
|
1003
|
+
const seenSlugs = new Set(catalogItems.map((s) => s.id));
|
|
1004
|
+
|
|
1005
|
+
const dedupedClawhub = clawhubSkills.filter((s) => {
|
|
1006
|
+
if (seenSlugs.has(s.id)) return false;
|
|
1007
|
+
seenSlugs.add(s.id);
|
|
1008
|
+
return true;
|
|
1009
|
+
});
|
|
1010
|
+
|
|
1011
|
+
const dedupedSkillssh = skillsshSkills.filter((s) => {
|
|
1012
|
+
if (seenSlugs.has(s.id)) return false;
|
|
1013
|
+
seenSlugs.add(s.id);
|
|
1014
|
+
return true;
|
|
1015
|
+
});
|
|
812
1016
|
|
|
813
1017
|
return {
|
|
814
1018
|
success: true,
|
|
815
|
-
|
|
1019
|
+
skills: [...catalogItems, ...dedupedClawhub, ...dedupedSkillssh],
|
|
816
1020
|
};
|
|
817
1021
|
} catch (err) {
|
|
818
1022
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -1002,6 +1206,7 @@ export interface CreateSkillParams {
|
|
|
1002
1206
|
emoji?: string;
|
|
1003
1207
|
bodyMarkdown: string;
|
|
1004
1208
|
overwrite?: boolean;
|
|
1209
|
+
contactId?: string;
|
|
1005
1210
|
}
|
|
1006
1211
|
|
|
1007
1212
|
export async function createSkill(
|
|
@@ -1016,6 +1221,7 @@ export async function createSkill(
|
|
|
1016
1221
|
emoji: params.emoji,
|
|
1017
1222
|
bodyMarkdown: params.bodyMarkdown,
|
|
1018
1223
|
overwrite: params.overwrite,
|
|
1224
|
+
contactId: params.contactId,
|
|
1019
1225
|
});
|
|
1020
1226
|
|
|
1021
1227
|
if (!result.created) {
|
|
@@ -1042,7 +1248,8 @@ export async function createSkill(
|
|
|
1042
1248
|
);
|
|
1043
1249
|
}
|
|
1044
1250
|
|
|
1045
|
-
|
|
1251
|
+
seedSkillGraphNodes();
|
|
1252
|
+
void seedUninstalledCatalogSkillMemories().catch(() => {});
|
|
1046
1253
|
return { success: true };
|
|
1047
1254
|
} catch (err) {
|
|
1048
1255
|
const message = err instanceof Error ? err.message : String(err);
|