@wolfx/pi-magic-context 0.22.4 → 0.23.1
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 +3877 -1158
- package/dist/subagent-entry.js +1303 -360
- 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
|
};
|
|
@@ -159529,9 +159936,8 @@ function persistCachedM0(db, sessionId, payload) {
|
|
|
159529
159936
|
cached_m0_session_facts_version = ?,
|
|
159530
159937
|
cached_m0_upgrade_state = ?,
|
|
159531
159938
|
cached_m0_system_hash = ?,
|
|
159532
|
-
cached_m0_tool_set_hash = ?,
|
|
159533
159939
|
cached_m0_model_key = ?
|
|
159534
|
-
WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, payload.systemHash ?? "", payload.
|
|
159940
|
+
WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, payload.systemHash ?? "", payload.modelKey ?? "", sessionId);
|
|
159535
159941
|
}
|
|
159536
159942
|
function clearCachedM0M1(db, sessionId) {
|
|
159537
159943
|
ensureSessionMetaRow(db, sessionId);
|
|
@@ -159593,12 +159999,6 @@ function isCompartmentRow(row) {
|
|
|
159593
159999
|
const candidate = row;
|
|
159594
160000
|
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
160001
|
}
|
|
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
160002
|
function insertCompartmentRows(db, sessionId, compartments, now) {
|
|
159603
160003
|
const stmt = getInsertCompartmentStatement(db);
|
|
159604
160004
|
for (const compartment of compartments) {
|
|
@@ -159627,16 +160027,6 @@ function toCompartment(row) {
|
|
|
159627
160027
|
createdAt: row.created_at
|
|
159628
160028
|
};
|
|
159629
160029
|
}
|
|
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
160030
|
function getCompartments(db, sessionId) {
|
|
159641
160031
|
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isCompartmentRow);
|
|
159642
160032
|
return rows.map(toCompartment);
|
|
@@ -159645,6 +160035,11 @@ function getLastCompartmentEndMessage(db, sessionId) {
|
|
|
159645
160035
|
const row = db.prepare("SELECT MAX(end_message) as max_end FROM compartments WHERE session_id = ?").get(sessionId);
|
|
159646
160036
|
return row?.max_end ?? -1;
|
|
159647
160037
|
}
|
|
160038
|
+
function getLastCompartmentEndMessageId(db, sessionId) {
|
|
160039
|
+
const row = db.prepare("SELECT end_message_id FROM compartments WHERE session_id = ? ORDER BY sequence DESC LIMIT 1").get(sessionId);
|
|
160040
|
+
const id = row?.end_message_id;
|
|
160041
|
+
return id && id.length > 0 ? id : null;
|
|
160042
|
+
}
|
|
159648
160043
|
function getCompartmentsByEndMessageId(db, sessionId, endMessageId) {
|
|
159649
160044
|
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? AND end_message_id = ? ORDER BY sequence ASC").all(sessionId, endMessageId).filter(isCompartmentRow);
|
|
159650
160045
|
return rows.map(toCompartment);
|
|
@@ -159657,10 +160052,6 @@ function appendCompartments(db, sessionId, compartments) {
|
|
|
159657
160052
|
insertCompartmentRows(db, sessionId, compartments, now);
|
|
159658
160053
|
})();
|
|
159659
160054
|
}
|
|
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
160055
|
function saveRecompStagingPass(db, sessionId, passNumber, compartments, facts) {
|
|
159665
160056
|
const now = Date.now();
|
|
159666
160057
|
db.transaction(() => {
|
|
@@ -159704,14 +160095,6 @@ function getRecompStaging(db, sessionId) {
|
|
|
159704
160095
|
lastEndMessage: lastEnd
|
|
159705
160096
|
};
|
|
159706
160097
|
}
|
|
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
160098
|
function clearRecompStaging(db, sessionId) {
|
|
159716
160099
|
db.transaction(() => {
|
|
159717
160100
|
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
@@ -159759,6 +160142,8 @@ function escapeXmlContent(s) {
|
|
|
159759
160142
|
}
|
|
159760
160143
|
|
|
159761
160144
|
// ../plugin/src/hooks/magic-context/read-session-db.ts
|
|
160145
|
+
init_data_path();
|
|
160146
|
+
init_logger();
|
|
159762
160147
|
import { existsSync as existsSync6 } from "node:fs";
|
|
159763
160148
|
import { join as join7 } from "node:path";
|
|
159764
160149
|
function getOpenCodeDbPath() {
|
|
@@ -159831,13 +160216,27 @@ function parseJsonUnknown(value) {
|
|
|
159831
160216
|
return null;
|
|
159832
160217
|
}
|
|
159833
160218
|
}
|
|
160219
|
+
function attachRawPartVersion(value, timeUpdated) {
|
|
160220
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
160221
|
+
return value;
|
|
160222
|
+
if (typeof timeUpdated !== "number")
|
|
160223
|
+
return value;
|
|
160224
|
+
try {
|
|
160225
|
+
Object.defineProperty(value, "__magicContextPartUpdatedAt", {
|
|
160226
|
+
value: timeUpdated,
|
|
160227
|
+
enumerable: false,
|
|
160228
|
+
configurable: true
|
|
160229
|
+
});
|
|
160230
|
+
} catch {}
|
|
160231
|
+
return value;
|
|
160232
|
+
}
|
|
159834
160233
|
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);
|
|
160234
|
+
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);
|
|
160235
|
+
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
160236
|
const partsByMessageId = new Map;
|
|
159838
160237
|
for (const part of partRows) {
|
|
159839
160238
|
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
159840
|
-
list.push(parseJsonUnknown(part.data));
|
|
160239
|
+
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
159841
160240
|
partsByMessageId.set(part.message_id, list);
|
|
159842
160241
|
}
|
|
159843
160242
|
const filtered = messageRows.filter((row) => {
|
|
@@ -159853,10 +160252,63 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
159853
160252
|
ordinal: index + 1,
|
|
159854
160253
|
id: row.id,
|
|
159855
160254
|
role,
|
|
159856
|
-
parts: partsByMessageId.get(row.id) ?? []
|
|
160255
|
+
parts: partsByMessageId.get(row.id) ?? [],
|
|
160256
|
+
version: row.time_updated ?? null
|
|
159857
160257
|
};
|
|
159858
160258
|
});
|
|
159859
160259
|
}
|
|
160260
|
+
function isAnchorRow(row) {
|
|
160261
|
+
return row !== null && typeof row === "object" && typeof row.time_created === "number" && typeof row.id === "string";
|
|
160262
|
+
}
|
|
160263
|
+
function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
160264
|
+
const anchorRow = db.prepare("SELECT time_created, id, data FROM message WHERE id = ? AND session_id = ?").get(anchorMessageId, sessionId);
|
|
160265
|
+
if (!isAnchorRow(anchorRow))
|
|
160266
|
+
return null;
|
|
160267
|
+
const anchorInfo = parseJsonRecord(anchorRow.data ?? "");
|
|
160268
|
+
if (anchorInfo?.summary === true && anchorInfo?.finish === "stop")
|
|
160269
|
+
return null;
|
|
160270
|
+
const messageRows = db.prepare(`SELECT id, data, time_updated FROM message
|
|
160271
|
+
WHERE session_id = ?
|
|
160272
|
+
AND (time_created > ? OR (time_created = ? AND id >= ?))
|
|
160273
|
+
ORDER BY time_created ASC, id ASC`).all(sessionId, anchorRow.time_created, anchorRow.time_created, anchorRow.id).filter(isRawMessageRow);
|
|
160274
|
+
const filtered = messageRows.filter((row) => {
|
|
160275
|
+
const info = parseJsonRecord(row.data);
|
|
160276
|
+
return !(info?.summary === true && info?.finish === "stop");
|
|
160277
|
+
});
|
|
160278
|
+
const ids = filtered.map((row) => row.id);
|
|
160279
|
+
const partsByMessageId = new Map;
|
|
160280
|
+
if (ids.length > 0) {
|
|
160281
|
+
const CHUNK = 800;
|
|
160282
|
+
for (let i = 0;i < ids.length; i += CHUNK) {
|
|
160283
|
+
const slice = ids.slice(i, i + CHUNK);
|
|
160284
|
+
const placeholders = slice.map(() => "?").join(",");
|
|
160285
|
+
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);
|
|
160286
|
+
for (const part of partRows) {
|
|
160287
|
+
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
160288
|
+
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
160289
|
+
partsByMessageId.set(part.message_id, list);
|
|
160290
|
+
}
|
|
160291
|
+
}
|
|
160292
|
+
}
|
|
160293
|
+
const messages = [];
|
|
160294
|
+
let ord = baseOrdinal;
|
|
160295
|
+
for (const row of filtered) {
|
|
160296
|
+
const info = parseJsonRecord(row.data);
|
|
160297
|
+
if (!info) {
|
|
160298
|
+
ord += 1;
|
|
160299
|
+
continue;
|
|
160300
|
+
}
|
|
160301
|
+
messages.push({
|
|
160302
|
+
ordinal: ord,
|
|
160303
|
+
id: row.id,
|
|
160304
|
+
role: typeof info.role === "string" ? info.role : "unknown",
|
|
160305
|
+
parts: partsByMessageId.get(row.id) ?? [],
|
|
160306
|
+
version: row.time_updated ?? null
|
|
160307
|
+
});
|
|
160308
|
+
ord += 1;
|
|
160309
|
+
}
|
|
160310
|
+
return { messages, absoluteMessageCount: Math.max(0, ord - 1) };
|
|
160311
|
+
}
|
|
159860
160312
|
|
|
159861
160313
|
// ../plugin/src/hooks/magic-context/tag-content-primitives.ts
|
|
159862
160314
|
var encoder = new TextEncoder;
|
|
@@ -160001,6 +160453,7 @@ class ToolMutationBatch {
|
|
|
160001
160453
|
|
|
160002
160454
|
// ../plugin/src/hooks/magic-context/read-session-chunk.ts
|
|
160003
160455
|
var activeRawMessageCache = null;
|
|
160456
|
+
var activeAbsoluteCountCache = null;
|
|
160004
160457
|
var sessionProviders = new Map;
|
|
160005
160458
|
function setRawMessageProvider(sessionId, provider2) {
|
|
160006
160459
|
sessionProviders.set(sessionId, provider2);
|
|
@@ -160032,12 +160485,14 @@ function withRawSessionMessageCache(fn) {
|
|
|
160032
160485
|
const outerCache = activeRawMessageCache;
|
|
160033
160486
|
if (!outerCache) {
|
|
160034
160487
|
activeRawMessageCache = new Map;
|
|
160488
|
+
activeAbsoluteCountCache = new Map;
|
|
160035
160489
|
}
|
|
160036
160490
|
try {
|
|
160037
160491
|
return fn();
|
|
160038
160492
|
} finally {
|
|
160039
160493
|
if (!outerCache) {
|
|
160040
160494
|
activeRawMessageCache = null;
|
|
160495
|
+
activeAbsoluteCountCache = null;
|
|
160041
160496
|
}
|
|
160042
160497
|
}
|
|
160043
160498
|
}
|
|
@@ -160053,6 +160508,40 @@ function readRawSessionMessages(sessionId) {
|
|
|
160053
160508
|
}
|
|
160054
160509
|
return readRawSessionMessagesFromSource(sessionId);
|
|
160055
160510
|
}
|
|
160511
|
+
function primeTailRawMessageCache(args) {
|
|
160512
|
+
const { sessionId, lastCompartmentEnd, anchorMessageId } = args;
|
|
160513
|
+
if (!activeRawMessageCache)
|
|
160514
|
+
return false;
|
|
160515
|
+
if (activeRawMessageCache.has(sessionId))
|
|
160516
|
+
return false;
|
|
160517
|
+
if (sessionProviders.has(sessionId))
|
|
160518
|
+
return false;
|
|
160519
|
+
if (!openCodeDbExists())
|
|
160520
|
+
return false;
|
|
160521
|
+
if (lastCompartmentEnd < 1 || !anchorMessageId)
|
|
160522
|
+
return false;
|
|
160523
|
+
const result = withReadOnlySessionDb((db) => readRawSessionTailFromDb(db, sessionId, lastCompartmentEnd, anchorMessageId));
|
|
160524
|
+
if (!result)
|
|
160525
|
+
return false;
|
|
160526
|
+
activeRawMessageCache.set(sessionId, result.messages);
|
|
160527
|
+
activeAbsoluteCountCache?.set(sessionId, result.absoluteMessageCount);
|
|
160528
|
+
return true;
|
|
160529
|
+
}
|
|
160530
|
+
function getCachedAbsoluteMessageCount(sessionId) {
|
|
160531
|
+
return activeAbsoluteCountCache?.get(sessionId) ?? null;
|
|
160532
|
+
}
|
|
160533
|
+
function primeInMemoryTailRawMessageCache(args) {
|
|
160534
|
+
const { sessionId, messages, absoluteMessageCount } = args;
|
|
160535
|
+
if (!activeRawMessageCache)
|
|
160536
|
+
return false;
|
|
160537
|
+
if (activeRawMessageCache.has(sessionId))
|
|
160538
|
+
return false;
|
|
160539
|
+
if (sessionProviders.has(sessionId))
|
|
160540
|
+
return false;
|
|
160541
|
+
activeRawMessageCache.set(sessionId, messages);
|
|
160542
|
+
activeAbsoluteCountCache?.set(sessionId, absoluteMessageCount);
|
|
160543
|
+
return true;
|
|
160544
|
+
}
|
|
160056
160545
|
function readRawSessionMessagesFromSource(sessionId) {
|
|
160057
160546
|
const provider2 = sessionProviders.get(sessionId);
|
|
160058
160547
|
if (provider2)
|
|
@@ -160117,7 +160606,7 @@ function getRawSessionTagKeysThrough(sessionId, upToMessageIndex) {
|
|
|
160117
160606
|
return { messageFileKeys, toolObservations };
|
|
160118
160607
|
}
|
|
160119
160608
|
var PROTECTED_TAIL_USER_TURNS = 5;
|
|
160120
|
-
function
|
|
160609
|
+
function getLegacyProtectedTailStartOrdinal(sessionId) {
|
|
160121
160610
|
const messages = readRawSessionMessages(sessionId);
|
|
160122
160611
|
const userOrdinals = messages.filter((m) => m.role === "user" && hasMeaningfulUserText(m.parts)).map((m) => m.ordinal);
|
|
160123
160612
|
if (userOrdinals.length < PROTECTED_TAIL_USER_TURNS) {
|
|
@@ -160127,6 +160616,7 @@ function getProtectedTailStartOrdinal(sessionId) {
|
|
|
160127
160616
|
}
|
|
160128
160617
|
function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal) {
|
|
160129
160618
|
const messages = readRawSessionMessages(sessionId);
|
|
160619
|
+
const totalMessageCount = getCachedAbsoluteMessageCount(sessionId) ?? messages.length;
|
|
160130
160620
|
const startOrdinal = Math.max(1, offset);
|
|
160131
160621
|
const lines = [];
|
|
160132
160622
|
const lineMeta = [];
|
|
@@ -160254,7 +160744,7 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
160254
160744
|
endMessageId: lastMessageId,
|
|
160255
160745
|
messageCount: messagesProcessed,
|
|
160256
160746
|
tokenEstimate: totalTokens,
|
|
160257
|
-
hasMore: lastOrdinal < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1,
|
|
160747
|
+
hasMore: lastOrdinal < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1, totalMessageCount) : totalMessageCount),
|
|
160258
160748
|
text: lines.join(`
|
|
160259
160749
|
`),
|
|
160260
160750
|
lines: lineMeta,
|
|
@@ -160264,7 +160754,13 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
160264
160754
|
}
|
|
160265
160755
|
|
|
160266
160756
|
// ../plugin/src/tools/ctx-expand/constants.ts
|
|
160267
|
-
var CTX_EXPAND_DESCRIPTION =
|
|
160757
|
+
var CTX_EXPAND_DESCRIPTION = `Recover the original conversation from your compacted history.
|
|
160758
|
+
|
|
160759
|
+
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:
|
|
160760
|
+
|
|
160761
|
+
ctx_expand(start=120, end=245) ← the compartment's own start/end attributes
|
|
160762
|
+
|
|
160763
|
+
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
160764
|
var CTX_EXPAND_TOKEN_BUDGET = 15000;
|
|
160269
160765
|
|
|
160270
160766
|
// ../../node_modules/.bun/typebox@1.1.38/node_modules/typebox/build/system/memory/memory.mjs
|
|
@@ -164433,11 +164929,31 @@ function findLastModelKeyFromBranch(entries) {
|
|
|
164433
164929
|
}
|
|
164434
164930
|
return;
|
|
164435
164931
|
}
|
|
164932
|
+
function rawEntryVersion(entry) {
|
|
164933
|
+
const record4 = entry;
|
|
164934
|
+
const updated = record4.updatedAt ?? record4.updated_at ?? record4.timestamp;
|
|
164935
|
+
return typeof updated === "string" || typeof updated === "number" ? updated : entry.id;
|
|
164936
|
+
}
|
|
164937
|
+
function attachPiPartVersion(parts, version2) {
|
|
164938
|
+
return parts.map((part) => {
|
|
164939
|
+
if (part === null || typeof part !== "object" || Array.isArray(part))
|
|
164940
|
+
return part;
|
|
164941
|
+
try {
|
|
164942
|
+
Object.defineProperty(part, "__magicContextPartUpdatedAt", {
|
|
164943
|
+
value: version2,
|
|
164944
|
+
enumerable: false,
|
|
164945
|
+
configurable: true
|
|
164946
|
+
});
|
|
164947
|
+
} catch {}
|
|
164948
|
+
return part;
|
|
164949
|
+
});
|
|
164950
|
+
}
|
|
164436
164951
|
function convertEntriesToRawMessages(entries) {
|
|
164437
164952
|
const result = [];
|
|
164438
164953
|
let nextOrdinal = 1;
|
|
164439
164954
|
let pendingToolParts = [];
|
|
164440
164955
|
let pendingFirstRealId = "";
|
|
164956
|
+
let pendingFirstRealVersion = "";
|
|
164441
164957
|
for (const entry of entries) {
|
|
164442
164958
|
if (!isMessageEntry(entry)) {
|
|
164443
164959
|
continue;
|
|
@@ -164445,24 +164961,29 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164445
164961
|
const msg = entry.message;
|
|
164446
164962
|
const role = msg.role;
|
|
164447
164963
|
if (role === "toolResult") {
|
|
164448
|
-
|
|
164964
|
+
const version2 = rawEntryVersion(entry);
|
|
164965
|
+
pendingToolParts.push(...attachPiPartVersion(synthesizeToolResultParts(msg), version2));
|
|
164449
164966
|
if (pendingFirstRealId === "") {
|
|
164450
164967
|
pendingFirstRealId = entry.id;
|
|
164968
|
+
pendingFirstRealVersion = version2;
|
|
164451
164969
|
}
|
|
164452
164970
|
continue;
|
|
164453
164971
|
}
|
|
164454
164972
|
if (role === "user") {
|
|
164973
|
+
const version2 = rawEntryVersion(entry);
|
|
164455
164974
|
const parts = [
|
|
164456
164975
|
...pendingToolParts,
|
|
164457
|
-
...synthesizeUserParts(msg)
|
|
164976
|
+
...attachPiPartVersion(synthesizeUserParts(msg), version2)
|
|
164458
164977
|
];
|
|
164459
164978
|
pendingToolParts = [];
|
|
164460
164979
|
pendingFirstRealId = "";
|
|
164980
|
+
pendingFirstRealVersion = "";
|
|
164461
164981
|
result.push({
|
|
164462
164982
|
ordinal: nextOrdinal++,
|
|
164463
164983
|
id: entry.id,
|
|
164464
164984
|
role: "user",
|
|
164465
|
-
parts
|
|
164985
|
+
parts,
|
|
164986
|
+
version: version2
|
|
164466
164987
|
});
|
|
164467
164988
|
continue;
|
|
164468
164989
|
}
|
|
@@ -164472,16 +164993,20 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164472
164993
|
ordinal: nextOrdinal++,
|
|
164473
164994
|
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
164474
164995
|
role: "user",
|
|
164475
|
-
parts: pendingToolParts
|
|
164996
|
+
parts: pendingToolParts,
|
|
164997
|
+
version: pendingFirstRealVersion
|
|
164476
164998
|
});
|
|
164477
164999
|
pendingToolParts = [];
|
|
164478
165000
|
pendingFirstRealId = "";
|
|
165001
|
+
pendingFirstRealVersion = "";
|
|
164479
165002
|
}
|
|
165003
|
+
const version2 = rawEntryVersion(entry);
|
|
164480
165004
|
result.push({
|
|
164481
165005
|
ordinal: nextOrdinal++,
|
|
164482
165006
|
id: entry.id,
|
|
164483
165007
|
role: "assistant",
|
|
164484
|
-
parts: synthesizeAssistantParts(msg)
|
|
165008
|
+
parts: attachPiPartVersion(synthesizeAssistantParts(msg), version2),
|
|
165009
|
+
version: version2
|
|
164485
165010
|
});
|
|
164486
165011
|
continue;
|
|
164487
165012
|
}
|
|
@@ -164489,7 +165014,8 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164489
165014
|
ordinal: nextOrdinal++,
|
|
164490
165015
|
id: entry.id,
|
|
164491
165016
|
role: typeof role === "string" ? role : "unknown",
|
|
164492
|
-
parts: []
|
|
165017
|
+
parts: [],
|
|
165018
|
+
version: rawEntryVersion(entry)
|
|
164493
165019
|
});
|
|
164494
165020
|
}
|
|
164495
165021
|
if (pendingToolParts.length > 0) {
|
|
@@ -164497,7 +165023,8 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164497
165023
|
ordinal: nextOrdinal,
|
|
164498
165024
|
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
164499
165025
|
role: "user",
|
|
164500
|
-
parts: pendingToolParts
|
|
165026
|
+
parts: pendingToolParts,
|
|
165027
|
+
version: pendingFirstRealVersion
|
|
164501
165028
|
});
|
|
164502
165029
|
}
|
|
164503
165030
|
return result;
|
|
@@ -164654,6 +165181,13 @@ function createCtxExpandTool(deps) {
|
|
|
164654
165181
|
}
|
|
164655
165182
|
|
|
164656
165183
|
// ../plugin/src/features/magic-context/memory/constants.ts
|
|
165184
|
+
var V2_MEMORY_CATEGORIES = [
|
|
165185
|
+
"PROJECT_RULES",
|
|
165186
|
+
"ARCHITECTURE",
|
|
165187
|
+
"CONSTRAINTS",
|
|
165188
|
+
"CONFIG_VALUES",
|
|
165189
|
+
"NAMING"
|
|
165190
|
+
];
|
|
164657
165191
|
var PROMOTABLE_CATEGORIES = [
|
|
164658
165192
|
"PROJECT_RULES",
|
|
164659
165193
|
"ARCHITECTURE",
|
|
@@ -164693,6 +165227,7 @@ var CATEGORY_DEFAULT_TTL = {
|
|
|
164693
165227
|
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
164694
165228
|
};
|
|
164695
165229
|
// ../plugin/src/features/magic-context/memory/embedding-backfill.ts
|
|
165230
|
+
init_logger();
|
|
164696
165231
|
async function ensureMemoryEmbeddings(args) {
|
|
164697
165232
|
const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
164698
165233
|
if (!snapshot?.enabled) {
|
|
@@ -164730,6 +165265,9 @@ async function ensureMemoryEmbeddings(args) {
|
|
|
164730
165265
|
}
|
|
164731
165266
|
return args.existingEmbeddings;
|
|
164732
165267
|
}
|
|
165268
|
+
// ../plugin/src/features/magic-context/memory/promotion.ts
|
|
165269
|
+
init_logger();
|
|
165270
|
+
|
|
164733
165271
|
// ../plugin/src/features/magic-context/memory/storage-memory.ts
|
|
164734
165272
|
var COLUMN_MAP = {
|
|
164735
165273
|
id: "id",
|
|
@@ -165401,7 +165939,7 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, lastIndexedOrdinal,
|
|
|
165401
165939
|
}
|
|
165402
165940
|
// ../plugin/src/features/magic-context/project-docs-hash.ts
|
|
165403
165941
|
import { createHash as createHash6 } from "node:crypto";
|
|
165404
|
-
import { readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
|
|
165942
|
+
import { lstatSync, readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
|
|
165405
165943
|
import path4 from "node:path";
|
|
165406
165944
|
var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
165407
165945
|
var PROJECT_DOCS_DELIMITER = `
|
|
@@ -165409,6 +165947,7 @@ var PROJECT_DOCS_DELIMITER = `
|
|
|
165409
165947
|
---
|
|
165410
165948
|
|
|
165411
165949
|
`;
|
|
165950
|
+
var MAX_PROJECT_DOC_BYTES = 256 * 1024;
|
|
165412
165951
|
var docsCache = new Map;
|
|
165413
165952
|
function canonicalizeDocContent(raw) {
|
|
165414
165953
|
return raw.replace(/^\uFEFF/, "").replace(/\r\n/g, `
|
|
@@ -165418,9 +165957,10 @@ function canonicalizeDocContent(raw) {
|
|
|
165418
165957
|
}
|
|
165419
165958
|
function fingerprintFile(filePath) {
|
|
165420
165959
|
try {
|
|
165421
|
-
const stat2 =
|
|
165960
|
+
const stat2 = lstatSync(filePath);
|
|
165961
|
+
const isReadableDoc = stat2.isFile() && stat2.size <= MAX_PROJECT_DOC_BYTES;
|
|
165422
165962
|
return {
|
|
165423
|
-
exists:
|
|
165963
|
+
exists: isReadableDoc,
|
|
165424
165964
|
mtimeMs: stat2.mtimeMs,
|
|
165425
165965
|
size: stat2.size
|
|
165426
165966
|
};
|
|
@@ -165463,6 +166003,16 @@ function readCanonicalPieces(projectDirectory, files) {
|
|
|
165463
166003
|
if (!fingerprint?.exists) {
|
|
165464
166004
|
continue;
|
|
165465
166005
|
}
|
|
166006
|
+
let safeToRead = false;
|
|
166007
|
+
try {
|
|
166008
|
+
const st = lstatSync(filePath);
|
|
166009
|
+
safeToRead = st.isFile() && st.size <= MAX_PROJECT_DOC_BYTES;
|
|
166010
|
+
} catch {
|
|
166011
|
+
safeToRead = false;
|
|
166012
|
+
}
|
|
166013
|
+
if (!safeToRead) {
|
|
166014
|
+
continue;
|
|
166015
|
+
}
|
|
165466
166016
|
const canonicalContent = canonicalizeDocContent(readFileSync4(filePath, "utf8"));
|
|
165467
166017
|
hashPieces.push(`file:${filename}
|
|
165468
166018
|
${canonicalContent}`);
|
|
@@ -165629,6 +166179,7 @@ function getMaxMemoryMutationId(db, projectPath) {
|
|
|
165629
166179
|
return row?.max_id ?? null;
|
|
165630
166180
|
}
|
|
165631
166181
|
// ../plugin/src/features/magic-context/storage-meta-persisted.ts
|
|
166182
|
+
init_logger();
|
|
165632
166183
|
var CAS_RETRY_LIMIT = 5;
|
|
165633
166184
|
var AUTO_SEARCH_NO_HINT_REASONS = new Set([
|
|
165634
166185
|
"below-threshold",
|
|
@@ -165638,12 +166189,6 @@ var AUTO_SEARCH_NO_HINT_REASONS = new Set([
|
|
|
165638
166189
|
"stacked",
|
|
165639
166190
|
"too-short"
|
|
165640
166191
|
]);
|
|
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
166192
|
function isPersistedNoteNudgeRow(row) {
|
|
165648
166193
|
if (row === null || typeof row !== "object")
|
|
165649
166194
|
return false;
|
|
@@ -165709,6 +166254,139 @@ function getDefaultHistorianFailureState() {
|
|
|
165709
166254
|
lastFailureAt: null
|
|
165710
166255
|
};
|
|
165711
166256
|
}
|
|
166257
|
+
var DEFAULT_PROTECTED_TAIL_META = {
|
|
166258
|
+
priorBoundaryOrdinal: 1,
|
|
166259
|
+
protectedTailPolicyVersion: 0,
|
|
166260
|
+
protectedTailDrainWindowStartedAt: 0,
|
|
166261
|
+
protectedTailDrainTokens: 0,
|
|
166262
|
+
recoveryNoEligibleHeadCount: 0,
|
|
166263
|
+
forceEmergencyBypassWindowStart: 0,
|
|
166264
|
+
forceEmergencyBypassUsed: 0
|
|
166265
|
+
};
|
|
166266
|
+
function toProtectedTailMeta(row) {
|
|
166267
|
+
if (row === null || typeof row !== "object")
|
|
166268
|
+
return { ...DEFAULT_PROTECTED_TAIL_META };
|
|
166269
|
+
const r = row;
|
|
166270
|
+
const numberOr = (value, fallback) => typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
166271
|
+
return {
|
|
166272
|
+
priorBoundaryOrdinal: Math.max(1, numberOr(r.prior_boundary_ordinal, 1)),
|
|
166273
|
+
protectedTailPolicyVersion: numberOr(r.protected_tail_policy_version, 0),
|
|
166274
|
+
protectedTailDrainWindowStartedAt: numberOr(r.protected_tail_drain_window_started_at, 0),
|
|
166275
|
+
protectedTailDrainTokens: numberOr(r.protected_tail_drain_tokens, 0),
|
|
166276
|
+
recoveryNoEligibleHeadCount: numberOr(r.recovery_no_eligible_head_count, 0),
|
|
166277
|
+
forceEmergencyBypassWindowStart: numberOr(r.force_emergency_bypass_window_start, 0),
|
|
166278
|
+
forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0)
|
|
166279
|
+
};
|
|
166280
|
+
}
|
|
166281
|
+
function loadProtectedTailMeta(db, sessionId) {
|
|
166282
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166283
|
+
const row = db.prepare(`SELECT prior_boundary_ordinal, protected_tail_policy_version,
|
|
166284
|
+
protected_tail_drain_window_started_at, protected_tail_drain_tokens,
|
|
166285
|
+
recovery_no_eligible_head_count, force_emergency_bypass_window_start,
|
|
166286
|
+
force_emergency_bypass_used
|
|
166287
|
+
FROM session_meta WHERE session_id = ?`).get(sessionId);
|
|
166288
|
+
return toProtectedTailMeta(row);
|
|
166289
|
+
}
|
|
166290
|
+
function markProtectedTailPolicyV3Seeded(db, sessionId, priorBoundaryOrdinal) {
|
|
166291
|
+
let seeded = false;
|
|
166292
|
+
db.transaction(() => {
|
|
166293
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166294
|
+
const existing = loadProtectedTailMeta(db, sessionId);
|
|
166295
|
+
if (existing.protectedTailPolicyVersion < 3) {
|
|
166296
|
+
db.prepare(`UPDATE session_meta
|
|
166297
|
+
SET prior_boundary_ordinal = ?, protected_tail_policy_version = 3
|
|
166298
|
+
WHERE session_id = ? AND protected_tail_policy_version < 3`).run(Math.max(1, Math.floor(priorBoundaryOrdinal)), sessionId);
|
|
166299
|
+
seeded = true;
|
|
166300
|
+
}
|
|
166301
|
+
})();
|
|
166302
|
+
return { ...loadProtectedTailMeta(db, sessionId), seeded };
|
|
166303
|
+
}
|
|
166304
|
+
function recordProtectedTailPublicationFloor(db, sessionId, floorOrdinal) {
|
|
166305
|
+
db.transaction(() => {
|
|
166306
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166307
|
+
db.prepare(`UPDATE session_meta
|
|
166308
|
+
SET prior_boundary_ordinal = MAX(COALESCE(prior_boundary_ordinal, 1), ?),
|
|
166309
|
+
recovery_no_eligible_head_count = 0
|
|
166310
|
+
WHERE session_id = ?`).run(Math.max(1, Math.floor(floorOrdinal)), sessionId);
|
|
166311
|
+
})();
|
|
166312
|
+
}
|
|
166313
|
+
function recordProtectedTailNoEligibleHead(db, sessionId) {
|
|
166314
|
+
db.transaction(() => {
|
|
166315
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166316
|
+
db.prepare(`UPDATE session_meta
|
|
166317
|
+
SET recovery_no_eligible_head_count = COALESCE(recovery_no_eligible_head_count, 0) + 1
|
|
166318
|
+
WHERE session_id = ?`).run(sessionId);
|
|
166319
|
+
})();
|
|
166320
|
+
return loadProtectedTailMeta(db, sessionId).recoveryNoEligibleHeadCount;
|
|
166321
|
+
}
|
|
166322
|
+
var DRAIN_WINDOW_MS = 10 * 60 * 1000;
|
|
166323
|
+
function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
166324
|
+
if (usagePercentage >= 95)
|
|
166325
|
+
return Math.min(1e6, Math.max(4 * perRunCap, Math.round(0.5 * usable)));
|
|
166326
|
+
if (usagePercentage >= 80)
|
|
166327
|
+
return Math.min(750000, Math.max(3 * perRunCap, Math.round(0.35 * usable)));
|
|
166328
|
+
return Math.min(500000, Math.max(perRunCap, Math.round(0.2 * usable)));
|
|
166329
|
+
}
|
|
166330
|
+
function reserveProtectedTailDrainTokens(args) {
|
|
166331
|
+
const now = args.now ?? Date.now();
|
|
166332
|
+
const requested = Math.max(0, Math.floor(args.trueRawTokens));
|
|
166333
|
+
if (requested === 0) {
|
|
166334
|
+
return { ok: true, reservedTokens: 0, overQuotaBypass: false, reservation: null };
|
|
166335
|
+
}
|
|
166336
|
+
let result = {
|
|
166337
|
+
ok: false,
|
|
166338
|
+
reservedTokens: 0,
|
|
166339
|
+
overQuotaBypass: false,
|
|
166340
|
+
reservation: null,
|
|
166341
|
+
skippedReason: "quota exhausted"
|
|
166342
|
+
};
|
|
166343
|
+
args.db.transaction(() => {
|
|
166344
|
+
ensureSessionMetaRow(args.db, args.sessionId);
|
|
166345
|
+
let meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
166346
|
+
if (now - meta3.protectedTailDrainWindowStartedAt > DRAIN_WINDOW_MS) {
|
|
166347
|
+
args.db.prepare(`UPDATE session_meta
|
|
166348
|
+
SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0,
|
|
166349
|
+
force_emergency_bypass_window_start = ?, force_emergency_bypass_used = 0
|
|
166350
|
+
WHERE session_id = ?`).run(now, now, args.sessionId);
|
|
166351
|
+
meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
166352
|
+
}
|
|
166353
|
+
const budget = protectedTailWindowBudget(args.usagePercentage, args.usable, args.perRunCap);
|
|
166354
|
+
const remaining = Math.max(0, budget - meta3.protectedTailDrainTokens);
|
|
166355
|
+
let reserved = Math.min(requested, args.perRunCap, remaining);
|
|
166356
|
+
let bypass = false;
|
|
166357
|
+
const bypassWindowExpired = now - meta3.forceEmergencyBypassWindowStart > DRAIN_WINDOW_MS;
|
|
166358
|
+
const bypassUsed = bypassWindowExpired ? 0 : meta3.forceEmergencyBypassUsed;
|
|
166359
|
+
if (reserved <= 0 && args.usagePercentage >= 95 && bypassUsed === 0) {
|
|
166360
|
+
reserved = Math.min(requested, args.perRunCap);
|
|
166361
|
+
bypass = true;
|
|
166362
|
+
}
|
|
166363
|
+
if (reserved <= 0)
|
|
166364
|
+
return;
|
|
166365
|
+
args.db.prepare(`UPDATE session_meta
|
|
166366
|
+
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,
|
|
166367
|
+
protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) + ?,
|
|
166368
|
+
force_emergency_bypass_window_start = CASE WHEN ? THEN ? ELSE force_emergency_bypass_window_start END,
|
|
166369
|
+
force_emergency_bypass_used = CASE WHEN ? THEN 1 ELSE force_emergency_bypass_used END
|
|
166370
|
+
WHERE session_id = ?`).run(now, reserved, bypass ? 1 : 0, now, bypass ? 1 : 0, args.sessionId);
|
|
166371
|
+
result = {
|
|
166372
|
+
ok: true,
|
|
166373
|
+
reservedTokens: reserved,
|
|
166374
|
+
overQuotaBypass: bypass,
|
|
166375
|
+
reservation: { sessionId: args.sessionId, runId: args.runId, tokens: reserved }
|
|
166376
|
+
};
|
|
166377
|
+
})();
|
|
166378
|
+
return result;
|
|
166379
|
+
}
|
|
166380
|
+
function rollbackProtectedTailDrainReservation(db, reservation) {
|
|
166381
|
+
if (!reservation || reservation.tokens <= 0)
|
|
166382
|
+
return;
|
|
166383
|
+
db.transaction(() => {
|
|
166384
|
+
ensureSessionMetaRow(db, reservation.sessionId);
|
|
166385
|
+
db.prepare(`UPDATE session_meta
|
|
166386
|
+
SET protected_tail_drain_tokens = MAX(0, COALESCE(protected_tail_drain_tokens, 0) - ?)
|
|
166387
|
+
WHERE session_id = ?`).run(reservation.tokens, reservation.sessionId);
|
|
166388
|
+
})();
|
|
166389
|
+
}
|
|
165712
166390
|
function setPersistedReasoningWatermark(db, sessionId, tagNumber) {
|
|
165713
166391
|
ensureSessionMetaRow(db, sessionId);
|
|
165714
166392
|
db.prepare("UPDATE session_meta SET cleared_reasoning_through_tag = ? WHERE session_id = ?").run(tagNumber, sessionId);
|
|
@@ -165716,27 +166394,95 @@ function setPersistedReasoningWatermark(db, sessionId, tagNumber) {
|
|
|
165716
166394
|
function clearPersistedReasoningWatermark(db, sessionId) {
|
|
165717
166395
|
setPersistedReasoningWatermark(db, sessionId, 0);
|
|
165718
166396
|
}
|
|
165719
|
-
function
|
|
165720
|
-
|
|
165721
|
-
|
|
165722
|
-
|
|
165723
|
-
|
|
165724
|
-
|
|
165725
|
-
|
|
165726
|
-
|
|
165727
|
-
|
|
165728
|
-
|
|
165729
|
-
|
|
165730
|
-
};
|
|
166397
|
+
function isEmergencyInputSampleRow(row) {
|
|
166398
|
+
return typeof row === "object" && row !== null && typeof row.last_emergency_input_sample === "number";
|
|
166399
|
+
}
|
|
166400
|
+
function getEmergencyInputSample(db, sessionId) {
|
|
166401
|
+
const result = db.prepare("SELECT last_emergency_input_sample FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166402
|
+
return isEmergencyInputSampleRow(result) ? result.last_emergency_input_sample : 0;
|
|
166403
|
+
}
|
|
166404
|
+
function setEmergencyDropSample(db, sessionId, inputSample) {
|
|
166405
|
+
db.transaction(() => {
|
|
166406
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166407
|
+
db.prepare("UPDATE session_meta SET last_emergency_input_sample = ? WHERE session_id = ?").run(Math.max(0, Math.round(inputSample)), sessionId);
|
|
166408
|
+
})();
|
|
165731
166409
|
}
|
|
165732
|
-
function
|
|
166410
|
+
function clearEmergencyDropSample(db, sessionId) {
|
|
165733
166411
|
db.transaction(() => {
|
|
165734
166412
|
ensureSessionMetaRow(db, sessionId);
|
|
165735
|
-
db.prepare("UPDATE session_meta SET
|
|
166413
|
+
db.prepare("UPDATE session_meta SET last_emergency_input_sample = 0 WHERE session_id = ?").run(sessionId);
|
|
165736
166414
|
})();
|
|
165737
166415
|
}
|
|
165738
|
-
function
|
|
165739
|
-
|
|
166416
|
+
function isLastNudgeUndroppedRow(row) {
|
|
166417
|
+
return typeof row === "object" && row !== null && typeof row.last_nudge_undropped === "number";
|
|
166418
|
+
}
|
|
166419
|
+
function isLastNudgeLevelRow(row) {
|
|
166420
|
+
return typeof row === "object" && row !== null && typeof row.last_nudge_level === "string";
|
|
166421
|
+
}
|
|
166422
|
+
function normalizeLastNudgeLevel(value) {
|
|
166423
|
+
return value === "gentle" || value === "firm" || value === "urgent" ? value : "";
|
|
166424
|
+
}
|
|
166425
|
+
function getLastNudgeUndropped(db, sessionId) {
|
|
166426
|
+
const result = db.prepare("SELECT last_nudge_undropped FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166427
|
+
return isLastNudgeUndroppedRow(result) ? result.last_nudge_undropped : 0;
|
|
166428
|
+
}
|
|
166429
|
+
function setLastNudgeUndropped(db, sessionId, value) {
|
|
166430
|
+
db.transaction(() => {
|
|
166431
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166432
|
+
db.prepare("UPDATE session_meta SET last_nudge_undropped = ? WHERE session_id = ?").run(Math.max(0, Math.round(value)), sessionId);
|
|
166433
|
+
})();
|
|
166434
|
+
}
|
|
166435
|
+
function getLastNudgeLevel(db, sessionId) {
|
|
166436
|
+
const result = db.prepare("SELECT last_nudge_level FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166437
|
+
return isLastNudgeLevelRow(result) ? normalizeLastNudgeLevel(result.last_nudge_level) : "";
|
|
166438
|
+
}
|
|
166439
|
+
function setLastNudgeLevel(db, sessionId, value) {
|
|
166440
|
+
db.transaction(() => {
|
|
166441
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166442
|
+
db.prepare("UPDATE session_meta SET last_nudge_level = ? WHERE session_id = ?").run(normalizeLastNudgeLevel(value), sessionId);
|
|
166443
|
+
})();
|
|
166444
|
+
}
|
|
166445
|
+
function resetLastNudgeCycle(db, sessionId) {
|
|
166446
|
+
db.transaction(() => {
|
|
166447
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166448
|
+
db.prepare("UPDATE session_meta SET last_nudge_undropped = 0, last_nudge_level = '' WHERE session_id = ?").run(sessionId);
|
|
166449
|
+
})();
|
|
166450
|
+
}
|
|
166451
|
+
function resetLastNudgeCycleIfTailShrank(db, sessionId, measuredUndropped) {
|
|
166452
|
+
let changed = false;
|
|
166453
|
+
db.transaction(() => {
|
|
166454
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166455
|
+
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)));
|
|
166456
|
+
changed = (result.changes ?? 0) > 0;
|
|
166457
|
+
})();
|
|
166458
|
+
return changed;
|
|
166459
|
+
}
|
|
166460
|
+
function isChannel2StateRow(row) {
|
|
166461
|
+
return typeof row === "object" && row !== null && typeof row.channel2_nudge_state === "string";
|
|
166462
|
+
}
|
|
166463
|
+
function getChannel2NudgeState(db, sessionId) {
|
|
166464
|
+
const result = db.prepare("SELECT channel2_nudge_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166465
|
+
if (!isChannel2StateRow(result))
|
|
166466
|
+
return "";
|
|
166467
|
+
const raw = result.channel2_nudge_state;
|
|
166468
|
+
return raw === "pending" || raw === "claimed" || raw === "delivered" ? raw : "";
|
|
166469
|
+
}
|
|
166470
|
+
function setChannel2NudgeState(db, sessionId, state) {
|
|
166471
|
+
db.transaction(() => {
|
|
166472
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166473
|
+
const claimedAt = state === "claimed" ? Date.now() : 0;
|
|
166474
|
+
db.prepare("UPDATE session_meta SET channel2_nudge_state = ?, channel2_nudge_claimed_at = ? WHERE session_id = ?").run(state, claimedAt, sessionId);
|
|
166475
|
+
})();
|
|
166476
|
+
}
|
|
166477
|
+
function casChannel2NudgeState(db, sessionId, from, to) {
|
|
166478
|
+
let changed = false;
|
|
166479
|
+
db.transaction(() => {
|
|
166480
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166481
|
+
const claimedAt = to === "claimed" ? Date.now() : 0;
|
|
166482
|
+
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);
|
|
166483
|
+
changed = (result.changes ?? 0) > 0;
|
|
166484
|
+
})();
|
|
166485
|
+
return changed;
|
|
165740
166486
|
}
|
|
165741
166487
|
function getPersistedNoteNudge(db, sessionId) {
|
|
165742
166488
|
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 +166529,8 @@ function casUpdateJsonArrayColumn(db, sessionId, column, validator, mutate, opti
|
|
|
165783
166529
|
}
|
|
165784
166530
|
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
165785
166531
|
const row = db.prepare(`SELECT ${column} FROM session_meta WHERE session_id = ?`).get(sessionId);
|
|
165786
|
-
const
|
|
166532
|
+
const rawCurrent = row?.[column] ?? null;
|
|
166533
|
+
const currentBlob = rawCurrent ?? "[]";
|
|
165787
166534
|
const current = parseJsonArray(currentBlob, validator);
|
|
165788
166535
|
const next = mutate(current);
|
|
165789
166536
|
if (next === null)
|
|
@@ -165791,7 +166538,7 @@ function casUpdateJsonArrayColumn(db, sessionId, column, validator, mutate, opti
|
|
|
165791
166538
|
const nextBlob = stableStringify(next);
|
|
165792
166539
|
if (nextBlob === currentBlob)
|
|
165793
166540
|
return true;
|
|
165794
|
-
const result = db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ? AND ${column}
|
|
166541
|
+
const result = db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ? AND ${column} IS ?`).run(nextBlob, sessionId, rawCurrent);
|
|
165795
166542
|
if (result.changes > 0)
|
|
165796
166543
|
return true;
|
|
165797
166544
|
}
|
|
@@ -165920,14 +166667,16 @@ function getHistorianFailureState(db, sessionId) {
|
|
|
165920
166667
|
};
|
|
165921
166668
|
}
|
|
165922
166669
|
function incrementHistorianFailure(db, sessionId, error51) {
|
|
166670
|
+
let nextCount = 1;
|
|
165923
166671
|
db.transaction(() => {
|
|
165924
166672
|
ensureSessionMetaRow(db, sessionId);
|
|
165925
166673
|
const current = getHistorianFailureState(db, sessionId);
|
|
165926
|
-
|
|
166674
|
+
nextCount = current.failureCount + 1;
|
|
165927
166675
|
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
166676
|
const reason = error51.replace(/\s+/g, " ").trim().slice(0, 300);
|
|
165929
166677
|
sessionLog(sessionId, `historian failure recorded: count=${nextCount} reason="${reason}"`);
|
|
165930
166678
|
})();
|
|
166679
|
+
return nextCount;
|
|
165931
166680
|
}
|
|
165932
166681
|
function clearHistorianFailureState(db, sessionId) {
|
|
165933
166682
|
db.transaction(() => {
|
|
@@ -165957,7 +166706,11 @@ function recordOverflowDetected(db, sessionId, reportedLimit) {
|
|
|
165957
166706
|
function clearEmergencyRecovery(db, sessionId) {
|
|
165958
166707
|
db.transaction(() => {
|
|
165959
166708
|
ensureSessionMetaRow(db, sessionId);
|
|
165960
|
-
|
|
166709
|
+
try {
|
|
166710
|
+
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0, recovery_no_eligible_head_count = 0 WHERE session_id = ?").run(sessionId);
|
|
166711
|
+
} catch {
|
|
166712
|
+
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0 WHERE session_id = ?").run(sessionId);
|
|
166713
|
+
}
|
|
165961
166714
|
})();
|
|
165962
166715
|
}
|
|
165963
166716
|
function clearDetectedContextLimit(db, sessionId) {
|
|
@@ -165996,10 +166749,39 @@ function getStrippedPlaceholderIds(db, sessionId) {
|
|
|
165996
166749
|
} catch {}
|
|
165997
166750
|
return new Set;
|
|
165998
166751
|
}
|
|
165999
|
-
function
|
|
166752
|
+
function applyStrippedPlaceholderDelta(db, sessionId, delta) {
|
|
166753
|
+
const add = delta.add ? [...delta.add] : [];
|
|
166754
|
+
const remove = delta.remove ? [...delta.remove] : [];
|
|
166755
|
+
if (add.length === 0 && remove.length === 0)
|
|
166756
|
+
return true;
|
|
166000
166757
|
ensureSessionMetaRow(db, sessionId);
|
|
166001
|
-
|
|
166002
|
-
|
|
166758
|
+
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
166759
|
+
const row = db.prepare("SELECT stripped_placeholder_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166760
|
+
const rawStored = row ? row.stripped_placeholder_ids ?? null : null;
|
|
166761
|
+
const current = new Set(parseStrippedBlob(rawStored));
|
|
166762
|
+
for (const id of add)
|
|
166763
|
+
current.add(id);
|
|
166764
|
+
for (const id of remove)
|
|
166765
|
+
current.delete(id);
|
|
166766
|
+
const nextBlob = current.size > 0 ? JSON.stringify([...current]) : "";
|
|
166767
|
+
if (nextBlob === (rawStored ?? ""))
|
|
166768
|
+
return true;
|
|
166769
|
+
const result = db.prepare("UPDATE session_meta SET stripped_placeholder_ids = ? WHERE session_id = ? AND stripped_placeholder_ids IS ?").run(nextBlob, sessionId, rawStored);
|
|
166770
|
+
if (result.changes > 0)
|
|
166771
|
+
return true;
|
|
166772
|
+
}
|
|
166773
|
+
sessionLog(sessionId, `stripped_placeholder_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
|
|
166774
|
+
return false;
|
|
166775
|
+
}
|
|
166776
|
+
function parseStrippedBlob(raw) {
|
|
166777
|
+
if (!raw || raw.length === 0)
|
|
166778
|
+
return [];
|
|
166779
|
+
try {
|
|
166780
|
+
const parsed = JSON.parse(raw);
|
|
166781
|
+
if (Array.isArray(parsed))
|
|
166782
|
+
return parsed.filter((v) => typeof v === "string");
|
|
166783
|
+
} catch {}
|
|
166784
|
+
return [];
|
|
166003
166785
|
}
|
|
166004
166786
|
function isPendingCompactionMarker(value) {
|
|
166005
166787
|
return typeof value === "object" && value !== null && typeof value.ordinal === "number" && typeof value.endMessageId === "string" && typeof value.publishedAt === "number";
|
|
@@ -166091,6 +166873,7 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
|
|
|
166091
166873
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
166092
166874
|
|
|
166093
166875
|
// ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
|
|
166876
|
+
init_logger();
|
|
166094
166877
|
function resolveIsSubagentFromOpenCodeDb(sessionId) {
|
|
166095
166878
|
try {
|
|
166096
166879
|
return withReadOnlySessionDb((openCodeDb) => {
|
|
@@ -166309,7 +167092,8 @@ function updateNote(db, noteId, updates, scope) {
|
|
|
166309
167092
|
sets.push("session_id = ?");
|
|
166310
167093
|
params.push(updates.sessionId);
|
|
166311
167094
|
}
|
|
166312
|
-
|
|
167095
|
+
const smartConditionChanged = existing.type === "smart" && updates.surfaceCondition !== undefined && updates.surfaceCondition !== existing.surfaceCondition;
|
|
167096
|
+
if (updates.status !== undefined && !smartConditionChanged) {
|
|
166313
167097
|
sets.push("status = ?");
|
|
166314
167098
|
params.push(updates.status);
|
|
166315
167099
|
}
|
|
@@ -166322,17 +167106,21 @@ function updateNote(db, noteId, updates, scope) {
|
|
|
166322
167106
|
sets.push("surface_condition = ?");
|
|
166323
167107
|
params.push(updates.surfaceCondition);
|
|
166324
167108
|
}
|
|
166325
|
-
if (
|
|
166326
|
-
sets.push("last_checked_at =
|
|
166327
|
-
|
|
166328
|
-
|
|
166329
|
-
|
|
166330
|
-
|
|
166331
|
-
|
|
166332
|
-
|
|
166333
|
-
|
|
166334
|
-
|
|
166335
|
-
|
|
167109
|
+
if (smartConditionChanged) {
|
|
167110
|
+
sets.push("status = 'pending'", "last_checked_at = NULL", "ready_at = NULL", "ready_reason = NULL");
|
|
167111
|
+
} else {
|
|
167112
|
+
if (updates.lastCheckedAt !== undefined) {
|
|
167113
|
+
sets.push("last_checked_at = ?");
|
|
167114
|
+
params.push(updates.lastCheckedAt);
|
|
167115
|
+
}
|
|
167116
|
+
if (updates.readyAt !== undefined) {
|
|
167117
|
+
sets.push("ready_at = ?");
|
|
167118
|
+
params.push(updates.readyAt);
|
|
167119
|
+
}
|
|
167120
|
+
if (updates.readyReason !== undefined) {
|
|
167121
|
+
sets.push("ready_reason = ?");
|
|
167122
|
+
params.push(updates.readyReason);
|
|
167123
|
+
}
|
|
166336
167124
|
}
|
|
166337
167125
|
}
|
|
166338
167126
|
if (sets.length === 1) {
|
|
@@ -166359,6 +167147,7 @@ function markNoteChecked(db, noteId) {
|
|
|
166359
167147
|
db.prepare("UPDATE notes SET last_checked_at = ?, updated_at = ? WHERE id = ? AND type = 'smart'").run(now, now, noteId);
|
|
166360
167148
|
}
|
|
166361
167149
|
// ../plugin/src/features/magic-context/storage-ops.ts
|
|
167150
|
+
init_logger();
|
|
166362
167151
|
var queuePendingOpStatements = new WeakMap;
|
|
166363
167152
|
var getPendingOpsStatements = new WeakMap;
|
|
166364
167153
|
var clearPendingOpsStatements = new WeakMap;
|
|
@@ -166521,7 +167310,7 @@ var getTagNumberByMessageIdStatements = new WeakMap;
|
|
|
166521
167310
|
function getInsertTagStatement(db) {
|
|
166522
167311
|
let stmt = insertTagStatements.get(db);
|
|
166523
167312
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
167313
|
+
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
167314
|
insertTagStatements.set(db, stmt);
|
|
166526
167315
|
}
|
|
166527
167316
|
return stmt;
|
|
@@ -166563,9 +167352,95 @@ function getUpdateTagInputByteSizeStatement(db) {
|
|
|
166563
167352
|
function updateTagByteSize(db, sessionId, tagNumber, newByteSize) {
|
|
166564
167353
|
getUpdateTagByteSizeStatement(db).run(newByteSize, sessionId, tagNumber);
|
|
166565
167354
|
}
|
|
167355
|
+
var CONTENT_ID_SUFFIX = /:(?:p|file)\d+$/;
|
|
167356
|
+
function ownerMessageIdForTagRow(row) {
|
|
167357
|
+
if (row.type === "tool") {
|
|
167358
|
+
return row.tool_owner_message_id ?? row.message_id;
|
|
167359
|
+
}
|
|
167360
|
+
return row.message_id.replace(CONTENT_ID_SUFFIX, "");
|
|
167361
|
+
}
|
|
167362
|
+
function getActiveTagTokenAggregate(db, sessionId) {
|
|
167363
|
+
const row = db.prepare(`SELECT
|
|
167364
|
+
COALESCE(SUM(CASE WHEN type != 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)
|
|
167365
|
+
+ COALESCE(SUM(COALESCE(reasoning_token_count, 0)), 0) AS conversation,
|
|
167366
|
+
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) + COALESCE(input_token_count, 0) ELSE 0 END), 0) AS tool_call,
|
|
167367
|
+
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0) AS tool_output,
|
|
167368
|
+
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
167369
|
+
FROM tags
|
|
167370
|
+
WHERE session_id = ? AND status = 'active'`).get(sessionId);
|
|
167371
|
+
return {
|
|
167372
|
+
conversation: row?.conversation ?? 0,
|
|
167373
|
+
toolCall: row?.tool_call ?? 0,
|
|
167374
|
+
toolOutput: row?.tool_output ?? 0,
|
|
167375
|
+
nullCount: row?.null_count ?? 0
|
|
167376
|
+
};
|
|
167377
|
+
}
|
|
167378
|
+
function getTriggerTagTokenUpperBound(db, sessionId) {
|
|
167379
|
+
const row = db.prepare(`SELECT
|
|
167380
|
+
COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
|
|
167381
|
+
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
167382
|
+
FROM tags
|
|
167383
|
+
WHERE session_id = ? AND status IN ('active', 'dropped')`).get(sessionId);
|
|
167384
|
+
return { bound: row?.bound ?? 0, nullCount: row?.null_count ?? 0 };
|
|
167385
|
+
}
|
|
166566
167386
|
function updateTagInputByteSize(db, sessionId, tagNumber, newInputByteSize) {
|
|
166567
167387
|
getUpdateTagInputByteSizeStatement(db).run(newInputByteSize, sessionId, tagNumber);
|
|
166568
167388
|
}
|
|
167389
|
+
var updateTagTokenCountStatements = new WeakMap;
|
|
167390
|
+
var updateTagInputTokenCountStatements = new WeakMap;
|
|
167391
|
+
function getUpdateTagTokenCountStatement(db) {
|
|
167392
|
+
let stmt = updateTagTokenCountStatements.get(db);
|
|
167393
|
+
if (!stmt) {
|
|
167394
|
+
stmt = db.prepare("UPDATE tags SET token_count = ? WHERE session_id = ? AND tag_number = ?");
|
|
167395
|
+
updateTagTokenCountStatements.set(db, stmt);
|
|
167396
|
+
}
|
|
167397
|
+
return stmt;
|
|
167398
|
+
}
|
|
167399
|
+
function getUpdateTagInputTokenCountStatement(db) {
|
|
167400
|
+
let stmt = updateTagInputTokenCountStatements.get(db);
|
|
167401
|
+
if (!stmt) {
|
|
167402
|
+
stmt = db.prepare("UPDATE tags SET input_token_count = ? WHERE session_id = ? AND tag_number = ?");
|
|
167403
|
+
updateTagInputTokenCountStatements.set(db, stmt);
|
|
167404
|
+
}
|
|
167405
|
+
return stmt;
|
|
167406
|
+
}
|
|
167407
|
+
function updateTagTokenCount(db, sessionId, tagNumber, newTokenCount) {
|
|
167408
|
+
getUpdateTagTokenCountStatement(db).run(newTokenCount, sessionId, tagNumber);
|
|
167409
|
+
}
|
|
167410
|
+
function getAllStatusTagTokenTotalsFlat(db, sessionId) {
|
|
167411
|
+
const rows = db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
167412
|
+
FROM tags
|
|
167413
|
+
WHERE session_id = ?`).all(sessionId);
|
|
167414
|
+
const totals = new Map;
|
|
167415
|
+
const nullMessageIds = new Set;
|
|
167416
|
+
for (const row of rows) {
|
|
167417
|
+
if (row.type === "tool" && row.tool_owner_message_id === null)
|
|
167418
|
+
continue;
|
|
167419
|
+
const owner = ownerMessageIdForTagRow(row);
|
|
167420
|
+
if (row.token_count === null) {
|
|
167421
|
+
nullMessageIds.add(owner);
|
|
167422
|
+
totals.delete(owner);
|
|
167423
|
+
continue;
|
|
167424
|
+
}
|
|
167425
|
+
if (nullMessageIds.has(owner))
|
|
167426
|
+
continue;
|
|
167427
|
+
const weight = (row.token_count ?? 0) + (row.input_token_count ?? 0) + (row.reasoning_token_count ?? 0);
|
|
167428
|
+
totals.set(owner, (totals.get(owner) ?? 0) + weight);
|
|
167429
|
+
}
|
|
167430
|
+
return { totals, nullMessageIds };
|
|
167431
|
+
}
|
|
167432
|
+
function updateTagInputTokenCount(db, sessionId, tagNumber, newInputTokenCount) {
|
|
167433
|
+
getUpdateTagInputTokenCountStatement(db).run(newInputTokenCount, sessionId, tagNumber);
|
|
167434
|
+
}
|
|
167435
|
+
function tagTokenCountIsNull(db, sessionId, tagNumber) {
|
|
167436
|
+
const row = db.prepare("SELECT token_count FROM tags WHERE session_id = ? AND tag_number = ?").get(sessionId, tagNumber);
|
|
167437
|
+
return row !== undefined && row.token_count === null;
|
|
167438
|
+
}
|
|
167439
|
+
function backfillTagTokenCounts(db, sessionId, tagNumber, counts) {
|
|
167440
|
+
db.prepare(`UPDATE tags
|
|
167441
|
+
SET token_count = ?, input_token_count = ?, reasoning_token_count = ?
|
|
167442
|
+
WHERE session_id = ? AND tag_number = ? AND token_count IS NULL`).run(counts.tokenCount ?? null, counts.inputTokenCount ?? null, counts.reasoningTokenCount ?? null, sessionId, tagNumber);
|
|
167443
|
+
}
|
|
166569
167444
|
function getMaxTagNumberBySessionStatement(db) {
|
|
166570
167445
|
let stmt = getMaxTagNumberBySessionStatements.get(db);
|
|
166571
167446
|
if (!stmt) {
|
|
@@ -166618,8 +167493,8 @@ function isMaxTagNumberRow(row) {
|
|
|
166618
167493
|
const r = row;
|
|
166619
167494
|
return typeof r.max_tag_number === "number";
|
|
166620
167495
|
}
|
|
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);
|
|
167496
|
+
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0, toolOwnerMessageId = null, entryFingerprint = null, tokenCounts = null) {
|
|
167497
|
+
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness(), toolOwnerMessageId, entryFingerprint, tokenCounts?.tokenCount ?? null, tokenCounts?.inputTokenCount ?? null, tokenCounts?.reasoningTokenCount ?? null);
|
|
166623
167498
|
return tagNumber;
|
|
166624
167499
|
}
|
|
166625
167500
|
function updateTagStatus(db, sessionId, tagId, status) {
|
|
@@ -166687,13 +167562,6 @@ function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
|
166687
167562
|
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
167563
|
return rows.map(toTagEntry);
|
|
166689
167564
|
}
|
|
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
167565
|
var getToolTagNumberByOwnerStatements = new WeakMap;
|
|
166698
167566
|
var getNullOwnerToolTagStatements = new WeakMap;
|
|
166699
167567
|
var adoptNullOwnerToolTagStatements = new WeakMap;
|
|
@@ -166759,44 +167627,43 @@ var ERROR_CLASSES = new Set([
|
|
|
166759
167627
|
"permission_denied",
|
|
166760
167628
|
"unknown"
|
|
166761
167629
|
]);
|
|
167630
|
+
// src/tools/ctx-memory.ts
|
|
167631
|
+
init_logger();
|
|
167632
|
+
|
|
167633
|
+
// ../plugin/src/tools/ctx-memory/constants.ts
|
|
167634
|
+
var CTX_MEMORY_DESCRIPTION = `Durable project knowledge shared across every session on this project.
|
|
167635
|
+
|
|
167636
|
+
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.
|
|
167637
|
+
|
|
167638
|
+
Actions:
|
|
167639
|
+
- write: save a new memory (content + category).
|
|
167640
|
+
- update: rewrite one memory whose fact changed (ids: [one], content).
|
|
167641
|
+
- archive: retire wrong or obsolete memories (ids: [one or more], optional reason).
|
|
167642
|
+
- merge: collapse duplicates into one memory (ids: [two or more], content).
|
|
167643
|
+
|
|
167644
|
+
Example: ctx_memory(action="write", category="CONSTRAINTS", content="Pi stores sessions as JSONL under ~/.pi/agent/sessions/, not SQLite")`;
|
|
167645
|
+
|
|
166762
167646
|
// src/tools/ctx-memory.ts
|
|
166763
167647
|
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
|
-
]);
|
|
167648
|
+
var ALL_ACTIONS = ["write", "archive", "update", "merge", "list"];
|
|
167649
|
+
var DREAMER_ONLY_ACTIONS = new Set(["list"]);
|
|
166782
167650
|
var ParamsSchema2 = exports_typebox.Object({
|
|
166783
|
-
action: exports_typebox.Union(ALL_ACTIONS.map((a) => exports_typebox.Literal(a)), { description: "
|
|
167651
|
+
action: exports_typebox.Union(ALL_ACTIONS.map((a) => exports_typebox.Literal(a)), { description: "What to do: write, update, archive, or merge" }),
|
|
166784
167652
|
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(", ")
|
|
167653
|
+
description: "The memory text — one standalone fact (required for write, update, merge)"
|
|
166789
167654
|
})),
|
|
166790
|
-
|
|
166791
|
-
description: "
|
|
167655
|
+
category: exports_typebox.Optional(exports_typebox.Union(V2_MEMORY_CATEGORIES.map((c) => exports_typebox.Literal(c)), {
|
|
167656
|
+
description: "What kind of fact this is (required for write; optional merge override)"
|
|
166792
167657
|
})),
|
|
166793
167658
|
ids: exports_typebox.Optional(exports_typebox.Array(exports_typebox.Number(), {
|
|
166794
|
-
description: "
|
|
167659
|
+
description: "Target memory id(s) from <project-memory>: update takes exactly one, archive one or more, merge two or more"
|
|
166795
167660
|
})),
|
|
166796
167661
|
limit: exports_typebox.Optional(exports_typebox.Number({
|
|
166797
|
-
description: "
|
|
167662
|
+
description: "Max results for list (default: 10)"
|
|
166798
167663
|
})),
|
|
166799
|
-
reason: exports_typebox.Optional(exports_typebox.String({
|
|
167664
|
+
reason: exports_typebox.Optional(exports_typebox.String({
|
|
167665
|
+
description: "Why the memory is being archived (optional, recommended)"
|
|
167666
|
+
}))
|
|
166800
167667
|
});
|
|
166801
167668
|
function ok2(text) {
|
|
166802
167669
|
return { content: [{ type: "text", text }], details: undefined };
|
|
@@ -166843,6 +167710,12 @@ function formatMemoryList(memories) {
|
|
|
166843
167710
|
].join(`
|
|
166844
167711
|
`);
|
|
166845
167712
|
}
|
|
167713
|
+
function isPrimaryMutableMemory(memory2) {
|
|
167714
|
+
return (memory2.status === "active" || memory2.status === "permanent") && memory2.supersededByMemoryId === null;
|
|
167715
|
+
}
|
|
167716
|
+
function inactiveMemoryError(id, action2) {
|
|
167717
|
+
return `Error: Memory with ID ${id} is archived or superseded; restore it before ${action2}.`;
|
|
167718
|
+
}
|
|
166846
167719
|
function queueEmbedding(args) {
|
|
166847
167720
|
const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
166848
167721
|
if (!snapshot?.enabled)
|
|
@@ -166863,7 +167736,8 @@ function queueEmbedding(args) {
|
|
|
166863
167736
|
}
|
|
166864
167737
|
function createCtxMemoryTool(deps) {
|
|
166865
167738
|
const dreamerAllowed = deps.allowDreamerActions === true;
|
|
166866
|
-
const description = dreamerAllowed ?
|
|
167739
|
+
const description = dreamerAllowed ? `${CTX_MEMORY_DESCRIPTION}
|
|
167740
|
+
- list: enumerate stored memories (maintenance sessions).` : CTX_MEMORY_DESCRIPTION;
|
|
166867
167741
|
return {
|
|
166868
167742
|
name: "ctx_memory",
|
|
166869
167743
|
label: "Magic Context: Memory",
|
|
@@ -166884,13 +167758,10 @@ function createCtxMemoryTool(deps) {
|
|
|
166884
167758
|
const content = params.content?.trim();
|
|
166885
167759
|
if (!content)
|
|
166886
167760
|
return err2("Error: 'content' is required when action is 'write'.");
|
|
166887
|
-
const rawCategory = params.category
|
|
167761
|
+
const rawCategory = params.category;
|
|
166888
167762
|
if (!rawCategory) {
|
|
166889
167763
|
return err2("Error: 'category' is required when action is 'write'.");
|
|
166890
167764
|
}
|
|
166891
|
-
if (!isMemoryCategory2(rawCategory)) {
|
|
166892
|
-
return err2(`Error: Unknown memory category '${rawCategory}'. Valid: ${CATEGORY_PRIORITY.join(", ")}`);
|
|
166893
|
-
}
|
|
166894
167765
|
const existing = getMemoryByHash(deps.db, projectIdentity, rawCategory, computeNormalizedHash(content));
|
|
166895
167766
|
if (existing) {
|
|
166896
167767
|
updateMemorySeenCount(deps.db, existing.id);
|
|
@@ -166904,45 +167775,31 @@ function createCtxMemoryTool(deps) {
|
|
|
166904
167775
|
sourceType: dreamerAllowed ? "dreamer" : "agent"
|
|
166905
167776
|
});
|
|
166906
167777
|
queueEmbedding({ deps, projectIdentity, memoryId: memory2.id, content });
|
|
166907
|
-
invalidateAllMemoryBlockCaches(deps.db);
|
|
166908
167778
|
return ok2(`Saved memory [ID: ${memory2.id}] in ${rawCategory}.`);
|
|
166909
167779
|
}
|
|
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
167780
|
if (params.action === "list") {
|
|
166929
167781
|
const limit = normalizeLimit(params.limit);
|
|
166930
167782
|
const filtered = getMemoriesByProject(deps.db, projectIdentity);
|
|
166931
|
-
const category = params.category
|
|
167783
|
+
const category = params.category;
|
|
166932
167784
|
const filtered2 = category ? filtered.filter((m) => m.category === category) : filtered;
|
|
166933
167785
|
return ok2(formatMemoryList(filtered2.slice(0, limit)));
|
|
166934
167786
|
}
|
|
166935
167787
|
if (params.action === "update") {
|
|
166936
|
-
|
|
166937
|
-
|
|
167788
|
+
const updateIds = params.ids;
|
|
167789
|
+
if (!updateIds || updateIds.length !== 1 || !updateIds.every(Number.isInteger)) {
|
|
167790
|
+
return err2("Error: 'ids' must contain exactly one integer memory ID when action is 'update'.");
|
|
166938
167791
|
}
|
|
167792
|
+
const updateId = updateIds[0];
|
|
166939
167793
|
const content = params.content?.trim();
|
|
166940
167794
|
if (!content) {
|
|
166941
167795
|
return err2("Error: 'content' is required when action is 'update'.");
|
|
166942
167796
|
}
|
|
166943
|
-
const memory2 = getMemoryById(deps.db,
|
|
166944
|
-
if (!memory2 || memory2.projectPath
|
|
166945
|
-
return err2(`Error: Memory with ID ${
|
|
167797
|
+
const memory2 = getMemoryById(deps.db, updateId);
|
|
167798
|
+
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
167799
|
+
return err2(`Error: Memory with ID ${updateId} was not found.`);
|
|
167800
|
+
}
|
|
167801
|
+
if (!dreamerAllowed && !isPrimaryMutableMemory(memory2)) {
|
|
167802
|
+
return err2(inactiveMemoryError(updateId, "updating"));
|
|
166946
167803
|
}
|
|
166947
167804
|
const normalizedHash = computeNormalizedHash(content);
|
|
166948
167805
|
const duplicate = getMemoryByHash(deps.db, projectIdentity, memory2.category, normalizedHash);
|
|
@@ -166963,9 +167820,12 @@ function createCtxMemoryTool(deps) {
|
|
|
166963
167820
|
return ok2(`Updated memory [ID: ${memory2.id}] in ${memory2.category}.`);
|
|
166964
167821
|
}
|
|
166965
167822
|
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'.");
|
|
167823
|
+
const ids = params.ids;
|
|
167824
|
+
if (!ids || ids.length < 2 || !ids.every(Number.isInteger)) {
|
|
167825
|
+
return err2("Error: 'ids' must include at least two integer memory IDs when action is 'merge'.");
|
|
167826
|
+
}
|
|
167827
|
+
if (new Set(ids).size !== ids.length) {
|
|
167828
|
+
return err2("Error: 'ids' must include at least two distinct memory IDs when action is 'merge'.");
|
|
166969
167829
|
}
|
|
166970
167830
|
const content = params.content?.trim();
|
|
166971
167831
|
if (!content) {
|
|
@@ -166975,14 +167835,17 @@ function createCtxMemoryTool(deps) {
|
|
|
166975
167835
|
if (sourceMemories.length !== ids.length) {
|
|
166976
167836
|
return err2("Error: One or more source memories were not found.");
|
|
166977
167837
|
}
|
|
166978
|
-
if (
|
|
166979
|
-
|
|
166980
|
-
|
|
166981
|
-
|
|
166982
|
-
|
|
166983
|
-
|
|
167838
|
+
if (!dreamerAllowed) {
|
|
167839
|
+
const foreign = sourceMemories.find((memory2) => !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity));
|
|
167840
|
+
if (foreign) {
|
|
167841
|
+
return err2(`Error: Memory with ID ${foreign.id} was not found.`);
|
|
167842
|
+
}
|
|
167843
|
+
const inactive = sourceMemories.find((memory2) => !isPrimaryMutableMemory(memory2));
|
|
167844
|
+
if (inactive) {
|
|
167845
|
+
return err2(inactiveMemoryError(inactive.id, "merging"));
|
|
167846
|
+
}
|
|
166984
167847
|
}
|
|
166985
|
-
const requestedCategoryTyped =
|
|
167848
|
+
const requestedCategoryTyped = params.category;
|
|
166986
167849
|
const fallbackCategory = sourceMemories[0]?.category;
|
|
166987
167850
|
const category = requestedCategoryTyped ?? fallbackCategory;
|
|
166988
167851
|
if (!category) {
|
|
@@ -167036,7 +167899,7 @@ function createCtxMemoryTool(deps) {
|
|
|
167036
167899
|
}
|
|
167037
167900
|
supersededMemory(deps.db, memory2.id, canonicalMemory.id);
|
|
167038
167901
|
queueMemoryMutation(deps.db, {
|
|
167039
|
-
projectPath: memory2.projectPath,
|
|
167902
|
+
projectPath: normalizeStoredProjectPath(memory2.projectPath),
|
|
167040
167903
|
mutationType: "superseded",
|
|
167041
167904
|
targetMemoryId: memory2.id,
|
|
167042
167905
|
supersededById: canonicalMemory.id
|
|
@@ -167044,7 +167907,7 @@ function createCtxMemoryTool(deps) {
|
|
|
167044
167907
|
}
|
|
167045
167908
|
if (canonicalExisting && canonicalContentChanged) {
|
|
167046
167909
|
queueMemoryMutation(deps.db, {
|
|
167047
|
-
projectPath: canonicalMemory.projectPath,
|
|
167910
|
+
projectPath: normalizeStoredProjectPath(canonicalMemory.projectPath),
|
|
167048
167911
|
mutationType: "update",
|
|
167049
167912
|
targetMemoryId: canonicalMemory.id,
|
|
167050
167913
|
category,
|
|
@@ -167062,29 +167925,57 @@ function createCtxMemoryTool(deps) {
|
|
|
167062
167925
|
return ok2(`Merged memories [${ids.join(", ")}] into canonical memory [ID: ${canonicalMemory.id}] in ${category}; superseded [${supersededIds.join(", ")}].`);
|
|
167063
167926
|
}
|
|
167064
167927
|
if (params.action === "archive") {
|
|
167065
|
-
|
|
167066
|
-
|
|
167928
|
+
const archiveIds = params.ids;
|
|
167929
|
+
if (!archiveIds || archiveIds.length === 0 || !archiveIds.every(Number.isInteger)) {
|
|
167930
|
+
return err2("Error: 'ids' must contain at least one integer memory ID when action is 'archive'.");
|
|
167067
167931
|
}
|
|
167068
|
-
const
|
|
167069
|
-
|
|
167070
|
-
|
|
167932
|
+
for (const memoryId of archiveIds) {
|
|
167933
|
+
const memory2 = getMemoryById(deps.db, memoryId);
|
|
167934
|
+
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
167935
|
+
return err2(`Error: Memory with ID ${memoryId} was not found.`);
|
|
167936
|
+
}
|
|
167937
|
+
if (!dreamerAllowed && !isPrimaryMutableMemory(memory2)) {
|
|
167938
|
+
return err2(inactiveMemoryError(memoryId, "archiving"));
|
|
167939
|
+
}
|
|
167071
167940
|
}
|
|
167072
167941
|
deps.db.transaction(() => {
|
|
167073
|
-
|
|
167074
|
-
|
|
167075
|
-
|
|
167076
|
-
|
|
167077
|
-
|
|
167078
|
-
|
|
167942
|
+
for (const memoryId of archiveIds) {
|
|
167943
|
+
archiveMemory(deps.db, memoryId, params.reason);
|
|
167944
|
+
queueMemoryMutation(deps.db, {
|
|
167945
|
+
projectPath: projectIdentity,
|
|
167946
|
+
mutationType: "archive",
|
|
167947
|
+
targetMemoryId: memoryId
|
|
167948
|
+
});
|
|
167949
|
+
}
|
|
167079
167950
|
})();
|
|
167080
167951
|
const reasonSuffix = params.reason ? ` (${params.reason})` : "";
|
|
167081
|
-
|
|
167952
|
+
const idList = archiveIds.join(", ");
|
|
167953
|
+
const plural = archiveIds.length > 1 ? "memories" : "memory";
|
|
167954
|
+
return ok2(`Archived ${plural} [ID: ${idList}]${reasonSuffix}.`);
|
|
167082
167955
|
}
|
|
167083
167956
|
return err2("Error: Unknown action.");
|
|
167084
167957
|
}
|
|
167085
167958
|
};
|
|
167086
167959
|
}
|
|
167087
167960
|
|
|
167961
|
+
// ../plugin/src/tools/ctx-note/constants.ts
|
|
167962
|
+
var CTX_NOTE_DESCRIPTION = `Working notes for this session's future — reminders, follow-ups, and things to revisit later.
|
|
167963
|
+
|
|
167964
|
+
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.
|
|
167965
|
+
|
|
167966
|
+
Actions:
|
|
167967
|
+
- write: save a note (content). Add surface_condition to make it a smart note (below).
|
|
167968
|
+
- 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.
|
|
167969
|
+
- update / dismiss: change or retire a note by note_id.
|
|
167970
|
+
|
|
167971
|
+
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:
|
|
167972
|
+
✓ "When PR #42 in cortexkit/magic-context is merged"
|
|
167973
|
+
✓ "When the latest release tag is >= v0.22.0"
|
|
167974
|
+
✓ "When packages/plugin/src/foo.ts contains a function named bar"
|
|
167975
|
+
✗ "When the user mentions X" / "when we revisit Y" / "after we finish this refactor" — no external signal; write a regular note instead.
|
|
167976
|
+
|
|
167977
|
+
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")`;
|
|
167978
|
+
|
|
167088
167979
|
// src/tools/ctx-note.ts
|
|
167089
167980
|
var FILTER_VALUES = [
|
|
167090
167981
|
"active",
|
|
@@ -167104,13 +167995,19 @@ var ParamsSchema3 = exports_typebox.Object({
|
|
|
167104
167995
|
})),
|
|
167105
167996
|
content: exports_typebox.Optional(exports_typebox.String({ description: "Note text to store when action is 'write'." })),
|
|
167106
167997
|
surface_condition: exports_typebox.Optional(exports_typebox.String({
|
|
167107
|
-
description: "
|
|
167998
|
+
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
167999
|
})),
|
|
167109
168000
|
note_id: exports_typebox.Optional(exports_typebox.Number({
|
|
167110
168001
|
description: "Note ID (required for 'dismiss' and 'update' actions)."
|
|
167111
168002
|
})),
|
|
167112
168003
|
filter: exports_typebox.Optional(exports_typebox.Union(FILTER_VALUES.map((value) => exports_typebox.Literal(value)), {
|
|
167113
168004
|
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."
|
|
168005
|
+
})),
|
|
168006
|
+
limit: exports_typebox.Optional(exports_typebox.Number({
|
|
168007
|
+
description: "Max notes per section for read, newest first (default: 25)"
|
|
168008
|
+
})),
|
|
168009
|
+
offset: exports_typebox.Optional(exports_typebox.Number({
|
|
168010
|
+
description: "Skip this many newest notes for read — page older ones (default: 0)"
|
|
167114
168011
|
}))
|
|
167115
168012
|
});
|
|
167116
168013
|
function ok3(text) {
|
|
@@ -167147,15 +168044,20 @@ function formatNoteLine(note) {
|
|
|
167147
168044
|
var DISMISS_FOOTER = `
|
|
167148
168045
|
|
|
167149
168046
|
To dismiss a stale note: ctx_note(action="dismiss", note_id=N)`;
|
|
168047
|
+
var DEFAULT_READ_LIMIT = 25;
|
|
168048
|
+
function paginateNewestFirst(notes, limit, offset) {
|
|
168049
|
+
const total = notes.length;
|
|
168050
|
+
const newestFirst = [...notes].reverse();
|
|
168051
|
+
const page = newestFirst.slice(offset, offset + limit);
|
|
168052
|
+
const remaining = total - offset - page.length;
|
|
168053
|
+
const footer = remaining > 0 ? `Showing ${page.length} of ${total} (newest first) — ${remaining} older: ctx_note(action="read", offset=${offset + page.length})` : null;
|
|
168054
|
+
return { page, total, footer };
|
|
168055
|
+
}
|
|
167150
168056
|
function createCtxNoteTool(deps) {
|
|
167151
168057
|
return {
|
|
167152
168058
|
name: "ctx_note",
|
|
167153
168059
|
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")`',
|
|
168060
|
+
description: CTX_NOTE_DESCRIPTION,
|
|
167159
168061
|
parameters: ParamsSchema3,
|
|
167160
168062
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
167161
168063
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
@@ -167237,11 +168139,15 @@ function createCtxNoteTool(deps) {
|
|
|
167237
168139
|
- ${parts.join(`
|
|
167238
168140
|
- `)}`);
|
|
167239
168141
|
}
|
|
168142
|
+
const limit = typeof params.limit === "number" && params.limit > 0 ? Math.floor(params.limit) : DEFAULT_READ_LIMIT;
|
|
168143
|
+
const offset = typeof params.offset === "number" && params.offset > 0 ? Math.floor(params.offset) : 0;
|
|
167240
168144
|
const sections = readNotes({
|
|
167241
168145
|
db: deps.db,
|
|
167242
168146
|
sessionId,
|
|
167243
168147
|
cwd: ctx.cwd,
|
|
167244
|
-
filter: params.filter
|
|
168148
|
+
filter: params.filter,
|
|
168149
|
+
limit,
|
|
168150
|
+
offset
|
|
167245
168151
|
});
|
|
167246
168152
|
try {
|
|
167247
168153
|
setNoteLastReadAt(deps.db, sessionId);
|
|
@@ -167249,7 +168155,7 @@ function createCtxNoteTool(deps) {
|
|
|
167249
168155
|
if (sections.length === 0) {
|
|
167250
168156
|
return ok3(`## Notes
|
|
167251
168157
|
|
|
167252
|
-
No notes
|
|
168158
|
+
No session notes or smart notes.`);
|
|
167253
168159
|
}
|
|
167254
168160
|
const body = sections.join(`
|
|
167255
168161
|
|
|
@@ -167276,10 +168182,14 @@ function readNotes(args) {
|
|
|
167276
168182
|
}) : [];
|
|
167277
168183
|
const sections2 = [];
|
|
167278
168184
|
if (sessionNotes2.length > 0) {
|
|
168185
|
+
const { page, footer } = paginateNewestFirst(sessionNotes2, args.limit, args.offset);
|
|
168186
|
+
const lines = page.map(formatNoteLine).join(`
|
|
168187
|
+
`);
|
|
167279
168188
|
sections2.push(`## Session Notes
|
|
167280
168189
|
|
|
167281
|
-
${
|
|
167282
|
-
|
|
168190
|
+
${lines}${footer ? `
|
|
168191
|
+
|
|
168192
|
+
${footer}` : ""}`);
|
|
167283
168193
|
}
|
|
167284
168194
|
if (readySmartNotes.length > 0) {
|
|
167285
168195
|
sections2.push(`## \uD83D\uDD14 Ready Smart Notes
|
|
@@ -167310,17 +168220,25 @@ ${readySmartNotes.map(formatNoteLine).join(`
|
|
|
167310
168220
|
}) : [];
|
|
167311
168221
|
const sections = [];
|
|
167312
168222
|
if (sessionNotes.length > 0) {
|
|
168223
|
+
const { page, footer } = paginateNewestFirst(sessionNotes, args.limit, args.offset);
|
|
168224
|
+
const lines = page.map(formatNoteLine).join(`
|
|
168225
|
+
`);
|
|
167313
168226
|
sections.push(`## Session Notes
|
|
167314
168227
|
|
|
167315
|
-
${
|
|
167316
|
-
|
|
168228
|
+
${lines}${footer ? `
|
|
168229
|
+
|
|
168230
|
+
${footer}` : ""}`);
|
|
167317
168231
|
}
|
|
167318
168232
|
if (smartNotes.length > 0) {
|
|
168233
|
+
const { page, footer } = paginateNewestFirst(smartNotes, args.limit, args.offset);
|
|
168234
|
+
const lines = page.map(formatNoteLine).join(`
|
|
168235
|
+
|
|
168236
|
+
`);
|
|
167319
168237
|
sections.push(`## Smart Notes
|
|
167320
168238
|
|
|
167321
|
-
${
|
|
168239
|
+
${lines}${footer ? `
|
|
167322
168240
|
|
|
167323
|
-
`
|
|
168241
|
+
${footer}` : ""}`);
|
|
167324
168242
|
}
|
|
167325
168243
|
return sections;
|
|
167326
168244
|
}
|
|
@@ -167328,7 +168246,7 @@ ${smartNotes.map(formatNoteLine).join(`
|
|
|
167328
168246
|
// ../plugin/src/features/magic-context/range-parser.ts
|
|
167329
168247
|
function parseRangeString(input) {
|
|
167330
168248
|
const maxRangeElements = 1000;
|
|
167331
|
-
const trimmed = input.trim();
|
|
168249
|
+
const trimmed = input.replace(/§/g, "").trim();
|
|
167332
168250
|
if (trimmed === "") {
|
|
167333
168251
|
throw new Error("Range string must not be empty");
|
|
167334
168252
|
}
|
|
@@ -167476,7 +168394,11 @@ function createCtxReduceTool(deps) {
|
|
|
167476
168394
|
};
|
|
167477
168395
|
}
|
|
167478
168396
|
|
|
168397
|
+
// ../plugin/src/features/magic-context/search.ts
|
|
168398
|
+
init_logger();
|
|
168399
|
+
|
|
167479
168400
|
// ../plugin/src/features/magic-context/git-commits/git-log-reader.ts
|
|
168401
|
+
init_logger();
|
|
167480
168402
|
import { execFile } from "node:child_process";
|
|
167481
168403
|
import { promisify } from "node:util";
|
|
167482
168404
|
var execFileAsync = promisify(execFile);
|
|
@@ -167560,7 +168482,11 @@ ${body}` : subject;
|
|
|
167560
168482
|
}
|
|
167561
168483
|
return commits;
|
|
167562
168484
|
}
|
|
168485
|
+
// ../plugin/src/features/magic-context/git-commits/indexer.ts
|
|
168486
|
+
init_logger();
|
|
168487
|
+
|
|
167563
168488
|
// ../plugin/src/features/magic-context/git-commits/storage-git-commits.ts
|
|
168489
|
+
init_logger();
|
|
167564
168490
|
var insertStatements = new WeakMap;
|
|
167565
168491
|
var existingShasStatements = new WeakMap;
|
|
167566
168492
|
var projectCountStatements = new WeakMap;
|
|
@@ -167773,6 +168699,7 @@ async function embedUnembeddedCommits(db, projectPath) {
|
|
|
167773
168699
|
}
|
|
167774
168700
|
}
|
|
167775
168701
|
// ../plugin/src/features/magic-context/git-commits/search-git-commits.ts
|
|
168702
|
+
init_logger();
|
|
167776
168703
|
var ftsStatements = new WeakMap;
|
|
167777
168704
|
var ftsPlainStatements = new WeakMap;
|
|
167778
168705
|
var getBySHAStatements = new WeakMap;
|
|
@@ -168443,6 +169370,9 @@ class BoundedSessionMap {
|
|
|
168443
169370
|
}
|
|
168444
169371
|
}
|
|
168445
169372
|
|
|
169373
|
+
// ../plugin/src/hooks/magic-context/inject-compartments.ts
|
|
169374
|
+
init_logger();
|
|
169375
|
+
|
|
168446
169376
|
// ../plugin/src/hooks/magic-context/decay-curve.ts
|
|
168447
169377
|
var H50 = 24;
|
|
168448
169378
|
var D = 25;
|
|
@@ -168506,6 +169436,9 @@ function escapeXmlAttr2(s) {
|
|
|
168506
169436
|
function escapeXmlContent2(s) {
|
|
168507
169437
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
168508
169438
|
}
|
|
169439
|
+
function isTieredRow(c) {
|
|
169440
|
+
return typeof c.p1 === "string" && c.p1.length > 0;
|
|
169441
|
+
}
|
|
168509
169442
|
function tierBody(c, tier2) {
|
|
168510
169443
|
const tiers = [c.p1, c.p2, c.p3, c.p4];
|
|
168511
169444
|
const requested = tiers[tier2 - 1];
|
|
@@ -168535,12 +169468,13 @@ function renderOneCompartment(c, tier2) {
|
|
|
168535
169468
|
const baseAttrs = `start="${c.startMessage}" end="${c.endMessage}" title="${escapeXmlAttr2(c.title)}"`;
|
|
168536
169469
|
if (tier2 >= 5)
|
|
168537
169470
|
return "";
|
|
168538
|
-
if (c.legacy === 1) {
|
|
168539
|
-
|
|
169471
|
+
if (c.legacy === 1 || !isTieredRow(c)) {
|
|
169472
|
+
const flat = (c.content ?? "").trim();
|
|
169473
|
+
if (tier2 >= 4 || flat.length === 0)
|
|
168540
169474
|
return `<compartment ${baseAttrs} />`;
|
|
168541
169475
|
return [
|
|
168542
169476
|
`<compartment ${baseAttrs}>`,
|
|
168543
|
-
escapeXmlContent2(legacyBodyForTier(
|
|
169477
|
+
escapeXmlContent2(legacyBodyForTier(flat, tier2)),
|
|
168544
169478
|
"</compartment>"
|
|
168545
169479
|
].join(`
|
|
168546
169480
|
`);
|
|
@@ -168721,6 +169655,7 @@ function isAftAvailable() {
|
|
|
168721
169655
|
}
|
|
168722
169656
|
|
|
168723
169657
|
// ../plugin/src/hooks/magic-context/key-files-block.ts
|
|
169658
|
+
init_logger();
|
|
168724
169659
|
var cachedKeyFilesBySession = new Map;
|
|
168725
169660
|
var staleUpdates = new Map;
|
|
168726
169661
|
function staleKey(update2) {
|
|
@@ -168974,6 +169909,21 @@ function renderMemoryBlockV2(memories, wrapper = "project-memory") {
|
|
|
168974
169909
|
`);
|
|
168975
169910
|
}
|
|
168976
169911
|
|
|
169912
|
+
// ../plugin/src/tools/ctx-search/constants.ts
|
|
169913
|
+
var CTX_SEARCH_DESCRIPTION = `Your long-term recall for this project — search everything that ever happened here, not just what's currently visible.
|
|
169914
|
+
|
|
169915
|
+
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.
|
|
169916
|
+
|
|
169917
|
+
Sources (omit for a broad search across all):
|
|
169918
|
+
- memory: curated cross-session project knowledge — rules, constraints, conventions.
|
|
169919
|
+
- 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).
|
|
169920
|
+
- git_commit: this repository's commit history.
|
|
169921
|
+
|
|
169922
|
+
Picking sources:
|
|
169923
|
+
- "when did this change / was this working before" → ["git_commit", "message"]
|
|
169924
|
+
- "did we discuss this earlier" → ["message"]
|
|
169925
|
+
- "what's our convention / rule for X" → ["memory"]`;
|
|
169926
|
+
|
|
168977
169927
|
// src/tools/ctx-search.ts
|
|
168978
169928
|
var DEFAULT_LIMIT = 10;
|
|
168979
169929
|
var ParamsSchema5 = exports_typebox.Object({
|
|
@@ -169057,18 +170007,7 @@ function createCtxSearchTool(deps) {
|
|
|
169057
170007
|
return {
|
|
169058
170008
|
name: "ctx_search",
|
|
169059
170009
|
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.",
|
|
170010
|
+
description: CTX_SEARCH_DESCRIPTION,
|
|
169072
170011
|
parameters: ParamsSchema5,
|
|
169073
170012
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
169074
170013
|
const query = params.query?.trim();
|
|
@@ -169087,6 +170026,7 @@ function createCtxSearchTool(deps) {
|
|
|
169087
170026
|
const embeddingEnabled = snapshot ? snapshot.enabled || snapshot.gitCommitEnabled : deps.embeddingEnabled;
|
|
169088
170027
|
const gitCommitsEnabled = snapshot?.gitCommitEnabled ?? deps.gitCommitsEnabled ?? false;
|
|
169089
170028
|
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
170029
|
+
const messageOrdinalCutoff = lastCompartmentEnd >= 0 ? lastCompartmentEnd : 0;
|
|
169090
170030
|
const visibleMemoryIds = getVisibleMemoryIds(deps.db, sessionId);
|
|
169091
170031
|
const results = await unifiedSearch(deps.db, sessionId, projectIdentity, query, {
|
|
169092
170032
|
limit: normalizeLimit3(params.limit),
|
|
@@ -169097,7 +170037,7 @@ function createCtxSearchTool(deps) {
|
|
|
169097
170037
|
return result?.vector ?? null;
|
|
169098
170038
|
},
|
|
169099
170039
|
isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
|
|
169100
|
-
maxMessageOrdinal:
|
|
170040
|
+
maxMessageOrdinal: messageOrdinalCutoff,
|
|
169101
170041
|
gitCommitsEnabled,
|
|
169102
170042
|
sources: params.sources,
|
|
169103
170043
|
visibleMemoryIds,
|
|
@@ -169184,13 +170124,15 @@ function registerMagicContextTools(pi, opts) {
|
|
|
169184
170124
|
embeddingEnabled: opts.embeddingEnabled,
|
|
169185
170125
|
gitCommitsEnabled: opts.gitCommitsEnabled
|
|
169186
170126
|
}));
|
|
169187
|
-
|
|
169188
|
-
|
|
169189
|
-
|
|
169190
|
-
|
|
169191
|
-
|
|
169192
|
-
|
|
169193
|
-
|
|
170127
|
+
if (opts.memoryToolEnabled !== false) {
|
|
170128
|
+
pi.registerTool(createCtxMemoryTool({
|
|
170129
|
+
db: opts.db,
|
|
170130
|
+
ensureProjectRegistered: opts.ensureProjectRegistered,
|
|
170131
|
+
memoryEnabled: opts.memoryEnabled,
|
|
170132
|
+
embeddingEnabled: opts.embeddingEnabled,
|
|
170133
|
+
allowDreamerActions: opts.allowDreamerActions ?? false
|
|
170134
|
+
}));
|
|
170135
|
+
}
|
|
169194
170136
|
if (!opts.sessionScopedToolsDisabled) {
|
|
169195
170137
|
pi.registerTool(createCtxNoteTool({
|
|
169196
170138
|
db: opts.db,
|
|
@@ -169213,7 +170155,7 @@ var openedDb;
|
|
|
169213
170155
|
function magicContextSubagentExtension(pi) {
|
|
169214
170156
|
setHarness("pi");
|
|
169215
170157
|
pi.registerFlag(SUBAGENT_DREAMER_ACTIONS_FLAG, {
|
|
169216
|
-
description: "
|
|
170158
|
+
description: "Register ctx_memory with dreamer actions for Magic Context subagents.",
|
|
169217
170159
|
type: "boolean",
|
|
169218
170160
|
default: false
|
|
169219
170161
|
});
|
|
@@ -169231,10 +170173,11 @@ function magicContextSubagentExtension(pi) {
|
|
|
169231
170173
|
registerMagicContextTools(pi, {
|
|
169232
170174
|
db,
|
|
169233
170175
|
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
170176
|
+
memoryToolEnabled: dreamerActionsEnabled,
|
|
169234
170177
|
allowDreamerActions: dreamerActionsEnabled,
|
|
169235
170178
|
sessionScopedToolsDisabled: true
|
|
169236
170179
|
});
|
|
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})`);
|
|
170180
|
+
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
170181
|
} catch (err5) {
|
|
169239
170182
|
const message = err5 instanceof Error ? err5.message : String(err5);
|
|
169240
170183
|
log(`[pi-subagent] startup failed: ${message}`);
|