@cortexkit/opencode-magic-context 0.33.1 → 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 (205) 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 +82 -2
  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-n48c783v.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 +57 -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.map +1 -1
  17. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  18. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  21. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  23. package/dist/features/magic-context/fail-closed-block.d.ts +10 -0
  24. package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
  25. package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -1
  26. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
  27. package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
  28. package/dist/features/magic-context/memory/embedding-local.d.ts +7 -1
  29. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  30. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  31. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  32. package/dist/features/magic-context/memory/project-identity.d.ts +2 -6
  33. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  34. package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
  35. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  36. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  37. package/dist/features/magic-context/mural/render-mural.d.ts.map +1 -1
  38. package/dist/features/magic-context/overflow-detection.d.ts +8 -1
  39. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  40. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  41. package/dist/features/magic-context/scheduler.d.ts.map +1 -1
  42. package/dist/features/magic-context/schema-fence-probe.d.ts +28 -0
  43. package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -0
  44. package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
  45. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  46. package/dist/features/magic-context/storage-db.d.ts +35 -1
  47. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  48. package/dist/features/magic-context/storage-meta-persisted.d.ts +38 -4
  49. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  50. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  51. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  52. package/dist/features/magic-context/storage.d.ts +1 -1
  53. package/dist/features/magic-context/storage.d.ts.map +1 -1
  54. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/boundary-execution.d.ts +1 -1
  56. package/dist/hooks/magic-context/boundary-execution.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/cache-busting-signals.d.ts +1 -0
  58. package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
  59. package/dist/hooks/magic-context/child-session-spawn.d.ts +26 -0
  60. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -0
  61. package/dist/hooks/magic-context/command-handler.d.ts +2 -0
  62. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  63. package/dist/hooks/magic-context/compaction-off-transition.d.ts +96 -0
  64. package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -0
  65. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -0
  66. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  67. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/compartment-runner-mapping.d.ts.map +1 -1
  69. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/compartment-trigger.d.ts +12 -5
  72. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  73. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +47 -1
  74. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
  75. package/dist/hooks/magic-context/emergency-drop.d.ts +2 -2
  76. package/dist/hooks/magic-context/event-handler.d.ts +7 -0
  77. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/event-resolvers.d.ts +13 -21
  79. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  80. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
  81. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  82. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +1 -1
  83. package/dist/hooks/magic-context/hook-handlers.d.ts +1 -0
  84. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  85. package/dist/hooks/magic-context/hook.d.ts +11 -1
  86. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  87. package/dist/hooks/magic-context/inject-compartments.d.ts +9 -0
  88. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  89. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  90. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  92. package/dist/hooks/magic-context/rust-mode-transform.d.ts +3 -0
  93. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  94. package/dist/hooks/magic-context/send-session-notification.d.ts +20 -1
  95. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  96. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -0
  97. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  98. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +30 -0
  99. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  100. package/dist/hooks/magic-context/transform.d.ts +27 -0
  101. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  102. package/dist/{index-ey1bc14z.js → index-b563sga5.js} +7 -264
  103. package/dist/{index-y1c9tcm3.js → index-cn960ffd.js} +101 -20
  104. package/dist/{index-xyaekybw.js → index-dtas91s5.js} +6 -4
  105. package/dist/index-fcyvznch.js +279 -0
  106. package/dist/{index-63dq2g4d.js → index-ry8rh8cv.js} +138 -24
  107. package/dist/{index-c2gahrks.js → index-s0mdn690.js} +1599 -892
  108. package/dist/index.d.ts.map +1 -1
  109. package/dist/index.js +1292 -623
  110. package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
  111. package/dist/plugin/hooks/create-session-hooks.d.ts +11 -0
  112. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  113. package/dist/plugin/messages-transform.d.ts +10 -0
  114. package/dist/plugin/messages-transform.d.ts.map +1 -1
  115. package/dist/plugin/rpc-handlers.d.ts +3 -7
  116. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  117. package/dist/plugin/tool-registry.d.ts +8 -0
  118. package/dist/plugin/tool-registry.d.ts.map +1 -1
  119. package/dist/{recomp-orchestrator-2yb2hfh2.js → recomp-orchestrator-8e82vmvb.js} +6 -4
  120. package/dist/send-session-notification-6njqewzk.js +20 -0
  121. package/dist/shared/conflict-detector.d.ts +38 -1
  122. package/dist/shared/conflict-detector.d.ts.map +1 -1
  123. package/dist/shared/conflict-fixer.d.ts +18 -1
  124. package/dist/shared/conflict-fixer.d.ts.map +1 -1
  125. package/dist/shared/context-limit-provenance.d.ts +3 -0
  126. package/dist/shared/context-limit-provenance.d.ts.map +1 -0
  127. package/dist/shared/escalation-bands.d.ts +9 -0
  128. package/dist/shared/escalation-bands.d.ts.map +1 -0
  129. package/dist/shared/format-threshold.d.ts +1 -1
  130. package/dist/shared/models-dev-cache.d.ts +29 -3
  131. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  132. package/dist/shared/rpc-server.d.ts.map +1 -1
  133. package/dist/shared/rpc-types.d.ts +46 -1
  134. package/dist/shared/rpc-types.d.ts.map +1 -1
  135. package/dist/shared/storage-permissions.d.ts +5 -0
  136. package/dist/shared/storage-permissions.d.ts.map +1 -0
  137. package/dist/{storage-meta-session-td6bwtky.js → storage-meta-session-xt41zbw4.js} +2 -1
  138. package/dist/tui/compaction-off.d.ts +13 -0
  139. package/dist/tui/compaction-off.d.ts.map +1 -0
  140. package/dist/tui/data/context-db.d.ts.map +1 -1
  141. package/dist/tui-compiled/compaction-off.d.ts +13 -0
  142. package/dist/tui-compiled/compaction-off.d.ts.map +1 -0
  143. package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
  144. package/package.json +7 -2
  145. package/src/agents/dreamer.ts +68 -0
  146. package/src/agents/hidden-agent-registrations.ts +331 -0
  147. package/src/agents/historian.ts +3 -0
  148. package/src/agents/language-directive.test.ts +138 -0
  149. package/src/agents/language-directive.ts +121 -0
  150. package/src/agents/magic-context-prompt.language.test.ts +35 -0
  151. package/src/agents/magic-context-prompt.test.ts +292 -0
  152. package/src/agents/magic-context-prompt.ts +182 -0
  153. package/src/agents/permissions.test.ts +252 -0
  154. package/src/agents/permissions.ts +186 -0
  155. package/src/agents/sidekick.ts +1 -0
  156. package/src/agents/smart-note-compiler.ts +1 -0
  157. package/src/config/agent-disable.ts +106 -0
  158. package/src/config/compaction-accessor-guard.test.ts +82 -0
  159. package/src/config/compaction-backcompat.test.ts +52 -0
  160. package/src/config/index.test.ts +904 -0
  161. package/src/config/index.ts +601 -0
  162. package/src/config/migrate-config-location.test.ts +332 -0
  163. package/src/config/migrate-config-location.ts +635 -0
  164. package/src/config/migrate-dreamer-v2.test.ts +287 -0
  165. package/src/config/migrate-dreamer-v2.ts +336 -0
  166. package/src/config/migrate-experimental.ts +159 -0
  167. package/src/config/project-security.test.ts +366 -0
  168. package/src/config/project-security.ts +588 -0
  169. package/src/config/prune-config-leaf.test.ts +78 -0
  170. package/src/config/prune-config-leaf.ts +68 -0
  171. package/src/config/removed-config-keys.test.ts +116 -0
  172. package/src/config/schema/agent-overrides.ts +45 -0
  173. package/src/config/schema/magic-context.test.ts +358 -0
  174. package/src/config/schema/magic-context.ts +1002 -0
  175. package/src/config/transform-mode.test.ts +62 -0
  176. package/src/config/transform-mode.ts +34 -0
  177. package/src/config/variable.test.ts +323 -0
  178. package/src/config/variable.ts +192 -0
  179. package/src/features/magic-context/defaults.ts +1 -0
  180. package/src/features/magic-context/dreamer/cron.ts +243 -0
  181. package/src/features/magic-context/dreamer/task-registry.ts +104 -0
  182. package/src/shared/conflict-detector.test.ts +121 -0
  183. package/src/shared/conflict-detector.ts +50 -3
  184. package/src/shared/conflict-fixer.test.ts +309 -0
  185. package/src/shared/conflict-fixer.ts +82 -5
  186. package/src/shared/context-limit-provenance.ts +6 -0
  187. package/src/shared/escalation-bands.test.ts +23 -0
  188. package/src/shared/escalation-bands.ts +18 -0
  189. package/src/shared/format-threshold.ts +1 -1
  190. package/src/shared/models-dev-cache.test.ts +171 -0
  191. package/src/shared/models-dev-cache.ts +195 -38
  192. package/src/shared/rpc-server.ts +27 -18
  193. package/src/shared/rpc-types.ts +46 -1
  194. package/src/shared/storage-permissions.ts +20 -0
  195. package/src/tui/compaction-off.test.ts +56 -0
  196. package/src/tui/compaction-off.ts +29 -0
  197. package/src/tui/data/context-db.ts +6 -0
  198. package/src/tui/index.tsx +113 -65
  199. package/src/tui/slots/sidebar-content.tsx +139 -83
  200. package/src/tui-compiled/compaction-off.ts +29 -0
  201. package/src/tui-compiled/data/context-db.ts +6 -0
  202. package/src/tui-compiled/index.tsx +558 -455
  203. package/src/tui-compiled/slots/sidebar-content.tsx +237 -161
  204. package/dist/send-session-notification-tghq9gnh.js +0 -11
  205. /package/dist/{index-v7fmc1s2.js → index-ygcng9t8.js} +0 -0
