@cortexkit/pi-magic-context 0.22.0 → 0.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +628 -459
- package/dist/subagent-entry.js +433 -177
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -86,9 +86,6 @@ function getMagicContextStorageDir() {
|
|
|
86
86
|
function getLegacyOpenCodeMagicContextStorageDir() {
|
|
87
87
|
return path2.join(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
88
88
|
}
|
|
89
|
-
function getCacheDir() {
|
|
90
|
-
return process.env.XDG_CACHE_HOME ?? path2.join(os.homedir(), ".cache");
|
|
91
|
-
}
|
|
92
89
|
var init_data_path = () => {};
|
|
93
90
|
|
|
94
91
|
// ../plugin/src/shared/logger.ts
|
|
@@ -142698,7 +142695,7 @@ var databases = new Map;
|
|
|
142698
142695
|
var persistenceByDatabase = new WeakMap;
|
|
142699
142696
|
var persistenceErrorByDatabase = new WeakMap;
|
|
142700
142697
|
var lastSchemaFenceRejection = null;
|
|
142701
|
-
var LATEST_SUPPORTED_VERSION =
|
|
142698
|
+
var LATEST_SUPPORTED_VERSION = 29;
|
|
142702
142699
|
function resolveDatabasePath(dbPathOverride) {
|
|
142703
142700
|
if (dbPathOverride) {
|
|
142704
142701
|
return { dbDir: dirname2(dbPathOverride), dbPath: dbPathOverride };
|
|
@@ -143018,6 +143015,17 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143018
143015
|
updated_at INTEGER NOT NULL DEFAULT 0
|
|
143019
143016
|
);
|
|
143020
143017
|
|
|
143018
|
+
CREATE TABLE IF NOT EXISTS git_sweep_coordinator (
|
|
143019
|
+
project_path TEXT PRIMARY KEY,
|
|
143020
|
+
lease_holder TEXT,
|
|
143021
|
+
lease_expires_at INTEGER,
|
|
143022
|
+
last_swept_at INTEGER
|
|
143023
|
+
);
|
|
143024
|
+
CREATE INDEX IF NOT EXISTS idx_git_sweep_coordinator_lease_expires
|
|
143025
|
+
ON git_sweep_coordinator(lease_expires_at);
|
|
143026
|
+
CREATE INDEX IF NOT EXISTS idx_git_sweep_coordinator_last_swept
|
|
143027
|
+
ON git_sweep_coordinator(last_swept_at);
|
|
143028
|
+
|
|
143021
143029
|
CREATE TABLE IF NOT EXISTS m0_mutation_log (
|
|
143022
143030
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143023
143031
|
session_id TEXT NOT NULL,
|
|
@@ -144240,6 +144248,38 @@ var MIGRATIONS = [
|
|
|
144240
144248
|
ON tags(session_id, entry_fingerprint)
|
|
144241
144249
|
WHERE type='message' AND entry_fingerprint IS NOT NULL`);
|
|
144242
144250
|
}
|
|
144251
|
+
},
|
|
144252
|
+
{
|
|
144253
|
+
version: 28,
|
|
144254
|
+
description: "Add git commit sweep coordinator lease/cooldown table",
|
|
144255
|
+
up: (db) => {
|
|
144256
|
+
db.exec(`
|
|
144257
|
+
CREATE TABLE IF NOT EXISTS git_sweep_coordinator (
|
|
144258
|
+
project_path TEXT PRIMARY KEY,
|
|
144259
|
+
lease_holder TEXT,
|
|
144260
|
+
lease_expires_at INTEGER,
|
|
144261
|
+
last_swept_at INTEGER
|
|
144262
|
+
);
|
|
144263
|
+
CREATE INDEX IF NOT EXISTS idx_git_sweep_coordinator_lease_expires
|
|
144264
|
+
ON git_sweep_coordinator(lease_expires_at);
|
|
144265
|
+
CREATE INDEX IF NOT EXISTS idx_git_sweep_coordinator_last_swept
|
|
144266
|
+
ON git_sweep_coordinator(last_swept_at);
|
|
144267
|
+
`);
|
|
144268
|
+
}
|
|
144269
|
+
},
|
|
144270
|
+
{
|
|
144271
|
+
version: 29,
|
|
144272
|
+
description: "Add anchor_ordinal to notes (traceback to the conversation tail)",
|
|
144273
|
+
up: (db) => {
|
|
144274
|
+
const notesExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='notes'").get();
|
|
144275
|
+
if (!notesExists) {
|
|
144276
|
+
return;
|
|
144277
|
+
}
|
|
144278
|
+
const columns = db.prepare("PRAGMA table_info(notes)").all();
|
|
144279
|
+
if (!columns.some((column) => column.name === "anchor_ordinal")) {
|
|
144280
|
+
db.exec("ALTER TABLE notes ADD COLUMN anchor_ordinal INTEGER");
|
|
144281
|
+
}
|
|
144282
|
+
}
|
|
144243
144283
|
}
|
|
144244
144284
|
];
|
|
144245
144285
|
var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -145127,7 +145167,8 @@ function toNote(row) {
|
|
|
145127
145167
|
updatedAt: row.updated_at,
|
|
145128
145168
|
lastCheckedAt: toNullableNumber(row.last_checked_at),
|
|
145129
145169
|
readyAt: toNullableNumber(row.ready_at),
|
|
145130
|
-
readyReason: toNullableString(row.ready_reason)
|
|
145170
|
+
readyReason: toNullableString(row.ready_reason),
|
|
145171
|
+
anchorOrdinal: toNullableNumber(row.anchor_ordinal)
|
|
145131
145172
|
};
|
|
145132
145173
|
}
|
|
145133
145174
|
function getNoteById(db, noteId) {
|
|
@@ -145179,7 +145220,7 @@ function getNotes(db, options = {}) {
|
|
|
145179
145220
|
}
|
|
145180
145221
|
function addNote(db, type, options) {
|
|
145181
145222
|
const now = Date.now();
|
|
145182
|
-
const result = type === "session" ? db.prepare("INSERT INTO notes (type, status, content, session_id, created_at, updated_at, harness) VALUES ('session', 'active', ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId, now, now, getHarness()) : db.prepare("INSERT INTO notes (type, status, content, session_id, project_path, surface_condition, created_at, updated_at, harness) VALUES ('smart', 'pending', ?, ?, ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId ?? null, options.projectPath, options.surfaceCondition, now, now, getHarness());
|
|
145223
|
+
const result = type === "session" ? db.prepare("INSERT INTO notes (type, status, content, session_id, created_at, updated_at, harness, anchor_ordinal) VALUES ('session', 'active', ?, ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId, now, now, getHarness(), options.anchorOrdinal ?? null) : db.prepare("INSERT INTO notes (type, status, content, session_id, project_path, surface_condition, created_at, updated_at, harness, anchor_ordinal) VALUES ('smart', 'pending', ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId ?? null, options.projectPath, options.surfaceCondition, now, now, getHarness(), options.anchorOrdinal ?? null);
|
|
145183
145224
|
if (!isNoteRow(result)) {
|
|
145184
145225
|
throw new Error("[notes] failed to insert note");
|
|
145185
145226
|
}
|
|
@@ -145949,219 +145990,56 @@ function getAgentFallbackModels(agent) {
|
|
|
145949
145990
|
|
|
145950
145991
|
// ../plugin/src/shared/models-dev-cache.ts
|
|
145951
145992
|
init_data_path();
|
|
145952
|
-
|
|
145953
|
-
import {
|
|
145954
|
-
import { homedir as homedir2, platform } from "node:os";
|
|
145993
|
+
init_logger();
|
|
145994
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, writeFileSync } from "node:fs";
|
|
145955
145995
|
import { join as join6 } from "node:path";
|
|
145956
|
-
|
|
145957
|
-
|
|
145958
|
-
function
|
|
145959
|
-
|
|
145960
|
-
let inString = false;
|
|
145961
|
-
let escaped = false;
|
|
145962
|
-
let inLineComment = false;
|
|
145963
|
-
let inBlockComment = false;
|
|
145964
|
-
for (let index = 0;index < content.length; index += 1) {
|
|
145965
|
-
const char = content[index];
|
|
145966
|
-
const next = content[index + 1];
|
|
145967
|
-
if (inLineComment) {
|
|
145968
|
-
if (char === `
|
|
145969
|
-
`) {
|
|
145970
|
-
inLineComment = false;
|
|
145971
|
-
result += char;
|
|
145972
|
-
}
|
|
145973
|
-
continue;
|
|
145974
|
-
}
|
|
145975
|
-
if (inBlockComment) {
|
|
145976
|
-
if (char === "*" && next === "/") {
|
|
145977
|
-
inBlockComment = false;
|
|
145978
|
-
index += 1;
|
|
145979
|
-
}
|
|
145980
|
-
continue;
|
|
145981
|
-
}
|
|
145982
|
-
if (inString) {
|
|
145983
|
-
result += char;
|
|
145984
|
-
if (escaped) {
|
|
145985
|
-
escaped = false;
|
|
145986
|
-
} else if (char === "\\") {
|
|
145987
|
-
escaped = true;
|
|
145988
|
-
} else if (char === '"') {
|
|
145989
|
-
inString = false;
|
|
145990
|
-
}
|
|
145991
|
-
continue;
|
|
145992
|
-
}
|
|
145993
|
-
if (char === '"') {
|
|
145994
|
-
inString = true;
|
|
145995
|
-
result += char;
|
|
145996
|
-
continue;
|
|
145997
|
-
}
|
|
145998
|
-
if (char === "/" && next === "/") {
|
|
145999
|
-
inLineComment = true;
|
|
146000
|
-
index += 1;
|
|
146001
|
-
continue;
|
|
146002
|
-
}
|
|
146003
|
-
if (char === "/" && next === "*") {
|
|
146004
|
-
inBlockComment = true;
|
|
146005
|
-
index += 1;
|
|
146006
|
-
continue;
|
|
146007
|
-
}
|
|
146008
|
-
result += char;
|
|
146009
|
-
}
|
|
146010
|
-
return result;
|
|
145996
|
+
var MIN_SANE_LIMIT = 20000;
|
|
145997
|
+
var MAX_SANE_LIMIT = 3000000;
|
|
145998
|
+
function isSaneLimit(limit) {
|
|
145999
|
+
return typeof limit === "number" && limit >= MIN_SANE_LIMIT && limit <= MAX_SANE_LIMIT;
|
|
146011
146000
|
}
|
|
146012
|
-
function stripTrailingCommas(content) {
|
|
146013
|
-
let result = "";
|
|
146014
|
-
let inString = false;
|
|
146015
|
-
let escaped = false;
|
|
146016
|
-
for (let index = 0;index < content.length; index += 1) {
|
|
146017
|
-
const char = content[index];
|
|
146018
|
-
if (inString) {
|
|
146019
|
-
result += char;
|
|
146020
|
-
if (escaped) {
|
|
146021
|
-
escaped = false;
|
|
146022
|
-
} else if (char === "\\") {
|
|
146023
|
-
escaped = true;
|
|
146024
|
-
} else if (char === '"') {
|
|
146025
|
-
inString = false;
|
|
146026
|
-
}
|
|
146027
|
-
continue;
|
|
146028
|
-
}
|
|
146029
|
-
if (char === '"') {
|
|
146030
|
-
inString = true;
|
|
146031
|
-
result += char;
|
|
146032
|
-
continue;
|
|
146033
|
-
}
|
|
146034
|
-
if (char === ",") {
|
|
146035
|
-
let lookahead = index + 1;
|
|
146036
|
-
while (lookahead < content.length && /\s/.test(content[lookahead] ?? "")) {
|
|
146037
|
-
lookahead += 1;
|
|
146038
|
-
}
|
|
146039
|
-
const next = content[lookahead];
|
|
146040
|
-
if (next === "}" || next === "]") {
|
|
146041
|
-
continue;
|
|
146042
|
-
}
|
|
146043
|
-
}
|
|
146044
|
-
result += char;
|
|
146045
|
-
}
|
|
146046
|
-
return result;
|
|
146047
|
-
}
|
|
146048
|
-
function parseJsonc(content) {
|
|
146049
|
-
const normalized = stripTrailingCommas(stripJsonComments(content));
|
|
146050
|
-
return JSON.parse(normalized);
|
|
146051
|
-
}
|
|
146052
|
-
|
|
146053
|
-
// ../plugin/src/shared/models-dev-cache.ts
|
|
146054
|
-
init_logger();
|
|
146055
|
-
var RELOAD_INTERVAL_MS = 5 * 60 * 1000;
|
|
146056
146001
|
var apiCache = null;
|
|
146057
|
-
var
|
|
146058
|
-
|
|
146059
|
-
|
|
146060
|
-
function hashFast(input) {
|
|
146061
|
-
return createHash5("sha1").update(input).digest("hex");
|
|
146062
|
-
}
|
|
146063
|
-
function getModelsJsonPath() {
|
|
146064
|
-
const explicit = process.env.OPENCODE_MODELS_PATH?.trim();
|
|
146065
|
-
if (explicit)
|
|
146066
|
-
return explicit;
|
|
146067
|
-
const cacheBase = getCacheDir();
|
|
146068
|
-
const source = process.env.OPENCODE_MODELS_URL?.trim();
|
|
146069
|
-
const filename = source && source !== "https://models.dev" ? `models-${hashFast(source)}.json` : "models.json";
|
|
146070
|
-
return join6(cacheBase, "opencode", filename);
|
|
146071
|
-
}
|
|
146072
|
-
function getOpencodeConfigPath() {
|
|
146073
|
-
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
146074
|
-
const configDir = envDir ? envDir : platform() === "win32" ? join6(homedir2(), ".config", "opencode") : join6(process.env.XDG_CONFIG_HOME || join6(homedir2(), ".config"), "opencode");
|
|
146075
|
-
const jsonc = join6(configDir, "opencode.jsonc");
|
|
146076
|
-
if (existsSync5(jsonc))
|
|
146077
|
-
return jsonc;
|
|
146078
|
-
const json = join6(configDir, "opencode.json");
|
|
146079
|
-
if (existsSync5(json))
|
|
146080
|
-
return json;
|
|
146081
|
-
return null;
|
|
146002
|
+
var persistSeedLoaded = false;
|
|
146003
|
+
function persistFilePath() {
|
|
146004
|
+
return join6(getMagicContextStorageDir(), `model-context-limits-${getHarness()}.json`);
|
|
146082
146005
|
}
|
|
146083
|
-
function
|
|
146084
|
-
if (
|
|
146006
|
+
function loadPersistedApiCacheOnce() {
|
|
146007
|
+
if (persistSeedLoaded || apiCache !== null)
|
|
146085
146008
|
return;
|
|
146086
|
-
|
|
146087
|
-
return limit.input;
|
|
146088
|
-
if (typeof limit.context === "number" && limit.context > 0)
|
|
146089
|
-
return limit.context;
|
|
146090
|
-
return;
|
|
146091
|
-
}
|
|
146092
|
-
function setCachedModelMetadata(cache, key, model) {
|
|
146093
|
-
const limit = resolveLimit(model?.limit);
|
|
146094
|
-
if (limit === undefined) {
|
|
146095
|
-
return;
|
|
146096
|
-
}
|
|
146097
|
-
const value = { limit };
|
|
146098
|
-
cache.set(key, value);
|
|
146099
|
-
const modes = model?.experimental?.modes;
|
|
146100
|
-
if (modes && typeof modes === "object") {
|
|
146101
|
-
for (const mode of Object.keys(modes)) {
|
|
146102
|
-
cache.set(`${key}-${mode}`, value);
|
|
146103
|
-
}
|
|
146104
|
-
}
|
|
146105
|
-
}
|
|
146106
|
-
function loadModelsDevMetadataFromFile() {
|
|
146107
|
-
const metadata = new Map;
|
|
146108
|
-
const modelsJsonPath = getModelsJsonPath();
|
|
146109
|
-
let fileFound = false;
|
|
146009
|
+
persistSeedLoaded = true;
|
|
146110
146010
|
try {
|
|
146111
|
-
|
|
146112
|
-
|
|
146113
|
-
|
|
146114
|
-
|
|
146115
|
-
|
|
146116
|
-
|
|
146117
|
-
continue;
|
|
146118
|
-
for (const [modelId, model] of Object.entries(provider.models)) {
|
|
146119
|
-
setCachedModelMetadata(metadata, `${providerId}/${modelId}`, model);
|
|
146120
|
-
}
|
|
146121
|
-
}
|
|
146011
|
+
const raw = readFileSync3(persistFilePath(), "utf-8");
|
|
146012
|
+
const obj = JSON.parse(raw);
|
|
146013
|
+
const map = new Map;
|
|
146014
|
+
for (const [key, limit] of Object.entries(obj)) {
|
|
146015
|
+
if (isSaneLimit(limit))
|
|
146016
|
+
map.set(key, { limit });
|
|
146122
146017
|
}
|
|
146123
|
-
|
|
146124
|
-
|
|
146125
|
-
|
|
146126
|
-
try {
|
|
146127
|
-
const configPath = getOpencodeConfigPath();
|
|
146128
|
-
if (configPath && existsSync5(configPath)) {
|
|
146129
|
-
const config = parseJsonc(readFileSync3(configPath, "utf-8"));
|
|
146130
|
-
if (config.provider && typeof config.provider === "object") {
|
|
146131
|
-
for (const [providerId, provider] of Object.entries(config.provider)) {
|
|
146132
|
-
if (!provider?.models || typeof provider.models !== "object")
|
|
146133
|
-
continue;
|
|
146134
|
-
for (const [modelId, model] of Object.entries(provider.models)) {
|
|
146135
|
-
setCachedModelMetadata(metadata, `${providerId}/${modelId}`, model);
|
|
146136
|
-
}
|
|
146137
|
-
}
|
|
146138
|
-
}
|
|
146018
|
+
if (map.size > 0) {
|
|
146019
|
+
apiCache = map;
|
|
146020
|
+
sessionLog("global", `models-dev-cache: seeded ${map.size} entries from persisted cache (cold start)`);
|
|
146139
146021
|
}
|
|
146140
|
-
} catch
|
|
146141
|
-
sessionLog("global", "models-dev-cache: failed to read opencode config for custom models:", error instanceof Error ? error.message : String(error));
|
|
146142
|
-
}
|
|
146143
|
-
sessionLog("global", `models-dev-cache: file-layer loaded ${metadata.size} model metadata entries (modelsJsonPath=${modelsJsonPath}, found=${fileFound})`);
|
|
146144
|
-
return metadata;
|
|
146022
|
+
} catch {}
|
|
146145
146023
|
}
|
|
146146
|
-
function
|
|
146147
|
-
|
|
146148
|
-
|
|
146149
|
-
|
|
146150
|
-
if (typeof fromApi === "number")
|
|
146151
|
-
return fromApi;
|
|
146152
|
-
}
|
|
146153
|
-
const now = Date.now();
|
|
146154
|
-
if (!fileCache || now - fileLastAttempt > RELOAD_INTERVAL_MS) {
|
|
146155
|
-
fileLastAttempt = now;
|
|
146156
|
-
fileCache = loadModelsDevMetadataFromFile();
|
|
146157
|
-
}
|
|
146158
|
-
return fileCache.get(key)?.limit;
|
|
146024
|
+
function getSdkContextLimit(providerID, modelID) {
|
|
146025
|
+
loadPersistedApiCacheOnce();
|
|
146026
|
+
const fromApi = lookupLimitWithTagFallback(apiCache, providerID, modelID);
|
|
146027
|
+
return isSaneLimit(fromApi) ? fromApi : undefined;
|
|
146159
146028
|
}
|
|
146160
|
-
function
|
|
146161
|
-
|
|
146162
|
-
|
|
146163
|
-
|
|
146164
|
-
|
|
146029
|
+
function lookupLimitWithTagFallback(cache, providerID, modelID) {
|
|
146030
|
+
if (!cache)
|
|
146031
|
+
return;
|
|
146032
|
+
const exact = cache.get(`${providerID}/${modelID}`)?.limit;
|
|
146033
|
+
if (typeof exact === "number")
|
|
146034
|
+
return exact;
|
|
146035
|
+
const colonIdx = modelID.lastIndexOf(":");
|
|
146036
|
+
if (colonIdx > 0) {
|
|
146037
|
+
const baseModel = modelID.slice(0, colonIdx);
|
|
146038
|
+
const fallback = cache.get(`${providerID}/${baseModel}`)?.limit;
|
|
146039
|
+
if (typeof fallback === "number")
|
|
146040
|
+
return fallback;
|
|
146041
|
+
}
|
|
146042
|
+
return;
|
|
146165
146043
|
}
|
|
146166
146044
|
|
|
146167
146045
|
// ../plugin/src/hooks/magic-context/derive-budgets.ts
|
|
@@ -146193,7 +146071,7 @@ function resolveHistorianContextLimit(historianModelOverride) {
|
|
|
146193
146071
|
const [providerID, ...rest] = historianModelOverride.split("/");
|
|
146194
146072
|
const modelID = rest.join("/");
|
|
146195
146073
|
if (providerID && modelID) {
|
|
146196
|
-
const limit =
|
|
146074
|
+
const limit = getSdkContextLimit(providerID, modelID);
|
|
146197
146075
|
if (typeof limit === "number" && limit > 0)
|
|
146198
146076
|
return limit;
|
|
146199
146077
|
}
|
|
@@ -146212,7 +146090,7 @@ function resolveHistorianContextLimit(historianModelOverride) {
|
|
|
146212
146090
|
const modelID = rest.join("/");
|
|
146213
146091
|
if (!providerID || !modelID)
|
|
146214
146092
|
continue;
|
|
146215
|
-
const limit =
|
|
146093
|
+
const limit = getSdkContextLimit(providerID, modelID);
|
|
146216
146094
|
if (typeof limit !== "number" || limit <= 0)
|
|
146217
146095
|
continue;
|
|
146218
146096
|
if (minLimit === undefined || limit < minLimit)
|
|
@@ -146225,37 +146103,6 @@ function resolveHistorianContextLimit(historianModelOverride) {
|
|
|
146225
146103
|
init_logger();
|
|
146226
146104
|
var DEFAULT_CONTEXT_LIMIT = 128000;
|
|
146227
146105
|
var MAX_EXECUTE_THRESHOLD = 80;
|
|
146228
|
-
function resolveContextLimit(providerID, modelID, ctx) {
|
|
146229
|
-
const fromModelsDev = providerID && modelID ? getModelsDevContextLimit(providerID, modelID) : undefined;
|
|
146230
|
-
const baseline = fromModelsDev ?? DEFAULT_CONTEXT_LIMIT;
|
|
146231
|
-
if (ctx?.db && ctx.sessionID) {
|
|
146232
|
-
try {
|
|
146233
|
-
const overflow = getOverflowState(ctx.db, ctx.sessionID);
|
|
146234
|
-
if (overflow.detectedContextLimit > 0 && overflow.detectedContextLimit < baseline) {
|
|
146235
|
-
return overflow.detectedContextLimit;
|
|
146236
|
-
}
|
|
146237
|
-
} catch {}
|
|
146238
|
-
}
|
|
146239
|
-
return baseline;
|
|
146240
|
-
}
|
|
146241
|
-
function resolveTrustedContextLimit(providerID, modelID, ctx) {
|
|
146242
|
-
const fromModelsDev = providerID && modelID ? getModelsDevContextLimit(providerID, modelID) : undefined;
|
|
146243
|
-
let detected;
|
|
146244
|
-
if (ctx?.db && ctx.sessionID) {
|
|
146245
|
-
try {
|
|
146246
|
-
const overflow = getOverflowState(ctx.db, ctx.sessionID);
|
|
146247
|
-
if (overflow.detectedContextLimit > 0) {
|
|
146248
|
-
detected = overflow.detectedContextLimit;
|
|
146249
|
-
}
|
|
146250
|
-
} catch {}
|
|
146251
|
-
}
|
|
146252
|
-
if (typeof fromModelsDev === "number" && fromModelsDev > 0) {
|
|
146253
|
-
if (detected !== undefined && detected < fromModelsDev)
|
|
146254
|
-
return detected;
|
|
146255
|
-
return fromModelsDev;
|
|
146256
|
-
}
|
|
146257
|
-
return detected;
|
|
146258
|
-
}
|
|
146259
146106
|
function resolveCacheTtl(cacheTtl, modelKey) {
|
|
146260
146107
|
if (typeof cacheTtl === "string") {
|
|
146261
146108
|
return cacheTtl;
|
|
@@ -146345,8 +146192,21 @@ function resolveExecuteThresholdDetail(config, modelKey, fallback, options) {
|
|
|
146345
146192
|
if (!Number.isFinite(resolved) || resolved < 0) {
|
|
146346
146193
|
resolved = fallback;
|
|
146347
146194
|
}
|
|
146195
|
+
const cappedPercentage = Math.min(resolved, MAX_EXECUTE_THRESHOLD);
|
|
146196
|
+
if (cappedPercentage < resolved) {
|
|
146197
|
+
const dedupeKey = `pct|${options?.sessionId ?? "__global__"}|${modelKey ?? "__default__"}|${resolved}`;
|
|
146198
|
+
if (!clampWarnSeen.has(dedupeKey)) {
|
|
146199
|
+
clampWarnSeen.add(dedupeKey);
|
|
146200
|
+
const msg = `execute_threshold clamped ${resolved}% → ${MAX_EXECUTE_THRESHOLD}% for ${modelKey ?? "default"} (capped for cache safety; a large step can overflow before compaction, and 80% stays below the 85%/95% emergency bands)`;
|
|
146201
|
+
if (options?.sessionId) {
|
|
146202
|
+
sessionLog(options.sessionId, `WARN: ${msg}`);
|
|
146203
|
+
} else {
|
|
146204
|
+
log(`[magic-context] WARN: ${msg}`);
|
|
146205
|
+
}
|
|
146206
|
+
}
|
|
146207
|
+
}
|
|
146348
146208
|
return {
|
|
146349
|
-
percentage:
|
|
146209
|
+
percentage: cappedPercentage,
|
|
146350
146210
|
mode: "percentage",
|
|
146351
146211
|
matchedKey
|
|
146352
146212
|
};
|
|
@@ -146463,7 +146323,7 @@ function clearNoteNudgeTriggerOnly(db, sessionId) {
|
|
|
146463
146323
|
}
|
|
146464
146324
|
|
|
146465
146325
|
// ../plugin/src/hooks/magic-context/todo-view.ts
|
|
146466
|
-
import { createHash as
|
|
146326
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
146467
146327
|
var TERMINAL_STATUSES = new Set(["completed", "cancelled"]);
|
|
146468
146328
|
var TITLE_DONE_STATUSES = new Set(["completed"]);
|
|
146469
146329
|
var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
|
|
@@ -146508,7 +146368,7 @@ function buildSyntheticTodoPart(stateJson) {
|
|
|
146508
146368
|
};
|
|
146509
146369
|
}
|
|
146510
146370
|
function computeSyntheticCallId(stateJson) {
|
|
146511
|
-
const hash =
|
|
146371
|
+
const hash = createHash5("sha256").update(stateJson).digest("hex").slice(0, 16);
|
|
146512
146372
|
return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
|
|
146513
146373
|
}
|
|
146514
146374
|
function parseTodoState(stateJson) {
|
|
@@ -146680,7 +146540,12 @@ function markAnnouncementSeen(version) {
|
|
|
146680
146540
|
function shouldShowAnnouncement() {
|
|
146681
146541
|
if (!ANNOUNCEMENT_VERSION || ANNOUNCEMENT_FEATURES.length === 0)
|
|
146682
146542
|
return false;
|
|
146683
|
-
|
|
146543
|
+
const lastVersion = readLastAnnouncedVersion();
|
|
146544
|
+
if (!lastVersion) {
|
|
146545
|
+
markAnnouncementSeen(ANNOUNCEMENT_VERSION);
|
|
146546
|
+
return false;
|
|
146547
|
+
}
|
|
146548
|
+
return lastVersion !== ANNOUNCEMENT_VERSION;
|
|
146684
146549
|
}
|
|
146685
146550
|
|
|
146686
146551
|
// src/index.ts
|
|
@@ -146757,7 +146622,7 @@ init_logger();
|
|
|
146757
146622
|
|
|
146758
146623
|
// src/subagent-runner.ts
|
|
146759
146624
|
import * as childProcess from "node:child_process";
|
|
146760
|
-
import { existsSync as
|
|
146625
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
146761
146626
|
import { createRequire as createRequire2 } from "node:module";
|
|
146762
146627
|
import { dirname as dirname3, join as join8, resolve as resolvePath } from "node:path";
|
|
146763
146628
|
import { createInterface } from "node:readline";
|
|
@@ -146861,7 +146726,7 @@ function resolveBundledPiCli() {
|
|
|
146861
146726
|
const require_ = createRequire2(import.meta.url);
|
|
146862
146727
|
const pkgJson = require_.resolve("@earendil-works/pi-coding-agent/package.json");
|
|
146863
146728
|
const cliPath = join8(dirname3(pkgJson), "dist/cli.js");
|
|
146864
|
-
if (
|
|
146729
|
+
if (existsSync6(cliPath))
|
|
146865
146730
|
return cliPath;
|
|
146866
146731
|
return null;
|
|
146867
146732
|
} catch {
|
|
@@ -146872,7 +146737,7 @@ function resolveSubagentEntryPath() {
|
|
|
146872
146737
|
try {
|
|
146873
146738
|
const here = dirname3(fileURLToPath(import.meta.url));
|
|
146874
146739
|
const candidate = resolvePath(here, "subagent-entry.js");
|
|
146875
|
-
if (
|
|
146740
|
+
if (existsSync6(candidate))
|
|
146876
146741
|
return candidate;
|
|
146877
146742
|
return;
|
|
146878
146743
|
} catch {
|
|
@@ -147632,7 +147497,7 @@ function clearStaleEntries(db, maxAgeMs, projectIdentity) {
|
|
|
147632
147497
|
// src/commands/ctx-dream.ts
|
|
147633
147498
|
init_logger();
|
|
147634
147499
|
// ../plugin/src/features/magic-context/dreamer/runner.ts
|
|
147635
|
-
import { existsSync as
|
|
147500
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
147636
147501
|
import { join as join11 } from "node:path";
|
|
147637
147502
|
|
|
147638
147503
|
// ../plugin/src/shared/index.ts
|
|
@@ -147886,12 +147751,12 @@ init_logger();
|
|
|
147886
147751
|
|
|
147887
147752
|
// ../plugin/src/features/magic-context/key-files/aft-availability.ts
|
|
147888
147753
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
147889
|
-
import { existsSync as
|
|
147890
|
-
import { homedir as
|
|
147754
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
|
|
147755
|
+
import { homedir as homedir2 } from "node:os";
|
|
147891
147756
|
import { join as join9 } from "node:path";
|
|
147892
147757
|
var overrideAvailability = null;
|
|
147893
147758
|
function parseConfig(path7) {
|
|
147894
|
-
if (!
|
|
147759
|
+
if (!existsSync7(path7))
|
|
147895
147760
|
return null;
|
|
147896
147761
|
return import_comment_json.parse(readFileSync5(path7, "utf-8"));
|
|
147897
147762
|
}
|
|
@@ -147913,7 +147778,7 @@ function hasAftAtKeys(value, keys) {
|
|
|
147913
147778
|
return false;
|
|
147914
147779
|
}
|
|
147915
147780
|
function getAftAvailability() {
|
|
147916
|
-
const home = process.env.HOME ||
|
|
147781
|
+
const home = process.env.HOME || homedir2();
|
|
147917
147782
|
const opencodePaths = [
|
|
147918
147783
|
join9(home, ".config", "opencode", "opencode.jsonc"),
|
|
147919
147784
|
join9(home, ".config", "opencode", "opencode.json")
|
|
@@ -148557,13 +148422,13 @@ function invalidateMemory(projectPath, memoryId) {
|
|
|
148557
148422
|
}
|
|
148558
148423
|
|
|
148559
148424
|
// ../plugin/src/features/magic-context/memory/normalize-hash.ts
|
|
148560
|
-
import { createHash as
|
|
148425
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
148561
148426
|
function normalizeMemoryContent(content) {
|
|
148562
148427
|
return content.toLowerCase().replace(/\s+/g, " ").trim();
|
|
148563
148428
|
}
|
|
148564
148429
|
function computeNormalizedHash(content) {
|
|
148565
148430
|
const normalized = normalizeMemoryContent(content);
|
|
148566
|
-
return
|
|
148431
|
+
return createHash6("md5").update(normalized).digest("hex");
|
|
148567
148432
|
}
|
|
148568
148433
|
|
|
148569
148434
|
// ../plugin/src/features/magic-context/memory/storage-memory.ts
|
|
@@ -149714,7 +149579,7 @@ function getOpenCodeDbPath2() {
|
|
|
149714
149579
|
}
|
|
149715
149580
|
function openOpenCodeDb() {
|
|
149716
149581
|
const dbPath = getOpenCodeDbPath2();
|
|
149717
|
-
if (!
|
|
149582
|
+
if (!existsSync8(dbPath)) {
|
|
149718
149583
|
log(`[key-files] OpenCode DB not found at ${dbPath} — skipping`);
|
|
149719
149584
|
return null;
|
|
149720
149585
|
}
|
|
@@ -149864,8 +149729,8 @@ async function runDream(args) {
|
|
|
149864
149729
|
try {
|
|
149865
149730
|
const docsDir = args.sessionDirectory ?? args.projectIdentity;
|
|
149866
149731
|
const existingDocs = taskName === "maintain-docs" ? {
|
|
149867
|
-
architecture:
|
|
149868
|
-
structure:
|
|
149732
|
+
architecture: existsSync8(join11(docsDir, "ARCHITECTURE.md")),
|
|
149733
|
+
structure: existsSync8(join11(docsDir, "STRUCTURE.md"))
|
|
149869
149734
|
} : undefined;
|
|
149870
149735
|
const userMemories = taskName === "archive-stale" ? getActiveUserMemories(args.db).map((um) => ({
|
|
149871
149736
|
id: um.id,
|
|
@@ -164841,25 +164706,26 @@ var PermissionSchema = exports_external.object({
|
|
|
164841
164706
|
external_directory: PermissionValueSchema.optional()
|
|
164842
164707
|
}).optional();
|
|
164843
164708
|
var AgentOverrideConfigSchema = exports_external.object({
|
|
164844
|
-
model: exports_external.string().optional(),
|
|
164845
|
-
temperature: exports_external.number().min(0).max(2).optional(),
|
|
164846
|
-
top_p: exports_external.number().min(0).max(1).optional(),
|
|
164847
|
-
prompt: exports_external.string().optional(),
|
|
164848
|
-
tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional(),
|
|
164849
|
-
disable: exports_external.boolean().optional(),
|
|
164850
|
-
description: exports_external.string().optional(),
|
|
164851
|
-
mode: exports_external.enum(["subagent", "primary", "all"]).optional(),
|
|
164852
|
-
color: exports_external.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
|
|
164853
|
-
maxSteps: exports_external.number().optional(),
|
|
164854
|
-
permission: PermissionSchema,
|
|
164855
|
-
maxTokens: exports_external.number().optional(),
|
|
164856
|
-
variant: exports_external.string().optional(),
|
|
164857
|
-
fallback_models: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).optional()
|
|
164709
|
+
model: exports_external.string().optional().describe("Primary model ID (e.g. 'claude-sonnet-4-6')"),
|
|
164710
|
+
temperature: exports_external.number().min(0).max(2).optional().describe("Sampling temperature (0-2)"),
|
|
164711
|
+
top_p: exports_external.number().min(0).max(1).optional().describe("Nucleus sampling top_p (0-1)"),
|
|
164712
|
+
prompt: exports_external.string().optional().describe("Additional system prompt text"),
|
|
164713
|
+
tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional().describe("Tool enable/disable overrides"),
|
|
164714
|
+
disable: exports_external.boolean().optional().describe("Disable this agent"),
|
|
164715
|
+
description: exports_external.string().optional().describe("Agent description"),
|
|
164716
|
+
mode: exports_external.enum(["subagent", "primary", "all"]).optional().describe("Agent mode (subagent, primary, or all)"),
|
|
164717
|
+
color: exports_external.string().regex(/^#[0-9A-Fa-f]{6}$/).optional().describe("Hex color for the agent (e.g. '#a1b2c3')"),
|
|
164718
|
+
maxSteps: exports_external.number().optional().describe("Maximum tool-call steps per invocation"),
|
|
164719
|
+
permission: PermissionSchema.describe("Per-tool permission overrides"),
|
|
164720
|
+
maxTokens: exports_external.number().optional().describe("Maximum output tokens"),
|
|
164721
|
+
variant: exports_external.string().optional().describe("OpenCode reasoning variant (e.g. for extended thinking)"),
|
|
164722
|
+
fallback_models: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).optional().describe("Fallback model IDs if primary is unavailable")
|
|
164858
164723
|
});
|
|
164859
164724
|
|
|
164860
164725
|
// ../plugin/src/config/schema/magic-context.ts
|
|
164861
164726
|
var DEFAULT_NUDGE_INTERVAL_TOKENS = 1e4;
|
|
164862
164727
|
var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65;
|
|
164728
|
+
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.";
|
|
164863
164729
|
var DEFAULT_HISTORIAN_TIMEOUT_MS = 300000;
|
|
164864
164730
|
var DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15;
|
|
164865
164731
|
var DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
|
|
@@ -164879,36 +164745,38 @@ var DEFAULT_DREAMER_TASKS = [
|
|
|
164879
164745
|
];
|
|
164880
164746
|
var PiThinkingLevelSchema = exports_external.enum(["off", "minimal", "low", "medium", "high", "xhigh"]).optional();
|
|
164881
164747
|
var DreamerConfigSchema = AgentOverrideConfigSchema.merge(exports_external.object({
|
|
164882
|
-
schedule: exports_external.string().default("02:00-06:00"),
|
|
164883
|
-
max_runtime_minutes: exports_external.number().min(10).default(120),
|
|
164884
|
-
tasks: exports_external.array(DreamingTaskSchema).default(DEFAULT_DREAMER_TASKS),
|
|
164885
|
-
task_timeout_minutes: exports_external.number().min(5).default(20),
|
|
164886
|
-
inject_docs: exports_external.boolean().default(true),
|
|
164748
|
+
schedule: exports_external.string().default("02:00-06:00").describe("Scheduled window for overnight dreaming (e.g. '02:00-06:00')"),
|
|
164749
|
+
max_runtime_minutes: exports_external.number().min(10).default(120).describe("Maximum runtime per dream session in minutes"),
|
|
164750
|
+
tasks: exports_external.array(DreamingTaskSchema).default(DEFAULT_DREAMER_TASKS).describe("Tasks to run during dreaming, in order"),
|
|
164751
|
+
task_timeout_minutes: exports_external.number().min(5).default(20).describe("Minutes allocated per task before moving to next"),
|
|
164752
|
+
inject_docs: exports_external.boolean().default(true).describe("Inject ARCHITECTURE.md and STRUCTURE.md into system prompt"),
|
|
164887
164753
|
user_memories: exports_external.object({
|
|
164888
|
-
enabled: exports_external.boolean().default(true),
|
|
164889
|
-
promotion_threshold: exports_external.number().min(2).max(20).default(3)
|
|
164890
|
-
}).default({ enabled: true, promotion_threshold: 3 }),
|
|
164754
|
+
enabled: exports_external.boolean().default(true).describe("Enable user memory extraction and promotion (default: true)"),
|
|
164755
|
+
promotion_threshold: exports_external.number().min(2).max(20).default(3).describe("Minimum candidate observations before dreamer considers promotion (default: 3)")
|
|
164756
|
+
}).default({ enabled: true, promotion_threshold: 3 }).describe("User memory pipeline: historian extracts behavior observations from each compartment run; dreamer reviews recurring patterns and promotes them to stable user memories injected into all sessions as <user-profile>. Requires dreamer to not be disabled for promotion to actually happen. Graduated from experimental in v0.14. Default: enabled."),
|
|
164891
164757
|
pin_key_files: exports_external.object({
|
|
164892
|
-
enabled: exports_external.boolean().default(false),
|
|
164893
|
-
token_budget: exports_external.number().min(2000).max(30000).default(1e4),
|
|
164894
|
-
min_reads: exports_external.number().min(2).max(20).default(4)
|
|
164895
|
-
}).default({ enabled: false, token_budget: 1e4, min_reads: 4 }),
|
|
164896
|
-
thinking_level: PiThinkingLevelSchema
|
|
164758
|
+
enabled: exports_external.boolean().default(false).describe("Enable key file pinning (default: false)"),
|
|
164759
|
+
token_budget: exports_external.number().min(2000).max(30000).default(1e4).describe("Total token budget for all pinned key files (min: 2000, max: 30000, default: 10000)"),
|
|
164760
|
+
min_reads: exports_external.number().min(2).max(20).default(4).describe("Minimum full-read count before a file is considered for pinning (min: 2, default: 4)")
|
|
164761
|
+
}).default({ enabled: false, token_budget: 1e4, min_reads: 4 }).describe("Pin frequently-read key files into the system prompt so the agent doesn't need to re-read them after context drops. Dreamer identifies key files per session based on read patterns. Requires dreamer to not be disabled for selection to happen. Graduated from experimental in v0.14. Default: disabled."),
|
|
164762
|
+
thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level for dreamer subagent invocations. See historian.thinking_level.")
|
|
164897
164763
|
}));
|
|
164898
164764
|
var SidekickConfigSchema = AgentOverrideConfigSchema.extend({
|
|
164899
|
-
timeout_ms: exports_external.number().default(30000),
|
|
164900
|
-
system_prompt: exports_external.string().optional(),
|
|
164901
|
-
thinking_level: PiThinkingLevelSchema
|
|
164765
|
+
timeout_ms: exports_external.number().default(30000).describe("Timeout for sidekick calls in milliseconds"),
|
|
164766
|
+
system_prompt: exports_external.string().optional().describe("Custom system prompt for sidekick"),
|
|
164767
|
+
thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level for sidekick subagent invocations. See historian.thinking_level.")
|
|
164902
164768
|
}).optional();
|
|
164903
164769
|
var HistorianConfigSchema = AgentOverrideConfigSchema.extend({
|
|
164904
|
-
two_pass: exports_external.boolean().default(false),
|
|
164905
|
-
thinking_level: PiThinkingLevelSchema
|
|
164770
|
+
two_pass: exports_external.boolean().default(false).describe("Run a second editor pass over historian output to clean low-signal U: lines and cross-compartment duplicates. Adds ~1 extra API call and ~1.3x cost per historian run. Useful for models without extended thinking support. (default: false)"),
|
|
164771
|
+
thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level passed as --thinking <level> to Pi historian subagent invocations. Required when using reasoning models (e.g. github-copilot/gpt-5.4) because Pi's default thinking-level resolution can pick a value the provider rejects. OpenCode users set variant instead. Valid: off | minimal | low | medium | high | xhigh")
|
|
164906
164772
|
}).optional();
|
|
164907
164773
|
var BaseEmbeddingConfigSchema = exports_external.object({
|
|
164908
|
-
provider: exports_external.enum(["local", "openai-compatible", "off"]).default("local"),
|
|
164909
|
-
model: exports_external.string().optional(),
|
|
164910
|
-
endpoint: exports_external.string().optional(),
|
|
164911
|
-
api_key: exports_external.string().optional()
|
|
164774
|
+
provider: exports_external.enum(["local", "openai-compatible", "off"]).default("local").describe("Embedding provider. 'local' uses Xenova/all-MiniLM-L6-v2, 'openai-compatible' requires endpoint and model, 'off' disables embeddings."),
|
|
164775
|
+
model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible, ignored for local."),
|
|
164776
|
+
endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
|
|
164777
|
+
api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
|
|
164778
|
+
input_type: exports_external.string().optional().describe("Optional input_type sent in the embedding request body. Required by some openai-compatible providers (e.g. NVIDIA NIM expects 'query' or 'passage'). Omitted from the request when unset."),
|
|
164779
|
+
truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset.")
|
|
164912
164780
|
}).superRefine((data, ctx) => {
|
|
164913
164781
|
if (data.provider === "openai-compatible" && !data.endpoint?.trim()) {
|
|
164914
164782
|
ctx.addIssue({
|
|
@@ -164934,76 +164802,80 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
|
|
|
164934
164802
|
}
|
|
164935
164803
|
if (data.provider === "openai-compatible") {
|
|
164936
164804
|
const apiKey = data.api_key?.trim();
|
|
164805
|
+
const inputType = data.input_type?.trim();
|
|
164806
|
+
const truncate = data.truncate?.trim();
|
|
164937
164807
|
return {
|
|
164938
164808
|
provider: "openai-compatible",
|
|
164939
164809
|
model: data.model?.trim() ?? "",
|
|
164940
164810
|
endpoint: data.endpoint?.trim() ?? "",
|
|
164941
|
-
...apiKey ? { api_key: apiKey } : {}
|
|
164811
|
+
...apiKey ? { api_key: apiKey } : {},
|
|
164812
|
+
...inputType ? { input_type: inputType } : {},
|
|
164813
|
+
...truncate ? { truncate } : {}
|
|
164942
164814
|
};
|
|
164943
164815
|
}
|
|
164944
164816
|
return { provider: "off" };
|
|
164945
164817
|
});
|
|
164946
164818
|
var MagicContextConfigSchema = exports_external.object({
|
|
164947
|
-
enabled: exports_external.boolean().default(true),
|
|
164948
|
-
auto_update: exports_external.boolean().optional(),
|
|
164949
|
-
ctx_reduce_enabled: exports_external.boolean().default(true),
|
|
164950
|
-
historian: HistorianConfigSchema,
|
|
164951
|
-
dreamer: DreamerConfigSchema.optional(),
|
|
164952
|
-
cache_ttl: exports_external.union([exports_external.string(), exports_external.object({ default: exports_external.string() }).catchall(exports_external.string())]).default("5m"),
|
|
164953
|
-
nudge_interval_tokens: exports_external.number().min(1000).default(DEFAULT_NUDGE_INTERVAL_TOKENS),
|
|
164819
|
+
enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
|
|
164820
|
+
auto_update: exports_external.boolean().optional().describe("Enable automatic npm self-update checks for the OpenCode plugin. Security: USER-only in config loader, so hostile project configs cannot suppress updates."),
|
|
164821
|
+
ctx_reduce_enabled: exports_external.boolean().default(true).describe("When false, ctx_reduce tool is hidden, all nudges disabled, and prompt guidance about ctx_reduce stripped. Heuristic cleanup, compartments, memory, and other features still work. (default: true)"),
|
|
164822
|
+
historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
|
|
164823
|
+
dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
|
|
164824
|
+
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" })'),
|
|
164825
|
+
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)"),
|
|
164954
164826
|
execute_threshold_percentage: exports_external.union([
|
|
164955
|
-
exports_external.number().min(20).max(80),
|
|
164956
|
-
exports_external.object({ default: exports_external.number().min(20).max(80) }).catchall(exports_external.number().min(20).max(80))
|
|
164957
|
-
]).default(DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE),
|
|
164827
|
+
exports_external.number().min(20).max(80, EXECUTE_THRESHOLD_CAP_MESSAGE),
|
|
164828
|
+
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))
|
|
164829
|
+
]).default(DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE).describe('Context percentage that forces queued operations to execute. Number or per-model object ({ default: 65, "provider/model": 45 }). Values above 80 are rejected because the runtime caps at 80% for cache safety (MAX_EXECUTE_THRESHOLD). Default: DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE'),
|
|
164958
164830
|
execute_threshold_tokens: exports_external.object({
|
|
164959
164831
|
default: exports_external.number().min(5000).max(2000000).optional()
|
|
164960
|
-
}).catchall(exports_external.number().min(5000).max(2000000)).optional(),
|
|
164961
|
-
protected_tags: exports_external.number().min(1).max(100).optional(),
|
|
164962
|
-
auto_drop_tool_age: exports_external.number().min(10).default(100),
|
|
164963
|
-
drop_tool_structure: exports_external.boolean().default(true),
|
|
164964
|
-
clear_reasoning_age: exports_external.number().min(10).default(50),
|
|
164965
|
-
iteration_nudge_threshold: exports_external.number().min(5).default(15),
|
|
164966
|
-
history_budget_percentage: exports_external.number().min(0.05).max(0.5).default(DEFAULT_HISTORY_BUDGET_PERCENTAGE),
|
|
164967
|
-
historian_timeout_ms: exports_external.number().min(60000).default(DEFAULT_HISTORIAN_TIMEOUT_MS),
|
|
164832
|
+
}).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."),
|
|
164833
|
+
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)"),
|
|
164834
|
+
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)"),
|
|
164835
|
+
drop_tool_structure: exports_external.boolean().default(true).describe("When true, dropped tool parts are fully removed instead of truncated in place (default: true)"),
|
|
164836
|
+
clear_reasoning_age: exports_external.number().min(10).default(50).describe("Clear reasoning/thinking blocks older than N tags (default: 50)"),
|
|
164837
|
+
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)"),
|
|
164838
|
+
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)"),
|
|
164839
|
+
historian_timeout_ms: exports_external.number().min(60000).default(DEFAULT_HISTORIAN_TIMEOUT_MS).describe("Timeout for each historian prompt call in milliseconds (default: 300000)"),
|
|
164968
164840
|
commit_cluster_trigger: exports_external.object({
|
|
164969
|
-
enabled: exports_external.boolean().default(true),
|
|
164970
|
-
min_clusters: exports_external.number().min(1).default(3)
|
|
164971
|
-
}).default({ enabled: true, min_clusters: 3 }),
|
|
164841
|
+
enabled: exports_external.boolean().default(true).describe("Enable commit-cluster based historian triggering (default: true)"),
|
|
164842
|
+
min_clusters: exports_external.number().min(1).default(3).describe("Minimum commit clusters required to trigger historian (min: 1, default: 3)")
|
|
164843
|
+
}).default({ enabled: true, min_clusters: 3 }).describe("Commit-cluster trigger: fire historian when enough commit clusters accumulate in the unsummarized tail"),
|
|
164972
164844
|
system_prompt_injection: exports_external.object({
|
|
164973
|
-
enabled: exports_external.boolean().default(true),
|
|
164974
|
-
skip_signatures: exports_external.array(exports_external.string()).default(["<!-- magic-context: skip -->"])
|
|
164845
|
+
enabled: exports_external.boolean().default(true).describe("When false, NO injection happens for ANY agent — global escape hatch. (default: true)"),
|
|
164846
|
+
skip_signatures: exports_external.array(exports_external.string()).default(["<!-- magic-context: skip -->"]).describe(`Substring opt-out list. If the agent's system prompt contains any of these strings, skip ALL Magic Context injection for that call. Default "<!-- magic-context: skip -->" is meant to be added inside a user's custom agent prompt to opt that agent out.`)
|
|
164975
164847
|
}).default({
|
|
164976
164848
|
enabled: true,
|
|
164977
164849
|
skip_signatures: ["<!-- magic-context: skip -->"]
|
|
164978
|
-
}),
|
|
164850
|
+
}).describe("Controls whether and where Magic Context augments the system prompt. Lets users opt specific agents out of the Magic Context guidance and the surrounding project-docs / user-profile / key-files blocks. OpenCode's internal hidden agents — title, summary, and compaction — are always skipped automatically."),
|
|
164979
164851
|
sqlite: exports_external.object({
|
|
164980
|
-
cache_size_mb: exports_external.number().min(2).max(2048).default(64),
|
|
164981
|
-
mmap_size_mb: exports_external.number().min(0).max(8192).default(0)
|
|
164982
|
-
}).default({ cache_size_mb: 64, mmap_size_mb: 0 }),
|
|
164852
|
+
cache_size_mb: exports_external.number().min(2).max(2048).default(64).describe("Page-cache size in MiB per connection (PRAGMA cache_size). Larger keeps more hot pages resident, cutting re-reads on repeated full-table scans. (min 2, max 2048, default 64)"),
|
|
164853
|
+
mmap_size_mb: exports_external.number().min(0).max(8192).default(0).describe("Memory-mapped I/O size in MiB (PRAGMA mmap_size). 0 disables mmap (SQLite default). Raising it can cut read overhead on large DBs at the cost of address space. (min 0, max 8192, default 0)")
|
|
164854
|
+
}).default({ cache_size_mb: 64, mmap_size_mb: 0 }).describe("SQLite connection tuning for Magic Context's own context.db. These are per-connection PRAGMAs applied at open; they do not change the schema or what is stored."),
|
|
164983
164855
|
embedding: EmbeddingConfigSchema.default({
|
|
164984
164856
|
provider: "local",
|
|
164985
164857
|
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
164986
|
-
}),
|
|
164987
|
-
temporal_awareness: exports_external.boolean().default(true),
|
|
164858
|
+
}).describe("Embedding provider configuration"),
|
|
164859
|
+
temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add start/end date attributes on compartments. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
|
|
164988
164860
|
caveman_text_compression: exports_external.object({
|
|
164989
|
-
enabled: exports_external.boolean().default(false),
|
|
164990
|
-
min_chars: exports_external.number().min(100).max(1e4).default(500)
|
|
164991
|
-
}).default({ enabled: false, min_chars: 500 }),
|
|
164861
|
+
enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Only active when ctx_reduce_enabled=false. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
|
|
164862
|
+
min_chars: exports_external.number().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
|
|
164863
|
+
}).default({ enabled: false, min_chars: 500 }).describe("Age-tier caveman compression for long user/assistant text parts. Only active when ctx_reduce_enabled is false. Oldest 20% of eligible tags (outside protected tail) go to ultra, next 20% to full, next 20% to lite, newest 40% untouched. Graduated from experimental.caveman_text_compression; opt-in, default off (lossy)."),
|
|
164992
164864
|
memory: exports_external.object({
|
|
164993
|
-
enabled: exports_external.boolean().default(true),
|
|
164994
|
-
injection_budget_tokens: exports_external.number().min(500).max(20000).default(4000),
|
|
164995
|
-
auto_promote: exports_external.boolean().default(true),
|
|
164996
|
-
retrieval_count_promotion_threshold: exports_external.number().min(1).default(3),
|
|
164865
|
+
enabled: exports_external.boolean().default(true).describe("Enable cross-session memory (default: true)"),
|
|
164866
|
+
injection_budget_tokens: exports_external.number().min(500).max(20000).default(4000).describe("Token budget for memory injection on session start (min: 500, max: 20000, default: 4000)"),
|
|
164867
|
+
auto_promote: exports_external.boolean().default(true).describe("Automatically promote eligible session facts into memory (default: true)"),
|
|
164868
|
+
retrieval_count_promotion_threshold: exports_external.number().min(1).default(3).describe("retrieval_count threshold for promoting memory to permanent status (min: 1, default: 3)"),
|
|
164997
164869
|
auto_search: exports_external.object({
|
|
164998
|
-
enabled: exports_external.boolean().default(true),
|
|
164999
|
-
score_threshold: exports_external.number().min(0.3).max(0.95).default(0.6),
|
|
165000
|
-
min_prompt_chars: exports_external.number().min(5).max(500).default(20)
|
|
165001
|
-
}).default({ enabled: true, score_threshold: 0.6, min_prompt_chars: 20 }),
|
|
164870
|
+
enabled: exports_external.boolean().default(true).describe("Automatically append a compact <ctx-search-hint> to eligible user messages when relevant memories, conversation, or commits are found. Graduated from experimental.auto_search; on by default (set false to opt out). Independent of memory.enabled."),
|
|
164871
|
+
score_threshold: exports_external.number().min(0.3).max(0.95).default(0.6).describe("Top hit score must exceed this threshold for the hint to fire (min: 0.3, max: 0.95, default: 0.60)"),
|
|
164872
|
+
min_prompt_chars: exports_external.number().min(5).max(500).default(20).describe("Skip hint when user message is shorter than this (min: 5, max: 500, default: 20)")
|
|
164873
|
+
}).default({ enabled: true, score_threshold: 0.6, min_prompt_chars: 20 }).describe("Auto-search hint: transform-time ctx_search on each new user message; when the top hit clears the threshold, append a compact <ctx-search-hint> block of vague fragments to that user message. Does NOT inject full content. Graduated from experimental.auto_search; enabled by default (set enabled: false to opt out). Independent of memory.enabled."),
|
|
165002
164874
|
git_commit_indexing: exports_external.object({
|
|
165003
|
-
enabled: exports_external.boolean().default(false),
|
|
165004
|
-
since_days: exports_external.number().min(7).max(3650).default(365),
|
|
165005
|
-
max_commits: exports_external.number().min(100).max(20000).default(2000)
|
|
165006
|
-
}).default({ enabled: false, since_days: 365, max_commits: 2000 })
|
|
164875
|
+
enabled: exports_external.boolean().default(false).describe("Index HEAD git commits for ctx_search (git_commit source). Graduated from experimental.git_commit_indexing; opt-in, default off. Independent of memory.enabled."),
|
|
164876
|
+
since_days: exports_external.number().min(7).max(3650).default(365).describe("Days of HEAD history to index (min: 7, max: 3650, default: 365)"),
|
|
164877
|
+
max_commits: exports_external.number().min(100).max(20000).default(2000).describe("Max commits kept per project; oldest evicted (min: 100, max: 20000, default: 2000)")
|
|
164878
|
+
}).default({ enabled: false, since_days: 365, max_commits: 2000 }).describe("Index git commit messages from HEAD into ctx_search. Commits become a 4th searchable source alongside memories and session history. Graduated from experimental.git_commit_indexing; opt-in, default off (per-project embedding cost). Independent of memory.enabled.")
|
|
165007
164879
|
}).default({
|
|
165008
164880
|
enabled: true,
|
|
165009
164881
|
injection_budget_tokens: 4000,
|
|
@@ -165011,8 +164883,8 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
165011
164883
|
retrieval_count_promotion_threshold: 3,
|
|
165012
164884
|
auto_search: { enabled: true, score_threshold: 0.6, min_prompt_chars: 20 },
|
|
165013
164885
|
git_commit_indexing: { enabled: false, since_days: 365, max_commits: 2000 }
|
|
165014
|
-
}),
|
|
165015
|
-
sidekick: SidekickConfigSchema
|
|
164886
|
+
}).describe("Cross-session memory configuration"),
|
|
164887
|
+
sidekick: SidekickConfigSchema.describe("Optional sidekick agent configuration for session-start memory retrieval")
|
|
165016
164888
|
}).transform((data) => {
|
|
165017
164889
|
return {
|
|
165018
164890
|
...data,
|
|
@@ -165052,7 +164924,8 @@ function getEmbeddingProviderIdentity(config2) {
|
|
|
165052
164924
|
provider: "openai-compatible",
|
|
165053
164925
|
model: config2.model.trim(),
|
|
165054
164926
|
endpoint: normalizeEndpoint(config2.endpoint),
|
|
165055
|
-
apiKeyPresent: Boolean(config2.api_key?.trim())
|
|
164927
|
+
apiKeyPresent: Boolean(config2.api_key?.trim()),
|
|
164928
|
+
inputType: config2.input_type?.trim() || ""
|
|
165056
164929
|
} : {
|
|
165057
164930
|
provider: "local",
|
|
165058
164931
|
model: config2.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
@@ -165063,7 +164936,7 @@ function getEmbeddingProviderIdentity(config2) {
|
|
|
165063
164936
|
}
|
|
165064
164937
|
|
|
165065
164938
|
// ../plugin/src/features/magic-context/memory/embedding-local.ts
|
|
165066
|
-
import { mkdirSync as
|
|
164939
|
+
import { mkdirSync as mkdirSync5 } from "node:fs";
|
|
165067
164940
|
import { open, stat, unlink, writeFile } from "node:fs/promises";
|
|
165068
164941
|
import { dirname as dirname4, join as join12 } from "node:path";
|
|
165069
164942
|
import { pathToFileURL } from "node:url";
|
|
@@ -165244,7 +165117,7 @@ class LocalEmbeddingProvider {
|
|
|
165244
165117
|
}
|
|
165245
165118
|
const modelCacheDir = join12(getMagicContextStorageDir(), "models");
|
|
165246
165119
|
try {
|
|
165247
|
-
|
|
165120
|
+
mkdirSync5(modelCacheDir, { recursive: true });
|
|
165248
165121
|
env.cacheDir = modelCacheDir;
|
|
165249
165122
|
} catch {
|
|
165250
165123
|
log("[magic-context] could not create model cache dir, using library default");
|
|
@@ -165418,6 +165291,8 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
165418
165291
|
endpoint;
|
|
165419
165292
|
model;
|
|
165420
165293
|
apiKey;
|
|
165294
|
+
inputType;
|
|
165295
|
+
truncate;
|
|
165421
165296
|
initialized = false;
|
|
165422
165297
|
failureTimes = [];
|
|
165423
165298
|
circuitOpenUntil = 0;
|
|
@@ -165427,6 +165302,8 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
165427
165302
|
this.endpoint = normalizeEndpoint2(options.endpoint);
|
|
165428
165303
|
this.model = options.model?.trim() ?? "";
|
|
165429
165304
|
this.apiKey = options.apiKey?.trim() ?? "";
|
|
165305
|
+
this.inputType = options.inputType?.trim() ?? "";
|
|
165306
|
+
this.truncate = options.truncate?.trim() ?? "";
|
|
165430
165307
|
this.modelId = getEmbeddingProviderIdentity({
|
|
165431
165308
|
provider: "openai-compatible",
|
|
165432
165309
|
endpoint: this.endpoint,
|
|
@@ -165483,7 +165360,9 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
165483
165360
|
},
|
|
165484
165361
|
body: JSON.stringify({
|
|
165485
165362
|
model: this.model,
|
|
165486
|
-
input: texts
|
|
165363
|
+
input: texts,
|
|
165364
|
+
...this.inputType ? { input_type: this.inputType } : {},
|
|
165365
|
+
...this.truncate ? { truncate: this.truncate } : {}
|
|
165487
165366
|
}),
|
|
165488
165367
|
signal: internalController.signal
|
|
165489
165368
|
});
|
|
@@ -165613,7 +165492,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
165613
165492
|
}
|
|
165614
165493
|
|
|
165615
165494
|
// ../plugin/src/features/magic-context/project-embedding-registry.ts
|
|
165616
|
-
import { createHash as
|
|
165495
|
+
import { createHash as createHash7, randomUUID } from "node:crypto";
|
|
165617
165496
|
init_logger();
|
|
165618
165497
|
|
|
165619
165498
|
// ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
|
|
@@ -165717,6 +165596,125 @@ function getDistinctCommitEmbeddingModelIds(db, projectPath) {
|
|
|
165717
165596
|
return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
|
|
165718
165597
|
}
|
|
165719
165598
|
|
|
165599
|
+
// ../plugin/src/features/magic-context/git-commits/sweep-coordinator.ts
|
|
165600
|
+
var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
|
|
165601
|
+
var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
165602
|
+
var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
|
|
165603
|
+
function runImmediate2(db, body) {
|
|
165604
|
+
db.exec("BEGIN IMMEDIATE");
|
|
165605
|
+
let committed = false;
|
|
165606
|
+
try {
|
|
165607
|
+
const result = body();
|
|
165608
|
+
db.exec("COMMIT");
|
|
165609
|
+
committed = true;
|
|
165610
|
+
return result;
|
|
165611
|
+
} finally {
|
|
165612
|
+
if (!committed) {
|
|
165613
|
+
try {
|
|
165614
|
+
db.exec("ROLLBACK");
|
|
165615
|
+
} catch {}
|
|
165616
|
+
}
|
|
165617
|
+
}
|
|
165618
|
+
}
|
|
165619
|
+
function rowToState(row) {
|
|
165620
|
+
return {
|
|
165621
|
+
projectPath: row.project_path,
|
|
165622
|
+
leaseHolder: row.lease_holder,
|
|
165623
|
+
leaseExpiresAt: row.lease_expires_at,
|
|
165624
|
+
lastSweptAt: row.last_swept_at
|
|
165625
|
+
};
|
|
165626
|
+
}
|
|
165627
|
+
function getGitSweepCoordinatorState(db, projectPath) {
|
|
165628
|
+
const row = db.prepare(`SELECT project_path, lease_holder, lease_expires_at, last_swept_at
|
|
165629
|
+
FROM git_sweep_coordinator
|
|
165630
|
+
WHERE project_path = ?`).get(projectPath);
|
|
165631
|
+
return row ? rowToState(row) : null;
|
|
165632
|
+
}
|
|
165633
|
+
function acquireGitSweepLease(db, projectPath, holderId, options = {}) {
|
|
165634
|
+
const cooldownMs = options.cooldownMs ?? GIT_SWEEP_COOLDOWN_MS;
|
|
165635
|
+
const leaseTtlMs = options.leaseTtlMs ?? GIT_SWEEP_LEASE_TTL_MS;
|
|
165636
|
+
return runImmediate2(db, () => {
|
|
165637
|
+
const now = Date.now();
|
|
165638
|
+
const row = getGitSweepCoordinatorState(db, projectPath);
|
|
165639
|
+
if (row?.leaseHolder && row.leaseExpiresAt !== null && row.leaseExpiresAt > now) {
|
|
165640
|
+
return {
|
|
165641
|
+
acquired: false,
|
|
165642
|
+
projectPath,
|
|
165643
|
+
reason: "lease_active",
|
|
165644
|
+
leaseHolder: row.leaseHolder,
|
|
165645
|
+
leaseExpiresAt: row.leaseExpiresAt,
|
|
165646
|
+
lastSweptAt: row.lastSweptAt,
|
|
165647
|
+
nextAllowedAt: null
|
|
165648
|
+
};
|
|
165649
|
+
}
|
|
165650
|
+
if (!options.ignoreCooldown && row?.lastSweptAt !== null && row?.lastSweptAt !== undefined) {
|
|
165651
|
+
const nextAllowedAt = row.lastSweptAt + cooldownMs;
|
|
165652
|
+
if (nextAllowedAt > now) {
|
|
165653
|
+
return {
|
|
165654
|
+
acquired: false,
|
|
165655
|
+
projectPath,
|
|
165656
|
+
reason: "cooldown_active",
|
|
165657
|
+
leaseHolder: row.leaseHolder,
|
|
165658
|
+
leaseExpiresAt: row.leaseExpiresAt,
|
|
165659
|
+
lastSweptAt: row.lastSweptAt,
|
|
165660
|
+
nextAllowedAt
|
|
165661
|
+
};
|
|
165662
|
+
}
|
|
165663
|
+
}
|
|
165664
|
+
const leaseExpiresAt = now + leaseTtlMs;
|
|
165665
|
+
db.prepare(`INSERT INTO git_sweep_coordinator (
|
|
165666
|
+
project_path,
|
|
165667
|
+
lease_holder,
|
|
165668
|
+
lease_expires_at,
|
|
165669
|
+
last_swept_at
|
|
165670
|
+
) VALUES (?, ?, ?, NULL)
|
|
165671
|
+
ON CONFLICT(project_path) DO UPDATE SET
|
|
165672
|
+
lease_holder = excluded.lease_holder,
|
|
165673
|
+
lease_expires_at = excluded.lease_expires_at`).run(projectPath, holderId, leaseExpiresAt);
|
|
165674
|
+
return {
|
|
165675
|
+
acquired: true,
|
|
165676
|
+
projectPath,
|
|
165677
|
+
holderId,
|
|
165678
|
+
acquiredAt: now,
|
|
165679
|
+
leaseExpiresAt
|
|
165680
|
+
};
|
|
165681
|
+
});
|
|
165682
|
+
}
|
|
165683
|
+
function renewGitSweepLease(db, projectPath, holderId, leaseTtlMs = GIT_SWEEP_LEASE_TTL_MS) {
|
|
165684
|
+
return runImmediate2(db, () => {
|
|
165685
|
+
const now = Date.now();
|
|
165686
|
+
const leaseExpiresAt = now + leaseTtlMs;
|
|
165687
|
+
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
165688
|
+
SET lease_expires_at = ?
|
|
165689
|
+
WHERE project_path = ?
|
|
165690
|
+
AND lease_holder = ?
|
|
165691
|
+
AND lease_expires_at > ?`).run(leaseExpiresAt, projectPath, holderId, now);
|
|
165692
|
+
return result.changes === 1;
|
|
165693
|
+
});
|
|
165694
|
+
}
|
|
165695
|
+
function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
|
|
165696
|
+
return runImmediate2(db, () => {
|
|
165697
|
+
const now = Date.now();
|
|
165698
|
+
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
165699
|
+
SET lease_holder = NULL,
|
|
165700
|
+
lease_expires_at = NULL,
|
|
165701
|
+
last_swept_at = ?
|
|
165702
|
+
WHERE project_path = ?
|
|
165703
|
+
AND lease_holder = ?
|
|
165704
|
+
AND lease_expires_at > ?`).run(now, projectPath, holderId, now);
|
|
165705
|
+
return result.changes === 1;
|
|
165706
|
+
});
|
|
165707
|
+
}
|
|
165708
|
+
function releaseGitSweepLease(db, projectPath, holderId) {
|
|
165709
|
+
runImmediate2(db, () => {
|
|
165710
|
+
db.prepare(`UPDATE git_sweep_coordinator
|
|
165711
|
+
SET lease_holder = NULL,
|
|
165712
|
+
lease_expires_at = NULL
|
|
165713
|
+
WHERE project_path = ?
|
|
165714
|
+
AND lease_holder = ?`).run(projectPath, holderId);
|
|
165715
|
+
});
|
|
165716
|
+
}
|
|
165717
|
+
|
|
165720
165718
|
// ../plugin/src/features/magic-context/project-embedding-registry.ts
|
|
165721
165719
|
var OFF_PROVIDER_IDENTITY = "embedding-provider:off";
|
|
165722
165720
|
var SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
|
|
@@ -165769,7 +165767,7 @@ function stableStringify2(value) {
|
|
|
165769
165767
|
return JSON.stringify(value);
|
|
165770
165768
|
}
|
|
165771
165769
|
function sha256Prefix(value, length = 16) {
|
|
165772
|
-
return
|
|
165770
|
+
return createHash7("sha256").update(value).digest("hex").slice(0, length);
|
|
165773
165771
|
}
|
|
165774
165772
|
function getRuntimeFingerprint(config2) {
|
|
165775
165773
|
if (config2.provider === "off") {
|
|
@@ -165999,7 +165997,9 @@ function createProvider2(config2) {
|
|
|
165999
165997
|
return new OpenAICompatibleEmbeddingProvider({
|
|
166000
165998
|
endpoint: config2.endpoint,
|
|
166001
165999
|
model: config2.model,
|
|
166002
|
-
apiKey: config2.api_key
|
|
166000
|
+
apiKey: config2.api_key,
|
|
166001
|
+
inputType: config2.input_type,
|
|
166002
|
+
truncate: config2.truncate
|
|
166003
166003
|
});
|
|
166004
166004
|
}
|
|
166005
166005
|
return new LocalEmbeddingProvider(config2.model);
|
|
@@ -166032,6 +166032,7 @@ var insertStatements = new WeakMap;
|
|
|
166032
166032
|
var existingShasStatements = new WeakMap;
|
|
166033
166033
|
var projectCountStatements = new WeakMap;
|
|
166034
166034
|
var evictStatements = new WeakMap;
|
|
166035
|
+
var evictOverflowStatements = new WeakMap;
|
|
166035
166036
|
var latestCommitTimeStatements = new WeakMap;
|
|
166036
166037
|
function getInsertStatement(db) {
|
|
166037
166038
|
let stmt = insertStatements.get(db);
|
|
@@ -166074,17 +166075,17 @@ function getLatestCommitTimeStatement(db) {
|
|
|
166074
166075
|
}
|
|
166075
166076
|
return stmt;
|
|
166076
166077
|
}
|
|
166077
|
-
function
|
|
166078
|
-
let stmt =
|
|
166078
|
+
function getEvictOverflowStatement(db) {
|
|
166079
|
+
let stmt = evictOverflowStatements.get(db);
|
|
166079
166080
|
if (!stmt) {
|
|
166080
166081
|
stmt = db.prepare(`DELETE FROM git_commits
|
|
166081
|
-
WHERE
|
|
166082
|
-
SELECT
|
|
166082
|
+
WHERE rowid IN (
|
|
166083
|
+
SELECT rowid FROM git_commits
|
|
166083
166084
|
WHERE project_path = ?
|
|
166084
|
-
ORDER BY committed_at
|
|
166085
|
-
LIMIT ?
|
|
166085
|
+
ORDER BY committed_at DESC, sha DESC
|
|
166086
|
+
LIMIT -1 OFFSET ?
|
|
166086
166087
|
)`);
|
|
166087
|
-
|
|
166088
|
+
evictOverflowStatements.set(db, stmt);
|
|
166088
166089
|
}
|
|
166089
166090
|
return stmt;
|
|
166090
166091
|
}
|
|
@@ -166122,22 +166123,15 @@ function getLatestIndexedCommitTimeMs(db, projectPath) {
|
|
|
166122
166123
|
const row = getLatestCommitTimeStatement(db).get(projectPath);
|
|
166123
166124
|
return row?.latest ?? null;
|
|
166124
166125
|
}
|
|
166125
|
-
function evictOldestCommits(db, projectPath, excess) {
|
|
166126
|
-
if (excess <= 0)
|
|
166127
|
-
return 0;
|
|
166128
|
-
const before = getCommitCount(db, projectPath);
|
|
166129
|
-
getEvictStatement(db).run(projectPath, excess);
|
|
166130
|
-
const after = getCommitCount(db, projectPath);
|
|
166131
|
-
return Math.max(0, before - after);
|
|
166132
|
-
}
|
|
166133
166126
|
function enforceProjectCap(db, projectPath, maxCommits) {
|
|
166134
166127
|
if (maxCommits <= 0)
|
|
166135
166128
|
return 0;
|
|
166136
166129
|
const count = getCommitCount(db, projectPath);
|
|
166137
166130
|
if (count <= maxCommits)
|
|
166138
166131
|
return 0;
|
|
166139
|
-
|
|
166140
|
-
const
|
|
166132
|
+
getEvictOverflowStatement(db).run(projectPath, maxCommits);
|
|
166133
|
+
const after = getCommitCount(db, projectPath);
|
|
166134
|
+
const evicted = Math.max(0, count - after);
|
|
166141
166135
|
if (evicted > 0) {
|
|
166142
166136
|
log(`[git-commits] evicted ${evicted} oldest commits for project ${projectPath} (cap=${maxCommits}, was=${count})`);
|
|
166143
166137
|
}
|
|
@@ -166517,10 +166511,31 @@ async function sweepProject(reg, origin, db, gitCommitEnabled = getProjectEmbedd
|
|
|
166517
166511
|
log(`[dreamer] timer-triggered queue processing failed for ${reg.directory}:`, error51);
|
|
166518
166512
|
}
|
|
166519
166513
|
}
|
|
166514
|
+
function startGitSweepLeaseRenewal(db, projectIdentity, holderId) {
|
|
166515
|
+
const timer = setInterval(() => {
|
|
166516
|
+
try {
|
|
166517
|
+
if (!renewGitSweepLease(db, projectIdentity, holderId)) {
|
|
166518
|
+
log(`[git-commits] sweep lease renewal failed for ${projectIdentity}`);
|
|
166519
|
+
}
|
|
166520
|
+
} catch (error51) {
|
|
166521
|
+
log(`[git-commits] sweep lease renewal errored for ${projectIdentity}: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
166522
|
+
}
|
|
166523
|
+
}, GIT_SWEEP_LEASE_RENEWAL_MS);
|
|
166524
|
+
timer.unref?.();
|
|
166525
|
+
return () => clearInterval(timer);
|
|
166526
|
+
}
|
|
166520
166527
|
async function sweepGitCommits(args) {
|
|
166521
166528
|
const { directory, projectIdentity, db, gitCommitIndexing } = args;
|
|
166529
|
+
const holderId = crypto.randomUUID();
|
|
166530
|
+
const lease2 = acquireGitSweepLease(db, projectIdentity, holderId);
|
|
166531
|
+
if (!lease2.acquired) {
|
|
166532
|
+
const reason = lease2.reason === "cooldown_active" ? `cooldown active until ${lease2.nextAllowedAt}` : `lease held by ${lease2.leaseHolder ?? "another holder"} until ${lease2.leaseExpiresAt ?? "unknown"}`;
|
|
166533
|
+
log(`[git-commits] sweep skipped for ${projectIdentity} (${directory}): ${reason}`);
|
|
166534
|
+
return;
|
|
166535
|
+
}
|
|
166522
166536
|
const startedAt = Date.now();
|
|
166523
|
-
|
|
166537
|
+
const stopRenewal = startGitSweepLeaseRenewal(db, projectIdentity, holderId);
|
|
166538
|
+
log(`[git-commits] sweep starting for ${directory} (project=${projectIdentity} sinceDays=${gitCommitIndexing.since_days} maxCommits=${gitCommitIndexing.max_commits})`);
|
|
166524
166539
|
try {
|
|
166525
166540
|
const result = await indexCommitsForProject(db, projectIdentity, directory, {
|
|
166526
166541
|
sinceDays: gitCommitIndexing.since_days,
|
|
@@ -166530,16 +166545,24 @@ async function sweepGitCommits(args) {
|
|
|
166530
166545
|
if (result.embedded > 0) {
|
|
166531
166546
|
drainedEmbeddings = await embedUnembeddedCommits(db, projectIdentity);
|
|
166532
166547
|
}
|
|
166548
|
+
const cooldownMarked = markGitSweepSuccessAndRelease(db, projectIdentity, holderId);
|
|
166549
|
+
if (!cooldownMarked) {
|
|
166550
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
166551
|
+
log(`[git-commits] sweep finished for ${projectIdentity}, but lease was no longer active; cooldown not advanced`);
|
|
166552
|
+
}
|
|
166533
166553
|
const elapsedMs = Date.now() - startedAt;
|
|
166534
166554
|
log(`[git-commits] sweep finished for ${projectIdentity} in ${elapsedMs}ms: scanned=${result.scanned} inserted=${result.inserted} updated=${result.updated} evicted=${result.evicted} embedded=${result.embedded} drained=${drainedEmbeddings}`);
|
|
166535
166555
|
} catch (error51) {
|
|
166556
|
+
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
166536
166557
|
const elapsedMs = Date.now() - startedAt;
|
|
166537
166558
|
log(`[git-commits] sweep failed for ${directory} after ${elapsedMs}ms: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
166559
|
+
} finally {
|
|
166560
|
+
stopRenewal();
|
|
166538
166561
|
}
|
|
166539
166562
|
}
|
|
166540
166563
|
|
|
166541
166564
|
// ../plugin/src/plugin/embedding-bootstrap-helpers.ts
|
|
166542
|
-
import { createHash as
|
|
166565
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
166543
166566
|
init_logger();
|
|
166544
166567
|
var EMBEDDING_AFFECTING_KEYS = new Set([
|
|
166545
166568
|
"embedding.api_key",
|
|
@@ -166551,7 +166574,7 @@ var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set(["embedding", "memory", "experi
|
|
|
166551
166574
|
var EMBEDDING_WARNING_TERMS = ["api_key", "endpoint", "model", "provider", "embedding"];
|
|
166552
166575
|
var loggedFailureSignatures = new Map;
|
|
166553
166576
|
function sha256Prefix2(value, length = 16) {
|
|
166554
|
-
return
|
|
166577
|
+
return createHash8("sha256").update(value).digest("hex").slice(0, length);
|
|
166555
166578
|
}
|
|
166556
166579
|
function warningLooksEmbeddingRelated(message) {
|
|
166557
166580
|
const lower = message.toLowerCase();
|
|
@@ -166615,8 +166638,8 @@ function handleUntrustedLoad(db, projectIdentity, directory, detailed) {
|
|
|
166615
166638
|
}
|
|
166616
166639
|
|
|
166617
166640
|
// src/config/index.ts
|
|
166618
|
-
import { existsSync as
|
|
166619
|
-
import { homedir as
|
|
166641
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
|
|
166642
|
+
import { homedir as homedir4 } from "node:os";
|
|
166620
166643
|
import { join as join13 } from "node:path";
|
|
166621
166644
|
|
|
166622
166645
|
// ../plugin/src/config/migrate-experimental.ts
|
|
@@ -166706,9 +166729,67 @@ function migrateLegacyExperimental(rawConfig, warnings) {
|
|
|
166706
166729
|
}
|
|
166707
166730
|
|
|
166708
166731
|
// ../plugin/src/config/variable.ts
|
|
166709
|
-
import { existsSync as
|
|
166710
|
-
import { homedir as
|
|
166732
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
|
|
166733
|
+
import { homedir as homedir3 } from "node:os";
|
|
166711
166734
|
import { dirname as dirname5, isAbsolute as isAbsolute2, resolve as resolve3 } from "node:path";
|
|
166735
|
+
|
|
166736
|
+
// ../plugin/src/shared/jsonc-parser.ts
|
|
166737
|
+
function stripJsonComments(content) {
|
|
166738
|
+
let result = "";
|
|
166739
|
+
let inString = false;
|
|
166740
|
+
let escaped = false;
|
|
166741
|
+
let inLineComment = false;
|
|
166742
|
+
let inBlockComment = false;
|
|
166743
|
+
for (let index = 0;index < content.length; index += 1) {
|
|
166744
|
+
const char = content[index];
|
|
166745
|
+
const next = content[index + 1];
|
|
166746
|
+
if (inLineComment) {
|
|
166747
|
+
if (char === `
|
|
166748
|
+
`) {
|
|
166749
|
+
inLineComment = false;
|
|
166750
|
+
result += char;
|
|
166751
|
+
}
|
|
166752
|
+
continue;
|
|
166753
|
+
}
|
|
166754
|
+
if (inBlockComment) {
|
|
166755
|
+
if (char === "*" && next === "/") {
|
|
166756
|
+
inBlockComment = false;
|
|
166757
|
+
index += 1;
|
|
166758
|
+
}
|
|
166759
|
+
continue;
|
|
166760
|
+
}
|
|
166761
|
+
if (inString) {
|
|
166762
|
+
result += char;
|
|
166763
|
+
if (escaped) {
|
|
166764
|
+
escaped = false;
|
|
166765
|
+
} else if (char === "\\") {
|
|
166766
|
+
escaped = true;
|
|
166767
|
+
} else if (char === '"') {
|
|
166768
|
+
inString = false;
|
|
166769
|
+
}
|
|
166770
|
+
continue;
|
|
166771
|
+
}
|
|
166772
|
+
if (char === '"') {
|
|
166773
|
+
inString = true;
|
|
166774
|
+
result += char;
|
|
166775
|
+
continue;
|
|
166776
|
+
}
|
|
166777
|
+
if (char === "/" && next === "/") {
|
|
166778
|
+
inLineComment = true;
|
|
166779
|
+
index += 1;
|
|
166780
|
+
continue;
|
|
166781
|
+
}
|
|
166782
|
+
if (char === "/" && next === "*") {
|
|
166783
|
+
inBlockComment = true;
|
|
166784
|
+
index += 1;
|
|
166785
|
+
continue;
|
|
166786
|
+
}
|
|
166787
|
+
result += char;
|
|
166788
|
+
}
|
|
166789
|
+
return result;
|
|
166790
|
+
}
|
|
166791
|
+
|
|
166792
|
+
// ../plugin/src/config/variable.ts
|
|
166712
166793
|
var ENV_PATTERN = /\{env:([^}]+)\}/g;
|
|
166713
166794
|
var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
166714
166795
|
function substituteConfigVariables(input) {
|
|
@@ -166760,11 +166841,11 @@ function substituteConfigVariables(input) {
|
|
|
166760
166841
|
}
|
|
166761
166842
|
let filePath = rawPath.trim();
|
|
166762
166843
|
if (filePath.startsWith("~/")) {
|
|
166763
|
-
filePath = resolve3(
|
|
166844
|
+
filePath = resolve3(homedir3(), filePath.slice(2));
|
|
166764
166845
|
} else if (!isAbsolute2(filePath)) {
|
|
166765
166846
|
filePath = resolve3(configDir, filePath);
|
|
166766
166847
|
}
|
|
166767
|
-
if (!
|
|
166848
|
+
if (!existsSync9(filePath)) {
|
|
166768
166849
|
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
166769
166850
|
continue;
|
|
166770
166851
|
}
|
|
@@ -166790,12 +166871,12 @@ function getProjectConfigPaths(cwd) {
|
|
|
166790
166871
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
166791
166872
|
}
|
|
166792
166873
|
function getUserConfigPaths() {
|
|
166793
|
-
const home = process.env.HOME ??
|
|
166874
|
+
const home = process.env.HOME ?? homedir4();
|
|
166794
166875
|
const basePath = join13(home, ".pi", "agent", CONFIG_FILE_NAME);
|
|
166795
166876
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
166796
166877
|
}
|
|
166797
166878
|
function resolveFirstExisting(paths) {
|
|
166798
|
-
return paths.find((path7) =>
|
|
166879
|
+
return paths.find((path7) => existsSync10(path7));
|
|
166799
166880
|
}
|
|
166800
166881
|
function loadConfigFile(path7, scope) {
|
|
166801
166882
|
try {
|
|
@@ -169399,6 +169480,62 @@ function buildToolTarget(part, message) {
|
|
|
169399
169480
|
|
|
169400
169481
|
// ../plugin/src/features/magic-context/search.ts
|
|
169401
169482
|
init_logger();
|
|
169483
|
+
|
|
169484
|
+
// ../plugin/src/features/magic-context/literal-probes.ts
|
|
169485
|
+
var MAX_PROBES = 5;
|
|
169486
|
+
var MIN_PROBE_LENGTH = 3;
|
|
169487
|
+
var SLASH_COMMAND_RE = /\/[a-z][a-z0-9]*(?:-[a-z0-9]+)+/gi;
|
|
169488
|
+
var KEBAB_SNAKE_RE = /[a-z][a-z0-9]*(?:[-_][a-z0-9]+)+/gi;
|
|
169489
|
+
var DOTTED_RE = /[a-z0-9][a-z0-9_-]*(?:\.[a-z0-9_-]+)+/gi;
|
|
169490
|
+
var CAMEL_RE = /\b[a-zA-Z][a-z0-9]*(?:[A-Z][a-z0-9]*)+\b/g;
|
|
169491
|
+
var SHA_RE = /\b[0-9a-f]{7,40}\b/gi;
|
|
169492
|
+
var ERROR_CODE_RE = /\b(?:TS\d{4,}|ERR_[A-Z][A-Z0-9_]*)\b/g;
|
|
169493
|
+
var QUOTED_RE = /["`]([^"`]{3,80})["`]/g;
|
|
169494
|
+
function looksLikeSha(token) {
|
|
169495
|
+
return /[0-9]/.test(token) && /^[0-9a-f]{7,40}$/i.test(token);
|
|
169496
|
+
}
|
|
169497
|
+
function extractLiteralProbes(query) {
|
|
169498
|
+
const trimmed = query.trim();
|
|
169499
|
+
if (trimmed.length === 0)
|
|
169500
|
+
return [];
|
|
169501
|
+
const ordered = [];
|
|
169502
|
+
const seen = new Set;
|
|
169503
|
+
const add = (raw) => {
|
|
169504
|
+
if (!raw)
|
|
169505
|
+
return;
|
|
169506
|
+
const probe = raw.trim();
|
|
169507
|
+
if (probe.length < MIN_PROBE_LENGTH)
|
|
169508
|
+
return;
|
|
169509
|
+
const key = probe.toLowerCase();
|
|
169510
|
+
if (seen.has(key))
|
|
169511
|
+
return;
|
|
169512
|
+
seen.add(key);
|
|
169513
|
+
ordered.push(probe);
|
|
169514
|
+
};
|
|
169515
|
+
for (const m of trimmed.matchAll(QUOTED_RE))
|
|
169516
|
+
add(m[1]);
|
|
169517
|
+
for (const m of trimmed.matchAll(SLASH_COMMAND_RE))
|
|
169518
|
+
add(m[0]);
|
|
169519
|
+
for (const m of trimmed.matchAll(ERROR_CODE_RE))
|
|
169520
|
+
add(m[0]);
|
|
169521
|
+
for (const m of trimmed.matchAll(DOTTED_RE))
|
|
169522
|
+
add(m[0]);
|
|
169523
|
+
for (const m of trimmed.matchAll(KEBAB_SNAKE_RE))
|
|
169524
|
+
add(m[0]);
|
|
169525
|
+
for (const m of trimmed.matchAll(CAMEL_RE))
|
|
169526
|
+
add(m[0]);
|
|
169527
|
+
for (const m of trimmed.matchAll(SHA_RE)) {
|
|
169528
|
+
if (looksLikeSha(m[0]))
|
|
169529
|
+
add(m[0]);
|
|
169530
|
+
}
|
|
169531
|
+
return ordered.slice(0, MAX_PROBES);
|
|
169532
|
+
}
|
|
169533
|
+
function containsProbeVerbatim(text, probes) {
|
|
169534
|
+
if (probes.length === 0)
|
|
169535
|
+
return false;
|
|
169536
|
+
const haystack = text.toLowerCase();
|
|
169537
|
+
return probes.some((probe) => haystack.includes(probe.toLowerCase()));
|
|
169538
|
+
}
|
|
169402
169539
|
// ../plugin/src/features/magic-context/memory/embedding-backfill.ts
|
|
169403
169540
|
init_logger();
|
|
169404
169541
|
async function ensureMemoryEmbeddings(args) {
|
|
@@ -169661,36 +169798,82 @@ function linearDecayScore(rank, total) {
|
|
|
169661
169798
|
return 0;
|
|
169662
169799
|
return Math.max(0, 1 - rank / total);
|
|
169663
169800
|
}
|
|
169664
|
-
function
|
|
169665
|
-
|
|
169666
|
-
if (sanitizedQuery.length === 0) {
|
|
169801
|
+
function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff) {
|
|
169802
|
+
if (ftsQuery.length === 0)
|
|
169667
169803
|
return [];
|
|
169668
|
-
|
|
169669
|
-
const
|
|
169670
|
-
|
|
169671
|
-
const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
|
|
169672
|
-
const filtered = rows.map((row) => {
|
|
169804
|
+
const rows = getMessageSearchStatement(db).all(sessionId, ftsQuery, fetchLimit).map((row) => row);
|
|
169805
|
+
const result = [];
|
|
169806
|
+
for (const row of rows) {
|
|
169673
169807
|
const messageOrdinal = getMessageOrdinal(row.messageOrdinal);
|
|
169674
169808
|
if (messageOrdinal === null || typeof row.messageId !== "string" || typeof row.role !== "string" || typeof row.content !== "string") {
|
|
169675
|
-
|
|
169809
|
+
continue;
|
|
169676
169810
|
}
|
|
169677
169811
|
if (cutoff !== null && messageOrdinal > cutoff) {
|
|
169678
|
-
|
|
169812
|
+
continue;
|
|
169679
169813
|
}
|
|
169680
|
-
|
|
169814
|
+
result.push({
|
|
169681
169815
|
messageOrdinal,
|
|
169682
169816
|
messageId: row.messageId,
|
|
169683
169817
|
role: row.role,
|
|
169684
169818
|
content: row.content
|
|
169685
|
-
};
|
|
169686
|
-
}
|
|
169687
|
-
return
|
|
169819
|
+
});
|
|
169820
|
+
}
|
|
169821
|
+
return result;
|
|
169822
|
+
}
|
|
169823
|
+
var RRF_K = 60;
|
|
169824
|
+
var VERBATIM_PROBE_BONUS = 0.5;
|
|
169825
|
+
function searchMessages(args) {
|
|
169826
|
+
const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
|
|
169827
|
+
const fetchLimit = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.limit * 3 : args.limit;
|
|
169828
|
+
const baseQuery = sanitizeFtsQuery(args.query.trim());
|
|
169829
|
+
const probes = args.probes ?? [];
|
|
169830
|
+
if (probes.length === 0) {
|
|
169831
|
+
const filtered = runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff).slice(0, args.limit);
|
|
169832
|
+
return filtered.map((row, rank) => ({
|
|
169833
|
+
source: "message",
|
|
169834
|
+
content: previewText(row.content),
|
|
169835
|
+
score: linearDecayScore(rank, filtered.length),
|
|
169836
|
+
messageOrdinal: row.messageOrdinal,
|
|
169837
|
+
messageId: row.messageId,
|
|
169838
|
+
role: row.role
|
|
169839
|
+
}));
|
|
169840
|
+
}
|
|
169841
|
+
const queryLists = [];
|
|
169842
|
+
if (baseQuery.length > 0) {
|
|
169843
|
+
queryLists.push(runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff));
|
|
169844
|
+
}
|
|
169845
|
+
for (const probe of probes) {
|
|
169846
|
+
const probeQuery = sanitizeFtsQuery(probe);
|
|
169847
|
+
if (probeQuery.length === 0)
|
|
169848
|
+
continue;
|
|
169849
|
+
queryLists.push(runMessageFtsQuery(args.db, args.sessionId, probeQuery, fetchLimit, cutoff));
|
|
169850
|
+
}
|
|
169851
|
+
const fused = new Map;
|
|
169852
|
+
for (const list of queryLists) {
|
|
169853
|
+
list.forEach((row, rank) => {
|
|
169854
|
+
const rrf = 1 / (RRF_K + rank);
|
|
169855
|
+
const existing = fused.get(row.messageId);
|
|
169856
|
+
if (existing) {
|
|
169857
|
+
existing.score += rrf;
|
|
169858
|
+
} else {
|
|
169859
|
+
fused.set(row.messageId, { row, score: rrf });
|
|
169860
|
+
}
|
|
169861
|
+
});
|
|
169862
|
+
}
|
|
169863
|
+
for (const entry of fused.values()) {
|
|
169864
|
+
if (containsProbeVerbatim(entry.row.content, probes)) {
|
|
169865
|
+
entry.score += VERBATIM_PROBE_BONUS;
|
|
169866
|
+
}
|
|
169867
|
+
}
|
|
169868
|
+
const ranked = [...fused.values()].sort((a, b) => b.score !== a.score ? b.score - a.score : a.row.messageOrdinal - b.row.messageOrdinal).slice(0, args.limit);
|
|
169869
|
+
const maxScore = ranked.length > 0 ? ranked[0].score : 1;
|
|
169870
|
+
return ranked.map((entry) => ({
|
|
169688
169871
|
source: "message",
|
|
169689
|
-
content: previewText(row.content),
|
|
169690
|
-
score:
|
|
169691
|
-
messageOrdinal: row.messageOrdinal,
|
|
169692
|
-
messageId: row.messageId,
|
|
169693
|
-
role: row.role
|
|
169872
|
+
content: previewText(entry.row.content),
|
|
169873
|
+
score: maxScore > 0 ? entry.score / maxScore : 0,
|
|
169874
|
+
messageOrdinal: entry.row.messageOrdinal,
|
|
169875
|
+
messageId: entry.row.messageId,
|
|
169876
|
+
role: entry.row.role
|
|
169694
169877
|
}));
|
|
169695
169878
|
}
|
|
169696
169879
|
function getSourceBoost(result) {
|
|
@@ -169774,12 +169957,14 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
169774
169957
|
return null;
|
|
169775
169958
|
}) : Promise.resolve(null);
|
|
169776
169959
|
await Promise.resolve();
|
|
169960
|
+
const messageProbes = options.explicitSearch ? extractLiteralProbes(trimmedQuery) : [];
|
|
169777
169961
|
const messageResults = runMessages ? searchMessages({
|
|
169778
169962
|
db,
|
|
169779
169963
|
sessionId,
|
|
169780
169964
|
query: trimmedQuery,
|
|
169781
169965
|
limit: tierLimit,
|
|
169782
|
-
maxOrdinal: options.maxMessageOrdinal
|
|
169966
|
+
maxOrdinal: options.maxMessageOrdinal,
|
|
169967
|
+
probes: messageProbes
|
|
169783
169968
|
}) : [];
|
|
169784
169969
|
const queryEmbedding = await queryEmbeddingPromise;
|
|
169785
169970
|
const [memoryResults, gitCommitResults] = await Promise.all([
|
|
@@ -175642,7 +175827,7 @@ function stripPiDroppedPlaceholderMessages(args) {
|
|
|
175642
175827
|
}
|
|
175643
175828
|
|
|
175644
175829
|
// src/system-prompt.ts
|
|
175645
|
-
import { createHash as
|
|
175830
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
175646
175831
|
|
|
175647
175832
|
// ../plugin/src/agents/magic-context-prompt.ts
|
|
175648
175833
|
var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
|
|
@@ -175787,7 +175972,7 @@ function processSystemPromptForCache(args) {
|
|
|
175787
175972
|
sessionLog(sessionId, `system prompt date frozen: real=${liveDate}, using=${stickyDate} (cache-stable pass)`);
|
|
175788
175973
|
}
|
|
175789
175974
|
}
|
|
175790
|
-
const currentHash =
|
|
175975
|
+
const currentHash = createHash9("md5").update(frozenPrompt).digest("hex");
|
|
175791
175976
|
const hashChanged = !isFirstHash && currentHash !== previousHash;
|
|
175792
175977
|
if (hashChanged) {
|
|
175793
175978
|
sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${frozenPrompt.length})`);
|
|
@@ -176903,14 +177088,10 @@ function registerPiContextHandler(pi, options) {
|
|
|
176903
177088
|
}
|
|
176904
177089
|
const sessionMeta = sessionMetaForUsage;
|
|
176905
177090
|
const modelKey = liveModelBySession.get(sessionId);
|
|
176906
|
-
if (usageContextLimit === undefined
|
|
176907
|
-
const
|
|
176908
|
-
|
|
176909
|
-
|
|
176910
|
-
sessionID: sessionId
|
|
176911
|
-
});
|
|
176912
|
-
if (trusted !== undefined && trusted > 0) {
|
|
176913
|
-
usageContextLimit = trusted;
|
|
177091
|
+
if (usageContextLimit === undefined) {
|
|
177092
|
+
const modelWindow = ctx.model?.contextWindow;
|
|
177093
|
+
if (isSaneLimit(modelWindow)) {
|
|
177094
|
+
usageContextLimit = modelWindow;
|
|
176914
177095
|
}
|
|
176915
177096
|
}
|
|
176916
177097
|
let schedulerDecision;
|
|
@@ -177163,27 +177344,8 @@ async function awaitInFlightHistorians() {
|
|
|
177163
177344
|
return;
|
|
177164
177345
|
await Promise.allSettled(Array.from(inFlightHistorian.values()));
|
|
177165
177346
|
}
|
|
177166
|
-
function splitModelKeyForPi(modelKey) {
|
|
177167
|
-
if (!modelKey)
|
|
177168
|
-
return { providerID: undefined, modelID: undefined };
|
|
177169
|
-
const slash = modelKey.indexOf("/");
|
|
177170
|
-
if (slash <= 0 || slash === modelKey.length - 1) {
|
|
177171
|
-
return { providerID: undefined, modelID: undefined };
|
|
177172
|
-
}
|
|
177173
|
-
return {
|
|
177174
|
-
providerID: modelKey.slice(0, slash),
|
|
177175
|
-
modelID: modelKey.slice(slash + 1)
|
|
177176
|
-
};
|
|
177177
|
-
}
|
|
177178
177347
|
function resolvePiHistorianTriggerInputs(args) {
|
|
177179
|
-
const
|
|
177180
|
-
let contextLimit = resolveContextLimit(providerID, modelID, {
|
|
177181
|
-
db: args.db,
|
|
177182
|
-
sessionID: args.sessionId
|
|
177183
|
-
});
|
|
177184
|
-
if ((providerID === undefined || modelID === undefined) && typeof args.usageContextLimit === "number" && Number.isFinite(args.usageContextLimit) && args.usageContextLimit > 0) {
|
|
177185
|
-
contextLimit = args.usageContextLimit;
|
|
177186
|
-
}
|
|
177348
|
+
const contextLimit = typeof args.usageContextLimit === "number" && Number.isFinite(args.usageContextLimit) && args.usageContextLimit > 0 ? args.usageContextLimit : DEFAULT_CONTEXT_LIMIT;
|
|
177187
177349
|
const executeThresholdPercentage = resolveExecuteThreshold(args.historian.executeThresholdPercentage ?? 65, args.modelKey, 65, {
|
|
177188
177350
|
tokensConfig: args.historian.executeThresholdTokens,
|
|
177189
177351
|
contextLimit,
|
|
@@ -178005,7 +178167,7 @@ ${result}`;
|
|
|
178005
178167
|
init_logger();
|
|
178006
178168
|
|
|
178007
178169
|
// ../plugin/src/hooks/magic-context/historian-state-file.ts
|
|
178008
|
-
import { mkdirSync as
|
|
178170
|
+
import { mkdirSync as mkdirSync6, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
178009
178171
|
init_data_path();
|
|
178010
178172
|
function cleanupHistorianStateFile(path7) {
|
|
178011
178173
|
if (!path7)
|
|
@@ -178209,7 +178371,7 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
|
|
|
178209
178371
|
}
|
|
178210
178372
|
|
|
178211
178373
|
// ../plugin/src/hooks/magic-context/compartment-runner-historian.ts
|
|
178212
|
-
import { mkdirSync as
|
|
178374
|
+
import { mkdirSync as mkdirSync7, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
178213
178375
|
import { join as join16 } from "node:path";
|
|
178214
178376
|
init_data_path();
|
|
178215
178377
|
function historianResponseDumpDir(directory) {
|
|
@@ -178514,11 +178676,11 @@ function cleanupHistorianDump(sessionId, dumpPath) {
|
|
|
178514
178676
|
function dumpHistorianResponse(sessionId, directory, label, text) {
|
|
178515
178677
|
try {
|
|
178516
178678
|
const dumpDir = historianResponseDumpDir(directory);
|
|
178517
|
-
|
|
178679
|
+
mkdirSync7(dumpDir, { recursive: true });
|
|
178518
178680
|
const safeSessionId = sanitizeDumpName(sessionId);
|
|
178519
178681
|
const safeLabel = sanitizeDumpName(label);
|
|
178520
178682
|
const dumpPath = join16(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
|
|
178521
|
-
|
|
178683
|
+
writeFileSync4(dumpPath, text, "utf8");
|
|
178522
178684
|
sessionLog(sessionId, "compartment agent: historian response dumped", {
|
|
178523
178685
|
label,
|
|
178524
178686
|
dumpPath
|
|
@@ -180430,7 +180592,7 @@ function formatThresholdPercent(value) {
|
|
|
180430
180592
|
// package.json
|
|
180431
180593
|
var package_default = {
|
|
180432
180594
|
name: "@cortexkit/pi-magic-context",
|
|
180433
|
-
version: "0.22.
|
|
180595
|
+
version: "0.22.2",
|
|
180434
180596
|
type: "module",
|
|
180435
180597
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
180436
180598
|
main: "dist/index.js",
|
|
@@ -185534,15 +185696,26 @@ function err3(text) {
|
|
|
185534
185696
|
isError: true
|
|
185535
185697
|
};
|
|
185536
185698
|
}
|
|
185699
|
+
function captureAnchorOrdinal(db, sessionId) {
|
|
185700
|
+
try {
|
|
185701
|
+
const ordinal = getLastIndexedOrdinal(db, sessionId);
|
|
185702
|
+
return ordinal > 0 ? ordinal : null;
|
|
185703
|
+
} catch {
|
|
185704
|
+
return null;
|
|
185705
|
+
}
|
|
185706
|
+
}
|
|
185707
|
+
function anchorSuffix(note) {
|
|
185708
|
+
return note.anchorOrdinal !== null ? ` ↳ @msg ${note.anchorOrdinal}` : "";
|
|
185709
|
+
}
|
|
185537
185710
|
function formatNoteLine(note) {
|
|
185538
185711
|
if (note.type === "smart") {
|
|
185539
185712
|
const conditionLine = note.status === "ready" ? note.readyReason ?? note.surfaceCondition ?? "Condition satisfied" : note.surfaceCondition ?? "No condition recorded";
|
|
185540
185713
|
const statusSuffix2 = note.status === "active" ? "" : ` (${note.status})`;
|
|
185541
|
-
return `- **#${note.id}**${statusSuffix2}: ${note.content}
|
|
185714
|
+
return `- **#${note.id}**${statusSuffix2}: ${note.content}${anchorSuffix(note)}
|
|
185542
185715
|
*Condition*: ${conditionLine}`;
|
|
185543
185716
|
}
|
|
185544
185717
|
const statusSuffix = note.status === "active" ? "" : ` (${note.status})`;
|
|
185545
|
-
return `- **#${note.id}**${statusSuffix}: ${note.content}`;
|
|
185718
|
+
return `- **#${note.id}**${statusSuffix}: ${note.content}${anchorSuffix(note)}`;
|
|
185546
185719
|
}
|
|
185547
185720
|
var DISMISS_FOOTER = `
|
|
185548
185721
|
|
|
@@ -185564,6 +185737,7 @@ function createCtxNoteTool(deps) {
|
|
|
185564
185737
|
const content = params.content?.trim();
|
|
185565
185738
|
if (!content)
|
|
185566
185739
|
return err3("Error: 'content' is required when action is 'write'.");
|
|
185740
|
+
const anchorOrdinal = captureAnchorOrdinal(deps.db, sessionId);
|
|
185567
185741
|
const surfaceCondition = params.surface_condition?.trim();
|
|
185568
185742
|
if (surfaceCondition) {
|
|
185569
185743
|
if (deps.dreamerEnabled !== true) {
|
|
@@ -185576,13 +185750,18 @@ function createCtxNoteTool(deps) {
|
|
|
185576
185750
|
const note2 = addNote(deps.db, "smart", {
|
|
185577
185751
|
content,
|
|
185578
185752
|
projectPath: projectIdentity,
|
|
185579
|
-
surfaceCondition
|
|
185753
|
+
surfaceCondition,
|
|
185754
|
+
anchorOrdinal
|
|
185580
185755
|
});
|
|
185581
185756
|
return ok3(`Created smart note #${note2.id}. Dreamer will evaluate the condition during nightly runs:
|
|
185582
185757
|
- Content: ${content}
|
|
185583
185758
|
- Condition: ${surfaceCondition}`);
|
|
185584
185759
|
}
|
|
185585
|
-
const note = addNote(deps.db, "session", {
|
|
185760
|
+
const note = addNote(deps.db, "session", {
|
|
185761
|
+
sessionId,
|
|
185762
|
+
content,
|
|
185763
|
+
anchorOrdinal
|
|
185764
|
+
});
|
|
185586
185765
|
return ok3(`Saved session note #${note.id}.`);
|
|
185587
185766
|
}
|
|
185588
185767
|
if (action2 === "dismiss") {
|
|
@@ -185645,9 +185824,13 @@ function createCtxNoteTool(deps) {
|
|
|
185645
185824
|
|
|
185646
185825
|
No notes for the current filter.`);
|
|
185647
185826
|
}
|
|
185648
|
-
|
|
185827
|
+
const body = sections.join(`
|
|
185828
|
+
|
|
185829
|
+
`);
|
|
185830
|
+
const anchorHint = body.includes("↳ @msg ") ? `
|
|
185649
185831
|
|
|
185650
|
-
|
|
185832
|
+
↳ @msg N marks the conversation tail when a note was written. To see what led to it: ctx_expand(start=N-x, end=N) (pick x for how far back to look).` : "";
|
|
185833
|
+
return ok3(`${body}${anchorHint}${DISMISS_FOOTER}`);
|
|
185651
185834
|
}
|
|
185652
185835
|
};
|
|
185653
185836
|
}
|
|
@@ -185992,7 +186175,8 @@ function createCtxSearchTool(deps) {
|
|
|
185992
186175
|
maxMessageOrdinal: lastCompartmentEnd >= 0 ? lastCompartmentEnd : undefined,
|
|
185993
186176
|
gitCommitsEnabled,
|
|
185994
186177
|
sources: params.sources,
|
|
185995
|
-
visibleMemoryIds
|
|
186178
|
+
visibleMemoryIds,
|
|
186179
|
+
explicitSearch: true
|
|
185996
186180
|
});
|
|
185997
186181
|
return {
|
|
185998
186182
|
content: [{ type: "text", text: formatSearchResults(query, results) }],
|
|
@@ -186140,8 +186324,7 @@ function getPiMessageModel(message) {
|
|
|
186140
186324
|
};
|
|
186141
186325
|
}
|
|
186142
186326
|
function resolvePiPressureContextLimit(args) {
|
|
186143
|
-
|
|
186144
|
-
let effectiveContextLimit = cachedLimit ?? args.piContextWindow;
|
|
186327
|
+
let effectiveContextLimit = isSaneLimit(args.piContextWindow) ? args.piContextWindow : 0;
|
|
186145
186328
|
try {
|
|
186146
186329
|
const overflowState = getOverflowState(args.db, args.sessionId);
|
|
186147
186330
|
if (overflowState.detectedContextLimit > 0) {
|
|
@@ -186157,8 +186340,6 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
186157
186340
|
const effectiveContextLimit = resolvePiPressureContextLimit({
|
|
186158
186341
|
db: args.db,
|
|
186159
186342
|
sessionId: args.sessionId,
|
|
186160
|
-
provider: provider2,
|
|
186161
|
-
model,
|
|
186162
186343
|
piContextWindow: args.piContextWindow
|
|
186163
186344
|
});
|
|
186164
186345
|
const usage = extractAssistantUsage(args.message);
|
|
@@ -186167,24 +186348,12 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
186167
186348
|
const messageHadOverflowError = typeof msg?.errorMessage === "string" && detectOverflow(msg.errorMessage).isOverflow;
|
|
186168
186349
|
const updates = { lastResponseTime: Date.now() };
|
|
186169
186350
|
if (pressure) {
|
|
186170
|
-
|
|
186171
|
-
|
|
186351
|
+
const percentage = pressure.percentage;
|
|
186352
|
+
const contextLimit = effectiveContextLimit;
|
|
186172
186353
|
const meta3 = getOrCreateSessionMeta(args.db, args.sessionId);
|
|
186173
186354
|
const observedSafeInputTokens = meta3.observedSafeInputTokens ?? 0;
|
|
186174
186355
|
if (percentage > 100 && observedSafeInputTokens > 0 && pressure.inputTokens <= observedSafeInputTokens * 2) {
|
|
186175
|
-
|
|
186176
|
-
clearModelsDevCache();
|
|
186177
|
-
contextLimit = resolvePiPressureContextLimit({
|
|
186178
|
-
db: args.db,
|
|
186179
|
-
sessionId: args.sessionId,
|
|
186180
|
-
provider: provider2,
|
|
186181
|
-
model,
|
|
186182
|
-
piContextWindow: args.piContextWindow
|
|
186183
|
-
});
|
|
186184
|
-
if (contextLimit >= pressure.inputTokens) {
|
|
186185
|
-
percentage = pressure.inputTokens / contextLimit * 100;
|
|
186186
|
-
log(`${PREFIX} models-dev-cache: regression recovered for ${provider2}/${model} via Pi cache reload (was=${oldLimit}, now=${contextLimit})`);
|
|
186187
|
-
} else if (!meta3.cacheAlertSent) {
|
|
186356
|
+
if (!meta3.cacheAlertSent) {
|
|
186188
186357
|
updates.cacheAlertSent = true;
|
|
186189
186358
|
const safeTokens = Math.max(observedSafeInputTokens, pressure.inputTokens);
|
|
186190
186359
|
const modelLabel = provider2 && model ? `${provider2}/${model}` : "the active model";
|
|
@@ -186655,7 +186824,7 @@ ${block}` : event.systemPrompt;
|
|
|
186655
186824
|
cacheTtlConfig: config2.cache_ttl
|
|
186656
186825
|
});
|
|
186657
186826
|
const piUsage = ctx.getContextUsage?.();
|
|
186658
|
-
const piContextWindow = piUsage && typeof piUsage.contextWindow === "number" ? piUsage.contextWindow : 0;
|
|
186827
|
+
const piContextWindow = piUsage && typeof piUsage.contextWindow === "number" && piUsage.contextWindow > 0 ? piUsage.contextWindow : ctx.model?.contextWindow ?? 0;
|
|
186659
186828
|
await persistPiPressureFromMessageEnd({
|
|
186660
186829
|
db,
|
|
186661
186830
|
sessionId,
|