@vellumai/assistant 0.8.5 → 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 +33 -1
- package/ARCHITECTURE.md +1 -1
- package/Dockerfile +1 -0
- package/bun.lock +11 -2
- package/bunfig.toml +6 -1
- package/docker-entrypoint.sh +8 -6
- package/docs/credential-execution-service.md +6 -6
- package/docs/plugins.md +67 -31
- 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 +15 -17
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +10 -3
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
- package/openapi.yaml +5585 -469
- package/package.json +7 -3
- package/scripts/generate-openapi.ts +20 -13
- package/src/__tests__/actor-token-service.test.ts +3 -2
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
- package/src/__tests__/agent-loop-exit-reason.test.ts +336 -42
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +21 -33
- 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 +5 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +23 -40
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/annotate-risk-options.test.ts +1 -0
- 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 +5 -11
- package/src/__tests__/approval-routes-http.test.ts +13 -15
- package/src/__tests__/assert-not-live-db.ts +79 -0
- package/src/__tests__/assistant-event.test.ts +15 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +11 -27
- package/src/__tests__/audit-log-rotation.test.ts +2 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
- 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__/background-workers-disk-pressure.test.ts +5 -8
- package/src/__tests__/browser-skill-endstate.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +10 -14
- package/src/__tests__/call-controller.test.ts +3 -2
- 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 +51 -22
- package/src/__tests__/channel-approvals.test.ts +3 -1
- package/src/__tests__/channel-guardian.test.ts +3 -2
- 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 +170 -0
- package/src/__tests__/channel-reply-delivery.test.ts +35 -0
- package/src/__tests__/channel-retry-sweep.test.ts +388 -79
- package/src/__tests__/checker.test.ts +12 -12
- 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 +6 -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 +186 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +1 -0
- package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +7 -5
- package/src/__tests__/computer-use-tools.test.ts +14 -16
- package/src/__tests__/config-loader-backfill.test.ts +13 -28
- package/src/__tests__/config-loader-corrupt.test.ts +5 -5
- package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
- package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
- package/src/__tests__/config-schema.test.ts +10 -10
- package/src/__tests__/config-watcher.test.ts +28 -0
- package/src/__tests__/connection-model-compat.test.ts +83 -0
- package/src/__tests__/contacts-tools.test.ts +3 -2
- package/src/__tests__/context-search-agent-runner.test.ts +6 -3
- package/src/__tests__/context-token-estimator.test.ts +56 -0
- package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +19 -7
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +4 -2
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +13 -27
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +464 -90
- package/src/__tests__/conversation-agent-loop.test.ts +1069 -64
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -3
- package/src/__tests__/conversation-app-control-instantiation.test.ts +29 -19
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +2 -1
- package/src/__tests__/conversation-attention-store.test.ts +101 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
- package/src/__tests__/conversation-clear-safety.test.ts +20 -10
- package/src/__tests__/conversation-confirmation-signals.test.ts +16 -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-error.test.ts +30 -0
- package/src/__tests__/conversation-fork-crud.test.ts +132 -157
- package/src/__tests__/conversation-fork-route.test.ts +19 -16
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
- package/src/__tests__/conversation-lifecycle.test.ts +4 -2
- package/src/__tests__/conversation-list-source.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +5 -3
- package/src/__tests__/conversation-load-history-stripped.test.ts +2 -1
- package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
- package/src/__tests__/conversation-pairing.test.ts +87 -4
- package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +30 -7
- package/src/__tests__/conversation-process-callsite.test.ts +28 -30
- package/src/__tests__/conversation-provider-retry-repair.test.ts +58 -44
- package/src/__tests__/conversation-queue.test.ts +603 -455
- package/src/__tests__/conversation-routes-disk-view.test.ts +6 -20
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +35 -10
- package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -4
- package/src/__tests__/conversation-runtime-assembly.test.ts +98 -22
- package/src/__tests__/conversation-runtime-workspace.test.ts +19 -1
- package/src/__tests__/conversation-skill-tools.test.ts +38 -142
- package/src/__tests__/conversation-slash-queue.test.ts +120 -62
- package/src/__tests__/conversation-slash-unknown.test.ts +18 -15
- package/src/__tests__/conversation-speed-override.test.ts +9 -22
- package/src/__tests__/conversation-stream-state.test.ts +484 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +52 -15
- package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
- package/src/__tests__/conversation-surfaces-table-action.test.ts +13 -32
- package/src/__tests__/conversation-sync-tags.test.ts +128 -12
- package/src/__tests__/conversation-title-service.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +53 -11
- package/src/__tests__/conversation-unread-route.test.ts +14 -2
- package/src/__tests__/conversation-usage.test.ts +1 -2
- package/src/__tests__/conversation-wipe.test.ts +1 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +4 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +53 -22
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +32 -7
- package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
- package/src/__tests__/credential-broker-server-use.test.ts +5 -5
- package/src/__tests__/credential-execution-client.test.ts +72 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +10 -12
- package/src/__tests__/credential-execution-tools.test.ts +1 -2
- package/src/__tests__/credential-health-service.test.ts +252 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -6
- package/src/__tests__/credential-vault-unit.test.ts +19 -19
- package/src/__tests__/credential-vault.test.ts +5 -5
- package/src/__tests__/cross-provider-web-search.test.ts +61 -3
- package/src/__tests__/cu-unified-flow.test.ts +26 -1
- package/src/__tests__/db-connection-isolation.test.ts +7 -6
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
- package/src/__tests__/db-schedule-syntax-migration.test.ts +11 -0
- package/src/__tests__/db-test-helpers.ts +58 -0
- package/src/__tests__/disk-pressure-guard.test.ts +119 -36
- package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
- package/src/__tests__/disk-pressure-routes.test.ts +9 -35
- package/src/__tests__/disk-pressure-tools.test.ts +0 -4
- package/src/__tests__/dm-persistence.test.ts +33 -42
- package/src/__tests__/document-create-dedupe.test.ts +189 -0
- package/src/__tests__/document-find-replace.test.ts +3 -2
- package/src/__tests__/document-tool-security.test.ts +81 -2
- package/src/__tests__/dynamic-page-surface.test.ts +68 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
- package/src/__tests__/edit-propagation.test.ts +1 -2
- package/src/__tests__/empty-response-pipeline.test.ts +127 -5
- package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
- package/src/__tests__/encrypted-store.test.ts +11 -9
- package/src/__tests__/feature-flag-test-helpers.ts +53 -0
- package/src/__tests__/filing-service.test.ts +3 -2
- package/src/__tests__/first-greeting.test.ts +103 -12
- package/src/__tests__/gateway-flag-listener.test.ts +0 -1
- package/src/__tests__/gemini-inline-media.test.ts +78 -0
- package/src/__tests__/gemini-provider.test.ts +375 -26
- package/src/__tests__/guardian-action-sweep.test.ts +3 -2
- package/src/__tests__/guardian-outbound-http.test.ts +3 -2
- package/src/__tests__/guardian-routing-state.test.ts +60 -71
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +10 -7
- package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
- package/src/__tests__/heartbeat-service.test.ts +3 -1
- package/src/__tests__/helpers/mock-logger.ts +26 -0
- 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-bash-routes.test.ts +1 -0
- package/src/__tests__/host-cu-proxy.test.ts +2 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +1 -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-routes-targeted.test.ts +1 -0
- 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 +11 -5
- package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
- package/src/__tests__/http-conversation-lineage.test.ts +3 -2
- package/src/__tests__/http-user-message-parity.test.ts +31 -9
- package/src/__tests__/identity-intro-cache.test.ts +154 -22
- package/src/__tests__/inbound-slack-persistence.test.ts +51 -74
- package/src/__tests__/inference-profile-reaper.test.ts +3 -2
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -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 +4 -18
- 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__/inline-skill-load-permissions.test.ts +4 -4
- package/src/__tests__/list-messages-attachments.test.ts +7 -8
- package/src/__tests__/list-messages-hidden-metadata.test.ts +93 -11
- 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-context-normalization.test.ts +42 -0
- package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
- package/src/__tests__/llm-resolver.test.ts +346 -39
- package/src/__tests__/llm-schema.test.ts +1 -1
- 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__/manual-token-reconciliation.test.ts +76 -1
- package/src/__tests__/mcp-abort-signal.test.ts +14 -0
- package/src/__tests__/mcp-auth-routes.test.ts +15 -10
- package/src/__tests__/mcp-client-auth.test.ts +14 -0
- 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 +9 -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-from-url.test.ts +3 -3
- package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +18 -2
- package/src/__tests__/model-intents.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +44 -22
- package/src/__tests__/notification-decision-identity.test.ts +9 -18
- package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
- package/src/__tests__/notification-deep-link.test.ts +62 -0
- package/src/__tests__/oauth-commands-routes.test.ts +38 -1
- package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
- package/src/__tests__/oauth-store.test.ts +3 -2
- package/src/__tests__/onboarding-template-contract.test.ts +13 -2
- package/src/__tests__/openai-provider.test.ts +74 -79
- package/src/__tests__/openai-responses-provider.test.ts +90 -86
- package/src/__tests__/openrouter-provider-only.test.ts +27 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +48 -2
- 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 +154 -27
- package/src/__tests__/persistence-secret-redaction.test.ts +85 -13
- package/src/__tests__/pipeline-runner.test.ts +2 -3
- package/src/__tests__/plugin-bootstrap.test.ts +60 -36
- 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 +51 -64
- 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 +38 -32
- package/src/__tests__/process-message-display-content.test.ts +49 -64
- package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
- 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 +215 -8
- package/src/__tests__/provider-registry-ollama.test.ts +45 -22
- 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__/recording-handler.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +82 -76
- package/src/__tests__/relay-server.test.ts +30 -23
- 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-attachment-metadata.test.ts +3 -2
- 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 +83 -1
- package/src/__tests__/schedule-tools.test.ts +125 -0
- package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
- package/src/__tests__/secret-ingress-http.test.ts +7 -3
- 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__/secure-keys.test.ts +3 -3
- package/src/__tests__/send-endpoint-busy.test.ts +83 -43
- package/src/__tests__/server-history-render.test.ts +4 -1
- package/src/__tests__/shell-observability.test.ts +249 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +19 -21
- package/src/__tests__/skill-feature-flags.test.ts +20 -22
- package/src/__tests__/skill-load-feature-flag.test.ts +15 -15
- package/src/__tests__/skill-projection-feature-flag.test.ts +44 -30
- package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
- package/src/__tests__/skill-tool-factory.test.ts +96 -95
- package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
- package/src/__tests__/skillssh-files.test.ts +1 -0
- package/src/__tests__/slack-channel-config.test.ts +3 -3
- 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 +13 -5
- package/src/__tests__/subagent-disposal.test.ts +27 -8
- package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
- package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
- package/src/__tests__/subagent-manager-notify.test.ts +20 -8
- package/src/__tests__/subagent-notify-parent.test.ts +5 -4
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
- package/src/__tests__/subagent-tools.test.ts +2 -1
- package/src/__tests__/suggestion-routes.test.ts +4 -3
- package/src/__tests__/sync-message-contract.test.ts +19 -16
- package/src/__tests__/system-prompt.test.ts +92 -0
- package/src/__tests__/terminal-tools.test.ts +3 -24
- package/src/__tests__/test-preload-verifier.ts +68 -0
- package/src/__tests__/test-preload.ts +32 -39
- 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-executor-lifecycle-events.test.ts +20 -7
- package/src/__tests__/tool-executor.test.ts +55 -10
- package/src/__tests__/tool-preview-lifecycle.test.ts +14 -11
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- 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__/twilio-routes.test.ts +3 -2
- package/src/__tests__/validate-input.test.ts +381 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +10 -7
- package/src/__tests__/voice-session-bridge.test.ts +50 -35
- package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
- package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
- package/src/acp/prepare-agent-env.ts +52 -11
- package/src/acp/session-manager.ts +5 -6
- package/src/agent/compaction-circuit.ts +140 -0
- package/src/agent/loop.ts +489 -85
- package/src/api/README.md +126 -2
- package/src/api/constants/call-sites.ts +27 -0
- 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 +49 -0
- package/src/api/events/assistant-text-delta.ts +30 -0
- package/src/api/events/assistant-turn-start.ts +31 -0
- 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 +44 -0
- package/src/api/events/document-comment-deleted.ts +22 -0
- package/src/api/events/document-comment-reopened.ts +23 -0
- package/src/api/events/document-comment-resolved.ts +25 -0
- 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 +22 -0
- package/src/api/events/generation-handoff.ts +39 -0
- 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 +40 -0
- 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 +28 -0
- package/src/api/events/question-request.ts +67 -0
- package/src/{events → api/events}/relationship-state-updated.ts +6 -8
- 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 +30 -0
- 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 +482 -3
- 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 +41 -0
- package/src/api/responses/llm-request-log-entry.ts +93 -0
- package/src/api/responses/memory-recall-log.ts +65 -0
- package/src/api/responses/memory-v2-activation-log.ts +78 -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/background-wake-routes.test.ts +687 -52
- package/src/background-wake/next-wake.test.ts +31 -1
- package/src/background-wake/next-wake.ts +4 -1
- package/src/background-wake/platform-client.test.ts +308 -0
- package/src/background-wake/platform-client.ts +167 -0
- package/src/background-wake/publisher.ts +91 -0
- package/src/background-wake/runtime-registry.ts +2 -2
- package/src/background-wake/wake-intent-hooks.test.ts +282 -0
- package/src/calls/call-conversation-messages.ts +6 -4
- package/src/calls/guardian-action-sweep.ts +6 -4
- package/src/calls/guardian-dispatch.ts +1 -0
- package/src/calls/relay-server.ts +12 -8
- package/src/calls/voice-session-bridge.ts +17 -31
- package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
- package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
- package/src/cli/commands/__tests__/notifications.test.ts +184 -40
- package/src/cli/commands/avatar.ts +17 -11
- package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
- package/src/cli/commands/channels/index.ts +229 -0
- 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 +168 -203
- package/src/cli/commands/notifications.ts +365 -55
- package/src/cli/lib/cli-colors.ts +24 -6
- package/src/cli/lib/open-browser.ts +7 -2
- package/src/cli/program.ts +6 -5
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/assistant-feature-flags.ts +25 -44
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -3
- package/src/config/bundled-skills/document-editor/SKILL.md +5 -1
- 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 +2 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +10 -2
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
- package/src/config/call-site-defaults.ts +3 -8
- package/src/config/feature-flag-cache.ts +86 -0
- package/src/config/feature-flag-registry.json +42 -26
- package/src/config/llm-context-resolution.ts +10 -1
- package/src/config/llm-resolver.ts +121 -15
- package/src/config/loader.ts +4 -5
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -211
- package/src/config/schemas/call-site-catalog.ts +8 -15
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +92 -4
- package/src/config/schemas/memory-lifecycle.ts +24 -0
- package/src/config/schemas/memory-v2.ts +0 -227
- package/src/config/schemas/memory-v3.ts +39 -0
- package/src/config/schemas/memory.ts +6 -1
- package/src/config/schemas/services.ts +6 -2
- package/src/config/schemas/timeouts.ts +3 -1
- package/src/config/seed-inference-profiles.ts +36 -16
- package/src/context/compactor.ts +54 -31
- package/src/context/token-estimator.ts +29 -5
- package/src/context/tool-result-truncation.ts +1 -43
- package/src/context/window-manager.ts +138 -20
- package/src/credential-execution/executable-discovery.ts +40 -0
- package/src/credential-execution/process-manager.ts +6 -2
- package/src/credential-health/credential-health-service.ts +125 -40
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +15 -17
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -2
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +11 -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 +613 -155
- package/src/daemon/conversation-agent-loop.ts +409 -605
- package/src/daemon/conversation-error.ts +40 -12
- 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 +83 -44
- package/src/daemon/conversation-notifiers.ts +7 -5
- package/src/daemon/conversation-process.ts +174 -116
- package/src/daemon/conversation-runtime-assembly.ts +76 -30
- package/src/daemon/conversation-skill-tools.ts +14 -30
- package/src/daemon/conversation-store.ts +6 -5
- package/src/daemon/conversation-surfaces.ts +124 -103
- package/src/daemon/conversation-tool-setup.ts +36 -48
- package/src/daemon/conversation.ts +111 -166
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/daemon-skill-host.ts +7 -4
- package/src/daemon/disk-pressure-guard.ts +54 -50
- package/src/daemon/external-plugins-bootstrap.ts +46 -24
- package/src/daemon/first-greeting.ts +53 -13
- package/src/daemon/guardian-action-generators.ts +2 -2
- package/src/daemon/handlers/conversations.ts +6 -22
- package/src/daemon/handlers/shared.ts +10 -1
- 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 +40 -67
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/meet-manifest-loader.ts +10 -17
- 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 +25 -125
- package/src/daemon/message-types/document-comments.ts +8 -44
- package/src/daemon/message-types/documents.ts +3 -9
- package/src/daemon/message-types/home.ts +5 -18
- package/src/daemon/message-types/integrations.ts +4 -13
- package/src/daemon/message-types/messages.ts +47 -377
- 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/subagents.ts +6 -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 +58 -55
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +28 -0
- package/src/daemon/switch-inference-profile-tool.ts +13 -3
- package/src/daemon/tool-setup-types.ts +0 -6
- package/src/daemon/tool-side-effects.ts +10 -7
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +21 -1
- package/src/documents/document-store.ts +38 -0
- package/src/export/__tests__/transcript-formatter.test.ts +1 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +31 -0
- package/src/heartbeat/heartbeat-run-store.ts +31 -0
- package/src/heartbeat/heartbeat-service.ts +79 -0
- package/src/home/__tests__/feed-writer.test.ts +161 -0
- package/src/home/__tests__/post-connect-feed.test.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +55 -59
- package/src/home/feature-gate.ts +22 -0
- package/src/home/feed-types.ts +36 -221
- package/src/home/feed-writer.ts +146 -7
- package/src/home/suggested-prompts.ts +27 -145
- package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
- package/src/ipc/__tests__/email-ipc.test.ts +0 -9
- package/src/ipc/gateway-client.test.ts +4 -1
- 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 +19 -9
- package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
- package/src/ipc/skill-routes/__tests__/registries.test.ts +59 -20
- package/src/ipc/skill-routes/memory.ts +27 -13
- package/src/ipc/skill-routes/providers.ts +5 -6
- package/src/ipc/skill-routes/registries.ts +39 -88
- 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-enqueue-gate.test.ts +1 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +11 -6
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
- 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-attention-store.ts +17 -3
- package/src/memory/conversation-crud.ts +386 -115
- package/src/memory/conversation-queries.ts +78 -22
- package/src/memory/db-connection.ts +29 -19
- package/src/memory/db-init.ts +12 -0
- package/src/memory/db-maintenance.ts +18 -2
- package/src/memory/db-singleton.ts +77 -0
- package/src/memory/delivery-channels.ts +82 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
- 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.test.ts +3 -3
- 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/embedding.test.ts +3 -2
- package/src/memory/job-handlers/summarization.ts +1 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
- package/src/memory/jobs-store.ts +3 -1
- package/src/memory/jobs-worker.ts +63 -40
- package/src/memory/llm-request-log-source-clickhouse.ts +55 -1
- package/src/memory/llm-request-log-source-local.ts +13 -0
- package/src/memory/llm-request-log-source.ts +21 -6
- package/src/memory/llm-request-log-store.ts +147 -3
- 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 +13 -1
- package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
- package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
- 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 +6 -0
- package/src/memory/schema/conversations.ts +9 -1
- package/src/memory/schema/inference.ts +0 -1
- package/src/memory/schema/infrastructure.ts +11 -0
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
- package/src/memory/v2/__tests__/consolidation-job.test.ts +124 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +9 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +9 -4
- package/src/memory/v2/__tests__/harness-runner.test.ts +26 -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 +9 -5
- package/src/memory/v2/backfill-jobs.ts +6 -0
- package/src/memory/v2/consolidation-job.ts +89 -9
- package/src/memory/v2/harness/metrics.ts +5 -1
- package/src/memory/v2/harness/replay-input.ts +19 -3
- package/src/memory/v2/harness/runner.ts +6 -0
- package/src/memory/v2/harness/trace.ts +6 -0
- 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/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
- package/src/notifications/adapters/slack.ts +45 -11
- package/src/notifications/broadcaster.ts +114 -63
- package/src/notifications/conversation-pairing.ts +30 -8
- package/src/notifications/decision-engine.ts +10 -13
- package/src/notifications/decisions-store.ts +32 -1
- package/src/notifications/deliveries-store.ts +45 -0
- package/src/notifications/edit-notification.ts +201 -0
- package/src/notifications/emit-signal.ts +11 -1
- package/src/notifications/preference-extractor.ts +11 -14
- package/src/notifications/signal.ts +10 -0
- package/src/notifications/types.ts +37 -0
- package/src/oauth/byo-connection.test.ts +67 -3
- package/src/oauth/byo-connection.ts +32 -5
- package/src/oauth/connect-orchestrator.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +76 -0
- package/src/oauth/connection-resolver.ts +49 -10
- package/src/oauth/manual-token-connection.ts +51 -3
- package/src/oauth/seed-providers.ts +3 -0
- package/src/permissions/approval-policy.test.ts +19 -5
- package/src/permissions/approval-policy.ts +14 -3
- package/src/permissions/checker.ts +21 -8
- 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/platform/client.test.ts +24 -1
- package/src/platform/client.ts +8 -0
- package/src/platform/feature-gate.ts +15 -0
- 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} +16 -46
- 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 +107 -102
- 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 +21 -8
- package/src/proactive-artifact/job.ts +3 -1
- package/src/prompts/__tests__/system-prompt.test.ts +4 -4
- package/src/prompts/sections.ts +20 -7
- package/src/prompts/system-prompt.ts +38 -40
- package/src/prompts/template-detection.ts +10 -4
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
- package/src/prompts/templates/BOOTSTRAP.md +10 -10
- package/src/prompts/templates/IDENTITY.md +0 -2
- package/src/prompts/templates/system-sections.ts +6 -0
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -4
- package/src/providers/__tests__/registry-native-web-search.test.ts +122 -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 +34 -18
- package/src/providers/connection-model-compat.ts +23 -0
- package/src/providers/connection-resolution.ts +39 -20
- package/src/providers/fireworks/client.ts +1 -0
- package/src/providers/gemini/client.ts +176 -37
- package/src/providers/gemini/inline-media.ts +74 -0
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
- package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
- package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
- package/src/providers/inference/auth.ts +0 -8
- package/src/providers/inference/connections.ts +3 -66
- package/src/providers/inference/resolve-auth.ts +2 -3
- package/src/providers/model-catalog.ts +35 -1
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -7
- package/src/providers/openai/chat-completions-provider.ts +111 -16
- package/src/providers/openai/codex-models.ts +2 -0
- package/src/providers/openai/responses-provider.ts +54 -57
- package/src/providers/openrouter/client.ts +14 -14
- package/src/providers/provider-send-message.ts +23 -14
- package/src/providers/ratelimit.ts +1 -9
- package/src/providers/registry.ts +48 -8
- package/src/providers/retry.ts +16 -9
- package/src/providers/search-provider-catalog.ts +17 -9
- package/src/providers/types.ts +20 -2
- package/src/providers/usage-tracking.ts +1 -9
- package/src/runtime/__tests__/agent-wake.test.ts +132 -26
- package/src/runtime/__tests__/background-job-runner.test.ts +2 -3
- package/src/runtime/access-request-helper.ts +1 -0
- 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 -1069
- 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 +70 -5
- package/src/runtime/channel-reply-delivery.ts +23 -0
- package/src/runtime/channel-retry-sweep.ts +59 -30
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- 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/migrations/vbundle-builder.ts +3 -2
- 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__/bookmark-routes.test.ts +1 -0
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +436 -0
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +26 -72
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +58 -5
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
- 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__/surface-content-routes.test.ts +294 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
- package/src/runtime/routes/__tests__/tts-routes.test.ts +3 -3
- package/src/runtime/routes/acp-routes-list.test.ts +3 -0
- 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 +208 -28
- 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 +201 -23
- 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 +9 -5
- 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 +11 -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 +292 -0
- package/src/runtime/routes/conversation-list-routes.ts +225 -9
- package/src/runtime/routes/conversation-management-routes.ts +96 -28
- package/src/runtime/routes/conversation-query-routes.ts +148 -51
- package/src/runtime/routes/conversation-routes.ts +259 -158
- package/src/runtime/routes/conversation-starter-routes.ts +22 -13
- package/src/runtime/routes/conversations-import-routes.ts +25 -7
- 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 +31 -11
- 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 +32 -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 +149 -16
- 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 +72 -16
- package/src/runtime/routes/identity-routes.ts +42 -11
- 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 +524 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +72 -27
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
- package/src/runtime/routes/inference-provider-connection-routes.ts +26 -31
- 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 +18 -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/llm-context-normalization.ts +7 -2
- 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 +283 -259
- package/src/runtime/routes/migration-rollback-routes.ts +5 -1
- package/src/runtime/routes/migration-routes.ts +49 -13
- package/src/runtime/routes/notification-routes.ts +80 -2
- package/src/runtime/routes/oauth-apps.ts +33 -11
- package/src/runtime/routes/oauth-commands-routes.ts +43 -15
- 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 +10 -38
- package/src/runtime/routes/surface-content-routes.ts +21 -6
- package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
- 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 +8 -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 +4 -4
- package/src/runtime/services/analyze-conversation.ts +3 -6
- package/src/runtime/services/conversation-serializer.ts +24 -2
- package/src/runtime/slack-dm-text-delivery.ts +177 -0
- package/src/runtime/sync/resource-sync-events.ts +17 -3
- package/src/runtime/sync/sync-publisher.ts +2 -2
- package/src/runtime/tool-grant-request-helper.ts +1 -0
- package/src/schedule/run-script.ts +28 -3
- package/src/schedule/schedule-store.ts +16 -1
- package/src/schedule/scheduler.ts +114 -16
- package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
- package/src/security/encrypted-store.ts +7 -16
- package/src/security/store-path-override.ts +61 -0
- package/src/signals/user-message.ts +10 -16
- 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/skills/validate-input.ts +177 -0
- package/src/subagent/manager.ts +16 -19
- package/src/subagent/types.ts +6 -0
- package/src/tasks/tool-sanitizer.ts +2 -2
- 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 +42 -24
- 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/browser/__tests__/browser-execution-acquire.test.ts +2 -8
- package/src/tools/computer-use/definitions.ts +295 -289
- 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/document/document-tool.ts +131 -8
- package/src/tools/execution-target.ts +3 -6
- package/src/tools/execution-timeout.ts +3 -4
- package/src/tools/executor.ts +18 -55
- 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.test.ts +1 -0
- package/src/tools/host-filesystem/edit.ts +44 -42
- package/src/tools/host-filesystem/read.test.ts +1 -0
- package/src/tools/host-filesystem/read.ts +49 -35
- package/src/tools/host-filesystem/transfer.test.ts +31 -6
- package/src/tools/host-filesystem/transfer.ts +121 -108
- package/src/tools/host-filesystem/write.test.ts +1 -0
- package/src/tools/host-filesystem/write.ts +33 -31
- package/src/tools/host-terminal/host-shell.ts +50 -48
- package/src/tools/mcp/mcp-tool-factory.ts +0 -2
- package/src/tools/memory/register.ts +23 -24
- package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
- package/src/tools/network/__tests__/web-search.test.ts +211 -3
- package/src/tools/network/managed-search-proxy.ts +183 -0
- package/src/tools/network/web-fetch.ts +49 -46
- package/src/tools/network/web-search.ts +215 -57
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/registry.ts +184 -118
- package/src/tools/schedule/create.ts +12 -1
- 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/skills/skill-tool-factory.ts +17 -36
- package/src/tools/subagent/notify-parent.ts +35 -32
- package/src/tools/subagent/spawn.ts +3 -0
- 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-approval-handler.ts +10 -4
- package/src/tools/tool-defaults.ts +20 -9
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/tool-name-aliases.ts +72 -14
- package/src/tools/types.ts +86 -33
- package/src/tools/ui-surface/definitions.ts +166 -94
- package/src/types/onboarding-context.ts +6 -0
- package/src/usage/attribution.ts +32 -1
- package/src/usage/types.ts +10 -0
- package/src/util/browser.ts +7 -2
- 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/090-memory-router-cost-optimized-profile.ts +109 -0
- package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
- 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 +10 -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 -344
- 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 -468
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
- package/src/memory/v3/__tests__/edges.test.ts +0 -563
- package/src/memory/v3/__tests__/filter.test.ts +0 -512
- package/src/memory/v3/__tests__/gate.test.ts +0 -574
- package/src/memory/v3/__tests__/index-composition.test.ts +0 -233
- package/src/memory/v3/__tests__/loop.test.ts +0 -530
- package/src/memory/v3/__tests__/retriever.test.ts +0 -226
- package/src/memory/v3/__tests__/scouts.test.ts +0 -440
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -312
- package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
- package/src/memory/v3/__tests__/traversal.test.ts +0 -469
- 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 -707
- package/src/memory/v3/__tests__/validate.test.ts +0 -245
- 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/edge-learning-job.ts +0 -160
- package/src/memory/v3/edges.ts +0 -249
- package/src/memory/v3/filter.ts +0 -281
- package/src/memory/v3/gate.ts +0 -334
- package/src/memory/v3/index-composition.ts +0 -113
- package/src/memory/v3/llm-capture.ts +0 -46
- package/src/memory/v3/loop.ts +0 -382
- 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 -420
- package/src/memory/v3/shadow-middleware.ts +0 -305
- package/src/memory/v3/traversal.ts +0 -206
- 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 -351
- package/src/memory/v3/validate.ts +0 -300
- 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 -127
- 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
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memory v3 — Tree index (DAG build + cache).
|
|
3
|
-
*
|
|
4
|
-
* The v3 tree is a DAG *overlay* over the flat `memory/concepts/` pages: every
|
|
5
|
-
* node carries an ordered `children` list whose entries are either
|
|
6
|
-
* `"page:<slug>"` (a leaf concept page, canonical content untouched by v3) or
|
|
7
|
-
* `"node:<id>"` (a sub-node in the tree). A page or node may be referenced by
|
|
8
|
-
* more than one parent — hence DAG, not tree.
|
|
9
|
-
*
|
|
10
|
-
* This module scans every node on disk and materializes that edge list into
|
|
11
|
-
* forward and reverse adjacency maps so downstream routing/validation can walk
|
|
12
|
-
* the graph without re-reading the filesystem:
|
|
13
|
-
* - `childrenByNode` — node id → ordered child refs (forward edges).
|
|
14
|
-
* - `parentsByNode` — node id → set of parent node ids (reverse edges for
|
|
15
|
-
* `node:` children).
|
|
16
|
-
* - `pageParents` — page slug → set of parent node ids (reverse edges for
|
|
17
|
-
* `page:` children).
|
|
18
|
-
*
|
|
19
|
-
* The build is **structural only**: it never verifies that a referenced page
|
|
20
|
-
* or node actually exists. Dangling refs are retained in the adjacency maps so
|
|
21
|
-
* a later validation pass can report them. Root detection prefers the reserved
|
|
22
|
-
* `_root` id; absent that it picks the single node with no parents (warning and
|
|
23
|
-
* picking deterministically if the choice is ambiguous).
|
|
24
|
-
*
|
|
25
|
-
* The build is cached module-locally per `workspaceDir`, mirroring
|
|
26
|
-
* `../v2/page-index.ts`. Callers must invalidate via `invalidateTreeIndex` when
|
|
27
|
-
* tree nodes change — `tree-store.ts`'s `writeNode` / `deleteNode` already do.
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
import { getLogger } from "../../util/logger.js";
|
|
31
|
-
import { listNodes, readNode, ROOT_NODE_ID } from "./tree-store.js";
|
|
32
|
-
import type { TreeNode } from "./types.js";
|
|
33
|
-
|
|
34
|
-
const log = getLogger("memory-v3-tree-index");
|
|
35
|
-
|
|
36
|
-
/** Prefix marking a child ref that targets a leaf concept page. */
|
|
37
|
-
const PAGE_REF_PREFIX = "page:";
|
|
38
|
-
|
|
39
|
-
/** Prefix marking a child ref that targets a sub-node in the tree. */
|
|
40
|
-
const NODE_REF_PREFIX = "node:";
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* A single parsed `children` entry. `kind` distinguishes a leaf concept page
|
|
44
|
-
* (`"page"`) from a sub-node (`"node"`); `ref` is the bare slug or node id with
|
|
45
|
-
* the `page:` / `node:` prefix stripped.
|
|
46
|
-
*/
|
|
47
|
-
export interface ChildRef {
|
|
48
|
-
kind: "page" | "node";
|
|
49
|
-
ref: string;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Snapshot of the v3 tree DAG for one workspace.
|
|
54
|
-
*
|
|
55
|
-
* `nodes` is every readable node keyed by id. The three adjacency maps are
|
|
56
|
-
* derived from each node's `children`:
|
|
57
|
-
* - `childrenByNode` — forward edges, preserving `children` order.
|
|
58
|
-
* - `parentsByNode` — reverse edges restricted to `node:` children.
|
|
59
|
-
* - `pageParents` — reverse edges restricted to `page:` children, keyed by
|
|
60
|
-
* page slug.
|
|
61
|
-
*
|
|
62
|
-
* `root` is the entry-point node id (`_root` when present). Dangling refs (a
|
|
63
|
-
* `node:`/`page:` target with no on-disk file) are retained throughout —
|
|
64
|
-
* validation, not the index build, is responsible for surfacing them.
|
|
65
|
-
*/
|
|
66
|
-
export interface TreeIndex {
|
|
67
|
-
nodes: Map<string, TreeNode>;
|
|
68
|
-
childrenByNode: Map<string, ReadonlyArray<ChildRef>>;
|
|
69
|
-
parentsByNode: Map<string, Set<string>>;
|
|
70
|
-
pageParents: Map<string, Set<string>>;
|
|
71
|
-
root: string;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
interface CachedIndex {
|
|
75
|
-
workspaceDir: string;
|
|
76
|
-
index: TreeIndex;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
let cache: CachedIndex | null = null;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Parse a raw `children` entry into a {@link ChildRef}. Returns `null` for any
|
|
83
|
-
* entry that does not carry a recognized `page:` / `node:` prefix or whose ref
|
|
84
|
-
* body is empty — those are malformed and dropped (with a warn) rather than
|
|
85
|
-
* faithfully threaded through adjacency.
|
|
86
|
-
*/
|
|
87
|
-
function parseChildRef(raw: string): ChildRef | null {
|
|
88
|
-
if (raw.startsWith(PAGE_REF_PREFIX)) {
|
|
89
|
-
const ref = raw.slice(PAGE_REF_PREFIX.length);
|
|
90
|
-
return ref.length > 0 ? { kind: "page", ref } : null;
|
|
91
|
-
}
|
|
92
|
-
if (raw.startsWith(NODE_REF_PREFIX)) {
|
|
93
|
-
const ref = raw.slice(NODE_REF_PREFIX.length);
|
|
94
|
-
return ref.length > 0 ? { kind: "node", ref } : null;
|
|
95
|
-
}
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** Append `parent` to the parent-set for `key`, creating the set on demand. */
|
|
100
|
-
function addParent(
|
|
101
|
-
map: Map<string, Set<string>>,
|
|
102
|
-
key: string,
|
|
103
|
-
parent: string,
|
|
104
|
-
): void {
|
|
105
|
-
let parents = map.get(key);
|
|
106
|
-
if (!parents) {
|
|
107
|
-
parents = new Set();
|
|
108
|
-
map.set(key, parents);
|
|
109
|
-
}
|
|
110
|
-
parents.add(parent);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Pick the root node id from the materialized adjacency. Prefers the reserved
|
|
115
|
-
* {@link ROOT_NODE_ID} when a node with that id exists. Otherwise the root is
|
|
116
|
-
* the single node with no parents; if several nodes are parentless the choice
|
|
117
|
-
* is ambiguous, so warn and pick the ASCII-smallest id for determinism. With no
|
|
118
|
-
* nodes at all the root is `_root` (the well-known handle a migration authors
|
|
119
|
-
* first), matching the empty-workspace contract.
|
|
120
|
-
*/
|
|
121
|
-
function pickRoot(
|
|
122
|
-
nodes: Map<string, TreeNode>,
|
|
123
|
-
parentsByNode: Map<string, Set<string>>,
|
|
124
|
-
): string {
|
|
125
|
-
if (nodes.has(ROOT_NODE_ID)) {
|
|
126
|
-
return ROOT_NODE_ID;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const parentless = [...nodes.keys()].filter(
|
|
130
|
-
(id) => !parentsByNode.has(id) || parentsByNode.get(id)!.size === 0,
|
|
131
|
-
);
|
|
132
|
-
parentless.sort();
|
|
133
|
-
|
|
134
|
-
if (parentless.length === 1) {
|
|
135
|
-
return parentless[0];
|
|
136
|
-
}
|
|
137
|
-
if (parentless.length === 0) {
|
|
138
|
-
return ROOT_NODE_ID;
|
|
139
|
-
}
|
|
140
|
-
log.warn(
|
|
141
|
-
{ parentless },
|
|
142
|
-
"Ambiguous tree root — no '_root' node and multiple parentless nodes; picking ASCII-smallest deterministically",
|
|
143
|
-
);
|
|
144
|
-
return parentless[0];
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Return a `TreeIndex` for `workspaceDir`. Cached module-locally; the cache is
|
|
149
|
-
* invalidated by `invalidateTreeIndex` (called by `tree-store.ts` hooks when
|
|
150
|
-
* nodes change).
|
|
151
|
-
*
|
|
152
|
-
* Cold builds list every node and read them in parallel, dropping any whose
|
|
153
|
-
* read rejects with a warn so one broken node never blocks the rest of the
|
|
154
|
-
* index. Each readable node's `children` is parsed into {@link ChildRef}s and
|
|
155
|
-
* threaded into forward (`childrenByNode`) and reverse (`parentsByNode` /
|
|
156
|
-
* `pageParents`) adjacency. The build is structural only — referenced
|
|
157
|
-
* pages/nodes are never verified to exist; dangling refs are retained for a
|
|
158
|
-
* later validation pass.
|
|
159
|
-
*/
|
|
160
|
-
export async function getTreeIndex(workspaceDir: string): Promise<TreeIndex> {
|
|
161
|
-
if (cache && cache.workspaceDir === workspaceDir) {
|
|
162
|
-
return cache.index;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const ids = await listNodes(workspaceDir);
|
|
166
|
-
|
|
167
|
-
// Read every node in parallel; nodes whose read rejects are dropped with a
|
|
168
|
-
// warn so a single broken node never blocks the rest of the index.
|
|
169
|
-
const settled = await Promise.allSettled(
|
|
170
|
-
ids.map((id) => readNode(workspaceDir, id)),
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
const nodes = new Map<string, TreeNode>();
|
|
174
|
-
const childrenByNode = new Map<string, ReadonlyArray<ChildRef>>();
|
|
175
|
-
const parentsByNode = new Map<string, Set<string>>();
|
|
176
|
-
const pageParents = new Map<string, Set<string>>();
|
|
177
|
-
|
|
178
|
-
for (let i = 0; i < settled.length; i++) {
|
|
179
|
-
const result = settled[i];
|
|
180
|
-
const id = ids[i];
|
|
181
|
-
if (result.status === "rejected") {
|
|
182
|
-
log.warn(
|
|
183
|
-
{ id, err: result.reason },
|
|
184
|
-
"Dropping tree node from index — read failed",
|
|
185
|
-
);
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
const node = result.value;
|
|
189
|
-
// `readNode` returns null only on ENOENT; a node listed by `listNodes`
|
|
190
|
-
// that vanishes between list and read is a benign race — drop it silently.
|
|
191
|
-
if (!node) continue;
|
|
192
|
-
nodes.set(id, node);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Build adjacency in a second pass so every node is registered first — that
|
|
196
|
-
// keeps a deterministic, list-order iteration independent of read timing.
|
|
197
|
-
for (const node of nodes.values()) {
|
|
198
|
-
const childRefs: ChildRef[] = [];
|
|
199
|
-
for (const raw of node.frontmatter.children) {
|
|
200
|
-
const parsed = parseChildRef(raw);
|
|
201
|
-
if (!parsed) {
|
|
202
|
-
log.warn(
|
|
203
|
-
{ id: node.id, raw },
|
|
204
|
-
"Dropping malformed child ref — expected 'page:<slug>' or 'node:<id>'",
|
|
205
|
-
);
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
childRefs.push(parsed);
|
|
209
|
-
const reverse = parsed.kind === "node" ? parentsByNode : pageParents;
|
|
210
|
-
addParent(reverse, parsed.ref, node.id);
|
|
211
|
-
}
|
|
212
|
-
childrenByNode.set(node.id, childRefs);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const root = pickRoot(nodes, parentsByNode);
|
|
216
|
-
|
|
217
|
-
const index: TreeIndex = {
|
|
218
|
-
nodes,
|
|
219
|
-
childrenByNode,
|
|
220
|
-
parentsByNode,
|
|
221
|
-
pageParents,
|
|
222
|
-
root,
|
|
223
|
-
};
|
|
224
|
-
cache = { workspaceDir, index };
|
|
225
|
-
return index;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Clear the cached index. Pass `workspaceDir` to scope invalidation to a
|
|
230
|
-
* specific cache entry; omit it to clear unconditionally.
|
|
231
|
-
*/
|
|
232
|
-
export function invalidateTreeIndex(workspaceDir?: string): void {
|
|
233
|
-
if (!cache) return;
|
|
234
|
-
if (workspaceDir === undefined || cache.workspaceDir === workspaceDir) {
|
|
235
|
-
cache = null;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
@@ -1,394 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memory v3 — Tree node store.
|
|
3
|
-
*
|
|
4
|
-
* Owns the on-disk read/write contract for `memory/tree/<id>.md`. Nodes may
|
|
5
|
-
* live directly under `memory/tree/` or nested in subdirectories (e.g.
|
|
6
|
-
* `memory/tree/people/colleagues.md`); the id encodes the relative path from
|
|
7
|
-
* `tree/` minus the `.md` extension, using forward slashes as separators (so
|
|
8
|
-
* `people/colleagues` is a valid id).
|
|
9
|
-
*
|
|
10
|
-
* The v3 tree is a DAG *overlay* over the existing flat `memory/concepts/`
|
|
11
|
-
* pages — this module never touches `memory/concepts/`. Pages stay canonical
|
|
12
|
-
* and shared; nodes reference pages and sub-nodes by `children` refs
|
|
13
|
-
* (`page:<slug>` / `node:<id>`), which are the portable replacement for
|
|
14
|
-
* filesystem symlinks.
|
|
15
|
-
*
|
|
16
|
-
* Each node is a YAML-frontmatter Markdown file: a `---`-delimited block
|
|
17
|
-
* (`children`, optional `routing_hints` / `summary`) followed by the prose body
|
|
18
|
-
* that is the node's full self-description. This module is the only v3
|
|
19
|
-
* component that knows how to parse or render that format — every other v3
|
|
20
|
-
* module routes through `readNode` / `writeNode` so the on-disk shape can
|
|
21
|
-
* evolve without touching downstream callers.
|
|
22
|
-
*
|
|
23
|
-
* Writes are atomic (temp + rename) so a crash mid-write leaves either the old
|
|
24
|
-
* file or the new file in place — never a half-written node. The id machinery
|
|
25
|
-
* mirrors v2's page-store `slugify` / `validateSlug` so node ids and page slugs
|
|
26
|
-
* share the same filesystem-safe shape.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
import { randomUUID } from "node:crypto";
|
|
30
|
-
import {
|
|
31
|
-
mkdir,
|
|
32
|
-
readdir,
|
|
33
|
-
readFile,
|
|
34
|
-
rename,
|
|
35
|
-
rm,
|
|
36
|
-
stat,
|
|
37
|
-
writeFile,
|
|
38
|
-
} from "node:fs/promises";
|
|
39
|
-
import { dirname, join, relative, sep } from "node:path";
|
|
40
|
-
|
|
41
|
-
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
42
|
-
|
|
43
|
-
import { FRONTMATTER_REGEX } from "../../skills/frontmatter.js";
|
|
44
|
-
import { invalidateTreeIndex } from "./tree-index.js";
|
|
45
|
-
import { type TreeNode, TreeNodeFrontmatterSchema } from "./types.js";
|
|
46
|
-
|
|
47
|
-
/** Filename suffix for tree nodes. */
|
|
48
|
-
const NODE_EXTENSION = ".md";
|
|
49
|
-
|
|
50
|
-
/** Cap individual id-segment length so we stay well under filesystem limits. */
|
|
51
|
-
const MAX_ID_SEGMENT_LENGTH = 80;
|
|
52
|
-
|
|
53
|
-
/** Cap the full id (including any folder separators) to a sane bound. */
|
|
54
|
-
const MAX_ID_TOTAL_LENGTH = 200;
|
|
55
|
-
|
|
56
|
-
/** Each path segment must match this — same shape `slugify` produces. */
|
|
57
|
-
const ID_SEGMENT_REGEX = /^[a-z0-9](?:[a-z0-9-]*)$/;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Reserved id for the root of the v3 tree. The root node is the entry point a
|
|
61
|
-
* future migration authors first; reserving the id keeps the well-known handle
|
|
62
|
-
* stable across the codebase.
|
|
63
|
-
*/
|
|
64
|
-
export const ROOT_NODE_ID = "_root";
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Convert an arbitrary input string into a filesystem-safe id **segment**.
|
|
68
|
-
*
|
|
69
|
-
* Returns a single path segment (no `/`). Path-shaped ids are constructed by
|
|
70
|
-
* the authoring migration writing files at full paths; this helper is for
|
|
71
|
-
* turning free-form text (e.g. a node label) into one clean segment.
|
|
72
|
-
*
|
|
73
|
-
* Rules:
|
|
74
|
-
* - Lowercase ASCII letters, digits, and hyphens only.
|
|
75
|
-
* - Non-ASCII / non-alphanumeric characters (including `/`) collapse to hyphens.
|
|
76
|
-
* - Consecutive hyphens collapse to one; leading/trailing hyphens trimmed.
|
|
77
|
-
* - Truncated to {@link MAX_ID_SEGMENT_LENGTH} characters (with trailing
|
|
78
|
-
* hyphen re-trimmed after truncation).
|
|
79
|
-
* - Empty inputs (e.g. emoji-only) fall back to `node-<random>` so the caller
|
|
80
|
-
* always gets a non-empty, write-safe segment.
|
|
81
|
-
*/
|
|
82
|
-
export function slugify(input: string): string {
|
|
83
|
-
let slug = input
|
|
84
|
-
.toLowerCase()
|
|
85
|
-
.normalize("NFKD")
|
|
86
|
-
.replace(/[^a-z0-9-]+/g, "-")
|
|
87
|
-
.replace(/-{2,}/g, "-")
|
|
88
|
-
.replace(/^-+|-+$/g, "");
|
|
89
|
-
|
|
90
|
-
if (slug.length > MAX_ID_SEGMENT_LENGTH) {
|
|
91
|
-
slug = slug.slice(0, MAX_ID_SEGMENT_LENGTH).replace(/-+$/, "");
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (!slug) {
|
|
95
|
-
slug = `node-${randomUUID().slice(0, 8)}`;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return slug;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Validate a node id — possibly path-shaped — that is about to cross the
|
|
103
|
-
* storage boundary. Throws on any malformed or unsafe value.
|
|
104
|
-
*
|
|
105
|
-
* The on-disk tree treats ids as relative paths under `memory/tree/`. A
|
|
106
|
-
* malformed id (e.g. `..`, leading `/`, embedded null byte) could escape that
|
|
107
|
-
* root via `path.join` if it slipped through, so we enforce shape here at every
|
|
108
|
-
* read/write/delete entry point rather than relying on callers.
|
|
109
|
-
*
|
|
110
|
-
* The reserved {@link ROOT_NODE_ID} (`_root`) is accepted as a special case;
|
|
111
|
-
* its leading underscore would otherwise fail {@link ID_SEGMENT_REGEX}.
|
|
112
|
-
*
|
|
113
|
-
* Rules:
|
|
114
|
-
* - Non-empty, ≤ {@link MAX_ID_TOTAL_LENGTH} chars.
|
|
115
|
-
* - Each `/`-separated segment matches {@link ID_SEGMENT_REGEX}
|
|
116
|
-
* (lowercase alphanum + hyphen, no leading hyphen, ≤80 chars).
|
|
117
|
-
* - No `..` segments, no empty segments (`a//b`), no leading or trailing `/`.
|
|
118
|
-
* - No `\` (Windows separator), no null bytes, no whitespace, no non-ASCII.
|
|
119
|
-
*/
|
|
120
|
-
export function validateNodeId(id: string): void {
|
|
121
|
-
if (typeof id !== "string" || id.length === 0) {
|
|
122
|
-
throw new Error(`Invalid tree-node id: empty`);
|
|
123
|
-
}
|
|
124
|
-
if (id === ROOT_NODE_ID) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
if (id.length > MAX_ID_TOTAL_LENGTH) {
|
|
128
|
-
throw new Error(
|
|
129
|
-
`Invalid tree-node id: length ${id.length} exceeds max ${MAX_ID_TOTAL_LENGTH}: ${id}`,
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
if (id.includes("\\")) {
|
|
133
|
-
throw new Error(`Invalid tree-node id: backslash not allowed: ${id}`);
|
|
134
|
-
}
|
|
135
|
-
if (id.includes("\0")) {
|
|
136
|
-
throw new Error(`Invalid tree-node id: null byte not allowed`);
|
|
137
|
-
}
|
|
138
|
-
if (/\s/.test(id)) {
|
|
139
|
-
throw new Error(`Invalid tree-node id: whitespace not allowed: ${id}`);
|
|
140
|
-
}
|
|
141
|
-
if (id.startsWith("/") || id.endsWith("/")) {
|
|
142
|
-
throw new Error(
|
|
143
|
-
`Invalid tree-node id: leading or trailing '/' not allowed: ${id}`,
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
const segments = id.split("/");
|
|
147
|
-
for (const segment of segments) {
|
|
148
|
-
if (segment.length === 0) {
|
|
149
|
-
throw new Error(`Invalid tree-node id: empty path segment: ${id}`);
|
|
150
|
-
}
|
|
151
|
-
if (segment === "..") {
|
|
152
|
-
throw new Error(`Invalid tree-node id: '..' segment not allowed: ${id}`);
|
|
153
|
-
}
|
|
154
|
-
if (segment.length > MAX_ID_SEGMENT_LENGTH) {
|
|
155
|
-
throw new Error(
|
|
156
|
-
`Invalid tree-node id: segment '${segment}' exceeds max ${MAX_ID_SEGMENT_LENGTH} chars: ${id}`,
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
if (!ID_SEGMENT_REGEX.test(segment)) {
|
|
160
|
-
throw new Error(
|
|
161
|
-
`Invalid tree-node id: segment '${segment}' must match [a-z0-9][a-z0-9-]*: ${id}`,
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// ---------------------------------------------------------------------------
|
|
168
|
-
// Path helpers
|
|
169
|
-
// ---------------------------------------------------------------------------
|
|
170
|
-
|
|
171
|
-
export function getTreeDir(workspaceDir: string): string {
|
|
172
|
-
return join(workspaceDir, "memory", "tree");
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Resolve the absolute path for a node id. Ids may contain `/` to indicate
|
|
177
|
-
* folder hierarchy under `memory/tree/`; `path.join` handles those correctly
|
|
178
|
-
* on POSIX, and `validateNodeId` (called at every public entry point) rejects
|
|
179
|
-
* shapes that could escape the tree root.
|
|
180
|
-
*/
|
|
181
|
-
function getNodePath(workspaceDir: string, id: string): string {
|
|
182
|
-
return join(getTreeDir(workspaceDir), `${id}${NODE_EXTENSION}`);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Compute the id for a tree-node file, given the tree root and the absolute
|
|
187
|
-
* file path. Returns the path-relative location with `.md` stripped and
|
|
188
|
-
* platform separators normalized to `/`. Tolerant of paths that don't end in
|
|
189
|
-
* `.md` so callers walking arbitrary content can use it defensively.
|
|
190
|
-
*/
|
|
191
|
-
function idFromNodePath(treeRoot: string, filePath: string): string {
|
|
192
|
-
const rel = relative(treeRoot, filePath);
|
|
193
|
-
const withoutExt = rel.endsWith(NODE_EXTENSION)
|
|
194
|
-
? rel.slice(0, -NODE_EXTENSION.length)
|
|
195
|
-
: rel;
|
|
196
|
-
return sep === "/" ? withoutExt : withoutExt.split(sep).join("/");
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// ---------------------------------------------------------------------------
|
|
200
|
-
// Frontmatter parse / render
|
|
201
|
-
// ---------------------------------------------------------------------------
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Split raw file contents into (frontmatter, body). If no frontmatter block is
|
|
205
|
-
* present the entire input is treated as body and an empty frontmatter block is
|
|
206
|
-
* returned (validated by `TreeNodeFrontmatterSchema` so any unexpected shape —
|
|
207
|
-
* bad types, extra junk — surfaces as a parse error to the caller, not silent
|
|
208
|
-
* dropped data).
|
|
209
|
-
*
|
|
210
|
-
* The schema's default guarantees `children` is always an array even on a
|
|
211
|
-
* freshly created node with empty frontmatter.
|
|
212
|
-
*/
|
|
213
|
-
function parseNodeContent(raw: string): {
|
|
214
|
-
frontmatter: TreeNode["frontmatter"];
|
|
215
|
-
body: string;
|
|
216
|
-
} {
|
|
217
|
-
const match = raw.match(FRONTMATTER_REGEX);
|
|
218
|
-
if (!match) {
|
|
219
|
-
return {
|
|
220
|
-
frontmatter: TreeNodeFrontmatterSchema.parse({}),
|
|
221
|
-
body: raw,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
const yamlBlock = match[1];
|
|
225
|
-
const body = raw.slice(match[0].length);
|
|
226
|
-
const parsed = parseYaml(yamlBlock) ?? {};
|
|
227
|
-
return {
|
|
228
|
-
frontmatter: TreeNodeFrontmatterSchema.parse(parsed),
|
|
229
|
-
body,
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Render a tree node back into the on-disk Markdown form. The output is always
|
|
235
|
-
* frontmatter + body; even nodes with empty `children` keep the explicit YAML
|
|
236
|
-
* key so callers see the canonical shape on round-trip.
|
|
237
|
-
*/
|
|
238
|
-
export function renderNodeContent(node: TreeNode): string {
|
|
239
|
-
const frontmatter = TreeNodeFrontmatterSchema.parse(node.frontmatter);
|
|
240
|
-
const yamlBlock = stringifyYaml(frontmatter, { indent: 2 }).trimEnd();
|
|
241
|
-
return `---\n${yamlBlock}\n---\n${node.body}`;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// ---------------------------------------------------------------------------
|
|
245
|
-
// Public API
|
|
246
|
-
// ---------------------------------------------------------------------------
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Read a single tree node. Returns `null` if the file does not exist.
|
|
250
|
-
*
|
|
251
|
-
* Any other read or parse failure (permission denied, malformed YAML,
|
|
252
|
-
* frontmatter that fails schema validation) throws — unlike "missing", these
|
|
253
|
-
* are programmer / data-corruption errors the caller needs to see.
|
|
254
|
-
*/
|
|
255
|
-
export async function readNode(
|
|
256
|
-
workspaceDir: string,
|
|
257
|
-
id: string,
|
|
258
|
-
): Promise<TreeNode | null> {
|
|
259
|
-
validateNodeId(id);
|
|
260
|
-
const path = getNodePath(workspaceDir, id);
|
|
261
|
-
let raw: string;
|
|
262
|
-
try {
|
|
263
|
-
raw = await readFile(path, "utf-8");
|
|
264
|
-
} catch (err) {
|
|
265
|
-
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
266
|
-
return null;
|
|
267
|
-
}
|
|
268
|
-
throw err;
|
|
269
|
-
}
|
|
270
|
-
const { frontmatter, body } = parseNodeContent(raw);
|
|
271
|
-
return { id, frontmatter, body };
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* File mtime for a tree node, in epoch ms. Returns 0 when the file is missing
|
|
276
|
-
* or unreadable — callers treat 0 as "no mtime" (e.g. the validator's stale-
|
|
277
|
-
* index check reads a missing node as the oldest possible mtime so it never
|
|
278
|
-
* spuriously flags a parent against an absent child). Mirrors v2's
|
|
279
|
-
* `getPageMtimeMs`.
|
|
280
|
-
*/
|
|
281
|
-
export async function getNodeMtimeMs(
|
|
282
|
-
workspaceDir: string,
|
|
283
|
-
id: string,
|
|
284
|
-
): Promise<number> {
|
|
285
|
-
validateNodeId(id);
|
|
286
|
-
try {
|
|
287
|
-
const s = await stat(getNodePath(workspaceDir, id));
|
|
288
|
-
return s.mtimeMs;
|
|
289
|
-
} catch {
|
|
290
|
-
return 0;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Write a tree node atomically (temp file + rename). A crash between the temp
|
|
296
|
-
* write and the rename leaves the prior file intact; a crash after the rename
|
|
297
|
-
* leaves the new file. Readers therefore never observe a partial node.
|
|
298
|
-
*
|
|
299
|
-
* Parent directories are created on demand (`mkdir -p`) so nested-folder ids
|
|
300
|
-
* like `people/colleagues` work without callers pre-creating the folder.
|
|
301
|
-
*/
|
|
302
|
-
export async function writeNode(
|
|
303
|
-
workspaceDir: string,
|
|
304
|
-
node: TreeNode,
|
|
305
|
-
): Promise<void> {
|
|
306
|
-
validateNodeId(node.id);
|
|
307
|
-
const path = getNodePath(workspaceDir, node.id);
|
|
308
|
-
const tmpPath = `${path}.tmp.${process.pid}.${randomUUID()}`;
|
|
309
|
-
const content = renderNodeContent(node);
|
|
310
|
-
try {
|
|
311
|
-
await mkdir(dirname(path), { recursive: true });
|
|
312
|
-
await writeFile(tmpPath, content, "utf-8");
|
|
313
|
-
await rename(tmpPath, path);
|
|
314
|
-
} catch (err) {
|
|
315
|
-
// Best-effort cleanup: if the rename failed (or the write succeeded but the
|
|
316
|
-
// rename did not), remove the orphan tmp file so we don't leak it into the
|
|
317
|
-
// tree/ directory where listNodes would then surface it.
|
|
318
|
-
await rm(tmpPath, { force: true }).catch(() => {});
|
|
319
|
-
throw err;
|
|
320
|
-
}
|
|
321
|
-
invalidateTreeIndex(workspaceDir);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* List every tree-node id present on disk, walking subdirectories.
|
|
326
|
-
*
|
|
327
|
-
* Ids are returned in path-relative form with forward slashes as separators
|
|
328
|
-
* (e.g. `people/colleagues`) so callers can pass them straight back to
|
|
329
|
-
* `readNode`.
|
|
330
|
-
*
|
|
331
|
-
* Hidden directories (segment starts with `.`), non-`.md` files, and atomic-
|
|
332
|
-
* write temp files (`.tmp.<pid>.<uuid>`) are skipped. If the tree/ directory
|
|
333
|
-
* does not yet exist (fresh workspace pre-migration), returns `[]`.
|
|
334
|
-
*/
|
|
335
|
-
export async function listNodes(workspaceDir: string): Promise<string[]> {
|
|
336
|
-
const root = getTreeDir(workspaceDir);
|
|
337
|
-
const ids: string[] = [];
|
|
338
|
-
const queue: string[] = [root];
|
|
339
|
-
|
|
340
|
-
while (queue.length > 0) {
|
|
341
|
-
const dir = queue.shift()!;
|
|
342
|
-
let entries;
|
|
343
|
-
try {
|
|
344
|
-
entries = await readdir(dir, { withFileTypes: true });
|
|
345
|
-
} catch (err) {
|
|
346
|
-
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
347
|
-
// Root missing → return []. Nested missing dir is impossible mid-walk
|
|
348
|
-
// (we only enqueue what readdir surfaced) but treat the same defensively.
|
|
349
|
-
if (dir === root) return [];
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
throw err;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
for (const entry of entries) {
|
|
356
|
-
if (entry.name.startsWith(".")) continue;
|
|
357
|
-
const fullPath = join(dir, entry.name);
|
|
358
|
-
if (entry.isDirectory()) {
|
|
359
|
-
queue.push(fullPath);
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
if (!entry.isFile()) continue;
|
|
363
|
-
if (!entry.name.endsWith(NODE_EXTENSION)) continue;
|
|
364
|
-
// Skip orphaned temp files left behind by a crashed atomic write.
|
|
365
|
-
if (entry.name.includes(".tmp.")) continue;
|
|
366
|
-
ids.push(idFromNodePath(root, fullPath));
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
ids.sort();
|
|
371
|
-
return ids;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* Delete a tree node. Idempotent — missing files are not an error.
|
|
376
|
-
*
|
|
377
|
-
* Any other failure (permission denied, etc.) throws so the caller can react.
|
|
378
|
-
*/
|
|
379
|
-
export async function deleteNode(
|
|
380
|
-
workspaceDir: string,
|
|
381
|
-
id: string,
|
|
382
|
-
): Promise<void> {
|
|
383
|
-
validateNodeId(id);
|
|
384
|
-
const path = getNodePath(workspaceDir, id);
|
|
385
|
-
try {
|
|
386
|
-
await rm(path);
|
|
387
|
-
} catch (err) {
|
|
388
|
-
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
throw err;
|
|
392
|
-
}
|
|
393
|
-
invalidateTreeIndex(workspaceDir);
|
|
394
|
-
}
|