@cortexkit/pi-magic-context 0.31.2 → 0.31.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1109 -275
- package/dist/subagent-entry.js +488 -35
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -155029,6 +155029,13 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
|
|
|
155029
155029
|
SET new_work_tokens = ?, total_input_tokens = ?
|
|
155030
155030
|
WHERE session_id = ?`).run(Math.max(0, Math.floor(newWorkTokens)), Math.max(0, Math.floor(totalInputTokens)), sessionId);
|
|
155031
155031
|
}
|
|
155032
|
+
function getSessionWorkMetrics(db, sessionId) {
|
|
155033
|
+
const row = db.prepare("SELECT new_work_tokens, total_input_tokens FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
155034
|
+
return {
|
|
155035
|
+
newWorkTokens: typeof row?.new_work_tokens === "number" ? row.new_work_tokens : 0,
|
|
155036
|
+
totalInputTokens: typeof row?.total_input_tokens === "number" ? row.total_input_tokens : 0
|
|
155037
|
+
};
|
|
155038
|
+
}
|
|
155032
155039
|
// ../plugin/src/features/magic-context/storage-meta-session.ts
|
|
155033
155040
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
155034
155041
|
|
|
@@ -157979,7 +157986,8 @@ function registerCtxAugCommand(pi, config) {
|
|
|
157979
157986
|
const branch = ctx.sessionManager.getBranch();
|
|
157980
157987
|
const lastEntryId = branch.length > 0 ? branch[branch.length - 1]?.id : "unknown";
|
|
157981
157988
|
const sessionLabel = `pi-session-${lastEntryId}`;
|
|
157982
|
-
|
|
157989
|
+
const currentConfig = typeof config === "function" ? config(ctx) : config;
|
|
157990
|
+
if (!currentConfig) {
|
|
157983
157991
|
ctx.ui.notify("/ctx-aug: Sidekick is not configured. Add `sidekick.model` to your magic-context.jsonc to enable this command.", "warning");
|
|
157984
157992
|
return;
|
|
157985
157993
|
}
|
|
@@ -157991,20 +157999,20 @@ function registerCtxAugCommand(pi, config) {
|
|
|
157991
157999
|
ctx.ui.notify("\uD83D\uDD0D Preparing augmentation… 2-10s depending on your sidekick provider.", "info");
|
|
157992
158000
|
}
|
|
157993
158001
|
sessionLog(sessionLabel, "/ctx-aug: spawning sidekick", {
|
|
157994
|
-
model:
|
|
158002
|
+
model: currentConfig.model
|
|
157995
158003
|
});
|
|
157996
158004
|
const projectIdentity = resolveProjectIdentity(ctx.cwd);
|
|
157997
158005
|
sessionLog(sessionLabel, "/ctx-aug: project identity", projectIdentity);
|
|
157998
158006
|
const result = await runner.run({
|
|
157999
158007
|
agent: "sidekick",
|
|
158000
|
-
systemPrompt: withContentLanguageDirective(
|
|
158008
|
+
systemPrompt: withContentLanguageDirective(currentConfig.systemPrompt ?? SIDEKICK_SYSTEM_PROMPT, currentConfig.language),
|
|
158001
158009
|
userMessage: prompt,
|
|
158002
|
-
model:
|
|
158003
|
-
fallbackModels:
|
|
158004
|
-
timeoutMs:
|
|
158010
|
+
model: currentConfig.model,
|
|
158011
|
+
fallbackModels: currentConfig.fallbackModels,
|
|
158012
|
+
timeoutMs: currentConfig.timeoutMs ?? 30000,
|
|
158005
158013
|
cwd: ctx.cwd,
|
|
158006
158014
|
signal: ctx.signal,
|
|
158007
|
-
thinkingLevel:
|
|
158015
|
+
thinkingLevel: currentConfig.thinking_level,
|
|
158008
158016
|
accountingSessionId: sessionLabel,
|
|
158009
158017
|
accountingSubagent: "sidekick"
|
|
158010
158018
|
});
|
|
@@ -173234,6 +173242,10 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
173234
173242
|
}).describe("Embedding provider configuration"),
|
|
173235
173243
|
temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add start/end date attributes on compartments. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
|
|
173236
173244
|
keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
|
|
173245
|
+
todowrite: exports_external.object({
|
|
173246
|
+
enabled: exports_external.boolean().default(true).describe("Pi only: register Magic Context's todowrite task-list tool. Disable if you use your own todo extension. OpenCode ships its own built-in todowrite; this setting has no effect there."),
|
|
173247
|
+
overlay: exports_external.boolean().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
|
|
173248
|
+
}).default({ enabled: true, overlay: true }).describe("Pi-only todowrite tool and overlay controls. Pi registers tools and widgets at extension boot, so changing this after /cd requires /reload or restart."),
|
|
173237
173249
|
smart_drops: exports_external.boolean().default(false).describe("Content-aware reclaim of provably-superseded tool output, layered on the existing execute-pass auto-drop. When on: superseded todowrite (keep newest 1), spent ctx_reduce (keep newest 5), and zero-value meta (bash_status, bash_kill, ctx_note read/dismiss) outputs are dropped; older edits to a file are compressed to a filePath-preserving marker while the newest edit per file stays full. Only acts on passes already busting the cache, so it never originates a cache bust. Honors the protected-tag reserve. Experimental: opt-in, default off until cache stability is proven; when off the wire is byte-identical to the positional-only reclaim. Requires a restart."),
|
|
173238
173250
|
caveman_text_compression: exports_external.object({
|
|
173239
173251
|
enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Active for primary sessions when enabled; never for subagents. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
|
|
@@ -176773,9 +176785,11 @@ import path7 from "node:path";
|
|
|
176773
176785
|
import { promisify } from "node:util";
|
|
176774
176786
|
var execFileAsync = promisify(execFile);
|
|
176775
176787
|
var GIT_TIMEOUT_MS2 = 1e4;
|
|
176788
|
+
var defaultExecFileForVerificationPaths = async (file2, args, options) => await execFileAsync(file2, [...args], options);
|
|
176789
|
+
var execFileForVerificationPaths = defaultExecFileForVerificationPaths;
|
|
176776
176790
|
async function runGit(cwd, args) {
|
|
176777
176791
|
try {
|
|
176778
|
-
const result = await
|
|
176792
|
+
const result = await execFileForVerificationPaths("git", args, {
|
|
176779
176793
|
cwd,
|
|
176780
176794
|
timeout: GIT_TIMEOUT_MS2,
|
|
176781
176795
|
maxBuffer: 16 * 1024 * 1024,
|
|
@@ -184714,6 +184728,7 @@ function registerCtxDreamCommand(pi, deps) {
|
|
|
184714
184728
|
projectDir: deps.projectDir,
|
|
184715
184729
|
projectIdentity: deps.projectIdentity
|
|
184716
184730
|
};
|
|
184731
|
+
const dreamerEnabled = deps.resolveDreamerEnabled?.(ctx) ?? deps.dreamerEnabled;
|
|
184717
184732
|
deps.onProjectSeen?.(project.projectIdentity);
|
|
184718
184733
|
const requested = typeof args === "string" ? args.trim() : String(args ?? "").trim();
|
|
184719
184734
|
let task;
|
|
@@ -184733,7 +184748,7 @@ Unknown task "${requested}".`,
|
|
|
184733
184748
|
}
|
|
184734
184749
|
task = requested;
|
|
184735
184750
|
}
|
|
184736
|
-
if (
|
|
184751
|
+
if (dreamerEnabled === false) {
|
|
184737
184752
|
sendCtxStatusMessage(pi, {
|
|
184738
184753
|
title: "/ctx-dream",
|
|
184739
184754
|
text: "## /ctx-dream\n\nDreamer is disabled for this project (`dreamer.disable=true`).",
|
|
@@ -184848,6 +184863,8 @@ function formatEmbedStatusText(coverage, drain) {
|
|
|
184848
184863
|
}
|
|
184849
184864
|
|
|
184850
184865
|
// src/commands/ctx-embed.ts
|
|
184866
|
+
var EMBED_PROGRESS_COMPARTMENT_STEP = 8;
|
|
184867
|
+
var EMBED_PROGRESS_MIN_INTERVAL_MS = 1e4;
|
|
184851
184868
|
function clearPiEmbedSessionState(sessionId) {
|
|
184852
184869
|
embedPauseBySession.delete(sessionId);
|
|
184853
184870
|
const ctrl = embedRunStateBySession.get(sessionId);
|
|
@@ -184857,7 +184874,7 @@ function clearPiEmbedSessionState(sessionId) {
|
|
|
184857
184874
|
}
|
|
184858
184875
|
autoEmbedAttemptedBySession.delete(sessionId);
|
|
184859
184876
|
}
|
|
184860
|
-
async function runEmbedDrain(db, projectIdentity, sessionId) {
|
|
184877
|
+
async function runEmbedDrain(db, projectIdentity, sessionId, options = {}) {
|
|
184861
184878
|
const activeCtrl = embedRunStateBySession.get(sessionId);
|
|
184862
184879
|
if (activeCtrl && !activeCtrl.signal.aborted) {
|
|
184863
184880
|
return {
|
|
@@ -184873,10 +184890,46 @@ Embedding is already running for this session.`,
|
|
|
184873
184890
|
prior.abort();
|
|
184874
184891
|
const controller = new AbortController;
|
|
184875
184892
|
embedRunStateBySession.set(sessionId, controller);
|
|
184893
|
+
const now = options.now ?? Date.now;
|
|
184894
|
+
let startEmitted = false;
|
|
184895
|
+
let lastProgressEmbedded = 0;
|
|
184896
|
+
let lastProgressAt = 0;
|
|
184897
|
+
const emitProgress = (progress) => {
|
|
184898
|
+
if (progress.total <= 0)
|
|
184899
|
+
return;
|
|
184900
|
+
if (!startEmitted) {
|
|
184901
|
+
startEmitted = true;
|
|
184902
|
+
lastProgressAt = now();
|
|
184903
|
+
options.onStatus?.({
|
|
184904
|
+
text: `## /ctx-embed
|
|
184905
|
+
|
|
184906
|
+
Embedding ${progress.total} compartment${progress.total === 1 ? "" : "s"} of history…`,
|
|
184907
|
+
level: "info"
|
|
184908
|
+
});
|
|
184909
|
+
return;
|
|
184910
|
+
}
|
|
184911
|
+
if (progress.embedded <= 0 || progress.embedded >= progress.total)
|
|
184912
|
+
return;
|
|
184913
|
+
const currentTime = now();
|
|
184914
|
+
const enoughCompartments = progress.embedded - lastProgressEmbedded >= EMBED_PROGRESS_COMPARTMENT_STEP;
|
|
184915
|
+
const enoughTime = currentTime - lastProgressAt >= EMBED_PROGRESS_MIN_INTERVAL_MS && progress.embedded > lastProgressEmbedded;
|
|
184916
|
+
if (!enoughCompartments && !enoughTime)
|
|
184917
|
+
return;
|
|
184918
|
+
lastProgressEmbedded = progress.embedded;
|
|
184919
|
+
lastProgressAt = currentTime;
|
|
184920
|
+
options.onStatus?.({
|
|
184921
|
+
text: `## /ctx-embed
|
|
184922
|
+
|
|
184923
|
+
Embedded ${progress.embedded}/${progress.total} compartments so far…`,
|
|
184924
|
+
level: "info"
|
|
184925
|
+
});
|
|
184926
|
+
};
|
|
184876
184927
|
let outcome;
|
|
184877
184928
|
try {
|
|
184878
184929
|
outcome = await embedSessionCompartmentChunks(db, projectIdentity, sessionId, {
|
|
184879
|
-
signal: controller.signal
|
|
184930
|
+
signal: controller.signal,
|
|
184931
|
+
onProgress: emitProgress,
|
|
184932
|
+
...options.batchSize !== undefined ? { batchSize: options.batchSize } : {}
|
|
184880
184933
|
});
|
|
184881
184934
|
} finally {
|
|
184882
184935
|
if (embedRunStateBySession.get(sessionId) === controller) {
|
|
@@ -184949,6 +185002,7 @@ No active Pi session is available.`,
|
|
|
184949
185002
|
projectDir: deps.projectDir,
|
|
184950
185003
|
projectIdentity: deps.projectIdentity
|
|
184951
185004
|
};
|
|
185005
|
+
const memoryEnabled = deps.resolveMemoryEnabled?.(ctx) ?? deps.memoryEnabled;
|
|
184952
185006
|
const sub = args.trim().toLowerCase();
|
|
184953
185007
|
if (sub === "pause") {
|
|
184954
185008
|
embedPauseBySession.add(sessionId);
|
|
@@ -184965,7 +185019,7 @@ Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`,
|
|
|
184965
185019
|
});
|
|
184966
185020
|
return;
|
|
184967
185021
|
}
|
|
184968
|
-
if (
|
|
185022
|
+
if (memoryEnabled === false) {
|
|
184969
185023
|
sendCtxStatusMessage(pi, {
|
|
184970
185024
|
title: "/ctx-embed",
|
|
184971
185025
|
text: `## /ctx-embed
|
|
@@ -184977,7 +185031,12 @@ Memory is disabled for this project, so there is no semantic embedding to backfi
|
|
|
184977
185031
|
}
|
|
184978
185032
|
await ensureProjectRegisteredFromPiDirectory(project.projectDir, deps.db);
|
|
184979
185033
|
if (sub === "start") {
|
|
184980
|
-
const { text, level } = await runEmbedDrain(deps.db, project.projectIdentity, sessionId
|
|
185034
|
+
const { text, level } = await runEmbedDrain(deps.db, project.projectIdentity, sessionId, {
|
|
185035
|
+
onStatus: (status) => sendCtxStatusMessage(pi, {
|
|
185036
|
+
title: "/ctx-embed",
|
|
185037
|
+
...status
|
|
185038
|
+
})
|
|
185039
|
+
});
|
|
184981
185040
|
sendCtxStatusMessage(pi, { title: "/ctx-embed", text, level });
|
|
184982
185041
|
return;
|
|
184983
185042
|
}
|
|
@@ -188010,6 +188069,11 @@ function renderMemoryBlockV2(memories, wrapper = "project-memory", renderOptions
|
|
|
188010
188069
|
`);
|
|
188011
188070
|
}
|
|
188012
188071
|
|
|
188072
|
+
// ../plugin/src/hooks/magic-context/sentinel.ts
|
|
188073
|
+
function modelAcceptsEmptyContent(providerID) {
|
|
188074
|
+
return providerID === "anthropic";
|
|
188075
|
+
}
|
|
188076
|
+
|
|
188013
188077
|
// ../plugin/src/hooks/magic-context/supersession-reclaim.ts
|
|
188014
188078
|
var TODOWRITE_KEEP = 1;
|
|
188015
188079
|
var CTX_REDUCE_KEEP = 5;
|
|
@@ -190510,8 +190574,8 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config2, pr
|
|
|
190510
190574
|
sessionLog(sessionId, `emergency tiered drop skipped: ${plan.reason}`);
|
|
190511
190575
|
}
|
|
190512
190576
|
}
|
|
190513
|
-
const staleReduce = collectStaleReduceCallIds(piMessages, buildMessageIdToMaxTagFromTargets(targets), toolAgeCutoff, resolveStableId);
|
|
190514
|
-
if (staleReduce.composite.size > 0 || staleReduce.bareCallIds.size > 0) {
|
|
190577
|
+
const staleReduce = config2.staleReduceStripEnabled ? collectStaleReduceCallIds(piMessages, buildMessageIdToMaxTagFromTargets(targets), toolAgeCutoff, resolveStableId) : { composite: new Set, bareCallIds: new Set };
|
|
190578
|
+
if (config2.staleReduceStripEnabled && (staleReduce.composite.size > 0 || staleReduce.bareCallIds.size > 0)) {
|
|
190515
190579
|
db.transaction(() => {
|
|
190516
190580
|
for (const tag of tags) {
|
|
190517
190581
|
if (tag.status !== "active")
|
|
@@ -194792,8 +194856,122 @@ function buildReferenceBlocks(args) {
|
|
|
194792
194856
|
init_logger();
|
|
194793
194857
|
var HISTORIAN_AGENT_NAME = "magic-context-historian";
|
|
194794
194858
|
var DEFAULT_HISTORIAN_TIMEOUT_MS2 = 120000;
|
|
194859
|
+
var MAX_HISTORIAN_RETRIES = 2;
|
|
194795
194860
|
var HISTORIAN_ALERT_COOLDOWN_MS = 60 * 1000;
|
|
194796
194861
|
var lastHistorianAlertBySession = new Map;
|
|
194862
|
+
function getHistorianRetryBackoffMs(retryIndex) {
|
|
194863
|
+
if (retryIndex === 0) {
|
|
194864
|
+
return 2000 + Math.floor(Math.random() * 1001);
|
|
194865
|
+
}
|
|
194866
|
+
return 6000 + Math.floor(Math.random() * 2001);
|
|
194867
|
+
}
|
|
194868
|
+
function isTransientHistorianPromptError(message) {
|
|
194869
|
+
const normalized = message.toLowerCase();
|
|
194870
|
+
if (normalized.includes("invalid request") || normalized.includes("bad request") || normalized.includes("unauthorized") || normalized.includes("forbidden") || normalized.includes("authentication") || normalized.includes("auth") || normalized.includes(" 400") || normalized.startsWith("400")) {
|
|
194871
|
+
return false;
|
|
194872
|
+
}
|
|
194873
|
+
return [
|
|
194874
|
+
"429",
|
|
194875
|
+
"rate limit",
|
|
194876
|
+
"timeout",
|
|
194877
|
+
"econnreset",
|
|
194878
|
+
"etimedout",
|
|
194879
|
+
"503",
|
|
194880
|
+
"502",
|
|
194881
|
+
"500",
|
|
194882
|
+
"overloaded"
|
|
194883
|
+
].some((token) => normalized.includes(token));
|
|
194884
|
+
}
|
|
194885
|
+
function isTransientHistorianRunFailure(result) {
|
|
194886
|
+
if (result.reason === "abort")
|
|
194887
|
+
return false;
|
|
194888
|
+
if (result.reason === "timeout")
|
|
194889
|
+
return true;
|
|
194890
|
+
return isTransientHistorianPromptError(result.error);
|
|
194891
|
+
}
|
|
194892
|
+
function historianAbortResult(startedAt) {
|
|
194893
|
+
return {
|
|
194894
|
+
ok: false,
|
|
194895
|
+
reason: "abort",
|
|
194896
|
+
error: "pi subagent aborted by caller",
|
|
194897
|
+
durationMs: Date.now() - startedAt
|
|
194898
|
+
};
|
|
194899
|
+
}
|
|
194900
|
+
async function sleepWithAbort(ms, signal) {
|
|
194901
|
+
if (signal?.aborted)
|
|
194902
|
+
return true;
|
|
194903
|
+
if (ms <= 0)
|
|
194904
|
+
return signal?.aborted === true;
|
|
194905
|
+
return new Promise((resolve3) => {
|
|
194906
|
+
let settled = false;
|
|
194907
|
+
let timeout;
|
|
194908
|
+
const finish = (aborted2) => {
|
|
194909
|
+
if (settled)
|
|
194910
|
+
return;
|
|
194911
|
+
settled = true;
|
|
194912
|
+
if (timeout)
|
|
194913
|
+
clearTimeout(timeout);
|
|
194914
|
+
signal?.removeEventListener("abort", onAbort);
|
|
194915
|
+
resolve3(aborted2);
|
|
194916
|
+
};
|
|
194917
|
+
const onAbort = () => finish(true);
|
|
194918
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
194919
|
+
timeout = setTimeout(() => finish(false), ms);
|
|
194920
|
+
});
|
|
194921
|
+
}
|
|
194922
|
+
async function runHistorianSubagentWithTransientRetries(args) {
|
|
194923
|
+
const startedAt = Date.now();
|
|
194924
|
+
if (args.options.signal?.aborted)
|
|
194925
|
+
return historianAbortResult(startedAt);
|
|
194926
|
+
for (let retryIndex = 0;retryIndex <= MAX_HISTORIAN_RETRIES; retryIndex += 1) {
|
|
194927
|
+
const attemptStart = Date.now();
|
|
194928
|
+
let result;
|
|
194929
|
+
try {
|
|
194930
|
+
result = await args.runner.run({
|
|
194931
|
+
...args.options,
|
|
194932
|
+
fallbackModels: undefined
|
|
194933
|
+
});
|
|
194934
|
+
} catch (error51) {
|
|
194935
|
+
const desc = describeError(error51);
|
|
194936
|
+
result = {
|
|
194937
|
+
ok: false,
|
|
194938
|
+
reason: "model_failed",
|
|
194939
|
+
error: desc.brief,
|
|
194940
|
+
durationMs: Date.now() - attemptStart
|
|
194941
|
+
};
|
|
194942
|
+
}
|
|
194943
|
+
if (result.ok)
|
|
194944
|
+
return result;
|
|
194945
|
+
if (result.reason === "abort" || args.options.signal?.aborted) {
|
|
194946
|
+
return result.reason === "abort" ? result : historianAbortResult(startedAt);
|
|
194947
|
+
}
|
|
194948
|
+
const shouldRetry = retryIndex < MAX_HISTORIAN_RETRIES && isTransientHistorianRunFailure(result);
|
|
194949
|
+
if (!shouldRetry)
|
|
194950
|
+
return result;
|
|
194951
|
+
const backoffMs2 = args.retryBackoffMs?.(retryIndex) ?? getHistorianRetryBackoffMs(retryIndex);
|
|
194952
|
+
sessionLog(args.sessionId, `historian[${args.passLabel}] transient failure; retry ${retryIndex + 1}/${MAX_HISTORIAN_RETRIES} on same model after ${backoffMs2}ms: ${result.error}`);
|
|
194953
|
+
const aborted2 = await sleepWithAbort(backoffMs2, args.options.signal);
|
|
194954
|
+
if (aborted2)
|
|
194955
|
+
return historianAbortResult(startedAt);
|
|
194956
|
+
}
|
|
194957
|
+
return historianAbortResult(startedAt);
|
|
194958
|
+
}
|
|
194959
|
+
function buildHistorianFallbackChain(primaryModel, fallbackModels, fallbackModelId) {
|
|
194960
|
+
const seen = new Set;
|
|
194961
|
+
if (primaryModel)
|
|
194962
|
+
seen.add(primaryModel);
|
|
194963
|
+
const chain = [];
|
|
194964
|
+
for (const candidate of fallbackModels ?? []) {
|
|
194965
|
+
if (!candidate || seen.has(candidate))
|
|
194966
|
+
continue;
|
|
194967
|
+
seen.add(candidate);
|
|
194968
|
+
chain.push({ modelId: candidate, kind: "configured" });
|
|
194969
|
+
}
|
|
194970
|
+
if (fallbackModelId && !seen.has(fallbackModelId)) {
|
|
194971
|
+
chain.push({ modelId: fallbackModelId, kind: "session" });
|
|
194972
|
+
}
|
|
194973
|
+
return chain;
|
|
194974
|
+
}
|
|
194797
194975
|
function parseSourceMessageTime(value) {
|
|
194798
194976
|
if (typeof value === "number" && Number.isFinite(value))
|
|
194799
194977
|
return value;
|
|
@@ -194842,11 +195020,14 @@ async function runPiHistorian(deps) {
|
|
|
194842
195020
|
runner,
|
|
194843
195021
|
historianModel,
|
|
194844
195022
|
fallbackModels,
|
|
195023
|
+
fallbackModelId,
|
|
194845
195024
|
historianChunkTokens,
|
|
194846
195025
|
boundarySnapshot: providedBoundarySnapshot,
|
|
194847
195026
|
refreshBoundarySnapshot,
|
|
194848
195027
|
currentContextLimit,
|
|
194849
195028
|
historianTimeoutMs = DEFAULT_HISTORIAN_TIMEOUT_MS2,
|
|
195029
|
+
signal,
|
|
195030
|
+
retryBackoffMs,
|
|
194850
195031
|
twoPass,
|
|
194851
195032
|
thinkingLevel,
|
|
194852
195033
|
memoryEnabled,
|
|
@@ -194860,7 +195041,9 @@ async function runPiHistorian(deps) {
|
|
|
194860
195041
|
forceDrainQuota,
|
|
194861
195042
|
forceKeepLastCompartment
|
|
194862
195043
|
} = deps;
|
|
195044
|
+
let issueNotified = false;
|
|
194863
195045
|
const notify = async (message) => {
|
|
195046
|
+
issueNotified = true;
|
|
194864
195047
|
if (shouldSuppressHistorianAlert(sessionId)) {
|
|
194865
195048
|
sessionLog(sessionId, "historian alert suppressed (cooldown)");
|
|
194866
195049
|
return;
|
|
@@ -195051,61 +195234,77 @@ ${chunkText}`,
|
|
|
195051
195234
|
retainDrainReservationForRetryThrottle = true;
|
|
195052
195235
|
const historianSystemPrompt = withContentLanguageDirective(COMPARTMENT_AGENT_SYSTEM_PROMPT, deps.language, { preserveUserQuotes: true });
|
|
195053
195236
|
const historianEditorSystemPrompt = withContentLanguageDirective(HISTORIAN_EDITOR_SYSTEM_PROMPT, deps.language, { preserveUserQuotes: true });
|
|
195054
|
-
const firstResult = await
|
|
195055
|
-
|
|
195056
|
-
|
|
195057
|
-
|
|
195058
|
-
|
|
195059
|
-
|
|
195060
|
-
timeoutMs: historianTimeoutMs,
|
|
195061
|
-
cwd: directory,
|
|
195062
|
-
thinkingLevel,
|
|
195063
|
-
onProgress: buildProgressLogger("first"),
|
|
195064
|
-
accountingSessionId: sessionId,
|
|
195065
|
-
accountingSubagent: "historian"
|
|
195066
|
-
});
|
|
195067
|
-
let validatedPass = await validateHistorianResult(firstResult, sessionId, chunk, priorCompartments, sequenceOffset);
|
|
195068
|
-
let validatedDraftText = firstResult.ok ? firstResult.assistantText : null;
|
|
195069
|
-
if (validatedPass.kind === "validation-failed") {
|
|
195070
|
-
sessionLog(sessionId, `historian: first pass validation failed, retrying with repair prompt: ${validatedPass.error}`);
|
|
195071
|
-
const repairPrompt = buildHistorianRepairPrompt(prompt, validatedPass.rawText, validatedPass.error, deps.language);
|
|
195072
|
-
const repairResult = await runner.run({
|
|
195237
|
+
const firstResult = await runHistorianSubagentWithTransientRetries({
|
|
195238
|
+
runner,
|
|
195239
|
+
sessionId,
|
|
195240
|
+
passLabel: "first",
|
|
195241
|
+
retryBackoffMs,
|
|
195242
|
+
options: {
|
|
195073
195243
|
agent: HISTORIAN_AGENT_NAME,
|
|
195074
195244
|
systemPrompt: historianSystemPrompt,
|
|
195075
|
-
userMessage:
|
|
195245
|
+
userMessage: prompt,
|
|
195076
195246
|
model: historianModel,
|
|
195077
|
-
fallbackModels,
|
|
195078
195247
|
timeoutMs: historianTimeoutMs,
|
|
195079
195248
|
cwd: directory,
|
|
195249
|
+
signal,
|
|
195080
195250
|
thinkingLevel,
|
|
195081
|
-
onProgress: buildProgressLogger("
|
|
195251
|
+
onProgress: buildProgressLogger("first"),
|
|
195082
195252
|
accountingSessionId: sessionId,
|
|
195083
195253
|
accountingSubagent: "historian"
|
|
195084
|
-
});
|
|
195085
|
-
validatedPass = await validateHistorianResult(repairResult, sessionId, chunk, priorCompartments, sequenceOffset);
|
|
195086
|
-
if (validatedPass.kind === "ok" && repairResult.ok) {
|
|
195087
|
-
validatedDraftText = repairResult.assistantText;
|
|
195088
195254
|
}
|
|
195089
|
-
}
|
|
195090
|
-
|
|
195091
|
-
|
|
195092
|
-
|
|
195093
|
-
|
|
195094
|
-
|
|
195095
|
-
|
|
195096
|
-
|
|
195097
|
-
|
|
195255
|
+
});
|
|
195256
|
+
let validatedPass = await validateHistorianResult(firstResult, sessionId, chunk, priorCompartments, sequenceOffset);
|
|
195257
|
+
let validatedDraftText = firstResult.ok ? firstResult.assistantText : null;
|
|
195258
|
+
if (validatedPass.kind === "validation-failed") {
|
|
195259
|
+
sessionLog(sessionId, `historian: first pass validation failed, retrying with repair prompt: ${validatedPass.error}`);
|
|
195260
|
+
const repairPrompt = buildHistorianRepairPrompt(prompt, validatedPass.rawText, validatedPass.error, deps.language);
|
|
195261
|
+
const repairResult = await runHistorianSubagentWithTransientRetries({
|
|
195262
|
+
runner,
|
|
195263
|
+
sessionId,
|
|
195264
|
+
passLabel: "repair",
|
|
195265
|
+
retryBackoffMs,
|
|
195266
|
+
options: {
|
|
195098
195267
|
agent: HISTORIAN_AGENT_NAME,
|
|
195099
195268
|
systemPrompt: historianSystemPrompt,
|
|
195100
|
-
userMessage:
|
|
195101
|
-
model:
|
|
195102
|
-
fallbackModels: undefined,
|
|
195269
|
+
userMessage: repairPrompt,
|
|
195270
|
+
model: historianModel,
|
|
195103
195271
|
timeoutMs: historianTimeoutMs,
|
|
195104
195272
|
cwd: directory,
|
|
195273
|
+
signal,
|
|
195105
195274
|
thinkingLevel,
|
|
195106
|
-
onProgress: buildProgressLogger("
|
|
195275
|
+
onProgress: buildProgressLogger("repair"),
|
|
195107
195276
|
accountingSessionId: sessionId,
|
|
195108
195277
|
accountingSubagent: "historian"
|
|
195278
|
+
}
|
|
195279
|
+
});
|
|
195280
|
+
validatedPass = await validateHistorianResult(repairResult, sessionId, chunk, priorCompartments, sequenceOffset);
|
|
195281
|
+
if (validatedPass.kind === "ok" && repairResult.ok) {
|
|
195282
|
+
validatedDraftText = repairResult.assistantText;
|
|
195283
|
+
}
|
|
195284
|
+
}
|
|
195285
|
+
const fallbackChain = buildHistorianFallbackChain(historianModel, fallbackModels, fallbackModelId);
|
|
195286
|
+
if (validatedPass.kind !== "ok" && !(validatedPass.kind === "spawn-failed" && validatedPass.reason === "abort") && fallbackChain.length > 0) {
|
|
195287
|
+
for (let i = 0;i < fallbackChain.length; i += 1) {
|
|
195288
|
+
const candidate = fallbackChain[i];
|
|
195289
|
+
sessionLog(sessionId, `historian: escalating to ${candidate.kind === "session" ? "session-model last resort" : "configured fallback model"} ${candidate.modelId}`);
|
|
195290
|
+
const fbResult = await runHistorianSubagentWithTransientRetries({
|
|
195291
|
+
runner,
|
|
195292
|
+
sessionId,
|
|
195293
|
+
passLabel: candidate.kind === "session" ? "fallback-session" : "fallback",
|
|
195294
|
+
retryBackoffMs,
|
|
195295
|
+
options: {
|
|
195296
|
+
agent: HISTORIAN_AGENT_NAME,
|
|
195297
|
+
systemPrompt: historianSystemPrompt,
|
|
195298
|
+
userMessage: prompt,
|
|
195299
|
+
model: candidate.modelId,
|
|
195300
|
+
timeoutMs: historianTimeoutMs,
|
|
195301
|
+
cwd: directory,
|
|
195302
|
+
signal,
|
|
195303
|
+
thinkingLevel,
|
|
195304
|
+
onProgress: buildProgressLogger("fallback"),
|
|
195305
|
+
accountingSessionId: sessionId,
|
|
195306
|
+
accountingSubagent: "historian"
|
|
195307
|
+
}
|
|
195109
195308
|
});
|
|
195110
195309
|
const fbPass = await validateHistorianResult(fbResult, sessionId, chunk, priorCompartments, sequenceOffset);
|
|
195111
195310
|
if (fbPass.kind === "ok") {
|
|
@@ -195114,6 +195313,10 @@ ${chunkText}`,
|
|
|
195114
195313
|
validatedDraftText = fbResult.assistantText;
|
|
195115
195314
|
break;
|
|
195116
195315
|
}
|
|
195316
|
+
if (fbPass.kind === "spawn-failed" && fbPass.reason === "abort") {
|
|
195317
|
+
validatedPass = fbPass;
|
|
195318
|
+
break;
|
|
195319
|
+
}
|
|
195117
195320
|
}
|
|
195118
195321
|
}
|
|
195119
195322
|
if (validatedPass.kind !== "ok") {
|
|
@@ -195130,17 +195333,24 @@ ${chunkText}`,
|
|
|
195130
195333
|
const draftAssistantText = validatedDraftText ?? "";
|
|
195131
195334
|
if (draftAssistantText.trim().length > 0) {
|
|
195132
195335
|
sessionLog(sessionId, "historian two-pass: running editor on draft");
|
|
195133
|
-
const editorResult = await
|
|
195134
|
-
|
|
195135
|
-
|
|
195136
|
-
|
|
195137
|
-
|
|
195138
|
-
|
|
195139
|
-
|
|
195140
|
-
|
|
195141
|
-
|
|
195142
|
-
|
|
195143
|
-
|
|
195336
|
+
const editorResult = await runHistorianSubagentWithTransientRetries({
|
|
195337
|
+
runner,
|
|
195338
|
+
sessionId,
|
|
195339
|
+
passLabel: "editor",
|
|
195340
|
+
retryBackoffMs,
|
|
195341
|
+
options: {
|
|
195342
|
+
agent: HISTORIAN_AGENT_NAME,
|
|
195343
|
+
systemPrompt: historianEditorSystemPrompt,
|
|
195344
|
+
userMessage: buildHistorianEditorPrompt(draftAssistantText),
|
|
195345
|
+
model: historianModel,
|
|
195346
|
+
timeoutMs: historianTimeoutMs,
|
|
195347
|
+
cwd: directory,
|
|
195348
|
+
signal,
|
|
195349
|
+
thinkingLevel,
|
|
195350
|
+
onProgress: buildProgressLogger("editor"),
|
|
195351
|
+
accountingSessionId: sessionId,
|
|
195352
|
+
accountingSubagent: "historian_editor"
|
|
195353
|
+
}
|
|
195144
195354
|
});
|
|
195145
195355
|
const editorPass = await validateHistorianResult(editorResult, sessionId, chunk, priorCompartments, sequenceOffset);
|
|
195146
195356
|
if (editorPass.kind === "ok") {
|
|
@@ -195353,7 +195563,7 @@ ${chunkText}`,
|
|
|
195353
195563
|
const desc = describeError(error51);
|
|
195354
195564
|
telemetry.failureReason = `exception: ${desc.brief}`;
|
|
195355
195565
|
sessionLog(sessionId, `historian failure: source=exception ${desc.brief}${desc.stackHead ? ` stackHead="${desc.stackHead}"` : ""}`);
|
|
195356
|
-
{
|
|
195566
|
+
if (!issueNotified) {
|
|
195357
195567
|
const failCount = incrementHistorianFailure(db, sessionId, desc.brief);
|
|
195358
195568
|
await notify(buildHistorianFailureNotice(failCount, desc.brief));
|
|
195359
195569
|
}
|
|
@@ -197302,6 +197512,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
197302
197512
|
}
|
|
197303
197513
|
const sessionMeta = sessionMetaForUsage;
|
|
197304
197514
|
const modelKey = liveModelBySession.get(sessionId);
|
|
197515
|
+
const providerId = typeof ctx.model?.provider === "string" ? ctx.model.provider : undefined;
|
|
197516
|
+
const canUseEmptySentinels = modelAcceptsEmptyContent(providerId);
|
|
197305
197517
|
if (usageContextLimit === undefined) {
|
|
197306
197518
|
const modelWindow = ctx.model?.contextWindow;
|
|
197307
197519
|
if (isSaneLimit(modelWindow)) {
|
|
@@ -197312,6 +197524,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
197312
197524
|
usagePercentage = usageInputTokens / usageContextLimit * 100;
|
|
197313
197525
|
}
|
|
197314
197526
|
({ percentage: usagePercentage, inputTokens: usageInputTokens } = applyForwardPressureFloor(usagePercentage, usageInputTokens, piUsage?.tokens, usageContextLimit));
|
|
197527
|
+
const realUsagePercentageBeforeEmergencyBump = usagePercentage;
|
|
197315
197528
|
if (needsEmergencyBump) {
|
|
197316
197529
|
sessionLog(sessionId, `transform: overflow recovery flag set — bumping percentage to 95% (detectedLimit=${usageContextLimit ?? "unknown"})`);
|
|
197317
197530
|
usagePercentage = Math.max(usagePercentage, 95);
|
|
@@ -197382,7 +197595,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
197382
197595
|
sessionLog(sessionId, "EMERGENCY: historian wait completed (or timed out)");
|
|
197383
197596
|
} catch {}
|
|
197384
197597
|
}
|
|
197385
|
-
if (emergencyRecoveryArmed && !inFlightHistorian.has(sessionId) && !hasEligiblePiCompartmentHistory(options.db, sessionId)) {
|
|
197598
|
+
if (emergencyRecoveryArmed && realUsagePercentageBeforeEmergencyBump < FORCE_MATERIALIZATION_PERCENTAGE && !inFlightHistorian.has(sessionId) && !hasEligiblePiCompartmentHistory(options.db, sessionId)) {
|
|
197386
197599
|
try {
|
|
197387
197600
|
clearEmergencyRecovery(options.db, sessionId);
|
|
197388
197601
|
sessionLog(sessionId, "EMERGENCY: disarming recovery — no eligible pre-tail history to compact (would otherwise loop at 95%)");
|
|
@@ -197437,6 +197650,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
197437
197650
|
reasoningClearing: {
|
|
197438
197651
|
clearReasoningAge: options.heuristics?.clearReasoningAge ?? DEFAULT_CLEAR_REASONING_AGE
|
|
197439
197652
|
},
|
|
197653
|
+
canUseEmptySentinels,
|
|
197440
197654
|
temporalAwareness: options.injection?.temporalAwareness === true,
|
|
197441
197655
|
appendCompaction: resolvePiAppendCompaction(ctx),
|
|
197442
197656
|
readBranchEntries: resolvePiReadBranchEntries(ctx),
|
|
@@ -197458,6 +197672,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
197458
197672
|
}
|
|
197459
197673
|
if (options.historian) {
|
|
197460
197674
|
maybeFireHistorian({
|
|
197675
|
+
pi,
|
|
197461
197676
|
ctx,
|
|
197462
197677
|
sessionId,
|
|
197463
197678
|
db: options.db,
|
|
@@ -197698,6 +197913,7 @@ function sendPiIgnoredNotification(ctx, message) {
|
|
|
197698
197913
|
}
|
|
197699
197914
|
function spawnPiHistorianRun(args) {
|
|
197700
197915
|
const {
|
|
197916
|
+
pi,
|
|
197701
197917
|
ctx,
|
|
197702
197918
|
sessionId,
|
|
197703
197919
|
db,
|
|
@@ -197706,7 +197922,8 @@ function spawnPiHistorianRun(args) {
|
|
|
197706
197922
|
unregister,
|
|
197707
197923
|
boundarySnapshot,
|
|
197708
197924
|
refreshBoundarySnapshot,
|
|
197709
|
-
currentContextLimit
|
|
197925
|
+
currentContextLimit,
|
|
197926
|
+
fallbackModelId
|
|
197710
197927
|
} = args;
|
|
197711
197928
|
const holderId = crypto3.randomUUID();
|
|
197712
197929
|
const runPromise = (async () => {
|
|
@@ -197732,6 +197949,7 @@ function spawnPiHistorianRun(args) {
|
|
|
197732
197949
|
runner: historian.runner,
|
|
197733
197950
|
historianModel: historian.model,
|
|
197734
197951
|
fallbackModels: historian.fallbackModels,
|
|
197952
|
+
fallbackModelId,
|
|
197735
197953
|
historianChunkTokens: historian.historianChunkTokens,
|
|
197736
197954
|
boundarySnapshot,
|
|
197737
197955
|
refreshBoundarySnapshot,
|
|
@@ -197744,6 +197962,17 @@ function spawnPiHistorianRun(args) {
|
|
|
197744
197962
|
userMemoriesEnabled: historian.userMemoriesEnabled,
|
|
197745
197963
|
language: historian.language,
|
|
197746
197964
|
compartmentLeaseHolderId: holderId,
|
|
197965
|
+
notifyIssue: (text) => {
|
|
197966
|
+
if (!isContextHandlerSessionActive(sessionId)) {
|
|
197967
|
+
sessionLog(sessionId, "historian failure notice skipped after session context cleared");
|
|
197968
|
+
return;
|
|
197969
|
+
}
|
|
197970
|
+
sendCtxStatusMessage(pi, {
|
|
197971
|
+
title: "Magic Context",
|
|
197972
|
+
text,
|
|
197973
|
+
level: "warning"
|
|
197974
|
+
});
|
|
197975
|
+
},
|
|
197747
197976
|
onPublished: () => {
|
|
197748
197977
|
const sessionStillActive = isContextHandlerSessionActive(sessionId);
|
|
197749
197978
|
try {
|
|
@@ -197893,6 +198122,7 @@ function maybeFireHistorian(args) {
|
|
|
197893
198122
|
|
|
197894
198123
|
Historian previously failed ${failureState.failureCount} time(s), so Magic Context is retrying history comparting immediately after restart.`);
|
|
197895
198124
|
spawnPiHistorianRun({
|
|
198125
|
+
pi: args.pi,
|
|
197896
198126
|
ctx,
|
|
197897
198127
|
sessionId,
|
|
197898
198128
|
db,
|
|
@@ -197901,7 +198131,8 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
197901
198131
|
unregister,
|
|
197902
198132
|
boundarySnapshot,
|
|
197903
198133
|
refreshBoundarySnapshot: resolveRunnablePiBoundarySnapshot,
|
|
197904
|
-
currentContextLimit: boundaryContextLimit
|
|
198134
|
+
currentContextLimit: boundaryContextLimit,
|
|
198135
|
+
fallbackModelId: modelKey
|
|
197905
198136
|
});
|
|
197906
198137
|
return;
|
|
197907
198138
|
}
|
|
@@ -197923,6 +198154,7 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
197923
198154
|
triggered = true;
|
|
197924
198155
|
sessionLog(sessionId, `historian trigger fired (reason=${trigger.reason ?? "unknown"}) usage=${usage.percentage.toFixed(1)}% — spawning subagent`);
|
|
197925
198156
|
spawnPiHistorianRun({
|
|
198157
|
+
pi: args.pi,
|
|
197926
198158
|
ctx,
|
|
197927
198159
|
sessionId,
|
|
197928
198160
|
db,
|
|
@@ -197934,7 +198166,8 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
197934
198166
|
triggerBoundarySnapshot: trigger.boundarySnapshot
|
|
197935
198167
|
}),
|
|
197936
198168
|
refreshBoundarySnapshot: resolveRunnablePiBoundarySnapshot,
|
|
197937
|
-
currentContextLimit: boundaryContextLimit
|
|
198169
|
+
currentContextLimit: boundaryContextLimit,
|
|
198170
|
+
fallbackModelId: modelKey
|
|
197938
198171
|
});
|
|
197939
198172
|
} catch (err) {
|
|
197940
198173
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -198014,7 +198247,10 @@ async function runPipeline(args) {
|
|
|
198014
198247
|
historyBudgetTokens: args.injection.historyBudgetTokens,
|
|
198015
198248
|
hardSignals: piHardSignals
|
|
198016
198249
|
}, args.db, getCompartments(args.db, args.sessionId)).value : false;
|
|
198017
|
-
const
|
|
198250
|
+
const historianRunning = inFlightHistorian.has(args.sessionId);
|
|
198251
|
+
const bypassHistorianGate = args.forceMaterialization === true || m0HardFoldThisPass;
|
|
198252
|
+
const hasPendingMaterializeSignal = hasPendingMaterialization(args.sessionId);
|
|
198253
|
+
const shouldRunHeuristics = args.heuristics !== undefined && (!historianRunning || bypassHistorianGate) && (args.forceMaterialization === true || hasPendingMaterializeSignal || deferredMaterializeEligible || m0HardFoldThisPass || args.schedulerDecision === "execute" && !alreadyRanHeuristicsThisTurn);
|
|
198018
198254
|
const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver);
|
|
198019
198255
|
adoptPiFallbackTags(args.db, args.sessionId, args.tagger, entryFingerprintByMessageId, {
|
|
198020
198256
|
messages: args.messages,
|
|
@@ -198048,14 +198284,13 @@ async function runPipeline(args) {
|
|
|
198048
198284
|
} catch (err) {
|
|
198049
198285
|
sessionLog(args.sessionId, `commit-detect failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
198050
198286
|
}
|
|
198051
|
-
const hasPendingMaterializeSignal = hasPendingMaterialization(args.sessionId);
|
|
198052
198287
|
const deferredMaterializationWasPending = deferredMaterializationSessions.has(args.sessionId);
|
|
198053
198288
|
const deferredHistoryRefreshWasPending = deferredHistoryWasPendingAtPassStart;
|
|
198054
198289
|
const pendingOps = getPendingOps(args.db, args.sessionId);
|
|
198055
198290
|
const baseShouldApplyPendingOps = args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || m0HardFoldThisPass;
|
|
198056
198291
|
const deferredMaterialize = canConsumeDeferredLate && deferredMaterializationWasPending;
|
|
198057
198292
|
const deferredHistoryRefresh = canConsumeDeferredLate && deferredHistoryRefreshWasPending;
|
|
198058
|
-
const shouldApplyPendingOps = baseShouldApplyPendingOps || deferredMaterialize;
|
|
198293
|
+
const shouldApplyPendingOps = (baseShouldApplyPendingOps || deferredMaterialize) && (!historianRunning || bypassHistorianGate);
|
|
198059
198294
|
if (shouldApplyPendingOps) {
|
|
198060
198295
|
const applyReason = hasPendingMaterializeSignal ? "explicit_flush" : deferredMaterialize ? "deferred_publication" : args.forceMaterialization ? "force_materialization" : m0HardFoldThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into known m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (scheduler=${args.schedulerDecision})`;
|
|
198061
198296
|
sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
|
|
@@ -198144,6 +198379,7 @@ async function runPipeline(args) {
|
|
|
198144
198379
|
const tHeuristic = performance.now();
|
|
198145
198380
|
heuristicsResult = applyPiHeuristicCleanup(args.sessionId, args.db, targets, args.messages, {
|
|
198146
198381
|
protectedTags: args.protectedTags,
|
|
198382
|
+
staleReduceStripEnabled: args.canUseEmptySentinels,
|
|
198147
198383
|
emergency: args.forceMaterialization === true && args.emergencyCeilingTokens !== undefined && args.emergencyCeilingTokens > 0 ? {
|
|
198148
198384
|
currentTotalInputTokens: args.contextUsage.inputTokens,
|
|
198149
198385
|
ceilingTokens: args.emergencyCeilingTokens
|
|
@@ -198729,7 +198965,7 @@ init_data_path();
|
|
|
198729
198965
|
function historianResponseDumpDir(directory) {
|
|
198730
198966
|
return getProjectMagicContextHistorianDir(directory);
|
|
198731
198967
|
}
|
|
198732
|
-
var
|
|
198968
|
+
var MAX_HISTORIAN_RETRIES2 = 2;
|
|
198733
198969
|
async function runValidatedHistorianPass(args) {
|
|
198734
198970
|
const firstRun = await runHistorianPrompt({
|
|
198735
198971
|
...args,
|
|
@@ -198870,7 +199106,7 @@ async function runHistorianPrompt(args) {
|
|
|
198870
199106
|
});
|
|
198871
199107
|
return { ok: false, error: "Historian could not create its child session." };
|
|
198872
199108
|
}
|
|
198873
|
-
for (let retryIndex = 0;retryIndex <=
|
|
199109
|
+
for (let retryIndex = 0;retryIndex <= MAX_HISTORIAN_RETRIES2; retryIndex += 1) {
|
|
198874
199110
|
try {
|
|
198875
199111
|
await promptSyncWithModelSuggestionRetry(client, {
|
|
198876
199112
|
path: { id: agentSessionId },
|
|
@@ -198885,17 +199121,17 @@ async function runHistorianPrompt(args) {
|
|
|
198885
199121
|
fallbackModels: modelOverride ? undefined : fallbackModels,
|
|
198886
199122
|
callContext: agentId === HISTORIAN_EDITOR_AGENT ? "historian:editor" : "historian"
|
|
198887
199123
|
});
|
|
198888
|
-
sessionLog(parentSessionId, `historian: prompt completed (attempt ${retryIndex + 1}/${
|
|
199124
|
+
sessionLog(parentSessionId, `historian: prompt completed (attempt ${retryIndex + 1}/${MAX_HISTORIAN_RETRIES2 + 1})`);
|
|
198889
199125
|
break;
|
|
198890
199126
|
} catch (error51) {
|
|
198891
199127
|
const errorMsg = getErrorMessage(error51);
|
|
198892
199128
|
sessionLog(parentSessionId, `historian: prompt attempt ${retryIndex + 1} failed: ${errorMsg}`);
|
|
198893
|
-
const shouldRetry = retryIndex <
|
|
199129
|
+
const shouldRetry = retryIndex < MAX_HISTORIAN_RETRIES2 && isTransientHistorianPromptError2(errorMsg);
|
|
198894
199130
|
if (!shouldRetry) {
|
|
198895
199131
|
throw error51;
|
|
198896
199132
|
}
|
|
198897
|
-
const backoffMs2 =
|
|
198898
|
-
sessionLog(parentSessionId, `historian retry ${retryIndex + 1}/${
|
|
199133
|
+
const backoffMs2 = getHistorianRetryBackoffMs2(retryIndex);
|
|
199134
|
+
sessionLog(parentSessionId, `historian retry ${retryIndex + 1}/${MAX_HISTORIAN_RETRIES2} after ${backoffMs2}ms: ${errorMsg}`);
|
|
198899
199135
|
await sleep(backoffMs2);
|
|
198900
199136
|
}
|
|
198901
199137
|
}
|
|
@@ -198988,13 +199224,13 @@ function parseModelOverride(modelId) {
|
|
|
198988
199224
|
}
|
|
198989
199225
|
return { providerID, modelID };
|
|
198990
199226
|
}
|
|
198991
|
-
function
|
|
199227
|
+
function getHistorianRetryBackoffMs2(retryIndex) {
|
|
198992
199228
|
if (retryIndex === 0) {
|
|
198993
199229
|
return 2000 + Math.floor(Math.random() * 1001);
|
|
198994
199230
|
}
|
|
198995
199231
|
return 6000 + Math.floor(Math.random() * 2001);
|
|
198996
199232
|
}
|
|
198997
|
-
function
|
|
199233
|
+
function isTransientHistorianPromptError2(message) {
|
|
198998
199234
|
const normalized = message.toLowerCase();
|
|
198999
199235
|
if (normalized.includes("invalid request") || normalized.includes("bad request") || normalized.includes("unauthorized") || normalized.includes("forbidden") || normalized.includes("authentication") || normalized.includes("auth") || normalized.includes(" 400") || normalized.startsWith("400")) {
|
|
199000
199236
|
return false;
|
|
@@ -200238,6 +200474,13 @@ function spawnPiRecompRun(args) {
|
|
|
200238
200474
|
// src/commands/ctx-recomp.ts
|
|
200239
200475
|
var confirmationBySession = new Map;
|
|
200240
200476
|
var RECOMP_CONFIRMATION_WINDOW_MS = 60000;
|
|
200477
|
+
var RECOMP_USAGE = [
|
|
200478
|
+
"Usage:",
|
|
200479
|
+
"- `/ctx-recomp` — full rebuild from message 1 to the protected tail",
|
|
200480
|
+
"- `/ctx-recomp <start>-<end>` — partial rebuild of a message range (e.g. `/ctx-recomp 1-11322`)",
|
|
200481
|
+
"- `/ctx-recomp --upgrade` — upgrade legacy v1 compartments to v2 layout (Wave 3 runner)"
|
|
200482
|
+
].join(`
|
|
200483
|
+
`);
|
|
200241
200484
|
function registerCtxRecompCommand(pi, deps) {
|
|
200242
200485
|
pi.registerCommand("ctx-recomp", {
|
|
200243
200486
|
description: "Rebuild Magic Context compartments from raw Pi session history",
|
|
@@ -200253,21 +200496,30 @@ No active Pi session is available.`,
|
|
|
200253
200496
|
});
|
|
200254
200497
|
return;
|
|
200255
200498
|
}
|
|
200256
|
-
|
|
200499
|
+
const currentDeps = deps.resolveRuntimeDeps?.(ctx) ?? deps;
|
|
200500
|
+
const parsed = parseRecompArgs(args);
|
|
200501
|
+
if (parsed.kind === "error") {
|
|
200257
200502
|
sendCtxStatusMessage(pi, {
|
|
200258
200503
|
title: "/ctx-recomp",
|
|
200259
|
-
text:
|
|
200504
|
+
text: `## Magic Recomp — Invalid Arguments
|
|
200505
|
+
|
|
200506
|
+
${parsed.message}`,
|
|
200260
200507
|
level: "error"
|
|
200261
200508
|
});
|
|
200262
200509
|
return;
|
|
200263
200510
|
}
|
|
200264
|
-
|
|
200265
|
-
if (parsed.kind === "error") {
|
|
200511
|
+
if (parsed.kind === "upgrade") {
|
|
200266
200512
|
sendCtxStatusMessage(pi, {
|
|
200267
200513
|
title: "/ctx-recomp",
|
|
200268
|
-
text:
|
|
200269
|
-
|
|
200270
|
-
|
|
200514
|
+
text: executeRecompUpgradeStub(currentDeps.db, sessionId),
|
|
200515
|
+
level: "info"
|
|
200516
|
+
});
|
|
200517
|
+
return;
|
|
200518
|
+
}
|
|
200519
|
+
if (!currentDeps.historianModel) {
|
|
200520
|
+
sendCtxStatusMessage(pi, {
|
|
200521
|
+
title: "/ctx-recomp",
|
|
200522
|
+
text: "## Magic Recomp\n\n/ctx-recomp is unavailable because `historian.model` is not configured.",
|
|
200271
200523
|
level: "error"
|
|
200272
200524
|
});
|
|
200273
200525
|
return;
|
|
@@ -200277,7 +200529,7 @@ ${parsed.message}`,
|
|
|
200277
200529
|
const confirmation = confirmationBySession.get(sessionId);
|
|
200278
200530
|
const confirmed = confirmation !== undefined && now - confirmation.timestamp < RECOMP_CONFIRMATION_WINDOW_MS && confirmation.argsKey === argsKey;
|
|
200279
200531
|
if (!confirmed) {
|
|
200280
|
-
const warning = buildConfirmationWarning(
|
|
200532
|
+
const warning = buildConfirmationWarning(currentDeps.db, sessionId, parsed);
|
|
200281
200533
|
if (!warning.confirmable)
|
|
200282
200534
|
confirmationBySession.delete(sessionId);
|
|
200283
200535
|
else
|
|
@@ -200289,7 +200541,7 @@ ${parsed.message}`,
|
|
|
200289
200541
|
});
|
|
200290
200542
|
return;
|
|
200291
200543
|
}
|
|
200292
|
-
if (isWrapupInProgress(
|
|
200544
|
+
if (isWrapupInProgress(currentDeps.db, sessionId)) {
|
|
200293
200545
|
sendCtxStatusMessage(pi, {
|
|
200294
200546
|
title: "/ctx-recomp",
|
|
200295
200547
|
text: "## Magic Recomp\n\n/ctx-wrapup is already compacting this session. Wait for it to finish, then try `/ctx-recomp` again.",
|
|
@@ -200323,16 +200575,19 @@ Historian recomp started. Rebuilding compartments and facts from raw Pi session
|
|
|
200323
200575
|
spawnPiRecompRun({
|
|
200324
200576
|
sessionId,
|
|
200325
200577
|
provider: provider2,
|
|
200326
|
-
onStatusChange: () => updateStatusLine(ctx, {
|
|
200578
|
+
onStatusChange: () => updateStatusLine(ctx, {
|
|
200579
|
+
db: currentDeps.db,
|
|
200580
|
+
projectIdentity: ctx.cwd
|
|
200581
|
+
}),
|
|
200327
200582
|
work: async () => {
|
|
200328
200583
|
const result = await executeContextRecompWithResult({
|
|
200329
200584
|
client: createPiHistorianClient({
|
|
200330
|
-
runner:
|
|
200331
|
-
model:
|
|
200332
|
-
systemPrompt: withContentLanguageDirective(COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT,
|
|
200333
|
-
fallbackModels:
|
|
200334
|
-
timeoutMs:
|
|
200335
|
-
thinkingLevel:
|
|
200585
|
+
runner: currentDeps.runner,
|
|
200586
|
+
model: currentDeps.historianModel,
|
|
200587
|
+
systemPrompt: withContentLanguageDirective(COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, currentDeps.language, { preserveUserQuotes: true }),
|
|
200588
|
+
fallbackModels: currentDeps.historianFallbacks,
|
|
200589
|
+
timeoutMs: currentDeps.historianTimeoutMs,
|
|
200590
|
+
thinkingLevel: currentDeps.historianThinkingLevel,
|
|
200336
200591
|
directory: ctx.cwd,
|
|
200337
200592
|
accountingSessionId: sessionId,
|
|
200338
200593
|
notify: (text) => {
|
|
@@ -200343,26 +200598,26 @@ Historian recomp started. Rebuilding compartments and facts from raw Pi session
|
|
|
200343
200598
|
});
|
|
200344
200599
|
}
|
|
200345
200600
|
}),
|
|
200346
|
-
db:
|
|
200601
|
+
db: currentDeps.db,
|
|
200347
200602
|
sessionId,
|
|
200348
|
-
historianChunkTokens:
|
|
200603
|
+
historianChunkTokens: currentDeps.historianChunkTokens,
|
|
200349
200604
|
directory: ctx.cwd,
|
|
200350
|
-
historianTimeoutMs:
|
|
200351
|
-
memoryEnabled:
|
|
200352
|
-
autoPromote:
|
|
200605
|
+
historianTimeoutMs: currentDeps.historianTimeoutMs,
|
|
200606
|
+
memoryEnabled: currentDeps.memoryEnabled,
|
|
200607
|
+
autoPromote: currentDeps.autoPromote,
|
|
200353
200608
|
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
200354
|
-
fallbackModels:
|
|
200355
|
-
language:
|
|
200609
|
+
fallbackModels: currentDeps.historianFallbacks,
|
|
200610
|
+
language: currentDeps.language,
|
|
200356
200611
|
fallbackModelId: ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined
|
|
200357
200612
|
}, parsed.kind === "partial" ? { range: parsed.range } : {});
|
|
200358
200613
|
if (result.published) {
|
|
200359
200614
|
try {
|
|
200360
|
-
clearEmergencyRecovery(
|
|
200615
|
+
clearEmergencyRecovery(currentDeps.db, sessionId);
|
|
200361
200616
|
} catch (recoveryError) {
|
|
200362
200617
|
sessionLog(sessionId, `/ctx-recomp: clearEmergencyRecovery failed (continuing): ${describeError(recoveryError).brief}`);
|
|
200363
200618
|
}
|
|
200364
200619
|
try {
|
|
200365
|
-
stagePiRecompMarker({ db:
|
|
200620
|
+
stagePiRecompMarker({ db: currentDeps.db, sessionId, ctx });
|
|
200366
200621
|
} catch (markerError) {
|
|
200367
200622
|
sessionLog(sessionId, `/ctx-recomp: marker staging failed (recomp already published; continuing): ${describeError(markerError).brief}`);
|
|
200368
200623
|
}
|
|
@@ -200383,11 +200638,15 @@ function parseRecompArgs(raw) {
|
|
|
200383
200638
|
const trimmed = raw.trim();
|
|
200384
200639
|
if (trimmed.length === 0)
|
|
200385
200640
|
return { kind: "full" };
|
|
200641
|
+
if (trimmed === "--upgrade")
|
|
200642
|
+
return { kind: "upgrade" };
|
|
200386
200643
|
const match = trimmed.match(/^(\d+)\s*-\s*(\d+)$/);
|
|
200387
200644
|
if (!match) {
|
|
200388
200645
|
return {
|
|
200389
200646
|
kind: "error",
|
|
200390
|
-
message:
|
|
200647
|
+
message: `Invalid /ctx-recomp arguments: \`${trimmed}\`.
|
|
200648
|
+
|
|
200649
|
+
${RECOMP_USAGE}`
|
|
200391
200650
|
};
|
|
200392
200651
|
}
|
|
200393
200652
|
const start = Number.parseInt(match[1], 10);
|
|
@@ -200401,6 +200660,21 @@ function parseRecompArgs(raw) {
|
|
|
200401
200660
|
};
|
|
200402
200661
|
return { kind: "partial", range: { start, end } };
|
|
200403
200662
|
}
|
|
200663
|
+
function executeRecompUpgradeStub(db, sessionId) {
|
|
200664
|
+
const legacyCount = getCompartments(db, sessionId).filter((compartment) => compartment.legacy === 1).length;
|
|
200665
|
+
if (legacyCount === 0) {
|
|
200666
|
+
return `## Magic Recomp Upgrade
|
|
200667
|
+
|
|
200668
|
+
Nothing to upgrade: this session has no legacy compartments.`;
|
|
200669
|
+
}
|
|
200670
|
+
return [
|
|
200671
|
+
"## Magic Recomp Upgrade",
|
|
200672
|
+
"",
|
|
200673
|
+
`Found ${legacyCount} legacy compartment${legacyCount === 1 ? "" : "s"} for this session.`,
|
|
200674
|
+
"The `--upgrade` flag is deprecated. Run `/ctx-session-upgrade` to upgrade this session."
|
|
200675
|
+
].join(`
|
|
200676
|
+
`);
|
|
200677
|
+
}
|
|
200404
200678
|
function buildConfirmationWarning(db, sessionId, parsed) {
|
|
200405
200679
|
const compartments = getCompartments(db, sessionId);
|
|
200406
200680
|
if (parsed.kind === "partial") {
|
|
@@ -200680,7 +200954,8 @@ No active Pi session is available.`,
|
|
|
200680
200954
|
});
|
|
200681
200955
|
return;
|
|
200682
200956
|
}
|
|
200683
|
-
|
|
200957
|
+
const currentDeps = deps.resolveRuntimeDeps?.(ctx) ?? deps;
|
|
200958
|
+
if (!currentDeps.historianModel) {
|
|
200684
200959
|
sendCtxStatusMessage(pi, {
|
|
200685
200960
|
title: "/ctx-session-upgrade",
|
|
200686
200961
|
text: "## Session Upgrade\n\nUnavailable because `historian.model` is not configured.",
|
|
@@ -200688,7 +200963,7 @@ No active Pi session is available.`,
|
|
|
200688
200963
|
});
|
|
200689
200964
|
return;
|
|
200690
200965
|
}
|
|
200691
|
-
if (isWrapupInProgress(
|
|
200966
|
+
if (isWrapupInProgress(currentDeps.db, sessionId)) {
|
|
200692
200967
|
sendCtxStatusMessage(pi, {
|
|
200693
200968
|
title: "/ctx-session-upgrade",
|
|
200694
200969
|
text: `## Session Upgrade
|
|
@@ -200708,27 +200983,27 @@ An upgrade or recomp is already running for this session in the background. Wait
|
|
|
200708
200983
|
});
|
|
200709
200984
|
return;
|
|
200710
200985
|
}
|
|
200711
|
-
const compartments = getCompartments(
|
|
200986
|
+
const compartments = getCompartments(currentDeps.db, sessionId);
|
|
200712
200987
|
const upgradableCount = compartments.filter((c) => c.legacy === 1 || !c.p1 || c.p1.trim() === "").length;
|
|
200713
200988
|
const sessionMainModel = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
200714
|
-
const migrationEnabled =
|
|
200989
|
+
const migrationEnabled = currentDeps.memoryEnabled;
|
|
200715
200990
|
const runMigration = async () => {
|
|
200716
200991
|
if (!migrationEnabled) {
|
|
200717
200992
|
return "Memory migration skipped (memory disabled).";
|
|
200718
200993
|
}
|
|
200719
200994
|
try {
|
|
200720
200995
|
const outcome = await runPiMemoryMigration({
|
|
200721
|
-
db:
|
|
200722
|
-
runner:
|
|
200996
|
+
db: currentDeps.db,
|
|
200997
|
+
runner: currentDeps.runner,
|
|
200723
200998
|
primaryModel: sessionMainModel,
|
|
200724
|
-
model:
|
|
200725
|
-
fallbackModels:
|
|
200726
|
-
timeoutMs:
|
|
200727
|
-
thinkingLevel:
|
|
200999
|
+
model: currentDeps.historianModel,
|
|
201000
|
+
fallbackModels: currentDeps.historianFallbacks,
|
|
201001
|
+
timeoutMs: currentDeps.historianTimeoutMs,
|
|
201002
|
+
thinkingLevel: currentDeps.historianThinkingLevel,
|
|
200728
201003
|
directory: ctx.cwd,
|
|
200729
201004
|
sessionId,
|
|
200730
|
-
userMemoriesEnabled:
|
|
200731
|
-
language:
|
|
201005
|
+
userMemoriesEnabled: currentDeps.userMemoriesEnabled,
|
|
201006
|
+
language: currentDeps.language
|
|
200732
201007
|
});
|
|
200733
201008
|
return outcome.summary;
|
|
200734
201009
|
} catch (error51) {
|
|
@@ -200737,7 +201012,7 @@ An upgrade or recomp is already running for this session in the background. Wait
|
|
|
200737
201012
|
};
|
|
200738
201013
|
if (upgradableCount === 0) {
|
|
200739
201014
|
const projectPath = resolveProjectIdentity(ctx.cwd);
|
|
200740
|
-
const migrationPending = migrationEnabled && !isMemoryMigrationDone(
|
|
201015
|
+
const migrationPending = migrationEnabled && !isMemoryMigrationDone(currentDeps.db, projectPath);
|
|
200741
201016
|
if (!migrationPending) {
|
|
200742
201017
|
sendCtxStatusMessage(pi, {
|
|
200743
201018
|
title: "/ctx-session-upgrade",
|
|
@@ -200763,7 +201038,10 @@ Compartments are already current. Re-organizing project memories. This may take
|
|
|
200763
201038
|
provider: {
|
|
200764
201039
|
readMessages: () => readPiSessionMessages(ctx)
|
|
200765
201040
|
},
|
|
200766
|
-
onStatusChange: () => updateStatusLine(ctx, {
|
|
201041
|
+
onStatusChange: () => updateStatusLine(ctx, {
|
|
201042
|
+
db: currentDeps.db,
|
|
201043
|
+
projectIdentity: ctx.cwd
|
|
201044
|
+
}),
|
|
200767
201045
|
work: async () => {
|
|
200768
201046
|
const summary = await runMigration();
|
|
200769
201047
|
sendCtxStatusMessage(pi, {
|
|
@@ -200789,35 +201067,38 @@ Rebuilding compartments into the v2 format and re-organizing project memories. T
|
|
|
200789
201067
|
spawnPiRecompRun({
|
|
200790
201068
|
sessionId,
|
|
200791
201069
|
provider: provider2,
|
|
200792
|
-
onStatusChange: () => updateStatusLine(ctx, {
|
|
201070
|
+
onStatusChange: () => updateStatusLine(ctx, {
|
|
201071
|
+
db: currentDeps.db,
|
|
201072
|
+
projectIdentity: ctx.cwd
|
|
201073
|
+
}),
|
|
200793
201074
|
work: async () => {
|
|
200794
201075
|
const recompResult = await executeContextRecompWithResult({
|
|
200795
201076
|
client: createPiHistorianClient({
|
|
200796
|
-
runner:
|
|
200797
|
-
model:
|
|
200798
|
-
fallbackModels:
|
|
200799
|
-
timeoutMs:
|
|
200800
|
-
thinkingLevel:
|
|
201077
|
+
runner: currentDeps.runner,
|
|
201078
|
+
model: currentDeps.historianModel,
|
|
201079
|
+
fallbackModels: currentDeps.historianFallbacks,
|
|
201080
|
+
timeoutMs: currentDeps.historianTimeoutMs,
|
|
201081
|
+
thinkingLevel: currentDeps.historianThinkingLevel,
|
|
200801
201082
|
directory: ctx.cwd,
|
|
200802
201083
|
accountingSessionId: sessionId,
|
|
200803
|
-
systemPrompt: withContentLanguageDirective(COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT,
|
|
201084
|
+
systemPrompt: withContentLanguageDirective(COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, currentDeps.language, { preserveUserQuotes: true }),
|
|
200804
201085
|
notify: (text) => sendCtxStatusMessage(pi, {
|
|
200805
201086
|
title: "/ctx-session-upgrade",
|
|
200806
201087
|
text,
|
|
200807
201088
|
level: "info"
|
|
200808
201089
|
})
|
|
200809
201090
|
}),
|
|
200810
|
-
db:
|
|
201091
|
+
db: currentDeps.db,
|
|
200811
201092
|
sessionId,
|
|
200812
|
-
historianChunkTokens:
|
|
201093
|
+
historianChunkTokens: currentDeps.historianChunkTokens,
|
|
200813
201094
|
directory: ctx.cwd,
|
|
200814
|
-
historianTimeoutMs:
|
|
200815
|
-
memoryEnabled:
|
|
200816
|
-
autoPromote:
|
|
201095
|
+
historianTimeoutMs: currentDeps.historianTimeoutMs,
|
|
201096
|
+
memoryEnabled: currentDeps.memoryEnabled,
|
|
201097
|
+
autoPromote: currentDeps.autoPromote,
|
|
200817
201098
|
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
200818
|
-
fallbackModels:
|
|
201099
|
+
fallbackModels: currentDeps.historianFallbacks,
|
|
200819
201100
|
fallbackModelId: sessionMainModel,
|
|
200820
|
-
language:
|
|
201101
|
+
language: currentDeps.language
|
|
200821
201102
|
}, {});
|
|
200822
201103
|
if (!recompResult.published || !isRecompComplete(recompResult.message)) {
|
|
200823
201104
|
const reason = contextualizeUpgradeReason(isRecompFailure(recompResult.message) ? extractRecompReason(recompResult.message) : `Compartments were not fully rebuilt: ${extractRecompReason(recompResult.message)}`);
|
|
@@ -200831,7 +201112,7 @@ ${reason}`,
|
|
|
200831
201112
|
return;
|
|
200832
201113
|
}
|
|
200833
201114
|
try {
|
|
200834
|
-
stagePiRecompMarker({ db:
|
|
201115
|
+
stagePiRecompMarker({ db: currentDeps.db, sessionId, ctx });
|
|
200835
201116
|
} catch (markerError) {
|
|
200836
201117
|
sessionLog(sessionId, `pi /ctx-session-upgrade marker staging failed (non-fatal, recomp already published): ${describeError(markerError).brief}`);
|
|
200837
201118
|
}
|
|
@@ -201029,7 +201310,7 @@ function formatThresholdPercent(value) {
|
|
|
201029
201310
|
// package.json
|
|
201030
201311
|
var package_default = {
|
|
201031
201312
|
name: "@cortexkit/pi-magic-context",
|
|
201032
|
-
version: "0.31.
|
|
201313
|
+
version: "0.31.3",
|
|
201033
201314
|
type: "module",
|
|
201034
201315
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
201035
201316
|
main: "dist/index.js",
|
|
@@ -201180,6 +201461,7 @@ function renderInner(s, theme, innerWidth) {
|
|
|
201180
201461
|
lines.push(`${theme.fg("accent", theme.bold("⚡ Magic Context Status"))} ${theme.fg("muted", `v${package_default.version}`)}`);
|
|
201181
201462
|
lines.push("");
|
|
201182
201463
|
lines.push(`Context ${theme.fg(pctColor, theme.bold(`${s.usagePercentage.toFixed(1)}%`))} · ${fmt2(s.inputTokens)} / ${s.contextLimit > 0 ? fmt2(s.contextLimit) : "?"} tokens`);
|
|
201464
|
+
lines.push(`Work tokens ${fmt2(s.newWorkTokens)} new · ${fmt2(s.totalInputTokens)} total input`);
|
|
201183
201465
|
lines.push(renderBar(s, innerWidth));
|
|
201184
201466
|
for (const seg of breakdownSegments(s)) {
|
|
201185
201467
|
const pct = (seg.tokens / (s.inputTokens || 1) * 100).toFixed(1);
|
|
@@ -201275,6 +201557,7 @@ ${safeStringify(tool.parameters)}`);
|
|
|
201275
201557
|
}
|
|
201276
201558
|
} catch {}
|
|
201277
201559
|
const conversationTokens = Math.max(0, inputTokens - systemPromptTokens - compartmentTokens - factTokens - memoryTokens - docsTokens - profileTokens - toolCallTokens - toolDefinitionTokens);
|
|
201560
|
+
const workMetrics = getSessionWorkMetrics(deps.db, sessionId);
|
|
201278
201561
|
const modelKey = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
201279
201562
|
const threshold = resolveExecuteThresholdDetail(deps.executeThresholdPercentage ?? 65, modelKey, 65, {
|
|
201280
201563
|
tokensConfig: deps.executeThresholdTokens,
|
|
@@ -201338,6 +201621,8 @@ ${safeStringify(tool.parameters)}`);
|
|
|
201338
201621
|
conversationTokens,
|
|
201339
201622
|
toolCallTokens,
|
|
201340
201623
|
toolDefinitionTokens,
|
|
201624
|
+
newWorkTokens: workMetrics.newWorkTokens,
|
|
201625
|
+
totalInputTokens: workMetrics.totalInputTokens,
|
|
201341
201626
|
upgradeNeededCount: safeRead(() => countCompartmentsNeedingUpgrade(deps.db, sessionId), 0),
|
|
201342
201627
|
recompInFlight: isPiRecompInFlight(sessionId)
|
|
201343
201628
|
};
|
|
@@ -201492,8 +201777,9 @@ function registerCtxStatusCommand(pi, deps) {
|
|
|
201492
201777
|
pi.registerCommand("ctx-status", {
|
|
201493
201778
|
description: "Show Magic Context status for the current Pi session",
|
|
201494
201779
|
handler: async (_args, ctx) => {
|
|
201495
|
-
const
|
|
201496
|
-
const
|
|
201780
|
+
const runtimeDeps = deps.resolveStatusDeps?.(ctx) ?? deps;
|
|
201781
|
+
const projectIdentity = runtimeDeps.resolveProject?.(ctx).projectIdentity ?? runtimeDeps.projectIdentity;
|
|
201782
|
+
const currentDeps = { ...runtimeDeps, projectIdentity };
|
|
201497
201783
|
const sessionId = resolveSessionId(ctx);
|
|
201498
201784
|
if (!sessionId) {
|
|
201499
201785
|
sendCtxStatusMessage(pi, {
|
|
@@ -201608,7 +201894,8 @@ No active Pi session is available.`,
|
|
|
201608
201894
|
});
|
|
201609
201895
|
return;
|
|
201610
201896
|
}
|
|
201611
|
-
const
|
|
201897
|
+
const currentDeps = deps.resolveRuntimeDeps?.(ctx) ?? deps;
|
|
201898
|
+
const sessionMeta = getOrCreateSessionMeta(currentDeps.db, sessionId);
|
|
201612
201899
|
if (sessionMeta.isSubagent) {
|
|
201613
201900
|
sendCtxStatusMessage(pi, {
|
|
201614
201901
|
title: "/ctx-wrapup",
|
|
@@ -201619,7 +201906,7 @@ No active Pi session is available.`,
|
|
|
201619
201906
|
});
|
|
201620
201907
|
return;
|
|
201621
201908
|
}
|
|
201622
|
-
if (!
|
|
201909
|
+
if (!currentDeps.historianModel) {
|
|
201623
201910
|
sendCtxStatusMessage(pi, {
|
|
201624
201911
|
title: "/ctx-wrapup",
|
|
201625
201912
|
text: "## Magic Wrapup\n\n/ctx-wrapup is unavailable because `historian.model` is not configured.",
|
|
@@ -201638,7 +201925,7 @@ ${parsed.message}`,
|
|
|
201638
201925
|
});
|
|
201639
201926
|
return;
|
|
201640
201927
|
}
|
|
201641
|
-
const result = await runPiWrapup(pi,
|
|
201928
|
+
const result = await runPiWrapup(pi, currentDeps, ctx, sessionId, parsed.messagesToKeep);
|
|
201642
201929
|
sendCtxStatusMessage(pi, {
|
|
201643
201930
|
title: "/ctx-wrapup",
|
|
201644
201931
|
text: result,
|
|
@@ -201812,6 +202099,7 @@ Chunk ${chunkIndex}: wrapping messages ${plan.snapshot.offset}-${plan.snapshot.e
|
|
|
201812
202099
|
runner: deps.runner,
|
|
201813
202100
|
historianModel: deps.historianModel,
|
|
201814
202101
|
fallbackModels: deps.historianFallbacks,
|
|
202102
|
+
fallbackModelId: modelKey,
|
|
201815
202103
|
historianChunkTokens: deps.historianChunkTokens,
|
|
201816
202104
|
boundarySnapshot: plan.snapshot,
|
|
201817
202105
|
refreshBoundarySnapshot: () => resolveWrapupProtectedTailBoundary({
|
|
@@ -206393,16 +206681,16 @@ __export(exports_typebox, {
|
|
|
206393
206681
|
// src/tools/ctx-expand.ts
|
|
206394
206682
|
var ParamsSchema = exports_typebox.Object({
|
|
206395
206683
|
start: exports_typebox.Optional(exports_typebox.Number({
|
|
206396
|
-
description:
|
|
206684
|
+
description: `First message ordinal to expand — a compartment's start="N" attribute, or an ordinal from a ctx_search message hit`
|
|
206397
206685
|
})),
|
|
206398
206686
|
end: exports_typebox.Optional(exports_typebox.Number({
|
|
206399
|
-
description:
|
|
206687
|
+
description: `Last message ordinal to expand (inclusive) — a compartment's end="M" attribute`
|
|
206400
206688
|
})),
|
|
206401
206689
|
verbose: exports_typebox.Optional(exports_typebox.Boolean({
|
|
206402
206690
|
description: "With start/end: list each message separately with its ordinal [N] and per-part preview, so you can recover one in full by ordinal."
|
|
206403
206691
|
})),
|
|
206404
206692
|
message: exports_typebox.Optional(exports_typebox.Number({
|
|
206405
|
-
description: "Full untruncated recovery of ONE message by its ordinal (text + every tool call's
|
|
206693
|
+
description: "Full untruncated recovery of ONE message by its ordinal (every text part + every tool call's complete input/output). Use an ordinal from a compartment, ctx_search hit, or verbose range. Recovers a tool output you dropped with ctx_reduce."
|
|
206406
206694
|
}))
|
|
206407
206695
|
});
|
|
206408
206696
|
function ok(text) {
|
|
@@ -206553,25 +206841,45 @@ function formatMemoryList(memories) {
|
|
|
206553
206841
|
id: String(m.id),
|
|
206554
206842
|
category: m.category,
|
|
206555
206843
|
status: m.status,
|
|
206844
|
+
verification: m.verificationStatus,
|
|
206556
206845
|
updated: new Date(m.updatedAt).toISOString(),
|
|
206557
206846
|
content: m.content.replace(/\s+/g, " ").trim()
|
|
206558
206847
|
}));
|
|
206848
|
+
const headers = {
|
|
206849
|
+
id: "ID",
|
|
206850
|
+
category: "CATEGORY",
|
|
206851
|
+
status: "STATUS",
|
|
206852
|
+
verification: "VERIFY",
|
|
206853
|
+
updated: "UPDATED",
|
|
206854
|
+
content: "CONTENT"
|
|
206855
|
+
};
|
|
206559
206856
|
const widths = {
|
|
206560
|
-
id: Math.max(
|
|
206561
|
-
category: Math.max(
|
|
206562
|
-
status: Math.max(
|
|
206563
|
-
|
|
206857
|
+
id: Math.max(headers.id.length, ...rows.map((r) => r.id.length)),
|
|
206858
|
+
category: Math.max(headers.category.length, ...rows.map((r) => r.category.length)),
|
|
206859
|
+
status: Math.max(headers.status.length, ...rows.map((r) => r.status.length)),
|
|
206860
|
+
verification: Math.max(headers.verification.length, ...rows.map((r) => r.verification.length)),
|
|
206861
|
+
updated: Math.max(headers.updated.length, ...rows.map((r) => r.updated.length))
|
|
206564
206862
|
};
|
|
206565
206863
|
const fmt3 = (r) => [
|
|
206566
206864
|
r.id.padEnd(widths.id),
|
|
206567
206865
|
r.category.padEnd(widths.category),
|
|
206568
206866
|
r.status.padEnd(widths.status),
|
|
206867
|
+
r.verification.padEnd(widths.verification),
|
|
206569
206868
|
r.updated.padEnd(widths.updated),
|
|
206570
206869
|
r.content
|
|
206571
206870
|
].join(" | ");
|
|
206572
206871
|
return [
|
|
206573
206872
|
`Found ${rows.length} active ${rows.length === 1 ? "memory" : "memories"}:`,
|
|
206574
206873
|
"",
|
|
206874
|
+
fmt3(headers),
|
|
206875
|
+
[
|
|
206876
|
+
"-".repeat(widths.id),
|
|
206877
|
+
"-".repeat(widths.category),
|
|
206878
|
+
"-".repeat(widths.status),
|
|
206879
|
+
"-".repeat(widths.verification),
|
|
206880
|
+
"-".repeat(widths.updated),
|
|
206881
|
+
"-------"
|
|
206882
|
+
].join("-+-"),
|
|
206575
206883
|
...rows.map(fmt3)
|
|
206576
206884
|
].join(`
|
|
206577
206885
|
`);
|
|
@@ -206977,6 +207285,7 @@ function createCtxNoteTool(deps) {
|
|
|
206977
207285
|
parameters: ParamsSchema3,
|
|
206978
207286
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
206979
207287
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
207288
|
+
const dreamerEnabled = deps.resolveDreamerEnabled?.(ctx) ?? deps.dreamerEnabled;
|
|
206980
207289
|
const action2 = params.action ?? (params.content?.trim() ? "write" : "read");
|
|
206981
207290
|
if (action2 === "write") {
|
|
206982
207291
|
const content = params.content?.trim();
|
|
@@ -206985,7 +207294,7 @@ function createCtxNoteTool(deps) {
|
|
|
206985
207294
|
const anchorOrdinal = captureAnchorOrdinal(deps.db, sessionId);
|
|
206986
207295
|
const surfaceCondition = params.surface_condition?.trim();
|
|
206987
207296
|
if (surfaceCondition) {
|
|
206988
|
-
if (
|
|
207297
|
+
if (dreamerEnabled !== true) {
|
|
206989
207298
|
return err3("Error: Smart notes require dreamer to be enabled. Enable dreamer in magic-context.jsonc to use surface_condition.");
|
|
206990
207299
|
}
|
|
206991
207300
|
const projectIdentity = resolveProjectIdentity(ctx.cwd);
|
|
@@ -206994,6 +207303,7 @@ function createCtxNoteTool(deps) {
|
|
|
206994
207303
|
}
|
|
206995
207304
|
const note2 = addNote(deps.db, "smart", {
|
|
206996
207305
|
content,
|
|
207306
|
+
sessionId,
|
|
206997
207307
|
projectPath: projectIdentity,
|
|
206998
207308
|
surfaceCondition,
|
|
206999
207309
|
anchorOrdinal
|
|
@@ -207245,6 +207555,7 @@ function createCtxReduceTool(deps) {
|
|
|
207245
207555
|
parameters: ParamsSchema4,
|
|
207246
207556
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
207247
207557
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
207558
|
+
const protectedTags = Math.max(0, Math.floor(deps.resolveProtectedTags?.(ctx) ?? deps.protectedTags));
|
|
207248
207559
|
if (!params.drop) {
|
|
207249
207560
|
return err4("Error: 'drop' must be provided.");
|
|
207250
207561
|
}
|
|
@@ -207262,7 +207573,7 @@ function createCtxReduceTool(deps) {
|
|
|
207262
207573
|
return err4(`Error: Unknown tag(s) ${formatIds(unknownIds)}. Check available tags in conversation.`);
|
|
207263
207574
|
}
|
|
207264
207575
|
const activeTags = allTags.filter((tag) => tag.status === "active");
|
|
207265
|
-
const protectedTagIds = activeTags.map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0,
|
|
207576
|
+
const protectedTagIds = activeTags.map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, protectedTags);
|
|
207266
207577
|
const protectedSet = new Set(protectedTagIds);
|
|
207267
207578
|
const tagStatusMap = new Map(allTags.map((tag) => [tag.tagNumber, tag.status]));
|
|
207268
207579
|
const pendingOps = getPendingOps(deps.db, sessionId);
|
|
@@ -207489,6 +207800,417 @@ function createCtxSearchTool(deps) {
|
|
|
207489
207800
|
};
|
|
207490
207801
|
}
|
|
207491
207802
|
|
|
207803
|
+
// src/tools/todo-view-pi.ts
|
|
207804
|
+
import {
|
|
207805
|
+
truncateToWidth as truncateToWidth2
|
|
207806
|
+
} from "@earendil-works/pi-tui";
|
|
207807
|
+
var TODO_TOOL_NAME = "todowrite";
|
|
207808
|
+
var TODOS_COMMAND_NAME = "todos";
|
|
207809
|
+
var WIDGET_KEY = "magic-context-todos";
|
|
207810
|
+
var MAX_OVERLAY_CONTENT_ROWS = 12;
|
|
207811
|
+
var TODO_STATUSES = [
|
|
207812
|
+
"pending",
|
|
207813
|
+
"in_progress",
|
|
207814
|
+
"completed",
|
|
207815
|
+
"cancelled"
|
|
207816
|
+
];
|
|
207817
|
+
var TODO_PRIORITIES = ["high", "medium", "low"];
|
|
207818
|
+
var STATUS_GLYPH = {
|
|
207819
|
+
pending: "○",
|
|
207820
|
+
in_progress: "◐",
|
|
207821
|
+
completed: "✓",
|
|
207822
|
+
cancelled: "✗"
|
|
207823
|
+
};
|
|
207824
|
+
var STATUS_COLOR = {
|
|
207825
|
+
pending: "dim",
|
|
207826
|
+
in_progress: "warning",
|
|
207827
|
+
completed: "success",
|
|
207828
|
+
cancelled: "error"
|
|
207829
|
+
};
|
|
207830
|
+
var snapshotsBySession = new Map;
|
|
207831
|
+
function isTodoStatus(value) {
|
|
207832
|
+
return TODO_STATUSES.includes(value);
|
|
207833
|
+
}
|
|
207834
|
+
function isTodoPriority(value) {
|
|
207835
|
+
return TODO_PRIORITIES.includes(value);
|
|
207836
|
+
}
|
|
207837
|
+
function cloneTodos(todos) {
|
|
207838
|
+
return todos.map((todo) => ({ ...todo }));
|
|
207839
|
+
}
|
|
207840
|
+
function parseTodos(input) {
|
|
207841
|
+
if (!Array.isArray(input))
|
|
207842
|
+
return null;
|
|
207843
|
+
const todos = [];
|
|
207844
|
+
for (const item of input) {
|
|
207845
|
+
if (item === null || typeof item !== "object")
|
|
207846
|
+
return null;
|
|
207847
|
+
const raw = item;
|
|
207848
|
+
if (typeof raw.content !== "string" || !isTodoStatus(raw.status)) {
|
|
207849
|
+
return null;
|
|
207850
|
+
}
|
|
207851
|
+
const todo = {
|
|
207852
|
+
content: raw.content,
|
|
207853
|
+
status: raw.status
|
|
207854
|
+
};
|
|
207855
|
+
if (isTodoPriority(raw.priority))
|
|
207856
|
+
todo.priority = raw.priority;
|
|
207857
|
+
if (typeof raw.id === "string" && raw.id.length > 0)
|
|
207858
|
+
todo.id = raw.id;
|
|
207859
|
+
todos.push(todo);
|
|
207860
|
+
}
|
|
207861
|
+
return todos;
|
|
207862
|
+
}
|
|
207863
|
+
function parseTodoStateJson(stateJson) {
|
|
207864
|
+
if (!stateJson)
|
|
207865
|
+
return null;
|
|
207866
|
+
try {
|
|
207867
|
+
return parseTodos(JSON.parse(stateJson));
|
|
207868
|
+
} catch {
|
|
207869
|
+
return null;
|
|
207870
|
+
}
|
|
207871
|
+
}
|
|
207872
|
+
function setTodoSnapshot(sessionId, todos) {
|
|
207873
|
+
const parsed = parseTodos(todos);
|
|
207874
|
+
if (parsed === null)
|
|
207875
|
+
return false;
|
|
207876
|
+
snapshotsBySession.set(sessionId, { todos: parsed });
|
|
207877
|
+
return true;
|
|
207878
|
+
}
|
|
207879
|
+
function seedTodoSnapshotFromStateJson(sessionId, stateJson) {
|
|
207880
|
+
const parsed = parseTodoStateJson(stateJson);
|
|
207881
|
+
if (parsed === null) {
|
|
207882
|
+
snapshotsBySession.delete(sessionId);
|
|
207883
|
+
return false;
|
|
207884
|
+
}
|
|
207885
|
+
snapshotsBySession.set(sessionId, { todos: parsed });
|
|
207886
|
+
return true;
|
|
207887
|
+
}
|
|
207888
|
+
function getTodoSnapshot(sessionId) {
|
|
207889
|
+
if (!sessionId)
|
|
207890
|
+
return { todos: [] };
|
|
207891
|
+
const snapshot = snapshotsBySession.get(sessionId);
|
|
207892
|
+
return { todos: snapshot ? cloneTodos(snapshot.todos) : [] };
|
|
207893
|
+
}
|
|
207894
|
+
function clearTodoSnapshot(sessionId) {
|
|
207895
|
+
snapshotsBySession.delete(sessionId);
|
|
207896
|
+
}
|
|
207897
|
+
function getSessionId(ctx) {
|
|
207898
|
+
try {
|
|
207899
|
+
const id = ctx.sessionManager?.getSessionId?.();
|
|
207900
|
+
return typeof id === "string" && id.length > 0 ? id : undefined;
|
|
207901
|
+
} catch {
|
|
207902
|
+
return;
|
|
207903
|
+
}
|
|
207904
|
+
}
|
|
207905
|
+
function countTodos(todos) {
|
|
207906
|
+
const counts = {
|
|
207907
|
+
total: todos.length,
|
|
207908
|
+
pending: 0,
|
|
207909
|
+
inProgress: 0,
|
|
207910
|
+
completed: 0,
|
|
207911
|
+
cancelled: 0
|
|
207912
|
+
};
|
|
207913
|
+
for (const todo of todos) {
|
|
207914
|
+
switch (todo.status) {
|
|
207915
|
+
case "pending":
|
|
207916
|
+
counts.pending++;
|
|
207917
|
+
break;
|
|
207918
|
+
case "in_progress":
|
|
207919
|
+
counts.inProgress++;
|
|
207920
|
+
break;
|
|
207921
|
+
case "completed":
|
|
207922
|
+
counts.completed++;
|
|
207923
|
+
break;
|
|
207924
|
+
case "cancelled":
|
|
207925
|
+
counts.cancelled++;
|
|
207926
|
+
break;
|
|
207927
|
+
}
|
|
207928
|
+
}
|
|
207929
|
+
return counts;
|
|
207930
|
+
}
|
|
207931
|
+
function activeTitleCount(todos) {
|
|
207932
|
+
return todos.filter((todo) => todo.status !== "completed").length;
|
|
207933
|
+
}
|
|
207934
|
+
function formatCounts(counts) {
|
|
207935
|
+
if (counts.total === 0)
|
|
207936
|
+
return "No todos";
|
|
207937
|
+
const parts = [`${counts.completed}/${counts.total} completed`];
|
|
207938
|
+
if (counts.inProgress > 0)
|
|
207939
|
+
parts.push(`${counts.inProgress} in progress`);
|
|
207940
|
+
if (counts.pending > 0)
|
|
207941
|
+
parts.push(`${counts.pending} pending`);
|
|
207942
|
+
if (counts.cancelled > 0)
|
|
207943
|
+
parts.push(`${counts.cancelled} cancelled`);
|
|
207944
|
+
return parts.join(" · ");
|
|
207945
|
+
}
|
|
207946
|
+
function formatTodoLine(todo, theme, options = {}) {
|
|
207947
|
+
const glyph = theme.fg(STATUS_COLOR[todo.status], STATUS_GLYPH[todo.status]);
|
|
207948
|
+
const id = options.showId && todo.id ? `${theme.fg("accent", `#${todo.id}`)} ` : "";
|
|
207949
|
+
const color = todo.status === "pending" || todo.status === "in_progress" ? "text" : "dim";
|
|
207950
|
+
let content = theme.fg(color, todo.content);
|
|
207951
|
+
if (todo.status === "completed" || todo.status === "cancelled") {
|
|
207952
|
+
content = theme.strikethrough(content);
|
|
207953
|
+
}
|
|
207954
|
+
return `${glyph} ${id}${content}`;
|
|
207955
|
+
}
|
|
207956
|
+
function formatCommandLine(todo) {
|
|
207957
|
+
const id = todo.id ? `#${todo.id} ` : "";
|
|
207958
|
+
return ` ${STATUS_GLYPH[todo.status]} ${id}${todo.content}`;
|
|
207959
|
+
}
|
|
207960
|
+
function lineComponent(renderLines) {
|
|
207961
|
+
return {
|
|
207962
|
+
render: renderLines,
|
|
207963
|
+
invalidate() {}
|
|
207964
|
+
};
|
|
207965
|
+
}
|
|
207966
|
+
function renderTodowriteCall(args, theme) {
|
|
207967
|
+
const todos = parseTodos(args.todos) ?? [];
|
|
207968
|
+
const active = activeTitleCount(todos);
|
|
207969
|
+
const activeColor = active > 0 ? "warning" : "success";
|
|
207970
|
+
const line = `${theme.fg("toolTitle", theme.bold("Todos"))} ${theme.fg("muted", "—")} ${theme.fg(activeColor, `${active} active`)}`;
|
|
207971
|
+
return lineComponent((width) => [truncateToWidth2(line, width, "…")]);
|
|
207972
|
+
}
|
|
207973
|
+
function renderTodowriteResult(result, theme) {
|
|
207974
|
+
const detailsTodos = result.details?.todos;
|
|
207975
|
+
let todos = parseTodos(detailsTodos);
|
|
207976
|
+
if (todos === null && Array.isArray(result.content)) {
|
|
207977
|
+
const text = result.content.find((part) => part !== null && typeof part === "object" && part.type === "text" && typeof part.text === "string")?.text;
|
|
207978
|
+
if (text) {
|
|
207979
|
+
try {
|
|
207980
|
+
todos = parseTodos(JSON.parse(text));
|
|
207981
|
+
} catch {}
|
|
207982
|
+
}
|
|
207983
|
+
}
|
|
207984
|
+
const renderedTodos = todos ?? [];
|
|
207985
|
+
return lineComponent((width) => {
|
|
207986
|
+
if (renderedTodos.length === 0)
|
|
207987
|
+
return [theme.fg("dim", "No todos")];
|
|
207988
|
+
return renderedTodos.map((todo) => truncateToWidth2(formatTodoLine(todo, theme, { showId: true }), width, "…"));
|
|
207989
|
+
});
|
|
207990
|
+
}
|
|
207991
|
+
function registerTodosCommand(pi) {
|
|
207992
|
+
pi.registerCommand(TODOS_COMMAND_NAME, {
|
|
207993
|
+
description: "Show the current Magic Context todo list",
|
|
207994
|
+
handler: async (_args, ctx) => {
|
|
207995
|
+
if (!ctx.hasUI) {
|
|
207996
|
+
ctx.ui.notify("The /todos command requires interactive UI.", "error");
|
|
207997
|
+
return;
|
|
207998
|
+
}
|
|
207999
|
+
const sessionId = getSessionId(ctx);
|
|
208000
|
+
const todos = getTodoSnapshot(sessionId).todos;
|
|
208001
|
+
if (todos.length === 0) {
|
|
208002
|
+
ctx.ui.notify("No todos yet.", "info");
|
|
208003
|
+
return;
|
|
208004
|
+
}
|
|
208005
|
+
const counts = countTodos(todos);
|
|
208006
|
+
const lines = [formatCounts(counts)];
|
|
208007
|
+
const groups = [
|
|
208008
|
+
["pending", "── Pending ──"],
|
|
208009
|
+
["in_progress", "── In Progress ──"],
|
|
208010
|
+
["completed", "── Completed ──"],
|
|
208011
|
+
["cancelled", "── Cancelled ──"]
|
|
208012
|
+
];
|
|
208013
|
+
for (const [status, heading] of groups) {
|
|
208014
|
+
const group = todos.filter((todo) => todo.status === status);
|
|
208015
|
+
if (group.length === 0)
|
|
208016
|
+
continue;
|
|
208017
|
+
lines.push(heading);
|
|
208018
|
+
for (const todo of group)
|
|
208019
|
+
lines.push(formatCommandLine(todo));
|
|
208020
|
+
}
|
|
208021
|
+
ctx.ui.notify(lines.join(`
|
|
208022
|
+
`), "info");
|
|
208023
|
+
}
|
|
208024
|
+
});
|
|
208025
|
+
}
|
|
208026
|
+
function todoKey(todo, index) {
|
|
208027
|
+
return todo.id ? `id:${todo.id}` : `pos:${index}:${todo.content}`;
|
|
208028
|
+
}
|
|
208029
|
+
function isOverlayLive(todo) {
|
|
208030
|
+
return todo.status === "pending" || todo.status === "in_progress";
|
|
208031
|
+
}
|
|
208032
|
+
|
|
208033
|
+
class TodoOverlay {
|
|
208034
|
+
uiCtx;
|
|
208035
|
+
sessionId;
|
|
208036
|
+
widgetRegistered = false;
|
|
208037
|
+
tui;
|
|
208038
|
+
completedTaskIdsPendingHide = new Set;
|
|
208039
|
+
hiddenCompletedTaskIds = new Set;
|
|
208040
|
+
lastTodoKeys = new Set;
|
|
208041
|
+
setUICtx(sessionId, ctx) {
|
|
208042
|
+
if (ctx !== this.uiCtx || sessionId !== this.sessionId) {
|
|
208043
|
+
this.uiCtx = ctx;
|
|
208044
|
+
this.sessionId = sessionId;
|
|
208045
|
+
this.widgetRegistered = false;
|
|
208046
|
+
this.tui = undefined;
|
|
208047
|
+
this.resetCompletedDisplayState();
|
|
208048
|
+
}
|
|
208049
|
+
}
|
|
208050
|
+
update(sessionId = this.sessionId) {
|
|
208051
|
+
if (!this.uiCtx || !this.sessionId || sessionId !== this.sessionId)
|
|
208052
|
+
return;
|
|
208053
|
+
const todos = getTodoSnapshot(this.sessionId).todos;
|
|
208054
|
+
this.pruneCompletedDisplayState(todos);
|
|
208055
|
+
const visible = this.selectOverlayTodos(todos);
|
|
208056
|
+
if (visible.length === 0) {
|
|
208057
|
+
if (this.widgetRegistered) {
|
|
208058
|
+
this.uiCtx.setWidget(WIDGET_KEY, undefined);
|
|
208059
|
+
this.widgetRegistered = false;
|
|
208060
|
+
this.tui = undefined;
|
|
208061
|
+
}
|
|
208062
|
+
return;
|
|
208063
|
+
}
|
|
208064
|
+
if (!this.widgetRegistered) {
|
|
208065
|
+
this.uiCtx.setWidget(WIDGET_KEY, (tui, theme) => {
|
|
208066
|
+
this.tui = tui;
|
|
208067
|
+
return {
|
|
208068
|
+
render: (width) => this.renderWidget(theme, width),
|
|
208069
|
+
invalidate: () => {
|
|
208070
|
+
this.widgetRegistered = false;
|
|
208071
|
+
this.tui = undefined;
|
|
208072
|
+
}
|
|
208073
|
+
};
|
|
208074
|
+
}, { placement: "aboveEditor" });
|
|
208075
|
+
this.widgetRegistered = true;
|
|
208076
|
+
} else {
|
|
208077
|
+
this.tui?.requestRender();
|
|
208078
|
+
}
|
|
208079
|
+
}
|
|
208080
|
+
resetCompletedDisplayState() {
|
|
208081
|
+
this.completedTaskIdsPendingHide.clear();
|
|
208082
|
+
this.hiddenCompletedTaskIds.clear();
|
|
208083
|
+
this.lastTodoKeys.clear();
|
|
208084
|
+
}
|
|
208085
|
+
hideCompletedTasksFromPreviousTurn() {
|
|
208086
|
+
if (this.completedTaskIdsPendingHide.size === 0)
|
|
208087
|
+
return;
|
|
208088
|
+
for (const taskId of this.completedTaskIdsPendingHide) {
|
|
208089
|
+
this.hiddenCompletedTaskIds.add(taskId);
|
|
208090
|
+
}
|
|
208091
|
+
this.completedTaskIdsPendingHide.clear();
|
|
208092
|
+
this.update();
|
|
208093
|
+
}
|
|
208094
|
+
disposeSession(sessionId) {
|
|
208095
|
+
if (this.sessionId !== sessionId)
|
|
208096
|
+
return;
|
|
208097
|
+
this.dispose();
|
|
208098
|
+
}
|
|
208099
|
+
dispose() {
|
|
208100
|
+
if (this.uiCtx)
|
|
208101
|
+
this.uiCtx.setWidget(WIDGET_KEY, undefined);
|
|
208102
|
+
this.widgetRegistered = false;
|
|
208103
|
+
this.tui = undefined;
|
|
208104
|
+
this.uiCtx = undefined;
|
|
208105
|
+
this.sessionId = undefined;
|
|
208106
|
+
this.resetCompletedDisplayState();
|
|
208107
|
+
}
|
|
208108
|
+
pruneCompletedDisplayState(todos) {
|
|
208109
|
+
const currentKeys = new Set(todos.map((todo, index) => todoKey(todo, index)));
|
|
208110
|
+
const hasSharedKeys = [...currentKeys].some((key) => this.lastTodoKeys.has(key));
|
|
208111
|
+
if (this.lastTodoKeys.size > 0 && currentKeys.size > 0 && !hasSharedKeys) {
|
|
208112
|
+
this.resetCompletedDisplayState();
|
|
208113
|
+
}
|
|
208114
|
+
this.lastTodoKeys = currentKeys;
|
|
208115
|
+
const completedKeys = new Set(todos.map((todo, index) => ({ todo, key: todoKey(todo, index) })).filter(({ todo }) => todo.status === "completed").map(({ key }) => key));
|
|
208116
|
+
for (const taskId of this.completedTaskIdsPendingHide) {
|
|
208117
|
+
if (!completedKeys.has(taskId))
|
|
208118
|
+
this.completedTaskIdsPendingHide.delete(taskId);
|
|
208119
|
+
}
|
|
208120
|
+
for (const taskId of this.hiddenCompletedTaskIds) {
|
|
208121
|
+
if (!completedKeys.has(taskId))
|
|
208122
|
+
this.hiddenCompletedTaskIds.delete(taskId);
|
|
208123
|
+
}
|
|
208124
|
+
}
|
|
208125
|
+
selectOverlayTodos(todos) {
|
|
208126
|
+
return todos.map((todo, index) => ({ todo, key: todoKey(todo, index) })).filter(({ todo, key }) => {
|
|
208127
|
+
if (isOverlayLive(todo))
|
|
208128
|
+
return true;
|
|
208129
|
+
return todo.status === "completed" && !this.hiddenCompletedTaskIds.has(key);
|
|
208130
|
+
});
|
|
208131
|
+
}
|
|
208132
|
+
renderWidget(theme, width) {
|
|
208133
|
+
if (!this.sessionId)
|
|
208134
|
+
return [];
|
|
208135
|
+
const todos = getTodoSnapshot(this.sessionId).todos;
|
|
208136
|
+
this.pruneCompletedDisplayState(todos);
|
|
208137
|
+
const overlayTodos = this.selectOverlayTodos(todos);
|
|
208138
|
+
if (overlayTodos.length === 0)
|
|
208139
|
+
return [];
|
|
208140
|
+
const counts = countTodos(todos);
|
|
208141
|
+
const hasInProgress = counts.inProgress > 0;
|
|
208142
|
+
const headingColor = hasInProgress ? "accent" : "dim";
|
|
208143
|
+
const headingIcon = hasInProgress ? "●" : "○";
|
|
208144
|
+
const heading = `${theme.fg(headingColor, headingIcon)} ${theme.fg(headingColor, "Todos")} ${theme.fg("muted", "—")} ${theme.fg("dim", formatCounts(counts))}`;
|
|
208145
|
+
const truncate3 = (line) => truncateToWidth2(line, width, "…");
|
|
208146
|
+
const lines = [truncate3(heading)];
|
|
208147
|
+
const hasTruncatedTail = overlayTodos.length > MAX_OVERLAY_CONTENT_ROWS;
|
|
208148
|
+
const visibleRows = hasTruncatedTail ? MAX_OVERLAY_CONTENT_ROWS - 1 : MAX_OVERLAY_CONTENT_ROWS;
|
|
208149
|
+
const truncatedTail = Math.max(0, overlayTodos.length - visibleRows);
|
|
208150
|
+
const visible = overlayTodos.slice(0, visibleRows);
|
|
208151
|
+
for (const [index, { todo, key }] of visible.entries()) {
|
|
208152
|
+
const isLast = index === visible.length - 1 && truncatedTail === 0;
|
|
208153
|
+
const branch = theme.fg("dim", isLast ? "└─" : "├─");
|
|
208154
|
+
lines.push(truncate3(`${branch} ${formatTodoLine(todo, theme, { showId: true })}`));
|
|
208155
|
+
if (todo.status === "completed")
|
|
208156
|
+
this.completedTaskIdsPendingHide.add(key);
|
|
208157
|
+
}
|
|
208158
|
+
if (truncatedTail > 0) {
|
|
208159
|
+
lines.push(truncate3(`${theme.fg("dim", "└─")} ${theme.fg("dim", `+${truncatedTail} more`)}`));
|
|
208160
|
+
}
|
|
208161
|
+
return lines;
|
|
208162
|
+
}
|
|
208163
|
+
}
|
|
208164
|
+
function registerTodoOverlay(pi, deps) {
|
|
208165
|
+
const overlay = new TodoOverlay;
|
|
208166
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
208167
|
+
const sessionId = getSessionId(ctx);
|
|
208168
|
+
if (!sessionId)
|
|
208169
|
+
return;
|
|
208170
|
+
seedTodoSnapshotFromStateJson(sessionId, deps.readLastTodoState(sessionId));
|
|
208171
|
+
if (!ctx.hasUI)
|
|
208172
|
+
return;
|
|
208173
|
+
overlay.setUICtx(sessionId, ctx.ui);
|
|
208174
|
+
overlay.update(sessionId);
|
|
208175
|
+
});
|
|
208176
|
+
pi.on("agent_start", async () => {
|
|
208177
|
+
overlay.hideCompletedTasksFromPreviousTurn();
|
|
208178
|
+
});
|
|
208179
|
+
pi.on("session_shutdown", async (_event, ctx) => {
|
|
208180
|
+
const sessionId = getSessionId(ctx);
|
|
208181
|
+
if (!sessionId)
|
|
208182
|
+
return;
|
|
208183
|
+
clearTodoSnapshot(sessionId);
|
|
208184
|
+
overlay.disposeSession(sessionId);
|
|
208185
|
+
});
|
|
208186
|
+
pi.on("session_before_switch", async (_event, ctx) => {
|
|
208187
|
+
const sessionId = getSessionId(ctx);
|
|
208188
|
+
if (!sessionId)
|
|
208189
|
+
return;
|
|
208190
|
+
clearTodoSnapshot(sessionId);
|
|
208191
|
+
overlay.disposeSession(sessionId);
|
|
208192
|
+
});
|
|
208193
|
+
return overlay;
|
|
208194
|
+
}
|
|
208195
|
+
function registerTodoStateLifecycle(pi, deps) {
|
|
208196
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
208197
|
+
const sessionId = getSessionId(ctx);
|
|
208198
|
+
if (!sessionId)
|
|
208199
|
+
return;
|
|
208200
|
+
seedTodoSnapshotFromStateJson(sessionId, deps.readLastTodoState(sessionId));
|
|
208201
|
+
});
|
|
208202
|
+
pi.on("session_shutdown", async (_event, ctx) => {
|
|
208203
|
+
const sessionId = getSessionId(ctx);
|
|
208204
|
+
if (sessionId)
|
|
208205
|
+
clearTodoSnapshot(sessionId);
|
|
208206
|
+
});
|
|
208207
|
+
pi.on("session_before_switch", async (_event, ctx) => {
|
|
208208
|
+
const sessionId = getSessionId(ctx);
|
|
208209
|
+
if (sessionId)
|
|
208210
|
+
clearTodoSnapshot(sessionId);
|
|
208211
|
+
});
|
|
208212
|
+
}
|
|
208213
|
+
|
|
207492
208214
|
// src/tools/todowrite.ts
|
|
207493
208215
|
var STATUS_VALUES = [
|
|
207494
208216
|
"pending",
|
|
@@ -207508,29 +208230,20 @@ var TodowriteParams = exports_typebox.Object({
|
|
|
207508
208230
|
description: "Replace the current task list with this complete set of todos. Include every task you intend to track this turn — pending, in_progress, completed, or cancelled — because the list overwrites previous state."
|
|
207509
208231
|
})
|
|
207510
208232
|
});
|
|
207511
|
-
var
|
|
207512
|
-
|
|
207513
|
-
"",
|
|
207514
|
-
"
|
|
207515
|
-
"mark
|
|
207516
|
-
"
|
|
207517
|
-
|
|
207518
|
-
"",
|
|
207519
|
-
"Task states:",
|
|
207520
|
-
" - pending: not started yet",
|
|
207521
|
-
" - in_progress: currently working on (limit to ONE task at a time)",
|
|
207522
|
-
" - completed: finished successfully",
|
|
207523
|
-
" - cancelled: no longer needed",
|
|
207524
|
-
"",
|
|
207525
|
-
"Use this tool proactively for non-trivial work spanning 3+ steps.",
|
|
207526
|
-
"Skip it for single-shot answers or trivial 1-2 step tasks."
|
|
207527
|
-
].join(`
|
|
207528
|
-
`);
|
|
208233
|
+
var PROMPT_SNIPPET = "Manage a task list to track multi-step progress";
|
|
208234
|
+
var PROMPT_GUIDELINES = [
|
|
208235
|
+
"Use `todowrite` for non-trivial work spanning 3+ steps, when the user gives you multiple tasks, or when you need to track progress across a verify/fix loop. Skip it for single-shot answers or trivial one-step work.",
|
|
208236
|
+
"Pass the COMPLETE updated todo list every time. This tool replaces the prior list rather than appending to it, so include pending, in_progress, completed, and cancelled tasks that should remain visible.",
|
|
208237
|
+
"When starting a task, mark exactly one todo `in_progress` before doing the work. Mark items `completed` immediately when done; use `cancelled` only for work that is no longer needed.",
|
|
208238
|
+
"Never mark a todo completed if verification is failing, implementation is partial, or an unresolved blocker remains. Keep it `in_progress` and add or update a todo for the blocker instead."
|
|
208239
|
+
];
|
|
207529
208240
|
function createTodowriteTool() {
|
|
207530
208241
|
return {
|
|
207531
|
-
name:
|
|
208242
|
+
name: TODO_TOOL_NAME,
|
|
207532
208243
|
label: "Todos",
|
|
207533
|
-
description:
|
|
208244
|
+
description: "Manage the session task list.",
|
|
208245
|
+
promptSnippet: PROMPT_SNIPPET,
|
|
208246
|
+
promptGuidelines: PROMPT_GUIDELINES,
|
|
207534
208247
|
parameters: TodowriteParams,
|
|
207535
208248
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
207536
208249
|
const todos = params.todos ?? [];
|
|
@@ -207549,6 +208262,12 @@ function createTodowriteTool() {
|
|
|
207549
208262
|
truncated: false
|
|
207550
208263
|
}
|
|
207551
208264
|
};
|
|
208265
|
+
},
|
|
208266
|
+
renderCall(args, theme) {
|
|
208267
|
+
return renderTodowriteCall(args, theme);
|
|
208268
|
+
},
|
|
208269
|
+
renderResult(result, _opts, theme) {
|
|
208270
|
+
return renderTodowriteResult(result, theme);
|
|
207552
208271
|
}
|
|
207553
208272
|
};
|
|
207554
208273
|
}
|
|
@@ -207574,15 +208293,22 @@ function registerMagicContextTools(pi, opts) {
|
|
|
207574
208293
|
if (!opts.sessionScopedToolsDisabled) {
|
|
207575
208294
|
pi.registerTool(createCtxNoteTool({
|
|
207576
208295
|
db: opts.db,
|
|
207577
|
-
dreamerEnabled: opts.dreamerEnabled ?? false
|
|
208296
|
+
dreamerEnabled: opts.dreamerEnabled ?? false,
|
|
208297
|
+
resolveDreamerEnabled: opts.resolveDreamerEnabled
|
|
207578
208298
|
}));
|
|
207579
208299
|
pi.registerTool(createCtxExpandTool({ db: opts.db }));
|
|
207580
208300
|
}
|
|
207581
|
-
|
|
208301
|
+
if (opts.todowriteEnabled !== false) {
|
|
208302
|
+
pi.registerTool(createTodowriteTool());
|
|
208303
|
+
if (opts.todowriteCommandEnabled !== false) {
|
|
208304
|
+
registerTodosCommand(pi);
|
|
208305
|
+
}
|
|
208306
|
+
}
|
|
207582
208307
|
if (!opts.sessionScopedToolsDisabled) {
|
|
207583
208308
|
pi.registerTool(createCtxReduceTool({
|
|
207584
208309
|
db: opts.db,
|
|
207585
|
-
protectedTags: opts.protectedTags ?? 20
|
|
208310
|
+
protectedTags: opts.protectedTags ?? 20,
|
|
208311
|
+
resolveProtectedTags: opts.resolveProtectedTags
|
|
207586
208312
|
}));
|
|
207587
208313
|
}
|
|
207588
208314
|
}
|
|
@@ -207594,6 +208320,10 @@ function resolveCurrentProject(ctx) {
|
|
|
207594
208320
|
const projectIdentity = resolveProjectIdentityOrFallback(projectDir);
|
|
207595
208321
|
return { projectDir, projectIdentity };
|
|
207596
208322
|
}
|
|
208323
|
+
function signalPiDeferredCompactionMarkerDrain(sessionId) {
|
|
208324
|
+
signalPiDeferredHistoryRefresh(sessionId);
|
|
208325
|
+
signalPiDeferredMaterialization(sessionId);
|
|
208326
|
+
}
|
|
207597
208327
|
function persistPiMessageEndModelMeta(args) {
|
|
207598
208328
|
if (!args.message || typeof args.message !== "object")
|
|
207599
208329
|
return;
|
|
@@ -207798,8 +208528,7 @@ async function src_default2(pi) {
|
|
|
207798
208528
|
try {
|
|
207799
208529
|
const pendingPiMarkerSessions = getSessionsWithPendingPiMarker(db);
|
|
207800
208530
|
for (const sid of pendingPiMarkerSessions) {
|
|
207801
|
-
|
|
207802
|
-
signalPiDeferredMaterialization(sid);
|
|
208531
|
+
signalPiDeferredCompactionMarkerDrain(sid);
|
|
207803
208532
|
}
|
|
207804
208533
|
if (pendingPiMarkerSessions.length > 0) {
|
|
207805
208534
|
log(`${PREFIX} rehydrated ${pendingPiMarkerSessions.length} Pi deferred compaction marker session(s)`);
|
|
@@ -207832,26 +208561,7 @@ async function src_default2(pi) {
|
|
|
207832
208561
|
}
|
|
207833
208562
|
await ensureProjectRegisteredFromPiDirectory(projectDir, db);
|
|
207834
208563
|
info(`registered embedding config for project ${projectIdentity}`);
|
|
207835
|
-
|
|
207836
|
-
db,
|
|
207837
|
-
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
207838
|
-
allowDreamerActions: false,
|
|
207839
|
-
memoryToolEnabled: true,
|
|
207840
|
-
protectedTags: config2.protected_tags ?? 20,
|
|
207841
|
-
dreamerEnabled: isDreamerRunnable(config2)
|
|
207842
|
-
});
|
|
207843
|
-
info("registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, ctx_reduce");
|
|
207844
|
-
const historianConfig = resolveHistorianFromConfig(config2);
|
|
207845
|
-
if (historianConfig) {
|
|
207846
|
-
historianConfig.onStatusChange = (ctx) => {
|
|
207847
|
-
updateStatusLine(ctx, {
|
|
207848
|
-
db,
|
|
207849
|
-
projectIdentity: resolveCurrentProject(ctx).projectIdentity
|
|
207850
|
-
});
|
|
207851
|
-
};
|
|
207852
|
-
}
|
|
207853
|
-
const autoSearchConfig = resolveAutoSearchFromConfig(config2);
|
|
207854
|
-
const contextOptionsByDir = new Map;
|
|
208564
|
+
const projectDepsByDir = new Map;
|
|
207855
208565
|
const buildContextOptions = (cfg, hist, auto) => ({
|
|
207856
208566
|
db: database,
|
|
207857
208567
|
smartDrops: cfg.smart_drops === true,
|
|
@@ -207892,46 +208602,110 @@ async function src_default2(pi) {
|
|
|
207892
208602
|
});
|
|
207893
208603
|
}
|
|
207894
208604
|
});
|
|
207895
|
-
function
|
|
207896
|
-
const
|
|
207897
|
-
if (
|
|
207898
|
-
|
|
207899
|
-
ensureConfigLocationsMigrated(dir);
|
|
207900
|
-
const switchedConfig = loadPiConfig({ cwd: dir }).config;
|
|
207901
|
-
const switchedHistorian = resolveHistorianFromConfig(switchedConfig);
|
|
207902
|
-
if (switchedHistorian) {
|
|
207903
|
-
switchedHistorian.onStatusChange = (ctx) => {
|
|
208605
|
+
function buildProjectDeps(dir, identity, cfg) {
|
|
208606
|
+
const hist = resolveHistorianFromConfig(cfg);
|
|
208607
|
+
if (hist) {
|
|
208608
|
+
hist.onStatusChange = (ctx) => {
|
|
207904
208609
|
updateStatusLine(ctx, {
|
|
207905
208610
|
db: database,
|
|
207906
208611
|
projectIdentity: resolveCurrentProject(ctx).projectIdentity
|
|
207907
208612
|
});
|
|
207908
208613
|
};
|
|
207909
208614
|
}
|
|
207910
|
-
const
|
|
207911
|
-
|
|
208615
|
+
const auto = resolveAutoSearchFromConfig(cfg);
|
|
208616
|
+
return {
|
|
208617
|
+
projectDir: dir,
|
|
208618
|
+
projectIdentity: identity,
|
|
208619
|
+
config: cfg,
|
|
208620
|
+
historianConfig: hist,
|
|
208621
|
+
autoSearchConfig: auto,
|
|
208622
|
+
contextOptions: buildContextOptions(cfg, hist, auto),
|
|
208623
|
+
sidekickConfig: resolveSidekickFromConfig(cfg),
|
|
208624
|
+
dreamerConfig: resolveDreamerFromConfig(cfg),
|
|
208625
|
+
dreamerEnabled: isDreamerRunnable(cfg)
|
|
208626
|
+
};
|
|
208627
|
+
}
|
|
208628
|
+
function resolveProjectDepsForDir(dir, identityOverride) {
|
|
208629
|
+
const cached2 = projectDepsByDir.get(dir);
|
|
208630
|
+
if (cached2)
|
|
208631
|
+
return cached2;
|
|
208632
|
+
ensureConfigLocationsMigrated(dir);
|
|
208633
|
+
const switchedConfig = loadPiConfig({ cwd: dir }).config;
|
|
208634
|
+
const switchedIdentity = identityOverride ?? resolveProjectIdentityOrFallback(dir);
|
|
208635
|
+
const built = buildProjectDeps(dir, switchedIdentity, switchedConfig);
|
|
208636
|
+
projectDepsByDir.set(dir, built);
|
|
207912
208637
|
return built;
|
|
207913
208638
|
}
|
|
207914
|
-
|
|
207915
|
-
|
|
207916
|
-
|
|
207917
|
-
|
|
207918
|
-
|
|
207919
|
-
|
|
207920
|
-
|
|
207921
|
-
|
|
208639
|
+
function resolveCurrentProjectDeps(ctx) {
|
|
208640
|
+
const currentProject = resolveCurrentProject(ctx);
|
|
208641
|
+
return resolveProjectDepsForDir(currentProject.projectDir, currentProject.projectIdentity);
|
|
208642
|
+
}
|
|
208643
|
+
function resolveContextOptionsForProject(dir) {
|
|
208644
|
+
return resolveProjectDepsForDir(dir).contextOptions;
|
|
208645
|
+
}
|
|
208646
|
+
const bootProjectDeps = buildProjectDeps(projectDir, projectIdentity, config2);
|
|
208647
|
+
projectDepsByDir.set(projectDir, bootProjectDeps);
|
|
208648
|
+
const todowriteEnabled = bootProjectDeps.config.todowrite.enabled !== false;
|
|
208649
|
+
const todowriteOverlayEnabled = todowriteEnabled && bootProjectDeps.config.todowrite.overlay !== false;
|
|
208650
|
+
registerMagicContextTools(pi, {
|
|
208651
|
+
db,
|
|
208652
|
+
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
208653
|
+
allowDreamerActions: false,
|
|
208654
|
+
memoryToolEnabled: true,
|
|
208655
|
+
protectedTags: config2.protected_tags ?? 20,
|
|
208656
|
+
resolveProtectedTags: (ctx) => resolveCurrentProjectDeps(ctx).config.protected_tags ?? 20,
|
|
208657
|
+
dreamerEnabled: isDreamerRunnable(config2),
|
|
208658
|
+
resolveDreamerEnabled: (ctx) => resolveCurrentProjectDeps(ctx).dreamerEnabled,
|
|
208659
|
+
todowriteEnabled
|
|
208660
|
+
});
|
|
208661
|
+
info(todowriteEnabled ? "registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, todowrite, ctx_reduce; registered /todos" : "registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, ctx_reduce (todowrite disabled)");
|
|
208662
|
+
const readLastTodoState = (sessionId) => getOrCreateSessionMeta(db, sessionId).lastTodoState;
|
|
208663
|
+
if (todowriteEnabled) {
|
|
208664
|
+
registerTodoStateLifecycle(pi, { readLastTodoState });
|
|
208665
|
+
}
|
|
208666
|
+
const todoOverlay = todowriteOverlayEnabled ? registerTodoOverlay(pi, {
|
|
208667
|
+
readLastTodoState
|
|
208668
|
+
}) : undefined;
|
|
208669
|
+
info(todowriteOverlayEnabled ? "registered todowrite overlay" : "registered todowrite overlay: DISABLED (todowrite.enabled=false or todowrite.overlay=false)");
|
|
208670
|
+
registerPiContextHandler(pi, bootProjectDeps.contextOptions);
|
|
208671
|
+
info(bootProjectDeps.historianConfig ? `registered historian trigger (model=${bootProjectDeps.historianConfig.model}, executeThreshold=${formatExecuteThresholdForLog(bootProjectDeps.historianConfig.executeThresholdPercentage)})` : "registered historian trigger: DISABLED (set historian.model in magic-context.jsonc)");
|
|
208672
|
+
info(bootProjectDeps.autoSearchConfig.enabled ? `registered auto-search hint (threshold=${bootProjectDeps.autoSearchConfig.scoreThreshold}, minChars=${bootProjectDeps.autoSearchConfig.minPromptChars})` : "registered auto-search hint: DISABLED (memory.auto_search.enabled=false)");
|
|
208673
|
+
registerCtxAugCommand(pi, (ctx) => resolveCurrentProjectDeps(ctx).sidekickConfig);
|
|
208674
|
+
info(bootProjectDeps.sidekickConfig ? `registered /ctx-aug (sidekick model=${bootProjectDeps.sidekickConfig.model})` : "registered /ctx-aug (sidekick disabled — set sidekick.disable=false and sidekick.model in config)");
|
|
208675
|
+
const recompRunner = new PiSubagentRunner;
|
|
208676
|
+
const wrapupRunner = new PiSubagentRunner;
|
|
208677
|
+
const upgradeRunner = new PiSubagentRunner;
|
|
207922
208678
|
registerCtxStatusCommand(pi, {
|
|
207923
208679
|
db,
|
|
207924
208680
|
projectIdentity,
|
|
207925
208681
|
resolveProject: resolveCurrentProject,
|
|
207926
|
-
protectedTags:
|
|
207927
|
-
executeThresholdPercentage:
|
|
207928
|
-
historyBudgetPercentage:
|
|
207929
|
-
injectionBudgetTokens:
|
|
207930
|
-
commitClusterTrigger:
|
|
207931
|
-
executeThresholdTokens:
|
|
208682
|
+
protectedTags: bootProjectDeps.config.protected_tags,
|
|
208683
|
+
executeThresholdPercentage: bootProjectDeps.config.execute_threshold_percentage,
|
|
208684
|
+
historyBudgetPercentage: bootProjectDeps.config.history_budget_percentage,
|
|
208685
|
+
injectionBudgetTokens: bootProjectDeps.config.memory?.injection_budget_tokens,
|
|
208686
|
+
commitClusterTrigger: bootProjectDeps.config.commit_cluster_trigger,
|
|
208687
|
+
executeThresholdTokens: bootProjectDeps.config.execute_threshold_tokens,
|
|
207932
208688
|
dreamer: {
|
|
207933
|
-
runnable:
|
|
207934
|
-
scheduleSummary: summarizeDreamSchedule(
|
|
208689
|
+
runnable: bootProjectDeps.dreamerEnabled,
|
|
208690
|
+
scheduleSummary: summarizeDreamSchedule(bootProjectDeps.config.dreamer)
|
|
208691
|
+
},
|
|
208692
|
+
resolveStatusDeps: (ctx) => {
|
|
208693
|
+
const current = resolveCurrentProjectDeps(ctx);
|
|
208694
|
+
return {
|
|
208695
|
+
db,
|
|
208696
|
+
projectIdentity: current.projectIdentity,
|
|
208697
|
+
resolveProject: resolveCurrentProject,
|
|
208698
|
+
protectedTags: current.config.protected_tags,
|
|
208699
|
+
executeThresholdPercentage: current.config.execute_threshold_percentage,
|
|
208700
|
+
historyBudgetPercentage: current.config.history_budget_percentage,
|
|
208701
|
+
injectionBudgetTokens: current.config.memory?.injection_budget_tokens,
|
|
208702
|
+
commitClusterTrigger: current.config.commit_cluster_trigger,
|
|
208703
|
+
executeThresholdTokens: current.config.execute_threshold_tokens,
|
|
208704
|
+
dreamer: {
|
|
208705
|
+
runnable: current.dreamerEnabled,
|
|
208706
|
+
scheduleSummary: summarizeDreamSchedule(current.config.dreamer)
|
|
208707
|
+
}
|
|
208708
|
+
};
|
|
207935
208709
|
}
|
|
207936
208710
|
});
|
|
207937
208711
|
info("registered /ctx-status");
|
|
@@ -207941,45 +208715,94 @@ async function src_default2(pi) {
|
|
|
207941
208715
|
info("registered /ctx-flush");
|
|
207942
208716
|
registerCtxRecompCommand(pi, {
|
|
207943
208717
|
db,
|
|
207944
|
-
runner:
|
|
207945
|
-
historianModel: historianConfig?.model,
|
|
207946
|
-
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(historianConfig?.model)),
|
|
207947
|
-
historianFallbacks: historianConfig?.fallbackModels,
|
|
207948
|
-
historianTimeoutMs:
|
|
207949
|
-
historianThinkingLevel: historianConfig?.thinkingLevel,
|
|
207950
|
-
language:
|
|
207951
|
-
memoryEnabled:
|
|
207952
|
-
autoPromote:
|
|
208718
|
+
runner: recompRunner,
|
|
208719
|
+
historianModel: bootProjectDeps.historianConfig?.model,
|
|
208720
|
+
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(bootProjectDeps.historianConfig?.model)),
|
|
208721
|
+
historianFallbacks: bootProjectDeps.historianConfig?.fallbackModels,
|
|
208722
|
+
historianTimeoutMs: bootProjectDeps.config.historian_timeout_ms,
|
|
208723
|
+
historianThinkingLevel: bootProjectDeps.historianConfig?.thinkingLevel,
|
|
208724
|
+
language: bootProjectDeps.config.language,
|
|
208725
|
+
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
208726
|
+
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
208727
|
+
resolveRuntimeDeps: (ctx) => {
|
|
208728
|
+
const current = resolveCurrentProjectDeps(ctx);
|
|
208729
|
+
return {
|
|
208730
|
+
db,
|
|
208731
|
+
runner: recompRunner,
|
|
208732
|
+
historianModel: current.historianConfig?.model,
|
|
208733
|
+
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(current.historianConfig?.model)),
|
|
208734
|
+
historianFallbacks: current.historianConfig?.fallbackModels,
|
|
208735
|
+
historianTimeoutMs: current.config.historian_timeout_ms,
|
|
208736
|
+
historianThinkingLevel: current.historianConfig?.thinkingLevel,
|
|
208737
|
+
language: current.config.language,
|
|
208738
|
+
memoryEnabled: current.config.memory.enabled,
|
|
208739
|
+
autoPromote: current.config.memory.auto_promote
|
|
208740
|
+
};
|
|
208741
|
+
}
|
|
207953
208742
|
});
|
|
207954
208743
|
info("registered /ctx-recomp");
|
|
207955
208744
|
registerCtxWrapupCommand(pi, {
|
|
207956
208745
|
db,
|
|
207957
|
-
runner:
|
|
207958
|
-
historianModel: historianConfig?.model,
|
|
207959
|
-
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(historianConfig?.model)),
|
|
207960
|
-
historianFallbacks: historianConfig?.fallbackModels,
|
|
207961
|
-
historianTimeoutMs:
|
|
207962
|
-
historianThinkingLevel: historianConfig?.thinkingLevel,
|
|
207963
|
-
language:
|
|
207964
|
-
memoryEnabled:
|
|
207965
|
-
autoPromote:
|
|
207966
|
-
userMemoriesEnabled: userMemoryCollectionEnabled(
|
|
207967
|
-
executeThresholdPercentage:
|
|
207968
|
-
executeThresholdTokens:
|
|
208746
|
+
runner: wrapupRunner,
|
|
208747
|
+
historianModel: bootProjectDeps.historianConfig?.model,
|
|
208748
|
+
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(bootProjectDeps.historianConfig?.model)),
|
|
208749
|
+
historianFallbacks: bootProjectDeps.historianConfig?.fallbackModels,
|
|
208750
|
+
historianTimeoutMs: bootProjectDeps.config.historian_timeout_ms,
|
|
208751
|
+
historianThinkingLevel: bootProjectDeps.historianConfig?.thinkingLevel,
|
|
208752
|
+
language: bootProjectDeps.config.language,
|
|
208753
|
+
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
208754
|
+
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
208755
|
+
userMemoriesEnabled: userMemoryCollectionEnabled(bootProjectDeps.config.dreamer),
|
|
208756
|
+
executeThresholdPercentage: bootProjectDeps.config.execute_threshold_percentage,
|
|
208757
|
+
executeThresholdTokens: bootProjectDeps.config.execute_threshold_tokens,
|
|
208758
|
+
resolveRuntimeDeps: (ctx) => {
|
|
208759
|
+
const current = resolveCurrentProjectDeps(ctx);
|
|
208760
|
+
return {
|
|
208761
|
+
db,
|
|
208762
|
+
runner: wrapupRunner,
|
|
208763
|
+
historianModel: current.historianConfig?.model,
|
|
208764
|
+
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(current.historianConfig?.model)),
|
|
208765
|
+
historianFallbacks: current.historianConfig?.fallbackModels,
|
|
208766
|
+
historianTimeoutMs: current.config.historian_timeout_ms,
|
|
208767
|
+
historianThinkingLevel: current.historianConfig?.thinkingLevel,
|
|
208768
|
+
language: current.config.language,
|
|
208769
|
+
memoryEnabled: current.config.memory.enabled,
|
|
208770
|
+
autoPromote: current.config.memory.auto_promote,
|
|
208771
|
+
userMemoriesEnabled: userMemoryCollectionEnabled(current.config.dreamer),
|
|
208772
|
+
executeThresholdPercentage: current.config.execute_threshold_percentage,
|
|
208773
|
+
executeThresholdTokens: current.config.execute_threshold_tokens
|
|
208774
|
+
};
|
|
208775
|
+
}
|
|
207969
208776
|
});
|
|
207970
208777
|
info("registered /ctx-wrapup");
|
|
207971
208778
|
registerCtxSessionUpgradeCommand(pi, {
|
|
207972
208779
|
db,
|
|
207973
|
-
runner:
|
|
207974
|
-
historianModel: historianConfig?.model,
|
|
207975
|
-
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(historianConfig?.model)),
|
|
207976
|
-
historianFallbacks: historianConfig?.fallbackModels,
|
|
207977
|
-
historianTimeoutMs:
|
|
207978
|
-
historianThinkingLevel: historianConfig?.thinkingLevel,
|
|
207979
|
-
language:
|
|
207980
|
-
memoryEnabled:
|
|
207981
|
-
autoPromote:
|
|
207982
|
-
userMemoriesEnabled: userMemoryCollectionEnabled(
|
|
208780
|
+
runner: upgradeRunner,
|
|
208781
|
+
historianModel: bootProjectDeps.historianConfig?.model,
|
|
208782
|
+
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(bootProjectDeps.historianConfig?.model)),
|
|
208783
|
+
historianFallbacks: bootProjectDeps.historianConfig?.fallbackModels,
|
|
208784
|
+
historianTimeoutMs: bootProjectDeps.config.historian_timeout_ms,
|
|
208785
|
+
historianThinkingLevel: bootProjectDeps.historianConfig?.thinkingLevel,
|
|
208786
|
+
language: bootProjectDeps.config.language,
|
|
208787
|
+
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
208788
|
+
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
208789
|
+
userMemoriesEnabled: userMemoryCollectionEnabled(bootProjectDeps.config.dreamer),
|
|
208790
|
+
resolveRuntimeDeps: (ctx) => {
|
|
208791
|
+
const current = resolveCurrentProjectDeps(ctx);
|
|
208792
|
+
return {
|
|
208793
|
+
db,
|
|
208794
|
+
runner: upgradeRunner,
|
|
208795
|
+
historianModel: current.historianConfig?.model,
|
|
208796
|
+
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(current.historianConfig?.model)),
|
|
208797
|
+
historianFallbacks: current.historianConfig?.fallbackModels,
|
|
208798
|
+
historianTimeoutMs: current.config.historian_timeout_ms,
|
|
208799
|
+
historianThinkingLevel: current.historianConfig?.thinkingLevel,
|
|
208800
|
+
language: current.config.language,
|
|
208801
|
+
memoryEnabled: current.config.memory.enabled,
|
|
208802
|
+
autoPromote: current.config.memory.auto_promote,
|
|
208803
|
+
userMemoriesEnabled: userMemoryCollectionEnabled(current.config.dreamer)
|
|
208804
|
+
};
|
|
208805
|
+
}
|
|
207983
208806
|
});
|
|
207984
208807
|
info("registered /ctx-session-upgrade");
|
|
207985
208808
|
registerCtxDreamCommand(pi, {
|
|
@@ -207987,7 +208810,8 @@ async function src_default2(pi) {
|
|
|
207987
208810
|
projectDir,
|
|
207988
208811
|
projectIdentity,
|
|
207989
208812
|
resolveProject: resolveCurrentProject,
|
|
207990
|
-
dreamerEnabled:
|
|
208813
|
+
dreamerEnabled: bootProjectDeps.dreamerEnabled,
|
|
208814
|
+
resolveDreamerEnabled: (ctx) => resolveCurrentProjectDeps(ctx).dreamerEnabled,
|
|
207991
208815
|
onProjectSeen: (identity) => seenDreamerProjectIdentities.add(identity)
|
|
207992
208816
|
});
|
|
207993
208817
|
info("registered /ctx-dream");
|
|
@@ -207995,26 +208819,27 @@ async function src_default2(pi) {
|
|
|
207995
208819
|
db,
|
|
207996
208820
|
projectDir,
|
|
207997
208821
|
projectIdentity,
|
|
207998
|
-
memoryEnabled:
|
|
208822
|
+
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
208823
|
+
resolveMemoryEnabled: (ctx) => resolveCurrentProjectDeps(ctx).config.memory.enabled,
|
|
207999
208824
|
resolveProject: resolveCurrentProject
|
|
208000
208825
|
});
|
|
208001
208826
|
info("registered /ctx-embed");
|
|
208002
|
-
const dreamerConfig =
|
|
208827
|
+
const dreamerConfig = bootProjectDeps.dreamerConfig;
|
|
208003
208828
|
if (dreamerConfig) {
|
|
208004
208829
|
registerPiDreamerProject({
|
|
208005
208830
|
db,
|
|
208006
208831
|
projectDir,
|
|
208007
208832
|
projectIdentity,
|
|
208008
208833
|
config: dreamerConfig,
|
|
208009
|
-
embeddingConfig:
|
|
208010
|
-
memoryEnabled:
|
|
208011
|
-
language:
|
|
208012
|
-
gitCommitIndexing:
|
|
208834
|
+
embeddingConfig: bootProjectDeps.config.embedding,
|
|
208835
|
+
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
208836
|
+
language: bootProjectDeps.config.language,
|
|
208837
|
+
gitCommitIndexing: bootProjectDeps.config.memory.git_commit_indexing,
|
|
208013
208838
|
onAdjunctsRefreshNeeded: signalPiSystemPromptRefreshForProject
|
|
208014
208839
|
});
|
|
208015
208840
|
info(`registered dreamer (${summarizeDreamSchedule(dreamerConfig)})`);
|
|
208016
208841
|
} else {
|
|
208017
|
-
info(
|
|
208842
|
+
info(bootProjectDeps.dreamerEnabled ? "registered dreamer: DISABLED (no dreamer config)" : "registered dreamer: DISABLED (dreamer.disable=true or no dreamer config)");
|
|
208018
208843
|
}
|
|
208019
208844
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
208020
208845
|
try {
|
|
@@ -208035,13 +208860,14 @@ async function src_default2(pi) {
|
|
|
208035
208860
|
}
|
|
208036
208861
|
} catch {}
|
|
208037
208862
|
try {
|
|
208038
|
-
const
|
|
208863
|
+
const effectiveProjectDeps = resolveCurrentProjectDeps(ctx);
|
|
208864
|
+
const currentProject = {
|
|
208865
|
+
projectDir: effectiveProjectDeps.projectDir,
|
|
208866
|
+
projectIdentity: effectiveProjectDeps.projectIdentity
|
|
208867
|
+
};
|
|
208868
|
+
const effectiveConfig = effectiveProjectDeps.config;
|
|
208039
208869
|
seenDreamerProjectIdentities.add(currentProject.projectIdentity);
|
|
208040
|
-
const
|
|
208041
|
-
if (switchedProject)
|
|
208042
|
-
ensureConfigLocationsMigrated(currentProject.projectDir);
|
|
208043
|
-
const effectiveConfig = switchedProject ? loadPiConfig({ cwd: currentProject.projectDir }).config : config2;
|
|
208044
|
-
const effectiveDreamerConfig = switchedProject ? resolveDreamerFromConfig(effectiveConfig) : dreamerConfig;
|
|
208870
|
+
const effectiveDreamerConfig = effectiveProjectDeps.dreamerConfig;
|
|
208045
208871
|
if (effectiveDreamerConfig) {
|
|
208046
208872
|
try {
|
|
208047
208873
|
registerPiDreamerProject({
|
|
@@ -208051,13 +208877,14 @@ async function src_default2(pi) {
|
|
|
208051
208877
|
config: effectiveDreamerConfig,
|
|
208052
208878
|
embeddingConfig: effectiveConfig.embedding,
|
|
208053
208879
|
memoryEnabled: effectiveConfig.memory.enabled,
|
|
208880
|
+
language: effectiveConfig.language,
|
|
208054
208881
|
gitCommitIndexing: effectiveConfig.memory.git_commit_indexing,
|
|
208055
208882
|
onAdjunctsRefreshNeeded: signalPiSystemPromptRefreshForProject
|
|
208056
208883
|
});
|
|
208057
208884
|
} catch (err5) {
|
|
208058
208885
|
warn("before_agent_start: registerPiDreamerProject threw:", err5);
|
|
208059
208886
|
}
|
|
208060
|
-
} else
|
|
208887
|
+
} else {
|
|
208061
208888
|
try {
|
|
208062
208889
|
unregisterPiDreamerProject({
|
|
208063
208890
|
projectIdentity: currentProject.projectIdentity
|
|
@@ -208084,11 +208911,10 @@ async function src_default2(pi) {
|
|
|
208084
208911
|
const smForDrain = sm;
|
|
208085
208912
|
const canDrain = typeof smForDrain.appendCompaction === "function" && typeof smForDrain.getBranch === "function";
|
|
208086
208913
|
if (canDrain && getPendingPiCompactionMarkerState(db, sessionId)) {
|
|
208087
|
-
|
|
208088
|
-
signalPiPendingMaterialization(sessionId);
|
|
208914
|
+
signalPiDeferredCompactionMarkerDrain(sessionId);
|
|
208089
208915
|
}
|
|
208090
208916
|
} catch {}
|
|
208091
|
-
if (ctx.hasUI && historianConfig?.model) {
|
|
208917
|
+
if (ctx.hasUI && effectiveProjectDeps.historianConfig?.model) {
|
|
208092
208918
|
maybeSendUpgradeReminder({
|
|
208093
208919
|
client: null,
|
|
208094
208920
|
db,
|
|
@@ -208109,7 +208935,6 @@ async function src_default2(pi) {
|
|
|
208109
208935
|
return;
|
|
208110
208936
|
}
|
|
208111
208937
|
const isCacheBusting = sessionId ? hasSystemPromptRefresh(sessionId) : true;
|
|
208112
|
-
const effectiveDreamerRunnable = switchedProject ? isDreamerRunnable(effectiveConfig) : isDreamerRunnable(config2);
|
|
208113
208938
|
const block = buildMagicContextBlock({
|
|
208114
208939
|
db,
|
|
208115
208940
|
cwd: currentProject.projectDir,
|
|
@@ -208118,7 +208943,7 @@ async function src_default2(pi) {
|
|
|
208118
208943
|
includeGuidance: true,
|
|
208119
208944
|
protectedTags: effectiveConfig.protected_tags,
|
|
208120
208945
|
ctxReduceCallable: true,
|
|
208121
|
-
dreamerEnabled:
|
|
208946
|
+
dreamerEnabled: effectiveProjectDeps.dreamerEnabled,
|
|
208122
208947
|
temporalAwarenessEnabled: effectiveConfig.temporal_awareness ?? false,
|
|
208123
208948
|
cavemanTextCompressionEnabled: effectiveConfig.caveman_text_compression?.enabled === true,
|
|
208124
208949
|
language: effectiveConfig.language,
|
|
@@ -208176,6 +209001,10 @@ ${block}` : event.systemPrompt;
|
|
|
208176
209001
|
const todoArgs = event.args;
|
|
208177
209002
|
const todos = todoArgs?.todos;
|
|
208178
209003
|
const sessionMeta = Array.isArray(todos) ? getOrCreateSessionMeta(db, sessionId) : null;
|
|
209004
|
+
if (todowriteEnabled && Array.isArray(todos)) {
|
|
209005
|
+
setTodoSnapshot(sessionId, todos);
|
|
209006
|
+
todoOverlay?.update(sessionId);
|
|
209007
|
+
}
|
|
208179
209008
|
if (sessionMeta && !sessionMeta.isSubagent) {
|
|
208180
209009
|
const normalizedTodos = normalizeTodoStateJson(todos);
|
|
208181
209010
|
if (normalizedTodos !== null) {
|
|
@@ -208264,7 +209093,7 @@ ${block}` : event.systemPrompt;
|
|
|
208264
209093
|
db,
|
|
208265
209094
|
sessionId,
|
|
208266
209095
|
message: event.message,
|
|
208267
|
-
cacheTtlConfig:
|
|
209096
|
+
cacheTtlConfig: resolveCurrentProjectDeps(ctx).config.cache_ttl
|
|
208268
209097
|
});
|
|
208269
209098
|
const piUsage = ctx.getContextUsage?.();
|
|
208270
209099
|
const piContextWindow = piUsage && typeof piUsage.contextWindow === "number" && piUsage.contextWindow > 0 ? piUsage.contextWindow : ctx.model?.contextWindow ?? 0;
|
|
@@ -208306,6 +209135,10 @@ ${block}` : event.systemPrompt;
|
|
|
208306
209135
|
const normalized = normalizeTodoStateJson(todos);
|
|
208307
209136
|
if (normalized === null)
|
|
208308
209137
|
continue;
|
|
209138
|
+
if (todowriteEnabled) {
|
|
209139
|
+
setTodoSnapshot(sessionId, todos);
|
|
209140
|
+
todoOverlay?.update(sessionId);
|
|
209141
|
+
}
|
|
208309
209142
|
updateSessionMeta(db, sessionId, {
|
|
208310
209143
|
lastTodoState: normalized
|
|
208311
209144
|
});
|
|
@@ -208397,6 +209230,7 @@ function formatExecuteThresholdForLog(value) {
|
|
|
208397
209230
|
return overrides.length > 0 ? `${base} (${overrides.join(", ")})` : base;
|
|
208398
209231
|
}
|
|
208399
209232
|
export {
|
|
209233
|
+
signalPiDeferredCompactionMarkerDrain,
|
|
208400
209234
|
resolveSidekickFromConfig,
|
|
208401
209235
|
resolveHistorianFromConfig,
|
|
208402
209236
|
resolveDreamerFromConfig,
|