@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,4 +1,5 @@
|
|
|
1
1
|
import { bootstrapConversation } from "../memory/conversation-bootstrap.js";
|
|
2
|
+
import { getConversation } from "../memory/conversation-crud.js";
|
|
2
3
|
import { invalidateAssistantInferredItemsForConversation } from "../memory/task-memory-cleanup.js";
|
|
3
4
|
import { runSequencesOnce } from "../sequence/engine.js";
|
|
4
5
|
import { getLogger } from "../util/logger.js";
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
completeScheduleRun,
|
|
15
16
|
createScheduleRun,
|
|
16
17
|
failOneShot,
|
|
18
|
+
getLastScheduleConversationId,
|
|
17
19
|
type RoutingIntent,
|
|
18
20
|
} from "./schedule-store.js";
|
|
19
21
|
|
|
@@ -188,7 +190,12 @@ async function runScheduleOnce(
|
|
|
188
190
|
);
|
|
189
191
|
const { runTask } = await import("../tasks/task-runner.js");
|
|
190
192
|
const result = await runTask(
|
|
191
|
-
{
|
|
193
|
+
{
|
|
194
|
+
taskId,
|
|
195
|
+
workingDir: process.cwd(),
|
|
196
|
+
source: "schedule",
|
|
197
|
+
scheduleJobId: job.id,
|
|
198
|
+
},
|
|
192
199
|
processMessage as (
|
|
193
200
|
conversationId: string,
|
|
194
201
|
message: string,
|
|
@@ -235,8 +242,10 @@ async function runScheduleOnce(
|
|
|
235
242
|
);
|
|
236
243
|
// Create a fallback conversation for the schedule run record
|
|
237
244
|
const fallbackConversation = bootstrapConversation({
|
|
245
|
+
conversationType: "scheduled",
|
|
238
246
|
source: "schedule",
|
|
239
247
|
scheduleJobId: job.id,
|
|
248
|
+
groupId: "system:scheduled",
|
|
240
249
|
origin: "schedule",
|
|
241
250
|
systemHint: `Schedule: ${job.name}`,
|
|
242
251
|
});
|
|
@@ -252,18 +261,36 @@ async function runScheduleOnce(
|
|
|
252
261
|
continue;
|
|
253
262
|
}
|
|
254
263
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
264
|
+
// Reuse the conversation from the last successful run when the flag is set
|
|
265
|
+
// and a prior conversation still exists; otherwise bootstrap a new one.
|
|
266
|
+
let conversationId: string | null = null;
|
|
267
|
+
let conversationReused = false;
|
|
268
|
+
if (job.reuseConversation && !isOneShot) {
|
|
269
|
+
const lastId = getLastScheduleConversationId(job.id);
|
|
270
|
+
if (lastId && getConversation(lastId)) {
|
|
271
|
+
conversationId = lastId;
|
|
272
|
+
conversationReused = true;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (!conversationId) {
|
|
276
|
+
const conversation = bootstrapConversation({
|
|
277
|
+
conversationType: "scheduled",
|
|
278
|
+
source: "schedule",
|
|
279
|
+
scheduleJobId: job.id,
|
|
280
|
+
groupId: "system:scheduled",
|
|
281
|
+
origin: "schedule",
|
|
282
|
+
systemHint: isOneShot
|
|
283
|
+
? `Reminder: ${job.name}`
|
|
284
|
+
: `Schedule: ${job.name}`,
|
|
285
|
+
});
|
|
286
|
+
conversationId = conversation.id;
|
|
287
|
+
}
|
|
261
288
|
onScheduleConversationCreated?.({
|
|
262
|
-
conversationId
|
|
289
|
+
conversationId,
|
|
263
290
|
scheduleJobId: job.id,
|
|
264
291
|
title: job.name,
|
|
265
292
|
});
|
|
266
|
-
const runId = createScheduleRun(job.id,
|
|
293
|
+
const runId = createScheduleRun(job.id, conversationId);
|
|
267
294
|
const isRruleSetMsg =
|
|
268
295
|
job.syntax === "rrule" &&
|
|
269
296
|
job.expression != null &&
|
|
@@ -278,11 +305,11 @@ async function runScheduleOnce(
|
|
|
278
305
|
expression: job.expression,
|
|
279
306
|
isRruleSet: isRruleSetMsg,
|
|
280
307
|
isOneShot,
|
|
281
|
-
conversationId
|
|
308
|
+
conversationId,
|
|
282
309
|
},
|
|
283
310
|
isOneShot ? "Executing one-shot schedule" : "Executing schedule",
|
|
284
311
|
);
|
|
285
|
-
await processMessage(
|
|
312
|
+
await processMessage(conversationId, job.message, {
|
|
286
313
|
trustClass: "guardian",
|
|
287
314
|
});
|
|
288
315
|
completeScheduleRun(runId, { status: "ok" });
|
|
@@ -310,13 +337,20 @@ async function runScheduleOnce(
|
|
|
310
337
|
completeScheduleRun(runId, { status: "error", error: message });
|
|
311
338
|
if (isOneShot) failOneShot(job.id);
|
|
312
339
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
340
|
+
// Only skip invalidation when the conversation was *actually* reused,
|
|
341
|
+
// i.e. it contains prior successful context worth preserving. When
|
|
342
|
+
// reuseConversation is true but no prior conversation existed (first run
|
|
343
|
+
// or deleted), the conversation is brand-new and should be invalidated
|
|
344
|
+
// like any other failed conversation.
|
|
345
|
+
if (!conversationReused) {
|
|
346
|
+
try {
|
|
347
|
+
invalidateAssistantInferredItemsForConversation(conversationId);
|
|
348
|
+
} catch (cleanupErr) {
|
|
349
|
+
log.warn(
|
|
350
|
+
{ err: cleanupErr, conversationId },
|
|
351
|
+
"Failed to invalidate assistant-inferred memory items",
|
|
352
|
+
);
|
|
353
|
+
}
|
|
320
354
|
}
|
|
321
355
|
}
|
|
322
356
|
}
|
package/src/security/oauth2.ts
CHANGED
|
@@ -61,7 +61,7 @@ export interface OAuth2TokenResult {
|
|
|
61
61
|
|
|
62
62
|
export interface OAuth2FlowCallbacks {
|
|
63
63
|
/** Open a URL in the user's browser (e.g. via `open_url` message). */
|
|
64
|
-
openUrl: (url: string) => void
|
|
64
|
+
openUrl: (url: string) => void | Promise<void>;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
export interface OAuth2FlowOptions {
|
|
@@ -22,9 +22,9 @@ import type {
|
|
|
22
22
|
SecureKeyDeleteResult,
|
|
23
23
|
} from "@vellumai/credential-storage";
|
|
24
24
|
|
|
25
|
-
import providerEnvVarsRegistry from "../../../meta/provider-env-vars.json" with { type: "json" };
|
|
26
25
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
27
26
|
import type { CesClient } from "../credential-execution/client.js";
|
|
27
|
+
import { PROVIDER_ENV_VAR_NAMES } from "../shared/provider-env-vars.js";
|
|
28
28
|
import { getLogger } from "../util/logger.js";
|
|
29
29
|
import { createCesCredentialBackend } from "./ces-credential-client.js";
|
|
30
30
|
import { CesRpcCredentialBackend } from "./ces-rpc-credential-backend.js";
|
|
@@ -395,14 +395,10 @@ export async function deleteSecureKeyAsync(
|
|
|
395
395
|
// ---------------------------------------------------------------------------
|
|
396
396
|
|
|
397
397
|
/**
|
|
398
|
-
* Env var names keyed by provider.
|
|
399
|
-
*
|
|
400
|
-
* by the CLI and the macOS client.
|
|
401
|
-
* Ollama is intentionally omitted from the registry — it doesn't require
|
|
402
|
-
* an API key.
|
|
398
|
+
* Env var names keyed by provider.
|
|
399
|
+
* Ollama is intentionally omitted — it doesn't require an API key.
|
|
403
400
|
*/
|
|
404
|
-
const PROVIDER_ENV_VARS: Record<string, string> =
|
|
405
|
-
providerEnvVarsRegistry.providers;
|
|
401
|
+
const PROVIDER_ENV_VARS: Record<string, string> = PROVIDER_ENV_VAR_NAMES;
|
|
406
402
|
|
|
407
403
|
/**
|
|
408
404
|
* Retrieve a provider API key, checking secure storage first and falling
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider API key environment variable names, keyed by provider ID.
|
|
3
|
+
*
|
|
4
|
+
* Keep in sync with:
|
|
5
|
+
* - cli/src/shared/provider-env-vars.ts
|
|
6
|
+
* - meta/provider-env-vars.json (consumed by the macOS client build)
|
|
7
|
+
*
|
|
8
|
+
* Once a consolidated shared package exists in packages/, all three
|
|
9
|
+
* copies can be replaced by a single import.
|
|
10
|
+
*/
|
|
11
|
+
export const PROVIDER_ENV_VAR_NAMES: Record<string, string> = {
|
|
12
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
13
|
+
openai: "OPENAI_API_KEY",
|
|
14
|
+
gemini: "GEMINI_API_KEY",
|
|
15
|
+
fireworks: "FIREWORKS_API_KEY",
|
|
16
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
17
|
+
brave: "BRAVE_API_KEY",
|
|
18
|
+
perplexity: "PERPLEXITY_API_KEY",
|
|
19
|
+
};
|
|
@@ -37,6 +37,11 @@ export async function getCatalog(): Promise<CatalogSkill[]> {
|
|
|
37
37
|
return catalog;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/** Return the cached catalog synchronously, or [] if no cache exists yet. */
|
|
41
|
+
export function getCachedCatalogSync(): CatalogSkill[] {
|
|
42
|
+
return cachedCatalog ?? [];
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
/** Invalidate the cache (for testing or forced refresh). */
|
|
41
46
|
export function invalidateCatalogCache(): void {
|
|
42
47
|
cachedCatalog = null;
|
|
@@ -14,9 +14,10 @@ import { dirname, join, posix, resolve, sep } from "node:path";
|
|
|
14
14
|
import { gunzipSync } from "node:zlib";
|
|
15
15
|
|
|
16
16
|
import { getPlatformBaseUrl } from "../config/env.js";
|
|
17
|
+
import { deleteSkillCapabilityNode } from "../memory/graph/capability-seed.js";
|
|
17
18
|
import { getLogger } from "../util/logger.js";
|
|
18
19
|
import { getWorkspaceSkillsDir, readPlatformToken } from "../util/platform.js";
|
|
19
|
-
import {
|
|
20
|
+
import { computeSkillHash, writeInstallMeta } from "./install-meta.js";
|
|
20
21
|
|
|
21
22
|
const log = getLogger("catalog-install");
|
|
22
23
|
|
|
@@ -263,13 +264,14 @@ export function uninstallSkillLocally(skillId: string): void {
|
|
|
263
264
|
|
|
264
265
|
rmSync(skillDir, { recursive: true, force: true });
|
|
265
266
|
removeSkillsIndexEntry(skillId);
|
|
266
|
-
|
|
267
|
+
deleteSkillCapabilityNode(skillId);
|
|
267
268
|
}
|
|
268
269
|
|
|
269
270
|
export async function installSkillLocally(
|
|
270
271
|
skillId: string,
|
|
271
272
|
catalogEntry: CatalogSkill,
|
|
272
273
|
overwrite: boolean,
|
|
274
|
+
contactId?: string,
|
|
273
275
|
): Promise<void> {
|
|
274
276
|
const skillDir = join(getWorkspaceSkillsDir(), skillId);
|
|
275
277
|
const skillFilePath = join(skillDir, "SKILL.md");
|
|
@@ -294,19 +296,18 @@ export async function installSkillLocally(
|
|
|
294
296
|
await fetchAndExtractSkill(skillId, skillDir);
|
|
295
297
|
}
|
|
296
298
|
|
|
297
|
-
// Write
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
JSON.stringify(meta, null, 2) + "\n",
|
|
306
|
-
);
|
|
307
|
-
}
|
|
299
|
+
// Write install metadata
|
|
300
|
+
writeInstallMeta(skillDir, {
|
|
301
|
+
origin: "vellum",
|
|
302
|
+
installedAt: new Date().toISOString(),
|
|
303
|
+
...(catalogEntry.version ? { version: catalogEntry.version } : {}),
|
|
304
|
+
...(contactId ? { installedBy: contactId } : {}),
|
|
305
|
+
contentHash: computeSkillHash(skillDir) ?? undefined,
|
|
306
|
+
});
|
|
308
307
|
|
|
309
|
-
//
|
|
308
|
+
// Post-install: install dependencies first, then index the skill.
|
|
309
|
+
// Running bun install before upsertSkillsIndex ensures we don't index a
|
|
310
|
+
// skill whose dependencies failed to install.
|
|
310
311
|
if (existsSync(join(skillDir, "package.json"))) {
|
|
311
312
|
const bunPath = `${homedir()}/.bun/bin`;
|
|
312
313
|
execSync("bun install", {
|
|
@@ -315,8 +316,6 @@ export async function installSkillLocally(
|
|
|
315
316
|
env: { ...process.env, PATH: `${bunPath}:${process.env.PATH}` },
|
|
316
317
|
});
|
|
317
318
|
}
|
|
318
|
-
|
|
319
|
-
// Register in SKILLS.md only after all steps succeed
|
|
320
319
|
upsertSkillsIndex(skillId);
|
|
321
320
|
}
|
|
322
321
|
|
|
@@ -393,6 +392,16 @@ export async function autoInstallFromCatalog(
|
|
|
393
392
|
return false;
|
|
394
393
|
}
|
|
395
394
|
|
|
395
|
+
// If the skill already exists on disk (stale index), re-index it instead
|
|
396
|
+
// of attempting a fresh install that would fail.
|
|
397
|
+
const skillDir = join(getWorkspaceSkillsDir(), skillId);
|
|
398
|
+
if (existsSync(join(skillDir, "SKILL.md"))) {
|
|
399
|
+
upsertSkillsIndex(skillId);
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// installSkillLocally handles dependency installation and SKILLS.md indexing.
|
|
396
404
|
await installSkillLocally(skillId, entry, false);
|
|
405
|
+
|
|
397
406
|
return true;
|
|
398
407
|
}
|
package/src/skills/clawhub.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
existsSync,
|
|
3
|
-
readdirSync,
|
|
4
|
-
readFileSync,
|
|
5
|
-
statSync,
|
|
6
|
-
writeFileSync,
|
|
7
|
-
} from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
8
2
|
import { dirname, join } from "node:path";
|
|
9
3
|
|
|
10
4
|
import { getLogger } from "../util/logger.js";
|
|
11
5
|
import { getWorkspaceSkillsDir } from "../util/platform.js";
|
|
6
|
+
import {
|
|
7
|
+
computeSkillHash,
|
|
8
|
+
readInstallMeta,
|
|
9
|
+
writeInstallMeta,
|
|
10
|
+
} from "./install-meta.js";
|
|
12
11
|
|
|
13
12
|
const log = getLogger("clawhub");
|
|
14
13
|
|
|
@@ -54,61 +53,15 @@ export function loadIntegrityManifest(): IntegrityManifest {
|
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
function saveIntegrityManifest(manifest: IntegrityManifest): void {
|
|
58
|
-
writeFileSync(
|
|
59
|
-
getIntegrityPath(),
|
|
60
|
-
JSON.stringify(manifest, null, 2) + "\n",
|
|
61
|
-
"utf-8",
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Collect all file contents in a directory tree, sorted by relative path for determinism. */
|
|
66
|
-
function collectFileContents(
|
|
67
|
-
dir: string,
|
|
68
|
-
prefix = "",
|
|
69
|
-
): Array<{ relPath: string; content: Buffer }> {
|
|
70
|
-
const results: Array<{ relPath: string; content: Buffer }> = [];
|
|
71
|
-
if (!existsSync(dir)) return results;
|
|
72
|
-
|
|
73
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
74
|
-
for (const entry of entries) {
|
|
75
|
-
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
76
|
-
const fullPath = join(dir, entry.name);
|
|
77
|
-
if (entry.isDirectory()) {
|
|
78
|
-
results.push(...collectFileContents(fullPath, relPath));
|
|
79
|
-
} else if (entry.isFile()) {
|
|
80
|
-
results.push({ relPath, content: readFileSync(fullPath) });
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return results.sort((a, b) => a.relPath.localeCompare(b.relPath));
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Compute a SHA-256 hash over all files in a skill directory.
|
|
88
|
-
* Returns format: "v2:sha256hex" (version prefix added to support hash format evolution).
|
|
89
|
-
*/
|
|
90
|
-
function computeSkillHash(skillDir: string): string | null {
|
|
91
|
-
if (!existsSync(skillDir) || !statSync(skillDir).isDirectory()) return null;
|
|
92
|
-
|
|
93
|
-
const files = collectFileContents(skillDir);
|
|
94
|
-
if (files.length === 0) return null;
|
|
95
|
-
|
|
96
|
-
const hasher = new Bun.CryptoHasher("sha256");
|
|
97
|
-
for (const file of files) {
|
|
98
|
-
// Length-prefix each segment to prevent boundary ambiguity collisions
|
|
99
|
-
const pathBuf = Buffer.from(file.relPath, "utf-8");
|
|
100
|
-
hasher.update(`${pathBuf.length}:`);
|
|
101
|
-
hasher.update(pathBuf);
|
|
102
|
-
hasher.update(`${file.content.length}:`);
|
|
103
|
-
hasher.update(file.content);
|
|
104
|
-
}
|
|
105
|
-
return `v2:${hasher.digest("hex")}`;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
56
|
/**
|
|
109
57
|
* Record or verify the content hash of an installed skill.
|
|
110
58
|
* On first install: stores the hash (trust-on-first-use).
|
|
111
59
|
* On subsequent installs: compares with stored hash and warns on mismatch.
|
|
60
|
+
*
|
|
61
|
+
* Always writes to `install-meta.json`. For skills that don't have one yet,
|
|
62
|
+
* creates a new `install-meta.json` with minimal metadata. Reads from the
|
|
63
|
+
* legacy `.integrity.json` manifest as a read-only fallback for stored hashes
|
|
64
|
+
* from skills that haven't been migrated yet.
|
|
112
65
|
*/
|
|
113
66
|
export function verifyAndRecordSkillHash(slug: string): void {
|
|
114
67
|
const skillDir = join(getManagedSkillsDir(), slug);
|
|
@@ -118,17 +71,28 @@ export function verifyAndRecordSkillHash(slug: string): void {
|
|
|
118
71
|
return;
|
|
119
72
|
}
|
|
120
73
|
|
|
121
|
-
|
|
122
|
-
const
|
|
74
|
+
// Try install-meta.json first for stored hash
|
|
75
|
+
const installMeta = readInstallMeta(skillDir);
|
|
76
|
+
let storedHash: string | undefined;
|
|
123
77
|
|
|
124
|
-
if (
|
|
125
|
-
|
|
78
|
+
if (installMeta?.contentHash) {
|
|
79
|
+
storedHash = installMeta.contentHash;
|
|
80
|
+
} else {
|
|
81
|
+
// Fall back to legacy .integrity.json manifest
|
|
82
|
+
const manifest = loadIntegrityManifest();
|
|
83
|
+
const existing = manifest[slug];
|
|
84
|
+
if (existing) {
|
|
85
|
+
storedHash =
|
|
86
|
+
typeof existing.sha256 === "string" ? existing.sha256 : undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
126
89
|
|
|
127
|
-
|
|
90
|
+
if (storedHash) {
|
|
91
|
+
// Guard against corrupted entries where hash is not a string
|
|
128
92
|
if (typeof storedHash !== "string") {
|
|
129
93
|
log.warn(
|
|
130
94
|
{ slug },
|
|
131
|
-
"
|
|
95
|
+
"Stored hash has non-string value — re-recording hash",
|
|
132
96
|
);
|
|
133
97
|
} else if (!storedHash.startsWith("v2:")) {
|
|
134
98
|
// Unknown format (not v2: prefix) — warn about integrity mismatch
|
|
@@ -155,9 +119,18 @@ export function verifyAndRecordSkillHash(slug: string): void {
|
|
|
155
119
|
);
|
|
156
120
|
}
|
|
157
121
|
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
|
|
122
|
+
// Write to install-meta.json (preferred). If no install-meta exists yet,
|
|
123
|
+
// create one with minimal metadata.
|
|
124
|
+
if (installMeta) {
|
|
125
|
+
writeInstallMeta(skillDir, { ...installMeta, contentHash: hash });
|
|
126
|
+
} else {
|
|
127
|
+
writeInstallMeta(skillDir, {
|
|
128
|
+
origin: "clawhub",
|
|
129
|
+
installedAt: new Date().toISOString(),
|
|
130
|
+
slug,
|
|
131
|
+
contentHash: hash,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
161
134
|
}
|
|
162
135
|
|
|
163
136
|
interface ClawhubInstallResult {
|
|
@@ -248,7 +221,7 @@ async function runClawhub(
|
|
|
248
221
|
|
|
249
222
|
export async function clawhubInstall(
|
|
250
223
|
slug: string,
|
|
251
|
-
opts?: { version?: string },
|
|
224
|
+
opts?: { version?: string; contactId?: string },
|
|
252
225
|
): Promise<ClawhubInstallResult> {
|
|
253
226
|
if (!validateSlug(slug)) {
|
|
254
227
|
return { success: false, error: `Invalid skill slug: ${slug}` };
|
|
@@ -264,7 +237,19 @@ export async function clawhubInstall(
|
|
|
264
237
|
result.stderr.trim() || result.stdout.trim() || "Unknown error";
|
|
265
238
|
return { success: false, error };
|
|
266
239
|
}
|
|
267
|
-
|
|
240
|
+
|
|
241
|
+
// Write install-meta.json for the installed skill.
|
|
242
|
+
// contentHash is included here, so there's no need to call
|
|
243
|
+
// verifyAndRecordSkillHash() — it would just rewrite the same data.
|
|
244
|
+
const skillDir = join(getManagedSkillsDir(), slug);
|
|
245
|
+
writeInstallMeta(skillDir, {
|
|
246
|
+
origin: "clawhub",
|
|
247
|
+
slug,
|
|
248
|
+
installedAt: new Date().toISOString(),
|
|
249
|
+
...(opts?.contactId ? { installedBy: opts.contactId } : {}),
|
|
250
|
+
contentHash: computeSkillHash(skillDir) ?? undefined,
|
|
251
|
+
});
|
|
252
|
+
|
|
268
253
|
return { success: true, skillName: slug };
|
|
269
254
|
} catch (err) {
|
|
270
255
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -292,63 +277,63 @@ export async function clawhubUpdate(
|
|
|
292
277
|
|
|
293
278
|
export async function clawhubSearch(
|
|
294
279
|
query: string,
|
|
280
|
+
opts?: { limit?: number },
|
|
295
281
|
): Promise<ClawhubSearchResult> {
|
|
282
|
+
const limit = opts?.limit ?? 25;
|
|
283
|
+
|
|
296
284
|
// Empty query: use explore (browse trending) instead of search
|
|
297
285
|
if (!query.trim()) {
|
|
298
|
-
return clawhubExplore();
|
|
286
|
+
return clawhubExplore({ limit });
|
|
299
287
|
}
|
|
300
288
|
|
|
289
|
+
const result = await runClawhub(["search", query, "--limit", String(limit)]);
|
|
290
|
+
if (result.exitCode !== 0) {
|
|
291
|
+
const error =
|
|
292
|
+
result.stderr.trim() || result.stdout.trim() || "Unknown error";
|
|
293
|
+
throw new Error(`clawhub search failed: ${error}`);
|
|
294
|
+
}
|
|
295
|
+
// Try JSON first
|
|
301
296
|
try {
|
|
302
|
-
const
|
|
303
|
-
if (
|
|
304
|
-
return {
|
|
297
|
+
const parsed = JSON.parse(result.stdout);
|
|
298
|
+
if (Array.isArray(parsed)) {
|
|
299
|
+
return {
|
|
300
|
+
skills: parsed.map((s: ClawhubSearchResultItem) => ({
|
|
301
|
+
...s,
|
|
302
|
+
source: s.source ?? ("clawhub" as const),
|
|
303
|
+
})),
|
|
304
|
+
};
|
|
305
305
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
source: s.source ?? ("clawhub" as const),
|
|
314
|
-
})),
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
if (parsed.skills && Array.isArray(parsed.skills)) {
|
|
318
|
-
return {
|
|
319
|
-
skills: parsed.skills.map((s: ClawhubSearchResultItem) => ({
|
|
320
|
-
...s,
|
|
321
|
-
source: s.source ?? ("clawhub" as const),
|
|
322
|
-
})),
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
} catch {
|
|
326
|
-
// CLI outputs text: "slug vVersion DisplayName (score)"
|
|
306
|
+
if (parsed.skills && Array.isArray(parsed.skills)) {
|
|
307
|
+
return {
|
|
308
|
+
skills: parsed.skills.map((s: ClawhubSearchResultItem) => ({
|
|
309
|
+
...s,
|
|
310
|
+
source: s.source ?? ("clawhub" as const),
|
|
311
|
+
})),
|
|
312
|
+
};
|
|
327
313
|
}
|
|
314
|
+
} catch {
|
|
315
|
+
// CLI outputs text: "slug vVersion DisplayName (score)"
|
|
316
|
+
}
|
|
328
317
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
318
|
+
// Parse text output lines: "slug vVersion Display Name (score)"
|
|
319
|
+
const skills: ClawhubSearchResultItem[] = [];
|
|
320
|
+
for (const line of result.stdout.split("\n")) {
|
|
321
|
+
const match = line.match(/^(\S+)\s+v(\S+)\s+(.+?)\s+\([\d.]+\)\s*$/);
|
|
322
|
+
if (match) {
|
|
323
|
+
skills.push({
|
|
324
|
+
slug: match[1],
|
|
325
|
+
version: match[2],
|
|
326
|
+
name: match[3].trim(),
|
|
327
|
+
description: "",
|
|
328
|
+
author: "",
|
|
329
|
+
stars: 0,
|
|
330
|
+
installs: 0,
|
|
331
|
+
createdAt: 0,
|
|
332
|
+
source: "clawhub",
|
|
333
|
+
});
|
|
346
334
|
}
|
|
347
|
-
return { skills };
|
|
348
|
-
} catch (err) {
|
|
349
|
-
log.warn({ err }, "clawhub search failed");
|
|
350
|
-
return { skills: [] };
|
|
351
335
|
}
|
|
336
|
+
return { skills };
|
|
352
337
|
}
|
|
353
338
|
|
|
354
339
|
export async function clawhubExplore(opts?: {
|
|
@@ -358,46 +343,41 @@ export async function clawhubExplore(opts?: {
|
|
|
358
343
|
const limit = String(opts?.limit ?? 25);
|
|
359
344
|
const sort = opts?.sort ?? "installsAllTime";
|
|
360
345
|
|
|
346
|
+
const result = await runClawhub([
|
|
347
|
+
"explore",
|
|
348
|
+
"--json",
|
|
349
|
+
"--limit",
|
|
350
|
+
limit,
|
|
351
|
+
"--sort",
|
|
352
|
+
sort,
|
|
353
|
+
]);
|
|
354
|
+
if (result.exitCode !== 0) {
|
|
355
|
+
const error =
|
|
356
|
+
result.stderr.trim() || result.stdout.trim() || "Unknown error";
|
|
357
|
+
throw new Error(`clawhub explore failed: ${error}`);
|
|
358
|
+
}
|
|
361
359
|
try {
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
description: (item.summary as string) ?? "",
|
|
384
|
-
author: (item.author as string) ?? "",
|
|
385
|
-
stars: (item.stats as Record<string, number>)?.stars ?? 0,
|
|
386
|
-
installs:
|
|
387
|
-
(item.stats as Record<string, number>)?.installsAllTime ?? 0,
|
|
388
|
-
version: (item.tags as Record<string, string>)?.latest ?? "",
|
|
389
|
-
createdAt: (item.createdAt as number) ?? 0,
|
|
390
|
-
source: "clawhub",
|
|
391
|
-
}),
|
|
392
|
-
);
|
|
393
|
-
return { skills };
|
|
394
|
-
} catch {
|
|
395
|
-
// parse failure
|
|
396
|
-
}
|
|
397
|
-
return { skills: [] };
|
|
398
|
-
} catch (err) {
|
|
399
|
-
log.warn({ err }, "clawhub explore failed");
|
|
400
|
-
return { skills: [] };
|
|
360
|
+
const parsed = JSON.parse(result.stdout);
|
|
361
|
+
const items = parsed.items ?? parsed;
|
|
362
|
+
if (!Array.isArray(items)) return { skills: [] };
|
|
363
|
+
|
|
364
|
+
// Normalize explore response to ClawhubSearchResultItem shape
|
|
365
|
+
const skills: ClawhubSearchResultItem[] = items.map(
|
|
366
|
+
(item: Record<string, unknown>) => ({
|
|
367
|
+
name: (item.displayName as string) ?? (item.slug as string) ?? "",
|
|
368
|
+
slug: (item.slug as string) ?? "",
|
|
369
|
+
description: (item.summary as string) ?? "",
|
|
370
|
+
author: (item.author as string) ?? "",
|
|
371
|
+
stars: (item.stats as Record<string, number>)?.stars ?? 0,
|
|
372
|
+
installs: (item.stats as Record<string, number>)?.installsAllTime ?? 0,
|
|
373
|
+
version: (item.tags as Record<string, string>)?.latest ?? "",
|
|
374
|
+
createdAt: (item.createdAt as number) ?? 0,
|
|
375
|
+
source: "clawhub",
|
|
376
|
+
}),
|
|
377
|
+
);
|
|
378
|
+
return { skills };
|
|
379
|
+
} catch {
|
|
380
|
+
throw new Error("Failed to parse clawhub explore output");
|
|
401
381
|
}
|
|
402
382
|
}
|
|
403
383
|
|