@cortexkit/opencode-magic-context 0.33.0 → 0.34.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 (265) hide show
  1. package/dist/config/agent-disable.d.ts +22 -0
  2. package/dist/config/agent-disable.d.ts.map +1 -1
  3. package/dist/config/index.d.ts.map +1 -1
  4. package/dist/config/project-security.d.ts +7 -0
  5. package/dist/config/project-security.d.ts.map +1 -1
  6. package/dist/config/schema/magic-context.d.ts +144 -24
  7. package/dist/config/schema/magic-context.d.ts.map +1 -1
  8. package/dist/config/transform-mode.d.ts +2 -0
  9. package/dist/config/transform-mode.d.ts.map +1 -1
  10. package/dist/{conflict-warning-hook-bwa99a04.js → conflict-warning-hook-fvpfvt0w.js} +1 -1
  11. package/dist/{derive-budgets-e9j09sjr.js → derive-budgets-9crp0cvd.js} +1 -1
  12. package/dist/features/builtin-commands/commands.d.ts +1 -1
  13. package/dist/features/builtin-commands/commands.d.ts.map +1 -1
  14. package/dist/features/magic-context/compaction-marker.d.ts +106 -0
  15. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  16. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +0 -2
  17. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  18. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  21. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  23. package/dist/features/magic-context/dreamer/task-registry.d.ts +0 -1
  24. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  25. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  26. package/dist/features/magic-context/fail-closed-block.d.ts +10 -0
  27. package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
  28. package/dist/features/magic-context/git-commits/index.d.ts +2 -2
  29. package/dist/features/magic-context/git-commits/index.d.ts.map +1 -1
  30. package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts +0 -2
  31. package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -1
  32. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts +0 -13
  33. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
  34. package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
  35. package/dist/features/magic-context/memory/embedding-local.d.ts +7 -1
  36. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  37. package/dist/features/magic-context/memory/embedding.d.ts +1 -2
  38. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  39. package/dist/features/magic-context/memory/memory-migration.d.ts +0 -6
  40. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  41. package/dist/features/magic-context/memory/project-identity.d.ts +2 -6
  42. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  43. package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts +0 -1
  44. package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
  45. package/dist/features/magic-context/memory/storage-memory.d.ts +1 -6
  46. package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
  47. package/dist/features/magic-context/memory/verification-paths.d.ts +0 -1
  48. package/dist/features/magic-context/memory/verification-paths.d.ts.map +1 -1
  49. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  50. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  51. package/dist/features/magic-context/mural/render-mural.d.ts.map +1 -1
  52. package/dist/features/magic-context/mural/storage-mural.d.ts +0 -1
  53. package/dist/features/magic-context/mural/storage-mural.d.ts.map +1 -1
  54. package/dist/features/magic-context/overflow-detection.d.ts +8 -1
  55. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  56. package/dist/features/magic-context/project-embedding-registry.d.ts +16 -2
  57. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  58. package/dist/features/magic-context/scheduler.d.ts.map +1 -1
  59. package/dist/features/magic-context/schema-fence-probe.d.ts +28 -0
  60. package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -0
  61. package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
  62. package/dist/features/magic-context/smart-notes/capabilities.d.ts +0 -2
  63. package/dist/features/magic-context/smart-notes/capabilities.d.ts.map +1 -1
  64. package/dist/features/magic-context/smart-notes/compiler.d.ts +0 -1
  65. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  66. package/dist/features/magic-context/smart-notes/types.d.ts +0 -16
  67. package/dist/features/magic-context/smart-notes/types.d.ts.map +1 -1
  68. package/dist/features/magic-context/storage-db.d.ts +35 -1
  69. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  70. package/dist/features/magic-context/storage-meta-persisted.d.ts +38 -5
  71. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  72. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  73. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  74. package/dist/features/magic-context/storage.d.ts +1 -1
  75. package/dist/features/magic-context/storage.d.ts.map +1 -1
  76. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  77. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +0 -2
  78. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  79. package/dist/hooks/auto-update-checker/types.d.ts +0 -3
  80. package/dist/hooks/auto-update-checker/types.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/boundary-execution.d.ts +1 -1
  82. package/dist/hooks/magic-context/boundary-execution.d.ts.map +1 -1
  83. package/dist/hooks/magic-context/cache-busting-signals.d.ts +1 -1
  84. package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
  85. package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/child-session-spawn.d.ts +26 -0
  87. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -0
  88. package/dist/hooks/magic-context/command-handler.d.ts +2 -0
  89. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  90. package/dist/hooks/magic-context/compaction-marker-manager.d.ts +49 -0
  91. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  92. package/dist/hooks/magic-context/compaction-off-transition.d.ts +96 -0
  93. package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -0
  94. package/dist/hooks/magic-context/compartment-parser.d.ts +12 -0
  95. package/dist/hooks/magic-context/compartment-parser.d.ts.map +1 -1
  96. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -0
  97. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  98. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/compartment-runner-mapping.d.ts +0 -12
  100. package/dist/hooks/magic-context/compartment-runner-mapping.d.ts.map +1 -1
  101. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  102. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  103. package/dist/hooks/magic-context/compartment-trigger.d.ts +12 -5
  104. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  105. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +47 -1
  106. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
  107. package/dist/hooks/magic-context/emergency-drop.d.ts +2 -2
  108. package/dist/hooks/magic-context/event-handler.d.ts +7 -0
  109. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  110. package/dist/hooks/magic-context/event-resolvers.d.ts +13 -21
  111. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  112. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
  113. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  114. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +1 -1
  115. package/dist/hooks/magic-context/historian-prompt.generated.d.ts +1 -1
  116. package/dist/hooks/magic-context/historian-prompt.generated.d.ts.map +1 -1
  117. package/dist/hooks/magic-context/hook-handlers.d.ts +1 -0
  118. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  119. package/dist/hooks/magic-context/hook.d.ts +11 -1
  120. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  121. package/dist/hooks/magic-context/inject-compartments.d.ts +18 -0
  122. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  123. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  124. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  125. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  126. package/dist/hooks/magic-context/rust-mode-transform.d.ts +3 -0
  127. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  128. package/dist/hooks/magic-context/send-session-notification.d.ts +20 -1
  129. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  130. package/dist/hooks/magic-context/sentinel.d.ts +39 -0
  131. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  132. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  133. package/dist/hooks/magic-context/tool-drop-target.d.ts +19 -0
  134. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  135. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -0
  136. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  137. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +30 -0
  138. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  139. package/dist/hooks/magic-context/transform.d.ts +27 -0
  140. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  141. package/dist/{index-kxz4tn6m.js → index-56yjaeb2.js} +56 -4
  142. package/dist/{index-bmkea2dq.js → index-b563sga5.js} +40 -287
  143. package/dist/{index-y1c9tcm3.js → index-cn960ffd.js} +101 -20
  144. package/dist/{index-k5y60ymm.js → index-dtas91s5.js} +27 -6
  145. package/dist/index-fcyvznch.js +279 -0
  146. package/dist/{index-63dq2g4d.js → index-ry8rh8cv.js} +138 -24
  147. package/dist/{index-h86twgsp.js → index-s0mdn690.js} +2113 -1067
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +1356 -627
  150. package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
  151. package/dist/plugin/hooks/create-session-hooks.d.ts +19 -8
  152. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  153. package/dist/plugin/messages-transform.d.ts +10 -0
  154. package/dist/plugin/messages-transform.d.ts.map +1 -1
  155. package/dist/plugin/rpc-handlers.d.ts +3 -7
  156. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  157. package/dist/plugin/tool-registry.d.ts +8 -0
  158. package/dist/plugin/tool-registry.d.ts.map +1 -1
  159. package/dist/{recomp-orchestrator-yh7pepvx.js → recomp-orchestrator-8e82vmvb.js} +6 -5
  160. package/dist/send-session-notification-6njqewzk.js +20 -0
  161. package/dist/shared/conflict-detector.d.ts +38 -1
  162. package/dist/shared/conflict-detector.d.ts.map +1 -1
  163. package/dist/shared/conflict-fixer.d.ts +18 -1
  164. package/dist/shared/conflict-fixer.d.ts.map +1 -1
  165. package/dist/shared/context-limit-provenance.d.ts +3 -0
  166. package/dist/shared/context-limit-provenance.d.ts.map +1 -0
  167. package/dist/shared/escalation-bands.d.ts +9 -0
  168. package/dist/shared/escalation-bands.d.ts.map +1 -0
  169. package/dist/shared/format-threshold.d.ts +1 -1
  170. package/dist/shared/models-dev-cache.d.ts +29 -3
  171. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  172. package/dist/shared/rpc-server.d.ts.map +1 -1
  173. package/dist/shared/rpc-types.d.ts +46 -1
  174. package/dist/shared/rpc-types.d.ts.map +1 -1
  175. package/dist/shared/sqlite.d.ts +9 -4
  176. package/dist/shared/sqlite.d.ts.map +1 -1
  177. package/dist/shared/storage-permissions.d.ts +5 -0
  178. package/dist/shared/storage-permissions.d.ts.map +1 -0
  179. package/dist/{storage-meta-session-1phy0b1z.js → storage-meta-session-xt41zbw4.js} +2 -1
  180. package/dist/{task-config-dn9k9szr.js → task-config-5nx3qfz8.js} +1 -2
  181. package/dist/tui/compaction-off.d.ts +13 -0
  182. package/dist/tui/compaction-off.d.ts.map +1 -0
  183. package/dist/tui/data/context-db.d.ts.map +1 -1
  184. package/dist/tui-compiled/compaction-off.d.ts +13 -0
  185. package/dist/tui-compiled/compaction-off.d.ts.map +1 -0
  186. package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
  187. package/package.json +8 -3
  188. package/src/agents/dreamer.ts +68 -0
  189. package/src/agents/hidden-agent-registrations.ts +331 -0
  190. package/src/agents/historian.ts +3 -0
  191. package/src/agents/language-directive.test.ts +138 -0
  192. package/src/agents/language-directive.ts +121 -0
  193. package/src/agents/magic-context-prompt.language.test.ts +35 -0
  194. package/src/agents/magic-context-prompt.test.ts +292 -0
  195. package/src/agents/magic-context-prompt.ts +182 -0
  196. package/src/agents/permissions.test.ts +252 -0
  197. package/src/agents/permissions.ts +186 -0
  198. package/src/agents/sidekick.ts +1 -0
  199. package/src/agents/smart-note-compiler.ts +1 -0
  200. package/src/config/agent-disable.ts +106 -0
  201. package/src/config/compaction-accessor-guard.test.ts +82 -0
  202. package/src/config/compaction-backcompat.test.ts +52 -0
  203. package/src/config/index.test.ts +904 -0
  204. package/src/config/index.ts +601 -0
  205. package/src/config/migrate-config-location.test.ts +332 -0
  206. package/src/config/migrate-config-location.ts +635 -0
  207. package/src/config/migrate-dreamer-v2.test.ts +287 -0
  208. package/src/config/migrate-dreamer-v2.ts +336 -0
  209. package/src/config/migrate-experimental.ts +159 -0
  210. package/src/config/project-security.test.ts +366 -0
  211. package/src/config/project-security.ts +588 -0
  212. package/src/config/prune-config-leaf.test.ts +78 -0
  213. package/src/config/prune-config-leaf.ts +68 -0
  214. package/src/config/removed-config-keys.test.ts +116 -0
  215. package/src/config/schema/agent-overrides.ts +45 -0
  216. package/src/config/schema/magic-context.test.ts +358 -0
  217. package/src/config/schema/magic-context.ts +1002 -0
  218. package/src/config/transform-mode.test.ts +62 -0
  219. package/src/config/transform-mode.ts +34 -0
  220. package/src/config/variable.test.ts +323 -0
  221. package/src/config/variable.ts +192 -0
  222. package/src/features/magic-context/defaults.ts +1 -0
  223. package/src/features/magic-context/dreamer/cron.ts +243 -0
  224. package/src/features/magic-context/dreamer/task-registry.ts +104 -0
  225. package/src/shared/conflict-detector.test.ts +251 -1
  226. package/src/shared/conflict-detector.ts +84 -5
  227. package/src/shared/conflict-fixer.test.ts +309 -0
  228. package/src/shared/conflict-fixer.ts +82 -5
  229. package/src/shared/context-limit-provenance.ts +6 -0
  230. package/src/shared/escalation-bands.test.ts +23 -0
  231. package/src/shared/escalation-bands.ts +18 -0
  232. package/src/shared/format-threshold.ts +1 -1
  233. package/src/shared/models-dev-cache.test.ts +171 -0
  234. package/src/shared/models-dev-cache.ts +195 -38
  235. package/src/shared/rpc-server.ts +27 -18
  236. package/src/shared/rpc-types.ts +46 -1
  237. package/src/shared/sqlite.ts +13 -33
  238. package/src/shared/storage-permissions.ts +20 -0
  239. package/src/tui/compaction-off.test.ts +56 -0
  240. package/src/tui/compaction-off.ts +29 -0
  241. package/src/tui/data/context-db.ts +6 -0
  242. package/src/tui/index.tsx +113 -65
  243. package/src/tui/slots/sidebar-content.tsx +139 -83
  244. package/src/tui-compiled/compaction-off.ts +29 -0
  245. package/src/tui-compiled/data/context-db.ts +6 -0
  246. package/src/tui-compiled/index.tsx +558 -455
  247. package/src/tui-compiled/slots/sidebar-content.tsx +237 -161
  248. package/dist/config/schema.d.ts +0 -3
  249. package/dist/config/schema.d.ts.map +0 -1
  250. package/dist/features/magic-context/plugin-messages.d.ts +0 -75
  251. package/dist/features/magic-context/plugin-messages.d.ts.map +0 -1
  252. package/dist/hooks/magic-context/compartment-runner-state-xml.d.ts +0 -21
  253. package/dist/hooks/magic-context/compartment-runner-state-xml.d.ts.map +0 -1
  254. package/dist/index-anhrfygk.js +0 -57
  255. package/dist/send-session-notification-tghq9gnh.js +0 -11
  256. package/dist/shared/opencode-compaction-detector.d.ts +0 -2
  257. package/dist/shared/opencode-compaction-detector.d.ts.map +0 -1
  258. package/dist/shared/transcript-opencode.d.ts +0 -71
  259. package/dist/shared/transcript-opencode.d.ts.map +0 -1
  260. package/dist/tools/index.d.ts +0 -6
  261. package/dist/tools/index.d.ts.map +0 -1
  262. package/src/shared/opencode-compaction-detector.test.ts +0 -239
  263. package/src/shared/opencode-compaction-detector.ts +0 -81
  264. package/src/shared/transcript-opencode.ts +0 -302
  265. /package/dist/{index-v7fmc1s2.js → index-ygcng9t8.js} +0 -0
