@cortexkit/opencode-magic-context 0.46.1 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/magic-context-prompt.d.ts +1 -1
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/{announcement-y35wzg2r.js → announcement-fp14dw0n.js} +3 -2
- package/dist/auto-search-worker.js +112 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/live-run-config.d.ts.map +1 -1
- package/dist/config/migrate-config-location.d.ts.map +1 -1
- package/dist/config/mural-model-deprecation.d.ts +15 -0
- package/dist/config/mural-model-deprecation.d.ts.map +1 -0
- package/dist/config/project-security.d.ts +0 -3
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +21 -9
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-7fj2b9jw.js → conflict-warning-hook-w8cykrnf.js} +12 -9
- package/dist/{context-sh2m2vde.js → context-m0cy262m.js} +1785 -913
- package/dist/{derive-budgets-7nj7r1rv.js → derive-budgets-sg0xsq7s.js} +4 -3
- package/dist/embedding-activity-g1dhes6g.js +10 -0
- package/dist/embedding-backfill-9rcm1mfy.js +21 -0
- package/dist/embedding-cache-mgyr73ef.js +16 -0
- package/dist/embedding-worker.js +11 -9
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +1 -0
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-config.d.ts +3 -3
- package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-registry.d.ts +1 -0
- package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-async.d.ts +16 -3
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-bounded.d.ts +17 -0
- package/dist/features/magic-context/message-index-bounded.d.ts.map +1 -0
- package/dist/features/magic-context/message-index.d.ts +7 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/mural/render-trigger.d.ts +7 -4
- package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
- package/dist/features/magic-context/overflow-detection.d.ts +2 -0
- package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts +7 -0
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +31 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/session-activity.d.ts.map +1 -1
- package/dist/features/magic-context/session-project-storage.d.ts +8 -2
- package/dist/features/magic-context/session-project-storage.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
- package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-historian-runs.d.ts +2 -5
- package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +12 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +6 -0
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts +30 -0
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +148 -3
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -0
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +4 -2
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/harness-e4avh192.js +10 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts +10 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -0
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-blocking.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/auto-search-blocking.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-deadline.d.ts +7 -0
- package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-host-review.fixture.d.ts +3 -0
- package/dist/hooks/magic-context/auto-search-host-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-lock-review.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/auto-search-lock-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-long-lock-review.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/auto-search-long-lock-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-omp-host-review.fixture.d.ts +4 -0
- package/dist/hooks/magic-context/auto-search-omp-host-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-omp-loader.fixture.d.ts +3 -0
- package/dist/hooks/magic-context/auto-search-omp-loader.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-snapshot.fixture.d.ts +4 -0
- package/dist/hooks/magic-context/auto-search-snapshot.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts +98 -0
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-worker.d.ts +2 -0
- package/dist/hooks/magic-context/auto-search-worker.d.ts.map +1 -0
- package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +1 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +3 -5
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts +2 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +3 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/historian-drain-gate.d.ts +11 -0
- package/dist/hooks/magic-context/historian-drain-gate.d.ts.map +1 -0
- package/dist/hooks/magic-context/hook.d.ts +3 -2
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/latest-assistant-turn.d.ts +25 -0
- package/dist/hooks/magic-context/latest-assistant-turn.d.ts.map +1 -0
- package/dist/hooks/magic-context/latest-thinking-recovery.d.ts +61 -0
- package/dist/hooks/magic-context/latest-thinking-recovery.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-persist.d.ts +4 -3
- package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-replay.d.ts +13 -8
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +139 -2
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
- package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/opencode-proven-floor.d.ts +6 -0
- package/dist/hooks/magic-context/opencode-proven-floor.d.ts.map +1 -0
- package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts +63 -0
- package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
- package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts +2 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +87 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +12 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +83 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/reasoning-budget-status.d.ts +15 -0
- package/dist/hooks/magic-context/reasoning-budget-status.d.ts.map +1 -0
- package/dist/hooks/magic-context/reasoning-budget.d.ts +40 -0
- package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -0
- package/dist/hooks/magic-context/reasoning-removal.d.ts +6 -6
- package/dist/hooks/magic-context/reasoning-removal.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +45 -1
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +21 -5
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +1 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +21 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts +6 -0
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
- package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
- package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts +5 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -28
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +28 -6
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +11 -3
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
- package/dist/{index-hpecdzec.js → index-0an7742d.js} +6820 -6587
- package/dist/index-0qhce371.js +120 -0
- package/dist/{index-q6hef7fh.js → index-0sahzkwr.js} +6 -19
- package/dist/{index-k5bdx1bx.js → index-0w56v4fm.js} +3 -5
- package/dist/index-14cjxt20.js +819 -0
- package/dist/{v2/server-51dv1pr5.js → index-1qb0z7wa.js} +301 -27
- package/dist/index-2bvekkfy.js +11 -0
- package/dist/{index-sj29b3z2.js → index-2y0s2hep.js} +3 -3
- package/dist/index-4dhv7mqz.js +131 -0
- package/dist/{index-b35pxds2.js → index-58e3y90n.js} +1 -18
- package/dist/index-5zygecde.js +152 -0
- package/dist/{index-sjthx78w.js → index-692jzy0p.js} +16879 -22907
- package/dist/index-72nhv486.js +2307 -0
- package/dist/index-7jzrrxap.js +931 -0
- package/dist/index-7mx8v0pw.js +3591 -0
- package/dist/index-8ajstryz.js +18 -0
- package/dist/{index-sfpzqvdz.js → index-8cd2j99z.js} +2 -3
- package/dist/{index-hybnrwq0.js → index-8j7gqj40.js} +131 -128
- package/dist/index-bdckkfw6.js +3261 -0
- package/dist/{index-8x2v7gg9.js → index-bhvjj0ys.js} +158 -2455
- package/dist/index-c43kr12f.js +3030 -0
- package/dist/index-cb7emxgj.js +984 -0
- package/dist/index-d9vfe7xq.js +16 -0
- package/dist/{index-5gq3b2ya.js → index-db7zwa3v.js} +147 -209
- package/dist/index-dhwzyd54.js +1142 -0
- package/dist/{index-8da2zjhz.js → index-eeezr5zz.js} +9 -7
- package/dist/{index-pkbcrdqs.js → index-f0h6xwqm.js} +3412 -4552
- package/dist/index-fb3zxn06.js +13 -0
- package/dist/index-fbv1dn35.js +171 -0
- package/dist/index-fr0wbhdn.js +43 -0
- package/dist/{index-mc22ayvf.js → index-ghc9f0n7.js} +11 -9
- package/dist/{index-fzbvakh0.js → index-jcbd3znx.js} +3 -3
- package/dist/{index-5p8jdswx.js → index-k1xb52kd.js} +20 -13
- package/dist/index-k9nnwad5.js +3532 -0
- package/dist/{v2/server-fg34g6a5.js → index-kb9nn0a0.js} +309 -52
- package/dist/index-knh4y330.js +566 -0
- package/dist/{index-q4yp4b52.js → index-mfkzp7qj.js} +28 -28
- package/dist/{index-sgthv3f7.js → index-mmyh6d8f.js} +4 -4
- package/dist/index-pavzsdc6.js +17 -0
- package/dist/{index-0d3g3461.js → index-pdecwzrd.js} +19 -16
- package/dist/index-pg50n748.js +1060 -0
- package/dist/index-q2tqeqde.js +2106 -0
- package/dist/index-q7h7csab.js +3469 -0
- package/dist/index-qt1qqasc.js +22 -0
- package/dist/{index-majxda46.js → index-ty64eqcn.js} +28 -18
- package/dist/{index-7qw742ev.js → index-yq8n9qcb.js} +25 -44
- package/dist/{index-sfnj6h8h.js → index-z8e0psj8.js} +20 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1061 -260
- package/dist/logger-d3wex3dz.js +20 -0
- package/dist/message-index-bounded-7ezbgddp.js +124 -0
- package/dist/{v2/message-time-backfill-r6qkem1x.js → message-time-backfill-brbd63hv.js} +8 -6
- package/dist/migration-worker.js +25 -16
- package/dist/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
- package/dist/plugin/dream-timer.d.ts +1 -1
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +3 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/host-stall-profiler-report.d.ts +2 -0
- package/dist/plugin/host-stall-profiler-report.d.ts.map +1 -0
- package/dist/plugin/host-stall-profiler.d.ts +3 -0
- package/dist/plugin/host-stall-profiler.d.ts.map +1 -0
- package/dist/plugin/messages-transform.d.ts +21 -19
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/project-embedding-registry-7qzptcw7.js +88 -0
- package/dist/raw-ordinal-warmup-worker.js +60 -0
- package/dist/{read-session-chunk-egz7r68d.js → read-session-chunk-6k83m4fj.js} +15 -9
- package/dist/read-session-raw-3g9qy1xa.js +58 -0
- package/dist/recomp-orchestrator-d3fp1cy0.js +57 -0
- package/dist/{v2/safe-notification-target-eb1n1vfb.js → safe-notification-target-5ffqq32m.js} +4 -2
- package/dist/search-epax1ecv.js +45 -0
- package/dist/{v2/send-session-notification-qs0j78v6.js → send-session-notification-erecz4y4.js} +10 -6
- package/dist/shared/auto-search-lifecycle.d.ts +7 -0
- package/dist/shared/auto-search-lifecycle.d.ts.map +1 -0
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/historian-tool-expansions.d.ts +1 -1
- package/dist/shared/historian-tool-expansions.d.ts.map +1 -1
- package/dist/shared/historian-tool-template.d.ts +2 -2
- package/dist/shared/historian-tool-template.d.ts.map +1 -1
- package/dist/shared/host-stall-profiler-bun.d.ts +46 -0
- package/dist/shared/host-stall-profiler-bun.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-common.d.ts +58 -0
- package/dist/shared/host-stall-profiler-common.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-node.d.ts +36 -0
- package/dist/shared/host-stall-profiler-node.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-report.d.ts +68 -0
- package/dist/shared/host-stall-profiler-report.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler.d.ts +5 -0
- package/dist/shared/host-stall-profiler.d.ts.map +1 -0
- package/dist/shared/model-resolution.d.ts +2 -3
- package/dist/shared/model-resolution.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +46 -1
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/stable-json.d.ts.map +1 -1
- package/dist/shared/status-view.d.ts.map +1 -1
- package/dist/shared/user-facing-codes.d.ts +0 -5
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/shared/window-geometry.d.ts +4 -0
- package/dist/shared/window-geometry.d.ts.map +1 -1
- package/dist/sqlite-context-pragmas-mv9jqwjh.js +6 -0
- package/dist/sqlite-mhjkerzq.js +46 -0
- package/dist/storage-memory-07fx57k6.js +71 -0
- package/dist/storage-tags-d3b0v2ss.js +131 -0
- package/dist/{task-config-v81k8jvk.js → task-config-cgpg0nvh.js} +2 -2
- package/dist/tools/ctx-expand/render.d.ts.map +1 -1
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/constants.d.ts +4 -0
- package/dist/tools/ctx-note/constants.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts +1 -0
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/tools.d.ts.map +1 -1
- package/dist/tools/parameter-descriptions.d.ts +2 -2
- package/dist/tools/parameter-descriptions.d.ts.map +1 -1
- package/dist/{transform-postprocess-phase-bqhz6vdr.js → transform-postprocess-phase-spcy2qre.js} +35 -17
- package/dist/transformers-node-wasm.js +18415 -18415
- package/dist/v2/auto-search-worker.js +112 -0
- package/dist/v2/{context-zecmzk5s.js → context-sf98kstd.js} +8378 -8530
- package/dist/v2/{derive-budgets-kdgp4s3r.js → derive-budgets-3vc0y84t.js} +4 -3
- package/dist/v2/embedding-activity-g1dhes6g.js +10 -0
- package/dist/v2/embedding-backfill-vn8g1nh1.js +21 -0
- package/dist/v2/embedding-cache-mgyr73ef.js +16 -0
- package/dist/v2/embedding-worker.js +12 -9
- package/dist/v2/fold/host-media.d.ts +4 -0
- package/dist/v2/fold/host-media.d.ts.map +1 -1
- package/dist/v2/fold/memory-cache.d.ts +70 -0
- package/dist/v2/fold/memory-cache.d.ts.map +1 -0
- package/dist/v2/fold/native-codec.d.ts +10 -0
- package/dist/v2/fold/native-codec.d.ts.map +1 -0
- package/dist/v2/fold/native-replay.d.ts +58 -0
- package/dist/v2/fold/native-replay.d.ts.map +1 -0
- package/dist/v2/fold/policy.d.ts +24 -0
- package/dist/v2/fold/policy.d.ts.map +1 -0
- package/dist/v2/harness-e4avh192.js +10 -0
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts +2 -2
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/dream-manual.d.ts +1 -1
- package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
- package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
- package/dist/v2/hooks/dream-trigger.d.ts +1 -2
- package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/hooks/tools.d.ts.map +1 -1
- package/dist/v2/hooks/types.d.ts +6 -0
- package/dist/v2/hooks/types.d.ts.map +1 -1
- package/dist/v2/logger-mxd0ym09.js +19 -0
- package/dist/v2/message-index-bounded-dy3s2k1e.js +123 -0
- package/dist/{message-time-backfill-68gj6t3e.js → v2/message-time-backfill-gtx1pwk1.js} +7 -7
- package/dist/v2/migration-worker.js +24 -15
- package/dist/v2/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
- package/dist/v2/project-embedding-registry-1tgba5dv.js +86 -0
- package/dist/v2/raw-ordinal-warmup-worker.js +60 -0
- package/dist/v2/{read-session-chunk-8vjp6581.js → read-session-chunk-rh4khdkv.js} +14 -8
- package/dist/v2/read-session-raw-bsbmf0vj.js +57 -0
- package/dist/v2/recomp-orchestrator-az61rfcg.js +57 -0
- package/dist/{safe-notification-target-43r8jsxw.js → v2/safe-notification-target-73ax1p5v.js} +3 -3
- package/dist/v2/search-nzkwrc6n.js +45 -0
- package/dist/{send-session-notification-dyw42dtr.js → v2/send-session-notification-6km439kn.js} +9 -7
- package/dist/{index-5eqk6z3s.js → v2/server-1r6pmz4f.js} +301 -27
- package/dist/v2/server-2bvekkfy.js +11 -0
- package/dist/v2/server-2fbhp79z.js +3205 -0
- package/dist/v2/{server-ajzeteqw.js → server-2ra6pwf3.js} +1 -18
- package/dist/v2/server-4dhv7mqz.js +131 -0
- package/dist/v2/{server-xa4xe3rv.js → server-4k748ke6.js} +11 -1053
- package/dist/v2/{server-vs5gpnd4.js → server-52awr2mw.js} +81 -145
- package/dist/v2/{server-1qbnzc80.js → server-5m3dt5r1.js} +136 -148
- package/dist/v2/server-686jg6eb.js +3508 -0
- package/dist/v2/server-7jzrrxap.js +931 -0
- package/dist/v2/server-7wwc2nga.js +3023 -0
- package/dist/v2/server-8ajstryz.js +18 -0
- package/dist/v2/{server-sfpzqvdz.js → server-8cd2j99z.js} +2 -3
- package/dist/v2/server-8pyt7hev.js +3408 -0
- package/dist/v2/server-8tqanswc.js +984 -0
- package/dist/v2/{server-14vq4kpm.js → server-aan4q8mx.js} +3 -3
- package/dist/v2/server-d9vfe7xq.js +16 -0
- package/dist/v2/server-e0vdaae2.js +3591 -0
- package/dist/v2/server-ezhze64f.js +1048 -0
- package/dist/v2/server-fb3zxn06.js +13 -0
- package/dist/v2/server-fr0wbhdn.js +43 -0
- package/dist/v2/server-g5r0n3b6.js +1137 -0
- package/dist/v2/server-gjcr4w98.js +154 -0
- package/dist/v2/server-k228xhjg.js +171 -0
- package/dist/v2/{server-jc7y02q0.js → server-k8x2rbxc.js} +5119 -10948
- package/dist/{index-fg34g6a5.js → v2/server-kb9nn0a0.js} +309 -52
- package/dist/v2/{server-g0fjrkta.js → server-mfkzp7qj.js} +28 -28
- package/dist/v2/server-pavzsdc6.js +17 -0
- package/dist/v2/server-psqc7e9n.js +2106 -0
- package/dist/v2/server-qt1qqasc.js +22 -0
- package/dist/v2/server-qye6ykf7.js +120 -0
- package/dist/v2/{server-qdjnb2z1.js → server-r5p3b1wy.js} +11 -9
- package/dist/v2/server-sggvvzhb.js +759 -0
- package/dist/v2/{server-y8maxeft.js → server-v06jcv0w.js} +16 -13
- package/dist/v2/server-vqpf3167.js +1048 -0
- package/dist/v2/{server-c5gz8wph.js → server-x2g40a71.js} +2048 -2059
- package/dist/v2/{server-wvjvfhck.js → server-xdfwt6kh.js} +20 -16
- package/dist/v2/{server-mcfawjgc.js → server-xxm59eww.js} +25 -44
- package/dist/v2/server-yczc713m.js +564 -0
- package/dist/v2/{server-3n4q9xme.js → server-z2037m6z.js} +4 -4
- package/dist/v2/{server-e29d7p7c.js → server-zm570tr2.js} +166 -160
- package/dist/v2/{server-6r257mf5.js → server-zxhgvsf9.js} +3 -3
- package/dist/v2/server.js +16 -14
- package/dist/v2/sqlite-context-pragmas-mv9jqwjh.js +6 -0
- package/dist/v2/sqlite-mhjkerzq.js +46 -0
- package/dist/v2/storage-memory-07fx57k6.js +71 -0
- package/dist/v2/storage-tags-w4tv77sn.js +130 -0
- package/dist/v2/store-reader.d.ts +16 -0
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/v2/{task-config-tbndqyny.js → task-config-x0hq3qfd.js} +2 -2
- package/dist/v2/transformers-node-wasm.js +18415 -18415
- package/dist/v2/tui/index.d.ts.map +1 -1
- package/dist/v2/tui/types.d.ts +1 -10
- package/dist/v2/tui/types.d.ts.map +1 -1
- package/dist/v2/{wrapup-orchestrator-0snhvwcv.js → wrapup-orchestrator-mz7efs7w.js} +51 -27
- package/dist/wrapup-orchestrator-amzta1t4.js +44 -0
- package/package.json +4 -3
- package/src/agents/magic-context-prompt.ts +27 -2
- package/src/agents/smart-notes-enabled.test.ts +294 -0
- package/src/agents/smart-notes-on.golden.json +70 -0
- package/src/config/index.test.ts +67 -1
- package/src/config/index.ts +8 -0
- package/src/config/latch-permanence-guard.test.ts +4 -0
- package/src/config/live-run-config.test.ts +37 -1
- package/src/config/live-run-config.ts +28 -0
- package/src/config/migrate-config-location.ts +10 -3
- package/src/config/mural-model-deprecation.ts +24 -0
- package/src/config/project-security.hostile-matrix.test.ts +4 -44
- package/src/config/project-security.test.ts +9 -14
- package/src/config/project-security.ts +13 -55
- package/src/config/schema/magic-context.test.ts +6 -5
- package/src/config/schema/magic-context.ts +34 -16
- package/src/features/magic-context/dreamer/task-registry.ts +6 -0
- package/src/shared/auto-search-lifecycle.ts +27 -0
- package/src/shared/conflict-detector.test.ts +56 -0
- package/src/shared/conflict-detector.ts +16 -5
- package/src/shared/historian-tool-defaults.json +6 -6
- package/src/shared/historian-tool-expansions.ts +65 -8
- package/src/shared/historian-tool-preview-defaults.json +13 -0
- package/src/shared/historian-tool-template.ts +48 -14
- package/src/shared/host-stall-profiler-bun.ts +358 -0
- package/src/shared/host-stall-profiler-common.ts +159 -0
- package/src/shared/host-stall-profiler-node.test.ts +234 -0
- package/src/shared/host-stall-profiler-node.ts +274 -0
- package/src/shared/host-stall-profiler-report.ts +248 -0
- package/src/shared/host-stall-profiler.ts +57 -0
- package/src/shared/model-resolution.test.ts +54 -17
- package/src/shared/model-resolution.ts +6 -17
- package/src/shared/sqlite-640-review-r2.test.ts +136 -0
- package/src/shared/sqlite-640-review.test.ts +183 -0
- package/src/shared/sqlite-acquisition-routing.test.ts +18 -0
- package/src/shared/sqlite.test.ts +52 -0
- package/src/shared/sqlite.ts +423 -37
- package/src/shared/stable-json-linear.test.ts +109 -0
- package/src/shared/stable-json.ts +37 -7
- package/src/shared/status-view.test.ts +6 -1
- package/src/shared/status-view.ts +15 -1
- package/src/shared/tag-transcript.ts +6 -0
- package/src/shared/user-facing-codes.ts +2 -6
- package/src/shared/window-geometry.ts +10 -0
- package/src/shared/write-transaction-attribution.test.ts +2 -2
- package/src/v2/tui/host-contract.test.ts +41 -67
- package/src/v2/tui/index.ts +6 -214
- package/src/v2/tui/types.ts +5 -17
- package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts +0 -45
- package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts.map +0 -1
- package/dist/features/magic-context/checkout-claim.d.ts +0 -155
- package/dist/features/magic-context/checkout-claim.d.ts.map +0 -1
- package/dist/index-3h0ybwah.js +0 -6540
- package/dist/index-r5hmbx3t.js +0 -7773
- package/dist/recomp-orchestrator-y15j0rb9.js +0 -39
- package/dist/v2/recomp-orchestrator-8ejxvrzz.js +0 -39
- package/dist/v2/server-frbm99q5.js +0 -7698
- package/dist/v2/server-qp5hx1ad.js +0 -6366
- package/dist/wrapup-orchestrator-39amhv9s.js +0 -26
- /package/dist/{index-en1k8h8m.js → index-2pp04pmg.js} +0 -0
- /package/dist/v2/{index-en1k8h8m.js → index-2pp04pmg.js} +0 -0
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
log2
|
|
3
|
+
} from "./server-5m3dt5r1.js";
|
|
4
|
+
import {
|
|
5
|
+
setWindowOverlayPath,
|
|
6
|
+
setOutputReserveConfig
|
|
7
|
+
} from "./server-v06jcv0w.js";
|
|
1
8
|
import {
|
|
2
9
|
DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE,
|
|
3
10
|
PROTECTED_TOKENS_MIN,
|
|
@@ -5,1039 +12,355 @@ import {
|
|
|
5
12
|
PER_HARNESS_MODEL_KEYS,
|
|
6
13
|
ConfigProfilesSchema,
|
|
7
14
|
MagicContextConfigSchema
|
|
8
|
-
} from "./server-
|
|
9
|
-
import {
|
|
10
|
-
log
|
|
11
|
-
} from "./server-1qbnzc80.js";
|
|
12
|
-
import {
|
|
13
|
-
setWindowOverlayPath,
|
|
14
|
-
setOutputReserveConfig
|
|
15
|
-
} from "./server-y8maxeft.js";
|
|
15
|
+
} from "./server-zm570tr2.js";
|
|
16
16
|
|
|
17
|
-
// src/config/
|
|
18
|
-
|
|
19
|
-
function isDreamerRunnable(config) {
|
|
20
|
-
return !!config.dreamer && config.dreamer.disable !== true;
|
|
21
|
-
}
|
|
22
|
-
function isCompactionEnabled(config) {
|
|
23
|
-
return config.compaction?.enabled !== false;
|
|
24
|
-
}
|
|
25
|
-
function clonePlainObject(value) {
|
|
26
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
return { ...value };
|
|
30
|
-
}
|
|
31
|
-
function migrateLegacyEnabledForAgent(args) {
|
|
32
|
-
const agent = clonePlainObject(args.patched[args.agentName]);
|
|
33
|
-
if (!agent || !("enabled" in agent))
|
|
34
|
-
return;
|
|
35
|
-
const enabled = agent.enabled;
|
|
36
|
-
const disable = agent.disable;
|
|
37
|
-
delete agent.enabled;
|
|
38
|
-
if (args.agentName === "historian") {
|
|
39
|
-
args.warnings.push('Removed invalid "historian.enabled" in-memory (run doctor to persist).');
|
|
40
|
-
args.patched.historian = agent;
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (disable !== true && enabled === false) {
|
|
44
|
-
agent.disable = true;
|
|
45
|
-
args.warnings.push('Migrated "dreamer.enabled=false" → "dreamer.disable=true" in-memory (run doctor to persist). This now also disables manual /ctx-dream; for manual-only remove disable and set schedule="".');
|
|
46
|
-
}
|
|
47
|
-
args.patched.dreamer = agent;
|
|
48
|
-
}
|
|
49
|
-
function migrateLegacyAgentEnabledInMemory(rawConfig, warnings) {
|
|
50
|
-
const shouldPatch = ["dreamer", "historian"].some((key) => {
|
|
51
|
-
const agent = rawConfig[key];
|
|
52
|
-
return typeof agent === "object" && agent !== null && !Array.isArray(agent) && "enabled" in agent;
|
|
53
|
-
});
|
|
54
|
-
if (!shouldPatch)
|
|
55
|
-
return rawConfig;
|
|
56
|
-
const patched = { ...rawConfig };
|
|
57
|
-
migrateLegacyEnabledForAgent({ patched, agentName: "dreamer", warnings });
|
|
58
|
-
migrateLegacyEnabledForAgent({ patched, agentName: "historian", warnings });
|
|
59
|
-
return patched;
|
|
60
|
-
}
|
|
17
|
+
// src/config/index.ts
|
|
18
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
61
19
|
|
|
62
|
-
// src/
|
|
63
|
-
var
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
var PROMPT_SURFACE_USER_ONLY_FIELDS = ["guidance_override_path", "tool_descriptions"];
|
|
71
|
-
var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools"];
|
|
72
|
-
var EMBEDDING_USER_ONLY_FIELDS = [
|
|
73
|
-
"endpoint",
|
|
74
|
-
"provider",
|
|
75
|
-
"fallback_provider",
|
|
76
|
-
"query_instruction",
|
|
77
|
-
"document_prefix"
|
|
78
|
-
];
|
|
79
|
-
var PERCENTAGE_THRESHOLD_REASON = "security: a repository may only raise compaction thresholds above the user's effective value; it cannot force earlier historian work or cloned-repo cost escalation.";
|
|
80
|
-
var TOKEN_THRESHOLD_REASON = "security: a repository may only raise execute_threshold_tokens above the user's trusted token threshold; it cannot force earlier historian work or cloned-repo cost escalation.";
|
|
81
|
-
var TOKEN_THRESHOLD_INTRODUCTION_REASON = "security: a repository cannot introduce a new execute_threshold_tokens override when the user has no trusted token threshold for that key; that could force earlier historian work or cloned-repo cost escalation.";
|
|
82
|
-
var PROTECTED_TOKENS_REASON = "security: a repository may only raise protected_tokens above the resolved user-or-derived floor; it cannot lower protection.";
|
|
83
|
-
function isPlainObject(value) {
|
|
84
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
85
|
-
}
|
|
86
|
-
function resolveProtectedTokensScalar(value) {
|
|
87
|
-
if (typeof value === "number" && Number.isInteger(value) && value >= 4000 && value <= 1e6) {
|
|
88
|
-
return value;
|
|
89
|
-
}
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
var PROTECTED_TOKENS_TIER_OVERRIDES = Symbol.for("@cortexkit/magic-context/protected-tokens-tier-overrides");
|
|
93
|
-
function attachProtectedTokensTierOverrides(config, args) {
|
|
94
|
-
const user = resolveProtectedTokensScalar(args.trustedUser);
|
|
95
|
-
const rawProject = resolveProtectedTokensScalar(args.project);
|
|
96
|
-
const project = rawProject !== undefined && (user === undefined || rawProject >= user) ? rawProject : undefined;
|
|
97
|
-
if (user === undefined && project === undefined)
|
|
98
|
-
return config;
|
|
99
|
-
Object.defineProperty(config, PROTECTED_TOKENS_TIER_OVERRIDES, {
|
|
100
|
-
value: {
|
|
101
|
-
...user !== undefined ? { user } : {},
|
|
102
|
-
...project !== undefined ? { project } : {}
|
|
20
|
+
// src/shared/builtin-commands.ts
|
|
21
|
+
var COMPACTION_ENABLED_PATH2 = `compaction${".enabled"}`;
|
|
22
|
+
function getMagicContextBuiltinCommands(compactionEnabled = true) {
|
|
23
|
+
const unavailableInCompactionOff = (command) => `Unavailable when ${COMPACTION_ENABLED_PATH2} is false: /${command} manages compacted history.`;
|
|
24
|
+
return {
|
|
25
|
+
"ctx-status": {
|
|
26
|
+
template: "ctx-status",
|
|
27
|
+
description: "Show magic context status, pending queue, cache TTL, and debug info"
|
|
103
28
|
},
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
29
|
+
"ctx-recomp": {
|
|
30
|
+
template: "ctx-recomp",
|
|
31
|
+
description: compactionEnabled ? "Rebuild compressed history from raw history (full or <start>-<end> range); memories are not changed" : unavailableInCompactionOff("ctx-recomp")
|
|
32
|
+
},
|
|
33
|
+
"ctx-wrapup": {
|
|
34
|
+
template: "ctx-wrapup",
|
|
35
|
+
description: compactionEnabled ? "Compact older live history while keeping the newest messages raw" : unavailableInCompactionOff("ctx-wrapup")
|
|
36
|
+
},
|
|
37
|
+
"ctx-flush": {
|
|
38
|
+
template: "ctx-flush",
|
|
39
|
+
description: compactionEnabled ? "Force-process all pending magic context operations immediately" : unavailableInCompactionOff("ctx-flush")
|
|
40
|
+
},
|
|
41
|
+
"ctx-dream": {
|
|
42
|
+
template: "ctx-dream",
|
|
43
|
+
description: "Run the hidden dreamer maintenance pass for this project now"
|
|
44
|
+
},
|
|
45
|
+
"ctx-embed": {
|
|
46
|
+
template: "ctx-embed",
|
|
47
|
+
description: "Embedding status, or start/pause history compartment embedding (start | pause)"
|
|
118
48
|
}
|
|
119
|
-
}
|
|
49
|
+
};
|
|
120
50
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
51
|
+
|
|
52
|
+
// src/shared/config-diagnostics.ts
|
|
53
|
+
var CONFIG_WARNING_CLASS = {
|
|
54
|
+
FILE_PARSE: "file-parse",
|
|
55
|
+
FILE_IO: "file-io",
|
|
56
|
+
INVALID_LEAF: "invalid-leaf"
|
|
57
|
+
};
|
|
58
|
+
var claimedFailures = new Set;
|
|
59
|
+
|
|
60
|
+
// src/shared/jsonc-parser.ts
|
|
61
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
62
|
+
|
|
63
|
+
// ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
64
|
+
function createScanner(text, ignoreTrivia = false) {
|
|
65
|
+
const len = text.length;
|
|
66
|
+
let pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
|
|
67
|
+
function scanHexDigits(count, exact) {
|
|
68
|
+
let digits = 0;
|
|
69
|
+
let value = 0;
|
|
70
|
+
while (digits < count || !exact) {
|
|
71
|
+
let ch = text.charCodeAt(pos);
|
|
72
|
+
if (ch >= 48 && ch <= 57) {
|
|
73
|
+
value = value * 16 + ch - 48;
|
|
74
|
+
} else if (ch >= 65 && ch <= 70) {
|
|
75
|
+
value = value * 16 + ch - 65 + 10;
|
|
76
|
+
} else if (ch >= 97 && ch <= 102) {
|
|
77
|
+
value = value * 16 + ch - 97 + 10;
|
|
78
|
+
} else {
|
|
79
|
+
break;
|
|
131
80
|
}
|
|
81
|
+
pos++;
|
|
82
|
+
digits++;
|
|
132
83
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
function stripNestedMuralModels(node, path, removed) {
|
|
136
|
-
for (const [key, value] of Object.entries(node)) {
|
|
137
|
-
if (key === "mural" && isPlainObject(value) && "model" in value) {
|
|
138
|
-
delete value.model;
|
|
139
|
-
removed.push(`${path}.${key}.model`);
|
|
140
|
-
} else if (isPlainObject(value)) {
|
|
141
|
-
stripNestedMuralModels(value, `${path}.${key}`, removed);
|
|
84
|
+
if (digits < count) {
|
|
85
|
+
value = -1;
|
|
142
86
|
}
|
|
87
|
+
return value;
|
|
143
88
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
function normalizeTrustedPercentageThresholds(value) {
|
|
152
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
153
|
-
return { defaultValue: value, overrides: new Map };
|
|
89
|
+
function setPosition(newPosition) {
|
|
90
|
+
pos = newPosition;
|
|
91
|
+
value = "";
|
|
92
|
+
tokenOffset = 0;
|
|
93
|
+
token = 16;
|
|
94
|
+
scanError = 0;
|
|
154
95
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
96
|
+
function scanNumber() {
|
|
97
|
+
let start = pos;
|
|
98
|
+
if (text.charCodeAt(pos) === 48) {
|
|
99
|
+
pos++;
|
|
100
|
+
} else {
|
|
101
|
+
pos++;
|
|
102
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
103
|
+
pos++;
|
|
162
104
|
}
|
|
163
105
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
continue;
|
|
176
|
-
if (typeof child === "number" && Number.isFinite(child)) {
|
|
177
|
-
overrides.set(key, child);
|
|
106
|
+
if (pos < text.length && text.charCodeAt(pos) === 46) {
|
|
107
|
+
pos++;
|
|
108
|
+
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
109
|
+
pos++;
|
|
110
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
111
|
+
pos++;
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
scanError = 3;
|
|
115
|
+
return text.substring(start, pos);
|
|
116
|
+
}
|
|
178
117
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
function clonePercentageThresholds(value) {
|
|
186
|
-
return {
|
|
187
|
-
defaultValue: value.defaultValue,
|
|
188
|
-
overrides: new Map(value.overrides)
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
function cloneTokenThresholds(value) {
|
|
192
|
-
return {
|
|
193
|
-
defaultValue: value.defaultValue,
|
|
194
|
-
overrides: new Map(value.overrides)
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
function percentageThresholdsEqual(left, right) {
|
|
198
|
-
if (left.defaultValue !== right.defaultValue)
|
|
199
|
-
return false;
|
|
200
|
-
if (left.overrides.size !== right.overrides.size)
|
|
201
|
-
return false;
|
|
202
|
-
for (const [key, value] of left.overrides) {
|
|
203
|
-
if (right.overrides.get(key) !== value)
|
|
204
|
-
return false;
|
|
205
|
-
}
|
|
206
|
-
return true;
|
|
207
|
-
}
|
|
208
|
-
function setMergedPercentageThreshold(mergedRaw, value) {
|
|
209
|
-
if (value.overrides.size === 0) {
|
|
210
|
-
mergedRaw.execute_threshold_percentage = value.defaultValue;
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
const serialized = { default: value.defaultValue };
|
|
214
|
-
for (const [key, threshold] of value.overrides) {
|
|
215
|
-
serialized[key] = threshold;
|
|
216
|
-
}
|
|
217
|
-
mergedRaw.execute_threshold_percentage = serialized;
|
|
218
|
-
}
|
|
219
|
-
function setMergedTokenThreshold(mergedRaw, value) {
|
|
220
|
-
if (value.defaultValue === undefined && value.overrides.size === 0) {
|
|
221
|
-
delete mergedRaw.execute_threshold_tokens;
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
const serialized = {};
|
|
225
|
-
if (value.defaultValue !== undefined) {
|
|
226
|
-
serialized.default = value.defaultValue;
|
|
227
|
-
}
|
|
228
|
-
for (const [key, threshold] of value.overrides) {
|
|
229
|
-
serialized[key] = threshold;
|
|
230
|
-
}
|
|
231
|
-
mergedRaw.execute_threshold_tokens = serialized;
|
|
232
|
-
}
|
|
233
|
-
function makeProjectThresholdWarning(field, reason) {
|
|
234
|
-
return `Ignoring ${field} from project config (${reason})`;
|
|
235
|
-
}
|
|
236
|
-
function stripUnsafeProjectConfigFields(projectRaw) {
|
|
237
|
-
const warnings = [];
|
|
238
|
-
if ("profiles" in projectRaw) {
|
|
239
|
-
delete projectRaw.profiles;
|
|
240
|
-
warnings.push("Ignoring profiles from project config (security: profile definitions are user-level only; a repository may select a named user profile with profile).");
|
|
241
|
-
}
|
|
242
|
-
if ("auto_update" in projectRaw) {
|
|
243
|
-
delete projectRaw.auto_update;
|
|
244
|
-
warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
|
|
245
|
-
}
|
|
246
|
-
if ("fail_closed_blocking" in projectRaw) {
|
|
247
|
-
delete projectRaw.fail_closed_blocking;
|
|
248
|
-
warnings.push("Ignoring fail_closed_blocking from project config (security: only user-level config may disable or force the loud inoperability gate).");
|
|
249
|
-
}
|
|
250
|
-
if ("debug_rpc" in projectRaw) {
|
|
251
|
-
delete projectRaw.debug_rpc;
|
|
252
|
-
warnings.push("Ignoring debug_rpc from project config (security: only user-level config may enable process heap diagnostics).");
|
|
253
|
-
}
|
|
254
|
-
if ("allow_home_project" in projectRaw) {
|
|
255
|
-
delete projectRaw.allow_home_project;
|
|
256
|
-
warnings.push("Ignoring allow_home_project from project config (security: only user-level config may opt the user's home directory into Magic Context).");
|
|
257
|
-
}
|
|
258
|
-
const compaction = projectRaw.compaction;
|
|
259
|
-
if (isPlainObject(compaction) && "enabled" in compaction) {
|
|
260
|
-
delete compaction.enabled;
|
|
261
|
-
warnings.push("Ignoring compaction.enabled from project config (security: only user-level config may disable Magic Context's context-window management; a cloned repo cannot change how the user's window is owned).");
|
|
262
|
-
}
|
|
263
|
-
if ("output_reserve" in projectRaw) {
|
|
264
|
-
delete projectRaw.output_reserve;
|
|
265
|
-
warnings.push("Ignoring output_reserve from project config (security: output-token reservation only honors user-level config).");
|
|
266
|
-
}
|
|
267
|
-
const models = projectRaw.models;
|
|
268
|
-
if (isPlainObject(models) && "window_overlay_path" in models) {
|
|
269
|
-
delete models.window_overlay_path;
|
|
270
|
-
warnings.push("Ignoring models.window_overlay_path from project config (security: only user-level config may select model geometry metadata).");
|
|
271
|
-
}
|
|
272
|
-
if ("language" in projectRaw) {
|
|
273
|
-
delete projectRaw.language;
|
|
274
|
-
warnings.push("Ignoring language from project config (security: output language is a user-level setting).");
|
|
275
|
-
}
|
|
276
|
-
if ("sqlite" in projectRaw) {
|
|
277
|
-
delete projectRaw.sqlite;
|
|
278
|
-
warnings.push("Ignoring sqlite.* from project config (security: SQLite cache/mmap PRAGMAs apply to the " + "process-global shared database handle; only user-level config may set them).");
|
|
279
|
-
}
|
|
280
|
-
const storage = projectRaw.storage;
|
|
281
|
-
if (isPlainObject(storage) && "enforce_private_permissions" in storage) {
|
|
282
|
-
delete storage.enforce_private_permissions;
|
|
283
|
-
warnings.push("Ignoring storage.enforce_private_permissions from project config (security: only user-level config may opt into externally managed shared storage permissions).");
|
|
284
|
-
}
|
|
285
|
-
const promptSurface = projectRaw.prompt_surface;
|
|
286
|
-
if (isPlainObject(promptSurface)) {
|
|
287
|
-
const removed = [];
|
|
288
|
-
for (const field of PROMPT_SURFACE_USER_ONLY_FIELDS) {
|
|
289
|
-
if (field in promptSurface) {
|
|
290
|
-
delete promptSurface[field];
|
|
291
|
-
removed.push(field);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
if (removed.length > 0) {
|
|
295
|
-
warnings.push(`Ignoring prompt_surface.${removed.join("/")} from project config (security: repositories may select prompt presets but only user config may provide guidance or tool-description text).`);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
const pi = projectRaw.pi;
|
|
299
|
-
if (isPlainObject(pi) && "subagent_extensions" in pi) {
|
|
300
|
-
delete pi.subagent_extensions;
|
|
301
|
-
warnings.push("Ignoring pi.subagent_extensions from project config (security: only user-level config may choose extensions loaded by Pi subagent children).");
|
|
302
|
-
}
|
|
303
|
-
for (const field of ["subc", "shadow_embedding"]) {
|
|
304
|
-
if (field in projectRaw) {
|
|
305
|
-
delete projectRaw[field];
|
|
306
|
-
warnings.push(`Ignoring ${field} from project config (security: daemon routing and developer-only embedding traffic are user-level settings).`);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
const embedding = projectRaw.embedding;
|
|
310
|
-
if (isPlainObject(embedding)) {
|
|
311
|
-
const removed = [];
|
|
312
|
-
for (const field of EMBEDDING_USER_ONLY_FIELDS) {
|
|
313
|
-
if (field in embedding) {
|
|
314
|
-
delete embedding[field];
|
|
315
|
-
removed.push(field);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
if (removed.length > 0) {
|
|
319
|
-
warnings.push(`Ignoring embedding.${removed.join("/")} from project config ` + "(security: a repository cannot choose where or how private text is embedded).");
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
for (const agentKey of HIDDEN_AGENT_KEYS) {
|
|
323
|
-
const block = projectRaw[agentKey];
|
|
324
|
-
if (!isPlainObject(block))
|
|
325
|
-
continue;
|
|
326
|
-
const removed = [];
|
|
327
|
-
stripEscalationAtExecutableSite(block, agentKey, removed);
|
|
328
|
-
for (const harness of HARNESS_KEYS) {
|
|
329
|
-
const harnessBlock = block[harness];
|
|
330
|
-
if (!isPlainObject(harnessBlock))
|
|
331
|
-
continue;
|
|
332
|
-
stripEscalationAtExecutableSite(harnessBlock, `${agentKey}.${harness}`, removed);
|
|
333
|
-
const tasks = harnessBlock.tasks;
|
|
334
|
-
if (isPlainObject(tasks)) {
|
|
335
|
-
for (const [taskName, taskBlock] of Object.entries(tasks)) {
|
|
336
|
-
if (isPlainObject(taskBlock)) {
|
|
337
|
-
stripEscalationAtExecutableSite(taskBlock, `${agentKey}.${harness}.tasks.${taskName}`, removed);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
118
|
+
let end = pos;
|
|
119
|
+
if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
|
|
120
|
+
pos++;
|
|
121
|
+
if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
|
|
122
|
+
pos++;
|
|
340
123
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
if (isPlainObject(taskBlock)) {
|
|
346
|
-
stripListedFields(taskBlock, AGENT_ESCALATION_FIELDS, `${agentKey}.tasks.${taskName}`, removed);
|
|
124
|
+
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
125
|
+
pos++;
|
|
126
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
127
|
+
pos++;
|
|
347
128
|
}
|
|
129
|
+
end = pos;
|
|
130
|
+
} else {
|
|
131
|
+
scanError = 3;
|
|
348
132
|
}
|
|
349
133
|
}
|
|
350
|
-
|
|
351
|
-
warnings.push(`Ignoring ${removed.join(", ")} from project config ` + "(security: a repository cannot reprogram or re-permission hidden agents).");
|
|
352
|
-
}
|
|
134
|
+
return text.substring(start, end);
|
|
353
135
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
136
|
+
function scanString() {
|
|
137
|
+
let result = "", start = pos;
|
|
138
|
+
while (true) {
|
|
139
|
+
if (pos >= len) {
|
|
140
|
+
result += text.substring(start, pos);
|
|
141
|
+
scanError = 2;
|
|
142
|
+
break;
|
|
361
143
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
144
|
+
const ch = text.charCodeAt(pos);
|
|
145
|
+
if (ch === 34) {
|
|
146
|
+
result += text.substring(start, pos);
|
|
147
|
+
pos++;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
if (ch === 92) {
|
|
151
|
+
result += text.substring(start, pos);
|
|
152
|
+
pos++;
|
|
153
|
+
if (pos >= len) {
|
|
154
|
+
scanError = 2;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
const ch2 = text.charCodeAt(pos++);
|
|
158
|
+
switch (ch2) {
|
|
159
|
+
case 34:
|
|
160
|
+
result += '"';
|
|
161
|
+
break;
|
|
162
|
+
case 92:
|
|
163
|
+
result += "\\";
|
|
164
|
+
break;
|
|
165
|
+
case 47:
|
|
166
|
+
result += "/";
|
|
167
|
+
break;
|
|
168
|
+
case 98:
|
|
169
|
+
result += "\b";
|
|
170
|
+
break;
|
|
171
|
+
case 102:
|
|
172
|
+
result += "\f";
|
|
173
|
+
break;
|
|
174
|
+
case 110:
|
|
175
|
+
result += `
|
|
176
|
+
`;
|
|
177
|
+
break;
|
|
178
|
+
case 114:
|
|
179
|
+
result += "\r";
|
|
180
|
+
break;
|
|
181
|
+
case 116:
|
|
182
|
+
result += "\t";
|
|
183
|
+
break;
|
|
184
|
+
case 117:
|
|
185
|
+
const ch3 = scanHexDigits(4, true);
|
|
186
|
+
if (ch3 >= 0) {
|
|
187
|
+
result += String.fromCharCode(ch3);
|
|
188
|
+
} else {
|
|
189
|
+
scanError = 4;
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
default:
|
|
193
|
+
scanError = 5;
|
|
194
|
+
}
|
|
195
|
+
start = pos;
|
|
366
196
|
continue;
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
197
|
+
}
|
|
198
|
+
if (ch >= 0 && ch <= 31) {
|
|
199
|
+
if (isLineBreak(ch)) {
|
|
200
|
+
result += text.substring(start, pos);
|
|
201
|
+
scanError = 2;
|
|
202
|
+
break;
|
|
203
|
+
} else {
|
|
204
|
+
scanError = 6;
|
|
371
205
|
}
|
|
372
206
|
}
|
|
207
|
+
pos++;
|
|
373
208
|
}
|
|
374
|
-
|
|
375
|
-
warnings.push(`Ignoring ${removed.map((path) => `historian.${path}`).join(", ")} from project config ` + "(security: historian model selection is user-level only; a repository cannot force extra compaction cost).");
|
|
376
|
-
}
|
|
209
|
+
return result;
|
|
377
210
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
return warnings;
|
|
405
|
-
}
|
|
406
|
-
function constrainProjectThresholdOverrides(args) {
|
|
407
|
-
const warnings = [];
|
|
408
|
-
const basePercentage = normalizeTrustedPercentageThresholds(args.trustedBaseConfig.execute_threshold_percentage);
|
|
409
|
-
const baseTokens = normalizeTrustedTokenThresholds(args.trustedBaseConfig.execute_threshold_tokens);
|
|
410
|
-
if ("execute_threshold_percentage" in args.projectRaw) {
|
|
411
|
-
const projectValue = args.projectRaw.execute_threshold_percentage;
|
|
412
|
-
if (isValidPercentageThreshold(projectValue)) {
|
|
413
|
-
const constrained = clonePercentageThresholds(basePercentage);
|
|
414
|
-
constrained.defaultValue = Math.max(basePercentage.defaultValue, projectValue);
|
|
415
|
-
for (const [modelKey, threshold] of basePercentage.overrides) {
|
|
416
|
-
const raisedThreshold = Math.max(threshold, projectValue);
|
|
417
|
-
if (raisedThreshold === constrained.defaultValue) {
|
|
418
|
-
constrained.overrides.delete(modelKey);
|
|
419
|
-
} else {
|
|
420
|
-
constrained.overrides.set(modelKey, raisedThreshold);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
setMergedPercentageThreshold(args.mergedRaw, constrained);
|
|
424
|
-
if (percentageThresholdsEqual(constrained, basePercentage)) {
|
|
425
|
-
warnings.push(makeProjectThresholdWarning("execute_threshold_percentage", PERCENTAGE_THRESHOLD_REASON));
|
|
211
|
+
function scanNext() {
|
|
212
|
+
value = "";
|
|
213
|
+
scanError = 0;
|
|
214
|
+
tokenOffset = pos;
|
|
215
|
+
lineStartOffset = lineNumber;
|
|
216
|
+
prevTokenLineStartOffset = tokenLineStartOffset;
|
|
217
|
+
if (pos >= len) {
|
|
218
|
+
tokenOffset = len;
|
|
219
|
+
return token = 17;
|
|
220
|
+
}
|
|
221
|
+
let code = text.charCodeAt(pos);
|
|
222
|
+
if (isWhiteSpace(code)) {
|
|
223
|
+
do {
|
|
224
|
+
pos++;
|
|
225
|
+
value += String.fromCharCode(code);
|
|
226
|
+
code = text.charCodeAt(pos);
|
|
227
|
+
} while (isWhiteSpace(code));
|
|
228
|
+
return token = 15;
|
|
229
|
+
}
|
|
230
|
+
if (isLineBreak(code)) {
|
|
231
|
+
pos++;
|
|
232
|
+
value += String.fromCharCode(code);
|
|
233
|
+
if (code === 13 && text.charCodeAt(pos) === 10) {
|
|
234
|
+
pos++;
|
|
235
|
+
value += `
|
|
236
|
+
`;
|
|
426
237
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
238
|
+
lineNumber++;
|
|
239
|
+
tokenLineStartOffset = pos;
|
|
240
|
+
return token = 14;
|
|
241
|
+
}
|
|
242
|
+
switch (code) {
|
|
243
|
+
case 123:
|
|
244
|
+
pos++;
|
|
245
|
+
return token = 1;
|
|
246
|
+
case 125:
|
|
247
|
+
pos++;
|
|
248
|
+
return token = 2;
|
|
249
|
+
case 91:
|
|
250
|
+
pos++;
|
|
251
|
+
return token = 3;
|
|
252
|
+
case 93:
|
|
253
|
+
pos++;
|
|
254
|
+
return token = 4;
|
|
255
|
+
case 58:
|
|
256
|
+
pos++;
|
|
257
|
+
return token = 6;
|
|
258
|
+
case 44:
|
|
259
|
+
pos++;
|
|
260
|
+
return token = 5;
|
|
261
|
+
case 34:
|
|
262
|
+
pos++;
|
|
263
|
+
value = scanString();
|
|
264
|
+
return token = 10;
|
|
265
|
+
case 47:
|
|
266
|
+
const start = pos - 1;
|
|
267
|
+
if (text.charCodeAt(pos + 1) === 47) {
|
|
268
|
+
pos += 2;
|
|
269
|
+
while (pos < len) {
|
|
270
|
+
if (isLineBreak(text.charCodeAt(pos))) {
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
pos++;
|
|
274
|
+
}
|
|
275
|
+
value = text.substring(start, pos);
|
|
276
|
+
return token = 12;
|
|
436
277
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
278
|
+
if (text.charCodeAt(pos + 1) === 42) {
|
|
279
|
+
pos += 2;
|
|
280
|
+
const safeLength = len - 1;
|
|
281
|
+
let commentClosed = false;
|
|
282
|
+
while (pos < safeLength) {
|
|
283
|
+
const ch = text.charCodeAt(pos);
|
|
284
|
+
if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
|
|
285
|
+
pos += 2;
|
|
286
|
+
commentClosed = true;
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
pos++;
|
|
290
|
+
if (isLineBreak(ch)) {
|
|
291
|
+
if (ch === 13 && text.charCodeAt(pos) === 10) {
|
|
292
|
+
pos++;
|
|
293
|
+
}
|
|
294
|
+
lineNumber++;
|
|
295
|
+
tokenLineStartOffset = pos;
|
|
296
|
+
}
|
|
450
297
|
}
|
|
451
|
-
|
|
452
|
-
|
|
298
|
+
if (!commentClosed) {
|
|
299
|
+
pos++;
|
|
300
|
+
scanError = 1;
|
|
301
|
+
}
|
|
302
|
+
value = text.substring(start, pos);
|
|
303
|
+
return token = 13;
|
|
453
304
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
305
|
+
value += String.fromCharCode(code);
|
|
306
|
+
pos++;
|
|
307
|
+
return token = 16;
|
|
308
|
+
case 45:
|
|
309
|
+
value += String.fromCharCode(code);
|
|
310
|
+
pos++;
|
|
311
|
+
if (pos === len || !isDigit(text.charCodeAt(pos))) {
|
|
312
|
+
return token = 16;
|
|
313
|
+
}
|
|
314
|
+
case 48:
|
|
315
|
+
case 49:
|
|
316
|
+
case 50:
|
|
317
|
+
case 51:
|
|
318
|
+
case 52:
|
|
319
|
+
case 53:
|
|
320
|
+
case 54:
|
|
321
|
+
case 55:
|
|
322
|
+
case 56:
|
|
323
|
+
case 57:
|
|
324
|
+
value += scanNumber();
|
|
325
|
+
return token = 11;
|
|
326
|
+
default:
|
|
327
|
+
while (pos < len && isUnknownContentCharacter(code)) {
|
|
328
|
+
pos++;
|
|
329
|
+
code = text.charCodeAt(pos);
|
|
330
|
+
}
|
|
331
|
+
if (tokenOffset !== pos) {
|
|
332
|
+
value = text.substring(tokenOffset, pos);
|
|
333
|
+
switch (value) {
|
|
334
|
+
case "true":
|
|
335
|
+
return token = 8;
|
|
336
|
+
case "false":
|
|
337
|
+
return token = 9;
|
|
338
|
+
case "null":
|
|
339
|
+
return token = 7;
|
|
340
|
+
}
|
|
341
|
+
return token = 16;
|
|
342
|
+
}
|
|
343
|
+
value += String.fromCharCode(code);
|
|
344
|
+
pos++;
|
|
345
|
+
return token = 16;
|
|
458
346
|
}
|
|
459
347
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
let touchedValidEntry = false;
|
|
464
|
-
if (isValidTokenThreshold(projectValue.default)) {
|
|
465
|
-
touchedValidEntry = true;
|
|
466
|
-
if (baseTokens.defaultValue === undefined) {
|
|
467
|
-
warnings.push(makeProjectThresholdWarning("execute_threshold_tokens.default", TOKEN_THRESHOLD_INTRODUCTION_REASON));
|
|
468
|
-
} else if (projectValue.default > baseTokens.defaultValue) {
|
|
469
|
-
constrained.defaultValue = projectValue.default;
|
|
470
|
-
} else {
|
|
471
|
-
warnings.push(makeProjectThresholdWarning("execute_threshold_tokens.default", TOKEN_THRESHOLD_REASON));
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
for (const [modelKey, rawValue] of Object.entries(projectValue)) {
|
|
475
|
-
if (modelKey === "default")
|
|
476
|
-
continue;
|
|
477
|
-
if (!isValidTokenThreshold(rawValue))
|
|
478
|
-
continue;
|
|
479
|
-
touchedValidEntry = true;
|
|
480
|
-
const baseValue = baseTokens.overrides.get(modelKey) ?? baseTokens.defaultValue;
|
|
481
|
-
if (baseValue === undefined) {
|
|
482
|
-
warnings.push(makeProjectThresholdWarning(`execute_threshold_tokens.${modelKey}`, TOKEN_THRESHOLD_INTRODUCTION_REASON));
|
|
483
|
-
continue;
|
|
484
|
-
}
|
|
485
|
-
if (rawValue > baseValue) {
|
|
486
|
-
if (rawValue === constrained.defaultValue) {
|
|
487
|
-
constrained.overrides.delete(modelKey);
|
|
488
|
-
} else {
|
|
489
|
-
constrained.overrides.set(modelKey, rawValue);
|
|
490
|
-
}
|
|
491
|
-
} else {
|
|
492
|
-
warnings.push(makeProjectThresholdWarning(`execute_threshold_tokens.${modelKey}`, TOKEN_THRESHOLD_REASON));
|
|
493
|
-
}
|
|
348
|
+
function isUnknownContentCharacter(code) {
|
|
349
|
+
if (isWhiteSpace(code) || isLineBreak(code)) {
|
|
350
|
+
return false;
|
|
494
351
|
}
|
|
495
|
-
|
|
496
|
-
|
|
352
|
+
switch (code) {
|
|
353
|
+
case 125:
|
|
354
|
+
case 93:
|
|
355
|
+
case 123:
|
|
356
|
+
case 91:
|
|
357
|
+
case 34:
|
|
358
|
+
case 58:
|
|
359
|
+
case 44:
|
|
360
|
+
case 47:
|
|
361
|
+
return false;
|
|
497
362
|
}
|
|
498
|
-
|
|
499
|
-
if ("protected_tokens" in args.projectRaw) {
|
|
500
|
-
const rawProject = args.projectRaw.protected_tokens;
|
|
501
|
-
const projectVal = resolveProtectedTokensScalar(rawProject);
|
|
502
|
-
const trustedUserVal = resolveProtectedTokensScalar(args.trustedBaseConfig.protected_tokens);
|
|
503
|
-
if (projectVal !== undefined) {
|
|
504
|
-
if (trustedUserVal !== undefined) {
|
|
505
|
-
if (projectVal >= trustedUserVal) {
|
|
506
|
-
args.mergedRaw.protected_tokens = projectVal;
|
|
507
|
-
} else {
|
|
508
|
-
args.mergedRaw.protected_tokens = trustedUserVal;
|
|
509
|
-
warnings.push(makeProjectThresholdWarning("protected_tokens", PROTECTED_TOKENS_REASON));
|
|
510
|
-
}
|
|
511
|
-
} else {
|
|
512
|
-
args.mergedRaw.protected_tokens = projectVal;
|
|
513
|
-
}
|
|
514
|
-
} else {
|
|
515
|
-
if (trustedUserVal !== undefined) {
|
|
516
|
-
args.mergedRaw.protected_tokens = trustedUserVal;
|
|
517
|
-
} else {
|
|
518
|
-
delete args.mergedRaw.protected_tokens;
|
|
519
|
-
}
|
|
520
|
-
warnings.push(makeProjectThresholdWarning("protected_tokens", PROTECTED_TOKENS_REASON));
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
return warnings;
|
|
524
|
-
}
|
|
525
|
-
function normalizeEndpoint(value) {
|
|
526
|
-
if (typeof value !== "string")
|
|
527
|
-
return;
|
|
528
|
-
const trimmed = value.trim().replace(/\/+$/, "");
|
|
529
|
-
return trimmed.length > 0 ? trimmed.toLowerCase() : undefined;
|
|
530
|
-
}
|
|
531
|
-
function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
|
|
532
|
-
const projectEmbedding = projectRaw.embedding;
|
|
533
|
-
if (!isPlainObject(projectEmbedding))
|
|
534
|
-
return [];
|
|
535
|
-
const redirectsEndpoint = "endpoint" in projectEmbedding;
|
|
536
|
-
if (!redirectsEndpoint)
|
|
537
|
-
return [];
|
|
538
|
-
const userEmbedding = userRaw?.embedding;
|
|
539
|
-
if (isPlainObject(userEmbedding)) {
|
|
540
|
-
const projectEndpoint = normalizeEndpoint(projectEmbedding.endpoint);
|
|
541
|
-
const userEndpoint = normalizeEndpoint(userEmbedding.endpoint);
|
|
542
|
-
if (projectEndpoint !== undefined && projectEndpoint === userEndpoint) {
|
|
543
|
-
return [];
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
const providesOwnKey = typeof projectEmbedding.api_key === "string" && projectEmbedding.api_key.length > 0;
|
|
547
|
-
if (providesOwnKey)
|
|
548
|
-
return [];
|
|
549
|
-
const mergedEmbedding = mergedRaw.embedding;
|
|
550
|
-
if (!isPlainObject(mergedEmbedding))
|
|
551
|
-
return [];
|
|
552
|
-
if (!("api_key" in mergedEmbedding))
|
|
553
|
-
return [];
|
|
554
|
-
delete mergedEmbedding.api_key;
|
|
555
|
-
return [
|
|
556
|
-
"Dropped inherited user embedding api_key because project config redirected " + "embedding.endpoint without supplying its own key (security: prevents key " + "exfiltration to a repository-chosen endpoint)."
|
|
557
|
-
];
|
|
558
|
-
}
|
|
559
|
-
function projectContributionPath(projectRaw, issuePath) {
|
|
560
|
-
let node = projectRaw;
|
|
561
|
-
for (let index = 0;index < issuePath.length; index++) {
|
|
562
|
-
const segment = String(issuePath[index]);
|
|
563
|
-
if (!isPlainObject(node) || !Object.hasOwn(node, segment))
|
|
564
|
-
return;
|
|
565
|
-
node = node[segment];
|
|
566
|
-
if (index === issuePath.length - 1 || !isPlainObject(node)) {
|
|
567
|
-
return issuePath.slice(0, index + 1);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
function displacedTrustedValue(trustedRaw, contribution) {
|
|
573
|
-
let node = trustedRaw;
|
|
574
|
-
for (let index = 0;index < contribution.length; index++) {
|
|
575
|
-
const segment = String(contribution[index]);
|
|
576
|
-
if (!isPlainObject(node) || !Object.hasOwn(node, segment))
|
|
577
|
-
return;
|
|
578
|
-
node = node[segment];
|
|
579
|
-
if (index === contribution.length - 1 || !isPlainObject(node)) {
|
|
580
|
-
return { path: contribution.slice(0, index + 1), value: node };
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
return;
|
|
584
|
-
}
|
|
585
|
-
function defineOwnValue(target, key, value) {
|
|
586
|
-
Object.defineProperty(target, key, {
|
|
587
|
-
value,
|
|
588
|
-
enumerable: true,
|
|
589
|
-
configurable: true,
|
|
590
|
-
writable: true
|
|
591
|
-
});
|
|
592
|
-
}
|
|
593
|
-
function writeOwnPath(root, path, value) {
|
|
594
|
-
let node = root;
|
|
595
|
-
for (let index = 0;index < path.length - 1; index++) {
|
|
596
|
-
const segment = String(path[index]);
|
|
597
|
-
const child = node[segment];
|
|
598
|
-
if (!isPlainObject(child))
|
|
599
|
-
return;
|
|
600
|
-
const copy = { ...child };
|
|
601
|
-
defineOwnValue(node, segment, copy);
|
|
602
|
-
node = copy;
|
|
603
|
-
}
|
|
604
|
-
defineOwnValue(node, String(path[path.length - 1]), value);
|
|
605
|
-
}
|
|
606
|
-
var MAX_PROJECT_RESTORE_ROUNDS = 16;
|
|
607
|
-
function restoreTrustedValuesOverInvalidProjectValues(args) {
|
|
608
|
-
const warnings = [];
|
|
609
|
-
const restoredTopLevelKeys = new Set;
|
|
610
|
-
const restored = new Set;
|
|
611
|
-
for (let round = 0;round < MAX_PROJECT_RESTORE_ROUNDS; round++) {
|
|
612
|
-
let changed = false;
|
|
613
|
-
for (const issuePath of args.collectIssuePaths(args.mergedRaw)) {
|
|
614
|
-
const contribution = projectContributionPath(args.projectRaw, issuePath);
|
|
615
|
-
if (contribution === undefined || contribution.length === 0)
|
|
616
|
-
continue;
|
|
617
|
-
const trusted = displacedTrustedValue(args.trustedRaw, contribution);
|
|
618
|
-
if (trusted === undefined)
|
|
619
|
-
continue;
|
|
620
|
-
const key = trusted.path.map(String).join(".");
|
|
621
|
-
if (restored.has(key))
|
|
622
|
-
continue;
|
|
623
|
-
writeOwnPath(args.mergedRaw, trusted.path, trusted.value);
|
|
624
|
-
restored.add(key);
|
|
625
|
-
restoredTopLevelKeys.add(String(trusted.path[0]));
|
|
626
|
-
changed = true;
|
|
627
|
-
warnings.push(`Ignoring invalid ${key} from project config and keeping the user-level value (security: a repository cannot reset user settings by supplying an invalid value).`);
|
|
628
|
-
}
|
|
629
|
-
if (!changed)
|
|
630
|
-
break;
|
|
631
|
-
}
|
|
632
|
-
return { warnings, restoredTopLevelKeys: [...restoredTopLevelKeys] };
|
|
633
|
-
}
|
|
634
|
-
var PROJECT_COMMAND_STRING_FIELDS = ["description", "agent", "model"];
|
|
635
|
-
function wellFormedCommand(value) {
|
|
636
|
-
if (!isPlainObject(value))
|
|
637
|
-
return;
|
|
638
|
-
if (typeof value.template !== "string" || value.template.trim().length === 0)
|
|
639
|
-
return;
|
|
640
|
-
const command = { template: value.template };
|
|
641
|
-
for (const field of PROJECT_COMMAND_STRING_FIELDS) {
|
|
642
|
-
if (value[field] === undefined)
|
|
643
|
-
continue;
|
|
644
|
-
if (typeof value[field] !== "string")
|
|
645
|
-
return;
|
|
646
|
-
command[field] = value[field];
|
|
647
|
-
}
|
|
648
|
-
if (value.subtask !== undefined) {
|
|
649
|
-
if (typeof value.subtask !== "boolean")
|
|
650
|
-
return;
|
|
651
|
-
command.subtask = value.subtask;
|
|
652
|
-
}
|
|
653
|
-
return command;
|
|
654
|
-
}
|
|
655
|
-
function constrainProjectCommands(args) {
|
|
656
|
-
if (!("command" in args.projectRaw))
|
|
657
|
-
return [];
|
|
658
|
-
const warnings = [];
|
|
659
|
-
const trustedCommands = isPlainObject(args.trustedRaw.command) ? args.trustedRaw.command : undefined;
|
|
660
|
-
const merged = { ...trustedCommands ?? {} };
|
|
661
|
-
const projectCommands = args.projectRaw.command;
|
|
662
|
-
if (!isPlainObject(projectCommands)) {
|
|
663
|
-
warnings.push("Ignoring command from project config (it must be an object of named commands).");
|
|
664
|
-
} else {
|
|
665
|
-
for (const [name, value] of Object.entries(projectCommands)) {
|
|
666
|
-
if (trustedCommands && Object.hasOwn(trustedCommands, name)) {
|
|
667
|
-
warnings.push(`Ignoring command.${name} from project config (security: a repository cannot replace a command defined in user config).`);
|
|
668
|
-
continue;
|
|
669
|
-
}
|
|
670
|
-
if (args.reservedNames.includes(name)) {
|
|
671
|
-
warnings.push(`Ignoring command.${name} from project config (security: a repository cannot replace a built-in Magic Context command).`);
|
|
672
|
-
continue;
|
|
673
|
-
}
|
|
674
|
-
const command = wellFormedCommand(value);
|
|
675
|
-
if (!command) {
|
|
676
|
-
warnings.push(`Ignoring command.${name} from project config (it needs a non-empty string template; description, agent and model must be strings and subtask a boolean).`);
|
|
677
|
-
continue;
|
|
678
|
-
}
|
|
679
|
-
Object.defineProperty(merged, name, {
|
|
680
|
-
value: command,
|
|
681
|
-
enumerable: true,
|
|
682
|
-
configurable: true,
|
|
683
|
-
writable: true
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
if (Object.keys(merged).length === 0)
|
|
688
|
-
delete args.mergedRaw.command;
|
|
689
|
-
else
|
|
690
|
-
args.mergedRaw.command = merged;
|
|
691
|
-
return warnings;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
// src/config/index.ts
|
|
695
|
-
import { existsSync as existsSync4 } from "node:fs";
|
|
696
|
-
|
|
697
|
-
// src/shared/builtin-commands.ts
|
|
698
|
-
var COMPACTION_ENABLED_PATH2 = `compaction${".enabled"}`;
|
|
699
|
-
function getMagicContextBuiltinCommands(compactionEnabled = true) {
|
|
700
|
-
const unavailableInCompactionOff = (command) => `Unavailable when ${COMPACTION_ENABLED_PATH2} is false: /${command} manages compacted history.`;
|
|
701
|
-
return {
|
|
702
|
-
"ctx-status": {
|
|
703
|
-
template: "ctx-status",
|
|
704
|
-
description: "Show magic context status, pending queue, cache TTL, and debug info"
|
|
705
|
-
},
|
|
706
|
-
"ctx-recomp": {
|
|
707
|
-
template: "ctx-recomp",
|
|
708
|
-
description: compactionEnabled ? "Rebuild compressed history from raw history (full or <start>-<end> range); memories are not changed" : unavailableInCompactionOff("ctx-recomp")
|
|
709
|
-
},
|
|
710
|
-
"ctx-wrapup": {
|
|
711
|
-
template: "ctx-wrapup",
|
|
712
|
-
description: compactionEnabled ? "Compact older live history while keeping the newest messages raw" : unavailableInCompactionOff("ctx-wrapup")
|
|
713
|
-
},
|
|
714
|
-
"ctx-flush": {
|
|
715
|
-
template: "ctx-flush",
|
|
716
|
-
description: compactionEnabled ? "Force-process all pending magic context operations immediately" : unavailableInCompactionOff("ctx-flush")
|
|
717
|
-
},
|
|
718
|
-
"ctx-dream": {
|
|
719
|
-
template: "ctx-dream",
|
|
720
|
-
description: "Run the hidden dreamer maintenance pass for this project now"
|
|
721
|
-
},
|
|
722
|
-
"ctx-embed": {
|
|
723
|
-
template: "ctx-embed",
|
|
724
|
-
description: "Embedding status, or start/pause history compartment embedding (start | pause)"
|
|
725
|
-
}
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
// src/shared/config-diagnostics.ts
|
|
730
|
-
var CONFIG_WARNING_CLASS = {
|
|
731
|
-
FILE_PARSE: "file-parse",
|
|
732
|
-
FILE_IO: "file-io",
|
|
733
|
-
INVALID_LEAF: "invalid-leaf"
|
|
734
|
-
};
|
|
735
|
-
var claimedFailures = new Set;
|
|
736
|
-
|
|
737
|
-
// src/shared/jsonc-parser.ts
|
|
738
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
739
|
-
|
|
740
|
-
// ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
741
|
-
function createScanner(text, ignoreTrivia = false) {
|
|
742
|
-
const len = text.length;
|
|
743
|
-
let pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
|
|
744
|
-
function scanHexDigits(count, exact) {
|
|
745
|
-
let digits = 0;
|
|
746
|
-
let value = 0;
|
|
747
|
-
while (digits < count || !exact) {
|
|
748
|
-
let ch = text.charCodeAt(pos);
|
|
749
|
-
if (ch >= 48 && ch <= 57) {
|
|
750
|
-
value = value * 16 + ch - 48;
|
|
751
|
-
} else if (ch >= 65 && ch <= 70) {
|
|
752
|
-
value = value * 16 + ch - 65 + 10;
|
|
753
|
-
} else if (ch >= 97 && ch <= 102) {
|
|
754
|
-
value = value * 16 + ch - 97 + 10;
|
|
755
|
-
} else {
|
|
756
|
-
break;
|
|
757
|
-
}
|
|
758
|
-
pos++;
|
|
759
|
-
digits++;
|
|
760
|
-
}
|
|
761
|
-
if (digits < count) {
|
|
762
|
-
value = -1;
|
|
763
|
-
}
|
|
764
|
-
return value;
|
|
765
|
-
}
|
|
766
|
-
function setPosition(newPosition) {
|
|
767
|
-
pos = newPosition;
|
|
768
|
-
value = "";
|
|
769
|
-
tokenOffset = 0;
|
|
770
|
-
token = 16;
|
|
771
|
-
scanError = 0;
|
|
772
|
-
}
|
|
773
|
-
function scanNumber() {
|
|
774
|
-
let start = pos;
|
|
775
|
-
if (text.charCodeAt(pos) === 48) {
|
|
776
|
-
pos++;
|
|
777
|
-
} else {
|
|
778
|
-
pos++;
|
|
779
|
-
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
780
|
-
pos++;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
if (pos < text.length && text.charCodeAt(pos) === 46) {
|
|
784
|
-
pos++;
|
|
785
|
-
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
786
|
-
pos++;
|
|
787
|
-
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
788
|
-
pos++;
|
|
789
|
-
}
|
|
790
|
-
} else {
|
|
791
|
-
scanError = 3;
|
|
792
|
-
return text.substring(start, pos);
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
let end = pos;
|
|
796
|
-
if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
|
|
797
|
-
pos++;
|
|
798
|
-
if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
|
|
799
|
-
pos++;
|
|
800
|
-
}
|
|
801
|
-
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
802
|
-
pos++;
|
|
803
|
-
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
804
|
-
pos++;
|
|
805
|
-
}
|
|
806
|
-
end = pos;
|
|
807
|
-
} else {
|
|
808
|
-
scanError = 3;
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
return text.substring(start, end);
|
|
812
|
-
}
|
|
813
|
-
function scanString() {
|
|
814
|
-
let result = "", start = pos;
|
|
815
|
-
while (true) {
|
|
816
|
-
if (pos >= len) {
|
|
817
|
-
result += text.substring(start, pos);
|
|
818
|
-
scanError = 2;
|
|
819
|
-
break;
|
|
820
|
-
}
|
|
821
|
-
const ch = text.charCodeAt(pos);
|
|
822
|
-
if (ch === 34) {
|
|
823
|
-
result += text.substring(start, pos);
|
|
824
|
-
pos++;
|
|
825
|
-
break;
|
|
826
|
-
}
|
|
827
|
-
if (ch === 92) {
|
|
828
|
-
result += text.substring(start, pos);
|
|
829
|
-
pos++;
|
|
830
|
-
if (pos >= len) {
|
|
831
|
-
scanError = 2;
|
|
832
|
-
break;
|
|
833
|
-
}
|
|
834
|
-
const ch2 = text.charCodeAt(pos++);
|
|
835
|
-
switch (ch2) {
|
|
836
|
-
case 34:
|
|
837
|
-
result += '"';
|
|
838
|
-
break;
|
|
839
|
-
case 92:
|
|
840
|
-
result += "\\";
|
|
841
|
-
break;
|
|
842
|
-
case 47:
|
|
843
|
-
result += "/";
|
|
844
|
-
break;
|
|
845
|
-
case 98:
|
|
846
|
-
result += "\b";
|
|
847
|
-
break;
|
|
848
|
-
case 102:
|
|
849
|
-
result += "\f";
|
|
850
|
-
break;
|
|
851
|
-
case 110:
|
|
852
|
-
result += `
|
|
853
|
-
`;
|
|
854
|
-
break;
|
|
855
|
-
case 114:
|
|
856
|
-
result += "\r";
|
|
857
|
-
break;
|
|
858
|
-
case 116:
|
|
859
|
-
result += "\t";
|
|
860
|
-
break;
|
|
861
|
-
case 117:
|
|
862
|
-
const ch3 = scanHexDigits(4, true);
|
|
863
|
-
if (ch3 >= 0) {
|
|
864
|
-
result += String.fromCharCode(ch3);
|
|
865
|
-
} else {
|
|
866
|
-
scanError = 4;
|
|
867
|
-
}
|
|
868
|
-
break;
|
|
869
|
-
default:
|
|
870
|
-
scanError = 5;
|
|
871
|
-
}
|
|
872
|
-
start = pos;
|
|
873
|
-
continue;
|
|
874
|
-
}
|
|
875
|
-
if (ch >= 0 && ch <= 31) {
|
|
876
|
-
if (isLineBreak(ch)) {
|
|
877
|
-
result += text.substring(start, pos);
|
|
878
|
-
scanError = 2;
|
|
879
|
-
break;
|
|
880
|
-
} else {
|
|
881
|
-
scanError = 6;
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
pos++;
|
|
885
|
-
}
|
|
886
|
-
return result;
|
|
887
|
-
}
|
|
888
|
-
function scanNext() {
|
|
889
|
-
value = "";
|
|
890
|
-
scanError = 0;
|
|
891
|
-
tokenOffset = pos;
|
|
892
|
-
lineStartOffset = lineNumber;
|
|
893
|
-
prevTokenLineStartOffset = tokenLineStartOffset;
|
|
894
|
-
if (pos >= len) {
|
|
895
|
-
tokenOffset = len;
|
|
896
|
-
return token = 17;
|
|
897
|
-
}
|
|
898
|
-
let code = text.charCodeAt(pos);
|
|
899
|
-
if (isWhiteSpace(code)) {
|
|
900
|
-
do {
|
|
901
|
-
pos++;
|
|
902
|
-
value += String.fromCharCode(code);
|
|
903
|
-
code = text.charCodeAt(pos);
|
|
904
|
-
} while (isWhiteSpace(code));
|
|
905
|
-
return token = 15;
|
|
906
|
-
}
|
|
907
|
-
if (isLineBreak(code)) {
|
|
908
|
-
pos++;
|
|
909
|
-
value += String.fromCharCode(code);
|
|
910
|
-
if (code === 13 && text.charCodeAt(pos) === 10) {
|
|
911
|
-
pos++;
|
|
912
|
-
value += `
|
|
913
|
-
`;
|
|
914
|
-
}
|
|
915
|
-
lineNumber++;
|
|
916
|
-
tokenLineStartOffset = pos;
|
|
917
|
-
return token = 14;
|
|
918
|
-
}
|
|
919
|
-
switch (code) {
|
|
920
|
-
case 123:
|
|
921
|
-
pos++;
|
|
922
|
-
return token = 1;
|
|
923
|
-
case 125:
|
|
924
|
-
pos++;
|
|
925
|
-
return token = 2;
|
|
926
|
-
case 91:
|
|
927
|
-
pos++;
|
|
928
|
-
return token = 3;
|
|
929
|
-
case 93:
|
|
930
|
-
pos++;
|
|
931
|
-
return token = 4;
|
|
932
|
-
case 58:
|
|
933
|
-
pos++;
|
|
934
|
-
return token = 6;
|
|
935
|
-
case 44:
|
|
936
|
-
pos++;
|
|
937
|
-
return token = 5;
|
|
938
|
-
case 34:
|
|
939
|
-
pos++;
|
|
940
|
-
value = scanString();
|
|
941
|
-
return token = 10;
|
|
942
|
-
case 47:
|
|
943
|
-
const start = pos - 1;
|
|
944
|
-
if (text.charCodeAt(pos + 1) === 47) {
|
|
945
|
-
pos += 2;
|
|
946
|
-
while (pos < len) {
|
|
947
|
-
if (isLineBreak(text.charCodeAt(pos))) {
|
|
948
|
-
break;
|
|
949
|
-
}
|
|
950
|
-
pos++;
|
|
951
|
-
}
|
|
952
|
-
value = text.substring(start, pos);
|
|
953
|
-
return token = 12;
|
|
954
|
-
}
|
|
955
|
-
if (text.charCodeAt(pos + 1) === 42) {
|
|
956
|
-
pos += 2;
|
|
957
|
-
const safeLength = len - 1;
|
|
958
|
-
let commentClosed = false;
|
|
959
|
-
while (pos < safeLength) {
|
|
960
|
-
const ch = text.charCodeAt(pos);
|
|
961
|
-
if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
|
|
962
|
-
pos += 2;
|
|
963
|
-
commentClosed = true;
|
|
964
|
-
break;
|
|
965
|
-
}
|
|
966
|
-
pos++;
|
|
967
|
-
if (isLineBreak(ch)) {
|
|
968
|
-
if (ch === 13 && text.charCodeAt(pos) === 10) {
|
|
969
|
-
pos++;
|
|
970
|
-
}
|
|
971
|
-
lineNumber++;
|
|
972
|
-
tokenLineStartOffset = pos;
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
if (!commentClosed) {
|
|
976
|
-
pos++;
|
|
977
|
-
scanError = 1;
|
|
978
|
-
}
|
|
979
|
-
value = text.substring(start, pos);
|
|
980
|
-
return token = 13;
|
|
981
|
-
}
|
|
982
|
-
value += String.fromCharCode(code);
|
|
983
|
-
pos++;
|
|
984
|
-
return token = 16;
|
|
985
|
-
case 45:
|
|
986
|
-
value += String.fromCharCode(code);
|
|
987
|
-
pos++;
|
|
988
|
-
if (pos === len || !isDigit(text.charCodeAt(pos))) {
|
|
989
|
-
return token = 16;
|
|
990
|
-
}
|
|
991
|
-
case 48:
|
|
992
|
-
case 49:
|
|
993
|
-
case 50:
|
|
994
|
-
case 51:
|
|
995
|
-
case 52:
|
|
996
|
-
case 53:
|
|
997
|
-
case 54:
|
|
998
|
-
case 55:
|
|
999
|
-
case 56:
|
|
1000
|
-
case 57:
|
|
1001
|
-
value += scanNumber();
|
|
1002
|
-
return token = 11;
|
|
1003
|
-
default:
|
|
1004
|
-
while (pos < len && isUnknownContentCharacter(code)) {
|
|
1005
|
-
pos++;
|
|
1006
|
-
code = text.charCodeAt(pos);
|
|
1007
|
-
}
|
|
1008
|
-
if (tokenOffset !== pos) {
|
|
1009
|
-
value = text.substring(tokenOffset, pos);
|
|
1010
|
-
switch (value) {
|
|
1011
|
-
case "true":
|
|
1012
|
-
return token = 8;
|
|
1013
|
-
case "false":
|
|
1014
|
-
return token = 9;
|
|
1015
|
-
case "null":
|
|
1016
|
-
return token = 7;
|
|
1017
|
-
}
|
|
1018
|
-
return token = 16;
|
|
1019
|
-
}
|
|
1020
|
-
value += String.fromCharCode(code);
|
|
1021
|
-
pos++;
|
|
1022
|
-
return token = 16;
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
function isUnknownContentCharacter(code) {
|
|
1026
|
-
if (isWhiteSpace(code) || isLineBreak(code)) {
|
|
1027
|
-
return false;
|
|
1028
|
-
}
|
|
1029
|
-
switch (code) {
|
|
1030
|
-
case 125:
|
|
1031
|
-
case 93:
|
|
1032
|
-
case 123:
|
|
1033
|
-
case 91:
|
|
1034
|
-
case 34:
|
|
1035
|
-
case 58:
|
|
1036
|
-
case 44:
|
|
1037
|
-
case 47:
|
|
1038
|
-
return false;
|
|
1039
|
-
}
|
|
1040
|
-
return true;
|
|
363
|
+
return true;
|
|
1041
364
|
}
|
|
1042
365
|
function scanNextNonTrivia() {
|
|
1043
366
|
let result;
|
|
@@ -1673,1186 +996,1846 @@ function visit(text, visitor, options = ParseOptions.DEFAULT) {
|
|
|
1673
996
|
}
|
|
1674
997
|
}
|
|
1675
998
|
}
|
|
1676
|
-
function handleError(error, skipUntilAfter = [], skipUntil = []) {
|
|
1677
|
-
onError(error);
|
|
1678
|
-
if (skipUntilAfter.length + skipUntil.length > 0) {
|
|
1679
|
-
let token = _scanner.getToken();
|
|
1680
|
-
while (token !== 17) {
|
|
1681
|
-
if (skipUntilAfter.indexOf(token) !== -1) {
|
|
1682
|
-
scanNext();
|
|
1683
|
-
break;
|
|
1684
|
-
} else if (skipUntil.indexOf(token) !== -1) {
|
|
1685
|
-
break;
|
|
999
|
+
function handleError(error, skipUntilAfter = [], skipUntil = []) {
|
|
1000
|
+
onError(error);
|
|
1001
|
+
if (skipUntilAfter.length + skipUntil.length > 0) {
|
|
1002
|
+
let token = _scanner.getToken();
|
|
1003
|
+
while (token !== 17) {
|
|
1004
|
+
if (skipUntilAfter.indexOf(token) !== -1) {
|
|
1005
|
+
scanNext();
|
|
1006
|
+
break;
|
|
1007
|
+
} else if (skipUntil.indexOf(token) !== -1) {
|
|
1008
|
+
break;
|
|
1009
|
+
}
|
|
1010
|
+
token = scanNext();
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
function parseString(isValue) {
|
|
1015
|
+
const value = _scanner.getTokenValue();
|
|
1016
|
+
if (isValue) {
|
|
1017
|
+
onLiteralValue(value);
|
|
1018
|
+
} else {
|
|
1019
|
+
onObjectProperty(value);
|
|
1020
|
+
_jsonPath.push(value);
|
|
1021
|
+
}
|
|
1022
|
+
scanNext();
|
|
1023
|
+
return true;
|
|
1024
|
+
}
|
|
1025
|
+
function parseLiteral() {
|
|
1026
|
+
switch (_scanner.getToken()) {
|
|
1027
|
+
case 11:
|
|
1028
|
+
const tokenValue = _scanner.getTokenValue();
|
|
1029
|
+
let value = Number(tokenValue);
|
|
1030
|
+
if (isNaN(value)) {
|
|
1031
|
+
handleError(2);
|
|
1032
|
+
value = 0;
|
|
1033
|
+
}
|
|
1034
|
+
onLiteralValue(value);
|
|
1035
|
+
break;
|
|
1036
|
+
case 7:
|
|
1037
|
+
onLiteralValue(null);
|
|
1038
|
+
break;
|
|
1039
|
+
case 8:
|
|
1040
|
+
onLiteralValue(true);
|
|
1041
|
+
break;
|
|
1042
|
+
case 9:
|
|
1043
|
+
onLiteralValue(false);
|
|
1044
|
+
break;
|
|
1045
|
+
default:
|
|
1046
|
+
return false;
|
|
1047
|
+
}
|
|
1048
|
+
scanNext();
|
|
1049
|
+
return true;
|
|
1050
|
+
}
|
|
1051
|
+
function parseProperty() {
|
|
1052
|
+
if (_scanner.getToken() !== 10) {
|
|
1053
|
+
handleError(3, [], [2, 5]);
|
|
1054
|
+
return false;
|
|
1055
|
+
}
|
|
1056
|
+
parseString(false);
|
|
1057
|
+
if (_scanner.getToken() === 6) {
|
|
1058
|
+
onSeparator(":");
|
|
1059
|
+
scanNext();
|
|
1060
|
+
if (!parseValue()) {
|
|
1061
|
+
handleError(4, [], [2, 5]);
|
|
1062
|
+
}
|
|
1063
|
+
} else {
|
|
1064
|
+
handleError(5, [], [2, 5]);
|
|
1065
|
+
}
|
|
1066
|
+
_jsonPath.pop();
|
|
1067
|
+
return true;
|
|
1068
|
+
}
|
|
1069
|
+
function parseObject() {
|
|
1070
|
+
onObjectBegin();
|
|
1071
|
+
scanNext();
|
|
1072
|
+
let needsComma = false;
|
|
1073
|
+
while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
|
|
1074
|
+
if (_scanner.getToken() === 5) {
|
|
1075
|
+
if (!needsComma) {
|
|
1076
|
+
handleError(4, [], []);
|
|
1077
|
+
}
|
|
1078
|
+
onSeparator(",");
|
|
1079
|
+
scanNext();
|
|
1080
|
+
if (_scanner.getToken() === 2 && allowTrailingComma) {
|
|
1081
|
+
break;
|
|
1082
|
+
}
|
|
1083
|
+
} else if (needsComma) {
|
|
1084
|
+
handleError(6, [], []);
|
|
1085
|
+
}
|
|
1086
|
+
if (!parseProperty()) {
|
|
1087
|
+
handleError(4, [], [2, 5]);
|
|
1088
|
+
}
|
|
1089
|
+
needsComma = true;
|
|
1090
|
+
}
|
|
1091
|
+
onObjectEnd();
|
|
1092
|
+
if (_scanner.getToken() !== 2) {
|
|
1093
|
+
handleError(7, [2], []);
|
|
1094
|
+
} else {
|
|
1095
|
+
scanNext();
|
|
1096
|
+
}
|
|
1097
|
+
return true;
|
|
1098
|
+
}
|
|
1099
|
+
function parseArray() {
|
|
1100
|
+
onArrayBegin();
|
|
1101
|
+
scanNext();
|
|
1102
|
+
let isFirstElement = true;
|
|
1103
|
+
let needsComma = false;
|
|
1104
|
+
while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
|
|
1105
|
+
if (_scanner.getToken() === 5) {
|
|
1106
|
+
if (!needsComma) {
|
|
1107
|
+
handleError(4, [], []);
|
|
1108
|
+
}
|
|
1109
|
+
onSeparator(",");
|
|
1110
|
+
scanNext();
|
|
1111
|
+
if (_scanner.getToken() === 4 && allowTrailingComma) {
|
|
1112
|
+
break;
|
|
1113
|
+
}
|
|
1114
|
+
} else if (needsComma) {
|
|
1115
|
+
handleError(6, [], []);
|
|
1116
|
+
}
|
|
1117
|
+
if (isFirstElement) {
|
|
1118
|
+
_jsonPath.push(0);
|
|
1119
|
+
isFirstElement = false;
|
|
1120
|
+
} else {
|
|
1121
|
+
_jsonPath[_jsonPath.length - 1]++;
|
|
1122
|
+
}
|
|
1123
|
+
if (!parseValue()) {
|
|
1124
|
+
handleError(4, [], [4, 5]);
|
|
1125
|
+
}
|
|
1126
|
+
needsComma = true;
|
|
1127
|
+
}
|
|
1128
|
+
onArrayEnd();
|
|
1129
|
+
if (!isFirstElement) {
|
|
1130
|
+
_jsonPath.pop();
|
|
1131
|
+
}
|
|
1132
|
+
if (_scanner.getToken() !== 4) {
|
|
1133
|
+
handleError(8, [4], []);
|
|
1134
|
+
} else {
|
|
1135
|
+
scanNext();
|
|
1136
|
+
}
|
|
1137
|
+
return true;
|
|
1138
|
+
}
|
|
1139
|
+
function parseValue() {
|
|
1140
|
+
switch (_scanner.getToken()) {
|
|
1141
|
+
case 3:
|
|
1142
|
+
return parseArray();
|
|
1143
|
+
case 1:
|
|
1144
|
+
return parseObject();
|
|
1145
|
+
case 10:
|
|
1146
|
+
return parseString(true);
|
|
1147
|
+
default:
|
|
1148
|
+
return parseLiteral();
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
scanNext();
|
|
1152
|
+
if (_scanner.getToken() === 17) {
|
|
1153
|
+
if (options.allowEmptyContent) {
|
|
1154
|
+
return true;
|
|
1155
|
+
}
|
|
1156
|
+
handleError(4, [], []);
|
|
1157
|
+
return false;
|
|
1158
|
+
}
|
|
1159
|
+
if (!parseValue()) {
|
|
1160
|
+
handleError(4, [], []);
|
|
1161
|
+
return false;
|
|
1162
|
+
}
|
|
1163
|
+
if (_scanner.getToken() !== 17) {
|
|
1164
|
+
handleError(9, [], []);
|
|
1165
|
+
}
|
|
1166
|
+
return true;
|
|
1167
|
+
}
|
|
1168
|
+
function getNodeType(value) {
|
|
1169
|
+
switch (typeof value) {
|
|
1170
|
+
case "boolean":
|
|
1171
|
+
return "boolean";
|
|
1172
|
+
case "number":
|
|
1173
|
+
return "number";
|
|
1174
|
+
case "string":
|
|
1175
|
+
return "string";
|
|
1176
|
+
case "object": {
|
|
1177
|
+
if (!value) {
|
|
1178
|
+
return "null";
|
|
1179
|
+
} else if (Array.isArray(value)) {
|
|
1180
|
+
return "array";
|
|
1181
|
+
}
|
|
1182
|
+
return "object";
|
|
1183
|
+
}
|
|
1184
|
+
default:
|
|
1185
|
+
return "null";
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/edit.js
|
|
1190
|
+
function setProperty(text, originalPath, value, options) {
|
|
1191
|
+
const path = originalPath.slice();
|
|
1192
|
+
const errors = [];
|
|
1193
|
+
const root = parseTree(text, errors);
|
|
1194
|
+
let parent = undefined;
|
|
1195
|
+
let lastSegment = undefined;
|
|
1196
|
+
while (path.length > 0) {
|
|
1197
|
+
lastSegment = path.pop();
|
|
1198
|
+
parent = findNodeAtLocation(root, path);
|
|
1199
|
+
if (parent === undefined && value !== undefined) {
|
|
1200
|
+
if (typeof lastSegment === "string") {
|
|
1201
|
+
value = { [lastSegment]: value };
|
|
1202
|
+
} else {
|
|
1203
|
+
value = [value];
|
|
1204
|
+
}
|
|
1205
|
+
} else {
|
|
1206
|
+
break;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
if (!parent) {
|
|
1210
|
+
if (value === undefined) {
|
|
1211
|
+
throw new Error("Can not delete in empty document");
|
|
1212
|
+
}
|
|
1213
|
+
return withFormatting(text, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, options);
|
|
1214
|
+
} else if (parent.type === "object" && typeof lastSegment === "string" && Array.isArray(parent.children)) {
|
|
1215
|
+
const existing = findNodeAtLocation(parent, [lastSegment]);
|
|
1216
|
+
if (existing !== undefined) {
|
|
1217
|
+
if (value === undefined) {
|
|
1218
|
+
if (!existing.parent) {
|
|
1219
|
+
throw new Error("Malformed AST");
|
|
1686
1220
|
}
|
|
1687
|
-
|
|
1221
|
+
const propertyIndex = parent.children.indexOf(existing.parent);
|
|
1222
|
+
let removeBegin;
|
|
1223
|
+
let removeEnd = existing.parent.offset + existing.parent.length;
|
|
1224
|
+
if (propertyIndex > 0) {
|
|
1225
|
+
let previous = parent.children[propertyIndex - 1];
|
|
1226
|
+
removeBegin = previous.offset + previous.length;
|
|
1227
|
+
} else {
|
|
1228
|
+
removeBegin = parent.offset + 1;
|
|
1229
|
+
if (parent.children.length > 1) {
|
|
1230
|
+
let next = parent.children[1];
|
|
1231
|
+
removeEnd = next.offset;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
return withFormatting(text, { offset: removeBegin, length: removeEnd - removeBegin, content: "" }, options);
|
|
1235
|
+
} else {
|
|
1236
|
+
return withFormatting(text, { offset: existing.offset, length: existing.length, content: JSON.stringify(value) }, options);
|
|
1237
|
+
}
|
|
1238
|
+
} else {
|
|
1239
|
+
if (value === undefined) {
|
|
1240
|
+
return [];
|
|
1241
|
+
}
|
|
1242
|
+
const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`;
|
|
1243
|
+
const index = options.getInsertionIndex ? options.getInsertionIndex(parent.children.map((p) => p.children[0].value)) : parent.children.length;
|
|
1244
|
+
let edit;
|
|
1245
|
+
if (index > 0) {
|
|
1246
|
+
let previous = parent.children[index - 1];
|
|
1247
|
+
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
1248
|
+
} else if (parent.children.length === 0) {
|
|
1249
|
+
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
1250
|
+
} else {
|
|
1251
|
+
edit = { offset: parent.offset + 1, length: 0, content: newProperty + "," };
|
|
1688
1252
|
}
|
|
1253
|
+
return withFormatting(text, edit, options);
|
|
1689
1254
|
}
|
|
1690
|
-
}
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1255
|
+
} else if (parent.type === "array" && typeof lastSegment === "number" && Array.isArray(parent.children)) {
|
|
1256
|
+
const insertIndex = lastSegment;
|
|
1257
|
+
if (insertIndex === -1) {
|
|
1258
|
+
const newProperty = `${JSON.stringify(value)}`;
|
|
1259
|
+
let edit;
|
|
1260
|
+
if (parent.children.length === 0) {
|
|
1261
|
+
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
1262
|
+
} else {
|
|
1263
|
+
const previous = parent.children[parent.children.length - 1];
|
|
1264
|
+
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
1265
|
+
}
|
|
1266
|
+
return withFormatting(text, edit, options);
|
|
1267
|
+
} else if (value === undefined && parent.children.length >= 0) {
|
|
1268
|
+
const removalIndex = lastSegment;
|
|
1269
|
+
const toRemove = parent.children[removalIndex];
|
|
1270
|
+
let edit;
|
|
1271
|
+
if (parent.children.length === 1) {
|
|
1272
|
+
edit = { offset: parent.offset + 1, length: parent.length - 2, content: "" };
|
|
1273
|
+
} else if (parent.children.length - 1 === removalIndex) {
|
|
1274
|
+
let previous = parent.children[removalIndex - 1];
|
|
1275
|
+
let offset = previous.offset + previous.length;
|
|
1276
|
+
let parentEndOffset = parent.offset + parent.length;
|
|
1277
|
+
edit = { offset, length: parentEndOffset - 2 - offset, content: "" };
|
|
1278
|
+
} else {
|
|
1279
|
+
edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: "" };
|
|
1280
|
+
}
|
|
1281
|
+
return withFormatting(text, edit, options);
|
|
1282
|
+
} else if (value !== undefined) {
|
|
1283
|
+
let edit;
|
|
1284
|
+
const newProperty = `${JSON.stringify(value)}`;
|
|
1285
|
+
if (!options.isArrayInsertion && parent.children.length > lastSegment) {
|
|
1286
|
+
const toModify = parent.children[lastSegment];
|
|
1287
|
+
edit = { offset: toModify.offset, length: toModify.length, content: newProperty };
|
|
1288
|
+
} else if (parent.children.length === 0 || lastSegment === 0) {
|
|
1289
|
+
edit = { offset: parent.offset + 1, length: 0, content: parent.children.length === 0 ? newProperty : newProperty + "," };
|
|
1290
|
+
} else {
|
|
1291
|
+
const index = lastSegment > parent.children.length ? parent.children.length : lastSegment;
|
|
1292
|
+
const previous = parent.children[index - 1];
|
|
1293
|
+
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
1294
|
+
}
|
|
1295
|
+
return withFormatting(text, edit, options);
|
|
1695
1296
|
} else {
|
|
1696
|
-
|
|
1697
|
-
_jsonPath.push(value);
|
|
1297
|
+
throw new Error(`Can not ${value === undefined ? "remove" : options.isArrayInsertion ? "insert" : "modify"} Array index ${insertIndex} as length is not sufficient`);
|
|
1698
1298
|
}
|
|
1699
|
-
|
|
1700
|
-
|
|
1299
|
+
} else {
|
|
1300
|
+
throw new Error(`Can not add ${typeof lastSegment !== "number" ? "index" : "property"} to parent of type ${parent.type}`);
|
|
1701
1301
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
case 8:
|
|
1717
|
-
onLiteralValue(true);
|
|
1718
|
-
break;
|
|
1719
|
-
case 9:
|
|
1720
|
-
onLiteralValue(false);
|
|
1721
|
-
break;
|
|
1722
|
-
default:
|
|
1723
|
-
return false;
|
|
1302
|
+
}
|
|
1303
|
+
function withFormatting(text, edit, options) {
|
|
1304
|
+
if (!options.formattingOptions) {
|
|
1305
|
+
return [edit];
|
|
1306
|
+
}
|
|
1307
|
+
let newText = applyEdit(text, edit);
|
|
1308
|
+
let begin = edit.offset;
|
|
1309
|
+
let end = edit.offset + edit.content.length;
|
|
1310
|
+
if (edit.length === 0 || edit.content.length === 0) {
|
|
1311
|
+
while (begin > 0 && !isEOL(newText, begin - 1)) {
|
|
1312
|
+
begin--;
|
|
1313
|
+
}
|
|
1314
|
+
while (end < newText.length && !isEOL(newText, end)) {
|
|
1315
|
+
end++;
|
|
1724
1316
|
}
|
|
1725
|
-
scanNext();
|
|
1726
|
-
return true;
|
|
1727
1317
|
}
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1318
|
+
const edits = format(newText, { offset: begin, length: end - begin }, { ...options.formattingOptions, keepLines: false });
|
|
1319
|
+
for (let i = edits.length - 1;i >= 0; i--) {
|
|
1320
|
+
const edit = edits[i];
|
|
1321
|
+
newText = applyEdit(newText, edit);
|
|
1322
|
+
begin = Math.min(begin, edit.offset);
|
|
1323
|
+
end = Math.max(end, edit.offset + edit.length);
|
|
1324
|
+
end += edit.content.length - edit.length;
|
|
1325
|
+
}
|
|
1326
|
+
const editLength = text.length - (newText.length - end) - begin;
|
|
1327
|
+
return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }];
|
|
1328
|
+
}
|
|
1329
|
+
function applyEdit(text, edit) {
|
|
1330
|
+
return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length);
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
// ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/main.js
|
|
1334
|
+
var createScanner2 = createScanner;
|
|
1335
|
+
var ScanError;
|
|
1336
|
+
(function(ScanError) {
|
|
1337
|
+
ScanError[ScanError["None"] = 0] = "None";
|
|
1338
|
+
ScanError[ScanError["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
|
|
1339
|
+
ScanError[ScanError["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
|
|
1340
|
+
ScanError[ScanError["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
|
|
1341
|
+
ScanError[ScanError["InvalidUnicode"] = 4] = "InvalidUnicode";
|
|
1342
|
+
ScanError[ScanError["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
|
|
1343
|
+
ScanError[ScanError["InvalidCharacter"] = 6] = "InvalidCharacter";
|
|
1344
|
+
})(ScanError || (ScanError = {}));
|
|
1345
|
+
var SyntaxKind;
|
|
1346
|
+
(function(SyntaxKind) {
|
|
1347
|
+
SyntaxKind[SyntaxKind["OpenBraceToken"] = 1] = "OpenBraceToken";
|
|
1348
|
+
SyntaxKind[SyntaxKind["CloseBraceToken"] = 2] = "CloseBraceToken";
|
|
1349
|
+
SyntaxKind[SyntaxKind["OpenBracketToken"] = 3] = "OpenBracketToken";
|
|
1350
|
+
SyntaxKind[SyntaxKind["CloseBracketToken"] = 4] = "CloseBracketToken";
|
|
1351
|
+
SyntaxKind[SyntaxKind["CommaToken"] = 5] = "CommaToken";
|
|
1352
|
+
SyntaxKind[SyntaxKind["ColonToken"] = 6] = "ColonToken";
|
|
1353
|
+
SyntaxKind[SyntaxKind["NullKeyword"] = 7] = "NullKeyword";
|
|
1354
|
+
SyntaxKind[SyntaxKind["TrueKeyword"] = 8] = "TrueKeyword";
|
|
1355
|
+
SyntaxKind[SyntaxKind["FalseKeyword"] = 9] = "FalseKeyword";
|
|
1356
|
+
SyntaxKind[SyntaxKind["StringLiteral"] = 10] = "StringLiteral";
|
|
1357
|
+
SyntaxKind[SyntaxKind["NumericLiteral"] = 11] = "NumericLiteral";
|
|
1358
|
+
SyntaxKind[SyntaxKind["LineCommentTrivia"] = 12] = "LineCommentTrivia";
|
|
1359
|
+
SyntaxKind[SyntaxKind["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
|
|
1360
|
+
SyntaxKind[SyntaxKind["LineBreakTrivia"] = 14] = "LineBreakTrivia";
|
|
1361
|
+
SyntaxKind[SyntaxKind["Trivia"] = 15] = "Trivia";
|
|
1362
|
+
SyntaxKind[SyntaxKind["Unknown"] = 16] = "Unknown";
|
|
1363
|
+
SyntaxKind[SyntaxKind["EOF"] = 17] = "EOF";
|
|
1364
|
+
})(SyntaxKind || (SyntaxKind = {}));
|
|
1365
|
+
var parse2 = parse;
|
|
1366
|
+
var parseTree2 = parseTree;
|
|
1367
|
+
var findNodeAtLocation2 = findNodeAtLocation;
|
|
1368
|
+
var getNodeValue2 = getNodeValue;
|
|
1369
|
+
var ParseErrorCode;
|
|
1370
|
+
(function(ParseErrorCode) {
|
|
1371
|
+
ParseErrorCode[ParseErrorCode["InvalidSymbol"] = 1] = "InvalidSymbol";
|
|
1372
|
+
ParseErrorCode[ParseErrorCode["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
|
|
1373
|
+
ParseErrorCode[ParseErrorCode["PropertyNameExpected"] = 3] = "PropertyNameExpected";
|
|
1374
|
+
ParseErrorCode[ParseErrorCode["ValueExpected"] = 4] = "ValueExpected";
|
|
1375
|
+
ParseErrorCode[ParseErrorCode["ColonExpected"] = 5] = "ColonExpected";
|
|
1376
|
+
ParseErrorCode[ParseErrorCode["CommaExpected"] = 6] = "CommaExpected";
|
|
1377
|
+
ParseErrorCode[ParseErrorCode["CloseBraceExpected"] = 7] = "CloseBraceExpected";
|
|
1378
|
+
ParseErrorCode[ParseErrorCode["CloseBracketExpected"] = 8] = "CloseBracketExpected";
|
|
1379
|
+
ParseErrorCode[ParseErrorCode["EndOfFileExpected"] = 9] = "EndOfFileExpected";
|
|
1380
|
+
ParseErrorCode[ParseErrorCode["InvalidCommentToken"] = 10] = "InvalidCommentToken";
|
|
1381
|
+
ParseErrorCode[ParseErrorCode["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
|
|
1382
|
+
ParseErrorCode[ParseErrorCode["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
|
|
1383
|
+
ParseErrorCode[ParseErrorCode["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
|
|
1384
|
+
ParseErrorCode[ParseErrorCode["InvalidUnicode"] = 14] = "InvalidUnicode";
|
|
1385
|
+
ParseErrorCode[ParseErrorCode["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
|
|
1386
|
+
ParseErrorCode[ParseErrorCode["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
1387
|
+
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
1388
|
+
function printParseErrorCode(code) {
|
|
1389
|
+
switch (code) {
|
|
1390
|
+
case 1:
|
|
1391
|
+
return "InvalidSymbol";
|
|
1392
|
+
case 2:
|
|
1393
|
+
return "InvalidNumberFormat";
|
|
1394
|
+
case 3:
|
|
1395
|
+
return "PropertyNameExpected";
|
|
1396
|
+
case 4:
|
|
1397
|
+
return "ValueExpected";
|
|
1398
|
+
case 5:
|
|
1399
|
+
return "ColonExpected";
|
|
1400
|
+
case 6:
|
|
1401
|
+
return "CommaExpected";
|
|
1402
|
+
case 7:
|
|
1403
|
+
return "CloseBraceExpected";
|
|
1404
|
+
case 8:
|
|
1405
|
+
return "CloseBracketExpected";
|
|
1406
|
+
case 9:
|
|
1407
|
+
return "EndOfFileExpected";
|
|
1408
|
+
case 10:
|
|
1409
|
+
return "InvalidCommentToken";
|
|
1410
|
+
case 11:
|
|
1411
|
+
return "UnexpectedEndOfComment";
|
|
1412
|
+
case 12:
|
|
1413
|
+
return "UnexpectedEndOfString";
|
|
1414
|
+
case 13:
|
|
1415
|
+
return "UnexpectedEndOfNumber";
|
|
1416
|
+
case 14:
|
|
1417
|
+
return "InvalidUnicode";
|
|
1418
|
+
case 15:
|
|
1419
|
+
return "InvalidEscapeCharacter";
|
|
1420
|
+
case 16:
|
|
1421
|
+
return "InvalidCharacter";
|
|
1422
|
+
}
|
|
1423
|
+
return "<unknown ParseErrorCode>";
|
|
1424
|
+
}
|
|
1425
|
+
function modify(text, path, value, options) {
|
|
1426
|
+
return setProperty(text, path, value, options);
|
|
1427
|
+
}
|
|
1428
|
+
function applyEdits(text, edits) {
|
|
1429
|
+
let sortedEdits = edits.slice(0).sort((a, b) => {
|
|
1430
|
+
const diff = a.offset - b.offset;
|
|
1431
|
+
if (diff === 0) {
|
|
1432
|
+
return a.length - b.length;
|
|
1732
1433
|
}
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1434
|
+
return diff;
|
|
1435
|
+
});
|
|
1436
|
+
let lastModifiedOffset = text.length;
|
|
1437
|
+
for (let i = sortedEdits.length - 1;i >= 0; i--) {
|
|
1438
|
+
let e = sortedEdits[i];
|
|
1439
|
+
if (e.offset + e.length <= lastModifiedOffset) {
|
|
1440
|
+
text = applyEdit(text, e);
|
|
1740
1441
|
} else {
|
|
1741
|
-
|
|
1442
|
+
throw new Error("Overlapping edit");
|
|
1742
1443
|
}
|
|
1743
|
-
|
|
1744
|
-
return true;
|
|
1444
|
+
lastModifiedOffset = e.offset;
|
|
1745
1445
|
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1446
|
+
return text;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
// src/shared/jsonc-parser.ts
|
|
1450
|
+
function stripJsonComments(content) {
|
|
1451
|
+
let result = "";
|
|
1452
|
+
let inString = false;
|
|
1453
|
+
let escaped = false;
|
|
1454
|
+
let inLineComment = false;
|
|
1455
|
+
let inBlockComment = false;
|
|
1456
|
+
for (let index = 0;index < content.length; index += 1) {
|
|
1457
|
+
const char = content[index];
|
|
1458
|
+
const next = content[index + 1];
|
|
1459
|
+
if (inLineComment) {
|
|
1460
|
+
if (char === `
|
|
1461
|
+
`) {
|
|
1462
|
+
inLineComment = false;
|
|
1463
|
+
result += char;
|
|
1762
1464
|
}
|
|
1763
|
-
|
|
1764
|
-
|
|
1465
|
+
continue;
|
|
1466
|
+
}
|
|
1467
|
+
if (inBlockComment) {
|
|
1468
|
+
if (char === "*" && next === "/") {
|
|
1469
|
+
inBlockComment = false;
|
|
1470
|
+
index += 1;
|
|
1765
1471
|
}
|
|
1766
|
-
|
|
1472
|
+
continue;
|
|
1767
1473
|
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1474
|
+
if (inString) {
|
|
1475
|
+
result += char;
|
|
1476
|
+
if (escaped) {
|
|
1477
|
+
escaped = false;
|
|
1478
|
+
} else if (char === "\\") {
|
|
1479
|
+
escaped = true;
|
|
1480
|
+
} else if (char === '"') {
|
|
1481
|
+
inString = false;
|
|
1482
|
+
}
|
|
1483
|
+
continue;
|
|
1773
1484
|
}
|
|
1774
|
-
|
|
1485
|
+
if (char === '"') {
|
|
1486
|
+
inString = true;
|
|
1487
|
+
result += char;
|
|
1488
|
+
continue;
|
|
1489
|
+
}
|
|
1490
|
+
if (char === "/" && next === "/") {
|
|
1491
|
+
inLineComment = true;
|
|
1492
|
+
index += 1;
|
|
1493
|
+
continue;
|
|
1494
|
+
}
|
|
1495
|
+
if (char === "/" && next === "*") {
|
|
1496
|
+
inBlockComment = true;
|
|
1497
|
+
index += 1;
|
|
1498
|
+
continue;
|
|
1499
|
+
}
|
|
1500
|
+
result += char;
|
|
1775
1501
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
handleError(6, [], []);
|
|
1793
|
-
}
|
|
1794
|
-
if (isFirstElement) {
|
|
1795
|
-
_jsonPath.push(0);
|
|
1796
|
-
isFirstElement = false;
|
|
1797
|
-
} else {
|
|
1798
|
-
_jsonPath[_jsonPath.length - 1]++;
|
|
1799
|
-
}
|
|
1800
|
-
if (!parseValue()) {
|
|
1801
|
-
handleError(4, [], [4, 5]);
|
|
1502
|
+
return result;
|
|
1503
|
+
}
|
|
1504
|
+
function stripTrailingCommas(content) {
|
|
1505
|
+
let result = "";
|
|
1506
|
+
let inString = false;
|
|
1507
|
+
let escaped = false;
|
|
1508
|
+
for (let index = 0;index < content.length; index += 1) {
|
|
1509
|
+
const char = content[index];
|
|
1510
|
+
if (inString) {
|
|
1511
|
+
result += char;
|
|
1512
|
+
if (escaped) {
|
|
1513
|
+
escaped = false;
|
|
1514
|
+
} else if (char === "\\") {
|
|
1515
|
+
escaped = true;
|
|
1516
|
+
} else if (char === '"') {
|
|
1517
|
+
inString = false;
|
|
1802
1518
|
}
|
|
1803
|
-
|
|
1519
|
+
continue;
|
|
1804
1520
|
}
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1521
|
+
if (char === '"') {
|
|
1522
|
+
inString = true;
|
|
1523
|
+
result += char;
|
|
1524
|
+
continue;
|
|
1808
1525
|
}
|
|
1809
|
-
if (
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1526
|
+
if (char === ",") {
|
|
1527
|
+
let lookahead = index + 1;
|
|
1528
|
+
while (lookahead < content.length && /\s/.test(content[lookahead] ?? "")) {
|
|
1529
|
+
lookahead += 1;
|
|
1530
|
+
}
|
|
1531
|
+
const next = content[lookahead];
|
|
1532
|
+
if (next === "}" || next === "]") {
|
|
1533
|
+
continue;
|
|
1534
|
+
}
|
|
1813
1535
|
}
|
|
1814
|
-
|
|
1536
|
+
result += char;
|
|
1815
1537
|
}
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1538
|
+
return result;
|
|
1539
|
+
}
|
|
1540
|
+
var PROTOTYPE_POLLUTION_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
1541
|
+
function isPrototypePollutionKey(key) {
|
|
1542
|
+
return PROTOTYPE_POLLUTION_KEYS.has(key);
|
|
1543
|
+
}
|
|
1544
|
+
function sanitizeParsedJson(value, options = {}, path = []) {
|
|
1545
|
+
if (Array.isArray(value)) {
|
|
1546
|
+
return value.map((entry, index) => sanitizeParsedJson(entry, options, [...path, index]));
|
|
1547
|
+
}
|
|
1548
|
+
if (value === null || typeof value !== "object")
|
|
1549
|
+
return value;
|
|
1550
|
+
const source = value;
|
|
1551
|
+
const sourcePrototype = Object.getPrototypeOf(source);
|
|
1552
|
+
if (sourcePrototype !== null && sourcePrototype !== Object.prototype) {
|
|
1553
|
+
options.onRejectedKey?.([...path, "__proto__"]);
|
|
1554
|
+
}
|
|
1555
|
+
const sanitized = {};
|
|
1556
|
+
for (const key of Object.keys(source)) {
|
|
1557
|
+
if (isPrototypePollutionKey(key)) {
|
|
1558
|
+
options.onRejectedKey?.([...path, key]);
|
|
1559
|
+
continue;
|
|
1826
1560
|
}
|
|
1561
|
+
Object.defineProperty(sanitized, key, {
|
|
1562
|
+
value: sanitizeParsedJson(source[key], options, [...path, key]),
|
|
1563
|
+
enumerable: true,
|
|
1564
|
+
configurable: true,
|
|
1565
|
+
writable: true
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
return sanitized;
|
|
1569
|
+
}
|
|
1570
|
+
function lineAndColumnAt(content, offset) {
|
|
1571
|
+
const before = content.slice(0, Math.max(0, offset));
|
|
1572
|
+
const lines = before.split(/\r?\n/);
|
|
1573
|
+
return { line: lines.length, column: (lines.at(-1)?.length ?? 0) + 1 };
|
|
1574
|
+
}
|
|
1575
|
+
function parseIssue(content, error) {
|
|
1576
|
+
const location = lineAndColumnAt(content, error.offset);
|
|
1577
|
+
const code = printParseErrorCode(error.error);
|
|
1578
|
+
const message = code.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
|
|
1579
|
+
return {
|
|
1580
|
+
...location,
|
|
1581
|
+
offset: error.offset,
|
|
1582
|
+
length: error.length,
|
|
1583
|
+
message
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
function normalizeJsoncParserObjects(value, options, path = []) {
|
|
1587
|
+
if (Array.isArray(value)) {
|
|
1588
|
+
return value.map((entry, index) => normalizeJsoncParserObjects(entry, options, [...path, String(index)]));
|
|
1589
|
+
}
|
|
1590
|
+
if (value === null || typeof value !== "object")
|
|
1591
|
+
return value;
|
|
1592
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1593
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
1594
|
+
options.onRejectedKey?.([...path, "__proto__"]);
|
|
1595
|
+
}
|
|
1596
|
+
const normalized = {};
|
|
1597
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
1598
|
+
Object.defineProperty(normalized, key, {
|
|
1599
|
+
configurable: true,
|
|
1600
|
+
enumerable: true,
|
|
1601
|
+
writable: true,
|
|
1602
|
+
value: normalizeJsoncParserObjects(entry, options, [...path, key])
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
return normalized;
|
|
1606
|
+
}
|
|
1607
|
+
function parseJsoncRecovering(content, options = {}) {
|
|
1608
|
+
const errors = [];
|
|
1609
|
+
const parsed = parse2(content, errors, {
|
|
1610
|
+
allowTrailingComma: true,
|
|
1611
|
+
disallowComments: false,
|
|
1612
|
+
allowEmptyContent: false
|
|
1613
|
+
});
|
|
1614
|
+
return {
|
|
1615
|
+
value: sanitizeParsedJson(normalizeJsoncParserObjects(parsed, options), options),
|
|
1616
|
+
issues: errors.map((error) => parseIssue(content, error))
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
function parseJsonc(content, options = {}) {
|
|
1620
|
+
const normalized = stripTrailingCommas(stripJsonComments(content));
|
|
1621
|
+
return sanitizeParsedJson(JSON.parse(normalized), options);
|
|
1622
|
+
}
|
|
1623
|
+
function readJsoncFile(filePath) {
|
|
1624
|
+
try {
|
|
1625
|
+
return parseJsonc(readFileSync(filePath, "utf-8"));
|
|
1626
|
+
} catch (_error) {
|
|
1627
|
+
return null;
|
|
1827
1628
|
}
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
return false;
|
|
1629
|
+
}
|
|
1630
|
+
function detectConfigFile(basePath) {
|
|
1631
|
+
const jsoncPath = `${basePath}.jsonc`;
|
|
1632
|
+
const jsonPath = `${basePath}.json`;
|
|
1633
|
+
if (existsSync(jsoncPath)) {
|
|
1634
|
+
return { format: "jsonc", path: jsoncPath };
|
|
1835
1635
|
}
|
|
1836
|
-
if (
|
|
1837
|
-
|
|
1838
|
-
return false;
|
|
1636
|
+
if (existsSync(jsonPath)) {
|
|
1637
|
+
return { format: "json", path: jsonPath };
|
|
1839
1638
|
}
|
|
1840
|
-
|
|
1841
|
-
|
|
1639
|
+
return { format: "none", path: jsoncPath };
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
// src/config/agent-disable.ts
|
|
1643
|
+
var COMPACTION_ENABLED_PATH = `compaction${"."}enabled`;
|
|
1644
|
+
function isDreamerRunnable(config) {
|
|
1645
|
+
return !!config.dreamer && config.dreamer.disable !== true;
|
|
1646
|
+
}
|
|
1647
|
+
function isCompactionEnabled(config) {
|
|
1648
|
+
return config.compaction?.enabled !== false;
|
|
1649
|
+
}
|
|
1650
|
+
function clonePlainObject(value) {
|
|
1651
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1652
|
+
return;
|
|
1842
1653
|
}
|
|
1843
|
-
return
|
|
1654
|
+
return { ...value };
|
|
1844
1655
|
}
|
|
1845
|
-
function
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
}
|
|
1861
|
-
default:
|
|
1862
|
-
return "null";
|
|
1656
|
+
function migrateLegacyEnabledForAgent(args) {
|
|
1657
|
+
const agent = clonePlainObject(args.patched[args.agentName]);
|
|
1658
|
+
if (!agent || !("enabled" in agent))
|
|
1659
|
+
return;
|
|
1660
|
+
const enabled = agent.enabled;
|
|
1661
|
+
const disable = agent.disable;
|
|
1662
|
+
delete agent.enabled;
|
|
1663
|
+
if (args.agentName === "historian") {
|
|
1664
|
+
args.warnings.push('Removed invalid "historian.enabled" in-memory (run doctor to persist).');
|
|
1665
|
+
args.patched.historian = agent;
|
|
1666
|
+
return;
|
|
1667
|
+
}
|
|
1668
|
+
if (disable !== true && enabled === false) {
|
|
1669
|
+
agent.disable = true;
|
|
1670
|
+
args.warnings.push('Migrated "dreamer.enabled=false" → "dreamer.disable=true" in-memory (run doctor to persist). This now also disables manual /ctx-dream; for manual-only remove disable and set schedule="".');
|
|
1863
1671
|
}
|
|
1672
|
+
args.patched.dreamer = agent;
|
|
1673
|
+
}
|
|
1674
|
+
function migrateLegacyAgentEnabledInMemory(rawConfig, warnings) {
|
|
1675
|
+
const shouldPatch = ["dreamer", "historian"].some((key) => {
|
|
1676
|
+
const agent = rawConfig[key];
|
|
1677
|
+
return typeof agent === "object" && agent !== null && !Array.isArray(agent) && "enabled" in agent;
|
|
1678
|
+
});
|
|
1679
|
+
if (!shouldPatch)
|
|
1680
|
+
return rawConfig;
|
|
1681
|
+
const patched = { ...rawConfig };
|
|
1682
|
+
migrateLegacyEnabledForAgent({ patched, agentName: "dreamer", warnings });
|
|
1683
|
+
migrateLegacyEnabledForAgent({ patched, agentName: "historian", warnings });
|
|
1684
|
+
return patched;
|
|
1864
1685
|
}
|
|
1865
1686
|
|
|
1866
|
-
//
|
|
1867
|
-
|
|
1868
|
-
|
|
1687
|
+
// src/config/migrate-config-location.ts
|
|
1688
|
+
import { homedir } from "node:os";
|
|
1689
|
+
import { basename, dirname, isAbsolute, join } from "node:path";
|
|
1690
|
+
|
|
1691
|
+
// src/shared/jsonc-edit.ts
|
|
1692
|
+
var TOKEN_COMMA = 5;
|
|
1693
|
+
var TOKEN_EOF = 17;
|
|
1694
|
+
function parseDocument(text) {
|
|
1869
1695
|
const errors = [];
|
|
1870
|
-
const root =
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
while (path.length > 0) {
|
|
1874
|
-
lastSegment = path.pop();
|
|
1875
|
-
parent = findNodeAtLocation(root, path);
|
|
1876
|
-
if (parent === undefined && value !== undefined) {
|
|
1877
|
-
if (typeof lastSegment === "string") {
|
|
1878
|
-
value = { [lastSegment]: value };
|
|
1879
|
-
} else {
|
|
1880
|
-
value = [value];
|
|
1881
|
-
}
|
|
1882
|
-
} else {
|
|
1883
|
-
break;
|
|
1884
|
-
}
|
|
1696
|
+
const root = parseTree2(text, errors, { allowTrailingComma: true });
|
|
1697
|
+
if (!root || errors.length > 0) {
|
|
1698
|
+
throw new Error("Cannot edit invalid JSONC");
|
|
1885
1699
|
}
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
removeBegin = parent.offset + 1;
|
|
1906
|
-
if (parent.children.length > 1) {
|
|
1907
|
-
let next = parent.children[1];
|
|
1908
|
-
removeEnd = next.offset;
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
|
-
return withFormatting(text, { offset: removeBegin, length: removeEnd - removeBegin, content: "" }, options);
|
|
1912
|
-
} else {
|
|
1913
|
-
return withFormatting(text, { offset: existing.offset, length: existing.length, content: JSON.stringify(value) }, options);
|
|
1914
|
-
}
|
|
1915
|
-
} else {
|
|
1916
|
-
if (value === undefined) {
|
|
1917
|
-
return [];
|
|
1918
|
-
}
|
|
1919
|
-
const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`;
|
|
1920
|
-
const index = options.getInsertionIndex ? options.getInsertionIndex(parent.children.map((p) => p.children[0].value)) : parent.children.length;
|
|
1921
|
-
let edit;
|
|
1922
|
-
if (index > 0) {
|
|
1923
|
-
let previous = parent.children[index - 1];
|
|
1924
|
-
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
1925
|
-
} else if (parent.children.length === 0) {
|
|
1926
|
-
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
1927
|
-
} else {
|
|
1928
|
-
edit = { offset: parent.offset + 1, length: 0, content: newProperty + "," };
|
|
1929
|
-
}
|
|
1930
|
-
return withFormatting(text, edit, options);
|
|
1931
|
-
}
|
|
1932
|
-
} else if (parent.type === "array" && typeof lastSegment === "number" && Array.isArray(parent.children)) {
|
|
1933
|
-
const insertIndex = lastSegment;
|
|
1934
|
-
if (insertIndex === -1) {
|
|
1935
|
-
const newProperty = `${JSON.stringify(value)}`;
|
|
1936
|
-
let edit;
|
|
1937
|
-
if (parent.children.length === 0) {
|
|
1938
|
-
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
1939
|
-
} else {
|
|
1940
|
-
const previous = parent.children[parent.children.length - 1];
|
|
1941
|
-
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
1942
|
-
}
|
|
1943
|
-
return withFormatting(text, edit, options);
|
|
1944
|
-
} else if (value === undefined && parent.children.length >= 0) {
|
|
1945
|
-
const removalIndex = lastSegment;
|
|
1946
|
-
const toRemove = parent.children[removalIndex];
|
|
1947
|
-
let edit;
|
|
1948
|
-
if (parent.children.length === 1) {
|
|
1949
|
-
edit = { offset: parent.offset + 1, length: parent.length - 2, content: "" };
|
|
1950
|
-
} else if (parent.children.length - 1 === removalIndex) {
|
|
1951
|
-
let previous = parent.children[removalIndex - 1];
|
|
1952
|
-
let offset = previous.offset + previous.length;
|
|
1953
|
-
let parentEndOffset = parent.offset + parent.length;
|
|
1954
|
-
edit = { offset, length: parentEndOffset - 2 - offset, content: "" };
|
|
1955
|
-
} else {
|
|
1956
|
-
edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: "" };
|
|
1957
|
-
}
|
|
1958
|
-
return withFormatting(text, edit, options);
|
|
1959
|
-
} else if (value !== undefined) {
|
|
1960
|
-
let edit;
|
|
1961
|
-
const newProperty = `${JSON.stringify(value)}`;
|
|
1962
|
-
if (!options.isArrayInsertion && parent.children.length > lastSegment) {
|
|
1963
|
-
const toModify = parent.children[lastSegment];
|
|
1964
|
-
edit = { offset: toModify.offset, length: toModify.length, content: newProperty };
|
|
1965
|
-
} else if (parent.children.length === 0 || lastSegment === 0) {
|
|
1966
|
-
edit = { offset: parent.offset + 1, length: 0, content: parent.children.length === 0 ? newProperty : newProperty + "," };
|
|
1967
|
-
} else {
|
|
1968
|
-
const index = lastSegment > parent.children.length ? parent.children.length : lastSegment;
|
|
1969
|
-
const previous = parent.children[index - 1];
|
|
1970
|
-
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
1971
|
-
}
|
|
1972
|
-
return withFormatting(text, edit, options);
|
|
1973
|
-
} else {
|
|
1974
|
-
throw new Error(`Can not ${value === undefined ? "remove" : options.isArrayInsertion ? "insert" : "modify"} Array index ${insertIndex} as length is not sufficient`);
|
|
1700
|
+
return root;
|
|
1701
|
+
}
|
|
1702
|
+
function findNode(text, path) {
|
|
1703
|
+
return findNodeAtLocation2(parseDocument(text), path);
|
|
1704
|
+
}
|
|
1705
|
+
function findComma(text, start, end) {
|
|
1706
|
+
const scanner = createScanner2(text, false);
|
|
1707
|
+
scanner.setPosition(start);
|
|
1708
|
+
for (;; ) {
|
|
1709
|
+
const kind = scanner.scan();
|
|
1710
|
+
const offset = scanner.getTokenOffset();
|
|
1711
|
+
if (kind === TOKEN_EOF || offset >= end)
|
|
1712
|
+
return;
|
|
1713
|
+
if (kind === TOKEN_COMMA) {
|
|
1714
|
+
return {
|
|
1715
|
+
offset,
|
|
1716
|
+
length: scanner.getTokenLength(),
|
|
1717
|
+
line: scanner.getTokenStartLine()
|
|
1718
|
+
};
|
|
1975
1719
|
}
|
|
1976
|
-
} else {
|
|
1977
|
-
throw new Error(`Can not add ${typeof lastSegment !== "number" ? "index" : "property"} to parent of type ${parent.type}`);
|
|
1978
1720
|
}
|
|
1979
1721
|
}
|
|
1980
|
-
function
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1722
|
+
function setJsoncValue(text, path, value) {
|
|
1723
|
+
const node = findNode(text, path);
|
|
1724
|
+
if (node) {
|
|
1725
|
+
if (Object.is(getNodeValue2(node), value))
|
|
1726
|
+
return text;
|
|
1727
|
+
const serialized = JSON.stringify(value);
|
|
1728
|
+
return text.slice(0, node.offset) + serialized + text.slice(node.offset + node.length);
|
|
1729
|
+
}
|
|
1730
|
+
return applyEdits(text, modify(text, path, value, { formattingOptions: documentFormatting(text) }));
|
|
1731
|
+
}
|
|
1732
|
+
function documentFormatting(text) {
|
|
1733
|
+
const eol = text.includes(`\r
|
|
1734
|
+
`) ? `\r
|
|
1735
|
+
` : `
|
|
1736
|
+
`;
|
|
1737
|
+
const indent = /\n([ \t]+)\S/.exec(text)?.[1];
|
|
1738
|
+
if (indent?.startsWith("\t"))
|
|
1739
|
+
return { eol, insertSpaces: false, tabSize: 1 };
|
|
1740
|
+
return { eol, insertSpaces: true, tabSize: indent ? indent.length : 2 };
|
|
1741
|
+
}
|
|
1742
|
+
function removeObjectProperty(text, object, key) {
|
|
1743
|
+
const properties = object.children ?? [];
|
|
1744
|
+
const index = properties.findIndex((property) => {
|
|
1745
|
+
const propertyKey = property.children?.[0];
|
|
1746
|
+
return propertyKey !== undefined && getNodeValue2(propertyKey) === key;
|
|
1747
|
+
});
|
|
1748
|
+
if (index === -1)
|
|
1749
|
+
return text;
|
|
1750
|
+
const property = properties[index];
|
|
1751
|
+
if (!property)
|
|
1752
|
+
return text;
|
|
1753
|
+
const closingBrace = object.offset + object.length - 1;
|
|
1754
|
+
const next = properties[index + 1];
|
|
1755
|
+
if (next) {
|
|
1756
|
+
const followingComma = findComma(text, property.offset + property.length, next.offset);
|
|
1757
|
+
if (!followingComma)
|
|
1758
|
+
return text;
|
|
1759
|
+
return text.slice(0, property.offset) + text.slice(followingComma.offset + followingComma.length);
|
|
1994
1760
|
}
|
|
1995
|
-
const
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
1761
|
+
const previous = properties[index - 1];
|
|
1762
|
+
const trailingComma = findComma(text, property.offset + property.length, closingBrace);
|
|
1763
|
+
if (!previous) {
|
|
1764
|
+
const afterProperty = property.offset + property.length;
|
|
1765
|
+
if (!trailingComma)
|
|
1766
|
+
return text.slice(0, property.offset) + text.slice(afterProperty);
|
|
1767
|
+
return text.slice(0, property.offset) + text.slice(afterProperty, trailingComma.offset) + text.slice(trailingComma.offset + trailingComma.length);
|
|
2002
1768
|
}
|
|
2003
|
-
const
|
|
2004
|
-
|
|
1769
|
+
const precedingComma = findComma(text, previous.offset + previous.length, property.offset);
|
|
1770
|
+
if (!precedingComma)
|
|
1771
|
+
return text;
|
|
1772
|
+
const afterProperty = property.offset + property.length;
|
|
1773
|
+
const withoutProperty = text.slice(0, precedingComma.offset) + text.slice(precedingComma.offset + precedingComma.length, property.offset) + text.slice(afterProperty);
|
|
1774
|
+
if (!trailingComma)
|
|
1775
|
+
return withoutProperty;
|
|
1776
|
+
const shiftedTrailingComma = trailingComma.offset - 1;
|
|
1777
|
+
return withoutProperty.slice(0, shiftedTrailingComma) + withoutProperty.slice(shiftedTrailingComma + trailingComma.length);
|
|
2005
1778
|
}
|
|
2006
|
-
function
|
|
2007
|
-
|
|
1779
|
+
function removeJsoncValue(text, path) {
|
|
1780
|
+
const key = path.at(-1);
|
|
1781
|
+
if (typeof key !== "string")
|
|
1782
|
+
return text;
|
|
1783
|
+
const parent = findNode(text, path.slice(0, -1));
|
|
1784
|
+
if (parent?.type !== "object")
|
|
1785
|
+
return text;
|
|
1786
|
+
return removeObjectProperty(text, parent, key);
|
|
2008
1787
|
}
|
|
2009
1788
|
|
|
2010
|
-
//
|
|
2011
|
-
var
|
|
2012
|
-
|
|
2013
|
-
(
|
|
2014
|
-
|
|
2015
|
-
ScanError[ScanError["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
|
|
2016
|
-
ScanError[ScanError["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
|
|
2017
|
-
ScanError[ScanError["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
|
|
2018
|
-
ScanError[ScanError["InvalidUnicode"] = 4] = "InvalidUnicode";
|
|
2019
|
-
ScanError[ScanError["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
|
|
2020
|
-
ScanError[ScanError["InvalidCharacter"] = 6] = "InvalidCharacter";
|
|
2021
|
-
})(ScanError || (ScanError = {}));
|
|
2022
|
-
var SyntaxKind;
|
|
2023
|
-
(function(SyntaxKind) {
|
|
2024
|
-
SyntaxKind[SyntaxKind["OpenBraceToken"] = 1] = "OpenBraceToken";
|
|
2025
|
-
SyntaxKind[SyntaxKind["CloseBraceToken"] = 2] = "CloseBraceToken";
|
|
2026
|
-
SyntaxKind[SyntaxKind["OpenBracketToken"] = 3] = "OpenBracketToken";
|
|
2027
|
-
SyntaxKind[SyntaxKind["CloseBracketToken"] = 4] = "CloseBracketToken";
|
|
2028
|
-
SyntaxKind[SyntaxKind["CommaToken"] = 5] = "CommaToken";
|
|
2029
|
-
SyntaxKind[SyntaxKind["ColonToken"] = 6] = "ColonToken";
|
|
2030
|
-
SyntaxKind[SyntaxKind["NullKeyword"] = 7] = "NullKeyword";
|
|
2031
|
-
SyntaxKind[SyntaxKind["TrueKeyword"] = 8] = "TrueKeyword";
|
|
2032
|
-
SyntaxKind[SyntaxKind["FalseKeyword"] = 9] = "FalseKeyword";
|
|
2033
|
-
SyntaxKind[SyntaxKind["StringLiteral"] = 10] = "StringLiteral";
|
|
2034
|
-
SyntaxKind[SyntaxKind["NumericLiteral"] = 11] = "NumericLiteral";
|
|
2035
|
-
SyntaxKind[SyntaxKind["LineCommentTrivia"] = 12] = "LineCommentTrivia";
|
|
2036
|
-
SyntaxKind[SyntaxKind["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
|
|
2037
|
-
SyntaxKind[SyntaxKind["LineBreakTrivia"] = 14] = "LineBreakTrivia";
|
|
2038
|
-
SyntaxKind[SyntaxKind["Trivia"] = 15] = "Trivia";
|
|
2039
|
-
SyntaxKind[SyntaxKind["Unknown"] = 16] = "Unknown";
|
|
2040
|
-
SyntaxKind[SyntaxKind["EOF"] = 17] = "EOF";
|
|
2041
|
-
})(SyntaxKind || (SyntaxKind = {}));
|
|
2042
|
-
var parse2 = parse;
|
|
2043
|
-
var parseTree2 = parseTree;
|
|
2044
|
-
var findNodeAtLocation2 = findNodeAtLocation;
|
|
2045
|
-
var getNodeValue2 = getNodeValue;
|
|
2046
|
-
var ParseErrorCode;
|
|
2047
|
-
(function(ParseErrorCode) {
|
|
2048
|
-
ParseErrorCode[ParseErrorCode["InvalidSymbol"] = 1] = "InvalidSymbol";
|
|
2049
|
-
ParseErrorCode[ParseErrorCode["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
|
|
2050
|
-
ParseErrorCode[ParseErrorCode["PropertyNameExpected"] = 3] = "PropertyNameExpected";
|
|
2051
|
-
ParseErrorCode[ParseErrorCode["ValueExpected"] = 4] = "ValueExpected";
|
|
2052
|
-
ParseErrorCode[ParseErrorCode["ColonExpected"] = 5] = "ColonExpected";
|
|
2053
|
-
ParseErrorCode[ParseErrorCode["CommaExpected"] = 6] = "CommaExpected";
|
|
2054
|
-
ParseErrorCode[ParseErrorCode["CloseBraceExpected"] = 7] = "CloseBraceExpected";
|
|
2055
|
-
ParseErrorCode[ParseErrorCode["CloseBracketExpected"] = 8] = "CloseBracketExpected";
|
|
2056
|
-
ParseErrorCode[ParseErrorCode["EndOfFileExpected"] = 9] = "EndOfFileExpected";
|
|
2057
|
-
ParseErrorCode[ParseErrorCode["InvalidCommentToken"] = 10] = "InvalidCommentToken";
|
|
2058
|
-
ParseErrorCode[ParseErrorCode["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
|
|
2059
|
-
ParseErrorCode[ParseErrorCode["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
|
|
2060
|
-
ParseErrorCode[ParseErrorCode["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
|
|
2061
|
-
ParseErrorCode[ParseErrorCode["InvalidUnicode"] = 14] = "InvalidUnicode";
|
|
2062
|
-
ParseErrorCode[ParseErrorCode["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
|
|
2063
|
-
ParseErrorCode[ParseErrorCode["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
2064
|
-
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
2065
|
-
function printParseErrorCode(code) {
|
|
2066
|
-
switch (code) {
|
|
2067
|
-
case 1:
|
|
2068
|
-
return "InvalidSymbol";
|
|
2069
|
-
case 2:
|
|
2070
|
-
return "InvalidNumberFormat";
|
|
2071
|
-
case 3:
|
|
2072
|
-
return "PropertyNameExpected";
|
|
2073
|
-
case 4:
|
|
2074
|
-
return "ValueExpected";
|
|
2075
|
-
case 5:
|
|
2076
|
-
return "ColonExpected";
|
|
2077
|
-
case 6:
|
|
2078
|
-
return "CommaExpected";
|
|
2079
|
-
case 7:
|
|
2080
|
-
return "CloseBraceExpected";
|
|
2081
|
-
case 8:
|
|
2082
|
-
return "CloseBracketExpected";
|
|
2083
|
-
case 9:
|
|
2084
|
-
return "EndOfFileExpected";
|
|
2085
|
-
case 10:
|
|
2086
|
-
return "InvalidCommentToken";
|
|
2087
|
-
case 11:
|
|
2088
|
-
return "UnexpectedEndOfComment";
|
|
2089
|
-
case 12:
|
|
2090
|
-
return "UnexpectedEndOfString";
|
|
2091
|
-
case 13:
|
|
2092
|
-
return "UnexpectedEndOfNumber";
|
|
2093
|
-
case 14:
|
|
2094
|
-
return "InvalidUnicode";
|
|
2095
|
-
case 15:
|
|
2096
|
-
return "InvalidEscapeCharacter";
|
|
2097
|
-
case 16:
|
|
2098
|
-
return "InvalidCharacter";
|
|
1789
|
+
// src/config/migrate-config-location.ts
|
|
1790
|
+
var CONFIG_FILE_BASENAME = "magic-context";
|
|
1791
|
+
function homeDir() {
|
|
1792
|
+
if (process.platform === "win32") {
|
|
1793
|
+
return process.env.USERPROFILE || process.env.HOME || homedir();
|
|
2099
1794
|
}
|
|
2100
|
-
return
|
|
1795
|
+
return process.env.HOME || homedir();
|
|
1796
|
+
}
|
|
1797
|
+
function configHome() {
|
|
1798
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
1799
|
+
if (xdg && isAbsolute(xdg))
|
|
1800
|
+
return xdg;
|
|
1801
|
+
return join(homeDir(), ".config");
|
|
1802
|
+
}
|
|
1803
|
+
function cortexKitUserConfigBasePath() {
|
|
1804
|
+
return join(configHome(), "cortexkit", CONFIG_FILE_BASENAME);
|
|
1805
|
+
}
|
|
1806
|
+
function cortexKitProjectConfigBasePath(directory) {
|
|
1807
|
+
return join(directory, ".cortexkit", CONFIG_FILE_BASENAME);
|
|
1808
|
+
}
|
|
1809
|
+
function legacySourcesForBase(basePath, label) {
|
|
1810
|
+
return [
|
|
1811
|
+
{ path: `${basePath}.jsonc`, label: `${label} magic-context.jsonc` },
|
|
1812
|
+
{ path: `${basePath}.json`, label: `${label} magic-context.json` }
|
|
1813
|
+
];
|
|
1814
|
+
}
|
|
1815
|
+
function userScopeConfigPaths() {
|
|
1816
|
+
return new Set([
|
|
1817
|
+
`${cortexKitUserConfigBasePath()}.jsonc`,
|
|
1818
|
+
`${cortexKitUserConfigBasePath()}.json`,
|
|
1819
|
+
join(configHome(), "opencode", `${CONFIG_FILE_BASENAME}.jsonc`),
|
|
1820
|
+
join(configHome(), "opencode", `${CONFIG_FILE_BASENAME}.json`),
|
|
1821
|
+
join(homeDir(), ".pi", "agent", `${CONFIG_FILE_BASENAME}.jsonc`),
|
|
1822
|
+
join(homeDir(), ".pi", "agent", `${CONFIG_FILE_BASENAME}.json`)
|
|
1823
|
+
]);
|
|
1824
|
+
}
|
|
1825
|
+
function resolveLegacyConfigSources(directory) {
|
|
1826
|
+
const userPaths = userScopeConfigPaths();
|
|
1827
|
+
return {
|
|
1828
|
+
user: [
|
|
1829
|
+
...legacySourcesForBase(join(configHome(), "opencode", CONFIG_FILE_BASENAME), "OpenCode user"),
|
|
1830
|
+
...legacySourcesForBase(join(homeDir(), ".pi", "agent", CONFIG_FILE_BASENAME), "Pi user")
|
|
1831
|
+
],
|
|
1832
|
+
project: [
|
|
1833
|
+
...legacySourcesForBase(join(directory, CONFIG_FILE_BASENAME), "project root"),
|
|
1834
|
+
...legacySourcesForBase(join(directory, ".opencode", CONFIG_FILE_BASENAME), "OpenCode project"),
|
|
1835
|
+
...legacySourcesForBase(join(directory, ".pi", CONFIG_FILE_BASENAME), "Pi project")
|
|
1836
|
+
].filter((source) => !userPaths.has(source.path))
|
|
1837
|
+
};
|
|
1838
|
+
}
|
|
1839
|
+
function resolveLegacyConfigSourcesForHarness(directory, harness) {
|
|
1840
|
+
if (harness === "pi") {
|
|
1841
|
+
return {
|
|
1842
|
+
user: legacySourcesForBase(join(homeDir(), ".pi", "agent", CONFIG_FILE_BASENAME), "Pi user"),
|
|
1843
|
+
project: legacySourcesForBase(join(directory, ".pi", CONFIG_FILE_BASENAME), "Pi project")
|
|
1844
|
+
};
|
|
1845
|
+
}
|
|
1846
|
+
return {
|
|
1847
|
+
user: legacySourcesForBase(join(configHome(), "opencode", CONFIG_FILE_BASENAME), "OpenCode user"),
|
|
1848
|
+
project: [
|
|
1849
|
+
...legacySourcesForBase(join(directory, CONFIG_FILE_BASENAME), "project root"),
|
|
1850
|
+
...legacySourcesForBase(join(directory, ".opencode", CONFIG_FILE_BASENAME), "OpenCode project")
|
|
1851
|
+
]
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
// src/config/migrate-dreamer-v2.ts
|
|
1856
|
+
var OLD_VERIFY_TASK = "verify";
|
|
1857
|
+
var OLD_CURATE_TASKS = ["consolidate", "archive-stale", "improve"];
|
|
1858
|
+
var RETIRED_OBJECT_MEMORY_TASKS = ["maintain-memory", ...OLD_CURATE_TASKS];
|
|
1859
|
+
var CANONICAL = [
|
|
1860
|
+
"map-memories",
|
|
1861
|
+
"verify",
|
|
1862
|
+
"verify-broad",
|
|
1863
|
+
"curate",
|
|
1864
|
+
"classify-memories",
|
|
1865
|
+
"retrospective",
|
|
1866
|
+
"maintain-docs",
|
|
1867
|
+
"evaluate-smart-notes",
|
|
1868
|
+
"review-user-memories",
|
|
1869
|
+
"promote-primers",
|
|
1870
|
+
"refresh-primers"
|
|
1871
|
+
];
|
|
1872
|
+
var DEFAULT_BASE_CRON = "0 2 * * *";
|
|
1873
|
+
var DEFAULT_CLASSIFY_CRON = "0 6 * * *";
|
|
1874
|
+
var DEFAULT_RETROSPECTIVE_CRON = "0 5 * * *";
|
|
1875
|
+
var DEFAULT_VERIFY_BROAD_CRON = "0 4 * * 0";
|
|
1876
|
+
function windowToCron(schedule) {
|
|
1877
|
+
if (typeof schedule !== "string")
|
|
1878
|
+
return DEFAULT_BASE_CRON;
|
|
1879
|
+
const m = /^(\d{1,2}):(\d{2})\s*-/.exec(schedule.trim());
|
|
1880
|
+
if (!m)
|
|
1881
|
+
return DEFAULT_BASE_CRON;
|
|
1882
|
+
const hour = Number(m[1]);
|
|
1883
|
+
const minute = Number(m[2]);
|
|
1884
|
+
if (hour >= 24 || minute >= 60)
|
|
1885
|
+
return DEFAULT_BASE_CRON;
|
|
1886
|
+
return `${minute} ${hour} * * *`;
|
|
2101
1887
|
}
|
|
2102
|
-
function
|
|
2103
|
-
return
|
|
1888
|
+
function asObject(value) {
|
|
1889
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
2104
1890
|
}
|
|
2105
|
-
function
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
return
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
1891
|
+
function cronIntervalScore(schedule) {
|
|
1892
|
+
const parts = schedule.trim().split(/\s+/);
|
|
1893
|
+
if (parts.length !== 5)
|
|
1894
|
+
return Number.POSITIVE_INFINITY;
|
|
1895
|
+
const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
1896
|
+
if (month !== "*")
|
|
1897
|
+
return 366 * 24 * 60;
|
|
1898
|
+
if (dayOfMonth !== "*")
|
|
1899
|
+
return 31 * 24 * 60;
|
|
1900
|
+
if (dayOfWeek !== "*")
|
|
1901
|
+
return 7 * 24 * 60;
|
|
1902
|
+
const everyHour = /^\*\/(\d+)$/.exec(hour ?? "");
|
|
1903
|
+
if (everyHour)
|
|
1904
|
+
return Math.max(1, Number(everyHour[1])) * 60;
|
|
1905
|
+
if (hour === "*") {
|
|
1906
|
+
const everyMinute = /^\*\/(\d+)$/.exec(minute ?? "");
|
|
1907
|
+
return everyMinute ? Math.max(1, Number(everyMinute[1])) : 60;
|
|
2122
1908
|
}
|
|
2123
|
-
return
|
|
1909
|
+
return 24 * 60;
|
|
2124
1910
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
if (inBlockComment) {
|
|
2145
|
-
if (char === "*" && next === "/") {
|
|
2146
|
-
inBlockComment = false;
|
|
2147
|
-
index += 1;
|
|
2148
|
-
}
|
|
2149
|
-
continue;
|
|
2150
|
-
}
|
|
2151
|
-
if (inString) {
|
|
2152
|
-
result += char;
|
|
2153
|
-
if (escaped) {
|
|
2154
|
-
escaped = false;
|
|
2155
|
-
} else if (char === "\\") {
|
|
2156
|
-
escaped = true;
|
|
2157
|
-
} else if (char === '"') {
|
|
2158
|
-
inString = false;
|
|
2159
|
-
}
|
|
1911
|
+
function mostFrequentSchedule(schedules) {
|
|
1912
|
+
const enabled = schedules.map((s) => s.trim()).filter(Boolean);
|
|
1913
|
+
if (enabled.length === 0)
|
|
1914
|
+
return "";
|
|
1915
|
+
return enabled.sort((a, b) => cronIntervalScore(a) - cronIntervalScore(b))[0] ?? "";
|
|
1916
|
+
}
|
|
1917
|
+
function withoutBroadInterval(entry) {
|
|
1918
|
+
const { broad_interval_days: _broad, ...rest } = entry;
|
|
1919
|
+
return rest;
|
|
1920
|
+
}
|
|
1921
|
+
function reconcileV2TasksObject(rawConfig, dreamer, tasksObject) {
|
|
1922
|
+
const hasVerifyBroad = "verify-broad" in tasksObject;
|
|
1923
|
+
const hasBroadIntervalAnywhere = Object.values(tasksObject).some((v) => asObject(v) && ("broad_interval_days" in v));
|
|
1924
|
+
const hasStaleKeyFiles = "key-files" in tasksObject;
|
|
1925
|
+
if (hasVerifyBroad && !hasBroadIntervalAnywhere && !hasStaleKeyFiles)
|
|
1926
|
+
return rawConfig;
|
|
1927
|
+
const nextTasks = {};
|
|
1928
|
+
for (const [key, value] of Object.entries(tasksObject)) {
|
|
1929
|
+
if (key === "key-files")
|
|
2160
1930
|
continue;
|
|
1931
|
+
const obj = asObject(value);
|
|
1932
|
+
nextTasks[key] = obj ? withoutBroadInterval(obj) : value;
|
|
1933
|
+
}
|
|
1934
|
+
if (!hasVerifyBroad) {
|
|
1935
|
+
const verify = asObject(tasksObject.verify);
|
|
1936
|
+
const verifyEnabled = typeof verify?.schedule === "string" && verify.schedule.trim() !== "";
|
|
1937
|
+
nextTasks["verify-broad"] = {
|
|
1938
|
+
schedule: verifyEnabled ? DEFAULT_VERIFY_BROAD_CRON : ""
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
return { ...rawConfig, dreamer: { ...dreamer, tasks: nextTasks } };
|
|
1942
|
+
}
|
|
1943
|
+
function migrateDreamerV2(rawConfig, warnings) {
|
|
1944
|
+
const dreamer = asObject(rawConfig.dreamer);
|
|
1945
|
+
if (!dreamer)
|
|
1946
|
+
return rawConfig;
|
|
1947
|
+
const tasksObject = asObject(dreamer.tasks);
|
|
1948
|
+
const hasRetiredObjectTasks = tasksObject ? RETIRED_OBJECT_MEMORY_TASKS.some((task) => (task in tasksObject)) : false;
|
|
1949
|
+
if (tasksObject && !hasRetiredObjectTasks) {
|
|
1950
|
+
const hasLegacyOutsideTasks = "schedule" in dreamer || "user_memories" in dreamer || "pin_key_files" in dreamer || "task_timeout_minutes" in dreamer || "max_runtime_minutes" in dreamer;
|
|
1951
|
+
if (!hasLegacyOutsideTasks) {
|
|
1952
|
+
return reconcileV2TasksObject(rawConfig, dreamer, tasksObject);
|
|
2161
1953
|
}
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
1954
|
+
}
|
|
1955
|
+
const hasLegacy = "schedule" in dreamer || Array.isArray(dreamer.tasks) || hasRetiredObjectTasks || "user_memories" in dreamer || "pin_key_files" in dreamer || "task_timeout_minutes" in dreamer || "max_runtime_minutes" in dreamer;
|
|
1956
|
+
if (!hasLegacy)
|
|
1957
|
+
return rawConfig;
|
|
1958
|
+
const baseCron = windowToCron(dreamer.schedule);
|
|
1959
|
+
const timeout = typeof dreamer.task_timeout_minutes === "number" ? dreamer.task_timeout_minutes : undefined;
|
|
1960
|
+
const withTimeout = (entry) => timeout !== undefined ? { ...entry, timeout_minutes: timeout } : entry;
|
|
1961
|
+
const classifySchedule = dreamer.disable === true ? "" : DEFAULT_CLASSIFY_CRON;
|
|
1962
|
+
const retrospectiveSchedule = dreamer.disable === true ? "" : DEFAULT_RETROSPECTIVE_CRON;
|
|
1963
|
+
const tasks = {};
|
|
1964
|
+
if (tasksObject) {
|
|
1965
|
+
for (const [key, value] of Object.entries(tasksObject)) {
|
|
1966
|
+
if (RETIRED_OBJECT_MEMORY_TASKS.includes(key))
|
|
1967
|
+
continue;
|
|
1968
|
+
if (asObject(value))
|
|
1969
|
+
tasks[key] = { ...value };
|
|
2166
1970
|
}
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
1971
|
+
const maintainMemoryEntry = asObject(tasksObject["maintain-memory"]);
|
|
1972
|
+
if (maintainMemoryEntry) {
|
|
1973
|
+
const schedule = typeof maintainMemoryEntry.schedule === "string" ? maintainMemoryEntry.schedule : baseCron;
|
|
1974
|
+
tasks.verify = withTimeout({
|
|
1975
|
+
...withoutBroadInterval(maintainMemoryEntry),
|
|
1976
|
+
...tasks.verify ?? {},
|
|
1977
|
+
schedule: tasks.verify?.schedule ?? schedule
|
|
1978
|
+
});
|
|
1979
|
+
tasks.curate = withTimeout({
|
|
1980
|
+
...withoutBroadInterval(maintainMemoryEntry),
|
|
1981
|
+
...tasks.curate ?? {},
|
|
1982
|
+
schedule: tasks.curate?.schedule ?? schedule
|
|
1983
|
+
});
|
|
2171
1984
|
}
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
1985
|
+
const oldVerifyEntry = asObject(tasksObject[OLD_VERIFY_TASK]);
|
|
1986
|
+
if (oldVerifyEntry) {
|
|
1987
|
+
tasks.verify = withTimeout({
|
|
1988
|
+
...withoutBroadInterval(oldVerifyEntry),
|
|
1989
|
+
...tasks.verify ?? {},
|
|
1990
|
+
schedule: tasks.verify?.schedule ?? (typeof oldVerifyEntry.schedule === "string" ? oldVerifyEntry.schedule : baseCron)
|
|
1991
|
+
});
|
|
2176
1992
|
}
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
let result = "";
|
|
2183
|
-
let inString = false;
|
|
2184
|
-
let escaped = false;
|
|
2185
|
-
for (let index = 0;index < content.length; index += 1) {
|
|
2186
|
-
const char = content[index];
|
|
2187
|
-
if (inString) {
|
|
2188
|
-
result += char;
|
|
2189
|
-
if (escaped) {
|
|
2190
|
-
escaped = false;
|
|
2191
|
-
} else if (char === "\\") {
|
|
2192
|
-
escaped = true;
|
|
2193
|
-
} else if (char === '"') {
|
|
2194
|
-
inString = false;
|
|
2195
|
-
}
|
|
2196
|
-
continue;
|
|
1993
|
+
if (!tasks["verify-broad"]) {
|
|
1994
|
+
const verifyEnabled = typeof tasks.verify?.schedule === "string" && tasks.verify.schedule.trim() !== "";
|
|
1995
|
+
tasks["verify-broad"] = withTimeout({
|
|
1996
|
+
schedule: verifyEnabled ? DEFAULT_VERIFY_BROAD_CRON : ""
|
|
1997
|
+
});
|
|
2197
1998
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
1999
|
+
const oldCurateEntries = OLD_CURATE_TASKS.map((task) => asObject(tasksObject[task])).filter((entry) => Boolean(entry));
|
|
2000
|
+
if (oldCurateEntries.length > 0) {
|
|
2001
|
+
const oldSchedules = oldCurateEntries.map((entry) => typeof entry.schedule === "string" ? entry.schedule : baseCron);
|
|
2002
|
+
tasks.curate = withTimeout({
|
|
2003
|
+
...tasks.curate ?? {},
|
|
2004
|
+
schedule: mostFrequentSchedule(oldSchedules)
|
|
2005
|
+
});
|
|
2202
2006
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
}
|
|
2208
|
-
const next = content[lookahead];
|
|
2209
|
-
if (next === "}" || next === "]") {
|
|
2210
|
-
continue;
|
|
2007
|
+
for (const task of CANONICAL) {
|
|
2008
|
+
if (!tasks[task]) {
|
|
2009
|
+
const schedule = task === "verify" || task === "curate" || task === "verify-broad" ? "" : task === "classify-memories" ? classifySchedule : task === "retrospective" ? retrospectiveSchedule : task === "maintain-docs" ? "" : baseCron;
|
|
2010
|
+
tasks[task] = withTimeout({ schedule });
|
|
2211
2011
|
}
|
|
2212
2012
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
const sourcePrototype = Object.getPrototypeOf(source);
|
|
2229
|
-
if (sourcePrototype !== null && sourcePrototype !== Object.prototype) {
|
|
2230
|
-
options.onRejectedKey?.([...path, "__proto__"]);
|
|
2231
|
-
}
|
|
2232
|
-
const sanitized = {};
|
|
2233
|
-
for (const key of Object.keys(source)) {
|
|
2234
|
-
if (isPrototypePollutionKey(key)) {
|
|
2235
|
-
options.onRejectedKey?.([...path, key]);
|
|
2236
|
-
continue;
|
|
2237
|
-
}
|
|
2238
|
-
Object.defineProperty(sanitized, key, {
|
|
2239
|
-
value: sanitizeParsedJson(source[key], options, [...path, key]),
|
|
2240
|
-
enumerable: true,
|
|
2241
|
-
configurable: true,
|
|
2242
|
-
writable: true
|
|
2013
|
+
} else {
|
|
2014
|
+
const legacyArray = Array.isArray(dreamer.tasks) ? dreamer.tasks.filter((t) => typeof t === "string") : null;
|
|
2015
|
+
const verifySelected = legacyArray ? legacyArray.includes(OLD_VERIFY_TASK) : true;
|
|
2016
|
+
const curateSelected = legacyArray ? legacyArray.some((task) => OLD_CURATE_TASKS.includes(task)) : true;
|
|
2017
|
+
tasks.verify = withTimeout({
|
|
2018
|
+
schedule: verifySelected ? baseCron : ""
|
|
2019
|
+
});
|
|
2020
|
+
tasks["verify-broad"] = withTimeout({
|
|
2021
|
+
schedule: verifySelected ? DEFAULT_VERIFY_BROAD_CRON : ""
|
|
2022
|
+
});
|
|
2023
|
+
tasks.curate = withTimeout({
|
|
2024
|
+
schedule: curateSelected ? baseCron : ""
|
|
2025
|
+
});
|
|
2026
|
+
tasks["classify-memories"] = withTimeout({
|
|
2027
|
+
schedule: classifySchedule
|
|
2243
2028
|
});
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
}
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
const lines = before.split(/\r?\n/);
|
|
2250
|
-
return { line: lines.length, column: (lines.at(-1)?.length ?? 0) + 1 };
|
|
2251
|
-
}
|
|
2252
|
-
function parseIssue(content, error) {
|
|
2253
|
-
const location = lineAndColumnAt(content, error.offset);
|
|
2254
|
-
const code = printParseErrorCode(error.error);
|
|
2255
|
-
const message = code.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
|
|
2256
|
-
return {
|
|
2257
|
-
...location,
|
|
2258
|
-
offset: error.offset,
|
|
2259
|
-
length: error.length,
|
|
2260
|
-
message
|
|
2261
|
-
};
|
|
2262
|
-
}
|
|
2263
|
-
function normalizeJsoncParserObjects(value, options, path = []) {
|
|
2264
|
-
if (Array.isArray(value)) {
|
|
2265
|
-
return value.map((entry, index) => normalizeJsoncParserObjects(entry, options, [...path, String(index)]));
|
|
2266
|
-
}
|
|
2267
|
-
if (value === null || typeof value !== "object")
|
|
2268
|
-
return value;
|
|
2269
|
-
const prototype = Object.getPrototypeOf(value);
|
|
2270
|
-
if (prototype !== Object.prototype && prototype !== null) {
|
|
2271
|
-
options.onRejectedKey?.([...path, "__proto__"]);
|
|
2272
|
-
}
|
|
2273
|
-
const normalized = {};
|
|
2274
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
2275
|
-
Object.defineProperty(normalized, key, {
|
|
2276
|
-
configurable: true,
|
|
2277
|
-
enumerable: true,
|
|
2278
|
-
writable: true,
|
|
2279
|
-
value: normalizeJsoncParserObjects(entry, options, [...path, key])
|
|
2029
|
+
tasks.retrospective = withTimeout({
|
|
2030
|
+
schedule: retrospectiveSchedule
|
|
2031
|
+
});
|
|
2032
|
+
tasks["maintain-docs"] = withTimeout({
|
|
2033
|
+
schedule: legacyArray?.includes("maintain-docs") ? baseCron : ""
|
|
2280
2034
|
});
|
|
2281
2035
|
}
|
|
2282
|
-
|
|
2283
|
-
}
|
|
2284
|
-
|
|
2285
|
-
const
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
value: sanitizeParsedJson(normalizeJsoncParserObjects(parsed, options), options),
|
|
2293
|
-
issues: errors.map((error) => parseIssue(content, error))
|
|
2294
|
-
};
|
|
2295
|
-
}
|
|
2296
|
-
function parseJsonc(content, options = {}) {
|
|
2297
|
-
const normalized = stripTrailingCommas(stripJsonComments(content));
|
|
2298
|
-
return sanitizeParsedJson(JSON.parse(normalized), options);
|
|
2299
|
-
}
|
|
2300
|
-
function readJsoncFile(filePath) {
|
|
2301
|
-
try {
|
|
2302
|
-
return parseJsonc(readFileSync(filePath, "utf-8"));
|
|
2303
|
-
} catch (_error) {
|
|
2304
|
-
return null;
|
|
2305
|
-
}
|
|
2306
|
-
}
|
|
2307
|
-
function detectConfigFile(basePath) {
|
|
2308
|
-
const jsoncPath = `${basePath}.jsonc`;
|
|
2309
|
-
const jsonPath = `${basePath}.json`;
|
|
2310
|
-
if (existsSync(jsoncPath)) {
|
|
2311
|
-
return { format: "jsonc", path: jsoncPath };
|
|
2312
|
-
}
|
|
2313
|
-
if (existsSync(jsonPath)) {
|
|
2314
|
-
return { format: "json", path: jsonPath };
|
|
2036
|
+
tasks["map-memories"] ??= withTimeout({ schedule: baseCron });
|
|
2037
|
+
tasks["evaluate-smart-notes"] ??= withTimeout({ schedule: baseCron });
|
|
2038
|
+
const um = asObject(dreamer.user_memories);
|
|
2039
|
+
const umEnabled = um ? um.enabled !== false : true;
|
|
2040
|
+
if (um || !tasks["review-user-memories"]) {
|
|
2041
|
+
tasks["review-user-memories"] = withTimeout({
|
|
2042
|
+
...tasks["review-user-memories"] ?? {},
|
|
2043
|
+
schedule: umEnabled ? baseCron : "",
|
|
2044
|
+
...um && typeof um.promotion_threshold === "number" ? { promotion_threshold: um.promotion_threshold } : {}
|
|
2045
|
+
});
|
|
2315
2046
|
}
|
|
2316
|
-
|
|
2047
|
+
const {
|
|
2048
|
+
schedule: _schedule,
|
|
2049
|
+
tasks: _tasks,
|
|
2050
|
+
task_timeout_minutes: _tto,
|
|
2051
|
+
max_runtime_minutes: _max,
|
|
2052
|
+
user_memories: _um,
|
|
2053
|
+
pin_key_files: _pkf,
|
|
2054
|
+
...rest
|
|
2055
|
+
} = dreamer;
|
|
2056
|
+
warnings.push('Migrated legacy dreamer scheduling (schedule window / tasks array / user_memories / pin_key_files) → per-task "dreamer.tasks" in-memory (run `doctor` to persist).');
|
|
2057
|
+
return { ...rawConfig, dreamer: { ...rest, tasks } };
|
|
2317
2058
|
}
|
|
2318
2059
|
|
|
2319
|
-
// src/config/migrate-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
var TOKEN_COMMA = 5;
|
|
2325
|
-
var TOKEN_EOF = 17;
|
|
2326
|
-
function parseDocument(text) {
|
|
2327
|
-
const errors = [];
|
|
2328
|
-
const root = parseTree2(text, errors, { allowTrailingComma: true });
|
|
2329
|
-
if (!root || errors.length > 0) {
|
|
2330
|
-
throw new Error("Cannot edit invalid JSONC");
|
|
2060
|
+
// src/config/migrate-experimental.ts
|
|
2061
|
+
function migrateLegacyExperimental(rawConfig, warnings) {
|
|
2062
|
+
const experimental = rawConfig.experimental;
|
|
2063
|
+
if (typeof experimental !== "object" || experimental === null) {
|
|
2064
|
+
return rawConfig;
|
|
2331
2065
|
}
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
const
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2066
|
+
const exp = experimental;
|
|
2067
|
+
const hasUM = "user_memories" in exp;
|
|
2068
|
+
const hasPKF = "pin_key_files" in exp;
|
|
2069
|
+
const hasMural = "mural" in exp;
|
|
2070
|
+
const TOP_LEVEL_GRADUATED = ["temporal_awareness", "caveman_text_compression"];
|
|
2071
|
+
const MEMORY_GRADUATED = ["auto_search", "git_commit_indexing"];
|
|
2072
|
+
const hasGraduated = TOP_LEVEL_GRADUATED.some((k) => (k in exp)) || MEMORY_GRADUATED.some((k) => (k in exp)) || hasMural;
|
|
2073
|
+
if (!hasUM && !hasPKF && !hasGraduated) {
|
|
2074
|
+
return rawConfig;
|
|
2075
|
+
}
|
|
2076
|
+
const patched = { ...rawConfig };
|
|
2077
|
+
const dreamer = typeof patched.dreamer === "object" && patched.dreamer !== null ? { ...patched.dreamer } : {};
|
|
2078
|
+
const memory = typeof patched.memory === "object" && patched.memory !== null ? { ...patched.memory } : {};
|
|
2079
|
+
const newExperimental = { ...exp };
|
|
2080
|
+
const coerceToObject = (value) => {
|
|
2081
|
+
if (typeof value === "boolean") {
|
|
2082
|
+
return { enabled: value };
|
|
2083
|
+
}
|
|
2084
|
+
if (typeof value === "object" && value !== null) {
|
|
2085
|
+
return { ...value };
|
|
2086
|
+
}
|
|
2087
|
+
return;
|
|
2088
|
+
};
|
|
2089
|
+
const relocate = (key, dest, destLabel) => {
|
|
2090
|
+
if (!(key in exp))
|
|
2344
2091
|
return;
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2092
|
+
const oldValue = exp[key];
|
|
2093
|
+
const existing = dest[key];
|
|
2094
|
+
if (existing === undefined) {
|
|
2095
|
+
dest[key] = oldValue;
|
|
2096
|
+
warnings.push(`Migrated "experimental.${key}" → "${destLabel}${key}" in-memory (run \`doctor\` to persist).`);
|
|
2097
|
+
} else if (typeof oldValue === "object" && oldValue !== null && typeof existing === "object" && existing !== null) {
|
|
2098
|
+
dest[key] = {
|
|
2099
|
+
...oldValue,
|
|
2100
|
+
...existing
|
|
2350
2101
|
};
|
|
2351
2102
|
}
|
|
2103
|
+
delete newExperimental[key];
|
|
2104
|
+
};
|
|
2105
|
+
for (const key of TOP_LEVEL_GRADUATED)
|
|
2106
|
+
relocate(key, patched, "");
|
|
2107
|
+
for (const key of MEMORY_GRADUATED)
|
|
2108
|
+
relocate(key, memory, "memory.");
|
|
2109
|
+
if (hasMural) {
|
|
2110
|
+
const oldMural = coerceToObject(exp.mural);
|
|
2111
|
+
const existingMural = patched.mural;
|
|
2112
|
+
if (existingMural === undefined) {
|
|
2113
|
+
patched.mural = oldMural ?? exp.mural;
|
|
2114
|
+
warnings.push('Deprecated "experimental.mural"; use top-level "mural" instead (migrated in memory; run `doctor` to persist).');
|
|
2115
|
+
} else if (oldMural !== undefined && typeof existingMural === "object" && existingMural !== null && !Array.isArray(existingMural)) {
|
|
2116
|
+
patched.mural = {
|
|
2117
|
+
...oldMural,
|
|
2118
|
+
...existingMural
|
|
2119
|
+
};
|
|
2120
|
+
}
|
|
2121
|
+
delete newExperimental.mural;
|
|
2352
2122
|
}
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
}
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
` : `
|
|
2368
|
-
`;
|
|
2369
|
-
const indent = /\n([ \t]+)\S/.exec(text)?.[1];
|
|
2370
|
-
if (indent?.startsWith("\t"))
|
|
2371
|
-
return { eol, insertSpaces: false, tabSize: 1 };
|
|
2372
|
-
return { eol, insertSpaces: true, tabSize: indent ? indent.length : 2 };
|
|
2373
|
-
}
|
|
2374
|
-
function removeObjectProperty(text, object, key) {
|
|
2375
|
-
const properties = object.children ?? [];
|
|
2376
|
-
const index = properties.findIndex((property) => {
|
|
2377
|
-
const propertyKey = property.children?.[0];
|
|
2378
|
-
return propertyKey !== undefined && getNodeValue2(propertyKey) === key;
|
|
2379
|
-
});
|
|
2380
|
-
if (index === -1)
|
|
2381
|
-
return text;
|
|
2382
|
-
const property = properties[index];
|
|
2383
|
-
if (!property)
|
|
2384
|
-
return text;
|
|
2385
|
-
const closingBrace = object.offset + object.length - 1;
|
|
2386
|
-
const next = properties[index + 1];
|
|
2387
|
-
if (next) {
|
|
2388
|
-
const followingComma = findComma(text, property.offset + property.length, next.offset);
|
|
2389
|
-
if (!followingComma)
|
|
2390
|
-
return text;
|
|
2391
|
-
return text.slice(0, property.offset) + text.slice(followingComma.offset + followingComma.length);
|
|
2123
|
+
if (hasUM) {
|
|
2124
|
+
const oldUM = coerceToObject(exp.user_memories);
|
|
2125
|
+
if (oldUM !== undefined) {
|
|
2126
|
+
if (dreamer.user_memories === undefined) {
|
|
2127
|
+
dreamer.user_memories = oldUM;
|
|
2128
|
+
warnings.push('Migrated "experimental.user_memories" → "dreamer.user_memories" in-memory (run `doctor` to persist).');
|
|
2129
|
+
} else if (typeof dreamer.user_memories === "object" && dreamer.user_memories !== null) {
|
|
2130
|
+
dreamer.user_memories = {
|
|
2131
|
+
...oldUM,
|
|
2132
|
+
...dreamer.user_memories
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
delete newExperimental.user_memories;
|
|
2392
2137
|
}
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2138
|
+
if (hasPKF) {
|
|
2139
|
+
const oldPKF = coerceToObject(exp.pin_key_files);
|
|
2140
|
+
if (oldPKF !== undefined) {
|
|
2141
|
+
if (dreamer.pin_key_files === undefined) {
|
|
2142
|
+
dreamer.pin_key_files = oldPKF;
|
|
2143
|
+
warnings.push('Migrated "experimental.pin_key_files" → "dreamer.pin_key_files" in-memory (run `doctor` to persist).');
|
|
2144
|
+
} else if (typeof dreamer.pin_key_files === "object" && dreamer.pin_key_files !== null) {
|
|
2145
|
+
dreamer.pin_key_files = {
|
|
2146
|
+
...oldPKF,
|
|
2147
|
+
...dreamer.pin_key_files
|
|
2148
|
+
};
|
|
2149
|
+
} else if (typeof dreamer.pin_key_files === "boolean") {
|
|
2150
|
+
dreamer.pin_key_files = { ...oldPKF, enabled: dreamer.pin_key_files };
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
delete newExperimental.pin_key_files;
|
|
2400
2154
|
}
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
return withoutProperty;
|
|
2408
|
-
const shiftedTrailingComma = trailingComma.offset - 1;
|
|
2409
|
-
return withoutProperty.slice(0, shiftedTrailingComma) + withoutProperty.slice(shiftedTrailingComma + trailingComma.length);
|
|
2410
|
-
}
|
|
2411
|
-
function removeJsoncValue(text, path) {
|
|
2412
|
-
const key = path.at(-1);
|
|
2413
|
-
if (typeof key !== "string")
|
|
2414
|
-
return text;
|
|
2415
|
-
const parent = findNode(text, path.slice(0, -1));
|
|
2416
|
-
if (parent?.type !== "object")
|
|
2417
|
-
return text;
|
|
2418
|
-
return removeObjectProperty(text, parent, key);
|
|
2155
|
+
patched.experimental = newExperimental;
|
|
2156
|
+
patched.dreamer = dreamer;
|
|
2157
|
+
if (Object.keys(memory).length > 0) {
|
|
2158
|
+
patched.memory = memory;
|
|
2159
|
+
}
|
|
2160
|
+
return patched;
|
|
2419
2161
|
}
|
|
2420
2162
|
|
|
2421
|
-
// src/config/
|
|
2422
|
-
var
|
|
2423
|
-
function
|
|
2424
|
-
|
|
2425
|
-
|
|
2163
|
+
// src/config/mural-model-deprecation.ts
|
|
2164
|
+
var MURAL_MODEL_DEPRECATION_WARNING = "mural.model is deprecated and ignored; compress-cues now uses the dreamer model for each harness, like every other dreamer task. To override it, set dreamer.opencode.tasks.compress-cues.model (or the pi/omp equivalent). This key no longer does anything; remove it.";
|
|
2165
|
+
function warnDeprecatedMuralModel(config, warnings) {
|
|
2166
|
+
const mural = config.mural;
|
|
2167
|
+
if (typeof mural === "object" && mural !== null && Object.hasOwn(mural, "model")) {
|
|
2168
|
+
warnings.push(MURAL_MODEL_DEPRECATION_WARNING);
|
|
2426
2169
|
}
|
|
2427
|
-
return process.env.HOME || homedir();
|
|
2428
|
-
}
|
|
2429
|
-
function configHome() {
|
|
2430
|
-
const xdg = process.env.XDG_CONFIG_HOME;
|
|
2431
|
-
if (xdg && isAbsolute(xdg))
|
|
2432
|
-
return xdg;
|
|
2433
|
-
return join(homeDir(), ".config");
|
|
2434
|
-
}
|
|
2435
|
-
function cortexKitUserConfigBasePath() {
|
|
2436
|
-
return join(configHome(), "cortexkit", CONFIG_FILE_BASENAME);
|
|
2437
|
-
}
|
|
2438
|
-
function cortexKitProjectConfigBasePath(directory) {
|
|
2439
|
-
return join(directory, ".cortexkit", CONFIG_FILE_BASENAME);
|
|
2440
|
-
}
|
|
2441
|
-
function legacySourcesForBase(basePath, label) {
|
|
2442
|
-
return [
|
|
2443
|
-
{ path: `${basePath}.jsonc`, label: `${label} magic-context.jsonc` },
|
|
2444
|
-
{ path: `${basePath}.json`, label: `${label} magic-context.json` }
|
|
2445
|
-
];
|
|
2446
2170
|
}
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
join(homeDir(), ".pi", "agent", `${CONFIG_FILE_BASENAME}.json`)
|
|
2455
|
-
]);
|
|
2171
|
+
|
|
2172
|
+
// src/config/profiles.ts
|
|
2173
|
+
function withoutProfileFields(raw) {
|
|
2174
|
+
const copy = { ...raw };
|
|
2175
|
+
delete copy.profile;
|
|
2176
|
+
delete copy.profiles;
|
|
2177
|
+
return copy;
|
|
2456
2178
|
}
|
|
2457
|
-
function
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
...legacySourcesForBase(join(directory, CONFIG_FILE_BASENAME), "project root"),
|
|
2466
|
-
...legacySourcesForBase(join(directory, ".opencode", CONFIG_FILE_BASENAME), "OpenCode project"),
|
|
2467
|
-
...legacySourcesForBase(join(directory, ".pi", CONFIG_FILE_BASENAME), "Pi project")
|
|
2468
|
-
].filter((source) => !userPaths.has(source.path))
|
|
2469
|
-
};
|
|
2179
|
+
function readProfileSelection(raw) {
|
|
2180
|
+
if (!Object.hasOwn(raw, "profile"))
|
|
2181
|
+
return { declared: false };
|
|
2182
|
+
const value = raw.profile;
|
|
2183
|
+
if (typeof value !== "string")
|
|
2184
|
+
return { declared: true };
|
|
2185
|
+
const name = value.trim();
|
|
2186
|
+
return name.length > 0 ? { declared: true, name } : { declared: true };
|
|
2470
2187
|
}
|
|
2471
|
-
function
|
|
2472
|
-
|
|
2188
|
+
function resolveConfigProfile(args) {
|
|
2189
|
+
const warnings = [];
|
|
2190
|
+
const userSelection = readProfileSelection(args.userRaw);
|
|
2191
|
+
const projectSelection = readProfileSelection(args.projectRaw);
|
|
2192
|
+
const selection = projectSelection.name ? { name: projectSelection.name, source: "project" } : userSelection.name ? { name: userSelection.name, source: "user" } : undefined;
|
|
2193
|
+
if (projectSelection.declared && !projectSelection.name) {
|
|
2194
|
+
warnings.push("Ignoring invalid profile selection from project config; expected a non-empty string.");
|
|
2195
|
+
}
|
|
2196
|
+
if (!projectSelection.declared && userSelection.declared && !userSelection.name) {
|
|
2197
|
+
warnings.push("Ignoring invalid profile selection from user config; expected a non-empty string.");
|
|
2198
|
+
}
|
|
2199
|
+
let profiles = {};
|
|
2200
|
+
if (Object.hasOwn(args.userRaw, "profiles")) {
|
|
2201
|
+
const parsed = ConfigProfilesSchema.safeParse(args.userRaw.profiles);
|
|
2202
|
+
if (parsed.success) {
|
|
2203
|
+
profiles = parsed.data;
|
|
2204
|
+
} else {
|
|
2205
|
+
warnings.push("Ignoring profiles from user config: invalid profile configuration; profiles may contain only historian/dreamer harness model blocks.");
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
if (!selection) {
|
|
2473
2209
|
return {
|
|
2474
|
-
|
|
2475
|
-
|
|
2210
|
+
userBase: withoutProfileFields(args.userRaw),
|
|
2211
|
+
projectBase: withoutProfileFields(args.projectRaw),
|
|
2212
|
+
overlay: {},
|
|
2213
|
+
warnings
|
|
2214
|
+
};
|
|
2215
|
+
}
|
|
2216
|
+
if (!Object.hasOwn(profiles, selection.name)) {
|
|
2217
|
+
warnings.push(`Unknown profile "${selection.name}" selected by ${selection.source} config; using base config without a profile.`);
|
|
2218
|
+
return {
|
|
2219
|
+
userBase: withoutProfileFields(args.userRaw),
|
|
2220
|
+
projectBase: withoutProfileFields(args.projectRaw),
|
|
2221
|
+
overlay: {},
|
|
2222
|
+
warnings
|
|
2476
2223
|
};
|
|
2477
2224
|
}
|
|
2225
|
+
const overlay = profiles[selection.name];
|
|
2478
2226
|
return {
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2227
|
+
userBase: withoutProfileFields(args.userRaw),
|
|
2228
|
+
projectBase: withoutProfileFields(args.projectRaw),
|
|
2229
|
+
overlay,
|
|
2230
|
+
activeProfile: selection.name,
|
|
2231
|
+
warnings
|
|
2484
2232
|
};
|
|
2485
2233
|
}
|
|
2486
2234
|
|
|
2487
|
-
// src/config/
|
|
2488
|
-
var
|
|
2489
|
-
var
|
|
2490
|
-
var
|
|
2491
|
-
|
|
2492
|
-
"
|
|
2493
|
-
"
|
|
2494
|
-
"verify-broad",
|
|
2495
|
-
"curate",
|
|
2496
|
-
"classify-memories",
|
|
2497
|
-
"retrospective",
|
|
2498
|
-
"maintain-docs",
|
|
2499
|
-
"evaluate-smart-notes",
|
|
2500
|
-
"review-user-memories",
|
|
2501
|
-
"promote-primers",
|
|
2502
|
-
"refresh-primers"
|
|
2235
|
+
// src/config/project-security.ts
|
|
2236
|
+
var HIDDEN_AGENT_KEYS = ["historian", "dreamer"];
|
|
2237
|
+
var HARNESS_KEYS = PER_HARNESS_MODEL_KEYS;
|
|
2238
|
+
var HISTORIAN_USER_ONLY_FIELDS = [
|
|
2239
|
+
...PER_HARNESS_MIGRATION_INVENTORY.historian.migrated_execution,
|
|
2240
|
+
"runner",
|
|
2241
|
+
"host_runner"
|
|
2503
2242
|
];
|
|
2504
|
-
var
|
|
2505
|
-
var
|
|
2506
|
-
var
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
return
|
|
2243
|
+
var PROMPT_SURFACE_USER_ONLY_FIELDS = ["guidance_override_path", "tool_descriptions"];
|
|
2244
|
+
var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools"];
|
|
2245
|
+
var EMBEDDING_USER_ONLY_FIELDS = [
|
|
2246
|
+
"endpoint",
|
|
2247
|
+
"provider",
|
|
2248
|
+
"fallback_provider",
|
|
2249
|
+
"query_instruction",
|
|
2250
|
+
"document_prefix"
|
|
2251
|
+
];
|
|
2252
|
+
var PERCENTAGE_THRESHOLD_REASON = "security: a repository may only raise compaction thresholds above the user's effective value; it cannot force earlier historian work or cloned-repo cost escalation.";
|
|
2253
|
+
var TOKEN_THRESHOLD_REASON = "security: a repository may only raise execute_threshold_tokens above the user's trusted token threshold; it cannot force earlier historian work or cloned-repo cost escalation.";
|
|
2254
|
+
var TOKEN_THRESHOLD_INTRODUCTION_REASON = "security: a repository cannot introduce a new execute_threshold_tokens override when the user has no trusted token threshold for that key; that could force earlier historian work or cloned-repo cost escalation.";
|
|
2255
|
+
var PROTECTED_TOKENS_REASON = "security: a repository may only raise protected_tokens above the resolved user-or-derived floor; it cannot lower protection.";
|
|
2256
|
+
function isPlainObject(value) {
|
|
2257
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2519
2258
|
}
|
|
2520
|
-
function
|
|
2521
|
-
|
|
2259
|
+
function resolveProtectedTokensScalar(value) {
|
|
2260
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 4000 && value <= 1e6) {
|
|
2261
|
+
return value;
|
|
2262
|
+
}
|
|
2263
|
+
return;
|
|
2522
2264
|
}
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
const
|
|
2528
|
-
if (
|
|
2529
|
-
return
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2265
|
+
var PROTECTED_TOKENS_TIER_OVERRIDES = Symbol.for("@cortexkit/magic-context/protected-tokens-tier-overrides");
|
|
2266
|
+
function attachProtectedTokensTierOverrides(config, args) {
|
|
2267
|
+
const user = resolveProtectedTokensScalar(args.trustedUser);
|
|
2268
|
+
const rawProject = resolveProtectedTokensScalar(args.project);
|
|
2269
|
+
const project = rawProject !== undefined && (user === undefined || rawProject >= user) ? rawProject : undefined;
|
|
2270
|
+
if (user === undefined && project === undefined)
|
|
2271
|
+
return config;
|
|
2272
|
+
Object.defineProperty(config, PROTECTED_TOKENS_TIER_OVERRIDES, {
|
|
2273
|
+
value: {
|
|
2274
|
+
...user !== undefined ? { user } : {},
|
|
2275
|
+
...project !== undefined ? { project } : {}
|
|
2276
|
+
},
|
|
2277
|
+
configurable: false,
|
|
2278
|
+
enumerable: false,
|
|
2279
|
+
writable: false
|
|
2280
|
+
});
|
|
2281
|
+
return config;
|
|
2282
|
+
}
|
|
2283
|
+
function getProtectedTokensTierOverrides(config) {
|
|
2284
|
+
return config[PROTECTED_TOKENS_TIER_OVERRIDES];
|
|
2285
|
+
}
|
|
2286
|
+
function stripListedFields(target, fields, path, removed) {
|
|
2287
|
+
for (const field of fields) {
|
|
2288
|
+
if (field in target) {
|
|
2289
|
+
delete target[field];
|
|
2290
|
+
removed.push(path.length > 0 ? `${path}.${field}` : field);
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
function stripEscalationAtExecutableSite(block, path, removed) {
|
|
2295
|
+
stripListedFields(block, AGENT_ESCALATION_FIELDS, path, removed);
|
|
2296
|
+
if (isPlainObject(block.model)) {
|
|
2297
|
+
stripListedFields(block.model, AGENT_ESCALATION_FIELDS, `${path}.model`, removed);
|
|
2298
|
+
}
|
|
2299
|
+
if (Array.isArray(block.fallback_models)) {
|
|
2300
|
+
for (let index = 0;index < block.fallback_models.length; index++) {
|
|
2301
|
+
const entry = block.fallback_models[index];
|
|
2302
|
+
if (isPlainObject(entry)) {
|
|
2303
|
+
stripListedFields(entry, AGENT_ESCALATION_FIELDS, `${path}.fallback_models.${index}`, removed);
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2540
2306
|
}
|
|
2541
|
-
return 24 * 60;
|
|
2542
2307
|
}
|
|
2543
|
-
function
|
|
2544
|
-
|
|
2545
|
-
if (enabled.length === 0)
|
|
2546
|
-
return "";
|
|
2547
|
-
return enabled.sort((a, b) => cronIntervalScore(a) - cronIntervalScore(b))[0] ?? "";
|
|
2308
|
+
function isValidPercentageThreshold(value) {
|
|
2309
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 20 && value <= 90;
|
|
2548
2310
|
}
|
|
2549
|
-
function
|
|
2550
|
-
|
|
2551
|
-
return rest;
|
|
2311
|
+
function isValidTokenThreshold(value) {
|
|
2312
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 5000 && value <= 2000000;
|
|
2552
2313
|
}
|
|
2553
|
-
function
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
if (
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2314
|
+
function normalizeTrustedPercentageThresholds(value) {
|
|
2315
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2316
|
+
return { defaultValue: value, overrides: new Map };
|
|
2317
|
+
}
|
|
2318
|
+
if (isPlainObject(value) && typeof value.default === "number" && Number.isFinite(value.default)) {
|
|
2319
|
+
const overrides = new Map;
|
|
2320
|
+
for (const [key, child] of Object.entries(value)) {
|
|
2321
|
+
if (key === "default")
|
|
2322
|
+
continue;
|
|
2323
|
+
if (typeof child === "number" && Number.isFinite(child)) {
|
|
2324
|
+
overrides.set(key, child);
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
return { defaultValue: value.default, overrides };
|
|
2328
|
+
}
|
|
2329
|
+
return { defaultValue: DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, overrides: new Map };
|
|
2330
|
+
}
|
|
2331
|
+
function normalizeTrustedTokenThresholds(value) {
|
|
2332
|
+
if (!isPlainObject(value)) {
|
|
2333
|
+
return { defaultValue: undefined, overrides: new Map };
|
|
2334
|
+
}
|
|
2335
|
+
const overrides = new Map;
|
|
2336
|
+
for (const [key, child] of Object.entries(value)) {
|
|
2337
|
+
if (key === "default")
|
|
2562
2338
|
continue;
|
|
2563
|
-
|
|
2564
|
-
|
|
2339
|
+
if (typeof child === "number" && Number.isFinite(child)) {
|
|
2340
|
+
overrides.set(key, child);
|
|
2341
|
+
}
|
|
2565
2342
|
}
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2343
|
+
return {
|
|
2344
|
+
defaultValue: typeof value.default === "number" && Number.isFinite(value.default) ? value.default : undefined,
|
|
2345
|
+
overrides
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2348
|
+
function clonePercentageThresholds(value) {
|
|
2349
|
+
return {
|
|
2350
|
+
defaultValue: value.defaultValue,
|
|
2351
|
+
overrides: new Map(value.overrides)
|
|
2352
|
+
};
|
|
2353
|
+
}
|
|
2354
|
+
function cloneTokenThresholds(value) {
|
|
2355
|
+
return {
|
|
2356
|
+
defaultValue: value.defaultValue,
|
|
2357
|
+
overrides: new Map(value.overrides)
|
|
2358
|
+
};
|
|
2359
|
+
}
|
|
2360
|
+
function percentageThresholdsEqual(left, right) {
|
|
2361
|
+
if (left.defaultValue !== right.defaultValue)
|
|
2362
|
+
return false;
|
|
2363
|
+
if (left.overrides.size !== right.overrides.size)
|
|
2364
|
+
return false;
|
|
2365
|
+
for (const [key, value] of left.overrides) {
|
|
2366
|
+
if (right.overrides.get(key) !== value)
|
|
2367
|
+
return false;
|
|
2572
2368
|
}
|
|
2573
|
-
return
|
|
2369
|
+
return true;
|
|
2574
2370
|
}
|
|
2575
|
-
function
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
return
|
|
2579
|
-
|
|
2580
|
-
const
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2371
|
+
function setMergedPercentageThreshold(mergedRaw, value) {
|
|
2372
|
+
if (value.overrides.size === 0) {
|
|
2373
|
+
mergedRaw.execute_threshold_percentage = value.defaultValue;
|
|
2374
|
+
return;
|
|
2375
|
+
}
|
|
2376
|
+
const serialized = { default: value.defaultValue };
|
|
2377
|
+
for (const [key, threshold] of value.overrides) {
|
|
2378
|
+
serialized[key] = threshold;
|
|
2379
|
+
}
|
|
2380
|
+
mergedRaw.execute_threshold_percentage = serialized;
|
|
2381
|
+
}
|
|
2382
|
+
function setMergedTokenThreshold(mergedRaw, value) {
|
|
2383
|
+
if (value.defaultValue === undefined && value.overrides.size === 0) {
|
|
2384
|
+
delete mergedRaw.execute_threshold_tokens;
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
const serialized = {};
|
|
2388
|
+
if (value.defaultValue !== undefined) {
|
|
2389
|
+
serialized.default = value.defaultValue;
|
|
2390
|
+
}
|
|
2391
|
+
for (const [key, threshold] of value.overrides) {
|
|
2392
|
+
serialized[key] = threshold;
|
|
2393
|
+
}
|
|
2394
|
+
mergedRaw.execute_threshold_tokens = serialized;
|
|
2395
|
+
}
|
|
2396
|
+
function makeProjectThresholdWarning(field, reason) {
|
|
2397
|
+
return `Ignoring ${field} from project config (${reason})`;
|
|
2398
|
+
}
|
|
2399
|
+
function stripUnsafeProjectConfigFields(projectRaw) {
|
|
2400
|
+
const warnings = [];
|
|
2401
|
+
if ("profiles" in projectRaw) {
|
|
2402
|
+
delete projectRaw.profiles;
|
|
2403
|
+
warnings.push("Ignoring profiles from project config (security: profile definitions are user-level only; a repository may select a named user profile with profile).");
|
|
2404
|
+
}
|
|
2405
|
+
if ("auto_update" in projectRaw) {
|
|
2406
|
+
delete projectRaw.auto_update;
|
|
2407
|
+
warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
|
|
2408
|
+
}
|
|
2409
|
+
if ("fail_closed_blocking" in projectRaw) {
|
|
2410
|
+
delete projectRaw.fail_closed_blocking;
|
|
2411
|
+
warnings.push("Ignoring fail_closed_blocking from project config (security: only user-level config may disable or force the loud inoperability gate).");
|
|
2412
|
+
}
|
|
2413
|
+
if ("debug_rpc" in projectRaw) {
|
|
2414
|
+
delete projectRaw.debug_rpc;
|
|
2415
|
+
warnings.push("Ignoring debug_rpc from project config (security: only user-level config may enable process heap diagnostics).");
|
|
2416
|
+
}
|
|
2417
|
+
if ("allow_home_project" in projectRaw) {
|
|
2418
|
+
delete projectRaw.allow_home_project;
|
|
2419
|
+
warnings.push("Ignoring allow_home_project from project config (security: only user-level config may opt the user's home directory into Magic Context).");
|
|
2420
|
+
}
|
|
2421
|
+
const compaction = projectRaw.compaction;
|
|
2422
|
+
if (isPlainObject(compaction) && "enabled" in compaction) {
|
|
2423
|
+
delete compaction.enabled;
|
|
2424
|
+
warnings.push("Ignoring compaction.enabled from project config (security: only user-level config may disable Magic Context's context-window management; a cloned repo cannot change how the user's window is owned).");
|
|
2425
|
+
}
|
|
2426
|
+
if ("output_reserve" in projectRaw) {
|
|
2427
|
+
delete projectRaw.output_reserve;
|
|
2428
|
+
warnings.push("Ignoring output_reserve from project config (security: output-token reservation only honors user-level config).");
|
|
2429
|
+
}
|
|
2430
|
+
const models = projectRaw.models;
|
|
2431
|
+
if (isPlainObject(models) && "window_overlay_path" in models) {
|
|
2432
|
+
delete models.window_overlay_path;
|
|
2433
|
+
warnings.push("Ignoring models.window_overlay_path from project config (security: only user-level config may select model geometry metadata).");
|
|
2434
|
+
}
|
|
2435
|
+
if ("language" in projectRaw) {
|
|
2436
|
+
delete projectRaw.language;
|
|
2437
|
+
warnings.push("Ignoring language from project config (security: output language is a user-level setting).");
|
|
2438
|
+
}
|
|
2439
|
+
if ("sqlite" in projectRaw) {
|
|
2440
|
+
delete projectRaw.sqlite;
|
|
2441
|
+
warnings.push("Ignoring sqlite.* from project config (security: SQLite cache/mmap PRAGMAs apply to the " + "process-global shared database handle; only user-level config may set them).");
|
|
2442
|
+
}
|
|
2443
|
+
const storage = projectRaw.storage;
|
|
2444
|
+
if (isPlainObject(storage) && "enforce_private_permissions" in storage) {
|
|
2445
|
+
delete storage.enforce_private_permissions;
|
|
2446
|
+
warnings.push("Ignoring storage.enforce_private_permissions from project config (security: only user-level config may opt into externally managed shared storage permissions).");
|
|
2447
|
+
}
|
|
2448
|
+
const smartNotes = projectRaw.smart_notes;
|
|
2449
|
+
if (isPlainObject(smartNotes) && "enabled" in smartNotes) {
|
|
2450
|
+
delete smartNotes.enabled;
|
|
2451
|
+
warnings.push("Ignoring smart_notes.enabled from project config (only user-level config may change process-wide tool definitions; restart required).");
|
|
2452
|
+
}
|
|
2453
|
+
const promptSurface = projectRaw.prompt_surface;
|
|
2454
|
+
if (isPlainObject(promptSurface)) {
|
|
2455
|
+
const removed = [];
|
|
2456
|
+
for (const field of PROMPT_SURFACE_USER_ONLY_FIELDS) {
|
|
2457
|
+
if (field in promptSurface) {
|
|
2458
|
+
delete promptSurface[field];
|
|
2459
|
+
removed.push(field);
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
if (removed.length > 0) {
|
|
2463
|
+
warnings.push(`Ignoring prompt_surface.${removed.join("/")} from project config (security: repositories may select prompt presets but only user config may provide guidance or tool-description text).`);
|
|
2585
2464
|
}
|
|
2586
2465
|
}
|
|
2587
|
-
const
|
|
2588
|
-
if (
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
if (tasksObject) {
|
|
2597
|
-
for (const [key, value] of Object.entries(tasksObject)) {
|
|
2598
|
-
if (RETIRED_OBJECT_MEMORY_TASKS.includes(key))
|
|
2599
|
-
continue;
|
|
2600
|
-
if (asObject(value))
|
|
2601
|
-
tasks[key] = { ...value };
|
|
2466
|
+
const pi = projectRaw.pi;
|
|
2467
|
+
if (isPlainObject(pi) && "subagent_extensions" in pi) {
|
|
2468
|
+
delete pi.subagent_extensions;
|
|
2469
|
+
warnings.push("Ignoring pi.subagent_extensions from project config (security: only user-level config may choose extensions loaded by Pi subagent children).");
|
|
2470
|
+
}
|
|
2471
|
+
for (const field of ["subc", "shadow_embedding"]) {
|
|
2472
|
+
if (field in projectRaw) {
|
|
2473
|
+
delete projectRaw[field];
|
|
2474
|
+
warnings.push(`Ignoring ${field} from project config (security: daemon routing and developer-only embedding traffic are user-level settings).`);
|
|
2602
2475
|
}
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
...withoutBroadInterval(maintainMemoryEntry),
|
|
2613
|
-
...tasks.curate ?? {},
|
|
2614
|
-
schedule: tasks.curate?.schedule ?? schedule
|
|
2615
|
-
});
|
|
2476
|
+
}
|
|
2477
|
+
const embedding = projectRaw.embedding;
|
|
2478
|
+
if (isPlainObject(embedding)) {
|
|
2479
|
+
const removed = [];
|
|
2480
|
+
for (const field of EMBEDDING_USER_ONLY_FIELDS) {
|
|
2481
|
+
if (field in embedding) {
|
|
2482
|
+
delete embedding[field];
|
|
2483
|
+
removed.push(field);
|
|
2484
|
+
}
|
|
2616
2485
|
}
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2486
|
+
if (removed.length > 0) {
|
|
2487
|
+
warnings.push(`Ignoring embedding.${removed.join("/")} from project config ` + "(security: a repository cannot choose where or how private text is embedded).");
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
for (const agentKey of HIDDEN_AGENT_KEYS) {
|
|
2491
|
+
const block = projectRaw[agentKey];
|
|
2492
|
+
if (!isPlainObject(block))
|
|
2493
|
+
continue;
|
|
2494
|
+
const removed = [];
|
|
2495
|
+
stripEscalationAtExecutableSite(block, agentKey, removed);
|
|
2496
|
+
for (const harness of HARNESS_KEYS) {
|
|
2497
|
+
const harnessBlock = block[harness];
|
|
2498
|
+
if (!isPlainObject(harnessBlock))
|
|
2499
|
+
continue;
|
|
2500
|
+
stripEscalationAtExecutableSite(harnessBlock, `${agentKey}.${harness}`, removed);
|
|
2501
|
+
const tasks = harnessBlock.tasks;
|
|
2502
|
+
if (isPlainObject(tasks)) {
|
|
2503
|
+
for (const [taskName, taskBlock] of Object.entries(tasks)) {
|
|
2504
|
+
if (isPlainObject(taskBlock)) {
|
|
2505
|
+
stripEscalationAtExecutableSite(taskBlock, `${agentKey}.${harness}.tasks.${taskName}`, removed);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2624
2509
|
}
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2510
|
+
const schedulingTasks = block.tasks;
|
|
2511
|
+
if (isPlainObject(schedulingTasks)) {
|
|
2512
|
+
for (const [taskName, taskBlock] of Object.entries(schedulingTasks)) {
|
|
2513
|
+
if (isPlainObject(taskBlock)) {
|
|
2514
|
+
stripListedFields(taskBlock, AGENT_ESCALATION_FIELDS, `${agentKey}.tasks.${taskName}`, removed);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2630
2517
|
}
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
const oldSchedules = oldCurateEntries.map((entry) => typeof entry.schedule === "string" ? entry.schedule : baseCron);
|
|
2634
|
-
tasks.curate = withTimeout({
|
|
2635
|
-
...tasks.curate ?? {},
|
|
2636
|
-
schedule: mostFrequentSchedule(oldSchedules)
|
|
2637
|
-
});
|
|
2518
|
+
if (removed.length > 0) {
|
|
2519
|
+
warnings.push(`Ignoring ${removed.join(", ")} from project config ` + "(security: a repository cannot reprogram or re-permission hidden agents).");
|
|
2638
2520
|
}
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2521
|
+
}
|
|
2522
|
+
const historian = projectRaw.historian;
|
|
2523
|
+
if (isPlainObject(historian)) {
|
|
2524
|
+
const removed = [];
|
|
2525
|
+
for (const field of HISTORIAN_USER_ONLY_FIELDS) {
|
|
2526
|
+
if (field in historian) {
|
|
2527
|
+
delete historian[field];
|
|
2528
|
+
removed.push(field);
|
|
2643
2529
|
}
|
|
2644
2530
|
}
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
schedule: classifySchedule
|
|
2660
|
-
});
|
|
2661
|
-
tasks.retrospective = withTimeout({
|
|
2662
|
-
schedule: retrospectiveSchedule
|
|
2663
|
-
});
|
|
2664
|
-
tasks["maintain-docs"] = withTimeout({
|
|
2665
|
-
schedule: legacyArray?.includes("maintain-docs") ? baseCron : ""
|
|
2666
|
-
});
|
|
2531
|
+
for (const harness of HARNESS_KEYS) {
|
|
2532
|
+
const harnessBlock = historian[harness];
|
|
2533
|
+
if (!isPlainObject(harnessBlock))
|
|
2534
|
+
continue;
|
|
2535
|
+
for (const field of HISTORIAN_USER_ONLY_FIELDS) {
|
|
2536
|
+
if (field in harnessBlock) {
|
|
2537
|
+
delete harnessBlock[field];
|
|
2538
|
+
removed.push(`${harness}.${field}`);
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
if (removed.length > 0) {
|
|
2543
|
+
warnings.push(`Ignoring ${removed.map((path) => `historian.${path}`).join(", ")} from project config ` + "(security: historian model selection is user-level only; a repository cannot force extra compaction cost).");
|
|
2544
|
+
}
|
|
2667
2545
|
}
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
if (um || !tasks["review-user-memories"]) {
|
|
2673
|
-
tasks["review-user-memories"] = withTimeout({
|
|
2674
|
-
...tasks["review-user-memories"] ?? {},
|
|
2675
|
-
schedule: umEnabled ? baseCron : "",
|
|
2676
|
-
...um && typeof um.promotion_threshold === "number" ? { promotion_threshold: um.promotion_threshold } : {}
|
|
2677
|
-
});
|
|
2546
|
+
const dreamer = projectRaw.dreamer;
|
|
2547
|
+
if (isPlainObject(dreamer) && "runner" in dreamer) {
|
|
2548
|
+
delete dreamer.runner;
|
|
2549
|
+
warnings.push("Ignoring dreamer.runner from project config (security: which process and provider account run dreamer completions is a user-level setting).");
|
|
2678
2550
|
}
|
|
2679
|
-
|
|
2680
|
-
schedule: _schedule,
|
|
2681
|
-
tasks: _tasks,
|
|
2682
|
-
task_timeout_minutes: _tto,
|
|
2683
|
-
max_runtime_minutes: _max,
|
|
2684
|
-
user_memories: _um,
|
|
2685
|
-
pin_key_files: _pkf,
|
|
2686
|
-
...rest
|
|
2687
|
-
} = dreamer;
|
|
2688
|
-
warnings.push('Migrated legacy dreamer scheduling (schedule window / tasks array / user_memories / pin_key_files) → per-task "dreamer.tasks" in-memory (run `doctor` to persist).');
|
|
2689
|
-
return { ...rawConfig, dreamer: { ...rest, tasks } };
|
|
2551
|
+
return warnings;
|
|
2690
2552
|
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
const
|
|
2695
|
-
if (
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2553
|
+
function constrainProjectThresholdOverrides(args) {
|
|
2554
|
+
const warnings = [];
|
|
2555
|
+
const basePercentage = normalizeTrustedPercentageThresholds(args.trustedBaseConfig.execute_threshold_percentage);
|
|
2556
|
+
const baseTokens = normalizeTrustedTokenThresholds(args.trustedBaseConfig.execute_threshold_tokens);
|
|
2557
|
+
if ("execute_threshold_percentage" in args.projectRaw) {
|
|
2558
|
+
const projectValue = args.projectRaw.execute_threshold_percentage;
|
|
2559
|
+
if (isValidPercentageThreshold(projectValue)) {
|
|
2560
|
+
const constrained = clonePercentageThresholds(basePercentage);
|
|
2561
|
+
constrained.defaultValue = Math.max(basePercentage.defaultValue, projectValue);
|
|
2562
|
+
for (const [modelKey, threshold] of basePercentage.overrides) {
|
|
2563
|
+
const raisedThreshold = Math.max(threshold, projectValue);
|
|
2564
|
+
if (raisedThreshold === constrained.defaultValue) {
|
|
2565
|
+
constrained.overrides.delete(modelKey);
|
|
2566
|
+
} else {
|
|
2567
|
+
constrained.overrides.set(modelKey, raisedThreshold);
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
setMergedPercentageThreshold(args.mergedRaw, constrained);
|
|
2571
|
+
if (percentageThresholdsEqual(constrained, basePercentage)) {
|
|
2572
|
+
warnings.push(makeProjectThresholdWarning("execute_threshold_percentage", PERCENTAGE_THRESHOLD_REASON));
|
|
2573
|
+
}
|
|
2574
|
+
} else if (isPlainObject(projectValue)) {
|
|
2575
|
+
const constrained = clonePercentageThresholds(basePercentage);
|
|
2576
|
+
let touchedValidEntry = false;
|
|
2577
|
+
if (isValidPercentageThreshold(projectValue.default)) {
|
|
2578
|
+
touchedValidEntry = true;
|
|
2579
|
+
if (projectValue.default > basePercentage.defaultValue) {
|
|
2580
|
+
constrained.defaultValue = projectValue.default;
|
|
2581
|
+
} else {
|
|
2582
|
+
warnings.push(makeProjectThresholdWarning("execute_threshold_percentage.default", PERCENTAGE_THRESHOLD_REASON));
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
for (const [modelKey, rawValue] of Object.entries(projectValue)) {
|
|
2586
|
+
if (modelKey === "default")
|
|
2587
|
+
continue;
|
|
2588
|
+
if (!isValidPercentageThreshold(rawValue))
|
|
2589
|
+
continue;
|
|
2590
|
+
touchedValidEntry = true;
|
|
2591
|
+
const baseValue = basePercentage.overrides.get(modelKey) ?? basePercentage.defaultValue;
|
|
2592
|
+
if (rawValue > baseValue) {
|
|
2593
|
+
if (rawValue === constrained.defaultValue) {
|
|
2594
|
+
constrained.overrides.delete(modelKey);
|
|
2595
|
+
} else {
|
|
2596
|
+
constrained.overrides.set(modelKey, rawValue);
|
|
2597
|
+
}
|
|
2598
|
+
} else {
|
|
2599
|
+
warnings.push(makeProjectThresholdWarning(`execute_threshold_percentage.${modelKey}`, PERCENTAGE_THRESHOLD_REASON));
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
if (touchedValidEntry) {
|
|
2603
|
+
setMergedPercentageThreshold(args.mergedRaw, constrained);
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2707
2606
|
}
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2607
|
+
if ("execute_threshold_tokens" in args.projectRaw && isPlainObject(args.projectRaw.execute_threshold_tokens)) {
|
|
2608
|
+
const projectValue = args.projectRaw.execute_threshold_tokens;
|
|
2609
|
+
const constrained = cloneTokenThresholds(baseTokens);
|
|
2610
|
+
let touchedValidEntry = false;
|
|
2611
|
+
if (isValidTokenThreshold(projectValue.default)) {
|
|
2612
|
+
touchedValidEntry = true;
|
|
2613
|
+
if (baseTokens.defaultValue === undefined) {
|
|
2614
|
+
warnings.push(makeProjectThresholdWarning("execute_threshold_tokens.default", TOKEN_THRESHOLD_INTRODUCTION_REASON));
|
|
2615
|
+
} else if (projectValue.default > baseTokens.defaultValue) {
|
|
2616
|
+
constrained.defaultValue = projectValue.default;
|
|
2617
|
+
} else {
|
|
2618
|
+
warnings.push(makeProjectThresholdWarning("execute_threshold_tokens.default", TOKEN_THRESHOLD_REASON));
|
|
2619
|
+
}
|
|
2715
2620
|
}
|
|
2716
|
-
|
|
2717
|
-
|
|
2621
|
+
for (const [modelKey, rawValue] of Object.entries(projectValue)) {
|
|
2622
|
+
if (modelKey === "default")
|
|
2623
|
+
continue;
|
|
2624
|
+
if (!isValidTokenThreshold(rawValue))
|
|
2625
|
+
continue;
|
|
2626
|
+
touchedValidEntry = true;
|
|
2627
|
+
const baseValue = baseTokens.overrides.get(modelKey) ?? baseTokens.defaultValue;
|
|
2628
|
+
if (baseValue === undefined) {
|
|
2629
|
+
warnings.push(makeProjectThresholdWarning(`execute_threshold_tokens.${modelKey}`, TOKEN_THRESHOLD_INTRODUCTION_REASON));
|
|
2630
|
+
continue;
|
|
2631
|
+
}
|
|
2632
|
+
if (rawValue > baseValue) {
|
|
2633
|
+
if (rawValue === constrained.defaultValue) {
|
|
2634
|
+
constrained.overrides.delete(modelKey);
|
|
2635
|
+
} else {
|
|
2636
|
+
constrained.overrides.set(modelKey, rawValue);
|
|
2637
|
+
}
|
|
2638
|
+
} else {
|
|
2639
|
+
warnings.push(makeProjectThresholdWarning(`execute_threshold_tokens.${modelKey}`, TOKEN_THRESHOLD_REASON));
|
|
2640
|
+
}
|
|
2718
2641
|
}
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
const relocate = (key, dest, destLabel) => {
|
|
2722
|
-
if (!(key in exp))
|
|
2723
|
-
return;
|
|
2724
|
-
const oldValue = exp[key];
|
|
2725
|
-
const existing = dest[key];
|
|
2726
|
-
if (existing === undefined) {
|
|
2727
|
-
dest[key] = oldValue;
|
|
2728
|
-
warnings.push(`Migrated "experimental.${key}" → "${destLabel}${key}" in-memory (run \`doctor\` to persist).`);
|
|
2729
|
-
} else if (typeof oldValue === "object" && oldValue !== null && typeof existing === "object" && existing !== null) {
|
|
2730
|
-
dest[key] = {
|
|
2731
|
-
...oldValue,
|
|
2732
|
-
...existing
|
|
2733
|
-
};
|
|
2642
|
+
if (touchedValidEntry) {
|
|
2643
|
+
setMergedTokenThreshold(args.mergedRaw, constrained);
|
|
2734
2644
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2645
|
+
}
|
|
2646
|
+
if ("protected_tokens" in args.projectRaw) {
|
|
2647
|
+
const rawProject = args.projectRaw.protected_tokens;
|
|
2648
|
+
const projectVal = resolveProtectedTokensScalar(rawProject);
|
|
2649
|
+
const trustedUserVal = resolveProtectedTokensScalar(args.trustedBaseConfig.protected_tokens);
|
|
2650
|
+
if (projectVal !== undefined) {
|
|
2651
|
+
if (trustedUserVal !== undefined) {
|
|
2652
|
+
if (projectVal >= trustedUserVal) {
|
|
2653
|
+
args.mergedRaw.protected_tokens = projectVal;
|
|
2654
|
+
} else {
|
|
2655
|
+
args.mergedRaw.protected_tokens = trustedUserVal;
|
|
2656
|
+
warnings.push(makeProjectThresholdWarning("protected_tokens", PROTECTED_TOKENS_REASON));
|
|
2657
|
+
}
|
|
2658
|
+
} else {
|
|
2659
|
+
args.mergedRaw.protected_tokens = projectVal;
|
|
2660
|
+
}
|
|
2661
|
+
} else {
|
|
2662
|
+
if (trustedUserVal !== undefined) {
|
|
2663
|
+
args.mergedRaw.protected_tokens = trustedUserVal;
|
|
2664
|
+
} else {
|
|
2665
|
+
delete args.mergedRaw.protected_tokens;
|
|
2666
|
+
}
|
|
2667
|
+
warnings.push(makeProjectThresholdWarning("protected_tokens", PROTECTED_TOKENS_REASON));
|
|
2752
2668
|
}
|
|
2753
|
-
delete newExperimental.mural;
|
|
2754
2669
|
}
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2670
|
+
return warnings;
|
|
2671
|
+
}
|
|
2672
|
+
function normalizeEndpoint(value) {
|
|
2673
|
+
if (typeof value !== "string")
|
|
2674
|
+
return;
|
|
2675
|
+
const trimmed = value.trim().replace(/\/+$/, "");
|
|
2676
|
+
return trimmed.length > 0 ? trimmed.toLowerCase() : undefined;
|
|
2677
|
+
}
|
|
2678
|
+
function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
|
|
2679
|
+
const projectEmbedding = projectRaw.embedding;
|
|
2680
|
+
if (!isPlainObject(projectEmbedding))
|
|
2681
|
+
return [];
|
|
2682
|
+
const redirectsEndpoint = "endpoint" in projectEmbedding;
|
|
2683
|
+
if (!redirectsEndpoint)
|
|
2684
|
+
return [];
|
|
2685
|
+
const userEmbedding = userRaw?.embedding;
|
|
2686
|
+
if (isPlainObject(userEmbedding)) {
|
|
2687
|
+
const projectEndpoint = normalizeEndpoint(projectEmbedding.endpoint);
|
|
2688
|
+
const userEndpoint = normalizeEndpoint(userEmbedding.endpoint);
|
|
2689
|
+
if (projectEndpoint !== undefined && projectEndpoint === userEndpoint) {
|
|
2690
|
+
return [];
|
|
2767
2691
|
}
|
|
2768
|
-
delete newExperimental.user_memories;
|
|
2769
2692
|
}
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2693
|
+
const providesOwnKey = typeof projectEmbedding.api_key === "string" && projectEmbedding.api_key.length > 0;
|
|
2694
|
+
if (providesOwnKey)
|
|
2695
|
+
return [];
|
|
2696
|
+
const mergedEmbedding = mergedRaw.embedding;
|
|
2697
|
+
if (!isPlainObject(mergedEmbedding))
|
|
2698
|
+
return [];
|
|
2699
|
+
if (!("api_key" in mergedEmbedding))
|
|
2700
|
+
return [];
|
|
2701
|
+
delete mergedEmbedding.api_key;
|
|
2702
|
+
return [
|
|
2703
|
+
"Dropped inherited user embedding api_key because project config redirected " + "embedding.endpoint without supplying its own key (security: prevents key " + "exfiltration to a repository-chosen endpoint)."
|
|
2704
|
+
];
|
|
2705
|
+
}
|
|
2706
|
+
function projectContributionPath(projectRaw, issuePath) {
|
|
2707
|
+
let node = projectRaw;
|
|
2708
|
+
for (let index = 0;index < issuePath.length; index++) {
|
|
2709
|
+
const segment = String(issuePath[index]);
|
|
2710
|
+
if (!isPlainObject(node) || !Object.hasOwn(node, segment))
|
|
2711
|
+
return;
|
|
2712
|
+
node = node[segment];
|
|
2713
|
+
if (index === issuePath.length - 1 || !isPlainObject(node)) {
|
|
2714
|
+
return issuePath.slice(0, index + 1);
|
|
2784
2715
|
}
|
|
2785
|
-
delete newExperimental.pin_key_files;
|
|
2786
2716
|
}
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2717
|
+
return;
|
|
2718
|
+
}
|
|
2719
|
+
function displacedTrustedValue(trustedRaw, contribution) {
|
|
2720
|
+
let node = trustedRaw;
|
|
2721
|
+
for (let index = 0;index < contribution.length; index++) {
|
|
2722
|
+
const segment = String(contribution[index]);
|
|
2723
|
+
if (!isPlainObject(node) || !Object.hasOwn(node, segment))
|
|
2724
|
+
return;
|
|
2725
|
+
node = node[segment];
|
|
2726
|
+
if (index === contribution.length - 1 || !isPlainObject(node)) {
|
|
2727
|
+
return { path: contribution.slice(0, index + 1), value: node };
|
|
2728
|
+
}
|
|
2791
2729
|
}
|
|
2792
|
-
return
|
|
2730
|
+
return;
|
|
2793
2731
|
}
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2732
|
+
function defineOwnValue(target, key, value) {
|
|
2733
|
+
Object.defineProperty(target, key, {
|
|
2734
|
+
value,
|
|
2735
|
+
enumerable: true,
|
|
2736
|
+
configurable: true,
|
|
2737
|
+
writable: true
|
|
2738
|
+
});
|
|
2801
2739
|
}
|
|
2802
|
-
function
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2740
|
+
function writeOwnPath(root, path, value) {
|
|
2741
|
+
let node = root;
|
|
2742
|
+
for (let index = 0;index < path.length - 1; index++) {
|
|
2743
|
+
const segment = String(path[index]);
|
|
2744
|
+
const child = node[segment];
|
|
2745
|
+
if (!isPlainObject(child))
|
|
2746
|
+
return;
|
|
2747
|
+
const copy = { ...child };
|
|
2748
|
+
defineOwnValue(node, segment, copy);
|
|
2749
|
+
node = copy;
|
|
2750
|
+
}
|
|
2751
|
+
defineOwnValue(node, String(path[path.length - 1]), value);
|
|
2810
2752
|
}
|
|
2811
|
-
|
|
2753
|
+
var MAX_PROJECT_RESTORE_ROUNDS = 16;
|
|
2754
|
+
function restoreTrustedValuesOverInvalidProjectValues(args) {
|
|
2812
2755
|
const warnings = [];
|
|
2813
|
-
const
|
|
2814
|
-
const
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2756
|
+
const restoredTopLevelKeys = new Set;
|
|
2757
|
+
const restored = new Set;
|
|
2758
|
+
for (let round = 0;round < MAX_PROJECT_RESTORE_ROUNDS; round++) {
|
|
2759
|
+
let changed = false;
|
|
2760
|
+
for (const issuePath of args.collectIssuePaths(args.mergedRaw)) {
|
|
2761
|
+
const contribution = projectContributionPath(args.projectRaw, issuePath);
|
|
2762
|
+
if (contribution === undefined || contribution.length === 0)
|
|
2763
|
+
continue;
|
|
2764
|
+
const trusted = displacedTrustedValue(args.trustedRaw, contribution);
|
|
2765
|
+
if (trusted === undefined)
|
|
2766
|
+
continue;
|
|
2767
|
+
const key = trusted.path.map(String).join(".");
|
|
2768
|
+
if (restored.has(key))
|
|
2769
|
+
continue;
|
|
2770
|
+
writeOwnPath(args.mergedRaw, trusted.path, trusted.value);
|
|
2771
|
+
restored.add(key);
|
|
2772
|
+
restoredTopLevelKeys.add(String(trusted.path[0]));
|
|
2773
|
+
changed = true;
|
|
2774
|
+
warnings.push(`Ignoring invalid ${key} from project config and keeping the user-level value (security: a repository cannot reset user settings by supplying an invalid value).`);
|
|
2829
2775
|
}
|
|
2776
|
+
if (!changed)
|
|
2777
|
+
break;
|
|
2830
2778
|
}
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2779
|
+
return { warnings, restoredTopLevelKeys: [...restoredTopLevelKeys] };
|
|
2780
|
+
}
|
|
2781
|
+
var PROJECT_COMMAND_STRING_FIELDS = ["description", "agent", "model"];
|
|
2782
|
+
function wellFormedCommand(value) {
|
|
2783
|
+
if (!isPlainObject(value))
|
|
2784
|
+
return;
|
|
2785
|
+
if (typeof value.template !== "string" || value.template.trim().length === 0)
|
|
2786
|
+
return;
|
|
2787
|
+
const command = { template: value.template };
|
|
2788
|
+
for (const field of PROJECT_COMMAND_STRING_FIELDS) {
|
|
2789
|
+
if (value[field] === undefined)
|
|
2790
|
+
continue;
|
|
2791
|
+
if (typeof value[field] !== "string")
|
|
2792
|
+
return;
|
|
2793
|
+
command[field] = value[field];
|
|
2838
2794
|
}
|
|
2839
|
-
if (
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
projectBase: withoutProfileFields(args.projectRaw),
|
|
2844
|
-
overlay: {},
|
|
2845
|
-
warnings
|
|
2846
|
-
};
|
|
2795
|
+
if (value.subtask !== undefined) {
|
|
2796
|
+
if (typeof value.subtask !== "boolean")
|
|
2797
|
+
return;
|
|
2798
|
+
command.subtask = value.subtask;
|
|
2847
2799
|
}
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
};
|
|
2800
|
+
return command;
|
|
2801
|
+
}
|
|
2802
|
+
function constrainProjectCommands(args) {
|
|
2803
|
+
if (!("command" in args.projectRaw))
|
|
2804
|
+
return [];
|
|
2805
|
+
const warnings = [];
|
|
2806
|
+
const trustedCommands = isPlainObject(args.trustedRaw.command) ? args.trustedRaw.command : undefined;
|
|
2807
|
+
const merged = { ...trustedCommands ?? {} };
|
|
2808
|
+
const projectCommands = args.projectRaw.command;
|
|
2809
|
+
if (!isPlainObject(projectCommands)) {
|
|
2810
|
+
warnings.push("Ignoring command from project config (it must be an object of named commands).");
|
|
2811
|
+
} else {
|
|
2812
|
+
for (const [name, value] of Object.entries(projectCommands)) {
|
|
2813
|
+
if (trustedCommands && Object.hasOwn(trustedCommands, name)) {
|
|
2814
|
+
warnings.push(`Ignoring command.${name} from project config (security: a repository cannot replace a command defined in user config).`);
|
|
2815
|
+
continue;
|
|
2816
|
+
}
|
|
2817
|
+
if (args.reservedNames.includes(name)) {
|
|
2818
|
+
warnings.push(`Ignoring command.${name} from project config (security: a repository cannot replace a built-in Magic Context command).`);
|
|
2819
|
+
continue;
|
|
2820
|
+
}
|
|
2821
|
+
const command = wellFormedCommand(value);
|
|
2822
|
+
if (!command) {
|
|
2823
|
+
warnings.push(`Ignoring command.${name} from project config (it needs a non-empty string template; description, agent and model must be strings and subtask a boolean).`);
|
|
2824
|
+
continue;
|
|
2825
|
+
}
|
|
2826
|
+
Object.defineProperty(merged, name, {
|
|
2827
|
+
value: command,
|
|
2828
|
+
enumerable: true,
|
|
2829
|
+
configurable: true,
|
|
2830
|
+
writable: true
|
|
2831
|
+
});
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
if (Object.keys(merged).length === 0)
|
|
2835
|
+
delete args.mergedRaw.command;
|
|
2836
|
+
else
|
|
2837
|
+
args.mergedRaw.command = merged;
|
|
2838
|
+
return warnings;
|
|
2856
2839
|
}
|
|
2857
2840
|
|
|
2858
2841
|
// src/config/prune-config-leaf.ts
|
|
@@ -3566,12 +3549,17 @@ function misplacedAgentModelWarnings(rawConfig) {
|
|
|
3566
3549
|
function warnProtectedTagsDeprecationOnce() {
|
|
3567
3550
|
if (!warnedProtectedTagsDeprecation) {
|
|
3568
3551
|
warnedProtectedTagsDeprecation = true;
|
|
3569
|
-
|
|
3552
|
+
log2("[magic-context] protected_tags is deprecated and ignored; use protected_tokens instead.");
|
|
3570
3553
|
}
|
|
3571
3554
|
}
|
|
3572
3555
|
function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
3573
3556
|
const preMigrationWarnings = [];
|
|
3574
3557
|
const configWithoutRemovedAgent = stripRemovedAgentConfig(rawConfig, preMigrationWarnings);
|
|
3558
|
+
if (Object.hasOwn(rawConfig, "clear_reasoning_age")) {
|
|
3559
|
+
const warning = "clear_reasoning_age is deprecated and ignored. Magic Context now keeps reasoning up to a token budget, keep_reasoning_tokens (default 10,000). Remove the key, or set keep_reasoning_tokens to a token count.";
|
|
3560
|
+
preMigrationWarnings.push(warning);
|
|
3561
|
+
log2(`[magic-context] ${warning}`);
|
|
3562
|
+
}
|
|
3575
3563
|
if (Object.hasOwn(rawConfig, "protected_tags")) {
|
|
3576
3564
|
warnProtectedTagsDeprecationOnce();
|
|
3577
3565
|
preMigrationWarnings.push("protected_tags is deprecated and ignored; use protected_tokens instead.");
|
|
@@ -3581,6 +3569,7 @@ function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
|
3581
3569
|
}
|
|
3582
3570
|
preMigrationWarnings.push(...misplacedAgentModelWarnings(rawConfig));
|
|
3583
3571
|
const migratedExperimental = migrateLegacyExperimental(configWithoutRemovedAgent, preMigrationWarnings);
|
|
3572
|
+
warnDeprecatedMuralModel(migratedExperimental, preMigrationWarnings);
|
|
3584
3573
|
const migratedDreamer = migrateDreamerV2(migratedExperimental, preMigrationWarnings);
|
|
3585
3574
|
const migrated = migrateLegacyAgentEnabledInMemory(migratedDreamer, preMigrationWarnings);
|
|
3586
3575
|
const parsed = MagicContextConfigSchema.safeParse(migrated);
|