@vellumai/assistant 0.8.6 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -4
- package/Dockerfile +1 -0
- package/bun.lock +11 -2
- package/docker-entrypoint.sh +8 -6
- package/docs/plugins.md +63 -28
- package/examples/plugins/echo/register.ts +4 -7
- package/knip.json +1 -0
- package/node_modules/@vellumai/environments/bun.lock +24 -0
- package/node_modules/@vellumai/environments/package.json +18 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +95 -0
- package/node_modules/@vellumai/environments/src/index.ts +11 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +73 -0
- package/node_modules/@vellumai/environments/src/types.ts +70 -0
- package/node_modules/@vellumai/environments/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +11 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +3 -4
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +6 -2
- package/openapi.yaml +3735 -353
- package/package.json +7 -3
- package/scripts/generate-openapi.ts +20 -13
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
- package/src/__tests__/agent-loop-exit-reason.test.ts +240 -39
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +19 -32
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +6 -4
- package/src/__tests__/agent-loop-thinking.test.ts +17 -12
- package/src/__tests__/agent-loop.test.ts +207 -341
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +4 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +22 -40
- package/src/__tests__/anthropic-provider.test.ts +201 -55
- package/src/__tests__/app-builder-skill-instructions.test.ts +22 -0
- package/src/__tests__/app-control-flow.test.ts +5 -0
- package/src/__tests__/approval-cascade.test.ts +4 -11
- package/src/__tests__/approval-routes-http.test.ts +4 -2
- package/src/__tests__/assistant-event.test.ts +15 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/avatar-e2e.test.ts +7 -37
- package/src/__tests__/avatar-generator.test.ts +12 -42
- package/src/__tests__/avatar-identity-sync.test.ts +28 -3
- package/src/__tests__/background-shell-bash.test.ts +3 -7
- package/src/__tests__/btw-routes.test.ts +7 -12
- package/src/__tests__/call-pointer-messages.test.ts +5 -3
- package/src/__tests__/call-site-routing-provider.test.ts +22 -40
- package/src/__tests__/catalog-files.test.ts +1 -0
- package/src/__tests__/channel-approval-routes.test.ts +48 -20
- package/src/__tests__/channel-approvals.test.ts +3 -1
- package/src/__tests__/channel-invite-transport.test.ts +1 -5
- package/src/__tests__/channel-readiness-routes.test.ts +0 -4
- package/src/__tests__/channel-readiness-slack-remote.test.ts +2 -7
- package/src/__tests__/channel-retry-sweep.test.ts +71 -79
- package/src/__tests__/circuit-breaker-pipeline.test.ts +3 -3
- package/src/__tests__/clawhub-files.test.ts +1 -0
- package/src/__tests__/compaction-events.test.ts +5 -17
- package/src/__tests__/compaction-pipeline.test.ts +1 -1
- package/src/__tests__/compaction-timeout-recovery.test.ts +37 -48
- package/src/__tests__/compaction-trail-store.test.ts +1 -79
- package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
- package/src/__tests__/computer-use-tools.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +28 -0
- package/src/__tests__/context-search-agent-runner.test.ts +6 -3
- package/src/__tests__/context-token-estimator.test.ts +34 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +14 -7
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +12 -27
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +430 -90
- package/src/__tests__/conversation-agent-loop.test.ts +581 -62
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -3
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clear-safety.test.ts +20 -10
- package/src/__tests__/conversation-confirmation-signals.test.ts +15 -45
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-disk-view.test.ts +10 -17
- package/src/__tests__/conversation-fork-crud.test.ts +86 -172
- package/src/__tests__/conversation-fork-route.test.ts +16 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
- package/src/__tests__/conversation-lifecycle.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +3 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -1
- package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
- package/src/__tests__/conversation-pairing.test.ts +34 -4
- package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -0
- package/src/__tests__/conversation-process-callsite.test.ts +27 -30
- package/src/__tests__/conversation-provider-retry-repair.test.ts +53 -44
- package/src/__tests__/conversation-queue.test.ts +270 -164
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -2
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +20 -22
- package/src/__tests__/conversation-runtime-workspace.test.ts +19 -1
- package/src/__tests__/conversation-slash-queue.test.ts +37 -31
- package/src/__tests__/conversation-slash-unknown.test.ts +13 -15
- package/src/__tests__/conversation-speed-override.test.ts +8 -22
- package/src/__tests__/conversation-stream-state.test.ts +484 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +6 -15
- package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
- package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -2
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -15
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +23 -11
- package/src/__tests__/conversation-unread-route.test.ts +14 -2
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-wipe.test.ts +1 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +3 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +48 -22
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +27 -7
- package/src/__tests__/credential-execution-tools.test.ts +1 -2
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/cross-provider-web-search.test.ts +6 -2
- package/src/__tests__/cu-unified-flow.test.ts +26 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +11 -0
- package/src/__tests__/disk-pressure-guard.test.ts +66 -0
- package/src/__tests__/disk-pressure-routes.test.ts +9 -2
- package/src/__tests__/dm-persistence.test.ts +7 -2
- package/src/__tests__/dynamic-page-surface.test.ts +68 -0
- package/src/__tests__/edit-propagation.test.ts +1 -2
- package/src/__tests__/empty-response-pipeline.test.ts +127 -5
- package/src/__tests__/filing-service.test.ts +2 -2
- package/src/__tests__/first-greeting.test.ts +55 -14
- package/src/__tests__/gemini-inline-media.test.ts +78 -0
- package/src/__tests__/gemini-provider.test.ts +351 -28
- package/src/__tests__/guardian-routing-state.test.ts +60 -71
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +9 -7
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +2 -1
- package/src/__tests__/history-repair-hook.test.ts +161 -0
- package/src/__tests__/history-repair-observability.test.ts +1 -1
- package/src/__tests__/history-repair.test.ts +2 -1
- package/src/__tests__/host-app-control-proxy.test.ts +2 -0
- package/src/__tests__/host-cu-proxy.test.ts +2 -0
- package/src/__tests__/host-file-edit-tool.test.ts +4 -2
- package/src/__tests__/host-file-proxy.test.ts +31 -0
- package/src/__tests__/host-file-read-tool.test.ts +4 -2
- package/src/__tests__/host-file-write-tool.test.ts +9 -3
- package/src/__tests__/host-proxy-preactivation.test.ts +53 -14
- package/src/__tests__/host-shell-tool.test.ts +9 -4
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/identity-intro-cache.test.ts +35 -14
- package/src/__tests__/inbound-slack-persistence.test.ts +7 -2
- package/src/__tests__/injector-background-turn.test.ts +1 -1
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-disk-pressure.test.ts +1 -1
- package/src/__tests__/injector-document-comments.test.ts +1 -1
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +1 -1
- package/src/__tests__/injector-v3-suppression.test.ts +220 -0
- package/src/__tests__/list-messages-attachments.test.ts +7 -8
- package/src/__tests__/list-messages-hidden-metadata.test.ts +17 -15
- package/src/__tests__/list-messages-page-latest.test.ts +0 -1
- package/src/__tests__/list-messages-tool-merge.test.ts +36 -6
- package/src/__tests__/llm-call-pipeline.test.ts +21 -15
- package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
- package/src/__tests__/llm-resolver.test.ts +23 -47
- package/src/__tests__/llm-usage-store.test.ts +45 -0
- package/src/__tests__/log-export-routes.test.ts +59 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +1 -8
- package/src/__tests__/mcp-auth-routes.test.ts +15 -10
- package/src/__tests__/mcp-health-check.test.ts +18 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +1 -1
- package/src/__tests__/memory-v2-static-injector.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +8 -4
- package/src/__tests__/migration-export-http.test.ts +12 -12
- package/src/__tests__/migration-import-commit-http.test.ts +8 -8
- package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +14 -20
- package/src/__tests__/notification-decision-identity.test.ts +9 -18
- package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
- package/src/__tests__/oauth-commands-routes.test.ts +1 -1
- package/src/__tests__/onboarding-template-contract.test.ts +10 -0
- package/src/__tests__/openai-provider.test.ts +66 -70
- package/src/__tests__/openai-responses-provider.test.ts +21 -77
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -1
- package/src/__tests__/overflow-reduce-pipeline.test.ts +2 -4
- package/src/__tests__/parallel-tool.benchmark.test.ts +24 -36
- package/src/__tests__/persistence-pipeline.test.ts +15 -26
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -1
- package/src/__tests__/pipeline-runner.test.ts +2 -3
- package/src/__tests__/plugin-bootstrap.test.ts +51 -25
- package/src/__tests__/plugin-route-contribution.test.ts +6 -16
- package/src/__tests__/plugin-skill-contribution.test.ts +7 -17
- package/src/__tests__/plugin-tool-contribution.test.ts +10 -26
- package/src/__tests__/plugin-types.test.ts +7 -14
- package/src/__tests__/prechat-onboarding-contract.test.ts +23 -0
- package/src/__tests__/process-message-background-slack.test.ts +17 -16
- package/src/__tests__/process-message-display-content.test.ts +30 -42
- package/src/__tests__/provider-commit-message-generator.test.ts +19 -14
- package/src/__tests__/provider-error-scenarios.test.ts +7 -6
- package/src/__tests__/provider-platform-proxy-integration.test.ts +3 -8
- package/src/__tests__/provider-send-message-override-profile.test.ts +9 -25
- package/src/__tests__/provider-streaming.benchmark.test.ts +12 -22
- package/src/__tests__/provider-usage-tracking.test.ts +0 -6
- package/src/__tests__/ratelimit.test.ts +9 -4
- package/src/__tests__/relay-server.test.ts +20 -13
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +5 -8
- package/src/__tests__/retry-thinking-tool-choice.test.ts +10 -13
- package/src/__tests__/retry-verbosity-normalization.test.ts +5 -8
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +353 -0
- package/src/__tests__/schedule-routes.test.ts +80 -10
- package/src/__tests__/schedule-store.test.ts +67 -0
- package/src/__tests__/schedule-tools.test.ts +125 -0
- package/src/__tests__/secret-ingress-http.test.ts +2 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +11 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +11 -9
- package/src/__tests__/secret-response-routing.test.ts +13 -11
- package/src/__tests__/send-endpoint-busy.test.ts +2 -1
- package/src/__tests__/shell-observability.test.ts +249 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +11 -11
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +10 -10
- package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
- package/src/__tests__/skillssh-files.test.ts +1 -0
- package/src/__tests__/starter-task-flow.test.ts +6 -6
- package/src/__tests__/strip-memory-injections.test.ts +102 -14
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +19 -16
- package/src/__tests__/system-prompt.test.ts +54 -0
- package/src/__tests__/terminal-tools.test.ts +3 -24
- package/src/__tests__/thread-backfill.test.ts +4 -9
- package/src/__tests__/title-generate-pipeline.test.ts +1 -1
- package/src/__tests__/token-estimate-pipeline.test.ts +2 -4
- package/src/__tests__/tool-error-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execute-pipeline.test.ts +1 -1
- package/src/__tests__/tool-preview-lifecycle.test.ts +13 -11
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +9 -12
- package/src/__tests__/tool-result-truncation.test.ts +3 -1
- package/src/__tests__/tools-audio-read.test.ts +113 -0
- package/src/__tests__/turn-boundary-resolution.test.ts +44 -84
- package/src/__tests__/turn-events-store.test.ts +11 -7
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +8 -6
- package/src/__tests__/voice-session-bridge.test.ts +13 -7
- package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
- package/src/acp/prepare-agent-env.ts +52 -11
- package/src/agent/compaction-circuit.ts +140 -0
- package/src/agent/loop.ts +409 -85
- package/src/api/README.md +19 -17
- package/src/api/constants/tool-execution.ts +21 -0
- package/src/api/events/assistant-activity-state.ts +75 -0
- package/src/api/events/assistant-outbound-attachment.ts +25 -27
- package/src/api/events/assistant-text-delta.ts +6 -8
- package/src/api/events/assistant-turn-start.ts +5 -7
- package/src/api/events/avatar-updated.ts +24 -0
- package/src/api/events/compaction-circuit-closed.ts +26 -0
- package/src/api/events/compaction-circuit-open.ts +28 -0
- package/src/api/events/confirmation-request.ts +114 -0
- package/src/api/events/contact-request.ts +33 -0
- package/src/api/events/conversation-error.ts +77 -0
- package/src/api/events/conversation-list-invalidated.ts +38 -0
- package/src/api/events/conversation-title-updated.ts +24 -0
- package/src/api/events/disk-pressure-status-changed.ts +61 -0
- package/src/api/events/document-comment-created.ts +24 -28
- package/src/api/events/document-comment-deleted.ts +6 -8
- package/src/api/events/document-comment-reopened.ts +6 -8
- package/src/api/events/document-comment-resolved.ts +8 -10
- package/src/api/events/document-editor-update.ts +27 -0
- package/src/api/events/error.ts +32 -0
- package/src/api/events/generation-cancelled.ts +4 -6
- package/src/api/events/generation-handoff.ts +13 -15
- package/src/api/events/home-feed-updated.ts +26 -0
- package/src/api/events/identity-changed.ts +32 -0
- package/src/api/events/interaction-resolved.ts +50 -0
- package/src/api/events/message-complete.ts +10 -12
- package/src/api/events/message-dequeued.ts +21 -0
- package/src/api/events/message-queued-deleted.ts +23 -0
- package/src/api/events/message-queued.ts +22 -0
- package/src/api/events/message-request-complete.ts +29 -0
- package/src/api/events/navigate-settings.ts +20 -0
- package/src/api/events/notification-intent.ts +33 -0
- package/src/api/events/open-url.ts +6 -8
- package/src/api/events/question-request.ts +67 -0
- package/src/api/events/relationship-state-updated.ts +4 -6
- package/src/api/events/secret-request.ts +42 -0
- package/src/api/events/subagent-event.ts +79 -0
- package/src/api/events/subagent-spawned.ts +40 -0
- package/src/api/events/subagent-status-changed.ts +65 -0
- package/src/api/events/sync-changed.ts +29 -0
- package/src/api/events/tool-result.ts +129 -0
- package/src/api/events/tool-use-start.ts +8 -10
- package/src/api/events/turn-profile-auto-routed.ts +28 -0
- package/src/api/events/ui-surface-complete.ts +30 -0
- package/src/api/events/ui-surface-dismiss.ts +22 -0
- package/src/api/events/ui-surface-show.ts +67 -0
- package/src/api/events/ui-surface-update.ts +26 -0
- package/src/api/events/usage-update.ts +34 -0
- package/src/api/events/user-message-echo.ts +35 -0
- package/src/api/index.ts +354 -0
- package/src/api/requests/dictation.ts +45 -0
- package/src/api/responses/disk-pressure-status.ts +26 -0
- package/src/api/responses/home.ts +217 -0
- package/src/api/responses/llm-context-response.ts +2 -0
- package/src/api/responses/memory-v3-selection-log.ts +50 -0
- package/src/api/responses/subagent-detail.ts +48 -0
- package/src/approvals/guardian-decision-primitive.ts +7 -15
- package/src/approvals/guardian-request-resolvers.ts +6 -9
- package/src/avatar/__tests__/avatar-manifest.test.ts +236 -0
- package/src/avatar/__tests__/avatar-store.test.ts +193 -0
- package/src/avatar/avatar-manifest.ts +195 -0
- package/src/avatar/avatar-store.ts +113 -0
- package/src/avatar/traits-png-sync.ts +8 -2
- package/src/background-wake/next-wake.test.ts +31 -1
- package/src/background-wake/next-wake.ts +4 -1
- package/src/calls/call-conversation-messages.ts +6 -4
- package/src/calls/guardian-action-sweep.ts +6 -4
- package/src/calls/relay-server.ts +12 -8
- package/src/calls/voice-session-bridge.ts +13 -27
- package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
- package/src/cli/commands/avatar.ts +17 -11
- package/src/cli/commands/conversations.ts +15 -1
- package/src/cli/commands/db/__tests__/repair.test.ts +540 -0
- package/src/cli/commands/db/__tests__/status.test.ts +253 -0
- package/src/cli/commands/db/format.ts +48 -0
- package/src/cli/commands/db/index.ts +29 -0
- package/src/cli/commands/db/repair-step-conversation-backfill.ts +345 -0
- package/src/cli/commands/db/repair-step-integrity.ts +146 -0
- package/src/cli/commands/db/repair-steps.ts +164 -0
- package/src/cli/commands/db/repair.ts +141 -0
- package/src/cli/commands/db/status.ts +366 -0
- package/src/cli/commands/memory-v3.ts +159 -445
- package/src/cli/lib/cli-colors.ts +24 -6
- package/src/cli/program.ts +4 -5
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/assistant-feature-flags.ts +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -3
- package/src/config/bundled-skills/media-processing/services/reduce.ts +6 -9
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +7 -2
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/call-site-defaults.ts +2 -7
- package/src/config/feature-flag-registry.json +25 -9
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -226
- package/src/config/schemas/call-site-catalog.ts +8 -15
- package/src/config/schemas/llm.ts +2 -3
- package/src/config/schemas/memory-lifecycle.ts +24 -0
- package/src/config/schemas/memory-v2.ts +0 -253
- package/src/config/schemas/memory-v3.ts +39 -0
- package/src/config/schemas/memory.ts +6 -1
- package/src/config/schemas/timeouts.ts +3 -1
- package/src/context/compactor.ts +54 -31
- package/src/context/token-estimator.ts +19 -0
- package/src/context/tool-result-truncation.ts +1 -43
- package/src/context/window-manager.ts +138 -20
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +2 -2
- package/src/daemon/__tests__/web-search-status-text.test.ts +10 -6
- package/src/daemon/approval-generators.ts +4 -4
- package/src/daemon/config-watcher.ts +7 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +225 -88
- package/src/daemon/conversation-agent-loop.ts +284 -584
- package/src/daemon/conversation-error.ts +7 -7
- package/src/daemon/conversation-history.ts +22 -6
- package/src/daemon/conversation-launch.ts +4 -8
- package/src/daemon/conversation-lifecycle.ts +10 -38
- package/src/daemon/conversation-messaging.ts +1 -3
- package/src/daemon/conversation-notifiers.ts +7 -5
- package/src/daemon/conversation-process.ts +100 -79
- package/src/daemon/conversation-runtime-assembly.ts +47 -21
- package/src/daemon/conversation-store.ts +6 -5
- package/src/daemon/conversation-surfaces.ts +55 -69
- package/src/daemon/conversation-tool-setup.ts +3 -0
- package/src/daemon/conversation.ts +91 -126
- package/src/daemon/daemon-skill-host.ts +2 -6
- package/src/daemon/disk-pressure-guard.ts +35 -29
- package/src/daemon/external-plugins-bootstrap.ts +46 -24
- package/src/daemon/first-greeting.ts +26 -4
- package/src/daemon/guardian-action-generators.ts +2 -2
- package/src/daemon/handlers/conversations.ts +6 -22
- package/src/daemon/handlers/shared.ts +4 -0
- package/src/daemon/handlers/skills.ts +15 -14
- package/src/daemon/host-app-control-proxy.ts +54 -1
- package/src/daemon/host-cu-proxy.ts +46 -22
- package/src/daemon/host-file-proxy.ts +25 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -6
- package/src/daemon/lifecycle.ts +28 -55
- package/src/daemon/message-protocol.ts +2 -3
- package/src/daemon/message-provenance.ts +49 -0
- package/src/daemon/message-types/contacts.ts +3 -20
- package/src/daemon/message-types/conversations.ts +13 -111
- package/src/daemon/message-types/documents.ts +3 -9
- package/src/daemon/message-types/home.ts +4 -17
- package/src/daemon/message-types/integrations.ts +2 -6
- package/src/daemon/message-types/messages.ts +28 -343
- package/src/daemon/message-types/notifications.ts +2 -32
- package/src/daemon/message-types/settings.ts +3 -8
- package/src/daemon/message-types/skills.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/sync.ts +12 -25
- package/src/daemon/message-types/workspace.ts +3 -11
- package/src/daemon/process-message.ts +49 -46
- package/src/daemon/server.ts +12 -0
- package/src/daemon/tool-side-effects.ts +10 -7
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +11 -1
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -1
- package/src/heartbeat/heartbeat-run-store.ts +31 -0
- package/src/heartbeat/heartbeat-service.ts +16 -0
- package/src/home/feature-gate.ts +22 -0
- package/src/home/feed-types.ts +36 -221
- package/src/ipc/__tests__/email-ipc.test.ts +0 -9
- package/src/ipc/routes/__tests__/route-adapter.test.ts +244 -0
- package/src/ipc/routes/route-adapter.ts +45 -6
- package/src/ipc/skill-routes/__tests__/memory.test.ts +18 -9
- package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
- package/src/ipc/skill-routes/__tests__/registries.test.ts +28 -18
- package/src/ipc/skill-routes/memory.ts +26 -13
- package/src/ipc/skill-routes/providers.ts +5 -6
- package/src/ipc/skill-routes/registries.ts +13 -61
- package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -11
- package/src/memory/__tests__/conversation-queries.test.ts +192 -8
- package/src/memory/__tests__/db-maintenance.test.ts +128 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
- package/src/memory/__tests__/memory-retrospective-job.test.ts +10 -6
- package/src/memory/__tests__/memory-v3-selections-migration.test.ts +103 -0
- package/src/memory/context-search/agent-runner.ts +2 -4
- package/src/memory/conversation-crud.ts +39 -8
- package/src/memory/conversation-queries.ts +78 -22
- package/src/memory/db-init.ts +8 -0
- package/src/memory/db-maintenance.ts +18 -2
- package/src/memory/graph/consolidation.ts +8 -11
- package/src/memory/graph/conversation-graph-memory.ts +41 -8
- package/src/memory/graph/extraction.ts +6 -9
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.ts +20 -26
- package/src/memory/graph/tools.ts +4 -4
- package/src/memory/job-handlers/conversation-starters.ts +32 -32
- package/src/memory/job-handlers/summarization.ts +1 -2
- package/src/memory/jobs-store.ts +3 -1
- package/src/memory/jobs-worker.ts +51 -39
- package/src/memory/llm-request-log-source-clickhouse.ts +5 -31
- package/src/memory/llm-request-log-source-local.ts +0 -11
- package/src/memory/llm-request-log-source.ts +9 -25
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +10 -0
- package/src/memory/memory-marker.ts +17 -0
- package/src/memory/memory-retrospective-job.ts +6 -2
- package/src/memory/memory-v2-activation-log-store.ts +1 -83
- package/src/memory/migrations/267-llm-usage-events-add-assistant-version.ts +46 -0
- package/src/memory/migrations/268-add-memory-v3-selections.ts +28 -0
- package/src/memory/migrations/269-schedule-script-timeout.ts +11 -0
- package/src/memory/migrations/270-messages-role-created-at-index.ts +18 -0
- package/src/memory/migrations/__tests__/267-llm-usage-events-add-assistant-version.test.ts +117 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/schema/infrastructure.ts +11 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +124 -0
- package/src/memory/v2/__tests__/migration.test.ts +11 -3
- package/src/memory/v2/__tests__/page-index.test.ts +37 -1
- package/src/memory/v2/__tests__/router.test.ts +14 -4
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -5
- package/src/memory/v2/backfill-jobs.ts +6 -0
- package/src/memory/v2/consolidation-job.ts +89 -9
- package/src/memory/v2/migration.ts +5 -3
- package/src/memory/v2/page-index.ts +11 -0
- package/src/memory/v2/router.ts +8 -11
- package/src/memory/v2/sweep-job.ts +8 -11
- package/src/memory/v2/types.ts +1 -0
- package/src/memory/v3/__tests__/assign.test.ts +242 -0
- package/src/memory/v3/__tests__/capabilities.test.ts +118 -0
- package/src/memory/v3/__tests__/core.test.ts +39 -0
- package/src/memory/v3/__tests__/fixtures/eval-turns.json +36 -0
- package/src/memory/v3/__tests__/fixtures/live-turns.json +37 -0
- package/src/memory/v3/__tests__/health.test.ts +203 -0
- package/src/memory/v3/__tests__/live-integration.test.ts +330 -0
- package/src/memory/v3/__tests__/maintain-job.test.ts +288 -0
- package/src/memory/v3/__tests__/needle.test.ts +107 -0
- package/src/memory/v3/__tests__/orchestrate.test.ts +400 -0
- package/src/memory/v3/__tests__/reconcile.test.ts +274 -0
- package/src/memory/v3/__tests__/render-injection.test.ts +61 -0
- package/src/memory/v3/__tests__/router.test.ts +260 -0
- package/src/memory/v3/__tests__/selection-log-store.test.ts +179 -0
- package/src/memory/v3/__tests__/selector.test.ts +404 -0
- package/src/memory/v3/__tests__/shadow-plugin.test.ts +414 -0
- package/src/memory/v3/__tests__/snapshot.test.ts +168 -0
- package/src/memory/v3/__tests__/tree.test.ts +192 -0
- package/src/memory/v3/__tests__/types.test.ts +54 -0
- package/src/memory/v3/__tests__/working-set-eviction.test.ts +106 -0
- package/src/memory/v3/__tests__/working-set-skeleton.test.ts +44 -0
- package/src/memory/v3/assign.ts +268 -0
- package/src/memory/v3/capabilities.ts +124 -0
- package/src/memory/v3/core.ts +26 -0
- package/src/memory/v3/data/README.md +84 -0
- package/src/memory/v3/data/assignments.json +5 -0
- package/src/memory/v3/data/core.json +1 -0
- package/src/memory/v3/data/leaves/domain-a/topic-x.md +9 -0
- package/src/memory/v3/data/leaves/domain-a/topic-y.md +9 -0
- package/src/memory/v3/data/leaves/domain-b/topic-z.md +9 -0
- package/src/memory/v3/health.ts +0 -0
- package/src/memory/v3/maintain-job.ts +314 -0
- package/src/memory/v3/needle.ts +115 -0
- package/src/memory/v3/orchestrate.ts +114 -0
- package/src/memory/v3/page-content.ts +34 -0
- package/src/memory/v3/provider-blocks.ts +16 -0
- package/src/memory/v3/reconcile.ts +523 -0
- package/src/memory/v3/render-injection.ts +32 -0
- package/src/memory/v3/router.ts +184 -0
- package/src/memory/v3/selection-log-store.ts +84 -0
- package/src/memory/v3/selector.ts +211 -0
- package/src/memory/v3/shadow-plugin.ts +379 -0
- package/src/memory/v3/snapshot.ts +209 -0
- package/src/memory/v3/tree.ts +174 -0
- package/src/memory/v3/types.ts +46 -60
- package/src/memory/v3/working-set.ts +88 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1 -1
- package/src/messaging/providers/slack/render-transcript.ts +2 -2
- package/src/messaging/style-analyzer.ts +8 -11
- package/src/notifications/conversation-pairing.ts +8 -6
- package/src/notifications/decision-engine.ts +10 -13
- package/src/notifications/preference-extractor.ts +11 -14
- package/src/permissions/prompter.ts +42 -36
- package/src/permissions/question-prompter.test.ts +35 -26
- package/src/permissions/question-prompter.ts +6 -10
- package/src/plugin-api/index.ts +2 -0
- package/src/plugin-api/types.ts +25 -3
- package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +93 -0
- package/src/plugins/defaults/circuit-breaker/package.json +15 -0
- package/src/plugins/defaults/circuit-breaker/register.ts +39 -0
- package/src/plugins/defaults/compaction/middlewares/compaction.ts +25 -0
- package/src/plugins/defaults/compaction/package.json +15 -0
- package/src/plugins/defaults/compaction/register.ts +35 -0
- package/src/plugins/defaults/compaction/terminal.ts +73 -0
- package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +22 -0
- package/src/plugins/defaults/empty-response/package.json +15 -0
- package/src/plugins/defaults/empty-response/register.ts +28 -0
- package/src/plugins/defaults/empty-response/terminal.ts +106 -0
- package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +35 -0
- package/src/plugins/defaults/history-repair/package.json +15 -0
- package/src/plugins/defaults/history-repair/register.ts +24 -0
- package/src/{daemon/history-repair.ts → plugins/defaults/history-repair/terminal.ts} +48 -35
- package/src/plugins/defaults/index.ts +29 -40
- package/src/plugins/defaults/injectors/package.json +15 -0
- package/src/plugins/defaults/{injectors.ts → injectors/register.ts} +14 -38
- package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +17 -0
- package/src/plugins/defaults/llm-call/package.json +15 -0
- package/src/plugins/defaults/{llm-call.ts → llm-call/register.ts} +6 -38
- package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +17 -0
- package/src/plugins/defaults/memory-retrieval/package.json +15 -0
- package/src/plugins/defaults/{memory-retrieval.ts → memory-retrieval/register.ts} +10 -48
- package/src/plugins/defaults/{overflow-reduce.ts → overflow-reduce/middlewares/overflowReduce.ts} +18 -77
- package/src/plugins/defaults/overflow-reduce/package.json +15 -0
- package/src/plugins/defaults/overflow-reduce/register.ts +42 -0
- package/src/plugins/defaults/persistence/middlewares/persistence.ts +19 -0
- package/src/plugins/defaults/persistence/package.json +15 -0
- package/src/plugins/defaults/persistence/register.ts +38 -0
- package/src/plugins/defaults/persistence/terminal.ts +83 -0
- package/src/plugins/defaults/title-generate/package.json +15 -0
- package/src/plugins/defaults/title-generate/register.ts +35 -0
- package/src/plugins/defaults/title-generate/terminal.ts +31 -0
- package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +23 -0
- package/src/plugins/defaults/token-estimate/package.json +15 -0
- package/src/plugins/defaults/token-estimate/register.ts +34 -0
- package/src/plugins/defaults/token-estimate/terminal.ts +40 -0
- package/src/plugins/defaults/tool-error/middlewares/toolError.ts +21 -0
- package/src/plugins/defaults/tool-error/package.json +15 -0
- package/src/plugins/defaults/tool-error/register.ts +35 -0
- package/src/plugins/defaults/tool-error/terminal.ts +47 -0
- package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +23 -0
- package/src/plugins/defaults/tool-execute/package.json +15 -0
- package/src/plugins/defaults/{tool-execute.ts → tool-execute/register.ts} +8 -46
- package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +23 -0
- package/src/plugins/defaults/tool-result-truncate/package.json +15 -0
- package/src/plugins/defaults/tool-result-truncate/register.ts +35 -0
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +113 -0
- package/src/plugins/defaults/tool-result-truncate/types.ts +22 -0
- package/src/plugins/external-plugin-loader.ts +2 -2
- package/src/plugins/pipeline.ts +0 -12
- package/src/plugins/types.ts +51 -90
- package/src/plugins/user-loader.ts +4 -3
- package/src/proactive-artifact/aux-message-injector.ts +0 -1
- package/src/proactive-artifact/job.test.ts +20 -8
- package/src/proactive-artifact/job.ts +3 -1
- package/src/prompts/sections.ts +20 -7
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
- package/src/prompts/templates/BOOTSTRAP.md +5 -1
- package/src/prompts/templates/system-sections.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -25
- package/src/providers/__tests__/satellite-connection-routing.test.ts +7 -21
- package/src/providers/anthropic/client.ts +24 -5
- package/src/providers/call-site-routing.ts +1 -9
- package/src/providers/gemini/client.ts +152 -34
- package/src/providers/gemini/inline-media.ts +74 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +0 -2
- package/src/providers/openai/chat-completions-provider.ts +1 -4
- package/src/providers/openai/responses-provider.ts +1 -4
- package/src/providers/openrouter/client.ts +1 -6
- package/src/providers/provider-send-message.ts +6 -6
- package/src/providers/ratelimit.ts +1 -9
- package/src/providers/retry.ts +0 -5
- package/src/providers/types.ts +11 -2
- package/src/providers/usage-tracking.ts +1 -9
- package/src/runtime/__tests__/agent-wake.test.ts +131 -26
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -3
- package/src/runtime/agent-wake.ts +93 -18
- package/src/runtime/assistant-event-hub.ts +2 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +75 -109
- package/src/runtime/auth/__tests__/route-policy.test.ts +153 -170
- package/src/runtime/auth/route-policy.ts +42 -1079
- package/src/runtime/background-job-runner.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -1
- package/src/runtime/channel-approvals.ts +3 -14
- package/src/runtime/channel-invite-transport.ts +5 -6
- package/src/runtime/channel-readiness-service.ts +2 -5
- package/src/runtime/channel-retry-sweep.ts +12 -16
- package/src/runtime/conversation-stream-state.ts +294 -0
- package/src/runtime/http-router.ts +19 -22
- package/src/runtime/http-types.ts +12 -6
- package/src/runtime/invite-instruction-generator.ts +3 -3
- package/src/runtime/pending-interactions.ts +2 -2
- package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +565 -0
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +62 -32
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -22
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +7 -2
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
- package/src/runtime/routes/__tests__/stt-routes.test.ts +3 -3
- package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +5 -2
- package/src/runtime/routes/__tests__/tts-routes.test.ts +3 -3
- package/src/runtime/routes/acp-routes.test.ts +97 -75
- package/src/runtime/routes/acp-routes.ts +29 -6
- package/src/runtime/routes/app-management-routes.ts +97 -24
- package/src/runtime/routes/app-routes.ts +25 -5
- package/src/runtime/routes/approval-routes.ts +16 -4
- package/src/runtime/routes/attachment-routes.ts +25 -1
- package/src/runtime/routes/audio-routes.ts +1 -0
- package/src/runtime/routes/audit-routes.ts +5 -0
- package/src/runtime/routes/auth-routes.ts +5 -0
- package/src/runtime/routes/avatar-routes.ts +238 -59
- package/src/runtime/routes/background-tool-routes.ts +9 -0
- package/src/runtime/routes/background-wake-routes.ts +13 -3
- package/src/runtime/routes/backup-routes.ts +45 -0
- package/src/runtime/routes/bookmark-routes.ts +13 -0
- package/src/runtime/routes/brain-graph-routes.ts +9 -0
- package/src/runtime/routes/browser-routes.ts +5 -0
- package/src/runtime/routes/browser-tabs-routes.ts +5 -0
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/cache-routes.ts +13 -0
- package/src/runtime/routes/call-routes.ts +21 -10
- package/src/runtime/routes/channel-availability-routes.ts +5 -1
- package/src/runtime/routes/channel-readiness-routes.ts +37 -4
- package/src/runtime/routes/channel-route-definitions.ts +21 -0
- package/src/runtime/routes/channel-verification-routes.ts +21 -0
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +9 -2
- package/src/runtime/routes/client-routes.ts +9 -0
- package/src/runtime/routes/consolidation-routes.ts +13 -5
- package/src/runtime/routes/contact-prompt-routes.ts +9 -0
- package/src/runtime/routes/contact-routes.ts +90 -23
- package/src/runtime/routes/content-source-routes.ts +5 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +5 -1
- package/src/runtime/routes/conversation-attention-routes.ts +5 -0
- package/src/runtime/routes/conversation-cli-routes.ts +54 -7
- package/src/runtime/routes/conversation-compaction-routes.ts +54 -25
- package/src/runtime/routes/conversation-list-routes.ts +81 -12
- package/src/runtime/routes/conversation-management-routes.ts +57 -14
- package/src/runtime/routes/conversation-query-routes.ts +88 -41
- package/src/runtime/routes/conversation-routes.ts +74 -19
- package/src/runtime/routes/conversation-starter-routes.ts +22 -13
- package/src/runtime/routes/conversations-import-routes.ts +6 -1
- package/src/runtime/routes/credential-prompt-routes.ts +5 -0
- package/src/runtime/routes/credential-routes.ts +25 -6
- package/src/runtime/routes/debug-bash-routes.ts +5 -0
- package/src/runtime/routes/debug-routes.ts +11 -2
- package/src/runtime/routes/defer-routes.ts +13 -0
- package/src/runtime/routes/diagnostics-routes.ts +37 -46
- package/src/runtime/routes/disk-pressure-routes.ts +17 -31
- package/src/runtime/routes/document-comments-routes.ts +46 -27
- package/src/runtime/routes/documents-routes.ts +21 -10
- package/src/runtime/routes/domain-routes.ts +61 -28
- package/src/runtime/routes/email-routes.ts +33 -0
- package/src/runtime/routes/events-routes.ts +114 -9
- package/src/runtime/routes/filing-routes.ts +9 -4
- package/src/runtime/routes/gateway-log-routes.ts +5 -0
- package/src/runtime/routes/global-search-routes.ts +53 -50
- package/src/runtime/routes/group-routes.ts +21 -5
- package/src/runtime/routes/guardian-action-routes.ts +9 -0
- package/src/runtime/routes/guardian-approval-interception.ts +0 -31
- package/src/runtime/routes/heartbeat-routes.ts +25 -9
- package/src/runtime/routes/home-feed-routes.ts +23 -19
- package/src/runtime/routes/home-state-routes.ts +8 -40
- package/src/runtime/routes/host-app-control-routes.ts +5 -0
- package/src/runtime/routes/host-bash-routes.ts +5 -0
- package/src/runtime/routes/host-browser-routes.ts +13 -0
- package/src/runtime/routes/host-cu-routes.ts +5 -0
- package/src/runtime/routes/host-file-routes.ts +26 -6
- package/src/runtime/routes/host-transfer-routes.ts +13 -2
- package/src/runtime/routes/http-adapter.ts +1 -2
- package/src/runtime/routes/identity-intro-cache.ts +17 -6
- package/src/runtime/routes/identity-routes.ts +12 -2
- package/src/runtime/routes/image-generation-routes.ts +5 -0
- package/src/runtime/routes/inbound-message-handler.ts +15 -11
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +15 -19
- package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
- package/src/runtime/routes/inference-provider-connection-routes.ts +21 -5
- package/src/runtime/routes/inference-send-routes.ts +11 -11
- package/src/runtime/routes/integrations/a2a.ts +30 -7
- package/src/runtime/routes/integrations/slack/channel.ts +19 -3
- package/src/runtime/routes/integrations/slack/share.ts +9 -2
- package/src/runtime/routes/integrations/telegram.ts +28 -9
- package/src/runtime/routes/integrations/twilio.ts +35 -7
- package/src/runtime/routes/integrations/vercel.ts +3 -3
- package/src/runtime/routes/internal-oauth-routes.ts +5 -0
- package/src/runtime/routes/internal-twilio-routes.ts +13 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +39 -4
- package/src/runtime/routes/log-export-routes.ts +28 -10
- package/src/runtime/routes/mcp-auth-routes.ts +25 -0
- package/src/runtime/routes/memory-item-routes.ts +21 -10
- package/src/runtime/routes/memory-v2-routes.ts +90 -36
- package/src/runtime/routes/memory-v3-routes.ts +273 -407
- package/src/runtime/routes/migration-rollback-routes.ts +5 -1
- package/src/runtime/routes/migration-routes.ts +29 -0
- package/src/runtime/routes/notification-routes.ts +17 -1
- package/src/runtime/routes/oauth-apps.ts +33 -11
- package/src/runtime/routes/oauth-commands-routes.ts +37 -14
- package/src/runtime/routes/oauth-connect-routes.ts +9 -0
- package/src/runtime/routes/oauth-lifecycle-routes.ts +5 -1
- package/src/runtime/routes/oauth-providers.ts +35 -10
- package/src/runtime/routes/platform-routes.ts +21 -0
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +3 -2
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +37 -16
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +7 -3
- package/src/runtime/routes/playground/__tests__/state.test.ts +10 -3
- package/src/runtime/routes/playground/force-compact.ts +1 -1
- package/src/runtime/routes/playground/helpers.ts +0 -1
- package/src/runtime/routes/playground/inject-failures.ts +13 -8
- package/src/runtime/routes/playground/reset-circuit.ts +14 -9
- package/src/runtime/routes/playground/seed-conversation.ts +1 -1
- package/src/runtime/routes/playground/seeded-conversations.ts +3 -3
- package/src/runtime/routes/playground/state.ts +4 -3
- package/src/runtime/routes/plugins-routes.ts +22 -19
- package/src/runtime/routes/profiler-routes.ts +17 -4
- package/src/runtime/routes/ps-routes.ts +5 -0
- package/src/runtime/routes/publish-routes.ts +13 -3
- package/src/runtime/routes/question-routes.ts +5 -0
- package/src/runtime/routes/recording-routes.ts +25 -12
- package/src/runtime/routes/rename-conversation-routes.ts +5 -0
- package/src/runtime/routes/sanity-routes.ts +9 -2
- package/src/runtime/routes/schedule-routes.ts +137 -47
- package/src/runtime/routes/secret-routes.ts +17 -4
- package/src/runtime/routes/sequence-routes.ts +33 -0
- package/src/runtime/routes/settings-routes.ts +65 -19
- package/src/runtime/routes/skills-routes.ts +133 -69
- package/src/runtime/routes/slack-channel-routes.ts +5 -0
- package/src/runtime/routes/stt-routes.ts +13 -6
- package/src/runtime/routes/subagents-routes.ts +24 -18
- package/src/runtime/routes/suggest-trust-rule-routes.ts +7 -2
- package/src/runtime/routes/surface-action-routes.ts +9 -0
- package/src/runtime/routes/surface-content-routes.ts +10 -2
- package/src/runtime/routes/task-routes.ts +37 -0
- package/src/runtime/routes/telemetry-routes.ts +9 -0
- package/src/runtime/routes/trace-event-routes.ts +42 -1
- package/src/runtime/routes/trust-rules-routes.ts +5 -0
- package/src/runtime/routes/tts-routes.ts +13 -6
- package/src/runtime/routes/types.ts +17 -8
- package/src/runtime/routes/ui-request-routes.ts +5 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +5 -0
- package/src/runtime/routes/usage-routes.ts +71 -3
- package/src/runtime/routes/user-routes-cli.ts +9 -0
- package/src/runtime/routes/user-routes.ts +5 -1
- package/src/runtime/routes/wake-conversation-routes.ts +5 -0
- package/src/runtime/routes/watcher-routes.ts +21 -0
- package/src/runtime/routes/webhook-routes.ts +9 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +5 -0
- package/src/runtime/routes/work-items-routes.ts +47 -19
- package/src/runtime/routes/workspace-commit-routes.ts +5 -0
- package/src/runtime/routes/workspace-routes.test.ts +42 -0
- package/src/runtime/routes/workspace-routes.ts +120 -9
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -4
- package/src/runtime/services/analyze-conversation.ts +3 -6
- package/src/runtime/services/conversation-serializer.ts +24 -2
- package/src/runtime/sync/resource-sync-events.ts +16 -2
- package/src/runtime/sync/sync-publisher.ts +2 -2
- package/src/schedule/run-script.ts +28 -3
- package/src/schedule/schedule-store.ts +8 -0
- package/src/schedule/scheduler.ts +3 -1
- package/src/signals/user-message.ts +5 -8
- package/src/skills/catalog-files.ts +4 -1
- package/src/skills/clawhub-files.ts +2 -0
- package/src/skills/skillssh-files.ts +2 -0
- package/src/subagent/manager.ts +3 -6
- package/src/telemetry/types.ts +26 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +138 -1
- package/src/telemetry/usage-telemetry-reporter.ts +31 -0
- package/src/tools/acp/spawn.test.ts +88 -38
- package/src/tools/apps/definitions.ts +8 -4
- package/src/tools/ask-question/ask-question-tool.test.ts +120 -105
- package/src/tools/ask-question/ask-question-tool.ts +85 -90
- package/src/tools/computer-use/definitions.ts +28 -24
- package/src/tools/credential-execution/make-authenticated-request.ts +56 -51
- package/src/tools/credential-execution/manage-secure-command-tool.ts +2 -2
- package/src/tools/credential-execution/run-authenticated-command.ts +82 -77
- package/src/tools/credentials/vault.ts +112 -111
- package/src/tools/execution-target.ts +1 -1
- package/src/tools/execution-timeout.ts +3 -4
- package/src/tools/filesystem/edit.ts +45 -42
- package/src/tools/filesystem/list.ts +33 -30
- package/src/tools/filesystem/read.ts +54 -35
- package/src/tools/filesystem/write.ts +34 -31
- package/src/tools/host-filesystem/edit.ts +44 -42
- package/src/tools/host-filesystem/read.ts +49 -35
- package/src/tools/host-filesystem/transfer.ts +121 -108
- package/src/tools/host-filesystem/write.ts +33 -31
- package/src/tools/host-terminal/host-shell.ts +50 -48
- package/src/tools/memory/register.ts +23 -24
- package/src/tools/network/web-fetch.ts +49 -46
- package/src/tools/network/web-search.ts +16 -13
- package/src/tools/registry.ts +39 -16
- package/src/tools/schedule/create.ts +11 -0
- package/src/tools/schedule/update.ts +16 -0
- package/src/tools/shared/filesystem/audio-read.ts +122 -0
- package/src/tools/shared/filesystem/image-read.ts +1 -1
- package/src/tools/skills/execute.ts +34 -31
- package/src/tools/skills/load.ts +29 -23
- package/src/tools/subagent/notify-parent.ts +35 -32
- package/src/tools/system/avatar-generator.ts +13 -22
- package/src/tools/system/request-permission.ts +30 -27
- package/src/tools/terminal/shell.ts +190 -61
- package/src/tools/tool-defaults.ts +20 -9
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +74 -23
- package/src/tools/ui-surface/definitions.ts +69 -9
- package/src/usage/types.ts +10 -0
- package/src/util/errors.ts +2 -2
- package/src/util/map-limit.ts +27 -0
- package/src/util/platform.ts +15 -12
- package/src/work-items/work-item-runner.ts +7 -2
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +7 -20
- package/src/workspace/migrations/092-backfill-v3-leaves.ts +169 -0
- package/src/workspace/migrations/093-backfill-leaf-ids.ts +144 -0
- package/src/workspace/migrations/094-seed-avatar-manifest.ts +155 -0
- package/src/workspace/migrations/__tests__/094-seed-avatar-manifest.test.ts +136 -0
- package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +175 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +124 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/provider-commit-message-generator.ts +15 -17
- package/tsconfig.json +4 -1
- package/src/__tests__/history-repair-pipeline.test.ts +0 -396
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +0 -340
- package/src/cli/commands/memory-v3-render.ts +0 -491
- package/src/daemon/message-types/disk-pressure.ts +0 -9
- package/src/email/feature-gate.ts +0 -23
- package/src/memory/v3/__tests__/coactivation-store.test.ts +0 -422
- package/src/memory/v3/__tests__/consolidation-job.test.ts +0 -466
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +0 -270
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
- package/src/memory/v3/__tests__/edges.test.ts +0 -706
- package/src/memory/v3/__tests__/filter.test.ts +0 -560
- package/src/memory/v3/__tests__/gate.test.ts +0 -637
- package/src/memory/v3/__tests__/index-composition.test.ts +0 -291
- package/src/memory/v3/__tests__/loop.test.ts +0 -775
- package/src/memory/v3/__tests__/retriever.test.ts +0 -226
- package/src/memory/v3/__tests__/scouts.test.ts +0 -489
- package/src/memory/v3/__tests__/shadow-diff.test.ts +0 -225
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -398
- package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
- package/src/memory/v3/__tests__/traversal.test.ts +0 -508
- package/src/memory/v3/__tests__/tree-index.test.ts +0 -280
- package/src/memory/v3/__tests__/tree-store.test.ts +0 -529
- package/src/memory/v3/__tests__/tree-walk.test.ts +0 -784
- package/src/memory/v3/__tests__/validate.test.ts +0 -277
- package/src/memory/v3/auto-edges.ts +0 -223
- package/src/memory/v3/coactivation-store.ts +0 -124
- package/src/memory/v3/consolidation-job.ts +0 -323
- package/src/memory/v3/coretrieval-seed.ts +0 -240
- package/src/memory/v3/edge-learning-job.ts +0 -160
- package/src/memory/v3/edges.ts +0 -286
- package/src/memory/v3/filter.ts +0 -286
- package/src/memory/v3/gate.ts +0 -349
- package/src/memory/v3/index-composition.ts +0 -126
- package/src/memory/v3/llm-capture.ts +0 -46
- package/src/memory/v3/loop.ts +0 -430
- package/src/memory/v3/maintenance.ts +0 -144
- package/src/memory/v3/prompt-context.ts +0 -33
- package/src/memory/v3/prompts/consolidation.ts +0 -458
- package/src/memory/v3/prompts/system-prompts.ts +0 -196
- package/src/memory/v3/retriever.ts +0 -33
- package/src/memory/v3/scouts.ts +0 -431
- package/src/memory/v3/shadow-diff.ts +0 -287
- package/src/memory/v3/shadow-middleware.ts +0 -347
- package/src/memory/v3/traversal.ts +0 -211
- package/src/memory/v3/tree-index.ts +0 -237
- package/src/memory/v3/tree-store.ts +0 -394
- package/src/memory/v3/tree-walk.ts +0 -356
- package/src/memory/v3/validate.ts +0 -323
- package/src/plugins/defaults/circuit-breaker.ts +0 -141
- package/src/plugins/defaults/compaction.ts +0 -141
- package/src/plugins/defaults/empty-response.ts +0 -124
- package/src/plugins/defaults/history-repair.ts +0 -83
- package/src/plugins/defaults/persistence.ts +0 -146
- package/src/plugins/defaults/title-generate.ts +0 -90
- package/src/plugins/defaults/token-estimate.ts +0 -101
- package/src/plugins/defaults/tool-error.ts +0 -119
- package/src/plugins/defaults/tool-result-truncate.ts +0 -84
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +0 -35
|
@@ -8,12 +8,21 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { RiskLevel } from "../../permissions/types.js";
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
ToolContext,
|
|
13
|
+
ToolDefinition,
|
|
14
|
+
ToolExecutionResult,
|
|
15
|
+
} from "../types.js";
|
|
12
16
|
|
|
13
17
|
// ---------------------------------------------------------------------------
|
|
14
18
|
// Helpers
|
|
15
19
|
// ---------------------------------------------------------------------------
|
|
16
20
|
|
|
21
|
+
const APP_BUILDER_ARTIFACT_RE =
|
|
22
|
+
/\b(app|apps|application|applications|website|websites|site|sites|dashboard|dashboards|game|games|calculator|calculators|tracker|trackers|visualization|visualizations|visualisation|visualisations|tool|tools|utility|utilities|counter|counters)\b/i;
|
|
23
|
+
const APP_BUILDER_BUILD_RE =
|
|
24
|
+
/\b(build|building|built|create|creating|created|make|making|made|generate|generating|generated)\b/i;
|
|
25
|
+
|
|
17
26
|
/**
|
|
18
27
|
* Forward execution to the connected macOS client via the request-bound
|
|
19
28
|
* `proxyToolResolver`. Returns a structured error when no resolver is
|
|
@@ -25,6 +34,14 @@ function proxyExecute(toolName: string) {
|
|
|
25
34
|
input: Record<string, unknown>,
|
|
26
35
|
context: ToolContext,
|
|
27
36
|
): Promise<ToolExecutionResult> => {
|
|
37
|
+
if (toolName === "ui_show" && isDynamicPageAppSubstitute(input)) {
|
|
38
|
+
return {
|
|
39
|
+
content:
|
|
40
|
+
'Error: ui_show dynamic_page is for transient UI surfaces only. This request is building an app-like experience, so load the app-builder skill first with `skill_load` using `skill: "app-builder"`, then create a persistent Library app with the app-builder workflow.',
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
28
45
|
if (!context.proxyToolResolver) {
|
|
29
46
|
return {
|
|
30
47
|
content: `No proxy resolver configured for proxy tool "${toolName}". This tool requires an external resolver (e.g. a connected macOS client).`,
|
|
@@ -35,14 +52,57 @@ function proxyExecute(toolName: string) {
|
|
|
35
52
|
};
|
|
36
53
|
}
|
|
37
54
|
|
|
55
|
+
function isDynamicPageAppSubstitute(input: Record<string, unknown>): boolean {
|
|
56
|
+
if (input.surface_type !== "dynamic_page") {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const text = collectRoutingText(input).join(" ");
|
|
61
|
+
if (!APP_BUILDER_ARTIFACT_RE.test(text)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return APP_BUILDER_BUILD_RE.test(text) || /\b(app|application)\b/i.test(text);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function collectRoutingText(input: Record<string, unknown>): string[] {
|
|
69
|
+
const values: string[] = [];
|
|
70
|
+
addString(values, input.title);
|
|
71
|
+
addString(values, input.activity);
|
|
72
|
+
|
|
73
|
+
const data = asRecord(input.data);
|
|
74
|
+
if (data) {
|
|
75
|
+
const preview = asRecord(data.preview);
|
|
76
|
+
if (preview) {
|
|
77
|
+
addString(values, preview.title);
|
|
78
|
+
addString(values, preview.subtitle);
|
|
79
|
+
addString(values, preview.description);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return values;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function asRecord(value: unknown): Record<string, unknown> | null {
|
|
87
|
+
return value !== null && typeof value === "object"
|
|
88
|
+
? (value as Record<string, unknown>)
|
|
89
|
+
: null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function addString(values: string[], value: unknown): void {
|
|
93
|
+
if (typeof value === "string") {
|
|
94
|
+
values.push(value);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
38
98
|
// ---------------------------------------------------------------------------
|
|
39
99
|
// ui_show
|
|
40
100
|
// ---------------------------------------------------------------------------
|
|
41
101
|
|
|
42
|
-
export const uiShowTool
|
|
102
|
+
export const uiShowTool = {
|
|
43
103
|
name: "ui_show",
|
|
44
104
|
description:
|
|
45
|
-
|
|
105
|
+
'Surface structured data or UI in the conversation. For long-form writing use the document skill. For interactive apps, dashboards, games, calculators, or durable tools, call `skill_load` with `skill: "app-builder"` and use the app-builder workflow; do not use `dynamic_page` as a substitute for a persistent app. App-like `dynamic_page` calls are rejected.\n\n' +
|
|
46
106
|
"Surface types (data shapes):\n" +
|
|
47
107
|
'- card: { title, subtitle?, body, metadata?: [{ label, value }], template?, templateData? }. Templates: "weather_forecast" (native weather widget), "task_progress" (live step tracker - update via ui_update on data.templateData; shape: { title, status: "in_progress"|"completed"|"failed", steps: [{ label, status: "pending"|"in_progress"|"completed"|"failed", detail? }] })\n' +
|
|
48
108
|
'- table: { columns: [{ id, label }], rows: [{ id, cells: Record<id, string | { text, icon?, iconColor?: "success"|"warning"|"error"|"muted" }>, selectable?, selected? }], selectionMode?: "none"|"single"|"multiple", caption? }\n' +
|
|
@@ -121,13 +181,13 @@ export const uiShowTool: Tool = {
|
|
|
121
181
|
},
|
|
122
182
|
|
|
123
183
|
execute: proxyExecute("ui_show"),
|
|
124
|
-
};
|
|
184
|
+
} satisfies ToolDefinition;
|
|
125
185
|
|
|
126
186
|
// ---------------------------------------------------------------------------
|
|
127
187
|
// ui_update
|
|
128
188
|
// ---------------------------------------------------------------------------
|
|
129
189
|
|
|
130
|
-
const uiUpdateTool
|
|
190
|
+
const uiUpdateTool = {
|
|
131
191
|
name: "ui_update",
|
|
132
192
|
description:
|
|
133
193
|
"Update an existing surface's data. The provided data object is merged into the surface's current data.\n" +
|
|
@@ -152,13 +212,13 @@ const uiUpdateTool: Tool = {
|
|
|
152
212
|
},
|
|
153
213
|
|
|
154
214
|
execute: proxyExecute("ui_update"),
|
|
155
|
-
};
|
|
215
|
+
} satisfies ToolDefinition;
|
|
156
216
|
|
|
157
217
|
// ---------------------------------------------------------------------------
|
|
158
218
|
// ui_dismiss
|
|
159
219
|
// ---------------------------------------------------------------------------
|
|
160
220
|
|
|
161
|
-
const uiDismissTool
|
|
221
|
+
const uiDismissTool = {
|
|
162
222
|
name: "ui_dismiss",
|
|
163
223
|
description: "Dismiss a currently displayed surface.",
|
|
164
224
|
category: "ui-surface",
|
|
@@ -177,9 +237,9 @@ const uiDismissTool: Tool = {
|
|
|
177
237
|
},
|
|
178
238
|
|
|
179
239
|
execute: proxyExecute("ui_dismiss"),
|
|
180
|
-
};
|
|
240
|
+
} satisfies ToolDefinition;
|
|
181
241
|
|
|
182
|
-
export const allUiSurfaceTools:
|
|
242
|
+
export const allUiSurfaceTools: ToolDefinition[] = [
|
|
183
243
|
uiShowTool,
|
|
184
244
|
uiUpdateTool,
|
|
185
245
|
uiDismissTool,
|
package/src/usage/types.ts
CHANGED
|
@@ -85,4 +85,14 @@ export interface UsageEvent extends UsageEventInput {
|
|
|
85
85
|
inferenceProfileSource: UsageAttributionProfileSource | null;
|
|
86
86
|
estimatedCostUsd: number | null;
|
|
87
87
|
pricingStatus: "priced" | "unpriced";
|
|
88
|
+
/**
|
|
89
|
+
* Version of the assistant binary at the moment this event was
|
|
90
|
+
* RECORDED, captured by `recordUsageEvent` and persisted with the
|
|
91
|
+
* row. Not provided by callers; computed at record time. Surfaces
|
|
92
|
+
* onto the telemetry wire as `assistant_version` so analytics
|
|
93
|
+
* stays truthful even when a batch flushes days after the events
|
|
94
|
+
* fired. `null` only for rows persisted before migration 267 ran.
|
|
95
|
+
* See `migrations/267-llm-usage-events-add-assistant-version.ts`.
|
|
96
|
+
*/
|
|
97
|
+
assistantVersion: string | null;
|
|
88
98
|
}
|
package/src/util/errors.ts
CHANGED
|
@@ -153,14 +153,14 @@ export class ConfigError extends AssistantError {
|
|
|
153
153
|
export class ProviderNotConfiguredError extends ConfigError {
|
|
154
154
|
/**
|
|
155
155
|
* Optional name of the `provider_connections` row whose credential was
|
|
156
|
-
* missing. Surfaced through `
|
|
156
|
+
* missing. Surfaced through `ConversationErrorEvent.connectionName` so
|
|
157
157
|
* the macOS chat banner can render "API key required for connection
|
|
158
158
|
* <name>" instead of a generic message.
|
|
159
159
|
*/
|
|
160
160
|
public readonly connectionName?: string;
|
|
161
161
|
/**
|
|
162
162
|
* Optional name of the resolved profile in play when this error was
|
|
163
|
-
* thrown. Forwarded to the wire `
|
|
163
|
+
* thrown. Forwarded to the wire `ConversationErrorEvent.profileName`
|
|
164
164
|
* for the same banner-attribution purpose as `connectionName`.
|
|
165
165
|
*/
|
|
166
166
|
public readonly profileName?: string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map `fn` over `items` with bounded concurrency, preserving input order in the
|
|
3
|
+
* result array. At most `limit` invocations of `fn` are in flight at once.
|
|
4
|
+
*
|
|
5
|
+
* Each of the `min(limit, items.length)` workers pulls the next index off a
|
|
6
|
+
* shared cursor and processes it, so faster items don't block on slower ones.
|
|
7
|
+
* Results are written back to their original positions, so `out[i]` always
|
|
8
|
+
* corresponds to `items[i]` regardless of completion order.
|
|
9
|
+
*/
|
|
10
|
+
export async function mapLimit<T, R>(
|
|
11
|
+
items: T[],
|
|
12
|
+
limit: number,
|
|
13
|
+
fn: (t: T) => Promise<R>,
|
|
14
|
+
): Promise<R[]> {
|
|
15
|
+
const out: R[] = new Array(items.length);
|
|
16
|
+
let next = 0;
|
|
17
|
+
await Promise.all(
|
|
18
|
+
Array.from({ length: Math.min(limit, items.length) }, async () => {
|
|
19
|
+
while (true) {
|
|
20
|
+
const i = next++;
|
|
21
|
+
if (i >= items.length) return;
|
|
22
|
+
out[i] = await fn(items[i]!);
|
|
23
|
+
}
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
return out;
|
|
27
|
+
}
|
package/src/util/platform.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { chmodSync, existsSync, mkdirSync } from "node:fs";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
|
|
5
|
+
import { SEEDS } from "@vellumai/environments";
|
|
6
|
+
|
|
5
7
|
import { getWorkspaceDirOverride } from "../config/env-registry.js";
|
|
6
8
|
|
|
7
9
|
/**
|
|
@@ -124,18 +126,19 @@ export function getAvatarImagePath(): string {
|
|
|
124
126
|
return join(getAvatarDir(), AVATAR_IMAGE_FILENAME);
|
|
125
127
|
}
|
|
126
128
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
129
|
+
/** Canonical filename for the avatar state manifest. */
|
|
130
|
+
export const AVATAR_MANIFEST_FILENAME = "avatar.json";
|
|
131
|
+
|
|
132
|
+
/** Returns the canonical avatar manifest path (~/.vellum/workspace/data/avatar/avatar.json). */
|
|
133
|
+
export function getAvatarManifestPath(): string {
|
|
134
|
+
return join(getAvatarDir(), AVATAR_MANIFEST_FILENAME);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// The set of known environment names, derived from the shared
|
|
138
|
+
// `@vellumai/environments` seed table so this site can never drift from the
|
|
139
|
+
// CLI. The Swift client mirrors the same list (it can't import TS); that
|
|
140
|
+
// cross-language pair is guarded by `cli/src/__tests__/env-drift.test.ts`.
|
|
141
|
+
const KNOWN_ENVIRONMENTS: ReadonlySet<string> = new Set(Object.keys(SEEDS));
|
|
139
142
|
|
|
140
143
|
/**
|
|
141
144
|
* Returns the env-scoped XDG config subdirectory name for Vellum
|
|
@@ -137,8 +137,13 @@ export function runWorkItemInBackground(workItemId: string): RunWorkItemResult {
|
|
|
137
137
|
conversation.taskRunId = taskRunId;
|
|
138
138
|
conversation.headlessLock = true;
|
|
139
139
|
}
|
|
140
|
-
await conversation.processMessage(
|
|
141
|
-
|
|
140
|
+
await conversation.processMessage({
|
|
141
|
+
content: message,
|
|
142
|
+
attachments: [],
|
|
143
|
+
onEvent: (event) => {
|
|
144
|
+
broadcastMessage(event);
|
|
145
|
+
},
|
|
146
|
+
isInteractive: false,
|
|
142
147
|
});
|
|
143
148
|
},
|
|
144
149
|
);
|
|
@@ -133,9 +133,7 @@ export const recoverConversationsFromDiskViewMigration: WorkspaceMigration = {
|
|
|
133
133
|
// Read and parse meta.json
|
|
134
134
|
const metaPath = join(dirPath, "meta.json");
|
|
135
135
|
if (!existsSync(metaPath)) {
|
|
136
|
-
log.warn(
|
|
137
|
-
`Skipping ${entry}: missing meta.json`,
|
|
138
|
-
);
|
|
136
|
+
log.warn(`Skipping ${entry}: missing meta.json`);
|
|
139
137
|
skipped++;
|
|
140
138
|
continue;
|
|
141
139
|
}
|
|
@@ -144,17 +142,13 @@ export const recoverConversationsFromDiskViewMigration: WorkspaceMigration = {
|
|
|
144
142
|
try {
|
|
145
143
|
meta = JSON.parse(readFileSync(metaPath, "utf-8")) as DiskMeta;
|
|
146
144
|
} catch (err) {
|
|
147
|
-
log.warn(
|
|
148
|
-
`Skipping ${entry}: malformed meta.json: ${err}`,
|
|
149
|
-
);
|
|
145
|
+
log.warn(`Skipping ${entry}: malformed meta.json: ${err}`);
|
|
150
146
|
skipped++;
|
|
151
147
|
continue;
|
|
152
148
|
}
|
|
153
149
|
|
|
154
150
|
if (!meta.id) {
|
|
155
|
-
log.warn(
|
|
156
|
-
`Skipping ${entry}: meta.json missing id`,
|
|
157
|
-
);
|
|
151
|
+
log.warn(`Skipping ${entry}: meta.json missing id`);
|
|
158
152
|
skipped++;
|
|
159
153
|
continue;
|
|
160
154
|
}
|
|
@@ -182,9 +176,7 @@ export const recoverConversationsFromDiskViewMigration: WorkspaceMigration = {
|
|
|
182
176
|
const trimmed = line.trim();
|
|
183
177
|
if (!trimmed) continue;
|
|
184
178
|
try {
|
|
185
|
-
messageRecords.push(
|
|
186
|
-
JSON.parse(trimmed) as DiskMessageRecord,
|
|
187
|
-
);
|
|
179
|
+
messageRecords.push(JSON.parse(trimmed) as DiskMessageRecord);
|
|
188
180
|
} catch {
|
|
189
181
|
log.warn(
|
|
190
182
|
`Skipping malformed JSONL line in ${entry}/messages.jsonl`,
|
|
@@ -192,9 +184,7 @@ export const recoverConversationsFromDiskViewMigration: WorkspaceMigration = {
|
|
|
192
184
|
}
|
|
193
185
|
}
|
|
194
186
|
} catch (err) {
|
|
195
|
-
log.warn(
|
|
196
|
-
`Failed to read messages.jsonl for ${entry}: ${err}`,
|
|
197
|
-
);
|
|
187
|
+
log.warn(`Failed to read messages.jsonl for ${entry}: ${err}`);
|
|
198
188
|
}
|
|
199
189
|
}
|
|
200
190
|
|
|
@@ -231,8 +221,7 @@ export const recoverConversationsFromDiskViewMigration: WorkspaceMigration = {
|
|
|
231
221
|
|
|
232
222
|
for (const record of messageRecords) {
|
|
233
223
|
const contentBlocks = buildContentBlocks(record);
|
|
234
|
-
const msgCreatedAt =
|
|
235
|
-
parseEpochMs(record.ts) ?? createdAt;
|
|
224
|
+
const msgCreatedAt = parseEpochMs(record.ts) ?? createdAt;
|
|
236
225
|
|
|
237
226
|
tx.insert(messages)
|
|
238
227
|
.values({
|
|
@@ -249,9 +238,7 @@ export const recoverConversationsFromDiskViewMigration: WorkspaceMigration = {
|
|
|
249
238
|
|
|
250
239
|
recovered++;
|
|
251
240
|
} catch (err) {
|
|
252
|
-
log.warn(
|
|
253
|
-
`Failed to insert conversation ${meta.id} (${entry}): ${err}`,
|
|
254
|
-
);
|
|
241
|
+
log.warn(`Failed to insert conversation ${meta.id} (${entry}): ${err}`);
|
|
255
242
|
errors++;
|
|
256
243
|
}
|
|
257
244
|
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* v3 leaf assignments and concept pages, addressed relative to the workspace.
|
|
8
|
+
*/
|
|
9
|
+
const ASSIGNMENTS_REL = join("memory", "v3", "data", "assignments.json");
|
|
10
|
+
const CONCEPTS_REL = join("memory", "concepts");
|
|
11
|
+
|
|
12
|
+
const FRONTMATTER_DELIMITER = "---";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Read the v3 slug -> leaf-path assignment map from the workspace data dir.
|
|
16
|
+
*
|
|
17
|
+
* Returns an empty map when `assignments.json` is absent (the v3 data dir was
|
|
18
|
+
* never materialized for this workspace) so the migration is a clean no-op.
|
|
19
|
+
*/
|
|
20
|
+
function readAssignments(workspaceDir: string): Record<string, string[]> {
|
|
21
|
+
const assignmentsPath = join(workspaceDir, ASSIGNMENTS_REL);
|
|
22
|
+
let raw: string;
|
|
23
|
+
try {
|
|
24
|
+
raw = fs.readFileSync(assignmentsPath, "utf8");
|
|
25
|
+
} catch (err) {
|
|
26
|
+
if ((err as NodeJS.ErrnoException).code === "ENOENT") return {};
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
30
|
+
return parsed && typeof parsed === "object"
|
|
31
|
+
? (parsed as Record<string, string[]>)
|
|
32
|
+
: {};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface SplitPage {
|
|
36
|
+
/** Raw YAML frontmatter block (between the `---` fences), without fences. */
|
|
37
|
+
frontmatter: string;
|
|
38
|
+
/** Everything after the closing frontmatter fence, verbatim. */
|
|
39
|
+
body: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Split a concept page into its YAML frontmatter block and body. Returns `null`
|
|
44
|
+
* when the file does not open with a `---` frontmatter fence (a page with no
|
|
45
|
+
* frontmatter, which we leave untouched).
|
|
46
|
+
*
|
|
47
|
+
* Inlined here rather than importing `../v2/page-store` — workspace migrations
|
|
48
|
+
* must stay self-contained (see AGENTS.md) so an append-only migration never
|
|
49
|
+
* shifts semantics when the runtime page parser evolves.
|
|
50
|
+
*/
|
|
51
|
+
function splitFrontmatter(content: string): SplitPage | null {
|
|
52
|
+
if (!content.startsWith(FRONTMATTER_DELIMITER)) return null;
|
|
53
|
+
const afterOpen = content.slice(FRONTMATTER_DELIMITER.length);
|
|
54
|
+
const closeMatch = afterOpen.match(/\r?\n---[ \t]*(?:\r?\n|$)/);
|
|
55
|
+
if (!closeMatch || closeMatch.index === undefined) return null;
|
|
56
|
+
const frontmatter = afterOpen.slice(0, closeMatch.index);
|
|
57
|
+
const body = afterOpen.slice(closeMatch.index + closeMatch[0].length);
|
|
58
|
+
return { frontmatter, body };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Locate a top-level `leaves:` field in the frontmatter lines: the index of its
|
|
63
|
+
* key line plus the (exclusive) index after any indented block-sequence items
|
|
64
|
+
* that belong to it. Returns `null` when no `leaves:` key is present.
|
|
65
|
+
*
|
|
66
|
+
* A line-shaped scan (rather than a YAML parse) keeps the migration free of an
|
|
67
|
+
* npm dependency, as AGENTS.md requires; leaf frontmatter is flat key/value so
|
|
68
|
+
* the only nesting is a `leaves:` block sequence (` - path`).
|
|
69
|
+
*/
|
|
70
|
+
function findLeavesField(
|
|
71
|
+
lines: string[],
|
|
72
|
+
): { start: number; end: number; nonEmpty: boolean } | null {
|
|
73
|
+
for (let i = 0; i < lines.length; i++) {
|
|
74
|
+
const m = /^leaves:[ \t]*(.*)$/.exec(lines[i]);
|
|
75
|
+
if (!m) continue;
|
|
76
|
+
const inline = m[1].trim();
|
|
77
|
+
if (inline.length > 0) {
|
|
78
|
+
// Inline form: `leaves: [a, b]` (non-empty) or `leaves: []` (empty).
|
|
79
|
+
return { start: i, end: i + 1, nonEmpty: inline !== "[]" };
|
|
80
|
+
}
|
|
81
|
+
// Block form: consume following indented lines (` - item`) as the value.
|
|
82
|
+
let end = i + 1;
|
|
83
|
+
let nonEmpty = false;
|
|
84
|
+
while (end < lines.length && /^[ \t]+\S/.test(lines[end])) {
|
|
85
|
+
if (/^[ \t]+-[ \t]+\S/.test(lines[end])) nonEmpty = true;
|
|
86
|
+
end++;
|
|
87
|
+
}
|
|
88
|
+
return { start: i, end, nonEmpty };
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Splice a non-empty `leaves:` block sequence into the frontmatter, replacing
|
|
95
|
+
* any existing (empty) `leaves:` field in place so we never leave a duplicate
|
|
96
|
+
* key. Leaf paths are simple slugs (`domain/topic`) that need no quoting; we
|
|
97
|
+
* still defensively quote any value containing YAML-significant characters.
|
|
98
|
+
*/
|
|
99
|
+
function withLeaves(frontmatter: string, leaves: string[]): string {
|
|
100
|
+
const quote = (v: string): string =>
|
|
101
|
+
/[:#[\]{}",&*!|>%@`]/.test(v) ? JSON.stringify(v) : v;
|
|
102
|
+
const block = ["leaves:", ...leaves.map((l) => ` - ${quote(l)}`)];
|
|
103
|
+
|
|
104
|
+
const lines = frontmatter.replace(/\s+$/, "").split(/\r?\n/);
|
|
105
|
+
// Drop a leading empty line so a previously blank frontmatter doesn't yield
|
|
106
|
+
// a stray newline at the top.
|
|
107
|
+
while (lines.length > 0 && lines[0].trim() === "") lines.shift();
|
|
108
|
+
|
|
109
|
+
const existing = findLeavesField(lines);
|
|
110
|
+
if (existing) {
|
|
111
|
+
lines.splice(existing.start, existing.end - existing.start, ...block);
|
|
112
|
+
} else {
|
|
113
|
+
lines.push(...block);
|
|
114
|
+
}
|
|
115
|
+
return lines.join("\n");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Backfill `leaves:` into concept-page frontmatter from the v3 assignment map.
|
|
120
|
+
*
|
|
121
|
+
* v3 routing persists a slug -> leaf-path map at
|
|
122
|
+
* `<workspace>/memory/v3/data/assignments.json`. Concept pages gained an
|
|
123
|
+
* optional `leaves` frontmatter field, but existing pages predate it. This
|
|
124
|
+
* one-time migration copies each slug's assignment into the matching page's
|
|
125
|
+
* frontmatter.
|
|
126
|
+
*
|
|
127
|
+
* Idempotent: pages that already carry a non-empty `leaves` are left untouched
|
|
128
|
+
* (never clobbered). A missing `assignments.json` or a slug with no matching
|
|
129
|
+
* page is a no-op — neither throws. All read/write logic is inlined (built-ins
|
|
130
|
+
* only) so the migration stays self-contained per AGENTS.md.
|
|
131
|
+
*/
|
|
132
|
+
export const backfillV3LeavesMigration: WorkspaceMigration = {
|
|
133
|
+
id: "092-backfill-v3-leaves",
|
|
134
|
+
description: "Backfill v3 leaf assignments into concept-page frontmatter",
|
|
135
|
+
|
|
136
|
+
run(workspaceDir: string): void {
|
|
137
|
+
const assignments = readAssignments(workspaceDir);
|
|
138
|
+
const conceptsDir = join(workspaceDir, CONCEPTS_REL);
|
|
139
|
+
|
|
140
|
+
for (const [slug, leaves] of Object.entries(assignments)) {
|
|
141
|
+
if (!Array.isArray(leaves) || leaves.length === 0) continue;
|
|
142
|
+
|
|
143
|
+
const file = join(conceptsDir, `${slug}.md`);
|
|
144
|
+
let content: string;
|
|
145
|
+
try {
|
|
146
|
+
content = fs.readFileSync(file, "utf8");
|
|
147
|
+
} catch (err) {
|
|
148
|
+
if ((err as NodeJS.ErrnoException).code === "ENOENT") continue;
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const split = splitFrontmatter(content);
|
|
153
|
+
if (!split) continue; // No frontmatter fence — leave the page untouched.
|
|
154
|
+
// Never clobber a page that already declares non-empty leaves.
|
|
155
|
+
const existing = findLeavesField(split.frontmatter.split(/\r?\n/));
|
|
156
|
+
if (existing?.nonEmpty) continue;
|
|
157
|
+
|
|
158
|
+
const rebuilt = `${FRONTMATTER_DELIMITER}\n${withLeaves(
|
|
159
|
+
split.frontmatter,
|
|
160
|
+
leaves,
|
|
161
|
+
)}\n${FRONTMATTER_DELIMITER}\n${split.body}`;
|
|
162
|
+
fs.writeFileSync(file, rebuilt, "utf8");
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
down(): void {
|
|
167
|
+
// no-op: `leaves` is an additive field; removing it would lose data.
|
|
168
|
+
},
|
|
169
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
4
|
+
|
|
5
|
+
import { getLogger } from "../../util/logger.js";
|
|
6
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
7
|
+
|
|
8
|
+
const log = getLogger("workspace-migration-093-backfill-leaf-ids");
|
|
9
|
+
|
|
10
|
+
/** v3 leaf files live under this path relative to the workspace dir. */
|
|
11
|
+
const LEAVES_REL = join("memory", "v3", "data", "leaves");
|
|
12
|
+
|
|
13
|
+
const FRONTMATTER_DELIMITER = "---";
|
|
14
|
+
|
|
15
|
+
interface SplitLeaf {
|
|
16
|
+
/** Raw YAML frontmatter block (between the `---` fences), without fences. */
|
|
17
|
+
frontmatter: string;
|
|
18
|
+
/** Everything after the closing frontmatter fence, verbatim. */
|
|
19
|
+
body: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Split a leaf `.md` file into its YAML frontmatter block and body. Returns
|
|
24
|
+
* `null` when the file does not open with a `---` frontmatter fence, so callers
|
|
25
|
+
* can skip files that are not well-formed leaves (we never rewrite those).
|
|
26
|
+
*/
|
|
27
|
+
function splitFrontmatter(content: string): SplitLeaf | null {
|
|
28
|
+
if (!content.startsWith(FRONTMATTER_DELIMITER)) return null;
|
|
29
|
+
// Skip the opening fence and find the closing one at the start of a line.
|
|
30
|
+
const afterOpen = content.slice(FRONTMATTER_DELIMITER.length);
|
|
31
|
+
const closeMatch = afterOpen.match(/\r?\n---[ \t]*(?:\r?\n|$)/);
|
|
32
|
+
if (!closeMatch || closeMatch.index === undefined) return null;
|
|
33
|
+
const frontmatter = afterOpen.slice(0, closeMatch.index);
|
|
34
|
+
const body = afterOpen.slice(closeMatch.index + closeMatch[0].length);
|
|
35
|
+
return { frontmatter, body };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Deterministic, stable id derived from the leaf's relative path at backfill
|
|
40
|
+
* time. The same path always yields the same id, so re-runs and re-installs
|
|
41
|
+
* converge. 12 hex chars (48 bits) is ample to avoid collisions across the
|
|
42
|
+
* handful-to-thousands of leaves a workspace holds.
|
|
43
|
+
*/
|
|
44
|
+
function stableIdForPath(relPath: string): string {
|
|
45
|
+
return createHash("sha256").update(relPath).digest("hex").slice(0, 12);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Recursively collect every `.md` file under `dir`. */
|
|
49
|
+
function collectLeafFiles(dir: string): string[] {
|
|
50
|
+
const out: string[] = [];
|
|
51
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
52
|
+
const full = join(dir, entry.name);
|
|
53
|
+
if (entry.isDirectory()) {
|
|
54
|
+
out.push(...collectLeafFiles(full));
|
|
55
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
56
|
+
out.push(full);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* True when the frontmatter already declares a non-empty top-level `id:` field.
|
|
64
|
+
* A line-shaped check (rather than a YAML parse) keeps the migration free of an
|
|
65
|
+
* npm `yaml` dependency, as AGENTS.md requires — leaf frontmatter is simple
|
|
66
|
+
* flat key/value, so a `^id:` scan is sufficient and durable.
|
|
67
|
+
*/
|
|
68
|
+
function hasStableId(frontmatter: string): boolean {
|
|
69
|
+
for (const line of frontmatter.split(/\r?\n/)) {
|
|
70
|
+
const m = /^id:[ \t]*(.*)$/.exec(line);
|
|
71
|
+
if (!m) continue;
|
|
72
|
+
return m[1].trim().replace(/^["']|["']$/g, "").length > 0;
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Backfill a stable `id` into the frontmatter of `file` if it lacks one.
|
|
79
|
+
* Returns `true` when the file was rewritten. Idempotent: a leaf that already
|
|
80
|
+
* has an `id` is left untouched. The id is keyed off the leaf's path relative
|
|
81
|
+
* to the leaves root so it is stable across machines and re-runs.
|
|
82
|
+
*
|
|
83
|
+
* Frontmatter is edited as text (the `id:` line is prepended to the existing
|
|
84
|
+
* block) rather than parsed/re-serialized through a YAML library: workspace
|
|
85
|
+
* migrations must stay self-contained with no npm deps (AGENTS.md), and a
|
|
86
|
+
* text splice also preserves the rest of the human-authored frontmatter
|
|
87
|
+
* verbatim (key order, comments, formatting).
|
|
88
|
+
*/
|
|
89
|
+
function backfillLeaf(leavesDir: string, file: string): boolean {
|
|
90
|
+
const content = fs.readFileSync(file, "utf8");
|
|
91
|
+
const split = splitFrontmatter(content);
|
|
92
|
+
if (!split) {
|
|
93
|
+
log.warn({ file }, "Leaf file missing YAML frontmatter; skipping");
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (hasStableId(split.frontmatter)) {
|
|
98
|
+
return false; // Already has a stable id — idempotent skip.
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const relPath = relative(leavesDir, file);
|
|
102
|
+
const idLine = `id: ${stableIdForPath(relPath)}`;
|
|
103
|
+
const existing = split.frontmatter.replace(/^\s+|\s+$/g, "");
|
|
104
|
+
const newFrontmatter =
|
|
105
|
+
existing.length > 0 ? `${idLine}\n${existing}` : idLine;
|
|
106
|
+
const rebuilt = `${FRONTMATTER_DELIMITER}\n${newFrontmatter}\n${FRONTMATTER_DELIMITER}\n${split.body}`;
|
|
107
|
+
fs.writeFileSync(file, rebuilt, "utf8");
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Backfill a stable `id` into every v3 leaf's frontmatter.
|
|
113
|
+
*
|
|
114
|
+
* v3 leaves are addressed by their on-disk `path`, which moves as the tree is
|
|
115
|
+
* reorganized. A stable `id` gives downstream self-maintenance machinery a
|
|
116
|
+
* durable handle that survives path churn. The id is a short hash of the leaf's
|
|
117
|
+
* relative path at backfill time — deterministic, so re-runs and fresh installs
|
|
118
|
+
* converge — and existing ids are preserved.
|
|
119
|
+
*/
|
|
120
|
+
export const backfillLeafIdsMigration: WorkspaceMigration = {
|
|
121
|
+
id: "092-backfill-leaf-ids",
|
|
122
|
+
description: "Backfill a stable id into every v3 leaf's frontmatter",
|
|
123
|
+
retryFailedCheckpoint: true,
|
|
124
|
+
|
|
125
|
+
run(workspaceDir: string): void {
|
|
126
|
+
const leavesDir = join(workspaceDir, LEAVES_REL);
|
|
127
|
+
if (!fs.existsSync(leavesDir)) return; // No v3 leaves yet — no-op.
|
|
128
|
+
|
|
129
|
+
let rewritten = 0;
|
|
130
|
+
for (const file of collectLeafFiles(leavesDir)) {
|
|
131
|
+
if (backfillLeaf(leavesDir, file)) rewritten += 1;
|
|
132
|
+
}
|
|
133
|
+
if (rewritten > 0) {
|
|
134
|
+
log.info(
|
|
135
|
+
{ rewritten, leavesDir },
|
|
136
|
+
"Backfilled stable ids into v3 leaves",
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
// No-op: stripping ids would discard the durable handles other code now
|
|
142
|
+
// relies on. A backfilled id is harmless to leave in place on rollback.
|
|
143
|
+
down(): void {},
|
|
144
|
+
};
|