@@ -0,0 +1,13 @@
1
+ import type { SidebarSnapshot } from "../shared/rpc-types";
2
+ export interface CompactionOffSidebarRow {
3
+ label: "Memories" | "Notes" | "Archived compartments";
4
+ value: string;
5
+ }
6
+ /**
7
+ * Formats context pressure from the current wire input and the model context
8
+ * limit. It deliberately does not use the stored Magic Context threshold
9
+ * percentage, because native compaction acts on the model window instead.
10
+ */
11
+ export declare function nativeCompactionContextLabel(snapshot: SidebarSnapshot): string;
12
+ export declare function compactionOffSidebarRows(snapshot: SidebarSnapshot): CompactionOffSidebarRow[];
13
+ //# sourceMappingURL=compaction-off.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction-off.d.ts","sourceRoot":"","sources":["../../src/tui-compiled/compaction-off.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,UAAU,GAAG,OAAO,GAAG,uBAAuB,CAAC;IACtD,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAI9E;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,GAAG,uBAAuB,EAAE,CAU7F"}
@@ -1 +1 @@
1
- {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui-compiled/data/context-db.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEzF,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAc3D,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;sCACsC;AACtC,wBAAgB,YAAY,IAAI,qBAAqB,GAAG,IAAI,CAE3D;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAM/B;AAuFD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CA0CvB;AAYD,gEAAgE;AAChE,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAchG;AAED,MAAM,MAAM,sBAAsB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhG,oFAAoF;AACpF,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAe5F;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED;mFACmF;AACnF,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQxE;AAED;;iDAEiD;AACjD,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUhF;AAED,gEAAgE;AAChE,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAQ3D;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAkBrE;AAED,wEAAwE;AACxE,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAQtD"}
1
+ {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui-compiled/data/context-db.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEzF,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAc3D,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;sCACsC;AACtC,wBAAgB,YAAY,IAAI,qBAAqB,GAAG,IAAI,CAE3D;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAM/B;AAwFD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CA+CvB;AAYD,gEAAgE;AAChE,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAchG;AAED,MAAM,MAAM,sBAAsB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhG,oFAAoF;AACpF,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAe5F;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED;mFACmF;AACnF,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQxE;AAED;;iDAEiD;AACjD,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUhF;AAED,gEAAgE;AAChE,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAQ3D;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAkBrE;AAED,wEAAwE;AACxE,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAQtD"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.33.0",
3
+ "version": "0.34.0",
4
4
  "type": "module",
5
- "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
5
+ "description": "OpenCode plugin for Magic Context \u2014 cross-session memory and context management",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "author": "ualtinok",
@@ -27,10 +27,15 @@
27
27
  "src/tui",
28
28
  "src/tui-compiled",
29
29
  "src/shared",
30
+ "src/config",
31
+ "src/agents",
32
+ "src/features/magic-context/defaults.ts",
33
+ "src/features/magic-context/dreamer/cron.ts",
34
+ "src/features/magic-context/dreamer/task-registry.ts",
30
35
  "README.md"
31
36
  ],
32
37
  "scripts": {
33
- "build": "bun run build:tui && bun build src/index.ts --outdir dist --target node --format esm --splitting --external @opencode-ai/plugin --external @huggingface/transformers --external onnxruntime-web --external bun:sqlite --external node:sqlite && tsc --emitDeclarationOnly",
38
+ "build": "bun run build:tui && rm -f dist/index.js dist/*-*.js && bun build src/index.ts --outdir dist --target node --format esm --splitting --external @opencode-ai/plugin --external @huggingface/transformers --external onnxruntime-web --external bun:sqlite --external node:sqlite && tsc --emitDeclarationOnly",
34
39
  "build:tui": "bun scripts/build-tui.ts",
35
40
  "check:tui-compiled": "bun run build:tui && git diff --exit-code -- src/tui-compiled && test -z \"$(git status --porcelain -- src/tui-compiled)\"",
36
41
  "typecheck": "tsc --noEmit && tsc -p tsconfig.scripts.json",
@@ -0,0 +1,68 @@
1
+ export const DREAMER_AGENT = "dreamer";
2
+ export const DREAMER_RETROSPECTIVE_AGENT = "dreamer-retrospective";
3
+ // Read-only code investigator for the refresh-primers task. Locked to
4
+ // navigation/read/search tools only — NO write/edit/bash/ctx_memory/ctx_note —
5
+ // because it runs an unsupervised, scheduled, weak-model agentic loop. A
6
+ // ctx_memory mutation here would bump the project memory epoch and bust m[0],
7
+ // violating the primers cache-neutral contract; write/bash could corrupt the
8
+ // user's source. Mirrors the dreamer-retrospective lockPermissions pattern.
9
+ export const DREAMER_PRIMER_INVESTIGATOR_AGENT = "dreamer-primer-investigator";
10
+
11
+ // Locked read-only code reader for the memory-maintenance tasks (map-memories,
12
+ // verify, verify-broad). Same source-safety + cache-neutrality lock as the
13
+ // primer investigator (NO write/edit/bash/ctx_memory), but deliberately WITHOUT
14
+ // ctx_search — these tasks check memories against the CURRENT local source, not
15
+ // cross-session recall. The host parses the agent's XML manifest and applies the
16
+ // DB writes itself, so the agent never needs a mutation tool.
17
+ export const DREAMER_MEMORY_MAPPER_AGENT = "dreamer-memory-mapper";
18
+
19
+ /** Read-only tool profile shared by the memory-maintenance reader agent.
20
+ * No ctx_search (local-source checks only), no write/bash/ctx_memory. */
21
+ export const DREAMER_MEMORY_MAPPER_ALLOWED_TOOLS = [
22
+ "read",
23
+ "grep",
24
+ "glob",
25
+ "aft_outline",
26
+ "aft_zoom",
27
+ "aft_search",
28
+ ] as const;
29
+
30
+ // Pure-transform classifier for the classify-memories task: prompt in → ONE XML
31
+ // manifest out, ZERO tools. classify scores metadata from the memory text alone
32
+ // (no code inspection), and the host applies the column writes — so the agent
33
+ // needs no tools at all. Locked so a user override can't grant any.
34
+ export const DREAMER_CLASSIFIER_AGENT = "dreamer-classifier";
35
+
36
+ // Docs maintainer for the maintain-docs task: explores the codebase and writes
37
+ // ARCHITECTURE.md / STRUCTURE.md. Needs file read + write/edit + bash (git log,
38
+ // find) + aft navigation, but deliberately NO ctx_memory/ctx_search/ctx_note —
39
+ // it touches docs, never the memory store. Locked so a user override can't add
40
+ // the memory surface back.
41
+ export const DREAMER_DOCS_AGENT = "dreamer-docs";
42
+
43
+ /** Codebase-read + doc-write tool profile for the docs maintainer. No memory
44
+ * tools (it edits docs, not the memory store). */
45
+ export const DREAMER_DOCS_ALLOWED_TOOLS = [
46
+ "read",
47
+ "grep",
48
+ "glob",
49
+ "bash",
50
+ "write",
51
+ "edit",
52
+ "aft_outline",
53
+ "aft_zoom",
54
+ "aft_search",
55
+ ] as const;
56
+
57
+ // Pure JSON reviewer for the review-user-memories task: reads the candidate
58
+ // observations the host renders and returns a JSON verdict the host applies. It
59
+ // calls NO tools (zero), so it gets the empty allow-list, locked.
60
+ export const DREAMER_REVIEWER_AGENT = "dreamer-reviewer";
61
+
62
+ /** Tool profile for the base `dreamer` agent, now CURATE-ONLY (memory-pool
63
+ * hygiene). Curate edits the memory store through ctx_memory and never reads
64
+ * code (a separate verify task owns memory-vs-code correctness), so it needs
65
+ * only ctx_memory — not the former bash/write/edit/read/aft/ctx_search/ctx_note
66
+ * kitchen sink. Kept on the `dreamer` id so the ctx_memory dreamer-action gate
67
+ * (toolContext.agent === DREAMER_AGENT) still recognizes it. */
68
+ export const DREAMER_CURATE_ALLOWED_TOOLS = ["ctx_memory"] as const;
@@ -0,0 +1,331 @@
1
+ import { applyDisallowedTools, buildAllowOnlyPermission } from "./permissions";
2
+
3
+ /**
4
+ * Hidden-agent registration builders.
5
+ *
6
+ * # Why this lives in its own module (NOT in the plugin entry `index.ts`)
7
+ *
8
+ * OpenCode loads a plugin module and, for the legacy plugin shape (a function
9
+ * `default` export rather than a `{ server, tui }` object), treats EVERY
10
+ * exported function in that module as a plugin factory and invokes it with the
11
+ * plugin input `{ client, directory, ... }` (see opencode
12
+ * `plugin/index.ts` → `getLegacyPlugins`). magic-context uses that legacy shape.
13
+ *
14
+ * If `buildHiddenAgentRegistrations` is exported from the entry module it gets
15
+ * called by the loader as `buildHiddenAgentRegistrations(pluginInput)` — with
16
+ * the wrong argument — so `args.historianDisallowed` is `undefined` and
17
+ * `applyDisallowedTools([...], undefined)` throws
18
+ * `undefined is not an object (evaluating 'disallowed.includes')`, which fails
19
+ * the WHOLE plugin load. Keeping these helpers out of the entry module means the
20
+ * entry module's only export is `default` (the real plugin factory); these
21
+ * builders are still bundled (inlined) into `dist/index.js`, just never treated
22
+ * as plugin factories.
23
+ */
24
+
25
+ // Clamp a user-provided step override to the hidden-agent's built-in cap (loop
26
+ // insurance — see buildHiddenAgentConfig). Caps live as inline literals in
27
+ // buildHiddenAgentRegistrations (historian/sidekick=40, dreamer=150): a handful
28
+ // of tool calls for the historian/sidekick, a real multi-step maintenance loop
29
+ // for the dreamer.
30
+ function clampHiddenAgentStepLimit(value: unknown, cap: number): number {
31
+ return typeof value === "number" && Number.isFinite(value) ? Math.min(value, cap) : cap;
32
+ }
33
+
34
+ /**
35
+ * Static registration data for one hidden agent. The id / allow-list / step cap
36
+ * are INLINE LITERALS in {@link buildHiddenAgentRegistrations} rather than
37
+ * cross-module `const` imports.
38
+ *
39
+ * # Why inline
40
+ *
41
+ * Belt-and-suspenders, not the load-bearing fix. The load failure was caused by
42
+ * exporting helpers from the entry module (see the module header) — that is what
43
+ * the entry-only-`default` rule fixes. Inlining the small id/tool/step values
44
+ * additionally removes any dependency on cross-module top-level `const` init
45
+ * timing, so this builder returns a complete, valid registration set the instant
46
+ * it is called regardless of module-evaluation order. Cheap insurance for a path
47
+ * that runs once per plugin-instance boot.
48
+ *
49
+ * The only value that cannot be inlined is the multi-KB generated system prompt;
50
+ * it stays a module `var` and is guarded at the call site (skip the agent + log
51
+ * if undefined, never register a broken/deny-all agent).
52
+ *
53
+ * `agent-registration-drift.test.ts` asserts the inline literals here stay
54
+ * byte-identical to the canonical exported constants so they can't silently
55
+ * diverge.
56
+ */
57
+ export interface HiddenAgentRegistration {
58
+ id: string;
59
+ prompt: string | undefined;
60
+ allowedTools: readonly string[];
61
+ maxSteps: number;
62
+ overrides?: Record<string, unknown>;
63
+ /** Drop any user `permission` override (privacy-critical agents only). */
64
+ lockPermissions?: boolean;
65
+ }
66
+
67
+ /**
68
+ * Hoisted function declaration: returns the four hidden-agent registrations with
69
+ * INLINE id / allow-list / step-cap literals (see {@link HiddenAgentRegistration}
70
+ * for why these must not come from module-level `var` consts). Prompts and
71
+ * computed overrides are passed in by the caller; the historian disallow filter
72
+ * is applied here against an inline default allow-list.
73
+ */
74
+ export function buildHiddenAgentRegistrations(args: {
75
+ dreamerPrompt: string | undefined;
76
+ smartNoteCompilerPrompt?: string | undefined;
77
+ historianPrompt: string | undefined;
78
+ historianRecompPrompt?: string | undefined;
79
+ historianEditorPrompt: string | undefined;
80
+ sidekickPrompt: string | undefined;
81
+ dreamerOverrides?: Record<string, unknown>;
82
+ historianOverrides?: Record<string, unknown>;
83
+ sidekickOverrides?: Record<string, unknown>;
84
+ historianDisallowed: readonly string[];
85
+ }): HiddenAgentRegistration[] {
86
+ const historianAllowedTools = applyDisallowedTools(
87
+ ["read", "aft_outline", "aft_zoom", "aft_search"],
88
+ args.historianDisallowed,
89
+ );
90
+ return [
91
+ {
92
+ id: "dreamer",
93
+ prompt: args.dreamerPrompt,
94
+ // CURATE-ONLY now. Curate edits the memory store via ctx_memory and
95
+ // never reads code (a separate verify task owns memory-vs-code
96
+ // correctness), so it needs only ctx_memory — not the former
97
+ // bash/write/edit/read/aft/ctx_search/ctx_note surface. maintain-docs
98
+ // and review-user-memories moved to their own scoped agents below.
99
+ // (Inline literal — kept byte-identical to DREAMER_CURATE_ALLOWED_TOOLS
100
+ // by agent-registration-drift.test.ts; see the module header for why
101
+ // these are not const imports.)
102
+ allowedTools: ["ctx_memory"],
103
+ // Curate is a genuine multi-step whole-pool hygiene loop, so it keeps a
104
+ // high cap.
105
+ maxSteps: 150,
106
+ overrides: args.dreamerOverrides,
107
+ // Lock the curate tool surface: a user dreamer `tools`/`permission`
108
+ // override must not re-grant bash/write/edit to this unsupervised
109
+ // memory-hygiene agent. Model/temperature overrides still apply.
110
+ lockPermissions: true,
111
+ },
112
+ {
113
+ id: "dreamer-docs",
114
+ prompt: args.dreamerPrompt,
115
+ // maintain-docs: explore code + write/edit ARCHITECTURE.md/STRUCTURE.md
116
+ // + bash (git log, find). NO ctx_memory/ctx_search/ctx_note — it edits
117
+ // docs, never the memory store. (Inline literal — kept byte-identical to
118
+ // DREAMER_DOCS_ALLOWED_TOOLS by agent-registration-drift.test.ts.)
119
+ allowedTools: [
120
+ "read",
121
+ "grep",
122
+ "glob",
123
+ "bash",
124
+ "write",
125
+ "edit",
126
+ "aft_outline",
127
+ "aft_zoom",
128
+ "aft_search",
129
+ ],
130
+ // Docs maintenance reads the tree and writes two files — a bounded loop,
131
+ // not the whole-pool 150.
132
+ maxSteps: 60,
133
+ overrides: args.dreamerOverrides,
134
+ // Lock so a user override can't add the memory surface back.
135
+ lockPermissions: true,
136
+ },
137
+ {
138
+ id: "dreamer-reviewer",
139
+ prompt: args.dreamerPrompt,
140
+ // review-user-memories: a pure JSON reviewer of behavioral observations.
141
+ // It calls NO tools — the host applies its verdict — so zero tools,
142
+ // locked (mirrors dreamer-classifier).
143
+ allowedTools: [],
144
+ maxSteps: 4,
145
+ overrides: args.dreamerOverrides,
146
+ lockPermissions: true,
147
+ },
148
+ {
149
+ id: "dreamer-retrospective",
150
+ prompt: args.dreamerPrompt,
151
+ allowedTools: ["ctx_search"],
152
+ maxSteps: 40,
153
+ overrides: args.dreamerOverrides,
154
+ // Privacy-critical: this child reads OTHER sessions' raw user text.
155
+ // Lock it to ctx_search-only — a user dreamer `permission` override
156
+ // must never broaden it.
157
+ lockPermissions: true,
158
+ },
159
+ {
160
+ id: "dreamer-primer-investigator",
161
+ prompt: args.dreamerPrompt,
162
+ // Read-only code investigation: read/navigate/search the CURRENT
163
+ // source to answer a primer. Deliberately NO write/edit/bash (could
164
+ // corrupt user source) and NO ctx_memory/ctx_note (ctx_memory
165
+ // update/archive/merge bumps the project memory epoch → busts m[0],
166
+ // violating the primers cache-neutral contract).
167
+ allowedTools: [
168
+ "read",
169
+ "grep",
170
+ "glob",
171
+ "aft_outline",
172
+ "aft_zoom",
173
+ "aft_search",
174
+ "ctx_search",
175
+ ],
176
+ // Tight read-only-lookup budget — NOT the dreamer's 150. A single
177
+ // primer is a targeted investigation, not a whole-pool maintenance
178
+ // loop; it also bounds the per-primer cost of an unsupervised run.
179
+ maxSteps: 40,
180
+ overrides: args.dreamerOverrides,
181
+ // A user dreamer `permission`/`tools` override must never re-grant the
182
+ // denied write/bash/ctx_memory surface to this unsupervised agent.
183
+ lockPermissions: true,
184
+ },
185
+ {
186
+ id: "dreamer-memory-mapper",
187
+ prompt: args.dreamerPrompt,
188
+ // Read-only local-source reader for map-memories / verify: open and
189
+ // check the CURRENT source. NO write/edit/bash (could corrupt user
190
+ // source), NO ctx_memory (mutations bump the project memory epoch →
191
+ // bust m[0]; the host applies the manifest's DB writes itself), and NO
192
+ // ctx_search (these tasks check against local code, not cross-session
193
+ // recall).
194
+ allowedTools: ["read", "grep", "glob", "aft_outline", "aft_zoom", "aft_search"],
195
+ // Bounded read-only-lookup budget (mirrors the primer investigator) —
196
+ // NOT the dreamer's 150. A map/verify batch is a targeted file-lookup
197
+ // pass, and this bounds the per-batch cost of an unsupervised run.
198
+ maxSteps: 60,
199
+ overrides: args.dreamerOverrides,
200
+ // A user dreamer `permission`/`tools` override must never re-grant the
201
+ // denied write/bash/ctx_memory surface to this unsupervised agent.
202
+ lockPermissions: true,
203
+ },
204
+ {
205
+ id: "dreamer-classifier",
206
+ prompt: args.dreamerPrompt,
207
+ // ZERO tools: classify scores importance/scope/shareable from the
208
+ // memory text alone (no code inspection), emits ONE XML manifest, and
209
+ // the host applies the column writes. A pure transform — no tool can
210
+ // help it, and locking prevents a user override from granting one.
211
+ allowedTools: [],
212
+ maxSteps: 4,
213
+ overrides: args.dreamerOverrides,
214
+ lockPermissions: true,
215
+ },
216
+ {
217
+ id: "smart-note-compiler",
218
+ prompt: args.smartNoteCompilerPrompt,
219
+ allowedTools: [],
220
+ maxSteps: 8,
221
+ overrides: args.dreamerOverrides,
222
+ // Security-critical: condition text is untrusted prompt data; never
223
+ // let user dreamer overrides grant tools to the compiler.
224
+ lockPermissions: true,
225
+ },
226
+ {
227
+ id: "historian",
228
+ prompt: args.historianPrompt,
229
+ allowedTools: historianAllowedTools,
230
+ maxSteps: 40,
231
+ overrides: args.historianOverrides,
232
+ },
233
+ {
234
+ id: "historian-recomp",
235
+ prompt: args.historianRecompPrompt ?? args.historianPrompt,
236
+ allowedTools: historianAllowedTools,
237
+ maxSteps: 40,
238
+ overrides: args.historianOverrides,
239
+ },
240
+ {
241
+ id: "historian-editor",
242
+ prompt: args.historianEditorPrompt,
243
+ allowedTools: historianAllowedTools,
244
+ maxSteps: 40,
245
+ overrides: args.historianOverrides,
246
+ },
247
+ {
248
+ id: "sidekick",
249
+ prompt: args.sidekickPrompt,
250
+ allowedTools: ["ctx_search", "aft_outline", "aft_zoom"],
251
+ maxSteps: 40,
252
+ overrides: args.sidekickOverrides,
253
+ },
254
+ ];
255
+ }
256
+
257
+ /**
258
+ * Build a hidden-agent config with a deny-everything-by-default permission
259
+ * baseline and a hard tool-iteration ceiling. User overrides may lower
260
+ * `steps`/`maxSteps`, but cannot raise either above the built-in cap.
261
+ */
262
+ export function buildHiddenAgentConfig(
263
+ prompt: string,
264
+ allowedTools: readonly string[],
265
+ maxSteps: number,
266
+ overrides?: Record<string, unknown>,
267
+ agentLabel?: string,
268
+ lockPermissions = false,
269
+ ) {
270
+ const {
271
+ permission: overridePermission,
272
+ tools: overrideTools,
273
+ // Pulled out so they can be conditionally re-added: under lockPermissions
274
+ // a user `prompt`/`system` override must NOT replace the hardened
275
+ // system prompt (see below). Spreading `...rest` below would otherwise
276
+ // clobber the positional `prompt` arg, since `...rest` lands after it.
277
+ prompt: overridePrompt,
278
+ system: overrideSystem,
279
+ ...rest
280
+ } = (overrides ?? {}) as {
281
+ permission?: Record<string, unknown>;
282
+ tools?: Record<string, boolean>;
283
+ prompt?: unknown;
284
+ system?: unknown;
285
+ [key: string]: unknown;
286
+ };
287
+ // When locked (privacy-critical agents), the user `tools` enable/disable map
288
+ // AND the `prompt`/`system` text are ALL dropped — each is a
289
+ // privilege/behavior-escalation surface. A user `dreamer.tools: { bash: true }`
290
+ // would otherwise re-enable a denied tool; a user `dreamer.prompt`/`system`
291
+ // would otherwise replace the privacy-hardened prompt that, e.g., keeps the
292
+ // retrospective agent from transcribing raw user text. Unlocked agents keep
293
+ // their `tools`/`prompt`/`system` overrides.
294
+ const promptOverrides: Record<string, unknown> = lockPermissions
295
+ ? {}
296
+ : {
297
+ ...(overridePrompt !== undefined ? { prompt: overridePrompt } : {}),
298
+ ...(overrideSystem !== undefined ? { system: overrideSystem } : {}),
299
+ };
300
+ const restOverrides: Record<string, unknown> = lockPermissions
301
+ ? { ...rest, ...promptOverrides }
302
+ : {
303
+ ...rest,
304
+ ...promptOverrides,
305
+ ...(overrideTools !== undefined ? { tools: overrideTools } : {}),
306
+ };
307
+ const basePermission = buildAllowOnlyPermission(allowedTools, agentLabel);
308
+ return {
309
+ prompt,
310
+ // No builtin fallback chain: the user's `fallback_models` (if any) flow
311
+ // through `restOverrides`. A hardcoded chain names providers the user may
312
+ // not have, producing `Model not found` retry storms.
313
+ ...restOverrides,
314
+ steps: clampHiddenAgentStepLimit(restOverrides.steps, maxSteps),
315
+ maxSteps: clampHiddenAgentStepLimit(restOverrides.maxSteps, maxSteps),
316
+ // Permission baseline goes after `restOverrides` so that accidental
317
+ // `permission` keys in user overrides we DIDN'T explicitly destructure
318
+ // can't bypass the deny. The explicit override (destructured above) is
319
+ // then layered on top — UNLESS lockPermissions is set, in which case the
320
+ // user override is dropped entirely. lockPermissions is for
321
+ // privacy-critical agents (dreamer-retrospective reads other sessions'
322
+ // raw user text and MUST stay ctx_search-only; a user dreamer `permission`
323
+ // override must never grant it bash/edit/ctx_memory/etc).
324
+ permission: {
325
+ ...basePermission,
326
+ ...(lockPermissions ? {} : (overridePermission ?? {})),
327
+ },
328
+ mode: "subagent" as const,
329
+ hidden: true,
330
+ };
331
+ }
@@ -0,0 +1,3 @@
1
+ export const HISTORIAN_AGENT = "historian";
2
+ export const HISTORIAN_RECOMP_AGENT = "historian-recomp";
3
+ export const HISTORIAN_EDITOR_AGENT = "historian-editor";
@@ -0,0 +1,138 @@
1
+ import { describe, expect, it } from "bun:test";
2
+
3
+ import {
4
+ buildContentLanguageDirective,
5
+ buildMigrationLanguageDirective,
6
+ buildPrimaryLanguageDirective,
7
+ isValidLanguageCode,
8
+ resolveLanguageName,
9
+ withContentLanguageDirective,
10
+ withMigrationLanguageDirective,
11
+ } from "./language-directive";
12
+
13
+ const EXHAUSTIVE_STRUCTURAL_TOKENS = [
14
+ "summary",
15
+ "symptom",
16
+ "model_or_provider_involved",
17
+ "ord_span",
18
+ "provider_sdk",
19
+ "model_behavior",
20
+ "tool_protocol",
21
+ "host_integration",
22
+ "historian_pipeline",
23
+ "edit_pipeline",
24
+ "environment",
25
+ "undocumented_internal",
26
+ "other",
27
+ "fixed",
28
+ "workaround",
29
+ "external_blocker",
30
+ "contained_failure",
31
+ "deferred",
32
+ "unknown_but_bounded",
33
+ "user",
34
+ "test_result",
35
+ "tool_result",
36
+ "self_review",
37
+ "unprocessed_from",
38
+ "verified",
39
+ "update",
40
+ "archive",
41
+ "candidate_ids",
42
+ "update_existing",
43
+ "memory_id",
44
+ "dismiss_existing",
45
+ "consume_candidate_ids",
46
+ "migrated",
47
+ "user_observations",
48
+ "answer",
49
+ ] as const;
50
+
51
+ describe("resolveLanguageName", () => {
52
+ it("maps a 2-letter ISO 639-1 code to 'English (Endonym)'", () => {
53
+ expect(resolveLanguageName("tr")).toBe("Turkish (Türkçe)");
54
+ expect(resolveLanguageName("es")).toBe("Spanish (Español)");
55
+ expect(resolveLanguageName("ja")).toBe("Japanese (日本語)");
56
+ });
57
+ it("normalizes case and surrounding whitespace", () => {
58
+ expect(resolveLanguageName(" TR ")).toBe("Turkish (Türkçe)");
59
+ });
60
+ it("returns the bare English name when the endonym matches it", () => {
61
+ expect(resolveLanguageName("en")).toBe("English");
62
+ });
63
+ it("returns '' for unset, blank, non-codes, and unknown codes", () => {
64
+ expect(resolveLanguageName()).toBe("");
65
+ expect(resolveLanguageName(" ")).toBe("");
66
+ expect(resolveLanguageName("Turkish")).toBe(""); // full name rejected
67
+ expect(resolveLanguageName("tur")).toBe(""); // 3-letter rejected
68
+ expect(resolveLanguageName("zz")).toBe(""); // not a real language
69
+ expect(resolveLanguageName("e1")).toBe("");
70
+ });
71
+ it("isValidLanguageCode mirrors resolveLanguageName", () => {
72
+ expect(isValidLanguageCode("tr")).toBe(true);
73
+ expect(isValidLanguageCode("zz")).toBe(false);
74
+ expect(isValidLanguageCode("Español")).toBe(false);
75
+ });
76
+ });
77
+
78
+ describe("language directives", () => {
79
+ it("emits the content directive with the resolved name and structural rule", () => {
80
+ const directive = buildContentLanguageDirective("tr");
81
+ expect(directive).toContain("Write human-readable prose you author in: Turkish (Türkçe).");
82
+ expect(directive).toContain("Copy required output schemas exactly");
83
+ expect(directive).toContain("No relevant memories found");
84
+ });
85
+
86
+ it("emits the preserve-user-quotes variant", () => {
87
+ const directive = buildContentLanguageDirective("es", {
88
+ preserveUserQuotes: true,
89
+ });
90
+ expect(directive).toContain(
91
+ "Preserve U: lines and directly quoted user text in their original source language; write the surrounding summary prose in Spanish (Español).",
92
+ );
93
+ });
94
+
95
+ it("emits the retrospective no-quote variant", () => {
96
+ const directive = buildContentLanguageDirective("tr", { retrospective: true });
97
+ expect(directive).toContain(
98
+ "Write the lesson text in Turkish (Türkçe); paraphrase source text and never quote the user.",
99
+ );
100
+ expect(directive).not.toContain("directly quoted user text");
101
+ });
102
+
103
+ it("emits the migration preserve-language variant", () => {
104
+ const directive = buildMigrationLanguageDirective("pt");
105
+ expect(directive).toContain("Preserve each migrated memory's existing language");
106
+ expect(directive).toContain(
107
+ "do NOT translate a memory just because an output language is set",
108
+ );
109
+ expect(directive).not.toContain("Write human-readable prose you author");
110
+ });
111
+
112
+ it("emits the primary one-liner with the resolved name", () => {
113
+ expect(buildPrimaryLanguageDirective("zh")).toBe(
114
+ "Use Chinese (中文) for your natural-language replies to the user unless the user explicitly asks for another language. Keep code, identifiers, file paths, commands, logs, and quoted text verbatim.",
115
+ );
116
+ });
117
+
118
+ it("returns empty or unchanged for blank or invalid language", () => {
119
+ expect(buildContentLanguageDirective()).toBe("");
120
+ expect(buildContentLanguageDirective(" ")).toBe("");
121
+ expect(buildContentLanguageDirective("Turkish")).toBe(""); // full name not a code
122
+ expect(buildMigrationLanguageDirective()).toBe("");
123
+ expect(buildPrimaryLanguageDirective()).toBe("");
124
+ expect(withContentLanguageDirective("base", "")).toBe("base");
125
+ expect(withMigrationLanguageDirective("base", " ")).toBe("base");
126
+ expect(withContentLanguageDirective("base", "zz")).toBe("base"); // unknown code
127
+ });
128
+
129
+ it("does not inline the exhaustive structural token inventory", () => {
130
+ const directive = buildContentLanguageDirective("tr");
131
+ for (const token of EXHAUSTIVE_STRUCTURAL_TOKENS) {
132
+ const escaped = token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
133
+ expect(directive, token).not.toMatch(
134
+ new RegExp(`(^|[^A-Za-z0-9_])${escaped}([^A-Za-z0-9_]|$)`),
135
+ );
136
+ }
137
+ });
138
+ });