@cortexkit/opencode-magic-context 0.47.0 → 0.49.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.
Files changed (425) hide show
  1. package/dist/agents/magic-context-prompt.d.ts +1 -1
  2. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  3. package/dist/{announcement-y35wzg2r.js → announcement-fp14dw0n.js} +3 -2
  4. package/dist/auto-search-worker.js +27 -30
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/mural-model-deprecation.d.ts +15 -0
  7. package/dist/config/mural-model-deprecation.d.ts.map +1 -0
  8. package/dist/config/project-security.d.ts +0 -3
  9. package/dist/config/project-security.d.ts.map +1 -1
  10. package/dist/config/schema/magic-context.d.ts +10 -6
  11. package/dist/config/schema/magic-context.d.ts.map +1 -1
  12. package/dist/{conflict-warning-hook-z44ynfz7.js → conflict-warning-hook-kzx4dmk1.js} +12 -10
  13. package/dist/{context-wq4ffwyb.js → context-nj5f293n.js} +2765 -1925
  14. package/dist/{derive-budgets-ke12jnnh.js → derive-budgets-qz5rrr08.js} +4 -3
  15. package/dist/embedding-activity-g1dhes6g.js +10 -0
  16. package/dist/embedding-backfill-aetxv1vt.js +21 -0
  17. package/dist/embedding-cache-mgyr73ef.js +16 -0
  18. package/dist/embedding-worker.js +11 -9
  19. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +1 -0
  21. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/task-config.d.ts +3 -3
  23. package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -1
  25. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  26. package/dist/features/magic-context/dreamer/task-registry.d.ts +1 -0
  27. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  28. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  29. package/dist/features/magic-context/git-commits/search-git-commits.d.ts +2 -0
  30. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  31. package/dist/features/magic-context/message-index-async.d.ts +16 -3
  32. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  33. package/dist/features/magic-context/message-index-bounded.d.ts +17 -0
  34. package/dist/features/magic-context/message-index-bounded.d.ts.map +1 -0
  35. package/dist/features/magic-context/message-index.d.ts +7 -1
  36. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  37. package/dist/features/magic-context/mural/render-trigger.d.ts +7 -4
  38. package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
  39. package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
  40. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
  41. package/dist/features/magic-context/search-rerank.d.ts +35 -0
  42. package/dist/features/magic-context/search-rerank.d.ts.map +1 -0
  43. package/dist/features/magic-context/search.d.ts +40 -0
  44. package/dist/features/magic-context/search.d.ts.map +1 -1
  45. package/dist/features/magic-context/session-activity.d.ts.map +1 -1
  46. package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
  47. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
  48. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  49. package/dist/features/magic-context/storage-meta-persisted.d.ts +13 -2
  50. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  51. package/dist/features/magic-context/storage-meta-session.d.ts +7 -1
  52. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  53. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  54. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  55. package/dist/features/magic-context/storage-session-tables.d.ts +2 -0
  56. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  57. package/dist/features/magic-context/storage-tag-identity-revision.d.ts +50 -0
  58. package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
  59. package/dist/features/magic-context/storage-tags.d.ts +153 -4
  60. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  61. package/dist/features/magic-context/storage.d.ts +1 -1
  62. package/dist/features/magic-context/storage.d.ts.map +1 -1
  63. package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
  64. package/dist/features/magic-context/tagger.d.ts +2 -0
  65. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  66. package/dist/features/magic-context/transform-decision-log.d.ts +4 -1
  67. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  68. package/dist/harness-e4avh192.js +10 -0
  69. package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
  70. package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts +24 -0
  73. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts.map +1 -0
  74. package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
  75. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/auto-search-worker-client.d.ts +34 -3
  77. package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/command-handler.d.ts +3 -0
  79. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  80. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  82. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  83. package/dist/hooks/magic-context/emergency-fail-closed.d.ts +28 -0
  84. package/dist/hooks/magic-context/emergency-fail-closed.d.ts.map +1 -1
  85. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/historian-host-runner.d.ts +8 -0
  87. package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
  88. package/dist/hooks/magic-context/hook.d.ts +3 -2
  89. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  90. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts +7 -0
  92. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts.map +1 -1
  93. package/dist/hooks/magic-context/lkg-persist.d.ts +4 -3
  94. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/lkg-replay.d.ts +13 -8
  96. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/lkg-slot.d.ts +139 -2
  98. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts +2 -0
  100. package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts.map +1 -0
  101. package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts +2 -0
  102. package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts.map +1 -0
  103. package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts +2 -0
  104. package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts.map +1 -0
  105. package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts +63 -0
  106. package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts.map +1 -0
  107. package/dist/hooks/magic-context/pass-outcome.d.ts +1 -0
  108. package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
  109. package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
  110. package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
  111. package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts +2 -0
  112. package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts.map +1 -0
  113. package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts +2 -0
  114. package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts.map +1 -0
  115. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +87 -0
  116. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -0
  117. package/dist/hooks/magic-context/read-session-chunk.d.ts +19 -1
  118. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  119. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  120. package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
  121. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  122. package/dist/hooks/magic-context/read-session-raw.d.ts +118 -1
  123. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  124. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  125. package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
  126. package/dist/hooks/magic-context/rust-mode-transform.d.ts +36 -0
  127. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  128. package/dist/hooks/magic-context/sentinel.d.ts +41 -1
  129. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  130. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts +8 -1
  131. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts.map +1 -1
  132. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
  133. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
  134. package/dist/hooks/magic-context/strip-content.d.ts +14 -2
  135. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  136. package/dist/hooks/magic-context/system-prompt-hash.d.ts +1 -0
  137. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  138. package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
  139. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  140. package/dist/hooks/magic-context/tag-owner-warmup.d.ts +6 -0
  141. package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
  142. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  143. package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
  144. package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
  145. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +13 -0
  146. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  147. package/dist/hooks/magic-context/transform.d.ts +9 -2
  148. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  149. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  150. package/dist/{index-q6hef7fh.js → index-0sahzkwr.js} +6 -19
  151. package/dist/{index-k5bdx1bx.js → index-0w56v4fm.js} +3 -5
  152. package/dist/{index-5gq3b2ya.js → index-1bt88epp.js} +227 -205
  153. package/dist/{index-cwf6s3ay.js → index-1g30axtz.js} +3279 -2907
  154. package/dist/{index-5a2r0p9f.js → index-1r0k9js3.js} +20 -13
  155. package/dist/index-2bvekkfy.js +11 -0
  156. package/dist/{index-6d9e1m08.js → index-2jcbj7r1.js} +13301 -13225
  157. package/dist/index-2jgwttpt.js +3269 -0
  158. package/dist/index-4dhv7mqz.js +131 -0
  159. package/dist/{index-sj29b3z2.js → index-4mjhqadz.js} +3 -3
  160. package/dist/{index-0c82743p.js → index-57mrqed8.js} +17 -15
  161. package/dist/{index-b35pxds2.js → index-58e3y90n.js} +1 -18
  162. package/dist/index-7jzrrxap.js +931 -0
  163. package/dist/index-8ajstryz.js +18 -0
  164. package/dist/{index-sfpzqvdz.js → index-8cd2j99z.js} +2 -3
  165. package/dist/{index-6wkcswft.js → index-9qjqq45k.js} +29 -19
  166. package/dist/{index-adwfkpex.js → index-9rt53q79.js} +23 -23
  167. package/dist/index-b7mv1jx3.js +1060 -0
  168. package/dist/index-d9vfe7xq.js +16 -0
  169. package/dist/{index-gg8j07zz.js → index-ezmszwbd.js} +8 -6
  170. package/dist/index-fb3zxn06.js +13 -0
  171. package/dist/index-fr0wbhdn.js +43 -0
  172. package/dist/{index-mc22ayvf.js → index-ghc9f0n7.js} +11 -9
  173. package/dist/index-gzcmtmar.js +171 -0
  174. package/dist/{index-w2t4ah5j.js → index-h2py7207.js} +6762 -7400
  175. package/dist/index-h2wc01qk.js +120 -0
  176. package/dist/index-h5zfkjyk.js +1277 -0
  177. package/dist/{index-92bp57hg.js → index-ha87j7a8.js} +1343 -149
  178. package/dist/index-hj2q50k0.js +856 -0
  179. package/dist/{index-wx8a6bw3.js → index-kb9nn0a0.js} +270 -53
  180. package/dist/index-kmpvemph.js +1314 -0
  181. package/dist/index-kp5qe690.js +3030 -0
  182. package/dist/{index-m5fe6jch.js → index-kq57tdf0.js} +152 -2453
  183. package/dist/{v2/server-fq7kq32k.js → index-mfkzp7qj.js} +1 -16
  184. package/dist/{v2/server-njt3np1k.js → index-nm6a8xpd.js} +220 -961
  185. package/dist/{index-hybnrwq0.js → index-nsjyysj0.js} +137 -130
  186. package/dist/index-nydv6g8r.js +3569 -0
  187. package/dist/index-pavzsdc6.js +17 -0
  188. package/dist/index-peshmj6h.js +152 -0
  189. package/dist/index-pxwp2hjk.js +571 -0
  190. package/dist/{v2/server-yr3zj7e7.js → index-qt1qqasc.js} +6 -7
  191. package/dist/{v2/server-51dv1pr5.js → index-qx53vezw.js} +301 -27
  192. package/dist/{index-rrrsepyw.js → index-s4j7t92z.js} +90 -85
  193. package/dist/{index-9pk9exrb.js → index-stbr4ce6.js} +18 -18
  194. package/dist/{index-fzbvakh0.js → index-tqf7yg27.js} +3 -3
  195. package/dist/index-vkbqdnkj.js +2307 -0
  196. package/dist/{index-8da2zjhz.js → index-z1tjp257.js} +9 -7
  197. package/dist/index.d.ts.map +1 -1
  198. package/dist/index.js +608 -349
  199. package/dist/logger-ewak5q1s.js +20 -0
  200. package/dist/message-index-bounded-h0mrd4pr.js +124 -0
  201. package/dist/{v2/message-time-backfill-1f9tzvcs.js → message-time-backfill-8x06r9kx.js} +8 -6
  202. package/dist/migration-worker.js +25 -18
  203. package/dist/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
  204. package/dist/plugin/dream-timer.d.ts +1 -1
  205. package/dist/plugin/dream-timer.d.ts.map +1 -1
  206. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
  207. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  208. package/dist/plugin/host-stall-profiler-report.d.ts +1 -66
  209. package/dist/plugin/host-stall-profiler-report.d.ts.map +1 -1
  210. package/dist/plugin/host-stall-profiler.d.ts +2 -95
  211. package/dist/plugin/host-stall-profiler.d.ts.map +1 -1
  212. package/dist/plugin/messages-transform.d.ts +0 -13
  213. package/dist/plugin/messages-transform.d.ts.map +1 -1
  214. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  215. package/dist/plugin/tool-registry.d.ts.map +1 -1
  216. package/dist/project-embedding-registry-rtt0djyb.js +88 -0
  217. package/dist/raw-ordinal-warmup-worker.js +60 -0
  218. package/dist/{read-session-chunk-4jey7hpt.js → read-session-chunk-ty89v75e.js} +17 -9
  219. package/dist/read-session-raw-8sjbc9h0.js +60 -0
  220. package/dist/recomp-orchestrator-4f1yyd1q.js +57 -0
  221. package/dist/{v2/safe-notification-target-eb1n1vfb.js → safe-notification-target-q0cyrx3x.js} +4 -2
  222. package/dist/search-pz4f4wge.js +45 -0
  223. package/dist/{v2/send-session-notification-c0wtscea.js → send-session-notification-38cd5dqt.js} +10 -7
  224. package/dist/shared/auto-search-lifecycle.d.ts +14 -0
  225. package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
  226. package/dist/shared/conflict-detector.d.ts.map +1 -1
  227. package/dist/shared/host-stall-profiler-bun.d.ts +46 -0
  228. package/dist/shared/host-stall-profiler-bun.d.ts.map +1 -0
  229. package/dist/shared/host-stall-profiler-common.d.ts +58 -0
  230. package/dist/shared/host-stall-profiler-common.d.ts.map +1 -0
  231. package/dist/shared/host-stall-profiler-node.d.ts +36 -0
  232. package/dist/shared/host-stall-profiler-node.d.ts.map +1 -0
  233. package/dist/shared/host-stall-profiler-report.d.ts +68 -0
  234. package/dist/shared/host-stall-profiler-report.d.ts.map +1 -0
  235. package/dist/shared/host-stall-profiler.d.ts +5 -0
  236. package/dist/shared/host-stall-profiler.d.ts.map +1 -0
  237. package/dist/shared/logger.d.ts.map +1 -1
  238. package/dist/shared/model-resolution.d.ts +2 -3
  239. package/dist/shared/model-resolution.d.ts.map +1 -1
  240. package/dist/shared/models-dev-temperature.d.ts +18 -0
  241. package/dist/shared/models-dev-temperature.d.ts.map +1 -0
  242. package/dist/shared/project-directory-key.d.ts +16 -0
  243. package/dist/shared/project-directory-key.d.ts.map +1 -1
  244. package/dist/shared/sqlite.d.ts +30 -0
  245. package/dist/shared/sqlite.d.ts.map +1 -1
  246. package/dist/shared/stable-json.d.ts.map +1 -1
  247. package/dist/shared/subagent-temperature.d.ts +46 -0
  248. package/dist/shared/subagent-temperature.d.ts.map +1 -0
  249. package/dist/shared/user-facing-codes.d.ts +0 -5
  250. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  251. package/dist/sqlite-context-pragmas-mv9jqwjh.js +6 -0
  252. package/dist/sqlite-mhjkerzq.js +46 -0
  253. package/dist/storage-memory-07fx57k6.js +71 -0
  254. package/dist/storage-tags-k0pda32s.js +133 -0
  255. package/dist/{task-config-v81k8jvk.js → task-config-cgpg0nvh.js} +2 -2
  256. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  257. package/dist/tools/ctx-note/constants.d.ts +4 -0
  258. package/dist/tools/ctx-note/constants.d.ts.map +1 -1
  259. package/dist/tools/ctx-note/tools.d.ts +1 -0
  260. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  261. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  262. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  263. package/dist/tools/ctx-search/types.d.ts +1 -0
  264. package/dist/tools/ctx-search/types.d.ts.map +1 -1
  265. package/dist/tools/parameter-descriptions.d.ts +2 -2
  266. package/dist/tools/parameter-descriptions.d.ts.map +1 -1
  267. package/dist/{transform-postprocess-phase-z5hzpsxv.js → transform-postprocess-phase-tck4g20s.js} +35 -20
  268. package/dist/transformers-node-wasm.js +18415 -18415
  269. package/dist/v2/auto-search-worker.js +27 -30
  270. package/dist/v2/{context-14v1hr8b.js → context-crbt6p1y.js} +4708 -4218
  271. package/dist/v2/{derive-budgets-nc9avxz8.js → derive-budgets-fgej9j46.js} +4 -3
  272. package/dist/v2/embedding-activity-g1dhes6g.js +10 -0
  273. package/dist/v2/embedding-backfill-ph1qfyn3.js +21 -0
  274. package/dist/v2/embedding-cache-mgyr73ef.js +16 -0
  275. package/dist/v2/embedding-worker.js +12 -9
  276. package/dist/v2/fold/host-media.d.ts +4 -0
  277. package/dist/v2/fold/host-media.d.ts.map +1 -1
  278. package/dist/v2/fold/memory-cache.d.ts +70 -0
  279. package/dist/v2/fold/memory-cache.d.ts.map +1 -0
  280. package/dist/v2/fold/native-codec.d.ts +10 -0
  281. package/dist/v2/fold/native-codec.d.ts.map +1 -0
  282. package/dist/v2/fold/native-replay.d.ts +58 -0
  283. package/dist/v2/fold/native-replay.d.ts.map +1 -0
  284. package/dist/v2/fold/policy.d.ts +24 -0
  285. package/dist/v2/fold/policy.d.ts.map +1 -0
  286. package/dist/v2/harness-e4avh192.js +10 -0
  287. package/dist/v2/hidden-child-native.d.ts.map +1 -1
  288. package/dist/v2/hidden-completion.d.ts +7 -0
  289. package/dist/v2/hidden-completion.d.ts.map +1 -1
  290. package/dist/v2/hooks/context.d.ts +2 -2
  291. package/dist/v2/hooks/context.d.ts.map +1 -1
  292. package/dist/v2/hooks/dream-manual.d.ts +1 -1
  293. package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
  294. package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
  295. package/dist/v2/hooks/dream-trigger.d.ts +5 -3
  296. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  297. package/dist/v2/hooks/generate.d.ts +9 -2
  298. package/dist/v2/hooks/generate.d.ts.map +1 -1
  299. package/dist/v2/hooks/payload.d.ts.map +1 -1
  300. package/dist/v2/hooks/tools.d.ts.map +1 -1
  301. package/dist/v2/hooks/types.d.ts +6 -0
  302. package/dist/v2/hooks/types.d.ts.map +1 -1
  303. package/dist/v2/logger-pj02s7sr.js +19 -0
  304. package/dist/v2/message-index-bounded-xwqdywxg.js +123 -0
  305. package/dist/{message-time-backfill-r5epkzj3.js → v2/message-time-backfill-cje68egj.js} +7 -7
  306. package/dist/v2/migration-worker.js +24 -17
  307. package/dist/v2/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
  308. package/dist/v2/project-embedding-registry-d6m7tyxr.js +86 -0
  309. package/dist/v2/raw-ordinal-warmup-worker.js +60 -0
  310. package/dist/v2/{read-session-chunk-gyyv7w2r.js → read-session-chunk-8p5mdryx.js} +16 -8
  311. package/dist/v2/read-session-raw-j8dvp7f4.js +59 -0
  312. package/dist/v2/recomp-orchestrator-ckfgt6wq.js +57 -0
  313. package/dist/{safe-notification-target-43r8jsxw.js → v2/safe-notification-target-y3p1hce9.js} +3 -3
  314. package/dist/v2/search-ym8rehhz.js +45 -0
  315. package/dist/{send-session-notification-0m68ms3n.js → v2/send-session-notification-5m0yapqx.js} +9 -8
  316. package/dist/v2/{server-rz514f14.js → server-19zjmn02.js} +2044 -2060
  317. package/dist/v2/server-1tk82krw.js +796 -0
  318. package/dist/v2/server-2bvekkfy.js +11 -0
  319. package/dist/v2/{server-ajzeteqw.js → server-2ra6pwf3.js} +1 -18
  320. package/dist/v2/server-2s6ayq3t.js +1048 -0
  321. package/dist/v2/{server-fcdehk1s.js → server-2s9qz6n7.js} +4 -4
  322. package/dist/v2/server-3j4d00kf.js +171 -0
  323. package/dist/v2/{server-14vq4kpm.js → server-3t0q2cqx.js} +3 -3
  324. package/dist/v2/server-4dhv7mqz.js +131 -0
  325. package/dist/v2/server-4ez8mntn.js +3213 -0
  326. package/dist/v2/{server-6r257mf5.js → server-676xw7at.js} +3 -3
  327. package/dist/v2/{server-vs5gpnd4.js → server-6byqfbqf.js} +165 -145
  328. package/dist/v2/server-7ekna9zs.js +120 -0
  329. package/dist/v2/server-7h861yms.js +1272 -0
  330. package/dist/v2/server-7jzrrxap.js +931 -0
  331. package/dist/v2/server-8ajstryz.js +18 -0
  332. package/dist/v2/{server-sfpzqvdz.js → server-8cd2j99z.js} +2 -3
  333. package/dist/v2/{server-cpepxy2q.js → server-8k2agx29.js} +14 -12
  334. package/dist/v2/server-c5rrgrcd.js +3545 -0
  335. package/dist/v2/server-d9vfe7xq.js +16 -0
  336. package/dist/v2/server-fb3zxn06.js +13 -0
  337. package/dist/v2/server-fr0wbhdn.js +43 -0
  338. package/dist/v2/{server-y10vbq6y.js → server-hb6xhh9q.js} +11 -1053
  339. package/dist/v2/server-jvxzm1jy.js +3023 -0
  340. package/dist/v2/{server-wx8a6bw3.js → server-kb9nn0a0.js} +270 -53
  341. package/dist/{index-5eqk6z3s.js → v2/server-kzns2hbz.js} +301 -27
  342. package/dist/{index-rrbbspwh.js → v2/server-mfkzp7qj.js} +1 -16
  343. package/dist/v2/server-pavzsdc6.js +17 -0
  344. package/dist/v2/{server-vd4e7174.js → server-pj4pjv02.js} +21 -17
  345. package/dist/v2/{server-e0c1b7a7.js → server-q4ph9bwn.js} +1340 -148
  346. package/dist/{index-yr3zj7e7.js → v2/server-qt1qqasc.js} +6 -7
  347. package/dist/v2/{server-qdjnb2z1.js → server-r5p3b1wy.js} +11 -9
  348. package/dist/v2/{server-d0sraw7m.js → server-sa8jvrfc.js} +291 -286
  349. package/dist/v2/server-ss95ky04.js +1048 -0
  350. package/dist/v2/{server-1qbnzc80.js → server-t4k4qexw.js} +142 -150
  351. package/dist/{index-x3kwrmqk.js → v2/server-v4mewb78.js} +35 -792
  352. package/dist/v2/server-w32kmdez.js +154 -0
  353. package/dist/v2/{server-nf82q6pt.js → server-x4hscabv.js} +5547 -5449
  354. package/dist/v2/server-xwz4dqh9.js +569 -0
  355. package/dist/v2/{server-efhwzx05.js → server-ycw9qqcy.js} +23 -23
  356. package/dist/v2/{server-50hvkg3v.js → server-zm570tr2.js} +160 -158
  357. package/dist/v2/server-zp53y8js.js +1311 -0
  358. package/dist/v2/server.js +16 -14
  359. package/dist/v2/sqlite-context-pragmas-mv9jqwjh.js +6 -0
  360. package/dist/v2/sqlite-mhjkerzq.js +46 -0
  361. package/dist/v2/storage-memory-07fx57k6.js +71 -0
  362. package/dist/v2/storage-tags-8vw924zn.js +132 -0
  363. package/dist/v2/store-reader.d.ts +24 -2
  364. package/dist/v2/store-reader.d.ts.map +1 -1
  365. package/dist/v2/{task-config-tbndqyny.js → task-config-x0hq3qfd.js} +2 -2
  366. package/dist/v2/transformers-node-wasm.js +18415 -18415
  367. package/dist/v2/tui/index.d.ts.map +1 -1
  368. package/dist/v2/tui/types.d.ts +1 -10
  369. package/dist/v2/tui/types.d.ts.map +1 -1
  370. package/dist/v2/{wrapup-orchestrator-nbz854vc.js → wrapup-orchestrator-a7efxaax.js} +51 -30
  371. package/dist/wrapup-orchestrator-barbc6h9.js +44 -0
  372. package/package.json +4 -3
  373. package/src/agents/magic-context-prompt.ts +27 -2
  374. package/src/agents/smart-notes-enabled.test.ts +294 -0
  375. package/src/agents/smart-notes-on.golden.json +70 -0
  376. package/src/config/index.test.ts +67 -1
  377. package/src/config/index.ts +2 -0
  378. package/src/config/latch-permanence-guard.test.ts +4 -0
  379. package/src/config/mural-model-deprecation.ts +24 -0
  380. package/src/config/project-security.hostile-matrix.test.ts +4 -44
  381. package/src/config/project-security.test.ts +9 -14
  382. package/src/config/project-security.ts +13 -55
  383. package/src/config/schema/magic-context.test.ts +2 -2
  384. package/src/config/schema/magic-context.ts +16 -10
  385. package/src/features/magic-context/dreamer/task-registry.ts +6 -0
  386. package/src/shared/auto-search-lifecycle.ts +43 -0
  387. package/src/shared/conflict-detector.test.ts +56 -0
  388. package/src/shared/conflict-detector.ts +16 -5
  389. package/src/shared/host-stall-profiler-bun.ts +358 -0
  390. package/src/shared/host-stall-profiler-common.ts +159 -0
  391. package/src/shared/host-stall-profiler-node.test.ts +234 -0
  392. package/src/shared/host-stall-profiler-node.ts +274 -0
  393. package/src/shared/host-stall-profiler-report.ts +248 -0
  394. package/src/shared/host-stall-profiler.ts +57 -0
  395. package/src/shared/logger.test.ts +38 -0
  396. package/src/shared/logger.ts +10 -2
  397. package/src/shared/model-resolution.test.ts +54 -17
  398. package/src/shared/model-resolution.ts +6 -17
  399. package/src/shared/models-dev-temperature.ts +107 -0
  400. package/src/shared/project-directory-key.test.ts +59 -0
  401. package/src/shared/project-directory-key.ts +20 -0
  402. package/src/shared/sqlite.test.ts +52 -0
  403. package/src/shared/sqlite.ts +339 -23
  404. package/src/shared/stable-json-linear.test.ts +109 -0
  405. package/src/shared/stable-json.ts +37 -7
  406. package/src/shared/subagent-temperature.test.ts +270 -0
  407. package/src/shared/subagent-temperature.ts +110 -0
  408. package/src/shared/user-facing-codes.ts +2 -6
  409. package/src/shared/write-transaction-attribution.test.ts +2 -2
  410. package/src/v2/tui/host-contract.test.ts +41 -67
  411. package/src/v2/tui/index.ts +6 -214
  412. package/src/v2/tui/types.ts +5 -17
  413. package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts +0 -45
  414. package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts.map +0 -1
  415. package/dist/features/magic-context/checkout-claim.d.ts +0 -155
  416. package/dist/features/magic-context/checkout-claim.d.ts.map +0 -1
  417. package/dist/index-bb36vgr3.js +0 -6608
  418. package/dist/index-fnn5pjtt.js +0 -6554
  419. package/dist/recomp-orchestrator-rervg6q4.js +0 -42
  420. package/dist/v2/recomp-orchestrator-42vjba7p.js +0 -42
  421. package/dist/v2/server-3trjk1hx.js +0 -6360
  422. package/dist/v2/server-nm9n3aqq.js +0 -6461
  423. package/dist/wrapup-orchestrator-b2dztrar.js +0 -29
  424. /package/dist/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
  425. /package/dist/v2/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Shared host stall report helpers. Both JavaScriptCore and V8 samples use
