@integrity-labs/agt-cli 0.28.148 → 0.28.150
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 +4 -4
- package/dist/{chunk-6BJVRM6Y.js → chunk-HYW5ZAGY.js} +2 -3
- package/dist/{chunk-LCEI5TTS.js → chunk-LCKA5XPX.js} +3 -3
- package/dist/{chunk-XZGF45BJ.js → chunk-SKANUWSB.js} +248 -5
- package/dist/chunk-SKANUWSB.js.map +1 -0
- package/dist/{claude-pair-runtime-AXBFPLBA.js → claude-pair-runtime-ZSBUAMO3.js} +2 -2
- package/dist/lib/manager-worker.js +100 -283
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/index.js +15 -3
- package/dist/{persistent-session-IRXYCR5Q.js → persistent-session-S2674LBO.js} +3 -3
- package/dist/{responsiveness-probe-VVDZTLJS.js → responsiveness-probe-NHQYDMHJ.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-XZGF45BJ.js.map +0 -1
- /package/dist/{chunk-6BJVRM6Y.js.map → chunk-HYW5ZAGY.js.map} +0 -0
- /package/dist/{chunk-LCEI5TTS.js.map → chunk-LCKA5XPX.js.map} +0 -0
- /package/dist/{claude-pair-runtime-AXBFPLBA.js.map → claude-pair-runtime-ZSBUAMO3.js.map} +0 -0
- /package/dist/{persistent-session-IRXYCR5Q.js.map → persistent-session-S2674LBO.js.map} +0 -0
- /package/dist/{responsiveness-probe-VVDZTLJS.js.map → responsiveness-probe-NHQYDMHJ.js.map} +0 -0
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
requireHost,
|
|
29
29
|
safeWriteJsonAtomic,
|
|
30
30
|
setConfigHash
|
|
31
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-LCKA5XPX.js";
|
|
32
32
|
import {
|
|
33
33
|
getProjectDir as getProjectDir2,
|
|
34
34
|
getReadyTasks,
|
|
@@ -61,7 +61,6 @@ import {
|
|
|
61
61
|
resolveClaudeBinary,
|
|
62
62
|
restartEgressSidecar,
|
|
63
63
|
rotateSessionForWedge,
|
|
64
|
-
sanitizeMcpJson,
|
|
65
64
|
sendToAgent,
|
|
66
65
|
sessionTranscriptDir,
|
|
67
66
|
startPersistentSession,
|
|
@@ -72,7 +71,7 @@ import {
|
|
|
72
71
|
takeZombieDetection,
|
|
73
72
|
transcriptActivityAgeSeconds,
|
|
74
73
|
writeEgressAllowlist
|
|
75
|
-
} from "../chunk-
|
|
74
|
+
} from "../chunk-HYW5ZAGY.js";
|
|
76
75
|
import {
|
|
77
76
|
FLAGS_SCHEMA_VERSION,
|
|
78
77
|
FLAG_REGISTRY,
|
|
@@ -98,6 +97,7 @@ import {
|
|
|
98
97
|
isResolveError,
|
|
99
98
|
isSelfCompletion,
|
|
100
99
|
isUnsetTimezone,
|
|
100
|
+
isVacuousDeliverReason,
|
|
101
101
|
laneTagFragment,
|
|
102
102
|
parseDeliverAssertion,
|
|
103
103
|
parseDeliveryTarget,
|
|
@@ -109,9 +109,8 @@ import {
|
|
|
109
109
|
resolveAvatarEnvUrl,
|
|
110
110
|
resolveChannels,
|
|
111
111
|
resolveDmTarget,
|
|
112
|
-
sumTranscriptUsageInWindow
|
|
113
|
-
|
|
114
|
-
} from "../chunk-XZGF45BJ.js";
|
|
112
|
+
sumTranscriptUsageInWindow
|
|
113
|
+
} from "../chunk-SKANUWSB.js";
|
|
115
114
|
import {
|
|
116
115
|
parsePsRows,
|
|
117
116
|
reapOrphanChannelMcps
|
|
@@ -119,7 +118,7 @@ import {
|
|
|
119
118
|
|
|
120
119
|
// src/lib/manager-worker.ts
|
|
121
120
|
import { createHash as createHash10 } from "crypto";
|
|
122
|
-
import { readFileSync as
|
|
121
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, existsSync as existsSync8, rmSync as rmSync4, readdirSync as readdirSync5, statSync as statSync4, unlinkSync, copyFileSync } from "fs";
|
|
123
122
|
import { execFileSync as syncExecFile } from "child_process";
|
|
124
123
|
import { join as join16, dirname as dirname5 } from "path";
|
|
125
124
|
import { homedir as homedir9 } from "os";
|
|
@@ -4778,10 +4777,6 @@ function deriveScheduledTaskNotify(task) {
|
|
|
4778
4777
|
if (!conversationId) return {};
|
|
4779
4778
|
return { notify_channel: "msteams", notify_to: conversationId };
|
|
4780
4779
|
}
|
|
4781
|
-
function isScheduledViaKanbanEnabled() {
|
|
4782
|
-
const v = process.env["AGT_SCHEDULED_VIA_KANBAN"];
|
|
4783
|
-
return !(v === "0" || v?.toLowerCase() === "false");
|
|
4784
|
-
}
|
|
4785
4780
|
|
|
4786
4781
|
// src/lib/manager/scheduler/runs.ts
|
|
4787
4782
|
import { createHash as createHash7 } from "crypto";
|
|
@@ -5145,9 +5140,10 @@ async function deliverScheduledCardResult(codeName, agentId, cardId, completedBy
|
|
|
5145
5140
|
return "terminal";
|
|
5146
5141
|
}
|
|
5147
5142
|
const deliveryPolicy = task.deliveryPolicy ?? "always";
|
|
5148
|
-
|
|
5143
|
+
const vacuousAssertion = deliveryPolicy === "conditional" && card.suppress_delivery === false && card.delivery_reason !== void 0 && isVacuousDeliverReason(card.delivery_reason);
|
|
5144
|
+
if (deliveryPolicy === "never" || deliveryPolicy === "conditional" && card.suppress_delivery !== false || vacuousAssertion) {
|
|
5149
5145
|
log(
|
|
5150
|
-
`[scheduled-kanban] Suppressed by delivery_policy=${deliveryPolicy} for card ${cardId} (task '${task.name}') on '${codeName}'
|
|
5146
|
+
`[scheduled-kanban] Suppressed by delivery_policy=${deliveryPolicy}` + (vacuousAssertion ? " (asserted delivery but reason was vacuous/empty)" : "") + ` for card ${cardId} (task '${task.name}') on '${codeName}' - result recorded on the card only (tombstone)`
|
|
5151
5147
|
);
|
|
5152
5148
|
if (task.deliveryMode === "announce" && task.deliveryTo) {
|
|
5153
5149
|
await reportDeliveryStatus(agentId, task.taskId, {
|
|
@@ -5237,7 +5233,7 @@ async function routeScheduledTaskViaKanban(codeName, agentId, task, prompt) {
|
|
|
5237
5233
|
if (run_id) void finishRun(run_id, "failed", { outcomeMessage: "kanban materialise incomplete", completeKanbanItemId: kanban_item_id });
|
|
5238
5234
|
return false;
|
|
5239
5235
|
}
|
|
5240
|
-
const suppressionTeaching = (task.deliveryPolicy ?? "always") === "conditional" ? `THIS task is CONDITIONAL: quiet runs stay SILENT automatically. Write your findings on the card and mark it done \u2014 if nothing met the user's criteria, NOTHING will be sent (no flag needed). If something DID meet the criteria and the user must be told, call kanban_done with suppress_delivery: false
|
|
5236
|
+
const suppressionTeaching = (task.deliveryPolicy ?? "always") === "conditional" ? `THIS task is CONDITIONAL: quiet runs stay SILENT automatically. Write your findings on the card and mark it done \u2014 if nothing met the user's criteria, NOTHING will be sent (no flag needed). If something DID meet the criteria and the user must be told, call kanban_done with suppress_delivery: false AND delivery_reason naming the concrete trigger that fired (e.g. "urgent email from the CEO", "CI failing on main"); a vacuous reason like "status check" or "all clear" is rejected and stays silent. That explicit, justified assert is the ONLY way this result reaches the user.
|
|
5241
5237
|
` : `If \u2014 and ONLY if \u2014 the task description contains explicit opt-out wording the user typed (e.g. "DO NOT notify me unless urgent", "only if X", "stay silent unless \u2026") and that condition is NOT met this run, call kanban_done with suppress_delivery: true \u2014 your result stays on the card but will NOT be messaged to the user. That is how you honor the user's do-not-notify instruction: a "nothing urgent" result without the flag would still be DELIVERED as a message. A report with zero items is only a valid deliverable when the task asks for a digest WITHOUT opt-out wording \u2014 when in doubt, deliver.
|
|
5242
5238
|
`;
|
|
5243
5239
|
const nudge = `You have a new scheduled task on your kanban board: id=${kanban_item_id} title=${JSON.stringify(task.name)}. Call kanban_move("${kanban_item_id}", "in_progress"), do the work described on the card, then write the finished result onto the card and mark it done. Do NOT send, post, or message the result to anyone yourself \u2014 the result you write on the card IS the message that will be delivered to the user; delivery happens automatically from the card.
|
|
@@ -5386,7 +5382,6 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
|
|
|
5386
5382
|
|
|
5387
5383
|
// src/lib/manager/scheduler/execution.ts
|
|
5388
5384
|
import { createHash as createHash9 } from "crypto";
|
|
5389
|
-
import { readFileSync as readFileSync13, existsSync as existsSync7 } from "fs";
|
|
5390
5385
|
import { homedir as homedir7 } from "os";
|
|
5391
5386
|
import { join as join14 } from "path";
|
|
5392
5387
|
function claudePidFilePath() {
|
|
@@ -5444,177 +5439,9 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
5444
5439
|
}
|
|
5445
5440
|
inFlightClaudeTasks.add(task.taskId);
|
|
5446
5441
|
claudeTaskConcurrency.set(codeName, (claudeTaskConcurrency.get(codeName) ?? 0) + 1);
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
claudeTaskConcurrency.set(codeName, Math.max(0, (claudeTaskConcurrency.get(codeName) ?? 1) - 1));
|
|
5451
|
-
continue;
|
|
5452
|
-
}
|
|
5453
|
-
log(`[claude-scheduler] Firing '${task.name}' for '${codeName}'`);
|
|
5454
|
-
executeAndProcessClaudeTask(codeName, agent.agent_id, task, prompt).finally(() => {
|
|
5455
|
-
inFlightClaudeTasks.delete(task.taskId);
|
|
5456
|
-
claudeTaskConcurrency.set(codeName, Math.max(0, (claudeTaskConcurrency.get(codeName) ?? 1) - 1));
|
|
5457
|
-
});
|
|
5458
|
-
}
|
|
5459
|
-
}
|
|
5460
|
-
async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
|
|
5461
|
-
const projectDir = getProjectDir2(codeName);
|
|
5462
|
-
const mcpConfigPath = join14(projectDir, ".mcp.json");
|
|
5463
|
-
let runId = null;
|
|
5464
|
-
let kanbanItemId = null;
|
|
5465
|
-
let taskResult;
|
|
5466
|
-
sanitizeMcpJson(mcpConfigPath, requireHost());
|
|
5467
|
-
const priorRuns = await fetchPriorScheduledRuns(agentId, task.taskId);
|
|
5468
|
-
prompt = wrapScheduledTaskPrompt(prompt, { priorRuns, timezone: task.timezone, deliveryPolicy: task.deliveryPolicy });
|
|
5469
|
-
try {
|
|
5470
|
-
const claudeMdPath = join14(projectDir, "CLAUDE.md");
|
|
5471
|
-
const serverNames = [];
|
|
5472
|
-
if (existsSync7(mcpConfigPath)) {
|
|
5473
|
-
try {
|
|
5474
|
-
const d = JSON.parse(readFileSync13(mcpConfigPath, "utf-8"));
|
|
5475
|
-
if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
|
|
5476
|
-
} catch {
|
|
5477
|
-
}
|
|
5478
|
-
}
|
|
5479
|
-
const allowedTools = buildAllowedTools(serverNames);
|
|
5480
|
-
const claudeArgs = [
|
|
5481
|
-
"-p",
|
|
5482
|
-
prompt,
|
|
5483
|
-
"--output-format",
|
|
5484
|
-
"text",
|
|
5485
|
-
"--mcp-config",
|
|
5486
|
-
mcpConfigPath,
|
|
5487
|
-
"--strict-mcp-config",
|
|
5488
|
-
"--permission-mode",
|
|
5489
|
-
"auto",
|
|
5490
|
-
"--allowedTools",
|
|
5491
|
-
allowedTools
|
|
5492
|
-
];
|
|
5493
|
-
if (existsSync7(claudeMdPath)) {
|
|
5494
|
-
claudeArgs.push("--system-prompt-file", claudeMdPath);
|
|
5495
|
-
}
|
|
5496
|
-
const childEnv = { ...process.env };
|
|
5497
|
-
const envIntPath = join14(projectDir, ".env.integrations");
|
|
5498
|
-
if (existsSync7(envIntPath)) {
|
|
5499
|
-
try {
|
|
5500
|
-
Object.assign(childEnv, parseEnvIntegrations(readFileSync13(envIntPath, "utf-8")));
|
|
5501
|
-
} catch {
|
|
5502
|
-
}
|
|
5503
|
-
}
|
|
5504
|
-
try {
|
|
5505
|
-
await applyClaudeAuthToEnv(childEnv, "claude-scheduler");
|
|
5506
|
-
} catch (err) {
|
|
5507
|
-
log(`[claude-scheduler] Skipping task '${task.name}' for '${codeName}' \u2014 auth resolve failed: ${err.message}`);
|
|
5508
|
-
return;
|
|
5509
|
-
}
|
|
5510
|
-
const startResult = await startRun({
|
|
5511
|
-
agent_id: agentId,
|
|
5512
|
-
source_type: "scheduled_task",
|
|
5513
|
-
source_ref: task.taskId,
|
|
5514
|
-
metadata: { template_id: task.templateId, name: task.name },
|
|
5515
|
-
materialize_kanban: { title: task.name, priority: 2, ...deriveScheduledTaskNotify(task) }
|
|
5516
|
-
});
|
|
5517
|
-
runId = startResult.run_id;
|
|
5518
|
-
kanbanItemId = startResult.kanban_item_id;
|
|
5519
|
-
if (runId) childEnv["AGT_RUN_ID"] = runId;
|
|
5520
|
-
for (const f of probeMcpEnvSubstitution({
|
|
5521
|
-
mcpConfigPath,
|
|
5522
|
-
envIntegrationsPath: envIntPath,
|
|
5523
|
-
baseEnv: childEnv
|
|
5524
|
-
})) {
|
|
5525
|
-
log(`[claude-scheduler] ${formatMissingVar(f)} agent=${codeName}`);
|
|
5526
|
-
}
|
|
5527
|
-
const claudeKind = task.templateId === "kanban-work" ? "kanban-work" : "scheduled-task";
|
|
5528
|
-
const { stdout, stderr } = await execFilePromiseLong(resolveClaudeBinary(), claudeArgs, {
|
|
5529
|
-
cwd: projectDir,
|
|
5530
|
-
timeout: 3e5,
|
|
5531
|
-
stdin: "ignore",
|
|
5532
|
-
env: childEnv,
|
|
5533
|
-
onSpawn: (pid) => registerClaudeSpawn({
|
|
5534
|
-
pid,
|
|
5535
|
-
started_at: Date.now(),
|
|
5536
|
-
kind: claudeKind,
|
|
5537
|
-
agent_id: agentId,
|
|
5538
|
-
agent_code_name: codeName,
|
|
5539
|
-
kanban_card_id: kanbanItemId ?? void 0
|
|
5540
|
-
}),
|
|
5541
|
-
onExit: (pid) => unregisterClaudeSpawn(pid)
|
|
5542
|
-
});
|
|
5543
|
-
if (stderr) {
|
|
5544
|
-
log(`[claude-scheduler] Task '${task.name}' stderr for '${codeName}': ${stderr.slice(0, 500)}`);
|
|
5545
|
-
}
|
|
5546
|
-
const output = stdout.trim();
|
|
5547
|
-
taskResult = output.slice(0, 4e3) || void 0;
|
|
5548
|
-
log(`[claude-scheduler] Task '${task.name}' completed for '${codeName}' (${output.length} chars): ${output.slice(0, 300)}`);
|
|
5549
|
-
const outcome = await processClaudeTaskResult(codeName, agentId, task.templateId, output, {
|
|
5550
|
-
mode: task.deliveryMode,
|
|
5551
|
-
channel: task.deliveryChannel,
|
|
5552
|
-
to: task.deliveryTo,
|
|
5553
|
-
taskId: task.taskId,
|
|
5554
|
-
// ENG-6803: hand the oneshot result processor the policy so it can enforce
|
|
5555
|
-
// conditional (suppressed-by-default, deliver only on a concrete
|
|
5556
|
-
// `<deliver: reason>` marker) / never. The in-session kanban caller
|
|
5557
|
-
// deliberately omits this — it gates upstream via suppress_delivery.
|
|
5558
|
-
deliveryPolicy: task.deliveryPolicy
|
|
5559
|
-
});
|
|
5560
|
-
if (!outcome.ok) {
|
|
5561
|
-
log(`[claude-scheduler] Task '${task.name}' result post failed for '${codeName}': ${outcome.error}`);
|
|
5562
|
-
if (runId) {
|
|
5563
|
-
try {
|
|
5564
|
-
await finishRun(runId, "failed", {
|
|
5565
|
-
outcomeMessage: outcome.error,
|
|
5566
|
-
completeKanbanItemId: kanbanItemId,
|
|
5567
|
-
result: taskResult
|
|
5568
|
-
});
|
|
5569
|
-
} catch {
|
|
5570
|
-
}
|
|
5571
|
-
}
|
|
5572
|
-
const failedUpdate = markTaskFired(codeName, task.taskId, "error");
|
|
5573
|
-
claudeSchedulerStates.set(codeName, failedUpdate);
|
|
5574
|
-
return;
|
|
5575
|
-
}
|
|
5576
|
-
if (runId) {
|
|
5577
|
-
await finishRun(runId, "completed", {
|
|
5578
|
-
metadata: { output_length: output.length },
|
|
5579
|
-
completeKanbanItemId: kanbanItemId,
|
|
5580
|
-
result: taskResult
|
|
5581
|
-
});
|
|
5582
|
-
}
|
|
5583
|
-
const updated = markTaskFired(codeName, task.taskId, "ok");
|
|
5584
|
-
claudeSchedulerStates.set(codeName, updated);
|
|
5585
|
-
if (task.scheduleKind === "at") {
|
|
5586
|
-
try {
|
|
5587
|
-
await api.post("/host/schedules/disable", { agent_id: agentId, task_id: task.taskId });
|
|
5588
|
-
log(`[claude-scheduler] One-off task '${task.name}' fired and disabled for '${codeName}'`);
|
|
5589
|
-
} catch (err) {
|
|
5590
|
-
log(`[claude-scheduler] Failed to disable one-off task '${task.name}': ${err.message}`);
|
|
5591
|
-
}
|
|
5592
|
-
}
|
|
5593
|
-
} catch (err) {
|
|
5594
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
5595
|
-
log(`[claude-scheduler] Task '${task.name}' failed for '${codeName}': ${errMsg}`);
|
|
5596
|
-
if (err instanceof ChildProcessError) {
|
|
5597
|
-
const errStdout = err.stdout.trim();
|
|
5598
|
-
if (errStdout) {
|
|
5599
|
-
taskResult = errStdout.slice(0, 4e3) || taskResult;
|
|
5600
|
-
log(`[claude-scheduler] Task '${task.name}' stdout for '${codeName}': ${errStdout.slice(0, 1e3)}`);
|
|
5601
|
-
}
|
|
5602
|
-
if (err.stderr.trim()) {
|
|
5603
|
-
log(`[claude-scheduler] Task '${task.name}' stderr for '${codeName}': ${err.stderr.trim().slice(0, 1e3)}`);
|
|
5604
|
-
}
|
|
5605
|
-
}
|
|
5606
|
-
if (runId) {
|
|
5607
|
-
try {
|
|
5608
|
-
await finishRun(runId, "failed", {
|
|
5609
|
-
outcomeMessage: errMsg,
|
|
5610
|
-
completeKanbanItemId: kanbanItemId,
|
|
5611
|
-
result: taskResult
|
|
5612
|
-
});
|
|
5613
|
-
} catch {
|
|
5614
|
-
}
|
|
5615
|
-
}
|
|
5616
|
-
const updated = markTaskFired(codeName, task.taskId, "error");
|
|
5617
|
-
claudeSchedulerStates.set(codeName, updated);
|
|
5442
|
+
await fireScheduledTaskViaKanban(codeName, agent.agent_id, task, prompt);
|
|
5443
|
+
inFlightClaudeTasks.delete(task.taskId);
|
|
5444
|
+
claudeTaskConcurrency.set(codeName, Math.max(0, (claudeTaskConcurrency.get(codeName) ?? 1) - 1));
|
|
5618
5445
|
}
|
|
5619
5446
|
}
|
|
5620
5447
|
|
|
@@ -5757,7 +5584,7 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
5757
5584
|
}
|
|
5758
5585
|
|
|
5759
5586
|
// src/lib/restart-flags.ts
|
|
5760
|
-
import { existsSync as
|
|
5587
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readdirSync as readdirSync4, readFileSync as readFileSync13, renameSync, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
5761
5588
|
import { homedir as homedir8 } from "os";
|
|
5762
5589
|
import { join as join15 } from "path";
|
|
5763
5590
|
import { randomUUID } from "crypto";
|
|
@@ -5769,12 +5596,12 @@ function flagPath(codeName) {
|
|
|
5769
5596
|
}
|
|
5770
5597
|
function readRestartFlags() {
|
|
5771
5598
|
const dir = restartFlagsDir();
|
|
5772
|
-
if (!
|
|
5599
|
+
if (!existsSync7(dir)) return [];
|
|
5773
5600
|
const out = [];
|
|
5774
5601
|
for (const entry of readdirSync4(dir)) {
|
|
5775
5602
|
if (!entry.endsWith(".flag")) continue;
|
|
5776
5603
|
try {
|
|
5777
|
-
const raw =
|
|
5604
|
+
const raw = readFileSync13(join15(dir, entry), "utf8");
|
|
5778
5605
|
const parsed = JSON.parse(raw);
|
|
5779
5606
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
5780
5607
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -5792,7 +5619,7 @@ function readRestartFlags() {
|
|
|
5792
5619
|
}
|
|
5793
5620
|
function deleteRestartFlag(codeName) {
|
|
5794
5621
|
const path = flagPath(codeName);
|
|
5795
|
-
if (
|
|
5622
|
+
if (existsSync7(path)) {
|
|
5796
5623
|
rmSync3(path, { force: true });
|
|
5797
5624
|
}
|
|
5798
5625
|
}
|
|
@@ -6867,7 +6694,7 @@ var runningMcpServerKeys = /* @__PURE__ */ new Map();
|
|
|
6867
6694
|
var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
6868
6695
|
function projectMcpHash(_codeName, projectDir) {
|
|
6869
6696
|
try {
|
|
6870
|
-
const raw =
|
|
6697
|
+
const raw = readFileSync14(join16(projectDir, ".mcp.json"), "utf-8");
|
|
6871
6698
|
return createHash10("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
6872
6699
|
} catch {
|
|
6873
6700
|
return null;
|
|
@@ -6875,7 +6702,7 @@ function projectMcpHash(_codeName, projectDir) {
|
|
|
6875
6702
|
}
|
|
6876
6703
|
function projectMcpKeys(_codeName, projectDir) {
|
|
6877
6704
|
try {
|
|
6878
|
-
const raw =
|
|
6705
|
+
const raw = readFileSync14(join16(projectDir, ".mcp.json"), "utf-8");
|
|
6879
6706
|
const parsed = JSON.parse(raw);
|
|
6880
6707
|
const servers = parsed.mcpServers;
|
|
6881
6708
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -7033,7 +6860,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
|
7033
6860
|
function projectChannelSecretHash(projectDir) {
|
|
7034
6861
|
try {
|
|
7035
6862
|
const entries = parseEnvIntegrations(
|
|
7036
|
-
|
|
6863
|
+
readFileSync14(join16(projectDir, ".env.integrations"), "utf-8")
|
|
7037
6864
|
);
|
|
7038
6865
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
7039
6866
|
} catch {
|
|
@@ -7122,7 +6949,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
7122
6949
|
var lastVersionCheckAt = 0;
|
|
7123
6950
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
7124
6951
|
var lastResponsivenessProbeAt = 0;
|
|
7125
|
-
var agtCliVersion = true ? "0.28.
|
|
6952
|
+
var agtCliVersion = true ? "0.28.150" : "dev";
|
|
7126
6953
|
function resolveBrewPath(execFileSync4) {
|
|
7127
6954
|
try {
|
|
7128
6955
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -7135,7 +6962,7 @@ function resolveBrewPath(execFileSync4) {
|
|
|
7135
6962
|
"/usr/local/bin/brew"
|
|
7136
6963
|
];
|
|
7137
6964
|
for (const path of fallbacks) {
|
|
7138
|
-
if (
|
|
6965
|
+
if (existsSync8(path)) return path;
|
|
7139
6966
|
}
|
|
7140
6967
|
return null;
|
|
7141
6968
|
}
|
|
@@ -7145,7 +6972,7 @@ function claudeBinaryInstalled(execFileSync4) {
|
|
|
7145
6972
|
"/opt/homebrew/bin/claude",
|
|
7146
6973
|
"/usr/local/bin/claude"
|
|
7147
6974
|
];
|
|
7148
|
-
if (canonical.some((path) =>
|
|
6975
|
+
if (canonical.some((path) => existsSync8(path))) return true;
|
|
7149
6976
|
try {
|
|
7150
6977
|
execFileSync4("which", ["claude"], { timeout: 5e3 });
|
|
7151
6978
|
return true;
|
|
@@ -7298,8 +7125,8 @@ function claudeManagedSettingsPath() {
|
|
|
7298
7125
|
function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
7299
7126
|
try {
|
|
7300
7127
|
let settings = {};
|
|
7301
|
-
if (
|
|
7302
|
-
const raw =
|
|
7128
|
+
if (existsSync8(path)) {
|
|
7129
|
+
const raw = readFileSync14(path, "utf-8").trim();
|
|
7303
7130
|
if (raw) {
|
|
7304
7131
|
let parsed;
|
|
7305
7132
|
try {
|
|
@@ -7361,7 +7188,7 @@ async function ensureFrameworkBinary(frameworkId) {
|
|
|
7361
7188
|
if (!process.env.PATH?.split(":").includes(brewBinDir)) {
|
|
7362
7189
|
process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
|
|
7363
7190
|
}
|
|
7364
|
-
if (
|
|
7191
|
+
if (existsSync8("/home/linuxbrew/.linuxbrew/bin/claude")) {
|
|
7365
7192
|
log("Claude Code installed successfully");
|
|
7366
7193
|
} else {
|
|
7367
7194
|
log("Claude Code install completed but binary not found at expected path \u2014 check brew logs");
|
|
@@ -7719,7 +7546,7 @@ async function checkClaudeAuth() {
|
|
|
7719
7546
|
}
|
|
7720
7547
|
var evalEmptyMcpConfigPath = null;
|
|
7721
7548
|
function ensureEvalEmptyMcpConfig() {
|
|
7722
|
-
if (evalEmptyMcpConfigPath &&
|
|
7549
|
+
if (evalEmptyMcpConfigPath && existsSync8(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
7723
7550
|
const dir = join16(homedir9(), ".augmented");
|
|
7724
7551
|
try {
|
|
7725
7552
|
mkdirSync6(dir, { recursive: true });
|
|
@@ -7802,7 +7629,7 @@ function resolveConversationEvalBackend() {
|
|
|
7802
7629
|
}
|
|
7803
7630
|
function loadGatewayPorts() {
|
|
7804
7631
|
try {
|
|
7805
|
-
return JSON.parse(
|
|
7632
|
+
return JSON.parse(readFileSync14(GATEWAY_PORTS_FILE, "utf-8"));
|
|
7806
7633
|
} catch {
|
|
7807
7634
|
return {};
|
|
7808
7635
|
}
|
|
@@ -7962,7 +7789,7 @@ async function migrateToProfiles() {
|
|
|
7962
7789
|
const sharedConfigPath = join16(homeDir, ".openclaw", "openclaw.json");
|
|
7963
7790
|
let sharedConfig;
|
|
7964
7791
|
try {
|
|
7965
|
-
sharedConfig = JSON.parse(
|
|
7792
|
+
sharedConfig = JSON.parse(readFileSync14(sharedConfigPath, "utf-8"));
|
|
7966
7793
|
} catch {
|
|
7967
7794
|
return;
|
|
7968
7795
|
}
|
|
@@ -7976,7 +7803,7 @@ async function migrateToProfiles() {
|
|
|
7976
7803
|
if (!codeName) continue;
|
|
7977
7804
|
if (codeName === "main") continue;
|
|
7978
7805
|
const profileDir = join16(homeDir, `.openclaw-${codeName}`);
|
|
7979
|
-
if (
|
|
7806
|
+
if (existsSync8(join16(profileDir, "openclaw.json"))) continue;
|
|
7980
7807
|
log(`Migrating agent '${codeName}' to per-agent profile`);
|
|
7981
7808
|
if (adapter.seedProfileConfig) {
|
|
7982
7809
|
adapter.seedProfileConfig(codeName);
|
|
@@ -7984,9 +7811,9 @@ async function migrateToProfiles() {
|
|
|
7984
7811
|
const sharedAuthDir = join16(homeDir, ".openclaw", "agents", codeName, "agent");
|
|
7985
7812
|
const profileAuthDir = join16(profileDir, "agents", codeName, "agent");
|
|
7986
7813
|
const authFile = join16(sharedAuthDir, "auth-profiles.json");
|
|
7987
|
-
if (
|
|
7814
|
+
if (existsSync8(authFile)) {
|
|
7988
7815
|
mkdirSync6(profileAuthDir, { recursive: true });
|
|
7989
|
-
const authContent =
|
|
7816
|
+
const authContent = readFileSync14(authFile, "utf-8");
|
|
7990
7817
|
writeFileSync6(join16(profileAuthDir, "auth-profiles.json"), authContent);
|
|
7991
7818
|
}
|
|
7992
7819
|
allocatePort(codeName);
|
|
@@ -8003,7 +7830,7 @@ function readGatewayToken(codeName) {
|
|
|
8003
7830
|
}
|
|
8004
7831
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
8005
7832
|
try {
|
|
8006
|
-
const cfg = JSON.parse(
|
|
7833
|
+
const cfg = JSON.parse(readFileSync14(join16(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
|
|
8007
7834
|
return cfg?.gateway?.auth?.token;
|
|
8008
7835
|
} catch {
|
|
8009
7836
|
return void 0;
|
|
@@ -8013,9 +7840,9 @@ var GATEWAY_HUNG_TIMEOUT_MS = 5 * 6e4;
|
|
|
8013
7840
|
function isGatewayHung(codeName) {
|
|
8014
7841
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
8015
7842
|
const jobsPath = join16(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
8016
|
-
if (!
|
|
7843
|
+
if (!existsSync8(jobsPath)) return false;
|
|
8017
7844
|
try {
|
|
8018
|
-
const data = JSON.parse(
|
|
7845
|
+
const data = JSON.parse(readFileSync14(jobsPath, "utf-8"));
|
|
8019
7846
|
const jobs = data.jobs ?? data;
|
|
8020
7847
|
if (!Array.isArray(jobs)) return false;
|
|
8021
7848
|
const now = Date.now();
|
|
@@ -8055,8 +7882,8 @@ async function ensureGatewayRunning(codeName, adapter) {
|
|
|
8055
7882
|
try {
|
|
8056
7883
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
8057
7884
|
const configPath = join16(homeDir, `.openclaw-${codeName}`, "openclaw.json");
|
|
8058
|
-
if (
|
|
8059
|
-
const cfg = JSON.parse(
|
|
7885
|
+
if (existsSync8(configPath)) {
|
|
7886
|
+
const cfg = JSON.parse(readFileSync14(configPath, "utf-8"));
|
|
8060
7887
|
if (cfg.gateway?.port !== status.port) {
|
|
8061
7888
|
if (!cfg.gateway) cfg.gateway = {};
|
|
8062
7889
|
cfg.gateway.port = status.port;
|
|
@@ -8081,8 +7908,8 @@ async function ensureGatewayRunning(codeName, adapter) {
|
|
|
8081
7908
|
try {
|
|
8082
7909
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
8083
7910
|
const configPath = join16(homeDir, `.openclaw-${codeName}`, "openclaw.json");
|
|
8084
|
-
if (
|
|
8085
|
-
const cfg = JSON.parse(
|
|
7911
|
+
if (existsSync8(configPath)) {
|
|
7912
|
+
const cfg = JSON.parse(readFileSync14(configPath, "utf-8"));
|
|
8086
7913
|
if (!cfg.gateway) cfg.gateway = {};
|
|
8087
7914
|
cfg.gateway.port = port;
|
|
8088
7915
|
writeFileSync6(configPath, JSON.stringify(cfg, null, 2));
|
|
@@ -8255,7 +8082,7 @@ async function pollCycle() {
|
|
|
8255
8082
|
}
|
|
8256
8083
|
try {
|
|
8257
8084
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
8258
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
8085
|
+
const { collectDiagnostics } = await import("../persistent-session-S2674LBO.js");
|
|
8259
8086
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
8260
8087
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
8261
8088
|
let tailscaleHostname;
|
|
@@ -8403,7 +8230,7 @@ async function pollCycle() {
|
|
|
8403
8230
|
const {
|
|
8404
8231
|
collectResponsivenessProbes,
|
|
8405
8232
|
getResponsivenessIntervalMs
|
|
8406
|
-
} = await import("../responsiveness-probe-
|
|
8233
|
+
} = await import("../responsiveness-probe-NHQYDMHJ.js");
|
|
8407
8234
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
8408
8235
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
8409
8236
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -8435,7 +8262,7 @@ async function pollCycle() {
|
|
|
8435
8262
|
collectResponsivenessProbes,
|
|
8436
8263
|
livePendingInboundOldestAgeSeconds,
|
|
8437
8264
|
parkPendingInbound
|
|
8438
|
-
} = await import("../responsiveness-probe-
|
|
8265
|
+
} = await import("../responsiveness-probe-NHQYDMHJ.js");
|
|
8439
8266
|
const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
|
|
8440
8267
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
8441
8268
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -8781,7 +8608,7 @@ async function pollCycle() {
|
|
|
8781
8608
|
// the watchdog, never fails the poll cycle.
|
|
8782
8609
|
signalGiveUp: (codeName) => {
|
|
8783
8610
|
const dir = join16(homedir9(), ".augmented", codeName);
|
|
8784
|
-
if (!
|
|
8611
|
+
if (!existsSync8(dir)) return;
|
|
8785
8612
|
atomicWriteFileSync(
|
|
8786
8613
|
join16(dir, "watchdog-give-up.json"),
|
|
8787
8614
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
@@ -8962,7 +8789,7 @@ async function processAgent(agent, agentStates) {
|
|
|
8962
8789
|
const residuals = {
|
|
8963
8790
|
gatewayRunning: gatewayLiveness.running,
|
|
8964
8791
|
portAllocated: Object.prototype.hasOwnProperty.call(ports, agent.code_name),
|
|
8965
|
-
provisionDirExists:
|
|
8792
|
+
provisionDirExists: existsSync8(agentDir)
|
|
8966
8793
|
};
|
|
8967
8794
|
if (!hasRevokedResiduals(residuals)) {
|
|
8968
8795
|
agentStates.push({
|
|
@@ -9181,7 +9008,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9181
9008
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
9182
9009
|
try {
|
|
9183
9010
|
const projectClaudeMd = join16(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
9184
|
-
const existing =
|
|
9011
|
+
const existing = readFileSync14(projectClaudeMd, "utf-8");
|
|
9185
9012
|
existingHash = sha256(stripDynamicSections(existing));
|
|
9186
9013
|
} catch {
|
|
9187
9014
|
existingHash = null;
|
|
@@ -9199,7 +9026,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9199
9026
|
const generatorKeys = Object.keys(generatorServers);
|
|
9200
9027
|
let existingRaw = "";
|
|
9201
9028
|
try {
|
|
9202
|
-
existingRaw =
|
|
9029
|
+
existingRaw = readFileSync14(filePath, "utf-8");
|
|
9203
9030
|
} catch {
|
|
9204
9031
|
}
|
|
9205
9032
|
const existingServers = parseMcp(existingRaw);
|
|
@@ -9221,7 +9048,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9221
9048
|
}
|
|
9222
9049
|
}
|
|
9223
9050
|
if (changedFiles.length > 0) {
|
|
9224
|
-
const isFirst = !
|
|
9051
|
+
const isFirst = !existsSync8(join16(agentDir, "CHARTER.md"));
|
|
9225
9052
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
9226
9053
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
9227
9054
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
@@ -9236,7 +9063,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9236
9063
|
}
|
|
9237
9064
|
try {
|
|
9238
9065
|
const provSkillsDir = join16(agentDir, ".claude", "skills");
|
|
9239
|
-
if (
|
|
9066
|
+
if (existsSync8(provSkillsDir)) {
|
|
9240
9067
|
for (const folder of readdirSync5(provSkillsDir)) {
|
|
9241
9068
|
if (folder.startsWith("knowledge-")) {
|
|
9242
9069
|
try {
|
|
@@ -9272,7 +9099,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9272
9099
|
if (Array.isArray(refreshData.workflows)) {
|
|
9273
9100
|
try {
|
|
9274
9101
|
const provWorkflowsDir = join16(agentDir, ".claude", "workflows");
|
|
9275
|
-
if (
|
|
9102
|
+
if (existsSync8(provWorkflowsDir)) {
|
|
9276
9103
|
const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
|
|
9277
9104
|
for (const file of readdirSync5(provWorkflowsDir)) {
|
|
9278
9105
|
if (!file.endsWith(".js")) continue;
|
|
@@ -9335,7 +9162,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9335
9162
|
}
|
|
9336
9163
|
let lastDriftCheckAt = now;
|
|
9337
9164
|
const written = agentState.writtenHashes.get(agent.agent_id);
|
|
9338
|
-
if (written &&
|
|
9165
|
+
if (written && existsSync8(agentDir)) {
|
|
9339
9166
|
const driftedFiles = [];
|
|
9340
9167
|
for (const [file, expectedHash] of written) {
|
|
9341
9168
|
const localHash = hashFile(join16(agentDir, file));
|
|
@@ -9701,7 +9528,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9701
9528
|
const projectMcpPath = join16(projectDir, ".mcp.json");
|
|
9702
9529
|
let mcpConfig = { mcpServers: {} };
|
|
9703
9530
|
try {
|
|
9704
|
-
mcpConfig = JSON.parse(
|
|
9531
|
+
mcpConfig = JSON.parse(readFileSync14(provisionMcpPath, "utf-8"));
|
|
9705
9532
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
9706
9533
|
} catch {
|
|
9707
9534
|
}
|
|
@@ -9711,7 +9538,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9711
9538
|
const tz = directChatTeamSettings?.["timezone"];
|
|
9712
9539
|
return typeof tz === "string" && tz.trim() !== "" ? tz.trim() : void 0;
|
|
9713
9540
|
})();
|
|
9714
|
-
if (
|
|
9541
|
+
if (existsSync8(localDirectChatChannel)) {
|
|
9715
9542
|
const directChatEnv = {
|
|
9716
9543
|
AGT_HOST: requireHost(),
|
|
9717
9544
|
// ENG-5901 Track D: templated — the manager exports the real
|
|
@@ -9746,7 +9573,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9746
9573
|
}
|
|
9747
9574
|
}
|
|
9748
9575
|
const staleChannelsPath = join16(projectDir, ".mcp-channels.json");
|
|
9749
|
-
if (
|
|
9576
|
+
if (existsSync8(staleChannelsPath)) {
|
|
9750
9577
|
try {
|
|
9751
9578
|
rmSync4(staleChannelsPath, { force: true });
|
|
9752
9579
|
} catch {
|
|
@@ -9832,7 +9659,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9832
9659
|
const envIntPath = join16(projectDir, ".env.integrations");
|
|
9833
9660
|
let preWriteEnv;
|
|
9834
9661
|
try {
|
|
9835
|
-
preWriteEnv =
|
|
9662
|
+
preWriteEnv = readFileSync14(envIntPath, "utf-8");
|
|
9836
9663
|
} catch {
|
|
9837
9664
|
preWriteEnv = void 0;
|
|
9838
9665
|
}
|
|
@@ -9845,8 +9672,8 @@ async function processAgent(agent, agentStates) {
|
|
|
9845
9672
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
9846
9673
|
try {
|
|
9847
9674
|
const projectMcpPath = join16(projectDir, ".mcp.json");
|
|
9848
|
-
const postWriteEnv =
|
|
9849
|
-
const mcpContent =
|
|
9675
|
+
const postWriteEnv = readFileSync14(envIntPath, "utf-8");
|
|
9676
|
+
const mcpContent = readFileSync14(projectMcpPath, "utf-8");
|
|
9850
9677
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
9851
9678
|
const mcpJsonForReap = JSON.parse(mcpContent);
|
|
9852
9679
|
const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
|
|
@@ -9930,8 +9757,8 @@ async function processAgent(agent, agentStates) {
|
|
|
9930
9757
|
const mcpPath = frameworkAdapter.getMcpPath(agent.code_name);
|
|
9931
9758
|
if (mcpPath) {
|
|
9932
9759
|
try {
|
|
9933
|
-
const { readFileSync:
|
|
9934
|
-
const mcpConfig = JSON.parse(
|
|
9760
|
+
const { readFileSync: readFileSync15 } = await import("fs");
|
|
9761
|
+
const mcpConfig = JSON.parse(readFileSync15(mcpPath, "utf-8"));
|
|
9935
9762
|
if (mcpConfig.mcpServers) {
|
|
9936
9763
|
const managedPrefixes = [
|
|
9937
9764
|
"composio_",
|
|
@@ -10033,7 +9860,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10033
9860
|
if (frameworkAdapter.installPlugin) {
|
|
10034
9861
|
try {
|
|
10035
9862
|
const pluginPath = join16(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
|
|
10036
|
-
if (
|
|
9863
|
+
if (existsSync8(pluginPath)) {
|
|
10037
9864
|
frameworkAdapter.installPlugin(agent.code_name, "augmented", pluginPath, {
|
|
10038
9865
|
agtHost: requireHost(),
|
|
10039
9866
|
agtApiKey: getApiKey() ?? void 0,
|
|
@@ -10112,7 +9939,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10112
9939
|
// install target but cheap to sweep.
|
|
10113
9940
|
join16(agentDir, ".claude", "skills")
|
|
10114
9941
|
];
|
|
10115
|
-
const existingDirs = candidateSkillDirs.filter((d) =>
|
|
9942
|
+
const existingDirs = candidateSkillDirs.filter((d) => existsSync8(d));
|
|
10116
9943
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
10117
9944
|
for (const dir of existingDirs) {
|
|
10118
9945
|
try {
|
|
@@ -10127,7 +9954,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10127
9954
|
const removeSkillFolder = (entry, reason) => {
|
|
10128
9955
|
for (const dir of existingDirs) {
|
|
10129
9956
|
const p = join16(dir, entry);
|
|
10130
|
-
if (
|
|
9957
|
+
if (existsSync8(p)) {
|
|
10131
9958
|
rmSync5(p, { recursive: true, force: true });
|
|
10132
9959
|
}
|
|
10133
9960
|
}
|
|
@@ -10165,7 +9992,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10165
9992
|
for (const id of plan.removes) {
|
|
10166
9993
|
for (const dir of globalSkillDirs) {
|
|
10167
9994
|
const p = join16(dir, id);
|
|
10168
|
-
if (
|
|
9995
|
+
if (existsSync8(p)) rmSync5(p, { recursive: true, force: true });
|
|
10169
9996
|
}
|
|
10170
9997
|
agentState.knownSkillHashes.delete(`global-skill:${agent.agent_id}:${id}`);
|
|
10171
9998
|
log(`Removed unpublished global skill '${id}' for '${agent.code_name}'`);
|
|
@@ -10256,8 +10083,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10256
10083
|
const agentFw = agentFrameworkCache.get(agent.code_name) ?? "openclaw";
|
|
10257
10084
|
const sessionMode = refreshData.agent.session_mode ?? "oneshot";
|
|
10258
10085
|
const wantsHybridInject = isKanbanHybridEnabled();
|
|
10259
|
-
|
|
10260
|
-
if ((wantsHybridInject || wantsScheduledReconcile) && agentFw === "claude-code" && sessionMode === "persistent") {
|
|
10086
|
+
if (agentFw === "claude-code" && sessionMode === "persistent") {
|
|
10261
10087
|
let hybridBoard = hasBoardTemplates ? boardItems : void 0;
|
|
10262
10088
|
if (!hybridBoard) {
|
|
10263
10089
|
try {
|
|
@@ -10341,7 +10167,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10341
10167
|
let mcpJsonParsed = null;
|
|
10342
10168
|
try {
|
|
10343
10169
|
const mcpPath = join16(getProjectDir(agent.code_name), ".mcp.json");
|
|
10344
|
-
mcpJsonParsed = JSON.parse(
|
|
10170
|
+
mcpJsonParsed = JSON.parse(readFileSync14(mcpPath, "utf-8"));
|
|
10345
10171
|
} catch {
|
|
10346
10172
|
}
|
|
10347
10173
|
reapMissingMcpSessions({
|
|
@@ -10561,9 +10387,9 @@ async function processAgent(agent, agentStates) {
|
|
|
10561
10387
|
if (agentFw === "openclaw" && gatewayRunning && gatewayPort) {
|
|
10562
10388
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
10563
10389
|
const jobsPath = join16(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
|
|
10564
|
-
if (
|
|
10390
|
+
if (existsSync8(jobsPath)) {
|
|
10565
10391
|
try {
|
|
10566
|
-
const jobsData = JSON.parse(
|
|
10392
|
+
const jobsData = JSON.parse(readFileSync14(jobsPath, "utf-8"));
|
|
10567
10393
|
const kanbanJob = (jobsData.jobs ?? []).find(
|
|
10568
10394
|
(j) => typeof j.name === "string" && j.name.includes("kanban-work")
|
|
10569
10395
|
);
|
|
@@ -10697,7 +10523,7 @@ In progress for ${age} minutes \u2014 auto-failed`).catch(() => {
|
|
|
10697
10523
|
}
|
|
10698
10524
|
}
|
|
10699
10525
|
const trackedFiles = frameworkAdapter.driftTrackedFiles();
|
|
10700
|
-
if (trackedFiles.length > 0 &&
|
|
10526
|
+
if (trackedFiles.length > 0 && existsSync8(agentDir)) {
|
|
10701
10527
|
const hashes = /* @__PURE__ */ new Map();
|
|
10702
10528
|
for (const file of trackedFiles) {
|
|
10703
10529
|
const h = hashFile(join16(agentDir, file));
|
|
@@ -10787,9 +10613,9 @@ function cleanupStaleSessions(codeName) {
|
|
|
10787
10613
|
}
|
|
10788
10614
|
function cleanupCronSessions(sessionsDir, keepCount) {
|
|
10789
10615
|
const indexPath = join16(sessionsDir, "sessions.json");
|
|
10790
|
-
if (!
|
|
10616
|
+
if (!existsSync8(indexPath)) return;
|
|
10791
10617
|
try {
|
|
10792
|
-
const raw =
|
|
10618
|
+
const raw = readFileSync14(indexPath, "utf-8");
|
|
10793
10619
|
const index = JSON.parse(raw);
|
|
10794
10620
|
const cronRunKeys = Object.keys(index).filter((k) => k.includes(":cron:") && k.includes(":run:")).map((k) => ({
|
|
10795
10621
|
key: k,
|
|
@@ -10804,7 +10630,7 @@ function cleanupCronSessions(sessionsDir, keepCount) {
|
|
|
10804
10630
|
if (entry.sessionId) {
|
|
10805
10631
|
const sessionFile = join16(sessionsDir, `${entry.sessionId}.jsonl`);
|
|
10806
10632
|
try {
|
|
10807
|
-
if (
|
|
10633
|
+
if (existsSync8(sessionFile)) {
|
|
10808
10634
|
unlinkSync(sessionFile);
|
|
10809
10635
|
deletedFiles++;
|
|
10810
10636
|
}
|
|
@@ -10825,7 +10651,7 @@ function cleanupCronSessions(sessionsDir, keepCount) {
|
|
|
10825
10651
|
if (parentSessionId) {
|
|
10826
10652
|
try {
|
|
10827
10653
|
const f = join16(sessionsDir, `${parentSessionId}.jsonl`);
|
|
10828
|
-
if (
|
|
10654
|
+
if (existsSync8(f)) {
|
|
10829
10655
|
unlinkSync(f);
|
|
10830
10656
|
deletedFiles++;
|
|
10831
10657
|
}
|
|
@@ -10843,9 +10669,9 @@ function cleanupCronSessions(sessionsDir, keepCount) {
|
|
|
10843
10669
|
}
|
|
10844
10670
|
var STALE_RUN_TIMEOUT_MS = 5 * 6e4;
|
|
10845
10671
|
function clearStaleCronRunState(jobsPath) {
|
|
10846
|
-
if (!
|
|
10672
|
+
if (!existsSync8(jobsPath)) return;
|
|
10847
10673
|
try {
|
|
10848
|
-
const raw =
|
|
10674
|
+
const raw = readFileSync14(jobsPath, "utf-8");
|
|
10849
10675
|
const data = JSON.parse(raw);
|
|
10850
10676
|
const jobs = data.jobs ?? data;
|
|
10851
10677
|
if (!Array.isArray(jobs)) return;
|
|
@@ -10876,7 +10702,7 @@ function clearStaleCronRunState(jobsPath) {
|
|
|
10876
10702
|
}
|
|
10877
10703
|
}
|
|
10878
10704
|
function cleanupOldFiles(dir, maxAgeDays, ext) {
|
|
10879
|
-
if (!
|
|
10705
|
+
if (!existsSync8(dir)) return;
|
|
10880
10706
|
const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
|
|
10881
10707
|
let removed = 0;
|
|
10882
10708
|
try {
|
|
@@ -11203,18 +11029,9 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash10("sha256")
|
|
|
11203
11029
|
}
|
|
11204
11030
|
inFlightClaudeTasks.add(task.taskId);
|
|
11205
11031
|
claudeTaskConcurrency.set(codeName, (claudeTaskConcurrency.get(codeName) ?? 0) + 1);
|
|
11206
|
-
|
|
11207
|
-
|
|
11208
|
-
|
|
11209
|
-
claudeTaskConcurrency.set(codeName, Math.max(0, (claudeTaskConcurrency.get(codeName) ?? 1) - 1));
|
|
11210
|
-
break;
|
|
11211
|
-
}
|
|
11212
|
-
log(`[persistent-session] Firing task '${task.name}' for '${codeName}' via claude -p`);
|
|
11213
|
-
executeAndProcessClaudeTask(codeName, agent.agent_id, task, prompt).catch(() => {
|
|
11214
|
-
}).finally(() => {
|
|
11215
|
-
inFlightClaudeTasks.delete(task.taskId);
|
|
11216
|
-
claudeTaskConcurrency.set(codeName, Math.max(0, (claudeTaskConcurrency.get(codeName) ?? 1) - 1));
|
|
11217
|
-
});
|
|
11032
|
+
await fireScheduledTaskViaKanban(codeName, agent.agent_id, task, prompt);
|
|
11033
|
+
inFlightClaudeTasks.delete(task.taskId);
|
|
11034
|
+
claudeTaskConcurrency.set(codeName, Math.max(0, (claudeTaskConcurrency.get(codeName) ?? 1) - 1));
|
|
11218
11035
|
break;
|
|
11219
11036
|
}
|
|
11220
11037
|
}
|
|
@@ -11430,7 +11247,7 @@ function ensureRealtimeKanbanStarted(agentStates) {
|
|
|
11430
11247
|
log(
|
|
11431
11248
|
`[realtime] Kanban completion forwarded for '${codeName}': item=${event.item_id} status=${event.status} actor=${event.last_actor_id ?? "unknown"}`
|
|
11432
11249
|
);
|
|
11433
|
-
if (event.status === "done" &&
|
|
11250
|
+
if (event.status === "done" && classifyActor(event.last_actor_id, event.agent_id) === "user" && isScheduledCardTracked(event.item_id)) {
|
|
11434
11251
|
void deliverScheduledCardResult(codeName, event.agent_id, event.item_id, "user");
|
|
11435
11252
|
}
|
|
11436
11253
|
},
|
|
@@ -11608,9 +11425,9 @@ ${escapeXml(msg.content)}
|
|
|
11608
11425
|
const projDir = ccProjectDir(agent.codeName);
|
|
11609
11426
|
const mcpConfigPath = join16(projDir, ".mcp.json");
|
|
11610
11427
|
const serverNames = [];
|
|
11611
|
-
if (
|
|
11428
|
+
if (existsSync8(mcpConfigPath)) {
|
|
11612
11429
|
try {
|
|
11613
|
-
const d = JSON.parse(
|
|
11430
|
+
const d = JSON.parse(readFileSync14(mcpConfigPath, "utf-8"));
|
|
11614
11431
|
if (d.mcpServers) serverNames.push(...Object.keys(d.mcpServers));
|
|
11615
11432
|
} catch {
|
|
11616
11433
|
}
|
|
@@ -11630,14 +11447,14 @@ ${escapeXml(msg.content)}
|
|
|
11630
11447
|
allowedTools
|
|
11631
11448
|
];
|
|
11632
11449
|
const chatClaudeMd = join16(projDir, "CLAUDE.md");
|
|
11633
|
-
if (
|
|
11450
|
+
if (existsSync8(chatClaudeMd)) {
|
|
11634
11451
|
chatArgs.push("--system-prompt-file", chatClaudeMd);
|
|
11635
11452
|
}
|
|
11636
11453
|
const envIntPath = join16(projDir, ".env.integrations");
|
|
11637
11454
|
const childEnv = { ...process.env };
|
|
11638
|
-
if (
|
|
11455
|
+
if (existsSync8(envIntPath)) {
|
|
11639
11456
|
try {
|
|
11640
|
-
Object.assign(childEnv, parseEnvIntegrations(
|
|
11457
|
+
Object.assign(childEnv, parseEnvIntegrations(readFileSync14(envIntPath, "utf-8")));
|
|
11641
11458
|
} catch {
|
|
11642
11459
|
}
|
|
11643
11460
|
}
|
|
@@ -12028,7 +11845,7 @@ async function processClaudePairSessions(agents) {
|
|
|
12028
11845
|
killPairSession,
|
|
12029
11846
|
pairTmuxSession,
|
|
12030
11847
|
finalizeClaudePairOnboarding
|
|
12031
|
-
} = await import("../claude-pair-runtime-
|
|
11848
|
+
} = await import("../claude-pair-runtime-ZSBUAMO3.js");
|
|
12032
11849
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
12033
11850
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
12034
11851
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -12284,14 +12101,14 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
12284
12101
|
}
|
|
12285
12102
|
pendingFreshMemorySync.delete(agent.agent_id);
|
|
12286
12103
|
}
|
|
12287
|
-
if (
|
|
12104
|
+
if (existsSync8(memoryDir)) {
|
|
12288
12105
|
const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
|
|
12289
12106
|
const currentHashes = /* @__PURE__ */ new Map();
|
|
12290
12107
|
const changedMemories = [];
|
|
12291
12108
|
for (const file of readdirSync5(memoryDir)) {
|
|
12292
12109
|
if (!file.endsWith(".md")) continue;
|
|
12293
12110
|
try {
|
|
12294
|
-
const raw =
|
|
12111
|
+
const raw = readFileSync14(join16(memoryDir, file), "utf-8");
|
|
12295
12112
|
const fileHash = createHash10("sha256").update(raw).digest("hex").slice(0, 16);
|
|
12296
12113
|
currentHashes.set(file, fileHash);
|
|
12297
12114
|
if (prevHashes.get(file) === fileHash) continue;
|
|
@@ -12316,7 +12133,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
12316
12133
|
} catch (err) {
|
|
12317
12134
|
for (const mem of changedMemories) {
|
|
12318
12135
|
for (const [file] of currentHashes) {
|
|
12319
|
-
const parsed = parseMemoryFile(
|
|
12136
|
+
const parsed = parseMemoryFile(readFileSync14(join16(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
12320
12137
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
12321
12138
|
}
|
|
12322
12139
|
}
|
|
@@ -12329,7 +12146,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
12329
12146
|
}
|
|
12330
12147
|
}
|
|
12331
12148
|
async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
12332
|
-
const localFiles =
|
|
12149
|
+
const localFiles = existsSync8(memoryDir) ? readdirSync5(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
12333
12150
|
const localListHash = createHash10("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
12334
12151
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
12335
12152
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
@@ -12360,10 +12177,10 @@ description: ${JSON.stringify(mem.content.slice(0, 200))}
|
|
|
12360
12177
|
|
|
12361
12178
|
${mem.content}
|
|
12362
12179
|
`;
|
|
12363
|
-
if (
|
|
12180
|
+
if (existsSync8(filePath)) {
|
|
12364
12181
|
let existing = "";
|
|
12365
12182
|
try {
|
|
12366
|
-
existing =
|
|
12183
|
+
existing = readFileSync14(filePath, "utf-8");
|
|
12367
12184
|
} catch {
|
|
12368
12185
|
}
|
|
12369
12186
|
if (existing === desired) continue;
|
|
@@ -12387,7 +12204,7 @@ ${mem.content}
|
|
|
12387
12204
|
}
|
|
12388
12205
|
}
|
|
12389
12206
|
async function cleanupAgentFiles(codeName, agentDir) {
|
|
12390
|
-
if (
|
|
12207
|
+
if (existsSync8(agentDir)) {
|
|
12391
12208
|
try {
|
|
12392
12209
|
rmSync4(agentDir, { recursive: true, force: true });
|
|
12393
12210
|
log(`Removed provision directory for '${codeName}'`);
|
|
@@ -12637,8 +12454,8 @@ function startManager(opts) {
|
|
|
12637
12454
|
config = opts;
|
|
12638
12455
|
try {
|
|
12639
12456
|
const stateFile = getStateFile();
|
|
12640
|
-
if (
|
|
12641
|
-
const raw =
|
|
12457
|
+
if (existsSync8(stateFile)) {
|
|
12458
|
+
const raw = readFileSync14(stateFile, "utf-8");
|
|
12642
12459
|
const parsed = JSON.parse(raw);
|
|
12643
12460
|
if (Array.isArray(parsed.agents)) {
|
|
12644
12461
|
state6.agents = parsed.agents;
|
|
@@ -12686,7 +12503,7 @@ async function reapOrphanedClaudePids() {
|
|
|
12686
12503
|
const looksLikeClaude = (pid) => {
|
|
12687
12504
|
if (process.platform !== "linux") return true;
|
|
12688
12505
|
try {
|
|
12689
|
-
const comm =
|
|
12506
|
+
const comm = readFileSync14(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
|
|
12690
12507
|
return comm.includes("claude");
|
|
12691
12508
|
} catch {
|
|
12692
12509
|
return false;
|
|
@@ -12803,7 +12620,7 @@ function deployMcpAssets() {
|
|
|
12803
12620
|
let dir = moduleDir;
|
|
12804
12621
|
for (let i = 0; i < 6; i++) {
|
|
12805
12622
|
const candidate = join16(dir, "dist", "mcp");
|
|
12806
|
-
if (
|
|
12623
|
+
if (existsSync8(join16(candidate, "index.js"))) {
|
|
12807
12624
|
mcpSourceDir = candidate;
|
|
12808
12625
|
break;
|
|
12809
12626
|
}
|
|
@@ -12818,8 +12635,8 @@ function deployMcpAssets() {
|
|
|
12818
12635
|
const changedBasenames = [];
|
|
12819
12636
|
const fileHash = (p) => {
|
|
12820
12637
|
try {
|
|
12821
|
-
if (!
|
|
12822
|
-
return createHash10("sha256").update(
|
|
12638
|
+
if (!existsSync8(p)) return null;
|
|
12639
|
+
return createHash10("sha256").update(readFileSync14(p)).digest("hex");
|
|
12823
12640
|
} catch {
|
|
12824
12641
|
return null;
|
|
12825
12642
|
}
|
|
@@ -12856,7 +12673,7 @@ function deployMcpAssets() {
|
|
|
12856
12673
|
]) {
|
|
12857
12674
|
const src = join16(mcpSourceDir, file);
|
|
12858
12675
|
const dst = join16(targetDir, file);
|
|
12859
|
-
if (!
|
|
12676
|
+
if (!existsSync8(src)) continue;
|
|
12860
12677
|
const before = fileHash(dst);
|
|
12861
12678
|
try {
|
|
12862
12679
|
copyFileSync(src, dst);
|
|
@@ -12876,13 +12693,13 @@ function deployMcpAssets() {
|
|
|
12876
12693
|
const localMcpPath = join16(targetDir, "index.js");
|
|
12877
12694
|
try {
|
|
12878
12695
|
const agentsDir = join16(homedir9(), ".augmented", "agents");
|
|
12879
|
-
if (
|
|
12696
|
+
if (existsSync8(agentsDir)) {
|
|
12880
12697
|
for (const entry of readdirSync5(agentsDir, { withFileTypes: true })) {
|
|
12881
12698
|
if (!entry.isDirectory()) continue;
|
|
12882
12699
|
for (const subdir of ["provision", "project"]) {
|
|
12883
12700
|
const mcpJsonPath = join16(agentsDir, entry.name, subdir, ".mcp.json");
|
|
12884
12701
|
try {
|
|
12885
|
-
const raw =
|
|
12702
|
+
const raw = readFileSync14(mcpJsonPath, "utf-8");
|
|
12886
12703
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|
|
12887
12704
|
const mcpConfig = JSON.parse(raw);
|
|
12888
12705
|
const augServer = mcpConfig.mcpServers?.["augmented"];
|