@cortexkit/opencode-magic-context 0.41.3 → 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 +14 -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-z5sd697e.js → conflict-warning-hook-6p3xqeac.js} +4 -4
- package/dist/{derive-budgets-901a0pk0.js → derive-budgets-s2pgnnm4.js} +4 -2
- 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/storage-dream-runs.d.ts +13 -0
- package/dist/features/magic-context/dreamer/storage-dream-runs.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 +7 -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 +81 -15
- 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 +5 -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/compartment-runner-types.d.ts +4 -0
- package/dist/hooks/magic-context/compartment-runner-types.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/derive-budgets.d.ts +1 -0
- package/dist/hooks/magic-context/derive-budgets.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 +9 -2
- 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 +8 -2
- 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 +11 -4
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts +5 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +17 -5
- 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/issue-423-fixture.d.ts +37 -0
- package/dist/hooks/magic-context/issue-423-fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/issue-424-fixture.d.ts +11 -0
- package/dist/hooks/magic-context/issue-424-fixture.d.ts.map +1 -0
- 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/producer-window-guard.d.ts +8 -0
- package/dist/hooks/magic-context/producer-window-guard.d.ts.map +1 -0
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts +65 -0
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +20 -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/read-session-true-raw-tokens.d.ts +4 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/recomp-orchestrator.d.ts +2 -0
- package/dist/hooks/magic-context/recomp-orchestrator.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 +79 -11
- 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/sentinel.d.ts +3 -3
- package/dist/hooks/magic-context/sentinel.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/tag-messages.d.ts +2 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +16 -6
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts +1 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +2 -0
- 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 +11 -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-npx8vhmy.js → index-36wd1d6k.js} +7 -30
- package/dist/{index-kby1sng5.js → index-avwt563y.js} +8 -1
- package/dist/{index-vmmjdpc0.js → index-c9hamh36.js} +18357 -16010
- package/dist/{index-0bycg0np.js → index-jmtjh2d3.js} +4 -4
- package/dist/{index-q264erdp.js → index-nqgjwfzn.js} +70 -38
- package/dist/index-sd3egckz.js +1583 -0
- package/dist/{index-dn1rwpd8.js → index-xdtge3y2.js} +58 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6826 -6660
- 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 +19 -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-f5m2wk74.js → recomp-orchestrator-3atsasjy.js} +6 -6
- package/dist/{send-session-notification-hdh02wy9.js → send-session-notification-1qeqkswb.js} +6 -4
- package/dist/shared/cache-ttl-display.d.ts +23 -0
- package/dist/shared/cache-ttl-display.d.ts.map +1 -0
- package/dist/shared/cache-ttl-seed.d.ts +10 -0
- package/dist/shared/cache-ttl-seed.d.ts.map +1 -0
- package/dist/shared/child-session-teardown.d.ts +34 -0
- package/dist/shared/child-session-teardown.d.ts.map +1 -0
- package/dist/shared/config-diagnostics.d.ts +30 -0
- package/dist/shared/config-diagnostics.d.ts.map +1 -0
- package/dist/shared/config-warning-surface.d.ts +3 -0
- package/dist/shared/config-warning-surface.d.ts.map +1 -0
- package/dist/shared/data-path.d.ts +10 -9
- package/dist/shared/data-path.d.ts.map +1 -1
- package/dist/shared/harness-provider-map.d.ts +7 -0
- package/dist/shared/harness-provider-map.d.ts.map +1 -1
- package/dist/shared/jsonc-parser.d.ts +12 -0
- package/dist/shared/jsonc-parser.d.ts.map +1 -1
- 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 +15 -11
- package/dist/shared/model-suggestion-retry.d.ts.map +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/pi-executable.d.ts +6 -0
- package/dist/shared/pi-executable.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 +117 -0
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/rpc-utils.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-3rxx9ekm.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 +169 -14
- package/src/config/index.ts +137 -21
- 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/cache-ttl-display.test.ts +84 -0
- package/src/shared/cache-ttl-display.ts +64 -0
- package/src/shared/cache-ttl-seed.ts +23 -0
- package/src/shared/child-session-teardown.test.ts +218 -0
- package/src/shared/child-session-teardown.ts +66 -0
- package/src/shared/config-diagnostics.test.ts +29 -0
- package/src/shared/config-diagnostics.ts +64 -0
- package/src/shared/config-warning-surface.ts +28 -0
- package/src/shared/data-path.ts +10 -9
- package/src/shared/harness-provider-map.test.ts +16 -0
- package/src/shared/harness-provider-map.ts +15 -0
- package/src/shared/jsonc-parser.test.ts +14 -1
- package/src/shared/jsonc-parser.ts +93 -0
- package/src/shared/keep-subagents.ts +9 -14
- package/src/shared/model-suggestion-retry.ts +144 -29
- package/src/shared/opencode-db-path.test.ts +196 -0
- package/src/shared/opencode-db-path.ts +215 -0
- package/src/shared/pi-executable.ts +20 -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 +124 -0
- package/src/shared/rpc-utils.ts +2 -3
- 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 +8 -4
- package/src/shared/status-detail-text.ts +20 -1
- package/src/shared/subagent-runner.ts +17 -10
- package/src/shared/tag-transcript.ts +53 -22
- 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 +18 -4
- package/src/tui/slots/sidebar-content.tsx +12 -7
- package/src/tui-compiled/index.tsx +237 -225
- 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-jfpk81yt.js +0 -146
- package/dist/index-raatkvw5.js +0 -360
- package/src/agents/sidekick.ts +0 -1
- package/src/features/magic-context/defaults.ts +0 -1
package/src/shared/sqlite.ts
CHANGED
|
@@ -39,12 +39,28 @@
|
|
|
39
39
|
* `run()` → {changes,lastInsertRowid}) is identical and was verified directly.
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
|
+
import { statSync } from "node:fs";
|
|
42
43
|
// Type import only — runtime is loaded dynamically below. @types/better-sqlite3
|
|
43
44
|
// has the richest definitions and is a structural superset of the API surface
|
|
44
45
|
// we use, so calls typed against BetterSqlite3 work under bun:sqlite and
|
|
45
46
|
// node:sqlite at runtime (both expose prepare/run/get/all/exec/close).
|
|
46
47
|
import type BetterSqlite3 from "better-sqlite3";
|
|
47
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Slow-write reporting is injected rather than imported: this module is also
|
|
51
|
+
* executed directly by Node (the `node:sqlite` smoke in CI, Pi, Desktop), and
|
|
52
|
+
* Node's type-stripping loader does not resolve extensionless imports, so any
|
|
53
|
+
* static import of the plugin's logging chain here breaks that path. The
|
|
54
|
+
* storage bootstrap registers the real reporter; until then slow privileged
|
|
55
|
+
* writes are simply not logged.
|
|
56
|
+
*/
|
|
57
|
+
type SlowWriteReporter = (site: string, transactionStartedAt: number) => void;
|
|
58
|
+
let reportSlowPrivilegedWrite: SlowWriteReporter | undefined;
|
|
59
|
+
|
|
60
|
+
export function registerSlowWriteReporter(reporter: SlowWriteReporter): void {
|
|
61
|
+
reportSlowPrivilegedWrite = reporter;
|
|
62
|
+
}
|
|
63
|
+
|
|
48
64
|
export type SqliteRuntime = "Bun" | "Node.js";
|
|
49
65
|
|
|
50
66
|
type SqliteModule = {
|
|
@@ -158,6 +174,88 @@ const DatabaseImpl: typeof BetterSqlite3 = isBun
|
|
|
158
174
|
? (sqliteModule.Database as typeof BetterSqlite3)
|
|
159
175
|
: buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
|
|
160
176
|
|
|
177
|
+
interface TrackedSqliteConnection {
|
|
178
|
+
sequence: number;
|
|
179
|
+
filename: string;
|
|
180
|
+
readonly: boolean;
|
|
181
|
+
reference: WeakRef<BetterSqlite3.Database>;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface SqliteConnectionMemoryStats {
|
|
185
|
+
sequence: number;
|
|
186
|
+
filename: string;
|
|
187
|
+
readonly: boolean;
|
|
188
|
+
pageSize: number | null;
|
|
189
|
+
pageCount: number | null;
|
|
190
|
+
freelistCount: number | null;
|
|
191
|
+
cacheSize: number | null;
|
|
192
|
+
cacheSizeUnit: "pages" | "kib" | null;
|
|
193
|
+
cacheUpperBoundBytes: number | null;
|
|
194
|
+
mmapSizeBytes: number | null;
|
|
195
|
+
walFileBytes: number | null;
|
|
196
|
+
shmFileBytes: number | null;
|
|
197
|
+
fts5TableCount: number | null;
|
|
198
|
+
journalMode: string | null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface SqliteMemoryStats {
|
|
202
|
+
connectionCount: number;
|
|
203
|
+
cacheUpperBoundBytes: number;
|
|
204
|
+
mmapUpperBoundBytes: number;
|
|
205
|
+
walFileBytes: number;
|
|
206
|
+
shmFileBytes: number;
|
|
207
|
+
sqliteStatusApi: "unavailable";
|
|
208
|
+
connections: SqliteConnectionMemoryStats[];
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const trackedSqliteConnections = new Map<number, TrackedSqliteConnection>();
|
|
212
|
+
let nextSqliteConnectionSequence = 1;
|
|
213
|
+
|
|
214
|
+
function trackSqliteConnection(
|
|
215
|
+
db: BetterSqlite3.Database,
|
|
216
|
+
filename: unknown,
|
|
217
|
+
options: unknown,
|
|
218
|
+
): BetterSqlite3.Database {
|
|
219
|
+
const originalClose = db.close.bind(db) as (...args: unknown[]) => unknown;
|
|
220
|
+
const sequence = nextSqliteConnectionSequence++;
|
|
221
|
+
const metadata = {
|
|
222
|
+
sequence,
|
|
223
|
+
filename:
|
|
224
|
+
typeof filename === "string"
|
|
225
|
+
? filename
|
|
226
|
+
: Buffer.isBuffer(filename)
|
|
227
|
+
? "<buffer>"
|
|
228
|
+
: ":memory:",
|
|
229
|
+
readonly:
|
|
230
|
+
Boolean(options) &&
|
|
231
|
+
typeof options === "object" &&
|
|
232
|
+
((options as { readonly?: unknown }).readonly === true ||
|
|
233
|
+
(options as { readOnly?: unknown }).readOnly === true),
|
|
234
|
+
};
|
|
235
|
+
Object.defineProperty(db, "close", {
|
|
236
|
+
configurable: true,
|
|
237
|
+
value: (...args: unknown[]) => {
|
|
238
|
+
try {
|
|
239
|
+
return originalClose(...args);
|
|
240
|
+
} finally {
|
|
241
|
+
trackedSqliteConnections.delete(sequence);
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
trackedSqliteConnections.set(sequence, {
|
|
246
|
+
...metadata,
|
|
247
|
+
reference: new WeakRef(db),
|
|
248
|
+
});
|
|
249
|
+
return db;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const TrackedDatabase = new Proxy(DatabaseImpl, {
|
|
253
|
+
construct(target, args) {
|
|
254
|
+
const db = Reflect.construct(target, args, target) as BetterSqlite3.Database;
|
|
255
|
+
return trackSqliteConnection(db, args[0], args[1]);
|
|
256
|
+
},
|
|
257
|
+
}) as typeof BetterSqlite3;
|
|
258
|
+
|
|
161
259
|
/**
|
|
162
260
|
* Wrap node:sqlite's `DatabaseSync` so it presents the better-sqlite3/bun
|
|
163
261
|
* surface the rest of the codebase calls:
|
|
@@ -259,7 +357,108 @@ function buildNodeSqliteDatabaseClass(DatabaseSync: any): typeof BetterSqlite3 {
|
|
|
259
357
|
return NodeSqliteDatabase as unknown as typeof BetterSqlite3;
|
|
260
358
|
}
|
|
261
359
|
|
|
262
|
-
export const Database: typeof BetterSqlite3 =
|
|
360
|
+
export const Database: typeof BetterSqlite3 = TrackedDatabase;
|
|
361
|
+
|
|
362
|
+
function pragmaValue(db: BetterSqlite3.Database, name: string): unknown {
|
|
363
|
+
const row = db.prepare(`PRAGMA ${name}`).get() as Record<string, unknown> | undefined;
|
|
364
|
+
if (!row) return undefined;
|
|
365
|
+
return row[name] ?? Object.values(row)[0];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function pragmaNumber(db: BetterSqlite3.Database, name: string): number | null {
|
|
369
|
+
try {
|
|
370
|
+
const value = pragmaValue(db, name);
|
|
371
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
372
|
+
} catch {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function pragmaString(db: BetterSqlite3.Database, name: string): string | null {
|
|
378
|
+
try {
|
|
379
|
+
const value = pragmaValue(db, name);
|
|
380
|
+
return typeof value === "string" ? value : null;
|
|
381
|
+
} catch {
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function sqliteSidecarBytes(filename: string, suffix: "-wal" | "-shm"): number | null {
|
|
387
|
+
if (filename === ":memory:" || filename === "<buffer>") return 0;
|
|
388
|
+
try {
|
|
389
|
+
return statSync(`${filename}${suffix}`).size;
|
|
390
|
+
} catch (error) {
|
|
391
|
+
return (error as NodeJS.ErrnoException).code === "ENOENT" ? 0 : null;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function fts5TableCount(db: BetterSqlite3.Database): number | null {
|
|
396
|
+
try {
|
|
397
|
+
const row = db
|
|
398
|
+
.prepare(
|
|
399
|
+
"SELECT COUNT(*) AS count FROM sqlite_master WHERE type = 'table' AND sql LIKE '%USING fts5%'",
|
|
400
|
+
)
|
|
401
|
+
.get() as { count?: unknown } | undefined;
|
|
402
|
+
return typeof row?.count === "number" ? row.count : null;
|
|
403
|
+
} catch {
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Read the SQLite memory bounds that Bun/node:sqlite expose without native FFI.
|
|
410
|
+
* SQLite's sqlite3_status()/sqlite3_db_status() counters are not surfaced by
|
|
411
|
+
* either runtime, so cache and mmap values are configured upper bounds rather
|
|
412
|
+
* than resident-byte measurements.
|
|
413
|
+
*/
|
|
414
|
+
export function getSqliteMemoryStats(): SqliteMemoryStats {
|
|
415
|
+
const connections: SqliteConnectionMemoryStats[] = [];
|
|
416
|
+
for (const [sequence, tracked] of trackedSqliteConnections) {
|
|
417
|
+
const db = tracked.reference.deref();
|
|
418
|
+
if (!db) {
|
|
419
|
+
trackedSqliteConnections.delete(sequence);
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
const pageSize = pragmaNumber(db, "page_size");
|
|
423
|
+
const cacheSize = pragmaNumber(db, "cache_size");
|
|
424
|
+
const cacheSizeUnit = cacheSize === null ? null : cacheSize < 0 ? "kib" : "pages";
|
|
425
|
+
const cacheUpperBoundBytes =
|
|
426
|
+
cacheSize === null
|
|
427
|
+
? null
|
|
428
|
+
: cacheSize < 0
|
|
429
|
+
? Math.abs(cacheSize) * 1024
|
|
430
|
+
: pageSize === null
|
|
431
|
+
? null
|
|
432
|
+
: cacheSize * pageSize;
|
|
433
|
+
connections.push({
|
|
434
|
+
sequence: tracked.sequence,
|
|
435
|
+
filename: tracked.filename,
|
|
436
|
+
readonly: tracked.readonly,
|
|
437
|
+
pageSize,
|
|
438
|
+
pageCount: pragmaNumber(db, "page_count"),
|
|
439
|
+
freelistCount: pragmaNumber(db, "freelist_count"),
|
|
440
|
+
cacheSize,
|
|
441
|
+
cacheSizeUnit,
|
|
442
|
+
cacheUpperBoundBytes,
|
|
443
|
+
mmapSizeBytes: pragmaNumber(db, "mmap_size"),
|
|
444
|
+
walFileBytes: sqliteSidecarBytes(tracked.filename, "-wal"),
|
|
445
|
+
shmFileBytes: sqliteSidecarBytes(tracked.filename, "-shm"),
|
|
446
|
+
fts5TableCount: fts5TableCount(db),
|
|
447
|
+
journalMode: pragmaString(db, "journal_mode"),
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
const sumKnown = (select: (connection: SqliteConnectionMemoryStats) => number | null): number =>
|
|
451
|
+
connections.reduce((sum, connection) => sum + (select(connection) ?? 0), 0);
|
|
452
|
+
return {
|
|
453
|
+
connectionCount: connections.length,
|
|
454
|
+
cacheUpperBoundBytes: sumKnown((connection) => connection.cacheUpperBoundBytes),
|
|
455
|
+
mmapUpperBoundBytes: sumKnown((connection) => connection.mmapSizeBytes),
|
|
456
|
+
walFileBytes: sumKnown((connection) => connection.walFileBytes),
|
|
457
|
+
shmFileBytes: sumKnown((connection) => connection.shmFileBytes),
|
|
458
|
+
sqliteStatusApi: "unavailable",
|
|
459
|
+
connections,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
263
462
|
|
|
264
463
|
/** Instance type alias used by helpers and storage modules. */
|
|
265
464
|
export type Database = BetterSqlite3.Database;
|
|
@@ -298,6 +497,7 @@ export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
|
|
|
298
497
|
const previousDepth = privilegeDepth.get(db) ?? 0;
|
|
299
498
|
const nested = isInTransaction(db);
|
|
300
499
|
const savepoint = "mc_privilege_scope";
|
|
500
|
+
const transactionStartedAt = nested ? undefined : performance.now();
|
|
301
501
|
if (nested) {
|
|
302
502
|
db.exec(`SAVEPOINT ${savepoint}`);
|
|
303
503
|
} else {
|
|
@@ -316,6 +516,9 @@ export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
|
|
|
316
516
|
db.exec(`RELEASE ${savepoint}`);
|
|
317
517
|
} else {
|
|
318
518
|
db.exec("COMMIT");
|
|
519
|
+
if (transactionStartedAt !== undefined) {
|
|
520
|
+
reportSlowPrivilegedWrite?.("privileged_writer", transactionStartedAt);
|
|
521
|
+
}
|
|
319
522
|
}
|
|
320
523
|
if (previousDepth > 0) privilegeDepth.set(db, previousDepth);
|
|
321
524
|
else privilegeDepth.delete(db);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { formatOpenCodeDbMissingStatusLine, resolveOpenCodeDbPath } from "./opencode-db-path";
|
|
2
3
|
import type { StatusDetail } from "./rpc-types";
|
|
3
4
|
import { formatStatusDetailMarkdown } from "./status-detail-text";
|
|
4
5
|
|
|
@@ -18,6 +19,7 @@ const STATUS_FIXTURE: StatusDetail = {
|
|
|
18
19
|
sessionNoteCount: 1,
|
|
19
20
|
readySmartNoteCount: 2,
|
|
20
21
|
cacheTtl: "5m",
|
|
22
|
+
cacheTtlSource: "session",
|
|
21
23
|
lastTransformError: null,
|
|
22
24
|
lastDreamerRunAt: null,
|
|
23
25
|
projectIdentity: "/repo",
|
|
@@ -67,17 +69,19 @@ const STATUS_FIXTURE: StatusDetail = {
|
|
|
67
69
|
};
|
|
68
70
|
|
|
69
71
|
describe("formatStatusDetailMarkdown", () => {
|
|
70
|
-
test("renders the fixed TUI status payload
|
|
71
|
-
expect(formatStatusDetailMarkdown(STATUS_FIXTURE)).toBe(
|
|
72
|
+
test("renders a missing-store condition before the fixed TUI status payload", () => {
|
|
73
|
+
expect(formatStatusDetailMarkdown(STATUS_FIXTURE)).toBe(
|
|
74
|
+
`${formatOpenCodeDbMissingStatusLine(resolveOpenCodeDbPath())}\n\n## Magic Context Status
|
|
72
75
|
|
|
73
76
|
- **Mode:** Magic Context compaction
|
|
74
77
|
- **Active profile:** work
|
|
75
78
|
- **Usage:** 75.0% (96,000 / 128,000 usable tokens)
|
|
76
|
-
- **Cache
|
|
79
|
+
- **Cache TTL: 5m (session)**; live (42s remaining); TTL 5m
|
|
77
80
|
- **Historian:** running; boundary present; coverage 12
|
|
78
81
|
- **Memory:** 8 active; 3 injected
|
|
79
82
|
- **Tags:** 4 active, 1 dropped; 2 pending drops
|
|
80
|
-
- **Execute threshold:** 65.0
|
|
83
|
+
- **Execute threshold:** 65.0%`,
|
|
84
|
+
);
|
|
81
85
|
});
|
|
82
86
|
|
|
83
87
|
test("shows module-routed host paths only in Rust-mode chat fallback", () => {
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import { formatCacheTtlDisplay } from "./cache-ttl-display";
|
|
2
|
+
import { formatConfigParseStatusLine } from "./config-diagnostics";
|
|
3
|
+
import {
|
|
4
|
+
formatOpenCodeDbMissingStatusLine,
|
|
5
|
+
formatOpenCodeDbReadFailureStatusLine,
|
|
6
|
+
getOpenCodeDbReadFailure,
|
|
7
|
+
openCodeDbPathExists,
|
|
8
|
+
resolveOpenCodeDbPath,
|
|
9
|
+
} from "./opencode-db-path";
|
|
1
10
|
import type { StatusDetail } from "./rpc-types";
|
|
2
11
|
import { RUST_MODE_HOST_PATHS_LINE } from "./rust-mode-status";
|
|
3
12
|
|
|
@@ -27,18 +36,28 @@ export function formatStatusDetailMarkdown(detail: StatusDetail): string {
|
|
|
27
36
|
? undefined
|
|
28
37
|
: `coverage ${detail.coverageOrdinal === null ? "none" : detail.coverageOrdinal}`,
|
|
29
38
|
].filter((value): value is string => value !== undefined);
|
|
39
|
+
const openCodeDbResolution = resolveOpenCodeDbPath();
|
|
40
|
+
const openCodeDbReadFailure = getOpenCodeDbReadFailure();
|
|
41
|
+
const openCodeDbStatusLine = !openCodeDbPathExists(openCodeDbResolution)
|
|
42
|
+
? formatOpenCodeDbMissingStatusLine(openCodeDbResolution)
|
|
43
|
+
: openCodeDbReadFailure?.path === openCodeDbResolution.path
|
|
44
|
+
? formatOpenCodeDbReadFailureStatusLine(openCodeDbReadFailure)
|
|
45
|
+
: null;
|
|
30
46
|
const mode =
|
|
31
47
|
detail.compaction_enabled === false
|
|
32
48
|
? "native compaction (Magic Context history compaction disabled)"
|
|
33
49
|
: "Magic Context compaction";
|
|
34
50
|
|
|
35
51
|
const lines = [
|
|
52
|
+
...(openCodeDbStatusLine ? [openCodeDbStatusLine, ""] : []),
|
|
53
|
+
...(detail.configParseFailures ?? []).map(formatConfigParseStatusLine),
|
|
54
|
+
...((detail.configParseFailures?.length ?? 0) > 0 ? [""] : []),
|
|
36
55
|
"## Magic Context Status",
|
|
37
56
|
"",
|
|
38
57
|
`- **Mode:** ${mode}`,
|
|
39
58
|
`- **Active profile:** ${detail.activeProfile ?? "none"}`,
|
|
40
59
|
`- **Usage:** ${detail.usagePercentage.toFixed(1)}% (${formatCount(detail.inputTokens)} / ${usableLimit})`,
|
|
41
|
-
`-
|
|
60
|
+
`- **${formatCacheTtlDisplay({ value: detail.cacheTtl, source: detail.cacheTtlSource ?? "session", modelKey: detail.cacheTtlModelKey })}**; ${formatCacheLane(detail)}`,
|
|
42
61
|
`- **Historian:** ${[historianState, ...historianDetails].join("; ")}`,
|
|
43
62
|
...(detail.hostBackendsModuleSide ? [`- ${RUST_MODE_HOST_PATHS_LINE}`] : []),
|
|
44
63
|
`- **Memory:** ${formatCount(detail.memoryCount)} active; ${formatCount(detail.memoryBlockCount)} injected`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cross-harness subagent runner abstraction.
|
|
3
3
|
*
|
|
4
|
-
* Magic Context spawns
|
|
4
|
+
* Magic Context spawns historian and Dreamer subagents
|
|
5
5
|
* each as a child "session" with its own model/prompt/tools. OpenCode and Pi
|
|
6
6
|
* have very different APIs for this:
|
|
7
7
|
*
|
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
* disk, optionally addressed via `--session <path>`.
|
|
16
16
|
*
|
|
17
17
|
* The runner interface below normalizes both into the same shape so the
|
|
18
|
-
* actual subagent business logic (historian XML parsing
|
|
19
|
-
*
|
|
18
|
+
* actual subagent business logic (historian XML parsing and Dreamer task loops)
|
|
19
|
+
* can stay harness-agnostic. Each harness ships its
|
|
20
20
|
* own runner implementation; agents take a `SubagentRunner` as a dep instead
|
|
21
21
|
* of reaching for `client.session.*` directly.
|
|
22
22
|
*
|
|
23
23
|
* Step 5a (this commit) defines the contract and ships `PiSubagentRunner`.
|
|
24
24
|
* Step 5b will refactor the OpenCode-side spawn paths in
|
|
25
|
-
* `compartment-runner-historian.ts
|
|
26
|
-
* `
|
|
25
|
+
* `compartment-runner-historian.ts` and `dreamer/runner.ts` onto an
|
|
26
|
+
* `OpenCodeSubagentRunner` so both harnesses
|
|
27
27
|
* share the agent business logic instead of duplicating it. Until 5b lands,
|
|
28
28
|
* OpenCode keeps its existing direct `client.session.*` calls untouched —
|
|
29
29
|
* the runner contract is purely additive on the OpenCode side.
|
|
@@ -36,11 +36,11 @@ import type { ModelInput } from "./model-resolution";
|
|
|
36
36
|
*
|
|
37
37
|
* Mirrors the union of OpenCode's `session.create` + `session.prompt` body
|
|
38
38
|
* fields and Pi's `--print` CLI flags, picking the shared subset that all
|
|
39
|
-
*
|
|
39
|
+
* the historian and Dreamer subagents actually use today.
|
|
40
40
|
*
|
|
41
41
|
* Fields:
|
|
42
42
|
* - `agent`: harness-specific agent name. OpenCode looks this up in its
|
|
43
|
-
* agent registry (`HISTORIAN_AGENT`, `DREAMER_AGENT
|
|
43
|
+
* agent registry (`HISTORIAN_AGENT`, `DREAMER_AGENT`).
|
|
44
44
|
* Pi has no concept of "agent name" beyond config, so this is ignored
|
|
45
45
|
* on the Pi side and used only by `OpenCodeSubagentRunner`.
|
|
46
46
|
* - `systemPrompt`: full system prompt for this child run. Replaces (not
|
|
@@ -88,7 +88,7 @@ export interface SubagentRunOptions {
|
|
|
88
88
|
/**
|
|
89
89
|
* Optional progress callback. The runner invokes it for milestone events
|
|
90
90
|
* during the run: spawn, first event received, terminal stop reason
|
|
91
|
-
* detected, child exit. Used by historian/dreamer
|
|
91
|
+
* detected, child exit. Used by historian/dreamer to write
|
|
92
92
|
* lifecycle entries to the magic-context.log without polluting the
|
|
93
93
|
* normal stdout stream.
|
|
94
94
|
*
|
|
@@ -104,7 +104,6 @@ export interface SubagentRunOptions {
|
|
|
104
104
|
| "historian_editor"
|
|
105
105
|
| "compressor"
|
|
106
106
|
| "dreamer"
|
|
107
|
-
| "sidekick"
|
|
108
107
|
| "user_memory_review"
|
|
109
108
|
| "recomp"
|
|
110
109
|
| undefined;
|
|
@@ -182,6 +181,11 @@ export type SubagentProgressEvent =
|
|
|
182
181
|
* here so the OpenCode runner can surface the child session ID for log
|
|
183
182
|
* correlation when Step 5b lands.
|
|
184
183
|
*/
|
|
184
|
+
export interface CompletedSubagentToolCall {
|
|
185
|
+
name: string;
|
|
186
|
+
arguments: Record<string, unknown>;
|
|
187
|
+
}
|
|
188
|
+
|
|
185
189
|
export type SubagentRunResult =
|
|
186
190
|
| {
|
|
187
191
|
ok: true;
|
|
@@ -196,6 +200,9 @@ export type SubagentRunResult =
|
|
|
196
200
|
* the real session messages.
|
|
197
201
|
*/
|
|
198
202
|
toolCallCount?: number;
|
|
203
|
+
/** Completed, non-error tool results preserved by runners that can
|
|
204
|
+
* reconstruct invocation/result pairs from their transcript. */
|
|
205
|
+
completedToolCalls?: CompletedSubagentToolCall[];
|
|
199
206
|
meta?: Record<string, unknown>;
|
|
200
207
|
}
|
|
201
208
|
| {
|
|
@@ -222,7 +229,7 @@ export type SubagentRunResult =
|
|
|
222
229
|
*
|
|
223
230
|
* Each harness ships a single instance — the OpenCode plugin wires
|
|
224
231
|
* `OpenCodeSubagentRunner` and the Pi plugin wires `PiSubagentRunner` in
|
|
225
|
-
* its `extension` boot path. Agent code (historian
|
|
232
|
+
* its `extension` boot path. Agent code (historian and dreamer)
|
|
226
233
|
* receives the runner as a dep and never reaches for harness-specific
|
|
227
234
|
* client APIs directly.
|
|
228
235
|
*/
|
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
updateTagTokenCount,
|
|
56
56
|
} from "../features/magic-context/storage-tags";
|
|
57
57
|
import { makeToolCompositeKey, type Tagger } from "../features/magic-context/tagger";
|
|
58
|
+
import { droppedInputMarker } from "../hooks/magic-context/dropped-input-guard";
|
|
58
59
|
import { applyEditMarkerToInput } from "../hooks/magic-context/edit-marker";
|
|
59
60
|
import { estimateImageTokensFromDataUrl } from "../hooks/magic-context/image-token-estimate";
|
|
60
61
|
import { estimateTokens } from "../hooks/magic-context/read-session-formatting";
|
|
@@ -184,6 +185,8 @@ interface ToolAggregate {
|
|
|
184
185
|
inputByteSize: number;
|
|
185
186
|
/** Persisted input-token count, or null for a legacy/unobserved invocation. */
|
|
186
187
|
inputTokenCount: number | null;
|
|
188
|
+
/** At least one assistant-side occurrence shares its message with native reasoning. */
|
|
189
|
+
requiresToolArcSkeleton: boolean;
|
|
187
190
|
}
|
|
188
191
|
|
|
189
192
|
function textIdentityDigest(value: string): string {
|
|
@@ -244,6 +247,9 @@ export function tagTranscript(
|
|
|
244
247
|
let textOrdinal = 0;
|
|
245
248
|
let toolResultOrdinal = 0;
|
|
246
249
|
const parts = message.parts;
|
|
250
|
+
const messageHasNativeReasoning =
|
|
251
|
+
message.requiresToolArcSkeleton ??
|
|
252
|
+
(message.info.role === "assistant" && parts.some((part) => part.kind === "thinking"));
|
|
247
253
|
const contentDerivedTextIds =
|
|
248
254
|
messageId !== undefined && options.textIdentityDriftMessageIds?.has(messageId) === true
|
|
249
255
|
? buildContentDerivedTextIds(messageId, parts)
|
|
@@ -345,6 +351,7 @@ export function tagTranscript(
|
|
|
345
351
|
const existing = toolAggregates.get(aggregateKey);
|
|
346
352
|
if (existing) {
|
|
347
353
|
existing.occurrences.push({ message, part, kind: part.kind });
|
|
354
|
+
existing.requiresToolArcSkeleton ||= messageHasNativeReasoning;
|
|
348
355
|
const canReuseIdentity = reuseIdentity && existing.identityReusable;
|
|
349
356
|
let text = "";
|
|
350
357
|
if (canReuseIdentity) {
|
|
@@ -463,6 +470,7 @@ export function tagTranscript(
|
|
|
463
470
|
toolName: null,
|
|
464
471
|
inputByteSize: reusableAccounting.inputByteSize,
|
|
465
472
|
inputTokenCount: reusableAccounting.inputTokenCount,
|
|
473
|
+
requiresToolArcSkeleton: messageHasNativeReasoning,
|
|
466
474
|
};
|
|
467
475
|
if (part.kind === "tool_result") {
|
|
468
476
|
text = part.getText() ?? "";
|
|
@@ -527,6 +535,7 @@ export function tagTranscript(
|
|
|
527
535
|
inputTokenCount:
|
|
528
536
|
persistedAccounting?.inputTokenCount ??
|
|
529
537
|
(part.kind === "tool_use" ? firstInputTokenCount : null),
|
|
538
|
+
requiresToolArcSkeleton: messageHasNativeReasoning,
|
|
530
539
|
};
|
|
531
540
|
if (part.kind === "tool_result") {
|
|
532
541
|
applyGrownToolResultAccounting({
|
|
@@ -678,7 +687,14 @@ function applyToolPrefixAndTarget(args: ApplyToolPrefixAndTargetArgs): void {
|
|
|
678
687
|
if (args.timing) args.timing.prefix += performance.now() - prefixStart;
|
|
679
688
|
}
|
|
680
689
|
const targetStart = args.timing ? performance.now() : 0;
|
|
681
|
-
args.targets.set(
|
|
690
|
+
args.targets.set(
|
|
691
|
+
args.tagId,
|
|
692
|
+
buildAggregateTarget(
|
|
693
|
+
args.tagId,
|
|
694
|
+
args.aggregate.occurrences,
|
|
695
|
+
args.aggregate.requiresToolArcSkeleton,
|
|
696
|
+
),
|
|
697
|
+
);
|
|
682
698
|
if (args.timing) args.timing.targets += performance.now() - targetStart;
|
|
683
699
|
}
|
|
684
700
|
|
|
@@ -1010,7 +1026,11 @@ function setToolContentOrText(part: TranscriptPart, content: string): boolean {
|
|
|
1010
1026
|
*
|
|
1011
1027
|
* Mirrors OpenCode's createToolDropTarget semantics in tool-drop-target.ts.
|
|
1012
1028
|
*/
|
|
1013
|
-
function buildAggregateTarget(
|
|
1029
|
+
function buildAggregateTarget(
|
|
1030
|
+
tagId: number,
|
|
1031
|
+
occurrences: ToolOccurrence[],
|
|
1032
|
+
requiresToolArcSkeleton: boolean,
|
|
1033
|
+
): TagTarget {
|
|
1014
1034
|
const role = occurrences[0]?.message.info.role ?? "user";
|
|
1015
1035
|
const messageId = occurrences[0]?.message.info.id;
|
|
1016
1036
|
|
|
@@ -1038,8 +1058,20 @@ function buildAggregateTarget(tagId: number, occurrences: ToolOccurrence[]): Tag
|
|
|
1038
1058
|
}
|
|
1039
1059
|
return occurrences[0]?.part.getText() ?? null;
|
|
1040
1060
|
},
|
|
1041
|
-
drop(): "removed" | "absent" {
|
|
1042
|
-
|
|
1061
|
+
drop(): "removed" | "absent" | "incomplete" {
|
|
1062
|
+
const complete =
|
|
1063
|
+
occurrences.some((occ) => occ.kind === "tool_use") &&
|
|
1064
|
+
occurrences.some((occ) => occ.kind === "tool_result");
|
|
1065
|
+
if (!complete) return "incomplete";
|
|
1066
|
+
if (
|
|
1067
|
+
!requiresToolArcSkeleton &&
|
|
1068
|
+
occurrences.every((occ) => occ.part.remove && occ.part.canRemove?.() !== false)
|
|
1069
|
+
) {
|
|
1070
|
+
let removed = false;
|
|
1071
|
+
for (const occ of occurrences) removed = occ.part.remove?.() || removed;
|
|
1072
|
+
return removed ? "removed" : "absent";
|
|
1073
|
+
}
|
|
1074
|
+
// Adapters without structural removal retain paired sentinels.
|
|
1043
1075
|
const sentinel = `[dropped \u00a7${tagId}\u00a7]`;
|
|
1044
1076
|
let any = false;
|
|
1045
1077
|
for (const occ of occurrences) {
|
|
@@ -1048,14 +1080,14 @@ function buildAggregateTarget(tagId: number, occurrences: ToolOccurrence[]): Tag
|
|
|
1048
1080
|
return any ? "removed" : "absent";
|
|
1049
1081
|
},
|
|
1050
1082
|
truncate(): "truncated" | "absent" {
|
|
1051
|
-
//
|
|
1052
|
-
//
|
|
1053
|
-
// drop and to OpenCode). Frozen by the dropMode column → replays
|
|
1054
|
-
// the same string every pass. The tool_use call survives intact.
|
|
1083
|
+
// Keep the paired call shell, but replace its arguments with one
|
|
1084
|
+
// non-executable marker; result halves carry the matching sentinel.
|
|
1055
1085
|
const sentinel = `[dropped \u00a7${tagId}\u00a7]`;
|
|
1056
1086
|
let any = false;
|
|
1057
1087
|
for (const occ of occurrences) {
|
|
1058
|
-
if (
|
|
1088
|
+
if (occ.kind === "tool_use" && occ.part.setToolInput) {
|
|
1089
|
+
if (occ.part.setToolInput(droppedInputMarker(tagId))) any = true;
|
|
1090
|
+
} else if (setToolContentOrText(occ.part, sentinel)) {
|
|
1059
1091
|
any = true;
|
|
1060
1092
|
}
|
|
1061
1093
|
}
|
|
@@ -1083,13 +1115,14 @@ function buildAggregateTarget(tagId: number, occurrences: ToolOccurrence[]): Tag
|
|
|
1083
1115
|
}
|
|
1084
1116
|
return any ? "truncated" : "absent";
|
|
1085
1117
|
},
|
|
1086
|
-
//
|
|
1087
|
-
// Pi sentinelizes BOTH halves, so unlike OpenCode there's no
|
|
1088
|
-
// result-part requirement — a target reclaims as long as it still has
|
|
1089
|
-
// at least one live occurrence to sentinelize.
|
|
1118
|
+
// Open invocations still belong to the current turn; only complete arcs reclaim.
|
|
1090
1119
|
canDrop(): boolean {
|
|
1091
|
-
return
|
|
1120
|
+
return (
|
|
1121
|
+
occurrences.some((occ) => occ.kind === "tool_use") &&
|
|
1122
|
+
occurrences.some((occ) => occ.kind === "tool_result")
|
|
1123
|
+
);
|
|
1092
1124
|
},
|
|
1125
|
+
requiresToolArcSkeleton,
|
|
1093
1126
|
// Non-mutating read of the invocation input (the tool_use occurrence
|
|
1094
1127
|
// carries the arguments). Used by smart-drops supersession selection.
|
|
1095
1128
|
readInput(): Record<string, unknown> | null {
|
|
@@ -1143,8 +1176,8 @@ function buildTextTarget(
|
|
|
1143
1176
|
* TagTarget for a tag-eligible tool part. Tool parts get full-drop or
|
|
1144
1177
|
* skeleton-drop treatment from `applyFlushedStatuses` based on the stored
|
|
1145
1178
|
* `drop_mode` column. Both render the SAME canonical `[dropped §N§]`
|
|
1146
|
-
* placeholder — full-drop replaces the whole pair, skeleton-drop keeps
|
|
1147
|
-
* tool_use call
|
|
1179
|
+
* placeholder — full-drop replaces the whole pair, while skeleton-drop keeps
|
|
1180
|
+
* the tool_use call with only a dropped-input marker. Marker bytes are
|
|
1148
1181
|
* byte-identical across passes and across harnesses.
|
|
1149
1182
|
*/
|
|
1150
1183
|
function buildToolTarget(
|
|
@@ -1171,12 +1204,10 @@ function buildToolTarget(
|
|
|
1171
1204
|
return replaced ? "removed" : "absent";
|
|
1172
1205
|
},
|
|
1173
1206
|
truncate(): "truncated" | "absent" {
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
const ok = setToolContentOrText(part, `[dropped \u00a7${tagId}\u00a7]`);
|
|
1179
|
-
return ok ? "truncated" : "absent";
|
|
1207
|
+
const changed = part.setToolInput
|
|
1208
|
+
? part.setToolInput(droppedInputMarker(tagId))
|
|
1209
|
+
: setToolContentOrText(part, `[dropped \u00a7${tagId}\u00a7]`);
|
|
1210
|
+
return changed ? "truncated" : "absent";
|
|
1180
1211
|
},
|
|
1181
1212
|
message: {
|
|
1182
1213
|
info: { id: message.info.id, role: message.info.role },
|
package/src/shared/transcript.ts
CHANGED
|
@@ -167,6 +167,11 @@ export interface TranscriptPart {
|
|
|
167
167
|
*/
|
|
168
168
|
replaceWithSentinel(sentinelText: string): boolean;
|
|
169
169
|
|
|
170
|
+
/** Remove one half of a complete tool arc. Callers must remove both halves together. */
|
|
171
|
+
remove?(): boolean;
|
|
172
|
+
/** Refuse structural deletion when the adapter cannot match provider-native identity safely. */
|
|
173
|
+
canRemove?(): boolean;
|
|
174
|
+
|
|
170
175
|
/**
|
|
171
176
|
* Optional: serialized byte size of the part's REAL payload, including
|
|
172
177
|
* non-text content (images, structured data) that `getText()` can't
|
|
@@ -187,6 +192,8 @@ export interface TranscriptPart {
|
|
|
187
192
|
* use `info.id` for cross-pass correlation, never the message reference.
|
|
188
193
|
*/
|
|
189
194
|
export interface TranscriptMessage {
|
|
195
|
+
/** Override when the receiving protocol does not merge adjacent assistant reasoning turns. */
|
|
196
|
+
requiresToolArcSkeleton?: boolean;
|
|
190
197
|
/**
|
|
191
198
|
* Lightweight metadata exposed for tagging, sentinel persistence, and
|
|
192
199
|
* cross-pass correlation. Adapters fill these from harness-native
|
|
@@ -4,6 +4,7 @@ import { tmpdir } from "node:os";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { resolveLimit, resolveOutputReserve } from "./models-dev-cache";
|
|
6
6
|
import {
|
|
7
|
+
applyProvenInputFloor,
|
|
7
8
|
deriveWindowGeometry,
|
|
8
9
|
formatWindowDerivationLine,
|
|
9
10
|
parseWindowOverlay,
|
|
@@ -298,6 +299,49 @@ describe("window geometry", () => {
|
|
|
298
299
|
expect(hooked?.derivation.reserve).toBe(30_000);
|
|
299
300
|
});
|
|
300
301
|
|
|
302
|
+
test("keeps shared-upfront emergency headroom below the separate absolute wall", () => {
|
|
303
|
+
const result = deriveWindowGeometry(
|
|
304
|
+
"openai-codex",
|
|
305
|
+
"gpt-5.6-sol",
|
|
306
|
+
{ context: 272_000, output: 128_000 },
|
|
307
|
+
{ providerLimit: { context: 272_000 }, harness: "pi" },
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
expect(result?.usableSoft).toBe(204_000);
|
|
311
|
+
expect(result?.usableHard).toBe(204_000);
|
|
312
|
+
expect(result?.usableHard).toBeLessThan(result?.derivation.absoluteWall ?? 0);
|
|
313
|
+
expect(result?.derivation.absoluteWall).toBe(272_000);
|
|
314
|
+
expect((result?.derivation.absoluteWall ?? 0) - (result?.usableHard ?? 0)).toBe(
|
|
315
|
+
result?.derivation.reserve,
|
|
316
|
+
);
|
|
317
|
+
expect(result?.derivation.windowSource).toBe("provider");
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
test("bounds proof at trusted absolute walls but retains the static-catalog escape hatch", () => {
|
|
321
|
+
const trusted = deriveWindowGeometry(
|
|
322
|
+
"openai-codex",
|
|
323
|
+
"gpt-5.6-sol",
|
|
324
|
+
{ context: 272_000, output: 128_000 },
|
|
325
|
+
{ providerLimit: { context: 272_000 }, harness: "pi" },
|
|
326
|
+
);
|
|
327
|
+
expect(trusted).toBeDefined();
|
|
328
|
+
const raisedWithinWall = applyProvenInputFloor(trusted!, 255_834);
|
|
329
|
+
expect(raisedWithinWall.geometry.usableSoft).toBe(255_834);
|
|
330
|
+
expect(raisedWithinWall.geometry.usableHard).toBe(204_000);
|
|
331
|
+
const refused = applyProvenInputFloor(trusted!, 593_717);
|
|
332
|
+
expect(refused.refused).toEqual({ reading: 593_717, absoluteWall: 272_000 });
|
|
333
|
+
expect(refused.geometry.usableSoft).toBe(204_000);
|
|
334
|
+
expect(refused.geometry.usableHard).toBe(204_000);
|
|
335
|
+
|
|
336
|
+
const staticFallback = deriveWindowGeometry("custom", "model", { context: 30_000 });
|
|
337
|
+
expect(staticFallback).toBeDefined();
|
|
338
|
+
const escaped = applyProvenInputFloor(staticFallback!, 90_000);
|
|
339
|
+
expect(escaped.refused).toBeUndefined();
|
|
340
|
+
expect(escaped.geometry.usableSoft).toBe(90_000);
|
|
341
|
+
expect(escaped.geometry.usableHard).toBe(90_000);
|
|
342
|
+
expect(escaped.geometry.derivation.absoluteWall).toBe(90_000);
|
|
343
|
+
});
|
|
344
|
+
|
|
301
345
|
test("clamps an inversion and logs it", () => {
|
|
302
346
|
const logs: string[] = [];
|
|
303
347
|
const result = deriveWindowGeometry(
|