@vellumai/assistant 0.8.1 → 0.8.3
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 +13 -19
- package/Dockerfile +75 -1
- package/bun.lock +11 -1
- package/docker-entrypoint.sh +17 -0
- package/docker-init-apt-root.sh +167 -0
- package/docker-kata-apt-env.sh +39 -0
- package/docs/plugins.md +88 -47
- package/docs/skills.md +9 -7
- package/examples/plugins/echo/README.md +27 -27
- package/examples/plugins/echo/package.json +3 -0
- package/examples/plugins/echo/register.ts +31 -31
- package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
- package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
- package/openapi.yaml +642 -5
- package/package.json +3 -1
- package/scripts/generate-openapi.ts +83 -10
- package/scripts/sync-llm-catalog.ts +2 -2
- package/scripts/sync-web-search-catalog.ts +47 -25
- package/src/__tests__/agent-image-optimize.test.ts +11 -3
- package/src/__tests__/agent-loop-exit-reason.test.ts +272 -0
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
- package/src/__tests__/anthropic-provider.test.ts +45 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
- package/src/__tests__/app-executors.test.ts +220 -4
- package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/channel-availability-routes.test.ts +206 -0
- package/src/__tests__/channel-delivery-store.test.ts +289 -1
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
- package/src/__tests__/clawhub.test.ts +75 -16
- package/src/__tests__/compactor-tail-resolution.test.ts +147 -0
- package/src/__tests__/config-get-vision-flag.test.ts +136 -0
- package/src/__tests__/config-loader-backfill.test.ts +115 -18
- package/src/__tests__/config-schema.test.ts +21 -0
- package/src/__tests__/config-set-route.test.ts +80 -0
- package/src/__tests__/config-sounds-sync.test.ts +97 -0
- package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
- package/src/__tests__/context-search-conversations-source.test.ts +117 -2
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +7 -0
- package/src/__tests__/context-token-estimator.test.ts +31 -65
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
- package/src/__tests__/conversation-agent-loop.test.ts +59 -1
- package/src/__tests__/conversation-error.test.ts +42 -3
- package/src/__tests__/conversation-fork-crud.test.ts +82 -0
- package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
- package/src/__tests__/conversation-lifecycle.test.ts +173 -0
- package/src/__tests__/conversation-media-retry.test.ts +19 -8
- package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
- package/src/__tests__/conversation-pairing.test.ts +54 -0
- package/src/__tests__/conversation-process-callsite.test.ts +4 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
- package/src/__tests__/conversation-queue.test.ts +4 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +102 -13
- package/src/__tests__/conversation-slash-queue.test.ts +59 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
- package/src/__tests__/conversation-sync-tags.test.ts +235 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +3 -2
- package/src/__tests__/date-context.test.ts +45 -0
- package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
- package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
- package/src/__tests__/disk-pressure-tools.test.ts +1 -0
- package/src/__tests__/dm-backfill.test.ts +121 -10
- package/src/__tests__/document-tool-security.test.ts +258 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/edit-propagation.test.ts +33 -0
- package/src/__tests__/empty-response-pipeline.test.ts +0 -4
- package/src/__tests__/external-plugin-loader.test.ts +151 -55
- package/src/__tests__/filing-service.test.ts +140 -0
- package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
- package/src/__tests__/heartbeat-service.test.ts +24 -164
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/helpers/tar-fixtures.ts +39 -0
- package/src/__tests__/helpers/wait-for.ts +21 -0
- package/src/__tests__/history-repair-pipeline.test.ts +0 -3
- package/src/__tests__/history-repair.test.ts +73 -0
- package/src/__tests__/host-app-control-proxy.test.ts +507 -10
- package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
- package/src/__tests__/image-credentials.test.ts +1 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
- package/src/__tests__/inference-profile-reaper.test.ts +4 -2
- package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
- package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
- package/src/__tests__/injector-background-turn.test.ts +153 -0
- package/src/__tests__/injector-chain.test.ts +15 -8
- package/src/__tests__/install-skill-routing.test.ts +155 -37
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +99 -3
- package/src/__tests__/list-messages-page-latest.test.ts +55 -0
- package/src/__tests__/llm-call-pipeline.test.ts +0 -3
- package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
- package/src/__tests__/llm-catalog-parity.test.ts +58 -13
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +36 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
- package/src/__tests__/llm-resolver.test.ts +255 -2
- package/src/__tests__/llm-usage-store.test.ts +114 -0
- package/src/__tests__/managed-profile-guard.test.ts +41 -29
- package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
- package/src/__tests__/managed-store.test.ts +84 -192
- package/src/__tests__/media-generate-image.test.ts +1 -1
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
- package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
- package/src/__tests__/notification-decision-fallback.test.ts +0 -91
- package/src/__tests__/notification-decision-strategy.test.ts +14 -31
- package/src/__tests__/notification-deep-link.test.ts +15 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -2
- package/src/__tests__/notification-platform-adapter.test.ts +5 -4
- package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
- package/src/__tests__/oauth-commands-routes.test.ts +168 -16
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
- package/src/__tests__/openai-provider.test.ts +242 -3
- package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
- package/src/__tests__/openrouter-provider-only.test.ts +51 -3
- package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
- package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
- package/src/__tests__/persistence-pipeline.test.ts +0 -2
- package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +7 -2
- package/src/__tests__/platform.test.ts +2 -0
- package/src/__tests__/plugin-api-shim.test.ts +125 -0
- package/src/__tests__/plugin-bootstrap.test.ts +10 -36
- package/src/__tests__/plugin-external-api.test.ts +68 -0
- package/src/__tests__/plugin-registry.test.ts +0 -77
- package/src/__tests__/plugin-route-contribution.test.ts +0 -1
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
- package/src/__tests__/plugin-types.test.ts +3 -13
- package/src/__tests__/process-message-background-slack.test.ts +8 -1
- package/src/__tests__/process-message-display-content.test.ts +421 -0
- package/src/__tests__/provider-catalog-visibility.test.ts +158 -0
- package/src/__tests__/provider-error-scenarios.test.ts +111 -0
- package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +33 -31
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
- package/src/__tests__/schedule-routes.test.ts +50 -3
- package/src/__tests__/schedule-store.test.ts +94 -0
- package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
- package/src/__tests__/schema-transforms.test.ts +20 -0
- package/src/__tests__/search-skills-unified.test.ts +0 -5
- package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +1 -1
- package/src/__tests__/server-history-render.test.ts +43 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
- package/src/__tests__/skill-load-tool.test.ts +27 -89
- package/src/__tests__/skill-memory.test.ts +23 -3
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
- package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
- package/src/__tests__/skills-install-extract.test.ts +49 -38
- package/src/__tests__/skills-install-staging.test.ts +159 -0
- package/src/__tests__/skills-uninstall.test.ts +9 -41
- package/src/__tests__/skills.test.ts +51 -58
- package/src/__tests__/slack-channel-config.test.ts +9 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/system-prompt.test.ts +670 -63
- package/src/__tests__/terminal-tools.test.ts +28 -1
- package/src/__tests__/thread-backfill.test.ts +557 -27
- package/src/__tests__/title-generate-pipeline.test.ts +0 -13
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
- package/src/__tests__/tool-error-pipeline.test.ts +0 -3
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +16 -4
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
- package/src/__tests__/turn-events-store.test.ts +256 -0
- package/src/__tests__/twilio-routes.test.ts +4 -0
- package/src/__tests__/user-plugin-loader.test.ts +0 -7
- package/src/__tests__/voice-session-bridge.test.ts +198 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
- package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
- package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
- package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
- package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
- package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
- package/src/a2a/__tests__/agent-card.test.ts +98 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
- package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
- package/src/a2a/__tests__/task-store.test.ts +246 -0
- package/src/a2a/agent-card.ts +58 -0
- package/src/a2a/feature-gate.ts +8 -0
- package/src/a2a/protocol-constants.ts +21 -0
- package/src/a2a/protocol-errors.ts +50 -0
- package/src/a2a/protocol-types.ts +162 -0
- package/src/a2a/task-store.ts +168 -0
- package/src/acp/resolve-agent.ts +1 -1
- package/src/agent/image-optimize.ts +13 -5
- package/src/agent/loop.ts +167 -18
- package/src/calls/voice-session-bridge.ts +61 -42
- package/src/channels/config.ts +9 -0
- package/src/channels/types.ts +122 -0
- package/src/cli/__tests__/unknown-command.test.ts +24 -0
- package/src/cli/commands/__tests__/changelog.test.ts +304 -319
- package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
- package/src/cli/commands/__tests__/schedules.test.ts +960 -0
- package/src/cli/commands/changelog.ts +106 -42
- package/src/cli/commands/conversations.ts +102 -17
- package/src/cli/commands/default-action.ts +10 -53
- package/src/cli/commands/notifications.ts +388 -346
- package/src/cli/commands/plugins.ts +252 -0
- package/src/cli/commands/schedules.ts +683 -0
- package/src/cli/commands/telemetry.ts +40 -0
- package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
- package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
- package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
- package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
- package/src/cli/lib/cli-colors.ts +12 -0
- package/src/cli/lib/confirm-prompt.ts +79 -0
- package/src/cli/lib/install-from-github.ts +303 -0
- package/src/cli/lib/list-installed-plugins.ts +137 -0
- package/src/cli/lib/search-plugins.ts +163 -0
- package/src/cli/lib/uninstall-plugin.ts +82 -0
- package/src/cli/lib/unknown-command.ts +111 -0
- package/src/cli/program.ts +52 -2
- package/src/config/assistant-feature-flags.ts +24 -54
- package/src/config/bundled-skills/app-builder/SKILL.md +140 -22
- package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
- package/src/config/bundled-skills/document/SKILL.md +23 -3
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
- package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
- package/src/config/bundled-tool-registry.ts +6 -0
- package/src/config/call-site-defaults.ts +105 -0
- package/src/config/feature-flag-registry.json +41 -9
- package/src/config/llm-resolver.ts +52 -1
- package/src/config/loader.ts +64 -38
- package/src/config/schema.ts +9 -10
- package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +3 -3
- package/src/config/schemas/channels.ts +17 -0
- package/src/config/schemas/compaction.ts +28 -0
- package/src/config/schemas/conversations.ts +10 -0
- package/src/config/schemas/heartbeat.ts +23 -0
- package/src/config/schemas/llm-request-logs.ts +31 -7
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-retrieval.ts +18 -0
- package/src/config/schemas/memory-retrospective.ts +1 -1
- package/src/config/schemas/memory-v2.ts +4 -4
- package/src/config/schemas/memory.ts +3 -1
- package/src/config/schemas/tools.ts +14 -0
- package/src/config/seed-inference-profiles.ts +99 -29
- package/src/config/skills.ts +3 -96
- package/src/context/compactor.ts +1107 -0
- package/src/context/token-estimator.ts +34 -36
- package/src/context/window-manager.ts +197 -1520
- package/src/credential-execution/managed-catalog.ts +37 -0
- package/src/credential-health/credential-health-service.ts +280 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +33 -18
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
- package/src/daemon/approval-generators.ts +8 -6
- package/src/daemon/config-watcher.ts +94 -31
- package/src/daemon/conversation-agent-loop-handlers.ts +78 -0
- package/src/daemon/conversation-agent-loop.ts +198 -11
- package/src/daemon/conversation-error.ts +171 -37
- package/src/daemon/conversation-lifecycle.ts +53 -40
- package/src/daemon/conversation-messaging.ts +25 -6
- package/src/daemon/conversation-process.ts +49 -12
- package/src/daemon/conversation-runtime-assembly.ts +25 -1
- package/src/daemon/conversation-slash.ts +12 -5
- package/src/daemon/conversation-store.ts +11 -4
- package/src/daemon/conversation-tool-setup.ts +39 -7
- package/src/daemon/conversation.ts +33 -8
- package/src/daemon/date-context.ts +40 -0
- package/src/daemon/external-plugins-bootstrap.ts +217 -181
- package/src/daemon/first-greeting.ts +22 -2
- package/src/daemon/guardian-action-generators.ts +1 -125
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
- package/src/daemon/handlers/config-a2a.ts +289 -0
- package/src/daemon/handlers/config-model.ts +6 -5
- package/src/daemon/handlers/config-slack-channel.ts +15 -3
- package/src/daemon/handlers/conversations.ts +1 -0
- package/src/daemon/handlers/shared.ts +14 -5
- package/src/daemon/handlers/skills.ts +111 -108
- package/src/daemon/history-repair.ts +28 -1
- package/src/daemon/host-app-control-proxy.ts +153 -27
- package/src/daemon/host-proxy-preactivation.ts +85 -18
- package/src/daemon/lifecycle.ts +89 -91
- package/src/daemon/meet-host-supervisor.ts +5 -4
- package/src/daemon/memory-v2-startup.ts +85 -0
- package/src/daemon/message-protocol.ts +1 -0
- package/src/daemon/message-types/conversations.ts +25 -0
- package/src/daemon/message-types/messages.ts +61 -0
- package/src/daemon/message-types/notifications.ts +21 -0
- package/src/daemon/message-types/subagents.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pkb-reminder-builder.test.ts +11 -54
- package/src/daemon/pkb-reminder-builder.ts +5 -20
- package/src/daemon/plugin-source-watcher.ts +146 -0
- package/src/daemon/process-message.ts +24 -3
- package/src/daemon/server.ts +11 -2
- package/src/daemon/skill-memory-refresh.ts +33 -0
- package/src/daemon/wake-target-adapter.ts +2 -0
- package/src/documents/document-store.ts +221 -3
- package/src/embedded/plugin-api.ts +40 -0
- package/src/export/__tests__/transcript-formatter.test.ts +121 -0
- package/src/export/transcript-formatter.ts +54 -20
- package/src/filing/filing-service.ts +39 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +135 -6
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +73 -189
- package/src/home/__tests__/feed-types.test.ts +80 -0
- package/src/home/feed-types.ts +36 -2
- package/src/home/post-connect-feed.ts +1 -0
- package/src/index.ts +18 -1
- package/src/ipc/cli-client.ts +147 -45
- package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
- package/src/mcp/client.ts +20 -4
- package/src/media/image-credentials.ts +3 -3
- package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
- package/src/memory/__tests__/conversation-queries.test.ts +483 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
- package/src/memory/__tests__/memory-retrospective-job.test.ts +87 -4
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
- package/src/memory/__tests__/message-content.test.ts +35 -0
- package/src/memory/bookmark-crud.ts +42 -10
- package/src/memory/context-search/sources/conversations.ts +62 -2
- package/src/memory/context-search/sources/workspace.ts +4 -0
- package/src/memory/conversation-crud.ts +63 -19
- package/src/memory/conversation-queries.ts +197 -11
- package/src/memory/conversation-title-service.ts +26 -4
- package/src/memory/db-init.ts +12 -0
- package/src/memory/delivery-crud.ts +152 -5
- package/src/memory/embedding-backend.ts +4 -4
- package/src/memory/external-conversation-store.ts +66 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +150 -12
- package/src/memory/graph/conversation-graph-memory.ts +49 -21
- package/src/memory/graph/tools.ts +9 -40
- package/src/memory/indexer.ts +34 -29
- package/src/memory/invite-store.ts +53 -0
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
- package/src/memory/jobs/embed-concept-page.ts +20 -11
- package/src/memory/jobs-worker.ts +6 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +24 -12
- package/src/memory/llm-request-log-source.ts +19 -52
- package/src/memory/llm-request-log-store.ts +92 -1
- package/src/memory/llm-usage-store.ts +125 -5
- package/src/memory/memory-retrospective-enqueue.ts +1 -20
- package/src/memory/memory-retrospective-job.ts +33 -6
- package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
- package/src/memory/message-content.ts +1 -1
- package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
- package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
- package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
- package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
- package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
- package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
- package/src/memory/migrations/251-a2a-tasks.ts +49 -0
- package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
- package/src/memory/migrations/index.ts +9 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/onboarding-events-store.ts +106 -0
- package/src/memory/schema/a2a.ts +15 -0
- package/src/memory/schema/bookmarks.ts +0 -2
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/inference.ts +3 -3
- package/src/memory/schema/infrastructure.ts +13 -0
- package/src/memory/turn-events-store.ts +127 -2
- package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
- package/src/memory/v2/__tests__/activation.test.ts +0 -8
- package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
- package/src/memory/v2/__tests__/injection.test.ts +288 -11
- package/src/memory/v2/__tests__/migration.test.ts +87 -0
- package/src/memory/v2/__tests__/page-index.test.ts +83 -0
- package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
- package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
- package/src/memory/v2/__tests__/router.test.ts +15 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
- package/src/memory/v2/__tests__/static-context.test.ts +12 -1
- package/src/memory/v2/activation-store.ts +14 -16
- package/src/memory/v2/cli-command-content.ts +19 -0
- package/src/memory/v2/cli-command-store.ts +304 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -1
- package/src/memory/v2/injection.ts +81 -26
- package/src/memory/v2/migration.ts +49 -19
- package/src/memory/v2/page-index.ts +63 -8
- package/src/memory/v2/prompts/router.ts +11 -8
- package/src/memory/v2/prompts/sweep.ts +2 -2
- package/src/memory/v2/qdrant.ts +135 -7
- package/src/memory/v2/router.ts +9 -8
- package/src/memory/v2/skill-store.ts +120 -35
- package/src/memory/v2/static-context.ts +4 -4
- package/src/memory/v2/types.ts +23 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
- package/src/messaging/providers/a2a/deliver.ts +156 -0
- package/src/messaging/providers/gmail/client.ts +9 -2
- package/src/messaging/providers/index.ts +11 -2
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
- package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
- package/src/messaging/providers/slack/adapter.ts +43 -5
- package/src/messaging/providers/slack/client.ts +27 -0
- package/src/messaging/providers/slack/deep-link.ts +65 -0
- package/src/messaging/providers/slack/download.ts +104 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
- package/src/messaging/providers/slack/message-metadata.ts +27 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
- package/src/messaging/providers/slack/render-transcript.ts +69 -5
- package/src/messaging/providers/slack/types.ts +20 -1
- package/src/notifications/__tests__/broadcaster.test.ts +203 -0
- package/src/notifications/__tests__/decision-engine.test.ts +283 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +430 -7
- package/src/notifications/adapters/macos.ts +12 -2
- package/src/notifications/broadcaster.ts +29 -4
- package/src/notifications/conversation-pairing.ts +2 -1
- package/src/notifications/copy-composer.ts +17 -64
- package/src/notifications/decision-engine.ts +113 -45
- package/src/notifications/deterministic-checks.ts +96 -0
- package/src/notifications/emit-signal.ts +21 -1
- package/src/notifications/home-feed-side-effect.ts +138 -5
- package/src/notifications/signal.ts +3 -5
- package/src/notifications/types.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -4
- package/src/oauth/platform-connection.test.ts +43 -3
- package/src/oauth/platform-connection.ts +19 -6
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/checker.ts +2 -0
- package/src/permissions/ipc-risk-types.ts +1 -0
- package/src/permissions/question-prompter.test.ts +416 -0
- package/src/permissions/question-prompter.ts +294 -0
- package/src/platform/client.test.ts +1 -1
- package/src/platform/client.ts +1 -1
- package/src/plugin-api/constants.ts +26 -0
- package/src/plugin-api/index.ts +34 -1
- package/src/plugin-api/types.ts +104 -22
- package/src/plugins/defaults/circuit-breaker.ts +0 -5
- package/src/plugins/defaults/compaction.ts +0 -4
- package/src/plugins/defaults/empty-response.ts +0 -2
- package/src/plugins/defaults/history-repair.ts +0 -2
- package/src/plugins/defaults/injectors.ts +74 -22
- package/src/plugins/defaults/llm-call.ts +0 -2
- package/src/plugins/defaults/memory-retrieval.ts +0 -1
- package/src/plugins/defaults/overflow-reduce.ts +0 -1
- package/src/plugins/defaults/persistence.ts +0 -2
- package/src/plugins/defaults/title-generate.ts +0 -5
- package/src/plugins/defaults/token-estimate.ts +0 -2
- package/src/plugins/defaults/tool-error.ts +0 -7
- package/src/plugins/defaults/tool-execute.ts +0 -2
- package/src/plugins/defaults/tool-result-truncate.ts +0 -4
- package/src/plugins/ensure-plugin-api-shim.ts +96 -0
- package/src/plugins/external-api.ts +104 -0
- package/src/plugins/external-plugin-loader.ts +187 -42
- package/src/plugins/feature-gate.ts +22 -0
- package/src/plugins/pipeline.ts +37 -0
- package/src/plugins/registry.ts +48 -80
- package/src/plugins/types.ts +40 -26
- package/src/plugins/user-loader.ts +21 -2
- package/src/proactive-artifact/aux-message-injector.ts +11 -0
- package/src/proactive-artifact/job.test.ts +37 -5
- package/src/prompts/__tests__/system-prompt.test.ts +10 -43
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +95 -0
- package/src/prompts/normalize-onboarding.ts +27 -0
- package/src/prompts/sections.ts +302 -0
- package/src/prompts/system-prompt.ts +63 -174
- package/src/prompts/templates/BOOTSTRAP.md +17 -1
- package/src/prompts/templates/system-sections.ts +164 -0
- package/src/providers/__tests__/inference.test.ts +24 -7
- package/src/providers/anthropic/client.ts +28 -28
- package/src/providers/call-site-routing.ts +24 -6
- package/src/providers/connection-resolution.ts +68 -11
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
- package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
- package/src/providers/inference/adapter-factory.ts +32 -6
- package/src/providers/inference/auth.ts +12 -0
- package/src/providers/inference/backfill.ts +14 -1
- package/src/providers/inference/connections.ts +159 -34
- package/src/providers/inference/resolve-auth.ts +14 -4
- package/src/providers/model-catalog.ts +249 -12
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
- package/src/providers/openai/chat-completions-provider.ts +169 -8
- package/src/providers/openrouter/client.ts +49 -4
- package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -2
- package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
- package/src/providers/provider-availability.ts +17 -2
- package/src/providers/provider-catalog-visibility.ts +38 -0
- package/src/providers/provider-send-message.ts +27 -12
- package/src/providers/registry.ts +52 -15
- package/src/providers/retry.ts +47 -1
- package/src/runtime/__tests__/agent-wake.test.ts +152 -0
- package/src/runtime/agent-wake.ts +103 -15
- package/src/runtime/auth/route-policy.ts +21 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/http-server.ts +7 -16
- package/src/runtime/http-types.ts +19 -47
- package/src/runtime/migrations/origin-mode.ts +1 -1
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +172 -23
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
- package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
- package/src/runtime/routes/acp-routes-list.test.ts +143 -0
- package/src/runtime/routes/acp-routes.ts +5 -3
- package/src/runtime/routes/auth-routes.ts +1 -1
- package/src/runtime/routes/bookmark-routes.ts +5 -3
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/channel-availability-routes.ts +126 -0
- package/src/runtime/routes/consolidation-routes.ts +100 -0
- package/src/runtime/routes/conversation-cli-routes.ts +44 -3
- package/src/runtime/routes/conversation-list-routes.ts +3 -20
- package/src/runtime/routes/conversation-management-routes.ts +17 -42
- package/src/runtime/routes/conversation-query-routes.ts +99 -35
- package/src/runtime/routes/conversation-routes.ts +97 -11
- package/src/runtime/routes/documents-routes.ts +25 -86
- package/src/runtime/routes/group-routes.ts +5 -0
- package/src/runtime/routes/inbound-conversation.ts +28 -8
- package/src/runtime/routes/inbound-message-handler.ts +236 -41
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
- package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
- package/src/runtime/routes/inference-provider-connection-routes.ts +199 -22
- package/src/runtime/routes/integrations/a2a.ts +235 -0
- package/src/runtime/routes/integrations/slack/share.ts +4 -52
- package/src/runtime/routes/integrations/slack/token.ts +43 -0
- package/src/runtime/routes/integrations/twilio.ts +6 -13
- package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
- package/src/runtime/routes/notification-routes.ts +1 -1
- package/src/runtime/routes/oauth-commands-routes.ts +105 -15
- package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
- package/src/runtime/routes/question-routes.ts +259 -0
- package/src/runtime/routes/rename-conversation-routes.ts +2 -33
- package/src/runtime/routes/schedule-routes.ts +4 -7
- package/src/runtime/routes/subagents-routes.ts +98 -18
- package/src/runtime/routes/telemetry-routes.ts +27 -0
- package/src/runtime/routes/tts-routes.ts +27 -2
- package/src/runtime/routes/workspace-routes.test.ts +43 -0
- package/src/runtime/routes/workspace-routes.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +39 -7
- package/src/runtime/sync/resource-sync-events.ts +93 -1
- package/src/schedule/schedule-store.ts +27 -2
- package/src/schedule/scheduler.ts +9 -1
- package/src/security/__tests__/untrusted-content.test.ts +86 -0
- package/src/security/untrusted-content.ts +93 -8
- package/src/skills/catalog-files.ts +1 -1
- package/src/skills/catalog-install.ts +233 -116
- package/src/skills/clawhub.ts +70 -13
- package/src/skills/managed-store.ts +4 -119
- package/src/skills/skillssh-registry.ts +27 -48
- package/src/subagent/manager.ts +17 -7
- package/src/telemetry/types.ts +113 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
- package/src/telemetry/usage-telemetry-reporter.ts +113 -7
- package/src/tools/apps/executors.ts +58 -7
- package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
- package/src/tools/ask-question/ask-question-tool.ts +304 -0
- package/src/tools/browser/browser-execution.ts +15 -11
- package/src/tools/computer-use/definitions.ts +3 -3
- package/src/tools/credentials/vault.ts +1 -1
- package/src/tools/document/document-tool.ts +124 -1
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +5 -2
- package/src/tools/host-filesystem/transfer.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +1 -1
- package/src/tools/memory/register.ts +1 -9
- package/src/tools/permission-checker.ts +1 -1
- package/src/tools/registry.ts +17 -7
- package/src/tools/schedule/create.ts +2 -2
- package/src/tools/schema-transforms.ts +7 -2
- package/src/tools/side-effects.ts +1 -0
- package/src/tools/skills/delete-managed.ts +4 -4
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/scaffold-managed.ts +3 -2
- package/src/tools/subagent/notify-parent.ts +1 -1
- package/src/tools/system/request-permission.ts +2 -2
- package/src/tools/terminal/safe-env.ts +60 -1
- package/src/tools/tool-manifest.ts +2 -0
- package/src/tools/types.ts +107 -21
- package/src/tools/ui-surface/definitions.ts +6 -5
- package/src/tts/__tests__/provider-adapters.test.ts +76 -2
- package/src/tts/providers/elevenlabs-provider.ts +75 -1
- package/src/types/onboarding-context.ts +2 -0
- package/src/util/errors.ts +17 -0
- package/src/util/platform.ts +10 -0
- package/src/watcher/__tests__/engine.test.ts +22 -0
- package/src/watcher/engine.ts +6 -2
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
- package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
- package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
- package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
- package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/migrations/runner.ts +39 -9
- package/src/workspace/migrations/types.ts +4 -0
- package/examples/plugins/echo/bun.lock +0 -25
- package/src/__tests__/context-window-manager.test.ts +0 -2481
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
- package/src/context/__tests__/compact-prompt.test.ts +0 -63
- package/src/context/prompts/compact.md +0 -26
- package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
- package/src/runtime/guardian-action-conversation-turn.ts +0 -99
|
@@ -43,9 +43,20 @@ interface GitHubRelease {
|
|
|
43
43
|
prerelease: boolean;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Cache shape persisted under `<workspace>/data/changelog-cache.json`.
|
|
48
|
+
*
|
|
49
|
+
* - `recent` holds the most recent stable releases, capped at
|
|
50
|
+
* `CACHE_STABLE_LIMIT`. TTL-gated via `fetchedAt`.
|
|
51
|
+
* - `byTag` is a content-addressed slot for single-tag lookups. Release
|
|
52
|
+
* tags are immutable once published, so entries here are kept without a
|
|
53
|
+
* TTL — first `show <tag>` populates, subsequent calls short-circuit
|
|
54
|
+
* the fetch.
|
|
55
|
+
*/
|
|
46
56
|
interface CacheStore {
|
|
47
57
|
fetchedAt: string;
|
|
48
|
-
|
|
58
|
+
recent: GitHubRelease[];
|
|
59
|
+
byTag: Record<string, GitHubRelease>;
|
|
49
60
|
}
|
|
50
61
|
|
|
51
62
|
// ── Config ───────────────────────────────────────────────────────────
|
|
@@ -54,6 +65,19 @@ const REPO = "vellum-ai/vellum-assistant";
|
|
|
54
65
|
const LIST_TTL_MS = 60 * 60 * 1000;
|
|
55
66
|
const DEFAULT_LIST_LIMIT = 30;
|
|
56
67
|
const MAX_LIST_LIMIT = 100;
|
|
68
|
+
/**
|
|
69
|
+
* Maximum number of stable releases we persist in the rolling `recent` slot.
|
|
70
|
+
* Most callers only ever read the latest one or two; capping the cache keeps
|
|
71
|
+
* the file small and the network round-trip predictable.
|
|
72
|
+
*/
|
|
73
|
+
const CACHE_STABLE_LIMIT = 5;
|
|
74
|
+
/**
|
|
75
|
+
* When fetching, request a page size that comfortably covers the caller's
|
|
76
|
+
* requested limit plus a small buffer to absorb the occasional draft or
|
|
77
|
+
* pre-release without forcing a second round-trip.
|
|
78
|
+
*/
|
|
79
|
+
const STABLE_BUFFER = 5;
|
|
80
|
+
const MIN_FETCH_PAGE_SIZE = 30;
|
|
57
81
|
const FETCH_TIMEOUT_MS = 10_000;
|
|
58
82
|
const USER_AGENT = "vellum-assistant-cli";
|
|
59
83
|
|
|
@@ -72,7 +96,9 @@ function readCache(): CacheStore | null {
|
|
|
72
96
|
) as Partial<CacheStore>;
|
|
73
97
|
if (
|
|
74
98
|
typeof parsed.fetchedAt !== "string" ||
|
|
75
|
-
!Array.isArray(parsed.
|
|
99
|
+
!Array.isArray(parsed.recent) ||
|
|
100
|
+
typeof parsed.byTag !== "object" ||
|
|
101
|
+
parsed.byTag === null
|
|
76
102
|
) {
|
|
77
103
|
return null;
|
|
78
104
|
}
|
|
@@ -122,8 +148,20 @@ function describeGithubError(status: number, body: string): string {
|
|
|
122
148
|
return `GitHub API error ${status}: ${body || "(no body)"}`;
|
|
123
149
|
}
|
|
124
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Compute the per-page size for a fetch that needs to cover `limit` stable
|
|
153
|
+
* releases. The buffer absorbs drafts/prereleases without paginating; we cap
|
|
154
|
+
* at `MAX_LIST_LIMIT` because that's GitHub's per-page maximum.
|
|
155
|
+
*/
|
|
156
|
+
function pageSizeFor(limit: number): number {
|
|
157
|
+
return Math.min(
|
|
158
|
+
MAX_LIST_LIMIT,
|
|
159
|
+
Math.max(limit + STABLE_BUFFER, MIN_FETCH_PAGE_SIZE),
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
125
163
|
async function fetchReleaseList(limit: number): Promise<GitHubRelease[]> {
|
|
126
|
-
const url = `https://api.github.com/repos/${REPO}/releases?per_page=${limit}`;
|
|
164
|
+
const url = `https://api.github.com/repos/${REPO}/releases?per_page=${pageSizeFor(limit)}`;
|
|
127
165
|
const res = await githubFetch(url);
|
|
128
166
|
if (!res.ok) {
|
|
129
167
|
const text = await res.text().catch(() => "");
|
|
@@ -150,28 +188,72 @@ interface LoadOpts {
|
|
|
150
188
|
limit: number;
|
|
151
189
|
}
|
|
152
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Persist the rolling list of stable releases. Cap at `CACHE_STABLE_LIMIT`.
|
|
193
|
+
* Mirror each entry into `byTag` so single-tag lookups short-circuit fetches
|
|
194
|
+
* for any tag that appears in the rolling list. Preserves any existing
|
|
195
|
+
* tag-keyed entries (which never expire).
|
|
196
|
+
*/
|
|
197
|
+
function persistRecent(stable: GitHubRelease[]): void {
|
|
198
|
+
const previous = readCache();
|
|
199
|
+
const recent = stable.slice(0, CACHE_STABLE_LIMIT);
|
|
200
|
+
const byTag: Record<string, GitHubRelease> = { ...(previous?.byTag ?? {}) };
|
|
201
|
+
for (const r of recent) {
|
|
202
|
+
byTag[r.tag_name] = r;
|
|
203
|
+
}
|
|
204
|
+
writeCache({ fetchedAt: new Date().toISOString(), recent, byTag });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Persist a single tag fetched via `show <tag>`. Tags are immutable; this
|
|
209
|
+
* entry survives subsequent list refreshes.
|
|
210
|
+
*/
|
|
211
|
+
function persistByTag(release: GitHubRelease): void {
|
|
212
|
+
const previous = readCache();
|
|
213
|
+
writeCache({
|
|
214
|
+
fetchedAt: previous?.fetchedAt ?? new Date().toISOString(),
|
|
215
|
+
recent: previous?.recent ?? [],
|
|
216
|
+
byTag: { ...(previous?.byTag ?? {}), [release.tag_name]: release },
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Returns up to `opts.limit` stable releases, newest first. Uses the cached
|
|
222
|
+
* rolling list when fresh and large enough; otherwise fetches a single page
|
|
223
|
+
* sized via `pageSizeFor` and filters stable. The cached rolling list is
|
|
224
|
+
* capped at `CACHE_STABLE_LIMIT` even if the caller asks for more.
|
|
225
|
+
*/
|
|
153
226
|
async function loadReleases(opts: LoadOpts): Promise<GitHubRelease[]> {
|
|
154
227
|
if (!opts.noCache) {
|
|
155
228
|
const cache = readCache();
|
|
156
|
-
if (cache && !isStale(cache) && cache.
|
|
157
|
-
return cache.
|
|
229
|
+
if (cache && !isStale(cache) && cache.recent.length >= opts.limit) {
|
|
230
|
+
return cache.recent.slice(0, opts.limit);
|
|
158
231
|
}
|
|
159
232
|
}
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
233
|
+
const raw = await fetchReleaseList(opts.limit);
|
|
234
|
+
const stable = stableReleases(raw);
|
|
235
|
+
persistRecent(stable);
|
|
236
|
+
return stable.slice(0, opts.limit);
|
|
163
237
|
}
|
|
164
238
|
|
|
239
|
+
/**
|
|
240
|
+
* Returns the release for a specific tag. Prefers the cached `byTag` slot
|
|
241
|
+
* (immutable, no TTL), then the rolling recent list, then the network.
|
|
242
|
+
* Persists fetched results into `byTag` so subsequent lookups short-circuit.
|
|
243
|
+
*/
|
|
165
244
|
async function loadReleaseByTag(
|
|
166
245
|
tag: string,
|
|
167
246
|
opts: { noCache: boolean },
|
|
168
247
|
): Promise<GitHubRelease | null> {
|
|
169
248
|
if (!opts.noCache) {
|
|
170
249
|
const cache = readCache();
|
|
171
|
-
const hit =
|
|
250
|
+
const hit =
|
|
251
|
+
cache?.byTag[tag] ?? cache?.recent.find((r) => r.tag_name === tag);
|
|
172
252
|
if (hit) return hit;
|
|
173
253
|
}
|
|
174
|
-
|
|
254
|
+
const release = await fetchReleaseByTag(tag);
|
|
255
|
+
if (release) persistByTag(release);
|
|
256
|
+
return release;
|
|
175
257
|
}
|
|
176
258
|
|
|
177
259
|
// ── Filtering / version utilities ────────────────────────────────────
|
|
@@ -264,11 +346,12 @@ interface DefaultOpts extends CommonOpts {
|
|
|
264
346
|
async function runDefault(opts: DefaultOpts): Promise<void> {
|
|
265
347
|
const noCache = opts.cache === false;
|
|
266
348
|
const useJson = opts.json === true;
|
|
267
|
-
const limit = parseLimit(opts.limit, DEFAULT_LIST_LIMIT);
|
|
268
349
|
|
|
269
350
|
if (opts.since) {
|
|
351
|
+
// --since needs the full rolling list so we can filter by tag.
|
|
352
|
+
const limit = parseLimit(opts.limit, DEFAULT_LIST_LIMIT);
|
|
270
353
|
const floor = normalizeTag(opts.since);
|
|
271
|
-
const all =
|
|
354
|
+
const all = await loadReleases({ noCache, limit });
|
|
272
355
|
const newer = all
|
|
273
356
|
.filter((r) => compareTags(r.tag_name, floor) > 0)
|
|
274
357
|
.sort((a, b) => compareTags(b.tag_name, a.tag_name));
|
|
@@ -285,7 +368,10 @@ async function runDefault(opts: DefaultOpts): Promise<void> {
|
|
|
285
368
|
return;
|
|
286
369
|
}
|
|
287
370
|
|
|
288
|
-
|
|
371
|
+
// Bare default action only needs the latest stable release. Asking for 1
|
|
372
|
+
// means a populated cache (even with a single entry) is enough to short-
|
|
373
|
+
// circuit the network round-trip.
|
|
374
|
+
const releases = await loadReleases({ noCache, limit: 1 });
|
|
289
375
|
if (releases.length === 0) {
|
|
290
376
|
emitError("No releases found.");
|
|
291
377
|
}
|
|
@@ -310,10 +396,7 @@ async function runList(opts: CommonOpts): Promise<void> {
|
|
|
310
396
|
const noCache = opts.cache === false;
|
|
311
397
|
const useJson = opts.json === true;
|
|
312
398
|
const limit = parseLimit(opts.limit, DEFAULT_LIST_LIMIT);
|
|
313
|
-
const releases =
|
|
314
|
-
0,
|
|
315
|
-
limit,
|
|
316
|
-
);
|
|
399
|
+
const releases = await loadReleases({ noCache, limit });
|
|
317
400
|
if (useJson) {
|
|
318
401
|
emit(JSON.stringify({ releases }, null, 2));
|
|
319
402
|
return;
|
|
@@ -335,15 +418,17 @@ export function registerChangelogCommand(program: Command): void {
|
|
|
335
418
|
registerCommand(program, {
|
|
336
419
|
name: "changelog",
|
|
337
420
|
transport: "local",
|
|
338
|
-
description:
|
|
421
|
+
description:
|
|
422
|
+
"Show release notes of the Vellum Assistant to see what new capabilities you have!",
|
|
339
423
|
build: (cmd) => {
|
|
340
424
|
cmd.addHelpText(
|
|
341
425
|
"after",
|
|
342
426
|
`
|
|
343
427
|
Release notes are fetched on demand from the public GitHub Releases of
|
|
344
|
-
${REPO}.
|
|
345
|
-
pass --no-cache to bypass
|
|
346
|
-
because release tags are
|
|
428
|
+
${REPO}. The most recent ${CACHE_STABLE_LIMIT} stable releases are cached
|
|
429
|
+
locally for ${LIST_TTL_MS / 60_000} minutes; pass --no-cache to bypass.
|
|
430
|
+
Specific tags are cached indefinitely once seen because release tags are
|
|
431
|
+
immutable.
|
|
347
432
|
|
|
348
433
|
Examples:
|
|
349
434
|
$ assistant changelog Show the latest release
|
|
@@ -391,24 +476,3 @@ Examples:
|
|
|
391
476
|
},
|
|
392
477
|
});
|
|
393
478
|
}
|
|
394
|
-
|
|
395
|
-
// ── Test-only exports ────────────────────────────────────────────────
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Internal helpers exported for unit tests only. Not part of the public CLI
|
|
399
|
-
* contract — do not import from outside `cli/commands/__tests__`.
|
|
400
|
-
*/
|
|
401
|
-
export const __testing = {
|
|
402
|
-
compareTags,
|
|
403
|
-
normalizeTag,
|
|
404
|
-
stableReleases,
|
|
405
|
-
renderRelease,
|
|
406
|
-
renderList,
|
|
407
|
-
parseLimit,
|
|
408
|
-
readCache,
|
|
409
|
-
writeCache,
|
|
410
|
-
isStale,
|
|
411
|
-
loadReleases,
|
|
412
|
-
loadReleaseByTag,
|
|
413
|
-
getCachePath,
|
|
414
|
-
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
|
|
1
3
|
import type { Command } from "commander";
|
|
2
4
|
|
|
3
5
|
import { cliIpcCall, exitFromIpcResult } from "../../ipc/cli-client.js";
|
|
@@ -7,6 +9,98 @@ import { log } from "../logger.js";
|
|
|
7
9
|
import { registerConversationsDeferCommand } from "./conversations-defer.js";
|
|
8
10
|
import { registerConversationsImportCommand } from "./conversations-import.js";
|
|
9
11
|
|
|
12
|
+
type ConversationSeedMessage = {
|
|
13
|
+
role: "user" | "assistant";
|
|
14
|
+
content: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function readSeedMessages(
|
|
18
|
+
contentFile?: string,
|
|
19
|
+
): ConversationSeedMessage[] | undefined {
|
|
20
|
+
if (!contentFile) return undefined;
|
|
21
|
+
if (!existsSync(contentFile)) {
|
|
22
|
+
log.error(`Error: content file not found: ${contentFile}`);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let parsed: unknown;
|
|
28
|
+
try {
|
|
29
|
+
parsed = JSON.parse(readFileSync(contentFile, "utf-8"));
|
|
30
|
+
} catch (err) {
|
|
31
|
+
log.error(
|
|
32
|
+
`Error: failed to read content file: ${err instanceof Error ? err.message : String(err)}`,
|
|
33
|
+
);
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!Array.isArray(parsed)) {
|
|
39
|
+
log.error("Error: content file must contain an array of messages");
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const messages: ConversationSeedMessage[] = [];
|
|
45
|
+
for (const [index, value] of parsed.entries()) {
|
|
46
|
+
if (
|
|
47
|
+
typeof value !== "object" ||
|
|
48
|
+
value === null ||
|
|
49
|
+
!("role" in value) ||
|
|
50
|
+
!("content" in value)
|
|
51
|
+
) {
|
|
52
|
+
log.error(`Error: message ${index} must include role and content`);
|
|
53
|
+
process.exitCode = 1;
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
const role = (value as { role?: unknown }).role;
|
|
57
|
+
const content = (value as { content?: unknown }).content;
|
|
58
|
+
if (
|
|
59
|
+
(role !== "user" && role !== "assistant") ||
|
|
60
|
+
typeof content !== "string"
|
|
61
|
+
) {
|
|
62
|
+
log.error(
|
|
63
|
+
`Error: message ${index} must have role user|assistant and string content`,
|
|
64
|
+
);
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
messages.push({ role, content });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return messages;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function createConversationCli(
|
|
75
|
+
title: string | undefined,
|
|
76
|
+
opts?: { contentFile?: string },
|
|
77
|
+
): Promise<void> {
|
|
78
|
+
const messages = readSeedMessages(opts?.contentFile);
|
|
79
|
+
if (process.exitCode) return;
|
|
80
|
+
|
|
81
|
+
const result = await cliIpcCall<{
|
|
82
|
+
id: string;
|
|
83
|
+
title: string;
|
|
84
|
+
conversationKey: string;
|
|
85
|
+
messagesInserted: number;
|
|
86
|
+
}>("conversation_create_cli", {
|
|
87
|
+
body: {
|
|
88
|
+
title,
|
|
89
|
+
messages,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (!result.ok) return exitFromIpcResult(result);
|
|
94
|
+
|
|
95
|
+
const conversation = result.result!;
|
|
96
|
+
const seedSuffix = conversation.messagesInserted
|
|
97
|
+
? `, seeded ${conversation.messagesInserted} messages`
|
|
98
|
+
: "";
|
|
99
|
+
log.info(
|
|
100
|
+
`Created conversation: ${conversation.title} (${conversation.id}), conversation key: ${conversation.conversationKey}${seedSuffix}`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
10
104
|
export function registerConversationsCommand(program: Command): void {
|
|
11
105
|
registerCommand(program, {
|
|
12
106
|
name: "conversations",
|
|
@@ -85,6 +179,7 @@ Examples:
|
|
|
85
179
|
conversations
|
|
86
180
|
.command("new [title]")
|
|
87
181
|
.description("Create a new conversation")
|
|
182
|
+
.option("--content-file <path>", "Seed messages from a JSON file")
|
|
88
183
|
.addHelpText(
|
|
89
184
|
"after",
|
|
90
185
|
`
|
|
@@ -92,26 +187,18 @@ Arguments:
|
|
|
92
187
|
title Optional conversation title (string). If omitted, a default title is
|
|
93
188
|
assigned by the assistant.
|
|
94
189
|
|
|
95
|
-
|
|
190
|
+
The content file must be a JSON array of { role, content } messages.
|
|
191
|
+
|
|
192
|
+
Creates a new conversation and prints its title, ID, and generated conversation
|
|
193
|
+
key.
|
|
96
194
|
|
|
97
195
|
Examples:
|
|
98
196
|
$ assistant conversations new
|
|
99
197
|
$ assistant conversations new "Project planning"
|
|
198
|
+
$ assistant conversations new --content-file /tmp/seed.json
|
|
100
199
|
$ assistant conversations new "Bug triage 2026-03-05"`,
|
|
101
200
|
)
|
|
102
|
-
.action(
|
|
103
|
-
const result = await cliIpcCall<{ id: string; title: string }>(
|
|
104
|
-
"conversation_create_cli",
|
|
105
|
-
{ body: { title } },
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
if (!result.ok) return exitFromIpcResult(result);
|
|
109
|
-
|
|
110
|
-
const conversation = result.result!;
|
|
111
|
-
log.info(
|
|
112
|
-
`Created conversation: ${conversation.title} (${conversation.id})`,
|
|
113
|
-
);
|
|
114
|
-
});
|
|
201
|
+
.action(createConversationCli);
|
|
115
202
|
|
|
116
203
|
// -------------------------------------------------------------------
|
|
117
204
|
// rename
|
|
@@ -278,9 +365,7 @@ Examples:
|
|
|
278
365
|
|
|
279
366
|
if (!result.ok) return exitFromIpcResult(result);
|
|
280
367
|
|
|
281
|
-
log.info(
|
|
282
|
-
`Cleared ${result.result!.cleared} conversations. Done.`,
|
|
283
|
-
);
|
|
368
|
+
log.info(`Cleared ${result.result!.cleared} conversations. Done.`);
|
|
284
369
|
});
|
|
285
370
|
|
|
286
371
|
// -------------------------------------------------------------------
|
|
@@ -3,6 +3,10 @@ import type { Command } from "commander";
|
|
|
3
3
|
import { startCli } from "../../cli.js";
|
|
4
4
|
import { shouldAutoStartDaemon } from "../../daemon/connection-policy.js";
|
|
5
5
|
import { ensureDaemonRunning } from "../../daemon/daemon-control.js";
|
|
6
|
+
import {
|
|
7
|
+
findClosestCommand,
|
|
8
|
+
formatUnknownCommandMessage,
|
|
9
|
+
} from "../lib/unknown-command.js";
|
|
6
10
|
|
|
7
11
|
export function registerDefaultAction(program: Command): void {
|
|
8
12
|
program.action(async (_options: unknown, cmd: Command) => {
|
|
@@ -10,16 +14,16 @@ export function registerDefaultAction(program: Command): void {
|
|
|
10
14
|
// args instead of raising an error. Detect this case and fail with a
|
|
11
15
|
// helpful message so users don't silently get the interactive CLI when
|
|
12
16
|
// they mistype a command name.
|
|
17
|
+
//
|
|
18
|
+
// The `assistant <unknown> --help` path is intercepted earlier (see
|
|
19
|
+
// src/index.ts) because Commander's `--help` short-circuit fires before
|
|
20
|
+
// this action runs. This branch covers `assistant <unknown>` with no
|
|
21
|
+
// `--help` flag.
|
|
13
22
|
if (cmd.args.length > 0) {
|
|
14
23
|
const unknown = cmd.args[0];
|
|
15
24
|
const available = cmd.commands.map((c) => c.name());
|
|
16
25
|
const suggestion = findClosestCommand(unknown, available);
|
|
17
|
-
|
|
18
|
-
if (suggestion) {
|
|
19
|
-
lines.push(`(Did you mean '${suggestion}'?)`);
|
|
20
|
-
}
|
|
21
|
-
lines.push(`Run 'assistant --help' to see a list of available commands.`);
|
|
22
|
-
cmd.error(lines.join("\n"), {
|
|
26
|
+
cmd.error(formatUnknownCommandMessage({ token: unknown, suggestion }), {
|
|
23
27
|
code: "commander.unknownCommand",
|
|
24
28
|
exitCode: 1,
|
|
25
29
|
});
|
|
@@ -32,50 +36,3 @@ export function registerDefaultAction(program: Command): void {
|
|
|
32
36
|
await startCli();
|
|
33
37
|
});
|
|
34
38
|
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Find the closest matching command name using Levenshtein distance.
|
|
38
|
-
* Returns the best match if the distance is ≤ 40% of the longer string's
|
|
39
|
-
* length, otherwise returns undefined.
|
|
40
|
-
*/
|
|
41
|
-
function findClosestCommand(
|
|
42
|
-
input: string,
|
|
43
|
-
candidates: string[],
|
|
44
|
-
): string | undefined {
|
|
45
|
-
let best: string | undefined;
|
|
46
|
-
let bestDist = Infinity;
|
|
47
|
-
|
|
48
|
-
for (const name of candidates) {
|
|
49
|
-
const dist = levenshtein(input.toLowerCase(), name.toLowerCase());
|
|
50
|
-
if (dist < bestDist) {
|
|
51
|
-
bestDist = dist;
|
|
52
|
-
best = name;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Only suggest if the edit distance is at most 40% of the longer string
|
|
57
|
-
const maxLen = Math.max(input.length, best?.length ?? 0);
|
|
58
|
-
if (best && bestDist <= Math.ceil(maxLen * 0.4)) {
|
|
59
|
-
return best;
|
|
60
|
-
}
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function levenshtein(a: string, b: string): number {
|
|
65
|
-
const m = a.length;
|
|
66
|
-
const n = b.length;
|
|
67
|
-
const dp: number[][] = Array.from({ length: m + 1 }, () =>
|
|
68
|
-
Array(n + 1).fill(0),
|
|
69
|
-
);
|
|
70
|
-
for (let i = 0; i <= m; i++) dp[i][0] = i;
|
|
71
|
-
for (let j = 0; j <= n; j++) dp[0][j] = j;
|
|
72
|
-
for (let i = 1; i <= m; i++) {
|
|
73
|
-
for (let j = 1; j <= n; j++) {
|
|
74
|
-
dp[i][j] =
|
|
75
|
-
a[i - 1] === b[j - 1]
|
|
76
|
-
? dp[i - 1][j - 1]
|
|
77
|
-
: 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return dp[m][n];
|
|
81
|
-
}
|