@cortexkit/opencode-magic-context 0.26.0 → 0.27.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 (285) hide show
  1. package/README.md +14 -12
  2. package/dist/agents/dreamer.d.ts +19 -0
  3. package/dist/agents/dreamer.d.ts.map +1 -1
  4. package/dist/agents/hidden-agent-registrations.d.ts +67 -0
  5. package/dist/agents/hidden-agent-registrations.d.ts.map +1 -0
  6. package/dist/agents/historian.d.ts +1 -0
  7. package/dist/agents/historian.d.ts.map +1 -1
  8. package/dist/agents/permissions.d.ts +15 -44
  9. package/dist/agents/permissions.d.ts.map +1 -1
  10. package/dist/agents/smart-note-compiler.d.ts +2 -0
  11. package/dist/agents/smart-note-compiler.d.ts.map +1 -0
  12. package/dist/config/index.d.ts +1 -1
  13. package/dist/config/index.d.ts.map +1 -1
  14. package/dist/config/migrate-config-location.d.ts +89 -0
  15. package/dist/config/migrate-config-location.d.ts.map +1 -0
  16. package/dist/config/migrate-dreamer-v2.d.ts +37 -0
  17. package/dist/config/migrate-dreamer-v2.d.ts.map +1 -0
  18. package/dist/config/migrate-experimental.d.ts.map +1 -1
  19. package/dist/config/project-security.d.ts +3 -0
  20. package/dist/config/project-security.d.ts.map +1 -1
  21. package/dist/config/prune-config-leaf.d.ts.map +1 -1
  22. package/dist/config/schema/magic-context.d.ts +584 -60
  23. package/dist/config/schema/magic-context.d.ts.map +1 -1
  24. package/dist/features/magic-context/compaction-marker.d.ts +9 -3
  25. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  26. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +1 -1
  27. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  28. package/dist/features/magic-context/dreamer/classify-prompt.d.ts +50 -0
  29. package/dist/features/magic-context/dreamer/classify-prompt.d.ts.map +1 -0
  30. package/dist/features/magic-context/dreamer/classify.d.ts +22 -0
  31. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -0
  32. package/dist/features/magic-context/dreamer/cron.d.ts +72 -0
  33. package/dist/features/magic-context/dreamer/cron.d.ts.map +1 -0
  34. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +30 -0
  35. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -0
  36. package/dist/features/magic-context/dreamer/index.d.ts +1 -3
  37. package/dist/features/magic-context/dreamer/index.d.ts.map +1 -1
  38. package/dist/features/magic-context/dreamer/lease.d.ts +44 -6
  39. package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
  40. package/dist/features/magic-context/dreamer/maintain-docs-protected-enforcement.d.ts +13 -0
  41. package/dist/features/magic-context/dreamer/maintain-docs-protected-enforcement.d.ts.map +1 -0
  42. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +36 -0
  43. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -0
  44. package/dist/features/magic-context/dreamer/map-memories.d.ts +22 -0
  45. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -0
  46. package/dist/features/magic-context/dreamer/open-opencode-db.d.ts +7 -0
  47. package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -0
  48. package/dist/features/magic-context/dreamer/primer-seed.d.ts +25 -0
  49. package/dist/features/magic-context/dreamer/primer-seed.d.ts.map +1 -0
  50. package/dist/features/magic-context/dreamer/promote-primers.d.ts +21 -0
  51. package/dist/features/magic-context/dreamer/promote-primers.d.ts.map +1 -0
  52. package/dist/features/magic-context/dreamer/protected-regions.d.ts +19 -0
  53. package/dist/features/magic-context/dreamer/protected-regions.d.ts.map +1 -0
  54. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +30 -0
  55. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -0
  56. package/dist/features/magic-context/dreamer/retrospective-learnings.d.ts +47 -0
  57. package/dist/features/magic-context/dreamer/retrospective-learnings.d.ts.map +1 -0
  58. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts +48 -0
  59. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts.map +1 -0
  60. package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts +81 -0
  61. package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts.map +1 -0
  62. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +8 -0
  63. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  64. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts +82 -0
  65. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts.map +1 -0
  66. package/dist/features/magic-context/dreamer/task-config.d.ts +28 -0
  67. package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -0
  68. package/dist/features/magic-context/dreamer/task-executor.d.ts +49 -0
  69. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -0
  70. package/dist/features/magic-context/dreamer/task-gates.d.ts +29 -0
  71. package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -0
  72. package/dist/features/magic-context/dreamer/task-prompts.d.ts +37 -6
  73. package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
  74. package/dist/features/magic-context/dreamer/task-registry.d.ts +48 -0
  75. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -0
  76. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +88 -0
  77. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -0
  78. package/dist/features/magic-context/dreamer/verify-gate.d.ts +43 -0
  79. package/dist/features/magic-context/dreamer/verify-gate.d.ts.map +1 -0
  80. package/dist/features/magic-context/dreamer/verify-prompt.d.ts +41 -0
  81. package/dist/features/magic-context/dreamer/verify-prompt.d.ts.map +1 -0
  82. package/dist/features/magic-context/dreamer/verify.d.ts +43 -0
  83. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -0
  84. package/dist/features/magic-context/git-commits/search-git-commits.d.ts +2 -0
  85. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  86. package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts +4 -4
  87. package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -1
  88. package/dist/features/magic-context/index.d.ts +1 -0
  89. package/dist/features/magic-context/index.d.ts.map +1 -1
  90. package/dist/features/magic-context/memory/embedding-cache.d.ts +2 -2
  91. package/dist/features/magic-context/memory/embedding-cache.d.ts.map +1 -1
  92. package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
  93. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  94. package/dist/features/magic-context/memory/embedding-openai.d.ts +12 -5
  95. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  96. package/dist/features/magic-context/memory/embedding.d.ts +2 -2
  97. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  98. package/dist/features/magic-context/memory/index.d.ts +4 -1
  99. package/dist/features/magic-context/memory/index.d.ts.map +1 -1
  100. package/dist/features/magic-context/memory/memory-migration.d.ts +1 -0
  101. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  102. package/dist/features/magic-context/memory/promotion.d.ts +16 -4
  103. package/dist/features/magic-context/memory/promotion.d.ts.map +1 -1
  104. package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts +2 -2
  105. package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
  106. package/dist/features/magic-context/memory/storage-memory-verifications.d.ts +31 -0
  107. package/dist/features/magic-context/memory/storage-memory-verifications.d.ts.map +1 -0
  108. package/dist/features/magic-context/memory/storage-memory.d.ts +12 -1
  109. package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
  110. package/dist/features/magic-context/memory/types.d.ts +4 -0
  111. package/dist/features/magic-context/memory/types.d.ts.map +1 -1
  112. package/dist/features/magic-context/memory/verification-paths.d.ts +32 -0
  113. package/dist/features/magic-context/memory/verification-paths.d.ts.map +1 -0
  114. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  115. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  116. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  117. package/dist/features/magic-context/primer-clustering.d.ts +29 -0
  118. package/dist/features/magic-context/primer-clustering.d.ts.map +1 -0
  119. package/dist/features/magic-context/project-embedding-registry.d.ts +25 -1
  120. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  121. package/dist/features/magic-context/search.d.ts +12 -2
  122. package/dist/features/magic-context/search.d.ts.map +1 -1
  123. package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
  124. package/dist/features/magic-context/smart-notes/capabilities.d.ts +31 -0
  125. package/dist/features/magic-context/smart-notes/capabilities.d.ts.map +1 -0
  126. package/dist/features/magic-context/smart-notes/compiler-prompt.d.ts +2 -0
  127. package/dist/features/magic-context/smart-notes/compiler-prompt.d.ts.map +1 -0
  128. package/dist/features/magic-context/smart-notes/compiler.d.ts +52 -0
  129. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -0
  130. package/dist/features/magic-context/smart-notes/index.d.ts +10 -0
  131. package/dist/features/magic-context/smart-notes/index.d.ts.map +1 -0
  132. package/dist/features/magic-context/smart-notes/runner.d.ts +18 -0
  133. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -0
  134. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +22 -0
  135. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -0
  136. package/dist/features/magic-context/smart-notes/schedule.d.ts +9 -0
  137. package/dist/features/magic-context/smart-notes/schedule.d.ts.map +1 -0
  138. package/dist/features/magic-context/smart-notes/ssrf-guard.d.ts +49 -0
  139. package/dist/features/magic-context/smart-notes/ssrf-guard.d.ts.map +1 -0
  140. package/dist/features/magic-context/smart-notes/storage.d.ts +27 -0
  141. package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -0
  142. package/dist/features/magic-context/smart-notes/types.d.ts +63 -0
  143. package/dist/features/magic-context/smart-notes/types.d.ts.map +1 -0
  144. package/dist/features/magic-context/storage-db.d.ts +5 -1
  145. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  146. package/dist/features/magic-context/storage-meta-persisted.d.ts +8 -4
  147. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  148. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  149. package/dist/features/magic-context/storage-meta-shared.d.ts +3 -1
  150. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  151. package/dist/features/magic-context/storage-notes.d.ts +15 -0
  152. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  153. package/dist/features/magic-context/storage-primers.d.ts +85 -0
  154. package/dist/features/magic-context/storage-primers.d.ts.map +1 -0
  155. package/dist/features/magic-context/storage-tags.d.ts +20 -0
  156. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  157. package/dist/features/magic-context/storage.d.ts +2 -1
  158. package/dist/features/magic-context/storage.d.ts.map +1 -1
  159. package/dist/features/magic-context/tagger.d.ts +6 -0
  160. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  161. package/dist/features/magic-context/tool-owner-backfill.d.ts.map +1 -1
  162. package/dist/features/magic-context/transform-decision-log.d.ts +10 -0
  163. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  164. package/dist/features/magic-context/types.d.ts +2 -0
  165. package/dist/features/magic-context/types.d.ts.map +1 -1
  166. package/dist/features/magic-context/user-memory/review-user-memories.d.ts +5 -0
  167. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  168. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +18 -0
  169. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  170. package/dist/features/magic-context/v22-deferred-backfill.d.ts.map +1 -1
  171. package/dist/hooks/auto-update-checker/semver.d.ts +9 -0
  172. package/dist/hooks/auto-update-checker/semver.d.ts.map +1 -1
  173. package/dist/hooks/magic-context/auto-search-hint.d.ts.map +1 -1
  174. package/dist/hooks/magic-context/command-handler.d.ts +8 -15
  175. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  176. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  177. package/dist/hooks/magic-context/compartment-parser.d.ts +9 -0
  178. package/dist/hooks/magic-context/compartment-parser.d.ts.map +1 -1
  179. package/dist/hooks/magic-context/compartment-prompt.d.ts +4 -1
  180. package/dist/hooks/magic-context/compartment-prompt.d.ts.map +1 -1
  181. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +1 -0
  182. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  183. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  184. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  185. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  186. package/dist/hooks/magic-context/compartment-runner-types.d.ts +8 -0
  187. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  188. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  189. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  190. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
  191. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  192. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  193. package/dist/hooks/magic-context/historian-prompt.generated.d.ts +1 -1
  194. package/dist/hooks/magic-context/historian-prompt.generated.d.ts.map +1 -1
  195. package/dist/hooks/magic-context/historian-state-file.d.ts.map +1 -1
  196. package/dist/hooks/magic-context/hook-handlers.d.ts +2 -1
  197. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  198. package/dist/hooks/magic-context/hook.d.ts +1 -0
  199. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  200. package/dist/hooks/magic-context/inject-compartments.d.ts +0 -3
  201. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  202. package/dist/hooks/magic-context/send-session-notification.d.ts +2 -0
  203. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  204. package/dist/hooks/magic-context/system-prompt-hash.d.ts +17 -0
  205. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  206. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +8 -5
  207. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  208. package/dist/hooks/magic-context/transform.d.ts +0 -2
  209. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  210. package/dist/index.d.ts +2 -2
  211. package/dist/index.d.ts.map +1 -1
  212. package/dist/index.js +17028 -4059
  213. package/dist/plugin/dream-timer.d.ts +17 -9
  214. package/dist/plugin/dream-timer.d.ts.map +1 -1
  215. package/dist/plugin/embedding-bootstrap-helpers.d.ts +1 -1
  216. package/dist/plugin/embedding-bootstrap-helpers.d.ts.map +1 -1
  217. package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
  218. package/dist/plugin/hooks/create-session-hooks.d.ts +211 -0
  219. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  220. package/dist/plugin/instance-disposal.d.ts +2 -0
  221. package/dist/plugin/instance-disposal.d.ts.map +1 -0
  222. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  223. package/dist/shared/announcement.d.ts +1 -1
  224. package/dist/shared/announcement.d.ts.map +1 -1
  225. package/dist/shared/data-path.d.ts +26 -7
  226. package/dist/shared/data-path.d.ts.map +1 -1
  227. package/dist/shared/model-suggestion-retry.d.ts +48 -2
  228. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  229. package/dist/shared/redaction.d.ts +7 -0
  230. package/dist/shared/redaction.d.ts.map +1 -0
  231. package/dist/shared/resolve-fallbacks.d.ts +12 -0
  232. package/dist/shared/resolve-fallbacks.d.ts.map +1 -1
  233. package/dist/shared/rpc-server.d.ts.map +1 -1
  234. package/dist/shared/rpc-types.d.ts +2 -0
  235. package/dist/shared/rpc-types.d.ts.map +1 -1
  236. package/dist/shared/subagent-runner.d.ts +12 -3
  237. package/dist/shared/subagent-runner.d.ts.map +1 -1
  238. package/dist/shared/tui-config.d.ts.map +1 -1
  239. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  240. package/dist/tools/ctx-memory/types.d.ts.map +1 -1
  241. package/dist/tools/ctx-memory/verification-recording.d.ts +8 -0
  242. package/dist/tools/ctx-memory/verification-recording.d.ts.map +1 -0
  243. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  244. package/dist/tools/ctx-search/types.d.ts +1 -1
  245. package/dist/tools/ctx-search/types.d.ts.map +1 -1
  246. package/dist/tui/data/context-db.d.ts +2 -0
  247. package/dist/tui/data/context-db.d.ts.map +1 -1
  248. package/package.json +3 -1
  249. package/src/shared/announcement.test.ts +20 -0
  250. package/src/shared/announcement.ts +19 -7
  251. package/src/shared/data-path.test.ts +70 -6
  252. package/src/shared/data-path.ts +50 -8
  253. package/src/shared/model-suggestion-retry.test.ts +79 -2
  254. package/src/shared/model-suggestion-retry.ts +181 -3
  255. package/src/shared/redaction.test.ts +48 -0
  256. package/src/shared/redaction.ts +240 -0
  257. package/src/shared/resolve-fallbacks.ts +14 -0
  258. package/src/shared/rpc-server.ts +24 -0
  259. package/src/shared/rpc-types.ts +2 -0
  260. package/src/shared/subagent-runner.ts +12 -3
  261. package/src/shared/tui-config.test.ts +63 -0
  262. package/src/shared/tui-config.ts +67 -39
  263. package/src/tui/data/context-db.ts +12 -0
  264. package/src/tui/index.tsx +87 -17
  265. package/src/tui/slots/sidebar-content.tsx +4 -0
  266. package/dist/features/magic-context/dreamer/queue.d.ts +0 -55
  267. package/dist/features/magic-context/dreamer/queue.d.ts.map +0 -1
  268. package/dist/features/magic-context/dreamer/runner.d.ts +0 -92
  269. package/dist/features/magic-context/dreamer/runner.d.ts.map +0 -1
  270. package/dist/features/magic-context/dreamer/scheduler.d.ts +0 -29
  271. package/dist/features/magic-context/dreamer/scheduler.d.ts.map +0 -1
  272. package/dist/features/magic-context/key-files/aft-availability.d.ts +0 -11
  273. package/dist/features/magic-context/key-files/aft-availability.d.ts.map +0 -1
  274. package/dist/features/magic-context/key-files/identify-key-files.d.ts +0 -84
  275. package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +0 -1
  276. package/dist/features/magic-context/key-files/project-key-files.d.ts +0 -42
  277. package/dist/features/magic-context/key-files/project-key-files.d.ts.map +0 -1
  278. package/dist/features/magic-context/key-files/read-history.d.ts +0 -26
  279. package/dist/features/magic-context/key-files/read-history.d.ts.map +0 -1
  280. package/dist/features/magic-context/key-files/read-stats.d.ts +0 -18
  281. package/dist/features/magic-context/key-files/read-stats.d.ts.map +0 -1
  282. package/dist/features/magic-context/key-files/storage-key-files.d.ts +0 -20
  283. package/dist/features/magic-context/key-files/storage-key-files.d.ts.map +0 -1
  284. package/dist/hooks/magic-context/key-files-block.d.ts +0 -27
  285. package/dist/hooks/magic-context/key-files-block.d.ts.map +0 -1
