@integrity-labs/agt-cli 0.28.412 → 0.28.414
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/bin/agt.js
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
success,
|
|
41
41
|
table,
|
|
42
42
|
warn
|
|
43
|
-
} from "../chunk-
|
|
43
|
+
} from "../chunk-UI5WQACL.js";
|
|
44
44
|
import {
|
|
45
45
|
AnchorSessionClient,
|
|
46
46
|
CHANNEL_REGISTRY,
|
|
@@ -4829,7 +4829,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
4829
4829
|
import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
|
|
4830
4830
|
import chalk18 from "chalk";
|
|
4831
4831
|
import ora16 from "ora";
|
|
4832
|
-
var cliVersion = true ? "0.28.
|
|
4832
|
+
var cliVersion = true ? "0.28.414" : "dev";
|
|
4833
4833
|
async function fetchLatestVersion() {
|
|
4834
4834
|
const host2 = getHost();
|
|
4835
4835
|
if (!host2) return null;
|
|
@@ -6001,7 +6001,7 @@ function handleError(err) {
|
|
|
6001
6001
|
}
|
|
6002
6002
|
|
|
6003
6003
|
// src/bin/agt.ts
|
|
6004
|
-
var cliVersion2 = true ? "0.28.
|
|
6004
|
+
var cliVersion2 = true ? "0.28.414" : "dev";
|
|
6005
6005
|
var program = new Command();
|
|
6006
6006
|
program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
|
|
6007
6007
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -6247,7 +6247,7 @@ function requireHost() {
|
|
|
6247
6247
|
}
|
|
6248
6248
|
|
|
6249
6249
|
// src/lib/api-client.ts
|
|
6250
|
-
var agtCliVersion = true ? "0.28.
|
|
6250
|
+
var agtCliVersion = true ? "0.28.414" : "dev";
|
|
6251
6251
|
var lastConfigHash = null;
|
|
6252
6252
|
function setConfigHash(hash) {
|
|
6253
6253
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -8751,4 +8751,4 @@ export {
|
|
|
8751
8751
|
managerInstallSystemUnitCommand,
|
|
8752
8752
|
managerUninstallSystemUnitCommand
|
|
8753
8753
|
};
|
|
8754
|
-
//# sourceMappingURL=chunk-
|
|
8754
|
+
//# sourceMappingURL=chunk-UI5WQACL.js.map
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
resolveEffectivePinRaw,
|
|
46
46
|
safeWriteJsonAtomic,
|
|
47
47
|
setConfigHash
|
|
48
|
-
} from "../chunk-
|
|
48
|
+
} from "../chunk-UI5WQACL.js";
|
|
49
49
|
import {
|
|
50
50
|
getProjectDir as getProjectDir2,
|
|
51
51
|
getReadyTasks,
|
|
@@ -154,7 +154,7 @@ import {
|
|
|
154
154
|
} from "../chunk-XWVM4KPK.js";
|
|
155
155
|
|
|
156
156
|
// src/lib/manager-worker.ts
|
|
157
|
-
import { createHash as
|
|
157
|
+
import { createHash as createHash15 } from "crypto";
|
|
158
158
|
import { readFileSync as readFileSync18, writeFileSync as writeFileSync12, mkdirSync as mkdirSync10, existsSync as existsSync11, rmSync as rmSync5, readdirSync as readdirSync6, statSync as statSync4, copyFileSync } from "fs";
|
|
159
159
|
import { execFileSync as syncExecFile } from "child_process";
|
|
160
160
|
import { join as join22, dirname as dirname7, delimiter as pathDelimiter } from "path";
|
|
@@ -1348,6 +1348,62 @@ function restartTargetsOpencodeServe(framework) {
|
|
|
1348
1348
|
return framework === "opencode";
|
|
1349
1349
|
}
|
|
1350
1350
|
|
|
1351
|
+
// src/lib/agent-runtime-teardown.ts
|
|
1352
|
+
function claudeTmuxSession(codeName) {
|
|
1353
|
+
return `agt-${codeName}`;
|
|
1354
|
+
}
|
|
1355
|
+
function stopAgentRuntime(codeName, reason, log2, deps) {
|
|
1356
|
+
const step = (label, run) => {
|
|
1357
|
+
try {
|
|
1358
|
+
run();
|
|
1359
|
+
} catch (err) {
|
|
1360
|
+
log2(`[teardown] ${label} failed for '${codeName}' (${reason}): ${err.message}`);
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
step("channel-ingest", () => deps.stopManagerHeldChannelIngest(codeName, log2));
|
|
1364
|
+
step("opencode-serve", () => deps.stopOpencodeServe(codeName, log2));
|
|
1365
|
+
step("claude-session", () => deps.stopClaudePersistentSession(codeName));
|
|
1366
|
+
step("claude-pane", () => {
|
|
1367
|
+
if (deps.killTmuxSession(claudeTmuxSession(codeName))) {
|
|
1368
|
+
log2(`[teardown] killed claude pane '${claudeTmuxSession(codeName)}' for '${codeName}' (${reason})`);
|
|
1369
|
+
}
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
// src/lib/opencode-credential-fingerprint.ts
|
|
1374
|
+
import { createHash as createHash4 } from "crypto";
|
|
1375
|
+
var FINGERPRINT_LENGTH = 16;
|
|
1376
|
+
var ABSENT = "none";
|
|
1377
|
+
function fingerprintOf(secret) {
|
|
1378
|
+
if (!secret) return ABSENT;
|
|
1379
|
+
return createHash4("sha256").update(secret, "utf8").digest("hex").slice(0, FINGERPRINT_LENGTH);
|
|
1380
|
+
}
|
|
1381
|
+
function opencodeCredentialFingerprint(inputs) {
|
|
1382
|
+
const openRouter = inputs.openRouterToken ? inputs.openRouterFingerprint || fingerprintOf(inputs.openRouterToken) : ABSENT;
|
|
1383
|
+
return `or:${openRouter}|an:${fingerprintOf(inputs.anthropicKey)}`;
|
|
1384
|
+
}
|
|
1385
|
+
function slots(fingerprint3) {
|
|
1386
|
+
const out = {};
|
|
1387
|
+
for (const part of fingerprint3.split("|")) {
|
|
1388
|
+
const idx = part.indexOf(":");
|
|
1389
|
+
if (idx > 0) out[part.slice(0, idx)] = part.slice(idx + 1);
|
|
1390
|
+
}
|
|
1391
|
+
return out;
|
|
1392
|
+
}
|
|
1393
|
+
function shouldRestartForCredentialChange(recorded, current) {
|
|
1394
|
+
if (recorded === current) return false;
|
|
1395
|
+
const before = slots(recorded);
|
|
1396
|
+
const after = slots(current);
|
|
1397
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) {
|
|
1398
|
+
const was = before[key] ?? ABSENT;
|
|
1399
|
+
const now = after[key] ?? ABSENT;
|
|
1400
|
+
if (was === now) continue;
|
|
1401
|
+
if (now === ABSENT) continue;
|
|
1402
|
+
return true;
|
|
1403
|
+
}
|
|
1404
|
+
return false;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1351
1407
|
// src/lib/connectivity-probe-runner.ts
|
|
1352
1408
|
var DEFAULT_INTERVAL_MS = 60 * 60 * 1e3;
|
|
1353
1409
|
var DEFAULT_MAX_PER_RUN = 25;
|
|
@@ -1799,7 +1855,7 @@ function isDirectChatMessageExpired(createdAt, nowMs, maxAgeMs) {
|
|
|
1799
1855
|
}
|
|
1800
1856
|
|
|
1801
1857
|
// ../../packages/core/dist/host-config/capture.js
|
|
1802
|
-
import { createHash as
|
|
1858
|
+
import { createHash as createHash5 } from "crypto";
|
|
1803
1859
|
var NON_SECRET_ENV_GATES = [
|
|
1804
1860
|
"AGT_MEMORY_EXTRACTION_ENABLED",
|
|
1805
1861
|
"AGT_CHANNEL_REPLAY_ENABLED",
|
|
@@ -3417,10 +3473,10 @@ function parseExpiresAt(raw) {
|
|
|
3417
3473
|
}
|
|
3418
3474
|
|
|
3419
3475
|
// src/lib/channel-config-hash.ts
|
|
3420
|
-
import { createHash as
|
|
3476
|
+
import { createHash as createHash6 } from "crypto";
|
|
3421
3477
|
var CHANNEL_WRITE_VERSION = 9;
|
|
3422
3478
|
function computeChannelConfigHash(input) {
|
|
3423
|
-
return
|
|
3479
|
+
return createHash6("sha256").update(
|
|
3424
3480
|
canonicalJson({
|
|
3425
3481
|
writeVersion: CHANNEL_WRITE_VERSION,
|
|
3426
3482
|
cliVersion: input.cliVersion,
|
|
@@ -4491,7 +4547,7 @@ function saveKanbanNudgeState(source, configDir) {
|
|
|
4491
4547
|
}
|
|
4492
4548
|
|
|
4493
4549
|
// src/lib/manager/kanban/notify.ts
|
|
4494
|
-
import { createHash as
|
|
4550
|
+
import { createHash as createHash7 } from "crypto";
|
|
4495
4551
|
async function enqueueKanbanNotice(opts) {
|
|
4496
4552
|
try {
|
|
4497
4553
|
const res = await api.post(
|
|
@@ -4506,7 +4562,7 @@ async function enqueueKanbanNotice(opts) {
|
|
|
4506
4562
|
return res.ok === true;
|
|
4507
4563
|
} catch (err) {
|
|
4508
4564
|
const errText = err instanceof Error ? err.message : String(err);
|
|
4509
|
-
const errId =
|
|
4565
|
+
const errId = createHash7("sha256").update(errText).digest("hex").slice(0, 12);
|
|
4510
4566
|
log(`[kanban] notice enqueue failed for agent_id=${opts.agentId} error_id=${errId}`);
|
|
4511
4567
|
return false;
|
|
4512
4568
|
}
|
|
@@ -4521,7 +4577,7 @@ async function cancelKanbanNotice(agentId) {
|
|
|
4521
4577
|
return typeof res.cancelled === "number" ? res.cancelled : 0;
|
|
4522
4578
|
} catch (err) {
|
|
4523
4579
|
const errText = err instanceof Error ? err.message : String(err);
|
|
4524
|
-
const errId =
|
|
4580
|
+
const errId = createHash7("sha256").update(errText).digest("hex").slice(0, 12);
|
|
4525
4581
|
log(`[kanban] notice cancel failed for agent_id=${agentId} error_id=${errId}`);
|
|
4526
4582
|
return null;
|
|
4527
4583
|
}
|
|
@@ -4927,7 +4983,7 @@ function deriveScheduledTaskNotify(task) {
|
|
|
4927
4983
|
}
|
|
4928
4984
|
|
|
4929
4985
|
// src/lib/manager/scheduler/runs.ts
|
|
4930
|
-
import { createHash as
|
|
4986
|
+
import { createHash as createHash8 } from "crypto";
|
|
4931
4987
|
async function startRun(opts) {
|
|
4932
4988
|
try {
|
|
4933
4989
|
const res = await api.post(
|
|
@@ -4942,7 +4998,7 @@ async function startRun(opts) {
|
|
|
4942
4998
|
};
|
|
4943
4999
|
} catch (err) {
|
|
4944
5000
|
const errText = err instanceof Error ? err.message : String(err);
|
|
4945
|
-
const errId =
|
|
5001
|
+
const errId = createHash8("sha256").update(errText).digest("hex").slice(0, 12);
|
|
4946
5002
|
log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
|
|
4947
5003
|
return { run_id: null, kanban_item_id: null };
|
|
4948
5004
|
}
|
|
@@ -4959,7 +5015,7 @@ async function finishRun(runId, outcome, options = {}) {
|
|
|
4959
5015
|
});
|
|
4960
5016
|
} catch (err) {
|
|
4961
5017
|
const errText = err instanceof Error ? err.message : String(err);
|
|
4962
|
-
const errId =
|
|
5018
|
+
const errId = createHash8("sha256").update(errText).digest("hex").slice(0, 12);
|
|
4963
5019
|
log(`[runs] finish failed for run_id=${runId} outcome=${outcome} error_id=${errId}`);
|
|
4964
5020
|
}
|
|
4965
5021
|
}
|
|
@@ -4976,7 +5032,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
|
|
|
4976
5032
|
return rows.filter((r) => typeof r.output_text === "string" && r.output_text.length > 0).map((r) => ({ startedAt: r.started_at, output: r.output_text }));
|
|
4977
5033
|
} catch (err) {
|
|
4978
5034
|
const errText = err instanceof Error ? err.message : String(err);
|
|
4979
|
-
const errId =
|
|
5035
|
+
const errId = createHash8("sha256").update(errText).digest("hex").slice(0, 12);
|
|
4980
5036
|
log(`[runs] prior-runs lookup failed for task_id=${taskId} error_id=${errId}`);
|
|
4981
5037
|
return [];
|
|
4982
5038
|
}
|
|
@@ -5025,13 +5081,13 @@ function closeScheduledRunsForCode(codeName, outcome, reason) {
|
|
|
5025
5081
|
}
|
|
5026
5082
|
|
|
5027
5083
|
// src/lib/manager/scheduler/kanban-route.ts
|
|
5028
|
-
import { createHash as
|
|
5084
|
+
import { createHash as createHash10 } from "crypto";
|
|
5029
5085
|
import { writeFileSync as writeFileSync8, renameSync, mkdirSync as mkdirSync6 } from "fs";
|
|
5030
5086
|
import { homedir as homedir7 } from "os";
|
|
5031
5087
|
import { join as join17, dirname as dirname5 } from "path";
|
|
5032
5088
|
|
|
5033
5089
|
// src/lib/manager/scheduler/notify.ts
|
|
5034
|
-
import { createHash as
|
|
5090
|
+
import { createHash as createHash9 } from "crypto";
|
|
5035
5091
|
async function enqueueScheduledTaskNotice(opts) {
|
|
5036
5092
|
try {
|
|
5037
5093
|
const res = await api.post(
|
|
@@ -5047,7 +5103,7 @@ async function enqueueScheduledTaskNotice(opts) {
|
|
|
5047
5103
|
return res.ok === true;
|
|
5048
5104
|
} catch (err) {
|
|
5049
5105
|
const errText = err instanceof Error ? err.message : String(err);
|
|
5050
|
-
const errId =
|
|
5106
|
+
const errId = createHash9("sha256").update(errText).digest("hex").slice(0, 12);
|
|
5051
5107
|
log(
|
|
5052
5108
|
`[scheduled-kanban] notice enqueue failed for agent_id=${opts.agentId} task_id=${opts.taskId} error_id=${errId}`
|
|
5053
5109
|
);
|
|
@@ -5481,24 +5537,24 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
5481
5537
|
const assertion = parseDeliverAssertion(rawOutput);
|
|
5482
5538
|
if (!assertion.deliver) {
|
|
5483
5539
|
const trimmed = (rawOutput ?? "").trim();
|
|
5484
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
5540
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash10("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
5485
5541
|
log(`[claude-scheduler] Suppressed by delivery_policy=conditional for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 ${assertion.vacuous ? "deliver marker had a vacuous reason" : "no deliver marker"}; output_len=${trimmed.length} output_hash=${outputHash}`);
|
|
5486
5542
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
5487
5543
|
await reportDeliveryStatus(agentId, delivery.taskId, { status: "skipped", error_code: "SUPPRESSED_BY_POLICY" });
|
|
5488
5544
|
}
|
|
5489
5545
|
return { ok: true };
|
|
5490
5546
|
}
|
|
5491
|
-
const reasonHash =
|
|
5547
|
+
const reasonHash = createHash10("sha256").update(assertion.reason ?? "").digest("hex").slice(0, 12);
|
|
5492
5548
|
log(`[claude-scheduler] Delivering conditional run for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 agent asserted a concrete trigger (reason_len=${(assertion.reason ?? "").length} reason_hash=${reasonHash})`);
|
|
5493
5549
|
rawOutput = assertion.deliverable;
|
|
5494
5550
|
}
|
|
5495
5551
|
const classification = classifyOutput(rawOutput);
|
|
5496
5552
|
if (classification.action === "suppress") {
|
|
5497
5553
|
const trimmed = (rawOutput ?? "").trim();
|
|
5498
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
5554
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash10("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
5499
5555
|
log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
|
|
5500
5556
|
if (classification.suppressedNotes) {
|
|
5501
|
-
const notesHash =
|
|
5557
|
+
const notesHash = createHash10("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
|
|
5502
5558
|
log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
|
|
5503
5559
|
}
|
|
5504
5560
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
@@ -5564,7 +5620,7 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
5564
5620
|
}
|
|
5565
5621
|
|
|
5566
5622
|
// src/lib/manager/scheduler/execution.ts
|
|
5567
|
-
import { createHash as
|
|
5623
|
+
import { createHash as createHash11 } from "crypto";
|
|
5568
5624
|
import { homedir as homedir8 } from "os";
|
|
5569
5625
|
import { join as join18 } from "path";
|
|
5570
5626
|
function claudePidFilePath() {
|
|
@@ -5588,10 +5644,10 @@ function unregisterClaudeSpawn(pid) {
|
|
|
5588
5644
|
}
|
|
5589
5645
|
async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData) {
|
|
5590
5646
|
const codeName = agent.code_name;
|
|
5591
|
-
const stableTasksHash =
|
|
5592
|
-
const boardHash = boardItems.length > 0 ?
|
|
5647
|
+
const stableTasksHash = createHash11("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
5648
|
+
const boardHash = boardItems.length > 0 ? createHash11("sha256").update(JSON.stringify(boardItems.map((b) => ({ id: b.id, title: b.title, status: b.status, priority: b.priority, deliverable: b.deliverable })))).digest("hex").slice(0, 16) : "empty";
|
|
5593
5649
|
const resolvedModels = resolveModelChain(refreshData);
|
|
5594
|
-
const modelsHash =
|
|
5650
|
+
const modelsHash = createHash11("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
|
|
5595
5651
|
const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
|
|
5596
5652
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
5597
5653
|
if (combinedHash !== prevHash) {
|
|
@@ -5629,7 +5685,7 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
5629
5685
|
}
|
|
5630
5686
|
|
|
5631
5687
|
// src/lib/opencode-slack-ingest.ts
|
|
5632
|
-
import { createHash as
|
|
5688
|
+
import { createHash as createHash12 } from "crypto";
|
|
5633
5689
|
|
|
5634
5690
|
// ../../packages/core/dist/channels/slack-rich-text.js
|
|
5635
5691
|
var MAX_DEPTH = 12;
|
|
@@ -6565,7 +6621,7 @@ function startSlackIngest(config2) {
|
|
|
6565
6621
|
// src/lib/opencode-slack-ingest.ts
|
|
6566
6622
|
var ingests = /* @__PURE__ */ new Map();
|
|
6567
6623
|
function fingerprint(params) {
|
|
6568
|
-
return
|
|
6624
|
+
return createHash12("sha256").update(
|
|
6569
6625
|
JSON.stringify({
|
|
6570
6626
|
appToken: params.appToken,
|
|
6571
6627
|
botToken: params.botToken,
|
|
@@ -6646,7 +6702,7 @@ function stopAllOpencodeSlackIngests(log2) {
|
|
|
6646
6702
|
}
|
|
6647
6703
|
|
|
6648
6704
|
// src/lib/manager/opencode-scheduler.ts
|
|
6649
|
-
import { createHash as
|
|
6705
|
+
import { createHash as createHash13 } from "crypto";
|
|
6650
6706
|
var MAX_OPENCODE_SCHED_CONCURRENCY = 2;
|
|
6651
6707
|
var opencodeSchedulerStates = /* @__PURE__ */ new Map();
|
|
6652
6708
|
var inFlightOpencodeTasks = /* @__PURE__ */ new Set();
|
|
@@ -6660,7 +6716,7 @@ function shouldDeliver(task, reply) {
|
|
|
6660
6716
|
}
|
|
6661
6717
|
async function syncAndCheckOpencodeScheduler(agent, tasks, refreshData) {
|
|
6662
6718
|
const codeName = agent.code_name;
|
|
6663
|
-
const tasksHash =
|
|
6719
|
+
const tasksHash = createHash13("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
6664
6720
|
if (knownOpencodeTaskHashes.get(agent.agent_id) !== tasksHash) {
|
|
6665
6721
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
6666
6722
|
const state8 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
|
|
@@ -6738,7 +6794,7 @@ async function fireOpencodeScheduledTask(agent, task) {
|
|
|
6738
6794
|
}
|
|
6739
6795
|
|
|
6740
6796
|
// src/lib/opencode-telegram-ingest.ts
|
|
6741
|
-
import { createHash as
|
|
6797
|
+
import { createHash as createHash14 } from "crypto";
|
|
6742
6798
|
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync15, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
|
|
6743
6799
|
import { randomUUID } from "crypto";
|
|
6744
6800
|
import { join as join19 } from "path";
|
|
@@ -7274,7 +7330,7 @@ function anySignal(signals) {
|
|
|
7274
7330
|
// src/lib/opencode-telegram-ingest.ts
|
|
7275
7331
|
var ingests2 = /* @__PURE__ */ new Map();
|
|
7276
7332
|
function fingerprint2(params) {
|
|
7277
|
-
return
|
|
7333
|
+
return createHash14("sha256").update(
|
|
7278
7334
|
JSON.stringify({
|
|
7279
7335
|
botToken: params.botToken,
|
|
7280
7336
|
allowedChats: [...params.allowedChats].sort(),
|
|
@@ -9025,7 +9081,7 @@ var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
|
|
|
9025
9081
|
function projectMcpHash(_codeName, projectDir) {
|
|
9026
9082
|
try {
|
|
9027
9083
|
const raw = readFileSync18(join22(projectDir, ".mcp.json"), "utf-8");
|
|
9028
|
-
return
|
|
9084
|
+
return createHash15("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
9029
9085
|
} catch {
|
|
9030
9086
|
return null;
|
|
9031
9087
|
}
|
|
@@ -9212,6 +9268,27 @@ function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason, gate
|
|
|
9212
9268
|
}
|
|
9213
9269
|
}
|
|
9214
9270
|
}
|
|
9271
|
+
var agentRuntimeTeardownDeps = {
|
|
9272
|
+
stopOpencodeServe: (codeName, teardownLog) => stopOpencodeSession(codeName, teardownLog),
|
|
9273
|
+
stopManagerHeldChannelIngest: (codeName, teardownLog) => {
|
|
9274
|
+
stopOpencodeSlackIngest(codeName, teardownLog);
|
|
9275
|
+
stopOpencodeTelegramIngest(codeName, teardownLog);
|
|
9276
|
+
},
|
|
9277
|
+
// No breaker reason: a deprovision is intentional and must not count against
|
|
9278
|
+
// the restart circuit breaker (see stopPersistentSessionAndForgetMcpBaseline).
|
|
9279
|
+
stopClaudePersistentSession: (codeName) => stopPersistentSessionAndForgetMcpBaseline(codeName),
|
|
9280
|
+
killTmuxSession: (sessionName) => {
|
|
9281
|
+
try {
|
|
9282
|
+
syncExecFile("tmux", ["kill-session", "-t", sessionName], { stdio: "ignore" });
|
|
9283
|
+
return true;
|
|
9284
|
+
} catch {
|
|
9285
|
+
return false;
|
|
9286
|
+
}
|
|
9287
|
+
}
|
|
9288
|
+
};
|
|
9289
|
+
function stopAgentRuntime2(codeName, reason) {
|
|
9290
|
+
stopAgentRuntime(codeName, reason, log, agentRuntimeTeardownDeps);
|
|
9291
|
+
}
|
|
9215
9292
|
function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
9216
9293
|
const currentHash = projectMcpHash(codeName, projectDir);
|
|
9217
9294
|
const action = decideMcpDriftAction(currentHash, runningMcpHashes.get(codeName));
|
|
@@ -9350,6 +9427,7 @@ function clearAgentCaches(agentId, codeName) {
|
|
|
9350
9427
|
stopOpencodeSlackIngest(codeName, log);
|
|
9351
9428
|
stopOpencodeTelegramIngest(codeName, log);
|
|
9352
9429
|
agentFrameworkCache.delete(codeName);
|
|
9430
|
+
opencodeCredentialFingerprintBySession.delete(codeName);
|
|
9353
9431
|
kanbanBoardCache.delete(codeName);
|
|
9354
9432
|
clearKanbanNudgeState(codeName);
|
|
9355
9433
|
notifyBoardCache.delete(codeName);
|
|
@@ -9378,7 +9456,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
9378
9456
|
var lastVersionCheckAt = 0;
|
|
9379
9457
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
9380
9458
|
var lastResponsivenessProbeAt = 0;
|
|
9381
|
-
var agtCliVersion = true ? "0.28.
|
|
9459
|
+
var agtCliVersion = true ? "0.28.414" : "dev";
|
|
9382
9460
|
function resolveBrewPath(execFileSync2) {
|
|
9383
9461
|
try {
|
|
9384
9462
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -10663,7 +10741,7 @@ async function pollCycle() {
|
|
|
10663
10741
|
claudeAuth = await detectClaudeAuth();
|
|
10664
10742
|
} catch (err) {
|
|
10665
10743
|
const errText = err instanceof Error ? err.message : String(err);
|
|
10666
|
-
const errId =
|
|
10744
|
+
const errId = createHash15("sha256").update(errText).digest("hex").slice(0, 12);
|
|
10667
10745
|
log(`Claude auth detection failed (error_id=${errId})`);
|
|
10668
10746
|
}
|
|
10669
10747
|
const hostHasClaudeCode = state6.agents.some(
|
|
@@ -11142,12 +11220,7 @@ async function pollCycle() {
|
|
|
11142
11220
|
if (!currentIds.has(prev.agentId)) {
|
|
11143
11221
|
log(`Agent '${prev.codeName}' removed from host (deleted or unassigned)`);
|
|
11144
11222
|
const adapter = resolveAgentFramework(prev.codeName);
|
|
11145
|
-
|
|
11146
|
-
try {
|
|
11147
|
-
const { execSync: es } = await import("child_process");
|
|
11148
|
-
es(`tmux kill-session -t agt-${prev.codeName} 2>/dev/null`, { stdio: "ignore" });
|
|
11149
|
-
} catch {
|
|
11150
|
-
}
|
|
11223
|
+
stopAgentRuntime2(prev.codeName, "removed-from-host");
|
|
11151
11224
|
killAgentChannelProcesses(prev.codeName, { log });
|
|
11152
11225
|
const agentDir = join22(adapter.getAgentDir(prev.codeName), "provision");
|
|
11153
11226
|
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
@@ -11393,13 +11466,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11393
11466
|
} else if (killPausedCodeNames.delete(agent.code_name)) {
|
|
11394
11467
|
log(`[kill-switch] '${agent.code_name}' kill switch cleared while still ${agent.status} (no resume \u2014 paused for another reason)`);
|
|
11395
11468
|
}
|
|
11396
|
-
|
|
11397
|
-
try {
|
|
11398
|
-
const { execSync: es } = await import("child_process");
|
|
11399
|
-
es(`tmux kill-session -t agt-${agent.code_name} 2>/dev/null`, { stdio: "ignore" });
|
|
11400
|
-
log(`Killed tmux session for paused agent '${agent.code_name}'`);
|
|
11401
|
-
} catch {
|
|
11402
|
-
}
|
|
11469
|
+
stopAgentRuntime2(agent.code_name, agent.status);
|
|
11403
11470
|
if (agent.status === "paused" && !agent.kill_switch) {
|
|
11404
11471
|
maybeAutoResume(agent);
|
|
11405
11472
|
}
|
|
@@ -11447,12 +11514,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11447
11514
|
);
|
|
11448
11515
|
}
|
|
11449
11516
|
log(`Agent '${agent.code_name}' is revoked, cleaning up`);
|
|
11450
|
-
|
|
11451
|
-
try {
|
|
11452
|
-
const { execSync: es } = await import("child_process");
|
|
11453
|
-
es(`tmux kill-session -t agt-${agent.code_name} 2>/dev/null`, { stdio: "ignore" });
|
|
11454
|
-
} catch {
|
|
11455
|
-
}
|
|
11517
|
+
stopAgentRuntime2(agent.code_name, "revoked");
|
|
11456
11518
|
killAgentChannelProcesses(agent.code_name, { log });
|
|
11457
11519
|
await cleanupAgentFiles(agent.code_name, agentDir);
|
|
11458
11520
|
clearAgentCaches(agent.agent_id, agent.code_name);
|
|
@@ -12100,7 +12162,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12100
12162
|
const behaviourSubset = extractMsTeamsBehaviourSubset(
|
|
12101
12163
|
msteamsEntry?.config
|
|
12102
12164
|
);
|
|
12103
|
-
const behaviourHash =
|
|
12165
|
+
const behaviourHash = createHash15("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
|
|
12104
12166
|
const prevBehaviourHash = agentState.knownMsTeamsBehaviourHashes.get(agent.agent_id);
|
|
12105
12167
|
const msteamsBehaviourRestrictive = isMsTeamsBehaviourRestrictive(behaviourSubset);
|
|
12106
12168
|
const behaviourDecision = decideSenderPolicyRestart({
|
|
@@ -12156,7 +12218,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12156
12218
|
const slackBehaviourSubset = extractSlackBehaviourSubset(
|
|
12157
12219
|
slackEntry?.config
|
|
12158
12220
|
);
|
|
12159
|
-
const slackBehaviourHash =
|
|
12221
|
+
const slackBehaviourHash = createHash15("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
|
|
12160
12222
|
const prevSlackBehaviourHash = agentState.knownSlackBehaviourHashes.get(agent.agent_id);
|
|
12161
12223
|
const slackBehaviourRestrictive = isSlackBehaviourRestrictive(slackBehaviourSubset);
|
|
12162
12224
|
const slackBehaviourDecision = decideSenderPolicyRestart({
|
|
@@ -12589,10 +12651,10 @@ async function processAgent(agent, agentStates) {
|
|
|
12589
12651
|
desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
|
|
12590
12652
|
}
|
|
12591
12653
|
const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
|
|
12592
|
-
const headersHash =
|
|
12654
|
+
const headersHash = createHash15("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
|
|
12593
12655
|
return `${e.serverId}|${e.url}|${headersHash}`;
|
|
12594
12656
|
}).join("\n");
|
|
12595
|
-
const mcpHash =
|
|
12657
|
+
const mcpHash = createHash15("sha256").update(hashBasis).digest("hex").slice(0, 16);
|
|
12596
12658
|
const prevMcpHash = agentState.knownManagedMcpHashes.get(agent.agent_id);
|
|
12597
12659
|
const structureHash = managedMcpStructureHash(desiredEntries);
|
|
12598
12660
|
const prevStructureHash = agentState.knownManagedMcpStructure.get(agent.agent_id);
|
|
@@ -12607,7 +12669,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12607
12669
|
if (mcpHash !== prevMcpHash) {
|
|
12608
12670
|
for (const e of desiredEntries) {
|
|
12609
12671
|
frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
|
|
12610
|
-
const urlHash =
|
|
12672
|
+
const urlHash = createHash15("sha256").update(e.url).digest("hex").slice(0, 12);
|
|
12611
12673
|
log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
|
|
12612
12674
|
}
|
|
12613
12675
|
if (frameworkAdapter.removeMcpServer && frameworkAdapter.readMcpServers) {
|
|
@@ -12709,7 +12771,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12709
12771
|
if (frameworkAdapter.installSkillFiles) {
|
|
12710
12772
|
const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
|
|
12711
12773
|
const installedIntegrationSkills = [];
|
|
12712
|
-
const { createHash:
|
|
12774
|
+
const { createHash: createHash16 } = await import("crypto");
|
|
12713
12775
|
const refreshAny = refreshData;
|
|
12714
12776
|
const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
|
|
12715
12777
|
const contextBySlug = /* @__PURE__ */ new Map();
|
|
@@ -12738,7 +12800,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12738
12800
|
)
|
|
12739
12801
|
}));
|
|
12740
12802
|
const bundle = buildIntegrationBundle(renderedScopes);
|
|
12741
|
-
const contentHash =
|
|
12803
|
+
const contentHash = createHash16("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
|
|
12742
12804
|
const hashKey = `plugin-skill:${agent.agent_id}:${integrationSkillId}`;
|
|
12743
12805
|
if (agentState.knownSkillHashes.get(hashKey) === contentHash) continue;
|
|
12744
12806
|
frameworkAdapter.installSkillFiles(agent.code_name, integrationSkillId, bundle.files);
|
|
@@ -12805,7 +12867,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12805
12867
|
const plan = planGlobalSkillSync(
|
|
12806
12868
|
[...globalSkillsPayload ?? [], ...sharedSkillsPayload ?? []],
|
|
12807
12869
|
prevIds,
|
|
12808
|
-
(content) =>
|
|
12870
|
+
(content) => createHash16("sha256").update(content).digest("hex").slice(0, 12),
|
|
12809
12871
|
(skillId) => agentState.knownSkillHashes.get(`global-skill:${agent.agent_id}:${skillId}`),
|
|
12810
12872
|
{ desiredResolved }
|
|
12811
12873
|
);
|
|
@@ -12856,7 +12918,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12856
12918
|
const slug = hook.integration_slug ?? hook.plugin_slug;
|
|
12857
12919
|
if (!slug) continue;
|
|
12858
12920
|
try {
|
|
12859
|
-
const scriptHash =
|
|
12921
|
+
const scriptHash = createHash16("sha256").update(hook.script).digest("hex").slice(0, 12);
|
|
12860
12922
|
const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
|
|
12861
12923
|
if (agentState.knownSkillHashes.get(hookKey) === scriptHash) continue;
|
|
12862
12924
|
const result = await frameworkAdapter.executePluginHook({
|
|
@@ -12871,9 +12933,9 @@ async function processAgent(agent, agentStates) {
|
|
|
12871
12933
|
} else if (result.timedOut) {
|
|
12872
12934
|
log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
|
|
12873
12935
|
} else {
|
|
12874
|
-
const stderrHash =
|
|
12936
|
+
const stderrHash = createHash16("sha256").update(result.stderr).digest("hex").slice(0, 12);
|
|
12875
12937
|
const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
|
|
12876
|
-
const missingCmdHash = missingCmd ?
|
|
12938
|
+
const missingCmdHash = missingCmd ? createHash16("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
|
|
12877
12939
|
log(
|
|
12878
12940
|
`Integration hook on_install '${slug}' exited ${result.exitCode} for '${agent.code_name}' ` + (missingCmdHash ? `[missing_command_hash=${missingCmdHash}] ` : "") + `[stderr_hash=${stderrHash} stderr_len=${result.stderr.length}]`
|
|
12879
12941
|
);
|
|
@@ -13472,6 +13534,7 @@ var lastModelApiErrorSig = /* @__PURE__ */ new Map();
|
|
|
13472
13534
|
var DAY_ROLLOVER_FORCE_GRACE_MIN = 30;
|
|
13473
13535
|
var persistentSessionStuckTracker = new PersistentSessionStuckTracker();
|
|
13474
13536
|
var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
|
|
13537
|
+
var opencodeCredentialFingerprintBySession = /* @__PURE__ */ new Map();
|
|
13475
13538
|
var egressAllowlistBySession = /* @__PURE__ */ new Map();
|
|
13476
13539
|
function deriveEgressAllowlist(toolsRaw) {
|
|
13477
13540
|
return buildEgressAllowlist(
|
|
@@ -13481,16 +13544,31 @@ function deriveEgressAllowlist(toolsRaw) {
|
|
|
13481
13544
|
var egressAllowlistEqual = (a, b) => a.length === b.length && a.every((d, i) => d === b[i]);
|
|
13482
13545
|
async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
13483
13546
|
const codeName = agent.code_name;
|
|
13547
|
+
const openRouterRaw = refreshData.openrouter ?? null;
|
|
13548
|
+
const anthropicRaw = refreshData.anthropic ?? null;
|
|
13549
|
+
const credentialFingerprint = opencodeCredentialFingerprint({
|
|
13550
|
+
openRouterToken: openRouterRaw?.auth_token,
|
|
13551
|
+
openRouterFingerprint: openRouterRaw?.fingerprint,
|
|
13552
|
+
anthropicKey: anthropicRaw?.api_key
|
|
13553
|
+
});
|
|
13484
13554
|
if (isOpencodeSessionHealthy(codeName)) {
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13555
|
+
const recorded = opencodeCredentialFingerprintBySession.get(codeName);
|
|
13556
|
+
if (recorded && shouldRestartForCredentialChange(recorded, credentialFingerprint)) {
|
|
13557
|
+
log(
|
|
13558
|
+
`[opencode-session] Provider credential rotated for '${codeName}' (${recorded} \u2192 ${credentialFingerprint}) \u2014 restarting serve`
|
|
13559
|
+
);
|
|
13560
|
+
stopOpencodeSession(codeName, log);
|
|
13561
|
+
opencodeCredentialFingerprintBySession.delete(codeName);
|
|
13562
|
+
} else {
|
|
13563
|
+
await ensureOpencodeSlackIngest({ codeName, agentId: agent.agent_id, log });
|
|
13564
|
+
await ensureOpencodeTelegramIngest({ codeName, agentId: agent.agent_id, log });
|
|
13565
|
+
if (!recorded) opencodeCredentialFingerprintBySession.set(codeName, credentialFingerprint);
|
|
13566
|
+
return { decision: "healthy", spawnAttempted: false, sessionHealthyAfter: true };
|
|
13567
|
+
}
|
|
13488
13568
|
}
|
|
13489
13569
|
stopOpencodeSlackIngest(codeName, log);
|
|
13490
13570
|
stopOpencodeTelegramIngest(codeName, log);
|
|
13491
13571
|
const opencodeProjectDir = join22(getFramework("opencode").getAgentDir(codeName), "provision");
|
|
13492
|
-
const openRouterRaw = refreshData.openrouter ?? null;
|
|
13493
|
-
const anthropicRaw = refreshData.anthropic ?? null;
|
|
13494
13572
|
const serveEnv = {
|
|
13495
13573
|
AGT_HOST: requireHost(),
|
|
13496
13574
|
AGT_API_KEY: getApiKey() ?? void 0,
|
|
@@ -13522,6 +13600,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
13522
13600
|
detail: tail ? `opencode spawn failed: ${tail.slice(0, 200)}` : "opencode spawn failed"
|
|
13523
13601
|
};
|
|
13524
13602
|
}
|
|
13603
|
+
opencodeCredentialFingerprintBySession.set(codeName, credentialFingerprint);
|
|
13525
13604
|
return {
|
|
13526
13605
|
decision: "spawn",
|
|
13527
13606
|
spawnAttempted,
|
|
@@ -13691,7 +13770,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
13691
13770
|
const ctx = getLastFailureContext(codeName);
|
|
13692
13771
|
const recovery = prepareForRespawn(codeName);
|
|
13693
13772
|
const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
|
|
13694
|
-
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${
|
|
13773
|
+
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash15("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
|
|
13695
13774
|
const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
|
|
13696
13775
|
const recoverySummary = recovery ? `; recovery=${recovery}` : "";
|
|
13697
13776
|
log(
|
|
@@ -13705,7 +13784,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash14("sha256")
|
|
|
13705
13784
|
);
|
|
13706
13785
|
getHostId().then((hostId) => {
|
|
13707
13786
|
if (!hostId) return;
|
|
13708
|
-
const paneTailHash = zombie.paneTail ? `sha256:${
|
|
13787
|
+
const paneTailHash = zombie.paneTail ? `sha256:${createHash15("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
|
|
13709
13788
|
return api.post("/host/events", {
|
|
13710
13789
|
host_id: hostId,
|
|
13711
13790
|
agent_code_name: codeName,
|
|
@@ -13854,7 +13933,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash14("sha256")
|
|
|
13854
13933
|
if (!claudeAuthTupleBySession.has(codeName)) {
|
|
13855
13934
|
claudeAuthTupleBySession.set(codeName, currentAuthTuple);
|
|
13856
13935
|
}
|
|
13857
|
-
const stableTasksHash =
|
|
13936
|
+
const stableTasksHash = createHash15("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
13858
13937
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
13859
13938
|
if (stableTasksHash !== prevHash) {
|
|
13860
13939
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
@@ -14855,7 +14934,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
14855
14934
|
if (!file.endsWith(".md")) continue;
|
|
14856
14935
|
try {
|
|
14857
14936
|
const raw = readFileSync18(join22(memoryDir, file), "utf-8");
|
|
14858
|
-
const fileHash =
|
|
14937
|
+
const fileHash = createHash15("sha256").update(raw).digest("hex").slice(0, 16);
|
|
14859
14938
|
currentHashes.set(file, fileHash);
|
|
14860
14939
|
if (prevHashes.get(file) === fileHash) continue;
|
|
14861
14940
|
const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
|
|
@@ -14893,14 +14972,14 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
14893
14972
|
}
|
|
14894
14973
|
async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
14895
14974
|
const localFiles = existsSync11(memoryDir) ? readdirSync6(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
14896
|
-
const localListHash =
|
|
14975
|
+
const localListHash = createHash15("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
14897
14976
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
14898
14977
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
14899
14978
|
try {
|
|
14900
14979
|
const dbMemories = await api.post("/host/memories", {
|
|
14901
14980
|
agent_id: agent.agent_id
|
|
14902
14981
|
});
|
|
14903
|
-
const responseHash =
|
|
14982
|
+
const responseHash = createHash15("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
|
|
14904
14983
|
if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
|
|
14905
14984
|
return true;
|
|
14906
14985
|
}
|
|
@@ -14939,7 +15018,7 @@ ${mem.content}
|
|
|
14939
15018
|
}
|
|
14940
15019
|
if (written > 0 || overwritten > 0) {
|
|
14941
15020
|
const updatedFiles = readdirSync6(memoryDir).filter((f) => f.endsWith(".md")).sort();
|
|
14942
|
-
lastLocalFileHash.set(agent.agent_id,
|
|
15021
|
+
lastLocalFileHash.set(agent.agent_id, createHash15("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
|
|
14943
15022
|
log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
|
|
14944
15023
|
}
|
|
14945
15024
|
}
|
|
@@ -15364,7 +15443,7 @@ function deployMcpAssets() {
|
|
|
15364
15443
|
const fileHash = (p) => {
|
|
15365
15444
|
try {
|
|
15366
15445
|
if (!existsSync11(p)) return null;
|
|
15367
|
-
return
|
|
15446
|
+
return createHash15("sha256").update(readFileSync18(p)).digest("hex");
|
|
15368
15447
|
} catch {
|
|
15369
15448
|
return null;
|
|
15370
15449
|
}
|