@chengchenccc/oh-my-agent 0.2.0-rc.2 → 0.2.0-rc.3

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 (209) hide show
  1. package/README.md +11 -6
  2. package/dist/cli/args.d.ts +1 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +9 -2
  5. package/dist/cli/gateway-commands.d.ts.map +1 -1
  6. package/dist/cli/gateway-commands.js +35 -5
  7. package/dist/cli/initial-input.d.ts +3 -2
  8. package/dist/cli/initial-input.d.ts.map +1 -1
  9. package/dist/core/coordination/registry.d.ts +11 -0
  10. package/dist/core/coordination/registry.d.ts.map +1 -1
  11. package/dist/core/coordination/registry.js +23 -0
  12. package/dist/core/gateway/artifact.d.ts +0 -1
  13. package/dist/core/gateway/artifact.d.ts.map +1 -1
  14. package/dist/core/gateway/artifact.js +1 -1
  15. package/dist/core/goals/index.d.ts +8 -0
  16. package/dist/core/goals/index.d.ts.map +1 -0
  17. package/dist/core/goals/index.js +7 -0
  18. package/dist/core/goals/runtime.d.ts +112 -0
  19. package/dist/core/goals/runtime.d.ts.map +1 -0
  20. package/dist/core/goals/runtime.js +241 -0
  21. package/dist/core/goals/state.d.ts +82 -0
  22. package/dist/core/goals/state.d.ts.map +1 -0
  23. package/dist/core/goals/state.js +225 -0
  24. package/dist/core/goals/tool.d.ts +10 -0
  25. package/dist/core/goals/tool.d.ts.map +1 -0
  26. package/dist/core/goals/tool.js +87 -0
  27. package/dist/core/index.d.ts.map +1 -1
  28. package/dist/core/index.js +4 -3
  29. package/dist/core/loops/condition.d.ts +57 -0
  30. package/dist/core/loops/condition.d.ts.map +1 -0
  31. package/dist/core/loops/condition.js +153 -0
  32. package/dist/core/loops/index.d.ts +9 -0
  33. package/dist/core/loops/index.d.ts.map +1 -0
  34. package/dist/core/loops/index.js +8 -0
  35. package/dist/core/loops/limits.d.ts +43 -0
  36. package/dist/core/loops/limits.d.ts.map +1 -0
  37. package/dist/core/loops/limits.js +219 -0
  38. package/dist/core/loops/ralph.d.ts +37 -0
  39. package/dist/core/loops/ralph.d.ts.map +1 -0
  40. package/dist/core/loops/ralph.js +72 -0
  41. package/dist/core/loops/runtime.d.ts +95 -0
  42. package/dist/core/loops/runtime.d.ts.map +1 -0
  43. package/dist/core/loops/runtime.js +222 -0
  44. package/dist/core/memory/managed-skills.d.ts +0 -11
  45. package/dist/core/memory/managed-skills.d.ts.map +1 -1
  46. package/dist/core/memory/managed-skills.js +2 -2
  47. package/dist/core/memory/vector-store.d.ts +0 -1
  48. package/dist/core/memory/vector-store.d.ts.map +1 -1
  49. package/dist/core/memory/vector-store.js +0 -3
  50. package/dist/core/plans/index.d.ts +7 -0
  51. package/dist/core/plans/index.d.ts.map +1 -0
  52. package/dist/core/plans/index.js +6 -0
  53. package/dist/core/plans/prompts.d.ts +20 -0
  54. package/dist/core/plans/prompts.d.ts.map +1 -0
  55. package/dist/core/plans/prompts.js +72 -0
  56. package/dist/core/plans/runtime.d.ts +89 -0
  57. package/dist/core/plans/runtime.d.ts.map +1 -0
  58. package/dist/core/plans/runtime.js +170 -0
  59. package/dist/core/plans/state.d.ts +55 -0
  60. package/dist/core/plans/state.d.ts.map +1 -0
  61. package/dist/core/plans/state.js +88 -0
  62. package/dist/core/runtime/agent-loop-messages.d.ts +6 -0
  63. package/dist/core/runtime/agent-loop-messages.d.ts.map +1 -1
  64. package/dist/core/runtime/agent-loop-messages.js +40 -15
  65. package/dist/core/runtime/agent-loop-run.d.ts.map +1 -1
  66. package/dist/core/runtime/agent-loop-run.js +18 -27
  67. package/dist/core/runtime/agent-loop-runner.d.ts +1 -23
  68. package/dist/core/runtime/agent-loop-runner.d.ts.map +1 -1
  69. package/dist/core/runtime/agent-loop-runner.js +84 -30
  70. package/dist/core/runtime/agent-loop-types.d.ts +4 -0
  71. package/dist/core/runtime/agent-loop-types.d.ts.map +1 -1
  72. package/dist/core/runtime/compaction.d.ts +9 -0
  73. package/dist/core/runtime/compaction.d.ts.map +1 -1
  74. package/dist/core/runtime/compaction.js +28 -0
  75. package/dist/core/runtime/context-estimate.d.ts +37 -4
  76. package/dist/core/runtime/context-estimate.d.ts.map +1 -1
  77. package/dist/core/runtime/context-estimate.js +70 -0
  78. package/dist/core/runtime/create-runtime.d.ts +27 -5
  79. package/dist/core/runtime/create-runtime.d.ts.map +1 -1
  80. package/dist/core/runtime/create-runtime.js +22 -2
  81. package/dist/core/runtime/permission-classifier.d.ts.map +1 -1
  82. package/dist/core/runtime/permission-classifier.js +83 -12
  83. package/dist/core/runtime/plugin.d.ts +7 -0
  84. package/dist/core/runtime/plugin.d.ts.map +1 -1
  85. package/dist/core/runtime/plugin.js +13 -0
  86. package/dist/core/runtime/process-tree.d.ts +0 -9
  87. package/dist/core/runtime/process-tree.d.ts.map +1 -1
  88. package/dist/core/runtime/process-tree.js +1 -1
  89. package/dist/core/runtime/run-runtime.d.ts.map +1 -1
  90. package/dist/core/runtime/run-runtime.js +88 -49
  91. package/dist/core/runtime/runtime-catalog.d.ts +0 -4
  92. package/dist/core/runtime/runtime-catalog.d.ts.map +1 -1
  93. package/dist/core/runtime/runtime-catalog.js +1 -1
  94. package/dist/core/runtime/stream-rules.d.ts +9 -2
  95. package/dist/core/runtime/stream-rules.d.ts.map +1 -1
  96. package/dist/core/runtime/stream-rules.js +19 -5
  97. package/dist/core/runtime/title.d.ts +13 -1
  98. package/dist/core/runtime/title.d.ts.map +1 -1
  99. package/dist/core/runtime/title.js +51 -17
  100. package/dist/core/runtime/tool-pruning.d.ts.map +1 -1
  101. package/dist/core/runtime/tool-pruning.js +8 -16
  102. package/dist/core/session/session-file.d.ts +91 -5
  103. package/dist/core/session/session-file.d.ts.map +1 -1
  104. package/dist/core/session/session-file.js +206 -24
  105. package/dist/core/session/session-loop.d.ts +3 -1
  106. package/dist/core/session/session-loop.d.ts.map +1 -1
  107. package/dist/core/session/session-loop.js +8 -4
  108. package/dist/core/settings/project-settings.d.ts +63 -9
  109. package/dist/core/settings/project-settings.d.ts.map +1 -1
  110. package/dist/core/settings/project-settings.js +43 -2
  111. package/dist/core/settings/workspace-context.js +4 -4
  112. package/dist/core/store/in-memory-session-store.d.ts.map +1 -1
  113. package/dist/core/store/in-memory-session-store.js +3 -2
  114. package/dist/core/store/session-store.contract.test-helper.d.ts +7 -5
  115. package/dist/core/store/session-store.contract.test-helper.d.ts.map +1 -1
  116. package/dist/core/store/session-store.contract.test-helper.js +7 -5
  117. package/dist/core/store/session-store.d.ts +4 -2
  118. package/dist/core/store/session-store.d.ts.map +1 -1
  119. package/dist/core/store/session-store.js +4 -2
  120. package/dist/core/tools/ask-question.d.ts.map +1 -1
  121. package/dist/core/tools/ask-question.js +51 -5
  122. package/dist/core/tools/bash-pty.d.ts +13 -4
  123. package/dist/core/tools/bash-pty.d.ts.map +1 -1
  124. package/dist/core/tools/bash-pty.js +15 -8
  125. package/dist/core/tools/bash-sandbox.d.ts +1 -1
  126. package/dist/core/tools/bash.d.ts +1 -1
  127. package/dist/core/tools/bash.d.ts.map +1 -1
  128. package/dist/core/tools/bash.js +18 -8
  129. package/dist/core/tools/browser.d.ts +54 -0
  130. package/dist/core/tools/browser.d.ts.map +1 -1
  131. package/dist/core/tools/browser.js +138 -1
  132. package/dist/core/tools/file-fingerprint.d.ts +24 -0
  133. package/dist/core/tools/file-fingerprint.d.ts.map +1 -0
  134. package/dist/core/tools/file-fingerprint.js +61 -0
  135. package/dist/core/tools/file-tools.d.ts +26 -0
  136. package/dist/core/tools/file-tools.d.ts.map +1 -1
  137. package/dist/core/tools/file-tools.js +113 -17
  138. package/dist/core/tools/index.d.ts +2 -0
  139. package/dist/core/tools/index.d.ts.map +1 -1
  140. package/dist/core/tools/index.js +1 -0
  141. package/dist/core/tools/mcp-mount.d.ts +1 -1
  142. package/dist/core/tools/mcp-mount.d.ts.map +1 -1
  143. package/dist/core/tools/mcp-mount.js +72 -26
  144. package/dist/core/tools/url-guard.d.ts +15 -0
  145. package/dist/core/tools/url-guard.d.ts.map +1 -1
  146. package/dist/core/tools/url-guard.js +54 -14
  147. package/dist/core/tools/web-ports-std.d.ts.map +1 -1
  148. package/dist/core/tools/web-ports-std.js +5 -2
  149. package/dist/modes/print-mode.d.ts +3 -2
  150. package/dist/modes/print-mode.d.ts.map +1 -1
  151. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  152. package/dist/modes/rpc/rpc-mode.js +2 -2
  153. package/dist/modes/shared.d.ts +12 -0
  154. package/dist/modes/shared.d.ts.map +1 -1
  155. package/dist/modes/shared.js +23 -6
  156. package/dist/modes/tui/agent-status.d.ts +20 -0
  157. package/dist/modes/tui/agent-status.d.ts.map +1 -0
  158. package/dist/modes/tui/agent-status.js +35 -0
  159. package/dist/modes/tui/ask-panel.d.ts +166 -0
  160. package/dist/modes/tui/ask-panel.d.ts.map +1 -0
  161. package/dist/modes/tui/ask-panel.js +888 -0
  162. package/dist/modes/tui/pty-console.d.ts +3 -0
  163. package/dist/modes/tui/pty-console.d.ts.map +1 -1
  164. package/dist/modes/tui/pty-console.js +19 -0
  165. package/dist/modes/tui/settings-overlay.d.ts +19 -0
  166. package/dist/modes/tui/settings-overlay.d.ts.map +1 -1
  167. package/dist/modes/tui/settings-overlay.js +46 -10
  168. package/dist/modes/tui/tui-commands-session.d.ts.map +1 -1
  169. package/dist/modes/tui/tui-commands-session.js +20 -6
  170. package/dist/modes/tui/tui-commands.d.ts +44 -3
  171. package/dist/modes/tui/tui-commands.d.ts.map +1 -1
  172. package/dist/modes/tui/tui-commands.js +380 -6
  173. package/dist/modes/tui/tui-components.d.ts +10 -0
  174. package/dist/modes/tui/tui-components.d.ts.map +1 -1
  175. package/dist/modes/tui/tui-components.js +26 -0
  176. package/dist/modes/tui/tui-format.d.ts +53 -4
  177. package/dist/modes/tui/tui-format.d.ts.map +1 -1
  178. package/dist/modes/tui/tui-format.js +137 -42
  179. package/dist/modes/tui/tui-frame-provider.d.ts +11 -3
  180. package/dist/modes/tui/tui-frame-provider.d.ts.map +1 -1
  181. package/dist/modes/tui/tui-frame-provider.js +14 -5
  182. package/dist/modes/tui/tui-interactive.d.ts.map +1 -1
  183. package/dist/modes/tui/tui-interactive.js +14 -0
  184. package/dist/modes/tui/tui-io.d.ts.map +1 -1
  185. package/dist/modes/tui/tui-io.js +150 -55
  186. package/dist/modes/tui/tui-mode.d.ts.map +1 -1
  187. package/dist/modes/tui/tui-mode.js +428 -23
  188. package/dist/modes/tui/tui-overlays.d.ts +6 -10
  189. package/dist/modes/tui/tui-overlays.d.ts.map +1 -1
  190. package/dist/modes/tui/tui-overlays.js +0 -43
  191. package/dist/modes/tui/tui-render.d.ts +10 -0
  192. package/dist/modes/tui/tui-render.d.ts.map +1 -1
  193. package/dist/modes/tui/tui-render.js +73 -38
  194. package/dist/modes/tui/tui-seam.d.ts +28 -6
  195. package/dist/modes/tui/tui-seam.d.ts.map +1 -1
  196. package/dist/modes/tui/tui-slash.d.ts.map +1 -1
  197. package/dist/modes/tui/tui-slash.js +3 -1
  198. package/dist/modes/tui/tui-tool-render.d.ts +14 -1
  199. package/dist/modes/tui/tui-tool-render.d.ts.map +1 -1
  200. package/dist/modes/tui/tui-tool-render.js +158 -50
  201. package/dist/modes/tui/tui-transcript-reconciler.d.ts +4 -0
  202. package/dist/modes/tui/tui-transcript-reconciler.d.ts.map +1 -1
  203. package/dist/modes/tui/tui-transcript-reconciler.js +12 -2
  204. package/dist/modes/tui/view-state.d.ts.map +1 -1
  205. package/dist/modes/tui/view-state.js +4 -1
  206. package/dist/protocol/transport.d.ts +10 -0
  207. package/dist/protocol/transport.d.ts.map +1 -1
  208. package/dist/protocol/transport.js +1 -0
  209. package/package.json +11 -11
