@vellumai/assistant 0.8.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +2 -2
- package/docker-entrypoint.sh +0 -1
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/knip.json +2 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +1492 -100
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +302 -33
- package/src/__tests__/approval-cascade.test.ts +1 -1
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
- package/src/__tests__/audit-log-rotation.test.ts +70 -16
- package/src/__tests__/background-workers-disk-pressure.test.ts +4 -3
- package/src/__tests__/btw-routes.test.ts +2 -3
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/channel-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-guardian.test.ts +3 -3
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/checker.test.ts +6 -15
- package/src/__tests__/compaction-events.test.ts +2 -1
- package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
- package/src/__tests__/computer-use-tools.test.ts +2 -4
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-token-estimator.test.ts +91 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
- package/src/__tests__/conversation-agent-loop.test.ts +188 -129
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-fork-crud.test.ts +324 -0
- package/src/__tests__/conversation-lifecycle.test.ts +53 -12
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-skill-tools.test.ts +2 -5
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-sync-tags.test.ts +99 -32
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
- package/src/__tests__/credential-execution-tools.test.ts +6 -6
- package/src/__tests__/credential-security-invariants.test.ts +7 -0
- package/src/__tests__/credential-vault-unit.test.ts +2 -2
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/first-greeting.test.ts +23 -2
- package/src/__tests__/gateway-flag-listener.test.ts +237 -0
- package/src/__tests__/gemini-provider.test.ts +78 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -5
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +4 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/injector-chain.test.ts +2 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
- package/src/__tests__/llm-resolver.test.ts +161 -9
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/logger.test.ts +89 -0
- package/src/__tests__/mcp-abort-signal.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +31 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/model-intents.test.ts +2 -4
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/onboarding-template-contract.test.ts +1 -1
- package/src/__tests__/openai-provider.test.ts +151 -0
- package/src/__tests__/openai-responses-provider.test.ts +118 -16
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -5
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +2 -2
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
- package/src/__tests__/plugin-types.test.ts +3 -2
- package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
- package/src/__tests__/pricing.test.ts +12 -0
- package/src/__tests__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
- package/src/__tests__/registry.test.ts +2 -8
- package/src/__tests__/require-fresh-approval.test.ts +2 -2
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
- package/src/__tests__/server-history-render.test.ts +83 -4
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
- package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
- package/src/__tests__/skill-tool-factory.test.ts +1 -1
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/sync-message-contract.test.ts +59 -0
- package/src/__tests__/system-prompt.test.ts +161 -124
- package/src/__tests__/terminal-tools.test.ts +12 -2
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- package/src/__tests__/tool-approval-handler.test.ts +1 -5
- package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
- package/src/__tests__/tool-executor.test.ts +89 -53
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
- package/src/__tests__/usage-routes.test.ts +3 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +94 -10
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
- package/src/acp/prepare-agent-env.ts +78 -0
- package/src/acp/session-manager.ts +1 -1
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +65 -20
- package/src/api/README.md +5 -0
- package/src/api/index.ts +4 -0
- package/src/api/package.json +10 -0
- package/src/background-wake/background-wake-routes.test.ts +233 -0
- package/src/background-wake/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/browser/operations.ts +15 -0
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
- package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
- package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +10 -12
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference-providers.ts +147 -1
- package/src/cli/commands/inference.ts +93 -40
- package/src/cli/commands/memory-v2-compare-render.ts +115 -0
- package/src/cli/commands/memory-v2.ts +483 -0
- package/src/cli/commands/memory-v3-render.ts +344 -0
- package/src/cli/commands/memory-v3.ts +316 -0
- package/src/cli/commands/notifications.ts +24 -2
- package/src/cli/program.ts +2 -0
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/assistant-feature-flags.ts +21 -9
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
- package/src/config/bundled-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +24 -12
- package/src/config/call-site-defaults.ts +20 -0
- package/src/config/feature-flag-registry.json +115 -3
- package/src/config/llm-resolver.ts +16 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
- package/src/config/schemas/call-site-catalog.ts +35 -0
- package/src/config/schemas/llm.ts +14 -0
- package/src/config/schemas/memory-v2.ts +294 -1
- package/src/config/schemas/memory.ts +2 -1
- package/src/context/compactor.ts +60 -1
- package/src/context/token-estimator.ts +47 -4
- package/src/context/window-manager.ts +25 -0
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
- package/src/daemon/conversation-agent-loop.ts +307 -88
- package/src/daemon/conversation-error.ts +31 -1
- package/src/daemon/conversation-lifecycle.ts +149 -118
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +145 -84
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +70 -3
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +54 -32
- package/src/daemon/disk-pressure-guard.ts +14 -2
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/config-a2a.ts +160 -0
- package/src/daemon/handlers/config-model.test.ts +2 -0
- package/src/daemon/handlers/conversations.ts +90 -3
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +5 -5
- package/src/daemon/host-file-proxy.ts +5 -5
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +11 -11
- package/src/daemon/lifecycle.ts +40 -23
- package/src/daemon/meet-manifest-loader.ts +1 -7
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +14 -9
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/home.ts +1 -13
- package/src/daemon/message-types/messages.ts +66 -7
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +69 -12
- package/src/daemon/shutdown-handlers.ts +24 -5
- package/src/daemon/switch-inference-profile-tool.ts +52 -0
- package/src/daemon/tool-setup-types.ts +13 -0
- package/src/daemon/trust-context.ts +6 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/events/relationship-state-updated.ts +25 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +6 -1
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +85 -0
- package/src/home/suggested-prompts.ts +168 -9
- package/src/ipc/gateway-flag-listener.ts +123 -0
- package/src/ipc/skill-routes/registries.ts +8 -12
- package/src/memory/__tests__/db-async-query.test.ts +165 -0
- package/src/memory/__tests__/db-maintenance.test.ts +115 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-crud.ts +191 -100
- package/src/memory/conversation-starters-cadence.ts +3 -1
- package/src/memory/conversation-title-service.ts +19 -3
- package/src/memory/db-async-query.ts +214 -0
- package/src/memory/db-init.ts +26 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- package/src/memory/graph/bootstrap.ts +8 -1
- package/src/memory/graph/capability-seed.ts +7 -3
- package/src/memory/graph/conversation-graph-memory.ts +100 -17
- package/src/memory/graph/extraction.ts +1 -5
- package/src/memory/graph/graph-search.ts +7 -1
- package/src/memory/indexer.ts +28 -18
- package/src/memory/job-handlers/cleanup.ts +76 -18
- package/src/memory/job-handlers/conversation-starters.ts +1 -4
- package/src/memory/jobs/embed-pkb-file.ts +6 -1
- package/src/memory/jobs-store.ts +14 -0
- package/src/memory/jobs-worker.ts +68 -15
- package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
- package/src/memory/llm-request-log-source-local.ts +7 -0
- package/src/memory/llm-request-log-source.ts +9 -2
- package/src/memory/llm-request-log-store.ts +43 -1
- package/src/memory/llm-usage-store.ts +24 -0
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +11 -3
- package/src/memory/memory-retrospective-job.ts +413 -18
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +41 -14
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
- package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
- package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
- package/src/memory/migrations/index.ts +34 -0
- package/src/memory/migrations/registry.ts +58 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/infrastructure.ts +22 -0
- package/src/memory/tool-usage-store.ts +36 -8
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
- package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
- package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +158 -112
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +660 -4
- package/src/memory/v2/consolidation-job.ts +14 -0
- package/src/memory/v2/harness/compare.ts +57 -0
- package/src/memory/v2/harness/metrics.ts +124 -0
- package/src/memory/v2/harness/oracle.ts +145 -0
- package/src/memory/v2/harness/replay-input.ts +224 -0
- package/src/memory/v2/harness/retriever.ts +74 -0
- package/src/memory/v2/harness/router-retriever.ts +43 -0
- package/src/memory/v2/harness/runner.ts +106 -0
- package/src/memory/v2/harness/trace.ts +58 -0
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +42 -25
- package/src/memory/v2/page-index.ts +209 -7
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +369 -62
- package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
- package/src/memory/v3/__tests__/edges.test.ts +563 -0
- package/src/memory/v3/__tests__/filter.test.ts +512 -0
- package/src/memory/v3/__tests__/gate.test.ts +574 -0
- package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
- package/src/memory/v3/__tests__/loop.test.ts +530 -0
- package/src/memory/v3/__tests__/retriever.test.ts +226 -0
- package/src/memory/v3/__tests__/scouts.test.ts +440 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
- package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
- package/src/memory/v3/__tests__/traversal.test.ts +469 -0
- package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
- package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
- package/src/memory/v3/__tests__/validate.test.ts +245 -0
- package/src/memory/v3/auto-edges.ts +223 -0
- package/src/memory/v3/coactivation-store.ts +124 -0
- package/src/memory/v3/consolidation-job.ts +323 -0
- package/src/memory/v3/edge-learning-job.ts +160 -0
- package/src/memory/v3/edges.ts +249 -0
- package/src/memory/v3/filter.ts +281 -0
- package/src/memory/v3/gate.ts +334 -0
- package/src/memory/v3/index-composition.ts +113 -0
- package/src/memory/v3/llm-capture.ts +46 -0
- package/src/memory/v3/loop.ts +382 -0
- package/src/memory/v3/maintenance.ts +144 -0
- package/src/memory/v3/prompt-context.ts +33 -0
- package/src/memory/v3/prompts/consolidation.ts +458 -0
- package/src/memory/v3/prompts/system-prompts.ts +196 -0
- package/src/memory/v3/retriever.ts +33 -0
- package/src/memory/v3/scouts.ts +420 -0
- package/src/memory/v3/shadow-middleware.ts +305 -0
- package/src/memory/v3/traversal.ts +206 -0
- package/src/memory/v3/tree-index.ts +237 -0
- package/src/memory/v3/tree-store.ts +394 -0
- package/src/memory/v3/tree-walk.ts +351 -0
- package/src/memory/v3/types.ts +65 -0
- package/src/memory/v3/validate.ts +300 -0
- package/src/messaging/providers/index.ts +7 -1
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/emit-signal.ts +38 -50
- package/src/notifications/home-feed-side-effect.ts +60 -30
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +8 -5
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +6 -3
- package/src/plugin-api/index.ts +4 -0
- package/src/plugin-api/types.ts +7 -33
- package/src/plugins/defaults/index.ts +6 -0
- package/src/plugins/defaults/injectors.ts +100 -20
- package/src/plugins/external-plugin-loader.ts +5 -68
- package/src/plugins/types.ts +11 -16
- package/src/proactive-artifact/aux-message-injector.ts +17 -4
- package/src/prompts/__tests__/system-prompt.test.ts +46 -2
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +69 -19
- package/src/prompts/system-prompt.ts +118 -216
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +10 -2
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +281 -9
- package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
- package/src/providers/__tests__/retry-callsite.test.ts +85 -5
- package/src/providers/anthropic/client.ts +159 -66
- package/src/providers/call-site-routing.ts +14 -2
- package/src/providers/connection-model-compat.ts +38 -0
- package/src/providers/connection-resolution.ts +16 -2
- package/src/providers/fireworks/client.ts +20 -2
- package/src/providers/gemini/client.ts +49 -6
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/adapter-factory.ts +18 -1
- package/src/providers/inference/auth.ts +3 -3
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/resolve-auth.ts +49 -6
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +91 -1
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openai/chat-completions-provider.ts +63 -23
- package/src/providers/openai/codex-models.ts +18 -0
- package/src/providers/openai/responses-provider.ts +86 -23
- package/src/providers/openrouter/client.ts +5 -1
- package/src/providers/provider-send-message.ts +7 -1
- package/src/providers/retry.ts +34 -3
- package/src/providers/thinking-config.ts +26 -1
- package/src/providers/types.ts +25 -0
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +152 -56
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +43 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-types.ts +7 -6
- package/src/runtime/migrations/vbundle-builder.ts +10 -3
- package/src/runtime/pending-interactions.ts +50 -8
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/approval-routes.ts +4 -1
- package/src/runtime/routes/avatar-routes.ts +10 -10
- package/src/runtime/routes/background-wake-routes.ts +188 -0
- package/src/runtime/routes/browser-tabs-routes.ts +200 -0
- package/src/runtime/routes/btw-routes.ts +0 -6
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +147 -2
- package/src/runtime/routes/conversation-list-routes.ts +12 -4
- package/src/runtime/routes/conversation-management-routes.ts +77 -20
- package/src/runtime/routes/conversation-query-routes.ts +196 -31
- package/src/runtime/routes/conversation-routes.ts +472 -425
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- package/src/runtime/routes/domain-routes.ts +60 -10
- package/src/runtime/routes/email-routes.ts +5 -2
- package/src/runtime/routes/events-routes.ts +54 -10
- package/src/runtime/routes/group-routes.ts +24 -8
- package/src/runtime/routes/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +17 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +20 -4
- package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
- package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
- package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
- package/src/runtime/routes/integrations/a2a.ts +60 -1
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +427 -0
- package/src/runtime/routes/memory-v3-routes.ts +316 -0
- package/src/runtime/routes/migration-routes.ts +21 -24
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/sanity-routes.ts +159 -0
- package/src/runtime/routes/secret-routes.ts +25 -5
- package/src/runtime/routes/settings-routes.ts +12 -11
- package/src/runtime/routes/slack-channel-routes.ts +188 -0
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/services/conversation-serializer.ts +30 -4
- package/src/runtime/sync/resource-sync-events.ts +106 -38
- package/src/runtime/sync/sync-publisher.test.ts +49 -0
- package/src/runtime/sync/sync-publisher.ts +2 -1
- package/src/runtime/verification-outbound-actions.ts +73 -1
- package/src/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- package/src/telemetry/types.ts +12 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/acp/spawn.test.ts +119 -0
- package/src/tools/acp/spawn.ts +15 -2
- package/src/tools/apps/definitions.ts +2 -8
- package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
- package/src/tools/ask-question/ask-question-tool.ts +38 -45
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +150 -0
- package/src/tools/browser/browser-execution.ts +106 -0
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
- package/src/tools/browser/cdp-client/factory.ts +171 -4
- package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
- package/src/tools/browser/cdp-client/types.ts +101 -0
- package/src/tools/browser/pinned-tabs.ts +146 -0
- package/src/tools/computer-use/definitions.ts +22 -78
- package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
- package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
- package/src/tools/credentials/vault.ts +3 -9
- package/src/tools/document/document-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +187 -2
- package/src/tools/execution-target.ts +21 -23
- package/src/tools/executor.ts +6 -1
- package/src/tools/filesystem/edit.ts +3 -9
- package/src/tools/filesystem/list.ts +3 -9
- package/src/tools/filesystem/read.ts +3 -9
- package/src/tools/filesystem/write.ts +3 -9
- package/src/tools/host-filesystem/edit.ts +3 -9
- package/src/tools/host-filesystem/read.ts +3 -9
- package/src/tools/host-filesystem/transfer.ts +3 -9
- package/src/tools/host-filesystem/write.ts +3 -9
- package/src/tools/host-terminal/host-shell.ts +3 -9
- package/src/tools/mcp/mcp-tool-factory.ts +1 -8
- package/src/tools/memory/register.test.ts +1 -1
- package/src/tools/memory/register.ts +4 -9
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +216 -73
- package/src/tools/network/web-search.ts +216 -98
- package/src/tools/registry.ts +7 -23
- package/src/tools/schema-transforms.ts +1 -1
- package/src/tools/skills/execute.ts +3 -9
- package/src/tools/skills/load.ts +3 -9
- package/src/tools/skills/skill-tool-factory.ts +1 -8
- package/src/tools/subagent/notify-parent.ts +3 -9
- package/src/tools/system/request-permission.ts +3 -9
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/types.ts +31 -98
- package/src/tools/ui-surface/definitions.ts +9 -23
- package/src/types/onboarding-context.ts +4 -0
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -7
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
- package/src/__tests__/message-complete-display-id.test.ts +0 -175
- package/src/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/prompts/cache-boundary.ts +0 -8
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
package/src/prompts/sections.ts
CHANGED
|
@@ -93,7 +93,10 @@ function collectSectionIds(workspaceDir: string): string[] {
|
|
|
93
93
|
if (name.endsWith(".md")) ids.add(name.slice(0, -".md".length));
|
|
94
94
|
}
|
|
95
95
|
} catch (err) {
|
|
96
|
-
log.warn(
|
|
96
|
+
log.warn(
|
|
97
|
+
{ err, workspaceDir },
|
|
98
|
+
"Failed to list workspace system prompt dir",
|
|
99
|
+
);
|
|
97
100
|
}
|
|
98
101
|
}
|
|
99
102
|
return [...ids].sort();
|
|
@@ -102,10 +105,12 @@ function collectSectionIds(workspaceDir: string): string[] {
|
|
|
102
105
|
interface ResolvedSection {
|
|
103
106
|
enabled: string | boolean | undefined;
|
|
104
107
|
body: string;
|
|
108
|
+
transform?: BundledSection["transform"];
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
function resolveSection(
|
|
108
112
|
id: string,
|
|
113
|
+
ctx: SectionRenderContext,
|
|
109
114
|
workspaceDir: string,
|
|
110
115
|
): ResolvedSection | null {
|
|
111
116
|
const workspacePath = join(workspaceDir, `${id}.md`);
|
|
@@ -114,12 +119,20 @@ function resolveSection(
|
|
|
114
119
|
try {
|
|
115
120
|
raw = readFileSync(workspacePath, "utf-8");
|
|
116
121
|
} catch (err) {
|
|
117
|
-
log.warn(
|
|
122
|
+
log.warn(
|
|
123
|
+
{ err, workspacePath },
|
|
124
|
+
"Failed to read workspace section override",
|
|
125
|
+
);
|
|
118
126
|
return null;
|
|
119
127
|
}
|
|
120
128
|
const parsed = parseFrontmatterFields(raw);
|
|
121
129
|
const fields = parsed?.fields ?? {};
|
|
122
130
|
const body = parsed?.body ?? raw;
|
|
131
|
+
// Workspace override skips the bundled transform: when the user has
|
|
132
|
+
// written their own `prompts/system/<id>.md` they've taken full
|
|
133
|
+
// control of the body shape, and re-running the bundled transform
|
|
134
|
+
// (e.g. unmodified-template detection on IDENTITY.md) would
|
|
135
|
+
// misclassify their override.
|
|
123
136
|
return { enabled: fields["enabled"] as string | boolean | undefined, body };
|
|
124
137
|
}
|
|
125
138
|
const bundled = BUNDLED_SYSTEM_SECTIONS.find((s) => s.id === id);
|
|
@@ -127,25 +140,58 @@ function resolveSection(
|
|
|
127
140
|
|
|
128
141
|
// A bundled section may delegate its body to a workspace file outside
|
|
129
142
|
// the section override directory (e.g. `SOUL.md` at the workspace
|
|
130
|
-
// root).
|
|
131
|
-
//
|
|
143
|
+
// root). `workspacePath` may be a single path or an array of paths
|
|
144
|
+
// tried in order — the first one whose file exists and has non-empty
|
|
145
|
+
// content wins. Each entry may reference `{{ctx-key}}` variables
|
|
146
|
+
// (e.g. `users/{{userSlug}}.md`) that are interpolated against the
|
|
147
|
+
// render context before resolution. Missing/empty files yield "",
|
|
148
|
+
// which `renderSection` then gates off via its empty-body check (or
|
|
149
|
+
// via the section's `transform`, if set).
|
|
132
150
|
if (bundled.workspacePath) {
|
|
133
|
-
const
|
|
151
|
+
const paths = Array.isArray(bundled.workspacePath)
|
|
152
|
+
? bundled.workspacePath
|
|
153
|
+
: [bundled.workspacePath];
|
|
134
154
|
let body = "";
|
|
135
|
-
|
|
155
|
+
for (const pathTemplate of paths) {
|
|
156
|
+
const interpolated = interpolateWorkspacePath(pathTemplate, ctx);
|
|
157
|
+
const filePath = getWorkspacePromptPath(interpolated);
|
|
158
|
+
if (!existsSync(filePath)) continue;
|
|
136
159
|
try {
|
|
137
|
-
|
|
160
|
+
const content = readFileSync(filePath, "utf-8");
|
|
161
|
+
if (content.trim().length > 0) {
|
|
162
|
+
body = content;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
138
165
|
} catch (err) {
|
|
139
|
-
log.warn(
|
|
140
|
-
{ err, filePath, id },
|
|
141
|
-
"Failed to read section workspacePath",
|
|
142
|
-
);
|
|
166
|
+
log.warn({ err, filePath, id }, "Failed to read section workspacePath");
|
|
143
167
|
}
|
|
144
168
|
}
|
|
145
|
-
return { enabled: bundled.enabled, body };
|
|
169
|
+
return { enabled: bundled.enabled, body, transform: bundled.transform };
|
|
146
170
|
}
|
|
147
171
|
|
|
148
|
-
return {
|
|
172
|
+
return {
|
|
173
|
+
enabled: bundled.enabled,
|
|
174
|
+
body: bundled.body,
|
|
175
|
+
transform: bundled.transform,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Interpolate `{{key}}` references in a workspace-path template against
|
|
181
|
+
* `ctx`. Section / inverted-section tags are not supported in paths —
|
|
182
|
+
* only flat variable substitution. Unresolved keys stay literal so a
|
|
183
|
+
* typo surfaces as a missing file rather than silently rendering an
|
|
184
|
+
* unrelated section.
|
|
185
|
+
*/
|
|
186
|
+
function interpolateWorkspacePath(
|
|
187
|
+
template: string,
|
|
188
|
+
ctx: SectionRenderContext,
|
|
189
|
+
): string {
|
|
190
|
+
return template.replace(VARIABLE, (match, key: string) => {
|
|
191
|
+
const value = ctx[key];
|
|
192
|
+
if (value === undefined || value === null) return match;
|
|
193
|
+
return String(value);
|
|
194
|
+
});
|
|
149
195
|
}
|
|
150
196
|
|
|
151
197
|
function renderSection(
|
|
@@ -153,12 +199,19 @@ function renderSection(
|
|
|
153
199
|
ctx: SectionRenderContext,
|
|
154
200
|
workspaceDir: string,
|
|
155
201
|
): string | null {
|
|
156
|
-
const section = resolveSection(id, workspaceDir);
|
|
202
|
+
const section = resolveSection(id, ctx, workspaceDir);
|
|
157
203
|
if (section === null) return null;
|
|
158
204
|
|
|
159
205
|
if (!isEnabled(section.enabled, ctx)) return null;
|
|
160
206
|
|
|
161
|
-
|
|
207
|
+
let body = section.body;
|
|
208
|
+
if (section.transform) {
|
|
209
|
+
const transformed = section.transform(body, ctx);
|
|
210
|
+
if (transformed === null) return null;
|
|
211
|
+
body = transformed;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const stripped = stripCommentLines(body).trim();
|
|
162
215
|
if (stripped.length === 0) return null;
|
|
163
216
|
return interpolateVariables(stripped, ctx);
|
|
164
217
|
}
|
|
@@ -190,10 +243,7 @@ const IDENT_REGEX = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
|
190
243
|
* typo on a `{{key}}` substitution surfaces at the warn log rather than
|
|
191
244
|
* inlining the string `"undefined"`).
|
|
192
245
|
*/
|
|
193
|
-
function interpolateVariables(
|
|
194
|
-
body: string,
|
|
195
|
-
ctx: SectionRenderContext,
|
|
196
|
-
): string {
|
|
246
|
+
function interpolateVariables(body: string, ctx: SectionRenderContext): string {
|
|
197
247
|
// Collapse standalone tag lines so multiline section templates render
|
|
198
248
|
// without phantom blank lines from the layout markers.
|
|
199
249
|
const collapsed = body.replace(STANDALONE_TAG_LINE, "$1");
|
|
@@ -4,12 +4,13 @@ import {
|
|
|
4
4
|
mkdirSync,
|
|
5
5
|
readdirSync,
|
|
6
6
|
readFileSync,
|
|
7
|
+
writeFileSync,
|
|
7
8
|
} from "node:fs";
|
|
8
9
|
import { join } from "node:path";
|
|
9
10
|
|
|
10
11
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
12
|
+
import type { ChannelCapabilities } from "../daemon/conversation-runtime-assembly.js";
|
|
13
|
+
import type { TrustContext } from "../daemon/trust-context.js";
|
|
13
14
|
import type { OnboardingContext } from "../types/onboarding-context.js";
|
|
14
15
|
import { resolveBundledDir } from "../util/bundled-asset.js";
|
|
15
16
|
import { getLogger } from "../util/logger.js";
|
|
@@ -20,25 +21,28 @@ import {
|
|
|
20
21
|
} from "../util/platform.js";
|
|
21
22
|
import { stripCommentLines } from "../util/strip-comment-lines.js";
|
|
22
23
|
import { cleanupBootstrapFiles } from "./bootstrap-cleanup.js";
|
|
23
|
-
import {
|
|
24
|
-
|
|
24
|
+
import {
|
|
25
|
+
resolveGuardianPersona,
|
|
26
|
+
resolveUserSlug,
|
|
27
|
+
} from "./persona-resolver.js";
|
|
25
28
|
import { renderWorkspaceSections } from "./sections.js";
|
|
29
|
+
import { isTemplateContent } from "./template-detection.js";
|
|
26
30
|
|
|
27
|
-
export {
|
|
31
|
+
export { isTemplateContent };
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Maps onboarding cohort identifiers to their cohort-specific bootstrap
|
|
35
|
+
* template filenames. When a cohort key is present in OnboardingContext,
|
|
36
|
+
* `maybeReseedBootstrapForCohort` swaps the generic BOOTSTRAP.md with the
|
|
37
|
+
* cohort-specific variant — but only if the workspace file is still pristine.
|
|
38
|
+
*/
|
|
39
|
+
const COHORT_BOOTSTRAP_TEMPLATES: Record<string, string> = {
|
|
40
|
+
"content-automation": "BOOTSTRAP-CONTENT-AUTOMATION.md",
|
|
37
41
|
};
|
|
38
42
|
|
|
39
43
|
const log = getLogger("system-prompt");
|
|
40
44
|
|
|
41
|
-
const PROMPT_FILES = ["
|
|
45
|
+
const PROMPT_FILES = ["IDENTITY.md", "SOUL.md"] as const;
|
|
42
46
|
|
|
43
47
|
function hasPopulatedUsersDir(): boolean {
|
|
44
48
|
try {
|
|
@@ -210,224 +214,118 @@ export function ensurePromptFiles(): void {
|
|
|
210
214
|
}
|
|
211
215
|
|
|
212
216
|
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
* 2. Append the resolved user persona from users/<slug>.md (via options.userPersona)
|
|
218
|
-
* 3. If BOOTSTRAP.md exists, append first-run ritual instructions
|
|
217
|
+
* One-shot swap: if the workspace BOOTSTRAP.md is still the unmodified generic
|
|
218
|
+
* template AND a cohort-specific template exists, overwrite the workspace file
|
|
219
|
+
* with the cohort variant. No-op when BOOTSTRAP.md has been deleted, modified,
|
|
220
|
+
* or the cohort has no mapped template.
|
|
219
221
|
*/
|
|
222
|
+
export function maybeReseedBootstrapForCohort(cohort: string): void {
|
|
223
|
+
const templateFileName = COHORT_BOOTSTRAP_TEMPLATES[cohort];
|
|
224
|
+
if (!templateFileName) return;
|
|
225
|
+
|
|
226
|
+
const bootstrapPath = getWorkspacePromptPath("BOOTSTRAP.md");
|
|
227
|
+
if (!existsSync(bootstrapPath)) return;
|
|
228
|
+
|
|
229
|
+
const currentContent = readPromptFile(bootstrapPath);
|
|
230
|
+
// Compare against the GENERIC "BOOTSTRAP.md" template, not the cohort-
|
|
231
|
+
// specific one. After the swap, the workspace content no longer matches
|
|
232
|
+
// the generic template, so this guard returns false on subsequent calls —
|
|
233
|
+
// making the swap idempotent. Do NOT change the comparison target to the
|
|
234
|
+
// cohort template filename; that would re-swap on every prompt build.
|
|
235
|
+
if (!isTemplateContent(currentContent, "BOOTSTRAP.md")) return;
|
|
236
|
+
|
|
237
|
+
const templatesDir = resolveBundledDir(
|
|
238
|
+
import.meta.dirname ?? __dirname,
|
|
239
|
+
"templates",
|
|
240
|
+
"templates",
|
|
241
|
+
);
|
|
242
|
+
const cohortTemplatePath = join(templatesDir, templateFileName);
|
|
243
|
+
if (!existsSync(cohortTemplatePath)) {
|
|
244
|
+
log.warn(
|
|
245
|
+
{ cohort, templateFileName },
|
|
246
|
+
"Cohort bootstrap template not found, keeping generic BOOTSTRAP.md",
|
|
247
|
+
);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
const cohortContent = readFileSync(cohortTemplatePath, "utf-8");
|
|
253
|
+
writeFileSync(bootstrapPath, cohortContent, "utf-8");
|
|
254
|
+
log.info(
|
|
255
|
+
{ cohort, templateFileName },
|
|
256
|
+
"Replaced generic BOOTSTRAP.md with cohort-specific template",
|
|
257
|
+
);
|
|
258
|
+
} catch (err) {
|
|
259
|
+
log.warn(
|
|
260
|
+
{ err, cohort, templateFileName },
|
|
261
|
+
"Failed to reseed BOOTSTRAP.md for cohort",
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
220
266
|
export interface BuildSystemPromptOptions {
|
|
221
267
|
hasNoClient?: boolean;
|
|
222
268
|
excludeBootstrap?: boolean;
|
|
223
269
|
excludeCustomPrefix?: boolean;
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
userSlug?: string | null;
|
|
270
|
+
trustContext?: TrustContext;
|
|
271
|
+
channelCapabilities?: ChannelCapabilities;
|
|
227
272
|
onboardingContext?: OnboardingContext;
|
|
228
273
|
}
|
|
229
274
|
|
|
230
275
|
/**
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* files change between turns.
|
|
276
|
+
* Build the system prompt by rendering `BUNDLED_SYSTEM_SECTIONS` (with
|
|
277
|
+
* workspace overrides per section). Per-section behaviour lives in
|
|
278
|
+
* `system-sections.ts`; the renderer in `sections.ts` handles
|
|
279
|
+
* frontmatter `enabled:` predicates, `{{variable}}` interpolation,
|
|
280
|
+
* file-backed bodies, and runtime-computed transforms.
|
|
237
281
|
*/
|
|
238
282
|
export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
283
|
+
// One-shot cohort swap: if the user has a cohort and BOOTSTRAP.md is still
|
|
284
|
+
// the generic template, replace it with the cohort-specific variant before
|
|
285
|
+
// the prompt reads the file.
|
|
286
|
+
if (options?.onboardingContext?.cohort) {
|
|
287
|
+
maybeReseedBootstrapForCohort(options.onboardingContext.cohort);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Slugs used by the persona sections (`10-user-persona`,
|
|
291
|
+
// `11-channel-persona`) and the BOOTSTRAP block. `userSlug` is the
|
|
292
|
+
// raw slug derived from the caller's trust context (falling back to
|
|
293
|
+
// the guardian's contact, then to "default" when nothing resolves);
|
|
294
|
+
// `users/<slug>.md → users/default.md` fallback lives in the
|
|
295
|
+
// section's `workspacePath` array. `channelSlug` is the channel
|
|
296
|
+
// identifier from `channelCapabilities`, defaulting to "vellum".
|
|
297
|
+
const userSlug = resolveUserSlug(options?.trustContext) ?? "default";
|
|
298
|
+
const channelSlug = options?.channelCapabilities?.channel ?? "vellum";
|
|
299
|
+
|
|
239
300
|
// Section render context. Workspace section frontmatter `enabled:`
|
|
240
|
-
// predicates
|
|
241
|
-
//
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
//
|
|
301
|
+
// predicates, `{{key}}` / `{{#flag}}...{{/flag}}` body interpolation,
|
|
302
|
+
// and `{{key}}` paths inside `workspacePath` all resolve against this
|
|
303
|
+
// map, so anything the renderer needs to see (runtime gates, slugs,
|
|
304
|
+
// paths) must be lifted onto `ctx` rather than branched on at the
|
|
305
|
+
// call site. Mustache section tags `{{#flag}}` / `{{^flag}}` coerce
|
|
306
|
+
// `ctx[flag]` to boolean via `Boolean(...)`, so options that are
|
|
307
|
+
// undefined (caller didn't pass them) behave identically to false —
|
|
308
|
+
// no explicit normalization needed; `...options` is enough.
|
|
247
309
|
const ctx = {
|
|
248
310
|
...options,
|
|
249
311
|
isContainerized: getIsContainerized(),
|
|
250
312
|
workspaceDir: getWorkspaceDir(),
|
|
313
|
+
userSlug,
|
|
314
|
+
channelSlug,
|
|
251
315
|
};
|
|
252
316
|
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
//
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
// SOUL.md is rendered by the `09-soul` workspace-backed section
|
|
261
|
-
// (see templates/system-sections.ts) — no inline read needed here.
|
|
262
|
-
const identityPath = getWorkspacePromptPath("IDENTITY.md");
|
|
263
|
-
const bootstrapPath = getWorkspacePromptPath("BOOTSTRAP.md");
|
|
264
|
-
|
|
265
|
-
const identity = readPromptFile(identityPath);
|
|
266
|
-
const bootstrap = readPromptFile(bootstrapPath);
|
|
267
|
-
|
|
268
|
-
const includeBootstrap = !!bootstrap && !options?.excludeBootstrap;
|
|
269
|
-
|
|
270
|
-
// Template prompt files contain placeholder fields and meta-instructions
|
|
271
|
-
// meant for the assistant to fill in during onboarding. When included
|
|
272
|
-
// verbatim in the system prompt, the model can leak internal details and
|
|
273
|
-
// narrate its own setup process instead of following the BOOTSTRAP.md
|
|
274
|
-
// ritual. Detect unmodified templates by comparing against the bundled
|
|
275
|
-
// source and skip them — SOUL.md provides sufficient personality defaults
|
|
276
|
-
// until onboarding completes.
|
|
277
|
-
const identityIsTemplate = isTemplateContent(identity, "IDENTITY.md");
|
|
278
|
-
|
|
279
|
-
if (identity && (!identityIsTemplate || includeBootstrap)) {
|
|
280
|
-
if (identityIsTemplate) {
|
|
281
|
-
// During bootstrap the model needs to see the template structure
|
|
282
|
-
// so it can produce a valid file_write with the right fields.
|
|
283
|
-
systemParts.push(identity);
|
|
284
|
-
} else {
|
|
285
|
-
// Strip placeholder lines (e.g. "- **Name:** _(not yet chosen)_") so
|
|
286
|
-
// the model doesn't treat unresolved fields as prompts to ask the user.
|
|
287
|
-
const cleanedIdentity = identity
|
|
288
|
-
.split("\n")
|
|
289
|
-
.filter((line) => !/_\(not yet (?:chosen|established)\)_/.test(line))
|
|
290
|
-
.join("\n");
|
|
291
|
-
if (cleanedIdentity.trim()) {
|
|
292
|
-
systemParts.push(cleanedIdentity);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
if (options?.userPersona) systemParts.push(options.userPersona);
|
|
297
|
-
if (options?.channelPersona) systemParts.push(options.channelPersona);
|
|
298
|
-
if (includeBootstrap) {
|
|
299
|
-
const userSlug = options?.userSlug ?? "default";
|
|
300
|
-
const bootstrapWithSlug = bootstrap.replaceAll(
|
|
301
|
-
"{{USER_PERSONA_FILE}}",
|
|
302
|
-
`${userSlug}.md`,
|
|
303
|
-
);
|
|
304
|
-
let bootstrapContent = bootstrapWithSlug;
|
|
305
|
-
const voiceBlock = options?.onboardingContext?.tone
|
|
306
|
-
? BOOTSTRAP_VOICE_BLOCKS[options.onboardingContext.tone]
|
|
307
|
-
: undefined;
|
|
308
|
-
if (voiceBlock) {
|
|
309
|
-
bootstrapContent = voiceBlock + "\n\n" + bootstrapContent;
|
|
310
|
-
}
|
|
311
|
-
systemParts.push(
|
|
312
|
-
"# First-Run Ritual\n\n" +
|
|
313
|
-
"BOOTSTRAP.md is present — this is your first conversation. Follow its instructions.\n\n" +
|
|
314
|
-
bootstrapContent,
|
|
315
|
-
);
|
|
316
|
-
|
|
317
|
-
if (options?.onboardingContext) {
|
|
318
|
-
const n = normalizeOnboardingContext(options.onboardingContext);
|
|
319
|
-
const lines: string[] = [
|
|
320
|
-
"## First-Run User Context",
|
|
321
|
-
"",
|
|
322
|
-
"The user completed setup before this conversation.",
|
|
323
|
-
"",
|
|
324
|
-
"Known context:",
|
|
325
|
-
];
|
|
326
|
-
if (n.preferredName) lines.push(`- Name: ${n.preferredName}`);
|
|
327
|
-
if (n.commonWork.length)
|
|
328
|
-
lines.push(`- Common work: ${n.commonWork.join("; ")}`);
|
|
329
|
-
if (n.dailyTools.length)
|
|
330
|
-
lines.push(`- Daily tools: ${n.dailyTools.join(", ")}`);
|
|
331
|
-
if (n.assistantName)
|
|
332
|
-
lines.push(`- Chosen assistant name: ${n.assistantName}`);
|
|
333
|
-
if (n.tone) lines.push(`- Preferred initial voice: ${n.tone}`);
|
|
334
|
-
if (n.googleConnected && n.googleServices?.length) {
|
|
335
|
-
lines.push(
|
|
336
|
-
`- Google connected: yes (${n.googleServices.join(", ")} access granted)`,
|
|
337
|
-
);
|
|
338
|
-
}
|
|
339
|
-
lines.push(
|
|
340
|
-
"",
|
|
341
|
-
"Apply this context quietly. Do not recap it as a list unless the user asks.",
|
|
342
|
-
);
|
|
343
|
-
systemParts.push(lines.join("\n"));
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
// Configuration section removed — workspace files are self-describing,
|
|
347
|
-
// tool routing lives in tool descriptions.
|
|
348
|
-
// External Communications Identity removed — guidance lives in messaging
|
|
349
|
-
// and phone-calls skill SKILL.md files.
|
|
350
|
-
const integrationSection = buildIntegrationSection();
|
|
351
|
-
if (integrationSection) systemParts.push(integrationSection);
|
|
352
|
-
|
|
353
|
-
// Journal entries are extracted into graph nodes by the memory pipeline.
|
|
354
|
-
// Journal files remain writable on disk.
|
|
355
|
-
|
|
356
|
-
return (
|
|
357
|
-
systemParts.slice(0, dynamicStart).join("\n\n") +
|
|
358
|
-
SYSTEM_PROMPT_CACHE_BOUNDARY +
|
|
359
|
-
systemParts.slice(dynamicStart).join("\n\n")
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
function buildIntegrationSection(): string {
|
|
364
|
-
const entries: { provider: string; accountInfo?: string | null }[] = [];
|
|
365
|
-
|
|
366
|
-
// Local (BYO) connections from the SQLite store.
|
|
367
|
-
try {
|
|
368
|
-
const local = listConnections().filter((c) => c.status === "active");
|
|
369
|
-
entries.push(...local);
|
|
370
|
-
} catch {
|
|
371
|
-
// DB not available — skip local connections
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Platform-managed connections from the in-memory cache (populated at
|
|
375
|
-
// daemon startup and refreshed periodically).
|
|
376
|
-
const managed = getCachedManagedConnections();
|
|
377
|
-
for (const mc of managed) {
|
|
378
|
-
// Provider-level dedup is intentional: this section is a summary of
|
|
379
|
-
// connected services for the system prompt, not an exhaustive account
|
|
380
|
-
// list. Multiple accounts for the same provider (e.g. two Google
|
|
381
|
-
// accounts) collapse into a single line to keep the prompt compact.
|
|
382
|
-
if (!entries.some((e) => e.provider === mc.provider)) {
|
|
383
|
-
entries.push(mc);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (entries.length === 0) return "";
|
|
388
|
-
|
|
389
|
-
const lines = ["# Connected Services", ""];
|
|
390
|
-
for (const conn of entries) {
|
|
391
|
-
const state = conn.accountInfo
|
|
392
|
-
? `Connected (${conn.accountInfo})`
|
|
393
|
-
: "Connected";
|
|
394
|
-
lines.push(`- **${conn.provider}**: ${state}`);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
return lines.join("\n");
|
|
317
|
+
// Every system-prompt block flows through the bundled section
|
|
318
|
+
// pipeline — including runtime-computed entries like
|
|
319
|
+
// `14-connected-services` whose body is derived from live OAuth
|
|
320
|
+
// caches. The whole prompt is treated as a single cached block by
|
|
321
|
+
// the Anthropic provider; per-provider details live in each
|
|
322
|
+
// provider's client.
|
|
323
|
+
return renderWorkspaceSections(ctx).join("\n\n");
|
|
398
324
|
}
|
|
399
325
|
|
|
400
326
|
// Re-export from shared util so existing importers don't break.
|
|
401
327
|
export { stripCommentLines } from "../util/strip-comment-lines.js";
|
|
402
328
|
|
|
403
|
-
/**
|
|
404
|
-
* Returns true when the prompt file content is still the unmodified template
|
|
405
|
-
* shipped with the daemon. Compares the stripped workspace content against
|
|
406
|
-
* the stripped bundled template source so the check stays accurate even if
|
|
407
|
-
* templates are edited in future releases.
|
|
408
|
-
*/
|
|
409
|
-
export function isTemplateContent(
|
|
410
|
-
content: string | null,
|
|
411
|
-
templateFileName: string,
|
|
412
|
-
): boolean {
|
|
413
|
-
if (content == null) return false;
|
|
414
|
-
const templatesDir = resolveBundledDir(
|
|
415
|
-
import.meta.dirname ?? __dirname,
|
|
416
|
-
"templates",
|
|
417
|
-
"templates",
|
|
418
|
-
);
|
|
419
|
-
const templatePath = join(templatesDir, templateFileName);
|
|
420
|
-
if (!existsSync(templatePath)) return false;
|
|
421
|
-
try {
|
|
422
|
-
const templateContent = stripCommentLines(
|
|
423
|
-
readFileSync(templatePath, "utf-8"),
|
|
424
|
-
);
|
|
425
|
-
return content === templateContent;
|
|
426
|
-
} catch {
|
|
427
|
-
return false;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
329
|
export function readPromptFile(path: string): string | null {
|
|
432
330
|
if (!existsSync(path)) return null;
|
|
433
331
|
|
|
@@ -444,14 +342,17 @@ export function readPromptFile(path: string): string | null {
|
|
|
444
342
|
|
|
445
343
|
/**
|
|
446
344
|
* Reads the core identity/personality prompt files (SOUL.md, IDENTITY.md)
|
|
447
|
-
* and concatenates whichever exist
|
|
345
|
+
* and concatenates whichever exist, plus the guardian's user persona when
|
|
346
|
+
* one is resolvable. Returns null if none are present.
|
|
448
347
|
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
348
|
+
* Used by subsystems (memory extraction, conversation starters,
|
|
349
|
+
* notification decisions) that run outside the per-turn pipeline and want
|
|
350
|
+
* the assistant's "view of themselves and their guardian" without a trust
|
|
351
|
+
* context. The guardian persona fold is what callers used to do manually
|
|
352
|
+
* by passing `userPersona: resolveGuardianPersona()` — folding it in here
|
|
353
|
+
* removes the duplicated dance at every call site.
|
|
451
354
|
*/
|
|
452
|
-
export function buildCoreIdentityContext(
|
|
453
|
-
userPersona?: string | null;
|
|
454
|
-
}): string | null {
|
|
355
|
+
export function buildCoreIdentityContext(): string | null {
|
|
455
356
|
const parts: string[] = [];
|
|
456
357
|
for (const file of PROMPT_FILES) {
|
|
457
358
|
const content = readPromptFile(getWorkspacePromptPath(file));
|
|
@@ -462,6 +363,7 @@ export function buildCoreIdentityContext(opts?: {
|
|
|
462
363
|
if (file !== "SOUL.md" && isTemplateContent(content, file)) continue;
|
|
463
364
|
parts.push(content);
|
|
464
365
|
}
|
|
465
|
-
|
|
366
|
+
const guardianPersona = resolveGuardianPersona();
|
|
367
|
+
if (guardianPersona) parts.push(guardianPersona);
|
|
466
368
|
return parts.length > 0 ? parts.join("\n\n") : null;
|
|
467
369
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { resolveBundledDir } from "../util/bundled-asset.js";
|
|
5
|
+
import { stripCommentLines } from "../util/strip-comment-lines.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Returns true when the prompt file content is still the unmodified template
|
|
9
|
+
* shipped with the daemon. Compares the stripped workspace content against
|
|
10
|
+
* the stripped bundled template source so the check stays accurate even if
|
|
11
|
+
* templates are edited in future releases.
|
|
12
|
+
*
|
|
13
|
+
* Kept in a leaf module so the bundled section registry can depend on it
|
|
14
|
+
* without forming a cycle through `system-prompt.ts → sections.ts →
|
|
15
|
+
* templates/system-sections.ts`.
|
|
16
|
+
*/
|
|
17
|
+
export function isTemplateContent(
|
|
18
|
+
content: string | null,
|
|
19
|
+
templateFileName: string,
|
|
20
|
+
): boolean {
|
|
21
|
+
if (content == null) return false;
|
|
22
|
+
const templatesDir = resolveBundledDir(
|
|
23
|
+
import.meta.dirname ?? __dirname,
|
|
24
|
+
"templates",
|
|
25
|
+
"templates",
|
|
26
|
+
);
|
|
27
|
+
const templatePath = join(templatesDir, templateFileName);
|
|
28
|
+
if (!existsSync(templatePath)) return false;
|
|
29
|
+
try {
|
|
30
|
+
const templateContent = stripCommentLines(
|
|
31
|
+
readFileSync(templatePath, "utf-8"),
|
|
32
|
+
);
|
|
33
|
+
return content === templateContent;
|
|
34
|
+
} catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|