@cortexkit/pi-magic-context 0.43.2 → 0.44.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/dist/{index-mea04n1j.js → index-2kj55q4e.js} +88 -26
- package/dist/{index-bkrh6jhp.js → index-8ytss1hp.js} +308 -190
- package/dist/{index-5v60m046.js → index-jscq7067.js} +1 -1
- package/dist/{index-17102c1m.js → index-mmkdxa5j.js} +1 -1
- package/dist/{index-bfd52y8p.js → index-tfzybajk.js} +22 -6
- package/dist/index.js +1142 -364
- package/dist/{message-time-backfill-f0v3yvza.js → message-time-backfill-3rp0w2z9.js} +3 -3
- package/dist/{read-session-chunk-ky2sprnf.js → read-session-chunk-2s116ah5.js} +4 -2
- package/dist/{safe-notification-target-d7f3t5qk.js → safe-notification-target-pd09ybr0.js} +2 -2
- package/dist/subagent-entry.js +4 -4
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
log,
|
|
10
10
|
sessionLog,
|
|
11
11
|
flushLogger
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-tfzybajk.js";
|
|
13
13
|
import {
|
|
14
14
|
COMPACTION_ENABLED_PATH,
|
|
15
15
|
isDreamerRunnable,
|
|
@@ -100,7 +100,9 @@ import {
|
|
|
100
100
|
escapeXmlContent,
|
|
101
101
|
getModuleNoteEvaluationBridge,
|
|
102
102
|
getContextStoreUuid,
|
|
103
|
+
getAuthorityManagedMarker,
|
|
103
104
|
drainMirrorPages,
|
|
105
|
+
V2_MEMORY_CATEGORIES,
|
|
104
106
|
parseCompartmentOutput,
|
|
105
107
|
resolveWorkspaceShareCategories,
|
|
106
108
|
resolveWorkspaceIdentitySet,
|
|
@@ -172,8 +174,8 @@ import {
|
|
|
172
174
|
clearDetectedContextLimit,
|
|
173
175
|
getStrippedPlaceholderIds,
|
|
174
176
|
applyStrippedPlaceholderDelta,
|
|
175
|
-
NEWEST_REASONING_BEARING_ASSISTANT,
|
|
176
177
|
THINKING_BINDING_RECOVERY_FROZEN_PREFIX,
|
|
178
|
+
THINKING_BINDING_STRIP_ORDER_END_MARKER,
|
|
177
179
|
thinkingBindingRecoveryFrozenId,
|
|
178
180
|
getThinkingBindingRecoveryTarget,
|
|
179
181
|
armThinkingBindingRecovery,
|
|
@@ -402,7 +404,7 @@ import {
|
|
|
402
404
|
registerTodoStateLifecycle,
|
|
403
405
|
syncCtxMemoryToolEnabled,
|
|
404
406
|
registerMagicContextTools
|
|
405
|
-
} from "./index-
|
|
407
|
+
} from "./index-8ytss1hp.js";
|
|
406
408
|
import {
|
|
407
409
|
CTX_REDUCE_KEEP,
|
|
408
410
|
newestCtxReduceTagNumbers,
|
|
@@ -497,6 +499,8 @@ import {
|
|
|
497
499
|
localBudget,
|
|
498
500
|
calibrationForModelKey,
|
|
499
501
|
historyLocalBudget,
|
|
502
|
+
SKELETON_REAL_INPUT_MAX_BYTES,
|
|
503
|
+
toolInputStringBytes,
|
|
500
504
|
setRawMessageProvider2,
|
|
501
505
|
withRawMessageProvider2,
|
|
502
506
|
cleanUserText2,
|
|
@@ -512,14 +516,14 @@ import {
|
|
|
512
516
|
getRawSessionTagKeysThrough2,
|
|
513
517
|
getLegacyProtectedTailStartOrdinal2,
|
|
514
518
|
readSessionChunk2
|
|
515
|
-
} from "./index-
|
|
519
|
+
} from "./index-2kj55q4e.js";
|
|
516
520
|
import {
|
|
517
521
|
pushNotification2
|
|
518
522
|
} from "./index-b3eqj1g6.js";
|
|
519
|
-
import"./index-
|
|
523
|
+
import"./index-jscq7067.js";
|
|
520
524
|
import {
|
|
521
525
|
logSlowWriteTransaction
|
|
522
|
-
} from "./index-
|
|
526
|
+
} from "./index-mmkdxa5j.js";
|
|
523
527
|
import {
|
|
524
528
|
__toESM
|
|
525
529
|
} from "./index-22jkk6wg.js";
|
|
@@ -527,7 +531,7 @@ import {
|
|
|
527
531
|
// src/index.ts
|
|
528
532
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
529
533
|
import { createRequire as createRequire2 } from "node:module";
|
|
530
|
-
import { join as join8, resolve as
|
|
534
|
+
import { join as join8, resolve as resolve4 } from "node:path";
|
|
531
535
|
|
|
532
536
|
// ../plugin/src/config/live-snapshot.ts
|
|
533
537
|
import { createHash } from "node:crypto";
|
|
@@ -1141,7 +1145,9 @@ var OVERFLOW_PATTERNS = [
|
|
|
1141
1145
|
/prompt too long; exceeded (?:max )?context length/i,
|
|
1142
1146
|
/too large for model with \d+ maximum context length/i,
|
|
1143
1147
|
/model_context_window_exceeded/i,
|
|
1144
|
-
/context size has been exceeded/i
|
|
1148
|
+
/context size has been exceeded/i,
|
|
1149
|
+
/prepared prompt exceeds engine max_context/i,
|
|
1150
|
+
/prompt exceeds (?:the )?.{0,32}\bmax_context\b/i
|
|
1145
1151
|
];
|
|
1146
1152
|
var LIMIT_EXTRACTION_PATTERNS = [
|
|
1147
1153
|
{ pattern: /maximum prompt length is (\d+)/i, provenance: "prompt_only" },
|
|
@@ -1162,11 +1168,15 @@ var LIMIT_EXTRACTION_PATTERNS = [
|
|
|
1162
1168
|
pattern: />\s*(\d+)\s*(?:tokens?\s*)?(?:maximum|max|limit)\b/i,
|
|
1163
1169
|
provenance: "prompt_only"
|
|
1164
1170
|
},
|
|
1171
|
+
{ pattern: /prepared prompt exceeds engine max_context\s+(\d+)/i, provenance: "unknown" },
|
|
1172
|
+
{ pattern: /prompt exceeds (?:the )?.{0,32}\bmax_context\s+(\d+)/i, provenance: "unknown" },
|
|
1165
1173
|
{ pattern: /max(?:imum)?.*context.*?(\d+)/i, provenance: "unknown" }
|
|
1166
1174
|
];
|
|
1167
1175
|
var MIN_PLAUSIBLE_LIMIT = 1024;
|
|
1168
1176
|
var MAX_PLAUSIBLE_LIMIT = 1e7;
|
|
1169
1177
|
var THINKING_BINDING_MISMATCH_PATTERN = /bound to a different conversation/i;
|
|
1178
|
+
var THINKING_BINDING_FAILING_PATH_PATTERN = /^\s*(messages\.\d+\.content\.\d+):/;
|
|
1179
|
+
var THINKING_BINDING_FIRST_CHANGED_PATTERN = /first at `?(messages\.\d+\.content\.\d+)`?/;
|
|
1170
1180
|
function extractErrorMessage(error) {
|
|
1171
1181
|
if (!error)
|
|
1172
1182
|
return "";
|
|
@@ -1195,29 +1205,6 @@ function extractErrorMessage(error) {
|
|
|
1195
1205
|
}
|
|
1196
1206
|
return String(error);
|
|
1197
1207
|
}
|
|
1198
|
-
function extractThinkingBindingMessageId(error) {
|
|
1199
|
-
if (!error || typeof error !== "object")
|
|
1200
|
-
return;
|
|
1201
|
-
const seen = new Set;
|
|
1202
|
-
const queue = [error];
|
|
1203
|
-
while (queue.length > 0) {
|
|
1204
|
-
const current = queue.shift();
|
|
1205
|
-
if (!current || seen.has(current))
|
|
1206
|
-
continue;
|
|
1207
|
-
seen.add(current);
|
|
1208
|
-
const record = current;
|
|
1209
|
-
for (const key of ["message_id", "messageID", "messageId"]) {
|
|
1210
|
-
const value = record[key];
|
|
1211
|
-
if (typeof value === "string" && value.length > 0)
|
|
1212
|
-
return value;
|
|
1213
|
-
}
|
|
1214
|
-
for (const value of Object.values(record)) {
|
|
1215
|
-
if (value && typeof value === "object")
|
|
1216
|
-
queue.push(value);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
return;
|
|
1220
|
-
}
|
|
1221
1208
|
function extractExplicitHttpStatus(error) {
|
|
1222
1209
|
if (!error || typeof error !== "object")
|
|
1223
1210
|
return;
|
|
@@ -1247,13 +1234,20 @@ function detectThinkingBindingMismatch(error) {
|
|
|
1247
1234
|
if (explicitStatus !== undefined && explicitStatus !== 400 || !THINKING_BINDING_MISMATCH_PATTERN.test(message)) {
|
|
1248
1235
|
return { isBindingMismatch: false };
|
|
1249
1236
|
}
|
|
1250
|
-
const
|
|
1237
|
+
const failingBlockPath = THINKING_BINDING_FAILING_PATH_PATTERN.exec(message)?.[1];
|
|
1238
|
+
const firstChangedPath = THINKING_BINDING_FIRST_CHANGED_PATTERN.exec(message)?.[1];
|
|
1251
1239
|
return {
|
|
1252
1240
|
isBindingMismatch: true,
|
|
1253
1241
|
matchedPattern: "bound to a different conversation",
|
|
1254
|
-
...
|
|
1242
|
+
...failingBlockPath ? { failingBlockPath } : {},
|
|
1243
|
+
...firstChangedPath ? { firstChangedPath } : {}
|
|
1255
1244
|
};
|
|
1256
1245
|
}
|
|
1246
|
+
function isPrefixBoundThinkingModel(providerID, modelID) {
|
|
1247
|
+
if (providerID?.toLowerCase() !== "anthropic" || !modelID)
|
|
1248
|
+
return false;
|
|
1249
|
+
return isFable51ThinkingBindingModel(providerID, modelID) || /(?:^|[-_.])opus[-_.]?5[-_.]5(?:$|[-_.])/i.test(modelID);
|
|
1250
|
+
}
|
|
1257
1251
|
function isFable51ThinkingBindingModel(providerID, modelID) {
|
|
1258
1252
|
if (providerID?.toLowerCase() !== "anthropic" || !modelID)
|
|
1259
1253
|
return false;
|
|
@@ -1586,6 +1580,31 @@ async function runSessionProjectBackfill(db, source, options = {}) {
|
|
|
1586
1580
|
return result;
|
|
1587
1581
|
}
|
|
1588
1582
|
|
|
1583
|
+
// ../plugin/src/features/magic-context/storage-unavailable-reason.ts
|
|
1584
|
+
function describeStorageUnavailability(fallbackCause) {
|
|
1585
|
+
const migration = getMigrationOnOpenRefusal();
|
|
1586
|
+
const blockingProcesses = migration?.blockingProcesses ?? migration?.serverPids.map((pid) => ({ kind: "process", pid })) ?? [];
|
|
1587
|
+
if (migration && (blockingProcesses.length > 0 || migration.unreadableFile)) {
|
|
1588
|
+
return {
|
|
1589
|
+
kind: "migration_guard",
|
|
1590
|
+
persistedVersion: migration.persistedVersion,
|
|
1591
|
+
supportedVersion: migration.supportedVersion,
|
|
1592
|
+
blockingProcesses,
|
|
1593
|
+
...migration.unreadableFile ? { unreadableFile: migration.unreadableFile } : {},
|
|
1594
|
+
...migration.unreadableArm ? { unreadableArm: migration.unreadableArm } : {}
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
const fence = getSchemaFenceRejection();
|
|
1598
|
+
if (fence) {
|
|
1599
|
+
return {
|
|
1600
|
+
kind: "schema_fence",
|
|
1601
|
+
persistedVersion: fence.persistedVersion,
|
|
1602
|
+
supportedVersion: fence.supportedVersion
|
|
1603
|
+
};
|
|
1604
|
+
}
|
|
1605
|
+
return { kind: "storage_failure", cause: fallbackCause };
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1589
1608
|
// ../plugin/src/features/magic-context/v22-deferred-backfill.ts
|
|
1590
1609
|
import { createHash as createHash2 } from "node:crypto";
|
|
1591
1610
|
import { realpathSync } from "node:fs";
|
|
@@ -2802,6 +2821,11 @@ var USER_FACING_FAILURES = {
|
|
|
2802
2821
|
sentence: "Memory maintenance could not reach its model.",
|
|
2803
2822
|
action: "Check the model connection, then run /ctx-dream again."
|
|
2804
2823
|
},
|
|
2824
|
+
dream_step_limit: {
|
|
2825
|
+
code: "MC-D10",
|
|
2826
|
+
sentence: "Memory maintenance stopped at its hidden agent step limit.",
|
|
2827
|
+
action: "This task needs less work per run; changing the model connection will not help."
|
|
2828
|
+
},
|
|
2805
2829
|
dream_empty_completion: {
|
|
2806
2830
|
code: "MC-D03",
|
|
2807
2831
|
sentence: "Memory maintenance received no usable response.",
|
|
@@ -2967,6 +2991,11 @@ var USER_FACING_FAILURES = {
|
|
|
2967
2991
|
sentence: "Magic Context is temporarily unavailable.",
|
|
2968
2992
|
action: "Retry in a moment."
|
|
2969
2993
|
},
|
|
2994
|
+
store_ahead_of_binary: {
|
|
2995
|
+
code: "MC-C13",
|
|
2996
|
+
sentence: "Magic Context refused to start: its store (store.db) was migrated by a newer ck-mc build than the one running.",
|
|
2997
|
+
action: "Update ck-mc, or roll back by restoring ck-mc together with context.db and store.db from the same backup."
|
|
2998
|
+
},
|
|
2970
2999
|
compaction_marker_missing: {
|
|
2971
3000
|
code: "MC-C11",
|
|
2972
3001
|
sentence: "The history boundary marker is missing from the OpenCode store, so requests carry the full session.",
|
|
@@ -2982,11 +3011,6 @@ var USER_FACING_FAILURES = {
|
|
|
2982
3011
|
sentence: "Memory authority is inconsistent between the host and module.",
|
|
2983
3012
|
action: "Run `ck doctor drain-authority` before changing Rust mode."
|
|
2984
3013
|
},
|
|
2985
|
-
rust_mode_unsupported: {
|
|
2986
|
-
code: "MC-S06",
|
|
2987
|
-
sentence: "Experimental Rust transform mode is not available on this OpenCode host.",
|
|
2988
|
-
action: 'Magic Context is running its TypeScript mode instead; set `transform_mode` to "ts" to stop requesting Rust.'
|
|
2989
|
-
},
|
|
2990
3014
|
dreamer_task_failing: {
|
|
2991
3015
|
code: "MC-S05",
|
|
2992
3016
|
sentence: "A background maintenance task keeps failing on its schedule.",
|
|
@@ -3018,6 +3042,7 @@ function renderCapabilityRefusal(capability) {
|
|
|
3018
3042
|
var DREAM_FAILURE_KEYS = {
|
|
3019
3043
|
provider_timeout: "dream_provider_timeout",
|
|
3020
3044
|
provider_error: "dream_provider_error",
|
|
3045
|
+
step_limit: "dream_step_limit",
|
|
3021
3046
|
empty_completion: "dream_empty_completion",
|
|
3022
3047
|
no_models: "dream_no_models",
|
|
3023
3048
|
child_aborted: "dream_child_aborted",
|
|
@@ -3047,6 +3072,10 @@ function renderEmbeddingFailure(failureClass, style = "markdown") {
|
|
|
3047
3072
|
return renderUserFacingFailure(EMBEDDING_FAILURE_KEYS[failureClass], style);
|
|
3048
3073
|
}
|
|
3049
3074
|
|
|
3075
|
+
// src/dreamer/index.ts
|
|
3076
|
+
import { homedir as homedir2 } from "node:os";
|
|
3077
|
+
import { parse, resolve as resolve3 } from "node:path";
|
|
3078
|
+
|
|
3050
3079
|
// ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
|
|
3051
3080
|
function openOpenCodeDb() {
|
|
3052
3081
|
const resolution = resolveOpenCodeDbPath();
|
|
@@ -3204,6 +3233,37 @@ class HiddenCompletionRefusal extends Error {
|
|
|
3204
3233
|
this.name = "HiddenCompletionRefusal";
|
|
3205
3234
|
}
|
|
3206
3235
|
}
|
|
3236
|
+
// ../plugin/src/v2/hooks/hidden-child.ts
|
|
3237
|
+
var HIDDEN_HISTORIAN_AGENT = "historian";
|
|
3238
|
+
var HIDDEN_DREAMER_AGENT = "dreamer-classifier";
|
|
3239
|
+
var HIDDEN_CURATE_AGENT = DREAMER_AGENT;
|
|
3240
|
+
var READ_TOOLS = ["read", "grep", "glob"];
|
|
3241
|
+
var AGENT_TOOLS = {
|
|
3242
|
+
[HIDDEN_HISTORIAN_AGENT]: [],
|
|
3243
|
+
[HIDDEN_DREAMER_AGENT]: [],
|
|
3244
|
+
[HIDDEN_CURATE_AGENT]: ["ctx_memory", "ctx_memory_list"],
|
|
3245
|
+
[DREAMER_MEMORY_MAPPER_AGENT]: READ_TOOLS,
|
|
3246
|
+
[DREAMER_PRIMER_INVESTIGATOR_AGENT]: [...READ_TOOLS, "ctx_search"],
|
|
3247
|
+
[DREAMER_RETROSPECTIVE_AGENT]: ["ctx_search"]
|
|
3248
|
+
};
|
|
3249
|
+
var AGENT_STEPS = {
|
|
3250
|
+
[HIDDEN_CURATE_AGENT]: 150,
|
|
3251
|
+
[DREAMER_MEMORY_MAPPER_AGENT]: 60,
|
|
3252
|
+
[DREAMER_DOCS_AGENT]: 60,
|
|
3253
|
+
[DREAMER_PRIMER_INVESTIGATOR_AGENT]: 40,
|
|
3254
|
+
[DREAMER_RETROSPECTIVE_AGENT]: 40
|
|
3255
|
+
};
|
|
3256
|
+
class HiddenAgentStepLimit extends Error {
|
|
3257
|
+
agent;
|
|
3258
|
+
cap;
|
|
3259
|
+
constructor(agent, cap) {
|
|
3260
|
+
super(`Hidden agent ${agent} exceeded its ${cap}-step limit`);
|
|
3261
|
+
this.name = "HiddenAgentStepLimit";
|
|
3262
|
+
this.agent = agent;
|
|
3263
|
+
this.cap = cap;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
|
|
3207
3267
|
// ../plugin/src/shared/assistant-message-extractor.ts
|
|
3208
3268
|
function asSessionMessage(value) {
|
|
3209
3269
|
if (!isRecord(value))
|
|
@@ -3302,6 +3362,14 @@ function copyPromptArgs(args, body) {
|
|
|
3302
3362
|
return { ...args, body: { ...body } };
|
|
3303
3363
|
}
|
|
3304
3364
|
var promptFailureDetails = new WeakMap;
|
|
3365
|
+
function isHostTimeoutError(error) {
|
|
3366
|
+
return error !== null && typeof error === "object" && error.name === "TimeoutError";
|
|
3367
|
+
}
|
|
3368
|
+
function isPromptTimeoutError(error) {
|
|
3369
|
+
if (isHostTimeoutError(error))
|
|
3370
|
+
return true;
|
|
3371
|
+
return error instanceof Error && /^prompt timed out after \d+ms$/.test(error.message);
|
|
3372
|
+
}
|
|
3305
3373
|
function getPromptFailureDetail(error) {
|
|
3306
3374
|
return error !== null && typeof error === "object" ? promptFailureDetails.get(error) ?? null : null;
|
|
3307
3375
|
}
|
|
@@ -3358,9 +3426,13 @@ function parseModelSuggestion(error) {
|
|
|
3358
3426
|
suggestion: suggestionMatch[1].trim()
|
|
3359
3427
|
};
|
|
3360
3428
|
}
|
|
3429
|
+
function externalAbortMessage(signal) {
|
|
3430
|
+
const reason = signal.reason;
|
|
3431
|
+
return `prompt aborted by external signal${reason instanceof Error && /^lease_(?:lost|expired):/.test(reason.message) ? `: ${reason.message}` : ""}`;
|
|
3432
|
+
}
|
|
3361
3433
|
async function promptWithTimeout(client, args, timeoutMs, signal, transport) {
|
|
3362
3434
|
if (signal?.aborted) {
|
|
3363
|
-
throw new Error(
|
|
3435
|
+
throw new Error(externalAbortMessage(signal));
|
|
3364
3436
|
}
|
|
3365
3437
|
const controller = new AbortController;
|
|
3366
3438
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -3380,7 +3452,7 @@ async function promptWithTimeout(client, args, timeoutMs, signal, transport) {
|
|
|
3380
3452
|
if (!transport || transport.childSessionId) {
|
|
3381
3453
|
await abortChildRun(client, transport?.childSessionId ?? args.path.id);
|
|
3382
3454
|
}
|
|
3383
|
-
throw new Error(
|
|
3455
|
+
throw new Error(externalAbortMessage(signal));
|
|
3384
3456
|
}
|
|
3385
3457
|
if (controller.signal.aborted) {
|
|
3386
3458
|
if (!transport || transport.childSessionId) {
|
|
@@ -3388,6 +3460,11 @@ async function promptWithTimeout(client, args, timeoutMs, signal, transport) {
|
|
|
3388
3460
|
}
|
|
3389
3461
|
throw new Error(`prompt timed out after ${timeoutMs}ms`);
|
|
3390
3462
|
}
|
|
3463
|
+
if (isHostTimeoutError(error)) {
|
|
3464
|
+
if (!transport || transport.childSessionId) {
|
|
3465
|
+
await abortChildRun(client, transport?.childSessionId ?? args.path.id);
|
|
3466
|
+
}
|
|
3467
|
+
}
|
|
3391
3468
|
throw error;
|
|
3392
3469
|
} finally {
|
|
3393
3470
|
clearTimeout(timeout);
|
|
@@ -3397,7 +3474,7 @@ async function promptWithTimeout(client, args, timeoutMs, signal, transport) {
|
|
|
3397
3474
|
if (!transport || transport.childSessionId) {
|
|
3398
3475
|
await abortChildRun(client, transport?.childSessionId ?? args.path.id);
|
|
3399
3476
|
}
|
|
3400
|
-
throw new Error(signal?.aborted ?
|
|
3477
|
+
throw new Error(signal?.aborted ? externalAbortMessage(signal) : `prompt timed out after ${timeoutMs}ms`);
|
|
3401
3478
|
}
|
|
3402
3479
|
}
|
|
3403
3480
|
async function abortChildRun(client, sessionId) {
|
|
@@ -3413,7 +3490,7 @@ async function abortChildRun(client, sessionId) {
|
|
|
3413
3490
|
}
|
|
3414
3491
|
}
|
|
3415
3492
|
function isNonRetryable(error, externalSignal) {
|
|
3416
|
-
if (externalSignal?.aborted)
|
|
3493
|
+
if (externalSignal?.aborted || error instanceof HiddenAgentStepLimit)
|
|
3417
3494
|
return true;
|
|
3418
3495
|
if (error instanceof Error) {
|
|
3419
3496
|
if (error.name === "AbortError")
|
|
@@ -3423,6 +3500,8 @@ function isNonRetryable(error, externalSignal) {
|
|
|
3423
3500
|
if (/^prompt timed out after \d+ms$/.test(error.message))
|
|
3424
3501
|
return true;
|
|
3425
3502
|
}
|
|
3503
|
+
if (isHostTimeoutError(error))
|
|
3504
|
+
return true;
|
|
3426
3505
|
if (detectOverflow(error).isOverflow)
|
|
3427
3506
|
return true;
|
|
3428
3507
|
return false;
|
|
@@ -3435,11 +3514,14 @@ function shortErr(error) {
|
|
|
3435
3514
|
}
|
|
3436
3515
|
function classifyPromptFailure(error, phase, externalSignal) {
|
|
3437
3516
|
const message = extractMessage(error);
|
|
3517
|
+
if (error instanceof HiddenAgentStepLimit)
|
|
3518
|
+
return "step_limit";
|
|
3438
3519
|
if (externalSignal?.aborted || message === "prompt aborted by external signal") {
|
|
3439
3520
|
return "child_aborted";
|
|
3440
3521
|
}
|
|
3441
|
-
if (/^prompt timed out after \d+ms$/.test(message))
|
|
3522
|
+
if (/^prompt timed out after \d+ms$/.test(message) || isHostTimeoutError(error)) {
|
|
3442
3523
|
return "provider_timeout";
|
|
3524
|
+
}
|
|
3443
3525
|
if (phase === "validation") {
|
|
3444
3526
|
if (/returned no (?:assistant )?output|no assistant output/i.test(message)) {
|
|
3445
3527
|
return "empty_completion";
|
|
@@ -3656,7 +3738,10 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
|
|
|
3656
3738
|
}
|
|
3657
3739
|
}
|
|
3658
3740
|
log(`[${callContext}] all models exhausted; tried: ${failedAttempts.map((failure) => failure.attempt.label).join(", ")}; original error: ${shortErr(firstError)}; last error: ${shortErr(lastError)}`);
|
|
3659
|
-
|
|
3741
|
+
const cause = lastError ?? firstError;
|
|
3742
|
+
const exhausted = cause instanceof Error ? cause : new Error(String(cause ?? "All fallback models failed validation"));
|
|
3743
|
+
exhausted.message = `All models exhausted (${failedAttempts.map((failure) => failure.attempt.label).join(", ")}): ${exhausted.message}`;
|
|
3744
|
+
throwWithPromptFailure(exhausted, failedAttempts, args, timeoutMs, options.transport);
|
|
3660
3745
|
}
|
|
3661
3746
|
// ../plugin/src/shared/normalize-sdk-response.ts
|
|
3662
3747
|
function normalizeSDKResponse(response, fallback, options) {
|
|
@@ -3681,6 +3766,149 @@ function normalizeSDKResponse(response, fallback, options) {
|
|
|
3681
3766
|
}
|
|
3682
3767
|
return fallback;
|
|
3683
3768
|
}
|
|
3769
|
+
// ../plugin/src/shared/prompt-async-transport.ts
|
|
3770
|
+
var DEFAULT_POLL_INTERVAL_MS = 1000;
|
|
3771
|
+
var DEFAULT_START_GRACE_MS = 30000;
|
|
3772
|
+
var MESSAGE_WINDOW = 20;
|
|
3773
|
+
function sessionApi(client) {
|
|
3774
|
+
return client?.session;
|
|
3775
|
+
}
|
|
3776
|
+
function supportsPromptAsync(client) {
|
|
3777
|
+
const session = sessionApi(client);
|
|
3778
|
+
return typeof session?.promptAsync === "function" && typeof session?.status === "function" && typeof session?.messages === "function";
|
|
3779
|
+
}
|
|
3780
|
+
function createPromptAsyncTransport(client, childSessionId, options = {}) {
|
|
3781
|
+
if (!supportsPromptAsync(client))
|
|
3782
|
+
return;
|
|
3783
|
+
return Object.assign((request) => promptAsyncAndWaitForIdle(client, request, options), { childSessionId });
|
|
3784
|
+
}
|
|
3785
|
+
function infoOf(message) {
|
|
3786
|
+
const info = message?.info;
|
|
3787
|
+
return info && typeof info === "object" ? info : {};
|
|
3788
|
+
}
|
|
3789
|
+
function messageId(message) {
|
|
3790
|
+
const id = infoOf(message).id;
|
|
3791
|
+
return typeof id === "string" ? id : null;
|
|
3792
|
+
}
|
|
3793
|
+
function isSettledAssistant(message) {
|
|
3794
|
+
const info = infoOf(message);
|
|
3795
|
+
if (info.role !== "assistant")
|
|
3796
|
+
return false;
|
|
3797
|
+
return info.time?.completed != null || info.error != null || info.finish != null;
|
|
3798
|
+
}
|
|
3799
|
+
function unwrapData(response) {
|
|
3800
|
+
if (response && typeof response === "object" && "data" in response) {
|
|
3801
|
+
return response.data;
|
|
3802
|
+
}
|
|
3803
|
+
return response;
|
|
3804
|
+
}
|
|
3805
|
+
function describeRejection(error) {
|
|
3806
|
+
if (error instanceof Error)
|
|
3807
|
+
return error.message;
|
|
3808
|
+
try {
|
|
3809
|
+
return JSON.stringify(error);
|
|
3810
|
+
} catch {
|
|
3811
|
+
return String(error);
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
function abortError(signal) {
|
|
3815
|
+
return signal.reason ?? new Error("prompt_async wait aborted");
|
|
3816
|
+
}
|
|
3817
|
+
function sleep(ms, signal) {
|
|
3818
|
+
return new Promise((resolve, reject) => {
|
|
3819
|
+
if (signal?.aborted) {
|
|
3820
|
+
reject(abortError(signal));
|
|
3821
|
+
return;
|
|
3822
|
+
}
|
|
3823
|
+
const onAbort = () => {
|
|
3824
|
+
clearTimeout(timer);
|
|
3825
|
+
reject(abortError(signal));
|
|
3826
|
+
};
|
|
3827
|
+
const timer = setTimeout(() => {
|
|
3828
|
+
signal?.removeEventListener("abort", onAbort);
|
|
3829
|
+
resolve();
|
|
3830
|
+
}, ms);
|
|
3831
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
3832
|
+
});
|
|
3833
|
+
}
|
|
3834
|
+
async function readMessages(session, sessionId, directory, signal) {
|
|
3835
|
+
const response = await session.messages?.({
|
|
3836
|
+
path: { id: sessionId },
|
|
3837
|
+
query: { ...directory ? { directory } : {}, limit: MESSAGE_WINDOW },
|
|
3838
|
+
...signal ? { signal } : {}
|
|
3839
|
+
});
|
|
3840
|
+
const data = unwrapData(response);
|
|
3841
|
+
return Array.isArray(data) ? data : [];
|
|
3842
|
+
}
|
|
3843
|
+
async function readStatus(session, sessionId, directory, signal) {
|
|
3844
|
+
try {
|
|
3845
|
+
const response = await session.status?.({
|
|
3846
|
+
...directory ? { query: { directory } } : {},
|
|
3847
|
+
...signal ? { signal } : {}
|
|
3848
|
+
});
|
|
3849
|
+
if (response && typeof response === "object" && "error" in response) {
|
|
3850
|
+
if (response.error)
|
|
3851
|
+
return null;
|
|
3852
|
+
}
|
|
3853
|
+
const data = unwrapData(response);
|
|
3854
|
+
if (!data || typeof data !== "object")
|
|
3855
|
+
return null;
|
|
3856
|
+
const entry = data[sessionId];
|
|
3857
|
+
const type = entry?.type;
|
|
3858
|
+
return typeof type === "string" ? type : "idle";
|
|
3859
|
+
} catch (error) {
|
|
3860
|
+
if (signal?.aborted)
|
|
3861
|
+
throw error;
|
|
3862
|
+
return null;
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
async function promptAsyncAndWaitForIdle(client, request, options = {}) {
|
|
3866
|
+
const session = sessionApi(client);
|
|
3867
|
+
if (!session || !supportsPromptAsync(client)) {
|
|
3868
|
+
throw new Error("prompt_async transport is unavailable on this client");
|
|
3869
|
+
}
|
|
3870
|
+
const sessionId = request.path.id;
|
|
3871
|
+
const directory = request.query?.directory;
|
|
3872
|
+
const dir = typeof directory === "string" ? directory : undefined;
|
|
3873
|
+
const signal = request.signal;
|
|
3874
|
+
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
3875
|
+
const startGraceMs = options.startGraceMs ?? DEFAULT_START_GRACE_MS;
|
|
3876
|
+
const baseline = new Set((await readMessages(session, sessionId, dir, signal)).map(messageId).filter((id) => id !== null));
|
|
3877
|
+
const sent = await session.promptAsync?.(request);
|
|
3878
|
+
if (sent && typeof sent === "object" && "error" in sent) {
|
|
3879
|
+
const rejection = sent.error;
|
|
3880
|
+
if (rejection)
|
|
3881
|
+
throw new Error(`prompt_async was rejected: ${describeRejection(rejection)}`);
|
|
3882
|
+
}
|
|
3883
|
+
const sentAt = Date.now();
|
|
3884
|
+
let sawBusy = false;
|
|
3885
|
+
for (;; ) {
|
|
3886
|
+
await sleep(pollIntervalMs, signal);
|
|
3887
|
+
const status = await readStatus(session, sessionId, dir, signal);
|
|
3888
|
+
if (status === "busy" || status === "retry") {
|
|
3889
|
+
sawBusy = true;
|
|
3890
|
+
continue;
|
|
3891
|
+
}
|
|
3892
|
+
if (status === null)
|
|
3893
|
+
continue;
|
|
3894
|
+
const messages = await readMessages(session, sessionId, dir, signal);
|
|
3895
|
+
const last = messages.at(-1);
|
|
3896
|
+
const lastId = messageId(last);
|
|
3897
|
+
if (last && lastId !== null && !baseline.has(lastId) && isSettledAssistant(last))
|
|
3898
|
+
return;
|
|
3899
|
+
const fresh = messages.some((message) => {
|
|
3900
|
+
const id = messageId(message);
|
|
3901
|
+
return id !== null && !baseline.has(id);
|
|
3902
|
+
});
|
|
3903
|
+
if (sawBusy && fresh)
|
|
3904
|
+
return;
|
|
3905
|
+
if (Date.now() - sentAt >= startGraceMs) {
|
|
3906
|
+
if (fresh)
|
|
3907
|
+
return;
|
|
3908
|
+
throw new Error(`prompt_async did not start a run in child session ${sessionId} within ${startGraceMs}ms`);
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3684
3912
|
// ../plugin/src/shared/summarize-child-stderr.ts
|
|
3685
3913
|
var MAX_CHILD_STDERR_SUMMARY_LENGTH = 500;
|
|
3686
3914
|
var CHILD_ERROR_LINE_PATTERN = /^(?:[A-Za-z]*Error|SqliteError|Error)\b[^\n]*/;
|
|
@@ -3820,6 +4048,9 @@ function failedInvocationStatus(error) {
|
|
|
3820
4048
|
const message = describeError(error).brief;
|
|
3821
4049
|
if (/timed out after \d+ms|prompt timed out/i.test(message))
|
|
3822
4050
|
return "timed_out";
|
|
4051
|
+
if (error !== null && typeof error === "object" && error.name === "TimeoutError") {
|
|
4052
|
+
return "timed_out";
|
|
4053
|
+
}
|
|
3823
4054
|
if (/length-capped|no (?:assistant )?output|empty (?:assistant )?(?:output|text)/i.test(message)) {
|
|
3824
4055
|
return "empty";
|
|
3825
4056
|
}
|
|
@@ -4881,7 +5112,7 @@ function shouldDiscardLastHistorianCompartment(compartments, chunk) {
|
|
|
4881
5112
|
function validateHistorianOutput(text, sessionId, chunk, _priorCompartments, sequenceOffset) {
|
|
4882
5113
|
const parseStarted = startHistorianPublishStage(sessionId, "parse", `response_chars=${text.length}`);
|
|
4883
5114
|
const parsed = parseCompartmentOutput(text);
|
|
4884
|
-
finishHistorianPublishStage(sessionId, "parse", parseStarted, "completed", `compartments=${parsed.compartments.length}`);
|
|
5115
|
+
finishHistorianPublishStage(sessionId, "parse", parseStarted, "completed", `compartments=${parsed.compartments.length} dropped_fact_blocks=${parsed.droppedFactBlocks} dropped_facts=${parsed.droppedFacts}`);
|
|
4885
5116
|
const validationStarted = startHistorianPublishStage(sessionId, "validate");
|
|
4886
5117
|
const finish = (result) => {
|
|
4887
5118
|
finishHistorianPublishStage(sessionId, "validate", validationStarted, result.ok ? "completed" : "failed", result.ok ? `compartments=${result.compartments.length}` : `reason=${JSON.stringify(result.error)}`);
|
|
@@ -4920,6 +5151,7 @@ function validateHistorianOutput(text, sessionId, chunk, _priorCompartments, seq
|
|
|
4920
5151
|
ok: true,
|
|
4921
5152
|
compartments: mapped.compartments,
|
|
4922
5153
|
facts: parsed.facts,
|
|
5154
|
+
...parsed.droppedFactBlocks > 0 ? { droppedFactBlocks: parsed.droppedFactBlocks, droppedFacts: parsed.droppedFacts } : {},
|
|
4923
5155
|
userObservations: parsed.userObservations.length > 0 ? parsed.userObservations : undefined,
|
|
4924
5156
|
primerCandidates: parsed.primerCandidates.length > 0 ? parsed.primerCandidates.slice(0, 1) : undefined,
|
|
4925
5157
|
events: parsed.events.length > 0 ? parsed.events : undefined
|
|
@@ -5172,6 +5404,7 @@ function resolveHiddenCompletionExecutor(executor, client, db, directory, entryP
|
|
|
5172
5404
|
return createV1HiddenCompletionExecutor(client, db, directory);
|
|
5173
5405
|
}
|
|
5174
5406
|
function createV1HiddenCompletionExecutor(client, db, directory) {
|
|
5407
|
+
const asyncChildren = new Set;
|
|
5175
5408
|
return {
|
|
5176
5409
|
capabilities: { tools: true, harness: "opencode" },
|
|
5177
5410
|
async open(run) {
|
|
@@ -5188,11 +5421,17 @@ function createV1HiddenCompletionExecutor(client, db, directory) {
|
|
|
5188
5421
|
preferResponseOnMissingData: true
|
|
5189
5422
|
});
|
|
5190
5423
|
const id = typeof created?.id === "string" ? created.id : "";
|
|
5424
|
+
if (id && run.kind === "dreamer-task")
|
|
5425
|
+
asyncChildren.add(id);
|
|
5191
5426
|
return { id, childSessionId: id || undefined };
|
|
5192
5427
|
},
|
|
5193
|
-
async attempt(
|
|
5428
|
+
async attempt(handle, request) {
|
|
5194
5429
|
if (!client)
|
|
5195
5430
|
throw new Error("Hidden completion client is unavailable");
|
|
5431
|
+
if (asyncChildren.has(handle.id) && supportsPromptAsync(client)) {
|
|
5432
|
+
await promptAsyncAndWaitForIdle(client, request);
|
|
5433
|
+
return;
|
|
5434
|
+
}
|
|
5196
5435
|
await client.session.prompt(request);
|
|
5197
5436
|
},
|
|
5198
5437
|
async collect(handle, limit) {
|
|
@@ -5220,6 +5459,8 @@ function createV1HiddenCompletionExecutor(client, db, directory) {
|
|
|
5220
5459
|
};
|
|
5221
5460
|
},
|
|
5222
5461
|
async close(handle, settlement) {
|
|
5462
|
+
if (handle?.id)
|
|
5463
|
+
asyncChildren.delete(handle.id);
|
|
5223
5464
|
if (!client)
|
|
5224
5465
|
return;
|
|
5225
5466
|
await teardownChildSession({
|
|
@@ -5231,6 +5472,9 @@ function createV1HiddenCompletionExecutor(client, db, directory) {
|
|
|
5231
5472
|
}
|
|
5232
5473
|
};
|
|
5233
5474
|
}
|
|
5475
|
+
function historianReasoningBudgetDiagnostic(outputTokens) {
|
|
5476
|
+
return `historian ran out of output budget while reasoning (length-capped at ${outputTokens} tokens, no text) — set historian.maxTokens or route historian.model to a low-reasoning lane/variant`;
|
|
5477
|
+
}
|
|
5234
5478
|
async function runValidatedHistorianPass(args) {
|
|
5235
5479
|
const firstRun = await runHistorianPrompt({
|
|
5236
5480
|
...args,
|
|
@@ -5457,14 +5701,14 @@ async function runHistorianPrompt(args) {
|
|
|
5457
5701
|
}
|
|
5458
5702
|
const backoffMs = getHistorianRetryBackoffMs(retryIndex);
|
|
5459
5703
|
sessionLog(parentSessionId, `historian retry ${retryIndex + 1}/${MAX_HISTORIAN_RETRIES} after ${backoffMs}ms: ${errorMsg}`);
|
|
5460
|
-
await
|
|
5704
|
+
await sleep2(backoffMs);
|
|
5461
5705
|
}
|
|
5462
5706
|
}
|
|
5463
5707
|
completion = await executor.collect(handle, 50);
|
|
5464
5708
|
const lengthCapped = completion.lengthCapped;
|
|
5465
5709
|
const textResult = completion.text;
|
|
5466
5710
|
const reasoningResult = textResult ? null : completion.reasoning;
|
|
5467
|
-
const emptyError = !textResult && reasoningResult && lengthCapped ?
|
|
5711
|
+
const emptyError = !textResult && reasoningResult && lengthCapped ? historianReasoningBudgetDiagnostic(completion.usage.output) : !textResult && !reasoningResult ? "Historian returned no assistant output." : !textResult ? "Historian returned reasoning but no assistant text." : lengthCapped ? "Historian returned length-capped output." : null;
|
|
5468
5712
|
const invocationId = recordInvocation({
|
|
5469
5713
|
status: emptyError ? "empty" : "completed",
|
|
5470
5714
|
messages: completion.messages,
|
|
@@ -5594,7 +5838,7 @@ function isTransientHistorianPromptError(message) {
|
|
|
5594
5838
|
"overloaded"
|
|
5595
5839
|
].some((token) => normalized.includes(token));
|
|
5596
5840
|
}
|
|
5597
|
-
function
|
|
5841
|
+
function sleep2(ms) {
|
|
5598
5842
|
return new Promise((resolve) => {
|
|
5599
5843
|
setTimeout(resolve, ms);
|
|
5600
5844
|
});
|
|
@@ -5791,13 +6035,25 @@ function runLeaseGuardedWrite(db, holderId, leaseKey, fn, slowWriteThresholdMs)
|
|
|
5791
6035
|
return fn();
|
|
5792
6036
|
}, `lease-guarded-write:${leaseKey}`, slowWriteThresholdMs);
|
|
5793
6037
|
}
|
|
5794
|
-
var LEASE_HEARTBEAT_INTERVAL_MS =
|
|
6038
|
+
var LEASE_HEARTBEAT_INTERVAL_MS = 40 * 1000;
|
|
6039
|
+
function reacquireOwnedLease(db, holderId, leaseKey, generation) {
|
|
6040
|
+
const keys = rowKeys(leaseKey);
|
|
6041
|
+
return runImmediate(db, () => {
|
|
6042
|
+
if (getLeaseHolder(db, leaseKey) !== holderId || getLeaseGeneration(db, leaseKey) !== generation) {
|
|
6043
|
+
return false;
|
|
6044
|
+
}
|
|
6045
|
+
const now = Date.now();
|
|
6046
|
+
setDreamState(db, keys.heartbeat, String(now));
|
|
6047
|
+
setDreamState(db, keys.expiry, String(now + LEASE_DURATION_MS));
|
|
6048
|
+
return true;
|
|
6049
|
+
});
|
|
6050
|
+
}
|
|
5795
6051
|
function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalOrAcquisition = LEASE_HEARTBEAT_INTERVAL_MS) {
|
|
5796
6052
|
const intervalMs = typeof intervalOrAcquisition === "number" ? intervalOrAcquisition : LEASE_HEARTBEAT_INTERVAL_MS;
|
|
5797
6053
|
const acquisition = typeof intervalOrAcquisition === "number" ? undefined : intervalOrAcquisition;
|
|
5798
6054
|
let lost = false;
|
|
5799
|
-
|
|
5800
|
-
let
|
|
6055
|
+
const expectedGeneration = acquisition?.generation ?? getLeaseGeneration(db, leaseKey);
|
|
6056
|
+
let renewalFailures = 0;
|
|
5801
6057
|
const declareLost = (reason) => {
|
|
5802
6058
|
if (lost)
|
|
5803
6059
|
return;
|
|
@@ -5809,32 +6065,20 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalOrAcquisiti
|
|
|
5809
6065
|
return;
|
|
5810
6066
|
try {
|
|
5811
6067
|
if (renewLease(db, holderId, leaseKey, expectedGeneration === null ? undefined : expectedGeneration)) {
|
|
5812
|
-
lastConfirmedAt = Date.now();
|
|
5813
6068
|
return;
|
|
5814
6069
|
}
|
|
5815
|
-
if (expectedGeneration !== null &&
|
|
5816
|
-
declareLost("lease generation changed — another holder acquired it");
|
|
5817
|
-
return;
|
|
5818
|
-
}
|
|
5819
|
-
if (Date.now() - lastConfirmedAt > LEASE_DURATION_MS) {
|
|
5820
|
-
declareLost("lease lapsed past TTL — another holder may have run");
|
|
5821
|
-
return;
|
|
5822
|
-
}
|
|
5823
|
-
const reacquired = acquireLeaseWithAcquisition(db, holderId, leaseKey);
|
|
5824
|
-
if (reacquired) {
|
|
5825
|
-
if (expectedGeneration !== null && reacquired.generation !== expectedGeneration) {
|
|
5826
|
-
declareLost("lease generation changed during reacquisition");
|
|
5827
|
-
return;
|
|
5828
|
-
}
|
|
5829
|
-
expectedGeneration = reacquired.generation;
|
|
5830
|
-
lastConfirmedAt = Date.now();
|
|
6070
|
+
if (expectedGeneration !== null && reacquireOwnedLease(db, holderId, leaseKey, expectedGeneration))
|
|
5831
6071
|
return;
|
|
6072
|
+
const holder = getLeaseHolder(db, leaseKey);
|
|
6073
|
+
if (holder !== null && holder !== holderId) {
|
|
6074
|
+
declareLost(`lease_lost: taken by ${holder}`);
|
|
6075
|
+
} else if (getLeaseGeneration(db, leaseKey) !== expectedGeneration) {
|
|
6076
|
+
declareLost("lease_lost: generation changed");
|
|
6077
|
+
} else {
|
|
6078
|
+
declareLost("lease_expired: reacquire failed (holder missing)");
|
|
5832
6079
|
}
|
|
5833
|
-
declareLost("lease acquired by another holder");
|
|
5834
6080
|
} catch {
|
|
5835
|
-
|
|
5836
|
-
declareLost("lease renewal unconfirmed past TTL");
|
|
5837
|
-
}
|
|
6081
|
+
renewalFailures += 1;
|
|
5838
6082
|
}
|
|
5839
6083
|
};
|
|
5840
6084
|
beat();
|
|
@@ -5846,6 +6090,9 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalOrAcquisiti
|
|
|
5846
6090
|
},
|
|
5847
6091
|
get lost() {
|
|
5848
6092
|
return lost;
|
|
6093
|
+
},
|
|
6094
|
+
get renewalFailures() {
|
|
6095
|
+
return renewalFailures;
|
|
5849
6096
|
}
|
|
5850
6097
|
};
|
|
5851
6098
|
}
|
|
@@ -5923,6 +6170,14 @@ function assertParsedManifestNonEmpty(parsedCount, expectedCount, text, expected
|
|
|
5923
6170
|
}
|
|
5924
6171
|
|
|
5925
6172
|
// ../plugin/src/features/magic-context/dreamer/module-apply.ts
|
|
6173
|
+
var loggedNotOwnerProjects = new Set;
|
|
6174
|
+
function logDreamerNotOwnerOnce(projectIdentity) {
|
|
6175
|
+
if (loggedNotOwnerProjects.has(projectIdentity))
|
|
6176
|
+
return;
|
|
6177
|
+
loggedNotOwnerProjects.add(projectIdentity);
|
|
6178
|
+
log(`[dreamer] ${projectIdentity}: module-managed project; skipping TS writes without an owner route`);
|
|
6179
|
+
}
|
|
6180
|
+
|
|
5926
6181
|
class DreamerModuleBusyError extends Error {
|
|
5927
6182
|
state;
|
|
5928
6183
|
transient = true;
|
|
@@ -6547,7 +6802,7 @@ async function runHiddenSingleShotPrompt(args) {
|
|
|
6547
6802
|
fetchOutput: () => args.executor.collect(handle, 50),
|
|
6548
6803
|
validateOutput: (completion) => {
|
|
6549
6804
|
if (completion.lengthCapped) {
|
|
6550
|
-
throw new Error(`${args.callContext} returned length-capped output`);
|
|
6805
|
+
throw new Error(completion.reasoning && !completion.text ? `${args.callContext} ran out of output budget while reasoning (length-capped at ${completion.usage.output} tokens, no text) — set dreamer.maxTokens or use a low-reasoning model` : `${args.callContext} returned length-capped output`);
|
|
6551
6806
|
}
|
|
6552
6807
|
const text = completion.text;
|
|
6553
6808
|
if (!text && !args.allowEmpty)
|
|
@@ -7120,12 +7375,45 @@ function validateClassifyManifest(text, expectedIds) {
|
|
|
7120
7375
|
return parsed;
|
|
7121
7376
|
}
|
|
7122
7377
|
|
|
7378
|
+
// ../plugin/src/features/magic-context/dreamer/failed-invocation-evidence.ts
|
|
7379
|
+
var FAILED_CHILD_READ_TIMEOUT_MS = 5000;
|
|
7380
|
+
var FAILED_CHILD_MESSAGE_LIMIT = 200;
|
|
7381
|
+
async function readFailedChildMessages(client, sessionId, directory) {
|
|
7382
|
+
if (!client || !sessionId)
|
|
7383
|
+
return;
|
|
7384
|
+
let timer;
|
|
7385
|
+
try {
|
|
7386
|
+
const response = await Promise.race([
|
|
7387
|
+
client.session.messages({
|
|
7388
|
+
path: { id: sessionId },
|
|
7389
|
+
query: { directory, limit: FAILED_CHILD_MESSAGE_LIMIT }
|
|
7390
|
+
}),
|
|
7391
|
+
new Promise((resolve) => {
|
|
7392
|
+
timer = setTimeout(() => resolve(null), FAILED_CHILD_READ_TIMEOUT_MS);
|
|
7393
|
+
})
|
|
7394
|
+
]);
|
|
7395
|
+
if (response === null)
|
|
7396
|
+
return;
|
|
7397
|
+
const messages = normalizeSDKResponse(response, [], {
|
|
7398
|
+
preferResponseOnMissingData: true
|
|
7399
|
+
});
|
|
7400
|
+
return Array.isArray(messages) ? messages : undefined;
|
|
7401
|
+
} catch (error) {
|
|
7402
|
+
log(`[dreamer] failed-child evidence read failed for ${sessionId}: ${String(error)}`);
|
|
7403
|
+
return;
|
|
7404
|
+
} finally {
|
|
7405
|
+
if (timer)
|
|
7406
|
+
clearTimeout(timer);
|
|
7407
|
+
}
|
|
7408
|
+
}
|
|
7409
|
+
|
|
7123
7410
|
// ../plugin/src/features/magic-context/dreamer/classify.ts
|
|
7124
7411
|
var MIN_POOL_TO_CLASSIFY = 10;
|
|
7125
7412
|
var FULL_POOL_CEILING = 100;
|
|
7126
7413
|
var STAGE3_ANCHOR_COUNT = 30;
|
|
7127
7414
|
var CLASSIFY_CHUNK_SIZE = 100;
|
|
7128
7415
|
var CLASSIFY_MODULE_RUN_TIMEOUT_MS = 660000;
|
|
7416
|
+
var HOST_COMPLETION_REQUIRED = "host_completion_required";
|
|
7129
7417
|
|
|
7130
7418
|
class ClassifyModuleFailureError extends Error {
|
|
7131
7419
|
transient = true;
|
|
@@ -7209,13 +7497,12 @@ async function runClassify(args) {
|
|
|
7209
7497
|
let stage;
|
|
7210
7498
|
let toClassify;
|
|
7211
7499
|
let anchors = [];
|
|
7500
|
+
const unclassifiedIds = new Set(getUnclassifiedMemoryIds(args.db, active.map((candidate) => candidate.contextMemory.id)));
|
|
7501
|
+
toClassify = active.filter((candidate) => unclassifiedIds.has(candidate.contextMemory.id));
|
|
7212
7502
|
if (active.length <= FULL_POOL_CEILING) {
|
|
7213
7503
|
stage = 2;
|
|
7214
|
-
toClassify = active;
|
|
7215
7504
|
} else {
|
|
7216
7505
|
stage = 3;
|
|
7217
|
-
const unclassifiedIds = new Set(getUnclassifiedMemoryIds(args.db, active.map((candidate) => candidate.contextMemory.id)));
|
|
7218
|
-
toClassify = active.filter((candidate) => unclassifiedIds.has(candidate.contextMemory.id));
|
|
7219
7506
|
const classified = active.filter((candidate) => !unclassifiedIds.has(candidate.contextMemory.id));
|
|
7220
7507
|
anchors = stratifiedAnchors(classified, STAGE3_ANCHOR_COUNT);
|
|
7221
7508
|
}
|
|
@@ -7236,7 +7523,7 @@ async function runClassify(args) {
|
|
|
7236
7523
|
chunks.push(toClassify.slice(i, i + CLASSIFY_CHUNK_SIZE));
|
|
7237
7524
|
}
|
|
7238
7525
|
const abortController = new AbortController;
|
|
7239
|
-
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
|
|
7526
|
+
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, (reason) => abortController.abort(new Error(reason)), args.leaseAcquisition);
|
|
7240
7527
|
try {
|
|
7241
7528
|
for (let i = 0;i < chunks.length; i += 1) {
|
|
7242
7529
|
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
@@ -7271,68 +7558,89 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
7271
7558
|
memories: chunk.map(toPromptMemory2),
|
|
7272
7559
|
anchors
|
|
7273
7560
|
});
|
|
7561
|
+
const runOnHostCarrier = async (system) => {
|
|
7562
|
+
const executor = resolveHiddenCompletionExecutor(args.hiddenCompletionExecutor, args.client, args.db, args.sessionDirectory, "classify-memories");
|
|
7563
|
+
closeExecutor = executor;
|
|
7564
|
+
handle = await executor.open({
|
|
7565
|
+
parentSessionId: args.parentSessionId,
|
|
7566
|
+
agent: DREAMER_CLASSIFIER_AGENT,
|
|
7567
|
+
kind: "dreamer-task",
|
|
7568
|
+
system,
|
|
7569
|
+
model: args.model,
|
|
7570
|
+
configuredModels: [
|
|
7571
|
+
...args.model ? [args.model] : [],
|
|
7572
|
+
...args.fallbackModels ?? []
|
|
7573
|
+
],
|
|
7574
|
+
timeoutMs: sliceMs,
|
|
7575
|
+
title: "magic-context-dream-classify",
|
|
7576
|
+
directory: args.sessionDirectory,
|
|
7577
|
+
metadata: { task: "classify-memories" }
|
|
7578
|
+
});
|
|
7579
|
+
agentSessionId = handle.id || null;
|
|
7580
|
+
if (!agentSessionId)
|
|
7581
|
+
throw new Error("Could not create classify session.");
|
|
7582
|
+
const opened = handle;
|
|
7583
|
+
const run = await promptSyncWithValidatedOutputRetry(args.client, {
|
|
7584
|
+
path: { id: agentSessionId },
|
|
7585
|
+
query: { directory: args.sessionDirectory },
|
|
7586
|
+
body: {
|
|
7587
|
+
agent: DREAMER_CLASSIFIER_AGENT,
|
|
7588
|
+
system,
|
|
7589
|
+
...modelBodyField(args.model),
|
|
7590
|
+
parts: [{ type: "text", text: prompt, synthetic: true }]
|
|
7591
|
+
}
|
|
7592
|
+
}, {
|
|
7593
|
+
transport: Object.assign((request) => executor.attempt(opened, request), { childSessionId: opened.childSessionId }),
|
|
7594
|
+
timeoutMs: sliceMs,
|
|
7595
|
+
signal,
|
|
7596
|
+
fallbackModels: args.fallbackModels,
|
|
7597
|
+
callContext: "dreamer:classify-memories",
|
|
7598
|
+
fetchOutput: () => executor.collect(opened, 50),
|
|
7599
|
+
validateOutput: (completion) => {
|
|
7600
|
+
const messages = completion.messages ?? [];
|
|
7601
|
+
if (completion.lengthCapped) {
|
|
7602
|
+
throw new Error(completion.reasoning && !completion.text ? `classify ran out of output budget while reasoning (length-capped at ${completion.usage.output} tokens, no text) — set dreamer.maxTokens or use a low-reasoning model` : "classify returned length-capped output");
|
|
7603
|
+
}
|
|
7604
|
+
const text = completion.text;
|
|
7605
|
+
if (!text)
|
|
7606
|
+
throw new Error("classify returned no output");
|
|
7607
|
+
try {
|
|
7608
|
+
validateClassifyManifest(text, new Set(chunk.map((candidate) => candidate.id)));
|
|
7609
|
+
} catch (error) {
|
|
7610
|
+
const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
|
|
7611
|
+
if (providerFailure)
|
|
7612
|
+
throw providerFailure;
|
|
7613
|
+
throw error;
|
|
7614
|
+
}
|
|
7615
|
+
return text;
|
|
7616
|
+
}
|
|
7617
|
+
});
|
|
7618
|
+
promptSettled = true;
|
|
7619
|
+
return run;
|
|
7620
|
+
};
|
|
7274
7621
|
if (moduleRoute) {
|
|
7275
|
-
const { accounting, ...run } = await runClassifyThroughModule(args, chunk, anchors, signal)
|
|
7622
|
+
const { accounting, ...run } = await runClassifyThroughModule(args, chunk, anchors, signal, async (system) => {
|
|
7623
|
+
const run = await runOnHostCarrier(system);
|
|
7624
|
+
const output = run.output;
|
|
7625
|
+
return {
|
|
7626
|
+
text: run.validated,
|
|
7627
|
+
model: output.providerId && output.modelId ? `${output.providerId}/${output.modelId}` : run.attempt.label,
|
|
7628
|
+
length_capped: output.lengthCapped === true,
|
|
7629
|
+
usage: {
|
|
7630
|
+
input: output.usage?.input ?? 0,
|
|
7631
|
+
output: output.usage?.output ?? 0,
|
|
7632
|
+
cache_read: output.usage?.cacheRead ?? 0,
|
|
7633
|
+
cache_write: output.usage?.cacheWrite ?? 0
|
|
7634
|
+
}
|
|
7635
|
+
};
|
|
7636
|
+
});
|
|
7276
7637
|
recordInvocation(args, startedAt, {
|
|
7277
7638
|
status: "completed",
|
|
7278
7639
|
moduleAccounting: accounting
|
|
7279
7640
|
});
|
|
7280
7641
|
return run;
|
|
7281
7642
|
}
|
|
7282
|
-
const
|
|
7283
|
-
closeExecutor = executor;
|
|
7284
|
-
handle = await executor.open({
|
|
7285
|
-
parentSessionId: args.parentSessionId,
|
|
7286
|
-
agent: DREAMER_CLASSIFIER_AGENT,
|
|
7287
|
-
kind: "dreamer-task",
|
|
7288
|
-
system: withContentLanguageDirective(CLASSIFY_SYSTEM_PROMPT, args.language),
|
|
7289
|
-
model: args.model,
|
|
7290
|
-
configuredModels: [...args.model ? [args.model] : [], ...args.fallbackModels ?? []],
|
|
7291
|
-
timeoutMs: sliceMs,
|
|
7292
|
-
title: "magic-context-dream-classify",
|
|
7293
|
-
directory: args.sessionDirectory,
|
|
7294
|
-
metadata: { task: "classify-memories" }
|
|
7295
|
-
});
|
|
7296
|
-
agentSessionId = handle.id || null;
|
|
7297
|
-
if (!agentSessionId)
|
|
7298
|
-
throw new Error("Could not create classify session.");
|
|
7299
|
-
const opened = handle;
|
|
7300
|
-
const run = await promptSyncWithValidatedOutputRetry(args.client, {
|
|
7301
|
-
path: { id: agentSessionId },
|
|
7302
|
-
query: { directory: args.sessionDirectory },
|
|
7303
|
-
body: {
|
|
7304
|
-
agent: DREAMER_CLASSIFIER_AGENT,
|
|
7305
|
-
system: withContentLanguageDirective(CLASSIFY_SYSTEM_PROMPT, args.language),
|
|
7306
|
-
...modelBodyField(args.model),
|
|
7307
|
-
parts: [{ type: "text", text: prompt, synthetic: true }]
|
|
7308
|
-
}
|
|
7309
|
-
}, {
|
|
7310
|
-
transport: Object.assign((request) => executor.attempt(opened, request), { childSessionId: opened.childSessionId }),
|
|
7311
|
-
timeoutMs: sliceMs,
|
|
7312
|
-
signal,
|
|
7313
|
-
fallbackModels: args.fallbackModels,
|
|
7314
|
-
callContext: "dreamer:classify-memories",
|
|
7315
|
-
fetchOutput: () => executor.collect(opened, 50),
|
|
7316
|
-
validateOutput: (completion) => {
|
|
7317
|
-
const messages = completion.messages ?? [];
|
|
7318
|
-
if (completion.lengthCapped) {
|
|
7319
|
-
throw new Error("classify returned length-capped output");
|
|
7320
|
-
}
|
|
7321
|
-
const text = completion.text;
|
|
7322
|
-
if (!text)
|
|
7323
|
-
throw new Error("classify returned no output");
|
|
7324
|
-
try {
|
|
7325
|
-
validateClassifyManifest(text, new Set(chunk.map((candidate) => candidate.id)));
|
|
7326
|
-
} catch (error) {
|
|
7327
|
-
const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
|
|
7328
|
-
if (providerFailure)
|
|
7329
|
-
throw providerFailure;
|
|
7330
|
-
throw error;
|
|
7331
|
-
}
|
|
7332
|
-
return text;
|
|
7333
|
-
}
|
|
7334
|
-
});
|
|
7335
|
-
promptSettled = true;
|
|
7643
|
+
const run = await runOnHostCarrier(withContentLanguageDirective(CLASSIFY_SYSTEM_PROMPT, args.language));
|
|
7336
7644
|
recordInvocation(args, startedAt, {
|
|
7337
7645
|
status: "completed",
|
|
7338
7646
|
messages: run.output.messages,
|
|
@@ -7345,7 +7653,8 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
7345
7653
|
log(`[dreamer] classify chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
7346
7654
|
recordInvocation(args, startedAt, {
|
|
7347
7655
|
status: failedInvocationStatus(failure),
|
|
7348
|
-
error: failure
|
|
7656
|
+
error: failure,
|
|
7657
|
+
messages: args.hiddenCompletionExecutor ? undefined : await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory)
|
|
7349
7658
|
});
|
|
7350
7659
|
if (moduleRoute || failure instanceof HiddenCompletionRefusal || signal.aborted || failure instanceof DreamerProviderOutputFailureError || getPromptFailureDetail(failure)?.failureClass !== "parse_failed" && getPromptFailureDetail(failure) !== null)
|
|
7351
7660
|
throw failure;
|
|
@@ -7359,7 +7668,7 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
7359
7668
|
});
|
|
7360
7669
|
}
|
|
7361
7670
|
}
|
|
7362
|
-
async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
7671
|
+
async function runClassifyThroughModule(args, chunk, anchors, signal, runOnHost) {
|
|
7363
7672
|
const prompt = buildClassifyPrompt({
|
|
7364
7673
|
projectPath: args.projectIdentity,
|
|
7365
7674
|
memories: chunk.map(toPromptMemory2),
|
|
@@ -7367,7 +7676,8 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
7367
7676
|
});
|
|
7368
7677
|
const modelChain = [args.model, ...args.fallbackModels ?? []].map(toModelEntry).filter((entry) => entry !== undefined).map((entry) => entry.model);
|
|
7369
7678
|
const resolvedModelChain = [...new Set(modelChain)];
|
|
7370
|
-
const
|
|
7679
|
+
const commandId = `classify:${args.moduleCommandId ?? Date.now()}:${createHash5("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`;
|
|
7680
|
+
const runTask = (hostCompletion) => args.moduleClient?.call({
|
|
7371
7681
|
sessionId: args.moduleSessionId,
|
|
7372
7682
|
projectRoot: args.moduleProjectRoot,
|
|
7373
7683
|
method: "dreamer.run_task",
|
|
@@ -7376,7 +7686,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
7376
7686
|
v: 1,
|
|
7377
7687
|
session_id: args.moduleSessionId,
|
|
7378
7688
|
task: "classify",
|
|
7379
|
-
command_id:
|
|
7689
|
+
command_id: commandId,
|
|
7380
7690
|
authority_generation: args.moduleAuthorityGeneration,
|
|
7381
7691
|
model_chain: resolvedModelChain,
|
|
7382
7692
|
payload: {
|
|
@@ -7385,12 +7695,20 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
7385
7695
|
memory_id: candidate.id,
|
|
7386
7696
|
content_hash: candidate.normalizedHash
|
|
7387
7697
|
}))
|
|
7388
|
-
}
|
|
7698
|
+
},
|
|
7699
|
+
...hostCompletion ? { host_completion: hostCompletion } : {}
|
|
7389
7700
|
},
|
|
7390
7701
|
signal,
|
|
7391
|
-
timeoutMs: CLASSIFY_MODULE_RUN_TIMEOUT_MS
|
|
7702
|
+
timeoutMs: Math.max(1, resolvedModelChain.length) * CLASSIFY_MODULE_RUN_TIMEOUT_MS + 30000
|
|
7392
7703
|
});
|
|
7393
|
-
const
|
|
7704
|
+
const unwrap = (response) => response?.result ?? response;
|
|
7705
|
+
let result = unwrap(await runTask());
|
|
7706
|
+
const asked = result;
|
|
7707
|
+
if (asked?.code === HOST_COMPLETION_REQUIRED) {
|
|
7708
|
+
if (typeof asked.system_prompt !== "string")
|
|
7709
|
+
throw new Error("module asked for a host classify completion without a system prompt");
|
|
7710
|
+
result = unwrap(await runTask(await runOnHost(asked.system_prompt)));
|
|
7711
|
+
}
|
|
7394
7712
|
if (!result || typeof result !== "object")
|
|
7395
7713
|
throw new Error("module returned invalid classify result");
|
|
7396
7714
|
const manifestText = result.manifest_text;
|
|
@@ -8152,7 +8470,7 @@ async function guardedReadFile(projectRoot, repoRelativePath, signal, fileLimitB
|
|
|
8152
8470
|
const body = guardedReadFileBody(projectRoot, repoRelativePath, signal, fileLimitBytes);
|
|
8153
8471
|
let onAbort;
|
|
8154
8472
|
const abort = new Promise((_, reject) => {
|
|
8155
|
-
onAbort = () => reject(
|
|
8473
|
+
onAbort = () => reject(abortError2(signal));
|
|
8156
8474
|
if (signal.aborted)
|
|
8157
8475
|
onAbort();
|
|
8158
8476
|
else
|
|
@@ -8222,9 +8540,9 @@ async function closeLateOpenOnAbort(openPromise, signal) {
|
|
|
8222
8540
|
return handle;
|
|
8223
8541
|
if (handle)
|
|
8224
8542
|
handle.close().catch(() => {});
|
|
8225
|
-
throw
|
|
8543
|
+
throw abortError2(signal);
|
|
8226
8544
|
}
|
|
8227
|
-
function
|
|
8545
|
+
function abortError2(signal) {
|
|
8228
8546
|
return signal.reason instanceof SmartNoteNetworkError ? signal.reason : new SmartNoteNetworkError("SMART_NOTE_NETWORK: aborted");
|
|
8229
8547
|
}
|
|
8230
8548
|
function isPathInside(root, target) {
|
|
@@ -9043,9 +9361,9 @@ async function evaluateSmartNotes(args) {
|
|
|
9043
9361
|
throw new Error(`Dream lease lost during smart-notes ${phase}`);
|
|
9044
9362
|
}
|
|
9045
9363
|
};
|
|
9046
|
-
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => {
|
|
9364
|
+
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, (reason) => {
|
|
9047
9365
|
leaseLost = true;
|
|
9048
|
-
leaseAbortController.abort(new Error(
|
|
9366
|
+
leaseAbortController.abort(new Error(reason));
|
|
9049
9367
|
log("[dreamer] smart notes: lease lost — aborting");
|
|
9050
9368
|
args.onLeaseLost?.("smart notes");
|
|
9051
9369
|
}, args.leaseAcquisition);
|
|
@@ -9360,6 +9678,7 @@ async function confirmReadOnly(args, noteId, content, surfaceCondition, leaseSig
|
|
|
9360
9678
|
parts: [{ type: "text", text: prompt, synthetic: true }]
|
|
9361
9679
|
}
|
|
9362
9680
|
}, {
|
|
9681
|
+
transport: createPromptAsyncTransport(client, childSessionId),
|
|
9363
9682
|
timeoutMs: Math.max(1000, args.deadline - Date.now()),
|
|
9364
9683
|
signal: promptSignal.signal,
|
|
9365
9684
|
fallbackModels: args.fallbackModels,
|
|
@@ -9667,7 +9986,7 @@ function computeMapBatchSliceMs(remainingMs, batchesRemaining) {
|
|
|
9667
9986
|
return Math.min(remainingMs, Math.max(MAP_BATCH_FLOOR_MS, Math.floor(remainingMs / batchesRemaining)));
|
|
9668
9987
|
}
|
|
9669
9988
|
function isTimeoutClassError2(error) {
|
|
9670
|
-
return
|
|
9989
|
+
return isPromptTimeoutError(error);
|
|
9671
9990
|
}
|
|
9672
9991
|
function shouldRequeueIndependentMapping(state, content, repoDir) {
|
|
9673
9992
|
if (!state.hasSentinel || state.files.length > 0)
|
|
@@ -9722,7 +10041,7 @@ async function mapMemories(args) {
|
|
|
9722
10041
|
}
|
|
9723
10042
|
result.remaining = inputs.length;
|
|
9724
10043
|
const abortController = new AbortController;
|
|
9725
|
-
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
|
|
10044
|
+
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, (reason) => abortController.abort(new Error(reason)), args.leaseAcquisition);
|
|
9726
10045
|
try {
|
|
9727
10046
|
let consecutiveTimeouts = 0;
|
|
9728
10047
|
let timeoutStreakElapsedMs = [];
|
|
@@ -9837,6 +10156,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
9837
10156
|
parts: [{ type: "text", text: prompt, synthetic: true }]
|
|
9838
10157
|
}
|
|
9839
10158
|
}, {
|
|
10159
|
+
transport: createPromptAsyncTransport(client, agentSessionId),
|
|
9840
10160
|
timeoutMs: sliceMs,
|
|
9841
10161
|
signal,
|
|
9842
10162
|
fallbackModels: args.fallbackModels,
|
|
@@ -9871,7 +10191,11 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
9871
10191
|
} catch (error) {
|
|
9872
10192
|
const desc = describeError(error);
|
|
9873
10193
|
log(`[dreamer] map-memories batch failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
9874
|
-
recordInvocation2(args, startedAt, {
|
|
10194
|
+
recordInvocation2(args, startedAt, {
|
|
10195
|
+
status: failedInvocationStatus(error),
|
|
10196
|
+
error,
|
|
10197
|
+
messages: await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory)
|
|
10198
|
+
});
|
|
9875
10199
|
if (error instanceof DreamerModuleFailureError)
|
|
9876
10200
|
throw error;
|
|
9877
10201
|
if (signal.aborted)
|
|
@@ -10196,7 +10520,7 @@ function pruneExpiredPrimerCandidatesForProject(db, projectIdentity, now = Date.
|
|
|
10196
10520
|
db.transaction(() => {
|
|
10197
10521
|
for (const id of toDelete)
|
|
10198
10522
|
stmt.run(id, projectIdentity);
|
|
10199
|
-
})();
|
|
10523
|
+
}).immediate();
|
|
10200
10524
|
return toDelete.length;
|
|
10201
10525
|
}
|
|
10202
10526
|
async function promotePrimers(args) {
|
|
@@ -10615,13 +10939,7 @@ var FRUSTRATION_MARKER_REGEX = /\b(?:not what i asked|i already (?:said|told you
|
|
|
10615
10939
|
var LEARNINGS_BLOCK_REGEX = /<learnings\b[^>]*>(.*?)<\/learnings>/is;
|
|
10616
10940
|
var LEARNING_REGEX = /<learning\b([^>]*)>(.*?)<\/learning>/gis;
|
|
10617
10941
|
var ATTR_REGEX = /([a-zA-Z_:-]+)\s*=\s*"([^"]*)"/g;
|
|
10618
|
-
var VALID_MEMORY_CATEGORIES = new Set(
|
|
10619
|
-
"PROJECT_RULES",
|
|
10620
|
-
"ARCHITECTURE",
|
|
10621
|
-
"CONSTRAINTS",
|
|
10622
|
-
"CONFIG_VALUES",
|
|
10623
|
-
"NAMING"
|
|
10624
|
-
]);
|
|
10942
|
+
var VALID_MEMORY_CATEGORIES = new Set(V2_MEMORY_CATEGORIES);
|
|
10625
10943
|
var RAW_QUOTE_REGEX = /["“”][^"“”]{4,}["“”]|'[^']{4,}'/;
|
|
10626
10944
|
var DATE_REGEX = /\b(?:20\d{2}[-/]\d{1,2}[-/]\d{1,2}|\d{1,2}\/\d{1,2}\/20\d{2}|(?:jan|feb|mar|apr|may|jun|jul|aug|sep|sept|oct|nov|dec)[a-z]*\s+\d{1,2},?\s+20\d{2})\b/i;
|
|
10627
10945
|
function parseRetrospectiveLearnings(text) {
|
|
@@ -11380,6 +11698,10 @@ function validateVerifyManifest(text, expectedIds) {
|
|
|
11380
11698
|
// ../plugin/src/features/magic-context/dreamer/verify.ts
|
|
11381
11699
|
var VERIFY_BATCH_SIZE = 50;
|
|
11382
11700
|
var IDENTICAL_PROVIDER_FAILURE_BATCH_LIMIT = 2;
|
|
11701
|
+
var VERIFY_BATCH_FLOOR_MS = 240000;
|
|
11702
|
+
function computeVerifyBatchSliceMs(remainingMs, batchesRemaining) {
|
|
11703
|
+
return Math.min(remainingMs, Math.max(VERIFY_BATCH_FLOOR_MS, Math.floor(remainingMs / batchesRemaining)));
|
|
11704
|
+
}
|
|
11383
11705
|
function closeBroadCycle(args, cycleStartAt) {
|
|
11384
11706
|
if (!args.forceBroad || cycleStartAt === undefined)
|
|
11385
11707
|
return;
|
|
@@ -11434,17 +11756,19 @@ async function runVerify(args) {
|
|
|
11434
11756
|
batches.push(gate.inScope.slice(i, i + VERIFY_BATCH_SIZE));
|
|
11435
11757
|
}
|
|
11436
11758
|
const abortController = new AbortController;
|
|
11437
|
-
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
|
|
11759
|
+
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, (reason) => abortController.abort(new Error(reason)), args.leaseAcquisition);
|
|
11438
11760
|
let consecutiveProviderFailures = 0;
|
|
11439
11761
|
let priorProviderFailureFingerprint = null;
|
|
11440
11762
|
let lastProviderFailure = null;
|
|
11441
11763
|
try {
|
|
11442
11764
|
for (let i = 0;i < batches.length; i += 1) {
|
|
11443
11765
|
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
11444
|
-
if (remainingMs
|
|
11766
|
+
if (remainingMs < VERIFY_BATCH_FLOOR_MS) {
|
|
11767
|
+
result.stopReason = "deadline";
|
|
11768
|
+
log(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: stopping before batch ${i + 1}/${batches.length} — remaining budget ${remainingMs}ms is below the ${VERIFY_BATCH_FLOOR_MS}ms batch floor`);
|
|
11445
11769
|
break;
|
|
11446
|
-
|
|
11447
|
-
const sliceMs =
|
|
11770
|
+
}
|
|
11771
|
+
const sliceMs = computeVerifyBatchSliceMs(remainingMs, batches.length - i);
|
|
11448
11772
|
const counts = await verifyOneBatch(args, batches[i], sliceMs, abortController.signal);
|
|
11449
11773
|
result.verified += counts.verified;
|
|
11450
11774
|
result.updated += counts.updated;
|
|
@@ -11455,6 +11779,11 @@ async function runVerify(args) {
|
|
|
11455
11779
|
result.remaining -= batchProcessed;
|
|
11456
11780
|
result.batches += 1;
|
|
11457
11781
|
args.onProgress?.(result.verified + result.updated + result.archived + result.skipped + result.refused, result.refused);
|
|
11782
|
+
if (counts.timedOut) {
|
|
11783
|
+
result.stopReason = "batch-timeout";
|
|
11784
|
+
log(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: batch ${i + 1}/${batches.length} timed out after its ${sliceMs}ms slice; stopping with ${result.remaining} remaining`);
|
|
11785
|
+
break;
|
|
11786
|
+
}
|
|
11458
11787
|
if (counts.providerFailure) {
|
|
11459
11788
|
lastProviderFailure = counts.providerFailure;
|
|
11460
11789
|
if (counts.providerFailure.fingerprint === priorProviderFailureFingerprint) {
|
|
@@ -11543,6 +11872,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
11543
11872
|
parts: [{ type: "text", text: prompt, synthetic: true }]
|
|
11544
11873
|
}
|
|
11545
11874
|
}, {
|
|
11875
|
+
transport: createPromptAsyncTransport(client, agentSessionId),
|
|
11546
11876
|
timeoutMs: sliceMs,
|
|
11547
11877
|
signal,
|
|
11548
11878
|
fallbackModels: args.fallbackModels,
|
|
@@ -11577,8 +11907,24 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
11577
11907
|
const providerFailure = error instanceof DreamerProviderOutputFailureError ? error : undefined;
|
|
11578
11908
|
const promptFailure = getPromptFailureDetail(error);
|
|
11579
11909
|
log(`[dreamer] verify batch ${providerFailure ? "provider failure" : "failed"}: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
11580
|
-
recordInvocation4(args, startedAt, {
|
|
11581
|
-
|
|
11910
|
+
recordInvocation4(args, startedAt, {
|
|
11911
|
+
status: failedInvocationStatus(error),
|
|
11912
|
+
error,
|
|
11913
|
+
messages: await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory)
|
|
11914
|
+
});
|
|
11915
|
+
if (error instanceof DreamerModuleFailureError || signal.aborted)
|
|
11916
|
+
throw error;
|
|
11917
|
+
if (promptFailure?.failureClass === "provider_timeout" || isPromptTimeoutError(error)) {
|
|
11918
|
+
return {
|
|
11919
|
+
verified: 0,
|
|
11920
|
+
updated: 0,
|
|
11921
|
+
archived: 0,
|
|
11922
|
+
skipped: 0,
|
|
11923
|
+
refused: 0,
|
|
11924
|
+
timedOut: true
|
|
11925
|
+
};
|
|
11926
|
+
}
|
|
11927
|
+
if (promptFailure !== null && promptFailure.failureClass !== "parse_failed" && !providerFailure)
|
|
11582
11928
|
throw error;
|
|
11583
11929
|
return {
|
|
11584
11930
|
verified: 0,
|
|
@@ -11820,6 +12166,16 @@ function dreamRunFailureDetail(error) {
|
|
|
11820
12166
|
}
|
|
11821
12167
|
const described = describeError(error);
|
|
11822
12168
|
const message = described.brief;
|
|
12169
|
+
if (error instanceof Error && error.name === "HiddenAgentStepLimit") {
|
|
12170
|
+
return {
|
|
12171
|
+
failure_class: "step_limit",
|
|
12172
|
+
model_attempted: null,
|
|
12173
|
+
models_tried: [],
|
|
12174
|
+
provider_error: null,
|
|
12175
|
+
timeout_ms: null,
|
|
12176
|
+
child_session_id: null
|
|
12177
|
+
};
|
|
12178
|
+
}
|
|
11823
12179
|
const providerFailure = error instanceof HiddenCompletionRefusal || error instanceof Error && error.name === "DreamerProviderOutputFailureError";
|
|
11824
12180
|
return {
|
|
11825
12181
|
failure_class: providerFailure ? "provider_error" : /no models?|model chain is empty/i.test(message) ? "no_models" : "unknown",
|
|
@@ -11959,11 +12315,16 @@ function createDreamTaskExecutor(deps) {
|
|
|
11959
12315
|
});
|
|
11960
12316
|
};
|
|
11961
12317
|
reportProgress(0);
|
|
12318
|
+
if (config.modelChainUnavailable) {
|
|
12319
|
+
return {
|
|
12320
|
+
status: "completed",
|
|
12321
|
+
detail: "skipped: Pi model chain is empty (no configured model resolves in Pi)"
|
|
12322
|
+
};
|
|
12323
|
+
}
|
|
11962
12324
|
const incompleteMessage = (remaining) => {
|
|
11963
12325
|
const processed = processedDreamTaskItems(backlogAtStart.pending, remaining);
|
|
11964
12326
|
return `${config.task} incomplete: ${remaining} remain (was ${backlogAtStart.pending} at run start; processed ${processed} this run)`;
|
|
11965
12327
|
};
|
|
11966
|
-
const parent = await resolveParentSessionId();
|
|
11967
12328
|
let moduleRoute;
|
|
11968
12329
|
if (config.task === "curate" || config.task === "map-memories" || config.task === "compress-cues" || config.task === "classify-memories" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
|
|
11969
12330
|
try {
|
|
@@ -11979,6 +12340,19 @@ function createDreamTaskExecutor(deps) {
|
|
|
11979
12340
|
throw new DreamerModuleFailureError("authority.status", error);
|
|
11980
12341
|
}
|
|
11981
12342
|
}
|
|
12343
|
+
if (!moduleRoute && getAuthorityManagedMarker(db, projectIdentity) && [
|
|
12344
|
+
"curate",
|
|
12345
|
+
"map-memories",
|
|
12346
|
+
"compress-cues",
|
|
12347
|
+
"classify-memories",
|
|
12348
|
+
"verify",
|
|
12349
|
+
"verify-broad",
|
|
12350
|
+
"retrospective"
|
|
12351
|
+
].includes(config.task)) {
|
|
12352
|
+
logDreamerNotOwnerOnce(projectIdentity);
|
|
12353
|
+
return { status: "completed", detail: "skipped: module-managed memory; not owner" };
|
|
12354
|
+
}
|
|
12355
|
+
const parent = await resolveParentSessionId();
|
|
11982
12356
|
if (!leaseOwnershipMatches(db, holderId, leaseAcquisition.generation, leaseKey)) {
|
|
11983
12357
|
throw new Error("Dream lease lost during executor setup");
|
|
11984
12358
|
}
|
|
@@ -12168,13 +12542,14 @@ function createDreamTaskExecutor(deps) {
|
|
|
12168
12542
|
});
|
|
12169
12543
|
return { status: "completed" };
|
|
12170
12544
|
}
|
|
12171
|
-
const
|
|
12545
|
+
const batchTimedOut = result.stopReason === "batch-timeout";
|
|
12546
|
+
const error = batchTimedOut ? `${config.task}: a batch timed out within its time slice; ${result.remaining} remain` : incompleteMessage(result.remaining);
|
|
12172
12547
|
recordRun("failed", error, {
|
|
12173
12548
|
progress: verificationProgress,
|
|
12174
12549
|
memoryChanges: computeMemoryDelta(memoryBefore),
|
|
12175
12550
|
backlogAfter
|
|
12176
12551
|
});
|
|
12177
|
-
return { status: "failed", transient:
|
|
12552
|
+
return { status: "failed", transient: !batchTimedOut, error };
|
|
12178
12553
|
}
|
|
12179
12554
|
recordRun("completed", null, {
|
|
12180
12555
|
progress: verificationProgress,
|
|
@@ -13000,25 +13375,45 @@ function ensureSeeded(db, projectIdentity, config, now) {
|
|
|
13000
13375
|
const nextDueAt = nextDueAtMs(config.schedule, now);
|
|
13001
13376
|
seedTaskScheduleState(db, projectIdentity, config.task, nextDueAt, lastRunAt, config.schedule);
|
|
13002
13377
|
}
|
|
13378
|
+
function firstRepeatedCivilMinute(candidateMs) {
|
|
13379
|
+
const date = new Date(candidateMs);
|
|
13380
|
+
const first = new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes()).getTime();
|
|
13381
|
+
return first < candidateMs ? first : null;
|
|
13382
|
+
}
|
|
13003
13383
|
function reconcileSchedule(db, projectIdentity, config, now) {
|
|
13004
13384
|
ensureSeeded(db, projectIdentity, config, now);
|
|
13005
|
-
|
|
13006
|
-
if (!stored || stored.schedule === config.schedule)
|
|
13007
|
-
return;
|
|
13008
|
-
if (config.schedule.trim() === "") {
|
|
13009
|
-
writeTaskScheduleState(db, { ...stored, schedule: config.schedule, nextDueAt: null });
|
|
13010
|
-
return;
|
|
13011
|
-
}
|
|
13012
|
-
if (stored.schedule === null && stored.nextDueAt !== null) {
|
|
13013
|
-
writeTaskScheduleState(db, { ...stored, schedule: config.schedule });
|
|
13385
|
+
if (getTaskScheduleState(db, projectIdentity, config.task)?.schedule === config.schedule)
|
|
13014
13386
|
return;
|
|
13387
|
+
const candidate = nextDueAtMs(config.schedule, now);
|
|
13388
|
+
const repeatedFirst = candidate === null ? null : firstRepeatedCivilMinute(candidate);
|
|
13389
|
+
const afterRepeatedFirst = repeatedFirst === null ? candidate : nextDueAtMs(config.schedule, now, repeatedFirst);
|
|
13390
|
+
db.exec("BEGIN IMMEDIATE");
|
|
13391
|
+
let committed = false;
|
|
13392
|
+
try {
|
|
13393
|
+
const stored = getTaskScheduleState(db, projectIdentity, config.task);
|
|
13394
|
+
if (stored && stored.schedule !== config.schedule) {
|
|
13395
|
+
if (stored.schedule === null && stored.nextDueAt !== null) {
|
|
13396
|
+
writeTaskScheduleState(db, { ...stored, schedule: config.schedule });
|
|
13397
|
+
} else {
|
|
13398
|
+
const nextDueAt = repeatedFirst !== null && candidate !== null && stored.nextDueAt !== null && stored.nextDueAt > candidate && stored.lastStatus !== null ? afterRepeatedFirst : candidate;
|
|
13399
|
+
const reconciledNextDueAt = stored.nextDueAt === null ? nextDueAt : nextDueAt === null ? stored.nextDueAt : Math.min(stored.nextDueAt, nextDueAt);
|
|
13400
|
+
writeTaskScheduleState(db, {
|
|
13401
|
+
...stored,
|
|
13402
|
+
schedule: config.schedule,
|
|
13403
|
+
nextDueAt: reconciledNextDueAt,
|
|
13404
|
+
retryCount: reconciledNextDueAt === stored.nextDueAt ? stored.retryCount : 0
|
|
13405
|
+
});
|
|
13406
|
+
}
|
|
13407
|
+
}
|
|
13408
|
+
db.exec("COMMIT");
|
|
13409
|
+
committed = true;
|
|
13410
|
+
} finally {
|
|
13411
|
+
if (!committed) {
|
|
13412
|
+
try {
|
|
13413
|
+
db.exec("ROLLBACK");
|
|
13414
|
+
} catch {}
|
|
13415
|
+
}
|
|
13015
13416
|
}
|
|
13016
|
-
writeTaskScheduleState(db, {
|
|
13017
|
-
...stored,
|
|
13018
|
-
schedule: config.schedule,
|
|
13019
|
-
nextDueAt: nextDueAtMs(config.schedule, now),
|
|
13020
|
-
retryCount: 0
|
|
13021
|
-
});
|
|
13022
13417
|
}
|
|
13023
13418
|
function planDueTasks(db, projectIdentity, tasks, now) {
|
|
13024
13419
|
const pruned = pruneNonCanonicalTaskRows(db, projectIdentity, CANONICAL_DREAM_TASKS);
|
|
@@ -13027,6 +13422,8 @@ function planDueTasks(db, projectIdentity, tasks, now) {
|
|
|
13027
13422
|
}
|
|
13028
13423
|
const due = [];
|
|
13029
13424
|
for (const config of tasks) {
|
|
13425
|
+
if (config.schedule.trim() === "")
|
|
13426
|
+
continue;
|
|
13030
13427
|
reconcileSchedule(db, projectIdentity, config, now);
|
|
13031
13428
|
const state = getTaskScheduleState(db, projectIdentity, config.task);
|
|
13032
13429
|
if (!state || state.nextDueAt === null)
|
|
@@ -13112,10 +13509,11 @@ async function runDomainGroup(deps, group, cb) {
|
|
|
13112
13509
|
}
|
|
13113
13510
|
try {
|
|
13114
13511
|
for (const due of [...group].sort((a, b) => compareTaskOrder(a.config.task, b.config.task))) {
|
|
13115
|
-
if (!
|
|
13512
|
+
if (!reacquireOwnedLease(db, holderId, leaseKey, acquisition.generation)) {
|
|
13116
13513
|
log(`[dreamer] domain lease lost (${leaseKey}) — stopping remaining task(s)`);
|
|
13117
13514
|
break;
|
|
13118
13515
|
}
|
|
13516
|
+
acquisition = { acquiredAt: Date.now(), generation: acquisition.generation };
|
|
13119
13517
|
if (!cb?.forceGate) {
|
|
13120
13518
|
const gatePass = evaluateTaskGate(due.config.task, {
|
|
13121
13519
|
db,
|
|
@@ -13704,7 +14102,8 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
|
|
|
13704
14102
|
}
|
|
13705
14103
|
const dreamerConfig = reg.dreamerConfig;
|
|
13706
14104
|
const dreamingEnabled = Boolean(dreamerConfig && dreamerConfig.disable !== true);
|
|
13707
|
-
const
|
|
14105
|
+
const configuredTasks = dreamingEnabled && dreamerConfig ? buildDreamTaskRuntimeConfigs(dreamerConfig, reg.harness, reg.language, reg.mural?.model) : [];
|
|
14106
|
+
const runtimeConfigs = reg.validateTaskModels?.(configuredTasks) ?? configuredTasks;
|
|
13708
14107
|
await sweepOrphanedInternalChildren(reg, runtimeConfigs.filter((config) => PRIVACY_SENSITIVE_CHILD_TASKS.includes(config.task)).map((config) => config.timeoutMinutes));
|
|
13709
14108
|
if (commitIndexingEnabled && reg.gitCommitIndexing) {
|
|
13710
14109
|
await sweepGitCommits({
|
|
@@ -13719,6 +14118,10 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
|
|
|
13719
14118
|
}
|
|
13720
14119
|
try {
|
|
13721
14120
|
await runCompiledSmartNoteSweep(reg, db);
|
|
14121
|
+
} catch (error) {
|
|
14122
|
+
log(`[dreamer] compiled smart-note sweep failed for ${reg.projectIdentity}:`, error);
|
|
14123
|
+
}
|
|
14124
|
+
try {
|
|
13722
14125
|
const executor = createDreamTaskExecutor({
|
|
13723
14126
|
client: reg.client,
|
|
13724
14127
|
sessionDirectory: reg.directory,
|
|
@@ -13773,6 +14176,10 @@ async function sweepOrphanedInternalChildren(reg, privacyTimeoutMinutes) {
|
|
|
13773
14176
|
}
|
|
13774
14177
|
}
|
|
13775
14178
|
async function runCompiledSmartNoteSweep(reg, db) {
|
|
14179
|
+
if (getAuthorityManagedMarker(db, reg.projectIdentity)) {
|
|
14180
|
+
logDreamerNotOwnerOnce(reg.projectIdentity);
|
|
14181
|
+
return;
|
|
14182
|
+
}
|
|
13776
14183
|
const leaseKey = leaseKeyFor("evaluate-smart-notes", reg.projectIdentity);
|
|
13777
14184
|
const holderId = crypto.randomUUID();
|
|
13778
14185
|
if (!acquireLease(db, holderId, leaseKey))
|
|
@@ -15418,6 +15825,40 @@ function extractPiTextContent(content) {
|
|
|
15418
15825
|
}
|
|
15419
15826
|
|
|
15420
15827
|
// src/dreamer/index.ts
|
|
15828
|
+
var warnedUnknownModels = new Set;
|
|
15829
|
+
var modelAvailability = new WeakMap;
|
|
15830
|
+
function validatePiDreamerModels(tasks, registry) {
|
|
15831
|
+
let resolved = modelAvailability.get(registry);
|
|
15832
|
+
if (!resolved) {
|
|
15833
|
+
resolved = new Map;
|
|
15834
|
+
modelAvailability.set(registry, resolved);
|
|
15835
|
+
}
|
|
15836
|
+
return tasks.map((task) => {
|
|
15837
|
+
const entries = [task.model, ...task.fallbackModels ?? []].filter((entry) => entry !== undefined);
|
|
15838
|
+
const valid = entries.filter((entry) => {
|
|
15839
|
+
const model = typeof entry === "string" ? entry : entry.model;
|
|
15840
|
+
let available = resolved.get(model);
|
|
15841
|
+
if (available === undefined) {
|
|
15842
|
+
const separator = model.indexOf("/");
|
|
15843
|
+
available = separator > 0 && Boolean(registry.find(model.slice(0, separator), model.slice(separator + 1)));
|
|
15844
|
+
resolved.set(model, available);
|
|
15845
|
+
}
|
|
15846
|
+
if (available)
|
|
15847
|
+
return true;
|
|
15848
|
+
if (!warnedUnknownModels.has(model)) {
|
|
15849
|
+
log(`[dreamer] WARNING: dropping Pi model not found: ${model}`);
|
|
15850
|
+
warnedUnknownModels.add(model);
|
|
15851
|
+
}
|
|
15852
|
+
return false;
|
|
15853
|
+
});
|
|
15854
|
+
return {
|
|
15855
|
+
...task,
|
|
15856
|
+
model: valid[0],
|
|
15857
|
+
fallbackModels: valid.slice(1),
|
|
15858
|
+
modelChainUnavailable: entries.length > 0 && valid.length === 0
|
|
15859
|
+
};
|
|
15860
|
+
});
|
|
15861
|
+
}
|
|
15421
15862
|
var PI_DREAMER_PROJECTS = Symbol.for("magic-context.pi.dreamer-registered-projects");
|
|
15422
15863
|
function getRegisteredProjects() {
|
|
15423
15864
|
const globals = globalThis;
|
|
@@ -15446,7 +15887,8 @@ var sessionCounter = 0;
|
|
|
15446
15887
|
var piSubagentRunnerFactory = () => new PiSubagentRunner;
|
|
15447
15888
|
var startDreamScheduleTimerFn = startDreamScheduleTimer;
|
|
15448
15889
|
function registerPiDreamerProject(opts) {
|
|
15449
|
-
|
|
15890
|
+
const directory = resolve3(opts.projectDir);
|
|
15891
|
+
if (opts.config.disable === true || directory === parse(directory).root || directory === homedir2()) {
|
|
15450
15892
|
return;
|
|
15451
15893
|
}
|
|
15452
15894
|
const existing = registeredProjects2.get(opts.projectIdentity);
|
|
@@ -15459,7 +15901,7 @@ function registerPiDreamerProject(opts) {
|
|
|
15459
15901
|
callback(projectIdentity);
|
|
15460
15902
|
};
|
|
15461
15903
|
if (existing) {
|
|
15462
|
-
if (existing.generation && existing.projectDir === opts.projectDir) {
|
|
15904
|
+
if (existing.generation && existing.projectDir === opts.projectDir && (!opts.modelRegistry || existing.modelRegistry)) {
|
|
15463
15905
|
return;
|
|
15464
15906
|
}
|
|
15465
15907
|
existing.cleanup();
|
|
@@ -15472,12 +15914,14 @@ function registerPiDreamerProject(opts) {
|
|
|
15472
15914
|
});
|
|
15473
15915
|
let cleanup;
|
|
15474
15916
|
let cancelled = false;
|
|
15917
|
+
const modelRegistry = opts.modelRegistry;
|
|
15475
15918
|
startDreamScheduleTimerFn({
|
|
15476
15919
|
directory: opts.projectDir,
|
|
15477
15920
|
projectIdentity: opts.projectIdentity,
|
|
15478
15921
|
harness: opts.harness,
|
|
15479
15922
|
client,
|
|
15480
15923
|
dreamerConfig: opts.config,
|
|
15924
|
+
validateTaskModels: modelRegistry ? (tasks) => validatePiDreamerModels(tasks, modelRegistry) : undefined,
|
|
15481
15925
|
sampleDreamRun: opts.sampleDreamRun,
|
|
15482
15926
|
language: opts.language,
|
|
15483
15927
|
gitCommitIndexing: opts.gitCommitIndexing,
|
|
@@ -15509,7 +15953,7 @@ function registerPiDreamerProject(opts) {
|
|
|
15509
15953
|
const manualRun = runManualDream({
|
|
15510
15954
|
db: manualOpts.db,
|
|
15511
15955
|
projectIdentity: manualOpts.projectIdentity,
|
|
15512
|
-
tasks: buildDreamTaskRuntimeConfigs(dreamerConfig, manualOpts.harness, manualOpts.language, mural?.model),
|
|
15956
|
+
tasks: manualOpts.modelRegistry ? validatePiDreamerModels(buildDreamTaskRuntimeConfigs(dreamerConfig, manualOpts.harness, manualOpts.language, mural?.model), manualOpts.modelRegistry) : buildDreamTaskRuntimeConfigs(dreamerConfig, manualOpts.harness, manualOpts.language, mural?.model),
|
|
15513
15957
|
executor: createDreamTaskExecutor({
|
|
15514
15958
|
client: manualClient,
|
|
15515
15959
|
sessionDirectory: manualOpts.projectDir,
|
|
@@ -15542,7 +15986,8 @@ function registerPiDreamerProject(opts) {
|
|
|
15542
15986
|
cleanup?.();
|
|
15543
15987
|
},
|
|
15544
15988
|
runManual,
|
|
15545
|
-
projectDir: opts.projectDir
|
|
15989
|
+
projectDir: opts.projectDir,
|
|
15990
|
+
modelRegistry: opts.modelRegistry
|
|
15546
15991
|
});
|
|
15547
15992
|
}
|
|
15548
15993
|
async function runPiDreamForProject(projectIdentity, task, registrationOwner) {
|
|
@@ -16054,7 +16499,7 @@ function formatEmbedStatusText(coverage, drain) {
|
|
|
16054
16499
|
lines.push(`Synapse — ${formatSynapseLaneDescriptor(coverage.synapseDescriptor)}`);
|
|
16055
16500
|
}
|
|
16056
16501
|
lines.push(`This session: ${coverage.session.embedded} / ${coverage.session.total} compartments embedded`);
|
|
16057
|
-
lines.push(`Project memories: ${coverage.memories.embedded} / ${coverage.memories.total} embedded`);
|
|
16502
|
+
lines.push(coverage.memories.memoryEnabled === false ? "Project memories: off (memory disabled)" : `Project memories: ${coverage.memories.embedded} / ${coverage.memories.total} embedded`);
|
|
16058
16503
|
if (coverage.commits.gitEnabled) {
|
|
16059
16504
|
lines.push(`Git commits: ${coverage.commits.embedded} / ${coverage.commits.total}`);
|
|
16060
16505
|
} else {
|
|
@@ -16230,7 +16675,6 @@ No active Pi session is available.`,
|
|
|
16230
16675
|
projectDir: deps.projectDir,
|
|
16231
16676
|
projectIdentity: deps.projectIdentity
|
|
16232
16677
|
};
|
|
16233
|
-
const memoryEnabled = deps.resolveMemoryEnabled?.(ctx) ?? deps.memoryEnabled;
|
|
16234
16678
|
const sub = args.trim().toLowerCase();
|
|
16235
16679
|
if (sub === "pause") {
|
|
16236
16680
|
embedPauseBySession.add(sessionId);
|
|
@@ -16247,16 +16691,6 @@ Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`,
|
|
|
16247
16691
|
});
|
|
16248
16692
|
return;
|
|
16249
16693
|
}
|
|
16250
|
-
if (memoryEnabled === false) {
|
|
16251
|
-
sendStatus({
|
|
16252
|
-
title: "/ctx-embed",
|
|
16253
|
-
text: `## /ctx-embed
|
|
16254
|
-
|
|
16255
|
-
Memory is disabled for this project, so there is no semantic embedding to backfill.`,
|
|
16256
|
-
level: "info"
|
|
16257
|
-
});
|
|
16258
|
-
return;
|
|
16259
|
-
}
|
|
16260
16694
|
await ensureProjectRegisteredFromPiDirectory(project.projectDir, deps.db);
|
|
16261
16695
|
if (sub === "start") {
|
|
16262
16696
|
const { text, level } = await runEmbedDrain(deps.db, project.projectIdentity, sessionId, {
|
|
@@ -16289,13 +16723,11 @@ ${statusText}`,
|
|
|
16289
16723
|
}
|
|
16290
16724
|
});
|
|
16291
16725
|
}
|
|
16292
|
-
function maybeAutoEmbedPiSession(deps, sessionId, projectDir, projectIdentity
|
|
16726
|
+
function maybeAutoEmbedPiSession(deps, sessionId, projectDir, projectIdentity) {
|
|
16293
16727
|
if (autoEmbedAttemptedBySession.has(sessionId))
|
|
16294
16728
|
return;
|
|
16295
16729
|
if (embedPauseBySession.has(sessionId))
|
|
16296
16730
|
return;
|
|
16297
|
-
if (deps.memoryEnabled === false)
|
|
16298
|
-
return;
|
|
16299
16731
|
autoEmbedAttemptedBySession.add(sessionId);
|
|
16300
16732
|
(async () => {
|
|
16301
16733
|
let drainReachedTerminal = false;
|
|
@@ -16331,7 +16763,7 @@ function executeFlush(db, sessionId) {
|
|
|
16331
16763
|
removePendingOp(db, sessionId, op.tagId);
|
|
16332
16764
|
dropped++;
|
|
16333
16765
|
}
|
|
16334
|
-
})();
|
|
16766
|
+
}).immediate();
|
|
16335
16767
|
const parts = [];
|
|
16336
16768
|
if (dropped > 0)
|
|
16337
16769
|
parts.push(`${dropped} dropped`);
|
|
@@ -16630,7 +17062,7 @@ function createTagger() {
|
|
|
16630
17062
|
db.transaction(() => {
|
|
16631
17063
|
getUpsertCounterStatement(db).run(sessionId, next, getHarness());
|
|
16632
17064
|
insertTag(db, sessionId, messageId, type, byteSize, next, reasoningByteSize, toolName, inputByteSize, toolOwnerMessageId, entryFingerprint, tokenCounts);
|
|
16633
|
-
})();
|
|
17065
|
+
}).immediate();
|
|
16634
17066
|
} catch (error) {
|
|
16635
17067
|
if (!isUniqueConstraintError(error)) {
|
|
16636
17068
|
throw error;
|
|
@@ -16866,7 +17298,8 @@ var canonicalReasons = new Set([
|
|
|
16866
17298
|
"ttl_expiry",
|
|
16867
17299
|
"epoch_change",
|
|
16868
17300
|
"coverage_fold",
|
|
16869
|
-
"profile_transition"
|
|
17301
|
+
"profile_transition",
|
|
17302
|
+
"host_compaction"
|
|
16870
17303
|
]);
|
|
16871
17304
|
var piReasonAliases = {
|
|
16872
17305
|
project_memory_change: "project_memory_epoch",
|
|
@@ -17100,6 +17533,72 @@ var RECENT_TOOL_SKELETON_WINDOW = 20;
|
|
|
17100
17533
|
function buildReplacementContent(tagId) {
|
|
17101
17534
|
return `[dropped §${tagId}§]`;
|
|
17102
17535
|
}
|
|
17536
|
+
function applyNewToolDrop(target, options) {
|
|
17537
|
+
if (!target)
|
|
17538
|
+
return { result: "absent", mode: "full" };
|
|
17539
|
+
if (options.inWindow && hasSmallToolInput(target) || options.keepSkeleton === true || target.cannotRemove?.() === true) {
|
|
17540
|
+
const strip = target.hasAttachments?.() === true;
|
|
17541
|
+
return {
|
|
17542
|
+
result: (strip ? target.skeletonStripped?.() : target.skeletonReal?.()) ?? "absent",
|
|
17543
|
+
mode: strip ? "skeleton_stripped" : "skeleton_real"
|
|
17544
|
+
};
|
|
17545
|
+
}
|
|
17546
|
+
const result = target.drop?.() ?? "absent";
|
|
17547
|
+
if (result === "truncated" && target.hasAttachments?.() === true) {
|
|
17548
|
+
return { result: target.skeletonStripped?.() ?? "absent", mode: "skeleton_stripped" };
|
|
17549
|
+
}
|
|
17550
|
+
return { result, mode: result === "truncated" ? "skeleton_real" : "full" };
|
|
17551
|
+
}
|
|
17552
|
+
function hasSmallToolInput(target) {
|
|
17553
|
+
const bytes = target?.inputStringBytes?.() ?? null;
|
|
17554
|
+
return bytes !== null && bytes <= SKELETON_REAL_INPUT_MAX_BYTES;
|
|
17555
|
+
}
|
|
17556
|
+
var CACHE_LOSING_FOLD_REASONS = new Set([
|
|
17557
|
+
"model_change",
|
|
17558
|
+
"system_hash",
|
|
17559
|
+
"ttl_idle",
|
|
17560
|
+
"host_compaction"
|
|
17561
|
+
]);
|
|
17562
|
+
function sameBytes(left, right) {
|
|
17563
|
+
if (left === null || right === null)
|
|
17564
|
+
return left === right;
|
|
17565
|
+
return Buffer.compare(Buffer.from(left), Buffer.from(right)) === 0;
|
|
17566
|
+
}
|
|
17567
|
+
function foldChangesServedPrefix(before, after) {
|
|
17568
|
+
if (!sameBytes(before.m0Bytes, after.m0Bytes))
|
|
17569
|
+
return true;
|
|
17570
|
+
if (!sameBytes(before.m1Bytes, after.m1Bytes))
|
|
17571
|
+
return true;
|
|
17572
|
+
return before.muralDataUrl !== after.muralDataUrl;
|
|
17573
|
+
}
|
|
17574
|
+
function foldBustsServedPrefix(reason, before, after) {
|
|
17575
|
+
return CACHE_LOSING_FOLD_REASONS.has(reason ?? "") || foldChangesServedPrefix(before, after);
|
|
17576
|
+
}
|
|
17577
|
+
function convertLegacyToolSkeletons(db, sessionId, targets) {
|
|
17578
|
+
const rows = db.prepare(`SELECT tag_number AS tagNumber, drop_mode AS dropMode
|
|
17579
|
+
FROM tags
|
|
17580
|
+
WHERE session_id = ? AND type = 'tool' AND status = 'dropped'
|
|
17581
|
+
AND drop_mode IN ('truncated', 'full')
|
|
17582
|
+
ORDER BY tag_number`).all(sessionId);
|
|
17583
|
+
const converted = new Map;
|
|
17584
|
+
for (const row of rows) {
|
|
17585
|
+
const target = targets.get(row.tagNumber);
|
|
17586
|
+
if (target?.canDrop?.() !== true)
|
|
17587
|
+
continue;
|
|
17588
|
+
const cannotRemove = target.cannotRemove?.() === true || target.requiresToolArcSkeleton === true || target.wouldStrandConversationEnd?.() === true;
|
|
17589
|
+
let mode;
|
|
17590
|
+
if (row.dropMode === "full") {
|
|
17591
|
+
if (target.cannotRemove?.() !== true)
|
|
17592
|
+
continue;
|
|
17593
|
+
mode = "skeleton_real";
|
|
17594
|
+
} else {
|
|
17595
|
+
mode = hasSmallToolInput(target) || cannotRemove ? "skeleton_real" : "full";
|
|
17596
|
+
}
|
|
17597
|
+
updateTagDropMode(db, sessionId, row.tagNumber, mode);
|
|
17598
|
+
converted.set(row.tagNumber, mode);
|
|
17599
|
+
}
|
|
17600
|
+
return converted;
|
|
17601
|
+
}
|
|
17103
17602
|
function applyPendingOperations(sessionId, db, targets, protectedTagIds, preloadedTags, preloadedPendingOps, syntheticPendingOps = [], editMarkerTagIds = new Set, onTagReduced, onBatchComplete) {
|
|
17104
17603
|
let didMutateMessage = false;
|
|
17105
17604
|
let diagnostics;
|
|
@@ -17159,7 +17658,8 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
17159
17658
|
let shouldPersistDrop = false;
|
|
17160
17659
|
if (isToolTag) {
|
|
17161
17660
|
if (editMarkerTagIds.has(pendingOp.tagId)) {
|
|
17162
|
-
const
|
|
17661
|
+
const strip = target?.hasAttachments?.() === true;
|
|
17662
|
+
const markResult = (strip ? target?.editMarkerStripped?.() : target?.editMarker?.()) ?? "absent";
|
|
17163
17663
|
if (markResult === "incomplete" || markResult === "absent") {
|
|
17164
17664
|
reject(`edit_marker_${markResult}`);
|
|
17165
17665
|
continue;
|
|
@@ -17167,34 +17667,23 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
17167
17667
|
didMutateMessage = true;
|
|
17168
17668
|
operationMutated = true;
|
|
17169
17669
|
onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "edit_marker" });
|
|
17170
|
-
updateTagDropMode(db, sessionId, pendingOp.tagId, "edit_marker");
|
|
17171
|
-
shouldPersistDrop = true;
|
|
17172
|
-
} else if (skeletonWindow.has(pendingOp.tagId)) {
|
|
17173
|
-
const truncResult = target?.truncate?.() ?? "absent";
|
|
17174
|
-
if (truncResult === "incomplete" || synthetic && truncResult !== "truncated") {
|
|
17175
|
-
reject(`truncate_${truncResult}`);
|
|
17176
|
-
continue;
|
|
17177
|
-
}
|
|
17178
|
-
if (truncResult === "truncated") {
|
|
17179
|
-
didMutateMessage = true;
|
|
17180
|
-
operationMutated = true;
|
|
17181
|
-
onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "truncated" });
|
|
17182
|
-
} else {
|
|
17183
|
-
reject(`truncate_${truncResult}`);
|
|
17184
|
-
}
|
|
17185
|
-
updateTagDropMode(db, sessionId, pendingOp.tagId, "truncated");
|
|
17670
|
+
updateTagDropMode(db, sessionId, pendingOp.tagId, strip ? "edit_marker_stripped" : "edit_marker");
|
|
17186
17671
|
shouldPersistDrop = true;
|
|
17187
17672
|
} else {
|
|
17188
|
-
const dropResult = target
|
|
17673
|
+
const { result: dropResult, mode: appliedMode } = applyNewToolDrop(target, {
|
|
17674
|
+
inWindow: skeletonWindow.has(pendingOp.tagId)
|
|
17675
|
+
});
|
|
17189
17676
|
if (dropResult === "incomplete" || synthetic && dropResult !== "removed" && dropResult !== "truncated") {
|
|
17190
17677
|
reject(`drop_${dropResult}`);
|
|
17191
17678
|
continue;
|
|
17192
17679
|
}
|
|
17193
|
-
const appliedMode = dropResult === "truncated" ? "truncated" : "full";
|
|
17194
17680
|
if (dropResult === "removed" || dropResult === "truncated") {
|
|
17195
17681
|
didMutateMessage = true;
|
|
17196
17682
|
operationMutated = true;
|
|
17197
|
-
onTagReduced?.({
|
|
17683
|
+
onTagReduced?.({
|
|
17684
|
+
tagNumber: pendingOp.tagId,
|
|
17685
|
+
mode: appliedMode === "full" ? "full" : "truncated"
|
|
17686
|
+
});
|
|
17198
17687
|
} else {
|
|
17199
17688
|
reject(`drop_${dropResult}`);
|
|
17200
17689
|
}
|
|
@@ -17261,11 +17750,24 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
|
|
|
17261
17750
|
if (tag.status === "dropped") {
|
|
17262
17751
|
const target = targets.get(tag.tagNumber);
|
|
17263
17752
|
if (tag.type === "tool") {
|
|
17264
|
-
if (tag.dropMode === "
|
|
17753
|
+
if (tag.dropMode === "edit_marker_stripped") {
|
|
17754
|
+
const result = target?.editMarkerStripped?.() ?? "absent";
|
|
17755
|
+
if (result === "truncated")
|
|
17756
|
+
didMutateMessage = true;
|
|
17757
|
+
} else if (tag.dropMode === "edit_marker") {
|
|
17265
17758
|
const markResult = target?.editMarker?.() ?? "absent";
|
|
17266
17759
|
if (markResult === "truncated") {
|
|
17267
17760
|
didMutateMessage = true;
|
|
17268
17761
|
}
|
|
17762
|
+
} else if (tag.dropMode === "skeleton_stripped") {
|
|
17763
|
+
const result = target?.skeletonStripped?.() ?? "absent";
|
|
17764
|
+
if (result === "truncated")
|
|
17765
|
+
didMutateMessage = true;
|
|
17766
|
+
} else if (tag.dropMode === "skeleton_real") {
|
|
17767
|
+
const result = target?.skeletonReal?.() ?? "absent";
|
|
17768
|
+
if (result === "truncated") {
|
|
17769
|
+
didMutateMessage = true;
|
|
17770
|
+
}
|
|
17269
17771
|
} else if (tag.dropMode === "truncated") {
|
|
17270
17772
|
const truncResult = target?.truncate?.() ?? "absent";
|
|
17271
17773
|
if (truncResult === "truncated") {
|
|
@@ -17611,7 +18113,7 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
|
|
|
17611
18113
|
else if (targetDepth === DEPTH_ULTRA)
|
|
17612
18114
|
result.compressedToUltra += 1;
|
|
17613
18115
|
}
|
|
17614
|
-
})();
|
|
18116
|
+
}).immediate();
|
|
17615
18117
|
const total = result.compressedToLite + result.compressedToFull + result.compressedToUltra;
|
|
17616
18118
|
if (total > 0) {
|
|
17617
18119
|
sessionLog(sessionId, `caveman cleanup: compressed ${total} text tags (lite=${result.compressedToLite}, full=${result.compressedToFull}, ultra=${result.compressedToUltra})`);
|
|
@@ -19533,6 +20035,7 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
|
|
|
19533
20035
|
let any = false;
|
|
19534
20036
|
for (const occ of occurrences) {
|
|
19535
20037
|
if (occ.kind === "tool_use" && occ.part.setToolInput) {
|
|
20038
|
+
occ.originalInput ??= occ.part.getToolInput?.() ?? undefined;
|
|
19536
20039
|
if (occ.part.setToolInput(droppedInputMarker(tagId)))
|
|
19537
20040
|
any = true;
|
|
19538
20041
|
} else if (setToolContentOrText(occ.part, sentinel)) {
|
|
@@ -19541,6 +20044,28 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
|
|
|
19541
20044
|
}
|
|
19542
20045
|
return any ? "truncated" : "absent";
|
|
19543
20046
|
};
|
|
20047
|
+
const complete = () => occurrences.some((occ) => occ.kind === "tool_use") && occurrences.some((occ) => occ.kind === "tool_result");
|
|
20048
|
+
const skeletonReal = () => {
|
|
20049
|
+
if (!complete())
|
|
20050
|
+
return "incomplete";
|
|
20051
|
+
const sentinel = `[dropped §${tagId}§]`;
|
|
20052
|
+
let any = false;
|
|
20053
|
+
for (const occ of occurrences) {
|
|
20054
|
+
if (occ.kind === "tool_use") {
|
|
20055
|
+
if (occ.originalInput && occ.part.setToolInput?.(occ.originalInput))
|
|
20056
|
+
any = true;
|
|
20057
|
+
} else if (setToolContentOrText(occ.part, sentinel)) {
|
|
20058
|
+
any = true;
|
|
20059
|
+
}
|
|
20060
|
+
}
|
|
20061
|
+
return any ? "truncated" : "absent";
|
|
20062
|
+
};
|
|
20063
|
+
const cannotRemove = () => {
|
|
20064
|
+
if (requiresToolArcSkeleton)
|
|
20065
|
+
return true;
|
|
20066
|
+
const authorization = occurrences.map((occ) => occ.part.canRemove?.());
|
|
20067
|
+
return !occurrences.every((occ, index) => occ.part.remove && authorization[index] !== false);
|
|
20068
|
+
};
|
|
19544
20069
|
return {
|
|
19545
20070
|
measureReclaim(skeleton) {
|
|
19546
20071
|
let beforeTools = 0;
|
|
@@ -19551,7 +20076,7 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
|
|
|
19551
20076
|
const before = occ.kind === "tool_use" ? JSON.stringify(occ.part.getToolInput?.() ?? {}) : occ.part.getText() ?? "";
|
|
19552
20077
|
beforeTools += estimateTokens(before);
|
|
19553
20078
|
if (skeleton || !removable) {
|
|
19554
|
-
const after = occ.kind === "tool_use" ?
|
|
20079
|
+
const after = occ.kind === "tool_use" ? before : `[dropped §${tagId}§]`;
|
|
19555
20080
|
afterTools += estimateTokens(after);
|
|
19556
20081
|
}
|
|
19557
20082
|
}
|
|
@@ -19580,8 +20105,7 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
|
|
|
19580
20105
|
return occurrences[0]?.part.getText() ?? null;
|
|
19581
20106
|
},
|
|
19582
20107
|
drop() {
|
|
19583
|
-
|
|
19584
|
-
if (!complete)
|
|
20108
|
+
if (!complete())
|
|
19585
20109
|
return "incomplete";
|
|
19586
20110
|
if (!requiresToolArcSkeleton) {
|
|
19587
20111
|
const authorization = occurrences.map((occ) => occ.part.canRemove?.());
|
|
@@ -19589,7 +20113,7 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
|
|
|
19589
20113
|
return "incomplete";
|
|
19590
20114
|
if (occurrences.every((occ, index) => occ.part.remove && authorization[index] !== false)) {
|
|
19591
20115
|
if (conversationEnd?.wouldStrand(occurrences))
|
|
19592
|
-
return
|
|
20116
|
+
return skeletonReal();
|
|
19593
20117
|
let removed = false;
|
|
19594
20118
|
for (const occ of occurrences)
|
|
19595
20119
|
removed = occ.part.remove?.() || removed;
|
|
@@ -19607,6 +20131,19 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
|
|
|
19607
20131
|
return any ? "removed" : "absent";
|
|
19608
20132
|
},
|
|
19609
20133
|
truncate,
|
|
20134
|
+
skeletonReal,
|
|
20135
|
+
cannotRemove,
|
|
20136
|
+
inputStringBytes() {
|
|
20137
|
+
for (const occ of occurrences) {
|
|
20138
|
+
if (occ.kind !== "tool_use")
|
|
20139
|
+
continue;
|
|
20140
|
+
return toolInputStringBytes(occ.originalInput ?? occ.part.getToolInput?.() ?? null);
|
|
20141
|
+
}
|
|
20142
|
+
return null;
|
|
20143
|
+
},
|
|
20144
|
+
wouldStrandConversationEnd() {
|
|
20145
|
+
return conversationEnd?.wouldStrand(occurrences) ?? false;
|
|
20146
|
+
},
|
|
19610
20147
|
editMarker() {
|
|
19611
20148
|
const sentinel = `[dropped §${tagId}§]`;
|
|
19612
20149
|
let any = false;
|
|
@@ -19625,9 +20162,7 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
|
|
|
19625
20162
|
}
|
|
19626
20163
|
return any ? "truncated" : "absent";
|
|
19627
20164
|
},
|
|
19628
|
-
canDrop
|
|
19629
|
-
return occurrences.some((occ) => occ.kind === "tool_use") && occurrences.some((occ) => occ.kind === "tool_result");
|
|
19630
|
-
},
|
|
20165
|
+
canDrop: complete,
|
|
19631
20166
|
requiresToolArcSkeleton,
|
|
19632
20167
|
readInput() {
|
|
19633
20168
|
for (const occ of occurrences) {
|
|
@@ -19673,6 +20208,15 @@ function buildToolTarget(part, message, tagId) {
|
|
|
19673
20208
|
const changed = part.setToolInput ? part.setToolInput(droppedInputMarker(tagId)) : setToolContentOrText(part, `[dropped §${tagId}§]`);
|
|
19674
20209
|
return changed ? "truncated" : "absent";
|
|
19675
20210
|
},
|
|
20211
|
+
skeletonReal() {
|
|
20212
|
+
if (part.setToolInput)
|
|
20213
|
+
return "truncated";
|
|
20214
|
+
return setToolContentOrText(part, `[dropped §${tagId}§]`) ? "truncated" : "absent";
|
|
20215
|
+
},
|
|
20216
|
+
cannotRemove: () => part.setToolInput !== undefined,
|
|
20217
|
+
inputStringBytes() {
|
|
20218
|
+
return part.setToolInput ? toolInputStringBytes(part.getToolInput?.() ?? null) : 0;
|
|
20219
|
+
},
|
|
19676
20220
|
message: {
|
|
19677
20221
|
info: { id: message.info.id, role: message.info.role },
|
|
19678
20222
|
parts: []
|
|
@@ -19946,7 +20490,7 @@ async function runAutoSearchHintForPi(args) {
|
|
|
19946
20490
|
try {
|
|
19947
20491
|
const snapshot = getProjectEmbeddingSnapshot(options.projectPath);
|
|
19948
20492
|
const memoryEnabled = snapshot?.features.memoryEnabled ?? true;
|
|
19949
|
-
const embeddingEnabled = snapshot ? snapshot.
|
|
20493
|
+
const embeddingEnabled = snapshot ? snapshot.historyEnabled : true;
|
|
19950
20494
|
const gitCommitsEnabled = snapshot?.gitCommitEnabled ?? false;
|
|
19951
20495
|
const searchOptions = {
|
|
19952
20496
|
limit: 10,
|
|
@@ -20010,6 +20554,8 @@ import * as crypto2 from "node:crypto";
|
|
|
20010
20554
|
async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compartments) {
|
|
20011
20555
|
if (compartments.length === 0)
|
|
20012
20556
|
return;
|
|
20557
|
+
if (getProjectChunkEmbeddingModelId(projectPath) === "off")
|
|
20558
|
+
return;
|
|
20013
20559
|
const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectPath);
|
|
20014
20560
|
for (const compartment of compartments) {
|
|
20015
20561
|
try {
|
|
@@ -20166,7 +20712,7 @@ function persistFilteredNoise(db, sessionId, chunk, eligibleEnd) {
|
|
|
20166
20712
|
}
|
|
20167
20713
|
]);
|
|
20168
20714
|
return true;
|
|
20169
|
-
})();
|
|
20715
|
+
}).immediate();
|
|
20170
20716
|
if (saved)
|
|
20171
20717
|
sessionLog(sessionId, `historian skipped ordinals ${start}-${eligibleEnd - 1}: all ${rows.length} raw rows excluded by chunk filters (no-content boundary marker)`);
|
|
20172
20718
|
return saved;
|
|
@@ -22763,8 +23309,7 @@ ${chunkText}`,
|
|
|
22763
23309
|
const discardedLast = newCompartments.length < emittedCompartments.length;
|
|
22764
23310
|
const weakLookaheadFinalCompartment = forceKeepLastCompartmentForChunk;
|
|
22765
23311
|
const skipUnanchoredPromotion = discardedLast || weakLookaheadFinalCompartment;
|
|
22766
|
-
const
|
|
22767
|
-
const promotionActive = embeddingActive && autoPromote !== false;
|
|
23312
|
+
const promotionActive = memoryEnabled !== false && autoPromote !== false;
|
|
22768
23313
|
const publishableEvents = (validatedPass.events ?? []).filter((e) => {
|
|
22769
23314
|
if (typeof e.atCompartment !== "number")
|
|
22770
23315
|
return !weakLookaheadFinalCompartment;
|
|
@@ -22897,7 +23442,7 @@ ${chunkText}`,
|
|
|
22897
23442
|
sessionLog(sessionId, "failed to store primer candidates:", error);
|
|
22898
23443
|
}
|
|
22899
23444
|
}
|
|
22900
|
-
if (
|
|
23445
|
+
if (newCompartments.length > 0) {
|
|
22901
23446
|
const chunksToEmbed = newCompartments.map((c, i) => ({
|
|
22902
23447
|
id: persistedIds[i],
|
|
22903
23448
|
startMessage: c.startMessage,
|
|
@@ -23280,7 +23825,7 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
23280
23825
|
const candidateTags = tags.filter((t) => t.status === "active" && t.type === "tool" && targets.get(t.tagNumber)?.canDrop?.());
|
|
23281
23826
|
const recentTags = new Set(candidateTags.slice().sort((a, b) => b.tagNumber - a.tagNumber).slice(0, 20).map((tag) => tag.tagNumber));
|
|
23282
23827
|
const calibration = sessionDecisionCalibration(db, sessionId);
|
|
23283
|
-
const activeTags = tags.filter((t) => t.status === "active").map((tag) => measureEmergencyTag(tag, targets.get(tag.tagNumber), calibration, targets.get(tag.tagNumber)?.requiresToolArcSkeleton === true || (emergency.usagePercentage ?? 0) < 95 && recentTags.has(tag.tagNumber)));
|
|
23828
|
+
const activeTags = tags.filter((t) => t.status === "active").map((tag) => measureEmergencyTag(tag, targets.get(tag.tagNumber), calibration, targets.get(tag.tagNumber)?.requiresToolArcSkeleton === true || (emergency.usagePercentage ?? 0) < 95 && recentTags.has(tag.tagNumber) && hasSmallToolInput(targets.get(tag.tagNumber))));
|
|
23284
23829
|
const byTag = new Map(activeTags.map((tag) => [tag.tagNumber, tag]));
|
|
23285
23830
|
const droppableTags = candidateTags.flatMap((tag) => {
|
|
23286
23831
|
const measured = byTag.get(tag.tagNumber);
|
|
@@ -23309,18 +23854,18 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
23309
23854
|
continue;
|
|
23310
23855
|
const target = targets.get(tag.tagNumber);
|
|
23311
23856
|
const recent = (emergency.usagePercentage ?? 0) < 95 && newestEmergencyTags.has(tag.tagNumber);
|
|
23312
|
-
const
|
|
23313
|
-
|
|
23314
|
-
|
|
23857
|
+
const { result, mode } = applyNewToolDrop(target, {
|
|
23858
|
+
inWindow: recent,
|
|
23859
|
+
keepSkeleton: target?.requiresToolArcSkeleton === true
|
|
23860
|
+
});
|
|
23315
23861
|
if (result === "removed" || result === "truncated") {
|
|
23316
|
-
const appliedMode = skeleton || result === "truncated" ? "truncated" : "full";
|
|
23317
23862
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
23318
|
-
updateTagDropMode(db, sessionId, tag.tagNumber,
|
|
23863
|
+
updateTagDropMode(db, sessionId, tag.tagNumber, mode);
|
|
23319
23864
|
droppedTools++;
|
|
23320
23865
|
emergencyDroppedTools++;
|
|
23321
23866
|
droppedTokenReductions.push({
|
|
23322
23867
|
tagNumber: tag.tagNumber,
|
|
23323
|
-
mode:
|
|
23868
|
+
mode: mode === "full" ? "full" : "truncated"
|
|
23324
23869
|
});
|
|
23325
23870
|
}
|
|
23326
23871
|
}
|
|
@@ -23344,10 +23889,10 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
23344
23889
|
if (!matched)
|
|
23345
23890
|
continue;
|
|
23346
23891
|
const target = targets.get(tag.tagNumber);
|
|
23347
|
-
const result = target
|
|
23892
|
+
const { result, mode } = applyNewToolDrop(target, { inWindow: false });
|
|
23348
23893
|
if (result === "incomplete")
|
|
23349
23894
|
continue;
|
|
23350
|
-
updateTagDropMode(db, sessionId, tag.tagNumber,
|
|
23895
|
+
updateTagDropMode(db, sessionId, tag.tagNumber, mode);
|
|
23351
23896
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
23352
23897
|
if (result === "removed" || result === "truncated") {
|
|
23353
23898
|
droppedStaleReduceCalls++;
|
|
@@ -23428,17 +23973,18 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
23428
23973
|
for (let i = 0;i < group.length - 1; i++) {
|
|
23429
23974
|
const tag = group[i];
|
|
23430
23975
|
const target = targets.get(tag.tagNumber);
|
|
23431
|
-
const result = target
|
|
23976
|
+
const { result, mode } = applyNewToolDrop(target, {
|
|
23977
|
+
inWindow: false
|
|
23978
|
+
});
|
|
23432
23979
|
if (result === "incomplete")
|
|
23433
23980
|
continue;
|
|
23434
|
-
|
|
23435
|
-
updateTagDropMode(db, sessionId, tag.tagNumber, appliedMode);
|
|
23981
|
+
updateTagDropMode(db, sessionId, tag.tagNumber, mode);
|
|
23436
23982
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
23437
23983
|
if (result === "removed" || result === "truncated") {
|
|
23438
23984
|
deduplicatedTools++;
|
|
23439
23985
|
droppedTokenReductions.push({
|
|
23440
23986
|
tagNumber: tag.tagNumber,
|
|
23441
|
-
mode:
|
|
23987
|
+
mode: mode === "full" ? "full" : "truncated"
|
|
23442
23988
|
});
|
|
23443
23989
|
}
|
|
23444
23990
|
}
|
|
@@ -26204,7 +26750,7 @@ function messageRole(message) {
|
|
|
26204
26750
|
const role = recordValue(message, "role");
|
|
26205
26751
|
return typeof role === "string" ? role : undefined;
|
|
26206
26752
|
}
|
|
26207
|
-
function
|
|
26753
|
+
function messageId2(message) {
|
|
26208
26754
|
const id = recordValue(messageInfo(message), "id") ?? recordValue(message, "id");
|
|
26209
26755
|
return typeof id === "string" && id.length > 0 ? id : null;
|
|
26210
26756
|
}
|
|
@@ -26337,7 +26883,7 @@ function validateLkgSeam(prefix, tail, providerKey) {
|
|
|
26337
26883
|
const calls = new Set;
|
|
26338
26884
|
const results = new Set;
|
|
26339
26885
|
for (const message of all) {
|
|
26340
|
-
const id =
|
|
26886
|
+
const id = messageId2(message);
|
|
26341
26887
|
if (id !== null) {
|
|
26342
26888
|
if (ids.has(id))
|
|
26343
26889
|
return false;
|
|
@@ -26880,6 +27426,56 @@ function resolvePiPressureSnapshot(args) {
|
|
|
26880
27426
|
...validInferredLimit ? { contextLimit: inferredLimit } : {}
|
|
26881
27427
|
};
|
|
26882
27428
|
}
|
|
27429
|
+
var estimateSetAsideLogged = new Set;
|
|
27430
|
+
function notePiUsageReadingUsed(sessionId) {
|
|
27431
|
+
estimateSetAsideLogged.delete(sessionId);
|
|
27432
|
+
}
|
|
27433
|
+
function entryUsageTokens(usage) {
|
|
27434
|
+
if (!usage || typeof usage !== "object")
|
|
27435
|
+
return 0;
|
|
27436
|
+
const u = usage;
|
|
27437
|
+
const n = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
27438
|
+
return n(u.totalTokens) || n(u.input) + n(u.output) + n(u.cacheRead) + n(u.cacheWrite);
|
|
27439
|
+
}
|
|
27440
|
+
function isPiLiveUsageRawBranchEstimate(branchEntries) {
|
|
27441
|
+
if (!branchEntries)
|
|
27442
|
+
return false;
|
|
27443
|
+
for (let index = branchEntries.length - 1;index >= 0; index -= 1) {
|
|
27444
|
+
const entry = branchEntries[index];
|
|
27445
|
+
if (!entry || typeof entry !== "object")
|
|
27446
|
+
continue;
|
|
27447
|
+
if (entry.type === "context_edit" || entry.type === "compaction")
|
|
27448
|
+
return true;
|
|
27449
|
+
if (entry.type !== "message")
|
|
27450
|
+
continue;
|
|
27451
|
+
const message = entry.message;
|
|
27452
|
+
if (message?.role === "assistant" && message.stopReason !== "aborted" && message.stopReason !== "error" && entryUsageTokens(message.usage) > 0) {
|
|
27453
|
+
return false;
|
|
27454
|
+
}
|
|
27455
|
+
}
|
|
27456
|
+
return false;
|
|
27457
|
+
}
|
|
27458
|
+
function noteRawBranchEstimateSetAside(sessionId, reading, source) {
|
|
27459
|
+
if (estimateSetAsideLogged.has(sessionId))
|
|
27460
|
+
return;
|
|
27461
|
+
estimateSetAsideLogged.add(sessionId);
|
|
27462
|
+
sessionLog(sessionId, `usage reading ${reading} set aside (${source}): Pi re-estimated its whole unreduced session branch because a context edit or compaction follows the last recorded usage (for example after a retried request); keeping the previous reading until provider usage arrives`);
|
|
27463
|
+
}
|
|
27464
|
+
function resolvePiPressureSnapshotWithEstimateGuard(args) {
|
|
27465
|
+
const live = typeof args.liveInputTokens === "number" && Number.isFinite(args.liveInputTokens) ? args.liveInputTokens : 0;
|
|
27466
|
+
const setAsideEstimate = args.liveIsRawBranchEstimate === true && live > 0;
|
|
27467
|
+
const snapshot = resolvePiPressureSnapshot(setAsideEstimate ? {
|
|
27468
|
+
...args,
|
|
27469
|
+
liveInputTokens: undefined,
|
|
27470
|
+
...args.persistedFromLive ? { persistedInputTokens: 0, persistedPercentage: 0 } : {}
|
|
27471
|
+
} : args);
|
|
27472
|
+
if (setAsideEstimate) {
|
|
27473
|
+
noteRawBranchEstimateSetAside(args.sessionId, live, args.source);
|
|
27474
|
+
} else if (snapshot.inputTokens > 0) {
|
|
27475
|
+
notePiUsageReadingUsed(args.sessionId);
|
|
27476
|
+
}
|
|
27477
|
+
return snapshot;
|
|
27478
|
+
}
|
|
26883
27479
|
function formatPiPressureForLog(snapshot) {
|
|
26884
27480
|
return `usage=${snapshot.percentage.toFixed(1)}% (${snapshot.inputTokens} tokens, limit=${snapshot.contextLimit ?? "?"})`;
|
|
26885
27481
|
}
|
|
@@ -27336,12 +27932,12 @@ function handlePiProviderFailure(args) {
|
|
|
27336
27932
|
const model = typeof message.model === "string" ? message.model : undefined;
|
|
27337
27933
|
const binding = detectThinkingBindingMismatch(message.errorMessage);
|
|
27338
27934
|
if (binding.isBindingMismatch) {
|
|
27339
|
-
const enabled = args.thinkingBindingRecoveryEnabled !== false && !args.compactionOff &&
|
|
27935
|
+
const enabled = args.thinkingBindingRecoveryEnabled !== false && !args.compactionOff && isPrefixBoundThinkingModel(provider, model);
|
|
27340
27936
|
if (enabled) {
|
|
27341
27937
|
armThinkingBindingRecovery(args.db, args.sessionId);
|
|
27342
27938
|
clearPiLkgSessionState(args.sessionId);
|
|
27343
27939
|
dropSlot(args.sessionId, "thinking-binding-recovery-arm");
|
|
27344
|
-
reportBindingRecovery(args.sessionId, args.report, `
|
|
27940
|
+
reportBindingRecovery(args.sessionId, args.report, `thinking-binding recovery armed from message_end (provider paths: failing=${binding.failingBlockPath ?? "?"} firstChanged=${binding.firstChangedPath ?? "?"})`);
|
|
27345
27941
|
}
|
|
27346
27942
|
return { kind: "thinking_binding", armed: enabled };
|
|
27347
27943
|
}
|
|
@@ -27390,36 +27986,25 @@ function stripThinkingParts(message) {
|
|
|
27390
27986
|
function applyPiThinkingBindingRecovery(args) {
|
|
27391
27987
|
if (args.provider?.toLowerCase() !== "anthropic")
|
|
27392
27988
|
return null;
|
|
27393
|
-
const frozenEntryIds =
|
|
27394
|
-
|
|
27395
|
-
if (!frozenId.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX))
|
|
27396
|
-
continue;
|
|
27397
|
-
const entryId = frozenId.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length);
|
|
27398
|
-
if (entryId.length > 0)
|
|
27399
|
-
frozenEntryIds.add(entryId);
|
|
27400
|
-
}
|
|
27401
|
-
const flagTarget = isFable51ThinkingBindingModel(args.provider, args.model) ? getThinkingBindingRecoveryTarget(args.db, args.sessionId) : null;
|
|
27989
|
+
const frozenEntryIds = frozenBindingEntryIds(args.db, args.sessionId);
|
|
27990
|
+
const flagTarget = isPrefixBoundThinkingModel(args.provider, args.model) ? getThinkingBindingRecoveryTarget(args.db, args.sessionId) : null;
|
|
27402
27991
|
let applied = null;
|
|
27403
27992
|
if (flagTarget) {
|
|
27404
|
-
|
|
27405
|
-
|
|
27406
|
-
|
|
27407
|
-
|
|
27408
|
-
|
|
27409
|
-
|
|
27410
|
-
|
|
27411
|
-
|
|
27412
|
-
|
|
27413
|
-
|
|
27414
|
-
|
|
27415
|
-
|
|
27416
|
-
|
|
27417
|
-
|
|
27418
|
-
|
|
27419
|
-
frozenEntryIds.add(entryId);
|
|
27420
|
-
applied = { flagTarget, entryId };
|
|
27421
|
-
reportBindingRecovery(args.sessionId, args.report, `Fable thinking-binding recovery consumed on context pass target=${flagTarget} entry=${entryId}`);
|
|
27422
|
-
}
|
|
27993
|
+
const entryIds = new Set;
|
|
27994
|
+
for (let index = 0;index < args.messages.length; index += 1) {
|
|
27995
|
+
const entryId = args.entryIds[index];
|
|
27996
|
+
if (entryId && hasThinkingPart(args.messages[index]))
|
|
27997
|
+
entryIds.add(entryId);
|
|
27998
|
+
}
|
|
27999
|
+
const newEntryIds = [...entryIds].filter((id) => !frozenEntryIds.has(id));
|
|
28000
|
+
if (newEntryIds.length === 0 || addMergedReasoningStrippedIds(args.db, args.sessionId, [
|
|
28001
|
+
...newEntryIds.map(thinkingBindingRecoveryFrozenId),
|
|
28002
|
+
...args.endOfPassOrder ? [THINKING_BINDING_STRIP_ORDER_END_MARKER] : []
|
|
28003
|
+
])) {
|
|
28004
|
+
for (const id of newEntryIds)
|
|
28005
|
+
frozenEntryIds.add(id);
|
|
28006
|
+
applied = { flagTarget, entryIds: [...entryIds] };
|
|
28007
|
+
reportBindingRecovery(args.sessionId, args.report, `thinking-binding recovery consumed on context pass target=${flagTarget} entries=${applied.entryIds.length} [${applied.entryIds.join(",")}]`);
|
|
27423
28008
|
}
|
|
27424
28009
|
}
|
|
27425
28010
|
for (let index = 0;index < args.messages.length; index += 1) {
|
|
@@ -27429,6 +28014,76 @@ function applyPiThinkingBindingRecovery(args) {
|
|
|
27429
28014
|
}
|
|
27430
28015
|
return applied;
|
|
27431
28016
|
}
|
|
28017
|
+
function applyPiProactiveThinkingStrip(args) {
|
|
28018
|
+
if (!args.cacheBustingPass)
|
|
28019
|
+
return null;
|
|
28020
|
+
if (!isPrefixBoundThinkingModel(args.provider, args.model))
|
|
28021
|
+
return null;
|
|
28022
|
+
const entryIds = [];
|
|
28023
|
+
const indices = [];
|
|
28024
|
+
for (let index = 0;index < args.messages.length; index += 1) {
|
|
28025
|
+
const entryId = args.entryIds[index];
|
|
28026
|
+
if (!entryId || !hasThinkingPart(args.messages[index]))
|
|
28027
|
+
continue;
|
|
28028
|
+
entryIds.push(entryId);
|
|
28029
|
+
indices.push(index);
|
|
28030
|
+
}
|
|
28031
|
+
if (entryIds.length === 0)
|
|
28032
|
+
return null;
|
|
28033
|
+
let persisted = false;
|
|
28034
|
+
try {
|
|
28035
|
+
persisted = addMergedReasoningStrippedIds(args.db, args.sessionId, [
|
|
28036
|
+
...entryIds.map(thinkingBindingRecoveryFrozenId),
|
|
28037
|
+
THINKING_BINDING_STRIP_ORDER_END_MARKER
|
|
28038
|
+
]);
|
|
28039
|
+
} catch {
|
|
28040
|
+
persisted = false;
|
|
28041
|
+
}
|
|
28042
|
+
if (!persisted) {
|
|
28043
|
+
reportBindingRecovery(args.sessionId, args.report, "proactive thinking strip: persistence failed; serving the thinking unchanged");
|
|
28044
|
+
return null;
|
|
28045
|
+
}
|
|
28046
|
+
for (const index of indices)
|
|
28047
|
+
stripThinkingParts(args.messages[index]);
|
|
28048
|
+
reportBindingRecovery(args.sessionId, args.report, `proactive thinking strip: busting pass froze thinking of ${entryIds.length} entr${entryIds.length === 1 ? "y" : "ies"} [${entryIds.join(",")}]`);
|
|
28049
|
+
return { entryIds };
|
|
28050
|
+
}
|
|
28051
|
+
function frozenBindingEntryIds(db, sessionId) {
|
|
28052
|
+
const ids = new Set;
|
|
28053
|
+
for (const entry of getMergedReasoningStrippedIds(db, sessionId)) {
|
|
28054
|
+
if (!entry.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX))
|
|
28055
|
+
continue;
|
|
28056
|
+
const entryId = entry.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length);
|
|
28057
|
+
if (entryId.length > 0)
|
|
28058
|
+
ids.add(entryId);
|
|
28059
|
+
}
|
|
28060
|
+
return ids;
|
|
28061
|
+
}
|
|
28062
|
+
function resolvePiBindingStripOrder(args) {
|
|
28063
|
+
const ledger = getMergedReasoningStrippedIds(args.db, args.sessionId);
|
|
28064
|
+
if (ledger.has(THINKING_BINDING_STRIP_ORDER_END_MARKER))
|
|
28065
|
+
return "end";
|
|
28066
|
+
const frozen = frozenBindingEntryIds(args.db, args.sessionId);
|
|
28067
|
+
if (frozen.size === 0)
|
|
28068
|
+
return "end";
|
|
28069
|
+
let onBranch = false;
|
|
28070
|
+
let carriesThinking = false;
|
|
28071
|
+
for (let index = 0;index < args.messages.length; index += 1) {
|
|
28072
|
+
const entryId = args.entryIds[index];
|
|
28073
|
+
if (!entryId || !frozen.has(entryId))
|
|
28074
|
+
continue;
|
|
28075
|
+
onBranch = true;
|
|
28076
|
+
if (hasThinkingPart(args.messages[index]))
|
|
28077
|
+
carriesThinking = true;
|
|
28078
|
+
}
|
|
28079
|
+
const mayChangeOrder = onBranch && carriesThinking && args.bustPermittedAtStart;
|
|
28080
|
+
if (mayChangeOrder && addMergedReasoningStrippedIds(args.db, args.sessionId, [
|
|
28081
|
+
THINKING_BINDING_STRIP_ORDER_END_MARKER
|
|
28082
|
+
])) {
|
|
28083
|
+
return "end";
|
|
28084
|
+
}
|
|
28085
|
+
return "start";
|
|
28086
|
+
}
|
|
27432
28087
|
|
|
27433
28088
|
// src/reasoning-replay-pi.ts
|
|
27434
28089
|
var INLINE_THINKING_PATTERNS = [
|
|
@@ -27976,9 +28631,9 @@ var BASE_INTRO = (memoryEnabled, dreamerEnabled, temporalAwarenessEnabled) => `#
|
|
|
27976
28631
|
|
|
27977
28632
|
Think of your context as a desk. Every message and every tool output lands on it, and each item arrives with a §N§ tag (§1§, §42§) — the tag is the item's handle.
|
|
27978
28633
|
|
|
27979
|
-
When an item no longer needs to stay on the desk for the work ahead, stamp it: \`ctx_reduce\` with its tag. Stamping does not remove anything — the item stays on the desk, fully readable. From time to time, when stamped items have piled up and the desk needs room, Magic Context clears them all in one sweep; you don't pick the moment, you only stamp. Stamp as soon as an item has served its purpose, not at the end of the turn, and do it silently: nobody wants to read "I'll drop these outputs". Never stamp a user message for what it asks of you; a large paste inside one is fine once you have used it.
|
|
28634
|
+
When an item no longer needs to stay on the desk for the work ahead, stamp it: \`ctx_reduce\` with its tag. Stamping does not remove anything — the item stays on the desk, fully readable. From time to time, when stamped items have piled up and the desk needs room, Magic Context clears them all in one sweep; you don't pick the moment, you only stamp. Stamp as soon as an item has served its purpose, not at the end of the turn, and do it silently: nobody wants to read "I'll drop these outputs". An output is used once you've taken what you need from it into your reasoning or your answer. Never stamp a user message for what it asks of you; a large paste inside one is fine once you have used it.
|
|
27980
28635
|
|
|
27981
|
-
Nothing stamped is ever lost. A cleared item goes to the archive — a recent one leaves a \`[dropped §N§]\` placeholder on the desk, an older one leaves nothing — and \`ctx_expand(message=N)\` brings it back whole: text, tool input, tool output. Now and then Magic Context leaves a short reminder on the desk saying how much unstamped material is lying around
|
|
28636
|
+
Nothing stamped is ever lost. A cleared item goes to the archive — a recent one leaves a \`[dropped §N§]\` placeholder on the desk, an older one leaves nothing — and \`ctx_expand(message=N)\` brings it back whole: text, tool input, tool output. Now and then Magic Context leaves a short reminder on the desk saying how much unstamped material is lying around. A reminder means stamping is overdue: act on it in your next step. It isn't a warning about the desk's size. The desk never gets smaller for it.
|
|
27982
28637
|
|
|
27983
28638
|
${TOOL_HISTORY_GUIDANCE}
|
|
27984
28639
|
|
|
@@ -28007,7 +28662,7 @@ var SMART_NOTE_GUIDANCE_LIGHT = `; a \`surface_condition\` leaves the note with
|
|
|
28007
28662
|
var TEMPORAL_AWARENESS_GUIDANCE_LIGHT = `, \`<!-- +Xm -->\` (time since your last reply)`;
|
|
28008
28663
|
var BASE_INTRO_LIGHT = (memoryEnabled, dreamerEnabled, temporalAwarenessEnabled) => `### Your desk
|
|
28009
28664
|
|
|
28010
|
-
Your context is a desk. Every message and tool output lands on it with a §N§ tag as its handle. When an item no longer needs to stay for the work ahead, stamp it: \`ctx_reduce\` with its tag. Stamping removes nothing — the item stays readable; from time to time, when stamped items have piled up and the desk needs room, Magic Context clears them in one sweep (you only stamp, you don't pick the moment). Stamp as soon as an item has served its purpose, silently; never stamp a user message for what it asks (a used paste inside one is fine). Nothing is lost: a cleared item goes to the archive (a recent one leaves \`[dropped §N§]\`, an older one nothing) and \`ctx_expand(message=N)\` brings it back whole. Occasional reminders about unstamped material
|
|
28665
|
+
Your context is a desk. Every message and tool output lands on it with a §N§ tag as its handle. When an item no longer needs to stay for the work ahead, stamp it: \`ctx_reduce\` with its tag. Stamping removes nothing — the item stays readable; from time to time, when stamped items have piled up and the desk needs room, Magic Context clears them in one sweep (you only stamp, you don't pick the moment). Stamp as soon as an item has served its purpose, silently; never stamp a user message for what it asks (a used paste inside one is fine). An output is used once you've taken what you need from it into your reasoning or your answer. Nothing is lost: a cleared item goes to the archive (a recent one leaves \`[dropped §N§]\`, an older one nothing) and \`ctx_expand(message=N)\` brings it back whole. Occasional reminders about unstamped material may appear. A reminder means stamping is overdue: act on it in your next step. It isn't a warning about the desk's size. The desk never gets smaller.
|
|
28011
28666
|
|
|
28012
28667
|
${TOOL_HISTORY_GUIDANCE_LIGHT}
|
|
28013
28668
|
|
|
@@ -29490,7 +30145,7 @@ function databaseIsInTransaction(db) {
|
|
|
29490
30145
|
}
|
|
29491
30146
|
function runImmediateTransaction(db, fn) {
|
|
29492
30147
|
if (databaseIsInTransaction(db)) {
|
|
29493
|
-
return db.transaction(fn)();
|
|
30148
|
+
return db.transaction(fn).immediate();
|
|
29494
30149
|
}
|
|
29495
30150
|
const transactionStartedAt = performance.now();
|
|
29496
30151
|
db.exec("BEGIN IMMEDIATE");
|
|
@@ -29672,6 +30327,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
29672
30327
|
logTransformTiming(sessionId, "findSessionId", tFindSession, `messages=${event.messages.length}`);
|
|
29673
30328
|
const tEntryBranch = performance.now();
|
|
29674
30329
|
const branchEntries = readPiBranchEntriesForContext(ctx, sessionId);
|
|
30330
|
+
const piLiveUsageIsRawBranchEstimate = isPiLiveUsageRawBranchEstimate(branchEntries);
|
|
29675
30331
|
schedulePiTransformDecisionResolve({
|
|
29676
30332
|
db: options.db,
|
|
29677
30333
|
sessionId,
|
|
@@ -29704,14 +30360,29 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
29704
30360
|
const lkgInputIdByRef = new Map;
|
|
29705
30361
|
for (const input of lkgPassSnapshot.inputs)
|
|
29706
30362
|
lkgInputIdByRef.set(event.messages[input.messageIndex], input.id);
|
|
29707
|
-
const
|
|
30363
|
+
const bindingStripOrder = resolvePiBindingStripOrder({
|
|
30364
|
+
db: options.db,
|
|
30365
|
+
sessionId,
|
|
30366
|
+
messages: event.messages,
|
|
30367
|
+
entryIds: lkgEntryIds ?? [],
|
|
30368
|
+
bustPermittedAtStart: hasPendingMaterialization(sessionId)
|
|
30369
|
+
});
|
|
30370
|
+
const startOfPassBindingRecovery = bindingStripOrder === "start" ? applyPiThinkingBindingRecovery({
|
|
29708
30371
|
db: options.db,
|
|
29709
30372
|
sessionId,
|
|
29710
30373
|
messages: event.messages,
|
|
29711
30374
|
entryIds: lkgEntryIds ?? [],
|
|
29712
30375
|
provider: lkgProviderKey ?? undefined,
|
|
29713
30376
|
model: ctx.model?.id
|
|
29714
|
-
});
|
|
30377
|
+
}) : null;
|
|
30378
|
+
const bindingEntryIdByRef = new Map;
|
|
30379
|
+
if (lkgEntryIds) {
|
|
30380
|
+
for (let index = 0;index < event.messages.length; index += 1) {
|
|
30381
|
+
const entryId = lkgEntryIds[index];
|
|
30382
|
+
if (entryId)
|
|
30383
|
+
bindingEntryIdByRef.set(event.messages[index], entryId);
|
|
30384
|
+
}
|
|
30385
|
+
}
|
|
29715
30386
|
const tMeta = performance.now();
|
|
29716
30387
|
const sessionMetaForUsage = getOrCreateSessionMeta(options.db, sessionId);
|
|
29717
30388
|
sessionMetaForPass = sessionMetaForUsage;
|
|
@@ -29921,7 +30592,11 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
29921
30592
|
if (!usedPersistedUsage && isSaneLimit(usageContextLimit) && usageInputTokens > 0) {
|
|
29922
30593
|
usagePercentage = usageInputTokens / usageContextLimit * 100;
|
|
29923
30594
|
}
|
|
29924
|
-
({ percentage: usagePercentage, inputTokens: usageInputTokens } =
|
|
30595
|
+
({ percentage: usagePercentage, inputTokens: usageInputTokens } = resolvePiPressureSnapshotWithEstimateGuard({
|
|
30596
|
+
sessionId,
|
|
30597
|
+
source: "transform",
|
|
30598
|
+
liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
|
|
30599
|
+
persistedFromLive: !usedPersistedUsage,
|
|
29925
30600
|
persistedPercentage: usagePercentage,
|
|
29926
30601
|
persistedInputTokens: usageInputTokens,
|
|
29927
30602
|
liveInputTokens: piUsage?.tokens,
|
|
@@ -30099,6 +30774,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
30099
30774
|
sessionMeta,
|
|
30100
30775
|
piUsage,
|
|
30101
30776
|
minimumPercentage: usagePercentage,
|
|
30777
|
+
liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
|
|
30102
30778
|
historianStateSnapshot: historianStateForPass,
|
|
30103
30779
|
publishedHistoryRide: isCacheBusting
|
|
30104
30780
|
});
|
|
@@ -30176,6 +30852,34 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
30176
30852
|
sessionLog(sessionId, `synthetic todowrite injection failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
30177
30853
|
}
|
|
30178
30854
|
logTransformTiming(sessionId, "todoCapture", tTodoCapture);
|
|
30855
|
+
const tThinkingBinding = performance.now();
|
|
30856
|
+
const outputEntryIds = resolvePiLkgOutputEntryIds(outputMessages, result.syntheticLeadingCount, (message) => result.lkgEntryIdByRef.get(message) ?? result.postCommitEntryIdByRef.get(message) ?? bindingEntryIdByRef.get(message)).map((entryId) => entryId ?? undefined);
|
|
30857
|
+
const thinkingBindingRecoveryApplied = bindingStripOrder === "end" ? applyPiThinkingBindingRecovery({
|
|
30858
|
+
db: options.db,
|
|
30859
|
+
sessionId,
|
|
30860
|
+
messages: outputMessages,
|
|
30861
|
+
entryIds: outputEntryIds,
|
|
30862
|
+
provider: lkgProviderKey ?? undefined,
|
|
30863
|
+
model: ctx.model?.id,
|
|
30864
|
+
endOfPassOrder: true
|
|
30865
|
+
}) : startOfPassBindingRecovery;
|
|
30866
|
+
if (!options.compactionOff && !sessionMeta.isSubagent && bindingStripOrder === "end") {
|
|
30867
|
+
try {
|
|
30868
|
+
applyPiProactiveThinkingStrip({
|
|
30869
|
+
db: options.db,
|
|
30870
|
+
sessionId,
|
|
30871
|
+
messages: outputMessages,
|
|
30872
|
+
entryIds: outputEntryIds,
|
|
30873
|
+
provider: lkgProviderKey ?? undefined,
|
|
30874
|
+
model: ctx.model?.id,
|
|
30875
|
+
cacheBustingPass: isCacheBusting || result.executedWorkThisPass,
|
|
30876
|
+
report: (line) => sessionLog(sessionId, line)
|
|
30877
|
+
});
|
|
30878
|
+
} catch (err) {
|
|
30879
|
+
sessionLog(sessionId, `proactive thinking strip failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
30880
|
+
}
|
|
30881
|
+
}
|
|
30882
|
+
logTransformTiming(sessionId, "thinkingBinding", tThinkingBinding);
|
|
30179
30883
|
const tChannelAccounting = performance.now();
|
|
30180
30884
|
try {
|
|
30181
30885
|
const sessionMetaForCh1 = sessionMeta;
|
|
@@ -30655,7 +31359,11 @@ function maybeFireHistorian(args) {
|
|
|
30655
31359
|
};
|
|
30656
31360
|
usageSource = "piUsage fallback";
|
|
30657
31361
|
}
|
|
30658
|
-
usage =
|
|
31362
|
+
usage = resolvePiPressureSnapshotWithEstimateGuard({
|
|
31363
|
+
sessionId,
|
|
31364
|
+
source: "historian trigger",
|
|
31365
|
+
liveIsRawBranchEstimate: args.liveIsRawBranchEstimate,
|
|
31366
|
+
persistedFromLive: usageSource === "piUsage fallback",
|
|
30659
31367
|
persistedPercentage: usage.percentage,
|
|
30660
31368
|
persistedInputTokens: usage.inputTokens,
|
|
30661
31369
|
liveInputTokens: piUsage?.tokens,
|
|
@@ -30978,6 +31686,7 @@ async function runPipeline(args) {
|
|
|
30978
31686
|
const foldDueDecision = piM0State ? mustMaterializePi(piM0State, args.db, injectionPassSnapshot?.compartments, injectionPassSnapshot) : { value: false, reason: null };
|
|
30979
31687
|
const firstRenderBust = piM0State !== undefined && !(injectionPassSnapshot?.cachedRow?.cached_m0_bytes && injectionPassSnapshot.cachedRow.cached_m1_bytes);
|
|
30980
31688
|
let foldExecutedThisPass = false;
|
|
31689
|
+
let foldBustsServedPrefixThisPass = false;
|
|
30981
31690
|
let publishedM1RefreshedThisPass = false;
|
|
30982
31691
|
let prefixPreflightContended = false;
|
|
30983
31692
|
const softRefreshOpportunity = args.schedulerDecision === "execute";
|
|
@@ -30991,6 +31700,18 @@ async function runPipeline(args) {
|
|
|
30991
31700
|
prefixPreflightContended = preFoldInjectionResult.contentionExhausted === true;
|
|
30992
31701
|
publishedM1RefreshedThisPass = !prefixPreflightContended && persistedM0BeforeFold.cachedM1Bytes?.toString("utf8") !== getOrCreateSessionMeta(args.db, args.sessionId).cachedM1Bytes?.toString("utf8");
|
|
30993
31702
|
foldExecutedThisPass = foldExecutesThisPass(foldDueDecision.value || softRefreshOpportunity, preFoldInjectionResult.m0Materialized === true);
|
|
31703
|
+
if (foldExecutedThisPass) {
|
|
31704
|
+
const afterFold = getOrCreateSessionMeta(args.db, args.sessionId);
|
|
31705
|
+
foldBustsServedPrefixThisPass = foldBustsServedPrefix(foldDueDecision.reason, {
|
|
31706
|
+
m0Bytes: persistedM0BeforeFold.cachedM0Bytes ?? null,
|
|
31707
|
+
m1Bytes: persistedM0BeforeFold.cachedM1Bytes ?? null,
|
|
31708
|
+
muralDataUrl: persistedM0BeforeFold.cachedM0MuralDataUrl ?? null
|
|
31709
|
+
}, {
|
|
31710
|
+
m0Bytes: afterFold.cachedM0Bytes ?? null,
|
|
31711
|
+
m1Bytes: afterFold.cachedM1Bytes ?? null,
|
|
31712
|
+
muralDataUrl: afterFold.cachedM0MuralDataUrl ?? null
|
|
31713
|
+
});
|
|
31714
|
+
}
|
|
30994
31715
|
if (preFoldInjectionResult.m0Materialized) {
|
|
30995
31716
|
injectionPassSnapshot = createPiM0M1PassSnapshot({
|
|
30996
31717
|
db: args.db,
|
|
@@ -31018,7 +31739,7 @@ async function runPipeline(args) {
|
|
|
31018
31739
|
sessionLog(args.sessionId, `pi m[0] HARD fold pre-execution failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
31019
31740
|
}
|
|
31020
31741
|
const mismatch = foldDueDecision.mismatch ? ` mismatch=${JSON.stringify(foldDueDecision.mismatch)}` : "";
|
|
31021
|
-
sessionLog(args.sessionId, `pi m[0] HARD fold decision: reason=${foldDueDecision.reason ?? "unknown"}${mismatch} executed=${foldExecutedThisPass}`);
|
|
31742
|
+
sessionLog(args.sessionId, `pi m[0] HARD fold decision: reason=${foldDueDecision.reason ?? "unknown"}${mismatch} executed=${foldExecutedThisPass} bustsServedPrefix=${foldBustsServedPrefixThisPass}`);
|
|
31022
31743
|
}
|
|
31023
31744
|
const executePressureEligible = args.schedulerDecision === "execute" || emergencyDropEligible;
|
|
31024
31745
|
if (!executePressureEligible) {
|
|
@@ -31029,7 +31750,7 @@ async function runPipeline(args) {
|
|
|
31029
31750
|
const routinePressureAlreadyApplied = !args.sessionMeta.isSubagent && executePressureEligible && routinePressureAppliedBySession.get(args.sessionId) === true;
|
|
31030
31751
|
const hasPendingMaterializeSignal = hasPendingMaterialization(args.sessionId);
|
|
31031
31752
|
const rideSignals = {
|
|
31032
|
-
hardFold:
|
|
31753
|
+
hardFold: foldBustsServedPrefixThisPass || firstRenderBust,
|
|
31033
31754
|
force: (args.forceMaterialization === true || emergencyDropEligible) && (args.contextUsage.percentage >= 95 || getEmergencyInputSample(args.db, args.sessionId) === 0),
|
|
31034
31755
|
explicitFlush: hasPendingMaterializeSignal || deferredMaterializeEligible && !prefixPreflightContended,
|
|
31035
31756
|
publishedHistory: !prefixPreflightContended && (args.isCacheBusting || publishedM1RefreshedThisPass || canConsumeDeferredLate && deferredHistoryWasPendingAtPassStart)
|
|
@@ -31045,7 +31766,7 @@ async function runPipeline(args) {
|
|
|
31045
31766
|
onRejectedProjectOverride: (warning) => sessionLog(args.sessionId, warning)
|
|
31046
31767
|
});
|
|
31047
31768
|
let protectionFloorResolution = resolveProtectionFloor();
|
|
31048
|
-
const shouldRunHeuristics = args.heuristics !== undefined && isCacheBustingPass && (rideSignals.publishedHistory || args.forceMaterialization === true || hasPendingMaterializeSignal || deferredMaterializeEligible ||
|
|
31769
|
+
const shouldRunHeuristics = args.heuristics !== undefined && isCacheBustingPass && (rideSignals.publishedHistory || args.forceMaterialization === true || hasPendingMaterializeSignal || deferredMaterializeEligible || foldBustsServedPrefixThisPass || firstRenderBust || args.schedulerDecision === "execute" && !alreadyRanHeuristicsThisTurn);
|
|
31049
31770
|
const tFallbackIdentity = performance.now();
|
|
31050
31771
|
const hasFallbackMessageTags = hasPiFallbackMessageTags(args.db, args.sessionId);
|
|
31051
31772
|
const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, hasFallbackMessageTags);
|
|
@@ -31085,6 +31806,19 @@ async function runPipeline(args) {
|
|
|
31085
31806
|
} : undefined
|
|
31086
31807
|
});
|
|
31087
31808
|
logTransformTiming(args.sessionId, "tagMessages", tTag);
|
|
31809
|
+
if (foldBustsServedPrefixThisPass) {
|
|
31810
|
+
try {
|
|
31811
|
+
let converted = 0;
|
|
31812
|
+
args.db.transaction(() => {
|
|
31813
|
+
converted = convertLegacyToolSkeletons(args.db, args.sessionId, targets).size;
|
|
31814
|
+
}).immediate();
|
|
31815
|
+
if (converted > 0) {
|
|
31816
|
+
sessionLog(args.sessionId, `pi HARD fold converted ${converted} legacy dropped-tool skeleton(s) to real-or-absent`);
|
|
31817
|
+
}
|
|
31818
|
+
} catch (error) {
|
|
31819
|
+
sessionLog(args.sessionId, `pi legacy dropped-tool skeleton conversion failed (kept legacy bytes): ${error instanceof Error ? error.message : String(error)}`);
|
|
31820
|
+
}
|
|
31821
|
+
}
|
|
31088
31822
|
try {
|
|
31089
31823
|
if (!args.sessionMeta.isSubagent) {
|
|
31090
31824
|
const hasRecentCommit = detectRecentCommit(args.messages);
|
|
@@ -31111,12 +31845,13 @@ async function runPipeline(args) {
|
|
|
31111
31845
|
mutationGateObserverForTests?.({
|
|
31112
31846
|
foldDue: foldDueDecision.value,
|
|
31113
31847
|
foldExecuted: foldExecutedThisPass,
|
|
31848
|
+
foldBustsServedPrefix: foldBustsServedPrefixThisPass,
|
|
31114
31849
|
shouldApplyPendingOps,
|
|
31115
31850
|
shouldRunHeuristics,
|
|
31116
31851
|
shouldRunReasoningCleanup: args.reasoningClearing !== undefined && shouldRunHeuristics
|
|
31117
31852
|
});
|
|
31118
31853
|
if (shouldApplyPendingOps) {
|
|
31119
|
-
const applyReason = hasPendingMaterializeSignal ? "explicit_flush" : deferredMaterialize ? "deferred_publication" : args.forceMaterialization ? "force_materialization" :
|
|
31854
|
+
const applyReason = hasPendingMaterializeSignal ? "explicit_flush" : deferredMaterialize ? "deferred_publication" : args.forceMaterialization ? "force_materialization" : foldBustsServedPrefixThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `${reclaimRideLabel(rideSignals)} (scheduler=${args.schedulerDecision})`;
|
|
31120
31855
|
const pendingOpsDepth = getPendingOpsCount(args.db, args.sessionId);
|
|
31121
31856
|
const pendingDecisionLog = `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOpsDepth === null ? "not loaded (deferred pass)" : pendingOpsDepth} context=${args.contextUsage.percentage.toFixed(1)}%`;
|
|
31122
31857
|
sessionLog(args.sessionId, pendingDecisionLog);
|
|
@@ -31203,7 +31938,7 @@ async function runPipeline(args) {
|
|
|
31203
31938
|
const activeTags = allTagsForPass.filter((tag) => tag.status === "active");
|
|
31204
31939
|
logTransformTiming(args.sessionId, "getTagsBySessionSnapshot", tActiveTags, `all=${allTagsForPass.length} active=${activeTags.length}`);
|
|
31205
31940
|
if (shouldRunHeuristics) {
|
|
31206
|
-
const reason = args.forceMaterialization ? "force_materialization" :
|
|
31941
|
+
const reason = args.forceMaterialization ? "force_materialization" : foldBustsServedPrefixThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `${reclaimRideLabel(rideSignals)} (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
|
|
31207
31942
|
const heuristicsDecisionLog = `heuristics WILL RUN — reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=n/a`;
|
|
31208
31943
|
sessionLog(args.sessionId, heuristicsDecisionLog);
|
|
31209
31944
|
pendingDecisionLogObserverForTests?.(heuristicsDecisionLog);
|
|
@@ -31216,7 +31951,7 @@ async function runPipeline(args) {
|
|
|
31216
31951
|
if (shouldRunHeuristics && args.heuristics) {
|
|
31217
31952
|
try {
|
|
31218
31953
|
const tHeuristic = performance.now();
|
|
31219
|
-
const independentMutationBeforeHeuristics = pendingOpsDidMutate ||
|
|
31954
|
+
const independentMutationBeforeHeuristics = pendingOpsDidMutate || foldBustsServedPrefixThisPass;
|
|
31220
31955
|
if (args.forceMaterialization === true && independentMutationBeforeHeuristics && getEmergencyInputSample(args.db, args.sessionId) > 0) {
|
|
31221
31956
|
clearEmergencyDropSample(args.db, args.sessionId);
|
|
31222
31957
|
}
|
|
@@ -31991,6 +32726,7 @@ ${result}`;
|
|
|
31991
32726
|
}
|
|
31992
32727
|
|
|
31993
32728
|
// ../plugin/src/features/magic-context/store-generation-rebase.ts
|
|
32729
|
+
var rebasesInFlight = new WeakMap;
|
|
31994
32730
|
var repairCheckedSessions = new WeakMap;
|
|
31995
32731
|
|
|
31996
32732
|
// ../plugin/src/hooks/magic-context/historian-state-file.ts
|
|
@@ -32195,7 +32931,7 @@ Found ${existingStaging.compartments.length} staged compartment(s) from ${existi
|
|
|
32195
32931
|
clearInjectionCache(sessionId);
|
|
32196
32932
|
}
|
|
32197
32933
|
promoted.facts;
|
|
32198
|
-
|
|
32934
|
+
{
|
|
32199
32935
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
32200
32936
|
await deps.ensureProjectRegistered?.(sessionDirectory, db);
|
|
32201
32937
|
const liveCompartments = getCompartments(db, sessionId);
|
|
@@ -32412,7 +33148,7 @@ Another process acquired the compartment-state lease before recomp could publish
|
|
|
32412
33148
|
queueDropsForCompartmentalizedMessages(db, sessionId, lastCompartmentEnd, compartmentTagKeys);
|
|
32413
33149
|
}
|
|
32414
33150
|
deps.onCompartmentStatePublished?.(sessionId);
|
|
32415
|
-
|
|
33151
|
+
{
|
|
32416
33152
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
32417
33153
|
await deps.ensureProjectRegistered?.(sessionDirectory, db);
|
|
32418
33154
|
const liveCompartments = getCompartments(db, sessionId);
|
|
@@ -32574,7 +33310,7 @@ Could not acquire the compartment-state lease for this session.`;
|
|
|
32574
33310
|
clearInjectionCache(sessionId);
|
|
32575
33311
|
}
|
|
32576
33312
|
deps.onCompartmentStatePublished?.(sessionId);
|
|
32577
|
-
|
|
33313
|
+
{
|
|
32578
33314
|
const projectIdentity = resolveProjectIdentity(sessionDirectory);
|
|
32579
33315
|
const liveCompartments = getCompartments(db, sessionId);
|
|
32580
33316
|
const chunksToEmbed = liveCompartments.map((c) => ({
|
|
@@ -33601,6 +34337,11 @@ function compressionText(summary) {
|
|
|
33601
34337
|
return "Waiting for enough conversation history";
|
|
33602
34338
|
}
|
|
33603
34339
|
}
|
|
34340
|
+
function runnerText(status) {
|
|
34341
|
+
const why = status.source === "configured" ? "configured" : `default for harness ${status.harness || "unknown"}`;
|
|
34342
|
+
const observed = status.observed === "last_completion" ? "" : " · no completion yet";
|
|
34343
|
+
return `${status.runner} (${why})${observed}`;
|
|
34344
|
+
}
|
|
33604
34345
|
function reclaimableText(summary) {
|
|
33605
34346
|
const count = Math.max(0, Math.floor(summary.reclaimable.toolOutputCount));
|
|
33606
34347
|
if (count === 0)
|
|
@@ -33642,6 +34383,12 @@ function renderUserStatusSummary(summary, style) {
|
|
|
33642
34383
|
],
|
|
33643
34384
|
["Search indexing", embeddingText(summary)]
|
|
33644
34385
|
];
|
|
34386
|
+
if (summary.historianRunner) {
|
|
34387
|
+
values.push(["Historian runner", runnerText(summary.historianRunner)]);
|
|
34388
|
+
}
|
|
34389
|
+
if (summary.dreamerRunner) {
|
|
34390
|
+
values.push(["Dreamer runner", runnerText(summary.dreamerRunner)]);
|
|
34391
|
+
}
|
|
33645
34392
|
if (summary.historianRefusal) {
|
|
33646
34393
|
values.push([
|
|
33647
34394
|
"Historian refusal",
|
|
@@ -34120,7 +34867,7 @@ function buildStatusView(source, options) {
|
|
|
34120
34867
|
// package.json
|
|
34121
34868
|
var package_default = {
|
|
34122
34869
|
name: "@cortexkit/pi-magic-context",
|
|
34123
|
-
version: "0.
|
|
34870
|
+
version: "0.44.0",
|
|
34124
34871
|
type: "module",
|
|
34125
34872
|
description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
|
|
34126
34873
|
main: "dist/index.js",
|
|
@@ -34147,6 +34894,7 @@ var package_default = {
|
|
|
34147
34894
|
"dist",
|
|
34148
34895
|
"README.md"
|
|
34149
34896
|
],
|
|
34897
|
+
"//": "The build intentionally bundles typebox (no --external typebox) and keeps it a regular dependency. OMP's extension loader rewrites every bare `typebox` import to its own omptype-based shim, whose schemas are callable objects rather than JSON Schema; they fail structuredClone during tool registration, so an external typebox import stops Magic Context loading on OMP. src/typebox-bundling.test.ts guards this.",
|
|
34150
34898
|
scripts: {
|
|
34151
34899
|
build: "bun ../../scripts/check-bun.mjs && tsc -p ../retina-local-fs/tsconfig.build.json && rm -f dist/index.js dist/subagent-entry.js dist/historian-calibration-extension.js dist/transformers-web.js dist/transformers-node-wasm.js dist/*-*.js && bun build ../plugin/src/features/magic-context/memory/transformers-web-entry.ts --outfile dist/transformers-web.js --target browser --format esm --external onnxruntime-web && bun ../plugin/scripts/build-transformers-node-wasm.ts dist && bun build src/index.ts src/subagent-entry.ts src/historian-calibration-extension.ts --outdir dist --target node --format esm --splitting --external @earendil-works/pi-coding-agent --external @earendil-works/pi-tui --external onnxruntime-node --external onnxruntime-web --external sharp --external node:sqlite",
|
|
34152
34900
|
"build:e2e-argv": "bun build src/subagent-runner.ts --outfile ../../tests/docker/.generated/subagent-runner-e2e.mjs --target node --format esm --external node:sqlite",
|
|
@@ -34161,7 +34909,7 @@ var package_default = {
|
|
|
34161
34909
|
prepublishOnly: "bun run build"
|
|
34162
34910
|
},
|
|
34163
34911
|
dependencies: {
|
|
34164
|
-
"@cortexkit/subc-client": "0.
|
|
34912
|
+
"@cortexkit/subc-client": "0.11.1",
|
|
34165
34913
|
"@jitl/quickjs-singlefile-cjs-release-asyncify": "0.32.0",
|
|
34166
34914
|
"ai-tokenizer": "^1.0.6",
|
|
34167
34915
|
"comment-json": "^5.0.0",
|
|
@@ -34183,6 +34931,7 @@ var package_default = {
|
|
|
34183
34931
|
"@types/better-sqlite3": "^7.6.13",
|
|
34184
34932
|
"@types/bun": "^1.3.10",
|
|
34185
34933
|
"@types/node": "^22.20.0",
|
|
34934
|
+
"pi-agent-core-087": "npm:@earendil-works/pi-agent-core@0.87.1",
|
|
34186
34935
|
"pi-ai-086": "npm:@earendil-works/pi-ai@0.86.0",
|
|
34187
34936
|
"pi-coding-agent-086": "npm:@earendil-works/pi-coding-agent@0.86.0",
|
|
34188
34937
|
"pi-coding-agent-087": "npm:@earendil-works/pi-coding-agent@0.87.1",
|
|
@@ -34723,11 +35472,14 @@ No active Pi session is available.`,
|
|
|
34723
35472
|
}
|
|
34724
35473
|
try {
|
|
34725
35474
|
if (ctx.hasUI) {
|
|
35475
|
+
if (currentDeps.modelChainWarning)
|
|
35476
|
+
ctx.ui.notify(currentDeps.modelChainWarning, "error");
|
|
34726
35477
|
await showStatusDialog(pi, ctx, currentDeps);
|
|
34727
35478
|
return;
|
|
34728
35479
|
}
|
|
34729
35480
|
const statusDetail = buildPiStatusDetail(pi, ctx, currentDeps, sessionId);
|
|
34730
|
-
const statusText = formatPiStatusSummary(statusDetail)
|
|
35481
|
+
const statusText = `${formatPiStatusSummary(statusDetail)}${currentDeps.modelChainWarning ? `
|
|
35482
|
+
WARNING: ${currentDeps.modelChainWarning}` : ""}`;
|
|
34731
35483
|
const details = buildStatusDetails(currentDeps, statusDetail);
|
|
34732
35484
|
sendStatus({
|
|
34733
35485
|
title: "/ctx-status",
|
|
@@ -35514,7 +36266,7 @@ function ensureConfigLocationsMigrated(dir) {
|
|
|
35514
36266
|
});
|
|
35515
36267
|
}
|
|
35516
36268
|
function logPiConfigLoad(args) {
|
|
35517
|
-
const key =
|
|
36269
|
+
const key = resolve4(args.dir);
|
|
35518
36270
|
if (args.dedupe && loggedPiConfigDirs.has(key))
|
|
35519
36271
|
return;
|
|
35520
36272
|
if (args.dedupe) {
|
|
@@ -35575,6 +36327,13 @@ function logPiUsageBoundOnce(sessionId, reading, absoluteWall, reason) {
|
|
|
35575
36327
|
piUsageBoundLogSeen.add(key);
|
|
35576
36328
|
info(`message_end: session=${sessionId} bounded ${reason} ${reading} at trusted absolute wall ${absoluteWall}; pressure_proof_not_capacity`);
|
|
35577
36329
|
}
|
|
36330
|
+
function logPiUsageAboveWindowOnce(sessionId, reading, absoluteWall) {
|
|
36331
|
+
const key = `${sessionId}|accepted above window`;
|
|
36332
|
+
if (piUsageBoundLogSeen.has(key))
|
|
36333
|
+
return;
|
|
36334
|
+
piUsageBoundLogSeen.add(key);
|
|
36335
|
+
info(`message_end: session=${sessionId} provider usage ${reading} exceeds configured window ${absoluteWall}; counted as real pressure against the configured limit`);
|
|
36336
|
+
}
|
|
35578
36337
|
function resolvePiPressureContextLimit(args) {
|
|
35579
36338
|
let detectedContextLimit;
|
|
35580
36339
|
try {
|
|
@@ -35606,24 +36365,32 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
35606
36365
|
});
|
|
35607
36366
|
const trustedAbsoluteWall = reportedGeometry && hasTrustedAbsoluteWall(reportedGeometry) ? reportedGeometry.derivation.absoluteWall : undefined;
|
|
35608
36367
|
const unboundedPressure = computePiPressure(usage, args.piContextWindow);
|
|
35609
|
-
const rawPressure = computePiPressure(usage, args.piContextWindow, trustedAbsoluteWall);
|
|
35610
|
-
if (unboundedPressure && trustedAbsoluteWall !== undefined && unboundedPressure.inputTokens > trustedAbsoluteWall) {
|
|
35611
|
-
logPiUsageBoundOnce(args.sessionId, unboundedPressure.inputTokens, trustedAbsoluteWall, "current reading");
|
|
35612
|
-
}
|
|
35613
36368
|
const msg = args.message && typeof args.message === "object" ? args.message : undefined;
|
|
35614
36369
|
const messageHadOverflowError = typeof msg?.errorMessage === "string" && detectOverflow(msg.errorMessage).isOverflow;
|
|
35615
|
-
const
|
|
35616
|
-
|
|
36370
|
+
const readingAboveTrustedWall = unboundedPressure !== null && trustedAbsoluteWall !== undefined && unboundedPressure.inputTokens > trustedAbsoluteWall;
|
|
36371
|
+
const requestAccepted = !messageHadOverflowError;
|
|
36372
|
+
if (readingAboveTrustedWall && unboundedPressure && trustedAbsoluteWall) {
|
|
36373
|
+
if (requestAccepted) {
|
|
36374
|
+
logPiUsageAboveWindowOnce(args.sessionId, unboundedPressure.inputTokens, trustedAbsoluteWall);
|
|
36375
|
+
} else {
|
|
36376
|
+
logPiUsageBoundOnce(args.sessionId, unboundedPressure.inputTokens, trustedAbsoluteWall, "current reading");
|
|
36377
|
+
}
|
|
36378
|
+
}
|
|
36379
|
+
const requestSucceeded = requestAccepted && !readingAboveTrustedWall;
|
|
36380
|
+
if (requestAccepted && unboundedPressure) {
|
|
35617
36381
|
const rawOverflow = getOverflowState(args.db, args.sessionId);
|
|
35618
36382
|
const detectedLimitMatchesModel = rawOverflow.detectedContextLimitModelKey === null || modelKey !== undefined && rawOverflow.detectedContextLimitModelKey === modelKey;
|
|
35619
|
-
if (rawOverflow.detectedContextLimit > 0 && detectedLimitMatchesModel &&
|
|
36383
|
+
if (rawOverflow.detectedContextLimit > 0 && detectedLimitMatchesModel && unboundedPressure.inputTokens > rawOverflow.detectedContextLimit) {
|
|
35620
36384
|
clearDetectedContextLimit(args.db, args.sessionId);
|
|
35621
|
-
info(`message_end: detected limit ${rawOverflow.detectedContextLimit} invalidated by a successful ${
|
|
36385
|
+
info(`message_end: detected limit ${rawOverflow.detectedContextLimit} invalidated by a successful ${unboundedPressure.inputTokens}-token request; using Pi contextWindow`);
|
|
35622
36386
|
}
|
|
35623
36387
|
}
|
|
35624
36388
|
const meta = getOrCreateSessionMeta(args.db, args.sessionId);
|
|
35625
36389
|
let observedSafeInputTokens = meta.observedSafeInputTokens ?? 0;
|
|
35626
|
-
const updates = {
|
|
36390
|
+
const updates = {};
|
|
36391
|
+
if (unboundedPressure !== null) {
|
|
36392
|
+
updates.lastResponseTime = Date.now();
|
|
36393
|
+
}
|
|
35627
36394
|
if (trustedAbsoluteWall !== undefined && observedSafeInputTokens > trustedAbsoluteWall) {
|
|
35628
36395
|
logPiUsageBoundOnce(args.sessionId, observedSafeInputTokens, trustedAbsoluteWall, "persisted floor");
|
|
35629
36396
|
observedSafeInputTokens = 0;
|
|
@@ -35644,8 +36411,10 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
35644
36411
|
provenInputTokens: observedSafeInputTokens
|
|
35645
36412
|
});
|
|
35646
36413
|
const reportedContextLimit = reportedGeometry?.usableSoft ?? 0;
|
|
35647
|
-
const pressure = computePiPressure(usage, effectiveContextLimit, trustedAbsoluteWall);
|
|
36414
|
+
const pressure = computePiPressure(usage, effectiveContextLimit, requestAccepted ? undefined : trustedAbsoluteWall);
|
|
36415
|
+
let cacheAlert;
|
|
35648
36416
|
if (pressure) {
|
|
36417
|
+
notePiUsageReadingUsed(args.sessionId);
|
|
35649
36418
|
const provenSafeInputTokens = requestSucceeded ? Math.max(observedSafeInputTokens, pressure.inputTokens) : observedSafeInputTokens;
|
|
35650
36419
|
const contextLimit = requestSucceeded ? resolvePiPressureContextLimit({
|
|
35651
36420
|
db: args.db,
|
|
@@ -35659,7 +36428,7 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
35659
36428
|
if (requestSucceeded && reportedContextLimit > 0 && reportedContextLimit < provenSafeInputTokens && !meta.cacheAlertSent) {
|
|
35660
36429
|
updates.cacheAlertSent = true;
|
|
35661
36430
|
const modelLabel = activeModel.provider && activeModel.id ? `${activeModel.provider}/${activeModel.id}` : "the active model";
|
|
35662
|
-
|
|
36431
|
+
cacheAlert = `⚠️ Magic Context: Pi reports a context limit of ${formatTokens(reportedContextLimit)} tokens for ${modelLabel}, but this session has sent ${formatTokens(provenSafeInputTokens)} tokens successfully. Magic Context will keep using the larger proven value for its pressure math. If Pi's model metadata is wrong for your provider, set contextWindow for that model in Pi's model configuration.`;
|
|
35663
36432
|
}
|
|
35664
36433
|
updates.lastContextPercentage = percentage;
|
|
35665
36434
|
updates.lastInputTokens = pressure.inputTokens;
|
|
@@ -35668,13 +36437,21 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
35668
36437
|
updates.observedSafeInputTokens = provenSafeInputTokens;
|
|
35669
36438
|
}
|
|
35670
36439
|
} else if (usage === null && typeof args.piTokens === "number" && (trustedAbsoluteWall === undefined || args.piTokens <= trustedAbsoluteWall)) {
|
|
35671
|
-
|
|
35672
|
-
|
|
35673
|
-
|
|
35674
|
-
|
|
36440
|
+
if (args.piTokensIsRawBranchEstimate === true) {
|
|
36441
|
+
noteRawBranchEstimateSetAside(args.sessionId, args.piTokens, "message_end estimate");
|
|
36442
|
+
} else {
|
|
36443
|
+
notePiUsageReadingUsed(args.sessionId);
|
|
36444
|
+
updates.lastInputTokens = args.piTokens;
|
|
36445
|
+
if (effectiveContextLimit > 0) {
|
|
36446
|
+
updates.lastContextPercentage = args.piTokens / effectiveContextLimit * 100;
|
|
36447
|
+
updates.lastUsageContextLimit = effectiveContextLimit;
|
|
36448
|
+
}
|
|
35675
36449
|
}
|
|
35676
36450
|
}
|
|
35677
36451
|
updateSessionMeta(args.db, args.sessionId, updates);
|
|
36452
|
+
if (cacheAlert !== undefined) {
|
|
36453
|
+
await args.notifyIssue?.(cacheAlert);
|
|
36454
|
+
}
|
|
35678
36455
|
}
|
|
35679
36456
|
var PLUGIN_VERSION = (() => {
|
|
35680
36457
|
try {
|
|
@@ -35685,17 +36462,27 @@ var PLUGIN_VERSION = (() => {
|
|
|
35685
36462
|
}
|
|
35686
36463
|
})();
|
|
35687
36464
|
setHarness(PI_HARNESS_KIND);
|
|
35688
|
-
function resolveHistorianFromConfig(config, harness = PI_HARNESS_KIND) {
|
|
36465
|
+
function resolveHistorianFromConfig(config, harness = PI_HARNESS_KIND, modelRegistry) {
|
|
35689
36466
|
const historian = config.historian;
|
|
35690
36467
|
if (historian?.disable === true)
|
|
35691
36468
|
return;
|
|
35692
36469
|
const resolved = resolveHistorianModel(config, harness);
|
|
35693
|
-
const
|
|
36470
|
+
const validated = modelRegistry && resolved.primary ? validatePiDreamerModels([
|
|
36471
|
+
{
|
|
36472
|
+
task: "classify-memories",
|
|
36473
|
+
schedule: "",
|
|
36474
|
+
timeoutMinutes: 20,
|
|
36475
|
+
model: resolved.primary,
|
|
36476
|
+
fallbackModels: resolved.fallbacks
|
|
36477
|
+
}
|
|
36478
|
+
], modelRegistry)[0] : undefined;
|
|
36479
|
+
const primary = validated ? typeof validated.model === "string" ? { model: validated.model } : validated.model : resolved.primary;
|
|
36480
|
+
const model = primary?.model;
|
|
35694
36481
|
if (!model)
|
|
35695
36482
|
return;
|
|
35696
36483
|
const historianContextLimit = resolveHistorianContextLimit(model);
|
|
35697
36484
|
const historianChunkTokens = deriveHistorianChunkTokens(historianContextLimit);
|
|
35698
|
-
const fallbackModels = resolved.fallbacks;
|
|
36485
|
+
const fallbackModels = validated?.fallbackModels ?? resolved.fallbacks;
|
|
35699
36486
|
return {
|
|
35700
36487
|
runner: new PiSubagentRunner,
|
|
35701
36488
|
model,
|
|
@@ -35706,7 +36493,7 @@ function resolveHistorianFromConfig(config, harness = PI_HARNESS_KIND) {
|
|
|
35706
36493
|
temperature: historian?.temperature,
|
|
35707
36494
|
maxOutputTokens: historian?.maxTokens,
|
|
35708
36495
|
twoPass: historian?.two_pass === true,
|
|
35709
|
-
thinkingLevel:
|
|
36496
|
+
thinkingLevel: primary?.qualifier,
|
|
35710
36497
|
executeThresholdPercentage: config.execute_threshold_percentage,
|
|
35711
36498
|
executeThresholdTokens: config.execute_threshold_tokens,
|
|
35712
36499
|
commitClusterTrigger: config.commit_cluster_trigger,
|
|
@@ -35770,30 +36557,7 @@ async function src_default(pi) {
|
|
|
35770
36557
|
return null;
|
|
35771
36558
|
}
|
|
35772
36559
|
};
|
|
35773
|
-
const unavailableReason = () => {
|
|
35774
|
-
const migration = getMigrationOnOpenRefusal();
|
|
35775
|
-
const blockingProcesses = migration?.blockingProcesses ?? migration?.serverPids.map((pid) => ({ kind: "process", pid })) ?? [];
|
|
35776
|
-
const fence = getSchemaFenceRejection();
|
|
35777
|
-
if (migration && blockingProcesses.length > 0) {
|
|
35778
|
-
return {
|
|
35779
|
-
kind: "migration_guard",
|
|
35780
|
-
persistedVersion: migration.persistedVersion,
|
|
35781
|
-
supportedVersion: migration.supportedVersion,
|
|
35782
|
-
blockingProcesses
|
|
35783
|
-
};
|
|
35784
|
-
}
|
|
35785
|
-
if (fence) {
|
|
35786
|
-
return {
|
|
35787
|
-
kind: "schema_fence",
|
|
35788
|
-
persistedVersion: fence.persistedVersion,
|
|
35789
|
-
supportedVersion: fence.supportedVersion
|
|
35790
|
-
};
|
|
35791
|
-
}
|
|
35792
|
-
return {
|
|
35793
|
-
kind: "storage_failure",
|
|
35794
|
-
cause: migration?.unreadableFile ? `migration guard could not read RPC discovery file ${migration.unreadableFile}` : openFailureCause ?? `storage unavailable at ${dbPath} (cache schema newer than this binary, or open failed)`
|
|
35795
|
-
};
|
|
35796
|
-
};
|
|
36560
|
+
const unavailableReason = () => describeStorageUnavailability(openFailureCause ?? `storage unavailable at ${dbPath} (cache schema newer than this binary, or open failed)`);
|
|
35797
36561
|
const bootResult = await bootPiRuntimeWithDeadline({
|
|
35798
36562
|
deadlineMs: PI_BOOT_DEADLINE_MS,
|
|
35799
36563
|
openStorage,
|
|
@@ -35979,15 +36743,8 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
35979
36743
|
maybeAutoEmbedPiSession({
|
|
35980
36744
|
db: database,
|
|
35981
36745
|
projectDir: dir,
|
|
35982
|
-
projectIdentity: identity
|
|
35983
|
-
|
|
35984
|
-
}, sessionId, dir, identity, (text) => {
|
|
35985
|
-
sendCtxStatusMessage(pi, {
|
|
35986
|
-
title: "/ctx-embed",
|
|
35987
|
-
text,
|
|
35988
|
-
level: "info"
|
|
35989
|
-
});
|
|
35990
|
-
});
|
|
36746
|
+
projectIdentity: identity
|
|
36747
|
+
}, sessionId, dir, identity);
|
|
35991
36748
|
}
|
|
35992
36749
|
});
|
|
35993
36750
|
function buildProjectDeps(dir, identity, cfg, loadMetadata) {
|
|
@@ -36041,10 +36798,11 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36041
36798
|
function resolveCurrentProjectDeps(ctx) {
|
|
36042
36799
|
return resolveProjectDepsForDir(ctx.cwd);
|
|
36043
36800
|
}
|
|
36801
|
+
let activeModelRegistry;
|
|
36044
36802
|
function resolveContextOptionsForProject(dir) {
|
|
36045
36803
|
const project = resolveProjectDepsForDir(dir);
|
|
36046
36804
|
const sampled = historianRunConfig(project.config, liveReaderFor(dir, project.config).poll().effective);
|
|
36047
|
-
const historian = resolveHistorianFromConfig(sampled);
|
|
36805
|
+
const historian = resolveHistorianFromConfig(sampled, PI_HARNESS_KIND, activeModelRegistry);
|
|
36048
36806
|
return { ...project.contextOptions, historian };
|
|
36049
36807
|
}
|
|
36050
36808
|
const bootProjectDeps = buildProjectDeps(projectDir, projectIdentity, config, {
|
|
@@ -36053,7 +36811,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36053
36811
|
hasDeprecatedProtectedTags
|
|
36054
36812
|
});
|
|
36055
36813
|
projectDepsByDir.set(projectDir, bootProjectDeps);
|
|
36056
|
-
function syncDreamerProjectRegistration(current) {
|
|
36814
|
+
function syncDreamerProjectRegistration(current, modelRegistry) {
|
|
36057
36815
|
if (sessionShuttingDown)
|
|
36058
36816
|
return;
|
|
36059
36817
|
seenDreamerProjectIdentities.add(current.projectIdentity);
|
|
@@ -36070,6 +36828,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36070
36828
|
projectIdentity: current.projectIdentity,
|
|
36071
36829
|
registrationOwner: dreamerRegistrationOwner,
|
|
36072
36830
|
config: current.dreamerConfig,
|
|
36831
|
+
modelRegistry,
|
|
36073
36832
|
sampleDreamRun: () => {
|
|
36074
36833
|
const fresh = liveReaderFor(current.projectDir, current.config).poll().effective;
|
|
36075
36834
|
const sampled = dreamerRunConfig(current.config, fresh);
|
|
@@ -36111,6 +36870,8 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36111
36870
|
pi.on("session_start", async (event, ctx) => {
|
|
36112
36871
|
projectDepsByDir.delete(ctx.cwd);
|
|
36113
36872
|
const current = resolveCurrentProjectDeps(ctx);
|
|
36873
|
+
activeModelRegistry = ctx.modelRegistry;
|
|
36874
|
+
syncDreamerProjectRegistration(current, ctx.modelRegistry);
|
|
36114
36875
|
syncCtxMemoryToolEnabled(pi, current.config.memory.enabled);
|
|
36115
36876
|
const failuresToShow = claimConfigParseFailuresOnce("pi", current.configParseFailures);
|
|
36116
36877
|
if (ctx.hasUI && failuresToShow.length > 0) {
|
|
@@ -36189,6 +36950,16 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36189
36950
|
runnable: current.dreamerEnabled,
|
|
36190
36951
|
scheduleSummary: summarizeDreamSchedule(current.config.dreamer)
|
|
36191
36952
|
},
|
|
36953
|
+
modelChainWarning: (() => {
|
|
36954
|
+
const registry = activeModelRegistry;
|
|
36955
|
+
if (!registry)
|
|
36956
|
+
return;
|
|
36957
|
+
const tasks = validatePiDreamerModels(buildDreamTaskRuntimeConfigs(current.config.dreamer, PI_HARNESS_KIND, current.config.language, current.config.mural.model), registry);
|
|
36958
|
+
const empty = tasks.filter((task) => task.modelChainUnavailable).map((task) => task.task);
|
|
36959
|
+
if (!resolveHistorianFromConfig(current.config, PI_HARNESS_KIND, registry) && current.historianConfig)
|
|
36960
|
+
empty.push("historian");
|
|
36961
|
+
return empty.length ? `Pi model chain empty (no model found): ${empty.join(", ")}` : undefined;
|
|
36962
|
+
})(),
|
|
36192
36963
|
activeProfile: current.config.profile,
|
|
36193
36964
|
cacheTtlConfig: current.config.cache_ttl,
|
|
36194
36965
|
cacheTtlConfigured: current.cacheTtlConfigured,
|
|
@@ -36218,7 +36989,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36218
36989
|
resolveRuntimeDeps: (ctx) => {
|
|
36219
36990
|
const current = resolveCurrentProjectDeps(ctx);
|
|
36220
36991
|
const fresh = historianRunConfig(current.config, liveReaderFor(current.projectDir, current.config).poll().effective);
|
|
36221
|
-
const historian = resolveHistorianFromConfig(fresh
|
|
36992
|
+
const historian = resolveHistorianFromConfig(fresh, PI_HARNESS_KIND, activeModelRegistry);
|
|
36222
36993
|
return {
|
|
36223
36994
|
db,
|
|
36224
36995
|
runner: recompRunner,
|
|
@@ -36253,7 +37024,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36253
37024
|
resolveRuntimeDeps: (ctx) => {
|
|
36254
37025
|
const current = resolveCurrentProjectDeps(ctx);
|
|
36255
37026
|
const fresh = historianRunConfig(current.config, liveReaderFor(current.projectDir, current.config).poll().effective);
|
|
36256
|
-
const historian = resolveHistorianFromConfig(fresh
|
|
37027
|
+
const historian = resolveHistorianFromConfig(fresh, PI_HARNESS_KIND, activeModelRegistry);
|
|
36257
37028
|
return {
|
|
36258
37029
|
db,
|
|
36259
37030
|
runner: wrapupRunner,
|
|
@@ -36287,7 +37058,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36287
37058
|
dreamerEnabled: bootProjectDeps.dreamerEnabled,
|
|
36288
37059
|
resolveDreamerEnabled: (ctx) => resolveCurrentProjectDeps(ctx).dreamerEnabled,
|
|
36289
37060
|
onProjectSeen: (identity) => seenDreamerProjectIdentities.add(identity),
|
|
36290
|
-
ensureRegistered: (ctx) => syncDreamerProjectRegistration(resolveCurrentProjectDeps(ctx)),
|
|
37061
|
+
ensureRegistered: (ctx) => syncDreamerProjectRegistration(resolveCurrentProjectDeps(ctx), ctx.modelRegistry),
|
|
36291
37062
|
registrationOwner: dreamerRegistrationOwner
|
|
36292
37063
|
});
|
|
36293
37064
|
info("registered /ctx-dream");
|
|
@@ -36295,8 +37066,6 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36295
37066
|
db,
|
|
36296
37067
|
projectDir,
|
|
36297
37068
|
projectIdentity,
|
|
36298
|
-
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
36299
|
-
resolveMemoryEnabled: (ctx) => resolveCurrentProjectDeps(ctx).config.memory.enabled,
|
|
36300
37069
|
resolveProject: (ctx) => {
|
|
36301
37070
|
const current = resolveCurrentProjectDeps(ctx);
|
|
36302
37071
|
return {
|
|
@@ -36340,7 +37109,8 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36340
37109
|
};
|
|
36341
37110
|
const effectiveConfig = effectiveProjectDeps.config;
|
|
36342
37111
|
try {
|
|
36343
|
-
|
|
37112
|
+
activeModelRegistry = ctx.modelRegistry;
|
|
37113
|
+
syncDreamerProjectRegistration(effectiveProjectDeps, ctx.modelRegistry);
|
|
36344
37114
|
} catch (err) {
|
|
36345
37115
|
warn("before_agent_start: dreamer registration sync threw:", err);
|
|
36346
37116
|
}
|
|
@@ -36540,6 +37310,14 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
36540
37310
|
piContextWindowSource: "catalog",
|
|
36541
37311
|
piModel: ctx.model,
|
|
36542
37312
|
piTokens: piUsage && typeof piUsage.tokens === "number" ? piUsage.tokens : undefined,
|
|
37313
|
+
piTokensIsRawBranchEstimate: (() => {
|
|
37314
|
+
try {
|
|
37315
|
+
const branch = ctx.sessionManager.getBranch?.();
|
|
37316
|
+
return isPiLiveUsageRawBranchEstimate(branch);
|
|
37317
|
+
} catch {
|
|
37318
|
+
return false;
|
|
37319
|
+
}
|
|
37320
|
+
})(),
|
|
36543
37321
|
notifyIssue: async (message) => {
|
|
36544
37322
|
const uiNotify = ctx.ui?.notify;
|
|
36545
37323
|
if (typeof uiNotify === "function") {
|