@@ -3,7 +3,15 @@
3
3
  * Called from the server plugin at startup so the TUI sidebar loads on next restart.
4
4
  */
5
5
 
6
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6
+ import {
7
+ chmodSync,
8
+ existsSync,
9
+ mkdirSync,
10
+ readFileSync,
11
+ renameSync,
12
+ statSync,
13
+ writeFileSync,
14
+ } from "node:fs";
7
15
  import { dirname, join } from "node:path";
8
16
  import { parse, stringify } from "comment-json";
9
17
  import { log } from "./logger";
@@ -12,27 +20,41 @@ import { getOpenCodeConfigPaths } from "./opencode-config-dir";
12
20
  const PLUGIN_NAME = "@cortexkit/opencode-magic-context";
13
21
  const PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
14
22
 
15
- /**
16
- * Detect whether a tui.json plugin entry already references magic-context, in
17
- * any form. Covers:
18
- * - Bare npm name: "@cortexkit/opencode-magic-context"
19
- * - Versioned npm: "@cortexkit/opencode-magic-context@latest" / "@0.15.7" / etc.
20
- * - Local dev directory path (absolute or relative): ".../magic-context"
21
- * or ".../magic-context/packages/plugin"
22
- * - file:// URLs pointing at the same paths
23
- * - Tarball paths ending in opencode-magic-context-*.tgz
24
- *
25
- * Without the path/URL detection, doctor/setup auto-injection adds the npm
26
- * @latest entry on top of an existing dev path, double-loading the plugin.
27
- */
28
- function isMagicContextEntry(entry: string): boolean {
29
- if (!entry) return false;
30
- if (entry === PLUGIN_NAME) return true;
31
- if (entry.startsWith(`${PLUGIN_NAME}@`)) return true;
32
- // Local directory paths: match anywhere in the string so the setup pattern
33
- // (dir-only, dir + /packages/plugin, file:// + either) all qualify.
34
- if (entry.includes("opencode-magic-context")) return true;
35
- return false;
23
+ function pluginEntryId(entry: unknown): string {
24
+ if (typeof entry === "string") return entry;
25
+ if (Array.isArray(entry) && typeof entry[0] === "string") return entry[0];
26
+ return "";
27
+ }
28
+
29
+ function isLocalMagicContextDevEntry(entry: unknown): boolean {
30
+ const id = pluginEntryId(entry);
31
+ if (!id) return false;
32
+ if (id === PLUGIN_NAME || id.startsWith(`${PLUGIN_NAME}@`)) return false;
33
+ const isPath =
34
+ id.startsWith("file://") || id.startsWith("/") || id.startsWith("./") || id.includes("\\");
35
+ if (!isPath) return false;
36
+ return id.includes("opencode-magic-context") || id.includes("magic-context");
37
+ }
38
+
39
+ function isMagicContextPluginEntry(entry: unknown): boolean {
40
+ const id = pluginEntryId(entry);
41
+ if (!id) return false;
42
+ if (id === PLUGIN_NAME || id.startsWith(`${PLUGIN_NAME}@`)) return true;
43
+ return isLocalMagicContextDevEntry(entry);
44
+ }
45
+
46
+ function writeTuiConfigAtomic(configPath: string, config: Record<string, unknown>): void {
47
+ const body = `${stringify(config, null, 2)}\n`;
48
+ const tmpPath = `${configPath}.tmp`;
49
+ writeFileSync(tmpPath, body);
50
+ try {
51
+ if (statSync(configPath, { throwIfNoEntry: false })?.isFile()) {
52
+ chmodSync(tmpPath, statSync(configPath).mode & 0o777);
53
+ }
54
+ } catch {
55
+ /* new file */
56
+ }
57
+ renameSync(tmpPath, configPath);
36
58
  }
37
59
 
38
60
  function resolveTuiConfigPath(): string {
@@ -59,35 +81,41 @@ export function ensureTuiPluginEntry(): boolean {
59
81
  config = (parse(raw) as Record<string, unknown>) ?? {};
60
82
  }
61
83
 
62
- const plugins = Array.isArray(config.plugin)
63
- ? config.plugin.filter((p): p is string => typeof p === "string")
64
- : [];
84
+ const plugins: unknown[] = Array.isArray(config.plugin) ? [...config.plugin] : [];
65
85
 
66
- const existingIdx = plugins.findIndex(isMagicContextEntry);
86
+ const existingIdx = plugins.findIndex(isMagicContextPluginEntry);
67
87
  if (existingIdx >= 0) {
68
88
  const existing = plugins[existingIdx];
69
- if (existing === PLUGIN_ENTRY) {
70
- return false; // Already @latest
89
+ if (isLocalMagicContextDevEntry(existing)) {
90
+ return false;
91
+ }
92
+ const id = pluginEntryId(existing);
93
+ if (id === PLUGIN_ENTRY) {
94
+ return false;
71
95
  }
72
- // Only upgrade the bare versionless npm name to @latest.
73
- // Pinned versions (e.g. @0.8.10), local dev paths
74
- // (~/Work/OSS/magic-context/packages/plugin), and
75
- // file:// URLs are all left as-is — the user chose them
76
- // intentionally and overwriting their dev-loop entry would
77
- // either double-load the plugin (npm + dev) or replace
78
- // their working directory pointer.
79
- if (existing === PLUGIN_NAME) {
80
- plugins[existingIdx] = PLUGIN_ENTRY;
96
+ if (id === PLUGIN_NAME) {
97
+ if (Array.isArray(existing) && existing.length >= 1) {
98
+ const replacement = [...existing];
99
+ replacement[0] = PLUGIN_ENTRY;
100
+ plugins[existingIdx] = replacement;
101
+ } else {
102
+ plugins[existingIdx] = PLUGIN_ENTRY;
103
+ }
81
104
  } else {
82
105
  return false;
83
106
  }
84
107
  } else {
85
- plugins.push(PLUGIN_ENTRY);
108
+ const hasDev = plugins.some(isLocalMagicContextDevEntry);
109
+ if (!hasDev) {
110
+ plugins.push(PLUGIN_ENTRY);
111
+ } else {
112
+ return false;
113
+ }
86
114
  }
87
115
  config.plugin = plugins;
88
116
 
89
117
  mkdirSync(dirname(configPath), { recursive: true });
90
- writeFileSync(configPath, `${stringify(config, null, 2)}\n`);
118
+ writeTuiConfigAtomic(configPath, config);
91
119
  log(`[magic-context] updated TUI plugin entry in ${configPath}`);
92
120
  return true;
93
121
  } catch (error) {
@@ -205,6 +205,7 @@ export async function loadStatusDetail(
205
205
  historyBlockTokens: 0,
206
206
  compressionBudget: null,
207
207
  compressionUsage: null,
208
+ toastDurationMs: 5000,
208
209
  };
209
210
 
210
211
  if (!rpcClient) return emptyDetail;
@@ -299,6 +300,17 @@ export async function dismissUpgradeReminder(sessionId: string): Promise<boolean
299
300
  }
300
301
  }
301
302
 
303
+ /** Resolve global toast duration from server config via RPC. */
304
+ export async function loadToastDurationMs(): Promise<number> {
305
+ if (!rpcClient) return 5000;
306
+ try {
307
+ const result = await rpcClient.call<{ toastDurationMs?: number }>("toast-duration", {});
308
+ return typeof result.toastDurationMs === "number" ? result.toastDurationMs : 5000;
309
+ } catch {
310
+ return 5000;
311
+ }
312
+ }
313
+
302
314
  export interface TuiMessage {
303
315
  id: number;
304
316
  type: string;
package/src/tui/index.tsx CHANGED
@@ -6,7 +6,7 @@ import { createMemo } from "solid-js"
6
6
  import type { TuiPlugin, TuiPluginApi, TuiThemeCurrent } from "@opencode-ai/plugin/tui"
7
7
  import { createSidebarContentSlot, kickRecompProgressRefresh } from "./slots/sidebar-content"
8
8
  import packageJson from "../../package.json"
9
- import { closeRpc, consumeTuiMessages, dismissUpgradeReminder, getAnnouncement, getCompartmentCount, getRpcGeneration, initRpcClient, loadEmbedDetail, loadStatusDetail, markAnnounced, markTuiMessagesHandled, requestRecomp, requestUpgrade, type EmbedDetail, type TuiMessage, type StatusDetail } from "./data/context-db"
9
+ import { closeRpc, consumeTuiMessages, dismissUpgradeReminder, getAnnouncement, getCompartmentCount, getRpcGeneration, initRpcClient, loadEmbedDetail, loadStatusDetail, loadToastDurationMs, markAnnounced, markTuiMessagesHandled, requestRecomp, requestUpgrade, type EmbedDetail, type TuiMessage, type StatusDetail } from "./data/context-db"
10
10
  import { formatThresholdPercent } from "../shared/format-threshold"
11
11
  import { detectConflicts } from "../shared/conflict-detector"
12
12
  import { fixConflicts } from "../shared/conflict-fixer"
@@ -14,6 +14,48 @@ import { readJsoncFile } from "../shared/jsonc-parser"
14
14
  import { getOpenCodeConfigPaths } from "../shared/opencode-config-dir"
15
15
 
16
16
  const PLUGIN_NAME = "@cortexkit/opencode-magic-context"
17
+ const DEFAULT_TOAST_DURATION_MS = 5000
18
+ let unifiedToastDurationMs = DEFAULT_TOAST_DURATION_MS
19
+
20
+ async function refreshToastDurationMs(): Promise<void> {
21
+ try {
22
+ const resolved = await loadToastDurationMs()
23
+ if (typeof resolved === "number" && Number.isFinite(resolved)) {
24
+ unifiedToastDurationMs = resolved
25
+ }
26
+ } catch {
27
+ // Keep the current value; the next poll/startup can retry.
28
+ }
29
+ }
30
+
31
+ function getToastDurationMs(): number {
32
+ return unifiedToastDurationMs
33
+ }
34
+
35
+ function showToast(
36
+ api: TuiPluginApi,
37
+ input: {
38
+ message: string
39
+ variant: "info" | "warning" | "error" | "success"
40
+ durationOverrideMs?: number
41
+ },
42
+ ): void {
43
+ const duration =
44
+ typeof input.durationOverrideMs === "number" && Number.isFinite(input.durationOverrideMs)
45
+ ? input.durationOverrideMs
46
+ : getToastDurationMs()
47
+ // toast_duration_ms = 0 disables Magic Context toasts entirely. An explicit
48
+ // positive per-call override (e.g. restart-required) still shows; only a
49
+ // non-positive effective duration suppresses the toast.
50
+ if (!(duration > 0)) {
51
+ return
52
+ }
53
+ api.ui.toast({
54
+ message: input.message,
55
+ variant: input.variant,
56
+ duration,
57
+ })
58
+ }
17
59
 
18
60
  function ensureParentDir(filePath: string) {
19
61
  mkdirSync(dirname(filePath), { recursive: true })
@@ -97,14 +139,18 @@ function showConflictDialog(api: TuiPluginApi, directory: string, reasons: strin
97
139
  title="✅ Configuration Fixed"
98
140
  message={`${actionSummary}\n\nPlease restart OpenCode for changes to take effect.`}
99
141
  onConfirm={() => {
100
- api.ui.toast({ message: "Restart OpenCode to enable Magic Context", variant: "warning", duration: 10000 })
142
+ showToast(api, {
143
+ message: "Restart OpenCode to enable Magic Context",
144
+ variant: "warning",
145
+ durationOverrideMs: 10_000,
146
+ })
101
147
  }}
102
148
  />
103
149
  ))
104
150
  }, 50)
105
151
  }}