3
+ * innermost-first frames so native calls can be attributed to their JS caller.
4
+ *
5
+ * Kept separate from runtime backends so attribution can be tested without
6
+ * running watchdog timers or starting a sampling profiler.
7
+ */
8
+
9
+ import { readFileSync } from "node:fs";
10
+ import * as path from "node:path";
11
+
12
+ /** One frame from Bun's JavaScriptCore sampling API; V8 frames are normalized to this shape. */
13
+ export interface JscSampleFrame {
14
+ name?: string;
15
+ sourceURL?: string;
16
+ line?: number;
17
+ column?: number;
18
+ category?: string;
19
+ }
20
+
21
+ /** One sample: `frames[0]` is the innermost (currently executing) frame. */
22
+ export interface JscSampleTrace {
23
+ /** Monotonic seconds. JSC has a separate origin; V8 conversion uses the watchdog clock. */
24
+ timestamp?: number;
25
+ frames?: JscSampleFrame[];
26
+ }
27
+
28
+ /** Deepest stack kept per sample; deeper frames are folded into one marker. */
29
+ export const MAX_STACK_DEPTH = 64;
30
+ export const TOP_STACK_COUNT = 30;
31
+ export const TOP_FRAME_COUNT = 30;
32
+
33
+ /** JSC uses UINT32_MAX for "no line/column known". */
34
+ const UNKNOWN_POSITION = 4294967295;
35
+
36
+ /**
37
+ * Owners that never explain a stall by themselves: a native host function is
38
+ * attributed to its JavaScript caller, and host-core/runtime frames sit below
39
+ * every plugin hook. A sample is attributed to the innermost frame whose owner
40
+ * is NOT one of these, so a plugin calling a blocking native API is blamed,
41
+ * not the native API or the host that invoked the plugin.
42
+ */
43
+ const BACKGROUND_OWNERS = new Set(["native", "runtime", "opencode", "pi", "omp"]);
44
+
45
+ const packageNameCache = new Map<string, string | null>();
46
+
47
+ function urlToPath(url: string): string {
48
+ if (url.startsWith("file://")) {
49
+ try {
50
+ return decodeURIComponent(new URL(url).pathname);
51
+ } catch {
52
+ return url.slice("file://".length);
53
+ }
54
+ }
55
+ return url;
56
+ }
57
+
58
+ /**
59
+ * Nearest `package.json` name above a source file, memoized per directory.
60
+ * Only reached for sources outside `node_modules` (a plugin loaded from a
61
+ * local checkout), and only after a stall has ended, so the bounded
62
+ * synchronous reads never run on a hot path.
63
+ */
64
+ function nearestPackageName(filePath: string): string | null {
65
+ let dir = path.dirname(filePath);
66
+ const visited: string[] = [];
67
+ for (let depth = 0; depth < 12; depth++) {
68
+ const cached = packageNameCache.get(dir);
69
+ if (cached !== undefined) {
70
+ for (const seen of visited) packageNameCache.set(seen, cached);
71
+ return cached;
72
+ }
73
+ visited.push(dir);
74
+ try {
75
+ const parsed = JSON.parse(readFileSync(path.join(dir, "package.json"), "utf8")) as {
76
+ name?: unknown;
77
+ };
78
+ const name = typeof parsed.name === "string" && parsed.name ? parsed.name : null;
79
+ if (name) {
80
+ for (const seen of visited) packageNameCache.set(seen, name);
81
+ return name;
82
+ }
83
+ } catch {
84
+ // No readable package.json at this level; keep walking up.
85
+ }
86
+ const parent = path.dirname(dir);
87
+ if (parent === dir) break;
88
+ dir = parent;
89
+ }
90
+ for (const seen of visited) packageNameCache.set(seen, null);
91
+ return null;
92
+ }
93
+
94
+ /**
95
+ * Map a frame's source URL to the code that owns it.
96
+ *
97
+ * - no URL: `native` (a host function such as a SQLite `get` or `readFileSync`)
98
+ * - Bun/Node builtin modules: `runtime`
99
+ * - the compiled OpenCode binary's embedded filesystem (`$bunfs`, `~BUN`): `opencode`
100
+ * - anything under `node_modules/<pkg>`: `npm:<pkg>` (the innermost package)
101
+ * - Pi/OMP core packages: `pi` / `omp`; agent extensions: package name or `extension:<entry>`
102
+ * - a file in an OpenCode `plugin/` or `plugins/` directory: `plugin:<file>`
103
+ * - any other file: `pkg:<name>` from the nearest package.json, else `file:<path>`
104
+ */
105
+ export function sourceOwner(sourceURL: string | undefined): string {
106
+ if (!sourceURL) return "native";
107
+ if (/^(?:node|bun|builtin|internal):/.test(sourceURL)) return "runtime";
108
+ if (sourceURL.includes("$bunfs") || sourceURL.includes("~BUN")) return "opencode";
109
+ const filePath = urlToPath(sourceURL).replaceAll("\\", "/");
110
+ const modules = [...filePath.matchAll(/\/node_modules\/((?:@[^/]+\/)?[^/]+)/g)];
111
+ const innermost = modules.at(-1);
112
+ if (innermost) {
113
+ const name = innermost[1];
114
+ if (name === "@cortexkit/pi-magic-context") return `pkg:${name}`;
115
+ if (/^@(?:earendil-works|mariozechner)\/pi-(?:coding-agent|agent-core|ai|tui)$/.test(name))
116
+ return "pi";
117
+ if (/^@oh-my-pi\/pi-(?:coding-agent|agent-core|ai|tui)$/.test(name)) return "omp";
118
+ return `npm:${name}`;
119
+ }
120
+ const extension = filePath.match(/\/(?:\.pi|\.omp)\/agent\/extensions\/([^/]+)/);
121
+ if (extension) {
122
+ const name = nearestPackageName(filePath);
123
+ return name ? `pkg:${name}` : `extension:${extension[1]}`;
124
+ }
125
+ const pluginDir = filePath.match(/\/plugins?\/([^/]+)$/);
126
+ if (pluginDir && /\/(?:\.?opencode)\/plugins?\//.test(filePath)) {
127
+ return `plugin:${pluginDir[1]}`;
128
+ }
129
+ const name = nearestPackageName(filePath);
130
+ return name ? `pkg:${name}` : `file:${filePath}`;
131
+ }
132
+
133
+ function frameLabel(frame: JscSampleFrame): string {
134
+ const name = frame.name && frame.name.length > 0 ? frame.name : "(anonymous)";
135
+ if (!frame.sourceURL) return `${name} [native]`;
136
+ const line =
137
+ typeof frame.line === "number" && frame.line !== UNKNOWN_POSITION ? `:${frame.line}` : "";
138
+ return `${name} ${frame.sourceURL}${line}`;
139
+ }
140
+
141
+ export interface OwnedFrame {
142
+ label: string;
143
+ owner: string;
144
+ }
145
+
146
+ /** Prefer the innermost plugin/extension frame over native, runtime or host-core callers. */
147
+ export function attributeSample(frames: OwnedFrame[]): string {
148
+ for (const frame of frames) {
149
+ if (!BACKGROUND_OWNERS.has(frame.owner)) return frame.owner;
150
+ }
151
+ for (const frame of frames) {
152
+ if (frame.owner !== "native") return frame.owner;
153
+ }
154
+ return "native";
155
+ }
156
+
157
+ export interface CountedFrame {
158
+ frame: string;
159
+ owner: string;
160
+ samples: number;
161
+ }
162
+
163
+ export interface CountedStack {
164
+ samples: number;
165
+ owner: string;
166
+ frames: string[];
167
+ }
168
+
169
+ export interface StallAggregate {
170
+ samples: number;
171
+ owners: Array<{ owner: string; samples: number; percent: number }>;
172
+ /** Innermost frame of each sample, native host functions included. */
173
+ top_frames: CountedFrame[];
174
+ /** Innermost frame that has JavaScript source, i.e. the JS caller of any native frame. */
175
+ top_js_frames: CountedFrame[];
176
+ top_stacks: CountedStack[];
177
+ }
178
+
179
+ function bump<T>(map: Map<string, T & { samples: number }>, key: string, init: () => T): void {
180
+ const existing = map.get(key);
181
+ if (existing) existing.samples += 1;
182
+ else map.set(key, { ...init(), samples: 1 });
183
+ }
184
+
185
+ function topBySamples<T extends { samples: number }>(values: Iterable<T>, limit: number): T[] {
186
+ return [...values].sort((a, b) => b.samples - a.samples).slice(0, limit);
187
+ }
188
+
189
+ export function aggregateTraces(traces: JscSampleTrace[]): StallAggregate {
190
+ const ownerOf = new Map<string, string>();
191
+ const owned = (frame: JscSampleFrame): OwnedFrame => {
192
+ const url = frame.sourceURL ?? "";
193
+ let owner = ownerOf.get(url);
194
+ if (owner === undefined) {
195
+ owner = sourceOwner(frame.sourceURL);
196
+ ownerOf.set(url, owner);
197
+ }
198
+ return { label: frameLabel(frame), owner };
199
+ };
200
+
201
+ const owners = new Map<string, { owner: string; samples: number }>();
202
+ const topFrames = new Map<string, CountedFrame>();
203
+ const topJsFrames = new Map<string, CountedFrame>();
204
+ const stacks = new Map<string, CountedStack>();
205
+ let samples = 0;
206
+
207
+ for (const trace of traces) {
208
+ const raw = Array.isArray(trace.frames) ? trace.frames : [];
209
+ if (raw.length === 0) continue;
210
+ samples += 1;
211
+ const frames = raw.slice(0, MAX_STACK_DEPTH).map(owned);
212
+ const owner = attributeSample(frames);
213
+ bump(owners, owner, () => ({ owner }));
214
+
215
+ const leaf = frames[0];
216
+ bump(topFrames, `${leaf.owner}\u0000${leaf.label}`, () => ({
217
+ frame: leaf.label,
218
+ owner: leaf.owner,
219
+ }));
220
+ const jsIndex = raw.findIndex(
221
+ (frame, index) => index < MAX_STACK_DEPTH && !!frame.sourceURL,
222
+ );
223
+ if (jsIndex >= 0) {
224
+ const js = frames[jsIndex];
225
+ bump(topJsFrames, `${js.owner}\u0000${js.label}`, () => ({
226
+ frame: js.label,
227
+ owner: js.owner,
228
+ }));
229
+ }
230
+
231
+ const labels = frames.map((frame) => `${frame.label} (${frame.owner})`);
232
+ if (raw.length > MAX_STACK_DEPTH) {
233
+ labels.push(`… ${raw.length - MAX_STACK_DEPTH} outer frames omitted`);
234
+ }
235
+ bump(stacks, labels.join("\n"), () => ({ owner, frames: labels }));
236
+ }
237
+
238
+ return {
239
+ samples,
240
+ owners: topBySamples(owners.values(), Number.POSITIVE_INFINITY).map((entry) => ({
241
+ ...entry,
242
+ percent: samples === 0 ? 0 : Math.round((entry.samples / samples) * 1000) / 10,
243
+ })),
244
+ top_frames: topBySamples(topFrames.values(), TOP_FRAME_COUNT),
245
+ top_js_frames: topBySamples(topJsFrames.values(), TOP_FRAME_COUNT),
246
+ top_stacks: topBySamples(stacks.values(), TOP_STACK_COUNT),
247
+ };
248
+ }
@@ -0,0 +1,57 @@
1
+ import * as path from "node:path";
2
+ import { getMagicContextStorageDir } from "./data-path";
3
+ import { createHostStallProfiler } from "./host-stall-profiler-bun";
4
+ import {
5
+ HOST_PROFILER_DIRNAME,
6
+ type HostStallProfilerHandle,
7
+ type ProfilerRuntimeDeps,
8
+ } from "./host-stall-profiler-common";
9
+ import { createNodeHostStallProfiler, type InspectorSession } from "./host-stall-profiler-node";
10
+ import { log } from "./logger";
11
+
12
+ export * from "./host-stall-profiler-common";
13
+
14
+ export function hostStallProfilerDir(): string {
15
+ return path.join(getMagicContextStorageDir(), HOST_PROFILER_DIRNAME);
16
+ }
17
+
18
+ const PROCESS_PROFILER_KEY = Symbol.for("cortexkit.magic-context.host-stall-profiler");
19
+ // Resolve at runtime: Node-only consumers do not install Bun's type declarations.
20
+ const jscModule: string = "bun:jsc";
21
+
22
+ /** All plugin/project instances watch the same main thread and share one sampler. */
23
+ export function startHostStallProfilerSwitch(): void {
24
+ try {
25
+ const holder = globalThis as unknown as Record<symbol, HostStallProfilerHandle | undefined>;
26
+ if (holder[PROCESS_PROFILER_KEY]) return;
27
+ const deps: ProfilerRuntimeDeps = {
28
+ profilerDir: hostStallProfilerDir,
29
+ now: () => performance.now(),
30
+ wallNow: () => Date.now(),
31
+ setInterval: (callback, ms) => {
32
+ const handle = setInterval(callback, ms);
33
+ (handle as { unref?: () => void }).unref?.();
34
+ return handle;
35
+ },
36
+ clearInterval: (handle) => clearInterval(handle as ReturnType<typeof setInterval>),
37
+ rss: () => process.memoryUsage.rss(),
38
+ log,
39
+ pid: process.pid,
40
+ bunVersion: process.versions.bun ?? null,
41
+ };
42
+ const handle = process.versions.bun
43
+ ? createHostStallProfiler({ ...deps, loadJsc: () => import(jscModule) })
44
+ : createNodeHostStallProfiler({
45
+ ...deps,
46
+ createSession: async () => {
47
+ const { Session } = await import("node:inspector");
48
+ return new Session() as unknown as InspectorSession;
49
+ },
50
+ memoryUsage: () => process.memoryUsage(),
51
+ });
52
+ holder[PROCESS_PROFILER_KEY] = handle;
53
+ handle.start();
54
+ } catch (error) {
55
+ log("[magic-context] host stall profiler: could not start the enable-file switch", error);
56
+ }
57
+ }
@@ -129,6 +129,28 @@ if (scenario === "retry") {
129
129
  predecessorMode: fs.statSync(predecessorPath).mode & 0o777,
130
130
  files: fs.readdirSync(path.dirname(logPath)).filter((name) => name.startsWith("magic-context.log")).sort(),
131
131
  }));
