@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.
- package/README.md +11 -6
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +9 -2
- package/dist/cli/gateway-commands.d.ts.map +1 -1
- package/dist/cli/gateway-commands.js +35 -5
- package/dist/cli/initial-input.d.ts +3 -2
- package/dist/cli/initial-input.d.ts.map +1 -1
- package/dist/core/coordination/registry.d.ts +11 -0
- package/dist/core/coordination/registry.d.ts.map +1 -1
- package/dist/core/coordination/registry.js +23 -0
- package/dist/core/gateway/artifact.d.ts +0 -1
- package/dist/core/gateway/artifact.d.ts.map +1 -1
- package/dist/core/gateway/artifact.js +1 -1
- package/dist/core/goals/index.d.ts +8 -0
- package/dist/core/goals/index.d.ts.map +1 -0
- package/dist/core/goals/index.js +7 -0
- package/dist/core/goals/runtime.d.ts +112 -0
- package/dist/core/goals/runtime.d.ts.map +1 -0
- package/dist/core/goals/runtime.js +241 -0
- package/dist/core/goals/state.d.ts +82 -0
- package/dist/core/goals/state.d.ts.map +1 -0
- package/dist/core/goals/state.js +225 -0
- package/dist/core/goals/tool.d.ts +10 -0
- package/dist/core/goals/tool.d.ts.map +1 -0
- package/dist/core/goals/tool.js +87 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -3
- package/dist/core/loops/condition.d.ts +57 -0
- package/dist/core/loops/condition.d.ts.map +1 -0
- package/dist/core/loops/condition.js +153 -0
- package/dist/core/loops/index.d.ts +9 -0
- package/dist/core/loops/index.d.ts.map +1 -0
- package/dist/core/loops/index.js +8 -0
- package/dist/core/loops/limits.d.ts +43 -0
- package/dist/core/loops/limits.d.ts.map +1 -0
- package/dist/core/loops/limits.js +219 -0
- package/dist/core/loops/ralph.d.ts +37 -0
- package/dist/core/loops/ralph.d.ts.map +1 -0
- package/dist/core/loops/ralph.js +72 -0
- package/dist/core/loops/runtime.d.ts +95 -0
- package/dist/core/loops/runtime.d.ts.map +1 -0
- package/dist/core/loops/runtime.js +222 -0
- package/dist/core/memory/managed-skills.d.ts +0 -11
- package/dist/core/memory/managed-skills.d.ts.map +1 -1
- package/dist/core/memory/managed-skills.js +2 -2
- package/dist/core/memory/vector-store.d.ts +0 -1
- package/dist/core/memory/vector-store.d.ts.map +1 -1
- package/dist/core/memory/vector-store.js +0 -3
- package/dist/core/plans/index.d.ts +7 -0
- package/dist/core/plans/index.d.ts.map +1 -0
- package/dist/core/plans/index.js +6 -0
- package/dist/core/plans/prompts.d.ts +20 -0
- package/dist/core/plans/prompts.d.ts.map +1 -0
- package/dist/core/plans/prompts.js +72 -0
- package/dist/core/plans/runtime.d.ts +89 -0
- package/dist/core/plans/runtime.d.ts.map +1 -0
- package/dist/core/plans/runtime.js +170 -0
- package/dist/core/plans/state.d.ts +55 -0
- package/dist/core/plans/state.d.ts.map +1 -0
- package/dist/core/plans/state.js +88 -0
- package/dist/core/runtime/agent-loop-messages.d.ts +6 -0
- package/dist/core/runtime/agent-loop-messages.d.ts.map +1 -1
- package/dist/core/runtime/agent-loop-messages.js +40 -15
- package/dist/core/runtime/agent-loop-run.d.ts.map +1 -1
- package/dist/core/runtime/agent-loop-run.js +18 -27
- package/dist/core/runtime/agent-loop-runner.d.ts +1 -23
- package/dist/core/runtime/agent-loop-runner.d.ts.map +1 -1
- package/dist/core/runtime/agent-loop-runner.js +84 -30
- package/dist/core/runtime/agent-loop-types.d.ts +4 -0
- package/dist/core/runtime/agent-loop-types.d.ts.map +1 -1
- package/dist/core/runtime/compaction.d.ts +9 -0
- package/dist/core/runtime/compaction.d.ts.map +1 -1
- package/dist/core/runtime/compaction.js +28 -0
- package/dist/core/runtime/context-estimate.d.ts +37 -4
- package/dist/core/runtime/context-estimate.d.ts.map +1 -1
- package/dist/core/runtime/context-estimate.js +70 -0
- package/dist/core/runtime/create-runtime.d.ts +27 -5
- package/dist/core/runtime/create-runtime.d.ts.map +1 -1
- package/dist/core/runtime/create-runtime.js +22 -2
- package/dist/core/runtime/permission-classifier.d.ts.map +1 -1
- package/dist/core/runtime/permission-classifier.js +83 -12
- package/dist/core/runtime/plugin.d.ts +7 -0
- package/dist/core/runtime/plugin.d.ts.map +1 -1
- package/dist/core/runtime/plugin.js +13 -0
- package/dist/core/runtime/process-tree.d.ts +0 -9
- package/dist/core/runtime/process-tree.d.ts.map +1 -1
- package/dist/core/runtime/process-tree.js +1 -1
- package/dist/core/runtime/run-runtime.d.ts.map +1 -1
- package/dist/core/runtime/run-runtime.js +88 -49
- package/dist/core/runtime/runtime-catalog.d.ts +0 -4
- package/dist/core/runtime/runtime-catalog.d.ts.map +1 -1
- package/dist/core/runtime/runtime-catalog.js +1 -1
- package/dist/core/runtime/stream-rules.d.ts +9 -2
- package/dist/core/runtime/stream-rules.d.ts.map +1 -1
- package/dist/core/runtime/stream-rules.js +19 -5
- package/dist/core/runtime/title.d.ts +13 -1
- package/dist/core/runtime/title.d.ts.map +1 -1
- package/dist/core/runtime/title.js +51 -17
- package/dist/core/runtime/tool-pruning.d.ts.map +1 -1
- package/dist/core/runtime/tool-pruning.js +8 -16
- package/dist/core/session/session-file.d.ts +91 -5
- package/dist/core/session/session-file.d.ts.map +1 -1
- package/dist/core/session/session-file.js +206 -24
- package/dist/core/session/session-loop.d.ts +3 -1
- package/dist/core/session/session-loop.d.ts.map +1 -1
- package/dist/core/session/session-loop.js +8 -4
- package/dist/core/settings/project-settings.d.ts +63 -9
- package/dist/core/settings/project-settings.d.ts.map +1 -1
- package/dist/core/settings/project-settings.js +43 -2
- package/dist/core/settings/workspace-context.js +4 -4
- package/dist/core/store/in-memory-session-store.d.ts.map +1 -1
- package/dist/core/store/in-memory-session-store.js +3 -2
- package/dist/core/store/session-store.contract.test-helper.d.ts +7 -5
- package/dist/core/store/session-store.contract.test-helper.d.ts.map +1 -1
- package/dist/core/store/session-store.contract.test-helper.js +7 -5
- package/dist/core/store/session-store.d.ts +4 -2
- package/dist/core/store/session-store.d.ts.map +1 -1
- package/dist/core/store/session-store.js +4 -2
- package/dist/core/tools/ask-question.d.ts.map +1 -1
- package/dist/core/tools/ask-question.js +51 -5
- package/dist/core/tools/bash-pty.d.ts +13 -4
- package/dist/core/tools/bash-pty.d.ts.map +1 -1
- package/dist/core/tools/bash-pty.js +15 -8
- package/dist/core/tools/bash-sandbox.d.ts +1 -1
- package/dist/core/tools/bash.d.ts +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +18 -8
- package/dist/core/tools/browser.d.ts +54 -0
- package/dist/core/tools/browser.d.ts.map +1 -1
- package/dist/core/tools/browser.js +138 -1
- package/dist/core/tools/file-fingerprint.d.ts +24 -0
- package/dist/core/tools/file-fingerprint.d.ts.map +1 -0
- package/dist/core/tools/file-fingerprint.js +61 -0
- package/dist/core/tools/file-tools.d.ts +26 -0
- package/dist/core/tools/file-tools.d.ts.map +1 -1
- package/dist/core/tools/file-tools.js +113 -17
- package/dist/core/tools/index.d.ts +2 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -0
- package/dist/core/tools/mcp-mount.d.ts +1 -1
- package/dist/core/tools/mcp-mount.d.ts.map +1 -1
- package/dist/core/tools/mcp-mount.js +72 -26
- package/dist/core/tools/url-guard.d.ts +15 -0
- package/dist/core/tools/url-guard.d.ts.map +1 -1
- package/dist/core/tools/url-guard.js +54 -14
- package/dist/core/tools/web-ports-std.d.ts.map +1 -1
- package/dist/core/tools/web-ports-std.js +5 -2
- package/dist/modes/print-mode.d.ts +3 -2
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -2
- package/dist/modes/shared.d.ts +12 -0
- package/dist/modes/shared.d.ts.map +1 -1
- package/dist/modes/shared.js +23 -6
- package/dist/modes/tui/agent-status.d.ts +20 -0
- package/dist/modes/tui/agent-status.d.ts.map +1 -0
- package/dist/modes/tui/agent-status.js +35 -0
- package/dist/modes/tui/ask-panel.d.ts +166 -0
- package/dist/modes/tui/ask-panel.d.ts.map +1 -0
- package/dist/modes/tui/ask-panel.js +888 -0
- package/dist/modes/tui/pty-console.d.ts +3 -0
- package/dist/modes/tui/pty-console.d.ts.map +1 -1
- package/dist/modes/tui/pty-console.js +19 -0
- package/dist/modes/tui/settings-overlay.d.ts +19 -0
- package/dist/modes/tui/settings-overlay.d.ts.map +1 -1
- package/dist/modes/tui/settings-overlay.js +46 -10
- package/dist/modes/tui/tui-commands-session.d.ts.map +1 -1
- package/dist/modes/tui/tui-commands-session.js +20 -6
- package/dist/modes/tui/tui-commands.d.ts +44 -3
- package/dist/modes/tui/tui-commands.d.ts.map +1 -1
- package/dist/modes/tui/tui-commands.js +380 -6
- package/dist/modes/tui/tui-components.d.ts +10 -0
- package/dist/modes/tui/tui-components.d.ts.map +1 -1
- package/dist/modes/tui/tui-components.js +26 -0
- package/dist/modes/tui/tui-format.d.ts +53 -4
- package/dist/modes/tui/tui-format.d.ts.map +1 -1
- package/dist/modes/tui/tui-format.js +137 -42
- package/dist/modes/tui/tui-frame-provider.d.ts +11 -3
- package/dist/modes/tui/tui-frame-provider.d.ts.map +1 -1
- package/dist/modes/tui/tui-frame-provider.js +14 -5
- package/dist/modes/tui/tui-interactive.d.ts.map +1 -1
- package/dist/modes/tui/tui-interactive.js +14 -0
- package/dist/modes/tui/tui-io.d.ts.map +1 -1
- package/dist/modes/tui/tui-io.js +150 -55
- package/dist/modes/tui/tui-mode.d.ts.map +1 -1
- package/dist/modes/tui/tui-mode.js +428 -23
- package/dist/modes/tui/tui-overlays.d.ts +6 -10
- package/dist/modes/tui/tui-overlays.d.ts.map +1 -1
- package/dist/modes/tui/tui-overlays.js +0 -43
- package/dist/modes/tui/tui-render.d.ts +10 -0
- package/dist/modes/tui/tui-render.d.ts.map +1 -1
- package/dist/modes/tui/tui-render.js +73 -38
- package/dist/modes/tui/tui-seam.d.ts +28 -6
- package/dist/modes/tui/tui-seam.d.ts.map +1 -1
- package/dist/modes/tui/tui-slash.d.ts.map +1 -1
- package/dist/modes/tui/tui-slash.js +3 -1
- package/dist/modes/tui/tui-tool-render.d.ts +14 -1
- package/dist/modes/tui/tui-tool-render.d.ts.map +1 -1
- package/dist/modes/tui/tui-tool-render.js +158 -50
- package/dist/modes/tui/tui-transcript-reconciler.d.ts +4 -0
- package/dist/modes/tui/tui-transcript-reconciler.d.ts.map +1 -1
- package/dist/modes/tui/tui-transcript-reconciler.js +12 -2
- package/dist/modes/tui/view-state.d.ts.map +1 -1
- package/dist/modes/tui/view-state.js +4 -1
- package/dist/protocol/transport.d.ts +10 -0
- package/dist/protocol/transport.d.ts.map +1 -1
- package/dist/protocol/transport.js +1 -0
- 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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EAEf,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"create-runtime.d.ts","sourceRoot":"","sources":["../../../src/core/runtime/create-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EAEf,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;sEAGsE;AACtE,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd;8DAC0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;4CACwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,WAAW,GAAG,YAAY,CAAC;IAC5C,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;qEAEiE;IACjE,iBAAiB,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACpD;;mDAE+C;IAC/C,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC/C;;uDAEmD;IACnD,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,KAAK,IAAI,CAAC;IAC3D,6DAA6D;IAC7D,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;qDACiD;IACjD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;qEAGiE;IACjE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;uDAImD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;qCAGiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;kCAE8B;IAC9B,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC;wEACoE;IACpE,gBAAgB,CAAC,EAAE;QACjB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;QAC3B,UAAU,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;KACzC,CAAC;IACF;gFAC4E;IAC5E,cAAc,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAClD;gDAC4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0DAA0D;IAC1D,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC5E;+DAC2D;IAC3D,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;kCAG8B;IAC9B,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,4DAA4D;IAC5D,cAAc,CAAC,EAAE,CACf,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,MAAM,CAAC,EAAE,WAAW,KACjB,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC1E;AAUD;;;;;;;;8CAQ8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAC;CAC3C;AAED,MAAM,WAAW,UAAU;IACzB;qEACiE;IACjE,GAAG,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,4EAA4E;IAC5E,KAAK,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD;yEACqE;IACrE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,6EAA6E;IAC7E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB;;uEAEmE;IACnE,WAAW,IAAI,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAAC;IACrD;;0BAEsB;IACtB,YAAY,IAAI,OAAO,CAAC;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IAChF;;;oBAGgB;IAChB,cAAc,IAAI,OAAO,CAAC,iBAAiB,CAAC,GAAG,SAAS,CAAC;CAC1D;AAwDD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,UAAU,CAAC,CAkR5F"}
|
|
@@ -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
|
-
|
|
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;
|
|
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"}
|