@@ -1,11 +1,12 @@
1
+ import { debugLog } from "@chengchenccc/agent-contract";
1
2
  import { ProviderError } from "@chengchenccc/ai";
2
3
  import { buildTextAssistantEntry, buildThinkingBlock, buildToolBatch, } from "./agent-loop-messages.js";
3
4
  import { executeTools, readBranchMessages, streamModelTurn, } from "./agent-loop-run.js";
4
- import { compactSession } from "./compaction.js";
5
+ import { compactSession, latestCompaction } from "./compaction.js";
5
6
  import { estimateContextTokens, isSilentContextOverflow, usageTotalTokens, } from "./context-estimate.js";
6
7
  import { buildLoopInput } from "./loop-input.js";
7
8
  import { renderLoopMeta } from "./prompt.js";
8
- import { buildTitleContext, generateTitle } from "./title.js";
9
+ import { buildTitleContext, generateTitleAndSummary } from "./title.js";
9
10
  import { pruneOldToolResults } from "./tool-pruning.js";
10
11
  /** Start the loop: bind runtime, resolve tools, persist the prompt, and
11
12
  * return the system prompt + first branch messages. */
@@ -118,6 +119,7 @@ async function finalizeLoop(ctx, stepState, step, runError) {
118
119
  }
119
120
  }
