@integrity-labs/agt-cli 0.28.413 → 0.28.415
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.
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
resolveEffectivePinRaw,
|
|
46
46
|
safeWriteJsonAtomic,
|
|
47
47
|
setConfigHash
|
|
48
|
-
} from "../chunk-
|
|
48
|
+
} from "../chunk-TGHZFWWX.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";
|
|
@@ -1370,6 +1370,40 @@ function stopAgentRuntime(codeName, reason, log2, deps) {
|
|
|
1370
1370
|
});
|
|
1371
1371
|
}
|
|
1372
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
|
+
|
|
1373
1407
|
// src/lib/connectivity-probe-runner.ts
|
|
1374
1408
|
var DEFAULT_INTERVAL_MS = 60 * 60 * 1e3;
|
|
1375
1409
|
var DEFAULT_MAX_PER_RUN = 25;
|
|
@@ -1821,7 +1855,7 @@ function isDirectChatMessageExpired(createdAt, nowMs, maxAgeMs) {
|
|
|
1821
1855
|
}
|
|
1822
1856
|
|
|
1823
1857
|
// ../../packages/core/dist/host-config/capture.js
|
|
1824
|
-
import { createHash as
|
|
1858
|
+
import { createHash as createHash5 } from "crypto";
|
|
1825
1859
|
var NON_SECRET_ENV_GATES = [
|
|
1826
1860
|
"AGT_MEMORY_EXTRACTION_ENABLED",
|
|
1827
1861
|
"AGT_CHANNEL_REPLAY_ENABLED",
|
|
@@ -3439,10 +3473,10 @@ function parseExpiresAt(raw) {
|
|
|
3439
3473
|
}
|
|
3440
3474
|
|
|
3441
3475
|
// src/lib/channel-config-hash.ts
|
|
3442
|
-
import { createHash as
|
|
3476
|
+
import { createHash as createHash6 } from "crypto";
|
|
3443
3477
|
var CHANNEL_WRITE_VERSION = 9;
|
|
3444
3478
|
function computeChannelConfigHash(input) {
|
|
3445
|
-
return
|
|
3479
|
+
return createHash6("sha256").update(
|
|
3446
3480
|
canonicalJson({
|
|
3447
3481
|
writeVersion: CHANNEL_WRITE_VERSION,
|
|
3448
3482
|
cliVersion: input.cliVersion,
|
|
@@ -4513,7 +4547,7 @@ function saveKanbanNudgeState(source, configDir) {
|
|
|
4513
4547
|
}
|
|
4514
4548
|
|
|
4515
4549
|
// src/lib/manager/kanban/notify.ts
|
|
4516
|
-
import { createHash as
|
|
4550
|
+
import { createHash as createHash7 } from "crypto";
|
|
4517
4551
|
async function enqueueKanbanNotice(opts) {
|
|
4518
4552
|
try {
|
|
4519
4553
|
const res = await api.post(
|
|
@@ -4528,7 +4562,7 @@ async function enqueueKanbanNotice(opts) {
|
|
|
4528
4562
|
return res.ok === true;
|
|
4529
4563
|
} catch (err) {
|
|
4530
4564
|
const errText = err instanceof Error ? err.message : String(err);
|
|
4531
|
-
const errId =
|
|
4565
|
+
const errId = createHash7("sha256").update(errText).digest("hex").slice(0, 12);
|
|
4532
4566
|
log(`[kanban] notice enqueue failed for agent_id=${opts.agentId} error_id=${errId}`);
|
|
4533
4567
|
return false;
|
|
4534
4568
|
}
|
|
@@ -4543,7 +4577,7 @@ async function cancelKanbanNotice(agentId) {
|
|
|
4543
4577
|
return typeof res.cancelled === "number" ? res.cancelled : 0;
|
|
4544
4578
|
} catch (err) {
|
|
4545
4579
|
const errText = err instanceof Error ? err.message : String(err);
|
|
4546
|
-
const errId =
|
|
4580
|
+
const errId = createHash7("sha256").update(errText).digest("hex").slice(0, 12);
|
|
4547
4581
|
log(`[kanban] notice cancel failed for agent_id=${agentId} error_id=${errId}`);
|
|
4548
4582
|
return null;
|
|
4549
4583
|
}
|
|
@@ -4949,7 +4983,7 @@ function deriveScheduledTaskNotify(task) {
|
|
|
4949
4983
|
}
|
|
4950
4984
|
|
|
4951
4985
|
// src/lib/manager/scheduler/runs.ts
|
|
4952
|
-
import { createHash as
|
|
4986
|
+
import { createHash as createHash8 } from "crypto";
|
|
4953
4987
|
async function startRun(opts) {
|
|
4954
4988
|
try {
|
|
4955
4989
|
const res = await api.post(
|
|
@@ -4964,7 +4998,7 @@ async function startRun(opts) {
|
|
|
4964
4998
|
};
|
|
4965
4999
|
} catch (err) {
|
|
4966
5000
|
const errText = err instanceof Error ? err.message : String(err);
|
|
4967
|
-
const errId =
|
|
5001
|
+
const errId = createHash8("sha256").update(errText).digest("hex").slice(0, 12);
|
|
4968
5002
|
log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
|
|
4969
5003
|
return { run_id: null, kanban_item_id: null };
|
|
4970
5004
|
}
|
|
@@ -4981,7 +5015,7 @@ async function finishRun(runId, outcome, options = {}) {
|
|
|
4981
5015
|
});
|
|
4982
5016
|
} catch (err) {
|
|
4983
5017
|
const errText = err instanceof Error ? err.message : String(err);
|
|
4984
|
-
const errId =
|
|
5018
|
+
const errId = createHash8("sha256").update(errText).digest("hex").slice(0, 12);
|
|
4985
5019
|
log(`[runs] finish failed for run_id=${runId} outcome=${outcome} error_id=${errId}`);
|
|
4986
5020
|
}
|
|
4987
5021
|
}
|
|
@@ -4998,7 +5032,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
|
|
|
4998
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 }));
|
|
4999
5033
|
} catch (err) {
|
|
5000
5034
|
const errText = err instanceof Error ? err.message : String(err);
|
|
5001
|
-
const errId =
|
|
5035
|
+
const errId = createHash8("sha256").update(errText).digest("hex").slice(0, 12);
|
|
5002
5036
|
log(`[runs] prior-runs lookup failed for task_id=${taskId} error_id=${errId}`);
|
|
5003
5037
|
return [];
|
|
5004
5038
|
}
|
|
@@ -5047,13 +5081,13 @@ function closeScheduledRunsForCode(codeName, outcome, reason) {
|
|
|
5047
5081
|
}
|
|
5048
5082
|
|
|
5049
5083
|
// src/lib/manager/scheduler/kanban-route.ts
|
|
5050
|
-
import { createHash as
|
|
5084
|
+
import { createHash as createHash10 } from "crypto";
|
|
5051
5085
|
import { writeFileSync as writeFileSync8, renameSync, mkdirSync as mkdirSync6 } from "fs";
|
|
5052
5086
|
import { homedir as homedir7 } from "os";
|
|
5053
5087
|
import { join as join17, dirname as dirname5 } from "path";
|
|
5054
5088
|
|
|
5055
5089
|
// src/lib/manager/scheduler/notify.ts
|
|
5056
|
-
import { createHash as
|
|
5090
|
+
import { createHash as createHash9 } from "crypto";
|
|
5057
5091
|
async function enqueueScheduledTaskNotice(opts) {
|
|
5058
5092
|
try {
|
|
5059
5093
|
const res = await api.post(
|
|
@@ -5069,7 +5103,7 @@ async function enqueueScheduledTaskNotice(opts) {
|
|
|
5069
5103
|
return res.ok === true;
|
|
5070
5104
|
} catch (err) {
|
|
5071
5105
|
const errText = err instanceof Error ? err.message : String(err);
|
|
5072
|
-
const errId =
|
|
5106
|
+
const errId = createHash9("sha256").update(errText).digest("hex").slice(0, 12);
|
|
5073
5107
|
log(
|
|
5074
5108
|
`[scheduled-kanban] notice enqueue failed for agent_id=${opts.agentId} task_id=${opts.taskId} error_id=${errId}`
|
|
5075
5109
|
);
|
|
@@ -5503,24 +5537,24 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
5503
5537
|
const assertion = parseDeliverAssertion(rawOutput);
|
|
5504
5538
|
if (!assertion.deliver) {
|
|
5505
5539
|
const trimmed = (rawOutput ?? "").trim();
|
|
5506
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
5540
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash10("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
5507
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}`);
|
|
5508
5542
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
5509
5543
|
await reportDeliveryStatus(agentId, delivery.taskId, { status: "skipped", error_code: "SUPPRESSED_BY_POLICY" });
|
|
5510
5544
|
}
|
|
5511
5545
|
return { ok: true };
|
|
5512
5546
|
}
|
|
5513
|
-
const reasonHash =
|
|
5547
|
+
const reasonHash = createHash10("sha256").update(assertion.reason ?? "").digest("hex").slice(0, 12);
|
|
5514
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})`);
|
|
5515
5549
|
rawOutput = assertion.deliverable;
|
|
5516
5550
|
}
|
|
5517
5551
|
const classification = classifyOutput(rawOutput);
|
|
5518
5552
|
if (classification.action === "suppress") {
|
|
5519
5553
|
const trimmed = (rawOutput ?? "").trim();
|
|
5520
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
5554
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash10("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
5521
5555
|
log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
|
|
5522
5556
|
if (classification.suppressedNotes) {
|
|
5523
|
-
const notesHash =
|
|
5557
|
+
const notesHash = createHash10("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
|
|
5524
5558
|
log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
|
|
5525
5559
|
}
|
|
5526
5560
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
@@ -5586,7 +5620,7 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
5586
5620
|
}
|
|
5587
5621
|
|
|
5588
5622
|
// src/lib/manager/scheduler/execution.ts
|
|
5589
|
-
import { createHash as
|
|
5623
|
+
import { createHash as createHash11 } from "crypto";
|
|
5590
5624
|
import { homedir as homedir8 } from "os";
|
|
5591
5625
|
import { join as join18 } from "path";
|
|
5592
5626
|
function claudePidFilePath() {
|
|
@@ -5610,10 +5644,10 @@ function unregisterClaudeSpawn(pid) {
|
|
|
5610
5644
|
}
|
|
5611
5645
|
async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData) {
|
|
5612
5646
|
const codeName = agent.code_name;
|
|
5613
|
-
const stableTasksHash =
|
|
5614
|
-
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";
|
|
5615
5649
|
const resolvedModels = resolveModelChain(refreshData);
|
|
5616
|
-
const modelsHash =
|
|
5650
|
+
const modelsHash = createHash11("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
|
|
5617
5651
|
const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
|
|
5618
5652
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
5619
5653
|
if (combinedHash !== prevHash) {
|
|
@@ -5651,7 +5685,7 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
5651
5685
|
}
|
|
5652
5686
|
|
|
5653
5687
|
// src/lib/opencode-slack-ingest.ts
|
|
5654
|
-
import { createHash as
|
|
5688
|
+
import { createHash as createHash12 } from "crypto";
|
|
5655
5689
|
|
|
5656
5690
|
// ../../packages/core/dist/channels/slack-rich-text.js
|
|
5657
5691
|
var MAX_DEPTH = 12;
|
|
@@ -6587,7 +6621,7 @@ function startSlackIngest(config2) {
|
|
|
6587
6621
|
// src/lib/opencode-slack-ingest.ts
|
|
6588
6622
|
var ingests = /* @__PURE__ */ new Map();
|
|
6589
6623
|
function fingerprint(params) {
|
|
6590
|
-
return
|
|
6624
|
+
return createHash12("sha256").update(
|
|
6591
6625
|
JSON.stringify({
|
|
6592
6626
|
appToken: params.appToken,
|
|
6593
6627
|
botToken: params.botToken,
|
|
@@ -6668,7 +6702,7 @@ function stopAllOpencodeSlackIngests(log2) {
|
|
|
6668
6702
|
}
|
|
6669
6703
|
|
|
6670
6704
|
// src/lib/manager/opencode-scheduler.ts
|
|
6671
|
-
import { createHash as
|
|
6705
|
+
import { createHash as createHash13 } from "crypto";
|
|
6672
6706
|
var MAX_OPENCODE_SCHED_CONCURRENCY = 2;
|
|
6673
6707
|
var opencodeSchedulerStates = /* @__PURE__ */ new Map();
|
|
6674
6708
|
var inFlightOpencodeTasks = /* @__PURE__ */ new Set();
|
|
@@ -6682,7 +6716,7 @@ function shouldDeliver(task, reply) {
|
|
|
6682
6716
|
}
|
|
6683
6717
|
async function syncAndCheckOpencodeScheduler(agent, tasks, refreshData) {
|
|
6684
6718
|
const codeName = agent.code_name;
|
|
6685
|
-
const tasksHash =
|
|
6719
|
+
const tasksHash = createHash13("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
6686
6720
|
if (knownOpencodeTaskHashes.get(agent.agent_id) !== tasksHash) {
|
|
6687
6721
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
6688
6722
|
const state8 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
|
|
@@ -6760,7 +6794,7 @@ async function fireOpencodeScheduledTask(agent, task) {
|
|
|
6760
6794
|
}
|
|
6761
6795
|
|
|
6762
6796
|
// src/lib/opencode-telegram-ingest.ts
|
|
6763
|
-
import { createHash as
|
|
6797
|
+
import { createHash as createHash14 } from "crypto";
|
|
6764
6798
|
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync15, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
|
|
6765
6799
|
import { randomUUID } from "crypto";
|
|
6766
6800
|
import { join as join19 } from "path";
|
|
@@ -7296,7 +7330,7 @@ function anySignal(signals) {
|
|
|
7296
7330
|
// src/lib/opencode-telegram-ingest.ts
|
|
7297
7331
|
var ingests2 = /* @__PURE__ */ new Map();
|
|
7298
7332
|
function fingerprint2(params) {
|
|
7299
|
-
return
|
|
7333
|
+
return createHash14("sha256").update(
|
|
7300
7334
|
JSON.stringify({
|
|
7301
7335
|
botToken: params.botToken,
|
|
7302
7336
|
allowedChats: [...params.allowedChats].sort(),
|
|
@@ -9047,7 +9081,7 @@ var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
|
|
|
9047
9081
|
function projectMcpHash(_codeName, projectDir) {
|
|
9048
9082
|
try {
|
|
9049
9083
|
const raw = readFileSync18(join22(projectDir, ".mcp.json"), "utf-8");
|
|
9050
|
-
return
|
|
9084
|
+
return createHash15("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
9051
9085
|
} catch {
|
|
9052
9086
|
return null;
|
|
9053
9087
|
}
|
|
@@ -9393,6 +9427,7 @@ function clearAgentCaches(agentId, codeName) {
|
|
|
9393
9427
|
stopOpencodeSlackIngest(codeName, log);
|
|
9394
9428
|
stopOpencodeTelegramIngest(codeName, log);
|
|
9395
9429
|
agentFrameworkCache.delete(codeName);
|
|
9430
|
+
opencodeCredentialFingerprintBySession.delete(codeName);
|
|
9396
9431
|
kanbanBoardCache.delete(codeName);
|
|
9397
9432
|
clearKanbanNudgeState(codeName);
|
|
9398
9433
|
notifyBoardCache.delete(codeName);
|
|
@@ -9421,7 +9456,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
9421
9456
|
var lastVersionCheckAt = 0;
|
|
9422
9457
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
9423
9458
|
var lastResponsivenessProbeAt = 0;
|
|
9424
|
-
var agtCliVersion = true ? "0.28.
|
|
9459
|
+
var agtCliVersion = true ? "0.28.415" : "dev";
|
|
9425
9460
|
function resolveBrewPath(execFileSync2) {
|
|
9426
9461
|
try {
|
|
9427
9462
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -10706,7 +10741,7 @@ async function pollCycle() {
|
|
|
10706
10741
|
claudeAuth = await detectClaudeAuth();
|
|
10707
10742
|
} catch (err) {
|
|
10708
10743
|
const errText = err instanceof Error ? err.message : String(err);
|
|
10709
|
-
const errId =
|
|
10744
|
+
const errId = createHash15("sha256").update(errText).digest("hex").slice(0, 12);
|
|
10710
10745
|
log(`Claude auth detection failed (error_id=${errId})`);
|
|
10711
10746
|
}
|
|
10712
10747
|
const hostHasClaudeCode = state6.agents.some(
|
|
@@ -12127,7 +12162,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12127
12162
|
const behaviourSubset = extractMsTeamsBehaviourSubset(
|
|
12128
12163
|
msteamsEntry?.config
|
|
12129
12164
|
);
|
|
12130
|
-
const behaviourHash =
|
|
12165
|
+
const behaviourHash = createHash15("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
|
|
12131
12166
|
const prevBehaviourHash = agentState.knownMsTeamsBehaviourHashes.get(agent.agent_id);
|
|
12132
12167
|
const msteamsBehaviourRestrictive = isMsTeamsBehaviourRestrictive(behaviourSubset);
|
|
12133
12168
|
const behaviourDecision = decideSenderPolicyRestart({
|
|
@@ -12183,7 +12218,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12183
12218
|
const slackBehaviourSubset = extractSlackBehaviourSubset(
|
|
12184
12219
|
slackEntry?.config
|
|
12185
12220
|
);
|
|
12186
|
-
const slackBehaviourHash =
|
|
12221
|
+
const slackBehaviourHash = createHash15("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
|
|
12187
12222
|
const prevSlackBehaviourHash = agentState.knownSlackBehaviourHashes.get(agent.agent_id);
|
|
12188
12223
|
const slackBehaviourRestrictive = isSlackBehaviourRestrictive(slackBehaviourSubset);
|
|
12189
12224
|
const slackBehaviourDecision = decideSenderPolicyRestart({
|
|
@@ -12616,10 +12651,10 @@ async function processAgent(agent, agentStates) {
|
|
|
12616
12651
|
desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
|
|
12617
12652
|
}
|
|
12618
12653
|
const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
|
|
12619
|
-
const headersHash =
|
|
12654
|
+
const headersHash = createHash15("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
|
|
12620
12655
|
return `${e.serverId}|${e.url}|${headersHash}`;
|
|
12621
12656
|
}).join("\n");
|
|
12622
|
-
const mcpHash =
|
|
12657
|
+
const mcpHash = createHash15("sha256").update(hashBasis).digest("hex").slice(0, 16);
|
|
12623
12658
|
const prevMcpHash = agentState.knownManagedMcpHashes.get(agent.agent_id);
|
|
12624
12659
|
const structureHash = managedMcpStructureHash(desiredEntries);
|
|
12625
12660
|
const prevStructureHash = agentState.knownManagedMcpStructure.get(agent.agent_id);
|
|
@@ -12634,7 +12669,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12634
12669
|
if (mcpHash !== prevMcpHash) {
|
|
12635
12670
|
for (const e of desiredEntries) {
|
|
12636
12671
|
frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
|
|
12637
|
-
const urlHash =
|
|
12672
|
+
const urlHash = createHash15("sha256").update(e.url).digest("hex").slice(0, 12);
|
|
12638
12673
|
log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
|
|
12639
12674
|
}
|
|
12640
12675
|
if (frameworkAdapter.removeMcpServer && frameworkAdapter.readMcpServers) {
|
|
@@ -12736,7 +12771,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12736
12771
|
if (frameworkAdapter.installSkillFiles) {
|
|
12737
12772
|
const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
|
|
12738
12773
|
const installedIntegrationSkills = [];
|
|
12739
|
-
const { createHash:
|
|
12774
|
+
const { createHash: createHash16 } = await import("crypto");
|
|
12740
12775
|
const refreshAny = refreshData;
|
|
12741
12776
|
const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
|
|
12742
12777
|
const contextBySlug = /* @__PURE__ */ new Map();
|
|
@@ -12765,7 +12800,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12765
12800
|
)
|
|
12766
12801
|
}));
|
|
12767
12802
|
const bundle = buildIntegrationBundle(renderedScopes);
|
|
12768
|
-
const contentHash =
|
|
12803
|
+
const contentHash = createHash16("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
|
|
12769
12804
|
const hashKey = `plugin-skill:${agent.agent_id}:${integrationSkillId}`;
|
|
12770
12805
|
if (agentState.knownSkillHashes.get(hashKey) === contentHash) continue;
|
|
12771
12806
|
frameworkAdapter.installSkillFiles(agent.code_name, integrationSkillId, bundle.files);
|
|
@@ -12832,7 +12867,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12832
12867
|
const plan = planGlobalSkillSync(
|
|
12833
12868
|
[...globalSkillsPayload ?? [], ...sharedSkillsPayload ?? []],
|
|
12834
12869
|
prevIds,
|
|
12835
|
-
(content) =>
|
|
12870
|
+
(content) => createHash16("sha256").update(content).digest("hex").slice(0, 12),
|
|
12836
12871
|
(skillId) => agentState.knownSkillHashes.get(`global-skill:${agent.agent_id}:${skillId}`),
|
|
12837
12872
|
{ desiredResolved }
|
|
12838
12873
|
);
|
|
@@ -12883,7 +12918,7 @@ async function processAgent(agent, agentStates) {
|
|
|
12883
12918
|
const slug = hook.integration_slug ?? hook.plugin_slug;
|
|
12884
12919
|
if (!slug) continue;
|
|
12885
12920
|
try {
|
|
12886
|
-
const scriptHash =
|
|
12921
|
+
const scriptHash = createHash16("sha256").update(hook.script).digest("hex").slice(0, 12);
|
|
12887
12922
|
const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
|
|
12888
12923
|
if (agentState.knownSkillHashes.get(hookKey) === scriptHash) continue;
|
|
12889
12924
|
const result = await frameworkAdapter.executePluginHook({
|
|
@@ -12898,9 +12933,9 @@ async function processAgent(agent, agentStates) {
|
|
|
12898
12933
|
} else if (result.timedOut) {
|
|
12899
12934
|
log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
|
|
12900
12935
|
} else {
|
|
12901
|
-
const stderrHash =
|
|
12936
|
+
const stderrHash = createHash16("sha256").update(result.stderr).digest("hex").slice(0, 12);
|
|
12902
12937
|
const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
|
|
12903
|
-
const missingCmdHash = missingCmd ?
|
|
12938
|
+
const missingCmdHash = missingCmd ? createHash16("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
|
|
12904
12939
|
log(
|
|
12905
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}]`
|
|
12906
12941
|
);
|
|
@@ -13499,6 +13534,7 @@ var lastModelApiErrorSig = /* @__PURE__ */ new Map();
|
|
|
13499
13534
|
var DAY_ROLLOVER_FORCE_GRACE_MIN = 30;
|
|
13500
13535
|
var persistentSessionStuckTracker = new PersistentSessionStuckTracker();
|
|
13501
13536
|
var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
|
|
13537
|
+
var opencodeCredentialFingerprintBySession = /* @__PURE__ */ new Map();
|
|
13502
13538
|
var egressAllowlistBySession = /* @__PURE__ */ new Map();
|
|
13503
13539
|
function deriveEgressAllowlist(toolsRaw) {
|
|
13504
13540
|
return buildEgressAllowlist(
|
|
@@ -13508,16 +13544,31 @@ function deriveEgressAllowlist(toolsRaw) {
|
|
|
13508
13544
|
var egressAllowlistEqual = (a, b) => a.length === b.length && a.every((d, i) => d === b[i]);
|
|
13509
13545
|
async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
13510
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
|
+
});
|
|
13511
13554
|
if (isOpencodeSessionHealthy(codeName)) {
|
|
13512
|
-
|
|
13513
|
-
|
|
13514
|
-
|
|
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
|
+
}
|
|
13515
13568
|
}
|
|
13516
13569
|
stopOpencodeSlackIngest(codeName, log);
|
|
13517
13570
|
stopOpencodeTelegramIngest(codeName, log);
|
|
13518
13571
|
const opencodeProjectDir = join22(getFramework("opencode").getAgentDir(codeName), "provision");
|
|
13519
|
-
const openRouterRaw = refreshData.openrouter ?? null;
|
|
13520
|
-
const anthropicRaw = refreshData.anthropic ?? null;
|
|
13521
13572
|
const serveEnv = {
|
|
13522
13573
|
AGT_HOST: requireHost(),
|
|
13523
13574
|
AGT_API_KEY: getApiKey() ?? void 0,
|
|
@@ -13549,6 +13600,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
|
|
|
13549
13600
|
detail: tail ? `opencode spawn failed: ${tail.slice(0, 200)}` : "opencode spawn failed"
|
|
13550
13601
|
};
|
|
13551
13602
|
}
|
|
13603
|
+
opencodeCredentialFingerprintBySession.set(codeName, credentialFingerprint);
|
|
13552
13604
|
return {
|
|
13553
13605
|
decision: "spawn",
|
|
13554
13606
|
spawnAttempted,
|
|
@@ -13718,7 +13770,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
13718
13770
|
const ctx = getLastFailureContext(codeName);
|
|
13719
13771
|
const recovery = prepareForRespawn(codeName);
|
|
13720
13772
|
const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
|
|
13721
|
-
${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)`;
|
|
13722
13774
|
const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
|
|
13723
13775
|
const recoverySummary = recovery ? `; recovery=${recovery}` : "";
|
|
13724
13776
|
log(
|
|
@@ -13732,7 +13784,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash14("sha256")
|
|
|
13732
13784
|
);
|
|
13733
13785
|
getHostId().then((hostId) => {
|
|
13734
13786
|
if (!hostId) return;
|
|
13735
|
-
const paneTailHash = zombie.paneTail ? `sha256:${
|
|
13787
|
+
const paneTailHash = zombie.paneTail ? `sha256:${createHash15("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
|
|
13736
13788
|
return api.post("/host/events", {
|
|
13737
13789
|
host_id: hostId,
|
|
13738
13790
|
agent_code_name: codeName,
|
|
@@ -13881,7 +13933,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash14("sha256")
|
|
|
13881
13933
|
if (!claudeAuthTupleBySession.has(codeName)) {
|
|
13882
13934
|
claudeAuthTupleBySession.set(codeName, currentAuthTuple);
|
|
13883
13935
|
}
|
|
13884
|
-
const stableTasksHash =
|
|
13936
|
+
const stableTasksHash = createHash15("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
13885
13937
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
13886
13938
|
if (stableTasksHash !== prevHash) {
|
|
13887
13939
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
@@ -14882,7 +14934,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
14882
14934
|
if (!file.endsWith(".md")) continue;
|
|
14883
14935
|
try {
|
|
14884
14936
|
const raw = readFileSync18(join22(memoryDir, file), "utf-8");
|
|
14885
|
-
const fileHash =
|
|
14937
|
+
const fileHash = createHash15("sha256").update(raw).digest("hex").slice(0, 16);
|
|
14886
14938
|
currentHashes.set(file, fileHash);
|
|
14887
14939
|
if (prevHashes.get(file) === fileHash) continue;
|
|
14888
14940
|
const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
|
|
@@ -14920,14 +14972,14 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
14920
14972
|
}
|
|
14921
14973
|
async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
14922
14974
|
const localFiles = existsSync11(memoryDir) ? readdirSync6(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
14923
|
-
const localListHash =
|
|
14975
|
+
const localListHash = createHash15("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
14924
14976
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
14925
14977
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
14926
14978
|
try {
|
|
14927
14979
|
const dbMemories = await api.post("/host/memories", {
|
|
14928
14980
|
agent_id: agent.agent_id
|
|
14929
14981
|
});
|
|
14930
|
-
const responseHash =
|
|
14982
|
+
const responseHash = createHash15("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
|
|
14931
14983
|
if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
|
|
14932
14984
|
return true;
|
|
14933
14985
|
}
|
|
@@ -14966,7 +15018,7 @@ ${mem.content}
|
|
|
14966
15018
|
}
|
|
14967
15019
|
if (written > 0 || overwritten > 0) {
|
|
14968
15020
|
const updatedFiles = readdirSync6(memoryDir).filter((f) => f.endsWith(".md")).sort();
|
|
14969
|
-
lastLocalFileHash.set(agent.agent_id,
|
|
15021
|
+
lastLocalFileHash.set(agent.agent_id, createHash15("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
|
|
14970
15022
|
log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
|
|
14971
15023
|
}
|
|
14972
15024
|
}
|
|
@@ -15391,7 +15443,7 @@ function deployMcpAssets() {
|
|
|
15391
15443
|
const fileHash = (p) => {
|
|
15392
15444
|
try {
|
|
15393
15445
|
if (!existsSync11(p)) return null;
|
|
15394
|
-
return
|
|
15446
|
+
return createHash15("sha256").update(readFileSync18(p)).digest("hex");
|
|
15395
15447
|
} catch {
|
|
15396
15448
|
return null;
|
|
15397
15449
|
}
|