@cortexkit/pi-magic-context 0.30.4 → 0.30.6
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 +142 -29
- package/dist/subagent-entry.js +41 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -156667,8 +156667,9 @@ init_logger();
|
|
|
156667
156667
|
|
|
156668
156668
|
// src/subagent-runner.ts
|
|
156669
156669
|
import * as childProcess from "node:child_process";
|
|
156670
|
-
import { existsSync as existsSync7 } from "node:fs";
|
|
156670
|
+
import { existsSync as existsSync7, mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
156671
156671
|
import { createRequire as createRequire2 } from "node:module";
|
|
156672
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
156672
156673
|
import { basename as basename2, dirname as dirname4, join as join8, resolve as resolvePath } from "node:path";
|
|
156673
156674
|
import { createInterface } from "node:readline";
|
|
156674
156675
|
import { fileURLToPath } from "node:url";
|
|
@@ -156889,9 +156890,11 @@ class PiSubagentRunner {
|
|
|
156889
156890
|
harness = "pi";
|
|
156890
156891
|
invocation;
|
|
156891
156892
|
spawnImpl;
|
|
156893
|
+
platform;
|
|
156892
156894
|
constructor(options = {}) {
|
|
156893
156895
|
this.invocation = options.piBinary ? { command: options.piBinary, prefixArgs: [] } : resolvePiInvocation();
|
|
156894
156896
|
this.spawnImpl = options.spawnImpl ?? childProcess.spawn;
|
|
156897
|
+
this.platform = options.platform ?? process.platform;
|
|
156895
156898
|
}
|
|
156896
156899
|
async run(options) {
|
|
156897
156900
|
const models = [options.model, ...options.fallbackModels ?? []].filter((model) => typeof model === "string" && model.length > 0);
|
|
@@ -156950,10 +156953,47 @@ class PiSubagentRunner {
|
|
|
156950
156953
|
}
|
|
156951
156954
|
return result;
|
|
156952
156955
|
}
|
|
156956
|
+
const failBeforeSpawn = (reason, error) => {
|
|
156957
|
+
const result = {
|
|
156958
|
+
ok: false,
|
|
156959
|
+
reason,
|
|
156960
|
+
error,
|
|
156961
|
+
durationMs: Date.now() - startTime
|
|
156962
|
+
};
|
|
156963
|
+
try {
|
|
156964
|
+
recordAccounting(result);
|
|
156965
|
+
} catch (err) {
|
|
156966
|
+
sessionLog(options.accountingSessionId ?? "subagent", `subagent accounting failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
156967
|
+
}
|
|
156968
|
+
return result;
|
|
156969
|
+
};
|
|
156953
156970
|
const promptBytes = Buffer.byteLength(options.userMessage, "utf8");
|
|
156954
|
-
const deliverViaStdin = promptBytes > PROMPT_ARGV_MAX_BYTES;
|
|
156971
|
+
const deliverViaStdin = promptBytes > PROMPT_ARGV_MAX_BYTES || this.platform === "win32";
|
|
156972
|
+
let systemPromptTempDir;
|
|
156973
|
+
let systemPromptPath;
|
|
156974
|
+
const cleanupSystemPromptFile = () => {
|
|
156975
|
+
if (!systemPromptTempDir)
|
|
156976
|
+
return;
|
|
156977
|
+
const tempDir = systemPromptTempDir;
|
|
156978
|
+
systemPromptTempDir = undefined;
|
|
156979
|
+
systemPromptPath = undefined;
|
|
156980
|
+
try {
|
|
156981
|
+
rmSync2(tempDir, { recursive: true, force: true });
|
|
156982
|
+
} catch {}
|
|
156983
|
+
};
|
|
156984
|
+
if (options.systemPrompt.length > 0) {
|
|
156985
|
+
try {
|
|
156986
|
+
systemPromptTempDir = mkdtempSync2(join8(tmpdir2(), "mc-pi-prompt-"));
|
|
156987
|
+
systemPromptPath = join8(systemPromptTempDir, "system-prompt.txt");
|
|
156988
|
+
writeFileSync5(systemPromptPath, options.systemPrompt, "utf8");
|
|
156989
|
+
} catch (error) {
|
|
156990
|
+
cleanupSystemPromptFile();
|
|
156991
|
+
return failBeforeSpawn("spawn_failed", `failed to prepare pi system prompt file: ${error instanceof Error ? error.message : String(error)}`);
|
|
156992
|
+
}
|
|
156993
|
+
}
|
|
156955
156994
|
const args = buildArgs(options, {
|
|
156956
|
-
omitPositionalMessage: deliverViaStdin
|
|
156995
|
+
omitPositionalMessage: deliverViaStdin,
|
|
156996
|
+
systemPromptPath
|
|
156957
156997
|
});
|
|
156958
156998
|
return new Promise((resolve) => {
|
|
156959
156999
|
let accountingMessages = [];
|
|
@@ -156962,6 +157002,7 @@ class PiSubagentRunner {
|
|
|
156962
157002
|
if (settled)
|
|
156963
157003
|
return;
|
|
156964
157004
|
settled = true;
|
|
157005
|
+
cleanupSystemPromptFile();
|
|
156965
157006
|
try {
|
|
156966
157007
|
recordAccounting(result, accountingMessages);
|
|
156967
157008
|
} catch (err) {
|
|
@@ -156987,6 +157028,7 @@ class PiSubagentRunner {
|
|
|
156987
157028
|
stdio: [deliverViaStdin ? "pipe" : "ignore", "pipe", "pipe"]
|
|
156988
157029
|
});
|
|
156989
157030
|
} catch (error) {
|
|
157031
|
+
cleanupSystemPromptFile();
|
|
156990
157032
|
settle({
|
|
156991
157033
|
ok: false,
|
|
156992
157034
|
reason: "spawn_failed",
|
|
@@ -157054,6 +157096,8 @@ class PiSubagentRunner {
|
|
|
157054
157096
|
return;
|
|
157055
157097
|
const parsed = parsePiEventLine(line);
|
|
157056
157098
|
if (!parsed.ok) {
|
|
157099
|
+
if ("noise" in parsed)
|
|
157100
|
+
return;
|
|
157057
157101
|
parseError = parsed.error;
|
|
157058
157102
|
return;
|
|
157059
157103
|
}
|
|
@@ -157280,7 +157324,8 @@ function buildArgs(options, opts) {
|
|
|
157280
157324
|
"json",
|
|
157281
157325
|
"--no-session",
|
|
157282
157326
|
"--no-skills",
|
|
157283
|
-
"--no-prompt-templates"
|
|
157327
|
+
"--no-prompt-templates",
|
|
157328
|
+
"--no-context-files"
|
|
157284
157329
|
];
|
|
157285
157330
|
const shouldLoadSubagentExtension = SUBAGENT_ENTRY_PATH && (SEARCH_ONLY_SUBAGENT_TOOL_AGENTS.has(options.agent) || DREAMER_ACTION_AGENTS.has(options.agent));
|
|
157286
157331
|
if (shouldLoadSubagentExtension) {
|
|
@@ -157300,8 +157345,8 @@ function buildArgs(options, opts) {
|
|
|
157300
157345
|
args.push("--no-tools");
|
|
157301
157346
|
}
|
|
157302
157347
|
}
|
|
157303
|
-
if (
|
|
157304
|
-
args.push("--system-prompt",
|
|
157348
|
+
if (opts?.systemPromptPath) {
|
|
157349
|
+
args.push("--system-prompt", opts.systemPromptPath);
|
|
157305
157350
|
}
|
|
157306
157351
|
if (typeof options.model === "string" && options.model.length > 0) {
|
|
157307
157352
|
args.push("--model", resolveModelRefForPi(options.model));
|
|
@@ -157353,6 +157398,9 @@ function countToolCalls(messages) {
|
|
|
157353
157398
|
return count;
|
|
157354
157399
|
}
|
|
157355
157400
|
function parsePiEventLine(line) {
|
|
157401
|
+
if (!line.trimStart().startsWith("{")) {
|
|
157402
|
+
return { ok: false, noise: true };
|
|
157403
|
+
}
|
|
157356
157404
|
try {
|
|
157357
157405
|
return { ok: true, event: JSON.parse(line) };
|
|
157358
157406
|
} catch (error) {
|
|
@@ -172538,7 +172586,7 @@ var DreamTasksSchema = exports_external.object({
|
|
|
172538
172586
|
}).describe("Per-task scheduling + model config. Each task has its own cron schedule and may override the dreamer-level model.");
|
|
172539
172587
|
var DreamerConfigSchema = AgentOverrideConfigSchema.merge(exports_external.object({
|
|
172540
172588
|
tasks: DreamTasksSchema.default(() => DreamTasksSchema.parse({})),
|
|
172541
|
-
inject_docs: exports_external.boolean().default(true).describe("Inject ARCHITECTURE.md and STRUCTURE.md into
|
|
172589
|
+
inject_docs: exports_external.boolean().default(true).describe("Inject ARCHITECTURE.md and STRUCTURE.md into the m[0] `<project-docs>` block (default true)"),
|
|
172542
172590
|
thinking_level: PiThinkingLevelSchema.describe("Pi only: default thinking level for dreamer subagent invocations. See historian.thinking_level.")
|
|
172543
172591
|
}));
|
|
172544
172592
|
var SidekickConfigSchema = AgentOverrideConfigSchema.extend({
|
|
@@ -174340,6 +174388,7 @@ function enforceProjectCap(db, projectPath, maxCommits) {
|
|
|
174340
174388
|
// ../plugin/src/features/magic-context/git-commits/sweep-coordinator.ts
|
|
174341
174389
|
var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
|
|
174342
174390
|
var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
174391
|
+
var GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
|
|
174343
174392
|
var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
|
|
174344
174393
|
function runImmediate(db, body) {
|
|
174345
174394
|
db.exec("BEGIN IMMEDIATE");
|
|
@@ -174446,6 +174495,20 @@ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
|
|
|
174446
174495
|
return result.changes === 1;
|
|
174447
174496
|
});
|
|
174448
174497
|
}
|
|
174498
|
+
function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWEEP_NON_INDEXABLE_REPROBE_MS) {
|
|
174499
|
+
return runImmediate(db, () => {
|
|
174500
|
+
const now = Date.now();
|
|
174501
|
+
const sweptAt = now + reprobeMs - GIT_SWEEP_COOLDOWN_MS;
|
|
174502
|
+
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
174503
|
+
SET lease_holder = NULL,
|
|
174504
|
+
lease_expires_at = NULL,
|
|
174505
|
+
last_swept_at = ?
|
|
174506
|
+
WHERE project_path = ?
|
|
174507
|
+
AND lease_holder = ?
|
|
174508
|
+
AND lease_expires_at > ?`).run(sweptAt, projectPath, holderId, now);
|
|
174509
|
+
return result.changes === 1;
|
|
174510
|
+
});
|
|
174511
|
+
}
|
|
174449
174512
|
function releaseGitSweepLease(db, projectPath, holderId) {
|
|
174450
174513
|
runImmediate(db, () => {
|
|
174451
174514
|
db.prepare(`UPDATE git_sweep_coordinator
|
|
@@ -179044,7 +179107,7 @@ Output exactly JSON: {"met": false}`;
|
|
|
179044
179107
|
|
|
179045
179108
|
// ../plugin/src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
|
|
179046
179109
|
init_logger();
|
|
179047
|
-
import { existsSync as existsSync10, readFileSync as readFileSync6, writeFileSync as
|
|
179110
|
+
import { existsSync as existsSync10, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
|
|
179048
179111
|
import { join as join11 } from "node:path";
|
|
179049
179112
|
|
|
179050
179113
|
// ../plugin/src/features/magic-context/dreamer/protected-regions.ts
|
|
@@ -179164,7 +179227,7 @@ function enforceMaintainDocsProtectedRegions(args) {
|
|
|
179164
179227
|
if (!violated) {
|
|
179165
179228
|
continue;
|
|
179166
179229
|
}
|
|
179167
|
-
|
|
179230
|
+
writeFileSync6(path9, text, "utf8");
|
|
179168
179231
|
log(`[dreamer] maintain-docs altered a protected region in ${fileName} — restored from pre-task snapshot`);
|
|
179169
179232
|
} catch (error51) {
|
|
179170
179233
|
log(`[dreamer] maintain-docs protected-region enforcement failed for ${fileName}: ${error51}`);
|
|
@@ -181614,11 +181677,21 @@ function recordTransientFailure(db, projectIdentity, due, finishedAt, error51) {
|
|
|
181614
181677
|
});
|
|
181615
181678
|
}
|
|
181616
181679
|
}
|
|
181680
|
+
var LEASE_WAIT_POLL_MS = 2000;
|
|
181681
|
+
var MANUAL_RUN_LEASE_WAIT_MS = 60000;
|
|
181617
181682
|
async function runDomainGroup(deps, group, cb) {
|
|
181618
181683
|
const { db, projectIdentity, executor } = deps;
|
|
181619
181684
|
const leaseKey = leaseKeyFor(group[0].config.task, projectIdentity);
|
|
181620
181685
|
const holderId = crypto.randomUUID();
|
|
181621
|
-
|
|
181686
|
+
let acquired = acquireLease(db, holderId, leaseKey);
|
|
181687
|
+
if (!acquired && cb?.leaseWaitMs) {
|
|
181688
|
+
const deadline = Date.now() + cb.leaseWaitMs;
|
|
181689
|
+
while (!acquired && Date.now() < deadline) {
|
|
181690
|
+
await new Promise((resolve) => setTimeout(resolve, LEASE_WAIT_POLL_MS));
|
|
181691
|
+
acquired = acquireLease(db, holderId, leaseKey);
|
|
181692
|
+
}
|
|
181693
|
+
}
|
|
181694
|
+
if (!acquired) {
|
|
181622
181695
|
log(`[dreamer] domain lease busy (${leaseKey}) — deferring ${group.length} task(s)`);
|
|
181623
181696
|
for (const due of group)
|
|
181624
181697
|
cb?.onBusy?.(due.config.task);
|
|
@@ -181713,6 +181786,7 @@ async function runManualDream(deps) {
|
|
|
181713
181786
|
}
|
|
181714
181787
|
await Promise.all([...groups.values()].map((group) => runDomainGroup({ ...deps, executor: deps.executor }, group, {
|
|
181715
181788
|
forceGate,
|
|
181789
|
+
leaseWaitMs: MANUAL_RUN_LEASE_WAIT_MS,
|
|
181716
181790
|
onRan: (t) => result.ran.push(t),
|
|
181717
181791
|
onFailed: (t) => result.failed.push(t),
|
|
181718
181792
|
onBusy: (t) => result.deferredBusy.push(t)
|
|
@@ -181843,7 +181917,15 @@ var GIT_TIMEOUT_MS3 = 1e4;
|
|
|
181843
181917
|
var DEFAULT_MAX_COMMITS = 5000;
|
|
181844
181918
|
var RECORD_SEPARATOR = "\x1E";
|
|
181845
181919
|
var FIELD_SEPARATOR = "\x1F";
|
|
181846
|
-
|
|
181920
|
+
function classifyGitLogFailure(message) {
|
|
181921
|
+
if (message.includes("not a git repository"))
|
|
181922
|
+
return "not_a_repo";
|
|
181923
|
+
if (message.includes("unknown revision or path not in the working tree") || message.includes("does not have any commits yet") || message.includes("bad revision")) {
|
|
181924
|
+
return "no_head";
|
|
181925
|
+
}
|
|
181926
|
+
return "transient";
|
|
181927
|
+
}
|
|
181928
|
+
async function readGitCommitsResult(directory, options = {}) {
|
|
181847
181929
|
const revision = options.branch ?? "HEAD";
|
|
181848
181930
|
if (revision.startsWith("-")) {
|
|
181849
181931
|
throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
|
|
@@ -181871,13 +181953,18 @@ async function readGitCommits(directory, options = {}) {
|
|
|
181871
181953
|
stdout = result.stdout;
|
|
181872
181954
|
} catch (error51) {
|
|
181873
181955
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
181874
|
-
|
|
181875
|
-
|
|
181956
|
+
const failure = classifyGitLogFailure(message);
|
|
181957
|
+
if (failure === "transient") {
|
|
181958
|
+
log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
|
|
181959
|
+
} else {
|
|
181960
|
+
log(`[git-commits] ${projectLabel} is not indexable (${failure})`);
|
|
181961
|
+
}
|
|
181962
|
+
return { commits: [], failure };
|
|
181876
181963
|
}
|
|
181877
181964
|
if (stdout.trim().length === 0) {
|
|
181878
181965
|
log(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
|
|
181879
181966
|
}
|
|
181880
|
-
return parseGitLogOutput(stdout);
|
|
181967
|
+
return { commits: parseGitLogOutput(stdout), failure: null };
|
|
181881
181968
|
}
|
|
181882
181969
|
function parseGitLogOutput(stdout) {
|
|
181883
181970
|
const commits = [];
|
|
@@ -181933,7 +182020,8 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
|
|
|
181933
182020
|
inserted: 0,
|
|
181934
182021
|
updated: 0,
|
|
181935
182022
|
evicted: 0,
|
|
181936
|
-
embedded: 0
|
|
182023
|
+
embedded: 0,
|
|
182024
|
+
nonIndexable: false
|
|
181937
182025
|
};
|
|
181938
182026
|
if (indexInProgress.has(projectPath)) {
|
|
181939
182027
|
log(`[git-commits] index already in progress for ${projectPath}, skipping`);
|
|
@@ -181943,12 +182031,17 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
|
|
|
181943
182031
|
try {
|
|
181944
182032
|
const latestIndexed = getLatestIndexedCommitTimeMs(db, projectPath);
|
|
181945
182033
|
const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
|
|
181946
|
-
const
|
|
182034
|
+
const read = await readGitCommitsResult(directory, {
|
|
181947
182035
|
sinceMs,
|
|
181948
182036
|
maxCommits: options.maxCommits,
|
|
181949
182037
|
projectIdentity: projectPath
|
|
181950
182038
|
});
|
|
182039
|
+
const commits = read.commits;
|
|
181951
182040
|
result.scanned = commits.length;
|
|
182041
|
+
if (read.failure === "not_a_repo" || read.failure === "no_head") {
|
|
182042
|
+
result.nonIndexable = true;
|
|
182043
|
+
return result;
|
|
182044
|
+
}
|
|
181952
182045
|
if (commits.length === 0) {
|
|
181953
182046
|
result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
|
|
181954
182047
|
log(`[git-commits] no new commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed ?? "none"} evicted=${result.evicted})`);
|
|
@@ -182370,6 +182463,12 @@ async function sweepGitCommits(args) {
|
|
|
182370
182463
|
sinceDays: gitCommitIndexing.since_days,
|
|
182371
182464
|
maxCommits: gitCommitIndexing.max_commits
|
|
182372
182465
|
});
|
|
182466
|
+
if (result.nonIndexable) {
|
|
182467
|
+
if (!parkGitSweepNonIndexable(db, projectIdentity, holderId)) {
|
|
182468
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
182469
|
+
}
|
|
182470
|
+
return;
|
|
182471
|
+
}
|
|
182373
182472
|
let drainedEmbeddings = 0;
|
|
182374
182473
|
if (result.embedded > 0) {
|
|
182375
182474
|
drainedEmbeddings = await embedUnembeddedCommits(db, projectIdentity);
|
|
@@ -184186,7 +184285,7 @@ Unknown task "${requested}".`,
|
|
|
184186
184285
|
if (result.skippedNoWork.length > 0)
|
|
184187
184286
|
lines.push(`Skipped (no work): ${result.skippedNoWork.join(", ")}`);
|
|
184188
184287
|
if (result.deferredBusy.length > 0)
|
|
184189
|
-
lines.push(`Busy
|
|
184288
|
+
lines.push(`Busy: ${result.deferredBusy.join(", ")} — another dream task holds this domain's lease; retry in a minute`);
|
|
184190
184289
|
if (lines.length === 0)
|
|
184191
184290
|
lines.push("No enabled dream tasks to run.");
|
|
184192
184291
|
sendCtxStatusMessage(pi, {
|
|
@@ -189868,6 +189967,13 @@ function safeGetActiveUserMemoriesPi(db) {
|
|
|
189868
189967
|
throw error51;
|
|
189869
189968
|
}
|
|
189870
189969
|
}
|
|
189970
|
+
var EMPTY_PI_PROJECT_DOCS = {
|
|
189971
|
+
renderedBlock: "",
|
|
189972
|
+
canonicalHash: ""
|
|
189973
|
+
};
|
|
189974
|
+
function readProjectDocsForPiM0(state) {
|
|
189975
|
+
return state.injectDocs !== false ? readProjectDocsCanonical(state.projectDirectory) : EMPTY_PI_PROJECT_DOCS;
|
|
189976
|
+
}
|
|
189871
189977
|
function memoryProjectPath(state) {
|
|
189872
189978
|
return state.memoryEnabled === false ? undefined : state.projectIdentity;
|
|
189873
189979
|
}
|
|
@@ -189994,7 +190100,7 @@ function readCurrentMarkersFromCompartments(db, state, compartments, projectDocs
|
|
|
189994
190100
|
projectMemoryEpoch: projectState?.projectMemoryEpoch ?? 0,
|
|
189995
190101
|
workspaceFingerprint: workspace.isWorkspaced ? computeWorkspaceEpochFingerprint(db, workspace.identities) : null,
|
|
189996
190102
|
projectUserProfileVersion: globalState?.projectUserProfileVersion ?? 0,
|
|
189997
|
-
projectDocsHash: projectDocsHash ??
|
|
190103
|
+
projectDocsHash: projectDocsHash ?? readProjectDocsForPiM0(state).canonicalHash,
|
|
189998
190104
|
sessionFactsVersion: getSessionFactsVersion(db, state.sessionId),
|
|
189999
190105
|
materializedAt: Date.now(),
|
|
190000
190106
|
upgradeState: `${PI_M0_UPGRADE_STATE}:${compartments.some((c) => c.legacy === 1) ? "legacy" : "ready"}`,
|
|
@@ -190055,7 +190161,7 @@ ${memories.map((memory) => `- ${escapeXmlContent(memory.content)}`).join(`
|
|
|
190055
190161
|
`)}
|
|
190056
190162
|
</${wrapper}>`;
|
|
190057
190163
|
}
|
|
190058
|
-
function renderM0Pi(state, db, projectDocs =
|
|
190164
|
+
function renderM0Pi(state, db, projectDocs = readProjectDocsForPiM0(state).renderedBlock, decayPressureMultiplier = 1, memoriesOverride, compartmentsOverride, userProfileOverride, workspaceOverride) {
|
|
190059
190165
|
const memPath = memoryProjectPath(state);
|
|
190060
190166
|
const workspace = workspaceOverride ?? resolveWorkspaceRenderContextPi(state, db);
|
|
190061
190167
|
const allMemories = memoriesOverride ?? (memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(db, memPath, ["active", "permanent"]) : []);
|
|
@@ -190123,7 +190229,7 @@ class PiMaterializeContentionError extends Error {
|
|
|
190123
190229
|
this.name = "PiMaterializeContentionError";
|
|
190124
190230
|
}
|
|
190125
190231
|
}
|
|
190126
|
-
function readFrozenM0InputsPi(state, db, docs =
|
|
190232
|
+
function readFrozenM0InputsPi(state, db, docs = readProjectDocsForPiM0(state), memoryCutoff) {
|
|
190127
190233
|
const memPath = memoryProjectPath(state);
|
|
190128
190234
|
const read = db.transaction(() => {
|
|
190129
190235
|
const workspace = resolveWorkspaceRenderContextPi(state, db);
|
|
@@ -190154,7 +190260,7 @@ function readFrozenM0InputsPi(state, db, docs = readProjectDocsCanonical(state.p
|
|
|
190154
190260
|
return read();
|
|
190155
190261
|
}
|
|
190156
190262
|
function renderFreshM0PiNonPersisted(state, db) {
|
|
190157
|
-
const docs =
|
|
190263
|
+
const docs = readProjectDocsForPiM0(state);
|
|
190158
190264
|
const cachedMaterializedAt = getOrCreateSessionMeta(db, state.sessionId).cachedM0MaterializedAt ?? 0;
|
|
190159
190265
|
const frozen = readFrozenM0InputsPi(state, db, docs, cachedMaterializedAt);
|
|
190160
190266
|
frozen.markers.materializedAt = cachedMaterializedAt;
|
|
@@ -190174,7 +190280,7 @@ function renderFreshM0PiNonPersisted(state, db) {
|
|
|
190174
190280
|
};
|
|
190175
190281
|
}
|
|
190176
190282
|
function materializeM0Pi(state, db) {
|
|
190177
|
-
const docs =
|
|
190283
|
+
const docs = readProjectDocsForPiM0(state);
|
|
190178
190284
|
const foldMaterializedAt = Date.now();
|
|
190179
190285
|
const frozen = readFrozenM0InputsPi(state, db, docs, foldMaterializedAt);
|
|
190180
190286
|
const snapshotMarkers = frozen.markers;
|
|
@@ -190192,7 +190298,7 @@ function materializeM0Pi(state, db) {
|
|
|
190192
190298
|
attempts += 1;
|
|
190193
190299
|
}
|
|
190194
190300
|
const m0Bytes = Buffer.from(m0, "utf8");
|
|
190195
|
-
const phase3ProjectDocsHash =
|
|
190301
|
+
const phase3ProjectDocsHash = readProjectDocsForPiM0(state).canonicalHash;
|
|
190196
190302
|
try {
|
|
190197
190303
|
db.exec("BEGIN IMMEDIATE");
|
|
190198
190304
|
} catch (error51) {
|
|
@@ -194524,6 +194630,9 @@ function getMessageId(message) {
|
|
|
194524
194630
|
}
|
|
194525
194631
|
return "";
|
|
194526
194632
|
}
|
|
194633
|
+
function isReplayableAnchor(message) {
|
|
194634
|
+
return message.stopReason !== "aborted" && message.stopReason !== "error";
|
|
194635
|
+
}
|
|
194527
194636
|
function hasToolCallWithId(message, callId) {
|
|
194528
194637
|
if (!Array.isArray(message.content))
|
|
194529
194638
|
return false;
|
|
@@ -194580,6 +194689,8 @@ function injectByAssistantId(messages, messageId, part) {
|
|
|
194580
194689
|
const assistant = m;
|
|
194581
194690
|
if (getMessageId(assistant) !== messageId)
|
|
194582
194691
|
continue;
|
|
194692
|
+
if (!isReplayableAnchor(assistant))
|
|
194693
|
+
return false;
|
|
194583
194694
|
if (hasToolCallWithId(assistant, part.callID)) {
|
|
194584
194695
|
if (findToolResultAfter(messages, i, part.callID) >= 0)
|
|
194585
194696
|
return true;
|
|
@@ -194605,6 +194716,8 @@ function injectIntoLatestAssistant(messages, part) {
|
|
|
194605
194716
|
if (m.role !== "assistant")
|
|
194606
194717
|
continue;
|
|
194607
194718
|
const assistant = m;
|
|
194719
|
+
if (!isReplayableAnchor(assistant))
|
|
194720
|
+
continue;
|
|
194608
194721
|
const id = getMessageId(assistant);
|
|
194609
194722
|
if (id.length === 0)
|
|
194610
194723
|
continue;
|
|
@@ -197323,6 +197436,7 @@ async function runPipeline(args) {
|
|
|
197323
197436
|
projectIdentity: args.projectIdentity,
|
|
197324
197437
|
projectDirectory: args.projectDirectory,
|
|
197325
197438
|
memoryEnabled: args.injection.memoryEnabled,
|
|
197439
|
+
injectDocs: args.injection.injectDocs,
|
|
197326
197440
|
injectionBudgetTokens: args.injection.injectionBudgetTokens,
|
|
197327
197441
|
historyBudgetTokens: args.injection.historyBudgetTokens,
|
|
197328
197442
|
hardSignals: piHardSignals
|
|
@@ -197634,7 +197748,7 @@ ${result}`;
|
|
|
197634
197748
|
init_logger();
|
|
197635
197749
|
|
|
197636
197750
|
// ../plugin/src/hooks/magic-context/historian-state-file.ts
|
|
197637
|
-
import { mkdirSync as mkdirSync8, unlinkSync as unlinkSync2, writeFileSync as
|
|
197751
|
+
import { mkdirSync as mkdirSync8, unlinkSync as unlinkSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
197638
197752
|
init_data_path();
|
|
197639
197753
|
function cleanupHistorianStateFile(path11) {
|
|
197640
197754
|
if (!path11)
|
|
@@ -197727,7 +197841,7 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
|
|
|
197727
197841
|
}
|
|
197728
197842
|
|
|
197729
197843
|
// ../plugin/src/hooks/magic-context/compartment-runner-historian.ts
|
|
197730
|
-
import { mkdirSync as mkdirSync9, unlinkSync as unlinkSync3, writeFileSync as
|
|
197844
|
+
import { mkdirSync as mkdirSync9, unlinkSync as unlinkSync3, writeFileSync as writeFileSync8 } from "node:fs";
|
|
197731
197845
|
import { join as join12 } from "node:path";
|
|
197732
197846
|
|
|
197733
197847
|
// ../plugin/src/agents/historian.ts
|
|
@@ -198047,7 +198161,7 @@ function dumpHistorianResponse(sessionId, directory, label, text) {
|
|
|
198047
198161
|
const safeSessionId = sanitizeDumpName(sessionId);
|
|
198048
198162
|
const safeLabel = sanitizeDumpName(label);
|
|
198049
198163
|
const dumpPath = join12(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
|
|
198050
|
-
|
|
198164
|
+
writeFileSync8(dumpPath, text, "utf8");
|
|
198051
198165
|
sessionLog(sessionId, "compartment agent: historian response dumped", {
|
|
198052
198166
|
label,
|
|
198053
198167
|
dumpPath
|
|
@@ -200012,7 +200126,7 @@ function formatThresholdPercent(value) {
|
|
|
200012
200126
|
// package.json
|
|
200013
200127
|
var package_default = {
|
|
200014
200128
|
name: "@cortexkit/pi-magic-context",
|
|
200015
|
-
version: "0.30.
|
|
200129
|
+
version: "0.30.6",
|
|
200016
200130
|
type: "module",
|
|
200017
200131
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
200018
200132
|
main: "dist/index.js",
|
|
@@ -206458,6 +206572,7 @@ async function src_default2(pi) {
|
|
|
206458
206572
|
},
|
|
206459
206573
|
injection: {
|
|
206460
206574
|
memoryEnabled: cfg.memory.enabled,
|
|
206575
|
+
injectDocs: cfg.dreamer?.inject_docs !== false,
|
|
206461
206576
|
injectionBudgetTokens: cfg.memory.injection_budget_tokens,
|
|
206462
206577
|
temporalAwareness: cfg.temporal_awareness === true
|
|
206463
206578
|
},
|
|
@@ -206686,13 +206801,11 @@ async function src_default2(pi) {
|
|
|
206686
206801
|
}
|
|
206687
206802
|
const isCacheBusting = sessionId ? hasSystemPromptRefresh(sessionId) : true;
|
|
206688
206803
|
const effectiveDreamerRunnable = switchedProject ? isDreamerRunnable(effectiveConfig) : isDreamerRunnable(config2);
|
|
206689
|
-
const injectDocs = switchedProject ? effectiveDreamerRunnable && (effectiveConfig.dreamer?.inject_docs ?? true) : isDreamerRunnable(config2) && (config2.dreamer?.inject_docs ?? true);
|
|
206690
206804
|
const block = buildMagicContextBlock({
|
|
206691
206805
|
db,
|
|
206692
206806
|
cwd: currentProject.projectDir,
|
|
206693
206807
|
sessionId,
|
|
206694
206808
|
memoryEnabled: effectiveConfig.memory.enabled,
|
|
206695
|
-
injectDocs,
|
|
206696
206809
|
includeGuidance: true,
|
|
206697
206810
|
protectedTags: effectiveConfig.protected_tags,
|
|
206698
206811
|
ctxReduceEnabled: effectiveConfig.ctx_reduce_enabled,
|
package/dist/subagent-entry.js
CHANGED
|
@@ -159656,7 +159656,7 @@ var DreamTasksSchema = exports_external.object({
|
|
|
159656
159656
|
}).describe("Per-task scheduling + model config. Each task has its own cron schedule and may override the dreamer-level model.");
|
|
159657
159657
|
var DreamerConfigSchema = AgentOverrideConfigSchema.merge(exports_external.object({
|
|
159658
159658
|
tasks: DreamTasksSchema.default(() => DreamTasksSchema.parse({})),
|
|
159659
|
-
inject_docs: exports_external.boolean().default(true).describe("Inject ARCHITECTURE.md and STRUCTURE.md into
|
|
159659
|
+
inject_docs: exports_external.boolean().default(true).describe("Inject ARCHITECTURE.md and STRUCTURE.md into the m[0] `<project-docs>` block (default true)"),
|
|
159660
159660
|
thinking_level: PiThinkingLevelSchema.describe("Pi only: default thinking level for dreamer subagent invocations. See historian.thinking_level.")
|
|
159661
159661
|
}));
|
|
159662
159662
|
var SidekickConfigSchema = AgentOverrideConfigSchema.extend({
|
|
@@ -161941,6 +161941,7 @@ function enforceProjectCap(db, projectPath, maxCommits) {
|
|
|
161941
161941
|
// ../plugin/src/features/magic-context/git-commits/sweep-coordinator.ts
|
|
161942
161942
|
var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
|
|
161943
161943
|
var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
161944
|
+
var GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
|
|
161944
161945
|
var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
|
|
161945
161946
|
function runImmediate(db, body) {
|
|
161946
161947
|
db.exec("BEGIN IMMEDIATE");
|
|
@@ -162047,6 +162048,20 @@ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
|
|
|
162047
162048
|
return result.changes === 1;
|
|
162048
162049
|
});
|
|
162049
162050
|
}
|
|
162051
|
+
function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWEEP_NON_INDEXABLE_REPROBE_MS) {
|
|
162052
|
+
return runImmediate(db, () => {
|
|
162053
|
+
const now = Date.now();
|
|
162054
|
+
const sweptAt = now + reprobeMs - GIT_SWEEP_COOLDOWN_MS;
|
|
162055
|
+
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
162056
|
+
SET lease_holder = NULL,
|
|
162057
|
+
lease_expires_at = NULL,
|
|
162058
|
+
last_swept_at = ?
|
|
162059
|
+
WHERE project_path = ?
|
|
162060
|
+
AND lease_holder = ?
|
|
162061
|
+
AND lease_expires_at > ?`).run(sweptAt, projectPath, holderId, now);
|
|
162062
|
+
return result.changes === 1;
|
|
162063
|
+
});
|
|
162064
|
+
}
|
|
162050
162065
|
function releaseGitSweepLease(db, projectPath, holderId) {
|
|
162051
162066
|
runImmediate(db, () => {
|
|
162052
162067
|
db.prepare(`UPDATE git_sweep_coordinator
|
|
@@ -173417,7 +173432,15 @@ var GIT_TIMEOUT_MS3 = 1e4;
|
|
|
173417
173432
|
var DEFAULT_MAX_COMMITS = 5000;
|
|
173418
173433
|
var RECORD_SEPARATOR = "\x1E";
|
|
173419
173434
|
var FIELD_SEPARATOR = "\x1F";
|
|
173420
|
-
|
|
173435
|
+
function classifyGitLogFailure(message) {
|
|
173436
|
+
if (message.includes("not a git repository"))
|
|
173437
|
+
return "not_a_repo";
|
|
173438
|
+
if (message.includes("unknown revision or path not in the working tree") || message.includes("does not have any commits yet") || message.includes("bad revision")) {
|
|
173439
|
+
return "no_head";
|
|
173440
|
+
}
|
|
173441
|
+
return "transient";
|
|
173442
|
+
}
|
|
173443
|
+
async function readGitCommitsResult(directory, options = {}) {
|
|
173421
173444
|
const revision = options.branch ?? "HEAD";
|
|
173422
173445
|
if (revision.startsWith("-")) {
|
|
173423
173446
|
throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
|
|
@@ -173445,13 +173468,18 @@ async function readGitCommits(directory, options = {}) {
|
|
|
173445
173468
|
stdout = result.stdout;
|
|
173446
173469
|
} catch (error51) {
|
|
173447
173470
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
173448
|
-
|
|
173449
|
-
|
|
173471
|
+
const failure = classifyGitLogFailure(message);
|
|
173472
|
+
if (failure === "transient") {
|
|
173473
|
+
log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
|
|
173474
|
+
} else {
|
|
173475
|
+
log(`[git-commits] ${projectLabel} is not indexable (${failure})`);
|
|
173476
|
+
}
|
|
173477
|
+
return { commits: [], failure };
|
|
173450
173478
|
}
|
|
173451
173479
|
if (stdout.trim().length === 0) {
|
|
173452
173480
|
log(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
|
|
173453
173481
|
}
|
|
173454
|
-
return parseGitLogOutput(stdout);
|
|
173482
|
+
return { commits: parseGitLogOutput(stdout), failure: null };
|
|
173455
173483
|
}
|
|
173456
173484
|
function parseGitLogOutput(stdout) {
|
|
173457
173485
|
const commits = [];
|
|
@@ -173507,7 +173535,8 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
|
|
|
173507
173535
|
inserted: 0,
|
|
173508
173536
|
updated: 0,
|
|
173509
173537
|
evicted: 0,
|
|
173510
|
-
embedded: 0
|
|
173538
|
+
embedded: 0,
|
|
173539
|
+
nonIndexable: false
|
|
173511
173540
|
};
|
|
173512
173541
|
if (indexInProgress.has(projectPath)) {
|
|
173513
173542
|
log(`[git-commits] index already in progress for ${projectPath}, skipping`);
|
|
@@ -173517,12 +173546,17 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
|
|
|
173517
173546
|
try {
|
|
173518
173547
|
const latestIndexed = getLatestIndexedCommitTimeMs(db, projectPath);
|
|
173519
173548
|
const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
|
|
173520
|
-
const
|
|
173549
|
+
const read = await readGitCommitsResult(directory, {
|
|
173521
173550
|
sinceMs,
|
|
173522
173551
|
maxCommits: options.maxCommits,
|
|
173523
173552
|
projectIdentity: projectPath
|
|
173524
173553
|
});
|
|
173554
|
+
const commits = read.commits;
|
|
173525
173555
|
result.scanned = commits.length;
|
|
173556
|
+
if (read.failure === "not_a_repo" || read.failure === "no_head") {
|
|
173557
|
+
result.nonIndexable = true;
|
|
173558
|
+
return result;
|
|
173559
|
+
}
|
|
173526
173560
|
if (commits.length === 0) {
|
|
173527
173561
|
result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
|
|
173528
173562
|
log(`[git-commits] no new commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed ?? "none"} evicted=${result.evicted})`);
|
package/package.json
CHANGED