@cortexkit/pi-magic-context 0.21.4 → 0.21.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 +534 -100
- package/dist/subagent-entry.js +207 -14
- package/package.json +1 -1
package/dist/subagent-entry.js
CHANGED
|
@@ -8489,8 +8489,10 @@ function deleteOrphanProjectKeyFiles(db, now = Date.now()) {
|
|
|
8489
8489
|
if (existsSync2(row.projectPath))
|
|
8490
8490
|
continue;
|
|
8491
8491
|
try {
|
|
8492
|
-
db.
|
|
8493
|
-
|
|
8492
|
+
db.transaction(() => {
|
|
8493
|
+
db.prepare("DELETE FROM project_key_files WHERE project_path = ?").run(row.projectPath);
|
|
8494
|
+
db.prepare("DELETE FROM project_key_files_version WHERE project_path = ?").run(row.projectPath);
|
|
8495
|
+
})();
|
|
8494
8496
|
deletedProjects++;
|
|
8495
8497
|
} catch (error) {
|
|
8496
8498
|
log(`[key-files] orphan GC failed for ${row.projectPath}:`, error);
|
|
@@ -8897,6 +8899,16 @@ var MIGRATIONS = [
|
|
|
8897
8899
|
WHERE auto_search_hint_decisions IS NULL
|
|
8898
8900
|
`);
|
|
8899
8901
|
}
|
|
8902
|
+
},
|
|
8903
|
+
{
|
|
8904
|
+
version: 18,
|
|
8905
|
+
description: "Add pending_pi_compaction_marker_state column for Pi deferred marker drain",
|
|
8906
|
+
up: (db) => {
|
|
8907
|
+
const cols = db.prepare("PRAGMA table_info(session_meta)").all();
|
|
8908
|
+
if (!cols.some((c) => c.name === "pending_pi_compaction_marker_state")) {
|
|
8909
|
+
db.exec("ALTER TABLE session_meta ADD COLUMN pending_pi_compaction_marker_state TEXT");
|
|
8910
|
+
}
|
|
8911
|
+
}
|
|
8900
8912
|
}
|
|
8901
8913
|
];
|
|
8902
8914
|
function ensureMigrationsTable(db) {
|
|
@@ -8912,7 +8924,7 @@ function getCurrentVersion(db) {
|
|
|
8912
8924
|
const row = db.prepare("SELECT MAX(version) as version FROM schema_migrations").get();
|
|
8913
8925
|
return row?.version ?? 0;
|
|
8914
8926
|
}
|
|
8915
|
-
function isSiblingMigrationConflict(error, version) {
|
|
8927
|
+
function isSiblingMigrationConflict(db, error, version) {
|
|
8916
8928
|
if (!(error instanceof Error))
|
|
8917
8929
|
return false;
|
|
8918
8930
|
const code = error.code;
|
|
@@ -8924,7 +8936,8 @@ function isSiblingMigrationConflict(error, version) {
|
|
|
8924
8936
|
return false;
|
|
8925
8937
|
if (!msg.toLowerCase().includes("version"))
|
|
8926
8938
|
return false;
|
|
8927
|
-
|
|
8939
|
+
const confirmed = db.prepare("SELECT 1 FROM schema_migrations WHERE version = ?").get(version);
|
|
8940
|
+
return confirmed != null;
|
|
8928
8941
|
}
|
|
8929
8942
|
function runMigrations(db) {
|
|
8930
8943
|
ensureMigrationsTable(db);
|
|
@@ -8945,7 +8958,7 @@ function runMigrations(db) {
|
|
|
8945
8958
|
log(`[migrations] applied v${migration.version}: ${migration.description}`);
|
|
8946
8959
|
migrationIndex += 1;
|
|
8947
8960
|
} catch (error) {
|
|
8948
|
-
if (isSiblingMigrationConflict(error, migration.version)) {
|
|
8961
|
+
if (isSiblingMigrationConflict(db, error, migration.version)) {
|
|
8949
8962
|
log(`[migrations] v${migration.version} already applied by sibling instance — resuming with re-read version`);
|
|
8950
8963
|
const reReadVersion = getCurrentVersion(db);
|
|
8951
8964
|
if (reReadVersion <= currentVersion) {
|
|
@@ -142134,6 +142147,11 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142134
142147
|
-- Excluded from healNullTextColumns. Readers filter IS NOT NULL AND
|
|
142135
142148
|
-- != empty-string defensively. Plan v6 section 3.
|
|
142136
142149
|
pending_compaction_marker_state TEXT,
|
|
142150
|
+
-- pending_pi_compaction_marker_state: intentionally NULLABLE without a
|
|
142151
|
+
-- default. Absence of a deferred Pi-native marker is SQL NULL; presence
|
|
142152
|
+
-- is a valid JSON blob written via setPendingPiCompactionMarkerState.
|
|
142153
|
+
-- Excluded from healNullTextColumns.
|
|
142154
|
+
pending_pi_compaction_marker_state TEXT,
|
|
142137
142155
|
-- deferred_execute_state: intentionally NULLABLE without a default.
|
|
142138
142156
|
-- Absence is SQL NULL; presence is a JSON blob written via
|
|
142139
142157
|
-- setDeferredExecutePendingIfAbsent. Excluded from healNullTextColumns.
|
|
@@ -142230,6 +142248,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142230
142248
|
ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
|
|
142231
142249
|
ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
|
|
142232
142250
|
ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
|
|
142251
|
+
ensureColumn(db, "session_meta", "pending_pi_compaction_marker_state", "TEXT");
|
|
142233
142252
|
ensureColumn(db, "session_meta", "deferred_execute_state", "TEXT");
|
|
142234
142253
|
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
142235
142254
|
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
@@ -156867,11 +156886,124 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
156867
156886
|
import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
|
|
156868
156887
|
import { homedir as homedir2 } from "node:os";
|
|
156869
156888
|
import { dirname as dirname3, isAbsolute, resolve as resolve2 } from "node:path";
|
|
156889
|
+
|
|
156890
|
+
// ../plugin/src/shared/jsonc-parser.ts
|
|
156891
|
+
function stripJsonComments(content) {
|
|
156892
|
+
let result = "";
|
|
156893
|
+
let inString = false;
|
|
156894
|
+
let escaped = false;
|
|
156895
|
+
let inLineComment = false;
|
|
156896
|
+
let inBlockComment = false;
|
|
156897
|
+
for (let index = 0;index < content.length; index += 1) {
|
|
156898
|
+
const char = content[index];
|
|
156899
|
+
const next = content[index + 1];
|
|
156900
|
+
if (inLineComment) {
|
|
156901
|
+
if (char === `
|
|
156902
|
+
`) {
|
|
156903
|
+
inLineComment = false;
|
|
156904
|
+
result += char;
|
|
156905
|
+
}
|
|
156906
|
+
continue;
|
|
156907
|
+
}
|
|
156908
|
+
if (inBlockComment) {
|
|
156909
|
+
if (char === "*" && next === "/") {
|
|
156910
|
+
inBlockComment = false;
|
|
156911
|
+
index += 1;
|
|
156912
|
+
}
|
|
156913
|
+
continue;
|
|
156914
|
+
}
|
|
156915
|
+
if (inString) {
|
|
156916
|
+
result += char;
|
|
156917
|
+
if (escaped) {
|
|
156918
|
+
escaped = false;
|
|
156919
|
+
} else if (char === "\\") {
|
|
156920
|
+
escaped = true;
|
|
156921
|
+
} else if (char === '"') {
|
|
156922
|
+
inString = false;
|
|
156923
|
+
}
|
|
156924
|
+
continue;
|
|
156925
|
+
}
|
|
156926
|
+
if (char === '"') {
|
|
156927
|
+
inString = true;
|
|
156928
|
+
result += char;
|
|
156929
|
+
continue;
|
|
156930
|
+
}
|
|
156931
|
+
if (char === "/" && next === "/") {
|
|
156932
|
+
inLineComment = true;
|
|
156933
|
+
index += 1;
|
|
156934
|
+
continue;
|
|
156935
|
+
}
|
|
156936
|
+
if (char === "/" && next === "*") {
|
|
156937
|
+
inBlockComment = true;
|
|
156938
|
+
index += 1;
|
|
156939
|
+
continue;
|
|
156940
|
+
}
|
|
156941
|
+
result += char;
|
|
156942
|
+
}
|
|
156943
|
+
return result;
|
|
156944
|
+
}
|
|
156945
|
+
function stripTrailingCommas(content) {
|
|
156946
|
+
let result = "";
|
|
156947
|
+
let inString = false;
|
|
156948
|
+
let escaped = false;
|
|
156949
|
+
for (let index = 0;index < content.length; index += 1) {
|
|
156950
|
+
const char = content[index];
|
|
156951
|
+
if (inString) {
|
|
156952
|
+
result += char;
|
|
156953
|
+
if (escaped) {
|
|
156954
|
+
escaped = false;
|
|
156955
|
+
} else if (char === "\\") {
|
|
156956
|
+
escaped = true;
|
|
156957
|
+
} else if (char === '"') {
|
|
156958
|
+
inString = false;
|
|
156959
|
+
}
|
|
156960
|
+
continue;
|
|
156961
|
+
}
|
|
156962
|
+
if (char === '"') {
|
|
156963
|
+
inString = true;
|
|
156964
|
+
result += char;
|
|
156965
|
+
continue;
|
|
156966
|
+
}
|
|
156967
|
+
if (char === ",") {
|
|
156968
|
+
let lookahead = index + 1;
|
|
156969
|
+
while (lookahead < content.length && /\s/.test(content[lookahead] ?? "")) {
|
|
156970
|
+
lookahead += 1;
|
|
156971
|
+
}
|
|
156972
|
+
const next = content[lookahead];
|
|
156973
|
+
if (next === "}" || next === "]") {
|
|
156974
|
+
continue;
|
|
156975
|
+
}
|
|
156976
|
+
}
|
|
156977
|
+
result += char;
|
|
156978
|
+
}
|
|
156979
|
+
return result;
|
|
156980
|
+
}
|
|
156981
|
+
function parseJsonc(content) {
|
|
156982
|
+
const normalized = stripTrailingCommas(stripJsonComments(content));
|
|
156983
|
+
return JSON.parse(normalized);
|
|
156984
|
+
}
|
|
156985
|
+
|
|
156986
|
+
// ../plugin/src/config/variable.ts
|
|
156870
156987
|
var ENV_PATTERN = /\{env:([^}]+)\}/g;
|
|
156871
156988
|
var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
156872
156989
|
function substituteConfigVariables(input) {
|
|
156873
156990
|
const warnings = [];
|
|
156874
156991
|
let text = input.text;
|
|
156992
|
+
if (input.isProjectConfig) {
|
|
156993
|
+
const hasEnvTokens = ENV_PATTERN.test(text);
|
|
156994
|
+
const hasFileTokens = FILE_PATTERN.test(text);
|
|
156995
|
+
ENV_PATTERN.lastIndex = 0;
|
|
156996
|
+
FILE_PATTERN.lastIndex = 0;
|
|
156997
|
+
if (hasEnvTokens || hasFileTokens) {
|
|
156998
|
+
const tokenTypes = [
|
|
156999
|
+
hasEnvTokens ? "{env:}" : undefined,
|
|
157000
|
+
hasFileTokens ? "{file:}" : undefined
|
|
157001
|
+
].filter(Boolean).join(" and ");
|
|
157002
|
+
warnings.push(`Project-level config no longer supports ${tokenTypes} tokens for security reasons; leaving tokens literal. Move secret expansion to user-level config.`);
|
|
157003
|
+
}
|
|
157004
|
+
return { text, warnings };
|
|
157005
|
+
}
|
|
157006
|
+
text = stripJsonComments(text);
|
|
156875
157007
|
text = text.replace(ENV_PATTERN, (_, rawName) => {
|
|
156876
157008
|
const varName = rawName.trim();
|
|
156877
157009
|
const value = varName ? process.env[varName] : undefined;
|
|
@@ -156879,7 +157011,7 @@ function substituteConfigVariables(input) {
|
|
|
156879
157011
|
warnings.push(`Environment variable ${varName} is not set (referenced via {env:${varName}}); using empty string`);
|
|
156880
157012
|
return "";
|
|
156881
157013
|
}
|
|
156882
|
-
return value;
|
|
157014
|
+
return JSON.stringify(value).slice(1, -1);
|
|
156883
157015
|
});
|
|
156884
157016
|
const fileMatches = Array.from(text.matchAll(FILE_PATTERN));
|
|
156885
157017
|
if (fileMatches.length === 0) {
|
|
@@ -163269,6 +163401,10 @@ function getLastCompartmentEndMessage(db, sessionId) {
|
|
|
163269
163401
|
const row = db.prepare("SELECT MAX(end_message) as max_end FROM compartments WHERE session_id = ?").get(sessionId);
|
|
163270
163402
|
return row?.max_end ?? -1;
|
|
163271
163403
|
}
|
|
163404
|
+
function getCompartmentsByEndMessageId(db, sessionId, endMessageId) {
|
|
163405
|
+
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? AND end_message_id = ? ORDER BY sequence ASC").all(sessionId, endMessageId).filter(isCompartmentRow);
|
|
163406
|
+
return rows.map(toCompartment);
|
|
163407
|
+
}
|
|
163272
163408
|
function appendCompartments(db, sessionId, compartments) {
|
|
163273
163409
|
if (compartments.length === 0)
|
|
163274
163410
|
return;
|
|
@@ -163378,7 +163514,7 @@ function promoteRecompStaging(db, sessionId) {
|
|
|
163378
163514
|
insertFactRows(db, sessionId, staging.facts, now);
|
|
163379
163515
|
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
163380
163516
|
db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
|
|
163381
|
-
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE session_id = ?").run(sessionId);
|
|
163517
|
+
db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
|
|
163382
163518
|
return { compartments: staging.compartments, facts: staging.facts };
|
|
163383
163519
|
})();
|
|
163384
163520
|
}
|
|
@@ -164927,6 +165063,39 @@ function clearPendingCompactionMarkerStateIf(db, sessionId, expected) {
|
|
|
164927
165063
|
WHERE session_id = ? AND pending_compaction_marker_state = ?`).run(sessionId, expectedBlob);
|
|
164928
165064
|
return result.changes > 0;
|
|
164929
165065
|
}
|
|
165066
|
+
function isPendingPiCompactionMarker(value) {
|
|
165067
|
+
return typeof value === "object" && value !== null && typeof value.firstKeptEntryId === "string" && typeof value.endMessageId === "string" && typeof value.ordinal === "number" && typeof value.tokensBefore === "number" && typeof value.summary === "string" && typeof value.publishedAt === "number";
|
|
165068
|
+
}
|
|
165069
|
+
function getPendingPiCompactionMarkerState(db, sessionId) {
|
|
165070
|
+
const row = db.prepare("SELECT pending_pi_compaction_marker_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
165071
|
+
const raw = row?.pending_pi_compaction_marker_state;
|
|
165072
|
+
if (raw === null || raw === undefined || raw === "")
|
|
165073
|
+
return null;
|
|
165074
|
+
try {
|
|
165075
|
+
const parsed = JSON.parse(raw);
|
|
165076
|
+
if (isPendingPiCompactionMarker(parsed)) {
|
|
165077
|
+
return parsed;
|
|
165078
|
+
}
|
|
165079
|
+
} catch {}
|
|
165080
|
+
return null;
|
|
165081
|
+
}
|
|
165082
|
+
function setPendingPiCompactionMarkerState(db, sessionId, state) {
|
|
165083
|
+
ensureSessionMetaRow(db, sessionId);
|
|
165084
|
+
const blob = state ? stableStringify(state) : null;
|
|
165085
|
+
db.prepare("UPDATE session_meta SET pending_pi_compaction_marker_state = ? WHERE session_id = ?").run(blob, sessionId);
|
|
165086
|
+
}
|
|
165087
|
+
function clearPendingPiCompactionMarkerStateIf(db, sessionId, expected) {
|
|
165088
|
+
const expectedBlob = stableStringify(expected);
|
|
165089
|
+
const result = db.prepare(`UPDATE session_meta SET pending_pi_compaction_marker_state = NULL
|
|
165090
|
+
WHERE session_id = ? AND pending_pi_compaction_marker_state = ?`).run(sessionId, expectedBlob);
|
|
165091
|
+
return result.changes > 0;
|
|
165092
|
+
}
|
|
165093
|
+
function getSessionsWithPendingPiMarker(db) {
|
|
165094
|
+
const rows = db.prepare(`SELECT session_id FROM session_meta
|
|
165095
|
+
WHERE pending_pi_compaction_marker_state IS NOT NULL
|
|
165096
|
+
AND pending_pi_compaction_marker_state != ''`).all();
|
|
165097
|
+
return rows.map((r) => r.session_id);
|
|
165098
|
+
}
|
|
164930
165099
|
function peekDeferredExecutePending(db, sessionId) {
|
|
164931
165100
|
const row = db.prepare("SELECT deferred_execute_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
164932
165101
|
const raw = row?.deferred_execute_state;
|
|
@@ -165047,6 +165216,12 @@ function getNoteById(db, noteId) {
|
|
|
165047
165216
|
const row = db.prepare("SELECT * FROM notes WHERE id = ?").get(noteId);
|
|
165048
165217
|
return isNoteRow(row) ? toNote(row) : null;
|
|
165049
165218
|
}
|
|
165219
|
+
function noteBelongsToScope(note, scope) {
|
|
165220
|
+
if (note.type === "session") {
|
|
165221
|
+
return note.sessionId === scope.sessionId;
|
|
165222
|
+
}
|
|
165223
|
+
return note.projectPath === scope.projectPath;
|
|
165224
|
+
}
|
|
165050
165225
|
function buildStatusClause(status) {
|
|
165051
165226
|
if (status === undefined) {
|
|
165052
165227
|
return null;
|
|
@@ -165108,9 +165283,9 @@ function getPendingSmartNotes(db, projectPath) {
|
|
|
165108
165283
|
function getReadySmartNotes(db, projectPath) {
|
|
165109
165284
|
return getSmartNotes(db, projectPath, "ready");
|
|
165110
165285
|
}
|
|
165111
|
-
function updateNote(db, noteId, updates) {
|
|
165286
|
+
function updateNote(db, noteId, updates, scope) {
|
|
165112
165287
|
const existing = getNoteById(db, noteId);
|
|
165113
|
-
if (!existing) {
|
|
165288
|
+
if (!existing || !noteBelongsToScope(existing, scope)) {
|
|
165114
165289
|
return null;
|
|
165115
165290
|
}
|
|
165116
165291
|
const now = Date.now();
|
|
@@ -165157,7 +165332,11 @@ function updateNote(db, noteId, updates) {
|
|
|
165157
165332
|
const result = db.prepare(`UPDATE notes SET ${sets.join(", ")} WHERE id = ? RETURNING *`).get(...params);
|
|
165158
165333
|
return isNoteRow(result) ? toNote(result) : null;
|
|
165159
165334
|
}
|
|
165160
|
-
function dismissNote(db, noteId) {
|
|
165335
|
+
function dismissNote(db, noteId, scope) {
|
|
165336
|
+
const existing = getNoteById(db, noteId);
|
|
165337
|
+
if (!existing || !noteBelongsToScope(existing, scope)) {
|
|
165338
|
+
return false;
|
|
165339
|
+
}
|
|
165161
165340
|
const result = db.prepare("UPDATE notes SET status = 'dismissed', updated_at = ? WHERE id = ? AND status != 'dismissed'").run(Date.now(), noteId);
|
|
165162
165341
|
return result.changes > 0;
|
|
165163
165342
|
}
|
|
@@ -165577,8 +165756,15 @@ function createCtxNoteTool(deps) {
|
|
|
165577
165756
|
if (typeof params.note_id !== "number") {
|
|
165578
165757
|
return err3("Error: 'note_id' is required when action is 'dismiss'.");
|
|
165579
165758
|
}
|
|
165580
|
-
const
|
|
165581
|
-
|
|
165759
|
+
const projectIdentity = resolveProjectIdentity(ctx.cwd);
|
|
165760
|
+
if (!projectIdentity) {
|
|
165761
|
+
return err3("Error: Could not resolve project identity for note dismiss.");
|
|
165762
|
+
}
|
|
165763
|
+
const dismissed = dismissNote(deps.db, params.note_id, {
|
|
165764
|
+
projectPath: projectIdentity,
|
|
165765
|
+
sessionId
|
|
165766
|
+
});
|
|
165767
|
+
return dismissed ? ok3(`Note #${params.note_id} dismissed.`) : err3(`Error: Note #${params.note_id} not found in your session/project or already dismissed.`);
|
|
165582
165768
|
}
|
|
165583
165769
|
if (action2 === "update") {
|
|
165584
165770
|
if (typeof params.note_id !== "number") {
|
|
@@ -165592,9 +165778,16 @@ function createCtxNoteTool(deps) {
|
|
|
165592
165778
|
if (!updates.content && !updates.surfaceCondition) {
|
|
165593
165779
|
return err3("Error: Provide 'content' and/or 'surface_condition' to update.");
|
|
165594
165780
|
}
|
|
165595
|
-
const
|
|
165781
|
+
const projectIdentity = resolveProjectIdentity(ctx.cwd);
|
|
165782
|
+
if (!projectIdentity) {
|
|
165783
|
+
return err3("Error: Could not resolve project identity for note update.");
|
|
165784
|
+
}
|
|
165785
|
+
const updated = updateNote(deps.db, params.note_id, updates, {
|
|
165786
|
+
projectPath: projectIdentity,
|
|
165787
|
+
sessionId
|
|
165788
|
+
});
|
|
165596
165789
|
if (!updated) {
|
|
165597
|
-
return err3(`Note #${params.note_id} not found.`);
|
|
165790
|
+
return err3(`Error: Note #${params.note_id} not found in your session/project.`);
|
|
165598
165791
|
}
|
|
165599
165792
|
const parts = [];
|
|
165600
165793
|
if (updates.content)
|
package/package.json
CHANGED