@@ -1,8 +1,13 @@
1
+ import {
2
+ closeQuietly,
3
+ getRawSessionMessageCountFromDb,
4
+ openCodeDbExists,
5
+ withReadOnlySessionDb
6
+ } from "./index-fcyvznch.js";
1
7
  import {
2
8
  log
3
9
  } from "./index-k1esqfwk.js";
4
10
  import {
5
- getDataDir,
6
11
  getHarness
7
12
  } from "./index-kvrcg31b.js";
8
13
  import {
@@ -50,268 +55,6 @@ function removeSystemReminders(text) {
50
55
  return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, "").trim();
51
56
  }
52
57
 
53
- // src/hooks/magic-context/read-session-db.ts
54
- import { existsSync } from "node:fs";
55
- import { join } from "node:path";
56
-
57
- // src/shared/sqlite.ts
58
- var isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
59
- var bunSpec = "bun:" + "sqlite";
60
- var nodeSpec = "node:" + "sqlite";
61
- var sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
62
- var DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
63
- function buildNodeSqliteDatabaseClass(DatabaseSync) {
64
- const SAVEPOINT = "mc_tx_sp";
65
-
66
- class NodeSqliteDatabase extends DatabaseSync {
67
- constructor(filename, options) {
68
- const translated = { ...options };
69
- if (options && "readonly" in options) {
70
- translated.readOnly = options.readonly;
71
- delete translated.readonly;
72
- }
73
- super(typeof filename === "string" ? filename : ":memory:", translated);
74
- }
75
- prepare(sql) {
76
- const stmt = super.prepare(sql);
77
- for (const method of ["run", "get", "all"]) {
78
- const original = stmt[method].bind(stmt);
79
- stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
80
- }
81
- return stmt;
82
- }
83
- transaction(fn) {
84
- const self = this;
85
- const execute = (mode, receiver, args) => {
86
- const nested = self.isTransaction === true;
87
- self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : `BEGIN${mode ? ` ${mode}` : ""}`);
88
- try {
89
- const result = fn.apply(receiver, args);
90
- self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
91
- return result;
92
- } catch (error) {
93
- if (nested) {
94
- self.exec(`ROLLBACK TO ${SAVEPOINT}`);
95
- self.exec(`RELEASE ${SAVEPOINT}`);
96
- } else {
97
- self.exec("ROLLBACK");
98
- }
99
- throw error;
100
- }
101
- };
102
- const wrapped = function(...args) {
103
- return execute("", this, args);
104
- };
105
- wrapped.default = function(...args) {
106
- return execute("", this, args);
107
- };
108
- wrapped.deferred = function(...args) {
109
- return execute("DEFERRED", this, args);
110
- };
111
- wrapped.immediate = function(...args) {
112
- return execute("IMMEDIATE", this, args);
113
- };
114
- wrapped.exclusive = function(...args) {
115
- return execute("EXCLUSIVE", this, args);
116
- };
117
- return wrapped;
118
- }
119
- }
120
- return NodeSqliteDatabase;
121
- }
122
- var Database = DatabaseImpl;
123
- var privilegeDepth = new WeakMap;
124
- function isInTransaction(db) {
125
- const candidate = db;
126
- return candidate.inTransaction === true || candidate.isTransaction === true;
127
- }
128
- function withPrivilegedWriter(db, operation) {
129
- const previousDepth = privilegeDepth.get(db) ?? 0;
130
- const nested = isInTransaction(db);
131
- const savepoint = "mc_privilege_scope";
132
- if (nested) {
133
- db.exec(`SAVEPOINT ${savepoint}`);
134
- } else {
135
- db.exec("BEGIN IMMEDIATE");
136
- }
137
- privilegeDepth.set(db, previousDepth + 1);
138
- try {
139
- db.prepare("INSERT INTO context_privilege_state(id, enabled) VALUES (1, 1) ON CONFLICT(id) DO UPDATE SET enabled = 1").run();
140
- const result = operation();
141
- if (previousDepth === 0) {
142
- db.prepare("UPDATE context_privilege_state SET enabled = 0 WHERE id = 1").run();
143
- }
144
- if (nested) {
145
- db.exec(`RELEASE ${savepoint}`);
146
- } else {
147
- db.exec("COMMIT");
148
- }
149
- if (previousDepth > 0)
150
- privilegeDepth.set(db, previousDepth);
151
- else
152
- privilegeDepth.delete(db);
153
- return result;
154
- } catch (error) {
155
- try {
156
- if (nested) {
157
- db.exec(`ROLLBACK TO ${savepoint}`);
158
- db.exec(`RELEASE ${savepoint}`);
159
- } else {
160
- db.exec("ROLLBACK");
161
- }
162
- } finally {
163
- if (previousDepth > 0)
164
- privilegeDepth.set(db, previousDepth);
165
- else
166
- privilegeDepth.delete(db);
167
- }
168
- throw error;
169
- }
170
- }
171
-
172
- // src/shared/sqlite-helpers.ts
173
- function closeQuietly(db) {
174
- if (!db)
175
- return;
176
- try {
177
- db.close();
178
- } catch {}
179
- }
180
-
181
- // src/hooks/magic-context/read-session-db.ts
182
- function getOpenCodeDbPath() {
183
- return join(getDataDir(), "opencode", "opencode.db");
184
- }
185
- function openCodeDbExists() {
186
- return existsSync(getOpenCodeDbPath());
187
- }
188
- var cachedReadOnlyDb = null;
189
- function closeCachedReadOnlyDb() {
190
- if (!cachedReadOnlyDb) {
191
- return;
192
- }
193
- try {
194
- closeQuietly(cachedReadOnlyDb.db);
195
- } catch (error) {
196
- log("[magic-context] failed to close cached OpenCode read-only DB:", error);
197
- } finally {
198
- cachedReadOnlyDb = null;
199
- }
200
- }
201
- function getReadOnlySessionDb() {
202
- const dbPath = getOpenCodeDbPath();
203
- if (cachedReadOnlyDb?.path === dbPath) {
204
- return cachedReadOnlyDb.db;
205
- }
206
- closeCachedReadOnlyDb();
207
- const db = new Database(dbPath, { readonly: true });
208
- cachedReadOnlyDb = { path: dbPath, db };
209
- return db;
210
- }
211
- function withReadOnlySessionDb(fn) {
212
- return fn(getReadOnlySessionDb());
213
- }
214
- function getRawSessionMessageCountFromDb(db, sessionId) {
215
- const row = db.prepare(`SELECT COUNT(*) as count FROM message WHERE session_id = ?
216
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
217
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')`).get(sessionId);
218
- return typeof row?.count === "number" ? row.count : 0;
219
- }
220
- function isMidTurn(_deps, sessionId) {
221
- try {
222
- return withReadOnlySessionDb((db) => isMidTurnFromOpenCodeDb(db, sessionId));
223
- } catch (error) {
224
- log("[magic-context] failed to inspect OpenCode mid-turn state:", error);
225
- return false;
226
- }
227
- }
228
- function isMidTurnFromOpenCodeDb(db, sessionId) {
229
- const latestAssistant = db.prepare(`SELECT id,
230
- json_extract(data, '$.finish') as finish,
231
- time_created as timeCreated
232
- FROM message
233
- WHERE session_id = ?
234
- AND json_extract(data, '$.role') = 'assistant'
235
- ORDER BY time_created DESC
236
- LIMIT 1`).get(sessionId);
237
- if (typeof latestAssistant?.id !== "string")
238
- return false;
239
- if (hasNewerRealUserMessage(db, sessionId, latestAssistant.timeCreated))
240
- return false;
241
- if (latestAssistant.finish === "tool-calls")
242
- return true;
243
- const partRows = db.prepare("SELECT data FROM part WHERE session_id = ? AND message_id = ?").all(sessionId, latestAssistant.id);
244
- return partRows.some((row) => {
245
- if (typeof row.data !== "string" || row.data.length === 0)
246
- return false;
247
- try {
248
- const part = JSON.parse(row.data);
249
- return part.type === "tool" && part.providerExecuted !== true;
250
- } catch {
251
- return false;
252
- }
253
- });
254
- }
255
- function hasNewerRealUserMessage(db, sessionId, latestAssistantTimeCreated) {
256
- if (typeof latestAssistantTimeCreated !== "number")
257
- return false;
258
- const row = db.prepare(`SELECT 1 as one
259
- FROM message
260
- WHERE session_id = ?
261
- AND time_created > ?
262
- AND json_extract(data, '$.role') = 'user'
263
- AND COALESCE(json_extract(data, '$.synthetic'), 0) NOT IN (1, 'true')
264
- LIMIT 1`).get(sessionId, latestAssistantTimeCreated);
265
- return row?.one === 1;
266
- }
267
- function getMessageTimesFromOpenCodeDb(sessionId, messageIds) {
268
- const result = new Map;
269
- if (messageIds.length === 0)
270
- return result;
271
- try {
272
- withReadOnlySessionDb((db) => {
273
- const placeholders = messageIds.map(() => "?").join(",");
274
- const rows = db.prepare(`SELECT id, time_created FROM message WHERE session_id = ? AND id IN (${placeholders})`).all(sessionId, ...messageIds);
275
- for (const row of rows) {
276
- if (typeof row.id === "string" && typeof row.time_created === "number") {
277
- result.set(row.id, row.time_created);
278
- }
279
- }
280
- });
281
- } catch (error) {
282
- log("[magic-context] failed to resolve message times from OpenCode DB:", error);
283
- }
284
- return result;
285
- }
286
- function findLastAssistantModelFromOpenCodeDb(sessionId) {
287
- try {
288
- return withReadOnlySessionDb((db) => {
289
- const row = db.prepare(`SELECT json_extract(data, '$.providerID') as providerID,
290
- json_extract(data, '$.modelID') as modelID,
291
- json_extract(data, '$.agent') as agent
292
- FROM message
293
- WHERE session_id = ?
294
- AND json_extract(data, '$.role') = 'assistant'
295
- AND json_extract(data, '$.providerID') IS NOT NULL
296
- AND json_extract(data, '$.modelID') IS NOT NULL
297
- ORDER BY time_created DESC
298
- LIMIT 1`).get(sessionId);
299
- if (!row || typeof row.providerID !== "string" || typeof row.modelID !== "string") {
300
- return null;
301
- }
302
- const agent = typeof row.agent === "string" && row.agent.length > 0 ? row.agent : undefined;
303
- return {
304
- providerID: row.providerID,
305
- modelID: row.modelID,
306
- ...agent ? { agent } : {}
307
- };
308
- });
309
- } catch (error) {
310
- log("[magic-context] failed to recover live model from OpenCode DB:", error);
311
- return null;
312
- }
313
- }
314
-
315
58
  // src/shared/commit-detection.ts
