@cortexkit/opencode-magic-context 0.41.4 → 0.42.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/README.md +21 -3
- package/dist/agents/hidden-agent-registrations.d.ts +1 -3
- package/dist/agents/hidden-agent-registrations.d.ts.map +1 -1
- package/dist/agents/magic-context-prompt.d.ts +1 -1
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/agents/permissions.d.ts +1 -22
- package/dist/agents/permissions.d.ts.map +1 -1
- package/dist/config/agent-disable.d.ts +0 -5
- package/dist/config/agent-disable.d.ts.map +1 -1
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/migrate-config-location.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +17 -0
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/removed-agent-config.d.ts +8 -0
- package/dist/config/removed-agent-config.d.ts.map +1 -0
- package/dist/config/schema/magic-context.d.ts +23 -201
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-ejkc9sjn.js → conflict-warning-hook-6p3xqeac.js} +3 -3
- package/dist/{derive-budgets-bc366cz8.js → derive-budgets-s2pgnnm4.js} +1 -1
- package/dist/features/builtin-commands/commands.d.ts +0 -4
- package/dist/features/builtin-commands/commands.d.ts.map +1 -1
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +7 -0
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
- package/dist/features/magic-context/context-authority.d.ts +31 -4
- package/dist/features/magic-context/context-authority.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts +19 -9
- package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts +4 -0
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/sweep-coordinator.d.ts.map +1 -1
- package/dist/features/magic-context/index.d.ts +0 -1
- package/dist/features/magic-context/index.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts +13 -0
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-synapse.d.ts +43 -10
- package/dist/features/magic-context/memory/embedding-synapse.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity.d.ts +1 -0
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/promotion.d.ts +7 -1
- package/dist/features/magic-context/memory/promotion.d.ts.map +1 -1
- package/dist/features/magic-context/merged-reasoning-decisions.d.ts +6 -0
- package/dist/features/magic-context/merged-reasoning-decisions.d.ts.map +1 -0
- package/dist/features/magic-context/message-fts-rowid-map.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-async.d.ts +12 -0
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
- package/dist/features/magic-context/mural/render-trigger.d.ts +6 -0
- package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
- package/dist/features/magic-context/no-content-compartment.d.ts +12 -0
- package/dist/features/magic-context/no-content-compartment.d.ts.map +1 -0
- package/dist/features/magic-context/pi-content-decisions.d.ts +9 -0
- package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -0
- package/dist/features/magic-context/project-docs-hash.d.ts +4 -0
- package/dist/features/magic-context/project-docs-hash.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts +13 -4
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/protection-window.d.ts +79 -0
- package/dist/features/magic-context/protection-window.d.ts.map +1 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
- package/dist/features/magic-context/shadow-backfill-state.d.ts +26 -0
- package/dist/features/magic-context/shadow-backfill-state.d.ts.map +1 -0
- package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +4 -0
- package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
- package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-embedding-measurements.d.ts +2 -2
- package/dist/features/magic-context/storage-embedding-measurements.d.ts.map +1 -1
- package/dist/features/magic-context/storage-historian-runs.d.ts +4 -0
- package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
- package/dist/features/magic-context/storage-memory-mutation-log.d.ts +1 -0
- package/dist/features/magic-context/storage-memory-mutation-log.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +79 -13
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage-native-replay.d.ts +29 -0
- package/dist/features/magic-context/storage-native-replay.d.ts.map +1 -0
- package/dist/features/magic-context/storage-notes.d.ts +6 -0
- package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
- package/dist/features/magic-context/storage-replay-document.d.ts +33 -0
- package/dist/features/magic-context/storage-replay-document.d.ts.map +1 -0
- package/dist/features/magic-context/storage-subagent-invocations.d.ts +1 -1
- package/dist/features/magic-context/storage-subagent-invocations.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +19 -11
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +3 -3
- 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/tagger.d.ts +13 -0
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/tool-owner-backfill.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
- package/dist/features/magic-context/workspaces.d.ts.map +1 -1
- package/dist/hooks/magic-context/apply-operations.d.ts +11 -5
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/cache-busting-signals.d.ts +9 -1
- package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
- package/dist/hooks/magic-context/caveman-cleanup.d.ts +1 -1
- package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
- package/dist/hooks/magic-context/child-session-spawn.d.ts +3 -3
- package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +1 -10
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +10 -21
- package/dist/hooks/magic-context/compartment-runner-drop-queue.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/ctx-reduce-nudge.d.ts +26 -2
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
- package/dist/hooks/magic-context/decay-render.d.ts.map +1 -1
- package/dist/hooks/magic-context/dropped-input-guard.d.ts +9 -0
- package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -0
- package/dist/hooks/magic-context/emergency-drop.d.ts +6 -1
- package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts +0 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-payloads.d.ts +7 -6
- package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/format-embed-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +7 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts +3 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +13 -4
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +14 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/live-session-state.d.ts +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +34 -0
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-state-sync-timing.d.ts +21 -0
- package/dist/hooks/magic-context/module-state-sync-timing.d.ts.map +1 -0
- package/dist/hooks/magic-context/module-state-sync.d.ts +21 -7
- package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-transport.d.ts +12 -0
- package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-wire.d.ts +8 -0
- package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
- package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
- package/dist/hooks/magic-context/persist-filtered-noise.d.ts +5 -0
- package/dist/hooks/magic-context/persist-filtered-noise.d.ts.map +1 -0
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts +6 -0
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +18 -18
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +22 -12
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +8 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +10 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +74 -9
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts +11 -10
- package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +7 -0
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/supersession-reclaim.d.ts +13 -0
- package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +2 -3
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +8 -3
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-context-state.d.ts +7 -1
- package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +11 -4
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +7 -2
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/upgrade-reminder.d.ts +7 -9
- package/dist/hooks/magic-context/upgrade-reminder.d.ts.map +1 -1
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
- package/dist/index-1974jvn3.js +783 -0
- package/dist/{index-4avmwfp5.js → index-36wd1d6k.js} +6 -29
- package/dist/{index-0y2mcg5y.js → index-c9hamh36.js} +18332 -16226
- package/dist/{index-fz104x1j.js → index-jmtjh2d3.js} +3 -3
- package/dist/{index-q264erdp.js → index-nqgjwfzn.js} +70 -38
- package/dist/{index-mjv9je4e.js → index-xdtge3y2.js} +45 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6199 -5088
- package/dist/plugin/conflict-warning-hook.d.ts +5 -6
- package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
- package/dist/plugin/dream-timer.d.ts +1 -0
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/embedding-routing.d.ts +4 -1
- package/dist/plugin/embedding-routing.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +16 -2
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +31 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/rust-tool-backends.d.ts +1 -0
- package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-q98r6rga.js → recomp-orchestrator-3atsasjy.js} +5 -5
- package/dist/{send-session-notification-hdh02wy9.js → send-session-notification-1qeqkswb.js} +6 -4
- package/dist/shared/child-session-teardown.d.ts +34 -0
- package/dist/shared/child-session-teardown.d.ts.map +1 -0
- package/dist/shared/keep-subagents.d.ts +1 -1
- package/dist/shared/keep-subagents.d.ts.map +1 -1
- package/dist/shared/model-suggestion-retry.d.ts +1 -1
- package/dist/shared/opencode-db-path.d.ts +24 -0
- package/dist/shared/opencode-db-path.d.ts.map +1 -0
- package/dist/shared/prompt-surface-runtime.d.ts +10 -5
- package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
- package/dist/shared/resolve-fallbacks.d.ts +1 -1
- package/dist/shared/rpc-types.d.ts +111 -0
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +42 -0
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/status-detail-text.d.ts.map +1 -1
- package/dist/shared/subagent-runner.d.ts +17 -10
- package/dist/shared/subagent-runner.d.ts.map +1 -1
- package/dist/shared/tag-transcript.d.ts.map +1 -1
- package/dist/shared/transcript.d.ts +6 -0
- package/dist/shared/transcript.d.ts.map +1 -1
- package/dist/shared/window-geometry.d.ts +23 -0
- package/dist/shared/window-geometry.d.ts.map +1 -1
- package/dist/shared/write-transaction-timing.d.ts +1 -1
- package/dist/shared/write-transaction-timing.d.ts.map +1 -1
- package/dist/{storage-meta-session-dvwfw778.js → storage-meta-session-e6g0mmec.js} +2 -2
- package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
- package/dist/tools/ctx-memory/verification-recording.d.ts.map +1 -1
- package/dist/tools/ctx-note/constants.d.ts +1 -1
- package/dist/tools/ctx-note/constants.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/types.d.ts +1 -0
- package/dist/tools/ctx-note/types.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts +10 -1
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/constants.d.ts +1 -1
- package/dist/tools/ctx-search/constants.d.ts.map +1 -1
- package/dist/tools/light-descriptions.d.ts +2 -2
- package/dist/tools/light-descriptions.d.ts.map +1 -1
- package/package.json +2 -3
- package/src/agents/hidden-agent-registrations.ts +3 -15
- package/src/agents/magic-context-prompt.test.ts +7 -5
- package/src/agents/magic-context-prompt.ts +22 -30
- package/src/agents/permissions.test.ts +1 -42
- package/src/agents/permissions.ts +1 -24
- package/src/config/agent-disable.ts +5 -22
- package/src/config/index.test.ts +126 -15
- package/src/config/index.ts +41 -6
- package/src/config/latch-permanence-guard.test.ts +4 -0
- package/src/config/migrate-config-location.test.ts +39 -6
- package/src/config/migrate-config-location.ts +18 -31
- package/src/config/profiles.ts +1 -1
- package/src/config/project-security.hostile-matrix.test.ts +0 -8
- package/src/config/project-security.test.ts +11 -22
- package/src/config/project-security.ts +103 -9
- package/src/config/protected-tokens.test.ts +235 -0
- package/src/config/removed-agent-config.ts +45 -0
- package/src/config/removed-agent-source-fence.test.ts +56 -0
- package/src/config/schema/magic-context.test.ts +21 -42
- package/src/config/schema/magic-context.ts +46 -37
- package/src/shared/child-session-teardown.test.ts +218 -0
- package/src/shared/child-session-teardown.ts +66 -0
- package/src/shared/keep-subagents.ts +9 -14
- package/src/shared/model-suggestion-retry.ts +1 -1
- package/src/shared/opencode-db-path.test.ts +196 -0
- package/src/shared/opencode-db-path.ts +215 -0
- package/src/shared/prompt-surface-a1-golden.md +50 -35
- package/src/shared/prompt-surface-runtime.test.ts +28 -0
- package/src/shared/prompt-surface-runtime.ts +22 -5
- package/src/shared/resolve-fallbacks.ts +1 -1
- package/src/shared/rpc-types.ts +118 -0
- package/src/shared/session-messages-bounded.test.ts +1 -1
- package/src/shared/sqlite-import-fence.test.ts +19 -0
- package/src/shared/sqlite.test.ts +27 -1
- package/src/shared/sqlite.ts +204 -1
- package/src/shared/status-detail-text.test.ts +6 -3
- package/src/shared/status-detail-text.ts +15 -0
- package/src/shared/subagent-runner.ts +17 -10
- package/src/shared/tag-transcript.ts +33 -21
- package/src/shared/transcript.ts +7 -0
- package/src/shared/window-geometry.test.ts +44 -0
- package/src/shared/window-geometry.ts +89 -11
- package/src/shared/write-transaction-attribution.test.ts +241 -0
- package/src/shared/write-transaction-timing.ts +2 -1
- package/src/tui/index.tsx +3 -3
- package/src/tui/slots/sidebar-content.tsx +12 -7
- package/src/tui-compiled/index.tsx +3 -3
- package/src/tui-compiled/slots/sidebar-content.tsx +301 -305
- package/dist/agents/sidekick.d.ts +0 -2
- package/dist/agents/sidekick.d.ts.map +0 -1
- package/dist/features/magic-context/defaults.d.ts +0 -2
- package/dist/features/magic-context/defaults.d.ts.map +0 -1
- package/dist/features/magic-context/sidekick/agent.d.ts +0 -14
- package/dist/features/magic-context/sidekick/agent.d.ts.map +0 -1
- package/dist/features/magic-context/sidekick/core.d.ts +0 -38
- package/dist/features/magic-context/sidekick/core.d.ts.map +0 -1
- package/dist/features/magic-context/sidekick/index.d.ts +0 -3
- package/dist/features/magic-context/sidekick/index.d.ts.map +0 -1
- package/dist/hooks/magic-context/boundary-execution.d.ts +0 -27
- package/dist/hooks/magic-context/boundary-execution.d.ts.map +0 -1
- package/dist/index-raatkvw5.js +0 -360
- package/src/agents/sidekick.ts +0 -1
- package/src/features/magic-context/defaults.ts +0 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const REMOVED_AGENT_CONFIG_KEY = "sidekick";
|
|
2
|
+
|
|
3
|
+
export const REMOVED_AGENT_CONFIG_WARNING = `The "${REMOVED_AGENT_CONFIG_KEY}" configuration was removed and is ignored.`;
|
|
4
|
+
|
|
5
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Remove the retired agent block before profile resolution or schema parsing.
|
|
11
|
+
* The same warning array may be shared across user and project layers so one
|
|
12
|
+
* load reports the removal once while preserving every unrelated setting.
|
|
13
|
+
*/
|
|
14
|
+
export function stripRemovedAgentConfig(
|
|
15
|
+
rawConfig: Record<string, unknown>,
|
|
16
|
+
warnings: string[],
|
|
17
|
+
): Record<string, unknown> {
|
|
18
|
+
let removed = false;
|
|
19
|
+
const patched = { ...rawConfig };
|
|
20
|
+
|
|
21
|
+
if (Object.hasOwn(patched, REMOVED_AGENT_CONFIG_KEY)) {
|
|
22
|
+
delete patched[REMOVED_AGENT_CONFIG_KEY];
|
|
23
|
+
removed = true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (isPlainObject(patched.profiles)) {
|
|
27
|
+
const profiles = { ...patched.profiles };
|
|
28
|
+
let profilesChanged = false;
|
|
29
|
+
for (const [name, value] of Object.entries(profiles)) {
|
|
30
|
+
if (!isPlainObject(value) || !Object.hasOwn(value, REMOVED_AGENT_CONFIG_KEY)) continue;
|
|
31
|
+
const profile = { ...value };
|
|
32
|
+
delete profile[REMOVED_AGENT_CONFIG_KEY];
|
|
33
|
+
profiles[name] = profile;
|
|
34
|
+
profilesChanged = true;
|
|
35
|
+
removed = true;
|
|
36
|
+
}
|
|
37
|
+
if (profilesChanged) patched.profiles = profiles;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (removed && !warnings.includes(REMOVED_AGENT_CONFIG_WARNING)) {
|
|
41
|
+
warnings.push(REMOVED_AGENT_CONFIG_WARNING);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return removed ? patched : rawConfig;
|
|
45
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from "bun:test";
|
|
4
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
5
|
+
import { join, relative } from "node:path";
|
|
6
|
+
|
|
7
|
+
const RETIRED_AGENT_NAME = ["side", "kick"].join("");
|
|
8
|
+
const RETIRED_AGENT_PATTERN = new RegExp(RETIRED_AGENT_NAME, "gi");
|
|
9
|
+
const REPO_ROOT = join(__dirname, "..", "..", "..", "..");
|
|
10
|
+
const WARNING_SOURCE = join(
|
|
11
|
+
REPO_ROOT,
|
|
12
|
+
"packages",
|
|
13
|
+
"plugin",
|
|
14
|
+
"src",
|
|
15
|
+
"config",
|
|
16
|
+
"removed-agent-config.ts",
|
|
17
|
+
);
|
|
18
|
+
const SOURCE_ROOTS = [
|
|
19
|
+
join(REPO_ROOT, "packages", "plugin", "src"),
|
|
20
|
+
join(REPO_ROOT, "packages", "pi-plugin", "src"),
|
|
21
|
+
join(REPO_ROOT, "packages", "cli", "src"),
|
|
22
|
+
join(REPO_ROOT, "packages", "dashboard", "src"),
|
|
23
|
+
join(REPO_ROOT, "packages", "dashboard", "src-tauri", "src"),
|
|
24
|
+
];
|
|
25
|
+
const SOURCE_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".rs", ".json"]);
|
|
26
|
+
|
|
27
|
+
function sourceFiles(directory: string, files: string[] = []): string[] {
|
|
28
|
+
for (const entry of readdirSync(directory)) {
|
|
29
|
+
if (entry === "node_modules" || entry === "dist") continue;
|
|
30
|
+
const path = join(directory, entry);
|
|
31
|
+
const stat = statSync(path);
|
|
32
|
+
if (stat.isDirectory()) {
|
|
33
|
+
sourceFiles(path, files);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const extension = entry.slice(entry.lastIndexOf("."));
|
|
37
|
+
if (stat.isFile() && SOURCE_EXTENSIONS.has(extension)) files.push(path);
|
|
38
|
+
}
|
|
39
|
+
return files;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe("retired agent source fence", () => {
|
|
43
|
+
it("keeps only the removed-config warning key literal", () => {
|
|
44
|
+
const offenses: string[] = [];
|
|
45
|
+
for (const file of SOURCE_ROOTS.flatMap((root) => sourceFiles(root))) {
|
|
46
|
+
const matches = readFileSync(file, "utf8").match(RETIRED_AGENT_PATTERN) ?? [];
|
|
47
|
+
const allowed = file === WARNING_SOURCE && matches.length === 1;
|
|
48
|
+
if (!allowed && matches.length > 0) {
|
|
49
|
+
offenses.push(`${relative(REPO_ROOT, file)} (${matches.length})`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
expect(offenses).toEqual([]);
|
|
54
|
+
expect(readFileSync(WARNING_SOURCE, "utf8").match(RETIRED_AGENT_PATTERN)).toHaveLength(1);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -23,7 +23,6 @@ describe("MagicContextConfigSchema", () => {
|
|
|
23
23
|
cache_ttl: "5m",
|
|
24
24
|
prompt_surface: { default: "full" },
|
|
25
25
|
execute_threshold_percentage: 65,
|
|
26
|
-
protected_tags: 20,
|
|
27
26
|
clear_reasoning_age: 50,
|
|
28
27
|
history_budget_percentage: DEFAULT_HISTORY_BUDGET_PERCENTAGE,
|
|
29
28
|
historian_timeout_ms: DEFAULT_HISTORIAN_TIMEOUT_MS,
|
|
@@ -46,7 +45,6 @@ describe("MagicContextConfigSchema", () => {
|
|
|
46
45
|
expect(result.historian_timeout_ms).toBeGreaterThanOrEqual(10 * 60_000);
|
|
47
46
|
expect(result.historian).toBeUndefined();
|
|
48
47
|
expect(result.dreamer).toBeUndefined();
|
|
49
|
-
expect(result.sidekick).toBeUndefined();
|
|
50
48
|
expect(result.pi).toBeUndefined();
|
|
51
49
|
expect(result.mural).toEqual({ enabled: false });
|
|
52
50
|
});
|
|
@@ -107,6 +105,7 @@ describe("MagicContextConfigSchema", () => {
|
|
|
107
105
|
},
|
|
108
106
|
temporal_awareness: false,
|
|
109
107
|
keep_subagents: false,
|
|
108
|
+
debug_rpc: false,
|
|
110
109
|
todowrite: {
|
|
111
110
|
enabled: false,
|
|
112
111
|
overlay: false,
|
|
@@ -145,15 +144,6 @@ describe("MagicContextConfigSchema", () => {
|
|
|
145
144
|
pi: {
|
|
146
145
|
subagent_extensions: ["@example/provider", "./extensions/local.ts"],
|
|
147
146
|
},
|
|
148
|
-
sidekick: {
|
|
149
|
-
disable: false,
|
|
150
|
-
model: "qwen-test",
|
|
151
|
-
fallback_models: ["qwen-fallback"],
|
|
152
|
-
temperature: 0.1,
|
|
153
|
-
variant: "fast",
|
|
154
|
-
timeout_ms: 12_000,
|
|
155
|
-
system_prompt: "Custom prompt",
|
|
156
|
-
},
|
|
157
147
|
compaction: {
|
|
158
148
|
enabled: true,
|
|
159
149
|
},
|
|
@@ -177,19 +167,6 @@ describe("MagicContextConfigSchema", () => {
|
|
|
177
167
|
).toBe(false);
|
|
178
168
|
});
|
|
179
169
|
|
|
180
|
-
it("applies sidekick defaults when the object is present", () => {
|
|
181
|
-
const result = MagicContextConfigSchema.parse({
|
|
182
|
-
sidekick: {
|
|
183
|
-
model: "github-copilot/gpt-5.4",
|
|
184
|
-
},
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
expect(result.sidekick).toEqual({
|
|
188
|
-
model: "github-copilot/gpt-5.4",
|
|
189
|
-
timeout_ms: 30000,
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
170
|
it("accepts disable on hidden agents and strips deprecated top-level enabled", () => {
|
|
194
171
|
const result = MagicContextConfigSchema.parse({
|
|
195
172
|
historian: { disable: true },
|
|
@@ -203,14 +180,11 @@ describe("MagicContextConfigSchema", () => {
|
|
|
203
180
|
"maintain-docs": { schedule: "0 * * * *" },
|
|
204
181
|
},
|
|
205
182
|
},
|
|
206
|
-
sidekick: { disable: true, enabled: true },
|
|
207
183
|
});
|
|
208
184
|
|
|
209
185
|
expect(result.historian?.disable).toBe(true);
|
|
210
186
|
expect(result.dreamer?.disable).toBe(true);
|
|
211
|
-
expect(result.sidekick?.disable).toBe(true);
|
|
212
187
|
expect("enabled" in (result.dreamer as Record<string, unknown>)).toBe(false);
|
|
213
|
-
expect("enabled" in (result.sidekick as Record<string, unknown>)).toBe(false);
|
|
214
188
|
expect(result.dreamer?.tasks["review-user-memories"].schedule).toBe("");
|
|
215
189
|
expect(result.dreamer?.tasks["maintain-docs"].schedule).toBe("0 * * * *");
|
|
216
190
|
expect(result.dreamer?.tasks["classify-memories"].schedule).toBe("0 6 * * *");
|
|
@@ -353,10 +327,6 @@ describe("MagicContextConfigSchema", () => {
|
|
|
353
327
|
thinking_level: "inherit",
|
|
354
328
|
},
|
|
355
329
|
},
|
|
356
|
-
sidekick: {
|
|
357
|
-
model: "anthropic/work-sidekick",
|
|
358
|
-
fallback_models: ["openai/work-sidekick-fallback"],
|
|
359
|
-
},
|
|
360
330
|
},
|
|
361
331
|
},
|
|
362
332
|
});
|
|
@@ -376,7 +346,6 @@ describe("MagicContextConfigSchema", () => {
|
|
|
376
346
|
{ model: "opencode/work-historian-fallback", thinking_level: "inherit" },
|
|
377
347
|
]);
|
|
378
348
|
expect(result.profiles?.work?.dreamer?.omp?.thinking_level).toBe("inherit");
|
|
379
|
-
expect(result.profiles?.work?.sidekick?.model).toBe("anthropic/work-sidekick");
|
|
380
349
|
});
|
|
381
350
|
|
|
382
351
|
it("rejects timeout_minutes in a dreamer profile", () => {
|
|
@@ -432,7 +401,7 @@ describe("MagicContextConfigSchema", () => {
|
|
|
432
401
|
},
|
|
433
402
|
},
|
|
434
403
|
{ work: { dreamer: { tasks: { verify: { schedule: "0 3 * * *" } } } } },
|
|
435
|
-
{ work: {
|
|
404
|
+
{ work: { dreamer: { timeout_ms: 60_000 } } },
|
|
436
405
|
];
|
|
437
406
|
|
|
438
407
|
for (const profiles of profilesWithExcludedFields) {
|
|
@@ -667,17 +636,27 @@ describe("MagicContextConfigSchema", () => {
|
|
|
667
636
|
).toThrow();
|
|
668
637
|
});
|
|
669
638
|
|
|
670
|
-
it("
|
|
671
|
-
expect(
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
expect(
|
|
639
|
+
it("accepts protected_tags at any value including 0 and 101 as deprecated inert key", () => {
|
|
640
|
+
expect(MagicContextConfigSchema.parse({ protected_tags: 101 }).protected_tags).toBe(
|
|
641
|
+
101,
|
|
642
|
+
);
|
|
643
|
+
expect(MagicContextConfigSchema.parse({ protected_tags: 0 }).protected_tags).toBe(0);
|
|
644
|
+
expect(MagicContextConfigSchema.parse({ protected_tags: 20 }).protected_tags).toBe(20);
|
|
676
645
|
});
|
|
677
646
|
|
|
678
|
-
it("
|
|
679
|
-
expect(MagicContextConfigSchema.parse({
|
|
680
|
-
expect(MagicContextConfigSchema.parse({
|
|
647
|
+
it("enforces protected_tokens override range at both ends", () => {
|
|
648
|
+
expect(() => MagicContextConfigSchema.parse({ protected_tokens: 3999 })).toThrow();
|
|
649
|
+
expect(() => MagicContextConfigSchema.parse({ protected_tokens: 1_000_001 })).toThrow();
|
|
650
|
+
expect(() => MagicContextConfigSchema.parse({ protected_tokens: 30000.5 })).toThrow();
|
|
651
|
+
expect(
|
|
652
|
+
MagicContextConfigSchema.parse({ protected_tokens: 4000 }).protected_tokens,
|
|
653
|
+
).toBe(4000);
|
|
654
|
+
expect(
|
|
655
|
+
MagicContextConfigSchema.parse({ protected_tokens: 1_000_000 }).protected_tokens,
|
|
656
|
+
).toBe(1_000_000);
|
|
657
|
+
expect(
|
|
658
|
+
MagicContextConfigSchema.parse({ protected_tokens: 30000 }).protected_tokens,
|
|
659
|
+
).toBe(30000);
|
|
681
660
|
});
|
|
682
661
|
|
|
683
662
|
it("rejects clear_reasoning_age below minimum", () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { isValidLanguageCode } from "../../agents/language-directive";
|
|
4
|
-
import { DEFAULT_PROTECTED_TAGS } from "../../features/magic-context/defaults";
|
|
5
4
|
import { isValidCron } from "../../features/magic-context/dreamer/cron";
|
|
6
5
|
import type {
|
|
7
6
|
AGENTIC_DREAM_TASKS,
|
|
@@ -446,27 +445,15 @@ const ProfileDreamerSchema = z
|
|
|
446
445
|
omp: ProfileOmpModelBlockSchema.optional(),
|
|
447
446
|
})
|
|
448
447
|
.strict();
|
|
449
|
-
const ProfileSidekickSchema = AgentOverrideConfigSchema.pick({
|
|
450
|
-
model: true,
|
|
451
|
-
fallback_models: true,
|
|
452
|
-
variant: true,
|
|
453
|
-
})
|
|
454
|
-
.extend({
|
|
455
|
-
thinking_level: PiThinkingLevelSchema.describe(
|
|
456
|
-
"Pi thinking level for the sidekick model selection.",
|
|
457
|
-
),
|
|
458
|
-
})
|
|
459
|
-
.strict();
|
|
460
448
|
|
|
461
449
|
export const ConfigProfileSchema = z
|
|
462
450
|
.object({
|
|
463
451
|
historian: ProfileHistorianSchema.optional(),
|
|
464
452
|
dreamer: ProfileDreamerSchema.optional(),
|
|
465
|
-
sidekick: ProfileSidekickSchema.optional(),
|
|
466
453
|
})
|
|
467
454
|
.strict()
|
|
468
455
|
.describe(
|
|
469
|
-
"User-owned model-selection overlay. Only historian/dreamer harness model blocks
|
|
456
|
+
"User-owned model-selection overlay. Only historian/dreamer harness model blocks are allowed.",
|
|
470
457
|
);
|
|
471
458
|
export type ConfigProfile = z.infer<typeof ConfigProfileSchema>;
|
|
472
459
|
|
|
@@ -626,15 +613,6 @@ export const DreamerConfigSchema = AgentMetadataSchema.extend({
|
|
|
626
613
|
});
|
|
627
614
|
export type DreamerConfig = z.infer<typeof DreamerConfigSchema>;
|
|
628
615
|
|
|
629
|
-
export const SidekickConfigSchema = AgentOverrideConfigSchema.extend({
|
|
630
|
-
timeout_ms: z.number().default(30000).describe("Timeout for sidekick calls in milliseconds"),
|
|
631
|
-
system_prompt: z.string().optional().describe("Custom system prompt for sidekick"),
|
|
632
|
-
thinking_level: PiThinkingLevelSchema.describe(
|
|
633
|
-
"Pi only: explicit thinking level for sidekick subagent invocations. See historian.pi.thinking_level.",
|
|
634
|
-
),
|
|
635
|
-
}).optional();
|
|
636
|
-
export type SidekickConfig = NonNullable<z.infer<typeof SidekickConfigSchema>>;
|
|
637
|
-
|
|
638
616
|
/**
|
|
639
617
|
* Historian metadata remains harness-independent. Only model resolution moves to
|
|
640
618
|
* the strict opencode, pi, and omp blocks; two_pass and disallowed_tools stay here.
|
|
@@ -871,7 +849,8 @@ export interface MagicContextConfig {
|
|
|
871
849
|
* this overrides `execute_threshold_percentage` for that model. Useful for hard caps
|
|
872
850
|
* matching provider input limits. Values above 90% × context_limit are clamped with a warning. */
|
|
873
851
|
execute_threshold_tokens?: { default?: number; [modelKey: string]: number | undefined };
|
|
874
|
-
|
|
852
|
+
protected_tokens?: number;
|
|
853
|
+
protected_tags?: number;
|
|
875
854
|
clear_reasoning_age: number;
|
|
876
855
|
history_budget_percentage: number;
|
|
877
856
|
historian_timeout_ms: number;
|
|
@@ -917,10 +896,12 @@ export interface MagicContextConfig {
|
|
|
917
896
|
* Graduated from `experimental.temporal_awareness`; default: true. */
|
|
918
897
|
temporal_awareness: boolean;
|
|
919
898
|
/** Debug: when true, keep the child sessions Magic Context spawns for its
|
|
920
|
-
* own subagents (historian, dreamer,
|
|
899
|
+
* own subagents (historian, dreamer, memory-migration) instead
|
|
921
900
|
* of deleting them on success. For short-term inspection/data collection;
|
|
922
901
|
* kept sessions accumulate until manually cleared. Default false. */
|
|
923
902
|
keep_subagents: boolean;
|
|
903
|
+
/** Enable loopback-only diagnostic RPCs that expose memory usage and heap snapshots. */
|
|
904
|
+
debug_rpc?: boolean;
|
|
924
905
|
/**
|
|
925
906
|
* When true (default), deterministic inoperability (schema fence, storage
|
|
926
907
|
* open/migration failure) blocks the primary-session transform with a loud
|
|
@@ -1011,7 +992,6 @@ export interface MagicContextConfig {
|
|
|
1011
992
|
max_commits: number;
|
|
1012
993
|
};
|
|
1013
994
|
};
|
|
1014
|
-
sidekick?: SidekickConfig;
|
|
1015
995
|
}
|
|
1016
996
|
|
|
1017
997
|
export const MagicContextConfigSchema = z
|
|
@@ -1063,7 +1043,7 @@ export const MagicContextConfigSchema = z
|
|
|
1063
1043
|
.describe(
|
|
1064
1044
|
"Output language for Magic Context's generated content and guidance, as a " +
|
|
1065
1045
|
'2-letter ISO 639-1 code (e.g. "tr", "es", "de", "ja", "pt"). When set, the ' +
|
|
1066
|
-
"historian, dreamer,
|
|
1046
|
+
"historian, dreamer, and the agent-guidance block instruct the model to " +
|
|
1067
1047
|
"write its PROSE in this language while keeping all structural tokens (XML tags, " +
|
|
1068
1048
|
"the five memory category names, code identifiers, file paths) in English. " +
|
|
1069
1049
|
"USER-LEVEL ONLY (ignored in project config for security). Unset = today's " +
|
|
@@ -1080,7 +1060,7 @@ export const MagicContextConfigSchema = z
|
|
|
1080
1060
|
"Select a named user-owned model profile. A valid project name overrides this user default; an empty string, null, or other non-string project value is ignored with a warning so the user selection still applies. Unknown names warn and use the base configuration.",
|
|
1081
1061
|
),
|
|
1082
1062
|
profiles: ConfigProfilesSchema.optional().describe(
|
|
1083
|
-
"User-level named model profiles. A profile may contain only historian/dreamer model, fallback_models, OpenCode variant, and Pi/OMP thinking_level fields
|
|
1063
|
+
"User-level named model profiles. A profile may contain only historian/dreamer model, fallback_models, OpenCode variant, and Pi/OMP thinking_level fields; task execution policy (including timeout_minutes) is excluded. Project configs may select a name but cannot define profiles.",
|
|
1084
1064
|
),
|
|
1085
1065
|
historian: HistorianConfigSchema.describe(
|
|
1086
1066
|
"Historian metadata plus independent strict OpenCode, Pi, and OMP execution blocks. Retained metadata stays at historian; model, fallback_models, variant, and thinking_level belong only in historian.opencode, historian.pi, or historian.omp.",
|
|
@@ -1153,14 +1133,22 @@ export const MagicContextConfigSchema = z
|
|
|
1153
1133
|
.describe(
|
|
1154
1134
|
"Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above 90% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000.",
|
|
1155
1135
|
),
|
|
1156
|
-
|
|
1136
|
+
protected_tokens: z
|
|
1157
1137
|
.number()
|
|
1158
|
-
.
|
|
1159
|
-
.
|
|
1138
|
+
.int()
|
|
1139
|
+
.min(4000)
|
|
1140
|
+
.max(1_000_000)
|
|
1160
1141
|
.optional()
|
|
1161
1142
|
.describe(
|
|
1162
|
-
"
|
|
1143
|
+
"Positive integer token floor to protect from automatic reclaim (min: 4_000, max: 1_000_000). When omitted, the derived default is clamp(round(0.05 × usableSoft), min(16_000, round(0.08 × usableSoft)), 64_000).",
|
|
1163
1144
|
),
|
|
1145
|
+
protected_tags: z
|
|
1146
|
+
.unknown()
|
|
1147
|
+
.optional()
|
|
1148
|
+
.describe(
|
|
1149
|
+
"Deprecated: number of recent tags to protect. Ignored for behaviour; use protected_tokens instead.",
|
|
1150
|
+
)
|
|
1151
|
+
.meta({ deprecated: true }),
|
|
1164
1152
|
clear_reasoning_age: z
|
|
1165
1153
|
.number()
|
|
1166
1154
|
.min(10)
|
|
@@ -1294,7 +1282,13 @@ export const MagicContextConfigSchema = z
|
|
|
1294
1282
|
.boolean()
|
|
1295
1283
|
.default(false)
|
|
1296
1284
|
.describe(
|
|
1297
|
-
"Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer,
|
|
1285
|
+
"Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect.",
|
|
1286
|
+
),
|
|
1287
|
+
debug_rpc: z
|
|
1288
|
+
.boolean()
|
|
1289
|
+
.default(false)
|
|
1290
|
+
.describe(
|
|
1291
|
+
"Developer-only: enable authenticated loopback RPCs for memory counters and heap snapshots. Disabled by default. USER-LEVEL ONLY and requires a restart.",
|
|
1298
1292
|
),
|
|
1299
1293
|
fail_closed_blocking: z
|
|
1300
1294
|
.boolean()
|
|
@@ -1459,13 +1453,28 @@ export const MagicContextConfigSchema = z
|
|
|
1459
1453
|
git_commit_indexing: { enabled: false, since_days: 365, max_commits: 2000 },
|
|
1460
1454
|
})
|
|
1461
1455
|
.describe("Cross-session memory configuration"),
|
|
1462
|
-
sidekick: SidekickConfigSchema.describe(
|
|
1463
|
-
"Optional sidekick agent configuration for session-start memory retrieval",
|
|
1464
|
-
),
|
|
1465
1456
|
})
|
|
1466
1457
|
.transform((data): MagicContextConfig => {
|
|
1467
1458
|
return {
|
|
1468
1459
|
...data,
|
|
1469
|
-
protected_tags: data.protected_tags
|
|
1460
|
+
protected_tags: data.protected_tags as number | undefined,
|
|
1470
1461
|
};
|
|
1471
1462
|
});
|
|
1463
|
+
|
|
1464
|
+
/**
|
|
1465
|
+
* Derived default protected_tokens formula:
|
|
1466
|
+
* clamp(round(0.05 × usableSoft), min(16000, round(0.08 × usableSoft)), 64000)
|
|
1467
|
+
*
|
|
1468
|
+
* Sizing table:
|
|
1469
|
+
* 100k -> 8,000
|
|
1470
|
+
* 200k -> 16,000
|
|
1471
|
+
* 372k -> 18,600
|
|
1472
|
+
* 872k -> 43,600
|
|
1473
|
+
* 1M -> 50,000
|
|
1474
|
+
*/
|
|
1475
|
+
export function deriveDefaultProtectedTokens(usableSoft: number): number {
|
|
1476
|
+
const clampedUsable = Math.max(0, usableSoft);
|
|
1477
|
+
const lowerBound = Math.min(16_000, Math.round(0.08 * clampedUsable));
|
|
1478
|
+
const target = Math.round(0.05 * clampedUsable);
|
|
1479
|
+
return Math.min(64_000, Math.max(lowerBound, target));
|
|
1480
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
|
|
3
|
+
import { afterEach, describe, expect, mock, test } from "bun:test";
|
|
4
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
5
|
+
import { join, relative } from "node:path";
|
|
6
|
+
import ts from "typescript";
|
|
7
|
+
|
|
8
|
+
import { sweepOrphanedRetrospectiveChildren } from "../features/magic-context/dreamer/retrospective-orphan-sweep";
|
|
9
|
+
import { teardownChildSession } from "./child-session-teardown";
|
|
10
|
+
import { _resetKeepSubagentsForTesting, setKeepSubagents } from "./keep-subagents";
|
|
11
|
+
import { Database } from "./sqlite";
|
|
12
|
+
import { closeQuietly } from "./sqlite-helpers";
|
|
13
|
+
|
|
14
|
+
interface TeardownFixture {
|
|
15
|
+
client: {
|
|
16
|
+
session: {
|
|
17
|
+
delete: ReturnType<typeof mock>;
|
|
18
|
+
update: ReturnType<typeof mock>;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
calls: string[];
|
|
22
|
+
deleted: string[];
|
|
23
|
+
archived: string[];
|
|
24
|
+
messages: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function teardownFixture(): TeardownFixture {
|
|
28
|
+
const calls: string[] = [];
|
|
29
|
+
const deleted: string[] = [];
|
|
30
|
+
const archived: string[] = [];
|
|
31
|
+
const messages: string[] = [];
|
|
32
|
+
return {
|
|
33
|
+
calls,
|
|
34
|
+
deleted,
|
|
35
|
+
archived,
|
|
36
|
+
messages,
|
|
37
|
+
client: {
|
|
38
|
+
session: {
|
|
39
|
+
update: mock(async ({ path }: { path: { id: string } }) => {
|
|
40
|
+
calls.push("archive");
|
|
41
|
+
archived.push(path.id);
|
|
42
|
+
return {};
|
|
43
|
+
}),
|
|
44
|
+
delete: mock(async ({ path }: { path: { id: string } }) => {
|
|
45
|
+
calls.push("delete");
|
|
46
|
+
deleted.push(path.id);
|
|
47
|
+
return {};
|
|
48
|
+
}),
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
afterEach(() => {
|
|
55
|
+
_resetKeepSubagentsForTesting();
|
|
56
|
+
mock.restore();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("teardownChildSession", () => {
|
|
60
|
+
test("deletes an ordinary child only after its prompt settles", async () => {
|
|
61
|
+
const fixture = teardownFixture();
|
|
62
|
+
await teardownChildSession({
|
|
63
|
+
client: fixture.client,
|
|
64
|
+
sessionId: "settled-ordinary",
|
|
65
|
+
sessionDirectory: "/repo",
|
|
66
|
+
promptSettled: true,
|
|
67
|
+
privacySensitive: false,
|
|
68
|
+
context: "ordinary",
|
|
69
|
+
log: (message) => fixture.messages.push(message),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
expect(fixture.deleted).toEqual(["settled-ordinary"]);
|
|
73
|
+
expect(fixture.archived).toEqual([]);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("keeps a settled ordinary child but deletes a settled privacy child under keep_subagents", async () => {
|
|
77
|
+
setKeepSubagents(true);
|
|
78
|
+
const ordinary = teardownFixture();
|
|
79
|
+
await teardownChildSession({
|
|
80
|
+
client: ordinary.client,
|
|
81
|
+
sessionId: "kept-ordinary",
|
|
82
|
+
promptSettled: true,
|
|
83
|
+
privacySensitive: false,
|
|
84
|
+
context: "ordinary",
|
|
85
|
+
log: (message) => ordinary.messages.push(message),
|
|
86
|
+
});
|
|
87
|
+
expect(ordinary.deleted).toEqual([]);
|
|
88
|
+
|
|
89
|
+
const privacy = teardownFixture();
|
|
90
|
+
await teardownChildSession({
|
|
91
|
+
client: privacy.client,
|
|
92
|
+
sessionId: "deleted-private",
|
|
93
|
+
promptSettled: true,
|
|
94
|
+
privacySensitive: true,
|
|
95
|
+
context: "private",
|
|
96
|
+
log: (message) => privacy.messages.push(message),
|
|
97
|
+
});
|
|
98
|
+
expect(privacy.deleted).toEqual(["deleted-private"]);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("archives an unsettled child before logging, leaves it intact, then the age gate reaps it", async () => {
|
|
102
|
+
const fixture = teardownFixture();
|
|
103
|
+
const db = new Database(":memory:");
|
|
104
|
+
db.exec(`
|
|
105
|
+
CREATE TABLE session (
|
|
106
|
+
id TEXT PRIMARY KEY,
|
|
107
|
+
title TEXT,
|
|
108
|
+
directory TEXT,
|
|
109
|
+
time_created INTEGER
|
|
110
|
+
);
|
|
111
|
+
INSERT INTO session VALUES (
|
|
112
|
+
'unsettled-private',
|
|
113
|
+
'magic-context-dream-map-memories',
|
|
114
|
+
'/repo',
|
|
115
|
+
1
|
|
116
|
+
);
|
|
117
|
+
`);
|
|
118
|
+
try {
|
|
119
|
+
await teardownChildSession({
|
|
120
|
+
client: fixture.client,
|
|
121
|
+
sessionId: "unsettled-private",
|
|
122
|
+
sessionDirectory: "/repo",
|
|
123
|
+
promptSettled: false,
|
|
124
|
+
privacySensitive: true,
|
|
125
|
+
context: "[dreamer] map-memories",
|
|
126
|
+
log: (message) => {
|
|
127
|
+
fixture.calls.push("log");
|
|
128
|
+
fixture.messages.push(message);
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
expect(fixture.calls).toEqual(["archive", "log"]);
|
|
133
|
+
expect(fixture.deleted).toEqual([]);
|
|
134
|
+
expect(fixture.messages).toEqual([
|
|
135
|
+
"[dreamer] map-memories: prompt unsettled — session unsettled-private left to the age-gated sweep",
|
|
136
|
+
]);
|
|
137
|
+
expect(
|
|
138
|
+
db.prepare("SELECT id FROM session WHERE id = ?").get("unsettled-private"),
|
|
139
|
+
).toEqual({
|
|
140
|
+
id: "unsettled-private",
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const swept = await sweepOrphanedRetrospectiveChildren({
|
|
144
|
+
opencodeDb: db,
|
|
145
|
+
client: fixture.client as never,
|
|
146
|
+
sessionDirectory: "/repo",
|
|
147
|
+
staleMs: 1_000,
|
|
148
|
+
now: 1_002,
|
|
149
|
+
});
|
|
150
|
+
expect(swept).toBe(1);
|
|
151
|
+
expect(fixture.deleted).toEqual(["unsettled-private"]);
|
|
152
|
+
} finally {
|
|
153
|
+
closeQuietly(db);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
function productionTypeScriptFiles(directory: string): string[] {
|
|
159
|
+
const files: string[] = [];
|
|
160
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
161
|
+
const path = join(directory, entry.name);
|
|
162
|
+
if (entry.isDirectory()) files.push(...productionTypeScriptFiles(path));
|
|
163
|
+
else if (entry.name.endsWith(".ts") && !entry.name.endsWith(".test.ts")) files.push(path);
|
|
164
|
+
}
|
|
165
|
+
return files;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function clientSessionDeleteOffsets(path: string, source: string): number[] {
|
|
169
|
+
const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);
|
|
170
|
+
const offsets: number[] = [];
|
|
171
|
+
const visit = (node: ts.Node): void => {
|
|
172
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {
|
|
173
|
+
const deleteAccess = node.expression;
|
|
174
|
+
const sessionAccess = deleteAccess.expression;
|
|
175
|
+
if (
|
|
176
|
+
deleteAccess.name.text === "delete" &&
|
|
177
|
+
ts.isPropertyAccessExpression(sessionAccess) &&
|
|
178
|
+
sessionAccess.name.text === "session" &&
|
|
179
|
+
(ts.isIdentifier(sessionAccess.expression)
|
|
180
|
+
? sessionAccess.expression.text === "client"
|
|
181
|
+
: ts.isPropertyAccessExpression(sessionAccess.expression) &&
|
|
182
|
+
sessionAccess.expression.name.text === "client")
|
|
183
|
+
) {
|
|
184
|
+
offsets.push(node.getStart(sourceFile));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
ts.forEachChild(node, visit);
|
|
188
|
+
};
|
|
189
|
+
visit(sourceFile);
|
|
190
|
+
return offsets;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
describe("child-session delete source fence", () => {
|
|
194
|
+
test("every client.session.delete call is the age-gated sweep or promptSettled-gated teardown", () => {
|
|
195
|
+
const sourceRoot = join(import.meta.dir, "..");
|
|
196
|
+
const sites: string[] = [];
|
|
197
|
+
for (const path of productionTypeScriptFiles(sourceRoot)) {
|
|
198
|
+
const source = readFileSync(path, "utf8");
|
|
199
|
+
for (const offset of clientSessionDeleteOffsets(path, source)) {
|
|
200
|
+
const line = source.slice(0, offset).split("\n").length;
|
|
201
|
+
sites.push(`${relative(sourceRoot, path)}:${line}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Directory walk order differs between macOS and Linux; the fence is a set.
|
|
206
|
+
expect(sites.map((site) => site.replace(/:\d+$/, "")).sort()).toEqual([
|
|
207
|
+
"features/magic-context/dreamer/retrospective-orphan-sweep.ts",
|
|
208
|
+
"shared/child-session-teardown.ts",
|
|
209
|
+
]);
|
|
210
|
+
const teardownSource = readFileSync(
|
|
211
|
+
join(sourceRoot, "shared/child-session-teardown.ts"),
|
|
212
|
+
"utf8",
|
|
213
|
+
);
|
|
214
|
+
expect(teardownSource).toMatch(
|
|
215
|
+
/if\s*\(\s*promptSettled[\s\S]{0,200}client\.session\.delete\s*\(/,
|
|
216
|
+
);
|
|
217
|
+
});
|
|
218
|
+
});
|