@integrity-labs/agt-cli 0.24.2 → 0.24.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/agt.js
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
success,
|
|
27
27
|
table,
|
|
28
28
|
warn
|
|
29
|
-
} from "../chunk-
|
|
29
|
+
} from "../chunk-3TYBPBDA.js";
|
|
30
30
|
import {
|
|
31
31
|
CHANNEL_REGISTRY,
|
|
32
32
|
DEPLOYMENT_TEMPLATES,
|
|
@@ -3736,7 +3736,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
3736
3736
|
import { existsSync as existsSync5, realpathSync } from "fs";
|
|
3737
3737
|
import chalk17 from "chalk";
|
|
3738
3738
|
import ora15 from "ora";
|
|
3739
|
-
var cliVersion = true ? "0.24.
|
|
3739
|
+
var cliVersion = true ? "0.24.4" : "dev";
|
|
3740
3740
|
async function fetchLatestVersion() {
|
|
3741
3741
|
const host2 = getHost();
|
|
3742
3742
|
if (!host2) return null;
|
|
@@ -4268,7 +4268,7 @@ function handleError(err) {
|
|
|
4268
4268
|
}
|
|
4269
4269
|
|
|
4270
4270
|
// src/bin/agt.ts
|
|
4271
|
-
var cliVersion2 = true ? "0.24.
|
|
4271
|
+
var cliVersion2 = true ? "0.24.4" : "dev";
|
|
4272
4272
|
var program = new Command();
|
|
4273
4273
|
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");
|
|
4274
4274
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
provisionOrientHook,
|
|
13
13
|
provisionStopHook,
|
|
14
14
|
requireHost
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-3TYBPBDA.js";
|
|
16
16
|
import {
|
|
17
17
|
findTaskByTemplate,
|
|
18
18
|
getProjectDir as getProjectDir2,
|
|
@@ -69,7 +69,7 @@ import {
|
|
|
69
69
|
} from "../chunk-ECDTRQLA.js";
|
|
70
70
|
|
|
71
71
|
// src/lib/manager-worker.ts
|
|
72
|
-
import { createHash as
|
|
72
|
+
import { createHash as createHash3 } from "crypto";
|
|
73
73
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync2, chmodSync, existsSync as existsSync4, rmSync as rmSync2, readdirSync as readdirSync3, statSync as statSync2, unlinkSync, copyFileSync } from "fs";
|
|
74
74
|
import https from "https";
|
|
75
75
|
import { execFileSync as syncExecFile } from "child_process";
|
|
@@ -78,15 +78,30 @@ import { homedir as homedir4 } from "os";
|
|
|
78
78
|
import { fileURLToPath } from "url";
|
|
79
79
|
|
|
80
80
|
// src/lib/mcp-config-drift.ts
|
|
81
|
+
import { createHash } from "crypto";
|
|
81
82
|
function decideMcpDriftAction(currentHash, knownHash) {
|
|
82
83
|
if (!currentHash) return { kind: "no-config" };
|
|
83
84
|
if (!knownHash) return { kind: "baseline", hash: currentHash };
|
|
84
85
|
if (knownHash === currentHash) return { kind: "no-drift" };
|
|
85
86
|
return { kind: "drift", previous: knownHash, current: currentHash };
|
|
86
87
|
}
|
|
88
|
+
function decideMcpRestartOnDrift(previousKeys, currentKeys) {
|
|
89
|
+
if (!previousKeys || !currentKeys) {
|
|
90
|
+
return { restart: true, membershipUnknown: true, addedOrRemoved: [] };
|
|
91
|
+
}
|
|
92
|
+
const addedOrRemoved = [];
|
|
93
|
+
for (const k of currentKeys) if (!previousKeys.has(k)) addedOrRemoved.push(k);
|
|
94
|
+
for (const k of previousKeys) if (!currentKeys.has(k)) addedOrRemoved.push(k);
|
|
95
|
+
addedOrRemoved.sort();
|
|
96
|
+
return { restart: addedOrRemoved.length > 0, membershipUnknown: false, addedOrRemoved };
|
|
97
|
+
}
|
|
98
|
+
function managedMcpStructureHash(entries) {
|
|
99
|
+
const basis = entries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => `${e.serverId}|${Object.keys(e.headers ?? {}).sort().join(",")}`).join("\n");
|
|
100
|
+
return createHash("sha256").update(basis).digest("hex").slice(0, 16);
|
|
101
|
+
}
|
|
87
102
|
|
|
88
103
|
// src/lib/integration-hash.ts
|
|
89
|
-
import { createHash } from "crypto";
|
|
104
|
+
import { createHash as createHash2 } from "crypto";
|
|
90
105
|
function canonicalize(value) {
|
|
91
106
|
if (Array.isArray(value)) return value.map(canonicalize);
|
|
92
107
|
if (value && typeof value === "object") {
|
|
@@ -103,7 +118,7 @@ function computeIntegrationsHash(integrations) {
|
|
|
103
118
|
const payload = integrations.map(
|
|
104
119
|
(i) => `${i.definition_id}:${JSON.stringify(canonicalize(i.credentials ?? {}))}:${JSON.stringify(canonicalize(i.config ?? {}))}`
|
|
105
120
|
);
|
|
106
|
-
return
|
|
121
|
+
return createHash2("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
|
|
107
122
|
}
|
|
108
123
|
|
|
109
124
|
// src/lib/stale-mcp-reaper.ts
|
|
@@ -790,6 +805,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
790
805
|
state2.set(codeName, next);
|
|
791
806
|
return;
|
|
792
807
|
}
|
|
808
|
+
let reported = 0;
|
|
793
809
|
for (let i = 0; i < pending.length; i += MAX_ENTRIES_PER_POST) {
|
|
794
810
|
const batch = pending.slice(i, i + MAX_ENTRIES_PER_POST);
|
|
795
811
|
try {
|
|
@@ -802,10 +818,14 @@ async function maybeReportTokenUsage(args) {
|
|
|
802
818
|
for (const b of batch) {
|
|
803
819
|
files.set(b.sessionId, b.fp);
|
|
804
820
|
}
|
|
821
|
+
reported += batch.length;
|
|
805
822
|
} catch (err) {
|
|
806
823
|
log2(`[token-usage] POST failed for '${codeName}': ${err.message}`);
|
|
807
824
|
}
|
|
808
825
|
}
|
|
826
|
+
if (reported > 0) {
|
|
827
|
+
log2(`[token-usage] reported ${reported} entr${reported === 1 ? "y" : "ies"} for '${codeName}'`);
|
|
828
|
+
}
|
|
809
829
|
state2.set(codeName, next);
|
|
810
830
|
}
|
|
811
831
|
|
|
@@ -2622,7 +2642,7 @@ var runningMcpServerKeys = /* @__PURE__ */ new Map();
|
|
|
2622
2642
|
function projectMcpHash(_codeName, projectDir) {
|
|
2623
2643
|
try {
|
|
2624
2644
|
const raw = readFileSync5(join6(projectDir, ".mcp.json"), "utf-8");
|
|
2625
|
-
return
|
|
2645
|
+
return createHash3("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
2626
2646
|
} catch {
|
|
2627
2647
|
return null;
|
|
2628
2648
|
}
|
|
@@ -2666,33 +2686,34 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
|
2666
2686
|
}
|
|
2667
2687
|
case "drift": {
|
|
2668
2688
|
log(
|
|
2669
|
-
`[hot-reload] .mcp.json content changed for '${codeName}' (${action.previous.slice(0, 12)} \u2192 ${action.current.slice(0, 12)})
|
|
2689
|
+
`[hot-reload] .mcp.json content changed for '${codeName}' (${action.previous.slice(0, 12)} \u2192 ${action.current.slice(0, 12)}) (ENG-4897)`
|
|
2670
2690
|
);
|
|
2671
2691
|
const previousKeys = runningMcpServerKeys.get(codeName);
|
|
2672
2692
|
const currentKeys = projectMcpKeys(codeName, projectDir);
|
|
2673
|
-
|
|
2693
|
+
const decision = decideMcpRestartOnDrift(previousKeys, currentKeys);
|
|
2694
|
+
if (decision.membershipUnknown) {
|
|
2674
2695
|
clearPresenceReaperState(codeName);
|
|
2675
2696
|
log(
|
|
2676
|
-
`[hot-reload] .mcp.json key membership unavailable for '${codeName}' \u2014 clearing full presence-reaper state (ENG-5285)`
|
|
2697
|
+
`[hot-reload] .mcp.json key membership unavailable for '${codeName}' \u2014 clearing full presence-reaper state and restarting (ENG-5285/ENG-5537)`
|
|
2698
|
+
);
|
|
2699
|
+
} else if (decision.restart) {
|
|
2700
|
+
clearPresenceReaperStateForKeys(codeName, new Set(decision.addedOrRemoved));
|
|
2701
|
+
log(
|
|
2702
|
+
`[hot-reload] .mcp.json membership changed for '${codeName}': ${decision.addedOrRemoved.length} key(s) added/removed [${decision.addedOrRemoved.join(", ")}] \u2014 reaper state cleared for those keys only (ENG-5285)`
|
|
2677
2703
|
);
|
|
2678
2704
|
} else {
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
);
|
|
2691
|
-
}
|
|
2705
|
+
log(
|
|
2706
|
+
`[hot-reload] .mcp.json value-only drift for '${codeName}' \u2014 preserving presence-reaper state and NOT restarting (ENG-5285/ENG-5537)`
|
|
2707
|
+
);
|
|
2708
|
+
}
|
|
2709
|
+
if (decision.restart) {
|
|
2710
|
+
scheduleSessionRestart(codeName, 0, ".mcp.json content change (ENG-4897)");
|
|
2711
|
+
runningMcpHashes.delete(codeName);
|
|
2712
|
+
runningMcpServerKeys.delete(codeName);
|
|
2713
|
+
} else {
|
|
2714
|
+
runningMcpHashes.set(codeName, action.current);
|
|
2715
|
+
if (currentKeys) runningMcpServerKeys.set(codeName, currentKeys);
|
|
2692
2716
|
}
|
|
2693
|
-
scheduleSessionRestart(codeName, 0, ".mcp.json content change (ENG-4897)");
|
|
2694
|
-
runningMcpHashes.delete(codeName);
|
|
2695
|
-
runningMcpServerKeys.delete(codeName);
|
|
2696
2717
|
return;
|
|
2697
2718
|
}
|
|
2698
2719
|
}
|
|
@@ -2702,6 +2723,7 @@ var knownModels = /* @__PURE__ */ new Map();
|
|
|
2702
2723
|
var knownTasksHashes = /* @__PURE__ */ new Map();
|
|
2703
2724
|
var knownIntegrationHashes = /* @__PURE__ */ new Map();
|
|
2704
2725
|
var knownManagedMcpHashes = /* @__PURE__ */ new Map();
|
|
2726
|
+
var knownManagedMcpStructure = /* @__PURE__ */ new Map();
|
|
2705
2727
|
var knownSkillHashes = /* @__PURE__ */ new Map();
|
|
2706
2728
|
var managedToolkitIdByAgentAndServerId = /* @__PURE__ */ new Map();
|
|
2707
2729
|
function managedToolkitMapKey(agentId, serverId) {
|
|
@@ -2753,6 +2775,7 @@ function clearAgentCaches(agentId, codeName) {
|
|
|
2753
2775
|
knownTasksHashes.delete(agentId);
|
|
2754
2776
|
knownIntegrationHashes.delete(agentId);
|
|
2755
2777
|
knownManagedMcpHashes.delete(agentId);
|
|
2778
|
+
knownManagedMcpStructure.delete(agentId);
|
|
2756
2779
|
agentDisplayNames.delete(codeName);
|
|
2757
2780
|
codeNameToAgentId.delete(codeName);
|
|
2758
2781
|
agentFrameworkCache.delete(codeName);
|
|
@@ -2783,7 +2806,7 @@ var cachedFrameworkVersion = null;
|
|
|
2783
2806
|
var lastVersionCheckAt = 0;
|
|
2784
2807
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2785
2808
|
var lastResponsivenessProbeAt = 0;
|
|
2786
|
-
var agtCliVersion = true ? "0.24.
|
|
2809
|
+
var agtCliVersion = true ? "0.24.4" : "dev";
|
|
2787
2810
|
function resolveBrewPath(execFileSync4) {
|
|
2788
2811
|
try {
|
|
2789
2812
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -3362,7 +3385,7 @@ function log(msg) {
|
|
|
3362
3385
|
}
|
|
3363
3386
|
}
|
|
3364
3387
|
function sha256(content) {
|
|
3365
|
-
return
|
|
3388
|
+
return createHash3("sha256").update(content, "utf8").digest("hex");
|
|
3366
3389
|
}
|
|
3367
3390
|
function hashFile(filePath) {
|
|
3368
3391
|
try {
|
|
@@ -3772,7 +3795,7 @@ async function pollCycle() {
|
|
|
3772
3795
|
claudeAuth = await detectClaudeAuth();
|
|
3773
3796
|
} catch (err) {
|
|
3774
3797
|
const errText = err instanceof Error ? err.message : String(err);
|
|
3775
|
-
const errId =
|
|
3798
|
+
const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
|
|
3776
3799
|
log(`Claude auth detection failed (error_id=${errId})`);
|
|
3777
3800
|
}
|
|
3778
3801
|
await api.post("/host/heartbeat", {
|
|
@@ -4492,7 +4515,7 @@ async function processAgent(agent, agentStates) {
|
|
|
4492
4515
|
const peersForHash = channelId === "telegram" ? extractCharterTelegramPeers(refreshData.charter?.raw_content ?? "", gateContext) : channelId === "slack" ? extractCharterSlackPeers(refreshData.charter?.raw_content ?? "", gateContext) : null;
|
|
4493
4516
|
const sessionModeForHash = refreshData.agent.session_mode;
|
|
4494
4517
|
const CHANNEL_WRITE_VERSION = 5;
|
|
4495
|
-
const configHash =
|
|
4518
|
+
const configHash = createHash3("sha256").update(
|
|
4496
4519
|
canonicalJson({
|
|
4497
4520
|
writeVersion: CHANNEL_WRITE_VERSION,
|
|
4498
4521
|
config: entry.config,
|
|
@@ -4754,15 +4777,17 @@ async function processAgent(agent, agentStates) {
|
|
|
4754
4777
|
desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
|
|
4755
4778
|
}
|
|
4756
4779
|
const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
|
|
4757
|
-
const headersHash =
|
|
4780
|
+
const headersHash = createHash3("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
|
|
4758
4781
|
return `${e.serverId}|${e.url}|${headersHash}`;
|
|
4759
4782
|
}).join("\n");
|
|
4760
|
-
const mcpHash =
|
|
4783
|
+
const mcpHash = createHash3("sha256").update(hashBasis).digest("hex").slice(0, 16);
|
|
4761
4784
|
const prevMcpHash = knownManagedMcpHashes.get(agent.agent_id);
|
|
4785
|
+
const structureHash = managedMcpStructureHash(desiredEntries);
|
|
4786
|
+
const prevStructureHash = knownManagedMcpStructure.get(agent.agent_id);
|
|
4762
4787
|
if (mcpHash !== prevMcpHash) {
|
|
4763
4788
|
for (const e of desiredEntries) {
|
|
4764
4789
|
frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
|
|
4765
|
-
const urlHash =
|
|
4790
|
+
const urlHash = createHash3("sha256").update(e.url).digest("hex").slice(0, 12);
|
|
4766
4791
|
log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
|
|
4767
4792
|
}
|
|
4768
4793
|
if (frameworkAdapter.removeMcpServer && frameworkAdapter.getMcpPath) {
|
|
@@ -4796,7 +4821,8 @@ async function processAgent(agent, agentStates) {
|
|
|
4796
4821
|
}
|
|
4797
4822
|
}
|
|
4798
4823
|
knownManagedMcpHashes.set(agent.agent_id, mcpHash);
|
|
4799
|
-
|
|
4824
|
+
knownManagedMcpStructure.set(agent.agent_id, structureHash);
|
|
4825
|
+
if (prevStructureHash !== void 0 && structureHash !== prevStructureHash && fwForMcp === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
4800
4826
|
const mcpNames = agentToolkits.map((tk) => tk.toolkit_name).join(", ") || "none (all removed)";
|
|
4801
4827
|
log(`[hot-reload] MCP servers changed for '${agent.code_name}': ${mcpNames} \u2014 restarting session`);
|
|
4802
4828
|
const restartNotice = agentToolkits.length > 0 ? `New MCP tool servers have been configured: ${mcpNames}. Note: MCP servers require a session restart to connect. Your manager will restart your session shortly.` : "Managed MCP tool servers were removed. Your manager will restart your session shortly so the session drops those tools.";
|
|
@@ -4884,7 +4910,7 @@ async function processAgent(agent, agentStates) {
|
|
|
4884
4910
|
if (frameworkAdapter.installSkillFiles) {
|
|
4885
4911
|
const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
|
|
4886
4912
|
const installedIntegrationSkills = [];
|
|
4887
|
-
const { createHash:
|
|
4913
|
+
const { createHash: createHash4 } = await import("crypto");
|
|
4888
4914
|
const refreshAny = refreshData;
|
|
4889
4915
|
const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
|
|
4890
4916
|
const contextBySlug = /* @__PURE__ */ new Map();
|
|
@@ -4913,7 +4939,7 @@ async function processAgent(agent, agentStates) {
|
|
|
4913
4939
|
)
|
|
4914
4940
|
}));
|
|
4915
4941
|
const bundle = buildIntegrationBundle(renderedScopes);
|
|
4916
|
-
const contentHash =
|
|
4942
|
+
const contentHash = createHash4("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
|
|
4917
4943
|
const hashKey = `plugin-skill:${agent.agent_id}:${integrationSkillId}`;
|
|
4918
4944
|
if (knownSkillHashes.get(hashKey) === contentHash) continue;
|
|
4919
4945
|
frameworkAdapter.installSkillFiles(agent.code_name, integrationSkillId, bundle.files);
|
|
@@ -4982,7 +5008,7 @@ async function processAgent(agent, agentStates) {
|
|
|
4982
5008
|
const slug = hook.integration_slug ?? hook.plugin_slug;
|
|
4983
5009
|
if (!slug) continue;
|
|
4984
5010
|
try {
|
|
4985
|
-
const scriptHash =
|
|
5011
|
+
const scriptHash = createHash4("sha256").update(hook.script).digest("hex").slice(0, 12);
|
|
4986
5012
|
const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
|
|
4987
5013
|
if (knownSkillHashes.get(hookKey) === scriptHash) continue;
|
|
4988
5014
|
const result = await frameworkAdapter.executePluginHook({
|
|
@@ -4997,9 +5023,9 @@ async function processAgent(agent, agentStates) {
|
|
|
4997
5023
|
} else if (result.timedOut) {
|
|
4998
5024
|
log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
|
|
4999
5025
|
} else {
|
|
5000
|
-
const stderrHash =
|
|
5026
|
+
const stderrHash = createHash4("sha256").update(result.stderr).digest("hex").slice(0, 12);
|
|
5001
5027
|
const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
|
|
5002
|
-
const missingCmdHash = missingCmd ?
|
|
5028
|
+
const missingCmdHash = missingCmd ? createHash4("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
|
|
5003
5029
|
log(
|
|
5004
5030
|
`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}]`
|
|
5005
5031
|
);
|
|
@@ -5189,10 +5215,10 @@ async function processAgent(agent, agentStates) {
|
|
|
5189
5215
|
} else if (agentFw === "claude-code" && tasks.length > 0) {
|
|
5190
5216
|
await syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData);
|
|
5191
5217
|
} else if (frameworkAdapter.syncScheduledTasks && gatewayRunning && gatewayPort) {
|
|
5192
|
-
const stableTasksHash =
|
|
5193
|
-
const boardHash = boardItems.length > 0 ?
|
|
5218
|
+
const stableTasksHash = createHash3("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
5219
|
+
const boardHash = boardItems.length > 0 ? createHash3("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";
|
|
5194
5220
|
const resolvedModels = resolveModelChain(refreshData);
|
|
5195
|
-
const modelsHash =
|
|
5221
|
+
const modelsHash = createHash3("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
|
|
5196
5222
|
const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
|
|
5197
5223
|
const prevTasksHash = knownTasksHashes.get(agent.agent_id);
|
|
5198
5224
|
if (combinedHash !== prevTasksHash) {
|
|
@@ -5572,10 +5598,10 @@ var MAX_CLAUDE_CONCURRENCY = 2;
|
|
|
5572
5598
|
var claudeSchedulerStates = /* @__PURE__ */ new Map();
|
|
5573
5599
|
async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData) {
|
|
5574
5600
|
const codeName = agent.code_name;
|
|
5575
|
-
const stableTasksHash =
|
|
5576
|
-
const boardHash = boardItems.length > 0 ?
|
|
5601
|
+
const stableTasksHash = createHash3("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
5602
|
+
const boardHash = boardItems.length > 0 ? createHash3("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";
|
|
5577
5603
|
const resolvedModels = resolveModelChain(refreshData);
|
|
5578
|
-
const modelsHash =
|
|
5604
|
+
const modelsHash = createHash3("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
|
|
5579
5605
|
const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
|
|
5580
5606
|
const prevHash = knownTasksHashes.get(agent.agent_id);
|
|
5581
5607
|
if (combinedHash !== prevHash) {
|
|
@@ -5653,7 +5679,7 @@ async function startRun(opts) {
|
|
|
5653
5679
|
return { run_id: res.run_id ?? null, kanban_item_id: res.kanban_item_id ?? null };
|
|
5654
5680
|
} catch (err) {
|
|
5655
5681
|
const errText = err instanceof Error ? err.message : String(err);
|
|
5656
|
-
const errId =
|
|
5682
|
+
const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
|
|
5657
5683
|
log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
|
|
5658
5684
|
return { run_id: null, kanban_item_id: null };
|
|
5659
5685
|
}
|
|
@@ -5670,7 +5696,7 @@ async function finishRun(runId, outcome, options = {}) {
|
|
|
5670
5696
|
});
|
|
5671
5697
|
} catch (err) {
|
|
5672
5698
|
const errText = err instanceof Error ? err.message : String(err);
|
|
5673
|
-
const errId =
|
|
5699
|
+
const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
|
|
5674
5700
|
log(`[runs] finish failed for run_id=${runId} outcome=${outcome} error_id=${errId}`);
|
|
5675
5701
|
}
|
|
5676
5702
|
}
|
|
@@ -5687,7 +5713,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
|
|
|
5687
5713
|
return rows.filter((r) => typeof r.output_text === "string" && r.output_text.length > 0).map((r) => ({ startedAt: r.started_at, output: r.output_text }));
|
|
5688
5714
|
} catch (err) {
|
|
5689
5715
|
const errText = err instanceof Error ? err.message : String(err);
|
|
5690
|
-
const errId =
|
|
5716
|
+
const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
|
|
5691
5717
|
log(`[runs] prior-runs lookup failed for task_id=${taskId} error_id=${errId}`);
|
|
5692
5718
|
return [];
|
|
5693
5719
|
}
|
|
@@ -5821,10 +5847,10 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
5821
5847
|
const classification = classifyOutput(rawOutput);
|
|
5822
5848
|
if (classification.action === "suppress") {
|
|
5823
5849
|
const trimmed = (rawOutput ?? "").trim();
|
|
5824
|
-
const outputHash = trimmed.length === 0 ? "empty" :
|
|
5850
|
+
const outputHash = trimmed.length === 0 ? "empty" : createHash3("sha256").update(trimmed).digest("hex").slice(0, 12);
|
|
5825
5851
|
log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
|
|
5826
5852
|
if (classification.suppressedNotes) {
|
|
5827
|
-
const notesHash =
|
|
5853
|
+
const notesHash = createHash3("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
|
|
5828
5854
|
log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
|
|
5829
5855
|
}
|
|
5830
5856
|
if (delivery?.mode === "announce" && delivery.to) {
|
|
@@ -6046,7 +6072,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
6046
6072
|
const ctx = getLastFailureContext(codeName);
|
|
6047
6073
|
const recovery = prepareForRespawn(codeName);
|
|
6048
6074
|
const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
|
|
6049
|
-
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${
|
|
6075
|
+
${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash3("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
|
|
6050
6076
|
const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
|
|
6051
6077
|
const recoverySummary = recovery ? `; recovery=${recovery}` : "";
|
|
6052
6078
|
log(
|
|
@@ -6060,7 +6086,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash2("sha256").
|
|
|
6060
6086
|
);
|
|
6061
6087
|
getHostId().then((hostId) => {
|
|
6062
6088
|
if (!hostId) return;
|
|
6063
|
-
const paneTailHash = zombie.paneTail ? `sha256:${
|
|
6089
|
+
const paneTailHash = zombie.paneTail ? `sha256:${createHash3("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
|
|
6064
6090
|
return api.post("/host/events", {
|
|
6065
6091
|
host_id: hostId,
|
|
6066
6092
|
agent_code_name: codeName,
|
|
@@ -6127,7 +6153,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash2("sha256").
|
|
|
6127
6153
|
if (!claudeAuthTupleBySession.has(codeName)) {
|
|
6128
6154
|
claudeAuthTupleBySession.set(codeName, currentAuthTuple);
|
|
6129
6155
|
}
|
|
6130
|
-
const stableTasksHash =
|
|
6156
|
+
const stableTasksHash = createHash3("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
6131
6157
|
const prevHash = knownTasksHashes.get(agent.agent_id);
|
|
6132
6158
|
if (stableTasksHash !== prevHash) {
|
|
6133
6159
|
const taskInputs = tasks.map((t) => ({
|
|
@@ -6611,7 +6637,7 @@ ${escapeXml(msg.content)}
|
|
|
6611
6637
|
log(`[direct-chat] Reply sent for '${agent.codeName}'`);
|
|
6612
6638
|
} catch (err) {
|
|
6613
6639
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
6614
|
-
const errorId =
|
|
6640
|
+
const errorId = createHash3("sha256").update(errMsg).digest("hex").slice(0, 12);
|
|
6615
6641
|
log(`[direct-chat] Failed to process message for '${agent.codeName}': error_id=${errorId} error=${errMsg.slice(0, 500)}`);
|
|
6616
6642
|
try {
|
|
6617
6643
|
await api.post("/host/direct-chat/reply", {
|
|
@@ -7842,7 +7868,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
7842
7868
|
if (!file.endsWith(".md")) continue;
|
|
7843
7869
|
try {
|
|
7844
7870
|
const raw = readFileSync5(join6(memoryDir, file), "utf-8");
|
|
7845
|
-
const fileHash =
|
|
7871
|
+
const fileHash = createHash3("sha256").update(raw).digest("hex").slice(0, 16);
|
|
7846
7872
|
currentHashes.set(file, fileHash);
|
|
7847
7873
|
if (prevHashes.get(file) === fileHash) continue;
|
|
7848
7874
|
const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
|
|
@@ -7880,14 +7906,14 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
7880
7906
|
}
|
|
7881
7907
|
async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
7882
7908
|
const localFiles = existsSync4(memoryDir) ? readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
7883
|
-
const localListHash =
|
|
7909
|
+
const localListHash = createHash3("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
7884
7910
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
7885
7911
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
7886
7912
|
try {
|
|
7887
7913
|
const dbMemories = await api.post("/host/memories", {
|
|
7888
7914
|
agent_id: agent.agent_id
|
|
7889
7915
|
});
|
|
7890
|
-
const responseHash =
|
|
7916
|
+
const responseHash = createHash3("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
|
|
7891
7917
|
if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
|
|
7892
7918
|
return true;
|
|
7893
7919
|
}
|
|
@@ -7926,7 +7952,7 @@ ${mem.content}
|
|
|
7926
7952
|
}
|
|
7927
7953
|
if (written > 0 || overwritten > 0) {
|
|
7928
7954
|
const updatedFiles = readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort();
|
|
7929
|
-
lastLocalFileHash.set(agent.agent_id,
|
|
7955
|
+
lastLocalFileHash.set(agent.agent_id, createHash3("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
|
|
7930
7956
|
log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
|
|
7931
7957
|
}
|
|
7932
7958
|
}
|
|
@@ -8211,7 +8237,7 @@ function deployMcpAssets() {
|
|
|
8211
8237
|
const fileHash = (p) => {
|
|
8212
8238
|
try {
|
|
8213
8239
|
if (!existsSync4(p)) return null;
|
|
8214
|
-
return
|
|
8240
|
+
return createHash3("sha256").update(readFileSync5(p)).digest("hex");
|
|
8215
8241
|
} catch {
|
|
8216
8242
|
return null;
|
|
8217
8243
|
}
|