@vellumai/assistant 0.5.15 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +3 -3
- package/Dockerfile +0 -3
- package/docs/architecture/integrations.md +15 -14
- package/knip.json +4 -1
- package/openapi.yaml +670 -122
- package/package.json +1 -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 +57 -3
- package/src/__tests__/app-compiler.test.ts +120 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +5 -377
- 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__/ces-rpc-credential-backend.test.ts +4 -1
- 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 +84 -3
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +108 -6
- package/src/__tests__/cli-memory.test.ts +377 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -2
- package/src/__tests__/config-schema.test.ts +1 -3
- package/src/__tests__/config-set-platform-guard.test.ts +302 -0
- package/src/__tests__/config-watcher-feature-flags.test.ts +211 -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 +9 -0
- package/src/__tests__/conversation-agent-loop.test.ts +9 -0
- 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 +5 -0
- 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 +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +2 -6
- package/src/__tests__/conversation-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-usage.test.ts +3 -6
- package/src/__tests__/conversation-wipe.test.ts +11 -408
- 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 +6 -1
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +7 -73
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -7
- 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 +343 -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 +1 -3
- package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
- package/src/__tests__/injection-block.test.ts +154 -0
- package/src/__tests__/install-meta.test.ts +506 -0
- package/src/__tests__/install-skill-routing.test.ts +292 -0
- package/src/__tests__/intent-routing.test.ts +6 -18
- 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 +2 -14
- package/src/__tests__/list-messages-attachments.test.ts +2 -6
- package/src/__tests__/llm-context-route-provider.test.ts +2 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +2 -6
- package/src/__tests__/llm-usage-store.test.ts +2 -6
- package/src/__tests__/log-export-workspace.test.ts +4 -34
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -37
- package/src/__tests__/managed-store.test.ts +40 -21
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
- package/src/__tests__/memory-recall-log-store.test.ts +2 -6
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
- package/src/__tests__/messaging-send-tool.test.ts +6 -6
- package/src/__tests__/migration-cross-version-compatibility.test.ts +1 -29
- package/src/__tests__/migration-export-http.test.ts +3 -34
- package/src/__tests__/migration-import-commit-http.test.ts +1 -29
- package/src/__tests__/migration-import-preflight-http.test.ts +3 -34
- package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +2 -1
- package/src/__tests__/non-member-access-request.test.ts +2 -6
- package/src/__tests__/notification-guardian-path.test.ts +2 -6
- package/src/__tests__/oauth-apps-routes.test.ts +120 -10
- package/src/__tests__/oauth-cli.test.ts +364 -2
- package/src/__tests__/oauth-connect-orchestrator.test.ts +709 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +2 -1
- package/src/__tests__/oauth-provider-visibility.test.ts +149 -0
- package/src/__tests__/oauth-providers-routes.test.ts +5 -2
- package/src/__tests__/oauth-store.test.ts +0 -5
- package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
- 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 +1071 -0
- package/src/__tests__/outlook-trash.test.ts +77 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
- package/src/__tests__/path-policy.test.ts +2 -17
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/platform-callback-registration.test.ts +7 -11
- package/src/__tests__/playbook-execution.test.ts +76 -80
- package/src/__tests__/playbook-tools.test.ts +5 -7
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- package/src/__tests__/provider-error-scenarios.test.ts +21 -2
- package/src/__tests__/qdrant-manager.test.ts +68 -21
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
- package/src/__tests__/registry.test.ts +2 -2
- package/src/__tests__/require-fresh-approval.test.ts +64 -3
- 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-diagnostics.test.ts +20 -29
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +2 -10
- 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__/scoped-approval-grants.test.ts +2 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
- package/src/__tests__/search-skills-unified.test.ts +421 -0
- package/src/__tests__/secret-allowlist.test.ts +20 -35
- package/src/__tests__/secret-onetime-send.test.ts +2 -0
- package/src/__tests__/send-endpoint-busy.test.ts +2 -6
- package/src/__tests__/sequence-store.test.ts +2 -6
- package/src/__tests__/server-history-render.test.ts +2 -6
- package/src/__tests__/shell-credential-ref.test.ts +0 -5
- 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 +13 -54
- package/src/__tests__/skill-load-inline-command.test.ts +3 -65
- package/src/__tests__/skill-load-inline-includes.test.ts +3 -65
- package/src/__tests__/skill-load-tool.test.ts +3 -67
- package/src/__tests__/skill-memory.test.ts +480 -195
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +23 -50
- package/src/__tests__/slack-channel-config.test.ts +2 -21
- package/src/__tests__/slack-inbound-verification.test.ts +2 -6
- package/src/__tests__/starter-bundle.test.ts +2 -8
- package/src/__tests__/stt-hints.test.ts +7 -2
- package/src/__tests__/system-prompt.test.ts +25 -45
- package/src/__tests__/task-compiler.test.ts +2 -27
- package/src/__tests__/task-management-tools.test.ts +2 -27
- package/src/__tests__/task-memory-cleanup.test.ts +173 -250
- package/src/__tests__/task-runner.test.ts +2 -27
- package/src/__tests__/task-scheduler.test.ts +2 -27
- package/src/__tests__/terminal-tools.test.ts +1 -17
- package/src/__tests__/test-preload.ts +3 -0
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +0 -79
- package/src/__tests__/tool-approval-handler.test.ts +4 -27
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +2 -11
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -25
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +4 -27
- package/src/__tests__/tool-preview-lifecycle.test.ts +0 -20
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +276 -0
- package/src/__tests__/trust-store.test.ts +10 -42
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -30
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +3 -27
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -28
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -28
- package/src/__tests__/trusted-contact-verification.test.ts +2 -28
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -34
- package/src/__tests__/twilio-provider.test.ts +0 -16
- package/src/__tests__/twilio-routes-twiml.test.ts +7 -12
- package/src/__tests__/twilio-routes.test.ts +0 -24
- package/src/__tests__/update-bulletin.test.ts +17 -89
- package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -26
- package/src/__tests__/usage-routes.test.ts +2 -27
- package/src/__tests__/user-reference.test.ts +1 -5
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +4 -34
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +2 -53
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +2 -27
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -30
- package/src/__tests__/voice-session-bridge.test.ts +2 -27
- 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 +4 -29
- package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +2 -2
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +4 -29
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +0 -6
- package/src/__tests__/workspace-policy.test.ts +1 -1
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/attachments.ts +7 -2
- package/src/agent/image-optimize.ts +165 -0
- package/src/agent/loop.ts +1 -15
- package/src/bundler/app-compiler.ts +179 -2
- package/src/bundler/package-resolver.ts +3 -5
- package/src/cli/__tests__/notifications.test.ts +1 -24
- package/src/cli/cli-memory.ts +179 -0
- package/src/cli/commands/avatar.ts +3 -3
- package/src/cli/commands/config.ts +26 -13
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/memory.ts +41 -55
- 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__/providers-update.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +26 -6
- package/src/cli/commands/oauth/mode.ts +7 -0
- package/src/cli/commands/oauth/providers.ts +49 -42
- package/src/cli/commands/oauth/shared.ts +39 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +3 -49
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +3 -49
- package/src/cli/commands/platform/__tests__/status.test.ts +5 -55
- package/src/cli/commands/platform/index.ts +16 -16
- package/src/cli/commands/skills.ts +88 -16
- package/src/cli/commands/trust.ts +2 -2
- package/src/cli/lib/daemon-credential-client.ts +2 -3
- package/src/config/bundled-skills/acp/TOOLS.json +1 -1
- package/src/config/bundled-skills/computer-use/TOOLS.json +7 -7
- 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 +2 -10
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
- package/src/config/bundled-skills/messaging/SKILL.md +26 -19
- 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/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/slack/SKILL.md +1 -7
- package/src/config/bundled-tool-registry.ts +56 -4
- package/src/config/env-registry.ts +15 -8
- package/src/config/feature-flag-registry.json +29 -116
- package/src/config/loader.ts +4 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +8 -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 +32 -9
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/process-manager.ts +3 -1
- package/src/daemon/config-watcher.ts +51 -0
- package/src/daemon/context-overflow-reducer.ts +46 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +123 -82
- package/src/daemon/conversation-agent-loop.ts +99 -63
- package/src/daemon/conversation-error.ts +31 -8
- package/src/daemon/conversation-lifecycle.ts +33 -0
- package/src/daemon/conversation-media-retry.ts +85 -7
- package/src/daemon/conversation-notifiers.ts +4 -1
- package/src/daemon/conversation-process.ts +1 -0
- package/src/daemon/conversation-runtime-assembly.ts +5 -0
- package/src/daemon/conversation-usage.ts +1 -0
- package/src/daemon/conversation.ts +41 -2
- package/src/daemon/daemon-control.ts +8 -2
- package/src/daemon/handlers/shared.ts +22 -12
- package/src/daemon/handlers/skills.ts +423 -201
- package/src/daemon/lifecycle.ts +52 -4
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +5 -1
- package/src/daemon/message-types/messages.ts +3 -1
- package/src/daemon/message-types/skills.ts +97 -36
- package/src/daemon/providers-setup.ts +7 -0
- package/src/daemon/server.ts +35 -22
- package/src/daemon/tool-side-effects.ts +27 -5
- package/src/events/domain-events.ts +1 -2
- package/src/heartbeat/heartbeat-service.ts +1 -0
- 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/memory/admin.ts +11 -45
- package/src/memory/conversation-bootstrap.ts +2 -0
- package/src/memory/conversation-crud.ts +242 -348
- package/src/memory/conversation-group-migration.ts +157 -0
- package/src/memory/conversation-queries.ts +4 -2
- package/src/memory/db-init.ts +39 -3
- 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 +512 -0
- package/src/memory/graph/capability-seed.ts +297 -0
- package/src/memory/graph/consolidation.ts +691 -0
- package/src/memory/graph/conversation-graph-memory.ts +630 -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 +69 -0
- package/src/memory/graph/extraction.test.ts +936 -0
- package/src/memory/graph/extraction.ts +1254 -0
- package/src/memory/graph/graph-search.ts +266 -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 +439 -0
- package/src/memory/graph/inspect.ts +534 -0
- package/src/memory/graph/narrative.ts +267 -0
- package/src/memory/graph/pattern-scan.ts +269 -0
- package/src/memory/graph/retriever.ts +1008 -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 +1050 -0
- package/src/memory/graph/store.ts +699 -0
- package/src/memory/graph/tool-handlers.ts +426 -0
- package/src/memory/graph/tools.ts +141 -0
- package/src/memory/graph/triggers.test.ts +487 -0
- package/src/memory/graph/triggers.ts +223 -0
- package/src/memory/graph/types.ts +271 -0
- package/src/memory/group-crud.ts +191 -0
- package/src/memory/indexer.ts +37 -19
- package/src/memory/job-handlers/cleanup.ts +0 -53
- package/src/memory/job-handlers/conversation-starters.ts +91 -53
- package/src/memory/job-handlers/embedding.test.ts +3 -27
- 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 +50 -70
- package/src/memory/jobs-worker.ts +147 -112
- package/src/memory/llm-usage-store.ts +35 -2
- package/src/memory/message-content.ts +1 -0
- package/src/memory/migrations/201-oauth-providers-feature-flag.ts +11 -0
- package/src/memory/migrations/202-drop-callback-transport-column.ts +13 -0
- package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
- package/src/memory/migrations/203-drop-memory-items-tables.ts +23 -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/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/qdrant-manager.ts +26 -5
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-graph.ts +139 -0
- package/src/memory/schema/oauth.ts +1 -1
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/slack-thread-store.ts +17 -0
- package/src/memory/task-memory-cleanup.ts +28 -50
- package/src/messaging/providers/outlook/adapter.ts +200 -0
- package/src/messaging/providers/outlook/client.ts +610 -0
- package/src/messaging/providers/outlook/types.ts +201 -0
- package/src/notifications/adapters/macos.ts +1 -0
- package/src/notifications/adapters/slack.ts +1 -1
- package/src/notifications/copy-composer.ts +9 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +1 -1
- package/src/oauth/connect-orchestrator.ts +10 -3
- package/src/oauth/oauth-store.ts +10 -11
- package/src/oauth/provider-serializer.ts +3 -0
- package/src/oauth/provider-visibility.ts +16 -0
- package/src/oauth/seed-providers.ts +50 -17
- package/src/permissions/checker.ts +62 -9
- package/src/permissions/defaults.ts +4 -4
- package/src/permissions/types.ts +2 -4
- package/src/permissions/workspace-policy.ts +1 -1
- package/src/playbooks/playbook-compiler.ts +19 -18
- package/src/playbooks/types.ts +4 -3
- package/src/prompts/system-prompt.ts +6 -93
- package/src/prompts/templates/UPDATES.md +6 -0
- package/src/providers/anthropic/client.ts +47 -19
- 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/__tests__/credential-service.test.ts +1 -27
- package/src/runtime/auth/__tests__/token-service.test.ts +1 -25
- package/src/runtime/auth/route-policy.ts +7 -4
- package/src/runtime/guardian-reply-router.ts +10 -2
- package/src/runtime/http-server.ts +23 -3
- package/src/runtime/middleware/auth.ts +20 -0
- package/src/runtime/routes/attachment-routes.test.ts +106 -0
- package/src/runtime/routes/attachment-routes.ts +106 -16
- package/src/runtime/routes/brain-graph-routes.ts +21 -22
- package/src/runtime/routes/btw-routes.ts +8 -0
- package/src/runtime/routes/conversation-management-routes.ts +2 -0
- package/src/runtime/routes/conversation-query-routes.ts +2 -58
- 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/inbound-message-handler.ts +19 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +43 -2
- 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/memory-item-routes.test.ts +2 -31
- package/src/runtime/routes/memory-item-routes.ts +385 -341
- package/src/runtime/routes/oauth-apps.ts +18 -1
- package/src/runtime/routes/oauth-providers.ts +13 -1
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/settings-routes.ts +1 -0
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/usage-routes.ts +19 -2
- package/src/runtime/routes/work-items-routes.test.ts +2 -27
- package/src/runtime/routes/workspace-routes.test.ts +3 -27
- package/src/schedule/scheduler.ts +8 -1
- package/src/security/oauth2.ts +1 -1
- package/src/security/secret-allowlist.ts +4 -4
- 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 +15 -14
- package/src/skills/clawhub.ts +134 -154
- package/src/skills/install-meta.ts +208 -0
- package/src/skills/managed-store.ts +27 -16
- package/src/skills/skill-memory.ts +210 -96
- package/src/skills/skillssh-registry.ts +19 -17
- package/src/tasks/task-runner.ts +3 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
- package/src/tools/browser/runtime-check.ts +3 -1
- package/src/tools/memory/register.ts +63 -46
- package/src/tools/permission-checker.ts +7 -19
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- package/src/tools/skills/skill-script-runner.ts +1 -1
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/tool-manifest.ts +3 -3
- package/src/util/browser.ts +25 -10
- package/src/util/bun-runtime.ts +172 -0
- package/src/util/device-id.ts +3 -65
- package/src/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- package/src/workspace/git-service.ts +27 -6
- 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/registry.ts +6 -0
- 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/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 -741
- package/src/memory/job-handlers/extraction.ts +0 -40
- package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -383
- 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 -1590
- package/src/memory/retriever.ts +0 -1323
- package/src/memory/search/formatting.test.ts +0 -140
- package/src/memory/search/formatting.ts +0 -262
- package/src/memory/search/mmr.ts +0 -136
- 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 -156
- package/src/tools/memory/definitions.ts +0 -69
- package/src/tools/memory/handlers.test.ts +0 -590
- package/src/tools/memory/handlers.ts +0 -434
|
@@ -253,7 +253,10 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
253
253
|
);
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
let body: {
|
|
256
|
+
let body: {
|
|
257
|
+
scopes?: string[];
|
|
258
|
+
callback_transport?: "loopback" | "gateway";
|
|
259
|
+
} = {};
|
|
257
260
|
try {
|
|
258
261
|
const text = await req.text();
|
|
259
262
|
if (text) {
|
|
@@ -263,6 +266,19 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
263
266
|
// No body or invalid JSON — use defaults
|
|
264
267
|
}
|
|
265
268
|
|
|
269
|
+
// Validate callback_transport if present
|
|
270
|
+
if (
|
|
271
|
+
body.callback_transport !== undefined &&
|
|
272
|
+
body.callback_transport !== "loopback" &&
|
|
273
|
+
body.callback_transport !== "gateway"
|
|
274
|
+
) {
|
|
275
|
+
return httpError(
|
|
276
|
+
"BAD_REQUEST",
|
|
277
|
+
'callback_transport must be "loopback" or "gateway"',
|
|
278
|
+
400,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
266
282
|
const clientSecret = await getAppClientSecret(app);
|
|
267
283
|
|
|
268
284
|
const result = await orchestrateOAuthConnect({
|
|
@@ -270,6 +286,7 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
270
286
|
clientId: app.clientId,
|
|
271
287
|
clientSecret,
|
|
272
288
|
requestedScopes: body.scopes,
|
|
289
|
+
callbackTransport: body.callback_transport ?? "loopback",
|
|
273
290
|
isInteractive: false,
|
|
274
291
|
});
|
|
275
292
|
|
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
* runtime auth middleware.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { loadConfig } from "../../config/loader.js";
|
|
9
10
|
import { getProvider, listProviders } from "../../oauth/oauth-store.js";
|
|
10
11
|
import { serializeProviderSummary } from "../../oauth/provider-serializer.js";
|
|
12
|
+
import { isProviderVisible } from "../../oauth/provider-visibility.js";
|
|
11
13
|
import { httpError } from "../http-errors.js";
|
|
12
14
|
import type { RouteDefinition } from "../http-router.js";
|
|
13
15
|
|
|
@@ -22,7 +24,9 @@ export function oauthProvidersRouteDefinitions(): RouteDefinition[] {
|
|
|
22
24
|
method: "GET",
|
|
23
25
|
handler: ({ url }) => {
|
|
24
26
|
const rows = listProviders();
|
|
25
|
-
|
|
27
|
+
const config = loadConfig();
|
|
28
|
+
const visibleRows = rows.filter((r) => isProviderVisible(r, config));
|
|
29
|
+
let serialized = visibleRows
|
|
26
30
|
.map((row) => serializeProviderSummary(row))
|
|
27
31
|
.filter((s): s is NonNullable<typeof s> => s !== null);
|
|
28
32
|
|
|
@@ -53,6 +57,14 @@ export function oauthProvidersRouteDefinitions(): RouteDefinition[] {
|
|
|
53
57
|
);
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
if (!isProviderVisible(row, loadConfig())) {
|
|
61
|
+
return httpError(
|
|
62
|
+
"NOT_FOUND",
|
|
63
|
+
`No OAuth provider registered for "${params.providerKey}"`,
|
|
64
|
+
404,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
56
68
|
return Response.json({ provider: serializeProviderSummary(row) });
|
|
57
69
|
},
|
|
58
70
|
},
|
|
@@ -229,6 +229,7 @@ async function handleRunScheduleNow(
|
|
|
229
229
|
);
|
|
230
230
|
const fallbackConversation = bootstrapConversation({
|
|
231
231
|
source: "schedule",
|
|
232
|
+
groupId: "system:scheduled",
|
|
232
233
|
origin: "schedule",
|
|
233
234
|
systemHint: `Schedule (manual): ${schedule.name}`,
|
|
234
235
|
});
|
|
@@ -241,6 +242,7 @@ async function handleRunScheduleNow(
|
|
|
241
242
|
// Regular message-based schedule
|
|
242
243
|
const conversation = bootstrapConversation({
|
|
243
244
|
source: "schedule",
|
|
245
|
+
groupId: "system:scheduled",
|
|
244
246
|
origin: "schedule",
|
|
245
247
|
systemHint: `Schedule (manual): ${schedule.name}`,
|
|
246
248
|
});
|
|
@@ -39,6 +39,85 @@ export interface SkillRouteDeps {
|
|
|
39
39
|
getSkillContext: () => SkillOperationContext;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
const slimSkillBase = {
|
|
43
|
+
id: z.string(),
|
|
44
|
+
name: z.string(),
|
|
45
|
+
description: z.string(),
|
|
46
|
+
emoji: z.string().optional(),
|
|
47
|
+
kind: z.enum(["bundled", "installed", "catalog"]),
|
|
48
|
+
status: z.enum(["enabled", "disabled", "available"]),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const slimSkillSchema = z.discriminatedUnion("origin", [
|
|
52
|
+
z.object({ ...slimSkillBase, origin: z.literal("vellum") }),
|
|
53
|
+
z.object({
|
|
54
|
+
...slimSkillBase,
|
|
55
|
+
origin: z.literal("clawhub"),
|
|
56
|
+
slug: z.string(),
|
|
57
|
+
author: z.string(),
|
|
58
|
+
stars: z.number(),
|
|
59
|
+
installs: z.number(),
|
|
60
|
+
reports: z.number(),
|
|
61
|
+
publishedAt: z.string().optional(),
|
|
62
|
+
}),
|
|
63
|
+
z.object({
|
|
64
|
+
...slimSkillBase,
|
|
65
|
+
origin: z.literal("skillssh"),
|
|
66
|
+
slug: z.string(),
|
|
67
|
+
sourceRepo: z.string(),
|
|
68
|
+
installs: z.number(),
|
|
69
|
+
}),
|
|
70
|
+
z.object({ ...slimSkillBase, origin: z.literal("custom") }),
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
const skillDetailSchema = z.discriminatedUnion("origin", [
|
|
74
|
+
z.object({ ...slimSkillBase, origin: z.literal("vellum") }),
|
|
75
|
+
z.object({
|
|
76
|
+
...slimSkillBase,
|
|
77
|
+
origin: z.literal("clawhub"),
|
|
78
|
+
slug: z.string(),
|
|
79
|
+
author: z.string(),
|
|
80
|
+
stars: z.number(),
|
|
81
|
+
installs: z.number(),
|
|
82
|
+
reports: z.number(),
|
|
83
|
+
publishedAt: z.string().optional(),
|
|
84
|
+
owner: z
|
|
85
|
+
.object({
|
|
86
|
+
handle: z.string(),
|
|
87
|
+
displayName: z.string(),
|
|
88
|
+
image: z.string().optional(),
|
|
89
|
+
})
|
|
90
|
+
.nullable()
|
|
91
|
+
.optional(),
|
|
92
|
+
stats: z
|
|
93
|
+
.object({
|
|
94
|
+
stars: z.number(),
|
|
95
|
+
installs: z.number(),
|
|
96
|
+
downloads: z.number(),
|
|
97
|
+
versions: z.number(),
|
|
98
|
+
})
|
|
99
|
+
.nullable()
|
|
100
|
+
.optional(),
|
|
101
|
+
latestVersion: z
|
|
102
|
+
.object({
|
|
103
|
+
version: z.string(),
|
|
104
|
+
changelog: z.string().optional(),
|
|
105
|
+
})
|
|
106
|
+
.nullable()
|
|
107
|
+
.optional(),
|
|
108
|
+
createdAt: z.number().nullable().optional(),
|
|
109
|
+
updatedAt: z.number().nullable().optional(),
|
|
110
|
+
}),
|
|
111
|
+
z.object({
|
|
112
|
+
...slimSkillBase,
|
|
113
|
+
origin: z.literal("skillssh"),
|
|
114
|
+
slug: z.string(),
|
|
115
|
+
sourceRepo: z.string(),
|
|
116
|
+
installs: z.number(),
|
|
117
|
+
}),
|
|
118
|
+
z.object({ ...slimSkillBase, origin: z.literal("custom") }),
|
|
119
|
+
]);
|
|
120
|
+
|
|
42
121
|
export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
43
122
|
const ctx = () => deps.getSkillContext();
|
|
44
123
|
|
|
@@ -60,34 +139,7 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
60
139
|
},
|
|
61
140
|
],
|
|
62
141
|
responseBody: z.object({
|
|
63
|
-
skills: z
|
|
64
|
-
.array(
|
|
65
|
-
z.object({
|
|
66
|
-
id: z.string(),
|
|
67
|
-
name: z.string(),
|
|
68
|
-
description: z.string(),
|
|
69
|
-
emoji: z.string().optional(),
|
|
70
|
-
homepage: z.string().optional(),
|
|
71
|
-
source: z.enum([
|
|
72
|
-
"bundled",
|
|
73
|
-
"managed",
|
|
74
|
-
"workspace",
|
|
75
|
-
"clawhub",
|
|
76
|
-
"extra",
|
|
77
|
-
"catalog",
|
|
78
|
-
]),
|
|
79
|
-
state: z.enum(["enabled", "disabled"]),
|
|
80
|
-
installStatus: z.enum(["bundled", "installed", "available"]),
|
|
81
|
-
updateAvailable: z.boolean(),
|
|
82
|
-
provenance: z.object({
|
|
83
|
-
kind: z.enum(["first-party", "third-party", "local"]),
|
|
84
|
-
provider: z.string().optional(),
|
|
85
|
-
originId: z.string().optional(),
|
|
86
|
-
sourceUrl: z.string().optional(),
|
|
87
|
-
}),
|
|
88
|
-
}),
|
|
89
|
-
)
|
|
90
|
-
.describe("Skill objects"),
|
|
142
|
+
skills: z.array(slimSkillSchema).describe("Skill objects"),
|
|
91
143
|
}),
|
|
92
144
|
handler: async ({ url }) => {
|
|
93
145
|
const include = url.searchParams.get("include");
|
|
@@ -201,16 +253,23 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
201
253
|
url: z.string().describe("Skill URL"),
|
|
202
254
|
spec: z.string().describe("Skill spec"),
|
|
203
255
|
version: z.string(),
|
|
256
|
+
origin: z
|
|
257
|
+
.enum(["clawhub", "skillssh"])
|
|
258
|
+
.optional()
|
|
259
|
+
.describe(
|
|
260
|
+
"Which registry to install from. When omitted, the install flow auto-detects based on slug format.",
|
|
261
|
+
),
|
|
204
262
|
}),
|
|
205
263
|
responseBody: z.object({
|
|
206
264
|
ok: z.boolean(),
|
|
207
265
|
}),
|
|
208
|
-
handler: async ({ req }) => {
|
|
266
|
+
handler: async ({ req, authContext }) => {
|
|
209
267
|
const body = (await req.json()) as {
|
|
210
268
|
slug?: string;
|
|
211
269
|
url?: string;
|
|
212
270
|
spec?: string;
|
|
213
271
|
version?: string;
|
|
272
|
+
origin?: "clawhub" | "skillssh";
|
|
214
273
|
};
|
|
215
274
|
const slug = body.slug ?? body.url ?? body.spec;
|
|
216
275
|
if (!slug || typeof slug !== "string") {
|
|
@@ -220,8 +279,9 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
220
279
|
400,
|
|
221
280
|
);
|
|
222
281
|
}
|
|
282
|
+
const contactId = authContext.actorPrincipalId ?? undefined;
|
|
223
283
|
const result = await installSkill(
|
|
224
|
-
{ slug, version: body.version },
|
|
284
|
+
{ slug, version: body.version, origin: body.origin, contactId },
|
|
225
285
|
ctx(),
|
|
226
286
|
);
|
|
227
287
|
if (!result.success) {
|
|
@@ -265,7 +325,9 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
265
325
|
},
|
|
266
326
|
],
|
|
267
327
|
responseBody: z.object({
|
|
268
|
-
|
|
328
|
+
skills: z
|
|
329
|
+
.array(slimSkillSchema)
|
|
330
|
+
.describe("Skill objects matching the search query"),
|
|
269
331
|
}),
|
|
270
332
|
handler: async ({ url }) => {
|
|
271
333
|
const query = url.searchParams.get("q") ?? "";
|
|
@@ -276,7 +338,7 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
276
338
|
if (!result.success) {
|
|
277
339
|
return httpError("INTERNAL_ERROR", result.error, 500);
|
|
278
340
|
}
|
|
279
|
-
return Response.json({
|
|
341
|
+
return Response.json({ skills: result.skills });
|
|
280
342
|
},
|
|
281
343
|
},
|
|
282
344
|
|
|
@@ -323,7 +385,7 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
323
385
|
responseBody: z.object({
|
|
324
386
|
ok: z.boolean(),
|
|
325
387
|
}),
|
|
326
|
-
handler: async ({ req }) => {
|
|
388
|
+
handler: async ({ req, authContext }) => {
|
|
327
389
|
const body = (await req.json()) as CreateSkillParams;
|
|
328
390
|
if (
|
|
329
391
|
!body.skillId ||
|
|
@@ -337,7 +399,8 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
337
399
|
400,
|
|
338
400
|
);
|
|
339
401
|
}
|
|
340
|
-
const
|
|
402
|
+
const contactId = authContext.actorPrincipalId ?? undefined;
|
|
403
|
+
const result = await createSkill({ ...body, contactId }, ctx());
|
|
341
404
|
if (!result.success) {
|
|
342
405
|
return httpError("INTERNAL_ERROR", result.error, 500);
|
|
343
406
|
}
|
|
@@ -395,10 +458,13 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
395
458
|
method: "GET",
|
|
396
459
|
policyKey: "skills",
|
|
397
460
|
summary: "Get skill",
|
|
398
|
-
description: "Return a single skill by ID.",
|
|
461
|
+
description: "Return a single skill by ID with enriched detail fields.",
|
|
399
462
|
tags: ["skills"],
|
|
400
|
-
|
|
401
|
-
|
|
463
|
+
responseBody: z.object({
|
|
464
|
+
skill: skillDetailSchema.describe("Skill detail object"),
|
|
465
|
+
}),
|
|
466
|
+
handler: async ({ params }) => {
|
|
467
|
+
const result = await getSkill(params.id, ctx());
|
|
402
468
|
if ("error" in result) {
|
|
403
469
|
if (result.status === 404) {
|
|
404
470
|
return httpError("NOT_FOUND", result.error, 404);
|
|
@@ -11,6 +11,7 @@ import { z } from "zod";
|
|
|
11
11
|
import {
|
|
12
12
|
getUsageDayBuckets,
|
|
13
13
|
getUsageGroupBreakdown,
|
|
14
|
+
getUsageHourBuckets,
|
|
14
15
|
getUsageTotals,
|
|
15
16
|
} from "../../memory/llm-usage-store.js";
|
|
16
17
|
import { httpError } from "../http-errors.js";
|
|
@@ -104,14 +105,30 @@ export function usageRouteDefinitions(): RouteDefinition[] {
|
|
|
104
105
|
schema: { type: "integer" },
|
|
105
106
|
description: "End epoch millis (required)",
|
|
106
107
|
},
|
|
108
|
+
{
|
|
109
|
+
name: "granularity",
|
|
110
|
+
schema: { type: "string", enum: ["daily", "hourly"] },
|
|
111
|
+
description: 'Bucket granularity: "daily" (default) or "hourly"',
|
|
112
|
+
},
|
|
107
113
|
],
|
|
108
114
|
responseBody: z.object({
|
|
109
|
-
buckets: z.array(z.unknown()).describe("
|
|
115
|
+
buckets: z.array(z.unknown()).describe("Usage bucket objects"),
|
|
110
116
|
}),
|
|
111
117
|
handler: ({ url }) => {
|
|
112
118
|
const range = parseTimeRange(url);
|
|
113
119
|
if (range instanceof Response) return range;
|
|
114
|
-
const
|
|
120
|
+
const granularity = url.searchParams.get("granularity") ?? "daily";
|
|
121
|
+
if (granularity !== "daily" && granularity !== "hourly") {
|
|
122
|
+
return httpError(
|
|
123
|
+
"BAD_REQUEST",
|
|
124
|
+
`Invalid "granularity" value: "${granularity}". Must be one of: daily, hourly`,
|
|
125
|
+
400,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
const buckets =
|
|
129
|
+
granularity === "hourly"
|
|
130
|
+
? getUsageHourBuckets(range)
|
|
131
|
+
: getUsageDayBuckets(range);
|
|
115
132
|
return Response.json({ buckets });
|
|
116
133
|
},
|
|
117
134
|
},
|
|
@@ -5,23 +5,7 @@
|
|
|
5
5
|
* item falls back to the task-level required tools instead of silently
|
|
6
6
|
* skipping permission checks.
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
9
|
-
import { tmpdir } from "node:os";
|
|
10
|
-
import { join } from "node:path";
|
|
11
|
-
import { afterAll, describe, expect, mock, test } from "bun:test";
|
|
12
|
-
|
|
13
|
-
const testDir = mkdtempSync(join(tmpdir(), "work-items-routes-test-"));
|
|
14
|
-
|
|
15
|
-
mock.module("../../util/platform.js", () => ({
|
|
16
|
-
getDataDir: () => testDir,
|
|
17
|
-
isMacOS: () => process.platform === "darwin",
|
|
18
|
-
isLinux: () => process.platform === "linux",
|
|
19
|
-
isWindows: () => process.platform === "win32",
|
|
20
|
-
getPidPath: () => join(testDir, "test.pid"),
|
|
21
|
-
getDbPath: () => join(testDir, "test.db"),
|
|
22
|
-
getLogPath: () => join(testDir, "test.log"),
|
|
23
|
-
ensureDataDir: () => {},
|
|
24
|
-
}));
|
|
8
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
25
9
|
|
|
26
10
|
mock.module("../../util/logger.js", () => ({
|
|
27
11
|
getLogger: () =>
|
|
@@ -35,7 +19,7 @@ mock.module("../../permissions/checker.js", () => ({
|
|
|
35
19
|
classifyRisk: async () => "high",
|
|
36
20
|
}));
|
|
37
21
|
|
|
38
|
-
import { initializeDb
|
|
22
|
+
import { initializeDb } from "../../memory/db.js";
|
|
39
23
|
import { createTask } from "../../tasks/task-store.js";
|
|
40
24
|
import { createWorkItem } from "../../work-items/work-item-store.js";
|
|
41
25
|
import type { RouteContext } from "../http-router.js";
|
|
@@ -46,15 +30,6 @@ import {
|
|
|
46
30
|
|
|
47
31
|
initializeDb();
|
|
48
32
|
|
|
49
|
-
afterAll(() => {
|
|
50
|
-
resetDb();
|
|
51
|
-
try {
|
|
52
|
-
rmSync(testDir, { recursive: true });
|
|
53
|
-
} catch {
|
|
54
|
-
/* best effort */
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
|
|
58
33
|
describe("empty required_tools snapshot bypass", () => {
|
|
59
34
|
test("falls back to task required tools when snapshot requiredTools is empty", async () => {
|
|
60
35
|
const task = createTask({
|
|
@@ -4,37 +4,17 @@
|
|
|
4
4
|
* Covers path resolution (traversal prevention), MIME type detection,
|
|
5
5
|
* directory listing, file metadata, and raw content serving with range support.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
8
|
-
existsSync,
|
|
9
|
-
mkdirSync,
|
|
10
|
-
mkdtempSync,
|
|
11
|
-
readFileSync,
|
|
12
|
-
realpathSync,
|
|
13
|
-
rmSync,
|
|
14
|
-
writeFileSync,
|
|
15
|
-
} from "node:fs";
|
|
16
|
-
import { tmpdir } from "node:os";
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
8
|
import { join } from "node:path";
|
|
18
|
-
import {
|
|
9
|
+
import { beforeAll, describe, expect, test } from "bun:test";
|
|
19
10
|
|
|
20
11
|
// ---------------------------------------------------------------------------
|
|
21
12
|
// Create a temp workspace directory for isolation
|
|
22
13
|
// ---------------------------------------------------------------------------
|
|
23
14
|
|
|
24
|
-
const testWorkspaceDir =
|
|
25
|
-
mkdtempSync(join(tmpdir(), "workspace-routes-test-")),
|
|
26
|
-
);
|
|
15
|
+
const testWorkspaceDir = process.env.VELLUM_WORKSPACE_DIR!;
|
|
27
16
|
|
|
28
17
|
// Mock platform module so getWorkspaceDir returns our temp dir
|
|
29
|
-
mock.module("../../util/platform.js", () => ({
|
|
30
|
-
getWorkspaceDir: () => testWorkspaceDir,
|
|
31
|
-
getRootDir: () => testWorkspaceDir,
|
|
32
|
-
getDataDir: () => testWorkspaceDir,
|
|
33
|
-
isMacOS: () => process.platform === "darwin",
|
|
34
|
-
isLinux: () => process.platform === "linux",
|
|
35
|
-
isWindows: () => process.platform === "win32",
|
|
36
|
-
}));
|
|
37
|
-
|
|
38
18
|
import { workspaceRouteDefinitions } from "./workspace-routes.js";
|
|
39
19
|
import { isTextMimeType, resolveWorkspacePath } from "./workspace-utils.js";
|
|
40
20
|
|
|
@@ -65,10 +45,6 @@ beforeAll(() => {
|
|
|
65
45
|
writeFileSync(binaryFile, pngSignature);
|
|
66
46
|
});
|
|
67
47
|
|
|
68
|
-
afterAll(() => {
|
|
69
|
-
rmSync(testWorkspaceDir, { recursive: true, force: true });
|
|
70
|
-
});
|
|
71
|
-
|
|
72
48
|
// ---------------------------------------------------------------------------
|
|
73
49
|
// Helpers
|
|
74
50
|
// ---------------------------------------------------------------------------
|
|
@@ -188,7 +188,12 @@ async function runScheduleOnce(
|
|
|
188
188
|
);
|
|
189
189
|
const { runTask } = await import("../tasks/task-runner.js");
|
|
190
190
|
const result = await runTask(
|
|
191
|
-
{
|
|
191
|
+
{
|
|
192
|
+
taskId,
|
|
193
|
+
workingDir: process.cwd(),
|
|
194
|
+
source: "schedule",
|
|
195
|
+
scheduleJobId: job.id,
|
|
196
|
+
},
|
|
192
197
|
processMessage as (
|
|
193
198
|
conversationId: string,
|
|
194
199
|
message: string,
|
|
@@ -237,6 +242,7 @@ async function runScheduleOnce(
|
|
|
237
242
|
const fallbackConversation = bootstrapConversation({
|
|
238
243
|
source: "schedule",
|
|
239
244
|
scheduleJobId: job.id,
|
|
245
|
+
groupId: "system:scheduled",
|
|
240
246
|
origin: "schedule",
|
|
241
247
|
systemHint: `Schedule: ${job.name}`,
|
|
242
248
|
});
|
|
@@ -255,6 +261,7 @@ async function runScheduleOnce(
|
|
|
255
261
|
const conversation = bootstrapConversation({
|
|
256
262
|
source: "schedule",
|
|
257
263
|
scheduleJobId: job.id,
|
|
264
|
+
groupId: "system:scheduled",
|
|
258
265
|
origin: "schedule",
|
|
259
266
|
systemHint: isOneShot ? `Reminder: ${job.name}` : `Schedule: ${job.name}`,
|
|
260
267
|
});
|
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 {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* User-defined allowlist for suppressing secret scanner false positives.
|
|
3
3
|
*
|
|
4
|
-
* Reads `~/.vellum/secret-allowlist.json` (if present) and provides
|
|
4
|
+
* Reads `~/.vellum/workspace/data/secret-allowlist.json` (if present) and provides
|
|
5
5
|
* `isAllowlisted(value)` to check whether a matched value should be
|
|
6
6
|
* suppressed.
|
|
7
7
|
*
|
|
@@ -18,7 +18,7 @@ import { join } from "node:path";
|
|
|
18
18
|
|
|
19
19
|
import { pathExists } from "../util/fs.js";
|
|
20
20
|
import { getLogger } from "../util/logger.js";
|
|
21
|
-
import {
|
|
21
|
+
import { getDataDir } from "../util/platform.js";
|
|
22
22
|
|
|
23
23
|
const log = getLogger("secret-allowlist");
|
|
24
24
|
|
|
@@ -45,7 +45,7 @@ let allowedRegexes: RegExp[] = [];
|
|
|
45
45
|
export function loadAllowlist(): void {
|
|
46
46
|
if (loaded || fileChecked) return;
|
|
47
47
|
|
|
48
|
-
const filePath = join(
|
|
48
|
+
const filePath = join(getDataDir(), "secret-allowlist.json");
|
|
49
49
|
if (!pathExists(filePath)) {
|
|
50
50
|
fileChecked = true;
|
|
51
51
|
return;
|
|
@@ -169,7 +169,7 @@ function validateAllowlist(
|
|
|
169
169
|
* Returns validation errors, or null if the file doesn't exist.
|
|
170
170
|
*/
|
|
171
171
|
export function validateAllowlistFile(): AllowlistValidationError[] | null {
|
|
172
|
-
const filePath = join(
|
|
172
|
+
const filePath = join(getDataDir(), "secret-allowlist.json");
|
|
173
173
|
if (!pathExists(filePath)) return null;
|
|
174
174
|
|
|
175
175
|
const raw = readFileSync(filePath, "utf-8");
|
|
@@ -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;
|
|
@@ -16,6 +16,7 @@ import { gunzipSync } from "node:zlib";
|
|
|
16
16
|
import { getPlatformBaseUrl } from "../config/env.js";
|
|
17
17
|
import { getLogger } from "../util/logger.js";
|
|
18
18
|
import { getWorkspaceSkillsDir, readPlatformToken } from "../util/platform.js";
|
|
19
|
+
import { computeSkillHash, writeInstallMeta } from "./install-meta.js";
|
|
19
20
|
import { deleteSkillCapabilityMemory } from "./skill-memory.js";
|
|
20
21
|
|
|
21
22
|
const log = getLogger("catalog-install");
|
|
@@ -270,6 +271,7 @@ 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,8 @@ export async function autoInstallFromCatalog(
|
|
|
393
392
|
return false;
|
|
394
393
|
}
|
|
395
394
|
|
|
395
|
+
// installSkillLocally handles dependency installation and SKILLS.md indexing.
|
|
396
396
|
await installSkillLocally(skillId, entry, false);
|
|
397
|
+
|
|
397
398
|
return true;
|
|
398
399
|
}
|