@cortexkit/pi-magic-context 0.21.2 → 0.21.5
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 +587 -106
- package/dist/subagent-entry.js +207 -15
- 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'");
|
|
@@ -156796,7 +156815,6 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
156796
156815
|
enabled: exports_external.boolean().default(true),
|
|
156797
156816
|
min_clusters: exports_external.number().min(1).default(3)
|
|
156798
156817
|
}).default({ enabled: true, min_clusters: 3 }),
|
|
156799
|
-
compaction_markers: exports_external.boolean().default(true),
|
|
156800
156818
|
system_prompt_injection: exports_external.object({
|
|
156801
156819
|
enabled: exports_external.boolean().default(true),
|
|
156802
156820
|
skip_signatures: exports_external.array(exports_external.string()).default(["<!-- magic-context: skip -->"])
|
|
@@ -156868,11 +156886,124 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
156868
156886
|
import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
|
|
156869
156887
|
import { homedir as homedir2 } from "node:os";
|
|
156870
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
|
|
156871
156987
|
var ENV_PATTERN = /\{env:([^}]+)\}/g;
|
|
156872
156988
|
var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
156873
156989
|
function substituteConfigVariables(input) {
|
|
156874
156990
|
const warnings = [];
|
|
156875
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);
|
|
156876
157007
|
text = text.replace(ENV_PATTERN, (_, rawName) => {
|
|
156877
157008
|
const varName = rawName.trim();
|
|
156878
157009
|
const value = varName ? process.env[varName] : undefined;
|
|
@@ -156880,7 +157011,7 @@ function substituteConfigVariables(input) {
|
|
|
156880
157011
|
warnings.push(`Environment variable ${varName} is not set (referenced via {env:${varName}}); using empty string`);
|
|
156881
157012
|
return "";
|
|
156882
157013
|
}
|
|
156883
|
-
return value;
|
|
157014
|
+
return JSON.stringify(value).slice(1, -1);
|
|
156884
157015
|
});
|
|
156885
157016
|
const fileMatches = Array.from(text.matchAll(FILE_PATTERN));
|
|
156886
157017
|
if (fileMatches.length === 0) {
|
|
@@ -163270,6 +163401,10 @@ function getLastCompartmentEndMessage(db, sessionId) {
|
|
|
163270
163401
|
const row = db.prepare("SELECT MAX(end_message) as max_end FROM compartments WHERE session_id = ?").get(sessionId);
|
|
163271
163402
|
return row?.max_end ?? -1;
|
|
163272
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
|
+
}
|
|
163273
163408
|
function appendCompartments(db, sessionId, compartments) {
|
|
163274
163409
|
if (compartments.length === 0)
|
|
163275
163410
|
return;
|
|
@@ -163379,7 +163514,7 @@ function promoteRecompStaging(db, sessionId) {
|
|
|
163379
163514
|
insertFactRows(db, sessionId, staging.facts, now);
|
|
163380
163515
|
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
163381
163516
|
db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
|
|
163382
|
-
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);
|
|
163383
163518
|
return { compartments: staging.compartments, facts: staging.facts };
|
|
163384
163519
|
})();
|
|
163385
163520
|
}
|
|
@@ -164928,6 +165063,39 @@ function clearPendingCompactionMarkerStateIf(db, sessionId, expected) {
|
|
|
164928
165063
|
WHERE session_id = ? AND pending_compaction_marker_state = ?`).run(sessionId, expectedBlob);
|
|
164929
165064
|
return result.changes > 0;
|
|
164930
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
|
+
}
|
|
164931
165099
|
function peekDeferredExecutePending(db, sessionId) {
|
|
164932
165100
|
const row = db.prepare("SELECT deferred_execute_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
164933
165101
|
const raw = row?.deferred_execute_state;
|
|
@@ -165048,6 +165216,12 @@ function getNoteById(db, noteId) {
|
|
|
165048
165216
|
const row = db.prepare("SELECT * FROM notes WHERE id = ?").get(noteId);
|
|
165049
165217
|
return isNoteRow(row) ? toNote(row) : null;
|
|
165050
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
|
+
}
|
|
165051
165225
|
function buildStatusClause(status) {
|
|
165052
165226
|
if (status === undefined) {
|
|
165053
165227
|
return null;
|
|
@@ -165109,9 +165283,9 @@ function getPendingSmartNotes(db, projectPath) {
|
|
|
165109
165283
|
function getReadySmartNotes(db, projectPath) {
|
|
165110
165284
|
return getSmartNotes(db, projectPath, "ready");
|
|
165111
165285
|
}
|
|
165112
|
-
function updateNote(db, noteId, updates) {
|
|
165286
|
+
function updateNote(db, noteId, updates, scope) {
|
|
165113
165287
|
const existing = getNoteById(db, noteId);
|
|
165114
|
-
if (!existing) {
|
|
165288
|
+
if (!existing || !noteBelongsToScope(existing, scope)) {
|
|
165115
165289
|
return null;
|
|
165116
165290
|
}
|
|
165117
165291
|
const now = Date.now();
|
|
@@ -165158,7 +165332,11 @@ function updateNote(db, noteId, updates) {
|
|
|
165158
165332
|
const result = db.prepare(`UPDATE notes SET ${sets.join(", ")} WHERE id = ? RETURNING *`).get(...params);
|
|
165159
165333
|
return isNoteRow(result) ? toNote(result) : null;
|
|
165160
165334
|
}
|
|
165161
|
-
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
|
+
}
|
|
165162
165340
|
const result = db.prepare("UPDATE notes SET status = 'dismissed', updated_at = ? WHERE id = ? AND status != 'dismissed'").run(Date.now(), noteId);
|
|
165163
165341
|
return result.changes > 0;
|
|
165164
165342
|
}
|
|
@@ -165578,8 +165756,15 @@ function createCtxNoteTool(deps) {
|
|
|
165578
165756
|
if (typeof params.note_id !== "number") {
|
|
165579
165757
|
return err3("Error: 'note_id' is required when action is 'dismiss'.");
|
|
165580
165758
|
}
|
|
165581
|
-
const
|
|
165582
|
-
|
|
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.`);
|
|
165583
165768
|
}
|
|
165584
165769
|
if (action2 === "update") {
|
|
165585
165770
|
if (typeof params.note_id !== "number") {
|
|
@@ -165593,9 +165778,16 @@ function createCtxNoteTool(deps) {
|
|
|
165593
165778
|
if (!updates.content && !updates.surfaceCondition) {
|
|
165594
165779
|
return err3("Error: Provide 'content' and/or 'surface_condition' to update.");
|
|
165595
165780
|
}
|
|
165596
|
-
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
|
+
});
|
|
165597
165789
|
if (!updated) {
|
|
165598
|
-
return err3(`Note #${params.note_id} not found.`);
|
|
165790
|
+
return err3(`Error: Note #${params.note_id} not found in your session/project.`);
|
|
165599
165791
|
}
|
|
165600
165792
|
const parts = [];
|
|
165601
165793
|
if (updates.content)
|
package/package.json
CHANGED