chat-recall 0.5.21 → 0.5.23
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 +398 -271
- package/dist/cli.js.map +1 -1
- package/dist/conformant-server.d.ts +17 -0
- package/dist/conformant-server.d.ts.map +1 -0
- package/dist/conformant-server.js +116 -0
- package/dist/conformant-server.js.map +1 -0
- package/dist/device-auth.d.ts +0 -4
- package/dist/device-auth.d.ts.map +1 -1
- package/dist/device-auth.js +43 -2
- package/dist/device-auth.js.map +1 -1
- package/dist/hostile-server.d.ts +47 -0
- package/dist/hostile-server.d.ts.map +1 -0
- package/dist/hostile-server.js +95 -0
- package/dist/hostile-server.js.map +1 -0
- package/dist/install-report.d.ts +21 -0
- package/dist/install-report.d.ts.map +1 -0
- package/dist/install-report.js +76 -0
- package/dist/install-report.js.map +1 -0
- package/dist/mcp.js +160 -8
- package/dist/server-probe.d.ts +35 -1
- package/dist/server-probe.d.ts.map +1 -1
- package/dist/server-probe.js +124 -3
- package/dist/server-probe.js.map +1 -1
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +47 -2
- package/dist/sync-client.js.map +1 -1
- package/dist/watch.js +250 -103
- package/package.json +2 -2
package/dist/watch.js
CHANGED
|
@@ -14306,8 +14306,11 @@ function isInside(child, parent) {
|
|
|
14306
14306
|
return c.startsWith(p);
|
|
14307
14307
|
}
|
|
14308
14308
|
function globMatch(pattern, path) {
|
|
14309
|
-
const re = new RegExp("^" + globToRegex(pattern) + "$");
|
|
14310
|
-
return re.test(path);
|
|
14309
|
+
const re = new RegExp("^" + globToRegex(toPosix(pattern)) + "$");
|
|
14310
|
+
return re.test(toPosix(path));
|
|
14311
|
+
}
|
|
14312
|
+
function toPosix(p) {
|
|
14313
|
+
return p.replace(/\\/g, "/");
|
|
14311
14314
|
}
|
|
14312
14315
|
function globToRegex(glob) {
|
|
14313
14316
|
let out = "";
|
|
@@ -19210,7 +19213,7 @@ var init_http = __esm({
|
|
|
19210
19213
|
CLI_VERSION = JSON.parse(readFileSync33(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
19211
19214
|
} catch {
|
|
19212
19215
|
try {
|
|
19213
|
-
if (true) CLI_VERSION = "0.5.
|
|
19216
|
+
if (true) CLI_VERSION = "0.5.23";
|
|
19214
19217
|
} catch {
|
|
19215
19218
|
}
|
|
19216
19219
|
}
|
|
@@ -19718,7 +19721,7 @@ var init_telemetry = __esm({
|
|
|
19718
19721
|
init_sync_client();
|
|
19719
19722
|
cliVersion = () => {
|
|
19720
19723
|
try {
|
|
19721
|
-
return true ? "0.5.
|
|
19724
|
+
return true ? "0.5.23" : "dev";
|
|
19722
19725
|
} catch {
|
|
19723
19726
|
return "dev";
|
|
19724
19727
|
}
|
|
@@ -19782,6 +19785,143 @@ var init_collector_health = __esm({
|
|
|
19782
19785
|
}
|
|
19783
19786
|
});
|
|
19784
19787
|
|
|
19788
|
+
// src/server-probe.ts
|
|
19789
|
+
var server_probe_exports = {};
|
|
19790
|
+
__export(server_probe_exports, {
|
|
19791
|
+
classifyUnreachable: () => classifyUnreachable,
|
|
19792
|
+
describeCause: () => describeCause,
|
|
19793
|
+
describeUnreachable: () => describeUnreachable,
|
|
19794
|
+
probeAdvice: () => probeAdvice,
|
|
19795
|
+
probeOk: () => probeOk,
|
|
19796
|
+
probeServer: () => probeServer
|
|
19797
|
+
});
|
|
19798
|
+
function probeOk(r) {
|
|
19799
|
+
return r.kind === "ok" && r.apiVersion >= 2;
|
|
19800
|
+
}
|
|
19801
|
+
async function probeServer(base2, opts = {}) {
|
|
19802
|
+
const f = opts.fetchImpl || fetch;
|
|
19803
|
+
let res;
|
|
19804
|
+
try {
|
|
19805
|
+
res = await f(`${base2.replace(/\/+$/, "")}/api/capabilities`, {
|
|
19806
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? 1e4)
|
|
19807
|
+
});
|
|
19808
|
+
} catch (err) {
|
|
19809
|
+
return {
|
|
19810
|
+
kind: "unreachable",
|
|
19811
|
+
error: describeCause(err),
|
|
19812
|
+
reason: classifyUnreachable(err)
|
|
19813
|
+
};
|
|
19814
|
+
}
|
|
19815
|
+
if (res.status === 401 || res.status === 403) return { kind: "unauthorized", status: res.status };
|
|
19816
|
+
if (res.status === 404 || res.status === 410) return { kind: "moved", status: res.status };
|
|
19817
|
+
if (res.status >= 500) return { kind: "server_error", status: res.status };
|
|
19818
|
+
if (!res.ok) return { kind: "moved", status: res.status };
|
|
19819
|
+
let body;
|
|
19820
|
+
try {
|
|
19821
|
+
body = await res.text();
|
|
19822
|
+
} catch (err) {
|
|
19823
|
+
return { kind: "unreachable", error: describeCause(err), reason: classifyUnreachable(err) };
|
|
19824
|
+
}
|
|
19825
|
+
let parsed;
|
|
19826
|
+
try {
|
|
19827
|
+
parsed = JSON.parse(body);
|
|
19828
|
+
} catch {
|
|
19829
|
+
return { kind: "not_api", status: res.status, snippet: body.trim().slice(0, 60) };
|
|
19830
|
+
}
|
|
19831
|
+
if (typeof parsed?.apiVersion !== "number") {
|
|
19832
|
+
return { kind: "not_api", status: res.status, snippet: body.trim().slice(0, 60) };
|
|
19833
|
+
}
|
|
19834
|
+
return {
|
|
19835
|
+
kind: "ok",
|
|
19836
|
+
apiVersion: parsed.apiVersion,
|
|
19837
|
+
edition: parsed.edition,
|
|
19838
|
+
cliVersion: parsed.cli?.version,
|
|
19839
|
+
raw: parsed
|
|
19840
|
+
};
|
|
19841
|
+
}
|
|
19842
|
+
function probeAdvice(r, base2) {
|
|
19843
|
+
switch (r.kind) {
|
|
19844
|
+
case "ok":
|
|
19845
|
+
return r.apiVersion >= 2 ? `apiVersion ${r.apiVersion}${r.edition ? `, edition ${r.edition}` : ""}` : `apiVersion ${r.apiVersion} is too old for this CLI \u2014 upgrade the server`;
|
|
19846
|
+
case "moved":
|
|
19847
|
+
return `HTTP ${r.status} \u2014 nothing is served at ${base2}. If the host moved, re-point it: \`chat-recall login <new-server-url>\``;
|
|
19848
|
+
case "unauthorized":
|
|
19849
|
+
return `HTTP ${r.status} \u2014 ${base2} rejected the credential. Re-login: \`chat-recall login ` + base2 + "`";
|
|
19850
|
+
case "server_error":
|
|
19851
|
+
return `HTTP ${r.status} \u2014 ${base2} is up but failing. Nothing to fix locally; check the server.`;
|
|
19852
|
+
case "not_api":
|
|
19853
|
+
return `${base2} answered ${r.status} with something that is not the chat-recall API (${JSON.stringify(r.snippet)}) \u2014 check the URL, a proxy or a captive portal`;
|
|
19854
|
+
case "unreachable":
|
|
19855
|
+
switch (r.reason) {
|
|
19856
|
+
case "dns":
|
|
19857
|
+
return `cannot resolve the host in ${base2} (${r.error}) \u2014 check the URL for a typo, and your DNS or VPN`;
|
|
19858
|
+
case "refused":
|
|
19859
|
+
return `${base2} resolves but refused the connection (${r.error}) \u2014 the server is not running, or the port is wrong`;
|
|
19860
|
+
case "tls":
|
|
19861
|
+
return `the TLS certificate at ${base2} was rejected (${r.error}) \u2014 expired, self-signed, or issued for another host. A corporate proxy that re-signs traffic does this.`;
|
|
19862
|
+
case "timeout":
|
|
19863
|
+
return `${base2} did not answer in time (${r.error}) \u2014 a firewall or proxy that drops traffic silently looks exactly like this`;
|
|
19864
|
+
case "reset":
|
|
19865
|
+
return `the connection to ${base2} was cut (${r.error}) \u2014 often a proxy or a captive portal`;
|
|
19866
|
+
case "bad_port":
|
|
19867
|
+
return `${base2} names a port that Node and every browser refuse to open (the WHATWG bad-port list) \u2014 use the server's real port`;
|
|
19868
|
+
default:
|
|
19869
|
+
return `no HTTP response from ${base2} (${r.error}) \u2014 check the URL, DNS, or that the server is running`;
|
|
19870
|
+
}
|
|
19871
|
+
}
|
|
19872
|
+
}
|
|
19873
|
+
function classifyUnreachable(err) {
|
|
19874
|
+
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) return "timeout";
|
|
19875
|
+
for (const e of walkErrorChain(err)) {
|
|
19876
|
+
const code = String(e.code ?? "");
|
|
19877
|
+
const msg = String(e.message ?? "");
|
|
19878
|
+
if (code === "ENOTFOUND" || code === "EAI_AGAIN") return "dns";
|
|
19879
|
+
if (code === "ECONNREFUSED") return "refused";
|
|
19880
|
+
if (code === "ECONNRESET" || code === "EPIPE") return "reset";
|
|
19881
|
+
if (code === "ETIMEDOUT" || code === "UND_ERR_CONNECT_TIMEOUT" || code === "UND_ERR_HEADERS_TIMEOUT") return "timeout";
|
|
19882
|
+
if (code.startsWith("CERT_") || code.startsWith("ERR_TLS") || code === "DEPTH_ZERO_SELF_SIGNED_CERT" || code === "SELF_SIGNED_CERT_IN_CHAIN" || code === "UNABLE_TO_VERIFY_LEAF_SIGNATURE" || /certificate/i.test(msg)) return "tls";
|
|
19883
|
+
if (/^bad port$/i.test(msg)) return "bad_port";
|
|
19884
|
+
}
|
|
19885
|
+
return "unknown";
|
|
19886
|
+
}
|
|
19887
|
+
function* walkErrorChain(err, depth = 0) {
|
|
19888
|
+
if (!err || typeof err !== "object" || depth > 5) return;
|
|
19889
|
+
yield err;
|
|
19890
|
+
const members = err.errors;
|
|
19891
|
+
if (Array.isArray(members)) {
|
|
19892
|
+
for (const m of members) yield* walkErrorChain(m, depth + 1);
|
|
19893
|
+
}
|
|
19894
|
+
yield* walkErrorChain(err.cause, depth + 1);
|
|
19895
|
+
}
|
|
19896
|
+
function describeCause(err) {
|
|
19897
|
+
const parts = [];
|
|
19898
|
+
for (const e of walkErrorChain(err)) {
|
|
19899
|
+
const code = e.code;
|
|
19900
|
+
if (typeof code === "string" && code && !parts.includes(code)) parts.push(code);
|
|
19901
|
+
}
|
|
19902
|
+
const base2 = err instanceof Error ? err.message : String(err);
|
|
19903
|
+
return parts.length ? `${base2}: ${parts.join(" \u2192 ")}` : base2;
|
|
19904
|
+
}
|
|
19905
|
+
function describeUnreachable(err) {
|
|
19906
|
+
const reason = classifyUnreachable(err);
|
|
19907
|
+
const detail = describeCause(err);
|
|
19908
|
+
const phrase = {
|
|
19909
|
+
dns: "the host name does not resolve",
|
|
19910
|
+
refused: "the connection was refused \u2014 nothing is listening there",
|
|
19911
|
+
tls: "the TLS certificate was rejected",
|
|
19912
|
+
timeout: "no answer before the timeout",
|
|
19913
|
+
reset: "the connection was cut mid-request",
|
|
19914
|
+
bad_port: "that port is one Node and every browser refuse to open",
|
|
19915
|
+
unknown: "no HTTP response"
|
|
19916
|
+
};
|
|
19917
|
+
return `${phrase[reason]} (${detail})`;
|
|
19918
|
+
}
|
|
19919
|
+
var init_server_probe = __esm({
|
|
19920
|
+
"src/server-probe.ts"() {
|
|
19921
|
+
"use strict";
|
|
19922
|
+
}
|
|
19923
|
+
});
|
|
19924
|
+
|
|
19785
19925
|
// src/client-events.ts
|
|
19786
19926
|
var client_events_exports = {};
|
|
19787
19927
|
__export(client_events_exports, {
|
|
@@ -20143,6 +20283,7 @@ async function fetchTenantSyncConfig(cred) {
|
|
|
20143
20283
|
persistSyncConfig(base2, config);
|
|
20144
20284
|
return config;
|
|
20145
20285
|
} catch (err) {
|
|
20286
|
+
if (isSyncRulesRefusal(err)) throw err;
|
|
20146
20287
|
return lastKnownSyncConfig(base2, err instanceof Error ? err.message : "request failed");
|
|
20147
20288
|
}
|
|
20148
20289
|
}
|
|
@@ -20152,9 +20293,14 @@ function lastKnownSyncConfig(base2, reason) {
|
|
|
20152
20293
|
console.error(`[sync] could not read server-side sync rules (${reason}) \u2014 applying the last known set from ${new Date(remembered.fetchedAt).toISOString()}`);
|
|
20153
20294
|
return remembered.config;
|
|
20154
20295
|
}
|
|
20155
|
-
|
|
20296
|
+
const refusal = new Error(
|
|
20156
20297
|
`Cannot read the server-side sync rules from ${base2} (${reason}), and this machine has never successfully read them. Refusing to sync: uploading without knowing your exclusions could ship a project you told the dashboard to hold back. Fix the server or retry.`
|
|
20157
20298
|
);
|
|
20299
|
+
refusal[SYNC_RULES_REFUSAL] = true;
|
|
20300
|
+
throw refusal;
|
|
20301
|
+
}
|
|
20302
|
+
function isSyncRulesRefusal(err) {
|
|
20303
|
+
return !!err && typeof err === "object" && err[SYNC_RULES_REFUSAL] === true;
|
|
20158
20304
|
}
|
|
20159
20305
|
function deviceLabel() {
|
|
20160
20306
|
try {
|
|
@@ -20378,7 +20524,12 @@ async function verifyServerApi(serverUrl, minApi) {
|
|
|
20378
20524
|
const base2 = serverUrl.replace(/\/$/, "");
|
|
20379
20525
|
const seen = capsOk.get(base2);
|
|
20380
20526
|
if (seen !== void 0 && Date.now() - seen < CAPS_TTL_MS) return true;
|
|
20381
|
-
const
|
|
20527
|
+
const { probeServer: probeServer2, probeAdvice: probeAdvice2 } = await Promise.resolve().then(() => (init_server_probe(), server_probe_exports));
|
|
20528
|
+
const probe = await probeServer2(base2, {
|
|
20529
|
+
fetchImpl: ((url, init) => fetchWithTimeout(String(url), init ?? {}))
|
|
20530
|
+
});
|
|
20531
|
+
if (probe.kind !== "ok") throw new Error(probeAdvice2(probe, base2));
|
|
20532
|
+
const caps = probe.raw;
|
|
20382
20533
|
if ((caps.apiVersion ?? 0) < minApi) {
|
|
20383
20534
|
throw new Error(`server too old: apiVersion ${caps.apiVersion ?? "none"} < required ${minApi} \u2014 update the server image before syncing`);
|
|
20384
20535
|
}
|
|
@@ -21368,7 +21519,7 @@ async function syncIncremental(opts = {}) {
|
|
|
21368
21519
|
lock.release();
|
|
21369
21520
|
}
|
|
21370
21521
|
}
|
|
21371
|
-
var ownVersion, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, hashPath, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES, FULL_BUILD_TAIL_BYTES, BATCH_SCAN_MAX_BYTES;
|
|
21522
|
+
var ownVersion, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, SYNC_RULES_REFUSAL, hashPath, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES, FULL_BUILD_TAIL_BYTES, BATCH_SCAN_MAX_BYTES;
|
|
21372
21523
|
var init_sync_client = __esm({
|
|
21373
21524
|
"src/sync-client.ts"() {
|
|
21374
21525
|
"use strict";
|
|
@@ -21414,7 +21565,7 @@ var init_sync_client = __esm({
|
|
|
21414
21565
|
ownVersion = JSON.parse(readFileSync37(join44(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21415
21566
|
} catch {
|
|
21416
21567
|
try {
|
|
21417
|
-
if (true) ownVersion = "0.5.
|
|
21568
|
+
if (true) ownVersion = "0.5.23";
|
|
21418
21569
|
} catch {
|
|
21419
21570
|
}
|
|
21420
21571
|
}
|
|
@@ -21425,6 +21576,7 @@ var init_sync_client = __esm({
|
|
|
21425
21576
|
SECURITY_CONFIG_TTL_MS = 5 * 60 * 1e3;
|
|
21426
21577
|
_syncConfigCache = /* @__PURE__ */ new Map();
|
|
21427
21578
|
EMPTY_SYNC_CONFIG = { excludeTools: [], excludeProjects: [], excludeSources: [], approveSources: [] };
|
|
21579
|
+
SYNC_RULES_REFUSAL = /* @__PURE__ */ Symbol.for("chat-recall.syncRulesRefusal");
|
|
21428
21580
|
hashPath = (p) => p ? "p_" + createHash12("sha256").update(p).digest("hex").slice(0, 12) : "";
|
|
21429
21581
|
MAX_DERIVED_ROW_BYTES = 2 * 1024 * 1024;
|
|
21430
21582
|
isLocalHost = isPrivateHost;
|
|
@@ -22012,6 +22164,65 @@ var init_toolkit_sync = __esm({
|
|
|
22012
22164
|
}
|
|
22013
22165
|
});
|
|
22014
22166
|
|
|
22167
|
+
// ../engine/dist/core/which.js
|
|
22168
|
+
import { existsSync as existsSync45, statSync as statSync40, accessSync, constants } from "node:fs";
|
|
22169
|
+
import { join as join48, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep2 } from "node:path";
|
|
22170
|
+
function executable(p) {
|
|
22171
|
+
try {
|
|
22172
|
+
if (!statSync40(p).isFile())
|
|
22173
|
+
return false;
|
|
22174
|
+
} catch {
|
|
22175
|
+
return false;
|
|
22176
|
+
}
|
|
22177
|
+
if (isWindows)
|
|
22178
|
+
return true;
|
|
22179
|
+
try {
|
|
22180
|
+
accessSync(p, constants.X_OK);
|
|
22181
|
+
return true;
|
|
22182
|
+
} catch {
|
|
22183
|
+
return false;
|
|
22184
|
+
}
|
|
22185
|
+
}
|
|
22186
|
+
function candidates(name) {
|
|
22187
|
+
if (!isWindows)
|
|
22188
|
+
return [name];
|
|
22189
|
+
const exts = (process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").map((e) => e.trim()).filter(Boolean);
|
|
22190
|
+
if (exts.some((e) => name.toLowerCase().endsWith(e.toLowerCase())))
|
|
22191
|
+
return [name];
|
|
22192
|
+
return exts.map((e) => name + e);
|
|
22193
|
+
}
|
|
22194
|
+
function resolveOnPath(name) {
|
|
22195
|
+
if (!name)
|
|
22196
|
+
return null;
|
|
22197
|
+
if (name.includes("/") || isWindows && name.includes(sep2) || isAbsolute2(name)) {
|
|
22198
|
+
for (const c of candidates(name))
|
|
22199
|
+
if (executable(c))
|
|
22200
|
+
return c;
|
|
22201
|
+
return null;
|
|
22202
|
+
}
|
|
22203
|
+
for (const raw of (process.env.PATH || "").split(delimiter2)) {
|
|
22204
|
+
const dir = raw.replace(/^"(.*)"$/, "$1");
|
|
22205
|
+
if (!dir)
|
|
22206
|
+
continue;
|
|
22207
|
+
for (const c of candidates(name)) {
|
|
22208
|
+
const full = join48(dir, c);
|
|
22209
|
+
if (existsSync45(full) && executable(full))
|
|
22210
|
+
return full;
|
|
22211
|
+
}
|
|
22212
|
+
}
|
|
22213
|
+
return null;
|
|
22214
|
+
}
|
|
22215
|
+
function isOnPath(name) {
|
|
22216
|
+
return resolveOnPath(name) !== null;
|
|
22217
|
+
}
|
|
22218
|
+
var isWindows;
|
|
22219
|
+
var init_which = __esm({
|
|
22220
|
+
"../engine/dist/core/which.js"() {
|
|
22221
|
+
"use strict";
|
|
22222
|
+
isWindows = process.platform === "win32";
|
|
22223
|
+
}
|
|
22224
|
+
});
|
|
22225
|
+
|
|
22015
22226
|
// ../engine/dist/core/toolkit-pull.js
|
|
22016
22227
|
var toolkit_pull_exports = {};
|
|
22017
22228
|
__export(toolkit_pull_exports, {
|
|
@@ -22020,26 +22231,20 @@ __export(toolkit_pull_exports, {
|
|
|
22020
22231
|
planPull: () => planPull,
|
|
22021
22232
|
portableCommand: () => portableCommand
|
|
22022
22233
|
});
|
|
22023
|
-
import { existsSync as
|
|
22024
|
-
import {
|
|
22234
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync12, statSync as statSync41, writeFileSync as writeFileSync12 } from "node:fs";
|
|
22235
|
+
import { dirname as dirname22, join as join49, basename as basename24, isAbsolute as isAbsolute3 } from "node:path";
|
|
22025
22236
|
function isExecutableFile(p) {
|
|
22026
22237
|
try {
|
|
22027
|
-
return
|
|
22238
|
+
return statSync41(p).isFile();
|
|
22028
22239
|
} catch {
|
|
22029
22240
|
return false;
|
|
22030
22241
|
}
|
|
22031
22242
|
}
|
|
22032
22243
|
function onPath(name) {
|
|
22033
|
-
|
|
22034
|
-
for (const d of dirs) {
|
|
22035
|
-
const candidate = join48(d, name);
|
|
22036
|
-
if (isExecutableFile(candidate))
|
|
22037
|
-
return candidate;
|
|
22038
|
-
}
|
|
22039
|
-
return null;
|
|
22244
|
+
return resolveOnPath(name);
|
|
22040
22245
|
}
|
|
22041
22246
|
function portableCommand(cmd) {
|
|
22042
|
-
if (!
|
|
22247
|
+
if (!isAbsolute3(cmd)) {
|
|
22043
22248
|
return onPath(cmd) ? { command: cmd, rewritten: false } : { missing: cmd };
|
|
22044
22249
|
}
|
|
22045
22250
|
if (isExecutableFile(cmd))
|
|
@@ -22177,9 +22382,9 @@ function executePull(rows, opts = {}) {
|
|
|
22177
22382
|
const outcomes = [];
|
|
22178
22383
|
for (const { name, body, truncated, redacted, tools } of skills) {
|
|
22179
22384
|
for (const tool of tools) {
|
|
22180
|
-
const dir =
|
|
22181
|
-
const file =
|
|
22182
|
-
if (
|
|
22385
|
+
const dir = join49(skillsDirFor(tool), name);
|
|
22386
|
+
const file = join49(dir, "SKILL.md");
|
|
22387
|
+
if (existsSync46(file)) {
|
|
22183
22388
|
outcomes.push({ type: "skill", name, tool, status: "present" });
|
|
22184
22389
|
continue;
|
|
22185
22390
|
}
|
|
@@ -22224,7 +22429,7 @@ function executePull(rows, opts = {}) {
|
|
|
22224
22429
|
outcomes.push({ type, name, tool, status: "failed", reason: e instanceof Error ? e.message : "emit failed" });
|
|
22225
22430
|
continue;
|
|
22226
22431
|
}
|
|
22227
|
-
if (
|
|
22432
|
+
if (existsSync46(out.path)) {
|
|
22228
22433
|
outcomes.push({ type, name, tool, status: "present" });
|
|
22229
22434
|
continue;
|
|
22230
22435
|
}
|
|
@@ -22298,6 +22503,7 @@ var NOT_REBUILDABLE;
|
|
|
22298
22503
|
var init_toolkit_pull = __esm({
|
|
22299
22504
|
"../engine/dist/core/toolkit-pull.js"() {
|
|
22300
22505
|
"use strict";
|
|
22506
|
+
init_which();
|
|
22301
22507
|
init_toolkit_sync();
|
|
22302
22508
|
init_artifact_codec();
|
|
22303
22509
|
NOT_REBUILDABLE = {
|
|
@@ -22523,8 +22729,8 @@ __export(shadow_prune_exports, {
|
|
|
22523
22729
|
DEFAULT_MAX_TOTAL_BYTES: () => DEFAULT_MAX_TOTAL_BYTES,
|
|
22524
22730
|
pruneShadow: () => pruneShadow
|
|
22525
22731
|
});
|
|
22526
|
-
import { readdirSync as readdirSync33, statSync as
|
|
22527
|
-
import { join as
|
|
22732
|
+
import { readdirSync as readdirSync33, statSync as statSync43, unlinkSync as unlinkSync3 } from "fs";
|
|
22733
|
+
import { join as join52 } from "path";
|
|
22528
22734
|
function listShadows(isFullyAcked) {
|
|
22529
22735
|
const out = [];
|
|
22530
22736
|
const root = shadowRoot();
|
|
@@ -22535,7 +22741,7 @@ function listShadows(isFullyAcked) {
|
|
|
22535
22741
|
return out;
|
|
22536
22742
|
}
|
|
22537
22743
|
for (const tool of tools) {
|
|
22538
|
-
const dir =
|
|
22744
|
+
const dir = join52(root, tool);
|
|
22539
22745
|
let names;
|
|
22540
22746
|
try {
|
|
22541
22747
|
names = readdirSync33(dir);
|
|
@@ -22545,10 +22751,10 @@ function listShadows(isFullyAcked) {
|
|
|
22545
22751
|
for (const name of names) {
|
|
22546
22752
|
if (!name.endsWith(".gz"))
|
|
22547
22753
|
continue;
|
|
22548
|
-
const path =
|
|
22754
|
+
const path = join52(dir, name);
|
|
22549
22755
|
let st;
|
|
22550
22756
|
try {
|
|
22551
|
-
st =
|
|
22757
|
+
st = statSync43(path);
|
|
22552
22758
|
} catch {
|
|
22553
22759
|
continue;
|
|
22554
22760
|
}
|
|
@@ -22662,65 +22868,6 @@ var init_code_intel = __esm({
|
|
|
22662
22868
|
}
|
|
22663
22869
|
});
|
|
22664
22870
|
|
|
22665
|
-
// ../engine/dist/core/which.js
|
|
22666
|
-
import { existsSync as existsSync48, statSync as statSync43, accessSync, constants } from "node:fs";
|
|
22667
|
-
import { join as join52, isAbsolute as isAbsolute3, delimiter as delimiter3, sep as sep2 } from "node:path";
|
|
22668
|
-
function executable(p) {
|
|
22669
|
-
try {
|
|
22670
|
-
if (!statSync43(p).isFile())
|
|
22671
|
-
return false;
|
|
22672
|
-
} catch {
|
|
22673
|
-
return false;
|
|
22674
|
-
}
|
|
22675
|
-
if (isWindows)
|
|
22676
|
-
return true;
|
|
22677
|
-
try {
|
|
22678
|
-
accessSync(p, constants.X_OK);
|
|
22679
|
-
return true;
|
|
22680
|
-
} catch {
|
|
22681
|
-
return false;
|
|
22682
|
-
}
|
|
22683
|
-
}
|
|
22684
|
-
function candidates(name) {
|
|
22685
|
-
if (!isWindows)
|
|
22686
|
-
return [name];
|
|
22687
|
-
const exts = (process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").map((e) => e.trim()).filter(Boolean);
|
|
22688
|
-
if (exts.some((e) => name.toLowerCase().endsWith(e.toLowerCase())))
|
|
22689
|
-
return [name];
|
|
22690
|
-
return exts.map((e) => name + e);
|
|
22691
|
-
}
|
|
22692
|
-
function resolveOnPath(name) {
|
|
22693
|
-
if (!name)
|
|
22694
|
-
return null;
|
|
22695
|
-
if (name.includes("/") || isWindows && name.includes(sep2) || isAbsolute3(name)) {
|
|
22696
|
-
for (const c of candidates(name))
|
|
22697
|
-
if (executable(c))
|
|
22698
|
-
return c;
|
|
22699
|
-
return null;
|
|
22700
|
-
}
|
|
22701
|
-
for (const raw of (process.env.PATH || "").split(delimiter3)) {
|
|
22702
|
-
const dir = raw.replace(/^"(.*)"$/, "$1");
|
|
22703
|
-
if (!dir)
|
|
22704
|
-
continue;
|
|
22705
|
-
for (const c of candidates(name)) {
|
|
22706
|
-
const full = join52(dir, c);
|
|
22707
|
-
if (existsSync48(full) && executable(full))
|
|
22708
|
-
return full;
|
|
22709
|
-
}
|
|
22710
|
-
}
|
|
22711
|
-
return null;
|
|
22712
|
-
}
|
|
22713
|
-
function isOnPath(name) {
|
|
22714
|
-
return resolveOnPath(name) !== null;
|
|
22715
|
-
}
|
|
22716
|
-
var isWindows;
|
|
22717
|
-
var init_which = __esm({
|
|
22718
|
-
"../engine/dist/core/which.js"() {
|
|
22719
|
-
"use strict";
|
|
22720
|
-
isWindows = process.platform === "win32";
|
|
22721
|
-
}
|
|
22722
|
-
});
|
|
22723
|
-
|
|
22724
22871
|
// ../engine/dist/core/companions.js
|
|
22725
22872
|
import { existsSync as existsSync49, mkdirSync as mkdirSync15, statSync as statSync44, chmodSync as chmodSync4, unlinkSync as unlinkSync4, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync44, writeFileSync as writeFileSync15 } from "node:fs";
|
|
22726
22873
|
import { homedir as homedir19 } from "node:os";
|
|
@@ -23929,8 +24076,8 @@ import { homedir as homedir20 } from "os";
|
|
|
23929
24076
|
init_http();
|
|
23930
24077
|
init_sync_client();
|
|
23931
24078
|
init_toolkit_sync();
|
|
23932
|
-
import { existsSync as
|
|
23933
|
-
import { join as
|
|
24079
|
+
import { existsSync as existsSync47, readFileSync as readFileSync41, writeFileSync as writeFileSync13, appendFileSync, mkdirSync as mkdirSync13 } from "node:fs";
|
|
24080
|
+
import { join as join50 } from "node:path";
|
|
23934
24081
|
import { homedir as homedir18 } from "node:os";
|
|
23935
24082
|
|
|
23936
24083
|
// src/project-tasks.ts
|
|
@@ -24090,7 +24237,7 @@ function applyCodeRecommendation(intent) {
|
|
|
24090
24237
|
const meta = JSON.parse(intent.name || "{}");
|
|
24091
24238
|
if (intent.artifact_type === "write_tasks_file") {
|
|
24092
24239
|
if (!meta.rootPath || !meta.content) return { status: "error", result: JSON.stringify({ error: "missing rootPath or content" }) };
|
|
24093
|
-
const file =
|
|
24240
|
+
const file = join50(meta.rootPath, meta.filename || "CODE_TASKS.md");
|
|
24094
24241
|
writeFileSync13(file, meta.content);
|
|
24095
24242
|
return { status: "done", result: JSON.stringify({ wrote: file }) };
|
|
24096
24243
|
}
|
|
@@ -24100,17 +24247,17 @@ function applyCodeRecommendation(intent) {
|
|
|
24100
24247
|
if (!text) return { status: "error", result: JSON.stringify({ error: "missing text" }) };
|
|
24101
24248
|
let file;
|
|
24102
24249
|
if (isGlobal) {
|
|
24103
|
-
const dir =
|
|
24250
|
+
const dir = join50(homedir18(), ".claude");
|
|
24104
24251
|
try {
|
|
24105
24252
|
mkdirSync13(dir, { recursive: true });
|
|
24106
24253
|
} catch {
|
|
24107
24254
|
}
|
|
24108
|
-
file =
|
|
24255
|
+
file = join50(dir, "CLAUDE.md");
|
|
24109
24256
|
} else {
|
|
24110
24257
|
if (!meta.rootPath) return { status: "error", result: JSON.stringify({ error: "missing rootPath" }) };
|
|
24111
|
-
file =
|
|
24258
|
+
file = join50(meta.rootPath, "CLAUDE.md");
|
|
24112
24259
|
}
|
|
24113
|
-
const existing =
|
|
24260
|
+
const existing = existsSync47(file) ? readFileSync41(file, "utf8") : "";
|
|
24114
24261
|
if (existing.includes(text)) return { status: "done", result: JSON.stringify({ skipped: "rule already present", file }) };
|
|
24115
24262
|
const block = `${existing && !existing.endsWith("\n") ? "\n" : ""}
|
|
24116
24263
|
## Rule (added by chat-recall recommendation)
|
|
@@ -24204,10 +24351,10 @@ async function runIntent(intent, ctx) {
|
|
|
24204
24351
|
var ownVersion2 = "0.0.0";
|
|
24205
24352
|
try {
|
|
24206
24353
|
const dir = dirname23(fileURLToPath4(import.meta.url));
|
|
24207
|
-
ownVersion2 = JSON.parse(readFileSync41(
|
|
24354
|
+
ownVersion2 = JSON.parse(readFileSync41(join50(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
24208
24355
|
} catch {
|
|
24209
24356
|
try {
|
|
24210
|
-
if (true) ownVersion2 = "0.5.
|
|
24357
|
+
if (true) ownVersion2 = "0.5.23";
|
|
24211
24358
|
} catch {
|
|
24212
24359
|
}
|
|
24213
24360
|
}
|
|
@@ -24272,8 +24419,8 @@ init_auto_update();
|
|
|
24272
24419
|
// src/code-index-cursor.ts
|
|
24273
24420
|
init_paths();
|
|
24274
24421
|
import { readFileSync as readFileSync42, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14 } from "fs";
|
|
24275
|
-
import { join as
|
|
24276
|
-
var cursorPath = () =>
|
|
24422
|
+
import { join as join51, dirname as dirname24 } from "path";
|
|
24423
|
+
var cursorPath = () => join51(getDataDir(), "code-index-cursor.json");
|
|
24277
24424
|
function readCursor() {
|
|
24278
24425
|
try {
|
|
24279
24426
|
const raw = JSON.parse(readFileSync42(cursorPath(), "utf-8"));
|
|
@@ -24491,11 +24638,11 @@ function checkSelfRestart(opts) {
|
|
|
24491
24638
|
}
|
|
24492
24639
|
|
|
24493
24640
|
// src/log-rotate.ts
|
|
24494
|
-
import { statSync as
|
|
24641
|
+
import { statSync as statSync42, copyFileSync as copyFileSync3, truncateSync } from "fs";
|
|
24495
24642
|
var LOG_MAX_BYTES = 32 * 1024 * 1024;
|
|
24496
24643
|
function rotateLogIfLarge(logPath, maxBytes = LOG_MAX_BYTES) {
|
|
24497
24644
|
try {
|
|
24498
|
-
const size =
|
|
24645
|
+
const size = statSync42(logPath).size;
|
|
24499
24646
|
if (size < maxBytes) return { rotated: false, sizeBefore: 0 };
|
|
24500
24647
|
copyFileSync3(logPath, `${logPath}.1`);
|
|
24501
24648
|
truncateSync(logPath, 0);
|
|
@@ -24507,8 +24654,8 @@ function rotateLogIfLarge(logPath, maxBytes = LOG_MAX_BYTES) {
|
|
|
24507
24654
|
|
|
24508
24655
|
// src/collector-migrate.ts
|
|
24509
24656
|
init_http();
|
|
24510
|
-
import { existsSync as
|
|
24511
|
-
function selectProjectsToReindex(projects, current, existsFn =
|
|
24657
|
+
import { existsSync as existsSync48 } from "node:fs";
|
|
24658
|
+
function selectProjectsToReindex(projects, current, existsFn = existsSync48) {
|
|
24512
24659
|
const reindex = [];
|
|
24513
24660
|
const missing = [];
|
|
24514
24661
|
for (const p of projects) {
|
|
@@ -24551,7 +24698,7 @@ async function runCollectorMigration(opts) {
|
|
|
24551
24698
|
init_sync_ledger();
|
|
24552
24699
|
init_collector_health();
|
|
24553
24700
|
import { existsSync as existsSync50, readFileSync as readFileSync46 } from "fs";
|
|
24554
|
-
var CLI_VERSION3 = true ? "0.5.
|
|
24701
|
+
var CLI_VERSION3 = true ? "0.5.23" : "0.0.0";
|
|
24555
24702
|
var DEBOUNCE_MS = 5e3;
|
|
24556
24703
|
var CLAUDE_DIR = claudeBackend.projectsDir();
|
|
24557
24704
|
var PLANS_DIR = claudeBackend.plansDir();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chat-recall",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.23",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/munhq/chat-recall.git"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"bugs": {
|
|
10
10
|
"url": "https://github.com/munhq/chat-recall/issues"
|
|
11
11
|
},
|
|
12
|
-
"description": "One memory across every AI coding tool
|
|
12
|
+
"description": "One memory across every AI coding tool — indexes Claude Code, Gemini CLI, Codex, OpenCode, Antigravity and Cursor sessions, redacts secrets, and exposes them to your agent over MCP.",
|
|
13
13
|
"keywords": [
|
|
14
14
|
"mcp",
|
|
15
15
|
"mcp-server",
|