106
152
  onCancel={() => {
107
- api.ui.toast({ message: "Magic Context remains disabled. Run: npx @cortexkit/opencode-magic-context@latest doctor", variant: "warning", duration: 5000 })
153
+ showToast(api, { message: "Magic Context remains disabled. Run: npx @cortexkit/opencode-magic-context@latest doctor", variant: "warning" })
108
154
  }}
109
155
  />
110
156
  ))
@@ -132,7 +178,7 @@ function showTuiSetupDialog(api: TuiPluginApi) {
132
178
  title="❌ Setup Failed"
133
179
  message={'Could not update tui.json automatically. Add the plugin manually:\n\n { "plugin": ["@cortexkit/opencode-magic-context"] }'}
134
180
  onConfirm={() => {
135
- api.ui.toast({ message: "Add plugin to tui.json manually", variant: "warning", duration: 5000 })
181
+ showToast(api, { message: "Add plugin to tui.json manually", variant: "warning" })
136
182
  }}
137
183
  />
138
184
  ))
@@ -146,14 +192,18 @@ function showTuiSetupDialog(api: TuiPluginApi) {
146
192
  title="✅ Sidebar Enabled"
147
193
  message="tui.json updated with Magic Context plugin.\n\nPlease restart OpenCode to see the sidebar."
148
194
  onConfirm={() => {
149
- api.ui.toast({ message: "Restart OpenCode to see the sidebar", variant: "warning", duration: 10000 })
195
+ showToast(api, {
196
+ message: "Restart OpenCode to see the sidebar",
197
+ variant: "warning",
198
+ durationOverrideMs: 10_000,
199
+ })
150
200
  }}
151
201
  />
152
202
  ))
