@cortexkit/pi-magic-context 0.22.5 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3314 -974
- package/dist/subagent-entry.js +964 -287
- package/package.json +2 -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, ".opencode", "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, ".opencode", "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 ''");
|
|
@@ -142495,6 +142578,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142495
142578
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_tags_pi_adopt
|
|
142496
142579
|
ON tags(session_id, entry_fingerprint)
|
|
142497
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");
|
|
142498
142584
|
ensureColumn(db, "session_meta", "system_prompt_tokens", "INTEGER DEFAULT 0");
|
|
142499
142585
|
ensureColumn(db, "session_meta", "compaction_marker_state", "TEXT DEFAULT ''");
|
|
142500
142586
|
ensureColumn(db, "session_meta", "key_files", "TEXT DEFAULT ''");
|
|
@@ -142535,6 +142621,14 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142535
142621
|
ensureColumn(db, "session_meta", "cached_m0_project_docs_hash", "TEXT");
|
|
142536
142622
|
ensureColumn(db, "session_meta", "cached_m1_bytes", "BLOB");
|
|
142537
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");
|
|
142538
142632
|
ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
|
|
142539
142633
|
ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
|
|
142540
142634
|
ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
|
|
@@ -142604,6 +142698,13 @@ function healAllNullColumns(db) {
|
|
|
142604
142698
|
healNullIntegerColumns(db);
|
|
142605
142699
|
healMissingMemoryBlockIds(db);
|
|
142606
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
|
+
}
|
|
142607
142708
|
function healMissingMemoryBlockIds(db) {
|
|
142608
142709
|
try {
|
|
142609
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();
|
|
@@ -142613,6 +142714,7 @@ function healNullTextColumns(db) {
|
|
|
142613
142714
|
const columns = [
|
|
142614
142715
|
["cache_ttl", ""],
|
|
142615
142716
|
["last_nudge_band", ""],
|
|
142717
|
+
["last_nudge_level", ""],
|
|
142616
142718
|
["last_transform_error", ""],
|
|
142617
142719
|
["nudge_anchor_message_id", ""],
|
|
142618
142720
|
["nudge_anchor_text", ""],
|
|
@@ -142653,7 +142755,17 @@ function healNullIntegerColumns(db) {
|
|
|
142653
142755
|
["observed_safe_input_tokens", 0],
|
|
142654
142756
|
["cache_alert_sent", 0],
|
|
142655
142757
|
["new_work_tokens", 0],
|
|
142656
|
-
["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]
|
|
142657
142769
|
];
|
|
142658
142770
|
for (const [column, fallback] of columns) {
|
|
142659
142771
|
try {
|
|
@@ -142692,6 +142804,7 @@ function openDatabase(dbPathOrOptions) {
|
|
|
142692
142804
|
if (!persistenceByDatabase.has(existing)) {
|
|
142693
142805
|
persistenceByDatabase.set(existing, true);
|
|
142694
142806
|
}
|
|
142807
|
+
healWedgedChannel2Claims(existing);
|
|
142695
142808
|
return existing;
|
|
142696
142809
|
}
|
|
142697
142810
|
try {
|
|
@@ -142717,6 +142830,7 @@ function openDatabase(dbPathOrOptions) {
|
|
|
142717
142830
|
log(`[magic-context] key-files orphan GC failed: ${getErrorMessage(error)}`);
|
|
142718
142831
|
}
|
|
142719
142832
|
}
|
|
142833
|
+
healWedgedChannel2Claims(db);
|
|
142720
142834
|
if (!explicitDbPath) {
|
|
142721
142835
|
try {
|
|
142722
142836
|
runToolOwnerBackfill(db);
|
|
@@ -142737,6 +142851,9 @@ function openDatabase(dbPathOrOptions) {
|
|
|
142737
142851
|
}
|
|
142738
142852
|
}
|
|
142739
142853
|
|
|
142854
|
+
// src/subagent-entry.ts
|
|
142855
|
+
init_logger();
|
|
142856
|
+
|
|
142740
142857
|
// ../plugin/src/config/prune-config-leaf.ts
|
|
142741
142858
|
function isPlainObject(value) {
|
|
142742
142859
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -142915,6 +143032,10 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
142915
143032
|
delete projectRaw.auto_update;
|
|
142916
143033
|
warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
|
|
142917
143034
|
}
|
|
143035
|
+
if ("sqlite" in projectRaw) {
|
|
143036
|
+
delete projectRaw.sqlite;
|
|
143037
|
+
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).");
|
|
143038
|
+
}
|
|
142918
143039
|
for (const agentKey of HIDDEN_AGENT_KEYS) {
|
|
142919
143040
|
const block = projectRaw[agentKey];
|
|
142920
143041
|
if (!isPlainObject2(block))
|
|
@@ -157273,7 +157394,6 @@ var AgentOverrideConfigSchema = exports_external.object({
|
|
|
157273
157394
|
});
|
|
157274
157395
|
|
|
157275
157396
|
// ../plugin/src/config/schema/magic-context.ts
|
|
157276
|
-
var DEFAULT_NUDGE_INTERVAL_TOKENS = 1e4;
|
|
157277
157397
|
var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65;
|
|
157278
157398
|
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.";
|
|
157279
157399
|
var DEFAULT_HISTORIAN_TIMEOUT_MS = 300000;
|
|
@@ -157372,7 +157492,6 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
157372
157492
|
historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
|
|
157373
157493
|
dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
|
|
157374
157494
|
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" })'),
|
|
157375
|
-
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)"),
|
|
157376
157495
|
execute_threshold_percentage: exports_external.union([
|
|
157377
157496
|
exports_external.number().min(20).max(80, EXECUTE_THRESHOLD_CAP_MESSAGE),
|
|
157378
157497
|
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))
|
|
@@ -157381,10 +157500,7 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
157381
157500
|
default: exports_external.number().min(5000).max(2000000).optional()
|
|
157382
157501
|
}).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."),
|
|
157383
157502
|
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)"),
|
|
157384
|
-
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)"),
|
|
157385
|
-
drop_tool_structure: exports_external.boolean().default(true).describe("When true, dropped tool parts are fully removed instead of truncated in place (default: true)"),
|
|
157386
157503
|
clear_reasoning_age: exports_external.number().min(10).default(50).describe("Clear reasoning/thinking blocks older than N tags (default: 50)"),
|
|
157387
|
-
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)"),
|
|
157388
157504
|
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)"),
|
|
157389
157505
|
historian_timeout_ms: exports_external.number().min(60000).default(DEFAULT_HISTORIAN_TIMEOUT_MS).describe("Timeout for each historian prompt call in milliseconds (default: 300000)"),
|
|
157390
157506
|
commit_cluster_trigger: exports_external.object({
|
|
@@ -157887,6 +158003,9 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
157887
158003
|
};
|
|
157888
158004
|
}
|
|
157889
158005
|
|
|
158006
|
+
// ../plugin/src/features/magic-context/memory/embedding.ts
|
|
158007
|
+
init_logger();
|
|
158008
|
+
|
|
157890
158009
|
// ../plugin/src/features/magic-context/memory/cosine-similarity.ts
|
|
157891
158010
|
function cosineSimilarity(a, b) {
|
|
157892
158011
|
if (a.length !== b.length) {
|
|
@@ -157942,6 +158061,8 @@ import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
|
157942
158061
|
import { open, stat, unlink, writeFile } from "node:fs/promises";
|
|
157943
158062
|
import { dirname as dirname4, join as join6 } from "node:path";
|
|
157944
158063
|
import { pathToFileURL } from "node:url";
|
|
158064
|
+
init_data_path();
|
|
158065
|
+
init_logger();
|
|
157945
158066
|
var LOCK_POLL_MS = 150;
|
|
157946
158067
|
var STALE_LOCK_MS = 3 * 60000;
|
|
157947
158068
|
var MAX_LOCK_WAIT_MS = 5 * 60000;
|
|
@@ -158276,6 +158397,9 @@ class LocalEmbeddingProvider {
|
|
|
158276
158397
|
}
|
|
158277
158398
|
}
|
|
158278
158399
|
|
|
158400
|
+
// ../plugin/src/features/magic-context/memory/embedding-openai.ts
|
|
158401
|
+
init_logger();
|
|
158402
|
+
|
|
158279
158403
|
// ../plugin/src/features/magic-context/memory/embedding-ssrf.ts
|
|
158280
158404
|
var METADATA_HOSTNAMES = new Set(["metadata.google.internal", "metadata.goog"]);
|
|
158281
158405
|
var IPV6_METADATA_HOSTS = new Set(["fd00:ec2::254"]);
|
|
@@ -158627,6 +158751,7 @@ function getDistinctStoredModelIds(db, projectPath) {
|
|
|
158627
158751
|
|
|
158628
158752
|
// ../plugin/src/features/magic-context/project-embedding-registry.ts
|
|
158629
158753
|
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
158754
|
+
init_logger();
|
|
158630
158755
|
|
|
158631
158756
|
// ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
|
|
158632
158757
|
var saveStatements = new WeakMap;
|
|
@@ -159383,6 +159508,7 @@ function storedPathBelongsToIdentity(storedProjectPath, projectIdentity) {
|
|
|
159383
159508
|
|
|
159384
159509
|
// ../plugin/src/plugin/embedding-bootstrap-helpers.ts
|
|
159385
159510
|
import { createHash as createHash5 } from "node:crypto";
|
|
159511
|
+
init_logger();
|
|
159386
159512
|
var EMBEDDING_AFFECTING_KEYS = new Set([
|
|
159387
159513
|
"embedding.api_key",
|
|
159388
159514
|
"embedding.endpoint",
|
|
@@ -159480,7 +159606,6 @@ async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
|
159480
159606
|
};
|
|
159481
159607
|
registerProjectEmbeddingAndMaybeWipe(db, projectIdentity, detailed.config.embedding, features, directory);
|
|
159482
159608
|
}
|
|
159483
|
-
|
|
159484
159609
|
// ../plugin/src/features/magic-context/compartment-lease.ts
|
|
159485
159610
|
var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
159486
159611
|
var COMPARTMENT_LEASE_RENEWAL_MS = 60 * 1000;
|
|
@@ -159578,6 +159703,14 @@ var SESSION_META_SELECT_COLUMNS = [
|
|
|
159578
159703
|
"cached_m0_tool_set_hash",
|
|
159579
159704
|
"cached_m0_model_key",
|
|
159580
159705
|
"last_observed_model_key",
|
|
159706
|
+
"last_usage_context_limit",
|
|
159707
|
+
"prior_boundary_ordinal",
|
|
159708
|
+
"protected_tail_policy_version",
|
|
159709
|
+
"protected_tail_drain_window_started_at",
|
|
159710
|
+
"protected_tail_drain_tokens",
|
|
159711
|
+
"recovery_no_eligible_head_count",
|
|
159712
|
+
"force_emergency_bypass_window_start",
|
|
159713
|
+
"force_emergency_bypass_used",
|
|
159581
159714
|
"upgrade_reminded_at",
|
|
159582
159715
|
"pi_stable_id_scheme"
|
|
159583
159716
|
];
|
|
@@ -159617,6 +159750,14 @@ var META_COLUMNS = {
|
|
|
159617
159750
|
cachedM0ToolSetHash: "cached_m0_tool_set_hash",
|
|
159618
159751
|
cachedM0ModelKey: "cached_m0_model_key",
|
|
159619
159752
|
lastObservedModelKey: "last_observed_model_key",
|
|
159753
|
+
lastUsageContextLimit: "last_usage_context_limit",
|
|
159754
|
+
priorBoundaryOrdinal: "prior_boundary_ordinal",
|
|
159755
|
+
protectedTailPolicyVersion: "protected_tail_policy_version",
|
|
159756
|
+
protectedTailDrainWindowStartedAt: "protected_tail_drain_window_started_at",
|
|
159757
|
+
protectedTailDrainTokens: "protected_tail_drain_tokens",
|
|
159758
|
+
recoveryNoEligibleHeadCount: "recovery_no_eligible_head_count",
|
|
159759
|
+
forceEmergencyBypassWindowStart: "force_emergency_bypass_window_start",
|
|
159760
|
+
forceEmergencyBypassUsed: "force_emergency_bypass_used",
|
|
159620
159761
|
upgradeRemindedAt: "upgrade_reminded_at",
|
|
159621
159762
|
piStableIdScheme: "pi_stable_id_scheme"
|
|
159622
159763
|
};
|
|
@@ -159658,7 +159799,7 @@ function isSessionMetaRow(row) {
|
|
|
159658
159799
|
if (row === null || typeof row !== "object")
|
|
159659
159800
|
return false;
|
|
159660
159801
|
const r = row;
|
|
159661
|
-
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);
|
|
159802
|
+
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);
|
|
159662
159803
|
}
|
|
159663
159804
|
function getDefaultSessionMeta(sessionId) {
|
|
159664
159805
|
return {
|
|
@@ -159698,6 +159839,14 @@ function getDefaultSessionMeta(sessionId) {
|
|
|
159698
159839
|
cachedM0ToolSetHash: null,
|
|
159699
159840
|
cachedM0ModelKey: null,
|
|
159700
159841
|
lastObservedModelKey: null,
|
|
159842
|
+
lastUsageContextLimit: 0,
|
|
159843
|
+
priorBoundaryOrdinal: 1,
|
|
159844
|
+
protectedTailPolicyVersion: 0,
|
|
159845
|
+
protectedTailDrainWindowStartedAt: 0,
|
|
159846
|
+
protectedTailDrainTokens: 0,
|
|
159847
|
+
recoveryNoEligibleHeadCount: 0,
|
|
159848
|
+
forceEmergencyBypassWindowStart: 0,
|
|
159849
|
+
forceEmergencyBypassUsed: 0,
|
|
159701
159850
|
upgradeRemindedAt: null,
|
|
159702
159851
|
piStableIdScheme: null
|
|
159703
159852
|
};
|
|
@@ -159752,6 +159901,14 @@ function toSessionMeta(row) {
|
|
|
159752
159901
|
cachedM0ToolSetHash: stringOrNull(row.cached_m0_tool_set_hash),
|
|
159753
159902
|
cachedM0ModelKey: stringOrNull(row.cached_m0_model_key),
|
|
159754
159903
|
lastObservedModelKey: stringOrNull(row.last_observed_model_key),
|
|
159904
|
+
lastUsageContextLimit: numOrZero(row.last_usage_context_limit),
|
|
159905
|
+
priorBoundaryOrdinal: Math.max(1, numOrZero(row.prior_boundary_ordinal) || 1),
|
|
159906
|
+
protectedTailPolicyVersion: numOrZero(row.protected_tail_policy_version),
|
|
159907
|
+
protectedTailDrainWindowStartedAt: numOrZero(row.protected_tail_drain_window_started_at),
|
|
159908
|
+
protectedTailDrainTokens: numOrZero(row.protected_tail_drain_tokens),
|
|
159909
|
+
recoveryNoEligibleHeadCount: numOrZero(row.recovery_no_eligible_head_count),
|
|
159910
|
+
forceEmergencyBypassWindowStart: numOrZero(row.force_emergency_bypass_window_start),
|
|
159911
|
+
forceEmergencyBypassUsed: numOrZero(row.force_emergency_bypass_used),
|
|
159755
159912
|
upgradeRemindedAt: numOrNull(row.upgrade_reminded_at),
|
|
159756
159913
|
piStableIdScheme: numOrNull(row.pi_stable_id_scheme)
|
|
159757
159914
|
};
|
|
@@ -159872,6 +160029,11 @@ function getLastCompartmentEndMessage(db, sessionId) {
|
|
|
159872
160029
|
const row = db.prepare("SELECT MAX(end_message) as max_end FROM compartments WHERE session_id = ?").get(sessionId);
|
|
159873
160030
|
return row?.max_end ?? -1;
|
|
159874
160031
|
}
|
|
160032
|
+
function getLastCompartmentEndMessageId(db, sessionId) {
|
|
160033
|
+
const row = db.prepare("SELECT end_message_id FROM compartments WHERE session_id = ? ORDER BY sequence DESC LIMIT 1").get(sessionId);
|
|
160034
|
+
const id = row?.end_message_id;
|
|
160035
|
+
return id && id.length > 0 ? id : null;
|
|
160036
|
+
}
|
|
159875
160037
|
function getCompartmentsByEndMessageId(db, sessionId, endMessageId) {
|
|
159876
160038
|
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? AND end_message_id = ? ORDER BY sequence ASC").all(sessionId, endMessageId).filter(isCompartmentRow);
|
|
159877
160039
|
return rows.map(toCompartment);
|
|
@@ -159974,6 +160136,8 @@ function escapeXmlContent(s) {
|
|
|
159974
160136
|
}
|
|
159975
160137
|
|
|
159976
160138
|
// ../plugin/src/hooks/magic-context/read-session-db.ts
|
|
160139
|
+
init_data_path();
|
|
160140
|
+
init_logger();
|
|
159977
160141
|
import { existsSync as existsSync6 } from "node:fs";
|
|
159978
160142
|
import { join as join7 } from "node:path";
|
|
159979
160143
|
function getOpenCodeDbPath() {
|
|
@@ -160046,13 +160210,27 @@ function parseJsonUnknown(value) {
|
|
|
160046
160210
|
return null;
|
|
160047
160211
|
}
|
|
160048
160212
|
}
|
|
160213
|
+
function attachRawPartVersion(value, timeUpdated) {
|
|
160214
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
160215
|
+
return value;
|
|
160216
|
+
if (typeof timeUpdated !== "number")
|
|
160217
|
+
return value;
|
|
160218
|
+
try {
|
|
160219
|
+
Object.defineProperty(value, "__magicContextPartUpdatedAt", {
|
|
160220
|
+
value: timeUpdated,
|
|
160221
|
+
enumerable: false,
|
|
160222
|
+
configurable: true
|
|
160223
|
+
});
|
|
160224
|
+
} catch {}
|
|
160225
|
+
return value;
|
|
160226
|
+
}
|
|
160049
160227
|
function readRawSessionMessagesFromDb(db, sessionId) {
|
|
160050
|
-
const messageRows = db.prepare("SELECT id, data FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
160051
|
-
const partRows = db.prepare("SELECT message_id, data FROM part WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawPartRow);
|
|
160228
|
+
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);
|
|
160229
|
+
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);
|
|
160052
160230
|
const partsByMessageId = new Map;
|
|
160053
160231
|
for (const part of partRows) {
|
|
160054
160232
|
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
160055
|
-
list.push(parseJsonUnknown(part.data));
|
|
160233
|
+
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
160056
160234
|
partsByMessageId.set(part.message_id, list);
|
|
160057
160235
|
}
|
|
160058
160236
|
const filtered = messageRows.filter((row) => {
|
|
@@ -160068,10 +160246,63 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
160068
160246
|
ordinal: index + 1,
|
|
160069
160247
|
id: row.id,
|
|
160070
160248
|
role,
|
|
160071
|
-
parts: partsByMessageId.get(row.id) ?? []
|
|
160249
|
+
parts: partsByMessageId.get(row.id) ?? [],
|
|
160250
|
+
version: row.time_updated ?? null
|
|
160072
160251
|
};
|
|
160073
160252
|
});
|
|
160074
160253
|
}
|
|
160254
|
+
function isAnchorRow(row) {
|
|
160255
|
+
return row !== null && typeof row === "object" && typeof row.time_created === "number" && typeof row.id === "string";
|
|
160256
|
+
}
|
|
160257
|
+
function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
160258
|
+
const anchorRow = db.prepare("SELECT time_created, id, data FROM message WHERE id = ? AND session_id = ?").get(anchorMessageId, sessionId);
|
|
160259
|
+
if (!isAnchorRow(anchorRow))
|
|
160260
|
+
return null;
|
|
160261
|
+
const anchorInfo = parseJsonRecord(anchorRow.data ?? "");
|
|
160262
|
+
if (anchorInfo?.summary === true && anchorInfo?.finish === "stop")
|
|
160263
|
+
return null;
|
|
160264
|
+
const messageRows = db.prepare(`SELECT id, data, time_updated FROM message
|
|
160265
|
+
WHERE session_id = ?
|
|
160266
|
+
AND (time_created > ? OR (time_created = ? AND id >= ?))
|
|
160267
|
+
ORDER BY time_created ASC, id ASC`).all(sessionId, anchorRow.time_created, anchorRow.time_created, anchorRow.id).filter(isRawMessageRow);
|
|
160268
|
+
const filtered = messageRows.filter((row) => {
|
|
160269
|
+
const info = parseJsonRecord(row.data);
|
|
160270
|
+
return !(info?.summary === true && info?.finish === "stop");
|
|
160271
|
+
});
|
|
160272
|
+
const ids = filtered.map((row) => row.id);
|
|
160273
|
+
const partsByMessageId = new Map;
|
|
160274
|
+
if (ids.length > 0) {
|
|
160275
|
+
const CHUNK = 800;
|
|
160276
|
+
for (let i = 0;i < ids.length; i += CHUNK) {
|
|
160277
|
+
const slice = ids.slice(i, i + CHUNK);
|
|
160278
|
+
const placeholders = slice.map(() => "?").join(",");
|
|
160279
|
+
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);
|
|
160280
|
+
for (const part of partRows) {
|
|
160281
|
+
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
160282
|
+
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
160283
|
+
partsByMessageId.set(part.message_id, list);
|
|
160284
|
+
}
|
|
160285
|
+
}
|
|
160286
|
+
}
|
|
160287
|
+
const messages = [];
|
|
160288
|
+
let ord = baseOrdinal;
|
|
160289
|
+
for (const row of filtered) {
|
|
160290
|
+
const info = parseJsonRecord(row.data);
|
|
160291
|
+
if (!info) {
|
|
160292
|
+
ord += 1;
|
|
160293
|
+
continue;
|
|
160294
|
+
}
|
|
160295
|
+
messages.push({
|
|
160296
|
+
ordinal: ord,
|
|
160297
|
+
id: row.id,
|
|
160298
|
+
role: typeof info.role === "string" ? info.role : "unknown",
|
|
160299
|
+
parts: partsByMessageId.get(row.id) ?? [],
|
|
160300
|
+
version: row.time_updated ?? null
|
|
160301
|
+
});
|
|
160302
|
+
ord += 1;
|
|
160303
|
+
}
|
|
160304
|
+
return { messages, absoluteMessageCount: Math.max(0, ord - 1) };
|
|
160305
|
+
}
|
|
160075
160306
|
|
|
160076
160307
|
// ../plugin/src/hooks/magic-context/tag-content-primitives.ts
|
|
160077
160308
|
var encoder = new TextEncoder;
|
|
@@ -160216,6 +160447,7 @@ class ToolMutationBatch {
|
|
|
160216
160447
|
|
|
160217
160448
|
// ../plugin/src/hooks/magic-context/read-session-chunk.ts
|
|
160218
160449
|
var activeRawMessageCache = null;
|
|
160450
|
+
var activeAbsoluteCountCache = null;
|
|
160219
160451
|
var sessionProviders = new Map;
|
|
160220
160452
|
function setRawMessageProvider(sessionId, provider2) {
|
|
160221
160453
|
sessionProviders.set(sessionId, provider2);
|
|
@@ -160247,12 +160479,14 @@ function withRawSessionMessageCache(fn) {
|
|
|
160247
160479
|
const outerCache = activeRawMessageCache;
|
|
160248
160480
|
if (!outerCache) {
|
|
160249
160481
|
activeRawMessageCache = new Map;
|
|
160482
|
+
activeAbsoluteCountCache = new Map;
|
|
160250
160483
|
}
|
|
160251
160484
|
try {
|
|
160252
160485
|
return fn();
|
|
160253
160486
|
} finally {
|
|
160254
160487
|
if (!outerCache) {
|
|
160255
160488
|
activeRawMessageCache = null;
|
|
160489
|
+
activeAbsoluteCountCache = null;
|
|
160256
160490
|
}
|
|
160257
160491
|
}
|
|
160258
160492
|
}
|
|
@@ -160268,6 +160502,40 @@ function readRawSessionMessages(sessionId) {
|
|
|
160268
160502
|
}
|
|
160269
160503
|
return readRawSessionMessagesFromSource(sessionId);
|
|
160270
160504
|
}
|
|
160505
|
+
function primeTailRawMessageCache(args) {
|
|
160506
|
+
const { sessionId, lastCompartmentEnd, anchorMessageId } = args;
|
|
160507
|
+
if (!activeRawMessageCache)
|
|
160508
|
+
return false;
|
|
160509
|
+
if (activeRawMessageCache.has(sessionId))
|
|
160510
|
+
return false;
|
|
160511
|
+
if (sessionProviders.has(sessionId))
|
|
160512
|
+
return false;
|
|
160513
|
+
if (!openCodeDbExists())
|
|
160514
|
+
return false;
|
|
160515
|
+
if (lastCompartmentEnd < 1 || !anchorMessageId)
|
|
160516
|
+
return false;
|
|
160517
|
+
const result = withReadOnlySessionDb((db) => readRawSessionTailFromDb(db, sessionId, lastCompartmentEnd, anchorMessageId));
|
|
160518
|
+
if (!result)
|
|
160519
|
+
return false;
|
|
160520
|
+
activeRawMessageCache.set(sessionId, result.messages);
|
|
160521
|
+
activeAbsoluteCountCache?.set(sessionId, result.absoluteMessageCount);
|
|
160522
|
+
return true;
|
|
160523
|
+
}
|
|
160524
|
+
function getCachedAbsoluteMessageCount(sessionId) {
|
|
160525
|
+
return activeAbsoluteCountCache?.get(sessionId) ?? null;
|
|
160526
|
+
}
|
|
160527
|
+
function primeInMemoryTailRawMessageCache(args) {
|
|
160528
|
+
const { sessionId, messages, absoluteMessageCount } = args;
|
|
160529
|
+
if (!activeRawMessageCache)
|
|
160530
|
+
return false;
|
|
160531
|
+
if (activeRawMessageCache.has(sessionId))
|
|
160532
|
+
return false;
|
|
160533
|
+
if (sessionProviders.has(sessionId))
|
|
160534
|
+
return false;
|
|
160535
|
+
activeRawMessageCache.set(sessionId, messages);
|
|
160536
|
+
activeAbsoluteCountCache?.set(sessionId, absoluteMessageCount);
|
|
160537
|
+
return true;
|
|
160538
|
+
}
|
|
160271
160539
|
function readRawSessionMessagesFromSource(sessionId) {
|
|
160272
160540
|
const provider2 = sessionProviders.get(sessionId);
|
|
160273
160541
|
if (provider2)
|
|
@@ -160332,7 +160600,7 @@ function getRawSessionTagKeysThrough(sessionId, upToMessageIndex) {
|
|
|
160332
160600
|
return { messageFileKeys, toolObservations };
|
|
160333
160601
|
}
|
|
160334
160602
|
var PROTECTED_TAIL_USER_TURNS = 5;
|
|
160335
|
-
function
|
|
160603
|
+
function getLegacyProtectedTailStartOrdinal(sessionId) {
|
|
160336
160604
|
const messages = readRawSessionMessages(sessionId);
|
|
160337
160605
|
const userOrdinals = messages.filter((m) => m.role === "user" && hasMeaningfulUserText(m.parts)).map((m) => m.ordinal);
|
|
160338
160606
|
if (userOrdinals.length < PROTECTED_TAIL_USER_TURNS) {
|
|
@@ -160342,6 +160610,7 @@ function getProtectedTailStartOrdinal(sessionId) {
|
|
|
160342
160610
|
}
|
|
160343
160611
|
function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal) {
|
|
160344
160612
|
const messages = readRawSessionMessages(sessionId);
|
|
160613
|
+
const totalMessageCount = getCachedAbsoluteMessageCount(sessionId) ?? messages.length;
|
|
160345
160614
|
const startOrdinal = Math.max(1, offset);
|
|
160346
160615
|
const lines = [];
|
|
160347
160616
|
const lineMeta = [];
|
|
@@ -160469,7 +160738,7 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
160469
160738
|
endMessageId: lastMessageId,
|
|
160470
160739
|
messageCount: messagesProcessed,
|
|
160471
160740
|
tokenEstimate: totalTokens,
|
|
160472
|
-
hasMore: lastOrdinal < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1,
|
|
160741
|
+
hasMore: lastOrdinal < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1, totalMessageCount) : totalMessageCount),
|
|
160473
160742
|
text: lines.join(`
|
|
160474
160743
|
`),
|
|
160475
160744
|
lines: lineMeta,
|
|
@@ -160479,7 +160748,13 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
160479
160748
|
}
|
|
160480
160749
|
|
|
160481
160750
|
// ../plugin/src/tools/ctx-expand/constants.ts
|
|
160482
|
-
var CTX_EXPAND_DESCRIPTION =
|
|
160751
|
+
var CTX_EXPAND_DESCRIPTION = `Recover the original conversation from your compacted history.
|
|
160752
|
+
|
|
160753
|
+
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:
|
|
160754
|
+
|
|
160755
|
+
ctx_expand(start=120, end=245) ← the compartment's own start/end attributes
|
|
160756
|
+
|
|
160757
|
+
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.`;
|
|
160483
160758
|
var CTX_EXPAND_TOKEN_BUDGET = 15000;
|
|
160484
160759
|
|
|
160485
160760
|
// ../../node_modules/.bun/typebox@1.1.38/node_modules/typebox/build/system/memory/memory.mjs
|
|
@@ -164648,11 +164923,31 @@ function findLastModelKeyFromBranch(entries) {
|
|
|
164648
164923
|
}
|
|
164649
164924
|
return;
|
|
164650
164925
|
}
|
|
164926
|
+
function rawEntryVersion(entry) {
|
|
164927
|
+
const record4 = entry;
|
|
164928
|
+
const updated = record4.updatedAt ?? record4.updated_at ?? record4.timestamp;
|
|
164929
|
+
return typeof updated === "string" || typeof updated === "number" ? updated : entry.id;
|
|
164930
|
+
}
|
|
164931
|
+
function attachPiPartVersion(parts, version2) {
|
|
164932
|
+
return parts.map((part) => {
|
|
164933
|
+
if (part === null || typeof part !== "object" || Array.isArray(part))
|
|
164934
|
+
return part;
|
|
164935
|
+
try {
|
|
164936
|
+
Object.defineProperty(part, "__magicContextPartUpdatedAt", {
|
|
164937
|
+
value: version2,
|
|
164938
|
+
enumerable: false,
|
|
164939
|
+
configurable: true
|
|
164940
|
+
});
|
|
164941
|
+
} catch {}
|
|
164942
|
+
return part;
|
|
164943
|
+
});
|
|
164944
|
+
}
|
|
164651
164945
|
function convertEntriesToRawMessages(entries) {
|
|
164652
164946
|
const result = [];
|
|
164653
164947
|
let nextOrdinal = 1;
|
|
164654
164948
|
let pendingToolParts = [];
|
|
164655
164949
|
let pendingFirstRealId = "";
|
|
164950
|
+
let pendingFirstRealVersion = "";
|
|
164656
164951
|
for (const entry of entries) {
|
|
164657
164952
|
if (!isMessageEntry(entry)) {
|
|
164658
164953
|
continue;
|
|
@@ -164660,24 +164955,29 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164660
164955
|
const msg = entry.message;
|
|
164661
164956
|
const role = msg.role;
|
|
164662
164957
|
if (role === "toolResult") {
|
|
164663
|
-
|
|
164958
|
+
const version2 = rawEntryVersion(entry);
|
|
164959
|
+
pendingToolParts.push(...attachPiPartVersion(synthesizeToolResultParts(msg), version2));
|
|
164664
164960
|
if (pendingFirstRealId === "") {
|
|
164665
164961
|
pendingFirstRealId = entry.id;
|
|
164962
|
+
pendingFirstRealVersion = version2;
|
|
164666
164963
|
}
|
|
164667
164964
|
continue;
|
|
164668
164965
|
}
|
|
164669
164966
|
if (role === "user") {
|
|
164967
|
+
const version2 = rawEntryVersion(entry);
|
|
164670
164968
|
const parts = [
|
|
164671
164969
|
...pendingToolParts,
|
|
164672
|
-
...synthesizeUserParts(msg)
|
|
164970
|
+
...attachPiPartVersion(synthesizeUserParts(msg), version2)
|
|
164673
164971
|
];
|
|
164674
164972
|
pendingToolParts = [];
|
|
164675
164973
|
pendingFirstRealId = "";
|
|
164974
|
+
pendingFirstRealVersion = "";
|
|
164676
164975
|
result.push({
|
|
164677
164976
|
ordinal: nextOrdinal++,
|
|
164678
164977
|
id: entry.id,
|
|
164679
164978
|
role: "user",
|
|
164680
|
-
parts
|
|
164979
|
+
parts,
|
|
164980
|
+
version: version2
|
|
164681
164981
|
});
|
|
164682
164982
|
continue;
|
|
164683
164983
|
}
|
|
@@ -164687,16 +164987,20 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164687
164987
|
ordinal: nextOrdinal++,
|
|
164688
164988
|
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
164689
164989
|
role: "user",
|
|
164690
|
-
parts: pendingToolParts
|
|
164990
|
+
parts: pendingToolParts,
|
|
164991
|
+
version: pendingFirstRealVersion
|
|
164691
164992
|
});
|
|
164692
164993
|
pendingToolParts = [];
|
|
164693
164994
|
pendingFirstRealId = "";
|
|
164995
|
+
pendingFirstRealVersion = "";
|
|
164694
164996
|
}
|
|
164997
|
+
const version2 = rawEntryVersion(entry);
|
|
164695
164998
|
result.push({
|
|
164696
164999
|
ordinal: nextOrdinal++,
|
|
164697
165000
|
id: entry.id,
|
|
164698
165001
|
role: "assistant",
|
|
164699
|
-
parts: synthesizeAssistantParts(msg)
|
|
165002
|
+
parts: attachPiPartVersion(synthesizeAssistantParts(msg), version2),
|
|
165003
|
+
version: version2
|
|
164700
165004
|
});
|
|
164701
165005
|
continue;
|
|
164702
165006
|
}
|
|
@@ -164704,7 +165008,8 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164704
165008
|
ordinal: nextOrdinal++,
|
|
164705
165009
|
id: entry.id,
|
|
164706
165010
|
role: typeof role === "string" ? role : "unknown",
|
|
164707
|
-
parts: []
|
|
165011
|
+
parts: [],
|
|
165012
|
+
version: rawEntryVersion(entry)
|
|
164708
165013
|
});
|
|
164709
165014
|
}
|
|
164710
165015
|
if (pendingToolParts.length > 0) {
|
|
@@ -164712,7 +165017,8 @@ function convertEntriesToRawMessages(entries) {
|
|
|
164712
165017
|
ordinal: nextOrdinal,
|
|
164713
165018
|
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
164714
165019
|
role: "user",
|
|
164715
|
-
parts: pendingToolParts
|
|
165020
|
+
parts: pendingToolParts,
|
|
165021
|
+
version: pendingFirstRealVersion
|
|
164716
165022
|
});
|
|
164717
165023
|
}
|
|
164718
165024
|
return result;
|
|
@@ -164869,6 +165175,13 @@ function createCtxExpandTool(deps) {
|
|
|
164869
165175
|
}
|
|
164870
165176
|
|
|
164871
165177
|
// ../plugin/src/features/magic-context/memory/constants.ts
|
|
165178
|
+
var V2_MEMORY_CATEGORIES = [
|
|
165179
|
+
"PROJECT_RULES",
|
|
165180
|
+
"ARCHITECTURE",
|
|
165181
|
+
"CONSTRAINTS",
|
|
165182
|
+
"CONFIG_VALUES",
|
|
165183
|
+
"NAMING"
|
|
165184
|
+
];
|
|
164872
165185
|
var PROMOTABLE_CATEGORIES = [
|
|
164873
165186
|
"PROJECT_RULES",
|
|
164874
165187
|
"ARCHITECTURE",
|
|
@@ -164908,6 +165221,7 @@ var CATEGORY_DEFAULT_TTL = {
|
|
|
164908
165221
|
KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
|
|
164909
165222
|
};
|
|
164910
165223
|
// ../plugin/src/features/magic-context/memory/embedding-backfill.ts
|
|
165224
|
+
init_logger();
|
|
164911
165225
|
async function ensureMemoryEmbeddings(args) {
|
|
164912
165226
|
const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
164913
165227
|
if (!snapshot?.enabled) {
|
|
@@ -164945,6 +165259,9 @@ async function ensureMemoryEmbeddings(args) {
|
|
|
164945
165259
|
}
|
|
164946
165260
|
return args.existingEmbeddings;
|
|
164947
165261
|
}
|
|
165262
|
+
// ../plugin/src/features/magic-context/memory/promotion.ts
|
|
165263
|
+
init_logger();
|
|
165264
|
+
|
|
164948
165265
|
// ../plugin/src/features/magic-context/memory/storage-memory.ts
|
|
164949
165266
|
var COLUMN_MAP = {
|
|
164950
165267
|
id: "id",
|
|
@@ -165856,6 +166173,7 @@ function getMaxMemoryMutationId(db, projectPath) {
|
|
|
165856
166173
|
return row?.max_id ?? null;
|
|
165857
166174
|
}
|
|
165858
166175
|
// ../plugin/src/features/magic-context/storage-meta-persisted.ts
|
|
166176
|
+
init_logger();
|
|
165859
166177
|
var CAS_RETRY_LIMIT = 5;
|
|
165860
166178
|
var AUTO_SEARCH_NO_HINT_REASONS = new Set([
|
|
165861
166179
|
"below-threshold",
|
|
@@ -165865,12 +166183,6 @@ var AUTO_SEARCH_NO_HINT_REASONS = new Set([
|
|
|
165865
166183
|
"stacked",
|
|
165866
166184
|
"too-short"
|
|
165867
166185
|
]);
|
|
165868
|
-
function isPersistedStickyTurnReminderRow(row) {
|
|
165869
|
-
if (row === null || typeof row !== "object")
|
|
165870
|
-
return false;
|
|
165871
|
-
const r = row;
|
|
165872
|
-
return typeof r.sticky_turn_reminder_text === "string" && typeof r.sticky_turn_reminder_message_id === "string";
|
|
165873
|
-
}
|
|
165874
166186
|
function isPersistedNoteNudgeRow(row) {
|
|
165875
166187
|
if (row === null || typeof row !== "object")
|
|
165876
166188
|
return false;
|
|
@@ -165936,6 +166248,139 @@ function getDefaultHistorianFailureState() {
|
|
|
165936
166248
|
lastFailureAt: null
|
|
165937
166249
|
};
|
|
165938
166250
|
}
|
|
166251
|
+
var DEFAULT_PROTECTED_TAIL_META = {
|
|
166252
|
+
priorBoundaryOrdinal: 1,
|
|
166253
|
+
protectedTailPolicyVersion: 0,
|
|
166254
|
+
protectedTailDrainWindowStartedAt: 0,
|
|
166255
|
+
protectedTailDrainTokens: 0,
|
|
166256
|
+
recoveryNoEligibleHeadCount: 0,
|
|
166257
|
+
forceEmergencyBypassWindowStart: 0,
|
|
166258
|
+
forceEmergencyBypassUsed: 0
|
|
166259
|
+
};
|
|
166260
|
+
function toProtectedTailMeta(row) {
|
|
166261
|
+
if (row === null || typeof row !== "object")
|
|
166262
|
+
return { ...DEFAULT_PROTECTED_TAIL_META };
|
|
166263
|
+
const r = row;
|
|
166264
|
+
const numberOr = (value, fallback) => typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
166265
|
+
return {
|
|
166266
|
+
priorBoundaryOrdinal: Math.max(1, numberOr(r.prior_boundary_ordinal, 1)),
|
|
166267
|
+
protectedTailPolicyVersion: numberOr(r.protected_tail_policy_version, 0),
|
|
166268
|
+
protectedTailDrainWindowStartedAt: numberOr(r.protected_tail_drain_window_started_at, 0),
|
|
166269
|
+
protectedTailDrainTokens: numberOr(r.protected_tail_drain_tokens, 0),
|
|
166270
|
+
recoveryNoEligibleHeadCount: numberOr(r.recovery_no_eligible_head_count, 0),
|
|
166271
|
+
forceEmergencyBypassWindowStart: numberOr(r.force_emergency_bypass_window_start, 0),
|
|
166272
|
+
forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0)
|
|
166273
|
+
};
|
|
166274
|
+
}
|
|
166275
|
+
function loadProtectedTailMeta(db, sessionId) {
|
|
166276
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166277
|
+
const row = db.prepare(`SELECT prior_boundary_ordinal, protected_tail_policy_version,
|
|
166278
|
+
protected_tail_drain_window_started_at, protected_tail_drain_tokens,
|
|
166279
|
+
recovery_no_eligible_head_count, force_emergency_bypass_window_start,
|
|
166280
|
+
force_emergency_bypass_used
|
|
166281
|
+
FROM session_meta WHERE session_id = ?`).get(sessionId);
|
|
166282
|
+
return toProtectedTailMeta(row);
|
|
166283
|
+
}
|
|
166284
|
+
function markProtectedTailPolicyV3Seeded(db, sessionId, priorBoundaryOrdinal) {
|
|
166285
|
+
let seeded = false;
|
|
166286
|
+
db.transaction(() => {
|
|
166287
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166288
|
+
const existing = loadProtectedTailMeta(db, sessionId);
|
|
166289
|
+
if (existing.protectedTailPolicyVersion < 3) {
|
|
166290
|
+
db.prepare(`UPDATE session_meta
|
|
166291
|
+
SET prior_boundary_ordinal = ?, protected_tail_policy_version = 3
|
|
166292
|
+
WHERE session_id = ? AND protected_tail_policy_version < 3`).run(Math.max(1, Math.floor(priorBoundaryOrdinal)), sessionId);
|
|
166293
|
+
seeded = true;
|
|
166294
|
+
}
|
|
166295
|
+
})();
|
|
166296
|
+
return { ...loadProtectedTailMeta(db, sessionId), seeded };
|
|
166297
|
+
}
|
|
166298
|
+
function recordProtectedTailPublicationFloor(db, sessionId, floorOrdinal) {
|
|
166299
|
+
db.transaction(() => {
|
|
166300
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166301
|
+
db.prepare(`UPDATE session_meta
|
|
166302
|
+
SET prior_boundary_ordinal = MAX(COALESCE(prior_boundary_ordinal, 1), ?),
|
|
166303
|
+
recovery_no_eligible_head_count = 0
|
|
166304
|
+
WHERE session_id = ?`).run(Math.max(1, Math.floor(floorOrdinal)), sessionId);
|
|
166305
|
+
})();
|
|
166306
|
+
}
|
|
166307
|
+
function recordProtectedTailNoEligibleHead(db, sessionId) {
|
|
166308
|
+
db.transaction(() => {
|
|
166309
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166310
|
+
db.prepare(`UPDATE session_meta
|
|
166311
|
+
SET recovery_no_eligible_head_count = COALESCE(recovery_no_eligible_head_count, 0) + 1
|
|
166312
|
+
WHERE session_id = ?`).run(sessionId);
|
|
166313
|
+
})();
|
|
166314
|
+
return loadProtectedTailMeta(db, sessionId).recoveryNoEligibleHeadCount;
|
|
166315
|
+
}
|
|
166316
|
+
var DRAIN_WINDOW_MS = 10 * 60 * 1000;
|
|
166317
|
+
function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
166318
|
+
if (usagePercentage >= 95)
|
|
166319
|
+
return Math.min(1e6, Math.max(4 * perRunCap, Math.round(0.5 * usable)));
|
|
166320
|
+
if (usagePercentage >= 80)
|
|
166321
|
+
return Math.min(750000, Math.max(3 * perRunCap, Math.round(0.35 * usable)));
|
|
166322
|
+
return Math.min(500000, Math.max(perRunCap, Math.round(0.2 * usable)));
|
|
166323
|
+
}
|
|
166324
|
+
function reserveProtectedTailDrainTokens(args) {
|
|
166325
|
+
const now = args.now ?? Date.now();
|
|
166326
|
+
const requested = Math.max(0, Math.floor(args.trueRawTokens));
|
|
166327
|
+
if (requested === 0) {
|
|
166328
|
+
return { ok: true, reservedTokens: 0, overQuotaBypass: false, reservation: null };
|
|
166329
|
+
}
|
|
166330
|
+
let result = {
|
|
166331
|
+
ok: false,
|
|
166332
|
+
reservedTokens: 0,
|
|
166333
|
+
overQuotaBypass: false,
|
|
166334
|
+
reservation: null,
|
|
166335
|
+
skippedReason: "quota exhausted"
|
|
166336
|
+
};
|
|
166337
|
+
args.db.transaction(() => {
|
|
166338
|
+
ensureSessionMetaRow(args.db, args.sessionId);
|
|
166339
|
+
let meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
166340
|
+
if (now - meta3.protectedTailDrainWindowStartedAt > DRAIN_WINDOW_MS) {
|
|
166341
|
+
args.db.prepare(`UPDATE session_meta
|
|
166342
|
+
SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0,
|
|
166343
|
+
force_emergency_bypass_window_start = ?, force_emergency_bypass_used = 0
|
|
166344
|
+
WHERE session_id = ?`).run(now, now, args.sessionId);
|
|
166345
|
+
meta3 = loadProtectedTailMeta(args.db, args.sessionId);
|
|
166346
|
+
}
|
|
166347
|
+
const budget = protectedTailWindowBudget(args.usagePercentage, args.usable, args.perRunCap);
|
|
166348
|
+
const remaining = Math.max(0, budget - meta3.protectedTailDrainTokens);
|
|
166349
|
+
let reserved = Math.min(requested, args.perRunCap, remaining);
|
|
166350
|
+
let bypass = false;
|
|
166351
|
+
const bypassWindowExpired = now - meta3.forceEmergencyBypassWindowStart > DRAIN_WINDOW_MS;
|
|
166352
|
+
const bypassUsed = bypassWindowExpired ? 0 : meta3.forceEmergencyBypassUsed;
|
|
166353
|
+
if (reserved <= 0 && args.usagePercentage >= 95 && bypassUsed === 0) {
|
|
166354
|
+
reserved = Math.min(requested, args.perRunCap);
|
|
166355
|
+
bypass = true;
|
|
166356
|
+
}
|
|
166357
|
+
if (reserved <= 0)
|
|
166358
|
+
return;
|
|
166359
|
+
args.db.prepare(`UPDATE session_meta
|
|
166360
|
+
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,
|
|
166361
|
+
protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) + ?,
|
|
166362
|
+
force_emergency_bypass_window_start = CASE WHEN ? THEN ? ELSE force_emergency_bypass_window_start END,
|
|
166363
|
+
force_emergency_bypass_used = CASE WHEN ? THEN 1 ELSE force_emergency_bypass_used END
|
|
166364
|
+
WHERE session_id = ?`).run(now, reserved, bypass ? 1 : 0, now, bypass ? 1 : 0, args.sessionId);
|
|
166365
|
+
result = {
|
|
166366
|
+
ok: true,
|
|
166367
|
+
reservedTokens: reserved,
|
|
166368
|
+
overQuotaBypass: bypass,
|
|
166369
|
+
reservation: { sessionId: args.sessionId, runId: args.runId, tokens: reserved }
|
|
166370
|
+
};
|
|
166371
|
+
})();
|
|
166372
|
+
return result;
|
|
166373
|
+
}
|
|
166374
|
+
function rollbackProtectedTailDrainReservation(db, reservation) {
|
|
166375
|
+
if (!reservation || reservation.tokens <= 0)
|
|
166376
|
+
return;
|
|
166377
|
+
db.transaction(() => {
|
|
166378
|
+
ensureSessionMetaRow(db, reservation.sessionId);
|
|
166379
|
+
db.prepare(`UPDATE session_meta
|
|
166380
|
+
SET protected_tail_drain_tokens = MAX(0, COALESCE(protected_tail_drain_tokens, 0) - ?)
|
|
166381
|
+
WHERE session_id = ?`).run(reservation.tokens, reservation.sessionId);
|
|
166382
|
+
})();
|
|
166383
|
+
}
|
|
165939
166384
|
function setPersistedReasoningWatermark(db, sessionId, tagNumber) {
|
|
165940
166385
|
ensureSessionMetaRow(db, sessionId);
|
|
165941
166386
|
db.prepare("UPDATE session_meta SET cleared_reasoning_through_tag = ? WHERE session_id = ?").run(tagNumber, sessionId);
|
|
@@ -165943,27 +166388,95 @@ function setPersistedReasoningWatermark(db, sessionId, tagNumber) {
|
|
|
165943
166388
|
function clearPersistedReasoningWatermark(db, sessionId) {
|
|
165944
166389
|
setPersistedReasoningWatermark(db, sessionId, 0);
|
|
165945
166390
|
}
|
|
165946
|
-
function
|
|
165947
|
-
|
|
165948
|
-
|
|
165949
|
-
|
|
165950
|
-
|
|
165951
|
-
|
|
165952
|
-
|
|
165953
|
-
|
|
165954
|
-
|
|
165955
|
-
|
|
165956
|
-
|
|
165957
|
-
};
|
|
166391
|
+
function isEmergencyInputSampleRow(row) {
|
|
166392
|
+
return typeof row === "object" && row !== null && typeof row.last_emergency_input_sample === "number";
|
|
166393
|
+
}
|
|
166394
|
+
function getEmergencyInputSample(db, sessionId) {
|
|
166395
|
+
const result = db.prepare("SELECT last_emergency_input_sample FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166396
|
+
return isEmergencyInputSampleRow(result) ? result.last_emergency_input_sample : 0;
|
|
166397
|
+
}
|
|
166398
|
+
function setEmergencyDropSample(db, sessionId, inputSample) {
|
|
166399
|
+
db.transaction(() => {
|
|
166400
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166401
|
+
db.prepare("UPDATE session_meta SET last_emergency_input_sample = ? WHERE session_id = ?").run(Math.max(0, Math.round(inputSample)), sessionId);
|
|
166402
|
+
})();
|
|
166403
|
+
}
|
|
166404
|
+
function clearEmergencyDropSample(db, sessionId) {
|
|
166405
|
+
db.transaction(() => {
|
|
166406
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166407
|
+
db.prepare("UPDATE session_meta SET last_emergency_input_sample = 0 WHERE session_id = ?").run(sessionId);
|
|
166408
|
+
})();
|
|
166409
|
+
}
|
|
166410
|
+
function isLastNudgeUndroppedRow(row) {
|
|
166411
|
+
return typeof row === "object" && row !== null && typeof row.last_nudge_undropped === "number";
|
|
166412
|
+
}
|
|
166413
|
+
function isLastNudgeLevelRow(row) {
|
|
166414
|
+
return typeof row === "object" && row !== null && typeof row.last_nudge_level === "string";
|
|
166415
|
+
}
|
|
166416
|
+
function normalizeLastNudgeLevel(value) {
|
|
166417
|
+
return value === "gentle" || value === "firm" || value === "urgent" ? value : "";
|
|
166418
|
+
}
|
|
166419
|
+
function getLastNudgeUndropped(db, sessionId) {
|
|
166420
|
+
const result = db.prepare("SELECT last_nudge_undropped FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166421
|
+
return isLastNudgeUndroppedRow(result) ? result.last_nudge_undropped : 0;
|
|
166422
|
+
}
|
|
166423
|
+
function setLastNudgeUndropped(db, sessionId, value) {
|
|
166424
|
+
db.transaction(() => {
|
|
166425
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166426
|
+
db.prepare("UPDATE session_meta SET last_nudge_undropped = ? WHERE session_id = ?").run(Math.max(0, Math.round(value)), sessionId);
|
|
166427
|
+
})();
|
|
166428
|
+
}
|
|
166429
|
+
function getLastNudgeLevel(db, sessionId) {
|
|
166430
|
+
const result = db.prepare("SELECT last_nudge_level FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166431
|
+
return isLastNudgeLevelRow(result) ? normalizeLastNudgeLevel(result.last_nudge_level) : "";
|
|
165958
166432
|
}
|
|
165959
|
-
function
|
|
166433
|
+
function setLastNudgeLevel(db, sessionId, value) {
|
|
165960
166434
|
db.transaction(() => {
|
|
165961
166435
|
ensureSessionMetaRow(db, sessionId);
|
|
165962
|
-
db.prepare("UPDATE session_meta SET
|
|
166436
|
+
db.prepare("UPDATE session_meta SET last_nudge_level = ? WHERE session_id = ?").run(normalizeLastNudgeLevel(value), sessionId);
|
|
165963
166437
|
})();
|
|
165964
166438
|
}
|
|
165965
|
-
function
|
|
165966
|
-
db.
|
|
166439
|
+
function resetLastNudgeCycle(db, sessionId) {
|
|
166440
|
+
db.transaction(() => {
|
|
166441
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166442
|
+
db.prepare("UPDATE session_meta SET last_nudge_undropped = 0, last_nudge_level = '' WHERE session_id = ?").run(sessionId);
|
|
166443
|
+
})();
|
|
166444
|
+
}
|
|
166445
|
+
function resetLastNudgeCycleIfTailShrank(db, sessionId, measuredUndropped) {
|
|
166446
|
+
let changed = false;
|
|
166447
|
+
db.transaction(() => {
|
|
166448
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166449
|
+
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)));
|
|
166450
|
+
changed = (result.changes ?? 0) > 0;
|
|
166451
|
+
})();
|
|
166452
|
+
return changed;
|
|
166453
|
+
}
|
|
166454
|
+
function isChannel2StateRow(row) {
|
|
166455
|
+
return typeof row === "object" && row !== null && typeof row.channel2_nudge_state === "string";
|
|
166456
|
+
}
|
|
166457
|
+
function getChannel2NudgeState(db, sessionId) {
|
|
166458
|
+
const result = db.prepare("SELECT channel2_nudge_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166459
|
+
if (!isChannel2StateRow(result))
|
|
166460
|
+
return "";
|
|
166461
|
+
const raw = result.channel2_nudge_state;
|
|
166462
|
+
return raw === "pending" || raw === "claimed" || raw === "delivered" ? raw : "";
|
|
166463
|
+
}
|
|
166464
|
+
function setChannel2NudgeState(db, sessionId, state) {
|
|
166465
|
+
db.transaction(() => {
|
|
166466
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166467
|
+
const claimedAt = state === "claimed" ? Date.now() : 0;
|
|
166468
|
+
db.prepare("UPDATE session_meta SET channel2_nudge_state = ?, channel2_nudge_claimed_at = ? WHERE session_id = ?").run(state, claimedAt, sessionId);
|
|
166469
|
+
})();
|
|
166470
|
+
}
|
|
166471
|
+
function casChannel2NudgeState(db, sessionId, from, to) {
|
|
166472
|
+
let changed = false;
|
|
166473
|
+
db.transaction(() => {
|
|
166474
|
+
ensureSessionMetaRow(db, sessionId);
|
|
166475
|
+
const claimedAt = to === "claimed" ? Date.now() : 0;
|
|
166476
|
+
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);
|
|
166477
|
+
changed = (result.changes ?? 0) > 0;
|
|
166478
|
+
})();
|
|
166479
|
+
return changed;
|
|
165967
166480
|
}
|
|
165968
166481
|
function getPersistedNoteNudge(db, sessionId) {
|
|
165969
166482
|
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);
|
|
@@ -166187,7 +166700,11 @@ function recordOverflowDetected(db, sessionId, reportedLimit) {
|
|
|
166187
166700
|
function clearEmergencyRecovery(db, sessionId) {
|
|
166188
166701
|
db.transaction(() => {
|
|
166189
166702
|
ensureSessionMetaRow(db, sessionId);
|
|
166190
|
-
|
|
166703
|
+
try {
|
|
166704
|
+
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0, recovery_no_eligible_head_count = 0 WHERE session_id = ?").run(sessionId);
|
|
166705
|
+
} catch {
|
|
166706
|
+
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0 WHERE session_id = ?").run(sessionId);
|
|
166707
|
+
}
|
|
166191
166708
|
})();
|
|
166192
166709
|
}
|
|
166193
166710
|
function clearDetectedContextLimit(db, sessionId) {
|
|
@@ -166350,6 +166867,7 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
|
|
|
166350
166867
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
166351
166868
|
|
|
166352
166869
|
// ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
|
|
166870
|
+
init_logger();
|
|
166353
166871
|
function resolveIsSubagentFromOpenCodeDb(sessionId) {
|
|
166354
166872
|
try {
|
|
166355
166873
|
return withReadOnlySessionDb((openCodeDb) => {
|
|
@@ -166568,7 +167086,8 @@ function updateNote(db, noteId, updates, scope) {
|
|
|
166568
167086
|
sets.push("session_id = ?");
|
|
166569
167087
|
params.push(updates.sessionId);
|
|
166570
167088
|
}
|
|
166571
|
-
|
|
167089
|
+
const smartConditionChanged = existing.type === "smart" && updates.surfaceCondition !== undefined && updates.surfaceCondition !== existing.surfaceCondition;
|
|
167090
|
+
if (updates.status !== undefined && !smartConditionChanged) {
|
|
166572
167091
|
sets.push("status = ?");
|
|
166573
167092
|
params.push(updates.status);
|
|
166574
167093
|
}
|
|
@@ -166581,17 +167100,21 @@ function updateNote(db, noteId, updates, scope) {
|
|
|
166581
167100
|
sets.push("surface_condition = ?");
|
|
166582
167101
|
params.push(updates.surfaceCondition);
|
|
166583
167102
|
}
|
|
166584
|
-
if (
|
|
166585
|
-
sets.push("last_checked_at =
|
|
166586
|
-
|
|
166587
|
-
|
|
166588
|
-
|
|
166589
|
-
|
|
166590
|
-
|
|
166591
|
-
|
|
166592
|
-
|
|
166593
|
-
|
|
166594
|
-
|
|
167103
|
+
if (smartConditionChanged) {
|
|
167104
|
+
sets.push("status = 'pending'", "last_checked_at = NULL", "ready_at = NULL", "ready_reason = NULL");
|
|
167105
|
+
} else {
|
|
167106
|
+
if (updates.lastCheckedAt !== undefined) {
|
|
167107
|
+
sets.push("last_checked_at = ?");
|
|
167108
|
+
params.push(updates.lastCheckedAt);
|
|
167109
|
+
}
|
|
167110
|
+
if (updates.readyAt !== undefined) {
|
|
167111
|
+
sets.push("ready_at = ?");
|
|
167112
|
+
params.push(updates.readyAt);
|
|
167113
|
+
}
|
|
167114
|
+
if (updates.readyReason !== undefined) {
|
|
167115
|
+
sets.push("ready_reason = ?");
|
|
167116
|
+
params.push(updates.readyReason);
|
|
167117
|
+
}
|
|
166595
167118
|
}
|
|
166596
167119
|
}
|
|
166597
167120
|
if (sets.length === 1) {
|
|
@@ -166618,6 +167141,7 @@ function markNoteChecked(db, noteId) {
|
|
|
166618
167141
|
db.prepare("UPDATE notes SET last_checked_at = ?, updated_at = ? WHERE id = ? AND type = 'smart'").run(now, now, noteId);
|
|
166619
167142
|
}
|
|
166620
167143
|
// ../plugin/src/features/magic-context/storage-ops.ts
|
|
167144
|
+
init_logger();
|
|
166621
167145
|
var queuePendingOpStatements = new WeakMap;
|
|
166622
167146
|
var getPendingOpsStatements = new WeakMap;
|
|
166623
167147
|
var clearPendingOpsStatements = new WeakMap;
|
|
@@ -166780,7 +167304,7 @@ var getTagNumberByMessageIdStatements = new WeakMap;
|
|
|
166780
167304
|
function getInsertTagStatement(db) {
|
|
166781
167305
|
let stmt = insertTagStatements.get(db);
|
|
166782
167306
|
if (!stmt) {
|
|
166783
|
-
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
167307
|
+
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
166784
167308
|
insertTagStatements.set(db, stmt);
|
|
166785
167309
|
}
|
|
166786
167310
|
return stmt;
|
|
@@ -166822,9 +167346,95 @@ function getUpdateTagInputByteSizeStatement(db) {
|
|
|
166822
167346
|
function updateTagByteSize(db, sessionId, tagNumber, newByteSize) {
|
|
166823
167347
|
getUpdateTagByteSizeStatement(db).run(newByteSize, sessionId, tagNumber);
|
|
166824
167348
|
}
|
|
167349
|
+
var CONTENT_ID_SUFFIX = /:(?:p|file)\d+$/;
|
|
167350
|
+
function ownerMessageIdForTagRow(row) {
|
|
167351
|
+
if (row.type === "tool") {
|
|
167352
|
+
return row.tool_owner_message_id ?? row.message_id;
|
|
167353
|
+
}
|
|
167354
|
+
return row.message_id.replace(CONTENT_ID_SUFFIX, "");
|
|
167355
|
+
}
|
|
167356
|
+
function getActiveTagTokenAggregate(db, sessionId) {
|
|
167357
|
+
const row = db.prepare(`SELECT
|
|
167358
|
+
COALESCE(SUM(CASE WHEN type != 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0)
|
|
167359
|
+
+ COALESCE(SUM(COALESCE(reasoning_token_count, 0)), 0) AS conversation,
|
|
167360
|
+
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) + COALESCE(input_token_count, 0) ELSE 0 END), 0) AS tool_call,
|
|
167361
|
+
COALESCE(SUM(CASE WHEN type = 'tool' THEN COALESCE(token_count, 0) ELSE 0 END), 0) AS tool_output,
|
|
167362
|
+
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
167363
|
+
FROM tags
|
|
167364
|
+
WHERE session_id = ? AND status = 'active'`).get(sessionId);
|
|
167365
|
+
return {
|
|
167366
|
+
conversation: row?.conversation ?? 0,
|
|
167367
|
+
toolCall: row?.tool_call ?? 0,
|
|
167368
|
+
toolOutput: row?.tool_output ?? 0,
|
|
167369
|
+
nullCount: row?.null_count ?? 0
|
|
167370
|
+
};
|
|
167371
|
+
}
|
|
167372
|
+
function getTriggerTagTokenUpperBound(db, sessionId) {
|
|
167373
|
+
const row = db.prepare(`SELECT
|
|
167374
|
+
COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
|
|
167375
|
+
COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
|
|
167376
|
+
FROM tags
|
|
167377
|
+
WHERE session_id = ? AND status IN ('active', 'dropped')`).get(sessionId);
|
|
167378
|
+
return { bound: row?.bound ?? 0, nullCount: row?.null_count ?? 0 };
|
|
167379
|
+
}
|
|
166825
167380
|
function updateTagInputByteSize(db, sessionId, tagNumber, newInputByteSize) {
|
|
166826
167381
|
getUpdateTagInputByteSizeStatement(db).run(newInputByteSize, sessionId, tagNumber);
|
|
166827
167382
|
}
|
|
167383
|
+
var updateTagTokenCountStatements = new WeakMap;
|
|
167384
|
+
var updateTagInputTokenCountStatements = new WeakMap;
|
|
167385
|
+
function getUpdateTagTokenCountStatement(db) {
|
|
167386
|
+
let stmt = updateTagTokenCountStatements.get(db);
|
|
167387
|
+
if (!stmt) {
|
|
167388
|
+
stmt = db.prepare("UPDATE tags SET token_count = ? WHERE session_id = ? AND tag_number = ?");
|
|
167389
|
+
updateTagTokenCountStatements.set(db, stmt);
|
|
167390
|
+
}
|
|
167391
|
+
return stmt;
|
|
167392
|
+
}
|
|
167393
|
+
function getUpdateTagInputTokenCountStatement(db) {
|
|
167394
|
+
let stmt = updateTagInputTokenCountStatements.get(db);
|
|
167395
|
+
if (!stmt) {
|
|
167396
|
+
stmt = db.prepare("UPDATE tags SET input_token_count = ? WHERE session_id = ? AND tag_number = ?");
|
|
167397
|
+
updateTagInputTokenCountStatements.set(db, stmt);
|
|
167398
|
+
}
|
|
167399
|
+
return stmt;
|
|
167400
|
+
}
|
|
167401
|
+
function updateTagTokenCount(db, sessionId, tagNumber, newTokenCount) {
|
|
167402
|
+
getUpdateTagTokenCountStatement(db).run(newTokenCount, sessionId, tagNumber);
|
|
167403
|
+
}
|
|
167404
|
+
function getAllStatusTagTokenTotalsFlat(db, sessionId) {
|
|
167405
|
+
const rows = db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
167406
|
+
FROM tags
|
|
167407
|
+
WHERE session_id = ?`).all(sessionId);
|
|
167408
|
+
const totals = new Map;
|
|
167409
|
+
const nullMessageIds = new Set;
|
|
167410
|
+
for (const row of rows) {
|
|
167411
|
+
if (row.type === "tool" && row.tool_owner_message_id === null)
|
|
167412
|
+
continue;
|
|
167413
|
+
const owner = ownerMessageIdForTagRow(row);
|
|
167414
|
+
if (row.token_count === null) {
|
|
167415
|
+
nullMessageIds.add(owner);
|
|
167416
|
+
totals.delete(owner);
|
|
167417
|
+
continue;
|
|
167418
|
+
}
|
|
167419
|
+
if (nullMessageIds.has(owner))
|
|
167420
|
+
continue;
|
|
167421
|
+
const weight = (row.token_count ?? 0) + (row.input_token_count ?? 0) + (row.reasoning_token_count ?? 0);
|
|
167422
|
+
totals.set(owner, (totals.get(owner) ?? 0) + weight);
|
|
167423
|
+
}
|
|
167424
|
+
return { totals, nullMessageIds };
|
|
167425
|
+
}
|
|
167426
|
+
function updateTagInputTokenCount(db, sessionId, tagNumber, newInputTokenCount) {
|
|
167427
|
+
getUpdateTagInputTokenCountStatement(db).run(newInputTokenCount, sessionId, tagNumber);
|
|
167428
|
+
}
|
|
167429
|
+
function tagTokenCountIsNull(db, sessionId, tagNumber) {
|
|
167430
|
+
const row = db.prepare("SELECT token_count FROM tags WHERE session_id = ? AND tag_number = ?").get(sessionId, tagNumber);
|
|
167431
|
+
return row !== undefined && row.token_count === null;
|
|
167432
|
+
}
|
|
167433
|
+
function backfillTagTokenCounts(db, sessionId, tagNumber, counts) {
|
|
167434
|
+
db.prepare(`UPDATE tags
|
|
167435
|
+
SET token_count = ?, input_token_count = ?, reasoning_token_count = ?
|
|
167436
|
+
WHERE session_id = ? AND tag_number = ? AND token_count IS NULL`).run(counts.tokenCount ?? null, counts.inputTokenCount ?? null, counts.reasoningTokenCount ?? null, sessionId, tagNumber);
|
|
167437
|
+
}
|
|
166828
167438
|
function getMaxTagNumberBySessionStatement(db) {
|
|
166829
167439
|
let stmt = getMaxTagNumberBySessionStatements.get(db);
|
|
166830
167440
|
if (!stmt) {
|
|
@@ -166877,8 +167487,8 @@ function isMaxTagNumberRow(row) {
|
|
|
166877
167487
|
const r = row;
|
|
166878
167488
|
return typeof r.max_tag_number === "number";
|
|
166879
167489
|
}
|
|
166880
|
-
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0, toolOwnerMessageId = null, entryFingerprint = null) {
|
|
166881
|
-
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness(), toolOwnerMessageId, entryFingerprint);
|
|
167490
|
+
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0, toolOwnerMessageId = null, entryFingerprint = null, tokenCounts = null) {
|
|
167491
|
+
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness(), toolOwnerMessageId, entryFingerprint, tokenCounts?.tokenCount ?? null, tokenCounts?.inputTokenCount ?? null, tokenCounts?.reasoningTokenCount ?? null);
|
|
166882
167492
|
return tagNumber;
|
|
166883
167493
|
}
|
|
166884
167494
|
function updateTagStatus(db, sessionId, tagId, status) {
|
|
@@ -166946,13 +167556,6 @@ function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
|
166946
167556
|
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);
|
|
166947
167557
|
return rows.map(toTagEntry);
|
|
166948
167558
|
}
|
|
166949
|
-
function getTopNBySize(db, sessionId, n) {
|
|
166950
|
-
if (n <= 0) {
|
|
166951
|
-
return [];
|
|
166952
|
-
}
|
|
166953
|
-
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);
|
|
166954
|
-
return rows.map(toTagEntry);
|
|
166955
|
-
}
|
|
166956
167559
|
var getToolTagNumberByOwnerStatements = new WeakMap;
|
|
166957
167560
|
var getNullOwnerToolTagStatements = new WeakMap;
|
|
166958
167561
|
var adoptNullOwnerToolTagStatements = new WeakMap;
|
|
@@ -167018,44 +167621,43 @@ var ERROR_CLASSES = new Set([
|
|
|
167018
167621
|
"permission_denied",
|
|
167019
167622
|
"unknown"
|
|
167020
167623
|
]);
|
|
167624
|
+
// src/tools/ctx-memory.ts
|
|
167625
|
+
init_logger();
|
|
167626
|
+
|
|
167627
|
+
// ../plugin/src/tools/ctx-memory/constants.ts
|
|
167628
|
+
var CTX_MEMORY_DESCRIPTION = `Durable project knowledge shared across every session on this project.
|
|
167629
|
+
|
|
167630
|
+
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.
|
|
167631
|
+
|
|
167632
|
+
Actions:
|
|
167633
|
+
- write: save a new memory (content + category).
|
|
167634
|
+
- update: rewrite one memory whose fact changed (ids: [one], content).
|
|
167635
|
+
- archive: retire wrong or obsolete memories (ids: [one or more], optional reason).
|
|
167636
|
+
- merge: collapse duplicates into one memory (ids: [two or more], content).
|
|
167637
|
+
|
|
167638
|
+
Example: ctx_memory(action="write", category="CONSTRAINTS", content="Pi stores sessions as JSONL under ~/.pi/agent/sessions/, not SQLite")`;
|
|
167639
|
+
|
|
167021
167640
|
// src/tools/ctx-memory.ts
|
|
167022
167641
|
var DEFAULT_LIST_LIMIT = 10;
|
|
167023
|
-
var
|
|
167024
|
-
|
|
167025
|
-
return VALID_CATEGORIES.has(value);
|
|
167026
|
-
}
|
|
167027
|
-
var ALL_ACTIONS = [
|
|
167028
|
-
"write",
|
|
167029
|
-
"delete",
|
|
167030
|
-
"list",
|
|
167031
|
-
"update",
|
|
167032
|
-
"merge",
|
|
167033
|
-
"archive"
|
|
167034
|
-
];
|
|
167035
|
-
var DREAMER_ONLY_ACTIONS = new Set([
|
|
167036
|
-
"list",
|
|
167037
|
-
"update",
|
|
167038
|
-
"merge",
|
|
167039
|
-
"archive"
|
|
167040
|
-
]);
|
|
167642
|
+
var ALL_ACTIONS = ["write", "archive", "update", "merge", "list"];
|
|
167643
|
+
var DREAMER_ONLY_ACTIONS = new Set(["list"]);
|
|
167041
167644
|
var ParamsSchema2 = exports_typebox.Object({
|
|
167042
|
-
action: exports_typebox.Union(ALL_ACTIONS.map((a) => exports_typebox.Literal(a)), { description: "
|
|
167645
|
+
action: exports_typebox.Union(ALL_ACTIONS.map((a) => exports_typebox.Literal(a)), { description: "What to do: write, update, archive, or merge" }),
|
|
167043
167646
|
content: exports_typebox.Optional(exports_typebox.String({
|
|
167044
|
-
description: "
|
|
167045
|
-
})),
|
|
167046
|
-
category: exports_typebox.Optional(exports_typebox.String({
|
|
167047
|
-
description: "Memory category (required for write, optional filter for list, optional override for merge). One of: " + CATEGORY_PRIORITY.join(", ")
|
|
167647
|
+
description: "The memory text — one standalone fact (required for write, update, merge)"
|
|
167048
167648
|
})),
|
|
167049
|
-
|
|
167050
|
-
description: "
|
|
167649
|
+
category: exports_typebox.Optional(exports_typebox.Union(V2_MEMORY_CATEGORIES.map((c) => exports_typebox.Literal(c)), {
|
|
167650
|
+
description: "What kind of fact this is (required for write; optional merge override)"
|
|
167051
167651
|
})),
|
|
167052
167652
|
ids: exports_typebox.Optional(exports_typebox.Array(exports_typebox.Number(), {
|
|
167053
|
-
description: "
|
|
167653
|
+
description: "Target memory id(s) from <project-memory>: update takes exactly one, archive one or more, merge two or more"
|
|
167054
167654
|
})),
|
|
167055
167655
|
limit: exports_typebox.Optional(exports_typebox.Number({
|
|
167056
|
-
description: "
|
|
167656
|
+
description: "Max results for list (default: 10)"
|
|
167057
167657
|
})),
|
|
167058
|
-
reason: exports_typebox.Optional(exports_typebox.String({
|
|
167658
|
+
reason: exports_typebox.Optional(exports_typebox.String({
|
|
167659
|
+
description: "Why the memory is being archived (optional, recommended)"
|
|
167660
|
+
}))
|
|
167059
167661
|
});
|
|
167060
167662
|
function ok2(text) {
|
|
167061
167663
|
return { content: [{ type: "text", text }], details: undefined };
|
|
@@ -167102,6 +167704,12 @@ function formatMemoryList(memories) {
|
|
|
167102
167704
|
].join(`
|
|
167103
167705
|
`);
|
|
167104
167706
|
}
|
|
167707
|
+
function isPrimaryMutableMemory(memory2) {
|
|
167708
|
+
return (memory2.status === "active" || memory2.status === "permanent") && memory2.supersededByMemoryId === null;
|
|
167709
|
+
}
|
|
167710
|
+
function inactiveMemoryError(id, action2) {
|
|
167711
|
+
return `Error: Memory with ID ${id} is archived or superseded; restore it before ${action2}.`;
|
|
167712
|
+
}
|
|
167105
167713
|
function queueEmbedding(args) {
|
|
167106
167714
|
const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
|
|
167107
167715
|
if (!snapshot?.enabled)
|
|
@@ -167122,7 +167730,8 @@ function queueEmbedding(args) {
|
|
|
167122
167730
|
}
|
|
167123
167731
|
function createCtxMemoryTool(deps) {
|
|
167124
167732
|
const dreamerAllowed = deps.allowDreamerActions === true;
|
|
167125
|
-
const description = dreamerAllowed ?
|
|
167733
|
+
const description = dreamerAllowed ? `${CTX_MEMORY_DESCRIPTION}
|
|
167734
|
+
- list: enumerate stored memories (maintenance sessions).` : CTX_MEMORY_DESCRIPTION;
|
|
167126
167735
|
return {
|
|
167127
167736
|
name: "ctx_memory",
|
|
167128
167737
|
label: "Magic Context: Memory",
|
|
@@ -167143,13 +167752,10 @@ function createCtxMemoryTool(deps) {
|
|
|
167143
167752
|
const content = params.content?.trim();
|
|
167144
167753
|
if (!content)
|
|
167145
167754
|
return err2("Error: 'content' is required when action is 'write'.");
|
|
167146
|
-
const rawCategory = params.category
|
|
167755
|
+
const rawCategory = params.category;
|
|
167147
167756
|
if (!rawCategory) {
|
|
167148
167757
|
return err2("Error: 'category' is required when action is 'write'.");
|
|
167149
167758
|
}
|
|
167150
|
-
if (!isMemoryCategory2(rawCategory)) {
|
|
167151
|
-
return err2(`Error: Unknown memory category '${rawCategory}'. Valid: ${CATEGORY_PRIORITY.join(", ")}`);
|
|
167152
|
-
}
|
|
167153
167759
|
const existing = getMemoryByHash(deps.db, projectIdentity, rawCategory, computeNormalizedHash(content));
|
|
167154
167760
|
if (existing) {
|
|
167155
167761
|
updateMemorySeenCount(deps.db, existing.id);
|
|
@@ -167165,42 +167771,29 @@ function createCtxMemoryTool(deps) {
|
|
|
167165
167771
|
queueEmbedding({ deps, projectIdentity, memoryId: memory2.id, content });
|
|
167166
167772
|
return ok2(`Saved memory [ID: ${memory2.id}] in ${rawCategory}.`);
|
|
167167
167773
|
}
|
|
167168
|
-
if (params.action === "delete") {
|
|
167169
|
-
if (typeof params.id !== "number" || !Number.isInteger(params.id)) {
|
|
167170
|
-
return err2("Error: 'id' is required when action is 'delete'.");
|
|
167171
|
-
}
|
|
167172
|
-
const memory2 = getMemoryById(deps.db, params.id);
|
|
167173
|
-
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
167174
|
-
return err2(`Error: Memory with ID ${params.id} was not found.`);
|
|
167175
|
-
}
|
|
167176
|
-
deps.db.transaction(() => {
|
|
167177
|
-
archiveMemory(deps.db, params.id);
|
|
167178
|
-
queueMemoryMutation(deps.db, {
|
|
167179
|
-
projectPath: projectIdentity,
|
|
167180
|
-
mutationType: "delete",
|
|
167181
|
-
targetMemoryId: params.id
|
|
167182
|
-
});
|
|
167183
|
-
})();
|
|
167184
|
-
return ok2(`Archived memory [ID: ${params.id}].`);
|
|
167185
|
-
}
|
|
167186
167774
|
if (params.action === "list") {
|
|
167187
167775
|
const limit = normalizeLimit(params.limit);
|
|
167188
167776
|
const filtered = getMemoriesByProject(deps.db, projectIdentity);
|
|
167189
|
-
const category = params.category
|
|
167777
|
+
const category = params.category;
|
|
167190
167778
|
const filtered2 = category ? filtered.filter((m) => m.category === category) : filtered;
|
|
167191
167779
|
return ok2(formatMemoryList(filtered2.slice(0, limit)));
|
|
167192
167780
|
}
|
|
167193
167781
|
if (params.action === "update") {
|
|
167194
|
-
|
|
167195
|
-
|
|
167782
|
+
const updateIds = params.ids;
|
|
167783
|
+
if (!updateIds || updateIds.length !== 1 || !updateIds.every(Number.isInteger)) {
|
|
167784
|
+
return err2("Error: 'ids' must contain exactly one integer memory ID when action is 'update'.");
|
|
167196
167785
|
}
|
|
167786
|
+
const updateId = updateIds[0];
|
|
167197
167787
|
const content = params.content?.trim();
|
|
167198
167788
|
if (!content) {
|
|
167199
167789
|
return err2("Error: 'content' is required when action is 'update'.");
|
|
167200
167790
|
}
|
|
167201
|
-
const memory2 = getMemoryById(deps.db,
|
|
167791
|
+
const memory2 = getMemoryById(deps.db, updateId);
|
|
167202
167792
|
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
167203
|
-
return err2(`Error: Memory with ID ${
|
|
167793
|
+
return err2(`Error: Memory with ID ${updateId} was not found.`);
|
|
167794
|
+
}
|
|
167795
|
+
if (!dreamerAllowed && !isPrimaryMutableMemory(memory2)) {
|
|
167796
|
+
return err2(inactiveMemoryError(updateId, "updating"));
|
|
167204
167797
|
}
|
|
167205
167798
|
const normalizedHash = computeNormalizedHash(content);
|
|
167206
167799
|
const duplicate = getMemoryByHash(deps.db, projectIdentity, memory2.category, normalizedHash);
|
|
@@ -167221,9 +167814,12 @@ function createCtxMemoryTool(deps) {
|
|
|
167221
167814
|
return ok2(`Updated memory [ID: ${memory2.id}] in ${memory2.category}.`);
|
|
167222
167815
|
}
|
|
167223
167816
|
if (params.action === "merge") {
|
|
167224
|
-
const ids = params.ids
|
|
167225
|
-
if (!ids || ids.length < 2) {
|
|
167226
|
-
return err2("Error: 'ids' must include at least two memory IDs when action is 'merge'.");
|
|
167817
|
+
const ids = params.ids;
|
|
167818
|
+
if (!ids || ids.length < 2 || !ids.every(Number.isInteger)) {
|
|
167819
|
+
return err2("Error: 'ids' must include at least two integer memory IDs when action is 'merge'.");
|
|
167820
|
+
}
|
|
167821
|
+
if (new Set(ids).size !== ids.length) {
|
|
167822
|
+
return err2("Error: 'ids' must include at least two distinct memory IDs when action is 'merge'.");
|
|
167227
167823
|
}
|
|
167228
167824
|
const content = params.content?.trim();
|
|
167229
167825
|
if (!content) {
|
|
@@ -167233,11 +167829,17 @@ function createCtxMemoryTool(deps) {
|
|
|
167233
167829
|
if (sourceMemories.length !== ids.length) {
|
|
167234
167830
|
return err2("Error: One or more source memories were not found.");
|
|
167235
167831
|
}
|
|
167236
|
-
|
|
167237
|
-
|
|
167238
|
-
|
|
167832
|
+
if (!dreamerAllowed) {
|
|
167833
|
+
const foreign = sourceMemories.find((memory2) => !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity));
|
|
167834
|
+
if (foreign) {
|
|
167835
|
+
return err2(`Error: Memory with ID ${foreign.id} was not found.`);
|
|
167836
|
+
}
|
|
167837
|
+
const inactive = sourceMemories.find((memory2) => !isPrimaryMutableMemory(memory2));
|
|
167838
|
+
if (inactive) {
|
|
167839
|
+
return err2(inactiveMemoryError(inactive.id, "merging"));
|
|
167840
|
+
}
|
|
167239
167841
|
}
|
|
167240
|
-
const requestedCategoryTyped =
|
|
167842
|
+
const requestedCategoryTyped = params.category;
|
|
167241
167843
|
const fallbackCategory = sourceMemories[0]?.category;
|
|
167242
167844
|
const category = requestedCategoryTyped ?? fallbackCategory;
|
|
167243
167845
|
if (!category) {
|
|
@@ -167317,29 +167919,57 @@ function createCtxMemoryTool(deps) {
|
|
|
167317
167919
|
return ok2(`Merged memories [${ids.join(", ")}] into canonical memory [ID: ${canonicalMemory.id}] in ${category}; superseded [${supersededIds.join(", ")}].`);
|
|
167318
167920
|
}
|
|
167319
167921
|
if (params.action === "archive") {
|
|
167320
|
-
|
|
167321
|
-
|
|
167922
|
+
const archiveIds = params.ids;
|
|
167923
|
+
if (!archiveIds || archiveIds.length === 0 || !archiveIds.every(Number.isInteger)) {
|
|
167924
|
+
return err2("Error: 'ids' must contain at least one integer memory ID when action is 'archive'.");
|
|
167322
167925
|
}
|
|
167323
|
-
const
|
|
167324
|
-
|
|
167325
|
-
|
|
167926
|
+
for (const memoryId of archiveIds) {
|
|
167927
|
+
const memory2 = getMemoryById(deps.db, memoryId);
|
|
167928
|
+
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
167929
|
+
return err2(`Error: Memory with ID ${memoryId} was not found.`);
|
|
167930
|
+
}
|
|
167931
|
+
if (!dreamerAllowed && !isPrimaryMutableMemory(memory2)) {
|
|
167932
|
+
return err2(inactiveMemoryError(memoryId, "archiving"));
|
|
167933
|
+
}
|
|
167326
167934
|
}
|
|
167327
167935
|
deps.db.transaction(() => {
|
|
167328
|
-
|
|
167329
|
-
|
|
167330
|
-
|
|
167331
|
-
|
|
167332
|
-
|
|
167333
|
-
|
|
167936
|
+
for (const memoryId of archiveIds) {
|
|
167937
|
+
archiveMemory(deps.db, memoryId, params.reason);
|
|
167938
|
+
queueMemoryMutation(deps.db, {
|
|
167939
|
+
projectPath: projectIdentity,
|
|
167940
|
+
mutationType: "archive",
|
|
167941
|
+
targetMemoryId: memoryId
|
|
167942
|
+
});
|
|
167943
|
+
}
|
|
167334
167944
|
})();
|
|
167335
167945
|
const reasonSuffix = params.reason ? ` (${params.reason})` : "";
|
|
167336
|
-
|
|
167946
|
+
const idList = archiveIds.join(", ");
|
|
167947
|
+
const plural = archiveIds.length > 1 ? "memories" : "memory";
|
|
167948
|
+
return ok2(`Archived ${plural} [ID: ${idList}]${reasonSuffix}.`);
|
|
167337
167949
|
}
|
|
167338
167950
|
return err2("Error: Unknown action.");
|
|
167339
167951
|
}
|
|
167340
167952
|
};
|
|
167341
167953
|
}
|
|
167342
167954
|
|
|
167955
|
+
// ../plugin/src/tools/ctx-note/constants.ts
|
|
167956
|
+
var CTX_NOTE_DESCRIPTION = `Working notes for this session's future — reminders, follow-ups, and things to revisit later.
|
|
167957
|
+
|
|
167958
|
+
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.
|
|
167959
|
+
|
|
167960
|
+
Actions:
|
|
167961
|
+
- write: save a note (content). Add surface_condition to make it a smart note (below).
|
|
167962
|
+
- 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.
|
|
167963
|
+
- update / dismiss: change or retire a note by note_id.
|
|
167964
|
+
|
|
167965
|
+
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:
|
|
167966
|
+
✓ "When PR #42 in cortexkit/magic-context is merged"
|
|
167967
|
+
✓ "When the latest release tag is >= v0.22.0"
|
|
167968
|
+
✓ "When packages/plugin/src/foo.ts contains a function named bar"
|
|
167969
|
+
✗ "When the user mentions X" / "when we revisit Y" / "after we finish this refactor" — no external signal; write a regular note instead.
|
|
167970
|
+
|
|
167971
|
+
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")`;
|
|
167972
|
+
|
|
167343
167973
|
// src/tools/ctx-note.ts
|
|
167344
167974
|
var FILTER_VALUES = [
|
|
167345
167975
|
"active",
|
|
@@ -167359,13 +167989,19 @@ var ParamsSchema3 = exports_typebox.Object({
|
|
|
167359
167989
|
})),
|
|
167360
167990
|
content: exports_typebox.Optional(exports_typebox.String({ description: "Note text to store when action is 'write'." })),
|
|
167361
167991
|
surface_condition: exports_typebox.Optional(exports_typebox.String({
|
|
167362
|
-
description: "
|
|
167992
|
+
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."
|
|
167363
167993
|
})),
|
|
167364
167994
|
note_id: exports_typebox.Optional(exports_typebox.Number({
|
|
167365
167995
|
description: "Note ID (required for 'dismiss' and 'update' actions)."
|
|
167366
167996
|
})),
|
|
167367
167997
|
filter: exports_typebox.Optional(exports_typebox.Union(FILTER_VALUES.map((value) => exports_typebox.Literal(value)), {
|
|
167368
167998
|
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."
|
|
167999
|
+
})),
|
|
168000
|
+
limit: exports_typebox.Optional(exports_typebox.Number({
|
|
168001
|
+
description: "Max notes per section for read, newest first (default: 25)"
|
|
168002
|
+
})),
|
|
168003
|
+
offset: exports_typebox.Optional(exports_typebox.Number({
|
|
168004
|
+
description: "Skip this many newest notes for read — page older ones (default: 0)"
|
|
167369
168005
|
}))
|
|
167370
168006
|
});
|
|
167371
168007
|
function ok3(text) {
|
|
@@ -167402,15 +168038,20 @@ function formatNoteLine(note) {
|
|
|
167402
168038
|
var DISMISS_FOOTER = `
|
|
167403
168039
|
|
|
167404
168040
|
To dismiss a stale note: ctx_note(action="dismiss", note_id=N)`;
|
|
168041
|
+
var DEFAULT_READ_LIMIT = 25;
|
|
168042
|
+
function paginateNewestFirst(notes, limit, offset) {
|
|
168043
|
+
const total = notes.length;
|
|
168044
|
+
const newestFirst = [...notes].reverse();
|
|
168045
|
+
const page = newestFirst.slice(offset, offset + limit);
|
|
168046
|
+
const remaining = total - offset - page.length;
|
|
168047
|
+
const footer = remaining > 0 ? `Showing ${page.length} of ${total} (newest first) — ${remaining} older: ctx_note(action="read", offset=${offset + page.length})` : null;
|
|
168048
|
+
return { page, total, footer };
|
|
168049
|
+
}
|
|
167405
168050
|
function createCtxNoteTool(deps) {
|
|
167406
168051
|
return {
|
|
167407
168052
|
name: "ctx_note",
|
|
167408
168053
|
label: "Magic Context: Notes",
|
|
167409
|
-
description:
|
|
167410
|
-
` + `Use this for short goals, constraints, decisions, or reminders worth carrying forward.
|
|
167411
|
-
|
|
167412
|
-
` + `Actions:
|
|
167413
|
-
` + "- `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")`',
|
|
168054
|
+
description: CTX_NOTE_DESCRIPTION,
|
|
167414
168055
|
parameters: ParamsSchema3,
|
|
167415
168056
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
167416
168057
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
@@ -167492,11 +168133,15 @@ function createCtxNoteTool(deps) {
|
|
|
167492
168133
|
- ${parts.join(`
|
|
167493
168134
|
- `)}`);
|
|
167494
168135
|
}
|
|
168136
|
+
const limit = typeof params.limit === "number" && params.limit > 0 ? Math.floor(params.limit) : DEFAULT_READ_LIMIT;
|
|
168137
|
+
const offset = typeof params.offset === "number" && params.offset > 0 ? Math.floor(params.offset) : 0;
|
|
167495
168138
|
const sections = readNotes({
|
|
167496
168139
|
db: deps.db,
|
|
167497
168140
|
sessionId,
|
|
167498
168141
|
cwd: ctx.cwd,
|
|
167499
|
-
filter: params.filter
|
|
168142
|
+
filter: params.filter,
|
|
168143
|
+
limit,
|
|
168144
|
+
offset
|
|
167500
168145
|
});
|
|
167501
168146
|
try {
|
|
167502
168147
|
setNoteLastReadAt(deps.db, sessionId);
|
|
@@ -167504,7 +168149,7 @@ function createCtxNoteTool(deps) {
|
|
|
167504
168149
|
if (sections.length === 0) {
|
|
167505
168150
|
return ok3(`## Notes
|
|
167506
168151
|
|
|
167507
|
-
No notes
|
|
168152
|
+
No session notes or smart notes.`);
|
|
167508
168153
|
}
|
|
167509
168154
|
const body = sections.join(`
|
|
167510
168155
|
|
|
@@ -167531,10 +168176,14 @@ function readNotes(args) {
|
|
|
167531
168176
|
}) : [];
|
|
167532
168177
|
const sections2 = [];
|
|
167533
168178
|
if (sessionNotes2.length > 0) {
|
|
168179
|
+
const { page, footer } = paginateNewestFirst(sessionNotes2, args.limit, args.offset);
|
|
168180
|
+
const lines = page.map(formatNoteLine).join(`
|
|
168181
|
+
`);
|
|
167534
168182
|
sections2.push(`## Session Notes
|
|
167535
168183
|
|
|
167536
|
-
${
|
|
167537
|
-
|
|
168184
|
+
${lines}${footer ? `
|
|
168185
|
+
|
|
168186
|
+
${footer}` : ""}`);
|
|
167538
168187
|
}
|
|
167539
168188
|
if (readySmartNotes.length > 0) {
|
|
167540
168189
|
sections2.push(`## \uD83D\uDD14 Ready Smart Notes
|
|
@@ -167565,17 +168214,25 @@ ${readySmartNotes.map(formatNoteLine).join(`
|
|
|
167565
168214
|
}) : [];
|
|
167566
168215
|
const sections = [];
|
|
167567
168216
|
if (sessionNotes.length > 0) {
|
|
168217
|
+
const { page, footer } = paginateNewestFirst(sessionNotes, args.limit, args.offset);
|
|
168218
|
+
const lines = page.map(formatNoteLine).join(`
|
|
168219
|
+
`);
|
|
167568
168220
|
sections.push(`## Session Notes
|
|
167569
168221
|
|
|
167570
|
-
${
|
|
167571
|
-
|
|
168222
|
+
${lines}${footer ? `
|
|
168223
|
+
|
|
168224
|
+
${footer}` : ""}`);
|
|
167572
168225
|
}
|
|
167573
168226
|
if (smartNotes.length > 0) {
|
|
168227
|
+
const { page, footer } = paginateNewestFirst(smartNotes, args.limit, args.offset);
|
|
168228
|
+
const lines = page.map(formatNoteLine).join(`
|
|
168229
|
+
|
|
168230
|
+
`);
|
|
167574
168231
|
sections.push(`## Smart Notes
|
|
167575
168232
|
|
|
167576
|
-
${
|
|
168233
|
+
${lines}${footer ? `
|
|
167577
168234
|
|
|
167578
|
-
`
|
|
168235
|
+
${footer}` : ""}`);
|
|
167579
168236
|
}
|
|
167580
168237
|
return sections;
|
|
167581
168238
|
}
|
|
@@ -167731,7 +168388,11 @@ function createCtxReduceTool(deps) {
|
|
|
167731
168388
|
};
|
|
167732
168389
|
}
|
|
167733
168390
|
|
|
168391
|
+
// ../plugin/src/features/magic-context/search.ts
|
|
168392
|
+
init_logger();
|
|
168393
|
+
|
|
167734
168394
|
// ../plugin/src/features/magic-context/git-commits/git-log-reader.ts
|
|
168395
|
+
init_logger();
|
|
167735
168396
|
import { execFile } from "node:child_process";
|
|
167736
168397
|
import { promisify } from "node:util";
|
|
167737
168398
|
var execFileAsync = promisify(execFile);
|
|
@@ -167815,7 +168476,11 @@ ${body}` : subject;
|
|
|
167815
168476
|
}
|
|
167816
168477
|
return commits;
|
|
167817
168478
|
}
|
|
168479
|
+
// ../plugin/src/features/magic-context/git-commits/indexer.ts
|
|
168480
|
+
init_logger();
|
|
168481
|
+
|
|
167818
168482
|
// ../plugin/src/features/magic-context/git-commits/storage-git-commits.ts
|
|
168483
|
+
init_logger();
|
|
167819
168484
|
var insertStatements = new WeakMap;
|
|
167820
168485
|
var existingShasStatements = new WeakMap;
|
|
167821
168486
|
var projectCountStatements = new WeakMap;
|
|
@@ -168028,6 +168693,7 @@ async function embedUnembeddedCommits(db, projectPath) {
|
|
|
168028
168693
|
}
|
|
168029
168694
|
}
|
|
168030
168695
|
// ../plugin/src/features/magic-context/git-commits/search-git-commits.ts
|
|
168696
|
+
init_logger();
|
|
168031
168697
|
var ftsStatements = new WeakMap;
|
|
168032
168698
|
var ftsPlainStatements = new WeakMap;
|
|
168033
168699
|
var getBySHAStatements = new WeakMap;
|
|
@@ -168698,6 +169364,9 @@ class BoundedSessionMap {
|
|
|
168698
169364
|
}
|
|
168699
169365
|
}
|
|
168700
169366
|
|
|
169367
|
+
// ../plugin/src/hooks/magic-context/inject-compartments.ts
|
|
169368
|
+
init_logger();
|
|
169369
|
+
|
|
168701
169370
|
// ../plugin/src/hooks/magic-context/decay-curve.ts
|
|
168702
169371
|
var H50 = 24;
|
|
168703
169372
|
var D = 25;
|
|
@@ -168980,6 +169649,7 @@ function isAftAvailable() {
|
|
|
168980
169649
|
}
|
|
168981
169650
|
|
|
168982
169651
|
// ../plugin/src/hooks/magic-context/key-files-block.ts
|
|
169652
|
+
init_logger();
|
|
168983
169653
|
var cachedKeyFilesBySession = new Map;
|
|
168984
169654
|
var staleUpdates = new Map;
|
|
168985
169655
|
function staleKey(update2) {
|
|
@@ -169233,6 +169903,21 @@ function renderMemoryBlockV2(memories, wrapper = "project-memory") {
|
|
|
169233
169903
|
`);
|
|
169234
169904
|
}
|
|
169235
169905
|
|
|
169906
|
+
// ../plugin/src/tools/ctx-search/constants.ts
|
|
169907
|
+
var CTX_SEARCH_DESCRIPTION = `Your long-term recall for this project — search everything that ever happened here, not just what's currently visible.
|
|
169908
|
+
|
|
169909
|
+
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.
|
|
169910
|
+
|
|
169911
|
+
Sources (omit for a broad search across all):
|
|
169912
|
+
- memory: curated cross-session project knowledge — rules, constraints, conventions.
|
|
169913
|
+
- 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).
|
|
169914
|
+
- git_commit: this repository's commit history.
|
|
169915
|
+
|
|
169916
|
+
Picking sources:
|
|
169917
|
+
- "when did this change / was this working before" → ["git_commit", "message"]
|
|
169918
|
+
- "did we discuss this earlier" → ["message"]
|
|
169919
|
+
- "what's our convention / rule for X" → ["memory"]`;
|
|
169920
|
+
|
|
169236
169921
|
// src/tools/ctx-search.ts
|
|
169237
169922
|
var DEFAULT_LIMIT = 10;
|
|
169238
169923
|
var ParamsSchema5 = exports_typebox.Object({
|
|
@@ -169316,18 +170001,7 @@ function createCtxSearchTool(deps) {
|
|
|
169316
170001
|
return {
|
|
169317
170002
|
name: "ctx_search",
|
|
169318
170003
|
label: "Magic Context: Search",
|
|
169319
|
-
description:
|
|
169320
|
-
|
|
169321
|
-
` + `Sources:
|
|
169322
|
-
` + `- memory: curated cross-session knowledge for this project
|
|
169323
|
-
` + `- message: raw user/assistant messages from older compartmentalized history
|
|
169324
|
-
` + `- git_commit: HEAD git commits (when git commit indexing is enabled)
|
|
169325
|
-
|
|
169326
|
-
` + "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"]
|
|
169327
|
-
` + `- "when did we change this" → ["git_commit"]
|
|
169328
|
-
` + `- "what is our naming convention" → ["memory"]
|
|
169329
|
-
` + `- "did we discuss this earlier" → ["message"]
|
|
169330
|
-
` + "Omit sources for a broad search across all enabled channels.",
|
|
170004
|
+
description: CTX_SEARCH_DESCRIPTION,
|
|
169331
170005
|
parameters: ParamsSchema5,
|
|
169332
170006
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
169333
170007
|
const query = params.query?.trim();
|
|
@@ -169444,13 +170118,15 @@ function registerMagicContextTools(pi, opts) {
|
|
|
169444
170118
|
embeddingEnabled: opts.embeddingEnabled,
|
|
169445
170119
|
gitCommitsEnabled: opts.gitCommitsEnabled
|
|
169446
170120
|
}));
|
|
169447
|
-
|
|
169448
|
-
|
|
169449
|
-
|
|
169450
|
-
|
|
169451
|
-
|
|
169452
|
-
|
|
169453
|
-
|
|
170121
|
+
if (opts.memoryToolEnabled !== false) {
|
|
170122
|
+
pi.registerTool(createCtxMemoryTool({
|
|
170123
|
+
db: opts.db,
|
|
170124
|
+
ensureProjectRegistered: opts.ensureProjectRegistered,
|
|
170125
|
+
memoryEnabled: opts.memoryEnabled,
|
|
170126
|
+
embeddingEnabled: opts.embeddingEnabled,
|
|
170127
|
+
allowDreamerActions: opts.allowDreamerActions ?? false
|
|
170128
|
+
}));
|
|
170129
|
+
}
|
|
169454
170130
|
if (!opts.sessionScopedToolsDisabled) {
|
|
169455
170131
|
pi.registerTool(createCtxNoteTool({
|
|
169456
170132
|
db: opts.db,
|
|
@@ -169473,7 +170149,7 @@ var openedDb;
|
|
|
169473
170149
|
function magicContextSubagentExtension(pi) {
|
|
169474
170150
|
setHarness("pi");
|
|
169475
170151
|
pi.registerFlag(SUBAGENT_DREAMER_ACTIONS_FLAG, {
|
|
169476
|
-
description: "
|
|
170152
|
+
description: "Register ctx_memory with dreamer actions for Magic Context subagents.",
|
|
169477
170153
|
type: "boolean",
|
|
169478
170154
|
default: false
|
|
169479
170155
|
});
|
|
@@ -169491,10 +170167,11 @@ function magicContextSubagentExtension(pi) {
|
|
|
169491
170167
|
registerMagicContextTools(pi, {
|
|
169492
170168
|
db,
|
|
169493
170169
|
ensureProjectRegistered: ensureProjectRegisteredFromPiDirectory,
|
|
170170
|
+
memoryToolEnabled: dreamerActionsEnabled,
|
|
169494
170171
|
allowDreamerActions: dreamerActionsEnabled,
|
|
169495
170172
|
sessionScopedToolsDisabled: true
|
|
169496
170173
|
});
|
|
169497
|
-
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})`);
|
|
170174
|
+
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})`);
|
|
169498
170175
|
} catch (err5) {
|
|
169499
170176
|
const message = err5 instanceof Error ? err5.message : String(err5);
|
|
169500
170177
|
log(`[pi-subagent] startup failed: ${message}`);
|