@cortexkit/pi-magic-context 0.22.4 → 0.22.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -3
- package/dist/index.js +549 -172
- package/dist/subagent-entry.js +340 -73
- package/package.json +1 -1
package/dist/subagent-entry.js
CHANGED
|
@@ -142476,6 +142476,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142476
142476
|
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
142477
142477
|
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
142478
142478
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
142479
|
+
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
142479
142480
|
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
142480
142481
|
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
142481
142482
|
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
@@ -142626,6 +142627,7 @@ function healNullTextColumns(db) {
|
|
|
142626
142627
|
["todo_synthetic_state_json", ""],
|
|
142627
142628
|
["system_prompt_hash", ""],
|
|
142628
142629
|
["stripped_placeholder_ids", ""],
|
|
142630
|
+
["stale_reduce_stripped_ids", ""],
|
|
142629
142631
|
["memory_block_cache", ""],
|
|
142630
142632
|
["memory_block_ids", ""],
|
|
142631
142633
|
["compaction_marker_state", ""],
|
|
@@ -142735,6 +142737,31 @@ function openDatabase(dbPathOrOptions) {
|
|
|
142735
142737
|
}
|
|
142736
142738
|
}
|
|
142737
142739
|
|
|
142740
|
+
// ../plugin/src/config/prune-config-leaf.ts
|
|
142741
|
+
function isPlainObject(value) {
|
|
142742
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
142743
|
+
}
|
|
142744
|
+
function pruneNestedConfigLeaf(block, relativePath) {
|
|
142745
|
+
if (relativePath.length === 0)
|
|
142746
|
+
return null;
|
|
142747
|
+
const result = { ...block };
|
|
142748
|
+
let cursor = result;
|
|
142749
|
+
for (let i = 0;i < relativePath.length - 1; i++) {
|
|
142750
|
+
const seg = String(relativePath[i]);
|
|
142751
|
+
const child = cursor[seg];
|
|
142752
|
+
if (!isPlainObject(child))
|
|
142753
|
+
return null;
|
|
142754
|
+
const clonedChild = { ...child };
|
|
142755
|
+
cursor[seg] = clonedChild;
|
|
142756
|
+
cursor = clonedChild;
|
|
142757
|
+
}
|
|
142758
|
+
const leaf = String(relativePath[relativePath.length - 1]);
|
|
142759
|
+
if (!(leaf in cursor))
|
|
142760
|
+
return null;
|
|
142761
|
+
delete cursor[leaf];
|
|
142762
|
+
return { block: result, removed: relativePath.map(String).join(".") };
|
|
142763
|
+
}
|
|
142764
|
+
|
|
142738
142765
|
// src/config/index.ts
|
|
142739
142766
|
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
142740
142767
|
import { homedir as homedir3 } from "node:os";
|
|
@@ -142876,6 +142903,70 @@ function migrateLegacyExperimental(rawConfig, warnings) {
|
|
|
142876
142903
|
return patched;
|
|
142877
142904
|
}
|
|
142878
142905
|
|
|
142906
|
+
// ../plugin/src/config/project-security.ts
|
|
142907
|
+
var HIDDEN_AGENT_KEYS = ["historian", "dreamer", "sidekick"];
|
|
142908
|
+
var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools", "system_prompt"];
|
|
142909
|
+
function isPlainObject2(value) {
|
|
142910
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
142911
|
+
}
|
|
142912
|
+
function stripUnsafeProjectConfigFields(projectRaw) {
|
|
142913
|
+
const warnings = [];
|
|
142914
|
+
if ("auto_update" in projectRaw) {
|
|
142915
|
+
delete projectRaw.auto_update;
|
|
142916
|
+
warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
|
|
142917
|
+
}
|
|
142918
|
+
for (const agentKey of HIDDEN_AGENT_KEYS) {
|
|
142919
|
+
const block = projectRaw[agentKey];
|
|
142920
|
+
if (!isPlainObject2(block))
|
|
142921
|
+
continue;
|
|
142922
|
+
const removed = [];
|
|
142923
|
+
for (const field of AGENT_ESCALATION_FIELDS) {
|
|
142924
|
+
if (field in block) {
|
|
142925
|
+
delete block[field];
|
|
142926
|
+
removed.push(field);
|
|
142927
|
+
}
|
|
142928
|
+
}
|
|
142929
|
+
if (removed.length > 0) {
|
|
142930
|
+
warnings.push(`Ignoring ${agentKey}.${removed.join("/")} from project config ` + "(security: a repository cannot reprogram or re-permission hidden agents).");
|
|
142931
|
+
}
|
|
142932
|
+
}
|
|
142933
|
+
return warnings;
|
|
142934
|
+
}
|
|
142935
|
+
function normalizeEndpoint(value) {
|
|
142936
|
+
if (typeof value !== "string")
|
|
142937
|
+
return;
|
|
142938
|
+
const trimmed = value.trim().replace(/\/+$/, "");
|
|
142939
|
+
return trimmed.length > 0 ? trimmed.toLowerCase() : undefined;
|
|
142940
|
+
}
|
|
142941
|
+
function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
|
|
142942
|
+
const projectEmbedding = projectRaw.embedding;
|
|
142943
|
+
if (!isPlainObject2(projectEmbedding))
|
|
142944
|
+
return [];
|
|
142945
|
+
const redirectsEndpoint = "endpoint" in projectEmbedding;
|
|
142946
|
+
if (!redirectsEndpoint)
|
|
142947
|
+
return [];
|
|
142948
|
+
const userEmbedding = userRaw?.embedding;
|
|
142949
|
+
if (isPlainObject2(userEmbedding)) {
|
|
142950
|
+
const projectEndpoint = normalizeEndpoint(projectEmbedding.endpoint);
|
|
142951
|
+
const userEndpoint = normalizeEndpoint(userEmbedding.endpoint);
|
|
142952
|
+
if (projectEndpoint !== undefined && projectEndpoint === userEndpoint) {
|
|
142953
|
+
return [];
|
|
142954
|
+
}
|
|
142955
|
+
}
|
|
142956
|
+
const providesOwnKey = typeof projectEmbedding.api_key === "string" && projectEmbedding.api_key.length > 0;
|
|
142957
|
+
if (providesOwnKey)
|
|
142958
|
+
return [];
|
|
142959
|
+
const mergedEmbedding = mergedRaw.embedding;
|
|
142960
|
+
if (!isPlainObject2(mergedEmbedding))
|
|
142961
|
+
return [];
|
|
142962
|
+
if (!("api_key" in mergedEmbedding))
|
|
142963
|
+
return [];
|
|
142964
|
+
delete mergedEmbedding.api_key;
|
|
142965
|
+
return [
|
|
142966
|
+
"Dropped inherited user embedding api_key because project config redirected " + "embedding.endpoint without supplying its own key (security: prevents key " + "exfiltration to a repository-chosen endpoint)."
|
|
142967
|
+
];
|
|
142968
|
+
}
|
|
142969
|
+
|
|
142879
142970
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
142880
142971
|
var exports_external = {};
|
|
142881
142972
|
__export(exports_external, {
|
|
@@ -143507,7 +143598,7 @@ __export(exports_util, {
|
|
|
143507
143598
|
jsonStringifyReplacer: () => jsonStringifyReplacer,
|
|
143508
143599
|
joinValues: () => joinValues,
|
|
143509
143600
|
issue: () => issue,
|
|
143510
|
-
isPlainObject: () =>
|
|
143601
|
+
isPlainObject: () => isPlainObject3,
|
|
143511
143602
|
isObject: () => isObject,
|
|
143512
143603
|
hexToUint8Array: () => hexToUint8Array,
|
|
143513
143604
|
getSizableOrigin: () => getSizableOrigin,
|
|
@@ -143689,7 +143780,7 @@ var allowsEval = /* @__PURE__ */ cached(() => {
|
|
|
143689
143780
|
return false;
|
|
143690
143781
|
}
|
|
143691
143782
|
});
|
|
143692
|
-
function
|
|
143783
|
+
function isPlainObject3(o) {
|
|
143693
143784
|
if (isObject(o) === false)
|
|
143694
143785
|
return false;
|
|
143695
143786
|
const ctor = o.constructor;
|
|
@@ -143706,7 +143797,7 @@ function isPlainObject(o) {
|
|
|
143706
143797
|
return true;
|
|
143707
143798
|
}
|
|
143708
143799
|
function shallowClone(o) {
|
|
143709
|
-
if (
|
|
143800
|
+
if (isPlainObject3(o))
|
|
143710
143801
|
return { ...o };
|
|
143711
143802
|
if (Array.isArray(o))
|
|
143712
143803
|
return [...o];
|
|
@@ -143910,7 +144001,7 @@ function omit(schema, mask) {
|
|
|
143910
144001
|
return clone(schema, def);
|
|
143911
144002
|
}
|
|
143912
144003
|
function extend(schema, shape) {
|
|
143913
|
-
if (!
|
|
144004
|
+
if (!isPlainObject3(shape)) {
|
|
143914
144005
|
throw new Error("Invalid input to extend: expected a plain object");
|
|
143915
144006
|
}
|
|
143916
144007
|
const checks = schema._zod.def.checks;
|
|
@@ -143933,7 +144024,7 @@ function extend(schema, shape) {
|
|
|
143933
144024
|
return clone(schema, def);
|
|
143934
144025
|
}
|
|
143935
144026
|
function safeExtend(schema, shape) {
|
|
143936
|
-
if (!
|
|
144027
|
+
if (!isPlainObject3(shape)) {
|
|
143937
144028
|
throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
143938
144029
|
}
|
|
143939
144030
|
const def = mergeDefs(schema._zod.def, {
|
|
@@ -146276,7 +146367,7 @@ function mergeValues(a, b) {
|
|
|
146276
146367
|
if (a instanceof Date && b instanceof Date && +a === +b) {
|
|
146277
146368
|
return { valid: true, data: a };
|
|
146278
146369
|
}
|
|
146279
|
-
if (
|
|
146370
|
+
if (isPlainObject3(a) && isPlainObject3(b)) {
|
|
146280
146371
|
const bKeys = Object.keys(b);
|
|
146281
146372
|
const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
146282
146373
|
const newObj = { ...a, ...b };
|
|
@@ -146462,7 +146553,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
146462
146553
|
$ZodType.init(inst, def);
|
|
146463
146554
|
inst._zod.parse = (payload, ctx) => {
|
|
146464
146555
|
const input = payload.value;
|
|
146465
|
-
if (!
|
|
146556
|
+
if (!isPlainObject3(input)) {
|
|
146466
146557
|
payload.issues.push({
|
|
146467
146558
|
expected: "record",
|
|
146468
146559
|
code: "invalid_type",
|
|
@@ -157416,6 +157507,21 @@ function stripJsonComments(content) {
|
|
|
157416
157507
|
// ../plugin/src/config/variable.ts
|
|
157417
157508
|
var ENV_PATTERN = /\{env:([^}]+)\}/g;
|
|
157418
157509
|
var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
157510
|
+
function sensitiveFilePathReason(resolvedPath) {
|
|
157511
|
+
const home = homedir2();
|
|
157512
|
+
const sensitiveDirs = [
|
|
157513
|
+
{ dir: resolve2(home, ".ssh"), label: "SSH keys" },
|
|
157514
|
+
{ dir: resolve2(home, ".aws"), label: "AWS credentials" },
|
|
157515
|
+
{ dir: resolve2(home, ".gnupg"), label: "GnuPG keyring" },
|
|
157516
|
+
{ dir: resolve2(home, ".config", "gh"), label: "GitHub CLI auth" }
|
|
157517
|
+
];
|
|
157518
|
+
for (const { dir, label } of sensitiveDirs) {
|
|
157519
|
+
if (resolvedPath === dir || resolvedPath.startsWith(`${dir}/`)) {
|
|
157520
|
+
return label;
|
|
157521
|
+
}
|
|
157522
|
+
}
|
|
157523
|
+
return null;
|
|
157524
|
+
}
|
|
157419
157525
|
function substituteConfigVariables(input) {
|
|
157420
157526
|
const warnings = [];
|
|
157421
157527
|
let text = input.text;
|
|
@@ -157469,6 +157575,10 @@ function substituteConfigVariables(input) {
|
|
|
157469
157575
|
} else if (!isAbsolute(filePath)) {
|
|
157470
157576
|
filePath = resolve2(configDir, filePath);
|
|
157471
157577
|
}
|
|
157578
|
+
const sensitiveReason = sensitiveFilePathReason(filePath);
|
|
157579
|
+
if (sensitiveReason) {
|
|
157580
|
+
warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
|
|
157581
|
+
}
|
|
157472
157582
|
if (!existsSync4(filePath)) {
|
|
157473
157583
|
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
157474
157584
|
continue;
|
|
@@ -157507,7 +157617,8 @@ function loadConfigFile(path3, scope) {
|
|
|
157507
157617
|
const rawText = readFileSync3(path3, "utf-8");
|
|
157508
157618
|
const substituted = substituteConfigVariables({
|
|
157509
157619
|
text: rawText,
|
|
157510
|
-
configPath: path3
|
|
157620
|
+
configPath: path3,
|
|
157621
|
+
isProjectConfig: scope === "project"
|
|
157511
157622
|
});
|
|
157512
157623
|
return {
|
|
157513
157624
|
path: path3,
|
|
@@ -157549,14 +157660,14 @@ function redactConfigValue(value) {
|
|
|
157549
157660
|
}
|
|
157550
157661
|
return typeof value;
|
|
157551
157662
|
}
|
|
157552
|
-
function
|
|
157663
|
+
function isPlainObject4(value) {
|
|
157553
157664
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
157554
157665
|
}
|
|
157555
157666
|
function mergeRawConfigs(base, override) {
|
|
157556
157667
|
const merged = { ...base };
|
|
157557
157668
|
for (const [key, overrideValue] of Object.entries(override)) {
|
|
157558
157669
|
const baseValue = merged[key];
|
|
157559
|
-
merged[key] =
|
|
157670
|
+
merged[key] = isPlainObject4(baseValue) && isPlainObject4(overrideValue) ? mergeRawConfigs(baseValue, overrideValue) : overrideValue;
|
|
157560
157671
|
}
|
|
157561
157672
|
return merged;
|
|
157562
157673
|
}
|
|
@@ -157570,10 +157681,15 @@ function parsePiConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
|
157570
157681
|
}
|
|
157571
157682
|
const defaults = MagicContextConfigSchema.parse({});
|
|
157572
157683
|
const errorPaths = new Set;
|
|
157684
|
+
const issuePathsByKey = new Map;
|
|
157573
157685
|
for (const issue2 of parsed.error.issues) {
|
|
157574
157686
|
const topKey = issue2.path[0];
|
|
157575
157687
|
if (topKey !== undefined) {
|
|
157576
|
-
|
|
157688
|
+
const key = String(topKey);
|
|
157689
|
+
errorPaths.add(key);
|
|
157690
|
+
const paths = issuePathsByKey.get(key) ?? [];
|
|
157691
|
+
paths.push([...issue2.path]);
|
|
157692
|
+
issuePathsByKey.set(key, paths);
|
|
157577
157693
|
}
|
|
157578
157694
|
}
|
|
157579
157695
|
const patched = { ...migrated };
|
|
@@ -157581,11 +157697,32 @@ function parsePiConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
|
157581
157697
|
for (const key of errorPaths) {
|
|
157582
157698
|
recoveredTopLevelKeys.push(key);
|
|
157583
157699
|
const isAgentConfig = key === "historian" || key === "dreamer" || key === "sidekick";
|
|
157584
|
-
delete patched[key];
|
|
157585
157700
|
if (isAgentConfig) {
|
|
157701
|
+
delete patched[key];
|
|
157586
157702
|
warnings.push(`"${key}": invalid agent configuration, ignoring. Check your magic-context.jsonc.`);
|
|
157587
157703
|
continue;
|
|
157588
157704
|
}
|
|
157705
|
+
const issuePaths = issuePathsByKey.get(key) ?? [];
|
|
157706
|
+
const rawValue = migrated[key];
|
|
157707
|
+
const allNested = issuePaths.length > 0 && issuePaths.every((p) => p.length >= 2) && typeof rawValue === "object" && rawValue !== null && !Array.isArray(rawValue);
|
|
157708
|
+
if (allNested) {
|
|
157709
|
+
let prunedBlock = {
|
|
157710
|
+
...rawValue
|
|
157711
|
+
};
|
|
157712
|
+
const prunedLeaves = [];
|
|
157713
|
+
for (const p of issuePaths) {
|
|
157714
|
+
const relative = p.slice(1);
|
|
157715
|
+
const result = pruneNestedConfigLeaf(prunedBlock, relative);
|
|
157716
|
+
if (result) {
|
|
157717
|
+
prunedBlock = result.block;
|
|
157718
|
+
prunedLeaves.push(result.removed);
|
|
157719
|
+
}
|
|
157720
|
+
}
|
|
157721
|
+
patched[key] = prunedBlock;
|
|
157722
|
+
warnings.push(`"${key}": invalid nested field(s) ${prunedLeaves.map((l) => `"${l}"`).join(", ")}, using defaults for those.`);
|
|
157723
|
+
continue;
|
|
157724
|
+
}
|
|
157725
|
+
delete patched[key];
|
|
157589
157726
|
const defaultValue = defaults[key];
|
|
157590
157727
|
warnings.push(`"${key}": invalid value (${redactConfigValue(rawConfig[key])}), using default ${JSON.stringify(defaultValue)}.`);
|
|
157591
157728
|
}
|
|
@@ -157618,10 +157755,22 @@ function loadPiConfig(opts = {}) {
|
|
|
157618
157755
|
return 0;
|
|
157619
157756
|
return a.scope === "user" ? -1 : 1;
|
|
157620
157757
|
});
|
|
157758
|
+
const userRaw = mergeFiles.find((f) => f.scope === "user")?.config;
|
|
157621
157759
|
for (const loaded of mergeFiles) {
|
|
157622
157760
|
const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
|
|
157623
157761
|
warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
|
|
157624
|
-
|
|
157762
|
+
if (loaded.scope === "project") {
|
|
157763
|
+
const projectRaw = { ...loaded.config };
|
|
157764
|
+
for (const warning of stripUnsafeProjectConfigFields(projectRaw)) {
|
|
157765
|
+
warnings.push(`${prefix} ${warning}`);
|
|
157766
|
+
}
|
|
157767
|
+
rawConfig = mergeRawConfigs(rawConfig, projectRaw);
|
|
157768
|
+
for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, rawConfig, userRaw)) {
|
|
157769
|
+
warnings.push(`${prefix} ${warning}`);
|
|
157770
|
+
}
|
|
157771
|
+
} else {
|
|
157772
|
+
rawConfig = mergeRawConfigs(rawConfig, loaded.config);
|
|
157773
|
+
}
|
|
157625
157774
|
}
|
|
157626
157775
|
const parsed = parsePiConfig(rawConfig);
|
|
157627
157776
|
warnings.push(...parsed.warnings.map((warning) => `[merged config] ${warning}`));
|
|
@@ -157696,10 +157845,22 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
157696
157845
|
return 0;
|
|
157697
157846
|
return a.scope === "user" ? -1 : 1;
|
|
157698
157847
|
});
|
|
157848
|
+
const userRaw = mergeFiles.find((f) => f.scope === "user")?.config;
|
|
157699
157849
|
for (const loaded of mergeFiles) {
|
|
157700
157850
|
const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
|
|
157701
157851
|
warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
|
|
157702
|
-
|
|
157852
|
+
if (loaded.scope === "project") {
|
|
157853
|
+
const projectRaw = { ...loaded.config };
|
|
157854
|
+
for (const warning of stripUnsafeProjectConfigFields(projectRaw)) {
|
|
157855
|
+
warnings.push(`${prefix} ${warning}`);
|
|
157856
|
+
}
|
|
157857
|
+
rawConfig = mergeRawConfigs(rawConfig, projectRaw);
|
|
157858
|
+
for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, rawConfig, userRaw)) {
|
|
157859
|
+
warnings.push(`${prefix} ${warning}`);
|
|
157860
|
+
}
|
|
157861
|
+
} else {
|
|
157862
|
+
rawConfig = mergeRawConfigs(rawConfig, loaded.config);
|
|
157863
|
+
}
|
|
157703
157864
|
}
|
|
157704
157865
|
const recoveredTopLevelKeys = [];
|
|
157705
157866
|
const parsed = parsePiConfig(rawConfig, recoveredTopLevelKeys);
|
|
@@ -157754,7 +157915,7 @@ function computeNormalizedHash(content) {
|
|
|
157754
157915
|
}
|
|
157755
157916
|
|
|
157756
157917
|
// ../plugin/src/features/magic-context/memory/embedding-identity.ts
|
|
157757
|
-
function
|
|
157918
|
+
function normalizeEndpoint2(endpoint) {
|
|
157758
157919
|
return endpoint?.trim().replace(/\/+$/, "") ?? "";
|
|
157759
157920
|
}
|
|
157760
157921
|
function getEmbeddingProviderIdentity(config2) {
|
|
@@ -157764,7 +157925,7 @@ function getEmbeddingProviderIdentity(config2) {
|
|
|
157764
157925
|
const identityInput = config2.provider === "openai-compatible" ? {
|
|
157765
157926
|
provider: "openai-compatible",
|
|
157766
157927
|
model: config2.model.trim(),
|
|
157767
|
-
endpoint:
|
|
157928
|
+
endpoint: normalizeEndpoint2(config2.endpoint),
|
|
157768
157929
|
apiKeyPresent: Boolean(config2.api_key?.trim()),
|
|
157769
157930
|
inputType: config2.input_type?.trim() || ""
|
|
157770
157931
|
} : {
|
|
@@ -158115,8 +158276,61 @@ class LocalEmbeddingProvider {
|
|
|
158115
158276
|
}
|
|
158116
158277
|
}
|
|
158117
158278
|
|
|
158279
|
+
// ../plugin/src/features/magic-context/memory/embedding-ssrf.ts
|
|
158280
|
+
var METADATA_HOSTNAMES = new Set(["metadata.google.internal", "metadata.goog"]);
|
|
158281
|
+
var IPV6_METADATA_HOSTS = new Set(["fd00:ec2::254"]);
|
|
158282
|
+
function isLinkLocalIpv4(host) {
|
|
158283
|
+
return /^169\.254\.\d{1,3}\.\d{1,3}$/.test(host);
|
|
158284
|
+
}
|
|
158285
|
+
function ipv4FromMappedIpv6(host) {
|
|
158286
|
+
const m = /^::ffff:(.+)$/.exec(host);
|
|
158287
|
+
if (!m)
|
|
158288
|
+
return null;
|
|
158289
|
+
const tail = m[1];
|
|
158290
|
+
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(tail))
|
|
158291
|
+
return tail;
|
|
158292
|
+
const hex3 = /^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(tail);
|
|
158293
|
+
if (hex3) {
|
|
158294
|
+
const hi = Number.parseInt(hex3[1], 16);
|
|
158295
|
+
const lo = Number.parseInt(hex3[2], 16);
|
|
158296
|
+
if (Number.isNaN(hi) || Number.isNaN(lo))
|
|
158297
|
+
return null;
|
|
158298
|
+
return `${hi >> 8 & 255}.${hi & 255}.${lo >> 8 & 255}.${lo & 255}`;
|
|
158299
|
+
}
|
|
158300
|
+
return null;
|
|
158301
|
+
}
|
|
158302
|
+
function blockedEmbeddingEndpointReason(endpoint) {
|
|
158303
|
+
const trimmed = endpoint.trim();
|
|
158304
|
+
if (trimmed.length === 0)
|
|
158305
|
+
return null;
|
|
158306
|
+
let url2;
|
|
158307
|
+
try {
|
|
158308
|
+
url2 = new URL(trimmed);
|
|
158309
|
+
} catch {
|
|
158310
|
+
return `embedding endpoint is not a valid URL: ${trimmed}`;
|
|
158311
|
+
}
|
|
158312
|
+
const host = url2.hostname.toLowerCase().replace(/^\[/, "").replace(/\]$/, "");
|
|
158313
|
+
if (METADATA_HOSTNAMES.has(host)) {
|
|
158314
|
+
return `embedding endpoint host ${host} is a cloud metadata service (blocked)`;
|
|
158315
|
+
}
|
|
158316
|
+
if (IPV6_METADATA_HOSTS.has(host)) {
|
|
158317
|
+
return `embedding endpoint host ${host} is the AWS IPv6 metadata service (blocked)`;
|
|
158318
|
+
}
|
|
158319
|
+
if (isLinkLocalIpv4(host)) {
|
|
158320
|
+
return `embedding endpoint host ${host} is link-local / cloud metadata (blocked)`;
|
|
158321
|
+
}
|
|
158322
|
+
const mappedV4 = ipv4FromMappedIpv6(host);
|
|
158323
|
+
if (mappedV4 && isLinkLocalIpv4(mappedV4)) {
|
|
158324
|
+
return `embedding endpoint host ${host} (IPv4-mapped ${mappedV4}) is link-local / cloud metadata (blocked)`;
|
|
158325
|
+
}
|
|
158326
|
+
if (host.startsWith("fe80:")) {
|
|
158327
|
+
return `embedding endpoint host ${host} is link-local / cloud metadata (blocked)`;
|
|
158328
|
+
}
|
|
158329
|
+
return null;
|
|
158330
|
+
}
|
|
158331
|
+
|
|
158118
158332
|
// ../plugin/src/features/magic-context/memory/embedding-openai.ts
|
|
158119
|
-
function
|
|
158333
|
+
function normalizeEndpoint3(endpoint) {
|
|
158120
158334
|
return endpoint?.trim().replace(/\/+$/, "") ?? "";
|
|
158121
158335
|
}
|
|
158122
158336
|
var FAILURE_THRESHOLD = 3;
|
|
@@ -158137,7 +158351,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
158137
158351
|
openLogged = false;
|
|
158138
158352
|
halfOpenProbeInFlight = false;
|
|
158139
158353
|
constructor(options) {
|
|
158140
|
-
this.endpoint =
|
|
158354
|
+
this.endpoint = normalizeEndpoint3(options.endpoint);
|
|
158141
158355
|
this.model = options.model?.trim() ?? "";
|
|
158142
158356
|
this.apiKey = options.apiKey?.trim() ?? "";
|
|
158143
158357
|
this.inputType = options.inputType?.trim() ?? "";
|
|
@@ -158157,6 +158371,12 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
158157
158371
|
this.initialized = false;
|
|
158158
158372
|
return false;
|
|
158159
158373
|
}
|
|
158374
|
+
const blockedReason = blockedEmbeddingEndpointReason(this.endpoint);
|
|
158375
|
+
if (blockedReason) {
|
|
158376
|
+
log(`[magic-context] embedding endpoint blocked: ${blockedReason}`);
|
|
158377
|
+
this.initialized = false;
|
|
158378
|
+
return false;
|
|
158379
|
+
}
|
|
158160
158380
|
this.initialized = true;
|
|
158161
158381
|
return true;
|
|
158162
158382
|
}
|
|
@@ -158202,6 +158422,7 @@ class OpenAICompatibleEmbeddingProvider {
|
|
|
158202
158422
|
...this.inputType ? { input_type: this.inputType } : {},
|
|
158203
158423
|
...this.truncate ? { truncate: this.truncate } : {}
|
|
158204
158424
|
}),
|
|
158425
|
+
redirect: "error",
|
|
158205
158426
|
signal: internalController.signal
|
|
158206
158427
|
});
|
|
158207
158428
|
if (!response.ok) {
|
|
@@ -158681,11 +158902,15 @@ function resolveEmbeddingConfig(config2) {
|
|
|
158681
158902
|
}
|
|
158682
158903
|
if (config2.provider === "openai-compatible") {
|
|
158683
158904
|
const apiKey = config2.api_key?.trim();
|
|
158905
|
+
const inputType = config2.input_type?.trim();
|
|
158906
|
+
const truncate = config2.truncate?.trim();
|
|
158684
158907
|
return {
|
|
158685
158908
|
provider: "openai-compatible",
|
|
158686
158909
|
model: config2.model.trim(),
|
|
158687
158910
|
endpoint: config2.endpoint.trim(),
|
|
158688
|
-
...apiKey ? { api_key: apiKey } : {}
|
|
158911
|
+
...apiKey ? { api_key: apiKey } : {},
|
|
158912
|
+
...inputType ? { input_type: inputType } : {},
|
|
158913
|
+
...truncate ? { truncate } : {}
|
|
158689
158914
|
};
|
|
158690
158915
|
}
|
|
158691
158916
|
return { provider: "off" };
|
|
@@ -158701,7 +158926,9 @@ function createProvider(config2) {
|
|
|
158701
158926
|
return new OpenAICompatibleEmbeddingProvider({
|
|
158702
158927
|
endpoint: config2.endpoint,
|
|
158703
158928
|
model: config2.model,
|
|
158704
|
-
apiKey: config2.api_key
|
|
158929
|
+
apiKey: config2.api_key,
|
|
158930
|
+
inputType: config2.input_type,
|
|
158931
|
+
truncate: config2.truncate
|
|
158705
158932
|
});
|
|
158706
158933
|
}
|
|
158707
158934
|
return new LocalEmbeddingProvider(config2.model);
|
|
@@ -159140,6 +159367,19 @@ function hasGitDir(canonical) {
|
|
|
159140
159367
|
return false;
|
|
159141
159368
|
}
|
|
159142
159369
|
}
|
|
159370
|
+
function normalizeStoredProjectPath(rawOrStored) {
|
|
159371
|
+
if (rawOrStored.startsWith("git:") || rawOrStored.startsWith("dir:")) {
|
|
159372
|
+
return rawOrStored;
|
|
159373
|
+
}
|
|
159374
|
+
try {
|
|
159375
|
+
return resolveProjectIdentity(rawOrStored);
|
|
159376
|
+
} catch {
|
|
159377
|
+
return directoryFallback(rawOrStored);
|
|
159378
|
+
}
|
|
159379
|
+
}
|
|
159380
|
+
function storedPathBelongsToIdentity(storedProjectPath, projectIdentity) {
|
|
159381
|
+
return storedProjectPath === projectIdentity || normalizeStoredProjectPath(storedProjectPath) === projectIdentity;
|
|
159382
|
+
}
|
|
159143
159383
|
|
|
159144
159384
|
// ../plugin/src/plugin/embedding-bootstrap-helpers.ts
|
|
159145
159385
|
import { createHash as createHash5 } from "node:crypto";
|
|
@@ -159147,10 +159387,20 @@ var EMBEDDING_AFFECTING_KEYS = new Set([
|
|
|
159147
159387
|
"embedding.api_key",
|
|
159148
159388
|
"embedding.endpoint",
|
|
159149
159389
|
"embedding.model",
|
|
159150
|
-
"embedding.provider"
|
|
159390
|
+
"embedding.provider",
|
|
159391
|
+
"embedding.input_type",
|
|
159392
|
+
"embedding.truncate"
|
|
159151
159393
|
]);
|
|
159152
159394
|
var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set(["embedding", "memory", "experimental"]);
|
|
159153
|
-
var EMBEDDING_WARNING_TERMS = [
|
|
159395
|
+
var EMBEDDING_WARNING_TERMS = [
|
|
159396
|
+
"api_key",
|
|
159397
|
+
"endpoint",
|
|
159398
|
+
"model",
|
|
159399
|
+
"provider",
|
|
159400
|
+
"embedding",
|
|
159401
|
+
"input_type",
|
|
159402
|
+
"truncate"
|
|
159403
|
+
];
|
|
159154
159404
|
var loggedFailureSignatures = new Map;
|
|
159155
159405
|
function sha256Prefix2(value, length = 16) {
|
|
159156
159406
|
return createHash5("sha256").update(value).digest("hex").slice(0, length);
|
|
@@ -159586,12 +159836,6 @@ function isCompartmentRow(row) {
|
|
|
159586
159836
|
const candidate = row;
|
|
159587
159837
|
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number" && typeof candidate.start_message_id === "string" && typeof candidate.end_message_id === "string" && typeof candidate.title === "string" && typeof candidate.content === "string" && isStringOrNullish(candidate.p1) && isStringOrNullish(candidate.p2) && isStringOrNullish(candidate.p3) && isStringOrNullish(candidate.p4) && isNumberOrNullish(candidate.importance) && isStringOrNullish(candidate.episode_type) && isNumberOrNullish(candidate.legacy) && typeof candidate.created_at === "number";
|
|
159588
159838
|
}
|
|
159589
|
-
function isSessionFactRow(row) {
|
|
159590
|
-
if (row === null || typeof row !== "object")
|
|
159591
|
-
return false;
|
|
159592
|
-
const candidate = row;
|
|
159593
|
-
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.category === "string" && typeof candidate.content === "string" && typeof candidate.created_at === "number" && typeof candidate.updated_at === "number";
|
|
159594
|
-
}
|
|
159595
159839
|
function insertCompartmentRows(db, sessionId, compartments, now) {
|
|
159596
159840
|
const stmt = getInsertCompartmentStatement(db);
|
|
159597
159841
|
for (const compartment of compartments) {
|
|
@@ -159620,16 +159864,6 @@ function toCompartment(row) {
|
|
|
159620
159864
|
createdAt: row.created_at
|
|
159621
159865
|
};
|
|
159622
159866
|
}
|
|
159623
|
-
function toSessionFact(row) {
|
|
159624
|
-
return {
|
|
159625
|
-
id: row.id,
|
|
159626
|
-
sessionId: row.session_id,
|
|
159627
|
-
category: row.category,
|
|
159628
|
-
content: row.content,
|
|
159629
|
-
createdAt: row.created_at,
|
|
159630
|
-
updatedAt: row.updated_at
|
|
159631
|
-
};
|
|
159632
|
-
}
|
|
159633
159867
|
function getCompartments(db, sessionId) {
|
|
159634
159868
|
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isCompartmentRow);
|
|
159635
159869
|
return rows.map(toCompartment);
|
|
@@ -159650,10 +159884,6 @@ function appendCompartments(db, sessionId, compartments) {
|
|
|
159650
159884
|
insertCompartmentRows(db, sessionId, compartments, now);
|
|
159651
159885
|
})();
|
|
159652
159886
|
}
|
|
159653
|
-
function getSessionFacts(db, sessionId) {
|
|
159654
|
-
const rows = db.prepare("SELECT * FROM session_facts WHERE session_id = ? ORDER BY category ASC, id ASC").all(sessionId).filter(isSessionFactRow);
|
|
159655
|
-
return rows.map(toSessionFact);
|
|
159656
|
-
}
|
|
159657
159887
|
function saveRecompStagingPass(db, sessionId, passNumber, compartments, facts) {
|
|
159658
159888
|
const now = Date.now();
|
|
159659
159889
|
db.transaction(() => {
|
|
@@ -159697,14 +159927,6 @@ function getRecompStaging(db, sessionId) {
|
|
|
159697
159927
|
lastEndMessage: lastEnd
|
|
159698
159928
|
};
|
|
159699
159929
|
}
|
|
159700
|
-
function invalidateAllMemoryBlockCaches(db) {
|
|
159701
|
-
try {
|
|
159702
|
-
const rows = db.prepare("SELECT session_id FROM session_meta").all();
|
|
159703
|
-
for (const row of rows) {
|
|
159704
|
-
clearCachedM0M1(db, row.session_id);
|
|
159705
|
-
}
|
|
159706
|
-
} catch {}
|
|
159707
|
-
}
|
|
159708
159930
|
function clearRecompStaging(db, sessionId) {
|
|
159709
159931
|
db.transaction(() => {
|
|
159710
159932
|
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
@@ -165394,7 +165616,7 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, lastIndexedOrdinal,
|
|
|
165394
165616
|
}
|
|
165395
165617
|
// ../plugin/src/features/magic-context/project-docs-hash.ts
|
|
165396
165618
|
import { createHash as createHash6 } from "node:crypto";
|
|
165397
|
-
import { readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
|
|
165619
|
+
import { lstatSync, readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
|
|
165398
165620
|
import path4 from "node:path";
|
|
165399
165621
|
var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
165400
165622
|
var PROJECT_DOCS_DELIMITER = `
|
|
@@ -165402,6 +165624,7 @@ var PROJECT_DOCS_DELIMITER = `
|
|
|
165402
165624
|
---
|
|
165403
165625
|
|
|
165404
165626
|
`;
|
|
165627
|
+
var MAX_PROJECT_DOC_BYTES = 256 * 1024;
|
|
165405
165628
|
var docsCache = new Map;
|
|
165406
165629
|
function canonicalizeDocContent(raw) {
|
|
165407
165630
|
return raw.replace(/^\uFEFF/, "").replace(/\r\n/g, `
|
|
@@ -165411,9 +165634,10 @@ function canonicalizeDocContent(raw) {
|
|
|
165411
165634
|
}
|
|
165412
165635
|
function fingerprintFile(filePath) {
|
|
165413
165636
|
try {
|
|
165414
|
-
const stat2 =
|
|
165637
|
+
const stat2 = lstatSync(filePath);
|
|
165638
|
+
const isReadableDoc = stat2.isFile() && stat2.size <= MAX_PROJECT_DOC_BYTES;
|
|
165415
165639
|
return {
|
|
165416
|
-
exists:
|
|
165640
|
+
exists: isReadableDoc,
|
|
165417
165641
|
mtimeMs: stat2.mtimeMs,
|
|
165418
165642
|
size: stat2.size
|
|
165419
165643
|
};
|
|
@@ -165456,6 +165680,16 @@ function readCanonicalPieces(projectDirectory, files) {
|
|
|
165456
165680
|
if (!fingerprint?.exists) {
|
|
165457
165681
|
continue;
|
|
165458
165682
|
}
|
|
165683
|
+
let safeToRead = false;
|
|
165684
|
+
try {
|
|
165685
|
+
const st = lstatSync(filePath);
|
|
165686
|
+
safeToRead = st.isFile() && st.size <= MAX_PROJECT_DOC_BYTES;
|
|
165687
|
+
} catch {
|
|
165688
|
+
safeToRead = false;
|
|
165689
|
+
}
|
|
165690
|
+
if (!safeToRead) {
|
|
165691
|
+
continue;
|
|
165692
|
+
}
|
|
165459
165693
|
const canonicalContent = canonicalizeDocContent(readFileSync4(filePath, "utf8"));
|
|
165460
165694
|
hashPieces.push(`file:${filename}
|
|
165461
165695
|
${canonicalContent}`);
|
|
@@ -165776,7 +166010,8 @@ function casUpdateJsonArrayColumn(db, sessionId, column, validator, mutate, opti
|
|
|
165776
166010
|
}
|
|
165777
166011
|
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
165778
166012
|
const row = db.prepare(`SELECT ${column} FROM session_meta WHERE session_id = ?`).get(sessionId);
|
|
165779
|
-
const
|
|
166013
|
+
const rawCurrent = row?.[column] ?? null;
|
|
166014
|
+
const currentBlob = rawCurrent ?? "[]";
|
|
165780
166015
|
const current = parseJsonArray(currentBlob, validator);
|
|
165781
166016
|
const next = mutate(current);
|
|
165782
166017
|
if (next === null)
|
|
@@ -165784,7 +166019,7 @@ function casUpdateJsonArrayColumn(db, sessionId, column, validator, mutate, opti
|
|
|
165784
166019
|
const nextBlob = stableStringify(next);
|
|
165785
166020
|
if (nextBlob === currentBlob)
|
|
165786
166021
|
return true;
|
|
165787
|
-
const result = db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ? AND ${column}
|
|
166022
|
+
const result = db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ? AND ${column} IS ?`).run(nextBlob, sessionId, rawCurrent);
|
|
165788
166023
|
if (result.changes > 0)
|
|
165789
166024
|
return true;
|
|
165790
166025
|
}
|
|
@@ -165913,14 +166148,16 @@ function getHistorianFailureState(db, sessionId) {
|
|
|
165913
166148
|
};
|
|
165914
166149
|
}
|
|
165915
166150
|
function incrementHistorianFailure(db, sessionId, error51) {
|
|
166151
|
+
let nextCount = 1;
|
|
165916
166152
|
db.transaction(() => {
|
|
165917
166153
|
ensureSessionMetaRow(db, sessionId);
|
|
165918
166154
|
const current = getHistorianFailureState(db, sessionId);
|
|
165919
|
-
|
|
166155
|
+
nextCount = current.failureCount + 1;
|
|
165920
166156
|
db.prepare("UPDATE session_meta SET historian_failure_count = ?, historian_last_error = ?, historian_last_failure_at = ? WHERE session_id = ?").run(nextCount, error51, Date.now(), sessionId);
|
|
165921
166157
|
const reason = error51.replace(/\s+/g, " ").trim().slice(0, 300);
|
|
165922
166158
|
sessionLog(sessionId, `historian failure recorded: count=${nextCount} reason="${reason}"`);
|
|
165923
166159
|
})();
|
|
166160
|
+
return nextCount;
|
|
165924
166161
|
}
|
|
165925
166162
|
function clearHistorianFailureState(db, sessionId) {
|
|
165926
166163
|
db.transaction(() => {
|
|
@@ -165989,10 +166226,39 @@ function getStrippedPlaceholderIds(db, sessionId) {
|
|
|
165989
166226
|
} catch {}
|
|
165990
166227
|
return new Set;
|
|
165991
166228
|
}
|
|
165992
|
-
function
|
|
166229
|
+
function applyStrippedPlaceholderDelta(db, sessionId, delta) {
|
|
166230
|
+
const add = delta.add ? [...delta.add] : [];
|
|
166231
|
+
const remove = delta.remove ? [...delta.remove] : [];
|
|
166232
|
+
if (add.length === 0 && remove.length === 0)
|
|
166233
|
+
return true;
|
|
165993
166234
|
ensureSessionMetaRow(db, sessionId);
|
|
165994
|
-
|
|
165995
|
-
|
|
166235
|
+
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
166236
|
+
const row = db.prepare("SELECT stripped_placeholder_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
166237
|
+
const rawStored = row ? row.stripped_placeholder_ids ?? null : null;
|
|
166238
|
+
const current = new Set(parseStrippedBlob(rawStored));
|
|
166239
|
+
for (const id of add)
|
|
166240
|
+
current.add(id);
|
|
166241
|
+
for (const id of remove)
|
|
166242
|
+
current.delete(id);
|
|
166243
|
+
const nextBlob = current.size > 0 ? JSON.stringify([...current]) : "";
|
|
166244
|
+
if (nextBlob === (rawStored ?? ""))
|
|
166245
|
+
return true;
|
|
166246
|
+
const result = db.prepare("UPDATE session_meta SET stripped_placeholder_ids = ? WHERE session_id = ? AND stripped_placeholder_ids IS ?").run(nextBlob, sessionId, rawStored);
|
|
166247
|
+
if (result.changes > 0)
|
|
166248
|
+
return true;
|
|
166249
|
+
}
|
|
166250
|
+
sessionLog(sessionId, `stripped_placeholder_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
|
|
166251
|
+
return false;
|
|
166252
|
+
}
|
|
166253
|
+
function parseStrippedBlob(raw) {
|
|
166254
|
+
if (!raw || raw.length === 0)
|
|
166255
|
+
return [];
|
|
166256
|
+
try {
|
|
166257
|
+
const parsed = JSON.parse(raw);
|
|
166258
|
+
if (Array.isArray(parsed))
|
|
166259
|
+
return parsed.filter((v) => typeof v === "string");
|
|
166260
|
+
} catch {}
|
|
166261
|
+
return [];
|
|
165996
166262
|
}
|
|
165997
166263
|
function isPendingCompactionMarker(value) {
|
|
165998
166264
|
return typeof value === "object" && value !== null && typeof value.ordinal === "number" && typeof value.endMessageId === "string" && typeof value.publishedAt === "number";
|
|
@@ -166897,7 +167163,6 @@ function createCtxMemoryTool(deps) {
|
|
|
166897
167163
|
sourceType: dreamerAllowed ? "dreamer" : "agent"
|
|
166898
167164
|
});
|
|
166899
167165
|
queueEmbedding({ deps, projectIdentity, memoryId: memory2.id, content });
|
|
166900
|
-
invalidateAllMemoryBlockCaches(deps.db);
|
|
166901
167166
|
return ok2(`Saved memory [ID: ${memory2.id}] in ${rawCategory}.`);
|
|
166902
167167
|
}
|
|
166903
167168
|
if (params.action === "delete") {
|
|
@@ -166905,7 +167170,7 @@ function createCtxMemoryTool(deps) {
|
|
|
166905
167170
|
return err2("Error: 'id' is required when action is 'delete'.");
|
|
166906
167171
|
}
|
|
166907
167172
|
const memory2 = getMemoryById(deps.db, params.id);
|
|
166908
|
-
if (!memory2 || memory2.projectPath
|
|
167173
|
+
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
166909
167174
|
return err2(`Error: Memory with ID ${params.id} was not found.`);
|
|
166910
167175
|
}
|
|
166911
167176
|
deps.db.transaction(() => {
|
|
@@ -166934,7 +167199,7 @@ function createCtxMemoryTool(deps) {
|
|
|
166934
167199
|
return err2("Error: 'content' is required when action is 'update'.");
|
|
166935
167200
|
}
|
|
166936
167201
|
const memory2 = getMemoryById(deps.db, params.id);
|
|
166937
|
-
if (!memory2 || memory2.projectPath
|
|
167202
|
+
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
166938
167203
|
return err2(`Error: Memory with ID ${params.id} was not found.`);
|
|
166939
167204
|
}
|
|
166940
167205
|
const normalizedHash = computeNormalizedHash(content);
|
|
@@ -166968,9 +167233,6 @@ function createCtxMemoryTool(deps) {
|
|
|
166968
167233
|
if (sourceMemories.length !== ids.length) {
|
|
166969
167234
|
return err2("Error: One or more source memories were not found.");
|
|
166970
167235
|
}
|
|
166971
|
-
if (sourceMemories.some((memory2) => memory2.projectPath !== projectIdentity)) {
|
|
166972
|
-
return err2("Error: All memories to merge must belong to the current project.");
|
|
166973
|
-
}
|
|
166974
167236
|
const requestedCategory = params.category?.trim();
|
|
166975
167237
|
if (requestedCategory && !isMemoryCategory2(requestedCategory)) {
|
|
166976
167238
|
return err2(`Error: Unknown memory category '${requestedCategory}'. Valid: ${CATEGORY_PRIORITY.join(", ")}`);
|
|
@@ -167029,7 +167291,7 @@ function createCtxMemoryTool(deps) {
|
|
|
167029
167291
|
}
|
|
167030
167292
|
supersededMemory(deps.db, memory2.id, canonicalMemory.id);
|
|
167031
167293
|
queueMemoryMutation(deps.db, {
|
|
167032
|
-
projectPath: memory2.projectPath,
|
|
167294
|
+
projectPath: normalizeStoredProjectPath(memory2.projectPath),
|
|
167033
167295
|
mutationType: "superseded",
|
|
167034
167296
|
targetMemoryId: memory2.id,
|
|
167035
167297
|
supersededById: canonicalMemory.id
|
|
@@ -167037,7 +167299,7 @@ function createCtxMemoryTool(deps) {
|
|
|
167037
167299
|
}
|
|
167038
167300
|
if (canonicalExisting && canonicalContentChanged) {
|
|
167039
167301
|
queueMemoryMutation(deps.db, {
|
|
167040
|
-
projectPath: canonicalMemory.projectPath,
|
|
167302
|
+
projectPath: normalizeStoredProjectPath(canonicalMemory.projectPath),
|
|
167041
167303
|
mutationType: "update",
|
|
167042
167304
|
targetMemoryId: canonicalMemory.id,
|
|
167043
167305
|
category,
|
|
@@ -167059,7 +167321,7 @@ function createCtxMemoryTool(deps) {
|
|
|
167059
167321
|
return err2("Error: 'id' is required when action is 'archive'.");
|
|
167060
167322
|
}
|
|
167061
167323
|
const memory2 = getMemoryById(deps.db, params.id);
|
|
167062
|
-
if (!memory2 || memory2.projectPath
|
|
167324
|
+
if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
|
|
167063
167325
|
return err2(`Error: Memory with ID ${params.id} was not found.`);
|
|
167064
167326
|
}
|
|
167065
167327
|
deps.db.transaction(() => {
|
|
@@ -167321,7 +167583,7 @@ ${smartNotes.map(formatNoteLine).join(`
|
|
|
167321
167583
|
// ../plugin/src/features/magic-context/range-parser.ts
|
|
167322
167584
|
function parseRangeString(input) {
|
|
167323
167585
|
const maxRangeElements = 1000;
|
|
167324
|
-
const trimmed = input.trim();
|
|
167586
|
+
const trimmed = input.replace(/§/g, "").trim();
|
|
167325
167587
|
if (trimmed === "") {
|
|
167326
167588
|
throw new Error("Range string must not be empty");
|
|
167327
167589
|
}
|
|
@@ -168499,6 +168761,9 @@ function escapeXmlAttr2(s) {
|
|
|
168499
168761
|
function escapeXmlContent2(s) {
|
|
168500
168762
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
168501
168763
|
}
|
|
168764
|
+
function isTieredRow(c) {
|
|
168765
|
+
return typeof c.p1 === "string" && c.p1.length > 0;
|
|
168766
|
+
}
|
|
168502
168767
|
function tierBody(c, tier2) {
|
|
168503
168768
|
const tiers = [c.p1, c.p2, c.p3, c.p4];
|
|
168504
168769
|
const requested = tiers[tier2 - 1];
|
|
@@ -168528,12 +168793,13 @@ function renderOneCompartment(c, tier2) {
|
|
|
168528
168793
|
const baseAttrs = `start="${c.startMessage}" end="${c.endMessage}" title="${escapeXmlAttr2(c.title)}"`;
|
|
168529
168794
|
if (tier2 >= 5)
|
|
168530
168795
|
return "";
|
|
168531
|
-
if (c.legacy === 1) {
|
|
168532
|
-
|
|
168796
|
+
if (c.legacy === 1 || !isTieredRow(c)) {
|
|
168797
|
+
const flat = (c.content ?? "").trim();
|
|
168798
|
+
if (tier2 >= 4 || flat.length === 0)
|
|
168533
168799
|
return `<compartment ${baseAttrs} />`;
|
|
168534
168800
|
return [
|
|
168535
168801
|
`<compartment ${baseAttrs}>`,
|
|
168536
|
-
escapeXmlContent2(legacyBodyForTier(
|
|
168802
|
+
escapeXmlContent2(legacyBodyForTier(flat, tier2)),
|
|
168537
168803
|
"</compartment>"
|
|
168538
168804
|
].join(`
|
|
168539
168805
|
`);
|
|
@@ -169080,6 +169346,7 @@ function createCtxSearchTool(deps) {
|
|
|
169080
169346
|
const embeddingEnabled = snapshot ? snapshot.enabled || snapshot.gitCommitEnabled : deps.embeddingEnabled;
|
|
169081
169347
|
const gitCommitsEnabled = snapshot?.gitCommitEnabled ?? deps.gitCommitsEnabled ?? false;
|
|
169082
169348
|
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
169349
|
+
const messageOrdinalCutoff = lastCompartmentEnd >= 0 ? lastCompartmentEnd : 0;
|
|
169083
169350
|
const visibleMemoryIds = getVisibleMemoryIds(deps.db, sessionId);
|
|
169084
169351
|
const results = await unifiedSearch(deps.db, sessionId, projectIdentity, query, {
|
|
169085
169352
|
limit: normalizeLimit3(params.limit),
|
|
@@ -169090,7 +169357,7 @@ function createCtxSearchTool(deps) {
|
|
|
169090
169357
|
return result?.vector ?? null;
|
|
169091
169358
|
},
|
|
169092
169359
|
isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
|
|
169093
|
-
maxMessageOrdinal:
|
|
169360
|
+
maxMessageOrdinal: messageOrdinalCutoff,
|
|
169094
169361
|
gitCommitsEnabled,
|
|
169095
169362
|
sources: params.sources,
|
|
169096
169363
|
visibleMemoryIds,
|