@vellumai/assistant 0.5.16 → 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 +1 -1
- package/Dockerfile +0 -3
- package/knip.json +2 -1
- package/openapi.yaml +660 -80
- 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 +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 +25 -3
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
- package/src/__tests__/cli-memory.test.ts +74 -69
- package/src/__tests__/config-schema.test.ts +1 -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 +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-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-usage.test.ts +2 -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 +2 -0
- 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__/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__/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 +2 -6
- package/src/__tests__/managed-store.test.ts +38 -11
- 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__/non-member-access-request.test.ts +2 -6
- 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__/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__/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__/provider-error-scenarios.test.ts +21 -0
- 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 -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__/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-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__/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 +11 -11
- package/src/__tests__/skill-memory.test.ts +140 -98
- 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__/task-compiler.test.ts +2 -6
- package/src/__tests__/task-management-tools.test.ts +2 -6
- package/src/__tests__/task-memory-cleanup.test.ts +173 -229
- package/src/__tests__/task-runner.test.ts +2 -6
- package/src/__tests__/task-scheduler.test.ts +2 -6
- package/src/__tests__/test-preload.ts +3 -0
- package/src/__tests__/tool-approval-handler.test.ts +2 -6
- package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +276 -0
- 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 +2 -6
- 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-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 +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 -2
- package/src/cli/cli-memory.ts +67 -64
- 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__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +11 -6
- 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/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/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 +10 -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/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 +21 -124
- package/src/config/schemas/platform.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 +6 -2
- package/src/credential-execution/process-manager.ts +3 -1
- 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 +96 -61
- 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-runtime-assembly.ts +5 -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 +416 -202
- package/src/daemon/lifecycle.ts +40 -1
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +4 -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 +5 -0
- package/src/daemon/server.ts +11 -2
- package/src/daemon/tool-side-effects.ts +27 -5
- 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 +30 -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.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/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 +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 +4 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-graph.ts +139 -0
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/task-memory-cleanup.ts +28 -50
- 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 +9 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/seed-providers.ts +2 -1
- package/src/permissions/checker.ts +24 -3
- package/src/permissions/defaults.ts +4 -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 +3 -29
- 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/route-policy.ts +7 -0
- package/src/runtime/guardian-reply-router.ts +5 -1
- 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-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/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 -14
- package/src/runtime/routes/memory-item-routes.ts +341 -388
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/work-items-routes.test.ts +2 -6
- package/src/schedule/scheduler.ts +8 -1
- 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 +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 +152 -77
- 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 -1
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- 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/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- 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 -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/daemon/lifecycle.ts
CHANGED
|
@@ -82,7 +82,10 @@ import {
|
|
|
82
82
|
setCesClient,
|
|
83
83
|
setCesReconnect,
|
|
84
84
|
} from "../security/secure-keys.js";
|
|
85
|
-
import {
|
|
85
|
+
import {
|
|
86
|
+
seedCatalogSkillMemories,
|
|
87
|
+
seedUninstalledCatalogSkillMemories,
|
|
88
|
+
} from "../skills/skill-memory.js";
|
|
86
89
|
import { UsageTelemetryReporter } from "../telemetry/usage-telemetry-reporter.js";
|
|
87
90
|
import { getDeviceId } from "../util/device-id.js";
|
|
88
91
|
import { getLogger, initLogger } from "../util/logger.js";
|
|
@@ -650,11 +653,47 @@ export async function runDaemon(): Promise<void> {
|
|
|
650
653
|
log.warn({ err }, "Catalog skill memory seeding failed — continuing");
|
|
651
654
|
}
|
|
652
655
|
|
|
656
|
+
// Seed memories for catalog skills not yet installed so they're
|
|
657
|
+
// discoverable via memory injection and can be auto-installed.
|
|
658
|
+
void seedUninstalledCatalogSkillMemories().catch((err) =>
|
|
659
|
+
log.warn(
|
|
660
|
+
{ err },
|
|
661
|
+
"Uninstalled catalog skill memory seeding failed — continuing",
|
|
662
|
+
),
|
|
663
|
+
);
|
|
664
|
+
|
|
653
665
|
try {
|
|
654
666
|
seedCliCommandMemories();
|
|
655
667
|
} catch (err) {
|
|
656
668
|
log.warn({ err }, "CLI command memory seeding failed — continuing");
|
|
657
669
|
}
|
|
670
|
+
|
|
671
|
+
// Seed capability graph nodes (new memory graph system)
|
|
672
|
+
try {
|
|
673
|
+
const { seedSkillGraphNodes, seedCliGraphNodes } =
|
|
674
|
+
await import("../memory/graph/capability-seed.js");
|
|
675
|
+
seedSkillGraphNodes();
|
|
676
|
+
seedCliGraphNodes();
|
|
677
|
+
} catch (err) {
|
|
678
|
+
log.warn({ err }, "Graph capability seeding failed — continuing");
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// Auto-bootstrap: if the graph has no non-procedural nodes but historical
|
|
682
|
+
// segments exist, enqueue a one-time graph_bootstrap job to populate the
|
|
683
|
+
// graph from conversation history and journal files.
|
|
684
|
+
try {
|
|
685
|
+
const {
|
|
686
|
+
maybeEnqueueGraphBootstrap,
|
|
687
|
+
cleanupStaleItemVectors,
|
|
688
|
+
} = await import("../memory/graph/bootstrap.js");
|
|
689
|
+
maybeEnqueueGraphBootstrap();
|
|
690
|
+
// Fire-and-forget: clean up orphaned Qdrant vectors from dropped memory_items table
|
|
691
|
+
void cleanupStaleItemVectors().catch((err) =>
|
|
692
|
+
log.warn({ err }, "Stale item vector cleanup failed — continuing"),
|
|
693
|
+
);
|
|
694
|
+
} catch (err) {
|
|
695
|
+
log.warn({ err }, "Graph bootstrap check failed — continuing");
|
|
696
|
+
}
|
|
658
697
|
}
|
|
659
698
|
|
|
660
699
|
// Fire-and-forget: Qdrant init runs concurrently with the rest of startup
|
package/src/daemon/main.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
process.title = "vellum-daemon";
|
|
3
3
|
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
|
|
4
7
|
import * as Sentry from "@sentry/node";
|
|
5
8
|
|
|
6
9
|
import { getLogger } from "../util/logger.js";
|
|
10
|
+
import { getDataDir } from "../util/platform.js";
|
|
7
11
|
import { runDaemon } from "./lifecycle.js";
|
|
8
12
|
import { emitDaemonError } from "./startup-error.js";
|
|
9
13
|
|
|
@@ -21,7 +25,7 @@ runDaemon().catch(async (err) => {
|
|
|
21
25
|
}
|
|
22
26
|
console.error("Failed to start assistant:", err);
|
|
23
27
|
console.error(
|
|
24
|
-
|
|
28
|
+
`Troubleshooting: check if another assistant is already running, verify ${join(homedir(), ".vellum")} permissions, and review logs at ${getDataDir()}/logs/`,
|
|
25
29
|
);
|
|
26
30
|
// Emit a structured error line as the last line of stderr so consumers
|
|
27
31
|
// (e.g. the macOS app) can parse it reliably.
|
|
@@ -264,8 +264,10 @@ export interface HistoryResponseToolCall {
|
|
|
264
264
|
input: Record<string, unknown>;
|
|
265
265
|
result?: string;
|
|
266
266
|
isError?: boolean;
|
|
267
|
-
/** Base64-encoded image data from tool contentBlocks (e.g. browser_screenshot). */
|
|
267
|
+
/** Base64-encoded image data from tool contentBlocks (e.g. browser_screenshot). @deprecated Use imageDataList. */
|
|
268
268
|
imageData?: string;
|
|
269
|
+
/** Base64-encoded image data from tool contentBlocks (e.g. browser_screenshot, image generation). */
|
|
270
|
+
imageDataList?: string[];
|
|
269
271
|
/** Unix ms when the tool started executing. */
|
|
270
272
|
startedAt?: number;
|
|
271
273
|
/** Unix ms when the tool completed. */
|
|
@@ -370,6 +372,7 @@ export interface ContextCompacted {
|
|
|
370
372
|
export type ConversationErrorCode =
|
|
371
373
|
| "PROVIDER_NETWORK"
|
|
372
374
|
| "PROVIDER_RATE_LIMIT"
|
|
375
|
+
| "PROVIDER_OVERLOADED"
|
|
373
376
|
| "PROVIDER_API"
|
|
374
377
|
| "PROVIDER_BILLING"
|
|
375
378
|
| "PROVIDER_ORDERING"
|
|
@@ -124,8 +124,10 @@ export interface ToolResult {
|
|
|
124
124
|
};
|
|
125
125
|
status?: string;
|
|
126
126
|
conversationId?: string;
|
|
127
|
-
/** Base64-encoded image data extracted from contentBlocks (e.g. browser_screenshot). */
|
|
127
|
+
/** Base64-encoded image data extracted from contentBlocks (e.g. browser_screenshot). @deprecated Use imageDataList. */
|
|
128
128
|
imageData?: string;
|
|
129
|
+
/** Base64-encoded image data extracted from contentBlocks (e.g. browser_screenshot, image generation). */
|
|
130
|
+
imageDataList?: string[];
|
|
129
131
|
/** The tool_use block ID for client-side correlation. */
|
|
130
132
|
toolUseId?: string;
|
|
131
133
|
}
|
|
@@ -76,33 +76,50 @@ export interface SkillsCreateRequest {
|
|
|
76
76
|
|
|
77
77
|
// === Server → Client ===
|
|
78
78
|
|
|
79
|
+
/** Fields shared by all skill origins. */
|
|
80
|
+
interface SlimSkillBase {
|
|
81
|
+
id: string;
|
|
82
|
+
name: string;
|
|
83
|
+
description: string;
|
|
84
|
+
emoji?: string;
|
|
85
|
+
kind: "bundled" | "installed" | "catalog";
|
|
86
|
+
status: "enabled" | "disabled" | "available";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface VellumSlimSkill extends SlimSkillBase {
|
|
90
|
+
origin: "vellum";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface ClawhubSlimSkill extends SlimSkillBase {
|
|
94
|
+
origin: "clawhub";
|
|
95
|
+
slug: string;
|
|
96
|
+
author: string;
|
|
97
|
+
stars: number;
|
|
98
|
+
installs: number;
|
|
99
|
+
reports: number;
|
|
100
|
+
publishedAt?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
interface SkillsshSlimSkill extends SlimSkillBase {
|
|
104
|
+
origin: "skillssh";
|
|
105
|
+
slug: string;
|
|
106
|
+
sourceRepo: string;
|
|
107
|
+
installs: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface CustomSlimSkill extends SlimSkillBase {
|
|
111
|
+
origin: "custom";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export type SlimSkillResponse =
|
|
115
|
+
| VellumSlimSkill
|
|
116
|
+
| ClawhubSlimSkill
|
|
117
|
+
| SkillsshSlimSkill
|
|
118
|
+
| CustomSlimSkill;
|
|
119
|
+
|
|
79
120
|
export interface SkillsListResponse {
|
|
80
121
|
type: "skills_list_response";
|
|
81
|
-
skills:
|
|
82
|
-
id: string;
|
|
83
|
-
name: string;
|
|
84
|
-
description: string;
|
|
85
|
-
emoji?: string;
|
|
86
|
-
homepage?: string;
|
|
87
|
-
source: "bundled" | "managed" | "workspace" | "clawhub" | "extra";
|
|
88
|
-
state: "enabled" | "disabled";
|
|
89
|
-
installedVersion?: string;
|
|
90
|
-
latestVersion?: string;
|
|
91
|
-
updateAvailable: boolean;
|
|
92
|
-
clawhub?: {
|
|
93
|
-
author: string;
|
|
94
|
-
stars: number;
|
|
95
|
-
installs: number;
|
|
96
|
-
reports: number;
|
|
97
|
-
publishedAt: string;
|
|
98
|
-
};
|
|
99
|
-
provenance?: {
|
|
100
|
-
kind: "first-party" | "third-party" | "local";
|
|
101
|
-
provider?: string;
|
|
102
|
-
originId?: string;
|
|
103
|
-
sourceUrl?: string;
|
|
104
|
-
};
|
|
105
|
-
}>;
|
|
122
|
+
skills: SlimSkillResponse[];
|
|
106
123
|
}
|
|
107
124
|
|
|
108
125
|
export interface SkillStateChanged {
|
|
@@ -111,15 +128,7 @@ export interface SkillStateChanged {
|
|
|
111
128
|
state: "enabled" | "disabled" | "installed" | "uninstalled";
|
|
112
129
|
}
|
|
113
130
|
|
|
114
|
-
export interface
|
|
115
|
-
type: "skills_operation_response";
|
|
116
|
-
operation: string;
|
|
117
|
-
success: boolean;
|
|
118
|
-
error?: string;
|
|
119
|
-
data?: unknown;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export interface SkillDetailResponse {
|
|
131
|
+
export interface SkillBodyResponse {
|
|
123
132
|
type: "skill_detail_response";
|
|
124
133
|
skillId: string;
|
|
125
134
|
body: string;
|
|
@@ -127,6 +136,59 @@ export interface SkillDetailResponse {
|
|
|
127
136
|
error?: string;
|
|
128
137
|
}
|
|
129
138
|
|
|
139
|
+
// ─── Detail endpoint response (HTTP API) ──────────────────────────────────
|
|
140
|
+
|
|
141
|
+
interface SkillDetailBase {
|
|
142
|
+
id: string;
|
|
143
|
+
name: string;
|
|
144
|
+
description: string;
|
|
145
|
+
emoji?: string;
|
|
146
|
+
kind: "bundled" | "installed" | "catalog";
|
|
147
|
+
status: "enabled" | "disabled" | "available";
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
interface VellumSkillDetail extends SkillDetailBase {
|
|
151
|
+
origin: "vellum";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
interface ClawhubSkillDetail extends SkillDetailBase {
|
|
155
|
+
origin: "clawhub";
|
|
156
|
+
slug: string;
|
|
157
|
+
author: string;
|
|
158
|
+
stars: number;
|
|
159
|
+
installs: number;
|
|
160
|
+
reports: number;
|
|
161
|
+
publishedAt?: string;
|
|
162
|
+
// Enrichment fields (from clawhubInspect):
|
|
163
|
+
owner?: { handle: string; displayName: string; image?: string } | null;
|
|
164
|
+
stats?: {
|
|
165
|
+
stars: number;
|
|
166
|
+
installs: number;
|
|
167
|
+
downloads: number;
|
|
168
|
+
versions: number;
|
|
169
|
+
} | null;
|
|
170
|
+
latestVersion?: { version: string; changelog?: string } | null;
|
|
171
|
+
createdAt?: number | null;
|
|
172
|
+
updatedAt?: number | null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
interface SkillsshSkillDetail extends SkillDetailBase {
|
|
176
|
+
origin: "skillssh";
|
|
177
|
+
slug: string;
|
|
178
|
+
sourceRepo: string;
|
|
179
|
+
installs: number;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
interface CustomSkillDetail extends SkillDetailBase {
|
|
183
|
+
origin: "custom";
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export type SkillDetailResponse =
|
|
187
|
+
| VellumSkillDetail
|
|
188
|
+
| ClawhubSkillDetail
|
|
189
|
+
| SkillsshSkillDetail
|
|
190
|
+
| CustomSkillDetail;
|
|
191
|
+
|
|
130
192
|
export interface SkillsDraftResponse {
|
|
131
193
|
type: "skills_draft_response";
|
|
132
194
|
success: boolean;
|
|
@@ -181,8 +243,7 @@ export type _SkillsClientMessages =
|
|
|
181
243
|
|
|
182
244
|
export type _SkillsServerMessages =
|
|
183
245
|
| SkillsListResponse
|
|
184
|
-
|
|
|
246
|
+
| SkillBodyResponse
|
|
185
247
|
| SkillStateChanged
|
|
186
|
-
| SkillsOperationResponse
|
|
187
248
|
| SkillsInspectResponse
|
|
188
249
|
| SkillsDraftResponse;
|
|
@@ -25,6 +25,8 @@ import { githubProvider } from "../watcher/providers/github.js";
|
|
|
25
25
|
import { gmailProvider } from "../watcher/providers/gmail.js";
|
|
26
26
|
import { googleCalendarProvider } from "../watcher/providers/google-calendar.js";
|
|
27
27
|
import { linearProvider } from "../watcher/providers/linear.js";
|
|
28
|
+
import { outlookProvider } from "../watcher/providers/outlook.js";
|
|
29
|
+
import { outlookCalendarProvider } from "../watcher/providers/outlook-calendar.js";
|
|
28
30
|
const log = getLogger("lifecycle");
|
|
29
31
|
|
|
30
32
|
export async function initializeProvidersAndTools(
|
|
@@ -135,6 +137,9 @@ export function registerWatcherProviders(): void {
|
|
|
135
137
|
registerWatcherProvider(googleCalendarProvider);
|
|
136
138
|
registerWatcherProvider(githubProvider);
|
|
137
139
|
registerWatcherProvider(linearProvider);
|
|
140
|
+
registerWatcherProvider(outlookProvider);
|
|
141
|
+
registerWatcherProvider(outlookCalendarProvider);
|
|
142
|
+
|
|
138
143
|
initWatcherEngine();
|
|
139
144
|
}
|
|
140
145
|
|
package/src/daemon/server.ts
CHANGED
|
@@ -625,9 +625,18 @@ export class DaemonServer {
|
|
|
625
625
|
if (conversation.isProcessing()) {
|
|
626
626
|
// Hydrate file data now — the queue path won't re-read from
|
|
627
627
|
// the attachment store, so base64 content must be inline.
|
|
628
|
-
for (
|
|
628
|
+
for (let i = resolvedAttachments.length - 1; i >= 0; i--) {
|
|
629
|
+
const att = resolvedAttachments[i];
|
|
629
630
|
if (att.filePath && !att.data) {
|
|
630
|
-
|
|
631
|
+
try {
|
|
632
|
+
att.data = readFileSync(att.filePath).toString("base64");
|
|
633
|
+
} catch (err) {
|
|
634
|
+
log.warn(
|
|
635
|
+
{ err, path: att.filePath },
|
|
636
|
+
"Failed to read queued signal attachment, skipping",
|
|
637
|
+
);
|
|
638
|
+
resolvedAttachments.splice(i, 1);
|
|
639
|
+
}
|
|
631
640
|
}
|
|
632
641
|
}
|
|
633
642
|
const requestId = crypto.randomUUID();
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { compileApp } from "../bundler/app-compiler.js";
|
|
11
11
|
import { generateAppIcon } from "../media/app-icon-generator.js";
|
|
12
12
|
import { getApp, getAppDirPath, isMultifileApp } from "../memory/app-store.js";
|
|
13
|
+
import { findActiveSession } from "../runtime/channel-verification-service.js";
|
|
13
14
|
import { deliverVerificationSlack } from "../runtime/verification-outbound-actions.js";
|
|
14
15
|
import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
|
|
15
16
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
@@ -222,18 +223,39 @@ registerHook("bash", (_name, input, result) => {
|
|
|
222
223
|
type PendingDm = { userId: string; text: string; assistantId: string };
|
|
223
224
|
type Parsed = { _pendingSlackDm?: PendingDm };
|
|
224
225
|
|
|
225
|
-
|
|
226
|
+
// Returns "delivered" when DM was sent, "rejected" when _pendingSlackDm
|
|
227
|
+
// was found but failed validation, or null when the field was absent.
|
|
228
|
+
const dispatch = (parsed: Parsed): "delivered" | "rejected" | null => {
|
|
226
229
|
if (parsed._pendingSlackDm) {
|
|
227
230
|
const { userId, text, assistantId } = parsed._pendingSlackDm;
|
|
231
|
+
|
|
232
|
+
// Validate that an active Slack verification session exists and
|
|
233
|
+
// that the destination matches the userId in the parsed payload.
|
|
234
|
+
const session = findActiveSession("slack");
|
|
235
|
+
if (!session) {
|
|
236
|
+
log.warn(
|
|
237
|
+
{ userId, assistantId },
|
|
238
|
+
"Bash hook: no active Slack verification session — ignoring _pendingSlackDm",
|
|
239
|
+
);
|
|
240
|
+
return "rejected";
|
|
241
|
+
}
|
|
242
|
+
if (session.destinationAddress !== userId) {
|
|
243
|
+
log.warn(
|
|
244
|
+
{ userId, expected: session.destinationAddress, assistantId },
|
|
245
|
+
"Bash hook: Slack DM userId does not match active session destination — ignoring",
|
|
246
|
+
);
|
|
247
|
+
return "rejected";
|
|
248
|
+
}
|
|
249
|
+
|
|
228
250
|
deliverVerificationSlack(userId, text, assistantId);
|
|
229
|
-
return
|
|
251
|
+
return "delivered";
|
|
230
252
|
}
|
|
231
|
-
return
|
|
253
|
+
return null;
|
|
232
254
|
};
|
|
233
255
|
|
|
234
256
|
// Try full content first (handles pretty-printed single-object JSON)
|
|
235
257
|
try {
|
|
236
|
-
if (dispatch(JSON.parse(result.content.trim()) as Parsed)) return;
|
|
258
|
+
if (dispatch(JSON.parse(result.content.trim()) as Parsed) !== null) return;
|
|
237
259
|
} catch {
|
|
238
260
|
// Not a single JSON object — fall back to line-by-line for
|
|
239
261
|
// multi-object output (e.g. cancel + create chained with &&).
|
|
@@ -242,7 +264,7 @@ registerHook("bash", (_name, input, result) => {
|
|
|
242
264
|
const trimmed = line.trim();
|
|
243
265
|
if (!trimmed.startsWith("{")) continue;
|
|
244
266
|
try {
|
|
245
|
-
if (dispatch(JSON.parse(trimmed) as Parsed)) return;
|
|
267
|
+
if (dispatch(JSON.parse(trimmed) as Parsed) === "delivered") return;
|
|
246
268
|
} catch {
|
|
247
269
|
continue;
|
|
248
270
|
}
|
package/src/hooks/cli.ts
CHANGED
|
@@ -20,7 +20,7 @@ export function registerHooksCommand(program: Command): void {
|
|
|
20
20
|
Hooks are user-installed scripts that run in response to assistant lifecycle
|
|
21
21
|
events (e.g. tool invocations, message sends). Each hook is a directory
|
|
22
22
|
containing a hook.json manifest and a script file. Hooks are stored in
|
|
23
|
-
|
|
23
|
+
$VELLUM_WORKSPACE_DIR/hooks/ and must be explicitly enabled after installation.
|
|
24
24
|
|
|
25
25
|
Examples:
|
|
26
26
|
$ assistant hooks list
|
|
@@ -136,7 +136,7 @@ Arguments:
|
|
|
136
136
|
The manifest must have name, script, description, version, and at
|
|
137
137
|
least one valid event.
|
|
138
138
|
|
|
139
|
-
Copies the hook directory into
|
|
139
|
+
Copies the hook directory into $VELLUM_WORKSPACE_DIR/hooks/<name>/ and registers it as
|
|
140
140
|
disabled by default. Run 'assistant hooks enable <name>' to activate.
|
|
141
141
|
|
|
142
142
|
Examples:
|
package/src/hooks/runner.ts
CHANGED
|
@@ -1,42 +1,19 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import {
|
|
3
|
+
import { extname, join } from "node:path";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { ensureBun } from "../util/bun-runtime.js";
|
|
6
6
|
import { getWorkspaceDir } from "../util/platform.js";
|
|
7
7
|
import { getHookSettings } from "./config.js";
|
|
8
8
|
import type { DiscoveredHook, HookEventData } from "./types.js";
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* daemon is a `bun build --compile` binary, `process.execPath` points to the
|
|
14
|
-
* compiled binary itself -- spawning it with `['run', script]` would re-launch
|
|
15
|
-
* the daemon. In that case we locate bun via PATH or at `~/.bun/bin/bun`.
|
|
16
|
-
*/
|
|
17
|
-
function resolveBunPath(): string {
|
|
18
|
-
const execBasename = basename(process.execPath);
|
|
19
|
-
if (execBasename === "bun" || execBasename === "bun.exe") {
|
|
20
|
-
return process.execPath;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Compiled-binary mode -- find a standalone bun runtime.
|
|
24
|
-
const found = Bun.which("bun");
|
|
25
|
-
if (found) return found;
|
|
26
|
-
|
|
27
|
-
const fallback = join(homedir(), ".bun", "bin", "bun");
|
|
28
|
-
if (pathExists(fallback)) return fallback;
|
|
29
|
-
|
|
30
|
-
throw new Error(
|
|
31
|
-
"Cannot find a bun runtime to execute .ts hooks. " +
|
|
32
|
-
"Install bun (https://bun.sh) or ensure it is on your PATH.",
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function getSpawnArgs(scriptPath: string): { command: string; args: string[] } {
|
|
10
|
+
async function getSpawnArgs(
|
|
11
|
+
scriptPath: string,
|
|
12
|
+
): Promise<{ command: string; args: string[] }> {
|
|
37
13
|
const ext = extname(scriptPath);
|
|
38
14
|
if (ext === ".ts") {
|
|
39
|
-
|
|
15
|
+
const bunPath = await ensureBun();
|
|
16
|
+
return { command: bunPath, args: ["run", scriptPath] };
|
|
40
17
|
}
|
|
41
18
|
return { command: scriptPath, args: [] };
|
|
42
19
|
}
|
|
@@ -54,15 +31,15 @@ export async function runHookScript(
|
|
|
54
31
|
): Promise<HookRunResult> {
|
|
55
32
|
const timeoutMs = options?.timeoutMs ?? 5000;
|
|
56
33
|
|
|
34
|
+
let spawnResult: { command: string; args: string[] };
|
|
35
|
+
try {
|
|
36
|
+
spawnResult = await getSpawnArgs(hook.scriptPath);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
return { exitCode: null, stdout: "", stderr: (err as Error).message };
|
|
39
|
+
}
|
|
40
|
+
const { command, args } = spawnResult;
|
|
41
|
+
|
|
57
42
|
return new Promise<HookRunResult>((resolve) => {
|
|
58
|
-
let spawnResult: { command: string; args: string[] };
|
|
59
|
-
try {
|
|
60
|
-
spawnResult = getSpawnArgs(hook.scriptPath);
|
|
61
|
-
} catch (err) {
|
|
62
|
-
resolve({ exitCode: null, stdout: "", stderr: (err as Error).message });
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
const { command, args } = spawnResult;
|
|
66
43
|
const child = spawn(command, args, {
|
|
67
44
|
cwd: hook.dir,
|
|
68
45
|
env: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Platform callback route registration for
|
|
2
|
+
* Platform callback route registration for platform-managed deployments.
|
|
3
3
|
*
|
|
4
|
-
* When the assistant daemon runs
|
|
4
|
+
* When the assistant daemon runs as a platform-managed instance (IS_PLATFORM=true)
|
|
5
5
|
* with a configured VELLUM_PLATFORM_URL and PLATFORM_ASSISTANT_ID, external
|
|
6
6
|
* service callbacks (Twilio webhooks, OAuth redirects, Telegram webhooks, etc.)
|
|
7
7
|
* must route through the platform's gateway proxy instead of hitting the
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* This module registers callback routes with the platform's internal
|
|
11
11
|
* gateway endpoint so the platform knows how to forward inbound provider
|
|
12
|
-
* webhooks to the correct
|
|
12
|
+
* webhooks to the correct platform-managed assistant instance.
|
|
13
13
|
*
|
|
14
14
|
* The platform endpoint is:
|
|
15
15
|
* POST {VELLUM_PLATFORM_URL}/v1/internal/gateway/callback-routes/register/
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
getPlatformBaseUrl,
|
|
24
24
|
getPlatformInternalApiKey,
|
|
25
25
|
} from "../config/env.js";
|
|
26
|
-
import {
|
|
26
|
+
import { getIsPlatform } from "../config/env-registry.js";
|
|
27
27
|
import { credentialKey } from "../security/credential-key.js";
|
|
28
28
|
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
29
29
|
import { getLogger } from "../util/logger.js";
|
|
@@ -31,7 +31,7 @@ import { getLogger } from "../util/logger.js";
|
|
|
31
31
|
const log = getLogger("platform-callback-registration");
|
|
32
32
|
|
|
33
33
|
export interface PlatformCallbackRegistrationContext {
|
|
34
|
-
|
|
34
|
+
isPlatform: boolean;
|
|
35
35
|
platformBaseUrl: string;
|
|
36
36
|
assistantId: string;
|
|
37
37
|
hasInternalApiKey: boolean;
|
|
@@ -42,21 +42,21 @@ export interface PlatformCallbackRegistrationContext {
|
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* Whether the daemon should register callback routes with the platform.
|
|
45
|
-
* True when
|
|
45
|
+
* True when IS_PLATFORM, VELLUM_PLATFORM_URL, and PLATFORM_ASSISTANT_ID
|
|
46
46
|
* are all set. Intentionally does **not** require the managed proxy API key
|
|
47
47
|
* so that callback-only flows (OAuth transport, Telegram/Twilio callback
|
|
48
48
|
* registration) work during partial bootstrap before the key is injected.
|
|
49
49
|
*/
|
|
50
50
|
export function shouldUsePlatformCallbacks(): boolean {
|
|
51
51
|
return (
|
|
52
|
-
|
|
52
|
+
getIsPlatform() &&
|
|
53
53
|
!!getPlatformBaseUrl() &&
|
|
54
54
|
!!getPlatformAssistantId()
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export async function resolvePlatformCallbackRegistrationContext(): Promise<PlatformCallbackRegistrationContext> {
|
|
59
|
-
const
|
|
59
|
+
const platform = getIsPlatform();
|
|
60
60
|
const [storedBaseUrlRaw, storedAssistantIdRaw, storedAssistantApiKeyRaw] =
|
|
61
61
|
await Promise.all([
|
|
62
62
|
getSecureKeyAsync(credentialKey("vellum", "platform_base_url")),
|
|
@@ -80,14 +80,14 @@ export async function resolvePlatformCallbackRegistrationContext(): Promise<Plat
|
|
|
80
80
|
: null;
|
|
81
81
|
|
|
82
82
|
return {
|
|
83
|
-
|
|
83
|
+
isPlatform: platform,
|
|
84
84
|
platformBaseUrl,
|
|
85
85
|
assistantId,
|
|
86
86
|
hasInternalApiKey: internalApiKey.length > 0,
|
|
87
87
|
hasAssistantApiKey: assistantApiKey.length > 0,
|
|
88
88
|
authHeader,
|
|
89
89
|
enabled:
|
|
90
|
-
|
|
90
|
+
platform &&
|
|
91
91
|
platformBaseUrl.length > 0 &&
|
|
92
92
|
assistantId.length > 0 &&
|
|
93
93
|
authHeader !== null,
|
|
@@ -119,7 +119,7 @@ export async function registerCallbackRoute(
|
|
|
119
119
|
const context = await resolvePlatformCallbackRegistrationContext();
|
|
120
120
|
if (!context.enabled || !context.authHeader) {
|
|
121
121
|
throw new Error(
|
|
122
|
-
"Platform callbacks not available — missing
|
|
122
|
+
"Platform callbacks not available — missing platform registration context",
|
|
123
123
|
);
|
|
124
124
|
}
|
|
125
125
|
|
|
@@ -166,7 +166,7 @@ export async function registerCallbackRoute(
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
/**
|
|
169
|
-
* Resolve a callback URL, registering with the platform when
|
|
169
|
+
* Resolve a callback URL, registering with the platform when platform-managed.
|
|
170
170
|
*
|
|
171
171
|
* When platform callbacks are enabled, registers the route and returns the
|
|
172
172
|
* platform's stable callback URL (optionally with query parameters appended).
|
|
@@ -176,7 +176,7 @@ export async function registerCallbackRoute(
|
|
|
176
176
|
* string) rather than an eagerly-evaluated string. This is critical because
|
|
177
177
|
* the direct URL builders (e.g. `getTwilioVoiceWebhookUrl`) call
|
|
178
178
|
* `getPublicBaseUrl()` which throws when no public ingress URL is configured.
|
|
179
|
-
* In
|
|
179
|
+
* In platform-managed environments that rely solely on platform callbacks, the
|
|
180
180
|
* direct URL is never needed — deferring evaluation avoids the throw.
|
|
181
181
|
*
|
|
182
182
|
* @param directUrl - Lazy supplier for the direct callback URL.
|
|
@@ -204,7 +204,7 @@ export async function resolveCallbackUrl(
|
|
|
204
204
|
}
|
|
205
205
|
return url;
|
|
206
206
|
} catch (err) {
|
|
207
|
-
// In managed
|
|
207
|
+
// In platform-managed mode there is no local-ingress fallback and
|
|
208
208
|
// ngrok is not applicable. Surface a clear error so callers (and the
|
|
209
209
|
// user) understand this is a platform-side issue, not a tunnel problem.
|
|
210
210
|
const detail = err instanceof Error ? err.message : String(err);
|