@cortexkit/pi-magic-context 0.30.5 → 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 +72 -9
- package/dist/subagent-entry.js +40 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -157096,6 +157096,8 @@ class PiSubagentRunner {
|
|
|
157096
157096
|
return;
|
|
157097
157097
|
const parsed = parsePiEventLine(line);
|
|
157098
157098
|
if (!parsed.ok) {
|
|
157099
|
+
if ("noise" in parsed)
|
|
157100
|
+
return;
|
|
157099
157101
|
parseError = parsed.error;
|
|
157100
157102
|
return;
|
|
157101
157103
|
}
|
|
@@ -157396,6 +157398,9 @@ function countToolCalls(messages) {
|
|
|
157396
157398
|
return count;
|
|
157397
157399
|
}
|
|
157398
157400
|
function parsePiEventLine(line) {
|
|
157401
|
+
if (!line.trimStart().startsWith("{")) {
|
|
157402
|
+
return { ok: false, noise: true };
|
|
157403
|
+
}
|
|
157399
157404
|
try {
|
|
157400
157405
|
return { ok: true, event: JSON.parse(line) };
|
|
157401
157406
|
} catch (error) {
|
|
@@ -174383,6 +174388,7 @@ function enforceProjectCap(db, projectPath, maxCommits) {
|
|
|
174383
174388
|
// ../plugin/src/features/magic-context/git-commits/sweep-coordinator.ts
|
|
174384
174389
|
var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
|
|
174385
174390
|
var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
174391
|
+
var GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
|
|
174386
174392
|
var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
|
|
174387
174393
|
function runImmediate(db, body) {
|
|
174388
174394
|
db.exec("BEGIN IMMEDIATE");
|
|
@@ -174489,6 +174495,20 @@ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
|
|
|
174489
174495
|
return result.changes === 1;
|
|
174490
174496
|
});
|
|
174491
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
|
+
}
|
|
174492
174512
|
function releaseGitSweepLease(db, projectPath, holderId) {
|
|
174493
174513
|
runImmediate(db, () => {
|
|
174494
174514
|
db.prepare(`UPDATE git_sweep_coordinator
|
|
@@ -181657,11 +181677,21 @@ function recordTransientFailure(db, projectIdentity, due, finishedAt, error51) {
|
|
|
181657
181677
|
});
|
|
181658
181678
|
}
|
|
181659
181679
|
}
|
|
181680
|
+
var LEASE_WAIT_POLL_MS = 2000;
|
|
181681
|
+
var MANUAL_RUN_LEASE_WAIT_MS = 60000;
|
|
181660
181682
|
async function runDomainGroup(deps, group, cb) {
|
|
181661
181683
|
const { db, projectIdentity, executor } = deps;
|
|
181662
181684
|
const leaseKey = leaseKeyFor(group[0].config.task, projectIdentity);
|
|
181663
181685
|
const holderId = crypto.randomUUID();
|
|
181664
|
-
|
|
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) {
|
|
181665
181695
|
log(`[dreamer] domain lease busy (${leaseKey}) — deferring ${group.length} task(s)`);
|
|
181666
181696
|
for (const due of group)
|
|
181667
181697
|
cb?.onBusy?.(due.config.task);
|
|
@@ -181756,6 +181786,7 @@ async function runManualDream(deps) {
|
|
|
181756
181786
|
}
|
|
181757
181787
|
await Promise.all([...groups.values()].map((group) => runDomainGroup({ ...deps, executor: deps.executor }, group, {
|
|
181758
181788
|
forceGate,
|
|
181789
|
+
leaseWaitMs: MANUAL_RUN_LEASE_WAIT_MS,
|
|
181759
181790
|
onRan: (t) => result.ran.push(t),
|
|
181760
181791
|
onFailed: (t) => result.failed.push(t),
|
|
181761
181792
|
onBusy: (t) => result.deferredBusy.push(t)
|
|
@@ -181886,7 +181917,15 @@ var GIT_TIMEOUT_MS3 = 1e4;
|
|
|
181886
181917
|
var DEFAULT_MAX_COMMITS = 5000;
|
|
181887
181918
|
var RECORD_SEPARATOR = "\x1E";
|
|
181888
181919
|
var FIELD_SEPARATOR = "\x1F";
|
|
181889
|
-
|
|
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 = {}) {
|
|
181890
181929
|
const revision = options.branch ?? "HEAD";
|
|
181891
181930
|
if (revision.startsWith("-")) {
|
|
181892
181931
|
throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
|
|
@@ -181914,13 +181953,18 @@ async function readGitCommits(directory, options = {}) {
|
|
|
181914
181953
|
stdout = result.stdout;
|
|
181915
181954
|
} catch (error51) {
|
|
181916
181955
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
181917
|
-
|
|
181918
|
-
|
|
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 };
|
|
181919
181963
|
}
|
|
181920
181964
|
if (stdout.trim().length === 0) {
|
|
181921
181965
|
log(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
|
|
181922
181966
|
}
|
|
181923
|
-
return parseGitLogOutput(stdout);
|
|
181967
|
+
return { commits: parseGitLogOutput(stdout), failure: null };
|
|
181924
181968
|
}
|
|
181925
181969
|
function parseGitLogOutput(stdout) {
|
|
181926
181970
|
const commits = [];
|
|
@@ -181976,7 +182020,8 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
|
|
|
181976
182020
|
inserted: 0,
|
|
181977
182021
|
updated: 0,
|
|
181978
182022
|
evicted: 0,
|
|
181979
|
-
embedded: 0
|
|
182023
|
+
embedded: 0,
|
|
182024
|
+
nonIndexable: false
|
|
181980
182025
|
};
|
|
181981
182026
|
if (indexInProgress.has(projectPath)) {
|
|
181982
182027
|
log(`[git-commits] index already in progress for ${projectPath}, skipping`);
|
|
@@ -181986,12 +182031,17 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
|
|
|
181986
182031
|
try {
|
|
181987
182032
|
const latestIndexed = getLatestIndexedCommitTimeMs(db, projectPath);
|
|
181988
182033
|
const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
|
|
181989
|
-
const
|
|
182034
|
+
const read = await readGitCommitsResult(directory, {
|
|
181990
182035
|
sinceMs,
|
|
181991
182036
|
maxCommits: options.maxCommits,
|
|
181992
182037
|
projectIdentity: projectPath
|
|
181993
182038
|
});
|
|
182039
|
+
const commits = read.commits;
|
|
181994
182040
|
result.scanned = commits.length;
|
|
182041
|
+
if (read.failure === "not_a_repo" || read.failure === "no_head") {
|
|
182042
|
+
result.nonIndexable = true;
|
|
182043
|
+
return result;
|
|
182044
|
+
}
|
|
181995
182045
|
if (commits.length === 0) {
|
|
181996
182046
|
result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
|
|
181997
182047
|
log(`[git-commits] no new commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed ?? "none"} evicted=${result.evicted})`);
|
|
@@ -182413,6 +182463,12 @@ async function sweepGitCommits(args) {
|
|
|
182413
182463
|
sinceDays: gitCommitIndexing.since_days,
|
|
182414
182464
|
maxCommits: gitCommitIndexing.max_commits
|
|
182415
182465
|
});
|
|
182466
|
+
if (result.nonIndexable) {
|
|
182467
|
+
if (!parkGitSweepNonIndexable(db, projectIdentity, holderId)) {
|
|
182468
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
182469
|
+
}
|
|
182470
|
+
return;
|
|
182471
|
+
}
|
|
182416
182472
|
let drainedEmbeddings = 0;
|
|
182417
182473
|
if (result.embedded > 0) {
|
|
182418
182474
|
drainedEmbeddings = await embedUnembeddedCommits(db, projectIdentity);
|
|
@@ -184229,7 +184285,7 @@ Unknown task "${requested}".`,
|
|
|
184229
184285
|
if (result.skippedNoWork.length > 0)
|
|
184230
184286
|
lines.push(`Skipped (no work): ${result.skippedNoWork.join(", ")}`);
|
|
184231
184287
|
if (result.deferredBusy.length > 0)
|
|
184232
|
-
lines.push(`Busy
|
|
184288
|
+
lines.push(`Busy: ${result.deferredBusy.join(", ")} — another dream task holds this domain's lease; retry in a minute`);
|
|
184233
184289
|
if (lines.length === 0)
|
|
184234
184290
|
lines.push("No enabled dream tasks to run.");
|
|
184235
184291
|
sendCtxStatusMessage(pi, {
|
|
@@ -194574,6 +194630,9 @@ function getMessageId(message) {
|
|
|
194574
194630
|
}
|
|
194575
194631
|
return "";
|
|
194576
194632
|
}
|
|
194633
|
+
function isReplayableAnchor(message) {
|
|
194634
|
+
return message.stopReason !== "aborted" && message.stopReason !== "error";
|
|
194635
|
+
}
|
|
194577
194636
|
function hasToolCallWithId(message, callId) {
|
|
194578
194637
|
if (!Array.isArray(message.content))
|
|
194579
194638
|
return false;
|
|
@@ -194630,6 +194689,8 @@ function injectByAssistantId(messages, messageId, part) {
|
|
|
194630
194689
|
const assistant = m;
|
|
194631
194690
|
if (getMessageId(assistant) !== messageId)
|
|
194632
194691
|
continue;
|
|
194692
|
+
if (!isReplayableAnchor(assistant))
|
|
194693
|
+
return false;
|
|
194633
194694
|
if (hasToolCallWithId(assistant, part.callID)) {
|
|
194634
194695
|
if (findToolResultAfter(messages, i, part.callID) >= 0)
|
|
194635
194696
|
return true;
|
|
@@ -194655,6 +194716,8 @@ function injectIntoLatestAssistant(messages, part) {
|
|
|
194655
194716
|
if (m.role !== "assistant")
|
|
194656
194717
|
continue;
|
|
194657
194718
|
const assistant = m;
|
|
194719
|
+
if (!isReplayableAnchor(assistant))
|
|
194720
|
+
continue;
|
|
194658
194721
|
const id = getMessageId(assistant);
|
|
194659
194722
|
if (id.length === 0)
|
|
194660
194723
|
continue;
|
|
@@ -200063,7 +200126,7 @@ function formatThresholdPercent(value) {
|
|
|
200063
200126
|
// package.json
|
|
200064
200127
|
var package_default = {
|
|
200065
200128
|
name: "@cortexkit/pi-magic-context",
|
|
200066
|
-
version: "0.30.
|
|
200129
|
+
version: "0.30.6",
|
|
200067
200130
|
type: "module",
|
|
200068
200131
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
200069
200132
|
main: "dist/index.js",
|
package/dist/subagent-entry.js
CHANGED
|
@@ -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