@wolfx/pi-magic-context 0.22.4 → 0.23.0
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/README.md +1 -3
- package/dist/index.js +3855 -1137
- package/dist/subagent-entry.js +1302 -358
- package/package.json +3 -1
package/dist/subagent-entry.js
CHANGED
|
@@ -46,6 +46,111 @@ var __export = (target, all) => {
|
|
|
46
46
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
47
47
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
48
48
|
|
|
49
|
+
// ../plugin/src/shared/harness.ts
|
|
50
|
+
function setHarness(value) {
|
|
51
|
+
if (harnessLocked && currentHarness !== value) {
|
|
52
|
+
throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
|
|
53
|
+
}
|
|
54
|
+
currentHarness = value;
|
|
55
|
+
harnessLocked = true;
|
|
56
|
+
}
|
|
57
|
+
function getHarness() {
|
|
58
|
+
return currentHarness;
|
|
59
|
+
}
|
|
60
|
+
var currentHarness = "opencode", harnessLocked = false;
|
|
61
|
+
|
|
62
|
+
// ../plugin/src/shared/data-path.ts
|
|
63
|
+
import * as os from "node:os";
|
|
64
|
+
import * as path from "node:path";
|
|
65
|
+
function getDataDir() {
|
|
66
|
+
return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
|
|
67
|
+
}
|
|
68
|
+
function getMagicContextTempDir(harness = getHarness()) {
|
|
69
|
+
return path.join(os.tmpdir(), harness, "magic-context");
|
|
70
|
+
}
|
|
71
|
+
function getMagicContextLogPath(harness = getHarness()) {
|
|
72
|
+
return path.join(getMagicContextTempDir(harness), "magic-context.log");
|
|
73
|
+
}
|
|
74
|
+
function getProjectMagicContextDir(directory) {
|
|
75
|
+
return path.join(directory, ".magic-context");
|
|
76
|
+
}
|
|
77
|
+
function getProjectMagicContextHistorianDir(directory) {
|
|
78
|
+
return path.join(getProjectMagicContextDir(directory), "historian");
|
|
79
|
+
}
|
|
80
|
+
function getOpenCodeStorageDir() {
|
|
81
|
+
return path.join(getDataDir(), "opencode", "storage");
|
|
82
|
+
}
|
|
83
|
+
function getMagicContextStorageDir() {
|
|
84
|
+
return path.join(getDataDir(), "cortexkit", "magic-context");
|
|
85
|
+
}
|
|
86
|
+
function getLegacyOpenCodeMagicContextStorageDir() {
|
|
87
|
+
return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
88
|
+
}
|
|
89
|
+
var init_data_path = () => {};
|
|
90
|
+
|
|
91
|
+
// ../plugin/src/shared/logger.ts
|
|
92
|
+
import * as fs from "node:fs";
|
|
93
|
+
import * as path2 from "node:path";
|
|
94
|
+
function ensureDir(filePath) {
|
|
95
|
+
const dir = path2.dirname(filePath);
|
|
96
|
+
if (dir === lastEnsuredDir)
|
|
97
|
+
return;
|
|
98
|
+
try {
|
|
99
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
100
|
+
lastEnsuredDir = dir;
|
|
101
|
+
} catch {}
|
|
102
|
+
}
|
|
103
|
+
function flush() {
|
|
104
|
+
if (flushTimer) {
|
|
105
|
+
clearTimeout(flushTimer);
|
|
106
|
+
flushTimer = null;
|
|
107
|
+
}
|
|
108
|
+
if (buffer.length === 0)
|
|
109
|
+
return;
|
|
110
|
+
const data = buffer.join("");
|
|
111
|
+
buffer = [];
|
|
112
|
+
try {
|
|
113
|
+
const logFile = getMagicContextLogPath();
|
|
114
|
+
ensureDir(logFile);
|
|
115
|
+
fs.appendFileSync(logFile, data);
|
|
116
|
+
} catch {}
|
|
117
|
+
}
|
|
118
|
+
function scheduleFlush() {
|
|
119
|
+
if (flushTimer)
|
|
120
|
+
return;
|
|
121
|
+
flushTimer = setTimeout(() => {
|
|
122
|
+
flushTimer = null;
|
|
123
|
+
flush();
|
|
124
|
+
}, FLUSH_INTERVAL_MS);
|
|
125
|
+
}
|
|
126
|
+
function log(message, data) {
|
|
127
|
+
if (isTestEnv)
|
|
128
|
+
return;
|
|
129
|
+
try {
|
|
130
|
+
const timestamp = new Date().toISOString();
|
|
131
|
+
const serialized = data === undefined ? "" : data instanceof Error ? ` ${data.message}${data.stack ? `
|
|
132
|
+
${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
|
|
133
|
+
buffer.push(`[${timestamp}] ${message}${serialized}
|
|
134
|
+
`);
|
|
135
|
+
if (buffer.length >= BUFFER_SIZE_LIMIT) {
|
|
136
|
+
flush();
|
|
137
|
+
} else {
|
|
138
|
+
scheduleFlush();
|
|
139
|
+
}
|
|
140
|
+
} catch {}
|
|
141
|
+
}
|
|
142
|
+
function sessionLog(sessionId, message, data) {
|
|
143
|
+
log(`[magic-context][${sessionId}] ${message}`, data);
|
|
144
|
+
}
|
|
145
|
+
var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, lastEnsuredDir = null;
|
|
146
|
+
var init_logger = __esm(() => {
|
|
147
|
+
init_data_path();
|
|
148
|
+
buffer = [];
|
|
149
|
+
if (!isTestEnv) {
|
|
150
|
+
process.on("exit", flush);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
49
154
|
// ../../node_modules/.bun/esprima@4.0.1/node_modules/esprima/dist/esprima.js
|
|
50
155
|
var require_esprima = __commonJS((exports, module) => {
|
|
51
156
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
@@ -7804,53 +7909,10 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
7804
7909
|
});
|
|
7805
7910
|
|
|
7806
7911
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
7912
|
+
init_data_path();
|
|
7807
7913
|
import { copyFileSync, cpSync, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "node:fs";
|
|
7808
7914
|
import { dirname as dirname2, join as join4 } from "node:path";
|
|
7809
7915
|
|
|
7810
|
-
// ../plugin/src/shared/data-path.ts
|
|
7811
|
-
import * as os from "node:os";
|
|
7812
|
-
import * as path from "node:path";
|
|
7813
|
-
|
|
7814
|
-
// ../plugin/src/shared/harness.ts
|
|
7815
|
-
var currentHarness = "opencode";
|
|
7816
|
-
var harnessLocked = false;
|
|
7817
|
-
function setHarness(value) {
|
|
7818
|
-
if (harnessLocked && currentHarness !== value) {
|
|
7819
|
-
throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
|
|
7820
|
-
}
|
|
7821
|
-
currentHarness = value;
|
|
7822
|
-
harnessLocked = true;
|
|
7823
|
-
}
|
|
7824
|
-
function getHarness() {
|
|
7825
|
-
return currentHarness;
|
|
7826
|
-
}
|
|
7827
|
-
|
|
7828
|
-
// ../plugin/src/shared/data-path.ts
|
|
7829
|
-
function getDataDir() {
|
|
7830
|
-
return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
|
|
7831
|
-
}
|
|
7832
|
-
function getMagicContextTempDir(harness = getHarness()) {
|
|
7833
|
-
return path.join(os.tmpdir(), harness, "magic-context");
|
|
7834
|
-
}
|
|
7835
|
-
function getMagicContextLogPath(harness = getHarness()) {
|
|
7836
|
-
return path.join(getMagicContextTempDir(harness), "magic-context.log");
|
|
7837
|
-
}
|
|
7838
|
-
function getProjectMagicContextDir(directory) {
|
|
7839
|
-
return path.join(directory, ".magic-context");
|
|
7840
|
-
}
|
|
7841
|
-
function getProjectMagicContextHistorianDir(directory) {
|
|
7842
|
-
return path.join(getProjectMagicContextDir(directory), "historian");
|
|
7843
|
-
}
|
|
7844
|
-
function getOpenCodeStorageDir() {
|
|
7845
|
-
return path.join(getDataDir(), "opencode", "storage");
|
|
7846
|
-
}
|
|
7847
|
-
function getMagicContextStorageDir() {
|
|
7848
|
-
return path.join(getDataDir(), "cortexkit", "magic-context");
|
|
7849
|
-
}
|
|
7850
|
-
function getLegacyOpenCodeMagicContextStorageDir() {
|
|
7851
|
-
return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
7852
|
-
}
|
|
7853
|
-
|
|
7854
7916
|
// ../plugin/src/shared/error-message.ts
|
|
7855
7917
|
function getErrorMessage(error) {
|
|
7856
7918
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -7927,69 +7989,8 @@ function safeString(value) {
|
|
|
7927
7989
|
}
|
|
7928
7990
|
}
|
|
7929
7991
|
|
|
7930
|
-
// ../plugin/src/
|
|
7931
|
-
|
|
7932
|
-
import * as path2 from "node:path";
|
|
7933
|
-
var isTestEnv = false;
|
|
7934
|
-
var buffer = [];
|
|
7935
|
-
var flushTimer = null;
|
|
7936
|
-
var FLUSH_INTERVAL_MS = 500;
|
|
7937
|
-
var BUFFER_SIZE_LIMIT = 50;
|
|
7938
|
-
var lastEnsuredDir = null;
|
|
7939
|
-
function ensureDir(filePath) {
|
|
7940
|
-
const dir = path2.dirname(filePath);
|
|
7941
|
-
if (dir === lastEnsuredDir)
|
|
7942
|
-
return;
|
|
7943
|
-
try {
|
|
7944
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
7945
|
-
lastEnsuredDir = dir;
|
|
7946
|
-
} catch {}
|
|
7947
|
-
}
|
|
7948
|
-
function flush() {
|
|
7949
|
-
if (flushTimer) {
|
|
7950
|
-
clearTimeout(flushTimer);
|
|
7951
|
-
flushTimer = null;
|
|
7952
|
-
}
|
|
7953
|
-
if (buffer.length === 0)
|
|
7954
|
-
return;
|
|
7955
|
-
const data = buffer.join("");
|
|
7956
|
-
buffer = [];
|
|
7957
|
-
try {
|
|
7958
|
-
const logFile = getMagicContextLogPath();
|
|
7959
|
-
ensureDir(logFile);
|
|
7960
|
-
fs.appendFileSync(logFile, data);
|
|
7961
|
-
} catch {}
|
|
7962
|
-
}
|
|
7963
|
-
function scheduleFlush() {
|
|
7964
|
-
if (flushTimer)
|
|
7965
|
-
return;
|
|
7966
|
-
flushTimer = setTimeout(() => {
|
|
7967
|
-
flushTimer = null;
|
|
7968
|
-
flush();
|
|
7969
|
-
}, FLUSH_INTERVAL_MS);
|
|
7970
|
-
}
|
|
7971
|
-
function log(message, data) {
|
|
7972
|
-
if (isTestEnv)
|
|
7973
|
-
return;
|
|
7974
|
-
try {
|
|
7975
|
-
const timestamp = new Date().toISOString();
|
|
7976
|
-
const serialized = data === undefined ? "" : data instanceof Error ? ` ${data.message}${data.stack ? `
|
|
7977
|
-
${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
|
|
7978
|
-
buffer.push(`[${timestamp}] ${message}${serialized}
|
|
7979
|
-
`);
|
|
7980
|
-
if (buffer.length >= BUFFER_SIZE_LIMIT) {
|
|
7981
|
-
flush();
|
|
7982
|
-
} else {
|
|
7983
|
-
scheduleFlush();
|
|
7984
|
-
}
|
|
7985
|
-
} catch {}
|
|
7986
|
-
}
|
|
7987
|
-
function sessionLog(sessionId, message, data) {
|
|
7988
|
-
log(`[magic-context][${sessionId}] ${message}`, data);
|
|
7989
|
-
}
|
|
7990
|
-
if (!isTestEnv) {
|
|
7991
|
-
process.on("exit", flush);
|
|
7992
|
-
}
|
|
7992
|
+
// ../plugin/src/features/magic-context/storage-db.ts
|
|
7993
|
+
init_logger();
|
|
7993
7994
|
|
|
7994
7995
|
// ../plugin/src/shared/sqlite.ts
|
|
7995
7996
|
var isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
|
|
@@ -8045,6 +8046,7 @@ function closeQuietly(db) {
|
|
|
8045
8046
|
}
|
|
8046
8047
|
|
|
8047
8048
|
// ../plugin/src/features/magic-context/key-files/project-key-files.ts
|
|
8049
|
+
init_logger();
|
|
8048
8050
|
import { createHash } from "node:crypto";
|
|
8049
8051
|
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
8050
8052
|
import { join as join2, resolve, sep } from "node:path";
|
|
@@ -8161,6 +8163,7 @@ function isRelativeProjectFile(projectPath, relativePath) {
|
|
|
8161
8163
|
}
|
|
8162
8164
|
|
|
8163
8165
|
// ../plugin/src/features/magic-context/migrations.ts
|
|
8166
|
+
init_logger();
|
|
8164
8167
|
function tableExists(db, name) {
|
|
8165
8168
|
return Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name));
|
|
8166
8169
|
}
|
|
@@ -8916,6 +8919,50 @@ var MIGRATIONS = [
|
|
|
8916
8919
|
cached_m0_model_key = NULL`).run();
|
|
8917
8920
|
}
|
|
8918
8921
|
}
|
|
8922
|
+
},
|
|
8923
|
+
{
|
|
8924
|
+
version: 31,
|
|
8925
|
+
description: "Nudge redesign: Channel 1 cadence (last_nudge_undropped) + Channel 2 ceiling lease " + "(channel2_nudge_state); zero legacy ctx_reduce-nudge sticky/anchor state (startup heal)",
|
|
8926
|
+
up: (db) => {
|
|
8927
|
+
const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta' LIMIT 1").get();
|
|
8928
|
+
if (!hasSessionMeta)
|
|
8929
|
+
return;
|
|
8930
|
+
ensureColumn(db, "session_meta", "last_nudge_undropped", "INTEGER DEFAULT 0");
|
|
8931
|
+
ensureColumn(db, "session_meta", "channel2_nudge_state", "TEXT DEFAULT ''");
|
|
8932
|
+
const columns = new Set(db.prepare("PRAGMA table_info(session_meta)").all().map((column) => column.name));
|
|
8933
|
+
if (columns.has("sticky_turn_reminder_text")) {
|
|
8934
|
+
db.prepare(`UPDATE session_meta SET
|
|
8935
|
+
sticky_turn_reminder_text = '',
|
|
8936
|
+
sticky_turn_reminder_message_id = '',
|
|
8937
|
+
nudge_anchor_message_id = '',
|
|
8938
|
+
nudge_anchor_text = ''`).run();
|
|
8939
|
+
}
|
|
8940
|
+
}
|
|
8941
|
+
},
|
|
8942
|
+
{
|
|
8943
|
+
version: 32,
|
|
8944
|
+
description: "Protected tail boundary state, usage resolver fields, recovery escape, and drain quota",
|
|
8945
|
+
up: (db) => {
|
|
8946
|
+
const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta' LIMIT 1").get();
|
|
8947
|
+
if (!hasSessionMeta)
|
|
8948
|
+
return;
|
|
8949
|
+
ensureColumn(db, "session_meta", "prior_boundary_ordinal", "INTEGER NOT NULL DEFAULT 1");
|
|
8950
|
+
ensureColumn(db, "session_meta", "protected_tail_policy_version", "INTEGER NOT NULL DEFAULT 0");
|
|
8951
|
+
ensureColumn(db, "session_meta", "protected_tail_drain_window_started_at", "INTEGER NOT NULL DEFAULT 0");
|
|
8952
|
+
ensureColumn(db, "session_meta", "protected_tail_drain_tokens", "INTEGER NOT NULL DEFAULT 0");
|
|
8953
|
+
ensureColumn(db, "session_meta", "recovery_no_eligible_head_count", "INTEGER NOT NULL DEFAULT 0");
|
|
8954
|
+
ensureColumn(db, "session_meta", "force_emergency_bypass_window_start", "INTEGER NOT NULL DEFAULT 0");
|
|
8955
|
+
ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
|
|
8956
|
+
ensureColumn(db, "session_meta", "last_usage_context_limit", "INTEGER NOT NULL DEFAULT 0");
|
|
8957
|
+
db.prepare("UPDATE session_meta SET prior_boundary_ordinal = 1 WHERE prior_boundary_ordinal IS NULL OR prior_boundary_ordinal < 1").run();
|
|
8958
|
+
db.prepare("UPDATE session_meta SET protected_tail_policy_version = 0 WHERE protected_tail_policy_version IS NULL").run();
|
|
8959
|
+
db.prepare("UPDATE session_meta SET protected_tail_drain_window_started_at = 0 WHERE protected_tail_drain_window_started_at IS NULL").run();
|
|
8960
|
+
db.prepare("UPDATE session_meta SET protected_tail_drain_tokens = 0 WHERE protected_tail_drain_tokens IS NULL").run();
|
|
8961
|
+
db.prepare("UPDATE session_meta SET recovery_no_eligible_head_count = 0 WHERE recovery_no_eligible_head_count IS NULL").run();
|
|
8962
|
+
db.prepare("UPDATE session_meta SET force_emergency_bypass_window_start = 0 WHERE force_emergency_bypass_window_start IS NULL").run();
|
|
8963
|
+
db.prepare("UPDATE session_meta SET force_emergency_bypass_used = 0 WHERE force_emergency_bypass_used IS NULL").run();
|
|
8964
|
+
db.prepare("UPDATE session_meta SET last_usage_context_limit = 0 WHERE last_usage_context_limit IS NULL").run();
|
|
8965
|
+
}
|
|
8919
8966
|
}
|
|
8920
8967
|
];
|
|
8921
8968
|
var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -141521,7 +141568,7 @@ var tokenizer = new src_default(exports_claude);
|
|
|
141521
141568
|
function estimateTokens(text) {
|
|
141522
141569
|
if (!text)
|
|
141523
141570
|
return 0;
|
|
141524
|
-
return tokenizer.
|
|
141571
|
+
return tokenizer.encode(text, "all").length;
|
|
141525
141572
|
}
|
|
141526
141573
|
function normalizeText(text) {
|
|
141527
141574
|
return text.replace(/\s+/g, " ").trim();
|
|
@@ -141631,6 +141678,8 @@ function loadToolDefinitionMeasurements(db) {
|
|
|
141631
141678
|
}
|
|
141632
141679
|
|
|
141633
141680
|
// ../plugin/src/features/magic-context/tool-owner-backfill.ts
|
|
141681
|
+
init_data_path();
|
|
141682
|
+
init_logger();
|
|
141634
141683
|
import { existsSync as existsSync2 } from "node:fs";
|
|
141635
141684
|
import { join as join3 } from "node:path";
|
|
141636
141685
|
var LEASE_DURATION_MS = 5 * 60 * 1000;
|
|
@@ -141746,6 +141795,11 @@ function markSessionCompleted(db, sessionId, now) {
|
|
|
141746
141795
|
SET status = 'completed', completed_at = ?, lease_expires_at = NULL, last_error = NULL
|
|
141747
141796
|
WHERE session_id = ?`).run(now, sessionId);
|
|
141748
141797
|
}
|
|
141798
|
+
function markSessionPendingRetry(db, sessionId) {
|
|
141799
|
+
db.prepare(`UPDATE tool_owner_backfill_state
|
|
141800
|
+
SET status = 'pending', completed_at = NULL, lease_expires_at = NULL, last_error = NULL
|
|
141801
|
+
WHERE session_id = ?`).run(sessionId);
|
|
141802
|
+
}
|
|
141749
141803
|
function markSessionSkipped(db, sessionId, now, reason) {
|
|
141750
141804
|
db.prepare(`INSERT INTO tool_owner_backfill_state(session_id, status, completed_at, last_error)
|
|
141751
141805
|
VALUES (?, 'skipped', ?, ?)
|
|
@@ -141822,12 +141876,18 @@ function applyOwnersForSession(db, sessionId, ownersByCallId) {
|
|
|
141822
141876
|
const updateRowStmt = db.prepare(`UPDATE tags
|
|
141823
141877
|
SET tool_owner_message_id = ?
|
|
141824
141878
|
WHERE id = ? AND tool_owner_message_id IS NULL`);
|
|
141879
|
+
const existingOwnerStmt = db.prepare(`SELECT 1 AS hit FROM tags
|
|
141880
|
+
WHERE session_id = ? AND message_id = ? AND type = 'tool'
|
|
141881
|
+
AND tool_owner_message_id = ?
|
|
141882
|
+
LIMIT 1`);
|
|
141825
141883
|
let rowsUpdated = 0;
|
|
141826
141884
|
db.transaction(() => {
|
|
141827
141885
|
for (const [callId, ownerId] of ownersByCallId) {
|
|
141828
141886
|
const orphan = findOrphanStmt.get(sessionId, callId);
|
|
141829
141887
|
if (!orphan)
|
|
141830
141888
|
continue;
|
|
141889
|
+
if (existingOwnerStmt.get(sessionId, callId, ownerId))
|
|
141890
|
+
continue;
|
|
141831
141891
|
const result = updateRowStmt.run(ownerId, orphan.id);
|
|
141832
141892
|
rowsUpdated += result.changes ?? 0;
|
|
141833
141893
|
}
|
|
@@ -141856,6 +141916,8 @@ function backfillToolOwnersInChunks(db, result) {
|
|
|
141856
141916
|
if (owners.size === 0) {
|
|
141857
141917
|
markSessionSkipped(db, sessionId, Date.now(), "no_oc_matches");
|
|
141858
141918
|
result.sessionsSkippedNoMatches += 1;
|
|
141919
|
+
} else if (rowsLeftNull > 0) {
|
|
141920
|
+
markSessionPendingRetry(db, sessionId);
|
|
141859
141921
|
} else {
|
|
141860
141922
|
markSessionCompleted(db, sessionId, Date.now());
|
|
141861
141923
|
result.sessionsCompleted += 1;
|
|
@@ -141878,7 +141940,7 @@ var databases = new Map;
|
|
|
141878
141940
|
var persistenceByDatabase = new WeakMap;
|
|
141879
141941
|
var persistenceErrorByDatabase = new WeakMap;
|
|
141880
141942
|
var lastSchemaFenceRejection = null;
|
|
141881
|
-
var LATEST_SUPPORTED_VERSION =
|
|
141943
|
+
var LATEST_SUPPORTED_VERSION = 32;
|
|
141882
141944
|
function resolveDatabasePath(dbPathOverride) {
|
|
141883
141945
|
if (dbPathOverride) {
|
|
141884
141946
|
return { dbDir: dirname2(dbPathOverride), dbPath: dbPathOverride };
|
|
@@ -141980,9 +142042,9 @@ function runSqliteOptimize(db) {
|
|
|
141980
142042
|
} catch {}
|
|
141981
142043
|
}
|
|
141982
142044
|
function initializeDatabase(db) {
|
|
142045
|
+
db.exec("PRAGMA busy_timeout=5000");
|
|
141983
142046
|
db.exec("PRAGMA foreign_keys=ON");
|
|
141984
142047
|
db.exec("PRAGMA journal_mode=WAL");
|
|
141985
|
-
db.exec("PRAGMA busy_timeout=5000");
|
|
141986
142048
|
applySqliteTuningPragmas(db);
|
|
141987
142049
|
db.exec(`
|
|
141988
142050
|
CREATE TABLE IF NOT EXISTS tags (
|
|
@@ -141995,6 +142057,9 @@ function initializeDatabase(db) {
|
|
|
141995
142057
|
tag_number INTEGER,
|
|
141996
142058
|
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
141997
142059
|
entry_fingerprint TEXT,
|
|
142060
|
+
token_count INTEGER,
|
|
142061
|
+
input_token_count INTEGER,
|
|
142062
|
+
reasoning_token_count INTEGER,
|
|
141998
142063
|
UNIQUE(session_id, tag_number)
|
|
141999
142064
|
);
|
|
142000
142065
|
|
|
@@ -142284,6 +142349,11 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142284
142349
|
counter INTEGER DEFAULT 0,
|
|
142285
142350
|
last_nudge_tokens INTEGER DEFAULT 0,
|
|
142286
142351
|
last_nudge_band TEXT DEFAULT '',
|
|
142352
|
+
last_nudge_undropped INTEGER DEFAULT 0,
|
|
142353
|
+
last_nudge_level TEXT DEFAULT '',
|
|
142354
|
+
channel2_nudge_state TEXT DEFAULT '',
|
|
142355
|
+
channel2_nudge_claimed_at INTEGER DEFAULT 0,
|
|
142356
|
+
last_emergency_input_sample INTEGER DEFAULT 0,
|
|
142287
142357
|
last_transform_error TEXT DEFAULT '',
|
|
142288
142358
|
nudge_anchor_message_id TEXT DEFAULT '',
|
|
142289
142359
|
nudge_anchor_text TEXT DEFAULT '',
|
|
@@ -142340,6 +142410,14 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142340
142410
|
cached_m0_project_docs_hash TEXT,
|
|
142341
142411
|
cached_m1_bytes BLOB,
|
|
142342
142412
|
last_observed_model_key TEXT,
|
|
142413
|
+
last_usage_context_limit INTEGER NOT NULL DEFAULT 0,
|
|
142414
|
+
prior_boundary_ordinal INTEGER NOT NULL DEFAULT 1,
|
|
142415
|
+
protected_tail_policy_version INTEGER NOT NULL DEFAULT 0,
|
|
142416
|
+
protected_tail_drain_window_started_at INTEGER NOT NULL DEFAULT 0,
|
|
142417
|
+
protected_tail_drain_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142418
|
+
recovery_no_eligible_head_count INTEGER NOT NULL DEFAULT 0,
|
|
142419
|
+
force_emergency_bypass_window_start INTEGER NOT NULL DEFAULT 0,
|
|
142420
|
+
force_emergency_bypass_used INTEGER NOT NULL DEFAULT 0,
|
|
142343
142421
|
cached_m0_materialized_at INTEGER,
|
|
142344
142422
|
cached_m0_session_facts_version INTEGER,
|
|
142345
142423
|
cached_m0_upgrade_state TEXT,
|
|
@@ -142450,6 +142528,11 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142450
142528
|
CREATE INDEX IF NOT EXISTS idx_message_history_index_updated_at ON message_history_index(updated_at);
|
|
142451
142529
|
`);
|
|
142452
142530
|
ensureColumn(db, "session_meta", "last_nudge_band", "TEXT DEFAULT ''");
|
|
142531
|
+
ensureColumn(db, "session_meta", "last_nudge_undropped", "INTEGER DEFAULT 0");
|
|
142532
|
+
ensureColumn(db, "session_meta", "last_nudge_level", "TEXT DEFAULT ''");
|
|
142533
|
+
ensureColumn(db, "session_meta", "channel2_nudge_state", "TEXT DEFAULT ''");
|
|
142534
|
+
ensureColumn(db, "session_meta", "channel2_nudge_claimed_at", "INTEGER DEFAULT 0");
|
|
142535
|
+
ensureColumn(db, "session_meta", "last_emergency_input_sample", "INTEGER DEFAULT 0");
|
|
142453
142536
|
ensureColumn(db, "session_meta", "last_transform_error", "TEXT DEFAULT ''");
|
|
142454
142537
|
ensureColumn(db, "session_meta", "nudge_anchor_message_id", "TEXT DEFAULT ''");
|
|
142455
142538
|
ensureColumn(db, "session_meta", "nudge_anchor_text", "TEXT DEFAULT ''");
|
|
@@ -142476,6 +142559,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142476
142559
|
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
142477
142560
|
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
142478
142561
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
142562
|
+
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
142479
142563
|
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
142480
142564
|
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
142481
142565
|
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
@@ -142494,6 +142578,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142494
142578
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_tags_pi_adopt
|
|
142495
142579
|
ON tags(session_id, entry_fingerprint)
|
|
142496
142580
|
WHERE type='message' AND entry_fingerprint IS NOT NULL`);
|
|
142581
|
+
ensureColumn(db, "tags", "token_count", "INTEGER");
|
|
142582
|
+
ensureColumn(db, "tags", "input_token_count", "INTEGER");
|
|
142583
|
+
ensureColumn(db, "tags", "reasoning_token_count", "INTEGER");
|
|
142497
142584
|
ensureColumn(db, "session_meta", "system_prompt_tokens", "INTEGER DEFAULT 0");
|
|
142498
142585
|
ensureColumn(db, "session_meta", "compaction_marker_state", "TEXT DEFAULT ''");
|
|
142499
142586
|
ensureColumn(db, "session_meta", "key_files", "TEXT DEFAULT ''");
|
|
@@ -142534,6 +142621,14 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142534
142621
|
ensureColumn(db, "session_meta", "cached_m0_project_docs_hash", "TEXT");
|
|
142535
142622
|
ensureColumn(db, "session_meta", "cached_m1_bytes", "BLOB");
|
|
142536
142623
|
ensureColumn(db, "session_meta", "last_observed_model_key", "TEXT");
|
|
142624
|
+
ensureColumn(db, "session_meta", "last_usage_context_limit", "INTEGER NOT NULL DEFAULT 0");
|
|
142625
|
+
ensureColumn(db, "session_meta", "prior_boundary_ordinal", "INTEGER NOT NULL DEFAULT 1");
|
|
142626
|
+
ensureColumn(db, "session_meta", "protected_tail_policy_version", "INTEGER NOT NULL DEFAULT 0");
|
|
142627
|
+
ensureColumn(db, "session_meta", "protected_tail_drain_window_started_at", "INTEGER NOT NULL DEFAULT 0");
|
|
142628
|
+
ensureColumn(db, "session_meta", "protected_tail_drain_tokens", "INTEGER NOT NULL DEFAULT 0");
|
|
142629
|
+
ensureColumn(db, "session_meta", "recovery_no_eligible_head_count", "INTEGER NOT NULL DEFAULT 0");
|
|
142630
|
+
ensureColumn(db, "session_meta", "force_emergency_bypass_window_start", "INTEGER NOT NULL DEFAULT 0");
|
|
142631
|
+
ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
|
|
142537
142632
|
ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
|
|
142538
142633
|
ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
|
|
142539
142634
|
ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
|
|
@@ -142603,6 +142698,13 @@ function healAllNullColumns(db) {
|
|
|
142603
142698
|
healNullIntegerColumns(db);
|
|
142604
142699
|
healMissingMemoryBlockIds(db);
|
|
142605
142700
|
}
|
|
142701
|
+
var CHANNEL2_CLAIM_TTL_MS = 120000;
|
|
142702
|
+
function healWedgedChannel2Claims(db) {
|
|
142703
|
+
try {
|
|
142704
|
+
const staleBefore = Date.now() - CHANNEL2_CLAIM_TTL_MS;
|
|
142705
|
+
db.prepare("UPDATE session_meta SET channel2_nudge_state = 'pending', channel2_nudge_claimed_at = 0 WHERE channel2_nudge_state = 'claimed' AND (channel2_nudge_claimed_at IS NULL OR channel2_nudge_claimed_at = 0 OR channel2_nudge_claimed_at <= ?)").run(staleBefore);
|
|
142706
|
+
} catch {}
|
|
142707
|
+
}
|
|
142606
142708
|
function healMissingMemoryBlockIds(db) {
|
|
142607
142709
|
try {
|
|
142608
142710
|
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE memory_block_cache != '' AND (memory_block_ids IS NULL OR memory_block_ids = '') AND memory_block_count > 0").run();
|
|
@@ -142612,6 +142714,7 @@ function healNullTextColumns(db) {
|
|
|
142612
142714
|
const columns = [
|
|
142613
142715
|
["cache_ttl", ""],
|
|
142614
142716
|
["last_nudge_band", ""],
|
|
142717
|
+
["last_nudge_level", ""],
|
|
142615
142718
|
["last_transform_error", ""],
|
|
142616
142719
|
["nudge_anchor_message_id", ""],
|
|
142617
142720
|
["nudge_anchor_text", ""],
|
|
@@ -142626,6 +142729,7 @@ function healNullTextColumns(db) {
|
|
|
142626
142729
|
["todo_synthetic_state_json", ""],
|
|
142627
142730
|
["system_prompt_hash", ""],
|
|
142628
142731
|
["stripped_placeholder_ids", ""],
|
|
142732
|
+
["stale_reduce_stripped_ids", ""],
|
|
142629
142733
|
["memory_block_cache", ""],
|
|
142630
142734
|
["memory_block_ids", ""],
|
|
142631
142735
|
["compaction_marker_state", ""],
|
|
@@ -142651,7 +142755,17 @@ function healNullIntegerColumns(db) {
|
|
|
142651
142755
|
["observed_safe_input_tokens", 0],
|
|
142652
142756
|
["cache_alert_sent", 0],
|
|
142653
142757
|
["new_work_tokens", 0],
|
|
142654
|
-
["total_input_tokens", 0]
|
|
142758
|
+
["total_input_tokens", 0],
|
|
142759
|
+
["last_emergency_input_sample", 0],
|
|
142760
|
+
["channel2_nudge_claimed_at", 0],
|
|
142761
|
+
["last_usage_context_limit", 0],
|
|
142762
|
+
["prior_boundary_ordinal", 1],
|
|
142763
|
+
["protected_tail_policy_version", 0],
|
|
142764
|
+
["protected_tail_drain_window_started_at", 0],
|
|
142765
|
+
["protected_tail_drain_tokens", 0],
|
|
142766
|
+
["recovery_no_eligible_head_count", 0],
|
|
142767
|
+
["force_emergency_bypass_window_start", 0],
|
|
142768
|
+
["force_emergency_bypass_used", 0]
|
|
142655
142769
|
];
|
|
142656
142770
|
for (const [column, fallback] of columns) {
|
|
142657
142771
|
try {
|
|
@@ -142690,6 +142804,7 @@ function openDatabase(dbPathOrOptions) {
|
|
|
142690
142804
|
if (!persistenceByDatabase.has(existing)) {
|
|
142691
142805
|
persistenceByDatabase.set(existing, true);
|
|
142692
142806
|
}
|
|
142807
|
+
healWedgedChannel2Claims(existing);
|
|
142693
142808
|
return existing;
|
|
142694
142809
|
}
|
|
142695
142810
|
try {
|
|
@@ -142715,6 +142830,7 @@ function openDatabase(dbPathOrOptions) {
|
|
|
142715
142830
|
log(`[magic-context] key-files orphan GC failed: ${getErrorMessage(error)}`);
|
|
142716
142831
|
}
|
|
142717
142832
|
}
|
|
142833
|
+
healWedgedChannel2Claims(db);
|
|
142718
142834
|
if (!explicitDbPath) {
|
|
142719
142835
|
try {
|
|
142720
142836
|
runToolOwnerBackfill(db);
|
|
@@ -142735,6 +142851,34 @@ function openDatabase(dbPathOrOptions) {
|
|
|
142735
142851
|
}
|
|
142736
142852
|
}
|
|
142737
142853
|
|
|
142854
|
+
// src/subagent-entry.ts
|
|
142855
|
+
init_logger();
|
|
142856
|
+
|
|
142857
|
+
// ../plugin/src/config/prune-config-leaf.ts
|
|
142858
|
+
function isPlainObject(value) {
|
|
142859
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
142860
|
+
}
|
|
142861
|
+
function pruneNestedConfigLeaf(block, relativePath) {
|
|
142862
|
+
if (relativePath.length === 0)
|
|
142863
|
+
return null;
|
|
142864
|
+
const result = { ...block };
|
|
142865
|
+
let cursor = result;
|
|
142866
|
+
for (let i = 0;i < relativePath.length - 1; i++) {
|
|
142867
|
+
const seg = String(relativePath[i]);
|
|
142868
|
+
const child = cursor[seg];
|
|
142869
|
+
if (!isPlainObject(child))
|
|
142870
|
+
return null;
|
|
142871
|
+
const clonedChild = { ...child };
|
|
142872
|
+
cursor[seg] = clonedChild;
|
|
142873
|
+
cursor = clonedChild;
|
|
142874
|
+
}
|
|
142875
|
+
const leaf = String(relativePath[relativePath.length - 1]);
|
|
142876
|
+
if (!(leaf in cursor))
|
|
142877
|
+
return null;
|
|
142878
|
+
delete cursor[leaf];
|
|
142879
|
+
return { block: result, removed: relativePath.map(String).join(".") };
|
|
142880
|
+
}
|
|
142881
|
+
|
|
142738
142882
|
// src/config/index.ts
|
|
142739
142883
|
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
142740
142884
|
import { homedir as homedir3 } from "node:os";
|
|
@@ -142880,6 +143024,74 @@ function migrateLegacyExperimental(rawConfig, warnings) {
|
|
|
142880
143024
|
return patched;
|
|
142881
143025
|
}
|
|
142882
143026
|
|
|
143027
|
+
// ../plugin/src/config/project-security.ts
|
|
143028
|
+
var HIDDEN_AGENT_KEYS = ["historian", "dreamer", "sidekick"];
|
|
143029
|
+
var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools", "system_prompt"];
|
|
143030
|
+
function isPlainObject2(value) {
|
|
143031
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
143032
|
+
}
|
|
143033
|
+
function stripUnsafeProjectConfigFields(projectRaw) {
|
|
143034
|
+
const warnings = [];
|
|
143035
|
+
if ("auto_update" in projectRaw) {
|
|
143036
|
+
delete projectRaw.auto_update;
|
|
143037
|
+
warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
|
|
143038
|
+
}
|
|
143039
|
+
if ("sqlite" in projectRaw) {
|
|
143040
|
+
delete projectRaw.sqlite;
|
|
143041
|
+
warnings.push("Ignoring sqlite.* from project config (security: SQLite cache/mmap PRAGMAs apply to the " + "process-global shared database handle; only user-level config may set them).");
|
|
143042
|
+
}
|
|
143043
|
+
for (const agentKey of HIDDEN_AGENT_KEYS) {
|
|
143044
|
+
const block = projectRaw[agentKey];
|
|
143045
|
+
if (!isPlainObject2(block))
|
|
143046
|
+
continue;
|
|
143047
|
+
const removed = [];
|
|
143048
|
+
for (const field of AGENT_ESCALATION_FIELDS) {
|
|
143049
|
+
if (field in block) {
|
|
143050
|
+
delete block[field];
|
|
143051
|
+
removed.push(field);
|
|
143052
|
+
}
|
|
143053
|
+
}
|
|
143054
|
+
if (removed.length > 0) {
|
|
143055
|
+
warnings.push(`Ignoring ${agentKey}.${removed.join("/")} from project config ` + "(security: a repository cannot reprogram or re-permission hidden agents).");
|
|
143056
|
+
}
|
|
143057
|
+
}
|
|
143058
|
+
return warnings;
|
|
143059
|
+
}
|
|
143060
|
+
function normalizeEndpoint(value) {
|
|
143061
|
+
if (typeof value !== "string")
|
|
143062
|
+
return;
|
|
143063
|
+
const trimmed = value.trim().replace(/\/+$/, "");
|
|
143064
|
+
return trimmed.length > 0 ? trimmed.toLowerCase() : undefined;
|
|
143065
|
+
}
|
|
143066
|
+
function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
|
|
143067
|
+
const projectEmbedding = projectRaw.embedding;
|
|
143068
|
+
if (!isPlainObject2(projectEmbedding))
|
|
143069
|
+
return [];
|
|
143070
|
+
const redirectsEndpoint = "endpoint" in projectEmbedding;
|
|
143071
|
+
if (!redirectsEndpoint)
|
|
143072
|
+
return [];
|
|
143073
|
+
const userEmbedding = userRaw?.embedding;
|
|
143074
|
+
if (isPlainObject2(userEmbedding)) {
|
|
143075
|
+
const projectEndpoint = normalizeEndpoint(projectEmbedding.endpoint);
|
|
143076
|
+
const userEndpoint = normalizeEndpoint(userEmbedding.endpoint);
|
|
143077
|
+
if (projectEndpoint !== undefined && projectEndpoint === userEndpoint) {
|
|
143078
|
+
return [];
|
|
143079
|
+
}
|
|
143080
|
+
}
|
|
143081
|
+
const providesOwnKey = typeof projectEmbedding.api_key === "string" && projectEmbedding.api_key.length > 0;
|
|
143082
|
+
if (providesOwnKey)
|
|
143083
|
+
return [];
|
|
143084
|
+
const mergedEmbedding = mergedRaw.embedding;
|
|
143085
|
+
if (!isPlainObject2(mergedEmbedding))
|
|
143086
|
+
return [];
|
|
143087
|
+
if (!("api_key" in mergedEmbedding))
|
|
143088
|
+
return [];
|
|
143089
|
+
delete mergedEmbedding.api_key;
|
|
143090
|
+
return [
|
|
143091
|
+
"Dropped inherited user embedding api_key because project config redirected " + "embedding.endpoint without supplying its own key (security: prevents key " + "exfiltration to a repository-chosen endpoint)."
|
|
143092
|
+
];
|
|
143093
|
+
}
|
|
143094
|
+
|
|
142883
143095
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
142884
143096
|
var exports_external = {};
|
|
142885
143097
|
__export(exports_external, {
|
|
@@ -143511,7 +143723,7 @@ __export(exports_util, {
|
|
|
143511
143723
|
jsonStringifyReplacer: () => jsonStringifyReplacer,
|
|
143512
143724
|
joinValues: () => joinValues,
|
|
143513
143725
|
issue: () => issue,
|
|
143514
|
-
isPlainObject: () =>
|
|
143726
|
+
isPlainObject: () => isPlainObject3,
|
|
143515
143727
|
isObject: () => isObject,
|
|
143516
143728
|
hexToUint8Array: () => hexToUint8Array,
|
|
143517
143729
|
getSizableOrigin: () => getSizableOrigin,
|
|
@@ -143693,7 +143905,7 @@ var allowsEval = /* @__PURE__ */ cached(() => {
|
|
|
143693
143905
|
return false;
|
|
143694
143906
|
}
|
|
143695
143907
|
});
|
|
143696
|
-
function
|
|
143908
|
+
function isPlainObject3(o) {
|
|
143697
143909
|
if (isObject(o) === false)
|
|
143698
143910
|
return false;
|
|
143699
143911
|
const ctor = o.constructor;
|
|
@@ -143710,7 +143922,7 @@ function isPlainObject(o) {
|
|
|
143710
143922
|
return true;
|
|
143711
143923
|
}
|
|
143712
143924
|
function shallowClone(o) {
|
|
143713
|
-
if (
|
|
143925
|
+
if (isPlainObject3(o))
|
|
143714
143926
|
return { ...o };
|
|
143715
143927
|
if (Array.isArray(o))
|
|
143716
143928
|
return [...o];
|
|
@@ -143914,7 +144126,7 @@ function omit(schema, mask) {
|
|
|
143914
144126
|
return clone(schema, def);
|
|
143915
144127
|
}
|
|
143916
144128
|
function extend(schema, shape) {
|
|
143917
|
-
if (!
|
|
144129
|
+
if (!isPlainObject3(shape)) {
|
|
143918
144130
|
throw new Error("Invalid input to extend: expected a plain object");
|
|
143919
144131
|
}
|
|
143920
144132
|
const checks = schema._zod.def.checks;
|
|
@@ -143937,7 +144149,7 @@ function extend(schema, shape) {
|
|
|
143937
144149
|
return clone(schema, def);
|
|
143938
144150
|
}
|
|
143939
144151
|
function safeExtend(schema, shape) {
|
|
143940
|
-
if (!
|
|
144152
|
+
if (!isPlainObject3(shape)) {
|
|
143941
144153
|
throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
143942
144154
|
}
|
|
143943
144155
|
const def = mergeDefs(schema._zod.def, {
|
|
@@ -146280,7 +146492,7 @@ function mergeValues(a, b) {
|
|
|
146280
146492
|
if (a instanceof Date && b instanceof Date && +a === +b) {
|
|
146281
146493
|
return { valid: true, data: a };
|
|
146282
146494
|
}
|
|
146283
|
-
if (
|
|
146495
|
+
if (isPlainObject3(a) && isPlainObject3(b)) {
|
|
146284
146496
|
const bKeys = Object.keys(b);
|
|
146285
146497
|
const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
146286
146498
|
const newObj = { ...a, ...b };
|
|
@@ -146466,7 +146678,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
146466
146678
|
$ZodType.init(inst, def);
|
|
146467
146679
|
inst._zod.parse = (payload, ctx) => {
|
|
146468
146680
|
const input = payload.value;
|
|
146469
|
-
if (!
|
|
146681
|
+
if (!isPlainObject3(input)) {
|
|
146470
146682
|
payload.issues.push({
|
|
146471
146683
|
expected: "record",
|
|
146472
146684
|
code: "invalid_type",
|
|
@@ -157186,7 +157398,6 @@ var AgentOverrideConfigSchema = exports_external.object({
|
|
|
157186
157398
|
});
|
|
157187
157399
|
|
|
157188
157400
|
// ../plugin/src/config/schema/magic-context.ts
|
|
157189
|
-
var DEFAULT_NUDGE_INTERVAL_TOKENS = 1e4;
|
|
157190
157401
|
var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65;
|
|
157191
157402
|
var EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 80% for cache safety: a single large agent step can overflow the context window before Magic Context can compact between turns, forcing OpenCode's native compaction (hard to recover from). 80% also leaves headroom below the 85%/95% emergency bands. Use a value between 20 and 80.";
|
|
157192
157403
|
var DEFAULT_HISTORIAN_TIMEOUT_MS = 300000;
|
|
@@ -157284,7 +157495,6 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
157284
157495
|
historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
|
|
157285
157496
|
dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
|
|
157286
157497
|
cache_ttl: exports_external.union([exports_external.string(), exports_external.object({ default: exports_external.string() }).catchall(exports_external.string())]).default("5m").describe('Cache TTL: string (e.g. "5m") or per-model object ({ default: "5m", "model-id": "10m" })'),
|
|
157287
|
-
nudge_interval_tokens: exports_external.number().min(1000).default(DEFAULT_NUDGE_INTERVAL_TOKENS).describe("Minimum token growth between low-priority rolling nudges (default: DEFAULT_NUDGE_INTERVAL_TOKENS)"),
|
|
157288
157498
|
execute_threshold_percentage: exports_external.union([
|
|
157289
157499
|
exports_external.number().min(20).max(80, EXECUTE_THRESHOLD_CAP_MESSAGE),
|
|
157290
157500
|
exports_external.object({ default: exports_external.number().min(20).max(80, EXECUTE_THRESHOLD_CAP_MESSAGE) }).catchall(exports_external.number().min(20).max(80, EXECUTE_THRESHOLD_CAP_MESSAGE))
|
|
@@ -157293,10 +157503,7 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
157293
157503
|
default: exports_external.number().min(5000).max(2000000).optional()
|
|
157294
157504
|
}).catchall(exports_external.number().min(5000).max(2000000)).optional().describe("Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above 80% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000."),
|
|
157295
157505
|
protected_tags: exports_external.number().min(1).max(100).optional().describe("Number of recent tags to protect from dropping (min: 1, max: 100, default: 20)"),
|
|
157296
|
-
auto_drop_tool_age: exports_external.number().min(10).default(100).describe("Auto-drop tool outputs older than N tags during queue execution (default: 100)"),
|
|
157297
|
-
drop_tool_structure: exports_external.boolean().default(true).describe("When true, dropped tool parts are fully removed instead of truncated in place (default: true)"),
|
|
157298
157506
|
clear_reasoning_age: exports_external.number().min(10).default(50).describe("Clear reasoning/thinking blocks older than N tags (default: 50)"),
|
|
157299
|
-
iteration_nudge_threshold: exports_external.number().min(5).default(15).describe("Number of consecutive assistant messages without user input to trigger iteration nudge (default: 15)"),
|
|
157300
157507
|
history_budget_percentage: exports_external.number().min(0.05).max(0.5).default(DEFAULT_HISTORY_BUDGET_PERCENTAGE).describe("Fraction of usable context (context_limit × execute_threshold) reserved for the session history block (default: 0.15)"),
|
|
157301
157508
|
historian_timeout_ms: exports_external.number().min(60000).default(DEFAULT_HISTORIAN_TIMEOUT_MS).describe("Timeout for each historian prompt call in milliseconds (default: 300000)"),
|
|
157302
157509
|
commit_cluster_trigger: exports_external.object({
|
|
@@ -157423,6 +157630,21 @@ function stripJsonComments(content) {
|
|
|
157423
157630
|
// ../plugin/src/config/variable.ts
|
|
157424
157631
|
var ENV_PATTERN = /\{env:([^}]+)\}/g;
|
|
157425
157632
|
var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
157633
|
+
function sensitiveFilePathReason(resolvedPath) {
|
|
157634
|
+
const home = homedir2();
|
|
157635
|
+
const sensitiveDirs = [
|
|
157636
|
+
{ dir: resolve2(home, ".ssh"), label: "SSH keys" },
|
|
157637
|
+
{ dir: resolve2(home, ".aws"), label: "AWS credentials" },
|
|
157638
|
+
{ dir: resolve2(home, ".gnupg"), label: "GnuPG keyring" },
|
|
157639
|
+
{ dir: resolve2(home, ".config", "gh"), label: "GitHub CLI auth" }
|
|
157640
|
+
];
|
|
157641
|
+
for (const { dir, label } of sensitiveDirs) {
|
|
157642
|
+
if (resolvedPath === dir || resolvedPath.startsWith(`${dir}/`)) {
|
|
157643
|
+
return label;
|
|
157644
|
+
}
|
|
157645
|
+
}
|
|
157646
|
+
return null;
|
|
157647
|
+
}
|
|
157426
157648
|
function substituteConfigVariables(input) {
|
|
157427
157649
|
const warnings = [];
|
|
157428
157650
|
let text = input.text;
|
|
@@ -157476,6 +157698,10 @@ function substituteConfigVariables(input) {
|
|
|
157476
157698
|
} else if (!isAbsolute(filePath)) {
|
|
157477
157699
|
filePath = resolve2(configDir, filePath);
|
|
157478
157700
|
}
|
|
157701
|
+
const sensitiveReason = sensitiveFilePathReason(filePath);
|
|
157702
|
+
if (sensitiveReason) {
|
|
157703
|
+
warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
|
|
157704
|
+
}
|
|
157479
157705
|
if (!existsSync4(filePath)) {
|
|
157480
157706
|
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
157481
157707
|
continue;
|
|
@@ -157514,7 +157740,8 @@ function loadConfigFile(path3, scope) {
|
|
|
157514
157740
|
const rawText = readFileSync3(path3, "utf-8");
|
|
157515
157741
|
const substituted = substituteConfigVariables({
|
|
157516
157742
|
text: rawText,
|
|
157517
|
-
configPath: path3
|
|
157743
|
+
configPath: path3,
|
|
157744
|
+
isProjectConfig: scope === "project"
|
|
157518
157745
|
});
|
|
157519
157746
|
return {
|
|
157520
157747
|
path: path3,
|
|
@@ -157556,14 +157783,14 @@ function redactConfigValue(value) {
|
|
|
157556
157783
|
}
|
|
157557
157784
|
return typeof value;
|
|
157558
157785
|
}
|
|
157559
|
-
function
|
|
157786
|
+
function isPlainObject4(value) {
|
|
157560
157787
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
157561
157788
|
}
|
|
157562
157789
|
function mergeRawConfigs(base, override) {
|
|
157563
157790
|
const merged = { ...base };
|
|
157564
157791
|
for (const [key, overrideValue] of Object.entries(override)) {
|
|
157565
157792
|
const baseValue = merged[key];
|
|
157566
|
-
merged[key] =
|
|
157793
|
+
merged[key] = isPlainObject4(baseValue) && isPlainObject4(overrideValue) ? mergeRawConfigs(baseValue, overrideValue) : overrideValue;
|
|
157567
157794
|
}
|
|
157568
157795
|
return merged;
|
|
157569
157796
|
}
|
|
@@ -157577,10 +157804,15 @@ function parsePiConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
|
157577
157804
|
}
|
|
157578
157805
|
const defaults = MagicContextConfigSchema.parse({});
|
|
157579
157806
|
const errorPaths = new Set;
|
|
157807
|
+
const issuePathsByKey = new Map;
|
|
157580
157808
|
for (const issue2 of parsed.error.issues) {
|
|
157581
157809
|
const topKey = issue2.path[0];
|
|
157582
157810
|
if (topKey !== undefined) {
|
|
157583
|
-
|
|
157811
|
+
const key = String(topKey);
|
|
157812
|
+
errorPaths.add(key);
|
|
157813
|
+
const paths = issuePathsByKey.get(key) ?? [];
|
|
157814
|
+
paths.push([...issue2.path]);
|
|
157815
|
+
issuePathsByKey.set(key, paths);
|
|
157584
157816
|
}
|
|
157585
157817
|
}
|
|
157586
157818
|
const patched = { ...migrated };
|
|
@@ -157588,11 +157820,32 @@ function parsePiConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
|
157588
157820
|
for (const key of errorPaths) {
|
|
157589
157821
|
recoveredTopLevelKeys.push(key);
|
|
157590
157822
|
const isAgentConfig = key === "historian" || key === "dreamer" || key === "sidekick";
|
|
157591
|
-
delete patched[key];
|
|
157592
157823
|
if (isAgentConfig) {
|
|
157824
|
+
delete patched[key];
|
|
157593
157825
|
warnings.push(`"${key}": invalid agent configuration, ignoring. Check your magic-context.jsonc.`);
|
|
157594
157826
|
continue;
|
|
157595
157827
|
}
|
|
157828
|
+
const issuePaths = issuePathsByKey.get(key) ?? [];
|
|
157829
|
+
const rawValue = migrated[key];
|
|
157830
|
+
const allNested = issuePaths.length > 0 && issuePaths.every((p) => p.length >= 2) && typeof rawValue === "object" && rawValue !== null && !Array.isArray(rawValue);
|
|
157831
|
+
if (allNested) {
|
|
157832
|
+
let prunedBlock = {
|
|
157833
|
+
...rawValue
|
|
157834
|
+
};
|
|
157835
|
+
const prunedLeaves = [];
|
|
157836
|
+
for (const p of issuePaths) {
|
|
157837
|
+
const relative = p.slice(1);
|
|
157838
|
+
const result = pruneNestedConfigLeaf(prunedBlock, relative);
|
|
157839
|
+
if (result) {
|
|
157840
|
+
prunedBlock = result.block;
|
|
157841
|
+
prunedLeaves.push(result.removed);
|
|
157842
|
+
}
|
|
157843
|
+
}
|
|
157844
|
+
patched[key] = prunedBlock;
|
|
157845
|
+
warnings.push(`"${key}": invalid nested field(s) ${prunedLeaves.map((l) => `"${l}"`).join(", ")}, using defaults for those.`);
|
|
157846
|
+
continue;
|
|
157847
|
+
}
|
|
157848
|
+
delete patched[key];
|
|
157596
157849
|
const defaultValue = defaults[key];
|
|
157597
157850
|
warnings.push(`"${key}": invalid value (${redactConfigValue(rawConfig[key])}), using default ${JSON.stringify(defaultValue)}.`);
|
|
157598
157851
|
}
|
|
@@ -157625,10 +157878,22 @@ function loadPiConfig(opts = {}) {
|
|
|
157625
157878
|
return 0;
|
|
157626
157879
|
return a.scope === "user" ? -1 : 1;
|
|
157627
157880
|
});
|
|
157881
|
+
const userRaw = mergeFiles.find((f) => f.scope === "user")?.config;
|
|
157628
157882
|
for (const loaded of mergeFiles) {
|
|
157629
157883
|
const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
|
|
157630
157884
|
warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
|
|
157631
|
-
|
|
157885
|
+
if (loaded.scope === "project") {
|
|
157886
|
+
const projectRaw = { ...loaded.config };
|
|
157887
|
+
for (const warning of stripUnsafeProjectConfigFields(projectRaw)) {
|
|
157888
|
+
warnings.push(`${prefix} ${warning}`);
|
|
157889
|
+
}
|
|
157890
|
+
rawConfig = mergeRawConfigs(rawConfig, projectRaw);
|
|
157891
|
+
for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, rawConfig, userRaw)) {
|
|
157892
|
+
warnings.push(`${prefix} ${warning}`);
|
|
157893
|
+
}
|
|
157894
|
+
} else {
|
|
157895
|
+
rawConfig = mergeRawConfigs(rawConfig, loaded.config);
|
|
157896
|
+
}
|
|
157632
157897
|
}
|
|
157633
157898
|
const parsed = parsePiConfig(rawConfig);
|
|
157634
157899
|
warnings.push(...parsed.warnings.map((warning) => `[merged config] ${warning}`));
|
|
@@ -157703,10 +157968,22 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
157703
157968
|
return 0;
|
|
157704
157969
|
return a.scope === "user" ? -1 : 1;
|
|
157705
157970
|
});
|
|
157971
|
+
const userRaw = mergeFiles.find((f) => f.scope === "user")?.config;
|
|
157706
157972
|
for (const loaded of mergeFiles) {
|
|
157707
157973
|
const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
|
|
157708
157974
|
warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
|
|
157709
|
-
|
|
157975
|
+
if (loaded.scope === "project") {
|
|
157976
|
+
const projectRaw = { ...loaded.config };
|
|
157977
|
+
for (const warning of stripUnsafeProjectConfigFields(projectRaw)) {
|
|
157978
|
+
warnings.push(`${prefix} ${warning}`);
|
|
157979
|
+
}
|
|
157980
|
+
rawConfig = mergeRawConfigs(rawConfig, projectRaw);
|
|
157981
|
+
for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, rawConfig, userRaw)) {
|
|
157982
|
+
warnings.push(`${prefix} ${warning}`);
|
|
157983
|
+
}
|
|
157984
|
+
} else {
|
|
157985
|
+
rawConfig = mergeRawConfigs(rawConfig, loaded.config);
|
|
157986
|
+
}
|
|
157710
157987
|
}
|
|
157711
157988
|
const recoveredTopLevelKeys = [];
|
|
157712
157989
|
const parsed = parsePiConfig(rawConfig, recoveredTopLevelKeys);
|
|
@@ -157733,6 +158010,9 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
157733
158010
|
};
|
|
157734
158011
|
}
|
|
157735
158012
|
|
|
158013
|
+
// ../plugin/src/features/magic-context/memory/embedding.ts
|
|
158014
|
+
init_logger();
|
|
158015
|
+
|
|
157736
158016
|
// ../plugin/src/features/magic-context/memory/cosine-similarity.ts
|
|
157737
158017
|
function cosineSimilarity(a, b) {
|
|
157738
158018
|
if (a.length !== b.length) {
|
|
@@ -157761,7 +158041,7 @@ function computeNormalizedHash(content) {
|
|
|
157761
158041
|
}
|
|
157762
158042
|
|
|
157763
158043
|
// ../plugin/src/features/magic-context/memory/embedding-identity.ts
|
|
157764
|
-
function
|
|
158044
|
+
function normalizeEndpoint2(endpoint) {
|
|
157765
158045
|
return endpoint?.trim().replace(/\/+$/, "") ?? "";
|
|
157766
158046
|
}
|
|
157767
158047
|
function getEmbeddingProviderIdentity(config2) {
|
|
@@ -157771,7 +158051,7 @@ function getEmbeddingProviderIdentity(config2) {
|
|
|
157771
158051
|
const identityInput = config2.provider === "openai-compatible" ? {
|
|
157772
158052
|
provider: "openai-compatible",
|
|
157773
158053
|
model: config2.model.trim(),
|
|
157774
|
-
endpoint:
|
|
158054
|
+
endpoint: normalizeEndpoint2(config2.endpoint),
|
|
157775
158055
|
apiKeyPresent: Boolean(config2.api_key?.trim()),
|
|
157776
158056
|
inputType: config2.input_type?.trim() || ""
|
|
157777
158057
|
} : {
|
|
@@ -157788,6 +158068,8 @@ import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
|
157788
158068
|
import { open, stat, unlink, writeFile } from "node:fs/promises";
|
|
157789
158069
|
import { dirname as dirname4, join as join6 } from "node:path";
|
|
157790
158070
|
import { pathToFileURL } from "node:url";
|
|
158071
|
+
init_data_path();
|
|
158072
|
+
init_logger();
|
|
157791
158073
|
var LOCK_POLL_MS = 150;
|
|
157792
158074
|
var STALE_LOCK_MS = 3 * 60000;
|
|
157793
158075
|
var MAX_LOCK_WAIT_MS = 5 * 60000;
|
|
@@ -158123,7 +158405,63 @@ class LocalEmbeddingProvider {
|
|
|
158123
158405
|
}
|
|
158124
158406
|
|
|
158125
158407
|
// ../plugin/src/features/magic-context/memory/embedding-openai.ts
|
|
158126
|
-
|
|
158408
|
+
init_logger();
|
|
158409
|
+
|
|
158410
|
+
// ../plugin/src/features/magic-context/memory/embedding-ssrf.ts
|
|
158411
|
+
var METADATA_HOSTNAMES = new Set(["metadata.google.internal", "metadata.goog"]);
|
|
158412
|
+
var IPV6_METADATA_HOSTS = new Set(["fd00:ec2::254"]);
|
|
158413
|
+
function isLinkLocalIpv4(host) {
|
|
158414
|
+
return /^169\.254\.\d{1,3}\.\d{1,3}$/.test(host);
|
|
158415
|
+
}
|
|
158416
|
+
function ipv4FromMappedIpv6(host) {
|
|
158417
|
+
const m = /^::ffff:(.+)$/.exec(host);
|
|
158418
|
+
if (!m)
|
|
158419
|
+
return null;
|
|
158420
|
+
const tail = m[1];
|
|
158421
|
+
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(tail))
|
|
158422
|
+
return tail;
|
|
158423
|
+
const hex3 = /^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(tail);
|
|
158424
|
+
if (hex3) {
|
|
158425
|
+
const hi = Number.parseInt(hex3[1], 16);
|
|
158426
|
+
const lo = Number.parseInt(hex3[2], 16);
|
|
158427
|
+
if (Number.isNaN(hi) || Number.isNaN(lo))
|
|
158428
|
+
return null;
|
|
158429
|
+
return `${hi >> 8 & 255}.${hi & 255}.${lo >> 8 & 255}.${lo & 255}`;
|
|
158430
|
+
}
|
|
158431
|
+
return null;
|
|
158432
|
+
}
|
|
158433
|
+
function blockedEmbeddingEndpointReason(endpoint) {
|
|
158434
|
+
const trimmed = endpoint.trim();
|
|
158435
|
+
if (trimmed.length === 0)
|
|
158436
|
+
return null;
|
|
158437
|
+
let url2;
|
|
158438
|
+
try {
|
|
158439
|
+
url2 = new URL(trimmed);
|
|
158440
|
+
} catch {
|
|
158441
|
+
return `embedding endpoint is not a valid URL: ${trimmed}`;
|
|
158442
|
+
}
|
|
158443
|
+
const host = url2.hostname.toLowerCase().replace(/^\[/, "").replace(/\]$/, "");
|
|
158444
|
+
if (METADATA_HOSTNAMES.has(host)) {
|
|
158445
|
+
return `embedding endpoint host ${host} is a cloud metadata service (blocked)`;
|
|
158446
|
+
}
|
|
158447
|
+
if (IPV6_METADATA_HOSTS.has(host)) {
|
|
158448
|
+
return `embedding endpoint host ${host} is the AWS IPv6 metadata service (blocked)`;
|
|
158449
|
+
}
|
|
158450
|
+
if (isLinkLocalIpv4(host)) {
|
|
158451
|
+
return `embedding endpoint host ${host} is link-local / cloud metadata (blocked)`;
|
|
158452
|
+
}
|
|
158453
|
+
const mappedV4 = ipv4FromMappedIpv6(host);
|
|
158454
|
+
if (mappedV4 && isLinkLocalIpv4(mappedV4)) {
|
|
158455
|
+
return `embedding endpoint host ${host} (IPv4-mapped ${mappedV4}) is link-local / cloud metadata (blocked)`;
|
|
158456
|
+
}
|
|
158457
|
+
if (host.startsWith("fe80:")) {
|
|
158458
|
+
return `embedding endpoint host ${host} is link-local / cloud metadata (blocked)`;
|
|
158459
|
+
}
|
|
158460
|
+
return null;
|
|
158461
|
+
}
|
|
158462
|
+
|
|
158463
|
+
// ../plugin/src/features/magic-context/memory/embedding-openai.ts
|
|
158464
|
+
function normalizeEndpoint3(endpoint) {
|
|
158127
158465
|
return endpoint?.trim().replace(/\/+$/, "") ?? "";
|
|
158128
158466
|
}
|
|
158129
158467
|
var FAILURE_THRESHOLD = 3;
|
|
@@ -158144,7 +158482,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
158144
158482
|
openLogged = false;
|
|
158145
158483
|
halfOpenProbeInFlight = false;
|
|
158146
158484
|
constructor(options) {
|
|
158147
|
-
this.endpoint =
|
|
158485
|
+
this.endpoint = normalizeEndpoint3(options.endpoint);
|
|
158148
158486
|
this.model = options.model?.trim() ?? "";
|
|
158149
158487
|
this.apiKey = options.apiKey?.trim() ?? "";
|
|
158150
158488
|
this.inputType = options.inputType?.trim() ?? "";
|
|
@@ -158164,6 +158502,12 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
158164
158502
|
this.initialized = false;
|
|
158165
158503
|
return false;
|
|
158166
158504
|
}
|
|
158505
|
+
const blockedReason = blockedEmbeddingEndpointReason(this.endpoint);
|
|
158506
|
+
if (blockedReason) {
|
|
158507
|
+
log(`[magic-context] embedding endpoint blocked: ${blockedReason}`);
|
|
158508
|
+
this.initialized = false;
|
|
158509
|
+
return false;
|
|
158510
|
+
}
|
|
158167
158511
|
this.initialized = true;
|
|
158168
158512
|
return true;
|
|
158169
158513
|
}
|
|
@@ -158209,6 +158553,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
158209
158553
|
...this.inputType ? { input_type: this.inputType } : {},
|
|
158210
158554
|
...this.truncate ? { truncate: this.truncate } : {}
|
|
158211
158555
|
}),
|
|
158556
|
+
redirect: "error",
|
|
158212
158557
|
signal: internalController.signal
|
|
158213
158558
|
});
|
|
158214
158559
|
if (!response.ok) {
|
|
@@ -158413,6 +158758,7 @@ function getDistinctStoredModelIds(db, projectPath) {
|
|
|
158413
158758
|
|
|
158414
158759
|
// ../plugin/src/features/magic-context/project-embedding-registry.ts
|
|
158415
158760
|
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
158761
|
+
init_logger();
|
|
158416
158762
|
|
|
158417
158763
|
// ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
|
|
158418
158764
|
var saveStatements = new WeakMap;
|
|
@@ -158688,11 +159034,15 @@ function resolveEmbeddingConfig(config2) {
|
|
|
158688
159034
|
}
|
|
158689
159035
|
if (config2.provider === "openai-compatible") {
|
|
158690
159036
|
const apiKey = config2.api_key?.trim();
|
|
159037
|
+
const inputType = config2.input_type?.trim();
|
|
159038
|
+
const truncate = config2.truncate?.trim();
|
|
158691
159039
|
return {
|
|
158692
159040
|
provider: "openai-compatible",
|
|
158693
159041
|
model: config2.model.trim(),
|
|
158694
159042
|
endpoint: config2.endpoint.trim(),
|
|
158695
|
-
...apiKey ? { api_key: apiKey } : {}
|
|
159043
|
+
...apiKey ? { api_key: apiKey } : {},
|
|
159044
|
+
...inputType ? { input_type: inputType } : {},
|
|
159045
|
+
...truncate ? { truncate } : {}
|
|
158696
159046
|
};
|
|
158697
159047
|
}
|
|
158698
159048
|
return { provider: "off" };
|
|
@@ -158708,7 +159058,9 @@ function createProvider(config2) {
|
|
|
158708
159058
|
return new OpenAICompatibleEmbeddingProvider({
|
|
158709
159059
|
endpoint: config2.endpoint,
|
|
158710
159060
|
model: config2.model,
|
|
158711
|
-
apiKey: config2.api_key
|
|
159061
|
+
apiKey: config2.api_key,
|
|
159062
|
+
inputType: config2.input_type,
|
|
159063
|
+
truncate: config2.truncate
|
|
158712
159064
|
});
|
|
158713
159065
|
}
|
|
158714
159066
|
return new LocalEmbeddingProvider(config2.model);
|
|
@@ -159147,17 +159499,41 @@ function hasGitDir(canonical) {
|
|
|
159147
159499
|
return false;
|
|
159148
159500
|
}
|
|
159149
159501
|
}
|
|
159502
|
+
function normalizeStoredProjectPath(rawOrStored) {
|
|
159503
|
+
if (rawOrStored.startsWith("git:") || rawOrStored.startsWith("dir:")) {
|
|
159504
|
+
return rawOrStored;
|
|
159505
|
+
}
|
|
159506
|
+
try {
|
|
159507
|
+
return resolveProjectIdentity(rawOrStored);
|
|
159508
|
+
} catch {
|
|
159509
|
+
return directoryFallback(rawOrStored);
|
|
159510
|
+
}
|
|
159511
|
+
}
|
|
159512
|
+
function storedPathBelongsToIdentity(storedProjectPath, projectIdentity) {
|
|
159513
|
+
return storedProjectPath === projectIdentity || normalizeStoredProjectPath(storedProjectPath) === projectIdentity;
|
|
159514
|
+
}
|
|
159150
159515
|
|
|
159151
159516
|
// ../plugin/src/plugin/embedding-bootstrap-helpers.ts
|
|
159152
159517
|
import { createHash as createHash5 } from "node:crypto";
|
|
159518
|
+
init_logger();
|
|
159153
159519
|
var EMBEDDING_AFFECTING_KEYS = new Set([
|
|
159154
159520
|
"embedding.api_key",
|
|
159155
159521
|
"embedding.endpoint",
|
|
159156
159522
|
"embedding.model",
|
|
159157
|
-
"embedding.provider"
|
|
159523
|
+
"embedding.provider",
|
|
159524
|
+
"embedding.input_type",
|
|
159525
|
+
"embedding.truncate"
|
|
159158
159526
|
]);
|
|
159159
159527
|
var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set(["embedding", "memory", "experimental"]);
|
|
159160
|
-
var EMBEDDING_WARNING_TERMS = [
|
|
159528
|
+
var EMBEDDING_WARNING_TERMS = [
|
|
159529
|
+
"api_key",
|
|
159530
|
+
"endpoint",
|
|
159531
|
+
"model",
|
|
159532
|
+
"provider",
|
|
159533
|
+
"embedding",
|
|
159534
|
+
"input_type",
|
|
159535
|
+
"truncate"
|
|
159536
|
+
];
|
|
159161
159537
|
var loggedFailureSignatures = new Map;
|
|
159162
159538
|
function sha256Prefix2(value, length = 16) {
|
|
159163
159539
|
return createHash5("sha256").update(value).digest("hex").slice(0, length);
|
|
@@ -159237,7 +159613,6 @@ async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
|
159237
159613
|
};
|
|
159238
159614
|
registerProjectEmbeddingAndMaybeWipe(db, projectIdentity, detailed.config.embedding, features, directory);
|
|
159239
159615
|
}
|
|
159240
|
-
|
|
159241
159616
|
// ../plugin/src/features/magic-context/compartment-lease.ts
|
|
159242
159617
|
var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
159243
159618
|
var COMPARTMENT_LEASE_RENEWAL_MS = 60 * 1000;
|
|
@@ -159335,6 +159710,14 @@ var SESSION_META_SELECT_COLUMNS = [
|
|
|
159335
159710
|
"cached_m0_tool_set_hash",
|
|
159336
159711
|
"cached_m0_model_key",
|
|
159337
159712
|
"last_observed_model_key",
|
|
159713
|
+
"last_usage_context_limit",
|
|
159714
|
+
"prior_boundary_ordinal",
|
|
159715
|
+
"protected_tail_policy_version",
|
|
159716
|
+
"protected_tail_drain_window_started_at",
|
|
159717
|
+
"protected_tail_drain_tokens",
|
|
159718
|
+
"recovery_no_eligible_head_count",
|
|
159719
|
+
"force_emergency_bypass_window_start",
|
|
159720
|
+
"force_emergency_bypass_used",
|
|
159338
159721
|
"upgrade_reminded_at",
|
|
159339
159722
|
"pi_stable_id_scheme"
|
|
159340
159723
|
];
|
|
@@ -159374,6 +159757,14 @@ var META_COLUMNS = {
|
|
|
159374
159757
|
cachedM0ToolSetHash: "cached_m0_tool_set_hash",
|
|
159375
159758
|
cachedM0ModelKey: "cached_m0_model_key",
|
|
159376
159759
|
lastObservedModelKey: "last_observed_model_key",
|
|
159760
|
+
lastUsageContextLimit: "last_usage_context_limit",
|
|
159761
|
+
priorBoundaryOrdinal: "prior_boundary_ordinal",
|
|
159762
|
+
protectedTailPolicyVersion: "protected_tail_policy_version",
|
|
159763
|
+
protectedTailDrainWindowStartedAt: "protected_tail_drain_window_started_at",
|
|
159764
|
+
protectedTailDrainTokens: "protected_tail_drain_tokens",
|
|
159765
|
+
recoveryNoEligibleHeadCount: "recovery_no_eligible_head_count",
|
|
159766
|
+
forceEmergencyBypassWindowStart: "force_emergency_bypass_window_start",
|
|
159767
|
+
forceEmergencyBypassUsed: "force_emergency_bypass_used",
|
|
159377
159768
|
upgradeRemindedAt: "upgrade_reminded_at",
|
|
159378
159769
|
piStableIdScheme: "pi_stable_id_scheme"
|
|
159379
159770
|
};
|
|
@@ -159415,7 +159806,7 @@ function isSessionMetaRow(row) {
|
|
|
159415
159806
|
if (row === null || typeof row !== "object")
|
|
159416
159807
|
return false;
|
|
159417
159808
|
const r = row;
|
|
159418
|
-
return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.cached_m0_system_hash) && isStringOrNull(r.cached_m0_tool_set_hash) && isStringOrNull(r.cached_m0_model_key) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
|
|
159809
|
+
return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.cached_m0_system_hash) && isStringOrNull(r.cached_m0_tool_set_hash) && isStringOrNull(r.cached_m0_model_key) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.last_usage_context_limit) && isNumberOrNull(r.prior_boundary_ordinal) && isNumberOrNull(r.protected_tail_policy_version) && isNumberOrNull(r.protected_tail_drain_window_started_at) && isNumberOrNull(r.protected_tail_drain_tokens) && isNumberOrNull(r.recovery_no_eligible_head_count) && isNumberOrNull(r.force_emergency_bypass_window_start) && isNumberOrNull(r.force_emergency_bypass_used) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
|
|
159419
159810
|
}
|
|
159420
159811
|
function getDefaultSessionMeta(sessionId) {
|
|
159421
159812
|
return {
|
|
@@ -159455,6 +159846,14 @@ function getDefaultSessionMeta(sessionId) {
|
|
|
159455
159846
|
cachedM0ToolSetHash: null,
|
|
159456
159847
|
cachedM0ModelKey: null,
|
|
159457
159848
|
lastObservedModelKey: null,
|
|
159849
|
+
lastUsageContextLimit: 0,
|
|
159850
|
+
priorBoundaryOrdinal: 1,
|
|
159851
|
+
protectedTailPolicyVersion: 0,
|
|
159852
|
+
protectedTailDrainWindowStartedAt: 0,
|
|
159853
|
+
protectedTailDrainTokens: 0,
|
|
159854
|
+
recoveryNoEligibleHeadCount: 0,
|
|
159855
|
+
forceEmergencyBypassWindowStart: 0,
|
|
159856
|
+
forceEmergencyBypassUsed: 0,
|
|
159458
159857
|
upgradeRemindedAt: null,
|
|
159459
159858
|
piStableIdScheme: null
|
|
159460
159859
|
};
|
|
@@ -159509,6 +159908,14 @@ function toSessionMeta(row) {
|
|
|
159509
159908
|
cachedM0ToolSetHash: stringOrNull(row.cached_m0_tool_set_hash),
|
|
159510
159909
|
cachedM0ModelKey: stringOrNull(row.cached_m0_model_key),
|
|
159511
159910
|
lastObservedModelKey: stringOrNull(row.last_observed_model_key),
|
|
159911
|
+
lastUsageContextLimit: numOrZero(row.last_usage_context_limit),
|
|
159912
|
+
priorBoundaryOrdinal: Math.max(1, numOrZero(row.prior_boundary_ordinal) || 1),
|
|
159913
|
+
protectedTailPolicyVersion: numOrZero(row.protected_tail_policy_version),
|
|
159914
|
+
protectedTailDrainWindowStartedAt: numOrZero(row.protected_tail_drain_window_started_at),
|
|
159915
|
+
protectedTailDrainTokens: numOrZero(row.protected_tail_drain_tokens),
|
|
159916
|
+
recoveryNoEligibleHeadCount: numOrZero(row.recovery_no_eligible_head_count),
|
|
159917
|
+
forceEmergencyBypassWindowStart: numOrZero(row.force_emergency_bypass_window_start),
|
|
159918
|
+
forceEmergencyBypassUsed: numOrZero(row.force_emergency_bypass_used),
|
|
159512
159919
|
upgradeRemindedAt: numOrNull(row.upgrade_reminded_at),
|
|
159513
159920
|
piStableIdScheme: numOrNull(row.pi_stable_id_scheme)
|
|
159514
159921
|
};
|
|
@@ -159593,12 +160000,6 @@ function isCompartmentRow(row) {
|
|
|
159593
160000
|
const candidate = row;
|
|
159594
160001
|
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number" && typeof candidate.start_message_id === "string" && typeof candidate.end_message_id === "string" && typeof candidate.title === "string" && typeof candidate.content === "string" && isStringOrNullish(candidate.p1) && isStringOrNullish(candidate.p2) && isStringOrNullish(candidate.p3) && isStringOrNullish(candidate.p4) && isNumberOrNullish(candidate.importance) && isStringOrNullish(candidate.episode_type) && isNumberOrNullish(candidate.legacy) && typeof candidate.created_at === "number";
|
|
159595
160002
|
}
|
|
159596
|
-
function isSessionFactRow(row) {
|
|
159597
|
-
if (row === null || typeof row !== "object")
|
|
159598
|
-
return false;
|
|
159599
|
-
const candidate = row;
|
|
159600
|
-
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.category === "string" && typeof candidate.content === "string" && typeof candidate.created_at === "number" && typeof candidate.updated_at === "number";
|
|
159601
|
-
}
|
|
159602
160003
|
function insertCompartmentRows(db, sessionId, compartments, now) {
|
|
159603
160004
|
const stmt = getInsertCompartmentStatement(db);
|
|
159604
160005
|
for (const compartment of compartments) {
|
|
@@ -159627,16 +160028,6 @@ function toCompartment(row) {
|
|
|
159627
160028
|
createdAt: row.created_at
|
|
159628
160029
|
};
|
|
159629
160030
|
}
|
|
159630
|
-
function toSessionFact(row) {
|
|
159631
|
-
return {
|
|
159632
|
-
id: row.id,
|
|
159633
|
-
sessionId: row.session_id,
|
|
159634
|
-
category: row.category,
|
|
159635
|
-
content: row.content,
|
|
159636
|
-
createdAt: row.created_at,
|
|
159637
|
-
updatedAt: row.updated_at
|
|
159638
|
-
};
|
|
159639
|
-
}
|
|
159640
160031
|
function getCompartments(db, sessionId) {
|
|
159641
160032
|
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isCompartmentRow);
|
|
159642
160033
|
return rows.map(toCompartment);
|
|
@@ -159645,6 +160036,11 @@ function getLastCompartmentEndMessage(db, sessionId) {
|
|
|
159645
160036
|
const row = db.prepare("SELECT MAX(end_message) as max_end FROM compartments WHERE session_id = ?").get(sessionId);
|
|
159646
160037
|
return row?.max_end ?? -1;
|
|
159647
160038
|
}
|
|
160039
|
+
function getLastCompartmentEndMessageId(db, sessionId) {
|
|
160040
|
+
const row = db.prepare("SELECT end_message_id FROM compartments WHERE session_id = ? ORDER BY sequence DESC LIMIT 1").get(sessionId);
|
|
160041
|
+
const id = row?.end_message_id;
|
|
160042
|
+
return id && id.length > 0 ? id : null;
|
|
160043
|
+
}
|
|
159648
160044
|
function getCompartmentsByEndMessageId(db, sessionId, endMessageId) {
|
|
159649
160045
|
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? AND end_message_id = ? ORDER BY sequence ASC").all(sessionId, endMessageId).filter(isCompartmentRow);
|
|
159650
160046
|
return rows.map(toCompartment);
|
|
@@ -159657,10 +160053,6 @@ function appendCompartments(db, sessionId, compartments) {
|
|
|
159657
160053
|
insertCompartmentRows(db, sessionId, compartments, now);
|
|
159658
160054
|
})();
|
|
159659
160055
|
}
|
|
159660
|
-
function getSessionFacts(db, sessionId) {
|
|
159661
|
-
const rows = db.prepare("SELECT * FROM session_facts WHERE session_id = ? ORDER BY category ASC, id ASC").all(sessionId).filter(isSessionFactRow);
|
|
159662
|
-
return rows.map(toSessionFact);
|
|
159663
|
-
}
|
|
159664
160056
|
function saveRecompStagingPass(db, sessionId, passNumber, compartments, facts) {
|
|
159665
160057
|
const now = Date.now();
|
|
159666
160058
|
db.transaction(() => {
|
|
@@ -159704,14 +160096,6 @@ function getRecompStaging(db, sessionId) {
|
|
|
159704
160096
|
lastEndMessage: lastEnd
|
|
159705
160097
|
};
|
|
159706
160098
|
}
|
|
159707
|
-
function invalidateAllMemoryBlockCaches(db) {
|
|
159708
|
-
try {
|
|
159709
|
-
const rows = db.prepare("SELECT session_id FROM session_meta").all();
|
|
159710
|
-
for (const row of rows) {
|
|
159711
|
-
clearCachedM0M1(db, row.session_id);
|
|
159712
|
-
}
|
|
159713
|
-
} catch {}
|
|
159714
|
-
}
|
|
159715
160099
|
function clearRecompStaging(db, sessionId) {
|
|
159716
160100
|
db.transaction(() => {
|
|
159717
160101
|
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
@@ -159759,6 +160143,8 @@ function escapeXmlContent(s) {
|
|
|
159759
160143
|
}
|
|
159760
160144
|
|
|
159761
160145
|
// ../plugin/src/hooks/magic-context/read-session-db.ts
|
|
160146
|
+
init_data_path();
|
|
160147
|
+
init_logger();
|
|
159762
160148
|
import { existsSync as existsSync6 } from "node:fs";
|
|
159763
160149
|
import { join as join7 } from "node:path";
|
|
159764
160150
|
function getOpenCodeDbPath() {
|
|
@@ -159831,13 +160217,27 @@ function parseJsonUnknown(value) {
|
|
|
159831
160217
|
return null;
|
|
159832
160218
|
}
|
|
159833
160219
|
}
|
|
160220
|
+
function attachRawPartVersion(value, timeUpdated) {
|
|
160221
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
160222
|
+
return value;
|
|
160223
|
+
if (typeof timeUpdated !== "number")
|
|
160224
|
+
return value;
|
|
160225
|
+
try {
|
|
160226
|
+
Object.defineProperty(value, "__magicContextPartUpdatedAt", {
|
|
160227
|
+
value: timeUpdated,
|
|
160228
|
+
enumerable: false,
|
|
160229
|
+
configurable: true
|
|
160230
|
+
});
|
|
160231
|
+
} catch {}
|
|
160232
|
+
return value;
|
|
160233
|
+
}
|
|
159834
160234
|
function readRawSessionMessagesFromDb(db, sessionId) {
|
|
159835
|
-
const messageRows = db.prepare("SELECT id, data FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
159836
|
-
const partRows = db.prepare("SELECT message_id, data FROM part WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawPartRow);
|
|
160235
|
+
const messageRows = db.prepare("SELECT id, data, time_updated FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
160236
|
+
const partRows = db.prepare("SELECT message_id, data, time_updated FROM part WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawPartRow);
|
|
159837
160237
|
const partsByMessageId = new Map;
|
|
159838
160238
|
for (const part of partRows) {
|
|
159839
160239
|
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
159840
|
-
list.push(parseJsonUnknown(part.data));
|
|
160240
|
+
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
159841
160241
|
partsByMessageId.set(part.message_id, list);
|
|
159842
160242
|
}
|
|
159843
160243
|
const filtered = messageRows.filter((row) => {
|
|
@@ -159853,10 +160253,63 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
159853
160253
|
ordinal: index + 1,
|
|
159854
160254
|
id: row.id,
|
|
159855
160255
|
role,
|
|
159856
|
-
parts: partsByMessageId.get(row.id) ?? []
|
|
160256
|
+
parts: partsByMessageId.get(row.id) ?? [],
|
|
160257
|
+
version: row.time_updated ?? null
|
|
159857
160258
|
};
|
|
159858
160259
|
});
|
|
159859
160260
|
}
|
|
160261
|
+
function isAnchorRow(row) {
|
|
160262
|
+
return row !== null && typeof row === "object" && typeof row.time_created === "number" && typeof row.id === "string";
|
|
160263
|
+
}
|
|
160264
|
+
function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
160265
|
+
const anchorRow = db.prepare("SELECT time_created, id, data FROM message WHERE id = ? AND session_id = ?").get(anchorMessageId, sessionId);
|
|
160266
|
+
if (!isAnchorRow(anchorRow))
|
|
160267
|
+
return null;
|
|
160268
|
+
const anchorInfo = parseJsonRecord(anchorRow.data ?? "");
|
|
160269
|
+
if (anchorInfo?.summary === true && anchorInfo?.finish === "stop")
|
|
160270
|
+
return null;
|
|
160271
|
+
const messageRows = db.prepare(`SELECT id, data, time_updated FROM message
|
|
160272
|
+
WHERE session_id = ?
|
|
160273
|
+
AND (time_created > ? OR (time_created = ? AND id >= ?))
|
|
160274
|
+
ORDER BY time_created ASC, id ASC`).all(sessionId, anchorRow.time_created, anchorRow.time_created, anchorRow.id).filter(isRawMessageRow);
|
|
160275
|
+
const filtered = messageRows.filter((row) => {
|
|
160276
|
+
const info = parseJsonRecord(row.data);
|
|
160277
|
+
return !(info?.summary === true && info?.finish === "stop");
|
|
160278
|
+
});
|
|
160279
|
+
const ids = filtered.map((row) => row.id);
|
|
160280
|
+
const partsByMessageId = new Map;
|
|
160281
|
+
if (ids.length > 0) {
|
|
160282
|
+
const CHUNK = 800;
|
|
160283
|
+
for (let i = 0;i < ids.length; i += CHUNK) {
|
|
160284
|
+
const slice = ids.slice(i, i + CHUNK);
|
|
160285
|
+
const placeholders = slice.map(() => "?").join(",");
|
|
160286
|
+
const partRows = db.prepare(`SELECT message_id, data, time_updated FROM part WHERE session_id = ? AND message_id IN (${placeholders}) ORDER BY time_created ASC, id ASC`).all(sessionId, ...slice).filter(isRawPartRow);
|
|
160287
|
+
for (const part of partRows) {
|
|
160288
|
+
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
160289
|
+
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
160290
|
+
partsByMessageId.set(part.message_id, list);
|
|
160291
|
+
}
|
|
160292
|
+
}
|
|
160293
|
+
}
|
|
160294
|
+
const messages = [];
|
|
160295
|
+
let ord = baseOrdinal;
|
|
160296
|
+
for (const row of filtered) {
|
|
160297
|
+
const info = parseJsonRecord(row.data);
|
|
160298
|
+
if (!info) {
|
|
160299
|
+
ord += 1;
|
|
160300
|
+
continue;
|
|
160301
|
+
}
|
|
160302
|
+
messages.push({
|
|
160303
|
+
ordinal: ord,
|
|
160304
|
+
id: row.id,
|
|
160305
|
+
role: typeof info.role === "string" ? info.role : "unknown",
|
|
160306
|
+
parts: partsByMessageId.get(row.id) ?? [],
|
|
160307
|
+
version: row.time_updated ?? null
|
|
160308
|
+
});
|
|
160309
|
+
ord += 1;
|
|
160310
|
+
}
|
|
160311
|
+
return { messages, absoluteMessageCount: Math.max(0, ord - 1) };
|
|
160312
|
+
}
|
|
159860
160313
|
|
|
159861
160314
|
// ../plugin/src/hooks/magic-context/tag-content-primitives.ts
|
|
159862
160315
|
var encoder = new TextEncoder;
|
|
@@ -160001,6 +160454,7 @@ class ToolMutationBatch {
|
|
|
160001
160454
|
|
|
160002
160455
|
// ../plugin/src/hooks/magic-context/read-session-chunk.ts
|
|
160003
160456
|
var activeRawMessageCache = null;
|
|
160457
|
+
var activeAbsoluteCountCache = null;
|
|
160004
160458
|
var sessionProviders = new Map;
|
|
160005
160459
|
function setRawMessageProvider(sessionId, provider2) {
|
|
160006
160460
|
sessionProviders.set(sessionId, provider2);
|
|
@@ -160032,12 +160486,14 @@ function withRawSessionMessageCache(fn) {
|
|
|
160032
160486
|
const outerCache = activeRawMessageCache;
|
|
160033
160487
|
if (!outerCache) {
|
|
160034
160488
|
activeRawMessageCache = new Map;
|
|
160489
|
+
activeAbsoluteCountCache = new Map;
|
|
160035
160490
|
}
|
|
160036
160491
|
try {
|
|
160037
160492
|
return fn();
|
|
160038
160493
|
} finally {
|
|
160039
160494
|
if (!outerCache) {
|
|
160040
160495
|
activeRawMessageCache = null;
|
|
160496
|
+
activeAbsoluteCountCache = null;
|
|
160041
160497
|
}
|
|
160042
160498
|
}
|
|
160043
160499
|
}
|
|
@@ -160053,6 +160509,40 @@ function readRawSessionMessages(sessionId) {
|
|
|
160053
160509
|
}
|
|
160054
160510
|
return readRawSessionMessagesFromSource(sessionId);
|
|
160055
160511
|
}
|
|
160512
|
+
function primeTailRawMessageCache(args) {
|
|
160513
|
+
const { sessionId, lastCompartmentEnd, anchorMessageId } = args;
|
|
160514
|
+
if (!activeRawMessageCache)
|
|
160515
|
+
return false;
|
|
160516
|
+
if (activeRawMessageCache.has(sessionId))
|
|
160517
|
+
return false;
|
|
160518
|
+
if (sessionProviders.has(sessionId))
|
|
160519
|
+
return false;
|
|
160520
|
+
if (!openCodeDbExists())
|
|
160521
|
+
return false;
|
|
160522
|
+
if (lastCompartmentEnd < 1 || !anchorMessageId)
|
|
160523
|
+
return false;
|
|
160524
|
+
const result = withReadOnlySessionDb((db) => readRawSessionTailFromDb(db, sessionId, lastCompartmentEnd, anchorMessageId));
|
|
160525
|
+
if (!result)
|
|
160526
|
+
return false;
|
|
160527
|
+
activeRawMessageCache.set(sessionId, result.messages);
|
|
160528
|
+
activeAbsoluteCountCache?.set(sessionId, result.absoluteMessageCount);
|
|
160529
|
+
return true;
|
|
160530
|
+
}
|
|
160531
|
+
function getCachedAbsoluteMessageCount(sessionId) {
|
|
160532
|
+
return activeAbsoluteCountCache?.get(sessionId) ?? null;
|
|
160533
|
+
}
|
|
160534
|
+
function primeInMemoryTailRawMessageCache(args) {
|
|
160535
|
+
const { sessionId, messages, absoluteMessageCount } = args;
|
|
160536
|
+
if (!activeRawMessageCache)
|
|
160537
|
+
return false;
|
|
160538
|
+
if (activeRawMessageCache.has(sessionId))
|
|
160539
|
+
return false;
|
|
160540
|
+
if (sessionProviders.has(sessionId))
|
|
160541
|
+
return false;
|
|
160542
|
+
activeRawMessageCache.set(sessionId, messages);
|
|
160543
|
+
activeAbsoluteCountCache?.set(sessionId, absoluteMessageCount);
|
|
160544
|
+
return true;
|
|
160545
|
+
}
|
|
160056
160546
|
function readRawSessionMessagesFromSource(sessionId) {
|
|
160057
160547
|
const provider2 = sessionProviders.get(sessionId);
|
|
160058
160548
|
if (provider2)
|
|
@@ -160117,7 +160607,7 @@ function getRawSessionTagKeysThrough(sessionId, upToMessageIndex) {
|
|
|
160117
160607
|
return { messageFileKeys, toolObservations };
|
|
160118
160608
|
}
|
|
160119
160609
|
var PROTECTED_TAIL_USER_TURNS = 5;
|
|
160120
|
-
function
|
|
160610
|
+
function getLegacyProtectedTailStartOrdinal(sessionId) {
|
|
160121
160611
|
const messages = readRawSessionMessages(sessionId);
|
|
160122
160612
|
const userOrdinals = messages.filter((m) => m.role === "user" && hasMeaningfulUserText(m.parts)).map((m) => m.ordinal);
|
|
160123
160613
|
if (userOrdinals.length < PROTECTED_TAIL_USER_TURNS) {
|
|
@@ -160127,6 +160617,7 @@ function getProtectedTailStartOrdinal(sessionId) {
|
|
|
160127
160617
|
}
|
|
160128
160618
|
function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal) {
|
|
160129
160619
|
const messages = readRawSessionMessages(sessionId);
|
|
160620
|
+
const totalMessageCount = getCachedAbsoluteMessageCount(sessionId) ?? messages.length;
|
|
160130
160621
|
const startOrdinal = Math.max(1, offset);
|
|
160131
160622
|
const lines = [];
|
|
160132
160623
|
const lineMeta = [];
|
|
@@ -160254,7 +160745,7 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
160254
160745
|
endMessageId: lastMessageId,
|
|
160255
160746
|
messageCount: messagesProcessed,
|
|
160256
160747
|
tokenEstimate: totalTokens,
|
|
160257
|
-
hasMore: lastOrdinal < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1,
|
|
160748
|
+
hasMore: lastOrdinal < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1, totalMessageCount) : totalMessageCount),
|
|
160258
160749
|
text: lines.join(`
|
|
160259
160750
|
`),
|
|
160260
160751
|
lines: lineMeta,
|
|
@@ -160264,7 +160755,13 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
160264
160755
|
}
|
|
160265
160756
|
|
|
160266
160757
|
// ../plugin/src/tools/ctx-expand/constants.ts
|
|
160267
|
-
var CTX_EXPAND_DESCRIPTION =
|
|
160758
|
+
var CTX_EXPAND_DESCRIPTION = `Recover the original conversation from your compacted history.
|
|
160759
|
+
|
|
160760
|
+
Older parts of this session are summarized into <compartment> blocks inside <session-history> — e.g. <compartment start="120" end="245" title="Fixed tagger collision">. Each one replaces the raw messages in that ordinal range with a summary. When the summary isn't enough — you need exact wording, a specific value, an error message, or the reasoning behind a decision — expand the range:
|
|
160761
|
+
|
|
160762
|
+
ctx_expand(start=120, end=245) ← the compartment's own start/end attributes
|
|
160763
|
+
|
|
160764
|
+
Returns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversized range returns the head and tells you where to continue. Also works with ordinals from ctx_search message results — expand a window around a hit (e.g. start=N-10, end=N+5). Ranges after the last compartment are your live tail — already visible in context, not expandable.`;
|
|
160268
160765
|
var CTX_EXPAND_TOKEN_BUDGET = 15000;
|
|
160269
160766
|
|
|
160270
160767
|
// ../../node_modules/.bun/typebox@1.1.38/node_modules/typebox/build/system/memory/memory.mjs
|
|
@@ -164433,11 +164930,31 @@ function findLastModelKeyFromBranch(entries) {
|
|
|
164433
164930
|
}
|
|
164434
164931
|
return;
|
|
164435
164932
|
}
|
|
164933
|
+
function rawEntryVersion(entry) {
|
|
164934
|
+
const record4 = entry;
|
|
164935
|
+
const updated = record4.updatedAt ?? record4.updated_at ?? record4.timestamp;
|
|
164936
|
+
return typeof updated === "string" || typeof updated === "number" ? updated : entry.id;
|
|
164937
|
+
}
|
|
164938
|
+
function attachPiPartVersion(parts, version2) {
|
|
164939
|
+
return parts.map((part) => {
|
|
164940
|
+
if (part === null || typeof part !== "object" || Array.isArray(part))
|
|
164941
|
+
return part;
|
|
164942
|
+
try {
|
|
164943
|
+
Object.defineProperty(part, "__magicContextPartUpdatedAt", {
|
|
164944
|
+
value: version2,
|
|
164945
|
+
enumerable: false,
|
|
164946
|
+
configurable: true
|
|
164947
|
+
});
|
|
164948
|
+
} catch {}
|
|
164949
|
+
return part;
|
|
164950
|
+
});
|
|
164951
|
+
}
|
|
164436
164952
|
function convertEntriesToRawMessages(entries) {
|
|
164437
164953
|
const result = [];
|
|
164438
164954
|
let nextOrdinal = 1;
|
|
164439
164955
|
let pendingToolParts = [];
|
|
164440
164956
|
let pendingFirstRealId = "";
|
|
164957
|
+
let pendingFirstRealVersion = "";
|
|
164441
164958
|
for (const entry of entries) {
|
|
164442
164959
|
if (!isMessageEntry(entry)) {
|
|
164443
164960
|
continue;
|
|
@@ -164445,24 +164962,29 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164445
164962
|
const msg = entry.message;
|
|
164446
164963
|
const role = msg.role;
|
|
164447
164964
|
if (role === "toolResult") {
|
|
164448
|
-
|
|
164965
|
+
const version2 = rawEntryVersion(entry);
|
|
164966
|
+
pendingToolParts.push(...attachPiPartVersion(synthesizeToolResultParts(msg), version2));
|
|
164449
164967
|
if (pendingFirstRealId === "") {
|
|
164450
164968
|
pendingFirstRealId = entry.id;
|
|
164969
|
+
pendingFirstRealVersion = version2;
|
|
164451
164970
|
}
|
|
164452
164971
|
continue;
|
|
164453
164972
|
}
|
|
164454
164973
|
if (role === "user") {
|
|
164974
|
+
const version2 = rawEntryVersion(entry);
|
|
164455
164975
|
const parts = [
|
|
164456
164976
|
...pendingToolParts,
|
|
164457
|
-
...synthesizeUserParts(msg)
|
|
164977
|
+
...attachPiPartVersion(synthesizeUserParts(msg), version2)
|
|
164458
164978
|
];
|
|
164459
164979
|
pendingToolParts = [];
|
|
164460
164980
|
pendingFirstRealId = "";
|
|
164981
|
+
pendingFirstRealVersion = "";
|
|
164461
164982
|
result.push({
|
|
164462
164983
|
ordinal: nextOrdinal++,
|
|
164463
164984
|
id: entry.id,
|
|
164464
164985
|
role: "user",
|
|
164465
|
-
parts
|
|
164986
|
+
parts,
|
|
164987
|
+
version: version2
|
|
164466
164988
|
});
|
|
164467
164989
|
continue;
|
|
164468
164990
|
}
|
|
@@ -164472,16 +164994,20 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164472
164994
|
ordinal: nextOrdinal++,
|
|
164473
164995
|
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
164474
164996
|
role: "user",
|
|
164475
|
-
parts: pendingToolParts
|
|
164997
|
+
parts: pendingToolParts,
|
|
164998
|
+
version: pendingFirstRealVersion
|
|
164476
164999
|
});
|
|
164477
165000
|
pendingToolParts = [];
|
|
164478
165001
|
pendingFirstRealId = "";
|
|
165002
|
+
pendingFirstRealVersion = "";
|
|
164479
165003
|
}
|
|
165004
|
+
const version2 = rawEntryVersion(entry);
|
|
164480
165005
|
result.push({
|
|
164481
165006
|
ordinal: nextOrdinal++,
|
|
164482
165007
|
id: entry.id,
|
|
164483
165008
|
role: "assistant",
|
|
164484
|
-
parts: synthesizeAssistantParts(msg)
|
|
165009
|
+
parts: attachPiPartVersion(synthesizeAssistantParts(msg), version2),
|
|
165010
|
+
version: version2
|
|
164485
165011
|
});
|
|
164486
165012
|
continue;
|
|
164487
165013
|
}
|
|
@@ -164489,7 +165015,8 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164489
165015
|
ordinal: nextOrdinal++,
|
|
164490
165016
|
id: entry.id,
|
|
164491
165017
|
role: typeof role === "string" ? role : "unknown",
|
|
164492
|
-
parts: []
|
|
165018
|
+
parts: [],
|
|
165019
|
+
version: rawEntryVersion(entry)
|
|
164493
165020
|
});
|
|
164494
165021
|
}
|
|
164495
165022
|
if (pendingToolParts.length > 0) {
|
|
@@ -164497,7 +165024,8 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164497
165024
|
ordinal: nextOrdinal,
|
|
164498
165025
|
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
164499
165026
|
role: "user",
|
|
164500
|
-
parts: pendingToolParts
|
|
165027
|
+
parts: pendingToolParts,
|
|
165028
|
+
version: pendingFirstRealVersion
|
|
164501
165029
|
});
|
|
164502
165030
|
}
|
|
164503
165031
|
return result;
|
|
@@ -164654,6 +165182,13 @@ function createCtxExpandTool(deps) {
|
|
|
164654
165182
|
}
|
|
164655
165183
|
|
|
164656
165184
|
// ../plugin/src/features/magic-context/memory/constants.ts
|
|
165185
|
+
var V2_MEMORY_CATEGORIES = [
|
|
165186
|
+
"PROJECT_RULES",
|
|
165187
|
+
"ARCHITECTURE",
|
|
165188
|
+
"CONSTRAINTS",
|
|
165189
|
+
"CONFIG_VALUES",
|
|
165190
|
+
"NAMING"
|
|
165191
|
+
];
|
|
164657
165192
|
var PROMOTABLE_CATEGORIES = [
|
|
164658
165193
|
"PROJECT_RULES",
|
|
164659
165194
|
"ARCHITECTURE",
|
|
@@ -164693,6 +165228,7 @@ var CATEGORY_DEFAULT_TTL = {
|
|
|
164693
165228
|
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
164694
165229
|
};
|
|
164695
165230
|
// ../plugin/src/features/magic-context/memory/embedding-backfill.ts
|
|
165231
|
+
init_logger();
|
|
164696
165232
|
async function ensureMemoryEmbeddings(args) {
|
|
164697
165233
|
const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
164698
165234
|
if (!snapshot?.enabled) {
|
|
@@ -164730,6 +165266,9 @@ async function ensureMemoryEmbeddings(args) {
|
|
|
164730
165266
|
}
|
|
164731
165267
|
return args.existingEmbeddings;
|
|
164732
165268
|
}
|
|
165269
|
+
// ../plugin/src/features/magic-context/memory/promotion.ts
|
|
165270
|
+
init_logger();
|
|
165271
|
+
|
|
164733
165272
|
// ../plugin/src/features/magic-context/memory/storage-memory.ts
|
|
164734
165273
|
var COLUMN_MAP = {
|
|
164735
165274
|
id: "id",
|
|
@@ -165401,7 +165940,7 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, lastIndexedOrdinal,
|
|
|
165401
165940
|
}
|
|
165402
165941
|
// ../plugin/src/features/magic-context/project-docs-hash.ts
|
|
165403
165942
|
import { createHash as createHash6 } from "node:crypto";
|
|
165404
|
-
import { readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
|
|
165943
|
+
import { lstatSync, readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
|
|
165405
165944
|
import path4 from "node:path";
|
|
165406
165945
|
var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
165407
165946
|
var PROJECT_DOCS_DELIMITER = `
|
|
@@ -165409,6 +165948,7 @@ var PROJECT_DOCS_DELIMITER = `
|
|
|
165409
165948
|
---
|
|
165410
165949
|
|
|
165411
165950
|
`;
|
|
165951
|
+
var MAX_PROJECT_DOC_BYTES = 256 * 1024;
|
|
165412
165952
|
var docsCache = new Map;
|
|
165413
165953
|
function canonicalizeDocContent(raw) {
|
|
165414
165954
|
return raw.replace(/^\uFEFF/, "").replace(/\r\n/g, `
|
|
@@ -165418,9 +165958,10 @@ function canonicalizeDocContent(raw) {
|
|
|
165418
165958
|
}
|
|
165419
165959
|
function fingerprintFile(filePath) {
|
|
165420
165960
|
try {
|
|
165421
|
-
const stat2 =
|
|
165961
|
+
const stat2 = lstatSync(filePath);
|
|
165962
|
+
const isReadableDoc = stat2.isFile() && stat2.size <= MAX_PROJECT_DOC_BYTES;
|
|
165422
165963
|
return {
|
|
165423
|
-
exists:
|
|
165964
|
+
exists: isReadableDoc,
|
|
165424
165965
|
mtimeMs: stat2.mtimeMs,
|
|
165425
165966
|
size: stat2.size
|
|
165426
165967
|
};
|
|
@@ -165463,6 +166004,16 @@ function readCanonicalPieces(projectDirectory, files) {
|
|
|
165463
166004
|
if (!fingerprint?.exists) {
|
|
165464
166005
|
continue;
|
|
165465
166006
|
}
|
|
166007
|
+
let safeToRead = false;
|
|
166008
|
+
try {
|
|
166009
|
+
const st = lstatSync(filePath);
|
|
166010
|
+
safeToRead = st.isFile() && st.size <= MAX_PROJECT_DOC_BYTES;
|
|
166011
|
+
} catch {
|
|
166012
|
+
safeToRead = false;
|
|
166013
|
+
}
|
|
166014
|
+
if (!safeToRead) {
|
|
166015
|
+
continue;
|
|
166016
|
+
}
|
|
165466
166017
|
const canonicalContent = canonicalizeDocContent(readFileSync4(filePath, "utf8"));
|
|
165467
166018
|
hashPieces.push(`file:${filename}
|
|
165468
166019
|
${canonicalContent}`);
|
|
@@ -165629,6 +166180,7 @@ function getMaxMemoryMutationId(db, projectPath) {
|
|
|
165629
166180
|
return row?.max_id ?? null;
|
|
165630
166181
|
}
|
|
165631
166182
|
// ../plugin/src/features/magic-context/storage-meta-persisted.ts
|
|
166183
|
+
init_logger();
|
|
165632
166184
|
var CAS_RETRY_LIMIT = 5;
|
|
165633
166185
|
var AUTO_SEARCH_NO_HINT_REASONS = new Set([
|
|
165634
166186
|
"below-threshold",
|
|
@@ -165638,12 +166190,6 @@ var AUTO_SEARCH_NO_HINT_REASONS = new Set([
|
|
|
165638
166190
|
"stacked",
|
|
165639
166191
|
"too-short"
|
|
165640
166192
|
]);
|
|
165641
|
-
function isPersistedStickyTurnReminderRow(row) {
|
|
165642
|
-
if (row === null || typeof row !== "object")
|
|
165643
|
-
return false;
|
|
165644
|
-
const r = row;
|
|
165645
|
-
return typeof r.sticky_turn_reminder_text === "string" && typeof r.sticky_turn_reminder_message_id === "string";
|
|
165646
|
-
}
|
|
165647
166193
|
function isPersistedNoteNudgeRow(row) {
|
|
165648
166194
|
if (row === null || typeof row !== "object")
|
|
165649
166195
|
return false;
|
|
@@ -165709,6 +166255,139 @@ function getDefaultHistorianFailureState() {
|
|
|
165709
166255
|
lastFailureAt: null
|
|
165710
166256
|
};
|
|
165711
166257
|
}
|
|
166258
|
+
var DEFAULT_PROTECTED_TAIL_META = {
|
|
166259
|
+
priorBoundaryOrdinal: 1,
|
|
166260
|
+
protectedTailPolicyVersion: 0,
|
|
166261
|
+
protectedTailDrainWindowStartedAt: 0,
|
|
166262
|
+
protectedTailDrainTokens: 0,
|
|
166263
|
+
recoveryNoEligibleHeadCount: 0,
|
|
166264
|
+
forceEmergencyBypassWindowStart: 0,
|
|
166265
|
+
forceEmergencyBypassUsed: 0
|
|
166266
|
+
};
|
|
166267
|
+
function toProtectedTailMeta(row) {
|
|
166268
|
+
if (row === null || typeof row !== "object")
|
|
166269
|
+
return { ...DEFAULT_PROTECTED_TAIL_META };
|
|
166270
|
+
const r = row;
|
|
166271
|
+
const numberOr = (value, fallback) => typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
166272
|
+
return {
|
|
166273
|
+
priorBoundaryOrdinal: Math.max(1, numberOr(r.prior_boundary_ordinal, 1)),
|
|
166274
|
+
protectedTailPolicyVersion: numberOr(r.protected_tail_policy_version, 0),
|
|
166275
|
+
protectedTailDrainWindowStartedAt: numberOr(r.protected_tail_drain_window_started_at, 0),
|
|
166276
|
+
protectedTailDrainTokens: numberOr(r.protected_tail_drain_tokens, 0),
|
|
166277
|
+
recoveryNoEligibleHeadCount: numberOr(r.recovery_no_eligible_head_count, 0),
|
|
166278
|
+
forceEmergencyBypassWindowStart: numberOr(r.force_emergency_bypass_window_start, 0),
|
|
166279
|
+
forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0)
|
|
166280
|
+
};
|
|
166281
|
+
}
|
|
166282
|
+
function loadProtectedTailMeta(db, sessionId) {
|
|
166283
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166284
|
+
const row = db.prepare(`SELECT prior_boundary_ordinal, protected_tail_policy_version,
|
|
166285
|
+
protected_tail_drain_window_started_at, protected_tail_drain_tokens,
|
|
166286
|
+
recovery_no_eligible_head_count, force_emergency_bypass_window_start,
|
|
166287
|
+
force_emergency_bypass_used
|
|
166288
|
+
FROM session_meta WHERE session_id = ?`).get(sessionId);
|
|
166289
|
+
return toProtectedTailMeta(row);
|
|
166290
|
+
}
|
|
166291
|
+
function markProtectedTailPolicyV3Seeded(db, sessionId, priorBoundaryOrdinal) {
|
|
166292
|
+
let seeded = false;
|
|
166293
|
+
db.transaction(() => {
|
|
166294
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166295
|
+
const existing = loadProtectedTailMeta(db, sessionId);
|
|
166296
|
+
if (existing.protectedTailPolicyVersion < 3) {
|
|
166297
|
+
db.prepare(`UPDATE session_meta
|
|
166298
|
+
SET prior_boundary_ordinal = ?, protected_tail_policy_version = 3
|
|
166299
|
+
WHERE session_id = ? AND protected_tail_policy_version < 3`).run(Math.max(1, Math.floor(priorBoundaryOrdinal)), sessionId);
|
|
166300
|
+
seeded = true;
|
|
166301
|
+
}
|
|
166302
|
+
})();
|
|
166303
|
+
return { ...loadProtectedTailMeta(db, sessionId), seeded };
|
|
166304
|
+
}
|
|
166305
|
+
function recordProtectedTailPublicationFloor(db, sessionId, floorOrdinal) {
|
|
166306
|
+
db.transaction(() => {
|
|
166307
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166308
|
+
db.prepare(`UPDATE session_meta
|
|
166309
|
+
SET prior_boundary_ordinal = MAX(COALESCE(prior_boundary_ordinal, 1), ?),
|
|
166310
|
+
recovery_no_eligible_head_count = 0
|
|
166311
|
+
WHERE session_id = ?`).run(Math.max(1, Math.floor(floorOrdinal)), sessionId);
|
|
166312
|
+
})();
|
|
166313
|
+
}
|
|
166314
|
+
function recordProtectedTailNoEligibleHead(db, sessionId) {
|
|
166315
|
+
db.transaction(() => {
|
|
166316
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166317
|
+
db.prepare(`UPDATE session_meta
|
|
166318
|
+
SET recovery_no_eligible_head_count = COALESCE(recovery_no_eligible_head_count, 0) + 1
|
|
166319
|
+
WHERE session_id = ?`).run(sessionId);
|
|
166320
|
+
})();
|
|
166321
|
+
return loadProtectedTailMeta(db, sessionId).recoveryNoEligibleHeadCount;
|
|
166322
|
+
}
|
|
166323
|
+
var DRAIN_WINDOW_MS = 10 * 60 * 1000;
|
|
166324
|
+
function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
166325
|
+
if (usagePercentage >= 95)
|
|
166326
|
+
return Math.min(1e6, Math.max(4 * perRunCap, Math.round(0.5 * usable)));
|
|
166327
|
+
if (usagePercentage >= 80)
|
|
166328
|
+
return Math.min(750000, Math.max(3 * perRunCap, Math.round(0.35 * usable)));
|
|
166329
|
+
return Math.min(500000, Math.max(perRunCap, Math.round(0.2 * usable)));
|
|
166330
|
+
}
|
|
166331
|
+
function reserveProtectedTailDrainTokens(args) {
|
|
166332
|
+
const now = args.now ?? Date.now();
|
|
166333
|
+
const requested = Math.max(0, Math.floor(args.trueRawTokens));
|
|
166334
|
+
if (requested === 0) {
|
|
166335
|
+
return { ok: true, reservedTokens: 0, overQuotaBypass: false, reservation: null };
|
|
166336
|
+
}
|
|
166337
|
+
let result = {
|
|
166338
|
+
ok: false,
|
|
166339
|
+
reservedTokens: 0,
|
|
166340
|
+
overQuotaBypass: false,
|
|
166341
|
+
reservation: null,
|
|
166342
|
+
skippedReason: "quota exhausted"
|
|
166343
|
+
};
|
|
166344
|
+
args.db.transaction(() => {
|
|
166345
|
+
ensureSessionMetaRow(args.db, args.sessionId);
|
|
166346
|
+
let meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
166347
|
+
if (now - meta3.protectedTailDrainWindowStartedAt > DRAIN_WINDOW_MS) {
|
|
166348
|
+
args.db.prepare(`UPDATE session_meta
|
|
166349
|
+
SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0,
|
|
166350
|
+
force_emergency_bypass_window_start = ?, force_emergency_bypass_used = 0
|
|
166351
|
+
WHERE session_id = ?`).run(now, now, args.sessionId);
|
|
166352
|
+
meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
166353
|
+
}
|
|
166354
|
+
const budget = protectedTailWindowBudget(args.usagePercentage, args.usable, args.perRunCap);
|
|
166355
|
+
const remaining = Math.max(0, budget - meta3.protectedTailDrainTokens);
|
|
166356
|
+
let reserved = Math.min(requested, args.perRunCap, remaining);
|
|
166357
|
+
let bypass = false;
|
|
166358
|
+
const bypassWindowExpired = now - meta3.forceEmergencyBypassWindowStart > DRAIN_WINDOW_MS;
|
|
166359
|
+
const bypassUsed = bypassWindowExpired ? 0 : meta3.forceEmergencyBypassUsed;
|
|
166360
|
+
if (reserved <= 0 && args.usagePercentage >= 95 && bypassUsed === 0) {
|
|
166361
|
+
reserved = Math.min(requested, args.perRunCap);
|
|
166362
|
+
bypass = true;
|
|
166363
|
+
}
|
|
166364
|
+
if (reserved <= 0)
|
|
166365
|
+
return;
|
|
166366
|
+
args.db.prepare(`UPDATE session_meta
|
|
166367
|
+
SET protected_tail_drain_window_started_at = CASE WHEN protected_tail_drain_window_started_at = 0 THEN ? ELSE protected_tail_drain_window_started_at END,
|
|
166368
|
+
protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) + ?,
|
|
166369
|
+
force_emergency_bypass_window_start = CASE WHEN ? THEN ? ELSE force_emergency_bypass_window_start END,
|
|
166370
|
+
force_emergency_bypass_used = CASE WHEN ? THEN 1 ELSE force_emergency_bypass_used END
|
|
166371
|
+
WHERE session_id = ?`).run(now, reserved, bypass ? 1 : 0, now, bypass ? 1 : 0, args.sessionId);
|
|
166372
|
+
result = {
|
|
166373
|
+
ok: true,
|
|
166374
|
+
reservedTokens: reserved,
|
|
166375
|
+
overQuotaBypass: bypass,
|
|
166376
|
+
reservation: { sessionId: args.sessionId, runId: args.runId, tokens: reserved }
|
|
166377
|
+
};
|
|
166378
|
+
})();
|
|
166379
|
+
return result;
|
|
166380
|
+
}
|
|
166381
|
+
function rollbackProtectedTailDrainReservation(db, reservation) {
|
|
166382
|
+
if (!reservation || reservation.tokens <= 0)
|
|
166383
|
+
return;
|
|
166384
|
+
db.transaction(() => {
|
|
166385
|
+
ensureSessionMetaRow(db, reservation.sessionId);
|
|
166386
|
+
db.prepare(`UPDATE session_meta
|
|
166387
|
+
SET protected_tail_drain_tokens = MAX(0, COALESCE(protected_tail_drain_tokens, 0) - ?)
|
|
166388
|
+
WHERE session_id = ?`).run(reservation.tokens, reservation.sessionId);
|
|
166389
|
+
})();
|
|
166390
|
+
}
|
|
165712
166391
|
function setPersistedReasoningWatermark(db, sessionId, tagNumber) {
|
|
165713
166392
|
ensureSessionMetaRow(db, sessionId);
|
|
165714
166393
|
db.prepare("UPDATE session_meta SET cleared_reasoning_through_tag = ? WHERE session_id = ?").run(tagNumber, sessionId);
|
|
@@ -165716,27 +166395,95 @@ function setPersistedReasoningWatermark(db, sessionId, tagNumber) {
|
|
|
165716
166395
|
function clearPersistedReasoningWatermark(db, sessionId) {
|
|
165717
166396
|
setPersistedReasoningWatermark(db, sessionId, 0);
|
|
165718
166397
|
}
|
|
165719
|
-
function
|
|
165720
|
-
|
|
165721
|
-
|
|
165722
|
-
|
|
165723
|
-
|
|
165724
|
-
|
|
165725
|
-
|
|
165726
|
-
|
|
165727
|
-
|
|
165728
|
-
|
|
165729
|
-
|
|
165730
|
-
};
|
|
166398
|
+
function isEmergencyInputSampleRow(row) {
|
|
166399
|
+
return typeof row === "object" && row !== null && typeof row.last_emergency_input_sample === "number";
|
|
166400
|
+
}
|
|
166401
|
+
function getEmergencyInputSample(db, sessionId) {
|
|
166402
|
+
const result = db.prepare("SELECT last_emergency_input_sample FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166403
|
+
return isEmergencyInputSampleRow(result) ? result.last_emergency_input_sample : 0;
|
|
166404
|
+
}
|
|
166405
|
+
function setEmergencyDropSample(db, sessionId, inputSample) {
|
|
166406
|
+
db.transaction(() => {
|
|
166407
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166408
|
+
db.prepare("UPDATE session_meta SET last_emergency_input_sample = ? WHERE session_id = ?").run(Math.max(0, Math.round(inputSample)), sessionId);
|
|
166409
|
+
})();
|
|
165731
166410
|
}
|
|
165732
|
-
function
|
|
166411
|
+
function clearEmergencyDropSample(db, sessionId) {
|
|
165733
166412
|
db.transaction(() => {
|
|
165734
166413
|
ensureSessionMetaRow(db, sessionId);
|
|
165735
|
-
db.prepare("UPDATE session_meta SET
|
|
166414
|
+
db.prepare("UPDATE session_meta SET last_emergency_input_sample = 0 WHERE session_id = ?").run(sessionId);
|
|
165736
166415
|
})();
|
|
165737
166416
|
}
|
|
165738
|
-
function
|
|
165739
|
-
|
|
166417
|
+
function isLastNudgeUndroppedRow(row) {
|
|
166418
|
+
return typeof row === "object" && row !== null && typeof row.last_nudge_undropped === "number";
|
|
166419
|
+
}
|
|
166420
|
+
function isLastNudgeLevelRow(row) {
|
|
166421
|
+
return typeof row === "object" && row !== null && typeof row.last_nudge_level === "string";
|
|
166422
|
+
}
|
|
166423
|
+
function normalizeLastNudgeLevel(value) {
|
|
166424
|
+
return value === "gentle" || value === "firm" || value === "urgent" ? value : "";
|
|
166425
|
+
}
|
|
166426
|
+
function getLastNudgeUndropped(db, sessionId) {
|
|
166427
|
+
const result = db.prepare("SELECT last_nudge_undropped FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166428
|
+
return isLastNudgeUndroppedRow(result) ? result.last_nudge_undropped : 0;
|
|
166429
|
+
}
|
|
166430
|
+
function setLastNudgeUndropped(db, sessionId, value) {
|
|
166431
|
+
db.transaction(() => {
|
|
166432
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166433
|
+
db.prepare("UPDATE session_meta SET last_nudge_undropped = ? WHERE session_id = ?").run(Math.max(0, Math.round(value)), sessionId);
|
|
166434
|
+
})();
|
|
166435
|
+
}
|
|
166436
|
+
function getLastNudgeLevel(db, sessionId) {
|
|
166437
|
+
const result = db.prepare("SELECT last_nudge_level FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166438
|
+
return isLastNudgeLevelRow(result) ? normalizeLastNudgeLevel(result.last_nudge_level) : "";
|
|
166439
|
+
}
|
|
166440
|
+
function setLastNudgeLevel(db, sessionId, value) {
|
|
166441
|
+
db.transaction(() => {
|
|
166442
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166443
|
+
db.prepare("UPDATE session_meta SET last_nudge_level = ? WHERE session_id = ?").run(normalizeLastNudgeLevel(value), sessionId);
|
|
166444
|
+
})();
|
|
166445
|
+
}
|
|
166446
|
+
function resetLastNudgeCycle(db, sessionId) {
|
|
166447
|
+
db.transaction(() => {
|
|
166448
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166449
|
+
db.prepare("UPDATE session_meta SET last_nudge_undropped = 0, last_nudge_level = '' WHERE session_id = ?").run(sessionId);
|
|
166450
|
+
})();
|
|
166451
|
+
}
|
|
166452
|
+
function resetLastNudgeCycleIfTailShrank(db, sessionId, measuredUndropped) {
|
|
166453
|
+
let changed = false;
|
|
166454
|
+
db.transaction(() => {
|
|
166455
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166456
|
+
const result = db.prepare("UPDATE session_meta SET last_nudge_undropped = 0, last_nudge_level = '' WHERE session_id = ? AND last_nudge_undropped > ?").run(sessionId, Math.max(0, Math.round(measuredUndropped)));
|
|
166457
|
+
changed = (result.changes ?? 0) > 0;
|
|
166458
|
+
})();
|
|
166459
|
+
return changed;
|
|
166460
|
+
}
|
|
166461
|
+
function isChannel2StateRow(row) {
|
|
166462
|
+
return typeof row === "object" && row !== null && typeof row.channel2_nudge_state === "string";
|
|
166463
|
+
}
|
|
166464
|
+
function getChannel2NudgeState(db, sessionId) {
|
|
166465
|
+
const result = db.prepare("SELECT channel2_nudge_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166466
|
+
if (!isChannel2StateRow(result))
|
|
166467
|
+
return "";
|
|
166468
|
+
const raw = result.channel2_nudge_state;
|
|
166469
|
+
return raw === "pending" || raw === "claimed" || raw === "delivered" ? raw : "";
|
|
166470
|
+
}
|
|
166471
|
+
function setChannel2NudgeState(db, sessionId, state) {
|
|
166472
|
+
db.transaction(() => {
|
|
166473
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166474
|
+
const claimedAt = state === "claimed" ? Date.now() : 0;
|
|
166475
|
+
db.prepare("UPDATE session_meta SET channel2_nudge_state = ?, channel2_nudge_claimed_at = ? WHERE session_id = ?").run(state, claimedAt, sessionId);
|
|
166476
|
+
})();
|
|
166477
|
+
}
|
|
166478
|
+
function casChannel2NudgeState(db, sessionId, from, to) {
|
|
166479
|
+
let changed = false;
|
|
166480
|
+
db.transaction(() => {
|
|
166481
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166482
|
+
const claimedAt = to === "claimed" ? Date.now() : 0;
|
|
166483
|
+
const result = db.prepare("UPDATE session_meta SET channel2_nudge_state = ?, channel2_nudge_claimed_at = ? WHERE session_id = ? AND channel2_nudge_state = ?").run(to, claimedAt, sessionId, from);
|
|
166484
|
+
changed = (result.changes ?? 0) > 0;
|
|
166485
|
+
})();
|
|
166486
|
+
return changed;
|
|
165740
166487
|
}
|
|
165741
166488
|
function getPersistedNoteNudge(db, sessionId) {
|
|
165742
166489
|
const result = db.prepare("SELECT note_nudge_trigger_pending, note_nudge_trigger_message_id, note_nudge_sticky_text, note_nudge_sticky_message_id FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
@@ -165783,7 +166530,8 @@ function casUpdateJsonArrayColumn(db, sessionId, column, validator, mutate, opti
|
|
|
165783
166530
|
}
|
|
165784
166531
|
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
165785
166532
|
const row = db.prepare(`SELECT ${column} FROM session_meta WHERE session_id = ?`).get(sessionId);
|
|
165786
|
-
const
|
|
166533
|
+
const rawCurrent = row?.[column] ?? null;
|
|
166534
|
+
const currentBlob = rawCurrent ?? "[]";
|
|
165787
166535
|
const current = parseJsonArray(currentBlob, validator);
|
|
165788
166536
|
const next = mutate(current);
|
|
165789
166537
|
if (next === null)
|
|
@@ -165791,7 +166539,7 @@ function casUpdateJsonArrayColumn(db, sessionId, column, validator, mutate, opti
|
|
|
165791
166539
|
const nextBlob = stableStringify(next);
|
|
165792
166540
|
if (nextBlob === currentBlob)
|
|
165793
166541
|
return true;
|
|
165794
|
-
const result = db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ? AND ${column}
|
|
166542
|
+
const result = db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ? AND ${column} IS ?`).run(nextBlob, sessionId, rawCurrent);
|
|
165795
166543
|
if (result.changes > 0)
|
|
165796
166544
|
return true;
|
|
165797
166545
|
}
|
|
@@ -165920,14 +166668,16 @@ function getHistorianFailureState(db, sessionId) {
|
|
|
165920
166668
|
};
|
|
165921
166669
|
}
|
|
165922
166670
|
function incrementHistorianFailure(db, sessionId, error51) {
|
|
166671
|
+
let nextCount = 1;
|
|
165923
166672
|
db.transaction(() => {
|
|
165924
166673
|
ensureSessionMetaRow(db, sessionId);
|
|
165925
166674
|
const current = getHistorianFailureState(db, sessionId);
|
|
165926
|
-
|
|
166675
|
+
nextCount = current.failureCount + 1;
|
|
165927
166676
|
db.prepare("UPDATE session_meta SET historian_failure_count = ?, historian_last_error = ?, historian_last_failure_at = ? WHERE session_id = ?").run(nextCount, error51, Date.now(), sessionId);
|
|
165928
166677
|
const reason = error51.replace(/\s+/g, " ").trim().slice(0, 300);
|
|
165929
166678
|
sessionLog(sessionId, `historian failure recorded: count=${nextCount} reason="${reason}"`);
|
|
165930
166679
|
})();
|
|
166680
|
+
return nextCount;
|
|
165931
166681
|
}
|
|
165932
166682
|
function clearHistorianFailureState(db, sessionId) {
|
|
165933
166683
|
db.transaction(() => {
|
|
@@ -165957,7 +166707,11 @@ function recordOverflowDetected(db, sessionId, reportedLimit) {
|
|
|
165957
166707
|
function clearEmergencyRecovery(db, sessionId) {
|
|
165958
166708
|
db.transaction(() => {
|
|
165959
166709
|
ensureSessionMetaRow(db, sessionId);
|
|
165960
|
-
|
|
166710
|
+
try {
|
|
166711
|
+
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0, recovery_no_eligible_head_count = 0 WHERE session_id = ?").run(sessionId);
|
|
166712
|
+
} catch {
|
|
166713
|
+
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0 WHERE session_id = ?").run(sessionId);
|
|
166714
|
+
}
|
|
165961
166715
|
})();
|
|
165962
166716
|
}
|
|
165963
166717
|
function clearDetectedContextLimit(db, sessionId) {
|
|
@@ -165996,10 +166750,39 @@ function getStrippedPlaceholderIds(db, sessionId) {
|
|
|
165996
166750
|
} catch {}
|
|
165997
166751
|
return new Set;
|
|
165998
166752
|
}
|
|
165999
|
-
function
|
|
166753
|
+
function applyStrippedPlaceholderDelta(db, sessionId, delta) {
|
|
166754
|
+
const add = delta.add ? [...delta.add] : [];
|
|
166755
|
+
const remove = delta.remove ? [...delta.remove] : [];
|
|
166756
|
+
if (add.length === 0 && remove.length === 0)
|
|
166757
|
+
return true;
|
|
166000
166758
|
ensureSessionMetaRow(db, sessionId);
|
|
166001
|
-
|
|
166002
|
-
|
|
166759
|
+
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
166760
|
+
const row = db.prepare("SELECT stripped_placeholder_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166761
|
+
const rawStored = row ? row.stripped_placeholder_ids ?? null : null;
|
|
166762
|
+
const current = new Set(parseStrippedBlob(rawStored));
|
|
166763
|
+
for (const id of add)
|
|
166764
|
+
current.add(id);
|
|
166765
|
+
for (const id of remove)
|
|
166766
|
+
current.delete(id);
|
|
166767
|
+
const nextBlob = current.size > 0 ? JSON.stringify([...current]) : "";
|
|
166768
|
+
if (nextBlob === (rawStored ?? ""))
|
|
166769
|
+
return true;
|
|
166770
|
+
const result = db.prepare("UPDATE session_meta SET stripped_placeholder_ids = ? WHERE session_id = ? AND stripped_placeholder_ids IS ?").run(nextBlob, sessionId, rawStored);
|
|
166771
|
+
if (result.changes > 0)
|
|
166772
|
+
return true;
|
|
166773
|
+
}
|
|
166774
|
+
sessionLog(sessionId, `stripped_placeholder_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
|
|
166775
|
+
return false;
|
|
166776
|
+
}
|
|
166777
|
+
function parseStrippedBlob(raw) {
|
|
166778
|
+
if (!raw || raw.length === 0)
|
|
166779
|
+
return [];
|
|
166780
|
+
try {
|
|
166781
|
+
const parsed = JSON.parse(raw);
|
|
166782
|
+
if (Array.isArray(parsed))
|
|
166783
|
+
return parsed.filter((v) => typeof v === "string");
|
|
166784
|
+
} catch {}
|
|
166785
|
+
return [];
|
|
166003
166786
|
}
|
|
166004
166787
|
function isPendingCompactionMarker(value) {
|
|
166005
166788
|
return typeof value === "object" && value !== null && typeof value.ordinal === "number" && typeof value.endMessageId === "string" && typeof value.publishedAt === "number";
|
|
@@ -166091,6 +166874,7 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
|
|
|
166091
166874
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
166092
166875
|
|
|
166093
166876
|
// ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
|
|
166877
|
+
init_logger();
|
|
166094
166878
|
function resolveIsSubagentFromOpenCodeDb(sessionId) {
|
|
166095
166879
|
try {
|
|
166096
166880
|
return withReadOnlySessionDb((openCodeDb) => {
|
|
@@ -166309,7 +167093,8 @@ function updateNote(db, noteId, updates, scope) {
|
|
|
166309
167093
|
sets.push("session_id = ?");
|
|
166310
167094
|
params.push(updates.sessionId);
|
|
166311
167095
|
}
|
|
166312
|
-
|
|
167096
|
+
const smartConditionChanged = existing.type === "smart" && updates.surfaceCondition !== undefined && updates.surfaceCondition !== existing.surfaceCondition;
|
|
167097
|
+
if (updates.status !== undefined && !smartConditionChanged) {
|
|
166313
167098
|
sets.push("status = ?");
|
|
166314
167099
|
params.push(updates.status);
|
|
166315
167100
|
}
|
|
@@ -166322,17 +167107,21 @@ function updateNote(db, noteId, updates, scope) {
|
|
|
166322
167107
|
sets.push("surface_condition = ?");
|
|
166323
167108
|
params.push(updates.surfaceCondition);
|
|
166324
167109
|
}
|
|
166325
|
-
if (
|
|
166326
|
-
sets.push("last_checked_at =
|
|
166327
|
-
|
|
166328
|
-
|
|
166329
|
-
|
|
166330
|
-
|
|
166331
|
-
|
|
166332
|
-
|
|
166333
|
-
|
|
166334
|
-
|
|
166335
|
-
|
|
167110
|
+
if (smartConditionChanged) {
|
|
167111
|
+
sets.push("status = 'pending'", "last_checked_at = NULL", "ready_at = NULL", "ready_reason = NULL");
|
|
167112
|
+
} else {
|
|
167113
|
+
if (updates.lastCheckedAt !== undefined) {
|
|
167114
|
+
sets.push("last_checked_at = ?");
|
|
167115
|
+
params.push(updates.lastCheckedAt);
|
|
167116
|
+
}
|
|
167117
|
+
if (updates.readyAt !== undefined) {
|
|
167118
|
+
sets.push("ready_at = ?");
|
|
167119
|
+
params.push(updates.readyAt);
|
|
167120
|
+
}
|
|
167121
|
+
if (updates.readyReason !== undefined) {
|
|
167122
|
+
sets.push("ready_reason = ?");
|
|
167123
|
+
params.push(updates.readyReason);
|
|
167124
|
+
}
|
|
166336
167125
|
}
|
|
166337
167126
|
}
|
|
166338
167127
|
if (sets.length === 1) {
|
|
@@ -166359,6 +167148,7 @@ function markNoteChecked(db, noteId) {
|
|
|
166359
167148
|
db.prepare("UPDATE notes SET last_checked_at = ?, updated_at = ? WHERE id = ? AND type = 'smart'").run(now, now, noteId);
|
|
166360
167149
|
}
|
|
166361
167150
|
// ../plugin/src/features/magic-context/storage-ops.ts
|
|
167151
|
+
init_logger();
|
|
166362
167152
|
var queuePendingOpStatements = new WeakMap;
|
|
166363
167153
|
var getPendingOpsStatements = new WeakMap;
|
|
166364
167154
|
var clearPendingOpsStatements = new WeakMap;
|
|
@@ -166521,7 +167311,7 @@ var getTagNumberByMessageIdStatements = new WeakMap;
|
|
|
166521
167311
|
function getInsertTagStatement(db) {
|
|
166522
167312
|
let stmt = insertTagStatements.get(db);
|
|
166523
167313
|
if (!stmt) {
|
|
166524
|
-
stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, reasoning_byte_size, tag_number, tool_name, input_byte_size, harness, tool_owner_message_id, entry_fingerprint) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
167314
|
+
stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, reasoning_byte_size, tag_number, tool_name, input_byte_size, harness, tool_owner_message_id, entry_fingerprint, token_count, input_token_count, reasoning_token_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
166525
167315
|
insertTagStatements.set(db, stmt);
|
|
166526
167316
|
}
|
|
166527
167317
|
return stmt;
|
|
@@ -166563,9 +167353,95 @@ function getUpdateTagInputByteSizeStatement(db) {
|
|
|
166563
167353
|
function updateTagByteSize(db, sessionId, tagNumber, newByteSize) {
|
|
166564
167354
|
getUpdateTagByteSizeStatement(db).run(newByteSize, sessionId, tagNumber);
|
|
166565
167355
|
}
|
|
167356
|
+
var CONTENT_ID_SUFFIX = /:(?:p|file)\d+$/;
|
|
167357
|
+
function ownerMessageIdForTagRow(row) {
|
|
167358
|
+
if (row.type === "tool") {
|
|
167359
|
+
return row.tool_owner_message_id ?? row.message_id;
|
|
167360
|
+
}
|
|
167361
|
+
return row.message_id.replace(CONTENT_ID_SUFFIX, "");
|
|
167362
|
+
}
|
|
167363
|
+
function getActiveTagTokenAggregate(db, sessionId) {
|
|
167364
|
+
const row = db.prepare(`SELECT
|
|
167365
|
+
COALESCE(SUM(CASE WHEN type != 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)
|
|
167366
|
+
+ COALESCE(SUM(COALESCE(reasoning_token_count, 0)), 0) AS conversation,
|
|
167367
|
+
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) + COALESCE(input_token_count, 0) ELSE 0 END), 0) AS tool_call,
|
|
167368
|
+
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0) AS tool_output,
|
|
167369
|
+
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
167370
|
+
FROM tags
|
|
167371
|
+
WHERE session_id = ? AND status = 'active'`).get(sessionId);
|
|
167372
|
+
return {
|
|
167373
|
+
conversation: row?.conversation ?? 0,
|
|
167374
|
+
toolCall: row?.tool_call ?? 0,
|
|
167375
|
+
toolOutput: row?.tool_output ?? 0,
|
|
167376
|
+
nullCount: row?.null_count ?? 0
|
|
167377
|
+
};
|
|
167378
|
+
}
|
|
167379
|
+
function getTriggerTagTokenUpperBound(db, sessionId) {
|
|
167380
|
+
const row = db.prepare(`SELECT
|
|
167381
|
+
COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
|
|
167382
|
+
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
167383
|
+
FROM tags
|
|
167384
|
+
WHERE session_id = ? AND status IN ('active', 'dropped')`).get(sessionId);
|
|
167385
|
+
return { bound: row?.bound ?? 0, nullCount: row?.null_count ?? 0 };
|
|
167386
|
+
}
|
|
166566
167387
|
function updateTagInputByteSize(db, sessionId, tagNumber, newInputByteSize) {
|
|
166567
167388
|
getUpdateTagInputByteSizeStatement(db).run(newInputByteSize, sessionId, tagNumber);
|
|
166568
167389
|
}
|
|
167390
|
+
var updateTagTokenCountStatements = new WeakMap;
|
|
167391
|
+
var updateTagInputTokenCountStatements = new WeakMap;
|
|
167392
|
+
function getUpdateTagTokenCountStatement(db) {
|
|
167393
|
+
let stmt = updateTagTokenCountStatements.get(db);
|
|
167394
|
+
if (!stmt) {
|
|
167395
|
+
stmt = db.prepare("UPDATE tags SET token_count = ? WHERE session_id = ? AND tag_number = ?");
|
|
167396
|
+
updateTagTokenCountStatements.set(db, stmt);
|
|
167397
|
+
}
|
|
167398
|
+
return stmt;
|
|
167399
|
+
}
|
|
167400
|
+
function getUpdateTagInputTokenCountStatement(db) {
|
|
167401
|
+
let stmt = updateTagInputTokenCountStatements.get(db);
|
|
167402
|
+
if (!stmt) {
|
|
167403
|
+
stmt = db.prepare("UPDATE tags SET input_token_count = ? WHERE session_id = ? AND tag_number = ?");
|
|
167404
|
+
updateTagInputTokenCountStatements.set(db, stmt);
|
|
167405
|
+
}
|
|
167406
|
+
return stmt;
|
|
167407
|
+
}
|
|
167408
|
+
function updateTagTokenCount(db, sessionId, tagNumber, newTokenCount) {
|
|
167409
|
+
getUpdateTagTokenCountStatement(db).run(newTokenCount, sessionId, tagNumber);
|
|
167410
|
+
}
|
|
167411
|
+
function getAllStatusTagTokenTotalsFlat(db, sessionId) {
|
|
167412
|
+
const rows = db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
167413
|
+
FROM tags
|
|
167414
|
+
WHERE session_id = ?`).all(sessionId);
|
|
167415
|
+
const totals = new Map;
|
|
167416
|
+
const nullMessageIds = new Set;
|
|
167417
|
+
for (const row of rows) {
|
|
167418
|
+
if (row.type === "tool" && row.tool_owner_message_id === null)
|
|
167419
|
+
continue;
|
|
167420
|
+
const owner = ownerMessageIdForTagRow(row);
|
|
167421
|
+
if (row.token_count === null) {
|
|
167422
|
+
nullMessageIds.add(owner);
|
|
167423
|
+
totals.delete(owner);
|
|
167424
|
+
continue;
|
|
167425
|
+
}
|
|
167426
|
+
if (nullMessageIds.has(owner))
|
|
167427
|
+
continue;
|
|
167428
|
+
const weight = (row.token_count ?? 0) + (row.input_token_count ?? 0) + (row.reasoning_token_count ?? 0);
|
|
167429
|
+
totals.set(owner, (totals.get(owner) ?? 0) + weight);
|
|
167430
|
+
}
|
|
167431
|
+
return { totals, nullMessageIds };
|
|
167432
|
+
}
|
|
167433
|
+
function updateTagInputTokenCount(db, sessionId, tagNumber, newInputTokenCount) {
|
|
167434
|
+
getUpdateTagInputTokenCountStatement(db).run(newInputTokenCount, sessionId, tagNumber);
|
|
167435
|
+
}
|
|
167436
|
+
function tagTokenCountIsNull(db, sessionId, tagNumber) {
|
|
167437
|
+
const row = db.prepare("SELECT token_count FROM tags WHERE session_id = ? AND tag_number = ?").get(sessionId, tagNumber);
|
|
167438
|
+
return row !== undefined && row.token_count === null;
|
|
167439
|
+
}
|
|
167440
|
+
function backfillTagTokenCounts(db, sessionId, tagNumber, counts) {
|
|
167441
|
+
db.prepare(`UPDATE tags
|
|
167442
|
+
SET token_count = ?, input_token_count = ?, reasoning_token_count = ?
|
|
167443
|
+
WHERE session_id = ? AND tag_number = ? AND token_count IS NULL`).run(counts.tokenCount ?? null, counts.inputTokenCount ?? null, counts.reasoningTokenCount ?? null, sessionId, tagNumber);
|
|
167444
|
+
}
|
|
166569
167445
|
function getMaxTagNumberBySessionStatement(db) {
|
|
166570
167446
|
let stmt = getMaxTagNumberBySessionStatements.get(db);
|
|
166571
167447
|
if (!stmt) {
|
|
@@ -166618,8 +167494,8 @@ function isMaxTagNumberRow(row) {
|
|
|
166618
167494
|
const r = row;
|
|
166619
167495
|
return typeof r.max_tag_number === "number";
|
|
166620
167496
|
}
|
|
166621
|
-
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0, toolOwnerMessageId = null, entryFingerprint = null) {
|
|
166622
|
-
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness(), toolOwnerMessageId, entryFingerprint);
|
|
167497
|
+
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0, toolOwnerMessageId = null, entryFingerprint = null, tokenCounts = null) {
|
|
167498
|
+
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness(), toolOwnerMessageId, entryFingerprint, tokenCounts?.tokenCount ?? null, tokenCounts?.inputTokenCount ?? null, tokenCounts?.reasoningTokenCount ?? null);
|
|
166623
167499
|
return tagNumber;
|
|
166624
167500
|
}
|
|
166625
167501
|
function updateTagStatus(db, sessionId, tagId, status) {
|
|
@@ -166687,13 +167563,6 @@ function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
|
166687
167563
|
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${placeholders}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
|
|
166688
167564
|
return rows.map(toTagEntry);
|
|
166689
167565
|
}
|
|
166690
|
-
function getTopNBySize(db, sessionId, n) {
|
|
166691
|
-
if (n <= 0) {
|
|
166692
|
-
return [];
|
|
166693
|
-
}
|
|
166694
|
-
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND status = 'active' ORDER BY byte_size DESC, tag_number ASC LIMIT ?`).all(sessionId, n).filter(isTagRow);
|
|
166695
|
-
return rows.map(toTagEntry);
|
|
166696
|
-
}
|
|
166697
167566
|
var getToolTagNumberByOwnerStatements = new WeakMap;
|
|
166698
167567
|
var getNullOwnerToolTagStatements = new WeakMap;
|
|
166699
167568
|
var adoptNullOwnerToolTagStatements = new WeakMap;
|
|
@@ -166759,44 +167628,43 @@ var ERROR_CLASSES = new Set([
|
|
|
166759
167628
|
"permission_denied",
|
|
166760
167629
|
"unknown"
|
|
166761
167630
|
]);
|
|
167631
|
+
// src/tools/ctx-memory.ts
|
|
167632
|
+
init_logger();
|
|
167633
|
+
|
|
167634
|
+
// ../plugin/src/tools/ctx-memory/constants.ts
|
|
167635
|
+
var CTX_MEMORY_DESCRIPTION = `Durable project knowledge shared across every session on this project.
|
|
167636
|
+
|
|
167637
|
+
Your active memories are already visible in <project-memory> (each with its id), and every future session starts with them — write one when you learn something future sessions must know: a project rule, an architectural fact, a hard-won constraint, a config value, or a naming convention. Keep each memory one standalone fact, phrased to make sense without this session's context.
|
|
167638
|
+
|
|
167639
|
+
Actions:
|
|
167640
|
+
- write: save a new memory (content + category).
|
|
167641
|
+
- update: rewrite one memory whose fact changed (ids: [one], content).
|
|
167642
|
+
- archive: retire wrong or obsolete memories (ids: [one or more], optional reason).
|
|
167643
|
+
- merge: collapse duplicates into one memory (ids: [two or more], content).
|
|
167644
|
+
|
|
167645
|
+
Example: ctx_memory(action="write", category="CONSTRAINTS", content="Pi stores sessions as JSONL under ~/.pi/agent/sessions/, not SQLite")`;
|
|
167646
|
+
|
|
166762
167647
|
// src/tools/ctx-memory.ts
|
|
166763
167648
|
var DEFAULT_LIST_LIMIT = 10;
|
|
166764
|
-
var
|
|
166765
|
-
|
|
166766
|
-
return VALID_CATEGORIES.has(value);
|
|
166767
|
-
}
|
|
166768
|
-
var ALL_ACTIONS = [
|
|
166769
|
-
"write",
|
|
166770
|
-
"delete",
|
|
166771
|
-
"list",
|
|
166772
|
-
"update",
|
|
166773
|
-
"merge",
|
|
166774
|
-
"archive"
|
|
166775
|
-
];
|
|
166776
|
-
var DREAMER_ONLY_ACTIONS = new Set([
|
|
166777
|
-
"list",
|
|
166778
|
-
"update",
|
|
166779
|
-
"merge",
|
|
166780
|
-
"archive"
|
|
166781
|
-
]);
|
|
167649
|
+
var ALL_ACTIONS = ["write", "archive", "update", "merge", "list"];
|
|
167650
|
+
var DREAMER_ONLY_ACTIONS = new Set(["list"]);
|
|
166782
167651
|
var ParamsSchema2 = exports_typebox.Object({
|
|
166783
|
-
action: exports_typebox.Union(ALL_ACTIONS.map((a) => exports_typebox.Literal(a)), { description: "
|
|
167652
|
+
action: exports_typebox.Union(ALL_ACTIONS.map((a) => exports_typebox.Literal(a)), { description: "What to do: write, update, archive, or merge" }),
|
|
166784
167653
|
content: exports_typebox.Optional(exports_typebox.String({
|
|
166785
|
-
description: "
|
|
166786
|
-
})),
|
|
166787
|
-
category: exports_typebox.Optional(exports_typebox.String({
|
|
166788
|
-
description: "Memory category (required for write, optional filter for list, optional override for merge). One of: " + CATEGORY_PRIORITY.join(", ")
|
|
167654
|
+
description: "The memory text — one standalone fact (required for write, update, merge)"
|
|
166789
167655
|
})),
|
|
166790
|
-
|
|
166791
|
-
description: "
|
|
167656
|
+
category: exports_typebox.Optional(exports_typebox.Union(V2_MEMORY_CATEGORIES.map((c) => exports_typebox.Literal(c)), {
|
|
167657
|
+
description: "What kind of fact this is (required for write; optional merge override)"
|
|
166792
167658
|
})),
|
|
166793
167659
|
ids: exports_typebox.Optional(exports_typebox.Array(exports_typebox.Number(), {
|
|
166794
|
-
description: "
|
|
167660
|
+
description: "Target memory id(s) from <project-memory>: update takes exactly one, archive one or more, merge two or more"
|
|
166795
167661
|
})),
|
|
166796
167662
|
limit: exports_typebox.Optional(exports_typebox.Number({
|
|
166797
|
-
description: "
|
|
167663
|
+
description: "Max results for list (default: 10)"
|
|
166798
167664
|
})),
|
|
166799
|
-
reason: exports_typebox.Optional(exports_typebox.String({
|
|
167665
|
+
reason: exports_typebox.Optional(exports_typebox.String({
|
|
167666
|
+
description: "Why the memory is being archived (optional, recommended)"
|
|
167667
|
+
}))
|
|
166800
167668
|
});
|
|
166801
167669
|
function ok2(text) {
|
|
166802
167670
|
return { content: [{ type: "text", text }], details: undefined };
|
|
@@ -166843,6 +167711,12 @@ function formatMemoryList(memories) {
|
|
|
166843
167711
|
].join(`
|
|
166844
167712
|
`);
|
|
166845
167713
|
}
|
|
167714
|
+
function isPrimaryMutableMemory(memory2) {
|
|
167715
|
+
return (memory2.status === "active" || memory2.status === "permanent") && memory2.supersededByMemoryId === null;
|
|
167716
|
+
}
|
|
167717
|
+
function inactiveMemoryError(id, action2) {
|
|
167718
|
+
return `Error: Memory with ID ${id} is archived or superseded; restore it before ${action2}.`;
|
|
167719
|
+
}
|
|
166846
167720
|
function queueEmbedding(args) {
|
|
166847
167721
|
const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
166848
167722
|
if (!snapshot?.enabled)
|
|
@@ -166863,7 +167737,8 @@ function queueEmbedding(args) {
|
|
|
166863
167737
|
}
|
|
166864
167738
|
function createCtxMemoryTool(deps) {
|
|
166865
167739
|
const dreamerAllowed = deps.allowDreamerActions === true;
|
|
166866
|
-
const description = dreamerAllowed ?
|
|
167740
|
+
const description = dreamerAllowed ? `${CTX_MEMORY_DESCRIPTION}
|
|
167741
|
+
- list: enumerate stored memories (maintenance sessions).` : CTX_MEMORY_DESCRIPTION;
|
|
166867
167742
|
return {
|
|
166868
167743
|
name: "ctx_memory",
|
|
166869
167744
|
label: "Magic Context: Memory",
|
|
@@ -166884,13 +167759,10 @@ function createCtxMemoryTool(deps) {
|
|
|
166884
167759
|
const content = params.content?.trim();
|
|
166885
167760
|
if (!content)
|
|
166886
167761
|
return err2("Error: 'content' is required when action is 'write'.");
|
|
166887
|
-
const rawCategory = params.category
|
|
167762
|
+
const rawCategory = params.category;
|
|
166888
167763
|
if (!rawCategory) {
|
|
166889
167764
|
return err2("Error: 'category' is required when action is 'write'.");
|
|
166890
167765
|
}
|
|
166891
|
-
if (!isMemoryCategory2(rawCategory)) {
|
|
166892
|
-
return err2(`Error: Unknown memory category '${rawCategory}'. Valid: ${CATEGORY_PRIORITY.join(", ")}`);
|
|
166893
|
-
}
|
|
166894
167766
|
const existing = getMemoryByHash(deps.db, projectIdentity, rawCategory, computeNormalizedHash(content));
|
|
166895
167767
|
if (existing) {
|
|
166896
167768
|
updateMemorySeenCount(deps.db, existing.id);
|
|
@@ -166904,45 +167776,31 @@ function createCtxMemoryTool(deps) {
|
|
|
166904
167776
|
sourceType: dreamerAllowed ? "dreamer" : "agent"
|
|
166905
167777
|
});
|
|
166906
167778
|
queueEmbedding({ deps, projectIdentity, memoryId: memory2.id, content });
|
|
166907
|
-
invalidateAllMemoryBlockCaches(deps.db);
|
|
166908
167779
|
return ok2(`Saved memory [ID: ${memory2.id}] in ${rawCategory}.`);
|
|
166909
167780
|
}
|
|
166910
|
-
if (params.action === "delete") {
|
|
166911
|
-
if (typeof params.id !== "number" || !Number.isInteger(params.id)) {
|
|
166912
|
-
return err2("Error: 'id' is required when action is 'delete'.");
|
|
166913
|
-
}
|
|
166914
|
-
const memory2 = getMemoryById(deps.db, params.id);
|
|
166915
|
-
if (!memory2 || memory2.projectPath !== projectIdentity) {
|
|
166916
|
-
return err2(`Error: Memory with ID ${params.id} was not found.`);
|
|
166917
|
-
}
|
|
166918
|
-
deps.db.transaction(() => {
|
|
166919
|
-
archiveMemory(deps.db, params.id);
|
|
166920
|
-
queueMemoryMutation(deps.db, {
|
|
166921
|
-
projectPath: projectIdentity,
|
|
166922
|
-
mutationType: "delete",
|
|
166923
|
-
targetMemoryId: params.id
|
|
166924
|
-
});
|
|
166925
|
-
})();
|
|
166926
|
-
return ok2(`Archived memory [ID: ${params.id}].`);
|
|
166927
|
-
}
|
|
166928
167781
|
if (params.action === "list") {
|
|
166929
167782
|
const limit = normalizeLimit(params.limit);
|
|
166930
167783
|
const filtered = getMemoriesByProject(deps.db, projectIdentity);
|
|
166931
|
-
const category = params.category
|
|
167784
|
+
const category = params.category;
|
|
166932
167785
|
const filtered2 = category ? filtered.filter((m) => m.category === category) : filtered;
|
|
166933
167786
|
return ok2(formatMemoryList(filtered2.slice(0, limit)));
|
|
166934
167787
|
}
|
|
166935
167788
|
if (params.action === "update") {
|
|
166936
|
-
|
|
166937
|
-
|
|
167789
|
+
const updateIds = params.ids;
|
|
167790
|
+
if (!updateIds || updateIds.length !== 1 || !updateIds.every(Number.isInteger)) {
|
|
167791
|
+
return err2("Error: 'ids' must contain exactly one integer memory ID when action is 'update'.");
|
|
166938
167792
|
}
|
|
167793
|
+
const updateId = updateIds[0];
|
|
166939
167794
|
const content = params.content?.trim();
|
|
166940
167795
|
if (!content) {
|
|
166941
167796
|
return err2("Error: 'content' is required when action is 'update'.");
|
|
166942
167797
|
}
|
|
166943
|
-
const memory2 = getMemoryById(deps.db,
|
|
166944
|
-
if (!memory2 || memory2.projectPath
|
|
166945
|
-
return err2(`Error: Memory with ID ${
|
|
167798
|
+
const memory2 = getMemoryById(deps.db, updateId);
|
|
167799
|
+
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
167800
|
+
return err2(`Error: Memory with ID ${updateId} was not found.`);
|
|
167801
|
+
}
|
|
167802
|
+
if (!dreamerAllowed && !isPrimaryMutableMemory(memory2)) {
|
|
167803
|
+
return err2(inactiveMemoryError(updateId, "updating"));
|
|
166946
167804
|
}
|
|
166947
167805
|
const normalizedHash = computeNormalizedHash(content);
|
|
166948
167806
|
const duplicate = getMemoryByHash(deps.db, projectIdentity, memory2.category, normalizedHash);
|
|
@@ -166963,9 +167821,12 @@ function createCtxMemoryTool(deps) {
|
|
|
166963
167821
|
return ok2(`Updated memory [ID: ${memory2.id}] in ${memory2.category}.`);
|
|
166964
167822
|
}
|
|
166965
167823
|
if (params.action === "merge") {
|
|
166966
|
-
const ids = params.ids
|
|
166967
|
-
if (!ids || ids.length < 2) {
|
|
166968
|
-
return err2("Error: 'ids' must include at least two memory IDs when action is 'merge'.");
|
|
167824
|
+
const ids = params.ids;
|
|
167825
|
+
if (!ids || ids.length < 2 || !ids.every(Number.isInteger)) {
|
|
167826
|
+
return err2("Error: 'ids' must include at least two integer memory IDs when action is 'merge'.");
|
|
167827
|
+
}
|
|
167828
|
+
if (new Set(ids).size !== ids.length) {
|
|
167829
|
+
return err2("Error: 'ids' must include at least two distinct memory IDs when action is 'merge'.");
|
|
166969
167830
|
}
|
|
166970
167831
|
const content = params.content?.trim();
|
|
166971
167832
|
if (!content) {
|
|
@@ -166975,14 +167836,17 @@ function createCtxMemoryTool(deps) {
|
|
|
166975
167836
|
if (sourceMemories.length !== ids.length) {
|
|
166976
167837
|
return err2("Error: One or more source memories were not found.");
|
|
166977
167838
|
}
|
|
166978
|
-
if (
|
|
166979
|
-
|
|
166980
|
-
|
|
166981
|
-
|
|
166982
|
-
|
|
166983
|
-
|
|
167839
|
+
if (!dreamerAllowed) {
|
|
167840
|
+
const foreign = sourceMemories.find((memory2) => !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity));
|
|
167841
|
+
if (foreign) {
|
|
167842
|
+
return err2(`Error: Memory with ID ${foreign.id} was not found.`);
|
|
167843
|
+
}
|
|
167844
|
+
const inactive = sourceMemories.find((memory2) => !isPrimaryMutableMemory(memory2));
|
|
167845
|
+
if (inactive) {
|
|
167846
|
+
return err2(inactiveMemoryError(inactive.id, "merging"));
|
|
167847
|
+
}
|
|
166984
167848
|
}
|
|
166985
|
-
const requestedCategoryTyped =
|
|
167849
|
+
const requestedCategoryTyped = params.category;
|
|
166986
167850
|
const fallbackCategory = sourceMemories[0]?.category;
|
|
166987
167851
|
const category = requestedCategoryTyped ?? fallbackCategory;
|
|
166988
167852
|
if (!category) {
|
|
@@ -167036,7 +167900,7 @@ function createCtxMemoryTool(deps) {
|
|
|
167036
167900
|
}
|
|
167037
167901
|
supersededMemory(deps.db, memory2.id, canonicalMemory.id);
|
|
167038
167902
|
queueMemoryMutation(deps.db, {
|
|
167039
|
-
projectPath: memory2.projectPath,
|
|
167903
|
+
projectPath: normalizeStoredProjectPath(memory2.projectPath),
|
|
167040
167904
|
mutationType: "superseded",
|
|
167041
167905
|
targetMemoryId: memory2.id,
|
|
167042
167906
|
supersededById: canonicalMemory.id
|
|
@@ -167044,7 +167908,7 @@ function createCtxMemoryTool(deps) {
|
|
|
167044
167908
|
}
|
|
167045
167909
|
if (canonicalExisting && canonicalContentChanged) {
|
|
167046
167910
|
queueMemoryMutation(deps.db, {
|
|
167047
|
-
projectPath: canonicalMemory.projectPath,
|
|
167911
|
+
projectPath: normalizeStoredProjectPath(canonicalMemory.projectPath),
|
|
167048
167912
|
mutationType: "update",
|
|
167049
167913
|
targetMemoryId: canonicalMemory.id,
|
|
167050
167914
|
category,
|
|
@@ -167062,29 +167926,57 @@ function createCtxMemoryTool(deps) {
|
|
|
167062
167926
|
return ok2(`Merged memories [${ids.join(", ")}] into canonical memory [ID: ${canonicalMemory.id}] in ${category}; superseded [${supersededIds.join(", ")}].`);
|
|
167063
167927
|
}
|
|
167064
167928
|
if (params.action === "archive") {
|
|
167065
|
-
|
|
167066
|
-
|
|
167929
|
+
const archiveIds = params.ids;
|
|
167930
|
+
if (!archiveIds || archiveIds.length === 0 || !archiveIds.every(Number.isInteger)) {
|
|
167931
|
+
return err2("Error: 'ids' must contain at least one integer memory ID when action is 'archive'.");
|
|
167067
167932
|
}
|
|
167068
|
-
const
|
|
167069
|
-
|
|
167070
|
-
|
|
167933
|
+
for (const memoryId of archiveIds) {
|
|
167934
|
+
const memory2 = getMemoryById(deps.db, memoryId);
|
|
167935
|
+
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
167936
|
+
return err2(`Error: Memory with ID ${memoryId} was not found.`);
|
|
167937
|
+
}
|
|
167938
|
+
if (!dreamerAllowed && !isPrimaryMutableMemory(memory2)) {
|
|
167939
|
+
return err2(inactiveMemoryError(memoryId, "archiving"));
|
|
167940
|
+
}
|
|
167071
167941
|
}
|
|
167072
167942
|
deps.db.transaction(() => {
|
|
167073
|
-
|
|
167074
|
-
|
|
167075
|
-
|
|
167076
|
-
|
|
167077
|
-
|
|
167078
|
-
|
|
167943
|
+
for (const memoryId of archiveIds) {
|
|
167944
|
+
archiveMemory(deps.db, memoryId, params.reason);
|
|
167945
|
+
queueMemoryMutation(deps.db, {
|
|
167946
|
+
projectPath: projectIdentity,
|
|
167947
|
+
mutationType: "archive",
|
|
167948
|
+
targetMemoryId: memoryId
|
|
167949
|
+
});
|
|
167950
|
+
}
|
|
167079
167951
|
})();
|
|
167080
167952
|
const reasonSuffix = params.reason ? ` (${params.reason})` : "";
|
|
167081
|
-
|
|
167953
|
+
const idList = archiveIds.join(", ");
|
|
167954
|
+
const plural = archiveIds.length > 1 ? "memories" : "memory";
|
|
167955
|
+
return ok2(`Archived ${plural} [ID: ${idList}]${reasonSuffix}.`);
|
|
167082
167956
|
}
|
|
167083
167957
|
return err2("Error: Unknown action.");
|
|
167084
167958
|
}
|
|
167085
167959
|
};
|
|
167086
167960
|
}
|
|
167087
167961
|
|
|
167962
|
+
// ../plugin/src/tools/ctx-note/constants.ts
|
|
167963
|
+
var CTX_NOTE_DESCRIPTION = `Working notes for this session's future — reminders, follow-ups, and things to revisit later.
|
|
167964
|
+
|
|
167965
|
+
Use a note when something matters LATER but not in the next few steps: "revisit the retry logic after the release", "user wants the dashboard polish batched", "flaky test to investigate when touching CI". Don't use notes for active multi-step work (use todos) or for durable project knowledge that should outlive this session (use ctx_memory). Notes resurface automatically at natural work boundaries and whenever you read them.
|
|
167966
|
+
|
|
167967
|
+
Actions:
|
|
167968
|
+
- write: save a note (content). Add surface_condition to make it a smart note (below).
|
|
167969
|
+
- read: list notes, newest first. Default: latest active session notes + ready smart notes; page older ones with limit/offset, or inspect other states with filter.
|
|
167970
|
+
- update / dismiss: change or retire a note by note_id.
|
|
167971
|
+
|
|
167972
|
+
Smart notes: pass surface_condition and the note stays hidden until a background checker confirms the condition — using ONLY externally verifiable signals (GitHub state via gh, files on disk, git history, web pages). It cannot see this conversation, so the condition must be checkable from outside:
|
|
167973
|
+
✓ "When PR #42 in cortexkit/magic-context is merged"
|
|
167974
|
+
✓ "When the latest release tag is >= v0.22.0"
|
|
167975
|
+
✓ "When packages/plugin/src/foo.ts contains a function named bar"
|
|
167976
|
+
✗ "When the user mentions X" / "when we revisit Y" / "after we finish this refactor" — no external signal; write a regular note instead.
|
|
167977
|
+
|
|
167978
|
+
Example: ctx_note(action="write", content="Re-run the perf benchmark once the boundary rework ships", surface_condition="When the latest release tag is >= v0.23.0")`;
|
|
167979
|
+
|
|
167088
167980
|
// src/tools/ctx-note.ts
|
|
167089
167981
|
var FILTER_VALUES = [
|
|
167090
167982
|
"active",
|
|
@@ -167104,13 +167996,19 @@ var ParamsSchema3 = exports_typebox.Object({
|
|
|
167104
167996
|
})),
|
|
167105
167997
|
content: exports_typebox.Optional(exports_typebox.String({ description: "Note text to store when action is 'write'." })),
|
|
167106
167998
|
surface_condition: exports_typebox.Optional(exports_typebox.String({
|
|
167107
|
-
description: "
|
|
167999
|
+
description: "Externally verifiable condition for smart notes. A background checker verifies it using ONLY outside signals (GitHub state via gh, files on disk, git history, web) — it cannot see this conversation. Use for PR/issue state, release tags, file contents, workflow runs. NOT for 'when the user mentions X' / 'when we revisit Y' — write a regular note instead."
|
|
167108
168000
|
})),
|
|
167109
168001
|
note_id: exports_typebox.Optional(exports_typebox.Number({
|
|
167110
168002
|
description: "Note ID (required for 'dismiss' and 'update' actions)."
|
|
167111
168003
|
})),
|
|
167112
168004
|
filter: exports_typebox.Optional(exports_typebox.Union(FILTER_VALUES.map((value) => exports_typebox.Literal(value)), {
|
|
167113
168005
|
description: "Optional read filter. Defaults to active session notes + ready smart notes. Use 'all' to inspect every status or 'pending' to inspect unsurfaced smart notes."
|
|
168006
|
+
})),
|
|
168007
|
+
limit: exports_typebox.Optional(exports_typebox.Number({
|
|
168008
|
+
description: "Max notes per section for read, newest first (default: 25)"
|
|
168009
|
+
})),
|
|
168010
|
+
offset: exports_typebox.Optional(exports_typebox.Number({
|
|
168011
|
+
description: "Skip this many newest notes for read — page older ones (default: 0)"
|
|
167114
168012
|
}))
|
|
167115
168013
|
});
|
|
167116
168014
|
function ok3(text) {
|
|
@@ -167147,15 +168045,20 @@ function formatNoteLine(note) {
|
|
|
167147
168045
|
var DISMISS_FOOTER = `
|
|
167148
168046
|
|
|
167149
168047
|
To dismiss a stale note: ctx_note(action="dismiss", note_id=N)`;
|
|
168048
|
+
var DEFAULT_READ_LIMIT = 25;
|
|
168049
|
+
function paginateNewestFirst(notes, limit, offset) {
|
|
168050
|
+
const total = notes.length;
|
|
168051
|
+
const newestFirst = [...notes].reverse();
|
|
168052
|
+
const page = newestFirst.slice(offset, offset + limit);
|
|
168053
|
+
const remaining = total - offset - page.length;
|
|
168054
|
+
const footer = remaining > 0 ? `Showing ${page.length} of ${total} (newest first) — ${remaining} older: ctx_note(action="read", offset=${offset + page.length})` : null;
|
|
168055
|
+
return { page, total, footer };
|
|
168056
|
+
}
|
|
167150
168057
|
function createCtxNoteTool(deps) {
|
|
167151
168058
|
return {
|
|
167152
168059
|
name: "ctx_note",
|
|
167153
168060
|
label: "Magic Context: Notes",
|
|
167154
|
-
description:
|
|
167155
|
-
` + `Use this for short goals, constraints, decisions, or reminders worth carrying forward.
|
|
167156
|
-
|
|
167157
|
-
` + `Actions:
|
|
167158
|
-
` + "- `write`: Append one note. Optionally provide `surface_condition` to create a smart note.\n" + "- `read`: Show current notes. Defaults to active session notes + ready smart notes; use `filter` to inspect all, pending, ready, active, or dismissed notes.\n" + "- `dismiss`: Dismiss a note by `note_id`.\n" + "- `update`: Update a note by `note_id`.\n\n" + "**Smart Notes**: When `surface_condition` is provided with `write`, the note becomes a project-scoped smart note. " + "The dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met. " + 'Example: `ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")`',
|
|
168061
|
+
description: CTX_NOTE_DESCRIPTION,
|
|
167159
168062
|
parameters: ParamsSchema3,
|
|
167160
168063
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
167161
168064
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
@@ -167237,11 +168140,15 @@ function createCtxNoteTool(deps) {
|
|
|
167237
168140
|
- ${parts.join(`
|
|
167238
168141
|
- `)}`);
|
|
167239
168142
|
}
|
|
168143
|
+
const limit = typeof params.limit === "number" && params.limit > 0 ? Math.floor(params.limit) : DEFAULT_READ_LIMIT;
|
|
168144
|
+
const offset = typeof params.offset === "number" && params.offset > 0 ? Math.floor(params.offset) : 0;
|
|
167240
168145
|
const sections = readNotes({
|
|
167241
168146
|
db: deps.db,
|
|
167242
168147
|
sessionId,
|
|
167243
168148
|
cwd: ctx.cwd,
|
|
167244
|
-
filter: params.filter
|
|
168149
|
+
filter: params.filter,
|
|
168150
|
+
limit,
|
|
168151
|
+
offset
|
|
167245
168152
|
});
|
|
167246
168153
|
try {
|
|
167247
168154
|
setNoteLastReadAt(deps.db, sessionId);
|
|
@@ -167249,7 +168156,7 @@ function createCtxNoteTool(deps) {
|
|
|
167249
168156
|
if (sections.length === 0) {
|
|
167250
168157
|
return ok3(`## Notes
|
|
167251
168158
|
|
|
167252
|
-
No notes
|
|
168159
|
+
No session notes or smart notes.`);
|
|
167253
168160
|
}
|
|
167254
168161
|
const body = sections.join(`
|
|
167255
168162
|
|
|
@@ -167276,10 +168183,14 @@ function readNotes(args) {
|
|
|
167276
168183
|
}) : [];
|
|
167277
168184
|
const sections2 = [];
|
|
167278
168185
|
if (sessionNotes2.length > 0) {
|
|
168186
|
+
const { page, footer } = paginateNewestFirst(sessionNotes2, args.limit, args.offset);
|
|
168187
|
+
const lines = page.map(formatNoteLine).join(`
|
|
168188
|
+
`);
|
|
167279
168189
|
sections2.push(`## Session Notes
|
|
167280
168190
|
|
|
167281
|
-
${
|
|
167282
|
-
|
|
168191
|
+
${lines}${footer ? `
|
|
168192
|
+
|
|
168193
|
+
${footer}` : ""}`);
|
|
167283
168194
|
}
|
|
167284
168195
|
if (readySmartNotes.length > 0) {
|
|
167285
168196
|
sections2.push(`## \uD83D\uDD14 Ready Smart Notes
|
|
@@ -167310,17 +168221,25 @@ ${readySmartNotes.map(formatNoteLine).join(`
|
|
|
167310
168221
|
}) : [];
|
|
167311
168222
|
const sections = [];
|
|
167312
168223
|
if (sessionNotes.length > 0) {
|
|
168224
|
+
const { page, footer } = paginateNewestFirst(sessionNotes, args.limit, args.offset);
|
|
168225
|
+
const lines = page.map(formatNoteLine).join(`
|
|
168226
|
+
`);
|
|
167313
168227
|
sections.push(`## Session Notes
|
|
167314
168228
|
|
|
167315
|
-
${
|
|
167316
|
-
|
|
168229
|
+
${lines}${footer ? `
|
|
168230
|
+
|
|
168231
|
+
${footer}` : ""}`);
|
|
167317
168232
|
}
|
|
167318
168233
|
if (smartNotes.length > 0) {
|
|
168234
|
+
const { page, footer } = paginateNewestFirst(smartNotes, args.limit, args.offset);
|
|
168235
|
+
const lines = page.map(formatNoteLine).join(`
|
|
168236
|
+
|
|
168237
|
+
`);
|
|
167319
168238
|
sections.push(`## Smart Notes
|
|
167320
168239
|
|
|
167321
|
-
${
|
|
168240
|
+
${lines}${footer ? `
|
|
167322
168241
|
|
|
167323
|
-
`
|
|
168242
|
+
${footer}` : ""}`);
|
|
167324
168243
|
}
|
|
167325
168244
|
return sections;
|
|
167326
168245
|
}
|
|
@@ -167328,7 +168247,7 @@ ${smartNotes.map(formatNoteLine).join(`
|
|
|
167328
168247
|
// ../plugin/src/features/magic-context/range-parser.ts
|
|
167329
168248
|
function parseRangeString(input) {
|
|
167330
168249
|
const maxRangeElements = 1000;
|
|
167331
|
-
const trimmed = input.trim();
|
|
168250
|
+
const trimmed = input.replace(/§/g, "").trim();
|
|
167332
168251
|
if (trimmed === "") {
|
|
167333
168252
|
throw new Error("Range string must not be empty");
|
|
167334
168253
|
}
|
|
@@ -167476,7 +168395,11 @@ function createCtxReduceTool(deps) {
|
|
|
167476
168395
|
};
|
|
167477
168396
|
}
|
|
167478
168397
|
|
|
168398
|
+
// ../plugin/src/features/magic-context/search.ts
|
|
168399
|
+
init_logger();
|
|
168400
|
+
|
|
167479
168401
|
// ../plugin/src/features/magic-context/git-commits/git-log-reader.ts
|
|
168402
|
+
init_logger();
|
|
167480
168403
|
import { execFile } from "node:child_process";
|
|
167481
168404
|
import { promisify } from "node:util";
|
|
167482
168405
|
var execFileAsync = promisify(execFile);
|
|
@@ -167560,7 +168483,11 @@ ${body}` : subject;
|
|
|
167560
168483
|
}
|
|
167561
168484
|
return commits;
|
|
167562
168485
|
}
|
|
168486
|
+
// ../plugin/src/features/magic-context/git-commits/indexer.ts
|
|
168487
|
+
init_logger();
|
|
168488
|
+
|
|
167563
168489
|
// ../plugin/src/features/magic-context/git-commits/storage-git-commits.ts
|
|
168490
|
+
init_logger();
|
|
167564
168491
|
var insertStatements = new WeakMap;
|
|
167565
168492
|
var existingShasStatements = new WeakMap;
|
|
167566
168493
|
var projectCountStatements = new WeakMap;
|
|
@@ -167773,6 +168700,7 @@ async function embedUnembeddedCommits(db, projectPath) {
|
|
|
167773
168700
|
}
|
|
167774
168701
|
}
|
|
167775
168702
|
// ../plugin/src/features/magic-context/git-commits/search-git-commits.ts
|
|
168703
|
+
init_logger();
|
|
167776
168704
|
var ftsStatements = new WeakMap;
|
|
167777
168705
|
var ftsPlainStatements = new WeakMap;
|
|
167778
168706
|
var getBySHAStatements = new WeakMap;
|
|
@@ -168443,6 +169371,9 @@ class BoundedSessionMap {
|
|
|
168443
169371
|
}
|
|
168444
169372
|
}
|
|
168445
169373
|
|
|
169374
|
+
// ../plugin/src/hooks/magic-context/inject-compartments.ts
|
|
169375
|
+
init_logger();
|
|
169376
|
+
|
|
168446
169377
|
// ../plugin/src/hooks/magic-context/decay-curve.ts
|
|
168447
169378
|
var H50 = 24;
|
|
168448
169379
|
var D = 25;
|
|
@@ -168506,6 +169437,9 @@ function escapeXmlAttr2(s) {
|
|
|
168506
169437
|
function escapeXmlContent2(s) {
|
|
168507
169438
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
168508
169439
|
}
|
|
169440
|
+
function isTieredRow(c) {
|
|
169441
|
+
return typeof c.p1 === "string" && c.p1.length > 0;
|
|
169442
|
+
}
|
|
168509
169443
|
function tierBody(c, tier2) {
|
|
168510
169444
|
const tiers = [c.p1, c.p2, c.p3, c.p4];
|
|
168511
169445
|
const requested = tiers[tier2 - 1];
|
|
@@ -168535,12 +169469,13 @@ function renderOneCompartment(c, tier2) {
|
|
|
168535
169469
|
const baseAttrs = `start="${c.startMessage}" end="${c.endMessage}" title="${escapeXmlAttr2(c.title)}"`;
|
|
168536
169470
|
if (tier2 >= 5)
|
|
168537
169471
|
return "";
|
|
168538
|
-
if (c.legacy === 1) {
|
|
168539
|
-
|
|
169472
|
+
if (c.legacy === 1 || !isTieredRow(c)) {
|
|
169473
|
+
const flat = (c.content ?? "").trim();
|
|
169474
|
+
if (tier2 >= 4 || flat.length === 0)
|
|
168540
169475
|
return `<compartment ${baseAttrs} />`;
|
|
168541
169476
|
return [
|
|
168542
169477
|
`<compartment ${baseAttrs}>`,
|
|
168543
|
-
escapeXmlContent2(legacyBodyForTier(
|
|
169478
|
+
escapeXmlContent2(legacyBodyForTier(flat, tier2)),
|
|
168544
169479
|
"</compartment>"
|
|
168545
169480
|
].join(`
|
|
168546
169481
|
`);
|
|
@@ -168721,6 +169656,7 @@ function isAftAvailable() {
|
|
|
168721
169656
|
}
|
|
168722
169657
|
|
|
168723
169658
|
// ../plugin/src/hooks/magic-context/key-files-block.ts
|
|
169659
|
+
init_logger();
|
|
168724
169660
|
var cachedKeyFilesBySession = new Map;
|
|
168725
169661
|
var staleUpdates = new Map;
|
|
168726
169662
|
function staleKey(update2) {
|
|
@@ -168974,6 +169910,21 @@ function renderMemoryBlockV2(memories, wrapper = "project-memory") {
|
|
|
168974
169910
|
`);
|
|
168975
169911
|
}
|
|
168976
169912
|
|
|
169913
|
+
// ../plugin/src/tools/ctx-search/constants.ts
|
|
169914
|
+
var CTX_SEARCH_DESCRIPTION = `Your long-term recall for this project — search everything that ever happened here, not just what's currently visible.
|
|
169915
|
+
|
|
169916
|
+
Reach for it when something feels familiar but isn't in view: "did we solve this before?", "what did we decide about X?", "when did this break?", "where does Y live?". Results only contain things you CANNOT currently see — memories already shown in <project-memory> and the live conversation tail are filtered out.
|
|
169917
|
+
|
|
169918
|
+
Sources (omit for a broad search across all):
|
|
169919
|
+
- memory: curated cross-session project knowledge — rules, constraints, conventions.
|
|
169920
|
+
- message: the raw conversation behind your compacted history. Hits include message ordinals — expand the surrounding exchange with ctx_expand(start=N-10, end=N+5).
|
|
169921
|
+
- git_commit: this repository's commit history.
|
|
169922
|
+
|
|
169923
|
+
Picking sources:
|
|
169924
|
+
- "when did this change / was this working before" → ["git_commit", "message"]
|
|
169925
|
+
- "did we discuss this earlier" → ["message"]
|
|
169926
|
+
- "what's our convention / rule for X" → ["memory"]`;
|
|
169927
|
+
|
|
168977
169928
|
// src/tools/ctx-search.ts
|
|
168978
169929
|
var DEFAULT_LIMIT = 10;
|
|
168979
169930
|
var ParamsSchema5 = exports_typebox.Object({
|
|
@@ -169057,18 +170008,7 @@ function createCtxSearchTool(deps) {
|
|
|
169057
170008
|
return {
|
|
169058
170009
|
name: "ctx_search",
|
|
169059
170010
|
label: "Magic Context: Search",
|
|
169060
|
-
description:
|
|
169061
|
-
|
|
169062
|
-
` + `Sources:
|
|
169063
|
-
` + `- memory: curated cross-session knowledge for this project
|
|
169064
|
-
` + `- message: raw user/assistant messages from older compartmentalized history
|
|
169065
|
-
` + `- git_commit: HEAD git commits (when git commit indexing is enabled)
|
|
169066
|
-
|
|
169067
|
-
` + "Narrow via the `sources` param when the question maps to a specific channel:\n" + `- "was this working before / when did this break" → ["git_commit", "message"]
|
|
169068
|
-
` + `- "when did we change this" → ["git_commit"]
|
|
169069
|
-
` + `- "what is our naming convention" → ["memory"]
|
|
169070
|
-
` + `- "did we discuss this earlier" → ["message"]
|
|
169071
|
-
` + "Omit sources for a broad search across all enabled channels.",
|
|
170011
|
+
description: CTX_SEARCH_DESCRIPTION,
|
|
169072
170012
|
parameters: ParamsSchema5,
|
|
169073
170013
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
169074
170014
|
const query = params.query?.trim();
|
|
@@ -169087,6 +170027,7 @@ function createCtxSearchTool(deps) {
|
|
|
169087
170027
|
const embeddingEnabled = snapshot ? snapshot.enabled || snapshot.gitCommitEnabled : deps.embeddingEnabled;
|
|
169088
170028
|
const gitCommitsEnabled = snapshot?.gitCommitEnabled ?? deps.gitCommitsEnabled ?? false;
|
|
169089
170029
|
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
170030
|
+
const messageOrdinalCutoff = lastCompartmentEnd >= 0 ? lastCompartmentEnd : 0;
|
|
169090
170031
|
const visibleMemoryIds = getVisibleMemoryIds(deps.db, sessionId);
|
|
169091
170032
|
const results = await unifiedSearch(deps.db, sessionId, projectIdentity, query, {
|
|
169092
170033
|
limit: normalizeLimit3(params.limit),
|
|
@@ -169097,7 +170038,7 @@ function createCtxSearchTool(deps) {
|
|
|
169097
170038
|
return result?.vector ?? null;
|
|
169098
170039
|
},
|
|
169099
170040
|
isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
|
|
169100
|
-
maxMessageOrdinal:
|
|
170041
|
+
maxMessageOrdinal: messageOrdinalCutoff,
|
|
169101
170042
|
gitCommitsEnabled,
|
|
169102
170043
|
sources: params.sources,
|
|
169103
170044
|
visibleMemoryIds,
|
|
@@ -169184,13 +170125,15 @@ function registerMagicContextTools(pi, opts) {
|
|
|
169184
170125
|
embeddingEnabled: opts.embeddingEnabled,
|
|
169185
170126
|
gitCommitsEnabled: opts.gitCommitsEnabled
|
|
169186
170127
|
}));
|
|
169187
|
-
|
|
169188
|
-
|
|
169189
|
-
|
|
169190
|
-
|
|
169191
|
-
|
|
169192
|
-
|
|
169193
|
-
|
|
170128
|
+
if (opts.memoryToolEnabled !== false) {
|
|
170129
|
+
pi.registerTool(createCtxMemoryTool({
|
|
170130
|
+
db: opts.db,
|
|
170131
|
+
ensureProjectRegistered: opts.ensureProjectRegistered,
|
|
170132
|
+
memoryEnabled: opts.memoryEnabled,
|
|
170133
|
+
embeddingEnabled: opts.embeddingEnabled,
|
|
170134
|
+
allowDreamerActions: opts.allowDreamerActions ?? false
|
|
170135
|
+
}));
|
|
170136
|
+
}
|
|
169194
170137
|
if (!opts.sessionScopedToolsDisabled) {
|
|
169195
170138
|
pi.registerTool(createCtxNoteTool({
|
|
169196
170139
|
db: opts.db,
|
|
@@ -169213,7 +170156,7 @@ var openedDb;
|
|
|
169213
170156
|
function magicContextSubagentExtension(pi) {
|
|
169214
170157
|
setHarness("pi");
|
|
169215
170158
|
pi.registerFlag(SUBAGENT_DREAMER_ACTIONS_FLAG, {
|
|
169216
|
-
description: "
|
|
170159
|
+
description: "Register ctx_memory with dreamer actions for Magic Context subagents.",
|
|
169217
170160
|
type: "boolean",
|
|
169218
170161
|
default: false
|
|
169219
170162
|
});
|
|
@@ -169231,10 +170174,11 @@ function magicContextSubagentExtension(pi) {
|
|
|
169231
170174
|
registerMagicContextTools(pi, {
|
|
169232
170175
|
db,
|
|
169233
170176
|
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
170177
|
+
memoryToolEnabled: dreamerActionsEnabled,
|
|
169234
170178
|
allowDreamerActions: dreamerActionsEnabled,
|
|
169235
170179
|
sessionScopedToolsDisabled: true
|
|
169236
170180
|
});
|
|
169237
|
-
log(`[pi-subagent] registered tools: ctx_search, ctx_memory` + ` (ctx_note/ctx_expand omitted: --no-session child;` + ` memory=${cfg.memory.enabled}, embedding=${cfg.embedding.provider !== "off"},` + ` git_commits=${cfg.memory.git_commit_indexing.enabled}, dreamer_actions=${dreamerActionsEnabled})`);
|
|
170181
|
+
log(`[pi-subagent] registered tools: ctx_search${dreamerActionsEnabled ? ", ctx_memory" : ""}` + ` (ctx_note/ctx_expand omitted: --no-session child;` + ` memory=${cfg.memory.enabled}, embedding=${cfg.embedding.provider !== "off"},` + ` git_commits=${cfg.memory.git_commit_indexing.enabled}, dreamer_actions=${dreamerActionsEnabled})`);
|
|
169238
170182
|
} catch (err5) {
|
|
169239
170183
|
const message = err5 instanceof Error ? err5.message : String(err5);
|
|
169240
170184
|
log(`[pi-subagent] startup failed: ${message}`);
|