@wolfx/pi-magic-context 0.24.0 → 0.24.1
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.js +108 -63
- package/dist/subagent-entry.js +33 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -146668,15 +146668,22 @@ function ownerMessageIdForTagRow(row) {
|
|
|
146668
146668
|
}
|
|
146669
146669
|
return row.message_id.replace(CONTENT_ID_SUFFIX, "");
|
|
146670
146670
|
}
|
|
146671
|
-
function getActiveTagTokenAggregate(db, sessionId) {
|
|
146672
|
-
const
|
|
146671
|
+
function getActiveTagTokenAggregate(db, sessionId, protectedTags = 0) {
|
|
146672
|
+
const toolOutputExpr = protectedTags > 0 ? `COALESCE(SUM(CASE WHEN type = 'tool' AND tag_number < (
|
|
146673
|
+
SELECT tag_number FROM tags
|
|
146674
|
+
WHERE session_id = ? AND status = 'active'
|
|
146675
|
+
ORDER BY tag_number DESC LIMIT 1 OFFSET ?
|
|
146676
|
+
) THEN COALESCE(token_count, 0) ELSE 0 END), 0)` : `COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)`;
|
|
146677
|
+
const sql = `SELECT
|
|
146673
146678
|
COALESCE(SUM(CASE WHEN type != 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)
|
|
146674
146679
|
+ COALESCE(SUM(COALESCE(reasoning_token_count, 0)), 0) AS conversation,
|
|
146675
146680
|
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) + COALESCE(input_token_count, 0) ELSE 0 END), 0) AS tool_call,
|
|
146676
|
-
|
|
146681
|
+
${toolOutputExpr} AS tool_output,
|
|
146677
146682
|
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
146678
146683
|
FROM tags
|
|
146679
|
-
WHERE session_id = ? AND status = 'active'
|
|
146684
|
+
WHERE session_id = ? AND status = 'active'`;
|
|
146685
|
+
const params = protectedTags > 0 ? [sessionId, protectedTags - 1, sessionId] : [sessionId];
|
|
146686
|
+
const row = db.prepare(sql).get(...params);
|
|
146680
146687
|
return {
|
|
146681
146688
|
conversation: row?.conversation ?? 0,
|
|
146682
146689
|
toolCall: row?.tool_call ?? 0,
|
|
@@ -166296,6 +166303,7 @@ init_logger();
|
|
|
166296
166303
|
// ../plugin/src/features/magic-context/compartment-chunk-embedding.ts
|
|
166297
166304
|
import { createHash as createHash8 } from "node:crypto";
|
|
166298
166305
|
var DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS = 512;
|
|
166306
|
+
var CHUNK_WINDOW_SAFETY_RATIO = 0.9;
|
|
166299
166307
|
var loadFtsRowsStatements = new WeakMap;
|
|
166300
166308
|
var existingHashStatements = new WeakMap;
|
|
166301
166309
|
var existingHashByProjectStatements = new WeakMap;
|
|
@@ -166531,9 +166539,10 @@ function chunkCanonicalText(canonicalText, startOrdinal, endOrdinal, maxInputTok
|
|
|
166531
166539
|
if (lines.length === 0 || endOrdinal < startOrdinal)
|
|
166532
166540
|
return [];
|
|
166533
166541
|
const normalizedMax = normalizeCompartmentChunkMaxInputTokens(maxInputTokens);
|
|
166542
|
+
const effectiveMax = Math.max(1, Math.floor(normalizedMax * CHUNK_WINDOW_SAFETY_RATIO));
|
|
166534
166543
|
const fullText = lines.join(`
|
|
166535
166544
|
`);
|
|
166536
|
-
if (estimateTokens(fullText) <=
|
|
166545
|
+
if (estimateTokens(fullText) <= effectiveMax) {
|
|
166537
166546
|
return [
|
|
166538
166547
|
{
|
|
166539
166548
|
windowIndex: 0,
|
|
@@ -166571,7 +166580,7 @@ function chunkCanonicalText(canonicalText, startOrdinal, endOrdinal, maxInputTok
|
|
|
166571
166580
|
const lineStart = range?.start ?? startOrdinal;
|
|
166572
166581
|
const lineEnd = range?.end ?? lineStart;
|
|
166573
166582
|
const lineTokens = estimateTokens(line);
|
|
166574
|
-
if (currentLines.length > 0 && currentTokens + lineTokens >
|
|
166583
|
+
if (currentLines.length > 0 && currentTokens + lineTokens > effectiveMax) {
|
|
166575
166584
|
flush2();
|
|
166576
166585
|
}
|
|
166577
166586
|
if (currentLines.length === 0) {
|
|
@@ -167171,6 +167180,13 @@ function blockedEmbeddingEndpointReason(endpoint) {
|
|
|
167171
167180
|
function normalizeEndpoint2(endpoint) {
|
|
167172
167181
|
return endpoint?.trim().replace(/\/+$/, "") ?? "";
|
|
167173
167182
|
}
|
|
167183
|
+
function embeddingModelsMatch(served, requested) {
|
|
167184
|
+
const a = served.trim().toLowerCase();
|
|
167185
|
+
const b = requested.trim().toLowerCase();
|
|
167186
|
+
if (a.length === 0 || b.length === 0)
|
|
167187
|
+
return true;
|
|
167188
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
167189
|
+
}
|
|
167174
167190
|
var FAILURE_THRESHOLD = 3;
|
|
167175
167191
|
var FAILURE_WINDOW_MS = 60000;
|
|
167176
167192
|
var OPEN_DURATION_MS = 5 * 60000;
|
|
@@ -167188,6 +167204,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
167188
167204
|
failureTimes = [];
|
|
167189
167205
|
circuitOpenUntil = 0;
|
|
167190
167206
|
openLogged = false;
|
|
167207
|
+
modelMismatchLogged = false;
|
|
167191
167208
|
halfOpenProbeInFlight = false;
|
|
167192
167209
|
constructor(options) {
|
|
167193
167210
|
this.endpoint = normalizeEndpoint2(options.endpoint);
|
|
@@ -167286,6 +167303,15 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
167286
167303
|
this.recordFailure(isProbe);
|
|
167287
167304
|
return Array.from({ length: texts.length }, () => null);
|
|
167288
167305
|
}
|
|
167306
|
+
const servedModel = typeof body.model === "string" ? body.model : "";
|
|
167307
|
+
if (this.model && servedModel && !embeddingModelsMatch(servedModel, this.model)) {
|
|
167308
|
+
if (!this.modelMismatchLogged) {
|
|
167309
|
+
log(`[magic-context] embedding endpoint served a DIFFERENT model than requested — refusing the substituted vectors (they have the wrong dimensions/space). requested="${this.model}" served="${servedModel}". The endpoint likely substituted a loaded model; load/select "${this.model}" on the endpoint, or set embedding.model to the served model.`);
|
|
167310
|
+
this.modelMismatchLogged = true;
|
|
167311
|
+
}
|
|
167312
|
+
this.recordFailure(isProbe);
|
|
167313
|
+
return Array.from({ length: texts.length }, () => null);
|
|
167314
|
+
}
|
|
167289
167315
|
const items = Array.isArray(body.data) ? body.data : [];
|
|
167290
167316
|
const results = Array.from({ length: texts.length }, (_, index) => {
|
|
167291
167317
|
const embedding = items[index]?.embedding;
|
|
@@ -167768,7 +167794,7 @@ function getChunkEmbeddingModelId(config2, providerIdentity) {
|
|
|
167768
167794
|
}
|
|
167769
167795
|
const chunkIdentity = {
|
|
167770
167796
|
providerIdentity,
|
|
167771
|
-
chunkerVersion:
|
|
167797
|
+
chunkerVersion: 2,
|
|
167772
167798
|
maxInputTokens: normalizeCompartmentChunkMaxInputTokens("max_input_tokens" in config2 ? config2.max_input_tokens : undefined),
|
|
167773
167799
|
truncate: config2.provider === "openai-compatible" ? config2.truncate ?? "" : ""
|
|
167774
167800
|
};
|
|
@@ -170312,6 +170338,51 @@ function computePiWorkMetrics(sessionEntries) {
|
|
|
170312
170338
|
return { newWorkTokens, totalInputTokens };
|
|
170313
170339
|
}
|
|
170314
170340
|
|
|
170341
|
+
// ../plugin/src/hooks/magic-context/system-injection-stripper.ts
|
|
170342
|
+
var SYSTEM_INJECTION_MARKERS = [
|
|
170343
|
+
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
170344
|
+
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
170345
|
+
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
170346
|
+
"[Category+Skill Reminder]",
|
|
170347
|
+
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
170348
|
+
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
170349
|
+
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
170350
|
+
"Unstable background agent appears idle",
|
|
170351
|
+
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
170352
|
+
];
|
|
170353
|
+
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
170354
|
+
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
170355
|
+
function stripSystemInjection(text) {
|
|
170356
|
+
let hasInjection = false;
|
|
170357
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
170358
|
+
if (text.includes(marker)) {
|
|
170359
|
+
hasInjection = true;
|
|
170360
|
+
break;
|
|
170361
|
+
}
|
|
170362
|
+
}
|
|
170363
|
+
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
170364
|
+
hasInjection = true;
|
|
170365
|
+
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
170366
|
+
if (!hasInjection)
|
|
170367
|
+
return null;
|
|
170368
|
+
let cleaned = text;
|
|
170369
|
+
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
170370
|
+
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
170371
|
+
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
170372
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
170373
|
+
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
170374
|
+
continue;
|
|
170375
|
+
const idx = cleaned.indexOf(marker);
|
|
170376
|
+
if (idx === -1)
|
|
170377
|
+
continue;
|
|
170378
|
+
const blockEnd = cleaned.indexOf(`
|
|
170379
|
+
|
|
170380
|
+
`, idx + marker.length);
|
|
170381
|
+
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
170382
|
+
}
|
|
170383
|
+
return cleaned.trim();
|
|
170384
|
+
}
|
|
170385
|
+
|
|
170315
170386
|
// ../plugin/src/hooks/magic-context/apply-operations.ts
|
|
170316
170387
|
var USER_DROP_PREVIEW_CHARS = 250;
|
|
170317
170388
|
var RECENT_TOOL_SKELETON_WINDOW = 20;
|
|
@@ -170321,6 +170392,10 @@ function buildReplacementContent(tagId, target) {
|
|
|
170321
170392
|
return `[dropped §${tagId}§]`;
|
|
170322
170393
|
}
|
|
170323
170394
|
const currentContent = target.getContent?.() ?? "";
|
|
170395
|
+
const strippedInjection = stripSystemInjection(currentContent);
|
|
170396
|
+
if (strippedInjection !== null && stripTagPrefix(strippedInjection).trim().length === 0) {
|
|
170397
|
+
return `[dropped §${tagId}§]`;
|
|
170398
|
+
}
|
|
170324
170399
|
const originalText = stripTagPrefix(currentContent);
|
|
170325
170400
|
if (originalText.length <= USER_DROP_PREVIEW_CHARS) {
|
|
170326
170401
|
return `[truncated §${tagId}§]
|
|
@@ -171929,8 +172004,8 @@ var CHANNEL1_SENTINEL = "<system-reminder>";
|
|
|
171929
172004
|
var TOKENS_PER_BYTE = 0.25;
|
|
171930
172005
|
var CHANNEL1_FLOOR_TOKENS = 1e4;
|
|
171931
172006
|
var CHANNEL1_REFIRE_FLOOR_TOKENS = 1e4;
|
|
171932
|
-
function channel1RefireTokens(
|
|
171933
|
-
const scaled = Math.round(0.05 * Math.max(0,
|
|
172007
|
+
function channel1RefireTokens(workingWindowTokens) {
|
|
172008
|
+
const scaled = Math.round(0.05 * Math.max(0, workingWindowTokens));
|
|
171934
172009
|
return Math.max(CHANNEL1_REFIRE_FLOOR_TOKENS, scaled);
|
|
171935
172010
|
}
|
|
171936
172011
|
var S_GENTLE = 0.2;
|
|
@@ -171946,7 +172021,7 @@ function toolOutputTokens(output) {
|
|
|
171946
172021
|
return Math.round(byteSize(output) * TOKENS_PER_BYTE);
|
|
171947
172022
|
}
|
|
171948
172023
|
function decideChannel1(input) {
|
|
171949
|
-
const { undroppedTokens, pressure,
|
|
172024
|
+
const { undroppedTokens, pressure, workingWindowTokens, hasRecentReduce } = input;
|
|
171950
172025
|
const resetCycle = hasRecentReduce || undroppedTokens < input.lastNudgeUndropped;
|
|
171951
172026
|
const lastNudge = resetCycle ? 0 : input.lastNudgeUndropped;
|
|
171952
172027
|
const lastLevel = resetCycle ? "" : input.lastNudgeLevel;
|
|
@@ -171961,7 +172036,7 @@ function decideChannel1(input) {
|
|
|
171961
172036
|
return quiet();
|
|
171962
172037
|
if (undroppedTokens < CHANNEL1_FLOOR_TOKENS)
|
|
171963
172038
|
return quiet();
|
|
171964
|
-
const budget =
|
|
172039
|
+
const budget = workingWindowTokens > 0 ? workingWindowTokens : undroppedTokens || 1;
|
|
171965
172040
|
const severity = undroppedTokens / budget * pressure;
|
|
171966
172041
|
if (severity < S_GENTLE)
|
|
171967
172042
|
return quiet();
|
|
@@ -171973,7 +172048,7 @@ function decideChannel1(input) {
|
|
|
171973
172048
|
else
|
|
171974
172049
|
level = "gentle";
|
|
171975
172050
|
if (lastLevel === "") {
|
|
171976
|
-
if (undroppedTokens < lastNudge + channel1RefireTokens(
|
|
172051
|
+
if (undroppedTokens < lastNudge + channel1RefireTokens(workingWindowTokens)) {
|
|
171977
172052
|
return quiet();
|
|
171978
172053
|
}
|
|
171979
172054
|
} else if (LEVEL_RANK[level] <= LEVEL_RANK[lastLevel]) {
|
|
@@ -172018,13 +172093,13 @@ function buildChannel1Reminder(level, undroppedTokens) {
|
|
|
172018
172093
|
let body;
|
|
172019
172094
|
switch (level) {
|
|
172020
172095
|
case "gentle":
|
|
172021
|
-
body = `You have ~${amount} tokens of tool output you have not reduced. ` + `
|
|
172096
|
+
body = `You have ~${amount} tokens of tool output you have not reduced. ` + `When you are done with earlier outputs, dropping them with ctx_reduce keeps context lean.`;
|
|
172022
172097
|
break;
|
|
172023
172098
|
case "firm":
|
|
172024
|
-
body = `~${amount} tokens of unreduced tool output
|
|
172099
|
+
body = `~${amount} tokens of unreduced tool output has built up. ` + `At your next natural stopping point, consider dropping what you have already processed with ctx_reduce.`;
|
|
172025
172100
|
break;
|
|
172026
172101
|
case "urgent":
|
|
172027
|
-
body = `~${amount} tokens of unreduced tool output remain
|
|
172102
|
+
body = `~${amount} tokens of unreduced tool output remain, and a large span of this session will be comparted before long. ` + `Consider dropping spent outputs with ctx_reduce so the archived span is the part that matters.`;
|
|
172028
172103
|
break;
|
|
172029
172104
|
}
|
|
172030
172105
|
return `
|
|
@@ -174343,10 +174418,11 @@ function maybeChannel1ReminderForToolResult(args) {
|
|
|
174343
174418
|
contextLimit: state.contextLimit,
|
|
174344
174419
|
executeThresholdPercentage: state.executeThresholdPercentage
|
|
174345
174420
|
});
|
|
174421
|
+
const workingWindowTokens = Math.round(state.contextLimit * state.executeThresholdPercentage / 100);
|
|
174346
174422
|
const decision = decideChannel1({
|
|
174347
174423
|
undroppedTokens,
|
|
174348
174424
|
pressure,
|
|
174349
|
-
|
|
174425
|
+
workingWindowTokens,
|
|
174350
174426
|
lastNudgeUndropped: getLastNudgeUndropped(db, sessionId),
|
|
174351
174427
|
lastNudgeLevel: getLastNudgeLevel(db, sessionId),
|
|
174352
174428
|
hasRecentReduce: false
|
|
@@ -174581,51 +174657,6 @@ function planEmergencyDrop(input) {
|
|
|
174581
174657
|
};
|
|
174582
174658
|
}
|
|
174583
174659
|
|
|
174584
|
-
// ../plugin/src/hooks/magic-context/system-injection-stripper.ts
|
|
174585
|
-
var SYSTEM_INJECTION_MARKERS = [
|
|
174586
|
-
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
174587
|
-
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
174588
|
-
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
174589
|
-
"[Category+Skill Reminder]",
|
|
174590
|
-
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
174591
|
-
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
174592
|
-
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
174593
|
-
"Unstable background agent appears idle",
|
|
174594
|
-
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
174595
|
-
];
|
|
174596
|
-
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
174597
|
-
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
174598
|
-
function stripSystemInjection(text) {
|
|
174599
|
-
let hasInjection = false;
|
|
174600
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
174601
|
-
if (text.includes(marker)) {
|
|
174602
|
-
hasInjection = true;
|
|
174603
|
-
break;
|
|
174604
|
-
}
|
|
174605
|
-
}
|
|
174606
|
-
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
174607
|
-
hasInjection = true;
|
|
174608
|
-
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
174609
|
-
if (!hasInjection)
|
|
174610
|
-
return null;
|
|
174611
|
-
let cleaned = text;
|
|
174612
|
-
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
174613
|
-
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
174614
|
-
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
174615
|
-
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
174616
|
-
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
174617
|
-
continue;
|
|
174618
|
-
const idx = cleaned.indexOf(marker);
|
|
174619
|
-
if (idx === -1)
|
|
174620
|
-
continue;
|
|
174621
|
-
const blockEnd = cleaned.indexOf(`
|
|
174622
|
-
|
|
174623
|
-
`, idx + marker.length);
|
|
174624
|
-
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
174625
|
-
}
|
|
174626
|
-
return cleaned.trim();
|
|
174627
|
-
}
|
|
174628
|
-
|
|
174629
174660
|
// src/heuristic-cleanup-pi.ts
|
|
174630
174661
|
init_logger();
|
|
174631
174662
|
var DEDUP_SAFE_TOOLS = new Set([
|
|
@@ -181745,7 +181776,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
181745
181776
|
let tailToolTokens;
|
|
181746
181777
|
let liveTailTokens;
|
|
181747
181778
|
try {
|
|
181748
|
-
const agg = getActiveTagTokenAggregate(options.db, sessionId);
|
|
181779
|
+
const agg = getActiveTagTokenAggregate(options.db, sessionId, options.protectedTags ?? 20);
|
|
181749
181780
|
tailToolTokens = agg.toolOutput;
|
|
181750
181781
|
liveTailTokens = agg.conversation + agg.toolCall;
|
|
181751
181782
|
} catch {
|
|
@@ -182098,6 +182129,15 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
182098
182129
|
const trigger = checkCompartmentTrigger(db, sessionId, sessionMeta, usage, 0, triggerInputs.executeThresholdPercentage, triggerInputs.triggerBudget, triggerInputs.clearReasoningAge, triggerInputs.commitClusterTrigger, args.activeTags, boundaryContextLimit);
|
|
182099
182130
|
if (!trigger.shouldFire) {
|
|
182100
182131
|
sessionLog(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
|
|
182132
|
+
try {
|
|
182133
|
+
const overflowState = getOverflowState(db, sessionId);
|
|
182134
|
+
if (overflowState.needsEmergencyRecovery && usage.percentage < FORCE_MATERIALIZATION_PERCENTAGE && !inFlightHistorian.has(sessionId) && !hasRunnableCompartmentWindow(boundarySnapshot)) {
|
|
182135
|
+
clearEmergencyRecovery(db, sessionId);
|
|
182136
|
+
sessionLog(sessionId, `historian: disarming stale emergency recovery — real pressure ${usage.percentage.toFixed(1)}% with no runnable compartment window (would otherwise bump to 95% every pass)`);
|
|
182137
|
+
}
|
|
182138
|
+
} catch (err) {
|
|
182139
|
+
sessionLog(sessionId, `historian: emergency-recovery disarm check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
182140
|
+
}
|
|
182101
182141
|
return;
|
|
182102
182142
|
}
|
|
182103
182143
|
triggered = true;
|
|
@@ -184478,6 +184518,11 @@ Historian recomp started. Rebuilding compartments and facts from raw Pi session
|
|
|
184478
184518
|
fallbackModelId: ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined
|
|
184479
184519
|
}, parsed.kind === "partial" ? { range: parsed.range } : {});
|
|
184480
184520
|
if (result.published) {
|
|
184521
|
+
try {
|
|
184522
|
+
clearEmergencyRecovery(deps.db, sessionId);
|
|
184523
|
+
} catch (recoveryError) {
|
|
184524
|
+
sessionLog(sessionId, `/ctx-recomp: clearEmergencyRecovery failed (continuing): ${describeError(recoveryError).brief}`);
|
|
184525
|
+
}
|
|
184481
184526
|
try {
|
|
184482
184527
|
stagePiRecompMarker({ db: deps.db, sessionId, ctx });
|
|
184483
184528
|
} catch (markerError) {
|
|
@@ -185131,7 +185176,7 @@ function formatThresholdPercent(value) {
|
|
|
185131
185176
|
// package.json
|
|
185132
185177
|
var package_default = {
|
|
185133
185178
|
name: "@wolfx/pi-magic-context",
|
|
185134
|
-
version: "0.24.
|
|
185179
|
+
version: "0.24.1",
|
|
185135
185180
|
type: "module",
|
|
185136
185181
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
185137
185182
|
main: "dist/index.js",
|
package/dist/subagent-entry.js
CHANGED
|
@@ -158709,6 +158709,7 @@ init_logger();
|
|
|
158709
158709
|
// ../plugin/src/features/magic-context/compartment-chunk-embedding.ts
|
|
158710
158710
|
import { createHash as createHash4 } from "node:crypto";
|
|
158711
158711
|
var DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS = 512;
|
|
158712
|
+
var CHUNK_WINDOW_SAFETY_RATIO = 0.9;
|
|
158712
158713
|
var loadFtsRowsStatements = new WeakMap;
|
|
158713
158714
|
var existingHashStatements = new WeakMap;
|
|
158714
158715
|
var existingHashByProjectStatements = new WeakMap;
|
|
@@ -158944,9 +158945,10 @@ function chunkCanonicalText(canonicalText, startOrdinal, endOrdinal, maxInputTok
|
|
|
158944
158945
|
if (lines.length === 0 || endOrdinal < startOrdinal)
|
|
158945
158946
|
return [];
|
|
158946
158947
|
const normalizedMax = normalizeCompartmentChunkMaxInputTokens(maxInputTokens);
|
|
158948
|
+
const effectiveMax = Math.max(1, Math.floor(normalizedMax * CHUNK_WINDOW_SAFETY_RATIO));
|
|
158947
158949
|
const fullText = lines.join(`
|
|
158948
158950
|
`);
|
|
158949
|
-
if (estimateTokens(fullText) <=
|
|
158951
|
+
if (estimateTokens(fullText) <= effectiveMax) {
|
|
158950
158952
|
return [
|
|
158951
158953
|
{
|
|
158952
158954
|
windowIndex: 0,
|
|
@@ -158984,7 +158986,7 @@ function chunkCanonicalText(canonicalText, startOrdinal, endOrdinal, maxInputTok
|
|
|
158984
158986
|
const lineStart = range?.start ?? startOrdinal;
|
|
158985
158987
|
const lineEnd = range?.end ?? lineStart;
|
|
158986
158988
|
const lineTokens = estimateTokens(line);
|
|
158987
|
-
if (currentLines.length > 0 && currentTokens + lineTokens >
|
|
158989
|
+
if (currentLines.length > 0 && currentTokens + lineTokens > effectiveMax) {
|
|
158988
158990
|
flush2();
|
|
158989
158991
|
}
|
|
158990
158992
|
if (currentLines.length === 0) {
|
|
@@ -159594,6 +159596,13 @@ function blockedEmbeddingEndpointReason(endpoint) {
|
|
|
159594
159596
|
function normalizeEndpoint3(endpoint) {
|
|
159595
159597
|
return endpoint?.trim().replace(/\/+$/, "") ?? "";
|
|
159596
159598
|
}
|
|
159599
|
+
function embeddingModelsMatch(served, requested) {
|
|
159600
|
+
const a = served.trim().toLowerCase();
|
|
159601
|
+
const b = requested.trim().toLowerCase();
|
|
159602
|
+
if (a.length === 0 || b.length === 0)
|
|
159603
|
+
return true;
|
|
159604
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
159605
|
+
}
|
|
159597
159606
|
var FAILURE_THRESHOLD = 3;
|
|
159598
159607
|
var FAILURE_WINDOW_MS = 60000;
|
|
159599
159608
|
var OPEN_DURATION_MS = 5 * 60000;
|
|
@@ -159611,6 +159620,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
159611
159620
|
failureTimes = [];
|
|
159612
159621
|
circuitOpenUntil = 0;
|
|
159613
159622
|
openLogged = false;
|
|
159623
|
+
modelMismatchLogged = false;
|
|
159614
159624
|
halfOpenProbeInFlight = false;
|
|
159615
159625
|
constructor(options) {
|
|
159616
159626
|
this.endpoint = normalizeEndpoint3(options.endpoint);
|
|
@@ -159709,6 +159719,15 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
159709
159719
|
this.recordFailure(isProbe);
|
|
159710
159720
|
return Array.from({ length: texts.length }, () => null);
|
|
159711
159721
|
}
|
|
159722
|
+
const servedModel = typeof body.model === "string" ? body.model : "";
|
|
159723
|
+
if (this.model && servedModel && !embeddingModelsMatch(servedModel, this.model)) {
|
|
159724
|
+
if (!this.modelMismatchLogged) {
|
|
159725
|
+
log(`[magic-context] embedding endpoint served a DIFFERENT model than requested — refusing the substituted vectors (they have the wrong dimensions/space). requested="${this.model}" served="${servedModel}". The endpoint likely substituted a loaded model; load/select "${this.model}" on the endpoint, or set embedding.model to the served model.`);
|
|
159726
|
+
this.modelMismatchLogged = true;
|
|
159727
|
+
}
|
|
159728
|
+
this.recordFailure(isProbe);
|
|
159729
|
+
return Array.from({ length: texts.length }, () => null);
|
|
159730
|
+
}
|
|
159712
159731
|
const items = Array.isArray(body.data) ? body.data : [];
|
|
159713
159732
|
const results = Array.from({ length: texts.length }, (_, index) => {
|
|
159714
159733
|
const embedding = items[index]?.embedding;
|
|
@@ -160307,7 +160326,7 @@ function getChunkEmbeddingModelId(config2, providerIdentity) {
|
|
|
160307
160326
|
}
|
|
160308
160327
|
const chunkIdentity = {
|
|
160309
160328
|
providerIdentity,
|
|
160310
|
-
chunkerVersion:
|
|
160329
|
+
chunkerVersion: 2,
|
|
160311
160330
|
maxInputTokens: normalizeCompartmentChunkMaxInputTokens("max_input_tokens" in config2 ? config2.max_input_tokens : undefined),
|
|
160312
160331
|
truncate: config2.provider === "openai-compatible" ? config2.truncate ?? "" : ""
|
|
160313
160332
|
};
|
|
@@ -168674,15 +168693,22 @@ function ownerMessageIdForTagRow(row) {
|
|
|
168674
168693
|
}
|
|
168675
168694
|
return row.message_id.replace(CONTENT_ID_SUFFIX, "");
|
|
168676
168695
|
}
|
|
168677
|
-
function getActiveTagTokenAggregate(db, sessionId) {
|
|
168678
|
-
const
|
|
168696
|
+
function getActiveTagTokenAggregate(db, sessionId, protectedTags = 0) {
|
|
168697
|
+
const toolOutputExpr = protectedTags > 0 ? `COALESCE(SUM(CASE WHEN type = 'tool' AND tag_number < (
|
|
168698
|
+
SELECT tag_number FROM tags
|
|
168699
|
+
WHERE session_id = ? AND status = 'active'
|
|
168700
|
+
ORDER BY tag_number DESC LIMIT 1 OFFSET ?
|
|
168701
|
+
) THEN COALESCE(token_count, 0) ELSE 0 END), 0)` : `COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)`;
|
|
168702
|
+
const sql = `SELECT
|
|
168679
168703
|
COALESCE(SUM(CASE WHEN type != 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)
|
|
168680
168704
|
+ COALESCE(SUM(COALESCE(reasoning_token_count, 0)), 0) AS conversation,
|
|
168681
168705
|
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) + COALESCE(input_token_count, 0) ELSE 0 END), 0) AS tool_call,
|
|
168682
|
-
|
|
168706
|
+
${toolOutputExpr} AS tool_output,
|
|
168683
168707
|
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
168684
168708
|
FROM tags
|
|
168685
|
-
WHERE session_id = ? AND status = 'active'
|
|
168709
|
+
WHERE session_id = ? AND status = 'active'`;
|
|
168710
|
+
const params = protectedTags > 0 ? [sessionId, protectedTags - 1, sessionId] : [sessionId];
|
|
168711
|
+
const row = db.prepare(sql).get(...params);
|
|
168686
168712
|
return {
|
|
168687
168713
|
conversation: row?.conversation ?? 0,
|
|
168688
168714
|
toolCall: row?.tool_call ?? 0,
|
package/package.json
CHANGED