132
+ } else if (scenario === "stale-rotation") {
133
+ const maxLogBytes = 32 * 1024 * 1024;
134
+ fs.mkdirSync(path.dirname(logPath), { recursive: true });
135
+ fs.writeFileSync(logPath, Buffer.alloc(maxLogBytes - 200, "o"));
136
+ fs.chmodSync(logPath, 0o600);
137
+ // This process now caches a size just under the bound.
138
+ logger.log("cached size");
139
+ logger.flushLogger();
140
+
141
+ // Another process sharing the file rotates it: the full log becomes the
142
+ // predecessor and the current file starts over.
143
+ fs.copyFileSync(logPath, logPath + ".1");
144
+ fs.writeFileSync(logPath, "written by the other process\\n");
145
+
146
+ // A line that crosses the bound only by this process's stale cached size.
147
+ logger.log("x".repeat(400));
148
+ logger.flushLogger();
149
+ console.log(JSON.stringify({
150
+ current: fs.readFileSync(logPath, "utf8"),
151
+ predecessorFirstByte: fs.readFileSync(logPath + ".1")[0],
152
+ predecessorSize: fs.statSync(logPath + ".1").size,
153
+ }));
132
154
  } else if (scenario === "hot-path") {
133
155
  for (let index = 0; index < 20; index++) {
134
156
  logger.log("hot-path-" + index);
@@ -182,6 +204,7 @@ async function runLoggerScenario<T>(
182
204
  | "recovery"
183
205
  | "diagnostics"
184
206
  | "rotation"
207
+ | "stale-rotation"
185
208
  | "hot-path"
186
209
  | "retry"
187
210
  | "bounded"
@@ -269,6 +292,21 @@ describe("logger", () => {
269
292
  }
270
293
  });
271
294
 
295
+ test("a stale cached size does not rotate a file another process already rotated", async () => {
296
+ const result = await runLoggerScenario<{
297
+ current: string;
298
+ predecessorFirstByte: number;
299
+ predecessorSize: number;
300
+ }>("stale-rotation");
301
+
302
+ // The other process's full predecessor survives, and the new line joins
303
+ // the restarted current file instead of replacing that predecessor.
304
+ expect(result.predecessorFirstByte).toBe("o".charCodeAt(0));
305
+ expect(result.predecessorSize).toBeGreaterThan(32 * 1024 * 1024 - 1024);
306
+ expect(result.current).toContain("written by the other process");
307
+ expect(result.current).toContain("x".repeat(400));
308
+ });
309
+
272
310
  test("uses cached size between periodic rotation checks", async () => {
273
311
  const result = await runLoggerScenario<HotPathScenarioResult>("hot-path");
274
312
 
@@ -163,8 +163,16 @@ function flush(): void {
163
163
  let currentSize = getCurrentLogSize(logFile);
164
164
  const dataSize = Buffer.byteLength(data);
165
165
  if (currentSize > 0 && currentSize + dataSize > MAX_LOG_FILE_BYTES) {
166
- rotateLogFile(logFile, currentSize);
167
- currentSize = 0;
166
+ // Several processes share this file and each caches its size. A stale
167
+ // cache must not rotate a file another process already rotated: that
168
+ // second rotation would overwrite the full predecessor with the few
169
+ // lines written since. Decide on the file's real size instead.
170
+ flushesSinceSizeCheck = SIZE_CHECK_INTERVAL_FLUSHES;
171
+ currentSize = getCurrentLogSize(logFile);
172
+ if (currentSize > 0 && currentSize + dataSize > MAX_LOG_FILE_BYTES) {
173
+ rotateLogFile(logFile, currentSize);
174
+ currentSize = 0;
175
+ }
168
176
  }
169
177
  fs.appendFileSync(logFile, data, { encoding: "utf8", mode: 0o600 });
170
178
  buffer = [];
@@ -231,41 +231,78 @@ describe("model-resolution", () => {
231
231
  });
232
232
  });
233
233
 
234
- test("uses mural model between compress-cues task and harness default", () => {
234
+ test("resolves compress-cues to each harness's dreamer default and ignores mural.model", () => {
235
+ // The retired shared mural.model sits in the same config to prove it
236
+ // no longer feeds resolution on any harness.
235
237
  const config = {
238
+ mural: { enabled: true, model: "google/antigravity-gemini-3.8-flash" },
236
239
  dreamer: {
237
240
  tasks: { "compress-cues": { schedule: "0 4 * * *" } },
238
241
  opencode: {
239
242
  model: { model: "open/default", variant: "default-variant" },
240
- tasks: { "compress-cues": { variant: "task-local-must-not-leak" } },
241
243
  },
242
244
  pi: {
243
- model: { model: "pi/default", thinking_level: "high" },
245
+ model: {
246
+ model: "google-antigravity/antigravity-gemini-3.8-flash",
247
+ thinking_level: "high",
248
+ },
244
249
  tasks: { "compress-cues": {} },
245
250
  },
246
251
  },
247
252
  };
248
253
 
249
254
  expect(
250
- resolveDreamerTaskModel({
251
- config,
252
- harness: "opencode",
253
- task: "compress-cues",
254
- muralModel: "mural/model",
255
- }),
255
+ resolveDreamerTaskModel({ config, harness: "opencode", task: "compress-cues" }),
256
256
  ).toMatchObject({
257
- primary: { model: "mural/model", qualifier: "default-variant" },
257
+ primary: { model: "open/default", qualifier: "default-variant" },
258
258
  fallbacks: [],
259
+ schedule: "0 4 * * *",
259
260
  });
260
261
  expect(
261
- resolveDreamerTaskModel({
262
- config,
263
- harness: "pi",
264
- task: "compress-cues",
265
- muralModel: "mural/model",
266
- }),
262
+ resolveDreamerTaskModel({ config, harness: "pi", task: "compress-cues" }),
263
+ ).toMatchObject({
264
+ primary: {
265
+ model: "google-antigravity/antigravity-gemini-3.8-flash",
266
+ qualifier: "high",
267
+ },
268
+ fallbacks: [],
269
+ schedule: "0 4 * * *",
270
+ });
271
+ });
272
+
273
+ test("a per-harness compress-cues task override wins over the harness default", () => {
274
+ const config = {
275
+ mural: { enabled: true, model: "shared/must-not-win" },
276
+ dreamer: {
277
+ opencode: {
278
+ model: "open/default",
279
+ fallback_models: ["open/default-fallback"],
280
+ tasks: {
281
+ "compress-cues": {
282
+ model: { model: "open/cues", variant: "low" },
283
+ fallback_models: ["open/cues-fallback"],
284
+ },
285
+ },
286
+ },
287
+ pi: {
288
+ model: "pi/default",
289
+ thinking_level: "high",
290
+ tasks: { "compress-cues": { model: "pi/cues" } },
291
+ },
292
+ },
293
+ };
294
+
295
+ expect(
296
+ resolveDreamerTaskModel({ config, harness: "opencode", task: "compress-cues" }),
297
+ ).toMatchObject({
298
+ primary: { model: "open/cues", qualifier: "low" },
299
+ fallbacks: [{ model: "open/cues-fallback" }],
300
+ });
301
+ // A task override without its own qualifier uses the harness default's qualifier.
302
+ expect(
303
+ resolveDreamerTaskModel({ config, harness: "pi", task: "compress-cues" }),
267
304
  ).toMatchObject({
268
- primary: { model: "mural/model", qualifier: "high" },
305
+ primary: { model: "pi/cues", qualifier: "high" },
269
306
  fallbacks: [],
270
307
  });
271
308
  });
@@ -137,14 +137,13 @@ export interface ResolvedDreamerTaskModel {
137
137
 
138
138
  /**
139
139
  * Resolve a dreamer task from one harness subtree. Model selection is task →
140
- * harness default, except compress-cues inserts its harness-independent mural
141
- * string between those two rungs. Scheduling remains at dreamer.tasks.<task>.
140
+ * harness default for every task, compress-cues included. Scheduling remains
141
+ * at dreamer.tasks.<task>.
142
142
  */
143
143
  export function resolveDreamerTaskModel(args: {
144
144
  config: unknown;
145
145
  harness: ModelHarness;
146
146
  task: string;
147
- muralModel?: unknown;
148
147
  }): ResolvedDreamerTaskModel {
149
148
  const dreamer = asRecord(asRecord(args.config)?.dreamer);
150
149
  const harnessBlock = resolveHarnessBlock(dreamer, args.harness);
@@ -166,19 +165,13 @@ export function resolveDreamerTaskModel(args: {
166
165
  }
167
166
 
168
167
  const taskQualifier = taskBlock?.[args.harness === "opencode" ? "variant" : "thinking_level"];
169
- // A mural string borrows the harness default's qualifier whether that
170
- // qualifier is written beside `model` or inside the default entry object.
168
+ // A task override without its own qualifier borrows the harness default's
169
+ // qualifier, whether written beside `model` or inside the default entry object.
171
170
  const harnessQualifier =
172
171
  harnessBlock[args.harness === "opencode" ? "variant" : "thinking_level"] ??
173
172
  normalizeModelEntry(harnessBlock.model, args.harness)?.qualifier;
174
173
  const taskHasModel = taskBlock !== undefined && hasOwn(taskBlock, "model");
175
- const usesMuralModel =
176
- !taskHasModel && args.task === "compress-cues" && Boolean(readString(args.muralModel));
177
- const primarySource = taskHasModel
178
- ? taskBlock?.model
179
- : usesMuralModel
180
- ? args.muralModel
181
- : harnessBlock.model;
174
+ const primarySource = taskHasModel ? taskBlock?.model : harnessBlock.model;
182
175
  const fallbackSource =
183
176
  taskBlock !== undefined && hasOwn(taskBlock, "fallback_models")
184
177
  ? taskBlock.fallback_models
@@ -187,11 +180,7 @@ export function resolveDreamerTaskModel(args: {
187
180
  return {
188
181
  primary: resolvePrimaryEntry({
189
182
  entry: primarySource,
190
- // mural.model is a plain string, so its qualifier is always the
191
- // executing harness default rather than a task-local default.
192
- defaultQualifier: usesMuralModel
193
- ? harnessQualifier
194
- : (taskQualifier ?? harnessQualifier),
183
+ defaultQualifier: taskQualifier ?? harnessQualifier,
195
184
  harness: args.harness,
196
185
  }),
197
186
  fallbacks: resolveFallbackEntries(fallbackSource, args.harness),
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Temperature capability from the models.dev catalog that OpenCode caches on disk.
3
+ *
4
+ * OpenCode 1 copies models.dev's `temperature` flag onto each model, but OpenCode 2's
5
+ * model rows, Pi's model registry and Oh My Pi's Gemini models carry no equivalent
6
+ * field. For those hosts the cached catalog is the only positive evidence on the
7
+ * machine, so a missing file, an unparsable file or a missing entry all mean "unknown"
8
+ * and the caller omits temperature.
9
+ *
10
+ * This module is bundled into the Pi/OMP historian child extension, so it must only
11
+ * depend on Node built-ins.
12
+ */
13
+ import { readFileSync, statSync } from "node:fs";
14
+ import { homedir } from "node:os";
15
+ import { join } from "node:path";
16
+
17
+ export interface CatalogTemperature {
18
+ temperature: boolean;
19
+ /** The catalog entry that decided, as `provider/model`. */
20
+ entry: string;
21
+ }
22
+
23
+ /**
24
+ * Harness provider ids that name the same models.dev provider. Codex (`openai-codex`)
25
+ * is deliberately absent: the ChatGPT backend is a different transport from the
26
+ * OpenAI API that models.dev describes, so it gets no catalog answer and no temperature.
27
+ */
28
+ const CATALOG_PROVIDER_ALIASES: Readonly<Record<string, string>> = {
29
+ "google-antigravity": "google",
30
+ "opencode-zen": "opencode",
31
+ };
32
+
33
+ /** The Antigravity auth plugins register Gemini models as `google/antigravity-<model>`. */
34
+ const ANTIGRAVITY_MODEL_PREFIX = "antigravity-";
35
+
36
+ type CatalogIndex = Map<string, boolean>;
37
+
38
+ let cached: { path: string; mtimeMs: number; size: number; index: CatalogIndex } | undefined;
39
+
40
+ /** OpenCode reads `OPENCODE_MODELS_PATH` instead of its cache when it is set. */
41
+ export function modelsDevCatalogPath(env: NodeJS.ProcessEnv = process.env): string {
42
+ if (env.OPENCODE_MODELS_PATH) return env.OPENCODE_MODELS_PATH;
43
+ return join(env.XDG_CACHE_HOME || join(homedir(), ".cache"), "opencode", "models.json");
44
+ }
45
+
46
+ function buildIndex(raw: unknown): CatalogIndex {
47
+ const index: CatalogIndex = new Map();
48
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return index;
49
+ for (const [providerID, provider] of Object.entries(raw as Record<string, unknown>)) {
50
+ const models = (provider as { models?: unknown } | null)?.models;
51
+ if (!models || typeof models !== "object") continue;
52
+ for (const [modelID, model] of Object.entries(models as Record<string, unknown>)) {
53
+ const temperature = (model as { temperature?: unknown } | null)?.temperature;
54
+ if (typeof temperature === "boolean")
55
+ index.set(`${providerID}/${modelID}`, temperature);
56
+ }
57
+ }
58
+ return index;
59
+ }
60
+
61
+ function loadIndex(): CatalogIndex | undefined {
62
+ const path = modelsDevCatalogPath();
63
+ try {
64
+ const stat = statSync(path);
65
+ if (cached?.path === path && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size)
66
+ return cached.index;
67
+ const index = buildIndex(JSON.parse(readFileSync(path, "utf8")));
68
+ cached = { path, mtimeMs: stat.mtimeMs, size: stat.size, index };
69
+ return index;
70
+ } catch {
71
+ // Absent or partially written catalog: no evidence either way.
72
+ return undefined;
73
+ }
74
+ }
75
+
76
+ /** Spellings to try for a harness `provider/model` reference, most specific first. */
77
+ export function catalogCandidates(providerID: string, modelID: string): string[] {
78
+ const provider = Object.hasOwn(CATALOG_PROVIDER_ALIASES, providerID)
79
+ ? CATALOG_PROVIDER_ALIASES[providerID]
80
+ : providerID;
81
+ const candidates = [`${provider}/${modelID}`];
82
+ if (provider === "google" && modelID.startsWith(ANTIGRAVITY_MODEL_PREFIX))
83
+ candidates.push(`google/${modelID.slice(ANTIGRAVITY_MODEL_PREFIX.length)}`);
84
+ return candidates;
85
+ }
86
+
87
+ /**
88
+ * Look `provider/model` up in the cached catalogue, trying only the exact spellings from
89
+ * `catalogCandidates`. A malformed reference, a missing catalogue or no entry returns undefined.
90
+ */
91
+ export function catalogTemperature(model: string): CatalogTemperature | undefined {
92
+ const slash = model.indexOf("/");
93
+ if (slash <= 0 || slash === model.length - 1) return undefined;
94
+ const index = loadIndex();
95
+ if (!index) return undefined;
96
+ for (const entry of catalogCandidates(model.slice(0, slash), model.slice(slash + 1))) {
97
+ const temperature = index.get(entry);
98
+ if (temperature !== undefined) return { temperature, entry };
99
+ }
100
+ return undefined;
101
+ }
102
+
103
+ export const __catalogTest = {
104
+ reset(): void {
105
+ cached = undefined;
106
+ },
107
+ };