316
59
  var HASH_HEX = "[0-9a-f]{7,12}";
317
60
  var COMMIT_HASH_TEST_PATTERN = new RegExp(`\\b${HASH_HEX}\\b`, "i");
@@ -135038,4 +134781,4 @@ function clearSession(db, sessionId) {
135038
134781
  })();
135039
134782
  }
135040
134783
 
135041
- export { Database, withPrivilegedWriter, closeQuietly, isRecord, clearCompressionDepth, clearCompressionDepthRange, ensureSessionMetaRow, persistCachedM0, clearCachedM0M1, openCodeDbExists, withReadOnlySessionDb, isMidTurn, getMessageTimesFromOpenCodeDb, findLastAssistantModelFromOpenCodeDb, textMentionsRecentCommit, hasMeaningfulUserText, extractTexts, extractToolCallSummaries, estimateTokens, normalizeText, isRawCompactionSummaryInfo, extractInMemoryMessageViews, buildInMemoryTailRawMessages, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isThinkingPart, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, isEditTool, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, setRawMessageProvider, cleanUserText, withRawSessionMessageCache, readRawSessionMessages, primeTailRawMessageCache, getCachedAbsoluteMessageCount, primeInMemoryTailRawMessageCache, readRawSessionMessageOrdinalPage, getRawSessionStoredMessageCount, readRawSessionMessagePartsById, readRawSessionMessageOrdinalById, readRawSessionMessageById, getRawSessionMessageCount, getRawSessionTagKeysThrough, getLegacyProtectedTailStartOrdinal, readSessionChunk, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getIndexedMessageCorpusSize, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, deleteIndexedMessage, clearIndexedMessages, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, clearSession };
134784
+ export { textMentionsRecentCommit, hasMeaningfulUserText, extractTexts, extractToolCallSummaries, estimateTokens, normalizeText, clearCompressionDepth, clearCompressionDepthRange, ensureSessionMetaRow, persistCachedM0, clearCachedM0M1, isRawCompactionSummaryInfo, extractInMemoryMessageViews, buildInMemoryTailRawMessages, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isThinkingPart, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, isRecord, isEditTool, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, setRawMessageProvider, cleanUserText, withRawSessionMessageCache, readRawSessionMessages, primeTailRawMessageCache, getCachedAbsoluteMessageCount, primeInMemoryTailRawMessageCache, readRawSessionMessageOrdinalPage, getRawSessionStoredMessageCount, readRawSessionMessagePartsById, readRawSessionMessageOrdinalById, readRawSessionMessageById, getRawSessionMessageCount, getRawSessionTagKeysThrough, getLegacyProtectedTailStartOrdinal, readSessionChunk, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getIndexedMessageCorpusSize, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, deleteIndexedMessage, clearIndexedMessages, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, retryPendingSessionCleanups, clearSession };
@@ -1,3 +1,6 @@
1
+ import {
2
+ isMidTurn
3
+ } from "./index-fcyvznch.js";
1
4
  import {
2
5
  sessionLog
3
6
  } from "./index-k1esqfwk.js";
