@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
|
@@ -35,7 +35,7 @@ The avatar system supports two modes:
|
|
|
35
35
|
2. Custom image — an externally provided image file placed directly in the
|
|
36
36
|
avatar directory. Custom images are not managed through this CLI.
|
|
37
37
|
|
|
38
|
-
Files are stored in
|
|
38
|
+
Files are stored in $VELLUM_WORKSPACE_DIR/data/avatar/:
|
|
39
39
|
character-traits.json Current trait selection (bodyShape, eyeStyle, color)
|
|
40
40
|
avatar-image.png Rendered PNG of the character
|
|
41
41
|
character-ascii.txt ASCII art representation (best-effort; may not be written)
|
|
@@ -61,7 +61,7 @@ Generates an avatar image using AI based on the provided text description
|
|
|
61
61
|
and saves it as the assistant's avatar PNG. This replaces any existing
|
|
62
62
|
native character avatar — the character traits and ASCII files are removed.
|
|
63
63
|
|
|
64
|
-
On success, writes avatar-image.png to
|
|
64
|
+
On success, writes avatar-image.png to $VELLUM_WORKSPACE_DIR/data/avatar/
|
|
65
65
|
and removes character-traits.json and character-ascii.txt if they exist.
|
|
66
66
|
|
|
67
67
|
Examples:
|
|
@@ -155,7 +155,7 @@ The --color flag sets the body fill color. Valid values:
|
|
|
155
155
|
green, orange, pink, purple, teal, yellow
|
|
156
156
|
|
|
157
157
|
On success, writes character-traits.json and avatar-image.png to
|
|
158
|
-
|
|
158
|
+
$VELLUM_WORKSPACE_DIR/data/avatar/. character-ascii.txt is written on a
|
|
159
159
|
best-effort basis and may be skipped if ASCII rendering fails.
|
|
160
160
|
|
|
161
161
|
Examples:
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { AssistantConfigSchema } from "../../config/schema.js";
|
|
11
11
|
import { getSchemaAtPath } from "../../config/schema-utils.js";
|
|
12
12
|
import { log } from "../logger.js";
|
|
13
|
+
import { requirePlatformConnection } from "./oauth/shared.js";
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Flatten a nested config object into dotted key paths.
|
|
@@ -34,6 +35,9 @@ function flattenConfig(
|
|
|
34
35
|
return result;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
/** Matches config paths like `services.inference.mode`, `services.image-generation.mode`, etc. */
|
|
39
|
+
const SERVICE_MODE_PATH_RE = /^services\.[^.]+\.mode$/;
|
|
40
|
+
|
|
37
41
|
export function registerConfigCommand(program: Command): void {
|
|
38
42
|
const config = program.command("config").description("Manage configuration");
|
|
39
43
|
|
|
@@ -80,19 +84,28 @@ Examples:
|
|
|
80
84
|
$ assistant config set services.inference.provider anthropic
|
|
81
85
|
$ assistant config set calls.enabled true`,
|
|
82
86
|
)
|
|
83
|
-
.action(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
87
|
+
.action(
|
|
88
|
+
async (key: string, value: string, _opts: unknown, cmd: Command) => {
|
|
89
|
+
// Try to parse as JSON for booleans/numbers, fall back to string
|
|
90
|
+
let parsed: unknown = value;
|
|
91
|
+
try {
|
|
92
|
+
parsed = JSON.parse(value);
|
|
93
|
+
} catch {
|
|
94
|
+
// keep as string
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Require platform connection when setting a service mode to "managed"
|
|
98
|
+
if (SERVICE_MODE_PATH_RE.test(key) && parsed === "managed") {
|
|
99
|
+
const connected = await requirePlatformConnection(cmd);
|
|
100
|
+
if (!connected) return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const raw = loadRawConfig();
|
|
104
|
+
setNestedValue(raw, key, parsed);
|
|
105
|
+
saveRawConfig(raw);
|
|
106
|
+
log.info(`Set ${key} = ${JSON.stringify(parsed)}`);
|
|
107
|
+
},
|
|
108
|
+
);
|
|
96
109
|
|
|
97
110
|
config
|
|
98
111
|
.command("get <key>")
|
|
@@ -39,7 +39,7 @@ Diagnostic checks performed:
|
|
|
39
39
|
2. API key configured Checks for a valid provider API key in secure storage
|
|
40
40
|
3. Assistant reachable HTTP health check against the assistant server
|
|
41
41
|
4. Database exists/readable Opens the SQLite database and runs a test query
|
|
42
|
-
5. Directory structure Verifies required
|
|
42
|
+
5. Directory structure Verifies required workspace directories exist
|
|
43
43
|
6. Disk space Ensures at least 100MB free on the data partition
|
|
44
44
|
7. Log file size Warns if the log file exceeds 50MB
|
|
45
45
|
8. Database integrity Runs SQLite PRAGMA integrity_check
|
|
@@ -129,7 +129,7 @@ Examples:
|
|
|
129
129
|
fail("Database exists and readable", `not found at ${dbPath}`);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
// 5.
|
|
132
|
+
// 5. Workspace directory structure
|
|
133
133
|
const protectedDir = getProtectedDir();
|
|
134
134
|
const dataDir = getDataDir();
|
|
135
135
|
const workspaceDir = getWorkspaceDir();
|
|
@@ -36,7 +36,7 @@ Key concepts:
|
|
|
36
36
|
Examples:
|
|
37
37
|
$ assistant memory status
|
|
38
38
|
$ assistant memory query "What is the project deadline?"
|
|
39
|
-
$ assistant memory backfill
|
|
39
|
+
$ assistant memory backfill`
|
|
40
40
|
);
|
|
41
41
|
|
|
42
42
|
memory
|
|
@@ -52,15 +52,13 @@ Fields shown:
|
|
|
52
52
|
degraded mode (e.g. missing embedding backend)
|
|
53
53
|
embedding backend The provider/model pair used for vector embeddings (or "none")
|
|
54
54
|
segments Total conversation segments indexed
|
|
55
|
-
|
|
55
|
+
graph nodes Total memory graph nodes stored
|
|
56
56
|
summaries Total compressed conversation summaries
|
|
57
57
|
embeddings Total vector embeddings computed
|
|
58
|
-
cleanup backlogs Number of superseded items pending cleanup
|
|
59
|
-
cleanup throughput Number of cleanup operations completed in the last 24 hours
|
|
60
58
|
jobs Status of background jobs (backfill, cleanup, rebuild-index)
|
|
61
59
|
|
|
62
60
|
Examples:
|
|
63
|
-
$ assistant memory status
|
|
61
|
+
$ assistant memory status`
|
|
64
62
|
)
|
|
65
63
|
.action(async () => {
|
|
66
64
|
initializeDb();
|
|
@@ -74,15 +72,9 @@ Examples:
|
|
|
74
72
|
log.info("Embedding backend: none");
|
|
75
73
|
}
|
|
76
74
|
log.info(`Segments: ${status.counts.segments.toLocaleString()}`);
|
|
77
|
-
log.info(`
|
|
75
|
+
log.info(`Graph nodes: ${status.counts.graphNodes.toLocaleString()}`);
|
|
78
76
|
log.info(`Summaries: ${status.counts.summaries.toLocaleString()}`);
|
|
79
77
|
log.info(`Embeddings: ${status.counts.embeddings.toLocaleString()}`);
|
|
80
|
-
log.info(
|
|
81
|
-
`Cleanup backlog (superseded items): ${status.cleanup.supersededBacklog.toLocaleString()}`,
|
|
82
|
-
);
|
|
83
|
-
log.info(
|
|
84
|
-
`Cleanup throughput 24h (superseded items): ${status.cleanup.supersededCompleted24h.toLocaleString()}`,
|
|
85
|
-
);
|
|
86
78
|
log.info("Jobs:");
|
|
87
79
|
for (const [key, value] of Object.entries(status.jobs)) {
|
|
88
80
|
log.info(` ${key}: ${value}`);
|
|
@@ -106,7 +98,7 @@ useful after bulk imports or if the incremental state has become inconsistent.
|
|
|
106
98
|
|
|
107
99
|
Examples:
|
|
108
100
|
$ assistant memory backfill
|
|
109
|
-
$ assistant memory backfill --force
|
|
101
|
+
$ assistant memory backfill --force`
|
|
110
102
|
)
|
|
111
103
|
.action((opts: { force?: boolean }) => {
|
|
112
104
|
initializeDb();
|
|
@@ -119,7 +111,7 @@ Examples:
|
|
|
119
111
|
.description("Queue cleanup jobs for stale superseded items")
|
|
120
112
|
.option(
|
|
121
113
|
"--retention-ms <ms>",
|
|
122
|
-
"Optional retention threshold in milliseconds"
|
|
114
|
+
"Optional retention threshold in milliseconds"
|
|
123
115
|
)
|
|
124
116
|
.addHelpText(
|
|
125
117
|
"after",
|
|
@@ -133,19 +125,17 @@ default retention period is used.
|
|
|
133
125
|
|
|
134
126
|
Examples:
|
|
135
127
|
$ assistant memory cleanup
|
|
136
|
-
$ assistant memory cleanup --retention-ms 86400000
|
|
128
|
+
$ assistant memory cleanup --retention-ms 86400000`
|
|
137
129
|
)
|
|
138
130
|
.action((opts: { retentionMs?: string }) => {
|
|
139
131
|
initializeDb();
|
|
140
132
|
const retentionMs = opts.retentionMs
|
|
141
133
|
? Number.parseInt(opts.retentionMs, 10)
|
|
142
134
|
: undefined;
|
|
143
|
-
|
|
144
|
-
Number.isFinite(retentionMs) ? retentionMs : undefined
|
|
145
|
-
);
|
|
146
|
-
log.info(
|
|
147
|
-
`Queued cleanup_stale_superseded_items job: ${jobs.staleSupersededItemsJobId}`,
|
|
135
|
+
requestMemoryCleanup(
|
|
136
|
+
Number.isFinite(retentionMs) ? retentionMs : undefined
|
|
148
137
|
);
|
|
138
|
+
log.info("Memory cleanup requested (legacy items table dropped)");
|
|
149
139
|
});
|
|
150
140
|
|
|
151
141
|
memory
|
|
@@ -156,7 +146,7 @@ Examples:
|
|
|
156
146
|
"after",
|
|
157
147
|
`
|
|
158
148
|
Removes segments shorter than the minimum character threshold from both
|
|
159
|
-
SQLite and Qdrant. Short fragments (e.g. "
|
|
149
|
+
SQLite and Qdrant. Short fragments (e.g. "OK sounds good") burn embedding
|
|
160
150
|
budget, retrieval slots, and injection tokens without adding value.
|
|
161
151
|
|
|
162
152
|
New segments are already filtered at creation time. This command cleans up
|
|
@@ -164,19 +154,21 @@ existing short segments that were stored before the filter was added.
|
|
|
164
154
|
|
|
165
155
|
Examples:
|
|
166
156
|
$ assistant memory cleanup-segments
|
|
167
|
-
$ assistant memory cleanup-segments --dry-run
|
|
157
|
+
$ assistant memory cleanup-segments --dry-run`
|
|
168
158
|
)
|
|
169
159
|
.action(async (opts: { dryRun?: boolean }) => {
|
|
170
160
|
initializeDb();
|
|
171
161
|
const result = await cleanupShortSegments({ dryRun: opts.dryRun });
|
|
172
162
|
if (opts.dryRun) {
|
|
173
163
|
log.info(
|
|
174
|
-
`Dry run: ${result.dryRunCount} short segment(s) would be removed
|
|
164
|
+
`Dry run: ${result.dryRunCount} short segment(s) would be removed.`
|
|
175
165
|
);
|
|
176
166
|
} else {
|
|
177
167
|
log.info(`Removed ${result.removed} short segment(s).`);
|
|
178
168
|
if (result.failed > 0) {
|
|
179
|
-
log.warn(
|
|
169
|
+
log.warn(
|
|
170
|
+
`${result.failed} segment(s) skipped — Qdrant deletion failed. Re-run when Qdrant is available.`
|
|
171
|
+
);
|
|
180
172
|
}
|
|
181
173
|
}
|
|
182
174
|
});
|
|
@@ -184,7 +176,7 @@ Examples:
|
|
|
184
176
|
memory
|
|
185
177
|
.command("query <text>")
|
|
186
178
|
.description(
|
|
187
|
-
"Run a memory recall query and print the injected memory payload"
|
|
179
|
+
"Run a memory recall query and print the injected memory payload"
|
|
188
180
|
)
|
|
189
181
|
.option("-c, --conversation <id>", "Optional conversation ID")
|
|
190
182
|
.addHelpText(
|
|
@@ -205,7 +197,7 @@ context-aware recall. If omitted, the most recent conversation is used.
|
|
|
205
197
|
Examples:
|
|
206
198
|
$ assistant memory query "What is the project deadline?"
|
|
207
199
|
$ assistant memory query "preferred communication style" --conversation conv_abc123
|
|
208
|
-
$ assistant memory query "API rate limits"
|
|
200
|
+
$ assistant memory query "API rate limits"`
|
|
209
201
|
)
|
|
210
202
|
.action(async (text: string, opts?: { conversation?: string }) => {
|
|
211
203
|
initializeDb();
|
|
@@ -215,18 +207,21 @@ Examples:
|
|
|
215
207
|
conversationId = latest?.id ?? "";
|
|
216
208
|
}
|
|
217
209
|
const result = await queryMemory(text, conversationId ?? "");
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
log.info(`Semantic hits: ${result.semanticHits}`);
|
|
222
|
-
log.info(`Merged count: ${result.mergedCount}`);
|
|
223
|
-
log.info(`Injected tokens: ${result.injectedTokens}`);
|
|
224
|
-
log.info(`Latency: ${result.latencyMs}ms`);
|
|
225
|
-
if (result.injectedText.length > 0) {
|
|
210
|
+
log.info(`Results: ${result.results.length}`);
|
|
211
|
+
log.info(`Mode: ${result.mode}`);
|
|
212
|
+
if (result.results.length > 0) {
|
|
226
213
|
log.info("");
|
|
227
|
-
|
|
214
|
+
for (const r of result.results) {
|
|
215
|
+
log.info(
|
|
216
|
+
`[${r.type}] (confidence: ${r.confidence.toFixed(
|
|
217
|
+
2
|
|
218
|
+
)}, score: ${r.score.toFixed(3)})`
|
|
219
|
+
);
|
|
220
|
+
log.info(r.content);
|
|
221
|
+
log.info("");
|
|
222
|
+
}
|
|
228
223
|
} else {
|
|
229
|
-
log.info("No
|
|
224
|
+
log.info("No results found.");
|
|
230
225
|
}
|
|
231
226
|
});
|
|
232
227
|
|
|
@@ -246,7 +241,7 @@ status" to monitor job progress.
|
|
|
246
241
|
|
|
247
242
|
Examples:
|
|
248
243
|
$ assistant memory rebuild-index
|
|
249
|
-
$ assistant memory status
|
|
244
|
+
$ assistant memory status`
|
|
250
245
|
)
|
|
251
246
|
.action(() => {
|
|
252
247
|
initializeDb();
|
|
@@ -257,18 +252,15 @@ Examples:
|
|
|
257
252
|
memory
|
|
258
253
|
.command("re-extract")
|
|
259
254
|
.description(
|
|
260
|
-
"Re-extract memories from conversations using the latest extraction prompt"
|
|
255
|
+
"Re-extract memories from conversations using the latest extraction prompt"
|
|
261
256
|
)
|
|
262
257
|
.option(
|
|
263
258
|
"-c, --conversation <id>",
|
|
264
259
|
"Target a specific conversation by ID (repeatable)",
|
|
265
260
|
(val: string, prev: string[]) => [...prev, val],
|
|
266
|
-
[] as string[]
|
|
267
|
-
)
|
|
268
|
-
.option(
|
|
269
|
-
"-t, --top <n>",
|
|
270
|
-
"Auto-select top N conversations by message count",
|
|
261
|
+
[] as string[]
|
|
271
262
|
)
|
|
263
|
+
.option("-t, --top <n>", "Auto-select top N conversations by message count")
|
|
272
264
|
.option("--dry-run", "Show what would be re-extracted without doing it")
|
|
273
265
|
.addHelpText(
|
|
274
266
|
"after",
|
|
@@ -289,14 +281,10 @@ background worker).
|
|
|
289
281
|
Examples:
|
|
290
282
|
$ assistant memory re-extract --top 20
|
|
291
283
|
$ assistant memory re-extract --conversation conv_abc123
|
|
292
|
-
$ assistant memory re-extract --top 10 --dry-run
|
|
284
|
+
$ assistant memory re-extract --top 10 --dry-run`
|
|
293
285
|
)
|
|
294
286
|
.action(
|
|
295
|
-
(opts: {
|
|
296
|
-
conversation?: string[];
|
|
297
|
-
top?: string;
|
|
298
|
-
dryRun?: boolean;
|
|
299
|
-
}) => {
|
|
287
|
+
(opts: { conversation?: string[]; top?: string; dryRun?: boolean }) => {
|
|
300
288
|
initializeDb();
|
|
301
289
|
|
|
302
290
|
const targets = [];
|
|
@@ -333,7 +321,7 @@ Examples:
|
|
|
333
321
|
|
|
334
322
|
if (targets.length === 0) {
|
|
335
323
|
log.info(
|
|
336
|
-
"No targets specified. Use --conversation <id> or --top <n>."
|
|
324
|
+
"No targets specified. Use --conversation <id> or --top <n>."
|
|
337
325
|
);
|
|
338
326
|
return;
|
|
339
327
|
}
|
|
@@ -342,9 +330,7 @@ Examples:
|
|
|
342
330
|
log.info(`\nRe-extraction targets (${targets.length}):`);
|
|
343
331
|
for (const t of targets) {
|
|
344
332
|
const title = t.title ?? "(untitled)";
|
|
345
|
-
log.info(
|
|
346
|
-
` ${t.conversationId} ${t.messageCount} msgs "${title}"`,
|
|
347
|
-
);
|
|
333
|
+
log.info(` ${t.conversationId} ${t.messageCount} msgs "${title}"`);
|
|
348
334
|
}
|
|
349
335
|
|
|
350
336
|
if (opts.dryRun) {
|
|
@@ -354,8 +340,8 @@ Examples:
|
|
|
354
340
|
|
|
355
341
|
const { jobIds } = requestReextract(targets);
|
|
356
342
|
log.info(
|
|
357
|
-
`\nQueued ${jobIds.length} re-extraction job(s). The assistant will process them in the background
|
|
343
|
+
`\nQueued ${jobIds.length} re-extraction job(s). The assistant will process them in the background.`
|
|
358
344
|
);
|
|
359
|
-
}
|
|
345
|
+
}
|
|
360
346
|
);
|
|
361
347
|
}
|
|
@@ -88,7 +88,7 @@ mock.module("../../../../platform/client.js", () => ({
|
|
|
88
88
|
}));
|
|
89
89
|
|
|
90
90
|
mock.module("../../../../util/browser.js", () => ({
|
|
91
|
-
|
|
91
|
+
openInHostBrowser: async (url: string) => {
|
|
92
92
|
mockOpenInBrowserCalls.push(url);
|
|
93
93
|
},
|
|
94
94
|
}));
|
|
@@ -127,7 +127,7 @@ mock.module("../shared.js", () => ({
|
|
|
127
127
|
JSON.stringify({
|
|
128
128
|
ok: false,
|
|
129
129
|
error:
|
|
130
|
-
"
|
|
130
|
+
"Not connected to Vellum platform. Run `vellum platform connect` to connect first.",
|
|
131
131
|
}) + "\n",
|
|
132
132
|
);
|
|
133
133
|
return null;
|
|
@@ -112,7 +112,7 @@ mock.module("../../../../platform/client.js", () => ({
|
|
|
112
112
|
}));
|
|
113
113
|
|
|
114
114
|
mock.module("../../../../util/browser.js", () => ({
|
|
115
|
-
|
|
115
|
+
openInHostBrowser: async () => {},
|
|
116
116
|
}));
|
|
117
117
|
|
|
118
118
|
mock.module("../../../../util/logger.js", () => ({
|
|
@@ -162,7 +162,7 @@ mock.module("../shared.js", () => ({
|
|
|
162
162
|
JSON.stringify({
|
|
163
163
|
ok: false,
|
|
164
164
|
error:
|
|
165
|
-
"
|
|
165
|
+
"Not connected to Vellum platform. Run `vellum platform connect` to connect first.",
|
|
166
166
|
}) + "\n",
|
|
167
167
|
);
|
|
168
168
|
return null;
|
|
@@ -34,6 +34,10 @@ let mockSetNestedValueCalls: Array<{
|
|
|
34
34
|
|
|
35
35
|
let mockConfigServices: Record<string, unknown> = {};
|
|
36
36
|
|
|
37
|
+
let mockRequirePlatformConnection: (
|
|
38
|
+
cmd: unknown,
|
|
39
|
+
) => Promise<boolean> = async () => true;
|
|
40
|
+
|
|
37
41
|
// ---------------------------------------------------------------------------
|
|
38
42
|
// Mocks
|
|
39
43
|
// ---------------------------------------------------------------------------
|
|
@@ -120,6 +124,8 @@ mock.module("../shared.js", () => ({
|
|
|
120
124
|
isManagedMode: () => false,
|
|
121
125
|
getManagedServiceConfigKey: (key: string) =>
|
|
122
126
|
mockGetManagedServiceConfigKey(key),
|
|
127
|
+
requirePlatformConnection: (cmd: unknown) =>
|
|
128
|
+
mockRequirePlatformConnection(cmd),
|
|
123
129
|
requirePlatformClient: async (_cmd: Command) => {
|
|
124
130
|
if (
|
|
125
131
|
!mockPlatformClientResult ||
|
|
@@ -130,7 +136,7 @@ mock.module("../shared.js", () => ({
|
|
|
130
136
|
JSON.stringify({
|
|
131
137
|
ok: false,
|
|
132
138
|
error:
|
|
133
|
-
"
|
|
139
|
+
"Not connected to Vellum platform. Run `vellum platform connect` to connect first.",
|
|
134
140
|
}) + "\n",
|
|
135
141
|
);
|
|
136
142
|
return null;
|
|
@@ -244,6 +250,7 @@ describe("assistant oauth mode", () => {
|
|
|
244
250
|
mockSaveRawConfigCalls = [];
|
|
245
251
|
mockSetNestedValueCalls = [];
|
|
246
252
|
mockConfigServices = {};
|
|
253
|
+
mockRequirePlatformConnection = async () => true;
|
|
247
254
|
process.exitCode = 0;
|
|
248
255
|
});
|
|
249
256
|
|
|
@@ -71,7 +71,7 @@ mock.module("../../../../platform/client.js", () => ({
|
|
|
71
71
|
}));
|
|
72
72
|
|
|
73
73
|
mock.module("../../../../util/browser.js", () => ({
|
|
74
|
-
|
|
74
|
+
openInHostBrowser: async () => {},
|
|
75
75
|
}));
|
|
76
76
|
|
|
77
77
|
mock.module("../../../../util/logger.js", () => ({
|
|
@@ -107,7 +107,7 @@ mock.module("../shared.js", () => ({
|
|
|
107
107
|
JSON.stringify({
|
|
108
108
|
ok: false,
|
|
109
109
|
error:
|
|
110
|
-
"
|
|
110
|
+
"Not connected to Vellum platform. Run `vellum platform connect` to connect first.",
|
|
111
111
|
}) + "\n",
|
|
112
112
|
);
|
|
113
113
|
return null;
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
getProvider,
|
|
10
10
|
} from "../../../oauth/oauth-store.js";
|
|
11
11
|
import { renderOAuthCompletionPage } from "../../../security/oauth-completion-page.js";
|
|
12
|
-
import {
|
|
12
|
+
import { openInHostBrowser } from "../../../util/browser.js";
|
|
13
13
|
import { getSecureKeyViaDaemon } from "../../lib/daemon-credential-client.js";
|
|
14
14
|
import { getCliLogger } from "../../logger.js";
|
|
15
15
|
import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
@@ -199,9 +199,14 @@ Examples:
|
|
|
199
199
|
|
|
200
200
|
if (!response.ok) {
|
|
201
201
|
const errorText = await response.text().catch(() => "");
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
202
|
+
const baseMsg = `Platform returned HTTP ${response.status}${errorText ? `: ${errorText}` : ""}`;
|
|
203
|
+
if (response.status === 401 || response.status === 403) {
|
|
204
|
+
writeError(
|
|
205
|
+
`${baseMsg}. Your platform session may have expired. Run \`vellum platform connect\` to reconnect.`,
|
|
206
|
+
);
|
|
207
|
+
} else {
|
|
208
|
+
writeError(baseMsg);
|
|
209
|
+
}
|
|
205
210
|
return;
|
|
206
211
|
}
|
|
207
212
|
|
|
@@ -229,7 +234,7 @@ Examples:
|
|
|
229
234
|
}
|
|
230
235
|
const snapshotIds = new Set(snapshotEntries.map((e) => e.id));
|
|
231
236
|
|
|
232
|
-
|
|
237
|
+
await openInHostBrowser(result.connect_url);
|
|
233
238
|
|
|
234
239
|
if (!jsonMode) {
|
|
235
240
|
log.info(
|
|
@@ -374,7 +379,7 @@ Examples:
|
|
|
374
379
|
clientSecret,
|
|
375
380
|
callbackTransport: opts.callbackTransport,
|
|
376
381
|
isInteractive: opts.browser !== false,
|
|
377
|
-
openUrl: opts.browser !== false ?
|
|
382
|
+
openUrl: opts.browser !== false ? openInHostBrowser : undefined,
|
|
378
383
|
...(opts.scopes ? { requestedScopes: opts.scopes } : {}),
|
|
379
384
|
});
|
|
380
385
|
|
|
@@ -17,6 +17,7 @@ import { shouldOutputJson, writeOutput } from "../../output.js";
|
|
|
17
17
|
import {
|
|
18
18
|
fetchActiveConnections,
|
|
19
19
|
getManagedServiceConfigKey,
|
|
20
|
+
requirePlatformConnection,
|
|
20
21
|
} from "./shared.js";
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -180,6 +181,12 @@ Examples:
|
|
|
180
181
|
return;
|
|
181
182
|
}
|
|
182
183
|
|
|
184
|
+
// Require platform connection when switching to managed mode
|
|
185
|
+
if (newMode === "managed") {
|
|
186
|
+
const connected = await requirePlatformConnection(cmd);
|
|
187
|
+
if (!connected) return;
|
|
188
|
+
}
|
|
189
|
+
|
|
183
190
|
// Read current mode
|
|
184
191
|
const services: Services = getConfig().services;
|
|
185
192
|
const currentMode = services[managedKey as keyof Services].mode;
|
|
@@ -59,11 +59,20 @@ export async function requirePlatformClient(
|
|
|
59
59
|
cmd: Command,
|
|
60
60
|
): Promise<VellumPlatformClient | null> {
|
|
61
61
|
const client = await VellumPlatformClient.create();
|
|
62
|
-
if (!client
|
|
62
|
+
if (!client) {
|
|
63
63
|
writeOutput(cmd, {
|
|
64
64
|
ok: false,
|
|
65
65
|
error:
|
|
66
|
-
"
|
|
66
|
+
"Not connected to Vellum platform. Run `vellum platform connect` to connect first.",
|
|
67
|
+
});
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
if (!client.platformAssistantId) {
|
|
72
|
+
writeOutput(cmd, {
|
|
73
|
+
ok: false,
|
|
74
|
+
error:
|
|
75
|
+
"Connected to Vellum platform but no assistant ID is configured. Ensure the assistant is registered on the platform.",
|
|
67
76
|
});
|
|
68
77
|
process.exitCode = 1;
|
|
69
78
|
return null;
|
|
@@ -71,6 +80,29 @@ export async function requirePlatformClient(
|
|
|
71
80
|
return client;
|
|
72
81
|
}
|
|
73
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Verify that the user has connected to the Vellum platform (has stored
|
|
85
|
+
* credentials). Unlike `requirePlatformClient`, this does NOT require a
|
|
86
|
+
* platform assistant ID — it only checks that credentials exist.
|
|
87
|
+
*
|
|
88
|
+
* Writes an error and sets exitCode=1 when the user is not connected.
|
|
89
|
+
*/
|
|
90
|
+
export async function requirePlatformConnection(
|
|
91
|
+
cmd: Command,
|
|
92
|
+
): Promise<boolean> {
|
|
93
|
+
const client = await VellumPlatformClient.create();
|
|
94
|
+
if (!client) {
|
|
95
|
+
writeOutput(cmd, {
|
|
96
|
+
ok: false,
|
|
97
|
+
error:
|
|
98
|
+
"Not connected to Vellum platform. Run `vellum platform connect` to connect first.",
|
|
99
|
+
});
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
74
106
|
/**
|
|
75
107
|
* Fetch active platform connections for a provider. Returns the parsed entries
|
|
76
108
|
* or writes an error and returns null.
|
|
@@ -94,9 +126,13 @@ export async function fetchActiveConnections(
|
|
|
94
126
|
|
|
95
127
|
if (!response.ok) {
|
|
96
128
|
if (!options?.silent) {
|
|
129
|
+
const hint =
|
|
130
|
+
response.status === 401 || response.status === 403
|
|
131
|
+
? `. Your platform session may have expired. Run \`vellum platform connect\` to reconnect.`
|
|
132
|
+
: "";
|
|
97
133
|
writeOutput(cmd, {
|
|
98
134
|
ok: false,
|
|
99
|
-
error: `Platform returned HTTP ${response.status}`,
|
|
135
|
+
error: `Platform returned HTTP ${response.status}${hint}`,
|
|
100
136
|
});
|
|
101
137
|
process.exitCode = 1;
|
|
102
138
|
}
|
|
@@ -30,7 +30,7 @@ mock.module("../../../lib/daemon-credential-client.js", () => ({
|
|
|
30
30
|
|
|
31
31
|
mock.module("../../../../inbound/platform-callback-registration.js", () => ({
|
|
32
32
|
resolvePlatformCallbackRegistrationContext: async () => ({
|
|
33
|
-
|
|
33
|
+
isPlatform: false,
|
|
34
34
|
platformBaseUrl: "",
|
|
35
35
|
assistantId: "",
|
|
36
36
|
hasInternalApiKey: false,
|
|
@@ -36,7 +36,7 @@ mock.module("../../../../config/env-registry.js", () => ({
|
|
|
36
36
|
|
|
37
37
|
mock.module("../../../../inbound/platform-callback-registration.js", () => ({
|
|
38
38
|
resolvePlatformCallbackRegistrationContext: async () => ({
|
|
39
|
-
|
|
39
|
+
isPlatform: false,
|
|
40
40
|
platformBaseUrl: "",
|
|
41
41
|
assistantId: "",
|
|
42
42
|
hasInternalApiKey: false,
|
|
@@ -11,7 +11,7 @@ let mockGetSecureKeyViaDaemon: (
|
|
|
11
11
|
let mockResolvePlatformCallbackRegistrationContext: () => Promise<
|
|
12
12
|
Record<string, unknown>
|
|
13
13
|
> = async () => ({
|
|
14
|
-
|
|
14
|
+
isPlatform: false,
|
|
15
15
|
platformBaseUrl: "",
|
|
16
16
|
assistantId: "",
|
|
17
17
|
hasInternalApiKey: false,
|
|
@@ -138,7 +138,7 @@ describe("assistant platform status", () => {
|
|
|
138
138
|
beforeEach(() => {
|
|
139
139
|
mockGetSecureKeyViaDaemon = async () => undefined;
|
|
140
140
|
mockResolvePlatformCallbackRegistrationContext = async () => ({
|
|
141
|
-
|
|
141
|
+
isPlatform: false,
|
|
142
142
|
platformBaseUrl: "",
|
|
143
143
|
assistantId: "",
|
|
144
144
|
hasInternalApiKey: false,
|
|
@@ -158,7 +158,7 @@ describe("assistant platform status", () => {
|
|
|
158
158
|
|
|
159
159
|
// GIVEN a containerized environment with platform configuration
|
|
160
160
|
mockResolvePlatformCallbackRegistrationContext = async () => ({
|
|
161
|
-
|
|
161
|
+
isPlatform: true,
|
|
162
162
|
platformBaseUrl: "https://platform.vellum.ai",
|
|
163
163
|
assistantId: "asst-abc-123",
|
|
164
164
|
hasInternalApiKey: true,
|
|
@@ -191,7 +191,7 @@ describe("assistant platform status", () => {
|
|
|
191
191
|
|
|
192
192
|
// AND the output contains the expected status fields
|
|
193
193
|
const parsed = JSON.parse(stdout);
|
|
194
|
-
expect(parsed.
|
|
194
|
+
expect(parsed.isPlatform).toBe(true);
|
|
195
195
|
expect(parsed.baseUrl).toBe("https://platform.vellum.ai");
|
|
196
196
|
expect(parsed.assistantId).toBe("asst-abc-123");
|
|
197
197
|
expect(parsed.hasInternalApiKey).toBe(true);
|
|
@@ -211,7 +211,7 @@ describe("assistant platform status", () => {
|
|
|
211
211
|
|
|
212
212
|
// GIVEN a disconnected environment with no stored credentials
|
|
213
213
|
mockResolvePlatformCallbackRegistrationContext = async () => ({
|
|
214
|
-
|
|
214
|
+
isPlatform: false,
|
|
215
215
|
platformBaseUrl: "",
|
|
216
216
|
assistantId: "",
|
|
217
217
|
hasInternalApiKey: false,
|