chat-recall 0.5.30 → 0.5.31
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/auto-update.d.ts +0 -4
- package/dist/auto-update.d.ts.map +1 -1
- package/dist/auto-update.js +20 -1
- package/dist/auto-update.js.map +1 -1
- package/dist/cli.js +86 -39
- package/dist/mcp.js +85 -38
- package/dist/scan-worker.js +2 -15
- package/dist/sync-client.d.ts +37 -0
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +109 -16
- package/dist/sync-client.js.map +1 -1
- package/dist/target-breaker.d.ts +13 -0
- package/dist/target-breaker.d.ts.map +1 -1
- package/dist/target-breaker.js +6 -4
- package/dist/target-breaker.js.map +1 -1
- package/dist/telemetry.d.ts +14 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +23 -0
- package/dist/telemetry.js.map +1 -1
- package/dist/watch.js +87 -41
- package/package.json +1 -1
package/dist/watch.js
CHANGED
|
@@ -11224,19 +11224,6 @@ var init_codex2 = __esm({
|
|
|
11224
11224
|
// ../engine/dist/core/backends/agy.js
|
|
11225
11225
|
import { existsSync as existsSync13, readdirSync as readdirSync9, readFileSync as readFileSync8, statSync as statSync11 } from "fs";
|
|
11226
11226
|
import { basename as basename11, dirname as dirname11, join as join14 } from "path";
|
|
11227
|
-
function getFallbackProjectPath(homeDir) {
|
|
11228
|
-
try {
|
|
11229
|
-
const settingsPath2 = join14(homeDir, "settings.json");
|
|
11230
|
-
if (existsSync13(settingsPath2)) {
|
|
11231
|
-
const json = JSON.parse(readFileSync8(settingsPath2, "utf-8"));
|
|
11232
|
-
if (Array.isArray(json?.trustedWorkspaces) && json.trustedWorkspaces[0]) {
|
|
11233
|
-
return json.trustedWorkspaces[0];
|
|
11234
|
-
}
|
|
11235
|
-
}
|
|
11236
|
-
} catch {
|
|
11237
|
-
}
|
|
11238
|
-
return "";
|
|
11239
|
-
}
|
|
11240
11227
|
function agyTranscriptPath(logsDir) {
|
|
11241
11228
|
const full = join14(logsDir, "transcript_full.jsonl");
|
|
11242
11229
|
if (existsSync13(full))
|
|
@@ -11249,8 +11236,8 @@ function agyTranscriptPath(logsDir) {
|
|
|
11249
11236
|
function resolveAgyProject(logsDir, homeDir) {
|
|
11250
11237
|
const deriveFrom = agyTranscriptPath(logsDir);
|
|
11251
11238
|
if (!deriveFrom)
|
|
11252
|
-
return
|
|
11253
|
-
return extractProjectPathFromTranscript(deriveFrom, homeDir)
|
|
11239
|
+
return "";
|
|
11240
|
+
return extractProjectPathFromTranscript(deriveFrom, homeDir);
|
|
11254
11241
|
}
|
|
11255
11242
|
function extractProjectPathFromTranscript(path, homeDir) {
|
|
11256
11243
|
let content;
|
|
@@ -18804,7 +18791,7 @@ var init_extractor_version = __esm({
|
|
|
18804
18791
|
command: 1
|
|
18805
18792
|
};
|
|
18806
18793
|
TOOL_EXTRACTOR_BUMP = {
|
|
18807
|
-
agy:
|
|
18794
|
+
agy: 3,
|
|
18808
18795
|
claude: 1,
|
|
18809
18796
|
codex: 1
|
|
18810
18797
|
};
|
|
@@ -19233,7 +19220,7 @@ var init_http = __esm({
|
|
|
19233
19220
|
CLI_VERSION = JSON.parse(readFileSync33(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
19234
19221
|
} catch {
|
|
19235
19222
|
try {
|
|
19236
|
-
if (true) CLI_VERSION = "0.5.
|
|
19223
|
+
if (true) CLI_VERSION = "0.5.31";
|
|
19237
19224
|
} catch {
|
|
19238
19225
|
}
|
|
19239
19226
|
}
|
|
@@ -19579,9 +19566,9 @@ function cooldownFor(failures) {
|
|
|
19579
19566
|
function breakerState(serverUrl, now = Date.now()) {
|
|
19580
19567
|
const s = state.get(key(serverUrl));
|
|
19581
19568
|
if (!s || s.openUntil <= now) {
|
|
19582
|
-
return { open: false, retryInMs: 0, failures: s?.failures ?? 0, lastError: s?.lastError ?? "" };
|
|
19569
|
+
return { open: false, retryInMs: 0, failures: s?.failures ?? 0, lastError: s?.lastError ?? "", tripped: false };
|
|
19583
19570
|
}
|
|
19584
|
-
return { open: true, retryInMs: s.openUntil - now, failures: s.failures, lastError: s.lastError };
|
|
19571
|
+
return { open: true, retryInMs: s.openUntil - now, failures: s.failures, lastError: s.lastError, tripped: false };
|
|
19585
19572
|
}
|
|
19586
19573
|
function noteTargetSuccess(serverUrl) {
|
|
19587
19574
|
state.delete(key(serverUrl));
|
|
@@ -19593,11 +19580,11 @@ function noteTargetFailure(serverUrl, error, now = Date.now()) {
|
|
|
19593
19580
|
const lastError = error.slice(0, 200);
|
|
19594
19581
|
if (failures < TRIP_AFTER_FAILURES) {
|
|
19595
19582
|
state.set(k, { failures, openUntil: 0, lastError });
|
|
19596
|
-
return { open: false, retryInMs: 0, failures, lastError };
|
|
19583
|
+
return { open: false, retryInMs: 0, failures, lastError, tripped: false };
|
|
19597
19584
|
}
|
|
19598
19585
|
const cooldown = cooldownFor(failures);
|
|
19599
19586
|
state.set(k, { failures, openUntil: now + cooldown, lastError });
|
|
19600
|
-
return { open: true, retryInMs: cooldown, failures, lastError };
|
|
19587
|
+
return { open: true, retryInMs: cooldown, failures, lastError, tripped: failures === TRIP_AFTER_FAILURES };
|
|
19601
19588
|
}
|
|
19602
19589
|
function breakerNotice(serverUrl, v) {
|
|
19603
19590
|
if (!v.open) return null;
|
|
@@ -19724,6 +19711,14 @@ async function flush() {
|
|
|
19724
19711
|
}
|
|
19725
19712
|
}));
|
|
19726
19713
|
}
|
|
19714
|
+
function stableMark(value) {
|
|
19715
|
+
try {
|
|
19716
|
+
const { createHash: createHash17 } = __require("node:crypto");
|
|
19717
|
+
return createHash17("sha256").update(value).digest("hex").slice(0, 12);
|
|
19718
|
+
} catch {
|
|
19719
|
+
return "";
|
|
19720
|
+
}
|
|
19721
|
+
}
|
|
19727
19722
|
function hashHost() {
|
|
19728
19723
|
try {
|
|
19729
19724
|
const { createHash: createHash17 } = __require("node:crypto");
|
|
@@ -19741,7 +19736,7 @@ var init_telemetry = __esm({
|
|
|
19741
19736
|
init_sync_client();
|
|
19742
19737
|
cliVersion = () => {
|
|
19743
19738
|
try {
|
|
19744
|
-
return true ? "0.5.
|
|
19739
|
+
return true ? "0.5.31" : "dev";
|
|
19745
19740
|
} catch {
|
|
19746
19741
|
return "dev";
|
|
19747
19742
|
}
|
|
@@ -20168,7 +20163,17 @@ async function runAutoUpdate(base2, authHeaders, ownVersion3, deps) {
|
|
|
20168
20163
|
}
|
|
20169
20164
|
const effectiveOwn = newerOf(ownVersion3, installedVersion());
|
|
20170
20165
|
const plan = planAutoUpdate(base2, caps, effectiveOwn, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
20171
|
-
if (!plan.update)
|
|
20166
|
+
if (!plan.update) {
|
|
20167
|
+
if (/disabled|no CLI release/.test(plan.reason) && !reportedStandingSkip.has(base2)) {
|
|
20168
|
+
reportedStandingSkip.add(base2);
|
|
20169
|
+
try {
|
|
20170
|
+
const { reportClientEvent: reportClientEvent2 } = await Promise.resolve().then(() => (init_client_events(), client_events_exports));
|
|
20171
|
+
reportClientEvent2("auto_update_skipped", { message: `${plan.reason} (server offers ${caps.cli?.version ?? "?"}, this device runs ${effectiveOwn})` });
|
|
20172
|
+
} catch {
|
|
20173
|
+
}
|
|
20174
|
+
}
|
|
20175
|
+
return { updated: false, reason: plan.reason };
|
|
20176
|
+
}
|
|
20172
20177
|
const result = await executeAutoUpdate(plan, {
|
|
20173
20178
|
download: deps?.download ?? realDownload,
|
|
20174
20179
|
install: deps?.install ?? realInstall,
|
|
@@ -20184,12 +20189,13 @@ async function runAutoUpdate(base2, authHeaders, ownVersion3, deps) {
|
|
|
20184
20189
|
}
|
|
20185
20190
|
return result;
|
|
20186
20191
|
}
|
|
20187
|
-
var tarballUrl;
|
|
20192
|
+
var tarballUrl, reportedStandingSkip;
|
|
20188
20193
|
var init_auto_update = __esm({
|
|
20189
20194
|
"src/auto-update.ts"() {
|
|
20190
20195
|
"use strict";
|
|
20191
20196
|
init_http();
|
|
20192
20197
|
tarballUrl = (base2) => `${base2.replace(/\/+$/, "")}/install/chat-recall.tgz`;
|
|
20198
|
+
reportedStandingSkip = /* @__PURE__ */ new Set();
|
|
20193
20199
|
}
|
|
20194
20200
|
});
|
|
20195
20201
|
|
|
@@ -20200,17 +20206,32 @@ import { tmpdir as tmpdir3, hostname as hostname2 } from "node:os";
|
|
|
20200
20206
|
import { createHash as createHash12 } from "node:crypto";
|
|
20201
20207
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
20202
20208
|
import { gzipSync as gzipSync3 } from "zlib";
|
|
20203
|
-
function
|
|
20209
|
+
function classedError(errorClass, message) {
|
|
20210
|
+
const e = new Error(message);
|
|
20211
|
+
Object.defineProperty(e, ERROR_CLASS, { value: errorClass, enumerable: false });
|
|
20212
|
+
return e;
|
|
20213
|
+
}
|
|
20214
|
+
function taggedClass(err) {
|
|
20215
|
+
const v = err?.[ERROR_CLASS];
|
|
20216
|
+
return typeof v === "string" && v ? v : null;
|
|
20217
|
+
}
|
|
20218
|
+
function isStandingFailure(err) {
|
|
20219
|
+
const c = taggedClass(err);
|
|
20220
|
+
return c !== null && STANDING_FAILURE.has(c);
|
|
20221
|
+
}
|
|
20222
|
+
function classifyError(msg, err) {
|
|
20223
|
+
const tagged = taggedClass(err);
|
|
20224
|
+
if (tagged) return tagged;
|
|
20204
20225
|
const m = msg.toLowerCase();
|
|
20205
20226
|
if (m.includes("429")) return "rate_limited";
|
|
20206
20227
|
if (m.includes("402")) return "payment_required";
|
|
20207
20228
|
if (m.includes("401") || m.includes("403") || m.includes("token")) return "auth";
|
|
20208
|
-
if (m.includes("timed out") || m.includes("etimedout")) return "timeout";
|
|
20229
|
+
if (m.includes("timed out") || m.includes("etimedout") || m.includes("aborted due to timeout")) return "timeout";
|
|
20209
20230
|
if (m.includes("econnrefused")) return "refused";
|
|
20210
20231
|
if (m.includes("enotfound") || m.includes("dns")) return "dns";
|
|
20211
20232
|
if (m.includes("fetch failed") || m.includes("econnreset")) return "network";
|
|
20212
|
-
if (m.includes("plain http") || m.includes("
|
|
20213
|
-
if (
|
|
20233
|
+
if (m.includes("over plain http") || m.includes("unsupported scheme")) return "insecure_transport";
|
|
20234
|
+
if (/\b5\d\d\b/.test(m)) return "server_error";
|
|
20214
20235
|
return "other";
|
|
20215
20236
|
}
|
|
20216
20237
|
function loadAllCredentials() {
|
|
@@ -20397,17 +20418,23 @@ async function syncSessions(opts = {}) {
|
|
|
20397
20418
|
let agg = null;
|
|
20398
20419
|
const errors = [];
|
|
20399
20420
|
const skippedTargets = [];
|
|
20421
|
+
const perTarget = {};
|
|
20400
20422
|
for (const cred of targets) {
|
|
20401
20423
|
const verdict = breakerState(cred.serverUrl);
|
|
20402
20424
|
if (verdict.open) {
|
|
20403
20425
|
const notice = breakerNotice(cred.serverUrl, verdict);
|
|
20404
20426
|
if (notice) console.error(`[sync] ${notice}`);
|
|
20405
20427
|
skippedTargets.push(cred.serverUrl);
|
|
20428
|
+
perTarget[cred.serverUrl] = {
|
|
20429
|
+
ok: false,
|
|
20430
|
+
error: notice ?? `in failure cooldown for ~${Math.max(1, Math.round(verdict.retryInMs / 6e4))}m`
|
|
20431
|
+
};
|
|
20406
20432
|
continue;
|
|
20407
20433
|
}
|
|
20408
20434
|
try {
|
|
20409
20435
|
const r = await syncToTarget(cred, opts);
|
|
20410
20436
|
noteTargetSuccess(cred.serverUrl);
|
|
20437
|
+
perTarget[cred.serverUrl] = { ok: true };
|
|
20411
20438
|
agg = agg ? {
|
|
20412
20439
|
uploaded: agg.uploaded + r.uploaded,
|
|
20413
20440
|
skipped: agg.skipped + r.skipped,
|
|
@@ -20424,14 +20451,20 @@ async function syncSessions(opts = {}) {
|
|
|
20424
20451
|
} catch (e) {
|
|
20425
20452
|
const msg = e instanceof Error ? e.message : String(e);
|
|
20426
20453
|
errors.push(`${cred.serverUrl}: ${msg}`);
|
|
20454
|
+
perTarget[cred.serverUrl] = { ok: false, error: msg };
|
|
20427
20455
|
const next = noteTargetFailure(cred.serverUrl, msg);
|
|
20428
20456
|
const notice = breakerNotice(cred.serverUrl, next);
|
|
20429
20457
|
if (notice) console.error(`[sync] ${notice}`);
|
|
20430
20458
|
record({
|
|
20431
|
-
|
|
20459
|
+
// `tripped`, not `open`: an open breaker re-opens on every attempt until
|
|
20460
|
+
// a success clears it, so `open` counted elapsed time. Every failure is
|
|
20461
|
+
// still reported — as `target_failure`, carrying the streak in
|
|
20462
|
+
// `failures` — so nothing becomes invisible, it just stops being counted
|
|
20463
|
+
// as a fresh incident.
|
|
20464
|
+
kind: next.tripped ? "breaker_trip" : "target_failure",
|
|
20432
20465
|
failures: next.failures,
|
|
20433
20466
|
retryInMs: next.retryInMs,
|
|
20434
|
-
errorClass: classifyError(msg),
|
|
20467
|
+
errorClass: classifyError(msg, e),
|
|
20435
20468
|
local: isLocalHost(cred.serverUrl) ? 1 : 0
|
|
20436
20469
|
});
|
|
20437
20470
|
}
|
|
@@ -20462,7 +20495,7 @@ async function syncSessions(opts = {}) {
|
|
|
20462
20495
|
${errors.join("\n ")}`);
|
|
20463
20496
|
if (errors.length > 0) console.error(`[sync] ${errors.length} target(s) failed (others succeeded):
|
|
20464
20497
|
${errors.join("\n ")}`);
|
|
20465
|
-
return agg;
|
|
20498
|
+
return { ...agg, perTarget };
|
|
20466
20499
|
}
|
|
20467
20500
|
async function postFieldBatch(base2, token, rows) {
|
|
20468
20501
|
const headers = { "content-type": "application/json" };
|
|
@@ -20622,7 +20655,7 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
20622
20655
|
}
|
|
20623
20656
|
async function syncToTargetInScope(cred, opts = {}) {
|
|
20624
20657
|
const risk = transportRisk(cred.serverUrl);
|
|
20625
|
-
if (risk) throw
|
|
20658
|
+
if (risk) throw classedError("insecure_transport", risk);
|
|
20626
20659
|
const sync = loadSettings().sync;
|
|
20627
20660
|
const serverCfg = await fetchTenantSyncConfig(cred);
|
|
20628
20661
|
const excludeTools = /* @__PURE__ */ new Set([...sync?.excludeTools ?? [], ...serverCfg.excludeTools]);
|
|
@@ -20722,7 +20755,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20722
20755
|
const retryable = res.status === 429 || res.status >= 500;
|
|
20723
20756
|
const text = await res.text().catch(() => "");
|
|
20724
20757
|
if (res.status === 401 || res.status === 403) {
|
|
20725
|
-
throw
|
|
20758
|
+
throw classedError("auth", `server rejected this machine's device token (HTTP ${res.status} \u2014 revoked?). Reconnect with: chat-recall login ${base2}`);
|
|
20726
20759
|
}
|
|
20727
20760
|
if (res.status === 402) {
|
|
20728
20761
|
let detail = text;
|
|
@@ -20736,7 +20769,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20736
20769
|
${body2.upgradeUrl}`;
|
|
20737
20770
|
} catch {
|
|
20738
20771
|
}
|
|
20739
|
-
throw
|
|
20772
|
+
throw classedError("payment_required", `sync paused by the server: ${detail}`);
|
|
20740
20773
|
}
|
|
20741
20774
|
if (!retryable) throw new Error(`sync failed: HTTP ${res.status} ${text}`);
|
|
20742
20775
|
if (attempt >= RETRY_DELAYS_MS.length) throw new Error(`sync failed after ${attempt + 1} attempts: HTTP ${res.status} ${text}`);
|
|
@@ -20746,7 +20779,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20746
20779
|
await sleep(waitMs);
|
|
20747
20780
|
continue;
|
|
20748
20781
|
} catch (err) {
|
|
20749
|
-
const fatal = err instanceof Error && /HTTP 4\d\d|sync failed after/.test(err.message);
|
|
20782
|
+
const fatal = isStandingFailure(err) || err instanceof Error && /HTTP 4\d\d|sync failed after/.test(err.message);
|
|
20750
20783
|
if (fatal || attempt >= RETRY_DELAYS_MS.length) throw err;
|
|
20751
20784
|
console.error(`[sync] upload attempt ${attempt + 1} failed (${err instanceof Error ? err.message : err}) \u2014 retrying in ${RETRY_DELAYS_MS[attempt] / 1e3}s`);
|
|
20752
20785
|
await sleep(RETRY_DELAYS_MS[attempt]);
|
|
@@ -21285,7 +21318,12 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21285
21318
|
const containerBytes = built ? built.files.reduce((n, f) => n + Buffer.byteLength(f.text), 0) : 0;
|
|
21286
21319
|
if (containerBytes > FULL_BUILD_MAX_BYTES) {
|
|
21287
21320
|
console.error(`[sync] ${ref.prefixedId} is ${(containerBytes / 1048576).toFixed(0)}MB (over the ${(FULL_BUILD_MAX_BYTES / 1048576).toFixed(0)}MB ceiling) \u2014 shipping without the raw archive and derived data to keep the walk in memory`);
|
|
21288
|
-
record({
|
|
21321
|
+
record({
|
|
21322
|
+
kind: "oversized_session",
|
|
21323
|
+
mb: Math.round(containerBytes / 1048576),
|
|
21324
|
+
tool: ref.toolId,
|
|
21325
|
+
dedupeKey: stableMark(ref.prefixedId)
|
|
21326
|
+
});
|
|
21289
21327
|
includeRaw = false;
|
|
21290
21328
|
includeMeta = false;
|
|
21291
21329
|
}
|
|
@@ -21596,7 +21634,7 @@ async function syncIncremental(opts = {}) {
|
|
|
21596
21634
|
lock.release();
|
|
21597
21635
|
}
|
|
21598
21636
|
}
|
|
21599
|
-
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;
|
|
21637
|
+
var ownVersion, ERROR_CLASS, STANDING_FAILURE, 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;
|
|
21600
21638
|
var init_sync_client = __esm({
|
|
21601
21639
|
"src/sync-client.ts"() {
|
|
21602
21640
|
"use strict";
|
|
@@ -21642,10 +21680,16 @@ var init_sync_client = __esm({
|
|
|
21642
21680
|
ownVersion = JSON.parse(readFileSync37(join44(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21643
21681
|
} catch {
|
|
21644
21682
|
try {
|
|
21645
|
-
if (true) ownVersion = "0.5.
|
|
21683
|
+
if (true) ownVersion = "0.5.31";
|
|
21646
21684
|
} catch {
|
|
21647
21685
|
}
|
|
21648
21686
|
}
|
|
21687
|
+
ERROR_CLASS = "__chatRecallErrorClass";
|
|
21688
|
+
STANDING_FAILURE = /* @__PURE__ */ new Set([
|
|
21689
|
+
"auth",
|
|
21690
|
+
"payment_required",
|
|
21691
|
+
"insecure_transport"
|
|
21692
|
+
]);
|
|
21649
21693
|
walkProgressForUpload = null;
|
|
21650
21694
|
lastServerPackSpec = null;
|
|
21651
21695
|
credPath = () => join44(getDataDir(), "credentials.json");
|
|
@@ -24430,7 +24474,7 @@ try {
|
|
|
24430
24474
|
ownVersion2 = JSON.parse(readFileSync41(join50(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
24431
24475
|
} catch {
|
|
24432
24476
|
try {
|
|
24433
|
-
if (true) ownVersion2 = "0.5.
|
|
24477
|
+
if (true) ownVersion2 = "0.5.31";
|
|
24434
24478
|
} catch {
|
|
24435
24479
|
}
|
|
24436
24480
|
}
|
|
@@ -24775,7 +24819,7 @@ async function runCollectorMigration(opts) {
|
|
|
24775
24819
|
init_sync_ledger();
|
|
24776
24820
|
init_collector_health();
|
|
24777
24821
|
import { existsSync as existsSync50, readFileSync as readFileSync46 } from "fs";
|
|
24778
|
-
var CLI_VERSION3 = true ? "0.5.
|
|
24822
|
+
var CLI_VERSION3 = true ? "0.5.31" : "0.0.0";
|
|
24779
24823
|
var DEBOUNCE_MS = 5e3;
|
|
24780
24824
|
var CLAUDE_DIR = claudeBackend.projectsDir();
|
|
24781
24825
|
var PLANS_DIR = claudeBackend.plansDir();
|
|
@@ -24812,7 +24856,9 @@ async function shipToServer(trigger) {
|
|
|
24812
24856
|
`Sync (${trigger}): ${result.uploaded} session(s) pushed, ${result.redactions} secret(s) redacted, ${result.skipped} skipped, ${result.items} items, ${result.links} links, ${result.derived} derived, ${result.kgEntities} KG entities, ${result.kgTriples} KG triples`
|
|
24813
24857
|
);
|
|
24814
24858
|
}
|
|
24815
|
-
for (const server of
|
|
24859
|
+
for (const [server, outcome] of Object.entries(result.perTarget ?? {})) {
|
|
24860
|
+
noteSyncOutcome(server, outcome.ok, outcome.error);
|
|
24861
|
+
}
|
|
24816
24862
|
} catch (err) {
|
|
24817
24863
|
const msg = err instanceof Error ? err.message : String(err);
|
|
24818
24864
|
daemonLog.error(`Sync failed (${trigger}, will retry next flush): ${msg.slice(0, 200)}`);
|