@cortexkit/opencode-magic-context 0.43.1 → 0.43.2
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/{conflict-warning-hook-956fkedc.js → conflict-warning-hook-hyk9y29x.js} +3 -3
- package/dist/features/magic-context/dreamer/classify.d.ts +12 -0
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/store-generation-rebase.d.ts +62 -1
- package/dist/features/magic-context/store-generation-rebase.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +6 -0
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts +7 -0
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +60 -8
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +3 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +9 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-kpmmr8s0.js → index-6j8th2hd.js} +1 -1
- package/dist/{index-v8qr6tt2.js → index-bmzt6xgy.js} +2 -2
- package/dist/{index-7wpwr2e2.js → index-g6hpfkqa.js} +250 -36
- package/dist/{index-yc81txp4.js → index-jgnag7sa.js} +1 -1
- package/dist/{index-1gtwrdc4.js → index-pa67brzn.js} +2 -2
- package/dist/{index-j7cnyvq1.js → index-tdrv6nd0.js} +1 -1
- package/dist/index.js +238 -28
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/{read-session-chunk-z7fv0qjv.js → read-session-chunk-53a7qbrh.js} +2 -2
- package/dist/{recomp-orchestrator-r00aa5t3.js → recomp-orchestrator-adsgqgse.js} +4 -4
- package/dist/{send-session-notification-3warjyjp.js → send-session-notification-e28r4xx2.js} +2 -2
- package/dist/shared/opencode-db-path.d.ts.map +1 -1
- package/dist/shared/test-fake-executable.d.ts +38 -0
- package/dist/shared/test-fake-executable.d.ts.map +1 -0
- package/dist/shared/user-facing-codes.d.ts +10 -0
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/refusal.d.ts +9 -1
- package/dist/v2/hooks/refusal.d.ts.map +1 -1
- package/dist/v2/hooks/restore-rows.d.ts +29 -0
- package/dist/v2/hooks/restore-rows.d.ts.map +1 -0
- package/dist/v2/hooks/update-check.d.ts +8 -0
- package/dist/v2/hooks/update-check.d.ts.map +1 -1
- package/dist/v2/server.js +470 -61
- package/dist/v2/store-reader.d.ts +8 -0
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/{wrapup-orchestrator-y0bs7t5a.js → wrapup-orchestrator-8xzbpvm8.js} +5 -5
- package/package.json +1 -1
- package/src/shared/opencode-db-path.test.ts +18 -0
- package/src/shared/opencode-db-path.ts +5 -2
- package/src/shared/test-fake-executable.test.ts +54 -0
- package/src/shared/test-fake-executable.ts +110 -0
- package/src/shared/user-facing-codes.ts +11 -0
package/dist/v2/server.js
CHANGED
|
@@ -15449,7 +15449,7 @@ var HOST_UNSERVED_ROW = "hostUnservedRow";
|
|
|
15449
15449
|
// src/shared/opencode-db-path.ts
|
|
15450
15450
|
import { existsSync as existsSync8, readdirSync, statSync as statSync7 } from "node:fs";
|
|
15451
15451
|
import { homedir as homedir8 } from "node:os";
|
|
15452
|
-
import { isAbsolute as isAbsolute4, join as join8 } from "node:path";
|
|
15452
|
+
import { isAbsolute as isAbsolute4, join as join8, resolve as resolve4 } from "node:path";
|
|
15453
15453
|
function openCodeDataDir(env = process.env, dataHome) {
|
|
15454
15454
|
return join8(dataHome ?? env.XDG_DATA_HOME ?? join8(homedir8(), ".local", "share"), "opencode");
|
|
15455
15455
|
}
|
|
@@ -15529,7 +15529,7 @@ function resolveV2Fresh(dataDir, channel, env) {
|
|
|
15529
15529
|
const filename = sourceOpenCodeDatabaseFilename("v2", channel, env);
|
|
15530
15530
|
const explicit = env.OPENCODE_DB !== undefined;
|
|
15531
15531
|
return {
|
|
15532
|
-
path: filename === ":memory:" ? filename :
|
|
15532
|
+
path: filename === ":memory:" ? filename : resolve4(dataDir, filename),
|
|
15533
15533
|
source: explicit ? "OPENCODE_DB" : env.OPENCODE_CHANNEL ? "channel" : "default",
|
|
15534
15534
|
channel: explicit ? null : channel
|
|
15535
15535
|
};
|
|
@@ -26133,7 +26133,7 @@ import {
|
|
|
26133
26133
|
statSync as statSync9,
|
|
26134
26134
|
unlinkSync as unlinkSync2
|
|
26135
26135
|
} from "node:fs";
|
|
26136
|
-
import { basename as basename3, dirname as dirname6, join as join9, resolve as
|
|
26136
|
+
import { basename as basename3, dirname as dirname6, join as join9, resolve as resolve5 } from "node:path";
|
|
26137
26137
|
function getSchemaFenceRejection() {
|
|
26138
26138
|
return lastSchemaFenceRejection;
|
|
26139
26139
|
}
|
|
@@ -26450,7 +26450,7 @@ function isDefaultSharedDatabasePath(dbPath) {
|
|
|
26450
26450
|
if (!process.env.XDG_DATA_HOME && (process.env.MAGIC_CONTEXT_TEST_DATA_DIR || false)) {
|
|
26451
26451
|
return false;
|
|
26452
26452
|
}
|
|
26453
|
-
return
|
|
26453
|
+
return resolve5(dbPath) === resolve5(join9(getMagicContextStorageDir(), "context.db"));
|
|
26454
26454
|
}
|
|
26455
26455
|
function migrationBlockingPiPids(dbPath, discovery, discoveredPiPids) {
|
|
26456
26456
|
if (isDefaultSharedDatabasePath(dbPath))
|
|
@@ -29016,6 +29016,7 @@ function emptyOutcome(status, generation, previousGeneration) {
|
|
|
29016
29016
|
previousGeneration,
|
|
29017
29017
|
compartmentsRebased: 0,
|
|
29018
29018
|
compartmentsUnresolved: 0,
|
|
29019
|
+
compartmentsDerived: 0,
|
|
29019
29020
|
compartmentsResolvedAgain: 0,
|
|
29020
29021
|
recompCompartmentsRebased: 0,
|
|
29021
29022
|
recompCompartmentsUnresolved: 0,
|
|
@@ -29069,6 +29070,12 @@ function readCoordinateRebaseNotice(db, sessionId) {
|
|
|
29069
29070
|
if (record.generation !== "v1" && record.generation !== "v2")
|
|
29070
29071
|
return null;
|
|
29071
29072
|
const count = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
29073
|
+
const ranges = (value) => Array.isArray(value) ? value.flatMap((entry) => {
|
|
29074
|
+
if (!entry || typeof entry !== "object")
|
|
29075
|
+
return [];
|
|
29076
|
+
const { sequence, start, end } = entry;
|
|
29077
|
+
return typeof sequence === "number" && typeof start === "number" && typeof end === "number" ? [{ sequence, start, end }] : [];
|
|
29078
|
+
}) : [];
|
|
29072
29079
|
return {
|
|
29073
29080
|
generation: record.generation,
|
|
29074
29081
|
previousGeneration: record.previousGeneration === "v1" || record.previousGeneration === "v2" ? record.previousGeneration : null,
|
|
@@ -29077,7 +29084,10 @@ function readCoordinateRebaseNotice(db, sessionId) {
|
|
|
29077
29084
|
discardedReductions: count(record.discardedReductions),
|
|
29078
29085
|
droppedDepthRows: count(record.droppedDepthRows),
|
|
29079
29086
|
healedGaps: count(record.healedGaps),
|
|
29080
|
-
narrativeGaps: count(record.narrativeGaps)
|
|
29087
|
+
narrativeGaps: count(record.narrativeGaps),
|
|
29088
|
+
derivedCompartments: ranges(record.derivedCompartments),
|
|
29089
|
+
unresolvedCompartmentRanges: ranges(record.unresolvedCompartmentRanges),
|
|
29090
|
+
neighbourRecoveryAt: typeof record.neighbourRecoveryAt === "number" && Number.isFinite(record.neighbourRecoveryAt) ? record.neighbourRecoveryAt : null
|
|
29081
29091
|
};
|
|
29082
29092
|
} catch {
|
|
29083
29093
|
return null;
|
|
@@ -29114,36 +29124,62 @@ function readCompartmentRows(db, table, sessionId) {
|
|
|
29114
29124
|
return db.prepare(`SELECT id, sequence, start_message, end_message, start_message_id, end_message_id, rebase_status
|
|
29115
29125
|
FROM ${table} WHERE session_id = ? ORDER BY sequence ASC`).all(sessionId).filter(isCompartmentCoordinateRow);
|
|
29116
29126
|
}
|
|
29127
|
+
function resolveAnchor(messageId, resolveOrdinal) {
|
|
29128
|
+
return messageId && messageId.length > 0 ? resolveOrdinal(messageId) : undefined;
|
|
29129
|
+
}
|
|
29117
29130
|
function planCompartments(rows, table, projection) {
|
|
29118
|
-
|
|
29119
|
-
|
|
29120
|
-
|
|
29121
|
-
|
|
29122
|
-
|
|
29123
|
-
|
|
29124
|
-
|
|
29125
|
-
|
|
29126
|
-
|
|
29127
|
-
|
|
29128
|
-
|
|
29129
|
-
|
|
29130
|
-
|
|
29131
|
-
|
|
29132
|
-
status: "unresolved",
|
|
29133
|
-
previousStatus
|
|
29134
|
-
};
|
|
29135
|
-
}
|
|
29136
|
-
return {
|
|
29131
|
+
const resolveOrdinal = (messageId) => projection.ordinalById.get(messageId);
|
|
29132
|
+
return recoverFromNeighbours(rows, table, rows.map((row) => ({
|
|
29133
|
+
start: resolveAnchor(row.start_message_id, resolveOrdinal),
|
|
29134
|
+
end: resolveAnchor(row.end_message_id, resolveOrdinal)
|
|
29135
|
+
})));
|
|
29136
|
+
}
|
|
29137
|
+
function recoverFromNeighbours(rows, table, known) {
|
|
29138
|
+
const plans = rows.map((row, index) => {
|
|
29139
|
+
const own = known[index] ?? { start: undefined, end: undefined };
|
|
29140
|
+
const previousEnd = index === 0 ? 0 : known[index - 1]?.end;
|
|
29141
|
+
const nextStart = index === rows.length - 1 ? undefined : known[index + 1]?.start;
|
|
29142
|
+
const start = own.start ?? (previousEnd === undefined ? undefined : previousEnd + 1);
|
|
29143
|
+
const end = own.end ?? (nextStart === undefined ? undefined : nextStart - 1);
|
|
29144
|
+
const base = {
|
|
29137
29145
|
table,
|
|
29138
29146
|
id: row.id,
|
|
29147
|
+
sequence: row.sequence,
|
|
29139
29148
|
previousStart: row.start_message,
|
|
29140
29149
|
previousEnd: row.end_message,
|
|
29141
|
-
|
|
29142
|
-
|
|
29143
|
-
|
|
29144
|
-
|
|
29150
|
+
previousStatus: row.rebase_status === "unresolved" ? "unresolved" : "ok"
|
|
29151
|
+
};
|
|
29152
|
+
if (start !== undefined && end !== undefined && start <= end) {
|
|
29153
|
+
return {
|
|
29154
|
+
...base,
|
|
29155
|
+
start,
|
|
29156
|
+
end,
|
|
29157
|
+
status: "ok",
|
|
29158
|
+
derived: own.start === undefined || own.end === undefined
|
|
29159
|
+
};
|
|
29160
|
+
}
|
|
29161
|
+
return {
|
|
29162
|
+
...base,
|
|
29163
|
+
start: start ?? row.start_message,
|
|
29164
|
+
end: end ?? row.end_message,
|
|
29165
|
+
status: "unresolved",
|
|
29166
|
+
derived: false
|
|
29145
29167
|
};
|
|
29146
29168
|
});
|
|
29169
|
+
for (let index = 0;index < plans.length; index += 1) {
|
|
29170
|
+
const plan = plans[index];
|
|
29171
|
+
if (plan?.status !== "unresolved")
|
|
29172
|
+
continue;
|
|
29173
|
+
const previous = plans[index - 1];
|
|
29174
|
+
const next = plans[index + 1];
|
|
29175
|
+
if (previous?.status === "ok" && plan.start <= previous.end) {
|
|
29176
|
+
plan.start = previous.end + 1;
|
|
29177
|
+
}
|
|
29178
|
+
if (next?.status === "ok" && plan.end >= next.start) {
|
|
29179
|
+
plan.end = next.start - 1;
|
|
29180
|
+
}
|
|
29181
|
+
}
|
|
29182
|
+
return plans;
|
|
29147
29183
|
}
|
|
29148
29184
|
function healNonNarrativeCompartmentGaps(plans, projection) {
|
|
29149
29185
|
let healed = 0;
|
|
@@ -29174,7 +29210,10 @@ function healNonNarrativeCompartmentGaps(plans, projection) {
|
|
|
29174
29210
|
return { healed, narrative };
|
|
29175
29211
|
}
|
|
29176
29212
|
function compartmentPlanChanges(plan) {
|
|
29177
|
-
return plan.status !== plan.previousStatus || plan.
|
|
29213
|
+
return plan.status !== plan.previousStatus || plan.start !== plan.previousStart || plan.end !== plan.previousEnd;
|
|
29214
|
+
}
|
|
29215
|
+
function rangeNotes(plans, predicate) {
|
|
29216
|
+
return plans.filter((plan) => plan.table === "compartments" && predicate(plan)).map((plan) => ({ sequence: plan.sequence, start: plan.start, end: plan.end }));
|
|
29178
29217
|
}
|
|
29179
29218
|
function planNotes(db, sessionId, projection) {
|
|
29180
29219
|
const rows = db.prepare("SELECT id, anchor_ordinal, anchor_block_id FROM notes WHERE session_id = ? AND anchor_ordinal IS NOT NULL").all(sessionId);
|
|
@@ -29260,7 +29299,14 @@ function rebaseSessionCoordinates(args) {
|
|
|
29260
29299
|
}
|
|
29261
29300
|
const previousGeneration = readCoordinateGeneration(db, sessionId);
|
|
29262
29301
|
if (previousGeneration === generation) {
|
|
29263
|
-
|
|
29302
|
+
const outcome = emptyOutcome("unchanged", generation, previousGeneration);
|
|
29303
|
+
const repair = repairStampedSessionOnce(db, sessionId, args.readMessages);
|
|
29304
|
+
if (repair !== null && repair.rowsRewritten > 0) {
|
|
29305
|
+
outcome.status = "repaired";
|
|
29306
|
+
outcome.compartmentsDerived = repair.derived.length;
|
|
29307
|
+
outcome.compartmentsUnresolved = repair.unresolved.length;
|
|
29308
|
+
}
|
|
29309
|
+
return outcome;
|
|
29264
29310
|
}
|
|
29265
29311
|
const impliedGeneration = previousGeneration ?? generationImpliedByHarness(db, sessionId) ?? generation;
|
|
29266
29312
|
if (impliedGeneration === generation) {
|
|
@@ -29324,6 +29370,8 @@ function rebaseSessionCoordinates(args) {
|
|
|
29324
29370
|
if (plan.table === "compartments") {
|
|
29325
29371
|
outcome.compartmentsRebased += rebased;
|
|
29326
29372
|
outcome.compartmentsUnresolved += unresolved;
|
|
29373
|
+
if (rebased === 1 && plan.derived)
|
|
29374
|
+
outcome.compartmentsDerived += 1;
|
|
29327
29375
|
if (rebased === 1 && plan.previousStatus === "unresolved")
|
|
29328
29376
|
outcome.compartmentsResolvedAgain += 1;
|
|
29329
29377
|
} else {
|
|
@@ -29380,7 +29428,10 @@ function rebaseSessionCoordinates(args) {
|
|
|
29380
29428
|
discardedReductions: outcome.queuedReductionsDiscarded,
|
|
29381
29429
|
droppedDepthRows: outcome.compressionDepthRowsDropped,
|
|
29382
29430
|
healedGaps: outcome.healedGaps,
|
|
29383
|
-
narrativeGaps: outcome.narrativeGaps
|
|
29431
|
+
narrativeGaps: outcome.narrativeGaps,
|
|
29432
|
+
derivedCompartments: rangeNotes(compartmentPlans, (plan) => plan.status === "ok" && plan.derived),
|
|
29433
|
+
unresolvedCompartmentRanges: rangeNotes(compartmentPlans, (plan) => plan.status === "unresolved"),
|
|
29434
|
+
neighbourRecoveryAt: Date.now()
|
|
29384
29435
|
});
|
|
29385
29436
|
db.exec("COMMIT");
|
|
29386
29437
|
committed = true;
|
|
@@ -29398,10 +29449,114 @@ function rebaseSessionCoordinates(args) {
|
|
|
29398
29449
|
sessionLog(sessionId, formatRebaseLogLine(outcome, performance.now() - startedAt));
|
|
29399
29450
|
return outcome;
|
|
29400
29451
|
}
|
|
29452
|
+
function recoverUnresolvedCompartments(args) {
|
|
29453
|
+
const { db, sessionId } = args;
|
|
29454
|
+
const rows = readCompartmentRows(db, "compartments", sessionId);
|
|
29455
|
+
const result = { rowsRewritten: 0, derived: [], unresolved: [] };
|
|
29456
|
+
if (!rows.some((row) => row.rebase_status === "unresolved"))
|
|
29457
|
+
return result;
|
|
29458
|
+
const known = rows.map((row) => {
|
|
29459
|
+
if (row.rebase_status !== "unresolved") {
|
|
29460
|
+
return { start: row.start_message, end: row.end_message };
|
|
29461
|
+
}
|
|
29462
|
+
return {
|
|
29463
|
+
start: resolveAnchor(row.start_message_id, args.resolveOrdinal),
|
|
29464
|
+
end: resolveAnchor(row.end_message_id, args.resolveOrdinal)
|
|
29465
|
+
};
|
|
29466
|
+
});
|
|
29467
|
+
const plans = recoverFromNeighbours(rows, "compartments", known);
|
|
29468
|
+
const wasUnresolved = (plan) => plan.previousStatus === "unresolved";
|
|
29469
|
+
result.derived = rangeNotes(plans, (plan) => wasUnresolved(plan) && plan.status === "ok" && plan.derived);
|
|
29470
|
+
result.unresolved = rangeNotes(plans, (plan) => plan.status === "unresolved");
|
|
29471
|
+
const changed = plans.filter(compartmentPlanChanges);
|
|
29472
|
+
const now = Date.now();
|
|
29473
|
+
db.exec("BEGIN IMMEDIATE");
|
|
29474
|
+
let committed = false;
|
|
29475
|
+
try {
|
|
29476
|
+
for (const plan of changed) {
|
|
29477
|
+
db.prepare("UPDATE compartments SET start_message = ?, end_message = ?, rebase_status = ? WHERE id = ?").run(plan.start, plan.end, plan.status, plan.id);
|
|
29478
|
+
}
|
|
29479
|
+
const previous = readCoordinateRebaseNotice(db, sessionId);
|
|
29480
|
+
const generation = previous?.generation ?? readCoordinateGeneration(db, sessionId);
|
|
29481
|
+
if (generation !== null) {
|
|
29482
|
+
const derivedSequences = new Set(result.derived.map((note) => note.sequence));
|
|
29483
|
+
const notice = {
|
|
29484
|
+
generation,
|
|
29485
|
+
previousGeneration: previous?.previousGeneration ?? null,
|
|
29486
|
+
at: previous?.at ?? now,
|
|
29487
|
+
unresolvedCompartments: result.unresolved.length,
|
|
29488
|
+
discardedReductions: previous?.discardedReductions ?? 0,
|
|
29489
|
+
droppedDepthRows: previous?.droppedDepthRows ?? 0,
|
|
29490
|
+
healedGaps: previous?.healedGaps ?? 0,
|
|
29491
|
+
narrativeGaps: previous?.narrativeGaps ?? 0,
|
|
29492
|
+
derivedCompartments: [
|
|
29493
|
+
...(previous?.derivedCompartments ?? []).filter((note) => !derivedSequences.has(note.sequence)),
|
|
29494
|
+
...result.derived
|
|
29495
|
+
],
|
|
29496
|
+
unresolvedCompartmentRanges: result.unresolved,
|
|
29497
|
+
neighbourRecoveryAt: now
|
|
29498
|
+
};
|
|
29499
|
+
ensureSessionMetaRow(db, sessionId);
|
|
29500
|
+
db.prepare("UPDATE session_meta SET coordinate_rebase_notice = ? WHERE session_id = ?").run(JSON.stringify(notice), sessionId);
|
|
29501
|
+
}
|
|
29502
|
+
db.exec("COMMIT");
|
|
29503
|
+
committed = true;
|
|
29504
|
+
} finally {
|
|
29505
|
+
if (!committed) {
|
|
29506
|
+
try {
|
|
29507
|
+
db.exec("ROLLBACK");
|
|
29508
|
+
} catch {}
|
|
29509
|
+
}
|
|
29510
|
+
}
|
|
29511
|
+
result.rowsRewritten = changed.length;
|
|
29512
|
+
sessionLog(sessionId, `INFO compartment neighbour recovery (${args.reason}) rows_rewritten=${changed.length} ` + `derived=${result.derived.map((note) => `${note.start}-${note.end}`).join(",") || "none"} ` + `unresolved=${result.unresolved.map((note) => `${note.start}-${note.end}`).join(",") || "none"}`);
|
|
29513
|
+
return result;
|
|
29514
|
+
}
|
|
29515
|
+
function unresolvedRowBreaksTiling(rows) {
|
|
29516
|
+
let expectedStart = 1;
|
|
29517
|
+
for (let index = 0;index < rows.length; index += 1) {
|
|
29518
|
+
const row = rows[index];
|
|
29519
|
+
if (!row)
|
|
29520
|
+
continue;
|
|
29521
|
+
const broken = row.start_message !== expectedStart || row.end_message < row.start_message;
|
|
29522
|
+
const touchesUnresolved = row.rebase_status === "unresolved" || rows[index - 1]?.rebase_status === "unresolved";
|
|
29523
|
+
if (broken && touchesUnresolved)
|
|
29524
|
+
return true;
|
|
29525
|
+
expectedStart = row.end_message + 1;
|
|
29526
|
+
}
|
|
29527
|
+
return false;
|
|
29528
|
+
}
|
|
29529
|
+
function repairStampedSessionOnce(db, sessionId, readMessages) {
|
|
29530
|
+
let checked = repairCheckedSessions.get(db);
|
|
29531
|
+
if (!checked) {
|
|
29532
|
+
checked = new Set;
|
|
29533
|
+
repairCheckedSessions.set(db, checked);
|
|
29534
|
+
}
|
|
29535
|
+
if (checked.has(sessionId))
|
|
29536
|
+
return null;
|
|
29537
|
+
checked.add(sessionId);
|
|
29538
|
+
const rows = readCompartmentRows(db, "compartments", sessionId);
|
|
29539
|
+
if (!rows.some((row) => row.rebase_status === "unresolved"))
|
|
29540
|
+
return null;
|
|
29541
|
+
if (readCoordinateRebaseNotice(db, sessionId)?.neighbourRecoveryAt != null)
|
|
29542
|
+
return null;
|
|
29543
|
+
if (!unresolvedRowBreaksTiling(rows))
|
|
29544
|
+
return null;
|
|
29545
|
+
let ordinalById = null;
|
|
29546
|
+
return recoverUnresolvedCompartments({
|
|
29547
|
+
db,
|
|
29548
|
+
sessionId,
|
|
29549
|
+
resolveOrdinal: (messageId) => {
|
|
29550
|
+
ordinalById ??= buildProjection(readMessages(sessionId)).ordinalById;
|
|
29551
|
+
return ordinalById.get(messageId);
|
|
29552
|
+
},
|
|
29553
|
+
reason: "stamped-session repair"
|
|
29554
|
+
});
|
|
29555
|
+
}
|
|
29401
29556
|
function formatRebaseLogLine(outcome, elapsedMs) {
|
|
29402
29557
|
const rowsRewritten = outcome.compartmentsRebased + outcome.recompCompartmentsRebased + outcome.notesRebased + outcome.notesCleared + (outcome.priorBoundaryRebased ? 1 : 0) + (outcome.recompPartialRangeRebased ? 1 : 0);
|
|
29403
29558
|
const unresolved = outcome.compartmentsUnresolved + outcome.recompCompartmentsUnresolved;
|
|
29404
|
-
return `INFO store-generation-rebase ${outcome.previousGeneration ?? "unrecorded"}->${outcome.generation} ` + `rows_rewritten=${rowsRewritten} unresolved=${unresolved} ` + `index_rows_rebuilt=${outcome.indexRowsRebuilt} drops_discarded=${outcome.queuedReductionsDiscarded} ` + `healed_gaps=${outcome.healedGaps} narrative_gaps=${outcome.narrativeGaps} ` + `ms=${Math.round(elapsedMs)} ` + `(chunk_windows_deleted=${outcome.chunkEmbeddingsDeleted} depth_rows_dropped=${outcome.compressionDepthRowsDropped} ` + `part_tags_folded=${outcome.partTagsFolded} lkg_slots_dropped=${outcome.lkgSlotsDropped} ` + `frozen_part_entries_dropped=${outcome.frozenPartEntriesDropped})`;
|
|
29559
|
+
return `INFO store-generation-rebase ${outcome.previousGeneration ?? "unrecorded"}->${outcome.generation} ` + `rows_rewritten=${rowsRewritten} unresolved=${unresolved} derived=${outcome.compartmentsDerived} ` + `index_rows_rebuilt=${outcome.indexRowsRebuilt} drops_discarded=${outcome.queuedReductionsDiscarded} ` + `healed_gaps=${outcome.healedGaps} narrative_gaps=${outcome.narrativeGaps} ` + `ms=${Math.round(elapsedMs)} ` + `(chunk_windows_deleted=${outcome.chunkEmbeddingsDeleted} depth_rows_dropped=${outcome.compressionDepthRowsDropped} ` + `part_tags_folded=${outcome.partTagsFolded} lkg_slots_dropped=${outcome.lkgSlotsDropped} ` + `frozen_part_entries_dropped=${outcome.frozenPartEntriesDropped})`;
|
|
29405
29560
|
}
|
|
29406
29561
|
function planPriorBoundary(db, sessionId, plans) {
|
|
29407
29562
|
const row = db.prepare("SELECT prior_boundary_ordinal FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
@@ -29445,11 +29600,13 @@ function indexDisagreesWithProjection(db, sessionId, projection) {
|
|
|
29445
29600
|
)`, sessionId);
|
|
29446
29601
|
return orphanedMapRows > 0;
|
|
29447
29602
|
}
|
|
29603
|
+
var repairCheckedSessions;
|
|
29448
29604
|
var init_store_generation_rebase = __esm(async () => {
|
|
29449
29605
|
init_logger();
|
|
29450
29606
|
init_storage_meta_shared();
|
|
29451
29607
|
init_storage_tags();
|
|
29452
29608
|
await init_message_index();
|
|
29609
|
+
repairCheckedSessions = new WeakMap;
|
|
29453
29610
|
});
|
|
29454
29611
|
|
|
29455
29612
|
// src/hooks/magic-context/derive-budgets.ts
|
|
@@ -75573,14 +75730,14 @@ var CTX_REDUCE_LIGHT_DESCRIPTION = `Stamp an item as no longer needed for the wo
|
|
|
75573
75730
|
|
|
75574
75731
|
// src/shared/prompt-surface-runtime.ts
|
|
75575
75732
|
import { existsSync as existsSync12, readFileSync as readFileSync12, statSync as statSync12 } from "node:fs";
|
|
75576
|
-
import { dirname as dirname8, isAbsolute as isAbsolute5, resolve as
|
|
75733
|
+
import { dirname as dirname8, isAbsolute as isAbsolute5, resolve as resolve6 } from "node:path";
|
|
75577
75734
|
function promptSurfaceHashMaterial(systemContent, preset = "full") {
|
|
75578
75735
|
return preset === "full" ? systemContent : `${systemContent}
|
|
75579
75736
|
\x00magic-context-prompt-surface:${preset}`;
|
|
75580
75737
|
}
|
|
75581
75738
|
function resolveUserConfigDirectory(options) {
|
|
75582
75739
|
if (options.userConfigDirectory)
|
|
75583
|
-
return
|
|
75740
|
+
return resolve6(options.userConfigDirectory);
|
|
75584
75741
|
const sharedBase = cortexKitUserConfigBasePath();
|
|
75585
75742
|
const shared = detectConfigFile(sharedBase);
|
|
75586
75743
|
if (shared.format !== "none")
|
|
@@ -75607,7 +75764,7 @@ function createPromptSurfaceRuntime(options) {
|
|
|
75607
75764
|
const readGuidanceOverride = (configuredPath) => {
|
|
75608
75765
|
if (!configuredPath)
|
|
75609
75766
|
return;
|
|
75610
|
-
const path = isAbsolute5(configuredPath) ? configuredPath :
|
|
75767
|
+
const path = isAbsolute5(configuredPath) ? configuredPath : resolve6(userConfigDirectory, configuredPath);
|
|
75611
75768
|
let content;
|
|
75612
75769
|
try {
|
|
75613
75770
|
if (!statSync12(path).isFile()) {
|
|
@@ -75757,6 +75914,11 @@ var init_user_facing_codes = __esm(() => {
|
|
|
75757
75914
|
sentence: "Some finished background sessions could not be removed from this host.",
|
|
75758
75915
|
action: "They are removed automatically the next time Magic Context runs inside a registered OpenCode service."
|
|
75759
75916
|
},
|
|
75917
|
+
historian_saved_history_misaligned: {
|
|
75918
|
+
code: "MC-H03",
|
|
75919
|
+
sentence: "History compression is paused because this session's saved summaries no longer line up with its messages.",
|
|
75920
|
+
action: "Run /ctx-recomp to rebuild them."
|
|
75921
|
+
},
|
|
75760
75922
|
recomp_unavailable: {
|
|
75761
75923
|
code: "MC-R01",
|
|
75762
75924
|
sentence: "History compression could not be rebuilt.",
|
|
@@ -75927,6 +76089,11 @@ var init_user_facing_codes = __esm(() => {
|
|
|
75927
76089
|
sentence: "History compression is paused while the engine syncs.",
|
|
75928
76090
|
action: "Retry in a moment."
|
|
75929
76091
|
},
|
|
76092
|
+
history_compression_needs_message: {
|
|
76093
|
+
code: "MC-C12",
|
|
76094
|
+
sentence: "History compression has not seen this session since Magic Context reconnected.",
|
|
76095
|
+
action: "Send a message in this session first, then run /ctx-wrapup again."
|
|
76096
|
+
},
|
|
75930
76097
|
context_service_unavailable: {
|
|
75931
76098
|
code: "MC-C10",
|
|
75932
76099
|
sentence: "Magic Context is temporarily unavailable.",
|
|
@@ -78056,6 +78223,14 @@ function buildHistorianFailureNotice(failureCount, _lastError) {
|
|
|
78056
78223
|
return [heading, "", renderUserFacingFailure("historian_unavailable")].join(`
|
|
78057
78224
|
`);
|
|
78058
78225
|
}
|
|
78226
|
+
function buildStoredCompartmentsInvalidNotice() {
|
|
78227
|
+
return [
|
|
78228
|
+
"## Magic Context — History compression",
|
|
78229
|
+
"",
|
|
78230
|
+
renderUserFacingFailure("historian_saved_history_misaligned")
|
|
78231
|
+
].join(`
|
|
78232
|
+
`);
|
|
78233
|
+
}
|
|
78059
78234
|
function buildHistorianRepairPrompt(originalPrompt, previousOutput, validationError, language) {
|
|
78060
78235
|
const prompt = [
|
|
78061
78236
|
originalPrompt,
|
|
@@ -84739,6 +84914,12 @@ function v2NonNarrativeStoredGapRanges(db, sessionId, compartments) {
|
|
|
84739
84914
|
}
|
|
84740
84915
|
return safeRanges;
|
|
84741
84916
|
}
|
|
84917
|
+
function storedCompartmentFailureBackingOff(db, sessionId, validationError, now = Date.now()) {
|
|
84918
|
+
if (getHistorianFailureState(db, sessionId).lastError !== validationError)
|
|
84919
|
+
return false;
|
|
84920
|
+
const failedAt = loadProtectedTailMeta(db, sessionId).historianDrainFailureAt;
|
|
84921
|
+
return failedAt > 0 && failedAt <= now && now - failedAt < STORED_COMPARTMENT_FAILURE_BACKOFF_MS;
|
|
84922
|
+
}
|
|
84742
84923
|
function shouldSuppressHistorianAlert(sessionId) {
|
|
84743
84924
|
const lastAlert = lastHistorianAlertBySession.get(sessionId);
|
|
84744
84925
|
if (lastAlert && Date.now() - lastAlert < HISTORIAN_ALERT_COOLDOWN_MS) {
|
|
@@ -84861,13 +85042,37 @@ async function runCompartmentAgent(deps) {
|
|
|
84861
85042
|
}
|
|
84862
85043
|
return;
|
|
84863
85044
|
}
|
|
84864
|
-
|
|
84865
|
-
|
|
85045
|
+
let priorCompartments = getCompartments(db, sessionId);
|
|
85046
|
+
let existingValidationError = validateStoredCompartments(priorCompartments, v2NonNarrativeStoredGapRanges(db, sessionId, priorCompartments));
|
|
85047
|
+
const unresolvedInvolved = existingValidationError !== null && priorCompartments.some((compartment) => compartment.rebaseStatus === "unresolved");
|
|
85048
|
+
if (unresolvedInvolved && existingValidationError && storedCompartmentFailureBackingOff(db, sessionId, existingValidationError)) {
|
|
85049
|
+
sessionLog(sessionId, `historian no-op: stored compartments still invalid ("${existingValidationError}"); backing off`);
|
|
85050
|
+
telemetry.status = "noop";
|
|
85051
|
+
telemetry.failureReason = `existing-validation backoff: ${existingValidationError}`;
|
|
85052
|
+
return;
|
|
85053
|
+
}
|
|
85054
|
+
if (unresolvedInvolved && existingValidationError) {
|
|
85055
|
+
const recovery = recoverUnresolvedCompartments({
|
|
85056
|
+
db,
|
|
85057
|
+
sessionId,
|
|
85058
|
+
resolveOrdinal: (messageId) => readRawSessionMessageOrdinalById(sessionId, messageId) ?? undefined,
|
|
85059
|
+
reason: `historian pre-run check failed: ${existingValidationError}`
|
|
85060
|
+
});
|
|
85061
|
+
if (recovery.rowsRewritten > 0) {
|
|
85062
|
+
priorCompartments = getCompartments(db, sessionId);
|
|
85063
|
+
existingValidationError = validateStoredCompartments(priorCompartments, v2NonNarrativeStoredGapRanges(db, sessionId, priorCompartments));
|
|
85064
|
+
}
|
|
85065
|
+
}
|
|
84866
85066
|
if (existingValidationError) {
|
|
84867
85067
|
sessionLog(sessionId, `historian failure: source=existing-validation reason="${existingValidationError}"`);
|
|
84868
85068
|
const failCount = incrementHistorianFailure(db, sessionId, existingValidationError);
|
|
84869
85069
|
telemetry.failureReason = `existing-validation: ${existingValidationError}`;
|
|
84870
|
-
|
|
85070
|
+
if (unresolvedInvolved) {
|
|
85071
|
+
retainDrainReservationForRetryThrottle = true;
|
|
85072
|
+
await notifyHistorianIssue(buildStoredCompartmentsInvalidNotice());
|
|
85073
|
+
} else {
|
|
85074
|
+
await notifyHistorianIssue(buildHistorianFailureNotice(failCount, existingValidationError));
|
|
85075
|
+
}
|
|
84871
85076
|
return;
|
|
84872
85077
|
}
|
|
84873
85078
|
const offset = priorCompartments.length > 0 ? priorCompartments[priorCompartments.length - 1].endMessage + 1 : 1;
|
|
@@ -85350,7 +85555,7 @@ ${chunkText}`,
|
|
|
85350
85555
|
cleanupHistorianStateFile(stateFilePath);
|
|
85351
85556
|
}
|
|
85352
85557
|
}
|
|
85353
|
-
var inconsistentProducerWindows, HISTORIAN_ALERT_COOLDOWN_MS, lastHistorianAlertBySession;
|
|
85558
|
+
var inconsistentProducerWindows, HISTORIAN_ALERT_COOLDOWN_MS, lastHistorianAlertBySession, STORED_COMPARTMENT_FAILURE_BACKOFF_MS;
|
|
85354
85559
|
var init_compartment_runner_incremental = __esm(async () => {
|
|
85355
85560
|
init_compartment_embedding();
|
|
85356
85561
|
init_compartment_events();
|
|
@@ -85393,6 +85598,7 @@ var init_compartment_runner_incremental = __esm(async () => {
|
|
|
85393
85598
|
inconsistentProducerWindows = new Set;
|
|
85394
85599
|
HISTORIAN_ALERT_COOLDOWN_MS = 60 * 1000;
|
|
85395
85600
|
lastHistorianAlertBySession = new Map;
|
|
85601
|
+
STORED_COMPARTMENT_FAILURE_BACKOFF_MS = 30 * 60 * 1000;
|
|
85396
85602
|
});
|
|
85397
85603
|
|
|
85398
85604
|
// src/hooks/magic-context/compartment-runner-recomp.ts
|
|
@@ -106994,6 +107200,8 @@ var TODOWRITE_TOOL = "todowrite";
|
|
|
106994
107200
|
var availabilityBySession = new BoundedSessionMap(1000);
|
|
106995
107201
|
var permissionDeniedBySession = new BoundedSessionMap(2000);
|
|
106996
107202
|
var ctxReducePermissionDenyLogged = new BoundedSessionMap(1000);
|
|
107203
|
+
var ctxReduceSpawnPermissionDenied = new BoundedSessionMap(1000);
|
|
107204
|
+
var ctxReduceSpawnPermissionReads = new Map;
|
|
106997
107205
|
function permissionCacheKey(toolName, sessionId) {
|
|
106998
107206
|
return `${toolName}\x00${sessionId}`;
|
|
106999
107207
|
}
|
|
@@ -107012,6 +107220,12 @@ function verdictFromToolsMap(tools, toolName) {
|
|
|
107012
107220
|
return false;
|
|
107013
107221
|
return null;
|
|
107014
107222
|
}
|
|
107223
|
+
function unfrozenVerdict(sessionId, toolName, mapVerdict) {
|
|
107224
|
+
if (toolName === CTX_REDUCE_TOOL && ctxReduceSpawnPermissionDenied.get(sessionId) === true) {
|
|
107225
|
+
return false;
|
|
107226
|
+
}
|
|
107227
|
+
return mapVerdict ?? true;
|
|
107228
|
+
}
|
|
107015
107229
|
function resolveToolAvailabilityFromMessages(sessionId, toolName, messages) {
|
|
107016
107230
|
if (toolName === CTX_REDUCE_TOOL && !ctxReduceRegisteredGlobally) {
|
|
107017
107231
|
return { callable: false, frozen: true };
|
|
@@ -107023,7 +107237,7 @@ function resolveToolAvailabilityFromMessages(sessionId, toolName, messages) {
|
|
|
107023
107237
|
for (const message of messages) {
|
|
107024
107238
|
if (message.info?.role !== "user")
|
|
107025
107239
|
continue;
|
|
107026
|
-
const verdict = verdictFromToolsMap(message.info.tools, toolName)
|
|
107240
|
+
const verdict = unfrozenVerdict(sessionId, toolName, verdictFromToolsMap(message.info.tools, toolName));
|
|
107027
107241
|
availabilityBySession.set(key, verdict);
|
|
107028
107242
|
return { callable: verdict, frozen: true };
|
|
107029
107243
|
}
|
|
@@ -107046,7 +107260,7 @@ function resolveToolAvailability(sessionId, toolName) {
|
|
|
107046
107260
|
if (!row)
|
|
107047
107261
|
return { callable: true, frozen: false };
|
|
107048
107262
|
const verdict = row.tools === null ? null : verdictFromToolsMap(JSON.parse(row.tools), toolName);
|
|
107049
|
-
const resolved =
|
|
107263
|
+
const resolved = unfrozenVerdict(sessionId, toolName, verdict);
|
|
107050
107264
|
availabilityBySession.set(key, resolved);
|
|
107051
107265
|
return { callable: resolved, frozen: true };
|
|
107052
107266
|
} catch (error) {
|
|
@@ -107162,6 +107376,58 @@ async function resolveToolPermissionDenied(client, sessionId, toolName, activeAg
|
|
|
107162
107376
|
permissionDeniedBySession.set(permissionCacheKey(toolName, sessionId), denied);
|
|
107163
107377
|
return denied;
|
|
107164
107378
|
}
|
|
107379
|
+
function primeCtxReduceSpawnPermission(client, sessionId, spawnAgent) {
|
|
107380
|
+
if (!ctxReduceSpawnPermissionReadNeeded(sessionId))
|
|
107381
|
+
return Promise.resolve();
|
|
107382
|
+
const inFlight = ctxReduceSpawnPermissionReads.get(sessionId);
|
|
107383
|
+
if (inFlight)
|
|
107384
|
+
return inFlight;
|
|
107385
|
+
const read = (async () => {
|
|
107386
|
+
try {
|
|
107387
|
+
const denied = await resolveToolPermissionDenied(client, sessionId, CTX_REDUCE_TOOL, spawnAgent);
|
|
107388
|
+
ctxReduceSpawnPermissionDenied.set(sessionId, denied);
|
|
107389
|
+
if (denied) {
|
|
107390
|
+
sessionLog(sessionId, `ctx_reduce permission is denied for agent=${spawnAgent ?? "(session default)"}; session freezes without ctx_reduce tags, guidance, or nudges`);
|
|
107391
|
+
}
|
|
107392
|
+
} catch (error) {
|
|
107393
|
+
sessionLog(sessionId, "ctx_reduce permission read before freeze failed (fail-open):", error);
|
|
107394
|
+
} finally {
|
|
107395
|
+
ctxReduceSpawnPermissionReads.delete(sessionId);
|
|
107396
|
+
}
|
|
107397
|
+
})();
|
|
107398
|
+
ctxReduceSpawnPermissionReads.set(sessionId, read);
|
|
107399
|
+
return read;
|
|
107400
|
+
}
|
|
107401
|
+
function ctxReduceSpawnPermissionReadNeeded(sessionId) {
|
|
107402
|
+
return ctxReduceRegisteredGlobally && availabilityBySession.get(cacheKey2(CTX_REDUCE_TOOL, sessionId)) === undefined && ctxReduceSpawnPermissionDenied.get(sessionId) === undefined;
|
|
107403
|
+
}
|
|
107404
|
+
function spawnAgentFromMessages(messages) {
|
|
107405
|
+
for (const message of messages) {
|
|
107406
|
+
if (message.info?.role !== "user")
|
|
107407
|
+
continue;
|
|
107408
|
+
const agent = message.info.agent;
|
|
107409
|
+
return typeof agent === "string" && agent.length > 0 ? agent : undefined;
|
|
107410
|
+
}
|
|
107411
|
+
return;
|
|
107412
|
+
}
|
|
107413
|
+
function spawnAgentFromOpenCodeDb(sessionId) {
|
|
107414
|
+
if (!openCodeDbExists())
|
|
107415
|
+
return { persisted: false };
|
|
107416
|
+
try {
|
|
107417
|
+
const row = withReadOnlySessionDb((db) => db.prepare(`SELECT json_extract(data, '$.agent') AS agent FROM message
|
|
107418
|
+
WHERE session_id = ? AND json_extract(data, '$.role') = 'user'
|
|
107419
|
+
ORDER BY time_created ASC LIMIT 1`).get(sessionId));
|
|
107420
|
+
if (!row)
|
|
107421
|
+
return { persisted: false };
|
|
107422
|
+
return {
|
|
107423
|
+
persisted: true,
|
|
107424
|
+
agent: typeof row.agent === "string" && row.agent.length > 0 ? row.agent : undefined
|
|
107425
|
+
};
|
|
107426
|
+
} catch (error) {
|
|
107427
|
+
sessionLog(sessionId, "ctx_reduce spawn agent read failed:", error);
|
|
107428
|
+
return { persisted: false };
|
|
107429
|
+
}
|
|
107430
|
+
}
|
|
107165
107431
|
function todowritePermissionDenied(client, sessionId, activeAgent) {
|
|
107166
107432
|
return resolveToolPermissionDenied(client, sessionId, TODOWRITE_TOOL, activeAgent);
|
|
107167
107433
|
}
|
|
@@ -108930,6 +109196,12 @@ function createSystemPromptHashHandler(deps) {
|
|
|
108930
109196
|
sessionLog(sessionId, "system-prompt-hash session meta load failed:", error);
|
|
108931
109197
|
}
|
|
108932
109198
|
const isSubagentSession = sessionMetaEarly?.isSubagent === true;
|
|
109199
|
+
if (deps.client && ctxReduceSpawnPermissionReadNeeded(sessionId)) {
|
|
109200
|
+
const spawn = spawnAgentFromOpenCodeDb(sessionId);
|
|
109201
|
+
if (spawn.persisted) {
|
|
109202
|
+
await primeCtxReduceSpawnPermission(deps.client, sessionId, spawn.agent);
|
|
109203
|
+
}
|
|
109204
|
+
}
|
|
108933
109205
|
const availability = resolveCtxReduceAvailability(sessionId);
|
|
108934
109206
|
const ctxReduceCallable = availability.callable;
|
|
108935
109207
|
const subagentReduceMode = isSubagentSession && ctxReduceCallable;
|
|
@@ -118754,6 +119026,9 @@ function createTransform(deps) {
|
|
|
118754
119026
|
passOutcome.record("compaction-mode-transition-failure");
|
|
118755
119027
|
sessionLog(sessionId, "compaction mode transition failed (retrying next pass):", error);
|
|
118756
119028
|
}
|
|
119029
|
+
if (deps.client !== undefined && !compactionOff) {
|
|
119030
|
+
await primeCtxReduceSpawnPermission(deps.client, sessionId, spawnAgentFromMessages(messages));
|
|
119031
|
+
}
|
|
118757
119032
|
if (deps.transformMode === "rust") {
|
|
118758
119033
|
if (!rustModeTransform) {
|
|
118759
119034
|
sessionLog(sessionId, "rust transform unavailable; using raw passthrough");
|
|
@@ -121778,7 +122053,7 @@ import { join as join15 } from "node:path";
|
|
|
121778
122053
|
|
|
121779
122054
|
// src/shared/opencode-config-dir.ts
|
|
121780
122055
|
import { homedir as homedir9 } from "node:os";
|
|
121781
|
-
import { join as join14, resolve as
|
|
122056
|
+
import { join as join14, resolve as resolve7 } from "node:path";
|
|
121782
122057
|
function resolveHomeDir() {
|
|
121783
122058
|
return process.env.HOME?.trim() || homedir9();
|
|
121784
122059
|
}
|
|
@@ -121790,7 +122065,7 @@ function getOpenCodeGlobalConfigDir() {
|
|
|
121790
122065
|
}
|
|
121791
122066
|
function getEnvConfigDir() {
|
|
121792
122067
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
121793
|
-
return envConfigDir ?
|
|
122068
|
+
return envConfigDir ? resolve7(envConfigDir) : undefined;
|
|
121794
122069
|
}
|
|
121795
122070
|
function getOpenCodeConfigDirs() {
|
|
121796
122071
|
const dirs = [getOpenCodeGlobalConfigDir(), join14(resolveHomeDir(), ".opencode")];
|
|
@@ -124025,6 +124300,17 @@ class V2StoreReader {
|
|
|
124025
124300
|
range(sessionID, after, through) {
|
|
124026
124301
|
return trackDecodeOperation("range", () => through <= after ? [] : this.all(sessionID, after, undefined, through));
|
|
124027
124302
|
}
|
|
124303
|
+
spanRowStamps(sessionID, after, through) {
|
|
124304
|
+
if (!Number.isSafeInteger(after) || !Number.isSafeInteger(through))
|
|
124305
|
+
throw new Error("Invalid seq span");
|
|
124306
|
+
const rows = this.db.prepare(`SELECT seq, id, time_updated AS updated, length(CAST(data AS BLOB)) AS bytes
|
|
124307
|
+
FROM session_message WHERE session_id = ? AND seq > ? AND seq <= ?
|
|
124308
|
+
ORDER BY seq ASC`).all(sessionID, after, through);
|
|
124309
|
+
const stamps = new Map;
|
|
124310
|
+
for (const row of rows)
|
|
124311
|
+
stamps.set(row.seq, `${row.id}\x00${row.updated ?? ""}\x00${row.bytes ?? ""}`);
|
|
124312
|
+
return stamps;
|
|
124313
|
+
}
|
|
124028
124314
|
rawRowsThrough(sessionID, throughSeq, limit) {
|
|
124029
124315
|
return trackDecodeOperation("rawRowsThrough", () => {
|
|
124030
124316
|
if (!Number.isSafeInteger(throughSeq))
|
|
@@ -126040,8 +126326,11 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
126040
126326
|
anchors
|
|
126041
126327
|
});
|
|
126042
126328
|
if (moduleRoute) {
|
|
126043
|
-
const run = await runClassifyThroughModule(args, chunk, anchors, signal);
|
|
126044
|
-
recordInvocation(args, startedAt, {
|
|
126329
|
+
const { accounting, ...run } = await runClassifyThroughModule(args, chunk, anchors, signal);
|
|
126330
|
+
recordInvocation(args, startedAt, {
|
|
126331
|
+
status: "completed",
|
|
126332
|
+
moduleAccounting: accounting
|
|
126333
|
+
});
|
|
126045
126334
|
return run;
|
|
126046
126335
|
}
|
|
126047
126336
|
const executor = resolveHiddenCompletionExecutor(args.hiddenCompletionExecutor, args.client, args.db, args.sessionDirectory, "classify-memories");
|
|
@@ -126143,7 +126432,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
126143
126432
|
task: "classify",
|
|
126144
126433
|
command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash29("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
|
|
126145
126434
|
authority_generation: args.moduleAuthorityGeneration,
|
|
126146
|
-
|
|
126435
|
+
model_chain: resolvedModelChain,
|
|
126147
126436
|
payload: {
|
|
126148
126437
|
prompt_body: prompt,
|
|
126149
126438
|
items: chunk.map((candidate) => ({
|
|
@@ -126164,6 +126453,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
126164
126453
|
if (result.truncated === true) {
|
|
126165
126454
|
throw new Error("classify returned length-capped output");
|
|
126166
126455
|
}
|
|
126456
|
+
const accounting = moduleClassifyAccounting(result);
|
|
126167
126457
|
const parsed = validateClassifyManifest(manifestText, new Set(chunk.map((candidate) => candidate.id)));
|
|
126168
126458
|
const rows = parsed.map((entry) => {
|
|
126169
126459
|
const candidate = chunk.find((item) => item.id === entry.id);
|
|
@@ -126236,7 +126526,39 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
126236
126526
|
throw new Error(`module accepted unknown memory ${moduleId}`);
|
|
126237
126527
|
return candidate.contextMemory.id;
|
|
126238
126528
|
});
|
|
126239
|
-
return {
|
|
126529
|
+
return {
|
|
126530
|
+
classified: acceptedContextIds.length,
|
|
126531
|
+
changed: acceptedContextIds.length,
|
|
126532
|
+
accounting
|
|
126533
|
+
};
|
|
126534
|
+
}
|
|
126535
|
+
function nonNegativeCount(value) {
|
|
126536
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
126537
|
+
}
|
|
126538
|
+
function moduleClassifyAccounting(result) {
|
|
126539
|
+
const accounting = {};
|
|
126540
|
+
const usage = result.usage;
|
|
126541
|
+
if (usage && typeof usage === "object") {
|
|
126542
|
+
const record = usage;
|
|
126543
|
+
accounting.tokens = {
|
|
126544
|
+
input: nonNegativeCount(record.input),
|
|
126545
|
+
output: nonNegativeCount(record.output),
|
|
126546
|
+
cacheRead: nonNegativeCount(record.cache_read),
|
|
126547
|
+
cacheWrite: nonNegativeCount(record.cache_write)
|
|
126548
|
+
};
|
|
126549
|
+
}
|
|
126550
|
+
const diagnostics = result.diagnostics;
|
|
126551
|
+
const model = diagnostics && typeof diagnostics === "object" ? diagnostics.model : undefined;
|
|
126552
|
+
if (typeof model === "string") {
|
|
126553
|
+
const parsed = parseProviderModel(model);
|
|
126554
|
+
if (parsed) {
|
|
126555
|
+
accounting.providerId = parsed.providerID;
|
|
126556
|
+
accounting.modelId = parsed.modelID;
|
|
126557
|
+
} else if (model.trim()) {
|
|
126558
|
+
accounting.modelId = model.trim();
|
|
126559
|
+
}
|
|
126560
|
+
}
|
|
126561
|
+
return accounting;
|
|
126240
126562
|
}
|
|
126241
126563
|
function applyClassifications(args, chunk, manifestText) {
|
|
126242
126564
|
const byId = new Map(chunk.map((m) => [m.id, m]));
|
|
@@ -126281,6 +126603,11 @@ function recordInvocation(args, startedAt, params) {
|
|
|
126281
126603
|
providerId: params.completion.providerId,
|
|
126282
126604
|
modelId: params.completion.modelId
|
|
126283
126605
|
} : {},
|
|
126606
|
+
...params.moduleAccounting ? {
|
|
126607
|
+
tokens: params.moduleAccounting.tokens,
|
|
126608
|
+
providerId: params.moduleAccounting.providerId,
|
|
126609
|
+
modelId: params.moduleAccounting.modelId
|
|
126610
|
+
} : {},
|
|
126284
126611
|
error: params.error
|
|
126285
126612
|
});
|
|
126286
126613
|
}
|
|
@@ -132253,13 +132580,18 @@ class V2ContextRefusal extends Error {
|
|
|
132253
132580
|
this.name = "V2ContextRefusal";
|
|
132254
132581
|
}
|
|
132255
132582
|
}
|
|
132256
|
-
|
|
132583
|
+
var INTERRUPT_CONFIRMATION_TIMEOUT_MS = 2000;
|
|
132584
|
+
var systemTimers = {
|
|
132585
|
+
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
132586
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
132587
|
+
};
|
|
132588
|
+
async function interruptBeforeProvider(session, sessionID, timers = systemTimers) {
|
|
132257
132589
|
let timer;
|
|
132258
132590
|
try {
|
|
132259
132591
|
const result = await Promise.race([
|
|
132260
132592
|
session.interrupt({ sessionID }),
|
|
132261
132593
|
new Promise((_, reject) => {
|
|
132262
|
-
timer = setTimeout(() => reject(new Error(
|
|
132594
|
+
timer = timers.setTimeout(() => reject(new Error(`interrupt exceeded ${INTERRUPT_CONFIRMATION_TIMEOUT_MS} ms`)), INTERRUPT_CONFIRMATION_TIMEOUT_MS);
|
|
132263
132595
|
})
|
|
132264
132596
|
]);
|
|
132265
132597
|
if (result.interrupted !== true)
|
|
@@ -132267,10 +132599,80 @@ async function interruptBeforeProvider(session, sessionID) {
|
|
|
132267
132599
|
} catch (cause) {
|
|
132268
132600
|
throw new V2ContextRefusal(undefined, { cause });
|
|
132269
132601
|
} finally {
|
|
132270
|
-
|
|
132602
|
+
if (timer !== undefined)
|
|
132603
|
+
timers.clearTimeout(timer);
|
|
132271
132604
|
}
|
|
132272
132605
|
}
|
|
132273
132606
|
|
|
132607
|
+
// src/v2/hooks/restore-rows.ts
|
|
132608
|
+
class RestoredRowCache {
|
|
132609
|
+
capacity;
|
|
132610
|
+
sessions = new Map;
|
|
132611
|
+
constructor(capacity = 16) {
|
|
132612
|
+
this.capacity = capacity;
|
|
132613
|
+
}
|
|
132614
|
+
rows(reader, sessionID, after, through) {
|
|
132615
|
+
if (through <= after)
|
|
132616
|
+
return [];
|
|
132617
|
+
const kept = this.sessions.get(sessionID) ?? new Map;
|
|
132618
|
+
const stamps = reader.spanRowStamps(sessionID, after, through);
|
|
132619
|
+
const runs = [];
|
|
132620
|
+
let previous = after;
|
|
132621
|
+
let open;
|
|
132622
|
+
for (const [seq, stamp] of stamps) {
|
|
132623
|
+
if (kept.get(seq)?.stamp === stamp) {
|
|
132624
|
+
open = undefined;
|
|
132625
|
+
} else if (open) {
|
|
132626
|
+
open.through = seq;
|
|
132627
|
+
} else {
|
|
132628
|
+
open = { after: previous, through: seq };
|
|
132629
|
+
runs.push(open);
|
|
132630
|
+
}
|
|
132631
|
+
previous = seq;
|
|
132632
|
+
}
|
|
132633
|
+
const fresh = new Map;
|
|
132634
|
+
for (const run of runs)
|
|
132635
|
+
for (const row of readPages(reader, sessionID, run.after, run.through))
|
|
132636
|
+
fresh.set(row.seq, row);
|
|
132637
|
+
const next = new Map;
|
|
132638
|
+
const rows = [];
|
|
132639
|
+
for (const [seq, stamp] of stamps) {
|
|
132640
|
+
const row = fresh.get(seq) ?? kept.get(seq)?.row;
|
|
132641
|
+
if (!row)
|
|
132642
|
+
continue;
|
|
132643
|
+
next.set(seq, { stamp, row });
|
|
132644
|
+
rows.push(row);
|
|
132645
|
+
}
|
|
132646
|
+
this.sessions.delete(sessionID);
|
|
132647
|
+
this.sessions.set(sessionID, next);
|
|
132648
|
+
while (this.sessions.size > this.capacity) {
|
|
132649
|
+
const oldest = this.sessions.keys().next().value;
|
|
132650
|
+
if (oldest === undefined)
|
|
132651
|
+
break;
|
|
132652
|
+
this.sessions.delete(oldest);
|
|
132653
|
+
}
|
|
132654
|
+
return structuredClone(rows);
|
|
132655
|
+
}
|
|
132656
|
+
forget(sessionID) {
|
|
132657
|
+
this.sessions.delete(sessionID);
|
|
132658
|
+
}
|
|
132659
|
+
clear() {
|
|
132660
|
+
this.sessions.clear();
|
|
132661
|
+
}
|
|
132662
|
+
}
|
|
132663
|
+
function readPages(reader, sessionID, after, through) {
|
|
132664
|
+
const rows = [];
|
|
132665
|
+
let cursor = after;
|
|
132666
|
+
while (cursor < through) {
|
|
132667
|
+
const page = reader.page(sessionID, { after: cursor, through, limit: 100 });
|
|
132668
|
+
rows.push(...page.rows);
|
|
132669
|
+
if (page.rows.length < 100 || page.cursor === undefined)
|
|
132670
|
+
break;
|
|
132671
|
+
cursor = page.cursor;
|
|
132672
|
+
}
|
|
132673
|
+
return rows;
|
|
132674
|
+
}
|
|
132675
|
+
|
|
132274
132676
|
// src/hooks/magic-context/live-session-state.ts
|
|
132275
132677
|
function createLiveSessionState() {
|
|
132276
132678
|
return {
|
|
@@ -146107,7 +146509,7 @@ import { isAbsolute as isAbsolute7 } from "node:path";
|
|
|
146107
146509
|
// ../retina-local-fs/src/path-fence.ts
|
|
146108
146510
|
import { lstat as lstat2, readlink, realpath as realpath2 } from "node:fs/promises";
|
|
146109
146511
|
import { homedir as homedir12 } from "node:os";
|
|
146110
|
-
import { basename as basename4, dirname as dirname10, isAbsolute as isAbsolute6, join as join20, relative, resolve as
|
|
146512
|
+
import { basename as basename4, dirname as dirname10, isAbsolute as isAbsolute6, join as join20, relative, resolve as resolve8, sep } from "node:path";
|
|
146111
146513
|
|
|
146112
146514
|
// ../retina-local-fs/src/errors.ts
|
|
146113
146515
|
class ProviderError extends Error {
|
|
@@ -146123,7 +146525,7 @@ class ProviderError extends Error {
|
|
|
146123
146525
|
async function resolveAndFenceProviderPath(configuredPath, options) {
|
|
146124
146526
|
const { home, dataDirectory } = await resolveFenceRoots(options);
|
|
146125
146527
|
const expanded = configuredPath.startsWith("~/") ? join20(home, configuredPath.slice(2)) : configuredPath === "~" ? home : configuredPath;
|
|
146126
|
-
const absolute = isAbsolute6(expanded) ?
|
|
146528
|
+
const absolute = isAbsolute6(expanded) ? resolve8(expanded) : resolve8(options.cwd ?? process.cwd(), expanded);
|
|
146127
146529
|
const canonical = await canonicalPath(absolute, options.allowMissing);
|
|
146128
146530
|
if (isFencedPath(canonical, home, dataDirectory)) {
|
|
146129
146531
|
throw new ProviderError("fenced_path", `Refusing fenced path: ${canonical}`);
|
|
@@ -146131,14 +146533,14 @@ async function resolveAndFenceProviderPath(configuredPath, options) {
|
|
|
146131
146533
|
return canonical;
|
|
146132
146534
|
}
|
|
146133
146535
|
async function resolveFenceRoots(options) {
|
|
146134
|
-
const configuredHomePath =
|
|
146536
|
+
const configuredHomePath = resolve8(options.homeDirectory ?? process.env.HOME ?? homedir12());
|
|
146135
146537
|
let home;
|
|
146136
146538
|
try {
|
|
146137
146539
|
home = await realpath2(configuredHomePath);
|
|
146138
146540
|
} catch (error) {
|
|
146139
146541
|
throw fsError(configuredHomePath, error);
|
|
146140
146542
|
}
|
|
146141
|
-
const configuredDataDirectory =
|
|
146543
|
+
const configuredDataDirectory = resolve8(options.dataDirectory ?? process.env.XDG_DATA_HOME ?? join20(home, ".local", "share"));
|
|
146142
146544
|
const dataDirectory = await canonicalPath(configuredDataDirectory, true);
|
|
146143
146545
|
return { home, dataDirectory };
|
|
146144
146546
|
}
|
|
@@ -146156,7 +146558,7 @@ async function canonicalPath(path, allowMissing) {
|
|
|
146156
146558
|
const metadata = await lstat2(candidate);
|
|
146157
146559
|
if (metadata.isSymbolicLink()) {
|
|
146158
146560
|
const target = await readlink(candidate);
|
|
146159
|
-
const resolvedTarget =
|
|
146561
|
+
const resolvedTarget = resolve8(dirname10(candidate), target);
|
|
146160
146562
|
return canonicalPath(join20(resolvedTarget, ...suffix), true);
|
|
146161
146563
|
}
|
|
146162
146564
|
} catch (candidateError) {
|
|
@@ -146180,8 +146582,8 @@ async function canonicalPath(path, allowMissing) {
|
|
|
146180
146582
|
}
|
|
146181
146583
|
}
|
|
146182
146584
|
}
|
|
146183
|
-
function isFencedPath(canonicalPath, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join20(
|
|
146184
|
-
const cortexkitRoot = join20(
|
|
146585
|
+
function isFencedPath(canonicalPath, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join20(resolve8(homeDirectory), ".local", "share")) {
|
|
146586
|
+
const cortexkitRoot = join20(resolve8(dataDirectory), "cortexkit");
|
|
146185
146587
|
const relativeToCortexkit = relative(cortexkitRoot, canonicalPath);
|
|
146186
146588
|
const insideCortexkit = relativeToCortexkit !== "" && relativeToCortexkit !== ".." && !relativeToCortexkit.startsWith(`..${sep}`) && !isAbsolute6(relativeToCortexkit);
|
|
146187
146589
|
const parts = insideCortexkit ? relativeToCortexkit.split(sep) : [];
|
|
@@ -147654,6 +148056,7 @@ async function registerContext(context) {
|
|
|
147654
148056
|
const historyRefreshSessions = new Set;
|
|
147655
148057
|
const pendingMaterializationSessions = new Set;
|
|
147656
148058
|
const lastHeuristicsTurnId = new Map;
|
|
148059
|
+
const restoredRows = new RestoredRowCache;
|
|
147657
148060
|
const rawProviders = new Map;
|
|
147658
148061
|
let passDuties;
|
|
147659
148062
|
let toolDuties;
|
|
@@ -147814,6 +148217,7 @@ async function registerContext(context) {
|
|
|
147814
148217
|
historyRefreshSessions.delete(sessionID);
|
|
147815
148218
|
pendingMaterializationSessions.delete(sessionID);
|
|
147816
148219
|
lastHeuristicsTurnId.delete(sessionID);
|
|
148220
|
+
restoredRows.forget(sessionID);
|
|
147817
148221
|
systemPromptRefreshSessions.delete(sessionID);
|
|
147818
148222
|
systemPrompt?.clearSession(sessionID);
|
|
147819
148223
|
tagger.cleanup(sessionID);
|
|
@@ -148038,7 +148442,7 @@ async function registerContext(context) {
|
|
|
148038
148442
|
const servedBoundary = boundaryID ? servedBoundaryRow(reader, draft.sessionID, boundaryID) : null;
|
|
148039
148443
|
const boundary = servedBoundary?.seq ?? reader.sequenceForId(draft.sessionID, boundaryID) ?? (reader.earliestSequence(draft.sessionID) ?? 0) - 1;
|
|
148040
148444
|
const present = new Set(draft.messages.map((message) => message.id));
|
|
148041
|
-
const restored =
|
|
148445
|
+
const restored = restoredRows.rows(reader, draft.sessionID, boundary, cut.seq).filter((row) => !present.has(row.id)).flatMap((row) => restoreRow(row, draft.model, hostUsesMediaAssets() ? {
|
|
148042
148446
|
asset: hostMediaAsset,
|
|
148043
148447
|
unavailable: (detail) => sessionLog(draft.sessionID, `v2 restore: attachment replaced by a note row=${detail.rowID} name=${JSON.stringify(detail.name ?? null)} mediaType=${detail.mediaType} reason=${JSON.stringify(detail.reason)}`)
|
|
148044
148448
|
} : undefined));
|
|
@@ -148191,6 +148595,7 @@ ${baseline}
|
|
|
148191
148595
|
for (const release of rawProviders.values())
|
|
148192
148596
|
release();
|
|
148193
148597
|
rawProviders.clear();
|
|
148598
|
+
restoredRows.clear();
|
|
148194
148599
|
}
|
|
148195
148600
|
};
|
|
148196
148601
|
}
|
|
@@ -148291,6 +148696,9 @@ function packageInfo() {
|
|
|
148291
148696
|
directory = parent;
|
|
148292
148697
|
}
|
|
148293
148698
|
}
|
|
148699
|
+
function formatUpdateAvailableMessage(latest, current) {
|
|
148700
|
+
return `Magic Context ${latest} is available (running ${current}). To install it, open /plugins, select Magic Context and press ctrl+u, or run \`opencode plugin update\`. A version-pinned plugin entry must be changed in your OpenCode config instead.`;
|
|
148701
|
+
}
|
|
148294
148702
|
function startUpdateChecks(context, check = (signal) => {
|
|
148295
148703
|
return packageInfo().development ? Promise.resolve(null) : getLatestVersion("latest", { signal });
|
|
148296
148704
|
}) {
|
|
@@ -148305,10 +148713,11 @@ function startUpdateChecks(context, check = (signal) => {
|
|
|
148305
148713
|
continue;
|
|
148306
148714
|
await context.storage.set("version-check-at", Date.now());
|
|
148307
148715
|
const latest = await check(controller.signal);
|
|
148308
|
-
const
|
|
148309
|
-
|
|
148716
|
+
const current = packageInfo().version;
|
|
148717
|
+
const comparison = latest ? compareSemverCore(latest, current) : null;
|
|
148718
|
+
if (latest && !controller.signal.aborted && comparison !== null && comparison > 0) {
|
|
148310
148719
|
pushNotification("toast", {
|
|
148311
|
-
message:
|
|
148720
|
+
message: formatUpdateAvailableMessage(latest, current),
|
|
148312
148721
|
variant: "info"
|
|
148313
148722
|
});
|
|
148314
148723
|
}
|