@@ -82,6 +85,56 @@ function safeString(value) {
82
85
  }
83
86
 
84
87
  // src/hooks/magic-context/send-session-notification.ts
88
+ var MAX_QUEUED_IGNORED_NOTIFICATIONS = 16;
89
+ var queuedIgnoredNotifications = new Map;
90
+ var flushingIgnoredNotifications = new Set;
91
+ var midTurnDetector = (sessionId) => isMidTurn(undefined, sessionId);
92
+ function queueIgnoredNotification(notification) {
93
+ const queued = queuedIgnoredNotifications.get(notification.sessionId) ?? [];
94
+ queued.push(notification);
95
+ if (queued.length > MAX_QUEUED_IGNORED_NOTIFICATIONS) {
96
+ queued.splice(0, queued.length - MAX_QUEUED_IGNORED_NOTIFICATIONS);
97
+ sessionLog(notification.sessionId, `ignored notification queue full; dropped oldest entries (kept newest ${MAX_QUEUED_IGNORED_NOTIFICATIONS})`);
98
+ }
99
+ queuedIgnoredNotifications.set(notification.sessionId, queued);
100
+ }
101
+ async function trySendTuiToast(sessionId, text, params, forcePersist) {
102
+ if (forcePersist)
103
+ return false;
104
+ const title = extractToastTitle(text);
105
+ const message = text.length > 200 ? `${text.slice(0, 200)}…` : text;
106
+ const toastVariant = inferToastVariant(text);
107
+ const duration = params.toastDurationMs ?? 5000;
108
+ const { isTuiConnected: checkTui } = await import("./rpc-notifications-4d22ybn5.js");
109
+ if (!checkTui(sessionId))
110
+ return false;
111
+ try {
112
+ const { pushNotification } = await import("./rpc-notifications-4d22ybn5.js");
113
+ pushNotification("toast", {
114
+ title,
115
+ message,
116
+ variant: toastVariant,
117
+ duration
118
+ }, sessionId);
119
+ return true;
120
+ } catch {
121
+ sessionLog(sessionId, "TUI RPC toast enqueue failed, falling back to ignored message");
122
+ return false;
123
+ }
124
+ }
125
+ var __ignoredNotificationTest = {
126
+ pendingTexts(sessionId) {
127
+ return (queuedIgnoredNotifications.get(sessionId) ?? []).map((item) => item.text);
128
+ },
129
+ reset() {
130
+ queuedIgnoredNotifications.clear();
131
+ flushingIgnoredNotifications.clear();
132
+ midTurnDetector = (sessionId) => isMidTurn(undefined, sessionId);
133
+ },
134
+ setMidTurnDetector(detector) {
135
+ midTurnDetector = detector;
136
+ }
137
+ };
85
138
  function hasNotificationSessionClient(client) {
86
139
  if (client === null || typeof client !== "object")
87
140
  return false;
@@ -113,31 +166,20 @@ function extractToastTitle(text) {
113
166
  return firstLine;
114
167
  return "Magic Context";
115
168
  }
116
- async function sendIgnoredMessage(client, sessionId, text, params, forcePersist = false) {
117
- const title = extractToastTitle(text);
118
- const message = text.length > 200 ? `${text.slice(0, 200)}…` : text;
119
- const toastVariant = inferToastVariant(text);
120
- const duration = params.toastDurationMs ?? 5000;
121
- const { isTuiConnected: checkTui } = await import("./rpc-notifications-4d22ybn5.js");
122
- if (!forcePersist && checkTui(sessionId)) {
123
- try {
124
- const { pushNotification } = await import("./rpc-notifications-4d22ybn5.js");
125
- pushNotification("toast", {
126
- title,
127
- message,
128
- variant: toastVariant,
129
- duration
130
- }, sessionId);
131
- return "sent";
132
- } catch {
133
- sessionLog(sessionId, "TUI RPC toast enqueue failed, falling back to ignored message");
134
- }
169
+ async function sendIgnoredMessageNow(client, sessionId, text, params, forcePersist) {
170
+ if (midTurnDetector(sessionId)) {
171
+ queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
172
+ return "queued";
135
173
  }
136
174
  const { waitForSafeNotificationTarget } = await import("./safe-notification-target-q9jk5n44.js");
137
175
  if (await waitForSafeNotificationTarget(client, sessionId) === "skip") {
138
176
  sessionLog(sessionId, "notification skipped (session not titled yet)");
139
177
  return "skipped";
140
178
  }
179
+ if (midTurnDetector(sessionId)) {
180
+ queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
181
+ return "queued";
182
+ }
141
183
  if (!hasNotificationSessionClient(client)) {
142
184
  sessionLog(sessionId, "session prompt API unavailable for notification");
143
185
  return "failed";
@@ -157,6 +199,10 @@ async function sendIgnoredMessage(client, sessionId, text, params, forcePersist
157
199
  }
158
200
  } catch {}
159
201
  }
202
+ if (midTurnDetector(sessionId)) {
203
+ queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
204
+ return "queued";
205
+ }
160
206
  const input = {
161
207
  path: { id: sessionId },
162
208
  body: {
@@ -190,6 +236,41 @@ async function sendIgnoredMessage(client, sessionId, text, params, forcePersist
190
236
  return "failed";
191
237
  }
192
238
  }
239
+ async function sendIgnoredMessage(client, sessionId, text, params, forcePersist = false) {
240
+ if (await trySendTuiToast(sessionId, text, params, forcePersist))
241
+ return "sent";
242
+ if (midTurnDetector(sessionId)) {
243
+ queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
244
+ return "queued";
245
+ }
246
+ return sendIgnoredMessageNow(client, sessionId, text, params, forcePersist);
247
+ }
248
+ async function flushIgnoredMessages(sessionId) {
249
+ if (flushingIgnoredNotifications.has(sessionId) || midTurnDetector(sessionId))
250
+ return;
251
+ const queued = queuedIgnoredNotifications.get(sessionId);
252
+ if (!queued || queued.length === 0)
253
+ return;
254
+ queuedIgnoredNotifications.delete(sessionId);
255
+ flushingIgnoredNotifications.add(sessionId);
256
+ try {
257
+ for (const notification of queued) {
258
+ const disposition = await sendIgnoredMessage(notification.client, notification.sessionId, notification.text, notification.params, notification.forcePersist);
259
+ if (disposition === "queued") {
260
+ for (const remaining of queued.slice(queued.indexOf(notification) + 1)) {
261
+ queueIgnoredNotification(remaining);
262
+ }
263
+ break;
264
+ }
265
+ }
266
+ } finally {
267
+ flushingIgnoredNotifications.delete(sessionId);
268
+ }
269
+ }
270
+ function clearIgnoredMessages(sessionId) {
271
+ queuedIgnoredNotifications.delete(sessionId);
272
+ flushingIgnoredNotifications.delete(sessionId);
273
+ }
193
274
  async function sendUserPrompt(client, sessionId, text) {
194
275
  if (!hasNotificationSessionClient(client)) {
195
276
  sessionLog(sessionId, "session prompt API unavailable for user prompt");
@@ -216,4 +297,4 @@ async function sendUserPrompt(client, sessionId, text) {
216
297
  }
217
298
  }
218
299
 
219
- export { getErrorMessage, describeError, sendIgnoredMessage, sendUserPrompt };
300
+ export { getErrorMessage, describeError, MAX_QUEUED_IGNORED_NOTIFICATIONS, __ignoredNotificationTest, sendIgnoredMessage, flushIgnoredMessages, clearIgnoredMessages, sendUserPrompt };
@@ -160,7 +160,8 @@ function getOpenCodeConfigPaths(options) {
160
160
  }
161
161
 
162
162
  // src/shared/conflict-detector.ts
163
- function detectConflicts(directory) {
163
+ function detectConflicts(directory, options) {
164
+ const compactionEnabled = options?.compactionEnabled ?? true;
164
165
  const conflicts = {
165
166
  compactionAuto: false,
166
167
  compactionPrune: false,
@@ -171,11 +172,11 @@ function detectConflicts(directory) {
171
172
  };
172
173
  const reasons = [];
173
174
  const compactionResult = checkCompaction(directory);
174
- if (compactionResult.auto) {
175
+ if (compactionEnabled && compactionResult.auto) {
175
176
  conflicts.compactionAuto = true;
176
177
  reasons.push("OpenCode auto-compaction is enabled (compaction.auto=true)");
177
178
  }
178
- if (compactionResult.prune) {
179
+ if (compactionEnabled && compactionResult.prune) {
179
180
  conflicts.compactionPrune = true;
180
181
  reasons.push("OpenCode prune is enabled (compaction.prune=true)");
181
182
  }
@@ -200,7 +201,8 @@ function detectConflicts(directory) {
200
201
  return {
201
202
  hasConflict: reasons.length > 0,
202
203
  reasons,
203
- conflicts
204
+ conflicts,
205
+ nativeCompaction: { auto: compactionResult.auto, prune: compactionResult.prune }
204
206
  };
205
207
  }
206
208
  function checkCompaction(directory) {