153
203
  }, 50)
154
204
  }}
155
205
  onCancel={() => {
156
- api.ui.toast({ message: "You can add the sidebar later via: npx @cortexkit/opencode-magic-context@latest doctor", variant: "info", duration: 5000 })
206
+ showToast(api, { message: "You can add the sidebar later via: npx @cortexkit/opencode-magic-context@latest doctor", variant: "info" })
157
207
  }}
158
208
  />
159
209
  ))
@@ -203,8 +253,16 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
203
253
  const t = () => theme()
204
254
  const s = () => props.s
205
255
 
256
+ // Prefer the RPC-provided model context limit (what the sidebar shows) so the
257
+ // two surfaces never disagree. Fall back to deriving from usage% only when the
258
+ // RPC limit is absent (0) — and that derivation is itself undefined at 0%, so
259
+ // it stays "?" rather than showing a number inconsistent with the sidebar.
206
260
  const contextLimit = () =>
207
- s().usagePercentage > 0 ? Math.round(s().inputTokens / (s().usagePercentage / 100)) : 0
261
+ s().contextLimit > 0
262
+ ? s().contextLimit
263
+ : s().usagePercentage > 0
264
+ ? Math.round(s().inputTokens / (s().usagePercentage / 100))
265
+ : 0
208
266
 
