@cortexkit/pi-magic-context 0.38.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/{emscripten-module-ap8t3st0.js → emscripten-module-49k43zfy.js} +1 -1
- package/dist/{emscripten-module-682pfzaa.js → emscripten-module-ex4v0x4z.js} +1 -1
- package/dist/{emscripten-module-r5h7aghp.js → emscripten-module-jfs3d1dq.js} +1 -1
- package/dist/{emscripten-module-bkktz927.js → emscripten-module-ss4g4spn.js} +1 -1
- package/dist/{ffi-d8pnn3mn.js → ffi-bbm9vkfa.js} +1 -1
- package/dist/{ffi-04jzypzk.js → ffi-kb5r0x1j.js} +1 -1
- package/dist/{ffi-t8b862vx.js → ffi-qnrt0y78.js} +1 -1
- package/dist/{ffi-9wvt2wwz.js → ffi-yx2hpf4p.js} +1 -1
- package/dist/{index-wckvcay0.js → index-1yh8g550.js} +8 -6
- package/dist/{index-3pnd4qh9.js → index-8sseka65.js} +50 -50
- package/dist/{index-6hs6yh6r.js → index-qqgk7jmy.js} +3883 -2641
- package/dist/{index-ayd60xnw.js → index-rgdqj8nj.js} +3 -3
- package/dist/index.js +633 -216
- package/dist/{module-ES6BEMUI-atfbtnbp.js → module-ES6BEMUI-1yjdz59c.js} +4 -4
- package/dist/{module-asyncify-2EFITU5U-7xckhw8w.js → module-asyncify-2EFITU5U-fdkx4fhy.js} +1 -1
- package/dist/{prompt-context-602yq94t.js → prompt-context-3kjq9ejq.js} +1 -1
- package/dist/{rpc-notifications-s2rw51c6.js → rpc-notifications-gmhvmfpy.js} +6 -6
- package/dist/{safe-notification-target-7n7s6xv7.js → safe-notification-target-q00qgjm6.js} +3 -3
- package/dist/subagent-entry.js +2 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -134,6 +134,7 @@ import {
|
|
|
134
134
|
getAllStatusTagTokenTotalsFlat,
|
|
135
135
|
getAutoSearchHintDecisions,
|
|
136
136
|
getCachedAbsoluteMessageCount,
|
|
137
|
+
getChannel1NudgeState,
|
|
137
138
|
getChannel2NudgeClaim,
|
|
138
139
|
getChannel2NudgeState,
|
|
139
140
|
getCompactionModeRecord,
|
|
@@ -149,7 +150,6 @@ import {
|
|
|
149
150
|
getLastCompartmentEndMessage,
|
|
150
151
|
getLastCompartmentEndMessageId,
|
|
151
152
|
getLastIndexedOrdinal,
|
|
152
|
-
getLastNudgeLevel,
|
|
153
153
|
getLastNudgeUndropped,
|
|
154
154
|
getLatestHistorianInvocationId,
|
|
155
155
|
getLegacyProtectedTailStartOrdinal,
|
|
@@ -343,11 +343,11 @@ import {
|
|
|
343
343
|
saveRecompStagingPass,
|
|
344
344
|
saveSourceContent,
|
|
345
345
|
scheduleAfterBootQuiet,
|
|
346
|
+
setChannel1NudgeState,
|
|
346
347
|
setChannel2NudgeState,
|
|
347
348
|
setCompactionModeRecord,
|
|
348
349
|
setDeferredExecutePendingIfAbsent,
|
|
349
350
|
setEmergencyDropSample,
|
|
350
|
-
setLastNudgeLevel,
|
|
351
351
|
setLastNudgeUndropped,
|
|
352
352
|
setMemoryClassification,
|
|
353
353
|
setMuralCue,
|
|
@@ -361,6 +361,7 @@ import {
|
|
|
361
361
|
setSqlitePragmaConfig,
|
|
362
362
|
setStoragePrivatePermissionEnforcement,
|
|
363
363
|
setTodoSnapshot,
|
|
364
|
+
shouldUseStickyChannel1Reminder,
|
|
364
365
|
sourceNameForMemory,
|
|
365
366
|
stripChannel1ReminderSpans,
|
|
366
367
|
stripMemoryMuralBlock,
|
|
@@ -395,7 +396,7 @@ import {
|
|
|
395
396
|
withMigrationLanguageDirective,
|
|
396
397
|
withRawMessageProvider,
|
|
397
398
|
withRawSessionMessageCache
|
|
398
|
-
} from "./index-
|
|
399
|
+
} from "./index-qqgk7jmy.js";
|
|
399
400
|
import {
|
|
400
401
|
pushNotification
|
|
401
402
|
} from "./index-hw34xmzk.js";
|
|
@@ -411,55 +412,110 @@ import {
|
|
|
411
412
|
import {
|
|
412
413
|
__require,
|
|
413
414
|
__toESM
|
|
414
|
-
} from "./index-
|
|
415
|
+
} from "./index-1yh8g550.js";
|
|
415
416
|
|
|
416
417
|
// src/index.ts
|
|
417
418
|
import { createRequire as createRequire3 } from "node:module";
|
|
418
419
|
import { join as join5, resolve as resolve2 } from "node:path";
|
|
419
420
|
|
|
420
|
-
// ../plugin/src/shared/
|
|
421
|
-
function
|
|
422
|
-
|
|
423
|
-
return dedupe(userList.filter(isValidModelSpec));
|
|
421
|
+
// ../plugin/src/shared/model-resolution.ts
|
|
422
|
+
function asRecord(value) {
|
|
423
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
424
424
|
}
|
|
425
|
-
function
|
|
426
|
-
if (
|
|
427
|
-
return
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
425
|
+
function readString(value) {
|
|
426
|
+
if (typeof value !== "string")
|
|
427
|
+
return;
|
|
428
|
+
const trimmed = value.trim();
|
|
429
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
430
|
+
}
|
|
431
|
+
function hasOwn(record, key) {
|
|
432
|
+
return Object.hasOwn(record, key);
|
|
433
|
+
}
|
|
434
|
+
function normalizeModelEntry(entry, harness) {
|
|
435
|
+
if (typeof entry === "string") {
|
|
436
|
+
const model2 = readString(entry);
|
|
437
|
+
return model2 ? { model: model2 } : undefined;
|
|
431
438
|
}
|
|
432
|
-
|
|
439
|
+
const objectEntry = asRecord(entry);
|
|
440
|
+
if (!objectEntry)
|
|
441
|
+
return;
|
|
442
|
+
const model = readString(objectEntry.model);
|
|
443
|
+
if (!model)
|
|
444
|
+
return;
|
|
445
|
+
const qualifier = readString(objectEntry[harness === "opencode" ? "variant" : "thinking_level"]);
|
|
446
|
+
return qualifier ? { model, qualifier } : { model };
|
|
433
447
|
}
|
|
434
|
-
function
|
|
435
|
-
const slash =
|
|
436
|
-
return slash > 0 && slash <
|
|
448
|
+
function isValidModelReference(entry) {
|
|
449
|
+
const slash = entry.model.indexOf("/");
|
|
450
|
+
return slash > 0 && slash < entry.model.length - 1;
|
|
437
451
|
}
|
|
438
|
-
function
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
452
|
+
function sameAttempt(a, b) {
|
|
453
|
+
return a.model === b.model && a.qualifier === b.qualifier;
|
|
454
|
+
}
|
|
455
|
+
function resolveFallbackEntries(value, harness) {
|
|
456
|
+
const values = Array.isArray(value) ? value : value === undefined ? [] : [value];
|
|
457
|
+
const resolved = [];
|
|
458
|
+
for (const value2 of values) {
|
|
459
|
+
const entry = normalizeModelEntry(value2, harness);
|
|
460
|
+
if (!entry || !isValidModelReference(entry))
|
|
443
461
|
continue;
|
|
444
|
-
|
|
445
|
-
|
|
462
|
+
if (resolved.some((candidate) => sameAttempt(candidate, entry)))
|
|
463
|
+
continue;
|
|
464
|
+
resolved.push(entry);
|
|
446
465
|
}
|
|
447
|
-
return
|
|
466
|
+
return resolved;
|
|
448
467
|
}
|
|
449
|
-
function
|
|
450
|
-
const
|
|
451
|
-
if (
|
|
452
|
-
return
|
|
468
|
+
function resolvePrimaryEntry(args) {
|
|
469
|
+
const entry = normalizeModelEntry(args.entry, args.harness);
|
|
470
|
+
if (!entry)
|
|
471
|
+
return;
|
|
472
|
+
const qualifier = entry.qualifier ?? readString(args.defaultQualifier);
|
|
473
|
+
return qualifier ? { ...entry, qualifier } : entry;
|
|
474
|
+
}
|
|
475
|
+
function resolveHistorianModel(config, harness) {
|
|
476
|
+
const historian = asRecord(asRecord(config)?.historian);
|
|
477
|
+
const block = asRecord(historian?.[harness]);
|
|
478
|
+
if (!block)
|
|
479
|
+
return { fallbacks: [] };
|
|
453
480
|
return {
|
|
454
|
-
|
|
455
|
-
|
|
481
|
+
primary: resolvePrimaryEntry({
|
|
482
|
+
entry: block.model,
|
|
483
|
+
defaultQualifier: block[harness === "opencode" ? "variant" : "thinking_level"],
|
|
484
|
+
harness
|
|
485
|
+
}),
|
|
486
|
+
fallbacks: resolveFallbackEntries(block.fallback_models, harness)
|
|
456
487
|
};
|
|
457
488
|
}
|
|
458
|
-
function
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
const
|
|
462
|
-
|
|
489
|
+
function resolveDreamerTaskModel(args) {
|
|
490
|
+
const dreamer = asRecord(asRecord(args.config)?.dreamer);
|
|
491
|
+
const harnessBlock = asRecord(dreamer?.[args.harness]);
|
|
492
|
+
const taskBlock = asRecord(asRecord(harnessBlock?.tasks)?.[args.task]);
|
|
493
|
+
const schedulingTask = asRecord(asRecord(dreamer?.tasks)?.[args.task]);
|
|
494
|
+
if (!harnessBlock) {
|
|
495
|
+
return {
|
|
496
|
+
fallbacks: [],
|
|
497
|
+
schedule: readString(schedulingTask?.schedule),
|
|
498
|
+
timeoutMinutes: typeof taskBlock?.timeout_minutes === "number" ? taskBlock.timeout_minutes : undefined,
|
|
499
|
+
promotionThreshold: typeof schedulingTask?.promotion_threshold === "number" ? schedulingTask.promotion_threshold : undefined
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
const taskQualifier = taskBlock?.[args.harness === "opencode" ? "variant" : "thinking_level"];
|
|
503
|
+
const harnessQualifier = harnessBlock[args.harness === "opencode" ? "variant" : "thinking_level"] ?? normalizeModelEntry(harnessBlock.model, args.harness)?.qualifier;
|
|
504
|
+
const taskHasModel = taskBlock !== undefined && hasOwn(taskBlock, "model");
|
|
505
|
+
const usesMuralModel = !taskHasModel && args.task === "compress-cues" && Boolean(readString(args.muralModel));
|
|
506
|
+
const primarySource = taskHasModel ? taskBlock?.model : usesMuralModel ? args.muralModel : harnessBlock.model;
|
|
507
|
+
const fallbackSource = taskBlock !== undefined && hasOwn(taskBlock, "fallback_models") ? taskBlock.fallback_models : harnessBlock.fallback_models;
|
|
508
|
+
return {
|
|
509
|
+
primary: resolvePrimaryEntry({
|
|
510
|
+
entry: primarySource,
|
|
511
|
+
defaultQualifier: usesMuralModel ? harnessQualifier : taskQualifier ?? harnessQualifier,
|
|
512
|
+
harness: args.harness
|
|
513
|
+
}),
|
|
514
|
+
fallbacks: resolveFallbackEntries(fallbackSource, args.harness),
|
|
515
|
+
schedule: readString(schedulingTask?.schedule),
|
|
516
|
+
timeoutMinutes: typeof taskBlock?.timeout_minutes === "number" ? taskBlock.timeout_minutes : undefined,
|
|
517
|
+
promotionThreshold: typeof schedulingTask?.promotion_threshold === "number" ? schedulingTask.promotion_threshold : undefined
|
|
518
|
+
};
|
|
463
519
|
}
|
|
464
520
|
|
|
465
521
|
// ../plugin/src/features/magic-context/dreamer/task-registry.ts
|
|
@@ -528,25 +584,23 @@ function compareTaskOrder(a, b) {
|
|
|
528
584
|
}
|
|
529
585
|
|
|
530
586
|
// ../plugin/src/features/magic-context/dreamer/task-config.ts
|
|
531
|
-
function buildDreamTaskRuntimeConfigs(dreamer, language) {
|
|
532
|
-
const tasks = dreamer.tasks ?? {};
|
|
587
|
+
function buildDreamTaskRuntimeConfigs(dreamer, harness, language, muralModel) {
|
|
533
588
|
return CANONICAL_DREAM_TASKS.map((task) => {
|
|
534
|
-
const
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
const thinkingLevel = t.thinking_level ?? dreamer.thinking_level;
|
|
589
|
+
const resolved = resolveDreamerTaskModel({
|
|
590
|
+
config: { dreamer },
|
|
591
|
+
harness,
|
|
592
|
+
task,
|
|
593
|
+
muralModel
|
|
594
|
+
});
|
|
541
595
|
return {
|
|
542
596
|
task,
|
|
543
|
-
schedule:
|
|
544
|
-
model,
|
|
545
|
-
fallbackModels,
|
|
546
|
-
thinkingLevel,
|
|
597
|
+
schedule: resolved.schedule ?? "",
|
|
598
|
+
model: resolved.primary,
|
|
599
|
+
fallbackModels: resolved.fallbacks,
|
|
600
|
+
thinkingLevel: harness === "pi" ? resolved.primary?.qualifier : undefined,
|
|
547
601
|
language,
|
|
548
|
-
timeoutMinutes:
|
|
549
|
-
promotionThreshold:
|
|
602
|
+
timeoutMinutes: resolved.timeoutMinutes ?? 20,
|
|
603
|
+
promotionThreshold: resolved.promotionThreshold
|
|
550
604
|
};
|
|
551
605
|
});
|
|
552
606
|
}
|
|
@@ -1951,6 +2005,59 @@ function shouldKeepSubagents() {
|
|
|
1951
2005
|
return keepSubagents;
|
|
1952
2006
|
}
|
|
1953
2007
|
|
|
2008
|
+
// ../plugin/src/shared/resolve-fallbacks.ts
|
|
2009
|
+
function resolveFallbackChain(userFallbacks) {
|
|
2010
|
+
const userList = normalizeUserFallbacks(userFallbacks);
|
|
2011
|
+
return dedupe(userList.filter(isValidModelSpec));
|
|
2012
|
+
}
|
|
2013
|
+
function normalizeUserFallbacks(userFallbacks) {
|
|
2014
|
+
if (!userFallbacks)
|
|
2015
|
+
return [];
|
|
2016
|
+
if (typeof userFallbacks === "string") {
|
|
2017
|
+
const trimmed = userFallbacks.trim();
|
|
2018
|
+
return trimmed ? [trimmed] : [];
|
|
2019
|
+
}
|
|
2020
|
+
return userFallbacks.map((s) => s.trim()).filter((s) => s.length > 0);
|
|
2021
|
+
}
|
|
2022
|
+
function isValidModelSpec(spec) {
|
|
2023
|
+
const slash = spec.indexOf("/");
|
|
2024
|
+
return slash > 0 && slash < spec.length - 1;
|
|
2025
|
+
}
|
|
2026
|
+
function dedupe(list) {
|
|
2027
|
+
const seen = new Set;
|
|
2028
|
+
const out = [];
|
|
2029
|
+
for (const item of list) {
|
|
2030
|
+
if (seen.has(item))
|
|
2031
|
+
continue;
|
|
2032
|
+
seen.add(item);
|
|
2033
|
+
out.push(item);
|
|
2034
|
+
}
|
|
2035
|
+
return out;
|
|
2036
|
+
}
|
|
2037
|
+
function parseProviderModel(spec) {
|
|
2038
|
+
const slash = spec.indexOf("/");
|
|
2039
|
+
if (slash < 1 || slash >= spec.length - 1)
|
|
2040
|
+
return null;
|
|
2041
|
+
return {
|
|
2042
|
+
providerID: spec.slice(0, slash).trim(),
|
|
2043
|
+
modelID: spec.slice(slash + 1).trim()
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
2046
|
+
function modelBodyField(spec) {
|
|
2047
|
+
const entry = toModelEntry(spec);
|
|
2048
|
+
if (!entry)
|
|
2049
|
+
return {};
|
|
2050
|
+
const parsed = parseProviderModel(entry.model);
|
|
2051
|
+
return parsed ? { model: parsed, ...entry.qualifier ? { variant: entry.qualifier } : {} } : {};
|
|
2052
|
+
}
|
|
2053
|
+
function toModelEntry(spec) {
|
|
2054
|
+
if (typeof spec === "string") {
|
|
2055
|
+
const model = spec.trim();
|
|
2056
|
+
return model ? { model } : undefined;
|
|
2057
|
+
}
|
|
2058
|
+
return spec;
|
|
2059
|
+
}
|
|
2060
|
+
|
|
1954
2061
|
// src/clone-inheritance.ts
|
|
1955
2062
|
import { readFile } from "node:fs/promises";
|
|
1956
2063
|
var CONTENT_ID_SUFFIX = /:(?:p|file)\d+$/;
|
|
@@ -2530,14 +2637,35 @@ class PiSubagentRunner {
|
|
|
2530
2637
|
return { result: isolatedResult, extensionRetryUsed: true };
|
|
2531
2638
|
}
|
|
2532
2639
|
async runModelChain(options, runMode, primaryModelRef) {
|
|
2533
|
-
const
|
|
2534
|
-
const
|
|
2640
|
+
const attempts = [];
|
|
2641
|
+
const seenAttempts = new Set;
|
|
2642
|
+
const appendAttempt = (candidate) => {
|
|
2643
|
+
if (!candidate.model)
|
|
2644
|
+
return;
|
|
2645
|
+
const key = `${candidate.model}\x00${candidate.qualifier ?? ""}`;
|
|
2646
|
+
if (seenAttempts.has(key))
|
|
2647
|
+
return;
|
|
2648
|
+
seenAttempts.add(key);
|
|
2649
|
+
attempts.push(candidate);
|
|
2650
|
+
};
|
|
2651
|
+
if (options.model) {
|
|
2652
|
+
appendAttempt({
|
|
2653
|
+
model: options.model,
|
|
2654
|
+
...options.thinkingLevel ? { qualifier: options.thinkingLevel } : {}
|
|
2655
|
+
});
|
|
2656
|
+
}
|
|
2657
|
+
for (const candidate of options.fallbackModels ?? []) {
|
|
2658
|
+
appendAttempt(typeof candidate === "string" ? { model: candidate } : candidate);
|
|
2659
|
+
}
|
|
2660
|
+
if (attempts.length === 0)
|
|
2661
|
+
attempts.push(undefined);
|
|
2535
2662
|
let lastResult = null;
|
|
2536
2663
|
for (let index = 0;index < attempts.length; index += 1) {
|
|
2537
|
-
const
|
|
2664
|
+
const attempt = attempts[index];
|
|
2538
2665
|
const attemptOptions = {
|
|
2539
2666
|
...options,
|
|
2540
|
-
model,
|
|
2667
|
+
model: attempt?.model,
|
|
2668
|
+
thinkingLevel: attempt?.qualifier,
|
|
2541
2669
|
fallbackModels: undefined
|
|
2542
2670
|
};
|
|
2543
2671
|
const result = await this.runOnce(attemptOptions, runMode, index === 0 ? primaryModelRef : undefined);
|
|
@@ -3748,11 +3876,11 @@ async function trySendTuiToast(sessionId, text, params, forcePersist) {
|
|
|
3748
3876
|
const message = text.length > 200 ? `${text.slice(0, 200)}…` : text;
|
|
3749
3877
|
const toastVariant = inferToastVariant(text);
|
|
3750
3878
|
const duration = params.toastDurationMs ?? 5000;
|
|
3751
|
-
const { isTuiConnected: checkTui } = await import("./rpc-notifications-
|
|
3879
|
+
const { isTuiConnected: checkTui } = await import("./rpc-notifications-gmhvmfpy.js");
|
|
3752
3880
|
if (!checkTui(sessionId))
|
|
3753
3881
|
return false;
|
|
3754
3882
|
try {
|
|
3755
|
-
const { pushNotification: pushNotification2 } = await import("./rpc-notifications-
|
|
3883
|
+
const { pushNotification: pushNotification2 } = await import("./rpc-notifications-gmhvmfpy.js");
|
|
3756
3884
|
pushNotification2("toast", {
|
|
3757
3885
|
title,
|
|
3758
3886
|
message,
|
|
@@ -3801,7 +3929,7 @@ async function sendIgnoredMessageNow(client, sessionId, text, params, forcePersi
|
|
|
3801
3929
|
queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
|
|
3802
3930
|
return "queued";
|
|
3803
3931
|
}
|
|
3804
|
-
const { waitForSafeNotificationTarget } = await import("./safe-notification-target-
|
|
3932
|
+
const { waitForSafeNotificationTarget } = await import("./safe-notification-target-q00qgjm6.js");
|
|
3805
3933
|
if (await waitForSafeNotificationTarget(client, sessionId) === "skip") {
|
|
3806
3934
|
sessionLog(sessionId, "notification skipped (session not titled yet)");
|
|
3807
3935
|
return "skipped";
|
|
@@ -3820,7 +3948,7 @@ async function sendIgnoredMessageNow(client, sessionId, text, params, forcePersi
|
|
|
3820
3948
|
let model = params.providerId && params.modelId ? { providerID: params.providerId, modelID: params.modelId } : undefined;
|
|
3821
3949
|
if (!agent || !model || !variant) {
|
|
3822
3950
|
try {
|
|
3823
|
-
const { resolvePromptContext } = await import("./prompt-context-
|
|
3951
|
+
const { resolvePromptContext } = await import("./prompt-context-3kjq9ejq.js");
|
|
3824
3952
|
const resolved = await resolvePromptContext(client, sessionId);
|
|
3825
3953
|
if (resolved) {
|
|
3826
3954
|
agent = agent ?? resolved.agent;
|
|
@@ -4091,15 +4219,18 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
|
|
|
4091
4219
|
log(`[${callContext}] primary (${explicitPrimaryLabel}) failed: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
|
|
4092
4220
|
}
|
|
4093
4221
|
for (let i = 0;i < fallbacks.length; i += 1) {
|
|
4094
|
-
const
|
|
4222
|
+
const fallback = toModelEntry(fallbacks[i]);
|
|
4223
|
+
const parsed = fallback ? parseProviderModel(fallback.model) : null;
|
|
4095
4224
|
if (!parsed) {
|
|
4096
|
-
log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
|
|
4225
|
+
log(`[${callContext}] skipping invalid fallback spec: ${String(fallbacks[i])}`);
|
|
4097
4226
|
continue;
|
|
4098
4227
|
}
|
|
4099
4228
|
const label = `${parsed.providerID}/${parsed.modelID}`;
|
|
4229
|
+
const { variant: _primaryVariant, ...bodyWithoutPrimaryVariant } = baseBody;
|
|
4100
4230
|
const attemptArgs = copyPromptArgs(baseArgs, {
|
|
4101
|
-
...
|
|
4102
|
-
model: parsed
|
|
4231
|
+
...bodyWithoutPrimaryVariant,
|
|
4232
|
+
model: parsed,
|
|
4233
|
+
...fallback?.qualifier ? { variant: fallback.qualifier } : {}
|
|
4103
4234
|
});
|
|
4104
4235
|
try {
|
|
4105
4236
|
await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label);
|
|
@@ -4115,7 +4246,7 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
|
|
|
4115
4246
|
}
|
|
4116
4247
|
}
|
|
4117
4248
|
}
|
|
4118
|
-
log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; last error: ${shortErr(lastError)}`);
|
|
4249
|
+
log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks.map((fallback) => toModelEntry(fallback)?.model ?? String(fallback))].join(", ")}; last error: ${shortErr(lastError)}`);
|
|
4119
4250
|
throw lastError ?? new Error("All fallback models failed");
|
|
4120
4251
|
}
|
|
4121
4252
|
async function attemptAndValidate(client, args, timeoutMs, signal, callContext, attempt, options) {
|
|
@@ -4153,15 +4284,18 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
|
|
|
4153
4284
|
log(`[${callContext}] primary (${explicitPrimaryLabel}) failed validation/prompt: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
|
|
4154
4285
|
}
|
|
4155
4286
|
for (let i = 0;i < fallbacks.length; i += 1) {
|
|
4156
|
-
const
|
|
4287
|
+
const fallback = toModelEntry(fallbacks[i]);
|
|
4288
|
+
const parsed = fallback ? parseProviderModel(fallback.model) : null;
|
|
4157
4289
|
if (!parsed) {
|
|
4158
|
-
log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
|
|
4290
|
+
log(`[${callContext}] skipping invalid fallback spec: ${String(fallbacks[i])}`);
|
|
4159
4291
|
continue;
|
|
4160
4292
|
}
|
|
4161
4293
|
const label = `${parsed.providerID}/${parsed.modelID}`;
|
|
4294
|
+
const { variant: _primaryVariant, ...bodyWithoutPrimaryVariant } = baseBody;
|
|
4162
4295
|
const attemptArgs = copyPromptArgs(baseArgs, {
|
|
4163
|
-
...
|
|
4164
|
-
model: parsed
|
|
4296
|
+
...bodyWithoutPrimaryVariant,
|
|
4297
|
+
model: parsed,
|
|
4298
|
+
...fallback?.qualifier ? { variant: fallback.qualifier } : {}
|
|
4165
4299
|
});
|
|
4166
4300
|
const attempt = {
|
|
4167
4301
|
label,
|
|
@@ -4186,7 +4320,7 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
|
|
|
4186
4320
|
}
|
|
4187
4321
|
}
|
|
4188
4322
|
}
|
|
4189
|
-
log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; original error: ${shortErr(firstError)}; last error: ${shortErr(lastError)}`);
|
|
4323
|
+
log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks.map((fallback) => toModelEntry(fallback)?.model ?? String(fallback))].join(", ")}; original error: ${shortErr(firstError)}; last error: ${shortErr(lastError)}`);
|
|
4190
4324
|
throw firstError ?? lastError ?? new Error("All fallback models failed validation");
|
|
4191
4325
|
}
|
|
4192
4326
|
// ../plugin/src/shared/normalize-sdk-response.ts
|
|
@@ -6882,22 +7016,67 @@ var asyncModulePromise = null;
|
|
|
6882
7016
|
function getAsyncModule() {
|
|
6883
7017
|
asyncModulePromise ??= (async () => {
|
|
6884
7018
|
const [{ default: singlefileAsyncifyVariant }, { newQuickJSAsyncWASMModuleFromVariant }] = await Promise.all([
|
|
6885
|
-
import("./index-
|
|
6886
|
-
import("./index-
|
|
7019
|
+
import("./index-rgdqj8nj.js").then((m)=>__toESM(m.default,1)),
|
|
7020
|
+
import("./index-8sseka65.js")
|
|
6887
7021
|
]);
|
|
6888
7022
|
return newQuickJSAsyncWASMModuleFromVariant(singlefileAsyncifyVariant);
|
|
6889
7023
|
})();
|
|
6890
7024
|
return asyncModulePromise;
|
|
6891
7025
|
}
|
|
7026
|
+
function acquireSandboxModule(signal) {
|
|
7027
|
+
const modulePromise = getAsyncModule();
|
|
7028
|
+
if (!signal)
|
|
7029
|
+
return modulePromise;
|
|
7030
|
+
if (signal.aborted) {
|
|
7031
|
+
return Promise.reject(signal.reason ?? new Error("smart-note check aborted"));
|
|
7032
|
+
}
|
|
7033
|
+
return new Promise((resolve, reject) => {
|
|
7034
|
+
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
7035
|
+
const onAbort = () => {
|
|
7036
|
+
cleanup();
|
|
7037
|
+
reject(signal.reason ?? new Error("smart-note check aborted"));
|
|
7038
|
+
};
|
|
7039
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
7040
|
+
modulePromise.then((module) => {
|
|
7041
|
+
cleanup();
|
|
7042
|
+
resolve(module);
|
|
7043
|
+
}, (error) => {
|
|
7044
|
+
cleanup();
|
|
7045
|
+
reject(error);
|
|
7046
|
+
});
|
|
7047
|
+
});
|
|
7048
|
+
}
|
|
6892
7049
|
var sandboxRunChain = Promise.resolve();
|
|
6893
|
-
function withSandboxLock(fn) {
|
|
6894
|
-
const
|
|
7050
|
+
function withSandboxLock(fn, signal, cancelled) {
|
|
7051
|
+
const start = () => signal?.aborted && cancelled ? cancelled() : fn();
|
|
7052
|
+
const run = sandboxRunChain.then(start, start);
|
|
6895
7053
|
sandboxRunChain = run.then(() => {
|
|
6896
7054
|
return;
|
|
6897
7055
|
}, () => {
|
|
6898
7056
|
return;
|
|
6899
7057
|
});
|
|
6900
|
-
return run;
|
|
7058
|
+
return resolveBeforeAbort(run, signal, cancelled);
|
|
7059
|
+
}
|
|
7060
|
+
function resolveBeforeAbort(run, signal, cancelled) {
|
|
7061
|
+
if (!signal || !cancelled)
|
|
7062
|
+
return run;
|
|
7063
|
+
if (signal.aborted)
|
|
7064
|
+
return Promise.resolve(cancelled());
|
|
7065
|
+
return new Promise((resolve, reject) => {
|
|
7066
|
+
const cleanup = () => signal.removeEventListener("abort", abort);
|
|
7067
|
+
const abort = () => {
|
|
7068
|
+
cleanup();
|
|
7069
|
+
resolve(cancelled());
|
|
7070
|
+
};
|
|
7071
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
7072
|
+
run.then((result) => {
|
|
7073
|
+
cleanup();
|
|
7074
|
+
resolve(result);
|
|
7075
|
+
}, (error) => {
|
|
7076
|
+
cleanup();
|
|
7077
|
+
reject(error);
|
|
7078
|
+
});
|
|
7079
|
+
});
|
|
6901
7080
|
}
|
|
6902
7081
|
var DEFAULT_TIMEOUT_MS = 2000;
|
|
6903
7082
|
var DEFAULT_HEAP_LIMIT_BYTES = 8 * 1024 * 1024;
|
|
@@ -6924,9 +7103,17 @@ async function runCompiledSmartNoteCheck(options) {
|
|
|
6924
7103
|
if (Buffer.byteLength(options.compiledCheck, "utf8") > MAX_COMPILED_CHECK_BYTES) {
|
|
6925
7104
|
return failureResult("compiled check exceeds 64 KiB", false);
|
|
6926
7105
|
}
|
|
6927
|
-
|
|
7106
|
+
let quickjs;
|
|
7107
|
+
try {
|
|
7108
|
+
quickjs = await acquireSandboxModule(options.signal);
|
|
7109
|
+
} catch (error) {
|
|
7110
|
+
if (options.signal?.aborted)
|
|
7111
|
+
return cancelledResult(options.signal.reason);
|
|
7112
|
+
return failureResult(formatSandboxError(error), false);
|
|
7113
|
+
}
|
|
7114
|
+
return withSandboxLock(() => runCompiledSmartNoteCheckLocked(options, quickjs), options.signal, () => cancelledResult(options.signal?.reason));
|
|
6928
7115
|
}
|
|
6929
|
-
async function runCompiledSmartNoteCheckLocked(options) {
|
|
7116
|
+
async function runCompiledSmartNoteCheckLocked(options, quickjs) {
|
|
6930
7117
|
if (options.signal?.aborted)
|
|
6931
7118
|
return cancelledResult(options.signal.reason);
|
|
6932
7119
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
@@ -6946,8 +7133,6 @@ async function runCompiledSmartNoteCheckLocked(options) {
|
|
|
6946
7133
|
throwIfRunAborted(controller.signal);
|
|
6947
7134
|
const capabilities = resolveCapabilitiesForRun(options, controller.signal);
|
|
6948
7135
|
const deadline = Date.now() + timeoutMs;
|
|
6949
|
-
const quickjs = await getAsyncModule();
|
|
6950
|
-
throwIfRunAborted(controller.signal);
|
|
6951
7136
|
const context = quickjs.newContext();
|
|
6952
7137
|
try {
|
|
6953
7138
|
context.runtime.setMemoryLimit(options.heapLimitBytes ?? DEFAULT_HEAP_LIMIT_BYTES);
|
|
@@ -7552,7 +7737,7 @@ async function evaluateSmartNotes(args) {
|
|
|
7552
7737
|
projectIdentity: args.projectIdentity,
|
|
7553
7738
|
projectRoot,
|
|
7554
7739
|
maxChecks: 10,
|
|
7555
|
-
sweepBudgetMs: 1e4,
|
|
7740
|
+
sweepBudgetMs: args.sweepBudgetMs ?? 1e4,
|
|
7556
7741
|
leaseHeld,
|
|
7557
7742
|
signal: leaseAbortController.signal,
|
|
7558
7743
|
retinaHandoff: args.retinaHandoff
|
|
@@ -8077,19 +8262,26 @@ function parseMapMemoriesManifest(text) {
|
|
|
8077
8262
|
if (out.length === 0 && body.trim().length > 0) {
|
|
8078
8263
|
throw new Error(describeUnrecognizedManifestShape(text, "mappings", "memory"));
|
|
8079
8264
|
}
|
|
8080
|
-
assertNoDuplicateManifestIds(out.map((entry) => entry.id), "mappings");
|
|
8081
8265
|
return out;
|
|
8082
8266
|
}
|
|
8083
8267
|
function validateMapMemoriesManifest(text, expectedIds) {
|
|
8084
8268
|
const parsed = parseMapMemoriesManifest(text);
|
|
8085
8269
|
assertParsedManifestNonEmpty(parsed.length, expectedIds.size, text, "mappings", "memory");
|
|
8086
|
-
|
|
8270
|
+
assertNoDuplicateManifestIds(parsed.filter((entry) => expectedIds.has(entry.id)).map((entry) => entry.id), "mappings");
|
|
8087
8271
|
return parsed;
|
|
8088
8272
|
}
|
|
8089
8273
|
|
|
8090
8274
|
// ../plugin/src/features/magic-context/dreamer/map-memories.ts
|
|
8091
8275
|
var MAP_BATCH_SIZE = 80;
|
|
8276
|
+
var MAP_BATCH_FLOOR_MS = 240000;
|
|
8277
|
+
var CONSECUTIVE_TIMEOUT_LIMIT2 = 2;
|
|
8092
8278
|
var MAX_INDEPENDENT_REQUEUE_PER_RUN = MAP_BATCH_SIZE;
|
|
8279
|
+
function computeMapBatchSliceMs(remainingMs, batchesRemaining) {
|
|
8280
|
+
return Math.min(remainingMs, Math.max(MAP_BATCH_FLOOR_MS, Math.floor(remainingMs / batchesRemaining)));
|
|
8281
|
+
}
|
|
8282
|
+
function isTimeoutClassError2(error) {
|
|
8283
|
+
return error instanceof Error && /^prompt timed out after \d+ms$/.test(error.message);
|
|
8284
|
+
}
|
|
8093
8285
|
function shouldRequeueIndependentMapping(state2, content, repoDir) {
|
|
8094
8286
|
if (!state2.hasSentinel || state2.files.length > 0)
|
|
8095
8287
|
return false;
|
|
@@ -8137,27 +8329,64 @@ async function mapMemories(args) {
|
|
|
8137
8329
|
return result;
|
|
8138
8330
|
const batches = [];
|
|
8139
8331
|
for (let i = 0;i < inputs.length; i += MAP_BATCH_SIZE) {
|
|
8140
|
-
batches.push(inputs.slice(i, i + MAP_BATCH_SIZE));
|
|
8332
|
+
batches.push({ inputs: inputs.slice(i, i + MAP_BATCH_SIZE), isOmissionRetry: false });
|
|
8141
8333
|
}
|
|
8142
8334
|
result.remaining = inputs.length;
|
|
8143
8335
|
const abortController = new AbortController;
|
|
8144
8336
|
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
|
|
8145
8337
|
try {
|
|
8338
|
+
let consecutiveTimeouts = 0;
|
|
8339
|
+
let timeoutStreakElapsedMs = [];
|
|
8146
8340
|
for (let i = 0;i < batches.length; i += 1) {
|
|
8147
8341
|
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
8148
|
-
if (remainingMs <= 0)
|
|
8342
|
+
if (remainingMs <= 0) {
|
|
8343
|
+
result.stopReason = "deadline";
|
|
8149
8344
|
break;
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8345
|
+
}
|
|
8346
|
+
if (remainingMs < MAP_BATCH_FLOOR_MS) {
|
|
8347
|
+
result.stopReason = "deadline";
|
|
8348
|
+
log(`[dreamer] map-memories: stopping before batch ${i + 1}/${batches.length} — remaining budget ${remainingMs}ms is below the ${MAP_BATCH_FLOOR_MS}ms batch floor; banking ${result.mapped + result.independent} mapping(s)`);
|
|
8349
|
+
break;
|
|
8350
|
+
}
|
|
8351
|
+
const sliceMs = computeMapBatchSliceMs(remainingMs, batches.length - i);
|
|
8352
|
+
const batch = batches[i];
|
|
8353
|
+
if (!batch)
|
|
8354
|
+
break;
|
|
8355
|
+
const outcome = await mapOneBatch(args, batch.inputs, sliceMs, abortController.signal);
|
|
8356
|
+
const committed = outcome.mapped + outcome.independent;
|
|
8357
|
+
result.mapped += outcome.mapped;
|
|
8358
|
+
result.independent += outcome.independent;
|
|
8359
|
+
result.remaining -= committed;
|
|
8360
|
+
if (committed > 0) {
|
|
8361
|
+
result.batches += 1;
|
|
8362
|
+
args.onProgress?.(result.mapped + result.independent);
|
|
8363
|
+
}
|
|
8364
|
+
if (outcome.requeue?.length) {
|
|
8365
|
+
if (!batch.isOmissionRetry) {
|
|
8366
|
+
batches.splice(i + 1, 0, {
|
|
8367
|
+
inputs: outcome.requeue,
|
|
8368
|
+
isOmissionRetry: true
|
|
8369
|
+
});
|
|
8370
|
+
log(`[dreamer] map-memories: committed ${committed}/${batch.inputs.length} mapping(s); requeueing ${outcome.requeue.length} omitted id(s) in a targeted retry`);
|
|
8371
|
+
} else {
|
|
8372
|
+
log(`[dreamer] map-memories: targeted retry still omitted ${outcome.requeue.length} id(s); leaving them unmapped for the next run`);
|
|
8373
|
+
}
|
|
8374
|
+
}
|
|
8375
|
+
if (outcome.failure?.class === "timeout") {
|
|
8376
|
+
consecutiveTimeouts += 1;
|
|
8377
|
+
timeoutStreakElapsedMs.push(outcome.failure.elapsedMs);
|
|
8378
|
+
if (consecutiveTimeouts >= CONSECUTIVE_TIMEOUT_LIMIT2) {
|
|
8379
|
+
result.stopReason = "timeout-circuit-breaker";
|
|
8380
|
+
log(`[dreamer] map-memories starvation: circuit breaker tripped after ${consecutiveTimeouts} consecutive batch timeouts (model too slow for its time slice); per-batch elapsed [${timeoutStreakElapsedMs.join("ms, ")}ms] vs ${sliceMs}ms slice; stopping with ${result.remaining} mapping(s) remaining`);
|
|
8381
|
+
break;
|
|
8382
|
+
}
|
|
8383
|
+
} else {
|
|
8384
|
+
consecutiveTimeouts = 0;
|
|
8385
|
+
timeoutStreakElapsedMs = [];
|
|
8386
|
+
}
|
|
8158
8387
|
}
|
|
8159
8388
|
result.complete = result.remaining === 0;
|
|
8160
|
-
log(`[dreamer] map-memories: mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}`);
|
|
8389
|
+
log(`[dreamer] map-memories: committed=${result.mapped + result.independent} mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}${result.stopReason ? ` stop_reason=${result.stopReason}` : ""}`);
|
|
8161
8390
|
return result;
|
|
8162
8391
|
} finally {
|
|
8163
8392
|
heartbeat.stop();
|
|
@@ -8211,12 +8440,16 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
8211
8440
|
const text = extractLatestAssistantText(messages);
|
|
8212
8441
|
if (!text)
|
|
8213
8442
|
throw new Error("map-memories returned no output");
|
|
8214
|
-
validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
|
|
8215
|
-
return text;
|
|
8443
|
+
return validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
|
|
8216
8444
|
}
|
|
8217
8445
|
});
|
|
8218
8446
|
recordInvocation2(args, startedAt, { status: "completed", messages: run.output });
|
|
8219
|
-
|
|
8447
|
+
const outcome = await applyParsedBatchMappings(args, batch, run.validated);
|
|
8448
|
+
const returnedIds = new Set(run.validated.filter((entry) => batch.some((memory) => memory.id === entry.id)).map((entry) => entry.id));
|
|
8449
|
+
return {
|
|
8450
|
+
...outcome,
|
|
8451
|
+
requeue: batch.filter((memory) => !returnedIds.has(memory.id))
|
|
8452
|
+
};
|
|
8220
8453
|
} catch (error) {
|
|
8221
8454
|
const desc = describeError(error);
|
|
8222
8455
|
log(`[dreamer] map-memories batch failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
@@ -8225,7 +8458,14 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
8225
8458
|
throw error;
|
|
8226
8459
|
if (signal.aborted)
|
|
8227
8460
|
throw error;
|
|
8228
|
-
return {
|
|
8461
|
+
return {
|
|
8462
|
+
mapped: 0,
|
|
8463
|
+
independent: 0,
|
|
8464
|
+
failure: {
|
|
8465
|
+
class: isTimeoutClassError2(error) ? "timeout" : "other",
|
|
8466
|
+
elapsedMs: Date.now() - startedAt
|
|
8467
|
+
}
|
|
8468
|
+
};
|
|
8229
8469
|
} finally {
|
|
8230
8470
|
if (agentSessionId && !shouldKeepSubagents()) {
|
|
8231
8471
|
await args.client.session.delete({
|
|
@@ -8237,14 +8477,21 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
8237
8477
|
}
|
|
8238
8478
|
}
|
|
8239
8479
|
}
|
|
8240
|
-
async function
|
|
8241
|
-
const batchIds = new Set(batch.map((
|
|
8242
|
-
const
|
|
8243
|
-
|
|
8244
|
-
if (
|
|
8480
|
+
async function applyParsedBatchMappings(args, batch, parsed) {
|
|
8481
|
+
const batchIds = new Set(batch.map((memory) => memory.id));
|
|
8482
|
+
const valid = parsed.filter((entry) => batchIds.has(entry.id));
|
|
8483
|
+
const unknown = parsed.filter((entry) => !batchIds.has(entry.id));
|
|
8484
|
+
if (unknown.length > 0) {
|
|
8485
|
+
log(`[dreamer] map-memories warning: dropping ${unknown.length} unknown mapping entr${unknown.length === 1 ? "y" : "ies"} outside the current batch (${unknown.map((entry) => entry.id).join(", ")})`);
|
|
8486
|
+
}
|
|
8487
|
+
assertNoDuplicateManifestIds(valid.map((entry) => entry.id), "mappings");
|
|
8488
|
+
if (valid.length * 2 < batch.length) {
|
|
8489
|
+
throw new Error(`mappings manifest covers ${valid.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
|
|
8490
|
+
}
|
|
8491
|
+
if (valid.length === 0)
|
|
8245
8492
|
return { mapped: 0, independent: 0 };
|
|
8246
8493
|
const planned = [];
|
|
8247
|
-
for (const p of
|
|
8494
|
+
for (const p of valid) {
|
|
8248
8495
|
if (p.independent) {
|
|
8249
8496
|
planned.push({ id: p.id, files: [], independent: true });
|
|
8250
8497
|
continue;
|
|
@@ -9549,14 +9796,13 @@ function parseVerifyManifest(text) {
|
|
|
9549
9796
|
if (verifyIds(out).length === 0 && body.trim().length > 0) {
|
|
9550
9797
|
throw new Error(describeUnrecognizedManifestShape(text, "verify", "verified"));
|
|
9551
9798
|
}
|
|
9552
|
-
assertNoDuplicateManifestIds(verifyIds(out), "verify");
|
|
9553
9799
|
return out;
|
|
9554
9800
|
}
|
|
9555
9801
|
function validateVerifyManifest(text, expectedIds) {
|
|
9556
9802
|
const parsed = parseVerifyManifest(text);
|
|
9557
9803
|
const ids = verifyIds(parsed);
|
|
9558
9804
|
assertParsedManifestNonEmpty(ids.length, expectedIds.size, text, "verify", "verified");
|
|
9559
|
-
|
|
9805
|
+
assertNoDuplicateManifestIds(ids.filter((id) => expectedIds.has(id)), "verify");
|
|
9560
9806
|
return parsed;
|
|
9561
9807
|
}
|
|
9562
9808
|
|
|
@@ -9709,19 +9955,14 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
9709
9955
|
const text = extractLatestAssistantText(messages);
|
|
9710
9956
|
if (!text)
|
|
9711
9957
|
throw new Error("verify returned no output");
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
if (providerFailure)
|
|
9717
|
-
throw providerFailure;
|
|
9718
|
-
throw error;
|
|
9719
|
-
}
|
|
9720
|
-
return text;
|
|
9958
|
+
const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
|
|
9959
|
+
if (providerFailure)
|
|
9960
|
+
throw providerFailure;
|
|
9961
|
+
return validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
|
|
9721
9962
|
}
|
|
9722
9963
|
});
|
|
9723
9964
|
recordInvocation4(args, startedAt, { status: "completed", messages: run.output });
|
|
9724
|
-
return await
|
|
9965
|
+
return await applyParsedVerifyManifest(args, batch, run.validated);
|
|
9725
9966
|
} catch (error) {
|
|
9726
9967
|
const desc = describeError(error);
|
|
9727
9968
|
const providerFailure = error instanceof DreamerProviderOutputFailureError ? error : undefined;
|
|
@@ -9741,17 +9982,31 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
9741
9982
|
}
|
|
9742
9983
|
}
|
|
9743
9984
|
}
|
|
9744
|
-
async function
|
|
9985
|
+
async function applyParsedVerifyManifest(args, batch, parsed) {
|
|
9745
9986
|
const batchIds = new Set(batch.map((m) => m.id));
|
|
9746
|
-
const
|
|
9747
|
-
|
|
9987
|
+
const valid = {
|
|
9988
|
+
verified: parsed.verified.filter((entry) => batchIds.has(entry.id)),
|
|
9989
|
+
updated: parsed.updated.filter((entry) => batchIds.has(entry.id)),
|
|
9990
|
+
archived: parsed.archived.filter((entry) => batchIds.has(entry.id))
|
|
9991
|
+
};
|
|
9992
|
+
const unknown = [...parsed.verified, ...parsed.updated, ...parsed.archived].filter((entry) => !batchIds.has(entry.id));
|
|
9993
|
+
if (unknown.length > 0) {
|
|
9994
|
+
log(`[dreamer] verify warning: dropping ${unknown.length} unknown verification entr${unknown.length === 1 ? "y" : "ies"} outside the current batch (${unknown.map((entry) => entry.id).join(", ")})`);
|
|
9995
|
+
}
|
|
9996
|
+
const validIds = [...valid.verified, ...valid.updated, ...valid.archived].map((entry) => entry.id);
|
|
9997
|
+
assertNoDuplicateManifestIds(validIds, "verify");
|
|
9998
|
+
if (validIds.length * 2 < batch.length) {
|
|
9999
|
+
throw new Error(`verify manifest covers ${validIds.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
|
|
10000
|
+
}
|
|
10001
|
+
if (validIds.length === 0)
|
|
10002
|
+
return { verified: 0, updated: 0, archived: 0 };
|
|
9748
10003
|
const now = Date.now();
|
|
9749
10004
|
const writes = [];
|
|
9750
|
-
for (const v of
|
|
10005
|
+
for (const v of valid.verified) {
|
|
9751
10006
|
const files = await normalizeFiles(args, v.files);
|
|
9752
10007
|
writes.push({ kind: "verify", id: v.id, files });
|
|
9753
10008
|
}
|
|
9754
|
-
for (const u of
|
|
10009
|
+
for (const u of valid.updated) {
|
|
9755
10010
|
const content = u.content.trim();
|
|
9756
10011
|
if (!content || content.length > 20000) {
|
|
9757
10012
|
const files2 = await normalizeFiles(args, u.files);
|
|
@@ -9767,7 +10022,7 @@ async function applyVerifyManifest(args, batch, manifestText) {
|
|
|
9767
10022
|
hash: computeNormalizedHash(content)
|
|
9768
10023
|
});
|
|
9769
10024
|
}
|
|
9770
|
-
for (const a of
|
|
10025
|
+
for (const a of valid.archived) {
|
|
9771
10026
|
writes.push({ kind: "archive", id: a.id, reason: a.reason });
|
|
9772
10027
|
}
|
|
9773
10028
|
if (writes.length === 0)
|
|
@@ -10074,7 +10329,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
10074
10329
|
leaseKey,
|
|
10075
10330
|
deadline,
|
|
10076
10331
|
leaseAcquisition,
|
|
10077
|
-
model: config.model
|
|
10332
|
+
model: config.model,
|
|
10078
10333
|
fallbackModels: config.fallbackModels,
|
|
10079
10334
|
moduleRoute,
|
|
10080
10335
|
onProgress: (processed) => reportProgress(processed)
|
|
@@ -10123,8 +10378,19 @@ function createDreamTaskExecutor(deps) {
|
|
|
10123
10378
|
moduleRoute,
|
|
10124
10379
|
onProgress: (processed) => reportProgress(processed)
|
|
10125
10380
|
});
|
|
10126
|
-
log(`[dreamer] map-memories: mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining}`);
|
|
10381
|
+
log(`[dreamer] map-memories: committed=${result.mapped + result.independent} mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}${result.stopReason ? ` stop_reason=${result.stopReason}` : ""}`);
|
|
10127
10382
|
if (!result.complete) {
|
|
10383
|
+
if (result.stopReason === "timeout-circuit-breaker") {
|
|
10384
|
+
const error2 = `map-memories starvation: timeout circuit breaker stopped the run with ${result.remaining} remain`;
|
|
10385
|
+
recordRun("failed", error2);
|
|
10386
|
+
return { status: "failed", transient: true, error: error2 };
|
|
10387
|
+
}
|
|
10388
|
+
const processed = result.mapped + result.independent;
|
|
10389
|
+
if (processed > 0) {
|
|
10390
|
+
const progress = `map-memories: committed ${processed} mapping(s) (mapped ${result.mapped}, independent ${result.independent}); ${result.remaining} remain`;
|
|
10391
|
+
recordRun("completed", null, { progress });
|
|
10392
|
+
return { status: "completed" };
|
|
10393
|
+
}
|
|
10128
10394
|
const error = incompleteMessage(result.remaining);
|
|
10129
10395
|
recordRun("failed", error);
|
|
10130
10396
|
return { status: "failed", transient: true, error };
|
|
@@ -10951,6 +11217,7 @@ async function runDueTasksForProject(deps) {
|
|
|
10951
11217
|
import { statSync as statSync2 } from "node:fs";
|
|
10952
11218
|
|
|
10953
11219
|
// ../plugin/src/features/magic-context/dreamer/retrospective-orphan-sweep.ts
|
|
11220
|
+
var HISTORIAN_CHILD_TITLE = "magic-context-compartment";
|
|
10954
11221
|
var RETROSPECTIVE_CHILD_TITLE = "magic-context-dream-retrospective";
|
|
10955
11222
|
var USER_MEMORIES_CHILD_TITLE = "magic-context-dream-user-memories";
|
|
10956
11223
|
var CURATE_CHILD_TITLE = "magic-context-dream-curate";
|
|
@@ -10976,16 +11243,34 @@ var PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES = {
|
|
|
10976
11243
|
],
|
|
10977
11244
|
prefixes: [SMART_NOTE_COMPILE_CHILD_TITLE_PREFIX, SMART_NOTE_CONFIRM_CHILD_TITLE_PREFIX]
|
|
10978
11245
|
};
|
|
11246
|
+
var HISTORIAN_CHILD_TITLE_MATCHES = {
|
|
11247
|
+
exact: [HISTORIAN_CHILD_TITLE],
|
|
11248
|
+
prefixes: []
|
|
11249
|
+
};
|
|
11250
|
+
var INTERNAL_CHILD_TITLE_MATCHES = {
|
|
11251
|
+
exact: [HISTORIAN_CHILD_TITLE, ...PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES.exact],
|
|
11252
|
+
prefixes: PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES.prefixes
|
|
11253
|
+
};
|
|
10979
11254
|
function retrospectiveOrphanStaleMs(taskTimeoutMinutes) {
|
|
10980
11255
|
const timeoutCandidates = Array.isArray(taskTimeoutMinutes) ? taskTimeoutMinutes : [taskTimeoutMinutes];
|
|
10981
11256
|
const maxTimeoutMinutes = Math.max(...timeoutCandidates.map((minutes) => Math.max(1, minutes ?? 20)), 20);
|
|
10982
11257
|
const timeoutMs = maxTimeoutMinutes * 60000;
|
|
10983
11258
|
return Math.max(60 * 60000, timeoutMs * 3);
|
|
10984
11259
|
}
|
|
11260
|
+
var HISTORIAN_OUTER_ATTEMPTS = 3;
|
|
11261
|
+
var HISTORIAN_MODEL_SUGGESTION_ATTEMPTS = 2;
|
|
11262
|
+
var HISTORIAN_MAX_RETRY_BACKOFF_MS = 11000;
|
|
11263
|
+
var HISTORIAN_DETACHED_WRITER_GRACE_MS = 15 * 60000;
|
|
11264
|
+
function historianOrphanStaleMs(timeoutMs, fallbackModelCount) {
|
|
11265
|
+
const timeout = Math.max(60000, timeoutMs);
|
|
11266
|
+
const fallbackCount = Math.max(0, Math.floor(fallbackModelCount));
|
|
11267
|
+
const fullAttemptBudget = timeout * HISTORIAN_OUTER_ATTEMPTS * HISTORIAN_MODEL_SUGGESTION_ATTEMPTS * (fallbackCount + 1);
|
|
11268
|
+
return Math.max(60 * 60000, fullAttemptBudget + HISTORIAN_MAX_RETRY_BACKOFF_MS + HISTORIAN_DETACHED_WRITER_GRACE_MS);
|
|
11269
|
+
}
|
|
10985
11270
|
async function sweepOrphanedRetrospectiveChildren(args) {
|
|
10986
11271
|
const { opencodeDb, client, sessionDirectory, staleMs } = args;
|
|
10987
|
-
const titleMatches = args.titleMatches ??
|
|
10988
|
-
if (!opencodeDb)
|
|
11272
|
+
const titleMatches = args.titleMatches ?? INTERNAL_CHILD_TITLE_MATCHES;
|
|
11273
|
+
if (!opencodeDb || args.keepSubagents === true)
|
|
10989
11274
|
return 0;
|
|
10990
11275
|
const now = args.now ?? Date.now();
|
|
10991
11276
|
const cutoff = now - staleMs;
|
|
@@ -11008,7 +11293,7 @@ async function sweepOrphanedRetrospectiveChildren(args) {
|
|
|
11008
11293
|
ORDER BY time_created ASC
|
|
11009
11294
|
LIMIT 200`).all(...titleParams, sessionDirectory, cutoff);
|
|
11010
11295
|
} catch (error) {
|
|
11011
|
-
log(`[
|
|
11296
|
+
log(`[magic-context] internal child orphan sweep: read skipped (${String(error)})`);
|
|
11012
11297
|
return 0;
|
|
11013
11298
|
}
|
|
11014
11299
|
if (rows.length === 0)
|
|
@@ -11023,7 +11308,7 @@ async function sweepOrphanedRetrospectiveChildren(args) {
|
|
|
11023
11308
|
}
|
|
11024
11309
|
}
|
|
11025
11310
|
if (deleted > 0) {
|
|
11026
|
-
log(`[
|
|
11311
|
+
log(`[magic-context] swept ${deleted} stale internal child session(s)`);
|
|
11027
11312
|
}
|
|
11028
11313
|
return deleted;
|
|
11029
11314
|
}
|
|
@@ -11163,7 +11448,7 @@ function scheduleInitialProjectRun(reg, db) {
|
|
|
11163
11448
|
startupTimers.set(reg.directory, timer);
|
|
11164
11449
|
}
|
|
11165
11450
|
async function runProjectMaintenance(reg, origin, db) {
|
|
11166
|
-
const projectMaintenanceEnabled = Boolean(reg.dreamerConfig && reg.dreamerConfig.disable !== true) || reg.memoryEnabled === true || reg.gitCommitIndexing?.enabled === true;
|
|
11451
|
+
const projectMaintenanceEnabled = Boolean(reg.dreamerConfig && reg.dreamerConfig.disable !== true) || reg.memoryEnabled === true || reg.gitCommitIndexing?.enabled === true || reg.historianChildSweep !== undefined;
|
|
11167
11452
|
if (!projectMaintenanceEnabled)
|
|
11168
11453
|
return;
|
|
11169
11454
|
await reg.ensureRegistered(reg.directory, db);
|
|
@@ -11200,6 +11485,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
|
|
|
11200
11485
|
if (gcDeleted > 0) {
|
|
11201
11486
|
log(`[magic-context] GC'd ${gcDeleted} stale embedding row(s) for ${reg.projectIdentity} ` + `(memory=${gc.memoryRowsDeleted} commit=${gc.commitRowsDeleted} chunk=${gc.chunkRowsDeleted})`);
|
|
11202
11487
|
}
|
|
11488
|
+
await sweepOrphanedHistorianChildren(reg);
|
|
11203
11489
|
const dreamerConfig = reg.dreamerConfig;
|
|
11204
11490
|
const dreamingEnabled = Boolean(dreamerConfig && dreamerConfig.disable !== true);
|
|
11205
11491
|
if (commitIndexingEnabled && reg.gitCommitIndexing) {
|
|
@@ -11215,7 +11501,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
|
|
|
11215
11501
|
}
|
|
11216
11502
|
try {
|
|
11217
11503
|
await runCompiledSmartNoteSweep(reg, db);
|
|
11218
|
-
const runtimeConfigs = buildDreamTaskRuntimeConfigs(dreamerConfig, reg.language);
|
|
11504
|
+
const runtimeConfigs = buildDreamTaskRuntimeConfigs(dreamerConfig, "opencode", reg.language, reg.mural?.model);
|
|
11219
11505
|
const executor = createDreamTaskExecutor({
|
|
11220
11506
|
client: reg.client,
|
|
11221
11507
|
sessionDirectory: reg.directory,
|
|
@@ -11225,7 +11511,6 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
|
|
|
11225
11511
|
userMemoryCollectionEnabled: userMemoryCollectionEnabled(dreamerConfig),
|
|
11226
11512
|
ensureProjectRegistered: reg.ensureRegistered,
|
|
11227
11513
|
language: reg.language,
|
|
11228
|
-
dreamerModel: dreamerConfig.model,
|
|
11229
11514
|
mural: reg.mural,
|
|
11230
11515
|
memoryInjectionBudgetTokens: reg.memoryInjectionBudgetTokens,
|
|
11231
11516
|
retinaHandoff: reg.retinaHandoff,
|
|
@@ -11263,6 +11548,27 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
|
|
|
11263
11548
|
log(`[dreamer] timer-triggered task scheduling failed for ${reg.projectIdentity}:`, error);
|
|
11264
11549
|
}
|
|
11265
11550
|
}
|
|
11551
|
+
async function sweepOrphanedHistorianChildren(reg) {
|
|
11552
|
+
const config = reg.historianChildSweep;
|
|
11553
|
+
if (!config || config.keepSubagents)
|
|
11554
|
+
return;
|
|
11555
|
+
const ocDb = openOpenCodeDb();
|
|
11556
|
+
if (!ocDb)
|
|
11557
|
+
return;
|
|
11558
|
+
try {
|
|
11559
|
+
await sweepOrphanedRetrospectiveChildren({
|
|
11560
|
+
opencodeDb: ocDb,
|
|
11561
|
+
client: reg.client,
|
|
11562
|
+
sessionDirectory: reg.directory,
|
|
11563
|
+
staleMs: historianOrphanStaleMs(config.timeoutMs, config.fallbackModelCount),
|
|
11564
|
+
titleMatches: HISTORIAN_CHILD_TITLE_MATCHES
|
|
11565
|
+
});
|
|
11566
|
+
} catch (error) {
|
|
11567
|
+
log(`[magic-context] historian child orphan sweep failed for ${reg.projectIdentity}:`, error);
|
|
11568
|
+
} finally {
|
|
11569
|
+
closeQuietly(ocDb);
|
|
11570
|
+
}
|
|
11571
|
+
}
|
|
11266
11572
|
async function runCompiledSmartNoteSweep(reg, db) {
|
|
11267
11573
|
const leaseKey = leaseKeyFor("evaluate-smart-notes", reg.projectIdentity);
|
|
11268
11574
|
const holderId = crypto.randomUUID();
|
|
@@ -11590,11 +11896,13 @@ function registerPiDreamerProject(opts) {
|
|
|
11590
11896
|
startDreamScheduleTimerFn({
|
|
11591
11897
|
directory: opts.projectDir,
|
|
11592
11898
|
projectIdentity: opts.projectIdentity,
|
|
11899
|
+
harness: "pi",
|
|
11593
11900
|
client,
|
|
11594
11901
|
dreamerConfig: opts.config,
|
|
11595
11902
|
language: opts.language,
|
|
11596
11903
|
gitCommitIndexing: opts.gitCommitIndexing,
|
|
11597
11904
|
retinaHandoff: opts.retinaHandoff,
|
|
11905
|
+
mural: opts.mural,
|
|
11598
11906
|
ensureRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
11599
11907
|
retrospectiveRawProvider: () => new PiRetrospectiveRawProvider({ projectCwd: opts.projectDir }),
|
|
11600
11908
|
primerRawProviderFactory: createPiPrimerRawProviderFactory()
|
|
@@ -11608,7 +11916,7 @@ function registerPiDreamerProject(opts) {
|
|
|
11608
11916
|
const runManual = async (task) => runManualDream({
|
|
11609
11917
|
db: opts.db,
|
|
11610
11918
|
projectIdentity: opts.projectIdentity,
|
|
11611
|
-
tasks: buildDreamTaskRuntimeConfigs(opts.config, opts.language),
|
|
11919
|
+
tasks: buildDreamTaskRuntimeConfigs(opts.config, "pi", opts.language, opts.mural?.model),
|
|
11612
11920
|
executor: createDreamTaskExecutor({
|
|
11613
11921
|
client,
|
|
11614
11922
|
sessionDirectory: opts.projectDir,
|
|
@@ -11620,7 +11928,8 @@ function registerPiDreamerProject(opts) {
|
|
|
11620
11928
|
userMemoryCollectionEnabled: userMemoryCollectionEnabled(opts.config),
|
|
11621
11929
|
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
11622
11930
|
language: opts.language,
|
|
11623
|
-
retinaHandoff: opts.retinaHandoff
|
|
11931
|
+
retinaHandoff: opts.retinaHandoff,
|
|
11932
|
+
mural: opts.mural
|
|
11624
11933
|
}),
|
|
11625
11934
|
task
|
|
11626
11935
|
});
|
|
@@ -11656,7 +11965,6 @@ async function awaitInFlightDreamers() {
|
|
|
11656
11965
|
}
|
|
11657
11966
|
function createPiDreamerClient(opts) {
|
|
11658
11967
|
const runner = piSubagentRunnerFactory();
|
|
11659
|
-
const model = opts.config.model;
|
|
11660
11968
|
const session = {
|
|
11661
11969
|
create: async (args) => {
|
|
11662
11970
|
const sessionId = `magic-context-pi-dream-${++sessionCounter}`;
|
|
@@ -11677,7 +11985,7 @@ function createPiDreamerClient(opts) {
|
|
|
11677
11985
|
}
|
|
11678
11986
|
const userMessage = extractUserMessage(args);
|
|
11679
11987
|
const systemPrompt = extractSystemPrompt(args);
|
|
11680
|
-
const perTaskModel = extractBodyModel(args)
|
|
11988
|
+
const perTaskModel = extractBodyModel(args);
|
|
11681
11989
|
const requestedAgent = extractBodyAgent(args) ?? "magic-context-dreamer";
|
|
11682
11990
|
const runPromise = runner.run({
|
|
11683
11991
|
agent: requestedAgent,
|
|
@@ -11688,7 +11996,7 @@ function createPiDreamerClient(opts) {
|
|
|
11688
11996
|
timeoutMs: 30 * 60 * 1000,
|
|
11689
11997
|
cwd: dreamSession.directory,
|
|
11690
11998
|
signal: args.signal ?? undefined,
|
|
11691
|
-
thinkingLevel:
|
|
11999
|
+
thinkingLevel: extractBodyVariant(args)
|
|
11692
12000
|
});
|
|
11693
12001
|
inFlightDreams.add(runPromise);
|
|
11694
12002
|
try {
|
|
@@ -11779,6 +12087,13 @@ function extractBodyModel(args) {
|
|
|
11779
12087
|
}
|
|
11780
12088
|
return;
|
|
11781
12089
|
}
|
|
12090
|
+
function extractBodyVariant(args) {
|
|
12091
|
+
const body = args.body;
|
|
12092
|
+
if (typeof body !== "object" || body === null)
|
|
12093
|
+
return;
|
|
12094
|
+
const variant = body.variant;
|
|
12095
|
+
return typeof variant === "string" && variant.length > 0 ? variant : undefined;
|
|
12096
|
+
}
|
|
11782
12097
|
function extractBodyAgent(args) {
|
|
11783
12098
|
const body = args.body;
|
|
11784
12099
|
if (typeof body !== "object" || body === null)
|
|
@@ -12916,10 +13231,19 @@ function writeTransformDecisionRow(dbPath, row) {
|
|
|
12916
13231
|
function writeTransformDecisionRowOnDatabase(db, row, configureBusyTimeout) {
|
|
12917
13232
|
if (configureBusyTimeout)
|
|
12918
13233
|
db.exec("PRAGMA busy_timeout=0");
|
|
13234
|
+
const systemHashPrev = row.materialized ? row.systemHashPrev : null;
|
|
13235
|
+
const systemHashNew = row.materialized ? row.systemHashNew : null;
|
|
13236
|
+
const m0ModelKeyPrev = row.materialized ? row.m0ModelKeyPrev : null;
|
|
13237
|
+
const m0ModelKeyNew = row.materialized ? row.m0ModelKeyNew : null;
|
|
13238
|
+
const m0ToolSetHashPrev = row.m0ToolSetHashPrev ?? null;
|
|
13239
|
+
const m0ToolSetHashNew = row.m0ToolSetHashNew ?? null;
|
|
12919
13240
|
db.prepare(`INSERT OR REPLACE INTO transform_decisions (
|
|
12920
13241
|
session_id, harness, message_id, ts_ms, decision, materialized,
|
|
12921
|
-
materialize_reason,
|
|
12922
|
-
|
|
13242
|
+
materialize_reason, system_hash_prev, system_hash_new,
|
|
13243
|
+
m0_tool_set_hash_prev, m0_tool_set_hash_new,
|
|
13244
|
+
m0_model_key_prev, m0_model_key_new, emergency, dropped_tokens,
|
|
13245
|
+
dropped_count, input_tokens
|
|
13246
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.sessionId, row.harness, row.messageId, row.tsMs, row.decision, row.materialized ? 1 : 0, row.materializeReason, systemHashPrev, systemHashNew, m0ToolSetHashPrev, m0ToolSetHashNew, m0ModelKeyPrev, m0ModelKeyNew, row.emergency ? 1 : 0, Math.max(0, Math.floor(row.droppedTokens)), Math.max(0, Math.floor(row.droppedCount)), Math.max(0, Math.floor(row.inputTokens)));
|
|
12923
13247
|
db.prepare(`DELETE FROM transform_decisions
|
|
12924
13248
|
WHERE session_id = ? AND harness = ?
|
|
12925
13249
|
AND rowid NOT IN (
|
|
@@ -15975,6 +16299,17 @@ function isSyntheticMessage(message, index, input) {
|
|
|
15975
16299
|
const role = typeof message.role === "string" ? message.role : "";
|
|
15976
16300
|
return role === "system" || role === "custom" || role === "compactionSummary";
|
|
15977
16301
|
}
|
|
16302
|
+
function countRealPiUserMessages(input) {
|
|
16303
|
+
let count = 0;
|
|
16304
|
+
for (let index = 0;index < input.messages.length; index += 1) {
|
|
16305
|
+
const message = input.messages[index];
|
|
16306
|
+
if (!isRecord3(message) || message.role !== "user")
|
|
16307
|
+
continue;
|
|
16308
|
+
if (!isSyntheticMessage(message, index, input))
|
|
16309
|
+
count += 1;
|
|
16310
|
+
}
|
|
16311
|
+
return count;
|
|
16312
|
+
}
|
|
15978
16313
|
function imageContentAndTokens(part) {
|
|
15979
16314
|
const data = typeof part.data === "string" ? part.data : "";
|
|
15980
16315
|
const mimeType = typeof part.mimeType === "string" ? part.mimeType : "image/png";
|
|
@@ -16168,7 +16503,7 @@ function excludedDraft(key, value) {
|
|
|
16168
16503
|
tokens: 0
|
|
16169
16504
|
};
|
|
16170
16505
|
}
|
|
16171
|
-
function finalizeParts(drafts, protectedTags) {
|
|
16506
|
+
function finalizeParts(drafts, protectedTags, pendingDropTagNumbers) {
|
|
16172
16507
|
const visibleTags = new Map;
|
|
16173
16508
|
for (const part of drafts) {
|
|
16174
16509
|
if (part.kind !== "excluded" && part.tag)
|
|
@@ -16183,7 +16518,8 @@ function finalizeParts(drafts, protectedTags) {
|
|
|
16183
16518
|
const parts = drafts.map((draft) => {
|
|
16184
16519
|
const protectedPart = draft.tag ? protectedNumbers.has(draft.tag.tagNumber) : false;
|
|
16185
16520
|
const tokens = Math.max(0, draft.tokens);
|
|
16186
|
-
const
|
|
16521
|
+
const queuedForDrop = draft.tag ? pendingDropTagNumbers.has(draft.tag.tagNumber) : false;
|
|
16522
|
+
const uTokens = draft.tag && !protectedPart && !queuedForDrop && draft.kind !== "excluded" ? tokens : 0;
|
|
16187
16523
|
t += tokens;
|
|
16188
16524
|
u += uTokens;
|
|
16189
16525
|
return {
|
|
@@ -16194,7 +16530,8 @@ function finalizeParts(drafts, protectedTags) {
|
|
|
16194
16530
|
uTokens,
|
|
16195
16531
|
tagNumber: draft.tag?.tagNumber ?? null,
|
|
16196
16532
|
tagStatus: draft.tag ? "active" : null,
|
|
16197
|
-
protected: protectedPart
|
|
16533
|
+
protected: protectedPart,
|
|
16534
|
+
queuedForDrop
|
|
16198
16535
|
};
|
|
16199
16536
|
});
|
|
16200
16537
|
const clampedT = Math.max(0, t);
|
|
@@ -16336,29 +16673,34 @@ function measurePiTailHygiene(input) {
|
|
|
16336
16673
|
drafts.push(excludedDraft(`${key}\x00excluded`, part));
|
|
16337
16674
|
}
|
|
16338
16675
|
}
|
|
16339
|
-
return finalizeParts(drafts, input.protectedTags);
|
|
16676
|
+
return finalizeParts(drafts, input.protectedTags, input.pendingDropTagNumbers ?? new Set);
|
|
16340
16677
|
}
|
|
16341
16678
|
function sameMeasuredPrefix(baseline, current) {
|
|
16342
16679
|
if (current.length < baseline.length)
|
|
16343
|
-
return { valid: false, boundaryAdvanceU: 0 };
|
|
16680
|
+
return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
|
|
16344
16681
|
let boundaryAdvanceU = 0;
|
|
16682
|
+
let queuedDropDeltaU = 0;
|
|
16345
16683
|
for (let index = 0;index < baseline.length; index += 1) {
|
|
16346
16684
|
const before = baseline[index];
|
|
16347
16685
|
const after = current[index];
|
|
16348
16686
|
if (before.key !== after.key || before.contentHash !== after.contentHash || before.kind !== after.kind || before.tokens !== after.tokens || before.tagNumber !== after.tagNumber || before.tagStatus !== after.tagStatus) {
|
|
16349
|
-
return { valid: false, boundaryAdvanceU: 0 };
|
|
16687
|
+
return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
|
|
16350
16688
|
}
|
|
16351
16689
|
if (!before.protected && after.protected)
|
|
16352
|
-
return { valid: false, boundaryAdvanceU: 0 };
|
|
16690
|
+
return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
|
|
16353
16691
|
if (before.protected && !after.protected) {
|
|
16354
16692
|
if (after.tagStatus !== "active")
|
|
16355
|
-
return { valid: false, boundaryAdvanceU: 0 };
|
|
16356
|
-
boundaryAdvanceU += after.
|
|
16693
|
+
return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
|
|
16694
|
+
boundaryAdvanceU += after.uTokens;
|
|
16695
|
+
} else if (before.queuedForDrop !== after.queuedForDrop) {
|
|
16696
|
+
if (before.tagStatus !== "active" || after.tagStatus !== "active")
|
|
16697
|
+
return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
|
|
16698
|
+
queuedDropDeltaU += after.uTokens - before.uTokens;
|
|
16357
16699
|
} else if (before.uTokens !== after.uTokens) {
|
|
16358
|
-
return { valid: false, boundaryAdvanceU: 0 };
|
|
16700
|
+
return { valid: false, boundaryAdvanceU: 0, queuedDropDeltaU: 0 };
|
|
16359
16701
|
}
|
|
16360
16702
|
}
|
|
16361
|
-
return { valid: true, boundaryAdvanceU };
|
|
16703
|
+
return { valid: true, boundaryAdvanceU, queuedDropDeltaU };
|
|
16362
16704
|
}
|
|
16363
16705
|
function refreshPiTailHygieneBaseline(input) {
|
|
16364
16706
|
const measured = measurePiTailHygiene(input);
|
|
@@ -16390,7 +16732,7 @@ function refreshPiTailHygieneBaseline(input) {
|
|
|
16390
16732
|
};
|
|
16391
16733
|
}
|
|
16392
16734
|
let turnDeltaT = 0;
|
|
16393
|
-
let turnDeltaU = prefix.boundaryAdvanceU;
|
|
16735
|
+
let turnDeltaU = prefix.boundaryAdvanceU + prefix.queuedDropDeltaU;
|
|
16394
16736
|
for (let index = input.previous.baselineParts.length;index < measured.parts.length; index += 1) {
|
|
16395
16737
|
const part = measured.parts[index];
|
|
16396
16738
|
turnDeltaT += part.tokens;
|
|
@@ -16484,20 +16826,38 @@ function maybeChannel1ReminderForToolResult(args) {
|
|
|
16484
16826
|
if (deltaTokens === 0)
|
|
16485
16827
|
return null;
|
|
16486
16828
|
state2.turnDeltaT += deltaTokens;
|
|
16829
|
+
if (state2.agentDropsAppliedThisPass)
|
|
16830
|
+
return null;
|
|
16831
|
+
const nudgeState = getChannel1NudgeState(db, sessionId);
|
|
16487
16832
|
const decision = decideChannel1({
|
|
16488
16833
|
...state2,
|
|
16489
16834
|
lastNudgeUndropped: getLastNudgeUndropped(db, sessionId),
|
|
16490
|
-
lastNudgeLevel:
|
|
16835
|
+
lastNudgeLevel: nudgeState.level,
|
|
16491
16836
|
hasRecentReduce: state2.reducedSinceRefresh
|
|
16492
16837
|
});
|
|
16493
16838
|
setLastNudgeUndropped(db, sessionId, decision.nextLastNudge);
|
|
16494
|
-
|
|
16495
|
-
|
|
16839
|
+
if (!decision.fire) {
|
|
16840
|
+
setChannel1NudgeState(db, sessionId, {
|
|
16841
|
+
level: decision.nextLastNudgeLevel,
|
|
16842
|
+
ordinal: decision.nextLastNudgeLevel === "" ? 0 : nudgeState.ordinal
|
|
16843
|
+
});
|
|
16496
16844
|
return null;
|
|
16497
|
-
|
|
16845
|
+
}
|
|
16846
|
+
const sticky = shouldUseStickyChannel1Reminder({
|
|
16847
|
+
lastLevel: nudgeState.level,
|
|
16848
|
+
lastOrdinal: nudgeState.ordinal,
|
|
16849
|
+
level: decision.level,
|
|
16850
|
+
currentRealUserTurnCount: state2.realUserTurnCount
|
|
16851
|
+
});
|
|
16852
|
+
const block = {
|
|
16498
16853
|
type: "text",
|
|
16499
|
-
text: buildChannel1Reminder(decision.level, decision.undroppedTokens, state2.oldestReclaimableToolTags)
|
|
16854
|
+
text: buildChannel1Reminder(decision.level, decision.undroppedTokens, state2.usableWindow, state2.oldestReclaimableToolTags, sticky)
|
|
16500
16855
|
};
|
|
16856
|
+
setChannel1NudgeState(db, sessionId, {
|
|
16857
|
+
level: decision.level,
|
|
16858
|
+
ordinal: state2.realUserTurnCount
|
|
16859
|
+
});
|
|
16860
|
+
return block;
|
|
16501
16861
|
}
|
|
16502
16862
|
var CHANNEL2_NUDGE_CUSTOM_TYPE = "magic-context:ceiling-nudge";
|
|
16503
16863
|
function maybeDeliverChannel2Pi(pi, db, sessionId) {
|
|
@@ -16528,7 +16888,7 @@ function maybeDeliverChannel2Pi(pi, db, sessionId) {
|
|
|
16528
16888
|
try {
|
|
16529
16889
|
const message = {
|
|
16530
16890
|
customType: CHANNEL2_NUDGE_CUSTOM_TYPE,
|
|
16531
|
-
content: buildChannel2Reminder(undropped, baseline.oldestReclaimableToolTags),
|
|
16891
|
+
content: buildChannel2Reminder(undropped, baseline.usableWindow, baseline.oldestReclaimableToolTags),
|
|
16532
16892
|
display: false,
|
|
16533
16893
|
details: { kind: "channel-2-ceiling-nudge" }
|
|
16534
16894
|
};
|
|
@@ -17694,6 +18054,11 @@ function injectM0M1Pi(state2, db, piMessages, entryIds, recomputeM1ThisPass = fa
|
|
|
17694
18054
|
m0 = stripMemoryMuralBlock(m0);
|
|
17695
18055
|
prependM0M1Messages(piMessages, m0, m1, muralWire);
|
|
17696
18056
|
sessionLog(state2.sessionId, `injected m[0]/m[1] into Pi messages (${m0.length} + ${m1.length} bytes, materialized=${materialized}${decision.reason ? ` reason=${decision.reason}` : ""})`);
|
|
18057
|
+
const comparison = decision.mismatch;
|
|
18058
|
+
const systemHashPrev = comparison?.signal === "systemHash" && typeof comparison.cached === "string" ? comparison.cached : null;
|
|
18059
|
+
const systemHashNew = comparison?.signal === "systemHash" && typeof comparison.current === "string" ? comparison.current : null;
|
|
18060
|
+
const m0ModelKeyPrev = comparison?.signal === "modelKey" && typeof comparison.cached === "string" ? comparison.cached : null;
|
|
18061
|
+
const m0ModelKeyNew = comparison?.signal === "modelKey" && typeof comparison.current === "string" ? comparison.current : null;
|
|
17697
18062
|
const memPath = memoryProjectPath(state2);
|
|
17698
18063
|
const workspace = resolveWorkspaceRenderContextPi(state2, db);
|
|
17699
18064
|
const memoryCount = memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories).length : getMemoriesByProject(db, memPath, ["active", "permanent"]).length : 0;
|
|
@@ -17705,6 +18070,10 @@ function injectM0M1Pi(state2, db, piMessages, entryIds, recomputeM1ThisPass = fa
|
|
|
17705
18070
|
skippedVisibleMessages,
|
|
17706
18071
|
m0Materialized: materialized,
|
|
17707
18072
|
m0Reason: decision.reason,
|
|
18073
|
+
systemHashPrev: materialized ? systemHashPrev : null,
|
|
18074
|
+
systemHashNew: materialized ? systemHashNew : null,
|
|
18075
|
+
m0ModelKeyPrev: materialized ? m0ModelKeyPrev : null,
|
|
18076
|
+
m0ModelKeyNew: materialized ? m0ModelKeyNew : null,
|
|
17708
18077
|
m0Bytes: m0.length,
|
|
17709
18078
|
m1Bytes: m1.length,
|
|
17710
18079
|
contentionExhausted,
|
|
@@ -20860,7 +21229,7 @@ function buildReferenceBlocks(args) {
|
|
|
20860
21229
|
|
|
20861
21230
|
// src/pi-historian-runner.ts
|
|
20862
21231
|
var HISTORIAN_AGENT_NAME = "magic-context-historian";
|
|
20863
|
-
var DEFAULT_HISTORIAN_TIMEOUT_MS2 =
|
|
21232
|
+
var DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
|
|
20864
21233
|
var MAX_HISTORIAN_RETRIES = 2;
|
|
20865
21234
|
var HISTORIAN_ALERT_COOLDOWN_MS = 60 * 1000;
|
|
20866
21235
|
var lastHistorianAlertBySession = new Map;
|
|
@@ -20961,19 +21330,24 @@ async function runHistorianSubagentWithTransientRetries(args) {
|
|
|
20961
21330
|
}
|
|
20962
21331
|
return historianAbortResult(startedAt);
|
|
20963
21332
|
}
|
|
20964
|
-
function buildHistorianFallbackChain(primaryModel, fallbackModels, fallbackModelId) {
|
|
20965
|
-
const seen = new Set
|
|
20966
|
-
|
|
20967
|
-
|
|
21333
|
+
function buildHistorianFallbackChain(primaryModel, primaryThinkingLevel, fallbackModels, fallbackModelId) {
|
|
21334
|
+
const seen = new Set([
|
|
21335
|
+
`${primaryModel}\x00${primaryThinkingLevel ?? ""}`
|
|
21336
|
+
]);
|
|
20968
21337
|
const chain = [];
|
|
20969
21338
|
for (const candidate of fallbackModels ?? []) {
|
|
20970
|
-
|
|
21339
|
+
const entry = typeof candidate === "string" ? { model: candidate } : candidate;
|
|
21340
|
+
const key = `${entry.model}\x00${entry.qualifier ?? ""}`;
|
|
21341
|
+
if (!entry.model || seen.has(key))
|
|
20971
21342
|
continue;
|
|
20972
|
-
seen.add(
|
|
20973
|
-
chain.push({
|
|
21343
|
+
seen.add(key);
|
|
21344
|
+
chain.push({ entry, kind: "configured" });
|
|
20974
21345
|
}
|
|
20975
|
-
if (fallbackModelId
|
|
20976
|
-
|
|
21346
|
+
if (fallbackModelId) {
|
|
21347
|
+
const entry = { model: fallbackModelId };
|
|
21348
|
+
const key = `${entry.model}\x00`;
|
|
21349
|
+
if (!seen.has(key))
|
|
21350
|
+
chain.push({ entry, kind: "session" });
|
|
20977
21351
|
}
|
|
20978
21352
|
return chain;
|
|
20979
21353
|
}
|
|
@@ -21292,11 +21666,11 @@ ${chunkText}`,
|
|
|
21292
21666
|
validatedDraftText = repairResult.assistantText;
|
|
21293
21667
|
}
|
|
21294
21668
|
}
|
|
21295
|
-
const fallbackChain = buildHistorianFallbackChain(historianModel, fallbackModels, fallbackModelId);
|
|
21669
|
+
const fallbackChain = buildHistorianFallbackChain(historianModel, thinkingLevel, fallbackModels, fallbackModelId);
|
|
21296
21670
|
if (validatedPass.kind !== "ok" && !(validatedPass.kind === "spawn-failed" && validatedPass.reason === "abort") && fallbackChain.length > 0) {
|
|
21297
21671
|
for (let i = 0;i < fallbackChain.length; i += 1) {
|
|
21298
21672
|
const candidate = fallbackChain[i];
|
|
21299
|
-
sessionLog(sessionId, `historian: escalating to ${candidate.kind === "session" ? "session-model last resort" : "configured fallback model"} ${candidate.
|
|
21673
|
+
sessionLog(sessionId, `historian: escalating to ${candidate.kind === "session" ? "session-model last resort" : "configured fallback model"} ${candidate.entry.model}`);
|
|
21300
21674
|
const fbResult = await runHistorianSubagentWithTransientRetries({
|
|
21301
21675
|
runner,
|
|
21302
21676
|
sessionId,
|
|
@@ -21306,11 +21680,11 @@ ${chunkText}`,
|
|
|
21306
21680
|
agent: HISTORIAN_AGENT_NAME,
|
|
21307
21681
|
systemPrompt: historianSystemPrompt,
|
|
21308
21682
|
userMessage: prompt,
|
|
21309
|
-
model: candidate.
|
|
21683
|
+
model: candidate.entry.model,
|
|
21310
21684
|
timeoutMs: historianTimeoutMs,
|
|
21311
21685
|
cwd: directory,
|
|
21312
21686
|
signal,
|
|
21313
|
-
thinkingLevel,
|
|
21687
|
+
thinkingLevel: candidate.entry.qualifier,
|
|
21314
21688
|
onProgress: buildProgressLogger("fallback"),
|
|
21315
21689
|
accountingSessionId: sessionId,
|
|
21316
21690
|
accountingSubagent: "historian"
|
|
@@ -24324,6 +24698,10 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
24324
24698
|
decision: schedulerDecision,
|
|
24325
24699
|
materialized: result.materialized,
|
|
24326
24700
|
materializeReason: normalizeMaterializeReason("pi", result.materializeReason, result.materialized),
|
|
24701
|
+
systemHashPrev: result.materialized ? result.injectionResult?.systemHashPrev ?? null : null,
|
|
24702
|
+
systemHashNew: result.materialized ? result.injectionResult?.systemHashNew ?? null : null,
|
|
24703
|
+
m0ModelKeyPrev: result.materialized ? result.injectionResult?.m0ModelKeyPrev ?? null : null,
|
|
24704
|
+
m0ModelKeyNew: result.materialized ? result.injectionResult?.m0ModelKeyNew ?? null : null,
|
|
24327
24705
|
emergency: result.emergency,
|
|
24328
24706
|
droppedTokens: result.droppedTokens,
|
|
24329
24707
|
droppedCount: result.droppedCount,
|
|
@@ -24415,11 +24793,13 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
24415
24793
|
if (!options.compactionOff && !sessionMetaForCh1.isSubagent) {
|
|
24416
24794
|
const tags = getTagsBySession(options.db, sessionId);
|
|
24417
24795
|
const protectedTags = options.protectedTags ?? 20;
|
|
24796
|
+
const pendingDropTagNumbers = new Set(getPendingOps(options.db, sessionId).filter((operation) => operation.operation === "drop").map((operation) => operation.tagId));
|
|
24418
24797
|
const stableId = (message) => message && typeof message === "object" ? result.postCommitEntryIdByRef.get(message) : undefined;
|
|
24419
24798
|
const baseline = refreshPiTailHygieneBaseline({
|
|
24420
24799
|
messages: outputMessages,
|
|
24421
24800
|
tags,
|
|
24422
24801
|
protectedTags,
|
|
24802
|
+
pendingDropTagNumbers,
|
|
24423
24803
|
stableId,
|
|
24424
24804
|
syntheticLeadingCount: result.syntheticLeadingCount,
|
|
24425
24805
|
cacheBusting: result.bustedThisPass,
|
|
@@ -24430,7 +24810,17 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
24430
24810
|
const oldestReclaimableToolTags = getOldestActiveUnprotectedToolTags(options.db, sessionId, protectedTags);
|
|
24431
24811
|
const channelState = {
|
|
24432
24812
|
...baseline,
|
|
24813
|
+
usableWindow: usageContextLimit ?? 0,
|
|
24814
|
+
realUserTurnCount: countRealPiUserMessages({
|
|
24815
|
+
messages: outputMessages,
|
|
24816
|
+
tags,
|
|
24817
|
+
protectedTags,
|
|
24818
|
+
pendingDropTagNumbers,
|
|
24819
|
+
stableId,
|
|
24820
|
+
syntheticLeadingCount: result.syntheticLeadingCount
|
|
24821
|
+
}),
|
|
24433
24822
|
reducedSinceRefresh: false,
|
|
24823
|
+
agentDropsAppliedThisPass: result.agentDropsAppliedThisPass,
|
|
24434
24824
|
oldestReclaimableToolTags
|
|
24435
24825
|
};
|
|
24436
24826
|
setPiChannel1Baseline(sessionId, channelState);
|
|
@@ -24455,6 +24845,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
24455
24845
|
messages: outputMessages,
|
|
24456
24846
|
tags,
|
|
24457
24847
|
protectedTags,
|
|
24848
|
+
pendingDropTagNumbers,
|
|
24458
24849
|
stableId,
|
|
24459
24850
|
syntheticLeadingCount: result.syntheticLeadingCount,
|
|
24460
24851
|
expectedSignature: baseline.contentSignature
|
|
@@ -24984,6 +25375,7 @@ async function runCompactionOffPipeline(args) {
|
|
|
24984
25375
|
droppedCount: 0,
|
|
24985
25376
|
emergency: false,
|
|
24986
25377
|
bustedThisPass: injectionResult?.m0Materialized === true,
|
|
25378
|
+
agentDropsAppliedThisPass: false,
|
|
24987
25379
|
targetCount: 0,
|
|
24988
25380
|
reasoningWatermark: args.sessionMeta.clearedReasoningThroughTag ?? 0,
|
|
24989
25381
|
activeTags: [],
|
|
@@ -25425,7 +25817,11 @@ async function runPipeline(args) {
|
|
|
25425
25817
|
injectionResult = preFoldInjectionResult?.m0Materialized ? {
|
|
25426
25818
|
...wireInjectionResult,
|
|
25427
25819
|
m0Materialized: true,
|
|
25428
|
-
m0Reason: preFoldInjectionResult.m0Reason ?? wireInjectionResult.m0Reason
|
|
25820
|
+
m0Reason: preFoldInjectionResult.m0Reason ?? wireInjectionResult.m0Reason,
|
|
25821
|
+
systemHashPrev: preFoldInjectionResult.systemHashPrev ?? null,
|
|
25822
|
+
systemHashNew: preFoldInjectionResult.systemHashNew ?? null,
|
|
25823
|
+
m0ModelKeyPrev: preFoldInjectionResult.m0ModelKeyPrev ?? null,
|
|
25824
|
+
m0ModelKeyNew: preFoldInjectionResult.m0ModelKeyNew ?? null
|
|
25429
25825
|
} : wireInjectionResult;
|
|
25430
25826
|
if (args.temporalAwareness && injectionResult.skippedVisibleMessages > 0) {
|
|
25431
25827
|
const firstRetainedMessage = args.messages[injectionResult.syntheticLeadingCount];
|
|
@@ -25553,6 +25949,7 @@ async function runPipeline(args) {
|
|
|
25553
25949
|
droppedCount,
|
|
25554
25950
|
emergency,
|
|
25555
25951
|
bustedThisPass,
|
|
25952
|
+
agentDropsAppliedThisPass: pendingOpsDidMutate,
|
|
25556
25953
|
targetCount: targets.size,
|
|
25557
25954
|
reasoningWatermark: args.sessionMeta.clearedReasoningThroughTag ?? 0,
|
|
25558
25955
|
activeTags,
|
|
@@ -25845,6 +26242,7 @@ async function runValidatedHistorianPass(args) {
|
|
|
25845
26242
|
const firstRun = await runHistorianPrompt({
|
|
25846
26243
|
...args,
|
|
25847
26244
|
dumpLabel: `${args.dumpLabelBase}-initial`,
|
|
26245
|
+
modelOverride: args.model,
|
|
25848
26246
|
agentId: args.agentId
|
|
25849
26247
|
});
|
|
25850
26248
|
if (!firstRun.ok || !firstRun.result) {
|
|
@@ -25873,6 +26271,7 @@ async function runValidatedHistorianPass(args) {
|
|
|
25873
26271
|
...args,
|
|
25874
26272
|
prompt: repairPrompt,
|
|
25875
26273
|
dumpLabel: `${args.dumpLabelBase}-repair`,
|
|
26274
|
+
modelOverride: args.model,
|
|
25876
26275
|
agentId: args.agentId
|
|
25877
26276
|
});
|
|
25878
26277
|
if (!repairRun.ok || !repairRun.result) {
|
|
@@ -25913,7 +26312,8 @@ async function runEditorPassOrFallback(args) {
|
|
|
25913
26312
|
timeoutMs: args.timeoutMs,
|
|
25914
26313
|
dumpLabel: `${args.dumpLabelBase}-editor`,
|
|
25915
26314
|
agentId: HISTORIAN_EDITOR_AGENT,
|
|
25916
|
-
parentInvocationId: args.draftInvocationId ?? null
|
|
26315
|
+
parentInvocationId: args.draftInvocationId ?? null,
|
|
26316
|
+
modelOverride: args.model
|
|
25917
26317
|
});
|
|
25918
26318
|
if (!editorRun.ok || !editorRun.result) {
|
|
25919
26319
|
sessionLog(args.parentSessionId, "historian two-pass: editor call failed", {
|
|
@@ -25966,7 +26366,7 @@ async function runHistorianPrompt(args) {
|
|
|
25966
26366
|
});
|
|
25967
26367
|
};
|
|
25968
26368
|
try {
|
|
25969
|
-
sessionLog(parentSessionId, `historian: creating child session (agent=${
|
|
26369
|
+
sessionLog(parentSessionId, `historian: creating child session (agent=${toModelEntry(modelOverride)?.model ?? `agent:${agentId}`})`);
|
|
25970
26370
|
const createResponse = await createChildSessionWithFence({
|
|
25971
26371
|
client,
|
|
25972
26372
|
db,
|
|
@@ -25990,7 +26390,7 @@ async function runHistorianPrompt(args) {
|
|
|
25990
26390
|
query: { directory: sessionDirectory },
|
|
25991
26391
|
body: {
|
|
25992
26392
|
agent: agentId,
|
|
25993
|
-
...modelOverride
|
|
26393
|
+
...modelBodyField(modelOverride),
|
|
25994
26394
|
parts: [{ type: "text", text: prompt, synthetic: true }]
|
|
25995
26395
|
}
|
|
25996
26396
|
}, {
|
|
@@ -26051,22 +26451,30 @@ async function runHistorianPrompt(args) {
|
|
|
26051
26451
|
error: `Historian failed while processing this session: ${desc.brief}`
|
|
26052
26452
|
};
|
|
26053
26453
|
} finally {
|
|
26054
|
-
if (agentSessionId
|
|
26055
|
-
|
|
26056
|
-
|
|
26057
|
-
});
|
|
26058
|
-
} else if (agentSessionId && (!outcomeOk || shouldKeepSubagents())) {
|
|
26059
|
-
sessionLog(parentSessionId, `historian: KEEPING child session ${agentSessionId} (${outcomeOk ? "keep_subagents" : "failed"}) — not deleted`);
|
|
26454
|
+
if (agentSessionId) {
|
|
26455
|
+
const retentionReason = shouldKeepSubagents() ? "keep_subagents" : outcomeOk ? "prompt completed; cleanup deferred to the age-gated sweep" : "failed; cleanup deferred to the age-gated sweep";
|
|
26456
|
+
sessionLog(parentSessionId, `historian: KEEPING child session ${agentSessionId} (${retentionReason}) — not deleted inline`);
|
|
26060
26457
|
}
|
|
26061
26458
|
}
|
|
26062
26459
|
}
|
|
26063
26460
|
async function runFallbackHistorianPass(args) {
|
|
26064
26461
|
const seen = new Set;
|
|
26065
26462
|
const chain = [];
|
|
26066
|
-
|
|
26067
|
-
|
|
26463
|
+
const primary = toModelEntry(args.model);
|
|
26464
|
+
for (const candidateInput of [
|
|
26465
|
+
...args.fallbackModels ?? [],
|
|
26466
|
+
...args.fallbackModelId ? [{ model: args.fallbackModelId }] : []
|
|
26467
|
+
]) {
|
|
26468
|
+
const candidate = toModelEntry(candidateInput);
|
|
26469
|
+
if (!candidate)
|
|
26068
26470
|
continue;
|
|
26069
|
-
|
|
26471
|
+
const key = `${candidate.model}\x00${candidate.qualifier ?? ""}`;
|
|
26472
|
+
if (!candidate.model || seen.has(key))
|
|
26473
|
+
continue;
|
|
26474
|
+
if (primary?.model === candidate.model && primary.qualifier === candidate.qualifier) {
|
|
26475
|
+
continue;
|
|
26476
|
+
}
|
|
26477
|
+
seen.add(key);
|
|
26070
26478
|
chain.push(candidate);
|
|
26071
26479
|
}
|
|
26072
26480
|
if (chain.length === 0) {
|
|
@@ -26074,9 +26482,9 @@ async function runFallbackHistorianPass(args) {
|
|
|
26074
26482
|
}
|
|
26075
26483
|
let lastError = args.error;
|
|
26076
26484
|
for (let i = 0;i < chain.length; i += 1) {
|
|
26077
|
-
const
|
|
26078
|
-
const
|
|
26079
|
-
if (!
|
|
26485
|
+
const modelOverride = chain[i];
|
|
26486
|
+
const modelId = modelOverride.model;
|
|
26487
|
+
if (!parseModelOverride(modelId))
|
|
26080
26488
|
continue;
|
|
26081
26489
|
const isSessionModelLastResort = modelId === args.fallbackModelId && i === chain.length - 1;
|
|
26082
26490
|
sessionLog(args.parentSessionId, `compartment agent: retrying historian with ${modelId} (${isSessionModelLastResort ? "session-model last resort" : "configured fallback"} ${i + 1}/${chain.length})`);
|
|
@@ -26405,6 +26813,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
|
|
|
26405
26813
|
sequenceOffset: candidateCompartments.length,
|
|
26406
26814
|
dumpLabelBase: `recomp-${sessionId}-${chunk.startIndex}-${chunk.endIndex}-pass-${passCount + 1}`,
|
|
26407
26815
|
timeoutMs: historianTimeoutMs,
|
|
26816
|
+
model: deps.model,
|
|
26408
26817
|
fallbackModelId: deps.fallbackModelId,
|
|
26409
26818
|
fallbackModels: deps.fallbackModels,
|
|
26410
26819
|
twoPass: deps.historianTwoPass,
|
|
@@ -26825,6 +27234,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
|
|
|
26825
27234
|
sequenceOffset: candidateCompartments.length,
|
|
26826
27235
|
dumpLabelBase: `partial-recomp-${sessionId}-${chunk.startIndex}-${chunk.endIndex}-pass-${passCount + 1}`,
|
|
26827
27236
|
timeoutMs: historianTimeoutMs,
|
|
27237
|
+
model: deps.model,
|
|
26828
27238
|
fallbackModelId: deps.fallbackModelId,
|
|
26829
27239
|
fallbackModels: deps.fallbackModels,
|
|
26830
27240
|
twoPass: deps.historianTwoPass,
|
|
@@ -27016,11 +27426,11 @@ function createPiHistorianClient(args) {
|
|
|
27016
27426
|
agent: "magic-context-historian",
|
|
27017
27427
|
systemPrompt: args.systemPrompt,
|
|
27018
27428
|
userMessage: promptText,
|
|
27019
|
-
model: modelOverride ?? args.model,
|
|
27429
|
+
model: modelOverride?.model ?? args.model,
|
|
27020
27430
|
fallbackModels: modelOverride ? undefined : args.fallbackModels,
|
|
27021
27431
|
timeoutMs: args.timeoutMs,
|
|
27022
27432
|
cwd: args.directory,
|
|
27023
|
-
thinkingLevel: args.thinkingLevel,
|
|
27433
|
+
thinkingLevel: modelOverride ? modelOverride.qualifier : args.thinkingLevel,
|
|
27024
27434
|
accountingSessionId: args.accountingSessionId,
|
|
27025
27435
|
accountingSubagent: "recomp"
|
|
27026
27436
|
});
|
|
@@ -27068,7 +27478,8 @@ function readBodyModel(body) {
|
|
|
27068
27478
|
return;
|
|
27069
27479
|
const { providerID, modelID } = model;
|
|
27070
27480
|
if (typeof providerID === "string" && providerID.length > 0 && typeof modelID === "string" && modelID.length > 0) {
|
|
27071
|
-
|
|
27481
|
+
const qualifier = typeof body.variant === "string" && body.variant.length > 0 ? body.variant : undefined;
|
|
27482
|
+
return qualifier ? { model: `${providerID}/${modelID}`, qualifier } : { model: `${providerID}/${modelID}` };
|
|
27072
27483
|
}
|
|
27073
27484
|
return;
|
|
27074
27485
|
}
|
|
@@ -27678,13 +28089,17 @@ async function runPiMemoryMigration(deps) {
|
|
|
27678
28089
|
const prompt = buildMemoryMigrationPrompt(memories);
|
|
27679
28090
|
const modelChain = [];
|
|
27680
28091
|
const seenModels = new Set;
|
|
27681
|
-
for (const
|
|
27682
|
-
|
|
27683
|
-
|
|
28092
|
+
for (const candidate of [
|
|
28093
|
+
{
|
|
28094
|
+
model: deps.primaryModel ?? deps.model,
|
|
28095
|
+
...deps.primaryModel ? {} : deps.thinkingLevel ? { qualifier: deps.thinkingLevel } : {}
|
|
28096
|
+
},
|
|
28097
|
+
...(deps.fallbackModels ?? []).map((fallback) => typeof fallback === "string" ? { model: fallback } : fallback)
|
|
27684
28098
|
]) {
|
|
27685
|
-
|
|
27686
|
-
|
|
27687
|
-
|
|
28099
|
+
const key = `${candidate.model}\x00${candidate.qualifier ?? ""}`;
|
|
28100
|
+
if (candidate.model && !seenModels.has(key)) {
|
|
28101
|
+
seenModels.add(key);
|
|
28102
|
+
modelChain.push(candidate);
|
|
27688
28103
|
}
|
|
27689
28104
|
}
|
|
27690
28105
|
let parsed = null;
|
|
@@ -27692,17 +28107,17 @@ async function runPiMemoryMigration(deps) {
|
|
|
27692
28107
|
for (let i = 0;i < modelChain.length; i += 1) {
|
|
27693
28108
|
const model = modelChain[i];
|
|
27694
28109
|
if (i > 0) {
|
|
27695
|
-
sessionLog(deps.sessionId, `memory-migration: escalating to configured fallback model ${model} (${i}/${modelChain.length - 1})`);
|
|
28110
|
+
sessionLog(deps.sessionId, `memory-migration: escalating to configured fallback model ${model.model} (${i}/${modelChain.length - 1})`);
|
|
27696
28111
|
}
|
|
27697
28112
|
const result = await deps.runner.run({
|
|
27698
28113
|
agent: "magic-context-historian",
|
|
27699
28114
|
systemPrompt: withMigrationLanguageDirective(MIGRATION_SYSTEM_PROMPT2, deps.language),
|
|
27700
28115
|
userMessage: prompt,
|
|
27701
|
-
model,
|
|
28116
|
+
model: model.model,
|
|
27702
28117
|
fallbackModels: undefined,
|
|
27703
28118
|
timeoutMs: deps.timeoutMs ?? 5 * 60 * 1000,
|
|
27704
28119
|
cwd: deps.directory,
|
|
27705
|
-
thinkingLevel:
|
|
28120
|
+
thinkingLevel: model.qualifier,
|
|
27706
28121
|
accountingSessionId: deps.sessionId,
|
|
27707
28122
|
accountingSubagent: "recomp"
|
|
27708
28123
|
});
|
|
@@ -28096,7 +28511,7 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
|
|
|
28096
28511
|
"### Cache TTL",
|
|
28097
28512
|
`- Configured: ${meta.cacheTtl}`,
|
|
28098
28513
|
`- Last response: ${meta.lastResponseTime > 0 ? `${Math.round(elapsed / 1000)}s ago` : "never"}`,
|
|
28099
|
-
`- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never
|
|
28514
|
+
`- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never (MC never assumes expiry — external cache-keep)" : `${Math.round(remainingMs / 1000)}s`}`,
|
|
28100
28515
|
`- Queue will auto-execute: ${cacheExpired ? "yes (cache expired)" : ttlMs === Number.POSITIVE_INFINITY ? `when context >= ${executeThresholdPercentage}%` : `when TTL expires or context >= ${executeThresholdPercentage}%`}`,
|
|
28101
28516
|
"",
|
|
28102
28517
|
"### Execute Threshold",
|
|
@@ -28216,7 +28631,7 @@ ${c.content}
|
|
|
28216
28631
|
// package.json
|
|
28217
28632
|
var package_default = {
|
|
28218
28633
|
name: "@cortexkit/pi-magic-context",
|
|
28219
|
-
version: "0.
|
|
28634
|
+
version: "0.39.0",
|
|
28220
28635
|
type: "module",
|
|
28221
28636
|
description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
|
|
28222
28637
|
main: "dist/index.js",
|
|
@@ -28247,7 +28662,7 @@ var package_default = {
|
|
|
28247
28662
|
build: "tsc -p ../retina-local-fs/tsconfig.build.json && rm -f dist/index.js dist/subagent-entry.js dist/*-*.js && bun build src/index.ts src/subagent-entry.ts --outdir dist --target node --format esm --splitting --external @earendil-works/pi-coding-agent --external @earendil-works/pi-tui --external @huggingface/transformers --external node:sqlite",
|
|
28248
28663
|
"build:e2e-argv": "bun build src/subagent-runner.ts --outfile ../../tests/docker/.generated/subagent-runner-e2e.mjs --target node --format esm --external node:sqlite",
|
|
28249
28664
|
typecheck: "tsc -p ../retina-local-fs/tsconfig.build.json && tsc --noEmit",
|
|
28250
|
-
test: "bun test",
|
|
28665
|
+
test: "bun install --frozen-lockfile && bun test",
|
|
28251
28666
|
lint: "biome check src",
|
|
28252
28667
|
"lint:fix": "biome check --write src",
|
|
28253
28668
|
format: "biome format --write src",
|
|
@@ -28411,7 +28826,7 @@ function renderInner(s, theme, innerWidth) {
|
|
|
28411
28826
|
lines.push(`Upgrade: ${theme.fg("accent", "up to date")}`);
|
|
28412
28827
|
}
|
|
28413
28828
|
lines.push(`Pending drops: ${s.pendingOpsCount}`);
|
|
28414
|
-
lines.push(`Cache TTL: ${s.cacheTtl} · last response ${s.lastResponseTime > 0 ? `${Math.round((Date.now() - s.lastResponseTime) / 1000)}s ago` : "never"} · ${s.cacheExpired ? theme.fg("warning", "expired") : s.cacheRemainingMs === Number.POSITIVE_INFINITY ? "never
|
|
28829
|
+
lines.push(`Cache TTL: ${s.cacheTtl} · last response ${s.lastResponseTime > 0 ? `${Math.round((Date.now() - s.lastResponseTime) / 1000)}s ago` : "never"} · ${s.cacheExpired ? theme.fg("warning", "expired") : s.cacheRemainingMs === Number.POSITIVE_INFINITY ? "never (MC never assumes expiry — external cache-keep)" : `${Math.round(s.cacheRemainingMs / 1000)}s remaining`}`);
|
|
28415
28830
|
lines.push("");
|
|
28416
28831
|
lines.push(theme.fg("muted", "Tags"));
|
|
28417
28832
|
lines.push(`Active ${s.activeTags} (~${formatBytes(s.activeBytes)}) · Dropped ${s.droppedTags} · Total ${s.totalTags}`);
|
|
@@ -29566,12 +29981,13 @@ function resolveHistorianFromConfig(config) {
|
|
|
29566
29981
|
const historian = config.historian;
|
|
29567
29982
|
if (historian?.disable === true)
|
|
29568
29983
|
return;
|
|
29569
|
-
const
|
|
29570
|
-
|
|
29984
|
+
const resolved = resolveHistorianModel(config, "pi");
|
|
29985
|
+
const model = resolved.primary?.model;
|
|
29986
|
+
if (!model)
|
|
29571
29987
|
return;
|
|
29572
29988
|
const historianContextLimit = resolveHistorianContextLimit(model);
|
|
29573
29989
|
const historianChunkTokens = deriveHistorianChunkTokens(historianContextLimit);
|
|
29574
|
-
const fallbackModels =
|
|
29990
|
+
const fallbackModels = resolved.fallbacks;
|
|
29575
29991
|
return {
|
|
29576
29992
|
runner: new PiSubagentRunner,
|
|
29577
29993
|
model,
|
|
@@ -29579,7 +29995,7 @@ function resolveHistorianFromConfig(config) {
|
|
|
29579
29995
|
historianChunkTokens,
|
|
29580
29996
|
timeoutMs: config.historian_timeout_ms,
|
|
29581
29997
|
twoPass: historian?.two_pass === true,
|
|
29582
|
-
thinkingLevel:
|
|
29998
|
+
thinkingLevel: resolved.primary?.qualifier,
|
|
29583
29999
|
executeThresholdPercentage: config.execute_threshold_percentage,
|
|
29584
30000
|
executeThresholdTokens: config.execute_threshold_tokens,
|
|
29585
30001
|
commitClusterTrigger: config.commit_cluster_trigger,
|
|
@@ -30069,6 +30485,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
30069
30485
|
embeddingConfig: bootProjectDeps.config.embedding,
|
|
30070
30486
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
30071
30487
|
retinaHandoff: bootProjectDeps.config.smart_notes.retina_handoff,
|
|
30488
|
+
mural: bootProjectDeps.config.mural,
|
|
30072
30489
|
language: bootProjectDeps.config.language,
|
|
30073
30490
|
gitCommitIndexing: bootProjectDeps.config.memory.git_commit_indexing,
|
|
30074
30491
|
onAdjunctsRefreshNeeded: signalPiSystemPromptRefreshForProject
|
|
@@ -30447,16 +30864,16 @@ function formatExecuteThresholdForLog(value) {
|
|
|
30447
30864
|
return overrides.length > 0 ? `${base} (${overrides.join(", ")})` : base;
|
|
30448
30865
|
}
|
|
30449
30866
|
export {
|
|
30450
|
-
|
|
30451
|
-
resolveSidekickFromConfig,
|
|
30452
|
-
resolveHistorianFromConfig,
|
|
30453
|
-
resolveDreamerFromConfig,
|
|
30454
|
-
persistPiPressureFromMessageEnd,
|
|
30455
|
-
persistPiMessageEndModelMeta,
|
|
30456
|
-
handlePiSessionBeforeCompact,
|
|
30457
|
-
src_default as default,
|
|
30458
|
-
capturePiTodowriteMessageIfCompatible,
|
|
30459
|
-
capturePiTodowriteArgsIfCompatible,
|
|
30867
|
+
__test,
|
|
30460
30868
|
canonicalPiModelKey,
|
|
30461
|
-
|
|
30869
|
+
capturePiTodowriteArgsIfCompatible,
|
|
30870
|
+
capturePiTodowriteMessageIfCompatible,
|
|
30871
|
+
src_default as default,
|
|
30872
|
+
handlePiSessionBeforeCompact,
|
|
30873
|
+
persistPiMessageEndModelMeta,
|
|
30874
|
+
persistPiPressureFromMessageEnd,
|
|
30875
|
+
resolveDreamerFromConfig,
|
|
30876
|
+
resolveHistorianFromConfig,
|
|
30877
|
+
resolveSidekickFromConfig,
|
|
30878
|
+
signalPiDeferredCompactionMarkerDrain
|
|
30462
30879
|
};
|