@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/index.js
CHANGED
|
@@ -208,6 +208,18 @@ async function resolveCallbackSecretWithMint(argsSecret, agentOsId, opts) {
|
|
|
208
208
|
"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"
|
|
209
209
|
);
|
|
210
210
|
}
|
|
211
|
+
async function refreshRunnerToken(agentOsId, opts) {
|
|
212
|
+
const apiKey = loadApiKey();
|
|
213
|
+
const baseUrl = resolveConfiguredBaseUrl(opts?.baseUrl);
|
|
214
|
+
if (!apiKey || !agentOsId || !baseUrl) return null;
|
|
215
|
+
try {
|
|
216
|
+
const token = await fetchRunnerCredential(agentOsId, { baseUrl, apiKey });
|
|
217
|
+
saveRunnerToken(agentOsId, token);
|
|
218
|
+
return token;
|
|
219
|
+
} catch {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
211
223
|
async function fetchRunnerCredential(agentOsId, opts) {
|
|
212
224
|
const apiKey = opts?.apiKey || loadApiKey();
|
|
213
225
|
if (!apiKey) throw new Error("API key required \u2014 run `kynver login` first");
|
|
@@ -1483,6 +1495,34 @@ async function sweepRun(args) {
|
|
|
1483
1495
|
|
|
1484
1496
|
// src/worker-ops.ts
|
|
1485
1497
|
import path11 from "node:path";
|
|
1498
|
+
async function postCompletion(url, secret, body) {
|
|
1499
|
+
const res = await fetch(url, {
|
|
1500
|
+
method: "POST",
|
|
1501
|
+
headers: buildHarnessCallbackHeaders(secret),
|
|
1502
|
+
body: JSON.stringify(body)
|
|
1503
|
+
});
|
|
1504
|
+
let parsed = null;
|
|
1505
|
+
try {
|
|
1506
|
+
parsed = await res.json();
|
|
1507
|
+
} catch {
|
|
1508
|
+
parsed = null;
|
|
1509
|
+
}
|
|
1510
|
+
return { ok: res.ok, status: res.status, parsed };
|
|
1511
|
+
}
|
|
1512
|
+
function completionErrorText(parsed) {
|
|
1513
|
+
if (parsed && typeof parsed === "object") {
|
|
1514
|
+
const err = parsed.error;
|
|
1515
|
+
if (typeof err === "string" && err.trim()) return err.trim();
|
|
1516
|
+
}
|
|
1517
|
+
return void 0;
|
|
1518
|
+
}
|
|
1519
|
+
function persistCompletionBlocker(worker, reason) {
|
|
1520
|
+
const current = worker.completionBlocker;
|
|
1521
|
+
if ((current ?? void 0) === (reason ?? void 0)) return;
|
|
1522
|
+
if (reason) worker.completionBlocker = reason;
|
|
1523
|
+
else delete worker.completionBlocker;
|
|
1524
|
+
saveWorker(worker.runId, worker);
|
|
1525
|
+
}
|
|
1486
1526
|
async function tryCompleteWorker(args) {
|
|
1487
1527
|
const worker = loadWorker(String(args.run), String(args.name));
|
|
1488
1528
|
const status = computeWorkerStatus(worker);
|
|
@@ -1495,7 +1535,8 @@ async function tryCompleteWorker(args) {
|
|
|
1495
1535
|
return { ok: true, skipped: true, reason: "worker-not-finished" };
|
|
1496
1536
|
}
|
|
1497
1537
|
const base = resolveBaseUrl(args.baseUrl ? String(args.baseUrl) : void 0);
|
|
1498
|
-
const
|
|
1538
|
+
const explicitSecret = args.secret ? String(args.secret) : void 0;
|
|
1539
|
+
let secret = await resolveCallbackSecretWithMint(explicitSecret, agentOsId, { baseUrl: base });
|
|
1499
1540
|
const url = `${base}/api/agent-os/by-id/${encodeURIComponent(agentOsId)}/harness/completion`;
|
|
1500
1541
|
const body = {
|
|
1501
1542
|
source: "openclaw-harness",
|
|
@@ -1507,18 +1548,23 @@ async function tryCompleteWorker(args) {
|
|
|
1507
1548
|
finishedAt: status.lastActivityAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1508
1549
|
status
|
|
1509
1550
|
};
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
parsed = await res.json();
|
|
1518
|
-
} catch {
|
|
1519
|
-
parsed = null;
|
|
1551
|
+
let result = await postCompletion(url, secret, body);
|
|
1552
|
+
if ((result.status === 401 || result.status === 403) && !explicitSecret) {
|
|
1553
|
+
const refreshed = await refreshRunnerToken(agentOsId, { baseUrl: base });
|
|
1554
|
+
if (refreshed && refreshed !== secret) {
|
|
1555
|
+
secret = refreshed;
|
|
1556
|
+
result = await postCompletion(url, secret, body);
|
|
1557
|
+
}
|
|
1520
1558
|
}
|
|
1521
|
-
|
|
1559
|
+
if (result.ok) {
|
|
1560
|
+
persistCompletionBlocker(worker, void 0);
|
|
1561
|
+
return { ok: true, httpStatus: result.status, response: result.parsed };
|
|
1562
|
+
}
|
|
1563
|
+
const authRejected = result.status === 401 || result.status === 403;
|
|
1564
|
+
const detail = completionErrorText(result.parsed) ?? (authRejected ? "runner token unauthorized" : "non-2xx response");
|
|
1565
|
+
const reason = authRejected ? `completion replay rejected (${result.status}): ${detail}` : `completion replay failed (${result.status}): ${detail}`;
|
|
1566
|
+
persistCompletionBlocker(worker, reason);
|
|
1567
|
+
return { ok: false, httpStatus: result.status, response: result.parsed, completionBlocked: true };
|
|
1522
1568
|
}
|
|
1523
1569
|
async function completeWorker(args) {
|
|
1524
1570
|
try {
|
|
@@ -1586,11 +1632,13 @@ function runStatus(args) {
|
|
|
1586
1632
|
return { worker: name, status: "missing", attention: "needs_attention", attentionReason: "worker.json not found" };
|
|
1587
1633
|
}
|
|
1588
1634
|
const status = computeWorkerStatus(worker, { base: run.base });
|
|
1635
|
+
const rawBlocker = worker.completionBlocker;
|
|
1636
|
+
const completionBlocker = typeof rawBlocker === "string" && rawBlocker ? rawBlocker : void 0;
|
|
1589
1637
|
return {
|
|
1590
1638
|
worker: status.worker,
|
|
1591
|
-
status: status.status,
|
|
1592
|
-
attention: status.attention.state,
|
|
1593
|
-
attentionReason: status.attention.reason,
|
|
1639
|
+
status: completionBlocker ? "blocked" : status.status,
|
|
1640
|
+
attention: completionBlocker ? "blocked" : status.attention.state,
|
|
1641
|
+
attentionReason: completionBlocker ?? status.attention.reason,
|
|
1594
1642
|
pid: status.pid,
|
|
1595
1643
|
alive: status.alive,
|
|
1596
1644
|
currentTool: status.currentTool,
|
|
@@ -1660,6 +1708,7 @@ function terminalStatusFor(run) {
|
|
|
1660
1708
|
if (names.length === 0) return "failed";
|
|
1661
1709
|
let anyAlive = false;
|
|
1662
1710
|
let anyResult = false;
|
|
1711
|
+
let anyCompletionBlocked = false;
|
|
1663
1712
|
for (const name of names) {
|
|
1664
1713
|
const worker = readJson(
|
|
1665
1714
|
path12.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
@@ -1671,9 +1720,13 @@ function terminalStatusFor(run) {
|
|
|
1671
1720
|
anyAlive = true;
|
|
1672
1721
|
break;
|
|
1673
1722
|
}
|
|
1723
|
+
if (typeof worker.completionBlocker === "string" && worker.completionBlocker) {
|
|
1724
|
+
anyCompletionBlocked = true;
|
|
1725
|
+
}
|
|
1674
1726
|
if (status.finalResult) anyResult = true;
|
|
1675
1727
|
}
|
|
1676
1728
|
if (anyAlive) return null;
|
|
1729
|
+
if (anyCompletionBlocked) return null;
|
|
1677
1730
|
return anyResult ? "completed" : "failed";
|
|
1678
1731
|
}
|
|
1679
1732
|
function finalizeStaleRuns() {
|
|
@@ -1772,9 +1825,10 @@ async function completeFinishedWorkers(runId, args) {
|
|
|
1772
1825
|
path14.join(runDirectory(run.id), "workers", safeSlug(name), "worker.json"),
|
|
1773
1826
|
void 0
|
|
1774
1827
|
);
|
|
1775
|
-
if (!worker?.
|
|
1828
|
+
if (!worker?.taskId) continue;
|
|
1776
1829
|
const status = computeWorkerStatus(worker);
|
|
1777
1830
|
if (!isFinishedWorkerStatus(status)) continue;
|
|
1831
|
+
if (!worker.dispatched && !status.finalResult) continue;
|
|
1778
1832
|
const result = await tryCompleteWorker({
|
|
1779
1833
|
run: runId,
|
|
1780
1834
|
name,
|
|
@@ -1802,8 +1856,8 @@ async function runPipelineTick(args) {
|
|
|
1802
1856
|
const agentOsId = String(required(String(args.agentOsId || ""), "--agent-os-id"));
|
|
1803
1857
|
const execute = args.execute !== false && args.execute !== "false";
|
|
1804
1858
|
runStatus({ run: runId });
|
|
1805
|
-
const finalizedStaleRuns = finalizeStaleRuns();
|
|
1806
1859
|
const completedWorkers = await completeFinishedWorkers(runId, args);
|
|
1860
|
+
const finalizedStaleRuns = finalizeStaleRuns();
|
|
1807
1861
|
const planProgressSync = await syncActiveWorkerPlanProgress(runId, args);
|
|
1808
1862
|
const workspacePrefs = await fetchWorkspaceRuntimePreferences(agentOsId, args);
|
|
1809
1863
|
const resourceGate = observeRunnerResourceGate({
|