chat-recall 0.7.3 → 0.7.4
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/cli.js +176 -72
- package/dist/cli.js.map +1 -1
- package/dist/intent-drain.d.ts.map +1 -1
- package/dist/intent-drain.js +3 -1
- package/dist/intent-drain.js.map +1 -1
- package/dist/mcp-relay.js +1 -1
- package/dist/mcp.js +139 -62
- package/dist/scan-worker.js +29 -2
- package/dist/sync-client.d.ts +4 -0
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +45 -1
- package/dist/sync-client.js.map +1 -1
- package/dist/sync-ledger.d.ts +2 -0
- package/dist/sync-ledger.d.ts.map +1 -1
- package/dist/sync-ledger.js +25 -0
- package/dist/sync-ledger.js.map +1 -1
- package/dist/watch.js +169 -65
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6689,7 +6689,7 @@ async function archiveRawSession(store, sessionId) {
|
|
|
6689
6689
|
return await store.putRawSession(sessionId, exp.tool, Math.floor(exp.mtime), gz, size);
|
|
6690
6690
|
}
|
|
6691
6691
|
function detectForkPredecessor(sessionPath) {
|
|
6692
|
-
const { readFileSync: readFileSync50, readdirSync:
|
|
6692
|
+
const { readFileSync: readFileSync50, readdirSync: readdirSync34 } = requireFs();
|
|
6693
6693
|
const { dirname: dirname30, join: join62, basename: basename28 } = requirePath();
|
|
6694
6694
|
let text;
|
|
6695
6695
|
try {
|
|
@@ -6719,7 +6719,7 @@ function detectForkPredecessor(sessionPath) {
|
|
|
6719
6719
|
const self = basename28(sessionPath);
|
|
6720
6720
|
let entries;
|
|
6721
6721
|
try {
|
|
6722
|
-
entries =
|
|
6722
|
+
entries = readdirSync34(dir);
|
|
6723
6723
|
} catch {
|
|
6724
6724
|
return null;
|
|
6725
6725
|
}
|
|
@@ -8350,8 +8350,35 @@ var init_codex2 = __esm({
|
|
|
8350
8350
|
configToml() {
|
|
8351
8351
|
return join9(this.homeDir(), "config.toml");
|
|
8352
8352
|
}
|
|
8353
|
-
|
|
8354
|
-
|
|
8353
|
+
/**
|
|
8354
|
+
* Plugins that are INSTALLED, one folder each:
|
|
8355
|
+
* `plugins/cache/<marketplace>/<plugin>/<version>/`, newest version.
|
|
8356
|
+
*
|
|
8357
|
+
* `.tmp/plugins/plugins/` is Codex's copy of the plugin catalog (62 plugins
|
|
8358
|
+
* and a README on one machine), not what is installed. Reading it reported
|
|
8359
|
+
* every catalog plugin's skills and MCP servers as the user's own, and a
|
|
8360
|
+
* pull then installed them into every tool: build-ios-apps' xcodebuildmcp
|
|
8361
|
+
* reached a Linux PC that never installed the plugin.
|
|
8362
|
+
*/
|
|
8363
|
+
installedPluginDirs() {
|
|
8364
|
+
const cache4 = join9(this.homeDir(), "plugins", "cache");
|
|
8365
|
+
const out = [];
|
|
8366
|
+
const dirs = (p) => {
|
|
8367
|
+
try {
|
|
8368
|
+
return readdirSync6(p, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name);
|
|
8369
|
+
} catch {
|
|
8370
|
+
return [];
|
|
8371
|
+
}
|
|
8372
|
+
};
|
|
8373
|
+
for (const market of dirs(cache4)) {
|
|
8374
|
+
for (const plugin of dirs(join9(cache4, market))) {
|
|
8375
|
+
const versions = dirs(join9(cache4, market, plugin)).sort((a, b) => a.localeCompare(b, void 0, { numeric: true }));
|
|
8376
|
+
const newest = versions[versions.length - 1];
|
|
8377
|
+
if (newest)
|
|
8378
|
+
out.push({ name: plugin, dir: join9(cache4, market, plugin, newest) });
|
|
8379
|
+
}
|
|
8380
|
+
}
|
|
8381
|
+
return out;
|
|
8355
8382
|
}
|
|
8356
8383
|
/** OpenAI-bundled, read-only system skills (imagegen, skill-creator, …). */
|
|
8357
8384
|
skillsSystemDir() {
|
|
@@ -17013,14 +17040,11 @@ var init_skills_source = __esm({
|
|
|
17013
17040
|
}
|
|
17014
17041
|
if (!isSourceEnabled("codex", "skills"))
|
|
17015
17042
|
return;
|
|
17016
|
-
const
|
|
17017
|
-
|
|
17018
|
-
|
|
17019
|
-
|
|
17020
|
-
|
|
17021
|
-
continue;
|
|
17022
|
-
yield* this.fromSkillRoot({ path: skillsDir, tool: "codex" }, pluginName);
|
|
17023
|
-
}
|
|
17043
|
+
for (const { name: pluginName, dir } of codexBackend.installedPluginDirs()) {
|
|
17044
|
+
const skillsDir = join32(dir, "skills");
|
|
17045
|
+
if (!existsSync33(skillsDir))
|
|
17046
|
+
continue;
|
|
17047
|
+
yield* this.fromSkillRoot({ path: skillsDir, tool: "codex" }, pluginName);
|
|
17024
17048
|
}
|
|
17025
17049
|
}
|
|
17026
17050
|
async *fromSkillRoot(root, pluginName) {
|
|
@@ -17133,7 +17157,7 @@ var init_skills_source = __esm({
|
|
|
17133
17157
|
});
|
|
17134
17158
|
|
|
17135
17159
|
// ../engine/dist/parsers/mcps-source.js
|
|
17136
|
-
import { existsSync as existsSync34,
|
|
17160
|
+
import { existsSync as existsSync34, readFileSync as readFileSync24, statSync as statSync30 } from "fs";
|
|
17137
17161
|
import { homedir as homedir13 } from "os";
|
|
17138
17162
|
import { join as join33 } from "path";
|
|
17139
17163
|
function readJson(path) {
|
|
@@ -17245,16 +17269,13 @@ var init_mcps_source = __esm({
|
|
|
17245
17269
|
scope: "user"
|
|
17246
17270
|
});
|
|
17247
17271
|
yield* this.fromCodexToml(codexBackend.configToml());
|
|
17248
|
-
const
|
|
17249
|
-
|
|
17250
|
-
|
|
17251
|
-
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
scope: "plugin"
|
|
17256
|
-
});
|
|
17257
|
-
}
|
|
17272
|
+
for (const { dir } of codexBackend.installedPluginDirs()) {
|
|
17273
|
+
const mcpPath = join33(dir, ".mcp.json");
|
|
17274
|
+
yield* this.fromObject(readJson(mcpPath)?.mcpServers, {
|
|
17275
|
+
tool: "codex",
|
|
17276
|
+
filePath: mcpPath,
|
|
17277
|
+
scope: "plugin"
|
|
17278
|
+
});
|
|
17258
17279
|
}
|
|
17259
17280
|
}
|
|
17260
17281
|
async *fromObject(obj, ctx) {
|
|
@@ -17292,7 +17313,12 @@ var init_mcps_source = __esm({
|
|
|
17292
17313
|
// MCP's url into a shell string, and `alwaysAllow` is truncated to
|
|
17293
17314
|
// 8 for the preview — rebuilding from either produces a broken or
|
|
17294
17315
|
// half-permissioned server, silently.
|
|
17295
|
-
spec
|
|
17316
|
+
spec,
|
|
17317
|
+
// Where this registration runs. A server that starts through npx
|
|
17318
|
+
// passes the command check on any machine, so this is what tells a
|
|
17319
|
+
// pull that it came from another platform (see toolkit-pull.ts).
|
|
17320
|
+
platform: process.platform,
|
|
17321
|
+
arch: process.arch
|
|
17296
17322
|
}
|
|
17297
17323
|
};
|
|
17298
17324
|
}
|
|
@@ -17471,7 +17497,7 @@ var init_toolkit_format = __esm({
|
|
|
17471
17497
|
});
|
|
17472
17498
|
|
|
17473
17499
|
// ../engine/dist/parsers/slash-commands-source.js
|
|
17474
|
-
import { existsSync as existsSync35, readdirSync as
|
|
17500
|
+
import { existsSync as existsSync35, readdirSync as readdirSync26, readFileSync as readFileSync25, statSync as statSync31 } from "fs";
|
|
17475
17501
|
import { join as join34, basename as basename18 } from "path";
|
|
17476
17502
|
function rebuildBody2(content) {
|
|
17477
17503
|
const { text, redacted } = redactInlineSecrets(content);
|
|
@@ -17526,7 +17552,7 @@ var init_slash_commands_source = __esm({
|
|
|
17526
17552
|
const projectsRoot = claudeBackend.projectsDir();
|
|
17527
17553
|
if (existsSync35(projectsRoot)) {
|
|
17528
17554
|
try {
|
|
17529
|
-
for (const entry of
|
|
17555
|
+
for (const entry of readdirSync26(projectsRoot, { withFileTypes: true })) {
|
|
17530
17556
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
17531
17557
|
continue;
|
|
17532
17558
|
const projectPath = resolveProjectDirName(entry.name);
|
|
@@ -17558,7 +17584,7 @@ var init_slash_commands_source = __esm({
|
|
|
17558
17584
|
const ext = root.format === "toml" ? ".toml" : ".md";
|
|
17559
17585
|
let files;
|
|
17560
17586
|
try {
|
|
17561
|
-
files =
|
|
17587
|
+
files = readdirSync26(root.path).filter((f) => f.endsWith(ext));
|
|
17562
17588
|
} catch {
|
|
17563
17589
|
continue;
|
|
17564
17590
|
}
|
|
@@ -17618,7 +17644,7 @@ var init_slash_commands_source = __esm({
|
|
|
17618
17644
|
});
|
|
17619
17645
|
|
|
17620
17646
|
// ../engine/dist/parsers/subagents-source.js
|
|
17621
|
-
import { existsSync as existsSync36, readdirSync as
|
|
17647
|
+
import { existsSync as existsSync36, readdirSync as readdirSync27, readFileSync as readFileSync26, statSync as statSync32 } from "fs";
|
|
17622
17648
|
import { join as join35, basename as basename19 } from "path";
|
|
17623
17649
|
function rebuildBody3(content) {
|
|
17624
17650
|
const { text, redacted } = redactInlineSecrets(content);
|
|
@@ -17675,7 +17701,7 @@ var init_subagents_source = __esm({
|
|
|
17675
17701
|
const projectsRoot = claudeBackend.projectsDir();
|
|
17676
17702
|
if (existsSync36(projectsRoot)) {
|
|
17677
17703
|
try {
|
|
17678
|
-
for (const entry of
|
|
17704
|
+
for (const entry of readdirSync27(projectsRoot, { withFileTypes: true })) {
|
|
17679
17705
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
17680
17706
|
continue;
|
|
17681
17707
|
const projectPath = resolveProjectDirName(entry.name);
|
|
@@ -17707,7 +17733,7 @@ var init_subagents_source = __esm({
|
|
|
17707
17733
|
const ext = root.format === "toml" ? ".toml" : ".md";
|
|
17708
17734
|
let files;
|
|
17709
17735
|
try {
|
|
17710
|
-
files =
|
|
17736
|
+
files = readdirSync27(root.path).filter((f) => f.endsWith(ext));
|
|
17711
17737
|
} catch {
|
|
17712
17738
|
continue;
|
|
17713
17739
|
}
|
|
@@ -17768,7 +17794,7 @@ var init_subagents_source = __esm({
|
|
|
17768
17794
|
});
|
|
17769
17795
|
|
|
17770
17796
|
// ../engine/dist/parsers/hooks-source.js
|
|
17771
|
-
import { existsSync as existsSync37, readFileSync as readFileSync27, readdirSync as
|
|
17797
|
+
import { existsSync as existsSync37, readFileSync as readFileSync27, readdirSync as readdirSync28, statSync as statSync33 } from "fs";
|
|
17772
17798
|
import { join as join36 } from "path";
|
|
17773
17799
|
function readJson2(path) {
|
|
17774
17800
|
if (!existsSync37(path))
|
|
@@ -17795,7 +17821,7 @@ var init_hooks_source = __esm({
|
|
|
17795
17821
|
const projectsRoot = claudeBackend.projectsDir();
|
|
17796
17822
|
if (existsSync37(projectsRoot)) {
|
|
17797
17823
|
try {
|
|
17798
|
-
for (const entry of
|
|
17824
|
+
for (const entry of readdirSync28(projectsRoot, { withFileTypes: true })) {
|
|
17799
17825
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
17800
17826
|
continue;
|
|
17801
17827
|
const projectPath = resolveProjectDirName(entry.name);
|
|
@@ -17891,7 +17917,7 @@ var init_hooks_source = __esm({
|
|
|
17891
17917
|
});
|
|
17892
17918
|
|
|
17893
17919
|
// ../engine/dist/parsers/plugins-source.js
|
|
17894
|
-
import { existsSync as existsSync38, readFileSync as readFileSync28, readdirSync as
|
|
17920
|
+
import { existsSync as existsSync38, readFileSync as readFileSync28, readdirSync as readdirSync29, statSync as statSync34 } from "fs";
|
|
17895
17921
|
import { homedir as homedir14 } from "os";
|
|
17896
17922
|
import { join as join37 } from "path";
|
|
17897
17923
|
function readJson3(path) {
|
|
@@ -17953,7 +17979,7 @@ var init_plugins_source = __esm({
|
|
|
17953
17979
|
if (isSourceEnabled("agy", "extensions") && existsSync38(gemRoot)) {
|
|
17954
17980
|
let entries;
|
|
17955
17981
|
try {
|
|
17956
|
-
entries =
|
|
17982
|
+
entries = readdirSync29(gemRoot);
|
|
17957
17983
|
} catch {
|
|
17958
17984
|
entries = [];
|
|
17959
17985
|
}
|
|
@@ -17997,16 +18023,8 @@ var init_plugins_source = __esm({
|
|
|
17997
18023
|
};
|
|
17998
18024
|
}
|
|
17999
18025
|
}
|
|
18000
|
-
|
|
18001
|
-
|
|
18002
|
-
let entries;
|
|
18003
|
-
try {
|
|
18004
|
-
entries = readdirSync30(codexPluginsRoot);
|
|
18005
|
-
} catch {
|
|
18006
|
-
entries = [];
|
|
18007
|
-
}
|
|
18008
|
-
for (const name of entries) {
|
|
18009
|
-
const pluginDir = join37(codexPluginsRoot, name);
|
|
18026
|
+
if (isSourceEnabled("codex", "plugins")) {
|
|
18027
|
+
for (const { name, dir: pluginDir } of codexBackend.installedPluginDirs()) {
|
|
18010
18028
|
let st;
|
|
18011
18029
|
try {
|
|
18012
18030
|
st = statSync34(pluginDir);
|
|
@@ -18120,7 +18138,8 @@ var init_all_sources = __esm({
|
|
|
18120
18138
|
|
|
18121
18139
|
// ../engine/dist/core/extractor-version.js
|
|
18122
18140
|
function extractorVersionForItem(id, sourceType) {
|
|
18123
|
-
|
|
18141
|
+
const tool = toolOfId(id);
|
|
18142
|
+
return extractorVersionForTool(tool) + (ITEM_SOURCE_BUMP[sourceType] ?? 0) + (ITEM_TOOL_SOURCE_BUMP[`${tool}:${sourceType}`] ?? 0);
|
|
18124
18143
|
}
|
|
18125
18144
|
function toolOfId(id) {
|
|
18126
18145
|
if (id.startsWith("agy_"))
|
|
@@ -18141,17 +18160,21 @@ function extractorVersionForTool(tool) {
|
|
|
18141
18160
|
function extractorVersionForId(id) {
|
|
18142
18161
|
return extractorVersionForTool(toolOfId(id));
|
|
18143
18162
|
}
|
|
18144
|
-
var BASE_EXTRACTOR_VERSION, ITEM_SOURCE_BUMP, TOOL_EXTRACTOR_BUMP, EXTRACTOR_VERSION;
|
|
18163
|
+
var BASE_EXTRACTOR_VERSION, ITEM_SOURCE_BUMP, ITEM_TOOL_SOURCE_BUMP, TOOL_EXTRACTOR_BUMP, EXTRACTOR_VERSION;
|
|
18145
18164
|
var init_extractor_version = __esm({
|
|
18146
18165
|
"../engine/dist/core/extractor-version.js"() {
|
|
18147
18166
|
"use strict";
|
|
18148
18167
|
BASE_EXTRACTOR_VERSION = 2;
|
|
18149
18168
|
ITEM_SOURCE_BUMP = {
|
|
18150
|
-
mcp:
|
|
18169
|
+
mcp: 2,
|
|
18151
18170
|
skill: 1,
|
|
18152
18171
|
agent: 1,
|
|
18153
18172
|
command: 1
|
|
18154
18173
|
};
|
|
18174
|
+
ITEM_TOOL_SOURCE_BUMP = {
|
|
18175
|
+
"codex:skill": 1,
|
|
18176
|
+
"codex:plugin": 1
|
|
18177
|
+
};
|
|
18155
18178
|
TOOL_EXTRACTOR_BUMP = {
|
|
18156
18179
|
agy: 3,
|
|
18157
18180
|
claude: 1,
|
|
@@ -18263,6 +18286,28 @@ function saveItemVersions(server, versions) {
|
|
|
18263
18286
|
writeFileSync5(tmp, JSON.stringify(all));
|
|
18264
18287
|
renameSync4(tmp, path);
|
|
18265
18288
|
}
|
|
18289
|
+
function loadInventoryHashes(server) {
|
|
18290
|
+
try {
|
|
18291
|
+
const parsed = JSON.parse(readFileSync29(inventoryPath(), "utf-8"));
|
|
18292
|
+
return { ...(parsed && typeof parsed === "object" ? parsed[server] : null) || {} };
|
|
18293
|
+
} catch {
|
|
18294
|
+
return {};
|
|
18295
|
+
}
|
|
18296
|
+
}
|
|
18297
|
+
function saveInventoryHashes(server, hashes) {
|
|
18298
|
+
let all = {};
|
|
18299
|
+
try {
|
|
18300
|
+
all = JSON.parse(readFileSync29(inventoryPath(), "utf-8"));
|
|
18301
|
+
} catch {
|
|
18302
|
+
}
|
|
18303
|
+
if (!all || typeof all !== "object") all = {};
|
|
18304
|
+
all[server] = { ...all[server] || {}, ...hashes };
|
|
18305
|
+
const path = inventoryPath();
|
|
18306
|
+
mkdirSync6(dirname15(path), { recursive: true });
|
|
18307
|
+
const tmp = `${path}.tmp`;
|
|
18308
|
+
writeFileSync5(tmp, JSON.stringify(all));
|
|
18309
|
+
renameSync4(tmp, path);
|
|
18310
|
+
}
|
|
18266
18311
|
function getSyncedRows(server) {
|
|
18267
18312
|
const data = load();
|
|
18268
18313
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -18374,7 +18419,7 @@ function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly) {
|
|
|
18374
18419
|
if (row.m >= Math.floor(mtime)) return "skip";
|
|
18375
18420
|
return "full";
|
|
18376
18421
|
}
|
|
18377
|
-
var ledgerPath, cache3, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, unackedCursorAttempts, reconcilePath, reconcileCache;
|
|
18422
|
+
var ledgerPath, cache3, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, inventoryPath, unackedCursorAttempts, reconcilePath, reconcileCache;
|
|
18378
18423
|
var init_sync_ledger = __esm({
|
|
18379
18424
|
"src/sync-ledger.ts"() {
|
|
18380
18425
|
"use strict";
|
|
@@ -18387,6 +18432,7 @@ var init_sync_ledger = __esm({
|
|
|
18387
18432
|
flushTimer = null;
|
|
18388
18433
|
itemVersionsPath = () => join38(getDataDir(), "item-versions.json");
|
|
18389
18434
|
itemVersionsCache = null;
|
|
18435
|
+
inventoryPath = () => join38(getDataDir(), "toolkit-inventory.json");
|
|
18390
18436
|
unackedCursorAttempts = 0;
|
|
18391
18437
|
reconcilePath = () => join38(getDataDir(), "sync-field-reconcile.json");
|
|
18392
18438
|
reconcileCache = null;
|
|
@@ -18541,7 +18587,7 @@ var init_http = __esm({
|
|
|
18541
18587
|
CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18542
18588
|
} catch {
|
|
18543
18589
|
try {
|
|
18544
|
-
if (true) CLI_VERSION = "0.7.
|
|
18590
|
+
if (true) CLI_VERSION = "0.7.4";
|
|
18545
18591
|
} catch {
|
|
18546
18592
|
}
|
|
18547
18593
|
}
|
|
@@ -19040,7 +19086,7 @@ var init_telemetry = __esm({
|
|
|
19040
19086
|
init_sync_client();
|
|
19041
19087
|
cliVersion2 = () => {
|
|
19042
19088
|
try {
|
|
19043
|
-
return true ? "0.7.
|
|
19089
|
+
return true ? "0.7.4" : "dev";
|
|
19044
19090
|
} catch {
|
|
19045
19091
|
return "dev";
|
|
19046
19092
|
}
|
|
@@ -19405,7 +19451,7 @@ __export(auto_update_exports, {
|
|
|
19405
19451
|
import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
|
|
19406
19452
|
import { readFileSync as readFileSync34, existsSync as existsSync41 } from "node:fs";
|
|
19407
19453
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19408
|
-
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as
|
|
19454
|
+
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync30, statSync as statSync36, mkdirSync as mkdirSync9 } from "node:fs";
|
|
19409
19455
|
import { join as join41, dirname as dirname18, sep as sep2, posix as pathPosix, win32 as pathWin32 } from "node:path";
|
|
19410
19456
|
import { tmpdir as tmpdir2, homedir as homedir15 } from "node:os";
|
|
19411
19457
|
import { createHash as createHash8 } from "node:crypto";
|
|
@@ -19450,7 +19496,7 @@ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
|
|
|
19450
19496
|
let removed = 0;
|
|
19451
19497
|
let entries;
|
|
19452
19498
|
try {
|
|
19453
|
-
entries =
|
|
19499
|
+
entries = readdirSync30(root);
|
|
19454
19500
|
} catch {
|
|
19455
19501
|
return 0;
|
|
19456
19502
|
}
|
|
@@ -19460,7 +19506,7 @@ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
|
|
|
19460
19506
|
try {
|
|
19461
19507
|
const st = statSync36(dir);
|
|
19462
19508
|
if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
|
|
19463
|
-
const inside =
|
|
19509
|
+
const inside = readdirSync30(dir);
|
|
19464
19510
|
if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
|
|
19465
19511
|
rmSync5(dir, { recursive: true, force: true });
|
|
19466
19512
|
removed++;
|
|
@@ -19664,6 +19710,7 @@ __export(sync_client_exports, {
|
|
|
19664
19710
|
DERIVED_MAX_BYTES: () => DERIVED_MAX_BYTES,
|
|
19665
19711
|
FULL_BUILD_MAX_BYTES: () => FULL_BUILD_MAX_BYTES,
|
|
19666
19712
|
SYNC_CHUNK_BYTES: () => SYNC_CHUNK_BYTES,
|
|
19713
|
+
TOOLKIT_INVENTORY_TYPES: () => TOOLKIT_INVENTORY_TYPES,
|
|
19667
19714
|
_acceptedUploads: () => _acceptedUploads,
|
|
19668
19715
|
_fetchTenantSyncConfigForTests: () => _fetchTenantSyncConfigForTests,
|
|
19669
19716
|
_resetCapsCacheForTests: () => _resetCapsCacheForTests,
|
|
@@ -19692,7 +19739,7 @@ __export(sync_client_exports, {
|
|
|
19692
19739
|
syncSessions: () => syncSessions
|
|
19693
19740
|
});
|
|
19694
19741
|
import { join as join42, dirname as dirname19, basename as basename20 } from "node:path";
|
|
19695
|
-
import { readFileSync as readFileSync35, writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync4, rmSync as rmSync6, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as
|
|
19742
|
+
import { readFileSync as readFileSync35, writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync4, rmSync as rmSync6, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync31, statSync as statSync37 } from "node:fs";
|
|
19696
19743
|
import { tmpdir as tmpdir3, hostname as hostname2 } from "node:os";
|
|
19697
19744
|
import { createHash as createHash9 } from "node:crypto";
|
|
19698
19745
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -20095,7 +20142,7 @@ function reapStaleScanDirs(dir = tmpdir3(), maxAgeMs = 6 * 36e5, now = Date.now(
|
|
|
20095
20142
|
let reaped = 0;
|
|
20096
20143
|
let names;
|
|
20097
20144
|
try {
|
|
20098
|
-
names =
|
|
20145
|
+
names = readdirSync31(dir);
|
|
20099
20146
|
} catch {
|
|
20100
20147
|
return 0;
|
|
20101
20148
|
}
|
|
@@ -20736,17 +20783,24 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20736
20783
|
const seenTools = /* @__PURE__ */ new Set();
|
|
20737
20784
|
const seenItemKeys = /* @__PURE__ */ new Map();
|
|
20738
20785
|
const registry = buildSourceRegistry();
|
|
20786
|
+
const inventory = /* @__PURE__ */ new Map();
|
|
20787
|
+
const inventoryFailed = /* @__PURE__ */ new Set();
|
|
20739
20788
|
for (const sourceType of registry.getRegisteredTypes()) {
|
|
20740
20789
|
if (sourceType === "session") continue;
|
|
20790
|
+
if (TOOLKIT_INVENTORY_TYPES.has(sourceType)) inventory.set(sourceType, /* @__PURE__ */ new Set());
|
|
20741
20791
|
for (const source of registry.getAll(sourceType)) {
|
|
20742
20792
|
let discovered;
|
|
20743
20793
|
try {
|
|
20744
20794
|
discovered = source.discover();
|
|
20745
20795
|
} catch {
|
|
20796
|
+
inventoryFailed.add(sourceType);
|
|
20746
20797
|
continue;
|
|
20747
20798
|
}
|
|
20748
20799
|
try {
|
|
20749
20800
|
for await (const item of discovered) {
|
|
20801
|
+
if (inventory.has(item.sourceType) && !excluded(item.projectPath || "") && includedProject(item.projectPath || "")) {
|
|
20802
|
+
inventory.get(item.sourceType).add(item.id);
|
|
20803
|
+
}
|
|
20750
20804
|
const itemTool = toolOfId(item.id);
|
|
20751
20805
|
seenTools.add(itemTool);
|
|
20752
20806
|
const itemKey = `${itemTool}:${item.sourceType}`;
|
|
@@ -20804,6 +20858,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20804
20858
|
redactions += count.redactions;
|
|
20805
20859
|
}
|
|
20806
20860
|
} catch (err) {
|
|
20861
|
+
inventoryFailed.add(sourceType);
|
|
20807
20862
|
console.error(`[sync] source '${sourceType}' failed mid-walk (its items may be incomplete this run): ${err instanceof Error ? err.message : err}`);
|
|
20808
20863
|
}
|
|
20809
20864
|
}
|
|
@@ -20830,6 +20885,27 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20830
20885
|
await kgTripleBatch.drain();
|
|
20831
20886
|
await findingsBatch.drain();
|
|
20832
20887
|
await drainInflight();
|
|
20888
|
+
{
|
|
20889
|
+
const sentHashes = loadInventoryHashes(base3);
|
|
20890
|
+
const entries = [];
|
|
20891
|
+
const hashes = {};
|
|
20892
|
+
for (const [sourceType, ids] of inventory) {
|
|
20893
|
+
if (inventoryFailed.has(sourceType)) continue;
|
|
20894
|
+
const sorted = [...ids].sort();
|
|
20895
|
+
const hash = createHash9("sha256").update(sorted.join("\n")).digest("hex").slice(0, 32);
|
|
20896
|
+
if (sentHashes[sourceType] === hash) continue;
|
|
20897
|
+
entries.push({ source_type: sourceType, ids: sorted });
|
|
20898
|
+
hashes[sourceType] = hash;
|
|
20899
|
+
}
|
|
20900
|
+
if (entries.length > 0) {
|
|
20901
|
+
try {
|
|
20902
|
+
await post({ inventory: entries });
|
|
20903
|
+
saveInventoryHashes(base3, hashes);
|
|
20904
|
+
} catch (err) {
|
|
20905
|
+
console.error(`[sync] toolkit inventory not sent (it is retried next sync): ${err instanceof Error ? err.message : err}`);
|
|
20906
|
+
}
|
|
20907
|
+
}
|
|
20908
|
+
}
|
|
20833
20909
|
if (seenTools.size > 0) {
|
|
20834
20910
|
try {
|
|
20835
20911
|
const rec = {};
|
|
@@ -21275,7 +21351,7 @@ async function syncIncremental(opts = {}) {
|
|
|
21275
21351
|
lock.release();
|
|
21276
21352
|
}
|
|
21277
21353
|
}
|
|
21278
|
-
var ownVersion, ERROR_CLASS, STANDING_FAILURE, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, _fetchTenantSyncConfigForTests, SYNC_RULES_REFUSAL, hashPath, acceptedUploads, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES, DERIVED_MAX_BYTES, SYNC_CHUNK_BYTES, BATCH_SCAN_MAX_BYTES;
|
|
21354
|
+
var ownVersion, ERROR_CLASS, STANDING_FAILURE, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, _fetchTenantSyncConfigForTests, SYNC_RULES_REFUSAL, hashPath, acceptedUploads, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES, DERIVED_MAX_BYTES, SYNC_CHUNK_BYTES, TOOLKIT_INVENTORY_TYPES, BATCH_SCAN_MAX_BYTES;
|
|
21279
21355
|
var init_sync_client = __esm({
|
|
21280
21356
|
"src/sync-client.ts"() {
|
|
21281
21357
|
"use strict";
|
|
@@ -21320,7 +21396,7 @@ var init_sync_client = __esm({
|
|
|
21320
21396
|
ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21321
21397
|
} catch {
|
|
21322
21398
|
try {
|
|
21323
|
-
if (true) ownVersion = "0.7.
|
|
21399
|
+
if (true) ownVersion = "0.7.4";
|
|
21324
21400
|
} catch {
|
|
21325
21401
|
}
|
|
21326
21402
|
}
|
|
@@ -21350,6 +21426,7 @@ var init_sync_client = __esm({
|
|
|
21350
21426
|
FULL_BUILD_MAX_BYTES = Math.max(8, parseInt(process.env.CHAT_RECALL_FULL_BUILD_MAX_MB || "24", 10)) * 1024 * 1024;
|
|
21351
21427
|
DERIVED_MAX_BYTES = Math.max(8, parseInt(process.env.CHAT_RECALL_DERIVED_MAX_MB || "64", 10)) * 1024 * 1024;
|
|
21352
21428
|
SYNC_CHUNK_BYTES = 8 * 1024 * 1024;
|
|
21429
|
+
TOOLKIT_INVENTORY_TYPES = /* @__PURE__ */ new Set(["skill", "mcp", "command", "agent", "plugin"]);
|
|
21353
21430
|
BATCH_SCAN_MAX_BYTES = Math.max(1, parseInt(process.env.CHAT_RECALL_BATCHSCAN_MAX_MB || "64", 10)) * 1024 * 1024;
|
|
21354
21431
|
}
|
|
21355
21432
|
});
|
|
@@ -22004,7 +22081,7 @@ __export(install_skills_exports, {
|
|
|
22004
22081
|
skillsSourceDir: () => skillsSourceDir,
|
|
22005
22082
|
uninstallSkills: () => uninstallSkills
|
|
22006
22083
|
});
|
|
22007
|
-
import { readdirSync as
|
|
22084
|
+
import { readdirSync as readdirSync32, existsSync as existsSync46, mkdirSync as mkdirSync14, rmSync as rmSync7, cpSync, writeFileSync as writeFileSync14, readFileSync as readFileSync39, statSync as statSync40, realpathSync as realpathSync4 } from "fs";
|
|
22008
22085
|
import { createHash as createHash11 } from "crypto";
|
|
22009
22086
|
import { join as join48, basename as basename21 } from "path";
|
|
22010
22087
|
function skillsSourceDir() {
|
|
@@ -22030,7 +22107,7 @@ function skillsFingerprint() {
|
|
|
22030
22107
|
}
|
|
22031
22108
|
function filesUnder(dir, prefix = "") {
|
|
22032
22109
|
const out = [];
|
|
22033
|
-
for (const e of
|
|
22110
|
+
for (const e of readdirSync32(dir, { withFileTypes: true })) {
|
|
22034
22111
|
if (e.name === MARKER) continue;
|
|
22035
22112
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
22036
22113
|
if (e.isDirectory()) out.push(...filesUnder(join48(dir, e.name), rel));
|
|
@@ -22044,7 +22121,7 @@ function skillStamp() {
|
|
|
22044
22121
|
function bundledSkillNames() {
|
|
22045
22122
|
const src = skillsSourceDir();
|
|
22046
22123
|
if (!existsSync46(src)) return [];
|
|
22047
|
-
return
|
|
22124
|
+
return readdirSync32(src, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync46(join48(src, e.name, "SKILL.md"))).map((e) => e.name).sort();
|
|
22048
22125
|
}
|
|
22049
22126
|
function realPathOrSelf(p) {
|
|
22050
22127
|
try {
|
|
@@ -22134,7 +22211,7 @@ function uninstallSkills() {
|
|
|
22134
22211
|
perTarget.push({ id: t.id, label: t.label, removed });
|
|
22135
22212
|
continue;
|
|
22136
22213
|
}
|
|
22137
|
-
for (const entry of
|
|
22214
|
+
for (const entry of readdirSync32(t.dir, { withFileTypes: true })) {
|
|
22138
22215
|
if (!entry.isDirectory()) continue;
|
|
22139
22216
|
const dir = join48(t.dir, entry.name);
|
|
22140
22217
|
if (isManaged(dir) && (names.has(entry.name) || entry.name.startsWith("chat-recall"))) {
|
|
@@ -22808,6 +22885,7 @@ __export(toolkit_pull_exports, {
|
|
|
22808
22885
|
entryFromSpec: () => entryFromSpec,
|
|
22809
22886
|
executePull: () => executePull,
|
|
22810
22887
|
planPull: () => planPull,
|
|
22888
|
+
platformRefusal: () => platformRefusal,
|
|
22811
22889
|
portableCommand: () => portableCommand
|
|
22812
22890
|
});
|
|
22813
22891
|
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as statSync41, writeFileSync as writeFileSync16 } from "node:fs";
|
|
@@ -22865,6 +22943,7 @@ function planPull(rows, opts = {}) {
|
|
|
22865
22943
|
const wanted = opts.types;
|
|
22866
22944
|
const seenUnsupported = /* @__PURE__ */ new Map();
|
|
22867
22945
|
const byName = /* @__PURE__ */ new Map();
|
|
22946
|
+
const platformsByName = /* @__PURE__ */ new Map();
|
|
22868
22947
|
const skillsByName = /* @__PURE__ */ new Map();
|
|
22869
22948
|
const agentsByName = /* @__PURE__ */ new Map();
|
|
22870
22949
|
const commandsByName = /* @__PURE__ */ new Map();
|
|
@@ -22928,6 +23007,9 @@ function planPull(rows, opts = {}) {
|
|
|
22928
23007
|
const name = extra.mcpName || row.title;
|
|
22929
23008
|
if (!name)
|
|
22930
23009
|
continue;
|
|
23010
|
+
if (typeof extra.platform === "string" && extra.platform) {
|
|
23011
|
+
(platformsByName.get(name) ?? platformsByName.set(name, /* @__PURE__ */ new Set()).get(name)).add(extra.platform);
|
|
23012
|
+
}
|
|
22931
23013
|
const spec = extra.spec || null;
|
|
22932
23014
|
if (!spec)
|
|
22933
23015
|
continue;
|
|
@@ -22937,7 +23019,12 @@ function planPull(rows, opts = {}) {
|
|
|
22937
23019
|
byName.set(name, spec);
|
|
22938
23020
|
}
|
|
22939
23021
|
const targets = SUPPORTED_TARGETS.mcp;
|
|
22940
|
-
const mcps = [...byName.entries()].map(([name, spec]) => ({
|
|
23022
|
+
const mcps = [...byName.entries()].map(([name, spec]) => ({
|
|
23023
|
+
name,
|
|
23024
|
+
spec,
|
|
23025
|
+
tools: targets,
|
|
23026
|
+
platforms: [...platformsByName.get(name) ?? []].sort()
|
|
23027
|
+
}));
|
|
22941
23028
|
const skills = [...skillsByName.entries()].map(([name, v]) => ({
|
|
22942
23029
|
name,
|
|
22943
23030
|
body: v.body,
|
|
@@ -22956,7 +23043,18 @@ function planPull(rows, opts = {}) {
|
|
|
22956
23043
|
];
|
|
22957
23044
|
return { mcps, skills, codecs, unsupported };
|
|
22958
23045
|
}
|
|
23046
|
+
function platformRefusal(name, platforms, here, explicit) {
|
|
23047
|
+
if (explicit.has(name) || platforms.includes(here))
|
|
23048
|
+
return null;
|
|
23049
|
+
const hint = `install it by name if it works on ${here}: chat-recall toolkit pull --mcp ${name}`;
|
|
23050
|
+
if (platforms.length === 0) {
|
|
23051
|
+
return `no device recorded its platform \u2014 re-sync from the device that has it, or ${hint}`;
|
|
23052
|
+
}
|
|
23053
|
+
return `registered only on ${platforms.join(", ")} \u2014 ${hint}`;
|
|
23054
|
+
}
|
|
22959
23055
|
function executePull(rows, opts = {}) {
|
|
23056
|
+
const here = opts.platform ?? process.platform;
|
|
23057
|
+
const explicit = new Set(opts.explicit ?? []);
|
|
22960
23058
|
const { mcps, skills, codecs, unsupported } = planPull(rows, opts);
|
|
22961
23059
|
const outcomes = [];
|
|
22962
23060
|
for (const { name, body, truncated, redacted, tools } of skills) {
|
|
@@ -23025,8 +23123,9 @@ function executePull(rows, opts = {}) {
|
|
|
23025
23123
|
}
|
|
23026
23124
|
}
|
|
23027
23125
|
}
|
|
23028
|
-
for (const { name, spec, tools } of mcps) {
|
|
23126
|
+
for (const { name, spec, tools, platforms } of mcps) {
|
|
23029
23127
|
const built = entryFromSpec(spec);
|
|
23128
|
+
const refusal = platformRefusal(name, platforms, here, explicit);
|
|
23030
23129
|
for (const tool of tools) {
|
|
23031
23130
|
if (!built) {
|
|
23032
23131
|
outcomes.push({ type: "mcp", name, tool, status: "skipped", reason: "stored row has no rebuildable spec (re-index on the source device)" });
|
|
@@ -23036,6 +23135,10 @@ function executePull(rows, opts = {}) {
|
|
|
23036
23135
|
outcomes.push({ type: "mcp", name, tool, status: "present" });
|
|
23037
23136
|
continue;
|
|
23038
23137
|
}
|
|
23138
|
+
if (refusal) {
|
|
23139
|
+
outcomes.push({ type: "mcp", name, tool, status: "skipped", reason: refusal });
|
|
23140
|
+
continue;
|
|
23141
|
+
}
|
|
23039
23142
|
if (spec.secretsRedacted) {
|
|
23040
23143
|
outcomes.push({
|
|
23041
23144
|
type: "mcp",
|
|
@@ -25320,7 +25423,7 @@ async function runPull(base3, opts) {
|
|
|
25320
25423
|
return r.title === opts.name;
|
|
25321
25424
|
}
|
|
25322
25425
|
}) : rows;
|
|
25323
|
-
const report = executePull2(filtered, { thisDeviceId: hostname3(), types: wanted });
|
|
25426
|
+
const report = executePull2(filtered, { thisDeviceId: hostname3(), types: wanted, explicit: opts.name ? [opts.name] : void 0 });
|
|
25324
25427
|
const written = report.outcomes.filter((o) => o.status === "written");
|
|
25325
25428
|
const failed = report.outcomes.filter((o) => o.status === "failed");
|
|
25326
25429
|
return {
|
|
@@ -25454,7 +25557,7 @@ var init_intent_drain = __esm({
|
|
|
25454
25557
|
ownVersion2 = JSON.parse(readFileSync45(join56(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
25455
25558
|
} catch {
|
|
25456
25559
|
try {
|
|
25457
|
-
if (true) ownVersion2 = "0.7.
|
|
25560
|
+
if (true) ownVersion2 = "0.7.4";
|
|
25458
25561
|
} catch {
|
|
25459
25562
|
}
|
|
25460
25563
|
}
|
|
@@ -25876,7 +25979,7 @@ var init_vault_crypto = __esm({
|
|
|
25876
25979
|
});
|
|
25877
25980
|
|
|
25878
25981
|
// ../engine/dist/core/vault-source.js
|
|
25879
|
-
import { existsSync as existsSync54, readdirSync as
|
|
25982
|
+
import { existsSync as existsSync54, readdirSync as readdirSync33, statSync as statSync44 } from "fs";
|
|
25880
25983
|
import { extname, join as join58 } from "path";
|
|
25881
25984
|
function* walkVaultSources() {
|
|
25882
25985
|
const t = loadSettings().team.vault;
|
|
@@ -25906,7 +26009,7 @@ function* walkClaude() {
|
|
|
25906
26009
|
return;
|
|
25907
26010
|
let projectDirs = [];
|
|
25908
26011
|
try {
|
|
25909
|
-
projectDirs =
|
|
26012
|
+
projectDirs = readdirSync33(root);
|
|
25910
26013
|
} catch {
|
|
25911
26014
|
return;
|
|
25912
26015
|
}
|
|
@@ -25917,7 +26020,7 @@ function* walkClaude() {
|
|
|
25917
26020
|
const projDir = join58(root, proj);
|
|
25918
26021
|
let entries = [];
|
|
25919
26022
|
try {
|
|
25920
|
-
entries =
|
|
26023
|
+
entries = readdirSync33(projDir);
|
|
25921
26024
|
} catch {
|
|
25922
26025
|
continue;
|
|
25923
26026
|
}
|
|
@@ -25962,7 +26065,7 @@ function* walkCodex() {
|
|
|
25962
26065
|
const dir = stack.pop();
|
|
25963
26066
|
let entries = [];
|
|
25964
26067
|
try {
|
|
25965
|
-
entries =
|
|
26068
|
+
entries = readdirSync33(dir, { withFileTypes: true });
|
|
25966
26069
|
} catch {
|
|
25967
26070
|
continue;
|
|
25968
26071
|
}
|
|
@@ -25988,7 +26091,7 @@ function* walkAgy() {
|
|
|
25988
26091
|
return;
|
|
25989
26092
|
let sessionDirs = [];
|
|
25990
26093
|
try {
|
|
25991
|
-
sessionDirs =
|
|
26094
|
+
sessionDirs = readdirSync33(brainDir);
|
|
25992
26095
|
} catch {
|
|
25993
26096
|
return;
|
|
25994
26097
|
}
|
|
@@ -29328,7 +29431,7 @@ toolkit.command("sync").description("Fan every artifact out to every tool that i
|
|
|
29328
29431
|
console.log(chalk2.bold(`Synced: ${r.copied.length} copied, ${r.skipped.length} already present, ${r.failed.length} failed.`));
|
|
29329
29432
|
if (r.copied.length > 0) await pushToolkitToServer();
|
|
29330
29433
|
});
|
|
29331
|
-
toolkit.command("pull").description("Install artifacts this device is missing, from the server (cross-device setup)").option("--types <list>", "comma-separated subset: mcp").option("--dry-run", "report what would change, write nothing").action(async (options) => {
|
|
29434
|
+
toolkit.command("pull").description("Install artifacts this device is missing, from the server (cross-device setup)").option("--types <list>", "comma-separated subset: mcp").option("--dry-run", "report what would change, write nothing").option("--mcp <names>", "comma-separated MCP servers to install even if only another platform registered them").action(async (options) => {
|
|
29332
29435
|
const { loadAllCredentials: loadAllCredentials2 } = await Promise.resolve().then(() => (init_sync_client(), sync_client_exports));
|
|
29333
29436
|
const { executePull: executePull2 } = await Promise.resolve().then(() => (init_toolkit_pull(), toolkit_pull_exports));
|
|
29334
29437
|
const { hostname: hostname3 } = await import("node:os");
|
|
@@ -29357,7 +29460,8 @@ toolkit.command("pull").description("Install artifacts this device is missing, f
|
|
|
29357
29460
|
return;
|
|
29358
29461
|
}
|
|
29359
29462
|
const types = options.types ? options.types.split(",").map((x) => x.trim()).filter(Boolean) : void 0;
|
|
29360
|
-
const
|
|
29463
|
+
const explicit = options.mcp ? options.mcp.split(",").map((x) => x.trim()).filter(Boolean) : void 0;
|
|
29464
|
+
const report = executePull2(rows, { thisDeviceId: hostname3(), types, dryRun: options.dryRun, explicit });
|
|
29361
29465
|
const written = report.outcomes.filter((o) => o.status === "written");
|
|
29362
29466
|
const present = report.outcomes.filter((o) => o.status === "present");
|
|
29363
29467
|
const failed = report.outcomes.filter((o) => o.status === "failed");
|