agentcache 0.5.0-beta.1 → 0.5.0-beta.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/README.md +6 -4
- package/dist/{chunk-ECMT4ANK.js → chunk-YKG6CDGT.js} +164 -71
- package/dist/{chunk-4T3I3ACZ.js → chunk-YY7QXBG5.js} +23 -5
- package/dist/cli.js +3 -3
- package/dist/mcp.js +2 -2
- package/dist/{setup-CXZFERQE.js → setup-7JJPW3VG.js} +1 -1
- package/docs/compatibility.md +9 -3
- package/docs/demo-script.md +1 -1
- package/docs/launch-copy.md +8 -10
- package/docs/privacy.md +1 -1
- package/docs/troubleshooting.md +6 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **Pick a coding session and continue it in another agent.**
|
|
4
4
|
|
|
5
|
-
**AgentCache 0.5.0-beta.
|
|
5
|
+
**AgentCache 0.5.0-beta.2 is a same-machine public beta.** It keeps a local,
|
|
6
6
|
portable timeline for an explicitly selected coding session, then hands a
|
|
7
7
|
bounded checkpoint to another registered agent through MCP. There is no
|
|
8
8
|
Markdown handoff file to maintain and no silent choice of “latest” session.
|
|
@@ -39,14 +39,16 @@ match.
|
|
|
39
39
|
1. Install the pinned beta and run the explicit setup step.
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
npm install -g agentcache@0.5.0-beta.
|
|
42
|
+
npm install -g agentcache@0.5.0-beta.2
|
|
43
43
|
agentcache setup
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
Installation has no postinstall configuration hook. Setup is explicit:
|
|
47
47
|
`agentcache setup` detects installed clients and adds a client-bound MCP
|
|
48
|
-
entry
|
|
49
|
-
|
|
48
|
+
entry using the exact active Node executable and installed AgentCache CLI.
|
|
49
|
+
This prevents an IDE's bundled Node from loading a native dependency built
|
|
50
|
+
for another Node version. Rerun setup after changing Node versions, global
|
|
51
|
+
npm prefixes, or AgentCache installations, then restart or reload clients.
|
|
50
52
|
|
|
51
53
|
2. Check what AgentCache actually detected and what each adapter can do.
|
|
52
54
|
|
|
@@ -18,7 +18,7 @@ import { dirname as dirname2, isAbsolute, join as join2, resolve as resolve2 } f
|
|
|
18
18
|
import { homedir } from "os";
|
|
19
19
|
import { TextDecoder } from "util";
|
|
20
20
|
import { parse as parseToml } from "smol-toml";
|
|
21
|
-
import { isMap, parseDocument } from "yaml";
|
|
21
|
+
import { isMap, isScalar, isSeq, parseDocument } from "yaml";
|
|
22
22
|
|
|
23
23
|
// src/utils/atomic-file.ts
|
|
24
24
|
import {
|
|
@@ -626,15 +626,22 @@ function isAgentCacheExecutable(value) {
|
|
|
626
626
|
executableBasename(value) ?? ""
|
|
627
627
|
);
|
|
628
628
|
}
|
|
629
|
+
function isPortableAbsolutePath(value) {
|
|
630
|
+
return isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || /^\\\\/.test(value);
|
|
631
|
+
}
|
|
632
|
+
function isRecognizedAgentCacheScript(value) {
|
|
633
|
+
if (typeof value !== "string" || !isPortableAbsolutePath(value)) return false;
|
|
634
|
+
if (isAgentCacheExecutable(value)) return true;
|
|
635
|
+
const segments = value.toLowerCase().split(/[/\\]+/).filter(Boolean);
|
|
636
|
+
return segments.length >= 3 && segments.at(-3) === "agentcache" && segments.at(-2) === "dist" && segments.at(-1) === "cli.js";
|
|
637
|
+
}
|
|
629
638
|
function isAgentCacheNodeWrapper(value, ide) {
|
|
630
|
-
if (!isJsonObject(value) || !["node", "node.exe"].includes(executableBasename(value.command) ?? "")) {
|
|
639
|
+
if (!isJsonObject(value) || typeof value.command !== "string" || !isPortableAbsolutePath(value.command) || !["node", "node.exe"].includes(executableBasename(value.command) ?? "")) {
|
|
631
640
|
return false;
|
|
632
641
|
}
|
|
633
642
|
if (!Array.isArray(value.args) || value.args.length < 2) return false;
|
|
634
643
|
const script = value.args[0];
|
|
635
|
-
|
|
636
|
-
const isAgentCacheScript = scriptName === "agentcache" || scriptName === "agentcache.cmd" || scriptName === "agentcache.exe" || scriptName === "cli.js" && typeof script === "string" && /agentcache/i.test(script);
|
|
637
|
-
if (!isAgentCacheScript) return false;
|
|
644
|
+
if (!isRecognizedAgentCacheScript(script)) return false;
|
|
638
645
|
return argsEqual(value.args.slice(1), ["serve"]) || argsEqual(value.args.slice(1), boundServeArgs(ide));
|
|
639
646
|
}
|
|
640
647
|
function registrationOwnership(config, ide, desired) {
|
|
@@ -649,7 +656,7 @@ function registrationOwnership(config, ide, desired) {
|
|
|
649
656
|
if (isJsonObject(existing) && isAgentCacheExecutable(existing.command) && (argsEqual(existing.args, ["serve"]) || argsEqual(existing.args, boundServeArgs(ide)))) {
|
|
650
657
|
return "owned";
|
|
651
658
|
}
|
|
652
|
-
if (
|
|
659
|
+
if (isAgentCacheNodeWrapper(existing, ide)) {
|
|
653
660
|
return "owned";
|
|
654
661
|
}
|
|
655
662
|
return "ambiguous";
|
|
@@ -845,7 +852,8 @@ function unregisterMcpServer(ide) {
|
|
|
845
852
|
}
|
|
846
853
|
function isMcpServerRegistered(ide) {
|
|
847
854
|
if (ide.mcpConfigFormat === "claude-settings") {
|
|
848
|
-
|
|
855
|
+
const desired = claudeServerConfig(ide);
|
|
856
|
+
return desired ? isJsonMcpServerRegistered(ide, desired) : false;
|
|
849
857
|
}
|
|
850
858
|
if (ide.mcpConfigFormat === "mcp-json" || ide.mcpConfigFormat === "continue-dir") {
|
|
851
859
|
const desired = serverConfig(ide);
|
|
@@ -859,8 +867,9 @@ function inspectMcpServerPresence(ide) {
|
|
|
859
867
|
const obsoletePresence = inspectObsoleteJsonRegistrationPresence(ide);
|
|
860
868
|
let currentPresence;
|
|
861
869
|
if (ide.mcpConfigFormat === "claude-settings") {
|
|
870
|
+
const desired = claudeServerConfig(ide);
|
|
862
871
|
currentPresence = combineRegistrationPresence(
|
|
863
|
-
inspectJsonMcpServerPresence(ide,
|
|
872
|
+
desired ? inspectJsonMcpServerPresence(ide, desired) : "unknown",
|
|
864
873
|
inspectClaudeSettingsPresence(claudeSettingsPath(ide))
|
|
865
874
|
);
|
|
866
875
|
} else if (ide.mcpConfigFormat === "mcp-json" || ide.mcpConfigFormat === "continue-dir") {
|
|
@@ -991,6 +1000,7 @@ function registerClaudeCode(ide) {
|
|
|
991
1000
|
const config = configFile.config;
|
|
992
1001
|
const settings = settingsFile.config;
|
|
993
1002
|
const desired = claudeServerConfig(ide);
|
|
1003
|
+
if (!desired) return skipped("trusted AgentCache CLI entrypoint unavailable");
|
|
994
1004
|
if (registrationOwnership(config, ide, desired) === "ambiguous") {
|
|
995
1005
|
return skipped("ambiguous AgentCache registration preserved");
|
|
996
1006
|
}
|
|
@@ -1045,7 +1055,9 @@ function unregisterClaudeCode(ide) {
|
|
|
1045
1055
|
if (!configFile || !settingsFile || !validServerMap(configFile.config.mcpServers)) return false;
|
|
1046
1056
|
const config = configFile.config;
|
|
1047
1057
|
const settings = settingsFile.config;
|
|
1048
|
-
const
|
|
1058
|
+
const desired = claudeServerConfig(ide);
|
|
1059
|
+
if (!desired) return false;
|
|
1060
|
+
const ownership = registrationOwnership(config, ide, desired);
|
|
1049
1061
|
if (ownership === "ambiguous") return false;
|
|
1050
1062
|
if (legacyClaudeHookOwnership(settings) === "ambiguous") return false;
|
|
1051
1063
|
const legacyOwnership = legacyLoopRegistrationOwnership(config);
|
|
@@ -1073,24 +1085,26 @@ function unregisterClaudeCode(ide) {
|
|
|
1073
1085
|
function boundServeArgs(ide) {
|
|
1074
1086
|
return ["serve", "--adapter", ide.adapterId];
|
|
1075
1087
|
}
|
|
1088
|
+
function pinnedServeCommand(ide) {
|
|
1089
|
+
if (!registrationCliEntrypoint) return void 0;
|
|
1090
|
+
return {
|
|
1091
|
+
command: process.execPath,
|
|
1092
|
+
args: [registrationCliEntrypoint, ...boundServeArgs(ide)]
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1076
1095
|
function claudeServerConfig(ide) {
|
|
1096
|
+
const pinned = pinnedServeCommand(ide);
|
|
1097
|
+
if (!pinned) return void 0;
|
|
1077
1098
|
return {
|
|
1078
1099
|
type: "stdio",
|
|
1079
|
-
|
|
1080
|
-
args: boundServeArgs(ide),
|
|
1100
|
+
...pinned,
|
|
1081
1101
|
env: {}
|
|
1082
1102
|
};
|
|
1083
1103
|
}
|
|
1084
1104
|
function serverConfig(ide) {
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
command: process.execPath,
|
|
1089
|
-
args: [registrationCliEntrypoint, ...boundServeArgs(ide)],
|
|
1090
|
-
disabled: false
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
return { command: "agentcache", args: boundServeArgs(ide) };
|
|
1105
|
+
const pinned = pinnedServeCommand(ide);
|
|
1106
|
+
if (!pinned) return void 0;
|
|
1107
|
+
return isVscodeExtensionIde(ide) ? { ...pinned, disabled: false } : pinned;
|
|
1094
1108
|
}
|
|
1095
1109
|
function isJsonMcpServerRegistered(ide, desired) {
|
|
1096
1110
|
const config = parseJsonFileForInspection(ide.mcpConfigPath);
|
|
@@ -1225,22 +1239,28 @@ function restoreGooseTarget(target, published, original) {
|
|
|
1225
1239
|
return !restore.conflict && !restore.unsupported && restore.changed;
|
|
1226
1240
|
}
|
|
1227
1241
|
function gooseServerConfig(ide) {
|
|
1242
|
+
const pinned = pinnedServeCommand(ide);
|
|
1243
|
+
if (!pinned) return void 0;
|
|
1228
1244
|
return {
|
|
1229
1245
|
enabled: true,
|
|
1230
1246
|
name: GOOSE_EXTENSION_KEY,
|
|
1231
1247
|
description: "AgentCache MCP server",
|
|
1232
1248
|
type: "stdio",
|
|
1233
|
-
cmd:
|
|
1234
|
-
args:
|
|
1249
|
+
cmd: pinned.command,
|
|
1250
|
+
args: pinned.args
|
|
1235
1251
|
};
|
|
1236
1252
|
}
|
|
1237
|
-
function gooseCoreMatches(value,
|
|
1238
|
-
return isJsonObject(value) && value.name === GOOSE_EXTENSION_KEY && value.type === "stdio" && value.cmd ===
|
|
1253
|
+
function gooseCoreMatches(value, expected) {
|
|
1254
|
+
return isJsonObject(value) && value.name === GOOSE_EXTENSION_KEY && value.type === "stdio" && value.cmd === expected.cmd && argsEqual(value.args, expected.args);
|
|
1239
1255
|
}
|
|
1240
|
-
function gooseOwnership(value, ide) {
|
|
1256
|
+
function gooseOwnership(value, ide, desired) {
|
|
1241
1257
|
if (value === void 0) return "absent";
|
|
1242
|
-
if (gooseCoreMatches(value,
|
|
1243
|
-
if (gooseCoreMatches(value,
|
|
1258
|
+
if (desired && gooseCoreMatches(value, desired)) return "owned";
|
|
1259
|
+
if (gooseCoreMatches(value, { cmd: "agentcache", args: boundServeArgs(ide) })) return "owned";
|
|
1260
|
+
if (gooseCoreMatches(value, { cmd: "agentcache", args: ["serve"] })) return "owned";
|
|
1261
|
+
if (isJsonObject(value) && value.name === GOOSE_EXTENSION_KEY && value.type === "stdio" && isAgentCacheNodeWrapper({ command: value.cmd, args: value.args }, ide)) {
|
|
1262
|
+
return "owned";
|
|
1263
|
+
}
|
|
1244
1264
|
return "ambiguous";
|
|
1245
1265
|
}
|
|
1246
1266
|
function parseGooseDocument(content) {
|
|
@@ -1289,11 +1309,12 @@ function registerGoose(ide) {
|
|
|
1289
1309
|
} catch {
|
|
1290
1310
|
return skipped("malformed or unsupported Goose YAML config preserved");
|
|
1291
1311
|
}
|
|
1292
|
-
const
|
|
1312
|
+
const desired = gooseServerConfig(ide);
|
|
1313
|
+
if (!desired) return skipped("trusted AgentCache CLI entrypoint unavailable");
|
|
1314
|
+
const ownership = gooseOwnership(existing, ide, desired);
|
|
1293
1315
|
if (ownership === "ambiguous" || existingNode !== void 0 && !isMap(existingNode)) {
|
|
1294
1316
|
return skipped("ambiguous AgentCache registration preserved");
|
|
1295
1317
|
}
|
|
1296
|
-
const desired = gooseServerConfig(ide);
|
|
1297
1318
|
if (ownership === "owned" && Object.entries(desired).every(([key, value]) => {
|
|
1298
1319
|
const existingValue = existing[key];
|
|
1299
1320
|
return Array.isArray(value) ? argsEqual(existingValue, value) : existingValue === value;
|
|
@@ -1320,7 +1341,29 @@ function registerGoose(ide) {
|
|
|
1320
1341
|
for (const [key, value] of Object.entries(desired)) {
|
|
1321
1342
|
const existingValue = existing[key];
|
|
1322
1343
|
const matches = Array.isArray(value) ? argsEqual(existingValue, value) : existingValue === value;
|
|
1323
|
-
if (!matches)
|
|
1344
|
+
if (!matches) {
|
|
1345
|
+
const currentNode = existingNode.get(key, true);
|
|
1346
|
+
if (isScalar(currentNode) && !Array.isArray(value)) currentNode.value = value;
|
|
1347
|
+
else {
|
|
1348
|
+
const replacement = document.createNode(value);
|
|
1349
|
+
if (isSeq(currentNode) && isSeq(replacement)) {
|
|
1350
|
+
replacement.comment = currentNode.comment;
|
|
1351
|
+
replacement.commentBefore = currentNode.commentBefore;
|
|
1352
|
+
replacement.spaceBefore = currentNode.spaceBefore;
|
|
1353
|
+
for (const replacementItem of replacement.items) {
|
|
1354
|
+
if (!isScalar(replacementItem)) continue;
|
|
1355
|
+
const previousItem = currentNode.items.find(
|
|
1356
|
+
(item) => isScalar(item) && item.value === replacementItem.value
|
|
1357
|
+
);
|
|
1358
|
+
if (!isScalar(previousItem)) continue;
|
|
1359
|
+
replacementItem.comment = previousItem.comment;
|
|
1360
|
+
replacementItem.commentBefore = previousItem.commentBefore;
|
|
1361
|
+
replacementItem.spaceBefore = previousItem.spaceBefore;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
existingNode.set(key, replacement);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1324
1367
|
}
|
|
1325
1368
|
} else {
|
|
1326
1369
|
const desiredNode = createGooseMap(document, desired);
|
|
@@ -1364,7 +1407,7 @@ function unregisterGoose(ide) {
|
|
|
1364
1407
|
} catch {
|
|
1365
1408
|
return false;
|
|
1366
1409
|
}
|
|
1367
|
-
if (gooseOwnership(existing, ide) !== "owned") return false;
|
|
1410
|
+
if (gooseOwnership(existing, ide, gooseServerConfig(ide)) !== "owned") return false;
|
|
1368
1411
|
extensions.delete(GOOSE_EXTENSION_KEY);
|
|
1369
1412
|
if (!gooseTargetStillBound(target, file.expectation)) return false;
|
|
1370
1413
|
const next = String(document);
|
|
@@ -1389,7 +1432,8 @@ function isGooseRegistered(ide) {
|
|
|
1389
1432
|
const entry = extensions.get(GOOSE_EXTENSION_KEY, true);
|
|
1390
1433
|
if (!entry || !isMap(entry)) return false;
|
|
1391
1434
|
const value = entry.toJSON();
|
|
1392
|
-
|
|
1435
|
+
const desired = gooseServerConfig(ide);
|
|
1436
|
+
return !!desired && isJsonObject(value) && value.enabled === true && gooseCoreMatches(value, desired);
|
|
1393
1437
|
} catch {
|
|
1394
1438
|
return false;
|
|
1395
1439
|
}
|
|
@@ -1409,21 +1453,25 @@ function inspectGoosePresence(ide) {
|
|
|
1409
1453
|
const entry = extensions.get(GOOSE_EXTENSION_KEY, true);
|
|
1410
1454
|
if (entry === void 0) return "absent";
|
|
1411
1455
|
if (!isMap(entry)) return "unknown";
|
|
1412
|
-
return gooseOwnership(entry.toJSON(), ide) === "owned" ? "present" : "unknown";
|
|
1456
|
+
return gooseOwnership(entry.toJSON(), ide, gooseServerConfig(ide)) === "owned" ? "present" : "unknown";
|
|
1413
1457
|
} catch {
|
|
1414
1458
|
return "unknown";
|
|
1415
1459
|
}
|
|
1416
1460
|
}
|
|
1417
|
-
function
|
|
1461
|
+
function formatCodexBlock(command, args) {
|
|
1418
1462
|
return [
|
|
1419
1463
|
CODEX_MARKER_START,
|
|
1420
1464
|
"[mcp_servers.agentcache]",
|
|
1421
|
-
|
|
1422
|
-
|
|
1465
|
+
`command = ${JSON.stringify(command)}`,
|
|
1466
|
+
`args = [${args.map((value) => JSON.stringify(value)).join(", ")}]`,
|
|
1423
1467
|
CODEX_MARKER_END,
|
|
1424
1468
|
""
|
|
1425
1469
|
].join("\n");
|
|
1426
1470
|
}
|
|
1471
|
+
function codexBlock(ide) {
|
|
1472
|
+
const pinned = pinnedServeCommand(ide);
|
|
1473
|
+
return pinned ? formatCodexBlock(pinned.command, pinned.args) : void 0;
|
|
1474
|
+
}
|
|
1427
1475
|
function maskTomlStrings(content) {
|
|
1428
1476
|
let state = "normal";
|
|
1429
1477
|
let masked = "";
|
|
@@ -1500,6 +1548,42 @@ function maskTomlStrings(content) {
|
|
|
1500
1548
|
}
|
|
1501
1549
|
return state === "normal" || state === "comment" ? masked : void 0;
|
|
1502
1550
|
}
|
|
1551
|
+
var TOML_HEADER_SENTINEL = "__agentcache_header_sentinel_4f20c6d1__";
|
|
1552
|
+
function tomlHeaderSentinelPaths(value) {
|
|
1553
|
+
if (!value || typeof value !== "object") return [];
|
|
1554
|
+
const paths = [];
|
|
1555
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1556
|
+
if (key === TOML_HEADER_SENTINEL && child === true) {
|
|
1557
|
+
paths.push([]);
|
|
1558
|
+
continue;
|
|
1559
|
+
}
|
|
1560
|
+
const candidates = Array.isArray(child) ? child : [child];
|
|
1561
|
+
for (const candidate of candidates) {
|
|
1562
|
+
for (const nestedPath of tomlHeaderSentinelPaths(candidate)) {
|
|
1563
|
+
paths.push([key, ...nestedPath]);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
return paths;
|
|
1568
|
+
}
|
|
1569
|
+
function parseTomlHeader(source) {
|
|
1570
|
+
try {
|
|
1571
|
+
const parsed = parseToml(`${source}
|
|
1572
|
+
${TOML_HEADER_SENTINEL} = true
|
|
1573
|
+
`);
|
|
1574
|
+
const paths = tomlHeaderSentinelPaths(parsed);
|
|
1575
|
+
if (paths.length !== 1 || paths[0].length === 0) return void 0;
|
|
1576
|
+
return { path: paths[0], array: source.startsWith("[[") };
|
|
1577
|
+
} catch {
|
|
1578
|
+
return void 0;
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
function isOwnedCodexHeader(header) {
|
|
1582
|
+
return header.path.length >= 2 && header.path[0] === "mcp_servers" && header.path[1] === "agentcache";
|
|
1583
|
+
}
|
|
1584
|
+
function isExactCodexHeader(header) {
|
|
1585
|
+
return !header.array && header.path.length === 2 && isOwnedCodexHeader(header);
|
|
1586
|
+
}
|
|
1503
1587
|
function scanToml(content) {
|
|
1504
1588
|
const masked = maskTomlStrings(content);
|
|
1505
1589
|
if (masked === void 0) return void 0;
|
|
@@ -1513,6 +1597,7 @@ function scanToml(content) {
|
|
|
1513
1597
|
while (offset < content.length) {
|
|
1514
1598
|
const newline = content.indexOf("\n", offset);
|
|
1515
1599
|
const end = newline < 0 ? content.length : newline + 1;
|
|
1600
|
+
const originalLine = content.slice(offset, end).replace(/\r?\n$/, "");
|
|
1516
1601
|
const maskedLine = masked.slice(offset, end).replace(/\r?\n$/, "");
|
|
1517
1602
|
const trimmed = maskedLine.trim();
|
|
1518
1603
|
const marker = trimmed === CODEX_MARKER_START ? "start" : trimmed === CODEX_MARKER_END ? "end" : void 0;
|
|
@@ -1523,11 +1608,10 @@ function scanToml(content) {
|
|
|
1523
1608
|
if (marker === "start") markerStarts.push(line);
|
|
1524
1609
|
if (marker === "end") markerEnds.push(line);
|
|
1525
1610
|
if (code.startsWith("[") && squareDepth === 0 && inlineTableDepth === 0) {
|
|
1526
|
-
const
|
|
1527
|
-
const
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
headers.push({ name, start: offset, bodyStart: end, end: content.length });
|
|
1611
|
+
const source = (commentAt < 0 ? originalLine : originalLine.slice(0, commentAt)).trim();
|
|
1612
|
+
const header = parseTomlHeader(source);
|
|
1613
|
+
if (!header) return void 0;
|
|
1614
|
+
headers.push({ ...header, start: offset, bodyStart: end, end: content.length });
|
|
1531
1615
|
} else if (code) {
|
|
1532
1616
|
const startsAtTopLevel = squareDepth === 0 && inlineTableDepth === 0;
|
|
1533
1617
|
if (startsAtTopLevel && !code.includes("=")) return void 0;
|
|
@@ -1557,68 +1641,69 @@ function scanToml(content) {
|
|
|
1557
1641
|
markerEnd: markerEnds[0]
|
|
1558
1642
|
};
|
|
1559
1643
|
}
|
|
1560
|
-
function managedCodexRange(content, scan, ide) {
|
|
1644
|
+
function managedCodexRange(content, scan, ide, desiredBlock) {
|
|
1561
1645
|
if (!scan.markerStart && !scan.markerEnd) return void 0;
|
|
1562
1646
|
if (!scan.markerStart || !scan.markerEnd) return null;
|
|
1563
1647
|
const range = { start: scan.markerStart.start, end: scan.markerEnd.end };
|
|
1564
1648
|
const managedContent = content.slice(range.start, range.end);
|
|
1565
|
-
const current = managedContent ===
|
|
1566
|
-
|
|
1567
|
-
const
|
|
1568
|
-
(header) => header.
|
|
1649
|
+
const current = managedContent === desiredBlock;
|
|
1650
|
+
const ownedHeaders = scan.headers.filter(isOwnedCodexHeader);
|
|
1651
|
+
const headersInside = scan.headers.filter(
|
|
1652
|
+
(header) => header.start > scan.markerStart.start && header.start < scan.markerEnd.start
|
|
1569
1653
|
);
|
|
1570
|
-
if (ownedHeaders.length !== 1 ||
|
|
1654
|
+
if (ownedHeaders.length !== 1 || headersInside.length !== 1 || headersInside[0] !== ownedHeaders[0] || !isExactCodexHeader(ownedHeaders[0]) || ownedHeaders[0].start < range.start || ownedHeaders[0].start >= range.end) {
|
|
1571
1655
|
return null;
|
|
1572
1656
|
}
|
|
1657
|
+
const leadingTableContent = scan.lines.some(
|
|
1658
|
+
(line) => line.start >= scan.markerStart.end && line.start < ownedHeaders[0].start && line.code.length > 0
|
|
1659
|
+
);
|
|
1660
|
+
if (leadingTableContent) return null;
|
|
1573
1661
|
const trailingTableContent = scan.lines.some(
|
|
1574
1662
|
(line) => line.start >= scan.markerEnd.end && line.start < ownedHeaders[0].end && line.code.length > 0
|
|
1575
1663
|
);
|
|
1576
1664
|
if (trailingTableContent) return null;
|
|
1665
|
+
if (!legacyCodexRange(content, scan, ide, true)) return null;
|
|
1577
1666
|
return { ...range, current };
|
|
1578
1667
|
}
|
|
1579
|
-
function legacyCodexRange(content, scan, ide) {
|
|
1580
|
-
const ownedHeaders = scan.headers.filter(
|
|
1581
|
-
(header2) => header2.name === "mcp_servers.agentcache" || header2.name.startsWith("mcp_servers.agentcache.")
|
|
1582
|
-
);
|
|
1668
|
+
function legacyCodexRange(content, scan, ide, allowManagedNodeWrapper = false) {
|
|
1669
|
+
const ownedHeaders = scan.headers.filter(isOwnedCodexHeader);
|
|
1583
1670
|
if (ownedHeaders.length === 0) return void 0;
|
|
1584
|
-
if (ownedHeaders.length !== 1 || ownedHeaders[0]
|
|
1671
|
+
if (ownedHeaders.length !== 1 || !isExactCodexHeader(ownedHeaders[0])) return null;
|
|
1585
1672
|
const header = ownedHeaders[0];
|
|
1586
1673
|
const bodyLines = scan.lines.filter(
|
|
1587
1674
|
(line) => line.start >= header.bodyStart && line.start < header.end && line.code.length > 0
|
|
1588
1675
|
);
|
|
1589
1676
|
let hasCommand = false;
|
|
1590
1677
|
let hasArgs = false;
|
|
1591
|
-
let hasBoundArgs = false;
|
|
1592
1678
|
let hasLegacyApproval = false;
|
|
1593
|
-
let
|
|
1679
|
+
let semanticServer;
|
|
1594
1680
|
try {
|
|
1595
1681
|
const parsed = parseToml(content);
|
|
1596
|
-
|
|
1682
|
+
const table = parsed.mcp_servers?.agentcache;
|
|
1683
|
+
if (!isJsonObject(table)) return null;
|
|
1684
|
+
semanticServer = { command: table.command, args: table.args };
|
|
1597
1685
|
} catch {
|
|
1598
1686
|
return null;
|
|
1599
1687
|
}
|
|
1600
|
-
const escapedAdapterId = ide.adapterId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1601
|
-
const boundArgs = new RegExp(
|
|
1602
|
-
`^args\\s*=\\s*\\[\\s*"serve"\\s*,\\s*"--adapter"\\s*,\\s*"${escapedAdapterId}"\\s*\\]\\s*(?:#.*)?$`
|
|
1603
|
-
);
|
|
1604
1688
|
for (const line of bodyLines) {
|
|
1605
1689
|
const source = content.slice(line.start, line.end).trim();
|
|
1606
1690
|
if (/^command\s*=/.test(source)) {
|
|
1607
|
-
if (hasCommand
|
|
1691
|
+
if (hasCommand) return null;
|
|
1608
1692
|
hasCommand = true;
|
|
1609
|
-
} else if (/^args\s
|
|
1610
|
-
hasArgs
|
|
1611
|
-
} else if (boundArgs.test(source)) {
|
|
1693
|
+
} else if (/^args\s*=/.test(source)) {
|
|
1694
|
+
if (hasArgs) return null;
|
|
1612
1695
|
hasArgs = true;
|
|
1613
|
-
hasBoundArgs = true;
|
|
1614
1696
|
} else if (/^default_tools_approval_mode\s*=\s*"auto"\s*(?:#.*)?$/.test(source)) {
|
|
1615
1697
|
hasLegacyApproval = true;
|
|
1616
1698
|
} else return null;
|
|
1617
1699
|
}
|
|
1618
|
-
|
|
1700
|
+
const desired = pinnedServeCommand(ide);
|
|
1701
|
+
const current = !!desired && serverCoreMatches(semanticServer, desired);
|
|
1702
|
+
const owned = current || isAgentCacheExecutable(semanticServer.command) && (argsEqual(semanticServer.args, ["serve"]) || argsEqual(semanticServer.args, boundServeArgs(ide))) || allowManagedNodeWrapper && isAgentCacheNodeWrapper(semanticServer, ide);
|
|
1703
|
+
return hasCommand && hasArgs && owned ? {
|
|
1619
1704
|
start: header.start,
|
|
1620
1705
|
end: header.end,
|
|
1621
|
-
current:
|
|
1706
|
+
current: current && !hasLegacyApproval
|
|
1622
1707
|
} : null;
|
|
1623
1708
|
}
|
|
1624
1709
|
function removeCodexRange(content, range) {
|
|
@@ -1627,6 +1712,8 @@ function removeCodexRange(content, range) {
|
|
|
1627
1712
|
return content.slice(0, start) + content.slice(range.end);
|
|
1628
1713
|
}
|
|
1629
1714
|
function registerCodex(ide) {
|
|
1715
|
+
const desiredBlock = codexBlock(ide);
|
|
1716
|
+
if (!desiredBlock) return skipped("trusted AgentCache CLI entrypoint unavailable");
|
|
1630
1717
|
const file = readBoundedRegistrationFile(ide.mcpConfigPath, true);
|
|
1631
1718
|
if (!file) return skipped("malformed or ambiguous TOML config preserved");
|
|
1632
1719
|
const original = file.content;
|
|
@@ -1635,14 +1722,14 @@ function registerCodex(ide) {
|
|
|
1635
1722
|
}
|
|
1636
1723
|
const scan = scanToml(original);
|
|
1637
1724
|
if (!scan) return skipped("malformed or ambiguous TOML config preserved");
|
|
1638
|
-
const managed = managedCodexRange(original, scan, ide);
|
|
1725
|
+
const managed = managedCodexRange(original, scan, ide, desiredBlock);
|
|
1639
1726
|
if (managed === null) return skipped("malformed or ambiguous TOML config preserved");
|
|
1640
1727
|
if (managed?.current) {
|
|
1641
1728
|
return atomicWriteExpectationMatches(ide.mcpConfigPath, file.expectation) ? { status: "unchanged" } : skipped("Codex config changed during registration");
|
|
1642
1729
|
}
|
|
1643
1730
|
const legacy = managed ?? legacyCodexRange(original, scan, ide);
|
|
1644
1731
|
if (legacy === null) return skipped("malformed or ambiguous TOML config preserved");
|
|
1645
|
-
const next = legacy ? original.slice(0, legacy.start) +
|
|
1732
|
+
const next = legacy ? original.slice(0, legacy.start) + desiredBlock + original.slice(legacy.end) : `${original}${original.length > 0 ? "\n\n" : ""}${desiredBlock}`;
|
|
1646
1733
|
if (!isValidToml(next)) {
|
|
1647
1734
|
return skipped("generated TOML would be invalid; existing config preserved");
|
|
1648
1735
|
}
|
|
@@ -1652,13 +1739,15 @@ function registerCodex(ide) {
|
|
|
1652
1739
|
);
|
|
1653
1740
|
}
|
|
1654
1741
|
function unregisterCodex(ide) {
|
|
1742
|
+
const desiredBlock = codexBlock(ide);
|
|
1743
|
+
if (!desiredBlock) return false;
|
|
1655
1744
|
const file = readBoundedRegistrationFile(ide.mcpConfigPath);
|
|
1656
1745
|
if (!file) return false;
|
|
1657
1746
|
const original = file.content;
|
|
1658
1747
|
if (!isValidToml(original)) return false;
|
|
1659
1748
|
const scan = scanToml(original);
|
|
1660
1749
|
if (!scan) return false;
|
|
1661
|
-
const managed = managedCodexRange(original, scan, ide);
|
|
1750
|
+
const managed = managedCodexRange(original, scan, ide, desiredBlock);
|
|
1662
1751
|
if (managed === null) return false;
|
|
1663
1752
|
const legacy = managed ? void 0 : legacyCodexRange(original, scan, ide);
|
|
1664
1753
|
if (legacy === null) return false;
|
|
@@ -1671,13 +1760,15 @@ function unregisterCodex(ide) {
|
|
|
1671
1760
|
}
|
|
1672
1761
|
function isCodexRegistered(ide) {
|
|
1673
1762
|
try {
|
|
1763
|
+
const desiredBlock = codexBlock(ide);
|
|
1764
|
+
if (!desiredBlock) return false;
|
|
1674
1765
|
const file = readBoundedRegistrationFile(ide.mcpConfigPath);
|
|
1675
1766
|
if (!file) return false;
|
|
1676
1767
|
const original = file.content;
|
|
1677
1768
|
if (!isValidToml(original)) return false;
|
|
1678
1769
|
const scan = scanToml(original);
|
|
1679
1770
|
if (!scan) return false;
|
|
1680
|
-
const managed = managedCodexRange(original, scan, ide);
|
|
1771
|
+
const managed = managedCodexRange(original, scan, ide, desiredBlock);
|
|
1681
1772
|
if (managed === null) return false;
|
|
1682
1773
|
if (managed) return managed.current;
|
|
1683
1774
|
const recognized = legacyCodexRange(original, scan, ide);
|
|
@@ -1688,6 +1779,8 @@ function isCodexRegistered(ide) {
|
|
|
1688
1779
|
}
|
|
1689
1780
|
function inspectCodexPresence(ide) {
|
|
1690
1781
|
try {
|
|
1782
|
+
const desiredBlock = codexBlock(ide);
|
|
1783
|
+
if (!desiredBlock) return "unknown";
|
|
1691
1784
|
const file = readBoundedRegistrationFile(ide.mcpConfigPath, true);
|
|
1692
1785
|
if (!file) return "unknown";
|
|
1693
1786
|
if (!file.expectation.existed) return "absent";
|
|
@@ -1695,7 +1788,7 @@ function inspectCodexPresence(ide) {
|
|
|
1695
1788
|
if (!isValidToml(original)) return "unknown";
|
|
1696
1789
|
const scan = scanToml(original);
|
|
1697
1790
|
if (!scan) return "unknown";
|
|
1698
|
-
const managed = managedCodexRange(original, scan, ide);
|
|
1791
|
+
const managed = managedCodexRange(original, scan, ide, desiredBlock);
|
|
1699
1792
|
if (managed === null) return "unknown";
|
|
1700
1793
|
if (managed) return "present";
|
|
1701
1794
|
const legacy = legacyCodexRange(original, scan, ide);
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
inspectMcpServerPresence,
|
|
3
3
|
registerMcpServer,
|
|
4
4
|
unregisterMcpServer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-YKG6CDGT.js";
|
|
6
6
|
import {
|
|
7
7
|
detectInstalledIdes
|
|
8
8
|
} from "./chunk-RXGW4Q3G.js";
|
|
@@ -3343,7 +3343,8 @@ import {
|
|
|
3343
3343
|
fstatSync as fstatSync2,
|
|
3344
3344
|
lstatSync as lstatSync2,
|
|
3345
3345
|
mkdirSync,
|
|
3346
|
-
openSync as openSync2
|
|
3346
|
+
openSync as openSync2,
|
|
3347
|
+
unlinkSync
|
|
3347
3348
|
} from "fs";
|
|
3348
3349
|
import { dirname as dirname4, posix as posix2 } from "path";
|
|
3349
3350
|
import Database from "better-sqlite3";
|
|
@@ -3717,7 +3718,8 @@ function prepareSessionDatabasePath(dbPath) {
|
|
|
3717
3718
|
const directory = preparePrivateDirectory(dirname4(dbPath));
|
|
3718
3719
|
let descriptor;
|
|
3719
3720
|
try {
|
|
3720
|
-
|
|
3721
|
+
const openResult = openOrCreateRegularFile(dbPath);
|
|
3722
|
+
descriptor = openResult.descriptor;
|
|
3721
3723
|
const opened = fstatSync2(descriptor);
|
|
3722
3724
|
if (!isSafeDatabaseFile(opened)) {
|
|
3723
3725
|
throw unsafeSessionStorage("Session database path must be a private regular file with one link");
|
|
@@ -3737,6 +3739,17 @@ function prepareSessionDatabasePath(dbPath) {
|
|
|
3737
3739
|
assertPathIdentity(dbPath, opened, "Session database path changed during initialization");
|
|
3738
3740
|
directory.verify();
|
|
3739
3741
|
},
|
|
3742
|
+
removeCreatedFile() {
|
|
3743
|
+
if (closed || !openResult.created) return;
|
|
3744
|
+
try {
|
|
3745
|
+
const currentDescriptor = fstatSync2(descriptor);
|
|
3746
|
+
if (currentDescriptor.size !== 0 || !isSafeDatabaseFile(currentDescriptor) || !sameIdentity(opened, currentDescriptor)) return;
|
|
3747
|
+
assertPathIdentity(dbPath, opened, "Session database path changed during cleanup");
|
|
3748
|
+
directory.verify();
|
|
3749
|
+
unlinkSync(dbPath);
|
|
3750
|
+
} catch {
|
|
3751
|
+
}
|
|
3752
|
+
},
|
|
3740
3753
|
close() {
|
|
3741
3754
|
if (closed) return;
|
|
3742
3755
|
closed = true;
|
|
@@ -3911,7 +3924,7 @@ function openOrCreateRegularFile(dbPath) {
|
|
|
3911
3924
|
if (!isSafeDatabaseFile(opened) || initial && !sameIdentity(initial, opened)) {
|
|
3912
3925
|
throw unsafeSessionStorage("Session database path changed during initialization");
|
|
3913
3926
|
}
|
|
3914
|
-
return descriptor;
|
|
3927
|
+
return { descriptor, created: !initial };
|
|
3915
3928
|
} catch (error) {
|
|
3916
3929
|
try {
|
|
3917
3930
|
closeSync2(descriptor);
|
|
@@ -4047,7 +4060,12 @@ var SqliteSessionRepository = class {
|
|
|
4047
4060
|
let database;
|
|
4048
4061
|
try {
|
|
4049
4062
|
if (dbPath !== ":memory:") validateSqliteSidecars(dbPath);
|
|
4050
|
-
|
|
4063
|
+
try {
|
|
4064
|
+
database = dbPath === ":memory:" ? new Database(dbPath) : new Database(dbPath, { fileMustExist: true });
|
|
4065
|
+
} catch (error) {
|
|
4066
|
+
pathGuard?.removeCreatedFile();
|
|
4067
|
+
throw error;
|
|
4068
|
+
}
|
|
4051
4069
|
pathGuard?.verify();
|
|
4052
4070
|
if (dbPath !== ":memory:") validateSqliteSidecars(dbPath);
|
|
4053
4071
|
this.db = database;
|
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
resolveWorkspace,
|
|
13
13
|
serializePublicResumeCapsule,
|
|
14
14
|
validateReadBudget
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-YY7QXBG5.js";
|
|
16
16
|
import {
|
|
17
17
|
loadOrCreateDeviceId
|
|
18
18
|
} from "./chunk-XRJ6QW6N.js";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
configureMcpRegistrationEntrypoint,
|
|
21
21
|
inspectLegacyClaudeHookPresence,
|
|
22
22
|
isMcpServerRegistered
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-YKG6CDGT.js";
|
|
24
24
|
import "./chunk-RXGW4Q3G.js";
|
|
25
25
|
import {
|
|
26
26
|
getSessionDbPath
|
|
@@ -2495,7 +2495,7 @@ function probeSessionDatabase(path) {
|
|
|
2495
2495
|
}
|
|
2496
2496
|
program.name("agentcache").description("Same-machine cross-agent session continuity with explicit user-selected handoffs").version(PKG_VERSION);
|
|
2497
2497
|
program.command("setup").description("Detect IDEs and register AgentCache").action(async () => {
|
|
2498
|
-
const { runSetup } = await import("./setup-
|
|
2498
|
+
const { runSetup } = await import("./setup-7JJPW3VG.js");
|
|
2499
2499
|
await runSetup();
|
|
2500
2500
|
});
|
|
2501
2501
|
program.command("serve").description("Start AgentCache MCP server (spawned by IDEs automatically)").requiredOption("--adapter <id>", "Trusted adapter identity for this MCP process").action(async (options) => {
|
package/dist/mcp.js
CHANGED
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
redactPortableText,
|
|
8
8
|
resolveWorkspace,
|
|
9
9
|
serializePublicResumeCapsule
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-YY7QXBG5.js";
|
|
11
|
+
import "./chunk-YKG6CDGT.js";
|
|
12
12
|
import "./chunk-RXGW4Q3G.js";
|
|
13
13
|
import {
|
|
14
14
|
getSessionDbPath
|
package/docs/compatibility.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AgentCache beta compatibility
|
|
2
2
|
|
|
3
3
|
This document describes the runtime registry shipped in AgentCache
|
|
4
|
-
`0.5.0-beta.
|
|
4
|
+
`0.5.0-beta.2`. The CLI remains the source of truth on an installed machine:
|
|
5
5
|
|
|
6
6
|
```bash
|
|
7
7
|
agentcache adapter list --json
|
|
@@ -69,12 +69,18 @@ unsupported for all seven adapters. In practical terms:
|
|
|
69
69
|
|
|
70
70
|
## Registration formats
|
|
71
71
|
|
|
72
|
-
Setup writes an adapter-bound
|
|
72
|
+
Setup writes an adapter-bound launch vector, never a bare PATH-resolved
|
|
73
|
+
identity:
|
|
73
74
|
|
|
74
75
|
```text
|
|
75
|
-
agentcache serve --adapter <adapter-id>
|
|
76
|
+
<absolute-node> <absolute-agentcache-cli> serve --adapter <adapter-id>
|
|
76
77
|
```
|
|
77
78
|
|
|
79
|
+
Both executable paths are captured from the AgentCache process performing
|
|
80
|
+
setup. Rerun setup after changing Node versions or version managers, changing
|
|
81
|
+
the global npm prefix, or reinstalling/upgrading AgentCache, then restart the
|
|
82
|
+
clients so they reload their MCP configuration.
|
|
83
|
+
|
|
78
84
|
The supported configuration families are Claude Code JSON, Cursor/Windsurf/Roo
|
|
79
85
|
Code MCP JSON, Continue's MCP JSON directory, Codex TOML, and Goose YAML.
|
|
80
86
|
Existing files are updated atomically with a restrictive backup. Malformed or
|
package/docs/demo-script.md
CHANGED
|
@@ -9,7 +9,7 @@ Do not cut around an error or replace real output with a mock.
|
|
|
9
9
|
|
|
10
10
|
## Preflight, off camera
|
|
11
11
|
|
|
12
|
-
- Install `agentcache@0.5.0-beta.
|
|
12
|
+
- Install `agentcache@0.5.0-beta.2`, run `agentcache setup`, and restart Claude
|
|
13
13
|
Code, Codex, and Cursor.
|
|
14
14
|
- Open the same small demo repository in all three clients.
|
|
15
15
|
- Run the global `agentcache doctor` to verify exact adapter-bound MCP
|
package/docs/launch-copy.md
CHANGED
|
@@ -5,13 +5,11 @@ portable AgentCache state from provider-native session state.
|
|
|
5
5
|
|
|
6
6
|
## Release gate
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
`0.5.0-beta.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
to the intended audience. Do not publish the package or change repository
|
|
14
|
-
visibility without explicit release approval.
|
|
8
|
+
The GitHub repository is public and `0.5.0-beta.1` has been published under the
|
|
9
|
+
`beta` npm tag. The `0.5.0-beta.2` copy below remains staged until the corrected
|
|
10
|
+
artifact and matching GitHub prerelease are published. Before using it, verify
|
|
11
|
+
the exact npm artifact and checksum, the `beta` dist-tag, and the public beta
|
|
12
|
+
issue form.
|
|
15
13
|
|
|
16
14
|
## One line
|
|
17
15
|
|
|
@@ -20,7 +18,7 @@ context in another registered agent on the same machine.
|
|
|
20
18
|
|
|
21
19
|
## Short post
|
|
22
20
|
|
|
23
|
-
AgentCache `0.5.0-beta.
|
|
21
|
+
AgentCache `0.5.0-beta.2` is available for testing.
|
|
24
22
|
|
|
25
23
|
Pick a coding session, choose a destination agent, and continue with a bounded
|
|
26
24
|
checkpoint of the goal, decisions, completed work, blockers, constraints, and
|
|
@@ -41,7 +39,7 @@ Treat that token as a temporary bearer secret.
|
|
|
41
39
|
Install the pinned beta:
|
|
42
40
|
|
|
43
41
|
```bash
|
|
44
|
-
npm install -g agentcache@0.5.0-beta.
|
|
42
|
+
npm install -g agentcache@0.5.0-beta.2
|
|
45
43
|
agentcache setup
|
|
46
44
|
```
|
|
47
45
|
|
|
@@ -51,7 +49,7 @@ AgentCache beta feedback issue form.
|
|
|
51
49
|
|
|
52
50
|
## GitHub release summary
|
|
53
51
|
|
|
54
|
-
### AgentCache 0.5.0-beta.
|
|
52
|
+
### AgentCache 0.5.0-beta.2 — explicit cross-agent session continuity
|
|
55
53
|
|
|
56
54
|
This beta changes AgentCache's default product path from automatic knowledge
|
|
57
55
|
compilation to explicit portable sessions.
|
package/docs/privacy.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Privacy and trust boundary
|
|
2
2
|
|
|
3
|
-
AgentCache `0.5.0-beta.
|
|
3
|
+
AgentCache `0.5.0-beta.2` is local-first and same-machine only. Its v2 database
|
|
4
4
|
and coordination state live on your machine. That statement is about where
|
|
5
5
|
AgentCache stores data; it is not a promise that an AI coding client or its
|
|
6
6
|
model provider operates offline.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -13,8 +13,11 @@ agentcache adapter list --json
|
|
|
13
13
|
agentcache adapter doctor <adapter-id> --json
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
AgentCache `0.5.0-beta.
|
|
17
|
-
|
|
16
|
+
AgentCache `0.5.0-beta.2` requires Node.js 22 or newer. Setup pins the exact
|
|
17
|
+
active Node executable and installed AgentCache CLI into each client config.
|
|
18
|
+
After changing Node versions or version managers, changing the global npm
|
|
19
|
+
prefix, reinstalling/upgrading AgentCache, or upgrading a client, rerun
|
|
20
|
+
`agentcache setup` and restart the client so it reloads that configuration.
|
|
18
21
|
|
|
19
22
|
The global `agentcache doctor` verifies exact adapter-bound MCP registration
|
|
20
23
|
commands and, after initialization, the v2 data store. On a fresh setup before
|
|
@@ -59,7 +62,7 @@ specific registration command. AgentCache does not overwrite an entry it cannot
|
|
|
59
62
|
prove it owns.
|
|
60
63
|
|
|
61
64
|
Goose uses a YAML configuration. A JSON-only diagnostic from an older
|
|
62
|
-
AgentCache build may misreport it; verify you are running `0.5.0-beta.
|
|
65
|
+
AgentCache build may misreport it; verify you are running `0.5.0-beta.2` before
|
|
63
66
|
reporting the result.
|
|
64
67
|
|
|
65
68
|
## Handoff errors
|