120
121
  let title;
122
+ let summary;
121
123
  // Auto-title retries on EVERY completed turn while the conversation is
122
124
  // still untitled (OMA_CONV_TITLED=1 marks it titled — the backend sets
123
125
  // it at spawn and re-checks on commit). The first turn may be low
@@ -129,7 +131,9 @@ async function finalizeLoop(ctx, stepState, step, runError) {
129
131
  const titleBranch = await readBranchMessages(opts.store, opts.sessionId);
130
132
  const titleCtx = buildTitleContext(titleBranch);
131
133
  if (titleCtx) {
132
- title = (await generateTitle(mutable.rt, titleCtx)) ?? undefined;
134
+ const generated = await generateTitleAndSummary(mutable.rt, titleCtx);
135
+ title = generated.title ?? undefined;
136
+ summary = generated.summary ?? undefined;
133
137
  }
134
138
  }
135
139
  await emit({ type: "agent_end", status: finalStatus });
@@ -147,12 +151,63 @@ async function finalizeLoop(ctx, stepState, step, runError) {
147
151
  usage: state.runUsage,
148
152
  error: runError,
149
153
  title,
154
+ summary,
150
155
  };
151
156
  }
152
157
  /** Run one model-turn retry loop (prune/compact/stream/handle). Returns
153
158
  * "break" when the turn completed, or a terminal result. */