209
267
  const elapsed = () => (s().lastResponseTime > 0 ? Date.now() - s().lastResponseTime : 0)
210
268
 
@@ -450,7 +508,7 @@ function getModelKeyFromMessages(api: TuiPluginApi, sessionId: string): string |
450
508
  async function showRecompDialog(api: TuiPluginApi, targetSessionId = getSessionId(api)): Promise<boolean> {
451
509
  const sessionId = targetSessionId
452
510
  if (!sessionId) {
453
- api.ui.toast({ message: "No active session", variant: "warning" })
511
+ showToast(api, { message: "No active session", variant: "warning" })
454
512
  return false
455
513
  }
456
514
 
@@ -475,10 +533,10 @@ async function showRecompDialog(api: TuiPluginApi, targetSessionId = getSessionI
475
533
  onConfirm={() => {
476
534
  void requestRecomp(sessionId)
477
535
  kickRecompProgressRefresh()
478
- api.ui.toast({ message: "Recomp requested — historian will start shortly", variant: "info", duration: 5000 })
536
+ showToast(api, { message: "Recomp requested — historian will start shortly", variant: "info" })
479
537
  }}
480
538
  onCancel={() => {
481
- api.ui.toast({ message: "Recomp cancelled", variant: "info", duration: 3000 })
539
+ showToast(api, { message: "Recomp cancelled", variant: "info", durationOverrideMs: 3000 })
482
540
  }}
483
541
  />
484
542
  ))
