@kynver-app/runtime 0.1.13 → 0.1.16
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/cli.js +71 -17
- package/dist/cli.js.map +2 -2
- package/dist/index.js +71 -17
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -207,6 +207,18 @@ async function resolveCallbackSecretWithMint(argsSecret, agentOsId, opts) {
|
|
|
207
207
|
"requires --secret, KYNVER_RUNNER_TOKEN, a scoped runner token (`kynver runner credential`), ~/.kynver/credentials runnerToken, KYNVER_API_KEY with an API base URL to mint one, or (legacy) KYNVER_RUNTIME_SECRET / OPENCLAW_CRON_SECRET"
|
|
208
208
|
);
|
|
209
209
|
}
|
|
210
|
+
async function refreshRunnerToken(agentOsId, opts) {
|
|
211
|
+
const apiKey = loadApiKey();
|
|
212
|
+
const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
|
|
213
|
+
if (!apiKey || !agentOsId || !baseUrl) return null;
|
|
214
|
+
try {
|
|
215
|
+
const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
|
|
216
|
+
saveRunnerToken(agentOsId, token);
|
|
217
|
+
return token;
|
|
218
|
+
} catch {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
210
222
|
async function fetchRunnerCredential(agentOsId, opts) {
|
|
211
223
|
const apiKey = opts?.apiKey || loadApiKey();
|
|
212
224
|
if (!apiKey) throw new Error("API key required \u2014 run `kynver login` first");
|
|
@@ -1455,6 +1467,34 @@ function failExists(message) {
|
|
|
1455
1467
|
|
|
1456
1468
|
// src/worker-ops.ts
|
|
1457
1469
|
import path11 from "node:path";
|
|
1470
|
+
async function postCompletion(url, secret, body) {
|
|
1471
|
+
const res = await fetch(url, {
|
|
1472
|
+
method: "POST",
|
|
1473
|
+
headers: buildHarnessCallbackHeaders(secret),
|
|
1474
|
+
body: JSON.stringify(body)
|
|
1475
|
+
});
|
|
1476
|
+
let parsed = null;
|
|
1477
|
+
try {
|
|
1478
|
+
parsed = await res.json();
|
|
1479
|
+
} catch {
|
|
1480
|
+
parsed = null;
|
|
1481
|
+
}
|
|
1482
|
+
return { ok: res.ok, status: res.status, parsed };
|
|
1483
|
+
}
|
|
1484
|
+
function completionErrorText(parsed) {
|
|
1485
|
+
if (parsed && typeof parsed === "object") {
|
|
1486
|
+
const err = parsed.error;
|
|
1487
|
+
if (typeof err === "string" && err.trim()) return err.trim();
|
|
1488
|
+
}
|
|
1489
|
+
return void 0;
|
|
1490
|
+
}
|
|
1491
|
+
function persistCompletionBlocker(worker, reason) {
|
|
1492
|
+
const current = worker.completionBlocker;
|
|
1493
|
+
if ((current ?? void 0) === (reason ?? void 0)) return;
|
|
1494
|
+
if (reason) worker.completionBlocker = reason;
|
|
1495
|
+
else delete worker.completionBlocker;
|
|
1496
|
+
saveWorker(worker.runId, worker);
|
|
1497
|
+
}
|
|
1458
1498
|
async function tryCompleteWorker(args) {
|
|
1459
1499
|
const worker = loadWorker(String(args.run), String(args.name));
|
|
1460
1500
|
const status = computeWorkerStatus(worker);
|
|
@@ -1467,7 +1507,8 @@ async function tryCompleteWorker(args) {
|
|
|
1467
1507
|
return { ok: true, skipped: true, reason: "worker-not-finished" };
|
|
1468
1508
|
}
|
|
1469
1509
|
const base = resolveBaseUrl(args.baseUrl ? String(args.baseUrl) : void 0);
|
|
1470
|
-
const
|
|
1510
|
+
const explicitSecret = args.secret ? String(args.secret) : void 0;
|
|
1511
|
+
let secret = await resolveCallbackSecretWithMint(explicitSecret, agentOsId, { baseUrl: base });
|
|
1471
1512
|
const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/harness/completion`;
|
|
1472
1513
|
const body = {
|
|
1473
1514
|
source: "openclaw-harness",
|
|
@@ -1479,18 +1520,23 @@ async function tryCompleteWorker(args) {
|
|
|
1479
1520
|
finishedAt: status.lastActivityAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1480
1521
|
status
|
|
1481
1522
|
};
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
parsed = await res.json();
|
|
1490
|
-
} catch {
|
|
1491
|
-
parsed = null;
|
|
1523
|
+
let result = await postCompletion(url, secret, body);
|
|
1524
|
+
if ((result.status === 401 || result.status === 403) && !explicitSecret) {
|
|
1525
|
+
const refreshed = await refreshRunnerToken(agentOsId, { baseUrl: base });
|
|
1526
|
+
if (refreshed && refreshed !== secret) {
|
|
1527
|
+
secret = refreshed;
|
|
1528
|
+
result = await postCompletion(url, secret, body);
|
|
1529
|
+
}
|
|
1492
1530
|
}
|
|
1493
|
-
|
|
1531
|
+
if (result.ok) {
|
|
1532
|
+
persistCompletionBlocker(worker, void 0);
|
|
1533
|
+
return { ok: true, httpStatus: result.status, response: result.parsed };
|
|
1534
|
+
}
|
|
1535
|
+
const authRejected = result.status === 401 || result.status === 403;
|
|
1536
|
+
const detail = completionErrorText(result.parsed) ?? (authRejected ? "runner token unauthorized" : "non-2xx response");
|
|
1537
|
+
const reason = authRejected ? `completion replay rejected (${result.status}): ${detail}` : `completion replay failed (${result.status}): ${detail}`;
|
|
1538
|
+
persistCompletionBlocker(worker, reason);
|
|
1539
|
+
return { ok: false, httpStatus: result.status, response: result.parsed, completionBlocked: true };
|
|
1494
1540
|
}
|
|
1495
1541
|
async function completeWorker(args) {
|
|
1496
1542
|
try {
|
|
@@ -1558,11 +1604,13 @@ function runStatus(args) {
|
|
|
1558
1604
|
return { worker: name, status: "missing", attention: "needs_attention", attentionReason: "worker.json not found" };
|
|
1559
1605
|
}
|
|
1560
1606
|
const status = computeWorkerStatus(worker, { base: run.base });
|
|
1607
|
+
const rawBlocker = worker.completionBlocker;
|
|
1608
|
+
const completionBlocker = typeof rawBlocker === "string" && rawBlocker ? rawBlocker : void 0;
|
|
1561
1609
|
return {
|
|
1562
1610
|
worker: status.worker,
|
|
1563
|
-
status: status.status,
|
|
1564
|
-
attention: status.attention.state,
|
|
1565
|
-
attentionReason: status.attention.reason,
|
|
1611
|
+
status: completionBlocker ? "blocked" : status.status,
|
|
1612
|
+
attention: completionBlocker ? "blocked" : status.attention.state,
|
|
1613
|
+
attentionReason: completionBlocker ?? status.attention.reason,
|
|
1566
1614
|
pid: status.pid,
|
|
1567
1615
|
alive: status.alive,
|
|
1568
1616
|
currentTool: status.currentTool,
|
|
@@ -1628,6 +1676,7 @@ function terminalStatusFor(run) {
|
|
|
1628
1676
|
if (names.length === 0) return "failed";
|
|
1629
1677
|
let anyAlive = false;
|
|
1630
1678
|
let anyResult = false;
|
|
1679
|
+
let anyCompletionBlocked = false;
|
|
1631
1680
|
for (const name of names) {
|
|
1632
1681
|
const worker = readJson(
|
|
1633
1682
|
path12.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
@@ -1639,9 +1688,13 @@ function terminalStatusFor(run) {
|
|
|
1639
1688
|
anyAlive = true;
|
|
1640
1689
|
break;
|
|
1641
1690
|
}
|
|
1691
|
+
if (typeof worker.completionBlocker === "string" && worker.completionBlocker) {
|
|
1692
|
+
anyCompletionBlocked = true;
|
|
1693
|
+
}
|
|
1642
1694
|
if (status.finalResult) anyResult = true;
|
|
1643
1695
|
}
|
|
1644
1696
|
if (anyAlive) return null;
|
|
1697
|
+
if (anyCompletionBlocked) return null;
|
|
1645
1698
|
return anyResult ? "completed" : "failed";
|
|
1646
1699
|
}
|
|
1647
1700
|
function finalizeStaleRuns() {
|
|
@@ -1740,9 +1793,10 @@ async function completeFinishedWorkers(runId, args) {
|
|
|
1740
1793
|
path14.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1741
1794
|
void 0
|
|
1742
1795
|
);
|
|
1743
|
-
if (!worker?.
|
|
1796
|
+
if (!worker?.taskId) continue;
|
|
1744
1797
|
const status = computeWorkerStatus(worker);
|
|
1745
1798
|
if (!isFinishedWorkerStatus(status)) continue;
|
|
1799
|
+
if (!worker.dispatched && !status.finalResult) continue;
|
|
1746
1800
|
const result = await tryCompleteWorker({
|
|
1747
1801
|
run: runId,
|
|
1748
1802
|
name,
|
|
@@ -1770,8 +1824,8 @@ async function runPipelineTick(args) {
|
|
|
1770
1824
|
const agentOsId = String(required(String(args.agentOsId || ""), "--agent-os-id"));
|
|
1771
1825
|
const execute = args.execute !== false && args.execute !== "false";
|
|
1772
1826
|
runStatus({ run: runId });
|
|
1773
|
-
const finalizedStaleRuns = finalizeStaleRuns();
|
|
1774
1827
|
const completedWorkers = await completeFinishedWorkers(runId, args);
|
|
1828
|
+
const finalizedStaleRuns = finalizeStaleRuns();
|
|
1775
1829
|
const planProgressSync = await syncActiveWorkerPlanProgress(runId, args);
|
|
1776
1830
|
const workspacePrefs = await fetchWorkspaceRuntimePreferences(agentOsId, args);
|
|
1777
1831
|
const resourceGate = observeRunnerResourceGate({
|