154
- export async function runModelTurnLoop(ctx, stepState) {
159
+ async function runModelTurnLoop(ctx, stepState) {
155
160
  const { opts, emit, persist, state, callCtx, tokenEstimateCache, mutable } = ctx;
161
+ /** One proactive compaction recovery, shared by the threshold trigger and the
162
+ * two overflow triggers (silent + provider error).
163
+ *
164
+ * It compacts down to the TRIGGER (`limit * triggerRatio`), not to `limit`.
165
+ * Sizing the retained tail to `limit` while the trigger sits at
166
+ * `limit * triggerRatio` left a freshly compacted branch over the threshold
167
+ * by construction, so the next iteration compacted again — summarizing
168
+ * entries the previous compaction had just retained. Targeting the trigger
169
+ * brings the estimate under it, which is what quiets the gate.
170
+ *
171
+ * There is deliberately NO "already compacted" flag. One was tried and had
172
+ * to be re-armed from state that the loop cannot observe (the check right
173
+ * after a recovery already sees the new turn's growth), so it silently
174
+ * disabled proactive compaction for the rest of the Run. The no-progress
175
+ * case is handled where the decision belongs: compactSession returns an
176
+ * empty result when a cut would cover nothing new, so triggering on the
177
+ * budget alone can neither loop nor summarize twice for nothing. */
178
+ const runCompactionRecovery = async () => {
179
+ stepState.usageAnchor = null;
180
+ tokenEstimateCache.clear();
181
+ await emit({ type: "compaction_start" });
182
+ const contextBudget = opts.contextBudget;
183
+ try {
184
+ const result = await compactSession(opts.store, opts.sessionId, opts.summarize, mutable.controller?.signal, {
185
+ estimate: contextBudget.estimate,
186
+ // Down to the proactive trigger, so the loop settles instead of
187
+ // compacting again next iteration — but never above the WINDOW: a
188
+ // deployment can configure a trigger above it (tests do, to isolate an
189
+ // overflow), and an overflow recovery must still compact then.
190
+ limit: contextBudget.limit * Math.min(1, contextBudget.triggerRatio),
191
+ });
192
+ if (result.coveredIds.length > 0) {
193
+ stepState.messages = await readBranchMessages(opts.store, opts.sessionId);
194
+ }
195
+ }
196
+ catch (err) {
197
+ // Compaction is a best-effort optimization, never a run verdict: a
198
+ // failed summarizer call (transient network, provider hiccup) used to
199
+ // propagate to runLoop's outer catch and terminalize an otherwise
200
+ // healthy run as "failed". Log it and let the model call proceed — if
201
+ // the context really is over the window, the provider-overflow path
202
+ // retries once and then terminalizes with its own one-shot guard.
203
+ debugLog("oma", `compaction failed (run continues): ${err instanceof Error ? err.message : String(err)}`);
204
+ }
205
+ finally {
206
+ // Always settle the UI state: compaction_start pushed a status item
207
+ // that only compaction_end retires.
208
+ await emit({ type: "compaction_end" });
209
+ }
210
+ };
156
211
  // One step = at most one model call. Overflow recovery stays INSIDE
157
212
  while (true) {
158
213
  // Prune old tool-result content: a lighter
@@ -172,20 +227,30 @@ export async function runModelTurnLoop(ctx, stepState) {
172
227
  let callBoundaryId = null;
173
228
  if (opts.contextBudget) {
174
229
  const branch = await opts.store.readBranch(opts.sessionId);
175
- const msgEntries = branch.filter((e) => e.type === "message");
230
+ // Only LIVE entries: after a compaction the covered prefix is no longer
231
+ // sent, but the branch still holds it. Counting it (the pre-fix behavior)
232
+ // kept the estimate above the threshold right after a compaction, so the
233
+ // very next iteration fired a SECOND compaction that re-summarized
234
+ // already-covered entries and cut further into the retained tail.
235
+ const compaction = latestCompaction(branch);
236
+ const coveredIds = compaction?.coveredIds ?? null;
237
+ const msgEntries = branch.filter((e) => e.type === "message" && !(coveredIds?.has(e.entryId) ?? false));
238
+ // The summary replaces the covered prefix on the wire, so it costs
239
+ // tokens too (it is a CompactionEntry, not a MessageEntry) — but only
240
+ // while there is no anchor: an anchor's token count comes from a call
241
+ // whose prompt already contained this summary.
242
+ const summaryTokens = compaction && !stepState.usageAnchor
243
+ ? opts.contextBudget.estimate({ role: "user", text: compaction.summary })
244
+ : 0;
176
245
  callBoundaryId = msgEntries.at(-1)?.entryId ?? null;
177
- if (!stepState.thresholdCompacted) {
178
- const totalTokens = estimateContextTokens(msgEntries, stepState.usageAnchor, (e) => tokenEstimateCache.estimate(e.entryId, e.message, opts.contextBudget.estimate));
179
- const overThreshold = totalTokens > opts.contextBudget.limit * opts.contextBudget.triggerRatio;
180
- if (overThreshold) {
181
- stepState.thresholdCompacted = true;
182
- stepState.usageAnchor = null;
183
- tokenEstimateCache.clear();
184
- await emit({ type: "compaction_start" });
185
- await compactSession(opts.store, opts.sessionId, opts.summarize, mutable.controller?.signal, opts.contextBudget);
186
- await emit({ type: "compaction_end" });
187
- stepState.messages = await readBranchMessages(opts.store, opts.sessionId);
188
- }
246
+ const totalTokens = estimateContextTokens(msgEntries, stepState.usageAnchor, (e) => tokenEstimateCache.estimate(e.entryId, e.message, opts.contextBudget.estimate)) + summaryTokens;
247
+ const overThreshold = totalTokens > opts.contextBudget.limit * opts.contextBudget.triggerRatio;
248
+ if (overThreshold) {
249
+ // Fires whenever the live context exceeds the trigger. Re-firing is
250
+ // safe because compactSession no-ops when nothing new can be covered,
251
+ // so a context that cannot shrink does not buy a summarizer call per
252
+ // iteration — and a Run that keeps growing keeps compacting.
253
+ await runCompactionRecovery();
189
254
  }
190
255
  }
191
256
  // beforeModel hook.
@@ -222,12 +287,7 @@ export async function runModelTurnLoop(ctx, stepState) {
222
287
  isSilentContextOverflow(turn.usage, turn.stopReason, opts.contextBudget.limit);
223
288
  if (silentOverflow) {
224
289
  stepState.overflowCompacted = true;
225
- stepState.usageAnchor = null;
226
- tokenEstimateCache.clear();
227
- await emit({ type: "compaction_start" });
228
- await compactSession(opts.store, opts.sessionId, opts.summarize, mutable.controller?.signal, opts.contextBudget);
229
- await emit({ type: "compaction_end" });
230
- stepState.messages = await readBranchMessages(opts.store, opts.sessionId);
290
+ await runCompactionRecovery();
231
291
  continue;
232
292
  }
233
293
  // TTSR stream-rule hit: discard the partial turn (nothing was
@@ -368,12 +428,7 @@ export async function runModelTurnLoop(ctx, stepState) {
368
428
  // Overflow: one-shot compaction recovery inside the same turn.
369
429
  if (err instanceof ProviderError && err.kind === "overflow" && !stepState.overflowCompacted) {
370
430
  stepState.overflowCompacted = true;
371
- stepState.usageAnchor = null;
372
- tokenEstimateCache.clear();
373
- await emit({ type: "compaction_start" });
374
- await compactSession(opts.store, opts.sessionId, opts.summarize, mutable.controller?.signal, opts.contextBudget);
375
- await emit({ type: "compaction_end" });
376
- stepState.messages = await readBranchMessages(opts.store, opts.sessionId);
431
+ await runCompactionRecovery();
377
432
  continue; // retry model call in the SAME turn, no extra step
378
433
  }
379
434
  // Anything else is terminal: retryStream already applied its
@@ -408,7 +463,6 @@ export async function runLoop(ctx, codingInput, mode) {
408
463
  messages: initialMessages,
409
464
  forceContinues: 0,
410
465
  overflowCompacted: false,
411
- thresholdCompacted: false,
412
466
  usageAnchor: null,
413
467
  naturalStop: false,
414
468
  runError: undefined,
@@ -127,6 +127,10 @@ export interface OmaLoopResult {
127
127
  readonly error?: string;
128
128
  /** Auto-generated conversation title (first Run only; backend guards). */
129
129
  readonly title?: string;
130
+ /** One-sentence session summary from the same call as the title. The CLI
131
+ * persists it as the session's `summary` event, which the resume list
132
+ * shows next to the title; products (backend) ignore it. */
133
+ readonly summary?: string;
130
134
  }
131
135
  export interface OmaSession {
132
136
  readonly sessionId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-loop-types.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/agent-loop-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-loop-types.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/agent-loop-types.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import type { Message } from "@chengchenccc/message";
2
2
  import type { SessionStore } from "../store/session-store.js";
3
+ import type { CodingSessionEntry } from "../store/session-tree.js";
3
4
  export interface CompactionResult {
4
5
  readonly entryId: string;
5
6
  readonly coveredIds: readonly string[];
@@ -10,6 +11,14 @@ export interface CompactionBudget {
10
11
  estimate(message: Message): number;
11
12
  limit: number;
12
13
  }
14
+ /** The latest compaction in a branch, if any: its summary and the entry ids it
15
+ * covered. Single source for "which entries are still live" — the branch
16
+ * rebuild (agent-loop-run) and the threshold estimator (agent-loop-runner)
17
+ * must agree, or the estimator counts entries the model no longer receives. */
18
+ export declare function latestCompaction(entries: readonly CodingSessionEntry[]): {
19
+ summary: string;
20
+ coveredIds: ReadonlySet<string>;
21
+ } | null;
13
22
  /** Compact a session branch: summarize oldest entries, append CompactionEntry,
14
23
  * leave tail entries intact. Shared by threshold/manual/overflow triggers.
15
24
  *
@@ -1 +1 @@
1
- {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAG9D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;0EAC0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;CACf;AA6DD;;;;;;;6EAO6E;AAC7E,wBAAsB,cAAc,CAClC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,EACnF,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAsC3B"}
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;0EAC0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;CACf;AAkCD;;;gFAGgF;AAChF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACjC,GAAG,IAAI,CAQP;AAkCD;;;;;;;6EAO6E;AAC7E,wBAAsB,cAAc,CAClC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,EACnF,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAiD3B"}
@@ -24,6 +24,19 @@ function adjustCutForToolPairs(messages, cutIdx) {
24
24
  }
25
25
  return cut;
26
26
  }
27
+ /** The latest compaction in a branch, if any: its summary and the entry ids it
28
+ * covered. Single source for "which entries are still live" — the branch
29
+ * rebuild (agent-loop-run) and the threshold estimator (agent-loop-runner)
30
+ * must agree, or the estimator counts entries the model no longer receives. */
31
+ export function latestCompaction(entries) {
32
+ for (let i = entries.length - 1; i >= 0; i--) {
33
+ const e = entries[i];
34
+ if (e?.type === "compaction") {
35
+ return { summary: e.summary, coveredIds: new Set(e.coversEntryIds) };
36
+ }
37
+ }
38
+ return null;
39
+ }
27
40
  /** Compute the compaction cut point. Always returns a value: without a budget
28
41
  * it uses a message-count heuristic; with a budget it accumulates tokens from
29
42
  * the oldest messages until the retained tail fits under the limit. When the
@@ -43,6 +56,11 @@ function findCut(messages, budget) {
43
56
  remaining -= tokens[cutIdx];
44
57
  cutIdx++;
45
58
  }
59
+ // Never cover the newest message. The summary is prepended to whatever
60
+ // survives, so a cut that covers everything leaves the model with an empty
61
+ // conversation — not even the summary. One oversized entry (a huge
62
+ // tool_result is enough) drives cutIdx to messages.length without this.
63
+ cutIdx = Math.min(cutIdx, messages.length - 1);
46
64
  return { cutIdx, tokensBefore };
47
65
  }
48
66
  /** Compact a session branch: summarize oldest entries, append CompactionEntry,
@@ -68,6 +86,16 @@ export async function compactSession(store, sessionId, summarizer, signal, budge
68
86
  const coveredIds = coveredEntries.map((m) => m.entryId);
69
87
  const retainedIds = messages.slice(cutIdx).map((m) => m.entryId);
70
88
  const coveredMessages = coveredEntries.map((m) => m.message);
89
+ const alreadyCovered = latestCompaction(branch)?.coveredIds;
90
+ if (alreadyCovered && coveredIds.every((id) => alreadyCovered.has(id))) {
91
+ return { entryId: "", coveredIds: [] };
92
+ }
93
+ // The no-progress guard: a cut that covers nothing new (everything it would
94
+ // cover is already covered by an earlier compaction) buys nothing and would
95
+ // append an identical CompactionEntry on every loop iteration. This is what
96
+ // lets the loop trigger compaction purely on the budget — there is no
97
+ // "already compacted" flag to get stuck in, because compaction itself is the
98
+ // thing that decides whether it can still do useful work.
71
99
  const summary = await summarizer(coveredMessages, signal);
72
100
  // If aborted during summarization, do not write a CompactionEntry.
73
101
  if (signal?.aborted)
@@ -1,6 +1,37 @@
1
- /** Context-token estimation helpers absorbed from oh-my-pi
2
- * (packages/agent/src/harness/compaction/compaction.ts):
3
- * usage-anchored estimation + silent-overflow detection. */
1
+ import type { Message } from "@chengchenccc/message";
2
+ /** Token estimate of ONE text run, CJK-aware.
3
+ *
4
+ * chars/4 is the English/code proxy (≈4 chars/token). For CJK it
5
+ * UNDER-counts 2-4× (Chinese ≈ 1-1.5 chars/token — deepseek's own docs put
6
+ * it at ~1.5), and under-counting is the dangerous direction for a compaction
7
+ * trigger: the estimate says "under budget" while the provider is already
8
+ * overflowing, so the recovery's own cut math no-ops and the retry 400s again
9
+ * (one-shot guard) — a terminally wedged run. CJK is therefore weighted at
10
+ * 1.5 chars/token. The usage anchor remains the real corrector while a run
11
+ * streams; this only needs to be right-side-of-the-line after a resume. */
12
+ export declare function estimateTextTokens(text: string): number;
13
+ /** Approximate token cost of ONE message as it will be SENT to the provider.
14
+ *
15
+ * The single estimator for both the compaction budget and tool-result pruning:
16
+ * two divergent copies meant the trigger and the pruning window measured
17
+ * different quantities (one counted `text` AND `blocks`, which for a tool
18
+ * message is the same payload twice), so pruning's "saved tokens" were not
19
+ * comparable to the budget they were subtracted from.
20
+ *
21
+ * What is counted mirrors the wire mapping in
22
+ * packages/ai/src/providers/anthropic-messages.ts:
23
+ * - a `tool` message sends ONLY its tool_result blocks (`text` is the UI's
24
+ * clean copy), so counting `text` as well would double it;
25
+ * - every other role sends `text` as a trailing text block unless a text block
26
+ * already carries it;
27
+ * - image payloads are ignored: providers price an image by its PIXEL
28
+ * dimensions (~width*height/750 tokens), not by the base64 length, so
29
+ * char/4 over the encoded bytes would over-count it by a size-dependent
30
+ * factor and compact far too early.
31
+ *
32
+ * Swap for a real tokenizer by replacing estimateTextTokens —
33
+ * `ContextBudget.estimate` stays the extension point. */
34
+ export declare function estimateMessageTokens(message: Message): number;
4
35
  /** Per-turn usage quartet (concrete, unlike the all-optional run Usage). */
5
36
  export interface TurnUsage {
6
37
  readonly inputTokens: number;
@@ -12,7 +43,9 @@ export interface TurnUsage {
12
43
  * (input + output + cache legs) and is authoritative for every entry
13
44
  * persisted before `afterEntryId`; only entries AFTER it fall back to
14
45
  * per-message estimation (chars/4). Falls back wholesale when the anchor
15
- * entry no longer exists (post-compaction branch, resumed runs).
46
+ * entry itself no longer exists — the loop clears the anchor when it
47
+ * compacts and re-anchors on the next call, so today that is reachable only
48
+ * for an out-of-band compaction of the same branch.
16
49
  *
17
50
  * ponytail: the anchor is in-memory per Run — pi persists usage on
18
51
  * assistant messages and re-anchors after resume. Persist it onto the
@@ -1 +1 @@
1
- {"version":3,"file":"context-estimate.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/context-estimate.ts"],"names":[],"mappings":"AAAA;;4DAE4D;AAE5D,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;sDAQsD;AACtD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAEzD;AAED;;;0CAG0C;AAC1C,wBAAgB,qBAAqB,CAAC,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EACjE,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,aAAa,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,GAClC,MAAM,CAOR;AAED;;;;wDAIwD;AACxD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAC5F,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,YAAY,EAAE,MAAM,GACnB,OAAO,CAQT"}
1
+ {"version":3,"file":"context-estimate.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/context-estimate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAgBrD;;;;;;;;;4EAS4E;AAC5E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED;;;;;;;;;;;;;;;;;;;;0DAoB0D;AAC1D,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAuB9D;AAED,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;sDAUsD;AACtD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAEzD;AAED;;;0CAG0C;AAC1C,wBAAgB,qBAAqB,CAAC,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EACjE,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,aAAa,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,GAClC,MAAM,CAOR;AAED;;;;wDAIwD;AACxD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAC5F,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,YAAY,EAAE,MAAM,GACnB,OAAO,CAQT"}
@@ -1,6 +1,76 @@
1
1
  /** Context-token estimation helpers absorbed from oh-my-pi
2
2
  * (packages/agent/src/harness/compaction/compaction.ts):
3
3
  * usage-anchored estimation + silent-overflow detection. */
4
+ /** Per-message framing overhead (role tag, separators — matches Anthropic's
5
+ * documented ~4 tokens/message). */
6
+ const MESSAGE_FRAMING_TOKENS = 4;
7
+ /** CJK code points (BMP): unified + ext-A + compat ideographs, kana, hangul,
8
+ * CJK punctuation and fullwidth forms. Astral-plane ideographs (ext B+) are
9
+ * rare in chat and count via their 2 UTF-16 units — the wrong direction is
10
+ * under-counting, and 2 units of "other" at /4 is still a lower bound. */
11
+ const CJK_RE = /[\u3000-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\uac00-\ud7af\uff00-\uffef]/g;
12
+ /** Token estimate of ONE text run, CJK-aware.
13
+ *
14
+ * chars/4 is the English/code proxy (≈4 chars/token). For CJK it
15
+ * UNDER-counts 2-4× (Chinese ≈ 1-1.5 chars/token — deepseek's own docs put
16
+ * it at ~1.5), and under-counting is the dangerous direction for a compaction
17
+ * trigger: the estimate says "under budget" while the provider is already
18
+ * overflowing, so the recovery's own cut math no-ops and the retry 400s again
19
+ * (one-shot guard) — a terminally wedged run. CJK is therefore weighted at
20
+ * 1.5 chars/token. The usage anchor remains the real corrector while a run
21
+ * streams; this only needs to be right-side-of-the-line after a resume. */
22
+ export function estimateTextTokens(text) {
23
+ const cjk = (text.match(CJK_RE) ?? []).length;
24
+ return (cjk * 2) / 3 + (text.length - cjk) / 4;
25
+ }
26
+ /** Approximate token cost of ONE message as it will be SENT to the provider.
27
+ *
28
+ * The single estimator for both the compaction budget and tool-result pruning:
29
+ * two divergent copies meant the trigger and the pruning window measured
30
+ * different quantities (one counted `text` AND `blocks`, which for a tool
31
+ * message is the same payload twice), so pruning's "saved tokens" were not
32
+ * comparable to the budget they were subtracted from.
33
+ *
34
+ * What is counted mirrors the wire mapping in
35
+ * packages/ai/src/providers/anthropic-messages.ts:
36
+ * - a `tool` message sends ONLY its tool_result blocks (`text` is the UI's
37
+ * clean copy), so counting `text` as well would double it;
38
+ * - every other role sends `text` as a trailing text block unless a text block
39
+ * already carries it;
40
+ * - image payloads are ignored: providers price an image by its PIXEL
41
+ * dimensions (~width*height/750 tokens), not by the base64 length, so
42
+ * char/4 over the encoded bytes would over-count it by a size-dependent
43
+ * factor and compact far too early.
44
+ *
45
+ * Swap for a real tokenizer by replacing estimateTextTokens —
46
+ * `ContextBudget.estimate` stays the extension point. */
47
+ export function estimateMessageTokens(message) {
48
+ const blocks = message.blocks ?? [];
49
+ if (blocks.length === 0) {
50
+ return Math.ceil(estimateTextTokens(message.text ?? "")) + MESSAGE_FRAMING_TOKENS;
51
+ }
52
+ let tokens = 0;
53
+ let carriesText = false;
54
+ for (const b of blocks) {
55
+ if (b.type === "text") {
56
+ tokens += estimateTextTokens(b.text);
57
+ carriesText = true;
58
+ }
59
+ else if (b.type === "thinking") {
60
+ tokens += estimateTextTokens(b.text + (b.signature ?? ""));
61
+ }
62
+ else if (b.type === "tool_use") {
63
+ tokens += estimateTextTokens(JSON.stringify(b.input));
64
+ }
65
+ else if (b.type === "tool_result") {
66
+ tokens += estimateTextTokens(b.content);
67
+ }
68
+ }
69
+ if (message.role !== "tool" && !carriesText && message.text) {
70
+ tokens += estimateTextTokens(message.text);
71
+ }
72
+ return Math.ceil(tokens) + MESSAGE_FRAMING_TOKENS;
73
+ }
4
74
  export function usageTotalTokens(usage) {
5
75
  return usage.inputTokens + usage.outputTokens + usage.cacheReadTokens + usage.cacheWriteTokens;
6
76
  }
@@ -58,14 +58,21 @@ export interface CreateOmaRuntimeOptions {
58
58
  * inherits another session's list. Absent = the legacy workspace-global
59
59
  * todo.json (product shape). */
60
60
  todoScope?: string;
61
+ /** Plan mode: while set, write/edit accept exactly this one path (the plan
62
+ * document). The mode layer decides WHEN it applies; the runtime only
63
+ * enforces the path rule. */
64
+ planMode?: {
65
+ planPath: string;
66
+ };
61
67
  /** Assembled plugin code components (from assemblePluginRuntime, mode
62
68
  * layer). The runtime mounts them; it never reads the registry. */
63
69
  pluginComponents?: {
64
70
  plugins: readonly Plugin[];
65
71
  mcpServers?: readonly PluginMcpConfig[];
66
72
  };
67
- /** Frozen Run permissionMode; "deny" drops plugin code components. */
68
- permissionMode?: "ask" | "auto" | "deny";
73
+ /** Frozen Run permissionMode; "deny" drops plugin code components.
74
+ * "yolo" = ungated at the gate + OS bash sandbox forced when available. */
75
+ permissionMode?: "ask" | "auto" | "deny" | "yolo";
69
76
  /** Standalone modes: gate the repo-controlled workspace .mcp.json behind
70
77
  * the trust record (spec follow-up #3). */
71
78
  gateWorkspaceMcp?: boolean;
@@ -82,12 +89,25 @@ export interface CreateOmaRuntimeOptions {
82
89
  * survive follow-up Runs. */
83
90
  registry?: CoordinationRegistry;
84
91
  /** M-bash: interactive pty console runner (TUI overlay). */
85
- bashPtyConsole?: (command: string, cwd: string, env: Record<string, string>) => Promise<{
92
+ bashPtyConsole?: (command: string, cwd: string, env: Record<string, string>, signal?: AbortSignal) => Promise<{
86
93
  exitCode: number | null;
87
94
  tail: string;
88
95
  killed: boolean;
89
96
  }>;
90
97
  }
98
+ /** One compaction produced by a Run.
99
+ *
100
+ * `replacesEarlierMessages` is true only when the summary describes EVERY
101
+ * message live in the run's branch — the one condition under which a durable
102
+ * transcript can fold it losslessly. It is deliberately not a count: coverage
103
+ * is measured over the branch, while the session file indexes its own message
104
+ * events, and the two spaces differ (branch-only entries such as
105
+ * `product_history`/`meta` never reach the file). A count in the wrong space
106
+ * silently drops messages; a flag cannot. */
107
+ export interface CompactionSummary {
108
+ readonly summary: string;
109
+ readonly replacesEarlierMessages: boolean;
110
+ }
91
111
  export interface OmaRuntime {
92
112
  /** Start the Run's loop. Returns the segment whose outcome is the Run's
93
113
  * ONLY terminal result. A Runtime accepts exactly one run(). */
@@ -99,8 +119,10 @@ export interface OmaRuntime {
99
119
  stop(): Promise<void>;
100
120
  /** Close MCP clients and the in-memory Store. Call after the run settles. */
101
121
  close(): Promise<void>;
102
- /** Compaction summaries from this run's loop; read before close(). */
103
- compactions(): Promise<string[]>;
122
+ /** Compaction summaries from this run's loop; read before close(). Each
123
+ * carries whether it describes the whole branch, which is what the durable
124
+ * session file needs to fold safely (see loadSessionMessages). */
125
+ compactions(): Promise<readonly CompactionSummary[]>;
104
126
  /** Estimated context footprint of the run's branch under the run model's
105
127
  * window — the same estimate/limit pair the compactor decides on. Read
106
128
  * before close(). */
@@ -1 +1 @@
1
- {"version":3,"file":"create-runtime.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/create-runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-runtime.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/create-runtime.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { mapRunEvent } from "../../protocol/index.js";
2
2
  import { extractAutonomousMemory } from "../memory/autonomous-memory.js";
3
3
  import { getVectorMemory } from "../memory/vector-memory.js";
4
+ import { latestCompaction } from "./compaction.js";
4
5
  import { assembleRunRuntime } from "./run-runtime.js";
5
6
  /** One Runtime = one Run. The loop runs directly in-process; steer injects
6
7
  * into the live loop; stop aborts it; close tears down MCP clients and the
@@ -40,6 +41,7 @@ function mapLoopResult(result) {
40
41
  status: "completed",
41
42
  ...(result.usage ? { usage: result.usage } : {}),
42
43
  ...(result.title ? { title: result.title } : {}),
44
+ ...(result.summary ? { summary: result.summary } : {}),
43
45
  }, result.messages);
44
46
  }
45
47
  if (result.status === "stopped") {
@@ -58,6 +60,7 @@ export async function createOmaRuntime(options) {
58
60
  skillRoots: options.skillRoots,
59
61
  bashPtyConsole: options.bashPtyConsole,
60
62
  ...(options.onPersistMessages ? { onPersistMessages: options.onPersistMessages } : {}),
63
+ ...(options.planMode ? { planMode: options.planMode } : {}),
61
64
  ...(options.pluginComponents?.plugins.length
62
65
  ? { codePlugins: options.pluginComponents.plugins }
63
66
  : {}),
@@ -196,6 +199,8 @@ export async function createOmaRuntime(options) {
196
199
  if (entry.type === "compaction" && entry.summary)
197
200
  compactions.push(entry.summary);
198
201
  }
202
+ // (The memory transcript wants the text only; the durable
203
+ // session file is the consumer that needs the coverage boundary.)
199
204
  // FIRE-AND-FORGET: awaiting here blocks the outcome (and the
200
205
  // TUI busy state) on a second model call the user cannot abort.
201
206
  memoryLearning = extractAutonomousMemory({
@@ -266,10 +271,19 @@ export async function createOmaRuntime(options) {
266
271
  * run never compacted). Read the store BEFORE close(). */
267
272
  async compactions() {
268
273
  const branch = await rt.store.readBranch(options.runId);
274
+ const liveEntries = branch.filter((e) => e.type === "message").map((e) => e.entryId);
269
275
  const summaries = [];
270
276
  for (const entry of branch) {
271
- if (entry.type === "compaction" && entry.summary)
272
- summaries.push(entry.summary);
277
+ if (entry.type === "compaction" && entry.summary) {
278
+ const covered = new Set(entry.coversEntryIds);
279
+ summaries.push({
280
+ summary: entry.summary,
281
+ // "Describes the branch" is checked against the branch AS IT IS
282
+ // NOW: a compaction that ran mid-run has messages persisted after
283
+ // it, which it cannot describe, so it must not fold them away.
284
+ replacesEarlierMessages: liveEntries.length > 0 && liveEntries.every((id) => covered.has(id)),
285
+ });
286
+ }
273
287
  }
274
288
  return summaries;
275
289
  },
@@ -280,10 +294,16 @@ export async function createOmaRuntime(options) {
280
294
  if (!budget)
281
295
  return undefined;
282
296
  const branch = await rt.store.readBranch(options.runId);
297
+ // Live entries only, like the loop's threshold check: counting the
298
+ // covered prefix would leave the meter above the window right after a
299
+ // compaction that just brought the context down.
300
+ const coveredIds = latestCompaction(branch)?.coveredIds ?? null;
283
301
  let estimatedTokens = 0;
284
302
  for (const entry of branch) {
285
303
  if (entry.type !== "message")
286
304
  continue;
305
+ if (coveredIds?.has(entry.entryId))
306
+ continue;
287
307
  estimatedTokens += budget.estimate(entry.message);
288
308
  }
289
309
  return { estimatedTokens, limit: budget.limit };
@@ -1 +1 @@
1
- {"version":3,"file":"permission-classifier.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/permission-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErE;;;;;2CAK2C;AAE3C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;8EAE8E;AAC9E,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAe,GAC9D,MAAM,GAAG,SAAS,CAIpB;AAED,eAAO,MAAM,6BAA6B,QAAS,CAAC;AAEpD,yEAAyE;AACzE,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAe,GAC9D,MAAM,CAIR;AAED;;yDAEyD;AACzD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,OAAO,EAAE,CAyBX;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CA0B5D;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,MAAM,CAAC,EAAE,WAAW,EACpB,eAAe,CAAC,EAAE,MAAM,KACrB,aAAa,CAAC,cAAc,CAAC,CAAC;AAEnC;2EAC2E;AAC3E,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;wCACoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgB7B;AA4BD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAgB3D"}
1
+ {"version":3,"file":"permission-classifier.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/permission-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErE;;;;;2CAK2C;AAE3C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;8EAE8E;AAC9E,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAe,GAC9D,MAAM,GAAG,SAAS,CAIpB;AAED,eAAO,MAAM,6BAA6B,QAAS,CAAC;AAEpD,yEAAyE;AACzE,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAe,GAC9D,MAAM,CAIR;AAED;;yDAEyD;AACzD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,OAAO,EAAE,CAyBX;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CA0B5D;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,MAAM,CAAC,EAAE,WAAW,EACpB,eAAe,CAAC,EAAE,MAAM,KACrB,aAAa,CAAC,cAAc,CAAC,CAAC;AAEnC;2EAC2E;AAC3E,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;wCACoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgB7B;AAiFD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAoC3D"}