@@ -535,12 +593,11 @@ function showUpgradeDialog(
535
593
  // call fires no message event, so without this the progress
536
594
  // bar wouldn't appear until the upgrade finished.
537
595
  kickRecompProgressRefresh()
538
- api.ui.toast({
596
+ showToast(api, {
539
597
  message: resume
540
598
  ? "Resuming session upgrade — running in the background"
541
599
  : "Session upgrade started — running in the background",
542
600
  variant: "info",
543
- duration: 5000,
544
601
  })
545
602
  // Dismiss the durable reminder ONLY after the upgrade request
546
603
  // actually started. If requestUpgrade() returns false (RPC /
@@ -558,10 +615,10 @@ function showUpgradeDialog(
558
615
  // never-upgraded session (dogfood 2026-05-30) relies on THIS
559
616
  // being the only place the TUI path stamps.
560
617
  void dismissUpgradeReminder(sessionId)
561
- api.ui.toast({
618
+ showToast(api, {
562
619
  message: "Upgrade skipped — run /ctx-session-upgrade anytime",
563
620
  variant: "info",
564
- duration: 4000,
621
+ durationOverrideMs: 4000,
565
622
  })
566
623
  }}
567
624
  />
@@ -573,7 +630,7 @@ function showUpgradeDialog(
573
630
  async function showStatusDialog(api: TuiPluginApi, targetSessionId = getSessionId(api)): Promise<boolean> {
574
631
  const sessionId = targetSessionId
575
632
  if (!sessionId) {
576
- api.ui.toast({ message: "No active session", variant: "warning" })
633
+ showToast(api, { message: "No active session", variant: "warning" })
577
634
  return false
578
635
  }
579
636
 
@@ -793,6 +850,7 @@ const tui: TuiPlugin = async (api, _options, meta) => {
793
850
  // Initialize RPC client for server communication
794
851
  const directory = api.state.path.directory ?? ""
795
852
  initRpcClient(directory)
853
+ await refreshToastDurationMs()
796
854
 
797
855
  // Register sidebar slot
798
856
  api.slots.register(createSidebarContentSlot(api))
@@ -830,6 +888,9 @@ const tui: TuiPlugin = async (api, _options, meta) => {
830
888
  pollInFlight = true
831
889
  const pollGeneration = getRpcGeneration()
832
890
  void consumeTuiMessages(requestedSessionId).then(async (messages) => {
891
+ if (unifiedToastDurationMs === DEFAULT_TOAST_DURATION_MS) {
892
+ void refreshToastDurationMs()
893
+ }
833
894
  // The dialog handlers read the current session when they run. If the
834
895
  // user switched routes while the RPC was in flight, drop this whole
835
896
  // batch without advancing the cursor; the next poll for the new
@@ -843,6 +904,12 @@ const tui: TuiPlugin = async (api, _options, meta) => {
843
904
  const orderedMessages = [...messages].sort((a, b) => a.id - b.id)
844
905
  const handledMessageIds = new Set<number>()
845
906
  for (const msg of orderedMessages) {
907
+ // A dialog helper earlier in this batch may have awaited; re-check
908
+ // the route before EACH message so a later action/toast in the same
909
+ // batch can't paint into a session the user switched to mid-batch
910
+ // (the pre-batch + pre-ack guards alone don't cover mid-batch awaits).
911
+ if (getRpcGeneration() !== pollGeneration) return
912
+ if (getSessionId(api) !== requestedSessionId) return
846
913
  // Drop any action/dialog whose sessionId doesn't match this TUI's
847
914
  // active session (session-less/global notifications still apply).
848
915
  if (
@@ -854,10 +921,13 @@ const tui: TuiPlugin = async (api, _options, meta) => {
854
921
  }
855
922
  if (msg.type === "toast") {
856
923
  const p = msg.payload
857
- api.ui.toast({
924
+ showToast(api, {
858
925
  message: String(p.message ?? ""),
859
926
  variant: (p.variant as "info" | "warning" | "error" | "success") ?? "info",
860
- duration: typeof p.duration === "number" ? p.duration : 5000,
927
+ durationOverrideMs:
928
+ typeof p.duration === "number" && Number.isFinite(p.duration)
929
+ ? p.duration
930
+ : undefined,
861
931
  })
862
932
  handledMessageIds.add(msg.id)
863
933
  } else if (msg.type === "action") {
@@ -503,6 +503,10 @@ const SidebarContent = (props: {
503
503
  const directory = props.api.state.path.directory ?? ""
504
504
  void loadSidebarSnapshot(sid, directory)
505
505
  .then((data) => {
506
+ // Guard against a session switch while this load was in flight:
507
+ // painting session A's snapshot into the now-active session B shows
508
+ // the wrong session's numbers until B's own refresh resolves.
509
+ if (props.sessionID() !== sid) return
506
510
  setSnapshot(data)
507
511
  try {
508
512
  props.api.renderer.requestRender()
@@ -1,55 +0,0 @@
1
- import type { Database } from "../../../shared/sqlite";
2
- export interface DreamQueueEntry {
3
- id: number;
4
- /** Project identity (e.g. "git:<sha>"), NOT a filesystem path */
5
- projectIdentity: string;
6
- reason: string;
7
- enqueuedAt: number;
8
- startedAt: number | null;
9
- }
10
- export declare function ensureDreamQueueTable(db: Database): void;
11
- export declare function hasActiveDreamLease(db: Database): boolean;
12
- /** Enqueue a project for dreaming. Skips if the same project already has any queue entry (queued or running).
13
- *
14
- * @param force - When true (e.g. manual /ctx-dream), uses the lease TTL (2 min) as the stale threshold
15
- * instead of the full 2-hour max-runtime window. This lets users re-trigger dreaming after a crash or
16
- * restart even when the previous queue entry was started only seconds ago.
17
- */
18
- export declare function enqueueDream(db: Database, projectIdentity: string, reason: string, force?: boolean): DreamQueueEntry | null;
19
- /** Peek at the next unstarted entry without claiming it.
20
- *
21
- * @param projectIdentity - When provided, only matches entries for this project.
22
- * This is critical for cross-process coexistence: each running OpenCode/Pi
23
- * process registers exactly one project, so it must only drain entries that
24
- * belong to it. Without this filter, Pi (running in project A) would dequeue
25
- * queue entries for project B and try to dream B with Pi's runner — which
26
- * either spawns `pi` in a directory that doesn't exist (the `git:<sha>`
27
- * identity string) or, even if it succeeded, runs the wrong harness for that
28
- * project.
29
- */
30
- export declare function peekQueue(db: Database, projectIdentity?: string): DreamQueueEntry | null;
31
- /** Claim the next unstarted entry atomically by marking started_at. Returns null if queue is empty.
32
- *
33
- * @param projectIdentity - When provided, only dequeues entries for this project.
34
- * See `peekQueue` for the cross-process coexistence rationale.
35
- */
36
- export declare function dequeueNext(db: Database, projectIdentity?: string): DreamQueueEntry | null;
37
- /** Remove a completed or failed entry from the queue. */
38
- export declare function removeDreamEntry(db: Database, id: number): void;
39
- /** Reset a dequeued entry so it can be retried (e.g., after lease failure). Increments retry_count. */
40
- export declare function resetDreamEntry(db: Database, id: number): void;
41
- /** Get the retry count for a queue entry. */
42
- export declare function getEntryRetryCount(db: Database, id: number): number;
43
- /**
44
- * Clear stale started entries (stuck for more than maxAgeMs).
45
- *
46
- * Callers MUST gate this on `!hasActiveDreamLease(db)` — a healthy long-running
47
- * dream can exceed `maxAgeMs` while still renewing its lease, and deleting its
48
- * own row mid-run is the bug this guard prevents (mirrors the enqueue path).
49
- *
50
- * `projectIdentity` scopes the delete to one project. The shared `dream_queue`
51
- * is cross-process (OpenCode + Pi); a global delete would reap other hosts'
52
- * still-running rows. Omit only for the legacy "reap any" test path.
53
- */
54
- export declare function clearStaleEntries(db: Database, maxAgeMs: number, projectIdentity?: string): number;
55
- //# sourceMappingURL=queue.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/dreamer/queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGvD,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAexD;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CASzD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CACxB,EAAE,EAAE,QAAQ,EACZ,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,KAAK,UAAQ,GACd,eAAe,GAAG,IAAI,CAsCxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CA4BxF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAa1F;AAED,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED,uGAAuG;AACvG,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAI9D;AAED,6CAA6C;AAC7C,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC7B,EAAE,EAAE,QAAQ,EACZ,QAAQ,EAAE,MAAM,EAChB,eAAe,CAAC,EAAE,MAAM,GACzB,MAAM,CAYR"}
@@ -1,92 +0,0 @@
1
- import type { DreamingTask } from "../../../config/schema/magic-context";
2
- import type { PluginContext } from "../../../plugin/types";
3
- import { Database } from "../../../shared/sqlite";
4
- interface ExperimentalPinKeyFilesConfig {
5
- enabled: boolean;
6
- token_budget: number;
7
- min_reads: number;
8
- }
9
- export declare function registerDreamProjectDirectory(projectIdentity: string, directory: string): void;
10
- export interface DreamRunResult {
11
- startedAt: number;
12
- finishedAt: number;
13
- holderId: string;
14
- smartNotesSurfaced: number;
15
- smartNotesPending: number;
16
- tasks: {
17
- name: string;
18
- durationMs: number;
19
- result: unknown;
20
- error?: string;
21
- }[];
22
- }
23
- export declare function runDream(args: {
24
- db: Database;
25
- client: PluginContext["client"];
26
- /** Project identity (e.g. "git:<sha>"), NOT a filesystem path. Used for dream state keys. */
27
- projectIdentity: string;
28
- tasks: DreamingTask[];
29
- taskTimeoutMinutes: number;
30
- maxRuntimeMinutes: number;
31
- parentSessionId?: string;
32
- sessionDirectory?: string;
33
- experimentalUserMemories?: {
34
- enabled: boolean;
35
- promotionThreshold: number;
36
- };
37
- experimentalPinKeyFiles?: ExperimentalPinKeyFilesConfig;
38
- /**
39
- * Resolved fallback chain for dreamer subagent calls. When the primary
40
- * `dreamer.model` fails (auth, model-not-found, rate limit, transient
41
- * network), each entry is tried in order before giving up. Empty/undefined
42
- * disables fallback iteration (legacy single-suggestion-retry only).
43
- *
44
- * Caller (`processDreamQueue` / direct caller) resolves this via
45
- * `resolveFallbackChain(DREAMER_AGENT, config.dreamer.fallback_models)`.
46
- */
47
- fallbackModels?: readonly string[];
48
- }): Promise<DreamRunResult>;
49
- export declare function processDreamQueue(args: {
50
- db: Database;
51
- client: PluginContext["client"];
52
- tasks: DreamingTask[];
53
- taskTimeoutMinutes: number;
54
- maxRuntimeMinutes: number;
55
- experimentalUserMemories?: {
56
- enabled: boolean;
57
- promotionThreshold: number;
58
- };
59
- experimentalPinKeyFiles?: ExperimentalPinKeyFilesConfig;
60
- /**
61
- * Optional project identity filter — when provided, only entries belonging
62
- * to this project are dequeued. Each running OpenCode/Pi process registers
63
- * exactly one project, and the host's dreamer client (and `pi` runner, in
64
- * Pi's case) is project-specific. Without this filter, a Pi process running
65
- * for project A would dequeue queue entries for project B and try to
66
- * `posix_spawn 'pi'` in B's `git:<sha>` identity string as a directory,
67
- * failing with ENOENT every cycle.
68
- *
69
- * Callers should pass this whenever they own a single project — both the
70
- * scheduled timer tick (`sweepProject`) and the `/ctx-dream` command
71
- * handler. Tests pass `undefined` to keep the legacy "dequeue any" semantics.
72
- */
73
- projectIdentity?: string;
74
- /**
75
- * Filesystem directory of the project THIS draining process owns. Because
76
- * project identity collapses worktrees/clones to one `git:<sha>`, resolving
77
- * the execution directory from the shared in-memory map can pick a stale
78
- * sibling checkout ("last-registered wins"). The drain caller always knows
79
- * its own live directory, so passing it here guarantees the dream runs in a
80
- * checkout this process actually registered. Paired with projectIdentity
81
- * (the queue filter), so the dequeued entry is guaranteed to be this
82
- * project's. Falls back to the map (then the identity string) when omitted.
83
- */
84
- sessionDirectoryOverride?: string;
85
- /**
86
- * Resolved Dreamer fallback chain. See `runDream` for semantics. Callers
87
- * compute via `resolveFallbackChain(DREAMER_AGENT, pluginConfig.dreamer?.fallback_models)`.
88
- */
89
- fallbackModels?: readonly string[];
90
- }): Promise<DreamRunResult | null>;
91
- export {};
92
- //# sourceMappingURL=runner.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/dreamer/runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAO3D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAiClD,UAAU,6BAA6B;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,6BAA6B,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAE9F;AAMD,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAClB,EAAE,CAAC;CACP;AAqED,wBAAsB,QAAQ,CAAC,IAAI,EAAE;IACjC,EAAE,EAAE,QAAQ,CAAC;IACb,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,6FAA6F;IAC7F,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wBAAwB,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,uBAAuB,CAAC,EAAE,6BAA6B,CAAC;IACxD;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,GAAG,OAAO,CAAC,cAAc,CAAC,CAijB1B;AA2OD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC1C,EAAE,EAAE,QAAQ,CAAC;IACb,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,wBAAwB,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,uBAAuB,CAAC,EAAE,6BAA6B,CAAC;IACxD;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;OASG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC;;;OAGG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAqEjC"}
@@ -1,29 +0,0 @@
1
- import type { Database } from "../../../shared/sqlite";
2
- /** Parse "HH:MM-HH:MM" into start/end minutes since midnight. */
3
- export declare function parseScheduleWindow(schedule: string): {
4
- startMinutes: number;
5
- endMinutes: number;
6
- } | null;
7
- /** Check if the current time is inside the schedule window. Handles overnight windows (e.g. 23:00-05:00). */
8
- export declare function isInScheduleWindow(schedule: string, now?: Date): boolean;
9
- /** Find projects that have memory updates or pending smart notes since their per-project last dream time. */
10
- export declare function findProjectsNeedingDream(db: Database): string[];
11
- /**
12
- * Check schedule and enqueue eligible projects.
13
- * Called periodically from the hook layer (debounced to once per hour).
14
- * Returns the number of projects enqueued.
15
- *
16
- * @param ownProjectIdentity - When provided, restricts enqueue to this project.
17
- * Each running OpenCode/Pi process registers exactly one project, so it
18
- * must only enqueue work for THAT project — otherwise a process running for
19
- * project A would enqueue dream entries for projects B, C, D... that this
20
- * host can't actually drain (it has the wrong client + the wrong
21
- * subagent-runner directory). Without the filter, a Pi process running for
22
- * `opencode-anthropic-auth` ends up trying to spawn `pi --print` for
23
- * `opencode-xtra` (a project Pi was never opened in), failing every cycle.
24
- *
25
- * When undefined, the legacy "enqueue everything that needs a dream"
26
- * behavior is preserved for tests and any future single-host caller.
27
- */
28
- export declare function checkScheduleAndEnqueue(db: Database, schedule: string, ownProjectIdentity?: string): number;
29
- //# sourceMappingURL=scheduler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/dreamer/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAIvD,iEAAiE;AACjE,wBAAgB,mBAAmB,CAC/B,QAAQ,EAAE,MAAM,GACjB;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAkBrD;AAaD,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,OAAO,CAYpF;AAED,6GAA6G;AAC7G,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,EAAE,CAwD/D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CACnC,EAAE,EAAE,QAAQ,EACZ,QAAQ,EAAE,MAAM,EAChB,kBAAkB,CAAC,EAAE,MAAM,GAC5B,MAAM,CAgCR"}
@@ -1,11 +0,0 @@
1
- export interface AftAvailability {
2
- available: boolean;
3
- opencode: boolean;
4
- pi: boolean;
5
- checkedPaths: string[];
6
- }
7
- export declare function getAftAvailability(): AftAvailability;
8
- export declare function isAftAvailable(): boolean;
9
- /** Test-only override for deterministic key-files unit tests. */
10
- export declare function setAftAvailabilityOverride(value: boolean | null): void;
11
- //# sourceMappingURL=aft-availability.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aft-availability.d.ts","sourceRoot":"","sources":["../../../../src/features/magic-context/key-files/aft-availability.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,EAAE,EAAE,OAAO,CAAC;IACZ,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B;AAsED,wBAAgB,kBAAkB,IAAI,eAAe,CAkDpD;AAED,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,iEAAiE;AACjE,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAEtE"}