mindweave 3.4.1 → 3.4.2
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 +26 -3
- package/dist/cli/App.js +52 -8
- package/dist/cli/App.js.map +1 -1
- package/dist/cli/commands.js +1 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/components/ToolLine.js +5 -3
- package/dist/cli/components/ToolLine.js.map +1 -1
- package/dist/cli/components/WorkGroup.js +82 -64
- package/dist/cli/components/WorkGroup.js.map +1 -1
- package/dist/cli/startupArgs.js +24 -4
- package/dist/cli/startupArgs.js.map +1 -1
- package/dist/cli/transcript.js +14 -0
- package/dist/cli/transcript.js.map +1 -1
- package/dist/cli/workLines.js +40 -0
- package/dist/cli/workLines.js.map +1 -1
- package/dist/core/turnRunner.js +35 -23
- package/dist/core/turnRunner.js.map +1 -1
- package/dist/dynamo/contextWindow.js +28 -36
- package/dist/dynamo/contextWindow.js.map +1 -1
- package/dist/dynamo/engine.js +51 -9
- package/dist/dynamo/engine.js.map +1 -1
- package/dist/dynamo/guard.js +1 -1
- package/dist/dynamo/guard.js.map +1 -1
- package/dist/dynamo/prompt.js +1 -1
- package/dist/headless/args.js +82 -0
- package/dist/headless/args.js.map +1 -0
- package/dist/headless/main.js +87 -0
- package/dist/headless/main.js.map +1 -0
- package/dist/headless/output.js +150 -0
- package/dist/headless/output.js.map +1 -0
- package/dist/headless/run.js +188 -0
- package/dist/headless/run.js.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/main.js +5 -0
- package/dist/main.js.map +1 -1
- package/dist/memory/compaction.js +94 -2
- package/dist/memory/compaction.js.map +1 -1
- package/dist/memory/rewind.js +10 -6
- package/dist/memory/rewind.js.map +1 -1
- package/dist/memory/session.js +2 -2
- package/dist/memory/session.js.map +1 -1
- package/dist/memory/sessionMemory.js +270 -69
- package/dist/memory/sessionMemory.js.map +1 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/project/context.js +34 -6
- package/dist/project/context.js.map +1 -1
- package/dist/tools/coauthor.js +154 -0
- package/dist/tools/coauthor.js.map +1 -0
- package/dist/tools/codeIntel.js +38 -10
- package/dist/tools/codeIntel.js.map +1 -1
- package/dist/tools/docOutline.js +250 -0
- package/dist/tools/docOutline.js.map +1 -0
- package/dist/tools/editRipple.js +29 -2
- package/dist/tools/editRipple.js.map +1 -1
- package/dist/tools/emptyResult.js +24 -0
- package/dist/tools/emptyResult.js.map +1 -0
- package/dist/tools/glob.js +11 -2
- package/dist/tools/glob.js.map +1 -1
- package/dist/tools/grep.js +4 -3
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/missingPath.js +90 -0
- package/dist/tools/missingPath.js.map +1 -0
- package/dist/tools/readFile.js +3 -1
- package/dist/tools/readFile.js.map +1 -1
- package/dist/tools/rebuildDetail.js +9 -5
- package/dist/tools/rebuildDetail.js.map +1 -1
- package/dist/tools/runCommand.js +5 -1
- package/dist/tools/runCommand.js.map +1 -1
- package/dist/tools/webSearch.js +3 -1
- package/dist/tools/webSearch.js.map +1 -1
- package/package.json +2 -2
|
@@ -246,44 +246,31 @@ export const COLD_COMPACT_MIN_IDLE_MS = 15 * 60 * 1000;
|
|
|
246
246
|
/** After a compaction for a cold cache, wait this long before doing it again. */
|
|
247
247
|
export const COLD_COMPACT_COOLDOWN_MS = 30 * 60 * 1000;
|
|
248
248
|
/**
|
|
249
|
-
*
|
|
249
|
+
* How many further calls a clear is assumed to keep paying off for.
|
|
250
250
|
*
|
|
251
|
-
* Clearing an old tool body is not free on a warm cache:
|
|
252
|
-
*
|
|
253
|
-
*
|
|
251
|
+
* Clearing an old tool body or image is not free on a warm cache: the provider holds the
|
|
252
|
+
* conversation as a prefix, a change inside it invalidates everything after the change, and
|
|
253
|
+
* the next request writes that tail again at the full input price (plus a write premium, where
|
|
254
|
+
* the provider charges one) where it would have read it at the cached price. Written out, with
|
|
255
|
+
* T the tokens from the first changed message to the end, R the tokens the clear reclaims, h the
|
|
256
|
+
* cached read price and w the write price:
|
|
254
257
|
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
+
* paid once, on the next call = T * (w - h)
|
|
259
|
+
* saved on every later call = R * h
|
|
260
|
+
* worth it when R * h * horizon >= T * (w - h)
|
|
258
261
|
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
262
|
+
* The prices decide it, and they differ by an order of magnitude between providers: a cached read
|
|
263
|
+
* costs 10% of input on one, 2% on another, 20% on a third. At 2% the saving per call is so
|
|
264
|
+
* small that a clear which rewrites a 25K tail to reclaim 26K needs about 47 further calls to
|
|
265
|
+
* break even; at 10% the same clear needs about 11. The same clear is right on one provider and
|
|
266
|
+
* a loss on another, which a fixed fraction of the prefix could not tell apart.
|
|
263
267
|
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* MEASURED against the derivation above (61 real sessions, 2026-09-16), and it is too
|
|
269
|
-
* pessimistic. Do not tighten this on the strength of the arithmetic:
|
|
270
|
-
*
|
|
271
|
-
* - A clear does not rewrite the whole remaining prefix, only what follows the first
|
|
272
|
-
* cleared result. Real clears cost 6-12K extra uncached tokens on a ~45K prompt,
|
|
273
|
-
* not the ~43K that `1.25(P-R)` charges.
|
|
274
|
-
* - Sessions run far past one turn. Clears were followed by 37-82 more calls on
|
|
275
|
-
* average, so savings keep accruing long after the break-even horizon of one turn.
|
|
276
|
-
* - The 0.1 / 1.25 ratios are one provider's. DeepSeek reads cache at 2% of input
|
|
277
|
-
* with no write premium; GLM Flash at 20%.
|
|
278
|
-
*
|
|
279
|
-
* Net of cache rewrites AND the re-reads clearing causes (about 18% of file reads re-read
|
|
280
|
-
* something that had been cleared), clearing saved 4.3% of spend on DeepSeek V4 Flash and
|
|
281
|
-
* 10.3% on GLM 5.3 Flash, and 28 of 32 individual clears paid for themselves, including
|
|
282
|
-
* most below this threshold. The policy is left as is because it is already net positive
|
|
283
|
-
* and loosening it trades a few percent of saving for more re-reads, which is not yet
|
|
284
|
-
* measured.
|
|
268
|
+
* A long run is 30 to 80 calls after a clear, so 40 is where it is still a fair bet. Past it
|
|
269
|
+
* the clear is declined and the context is allowed to fill: carrying the extra tokens is a
|
|
270
|
+
* cached read, cheap, and the clear is made anyway when the cache goes cold or the autocompact
|
|
271
|
+
* bar is close, both of which cost nothing extra.
|
|
285
272
|
*/
|
|
286
|
-
const
|
|
273
|
+
export const CLEAR_HORIZON_STEPS = 40;
|
|
287
274
|
/**
|
|
288
275
|
* Whether a proposed microcompaction should actually be committed.
|
|
289
276
|
*
|
|
@@ -293,8 +280,8 @@ const CLEAR_WORTH_FRACTION = 0.35;
|
|
|
293
280
|
* the rewrite is free. Any reclaim at all is profit.
|
|
294
281
|
* - `urgent`: context is close enough to the autocompact bar that FITTING matters more
|
|
295
282
|
* than cost. A request that does not fit cannot be sent at any price.
|
|
296
|
-
* - otherwise: only when
|
|
297
|
-
*
|
|
283
|
+
* - otherwise: only when what it saves over the next calls out-earns the cache rewrite
|
|
284
|
+
* it forces, at this provider's prices (see `CLEAR_HORIZON_STEPS`).
|
|
298
285
|
*
|
|
299
286
|
* Pure, because the alternative is discovering the economics were wrong from a bill.
|
|
300
287
|
*/
|
|
@@ -308,6 +295,11 @@ export function clearIsWorthIt(opts) {
|
|
|
308
295
|
// expensive summarization, and a prompt that overflows is not a cost question.
|
|
309
296
|
if (opts.before >= opts.autoBar * 0.9)
|
|
310
297
|
return true;
|
|
311
|
-
|
|
298
|
+
const write = opts.price.cacheWrite ?? opts.price.cacheMiss;
|
|
299
|
+
const paidOnce = opts.rewritten * Math.max(0, write - opts.price.cacheHit);
|
|
300
|
+
// A provider that charges the same for a hit as for a miss has nothing to lose by a rewrite.
|
|
301
|
+
if (paidOnce <= 0)
|
|
302
|
+
return true;
|
|
303
|
+
return reclaimed * opts.price.cacheHit * (opts.horizon ?? CLEAR_HORIZON_STEPS) >= paidOnce;
|
|
312
304
|
}
|
|
313
305
|
//# sourceMappingURL=contextWindow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contextWindow.js","sourceRoot":"","sources":["../../src/dynamo/contextWindow.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"contextWindow.js","sourceRoot":"","sources":["../../src/dynamo/contextWindow.ts"],"names":[],"mappings":"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"}
|
package/dist/dynamo/engine.js
CHANGED
|
@@ -53,10 +53,10 @@ import { directoryNotesFor } from "../memory/projectNotes.js";
|
|
|
53
53
|
import { rippleCheck } from "../tools/editRipple.js";
|
|
54
54
|
import { fullReadPaths, visibleReadRanges } from "../memory/presence.js";
|
|
55
55
|
import { RESTORE_MAX_TOKENS_PER_FILE, renderRestored, restoreBudgetFor, selectForRestore, } from "../memory/restore.js";
|
|
56
|
-
import { KEEP_LAST_N, KEEP_LAST_N_BOUNDARY, CLEARED_STUB, summaryRequest, SUMMARY_SYSTEM_PROMPT, dropOldestRounds, estimateEntriesTokens, estimateTokens, estimateTokensForChars, formatTranscriptForSummary, isContinuation, microcompact, spliceSummary, summaryForWire,
|
|
56
|
+
import { KEEP_LAST_N, KEEP_LAST_N_BOUNDARY, CLEARED_STUB, summaryRequest, SUMMARY_SYSTEM_PROMPT, dropOldestRounds, estimateEntriesTokens, estimateTokens, estimateTokensForChars, formatTranscriptForSummary, isContinuation, isRecapStub, microcompact, RECAP_STUB_NUDGE, spliceSummary, summaryForWire, summaryWireIsHistory, hasUnsettledHistory, settleSummaries, firstChangedEntry, SUMMARY_HISTORY_NOTE, usableSummary, } from "../memory/compaction.js";
|
|
57
57
|
import { MAX_PARALLEL_CALLS, partitionCalls, runLimited } from "./toolBatches.js";
|
|
58
58
|
import { loadPlanArtifact, completePlanArtifact, renderPlanBlock, planDivergenceStop } from "./planArtifact.js";
|
|
59
|
-
import { autoCompactThreshold, microCompactThreshold, cacheLikelyCold, cacheStatus, cacheLifetimeFor, cacheIsDiscounted, shouldCompactForCold, coldCompactionLine, clearIsWorthIt, measuredOverhead, sharpContextWindow, } from "./contextWindow.js";
|
|
59
|
+
import { autoCompactThreshold, microCompactThreshold, cacheLikelyCold, isCold, cacheStatus, cacheLifetimeFor, cacheIsDiscounted, shouldCompactForCold, coldCompactionLine, clearIsWorthIt, measuredOverhead, sharpContextWindow, } from "./contextWindow.js";
|
|
60
60
|
import { todoReminderDue, todoReminderText } from "./todoReminder.js";
|
|
61
61
|
import { refreshSessionMemory, sessionMemoryDue, settleSessionMemory } from "../memory/sessionMemory.js";
|
|
62
62
|
import { compactFromSessionMemory } from "../memory/sessionMemoryCompact.js";
|
|
@@ -187,8 +187,12 @@ directoryNotes = [],
|
|
|
187
187
|
/** Where the previous turn left the shell, when this turn started back at the root. */
|
|
188
188
|
cwdResetFrom = "",
|
|
189
189
|
/** A running Marathon's standing block (see marathonPrompt.ts), or "". */
|
|
190
|
-
marathon = ""
|
|
190
|
+
marathon = "",
|
|
191
|
+
/** What stands in for rewriting a compaction summary the user has written past (see SUMMARY_HISTORY_NOTE), or "". */
|
|
192
|
+
summaryNote = "") {
|
|
191
193
|
const parts = [];
|
|
194
|
+
if (summaryNote)
|
|
195
|
+
parts.push(summaryNote);
|
|
192
196
|
// Each turn starts at the project root, and a model that `cd`-ed into a subfolder last
|
|
193
197
|
// turn does not know that unless it is told. It was not, and a real session ran
|
|
194
198
|
// `cargo run` from the root expecting the subfolder: "could not find Cargo.toml".
|
|
@@ -540,7 +544,7 @@ directoryNotes = []) {
|
|
|
540
544
|
// A summary is sent as background once the user has written after it, so its
|
|
541
545
|
// hand-off "next step" cannot keep overriding what they actually asked.
|
|
542
546
|
const said = e.role === "summary"
|
|
543
|
-
? summaryForWire(e.content,
|
|
547
|
+
? summaryForWire(e.content, summaryWireIsHistory(e, session.transcript.slice(i + 1)))
|
|
544
548
|
: e.arrival ? arrivalNote(e.arrival, e.content) : e.content;
|
|
545
549
|
if (refs && refs.length > 0) {
|
|
546
550
|
const images = [];
|
|
@@ -631,7 +635,7 @@ directoryNotes = []) {
|
|
|
631
635
|
// "keep working toward the goal" would stop being an independent check.
|
|
632
636
|
session.marathon?.status === "running" && (session.toolContext.subagentDepth ?? 0) === 0
|
|
633
637
|
? marathonBlock(session.marathon.goal, session.marathon.turnsSpent === 0 ? "plan" : "run")
|
|
634
|
-
: ""),
|
|
638
|
+
: "", hasUnsettledHistory(session.transcript) ? SUMMARY_HISTORY_NOTE : ""),
|
|
635
639
|
tools,
|
|
636
640
|
model: session.modelConfig,
|
|
637
641
|
sessionId: session.id,
|
|
@@ -1287,6 +1291,7 @@ async function respondTurn(session, options = {}) {
|
|
|
1287
1291
|
// shorter than it was.
|
|
1288
1292
|
session.lastCallAt = Date.now();
|
|
1289
1293
|
(session.lastCallByModel ??= {})[session.modelConfig.model] = session.lastCallAt;
|
|
1294
|
+
session.lastRequest = { request, sent: session.transcript.slice(0, request.messages.length) };
|
|
1290
1295
|
result = await streamModel(request, options);
|
|
1291
1296
|
}
|
|
1292
1297
|
catch (error) {
|
|
@@ -1409,10 +1414,11 @@ async function respondTurn(session, options = {}) {
|
|
|
1409
1414
|
// what the user sees. ONE retry — a gate that can fire twice is a loop.
|
|
1410
1415
|
if (!replyRegated) {
|
|
1411
1416
|
const fault = replyFault(content, mutatedThisTurn);
|
|
1412
|
-
|
|
1417
|
+
const copiedStub = isRecapStub(content);
|
|
1418
|
+
if (fault || copiedStub) {
|
|
1413
1419
|
replyRegated = true;
|
|
1414
1420
|
overlongReplyAt = session.transcript.length - 1; // the draft pushed just above
|
|
1415
|
-
session.transcript.push({ role: "user", content: replyRewrite(fault), synthetic: true });
|
|
1421
|
+
session.transcript.push({ role: "user", content: fault ? replyRewrite(fault) : RECAP_STUB_NUDGE, synthetic: true });
|
|
1416
1422
|
// The draft has been streaming into the UI's buffer, unrendered. Drop it, or
|
|
1417
1423
|
// the rewrite would append to it and the user would read both.
|
|
1418
1424
|
options.onEvent?.({ type: "replyReset" });
|
|
@@ -2473,7 +2479,7 @@ async function sweepSessionMemory(session, options, mode) {
|
|
|
2473
2479
|
options.onEvent?.({ type: "usage", ...usage });
|
|
2474
2480
|
countUsage(session, usage, options);
|
|
2475
2481
|
recordAuxCall(session, usage, "notes");
|
|
2476
|
-
}).then(async (wrote) => {
|
|
2482
|
+
}, (unseenTokens) => sharedNotesPrefix(session, unseenTokens)).then(async (wrote) => {
|
|
2477
2483
|
if (wrote)
|
|
2478
2484
|
await options.persist?.(); // durable: the notes sidecar is written by the persister
|
|
2479
2485
|
return wrote;
|
|
@@ -2483,6 +2489,35 @@ async function sweepSessionMemory(session, options, mode) {
|
|
|
2483
2489
|
else
|
|
2484
2490
|
void run.catch(() => { });
|
|
2485
2491
|
}
|
|
2492
|
+
/**
|
|
2493
|
+
* The main request the notes writer may build on, or null when it should send its own.
|
|
2494
|
+
*
|
|
2495
|
+
* Building on it means the provider reads the whole conversation from the cache the last call just
|
|
2496
|
+
* filled, at the cached price, instead of being sent the unseen part at full price. That is only
|
|
2497
|
+
* cheaper while the copy is there (this model was called within its cache lifetime), the request still
|
|
2498
|
+
* describes the transcript (it ended on an entry that is still in the same place), and the cached read
|
|
2499
|
+
* of the whole prefix costs less than the full-price read of what is new.
|
|
2500
|
+
*/
|
|
2501
|
+
async function sharedNotesPrefix(session, unseenTokens) {
|
|
2502
|
+
const sent = session.lastRequest;
|
|
2503
|
+
const model = session.modelConfig.model;
|
|
2504
|
+
if (!sent || sent.request.model?.model !== model || session.transcript.length === 0)
|
|
2505
|
+
return null;
|
|
2506
|
+
// The provider holds the beginning of the conversation as it was sent. It only counts as the beginning
|
|
2507
|
+
// of this one if nothing in it has been rewritten since (a clear, a compaction, a settled summary).
|
|
2508
|
+
if (sent.sent.length > session.transcript.length || sent.sent.some((e, i) => e !== session.transcript[i]))
|
|
2509
|
+
return null;
|
|
2510
|
+
const status = cacheStatus({ now: Date.now(), model, lastByModel: session.lastCallByModel, ttlMs: cacheLifetimeFor(model) });
|
|
2511
|
+
if (status !== "warm" || !cacheIsDiscounted(model))
|
|
2512
|
+
return null;
|
|
2513
|
+
const price = manifestForModel(model).price(model);
|
|
2514
|
+
const prefixTokens = estimateEntriesTokens(sent.sent) + (session.contextOverhead?.model === model ? session.contextOverhead.tokens : 0);
|
|
2515
|
+
if (prefixTokens * price.cacheHit > unseenTokens * price.cacheMiss)
|
|
2516
|
+
return null;
|
|
2517
|
+
// Same system prompt, tools and model as the main request; the conversation as it is now.
|
|
2518
|
+
const { messages } = buildRequest(session, [], await loadImagePayloads(session));
|
|
2519
|
+
return { request: { ...sent.request, messages }, entries: session.transcript.length, last: session.transcript[session.transcript.length - 1] };
|
|
2520
|
+
}
|
|
2486
2521
|
/**
|
|
2487
2522
|
* How much of the context window is in use, in tokens.
|
|
2488
2523
|
*
|
|
@@ -2590,11 +2625,18 @@ async function maybeCompact(session, options) {
|
|
|
2590
2625
|
const proposed = microcompact(session.transcript).entries;
|
|
2591
2626
|
const before = estimateEntriesTokens(session.transcript);
|
|
2592
2627
|
const after = estimateEntriesTokens(proposed);
|
|
2593
|
-
|
|
2628
|
+
// What the provider would have to write again: everything from the first message the clear changes.
|
|
2629
|
+
const rewritten = estimateEntriesTokens(proposed.slice(firstChangedEntry(session.transcript, proposed)));
|
|
2630
|
+
if (clearIsWorthIt({ before, after, cold, autoBar, rewritten, price: manifestForModel(model).price(model) })) {
|
|
2631
|
+
// The prefix is being rewritten anyway, so a summary the user has written past is settled in the same move.
|
|
2594
2632
|
session.transcript = keepClearedOriginals(session, proposed);
|
|
2633
|
+
session.transcript = settleSummaries(session.transcript);
|
|
2595
2634
|
// Silent by design — trimming stale context is background machinery.
|
|
2596
2635
|
}
|
|
2597
2636
|
}
|
|
2637
|
+
// With the provider's copy gone there is nothing to lose by it either, clear or no clear.
|
|
2638
|
+
if (isCold(status))
|
|
2639
|
+
session.transcript = settleSummaries(session.transcript);
|
|
2598
2640
|
// The history is about to be sent at full price whatever it contains, so this is the cheapest
|
|
2599
2641
|
// moment to shrink it, and the session notes make that free: no model call. Only the top-level
|
|
2600
2642
|
// agent; a sub-agent starts with no cache of its own and its work is short.
|