@krapht/ork 1.0.0-alpha.12 → 1.0.0-alpha.14
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/{__build_info__-BJbE3Zvp.mjs → __build_info__-B82-dGJY.mjs} +3 -3
- package/dist/{attach-BmV5ckb9.mjs → attach-CdtGX9se.mjs} +5 -5
- package/dist/bin.mjs +274 -236
- package/dist/{builtin-files-w0YULJ4c.mjs → builtin-files-Bdq23IIi.mjs} +2 -2
- package/dist/{chips-CyeB_rhR.mjs → chips-BqcT58qr.mjs} +1 -1
- package/dist/{completion-CzElB8nS.mjs → completion--ywde-56.mjs} +52 -11
- package/dist/{context-BAwgVSX5.mjs → context-Y_I4Mofq.mjs} +18 -8
- package/dist/{find-p05wlbmu.mjs → find-BVX-bL4u.mjs} +1 -1
- package/dist/{format-Dni98cbh.mjs → format-CvTE5CZQ.mjs} +12 -12
- package/dist/{help-groups-DYP_zMRP.mjs → help-groups-CpR2UzSn.mjs} +20 -6
- package/dist/{in-a-run-BI-hLIl_.mjs → in-a-run-cL5N9gpH.mjs} +1 -1
- package/dist/{limits-CElmhowV.mjs → limits-Dhe--wmX.mjs} +2 -2
- package/dist/{mcp-CM3b65AZ.mjs → mcp-CsmboyXv.mjs} +6 -6
- package/dist/once-CrwI-ZdN.mjs +76 -0
- package/dist/{output-CnRzrbUM.mjs → output-B1kwo0YU.mjs} +17 -1
- package/dist/{pause-BuS83WAI.mjs → pause-DssrYcda.mjs} +4 -4
- package/dist/{relay-DAsJA8wF.mjs → relay-DASRgsTQ.mjs} +2 -2
- package/dist/run-D8divGCs.mjs +192 -0
- package/dist/send-CXv8bx0i.mjs +105 -0
- package/dist/{src-S9yK2OHU.mjs → src-8Mul0695.mjs} +8 -10
- package/dist/{src-BfxkJOYm.mjs → src-C7z_6fhn.mjs} +200 -72
- package/dist/{src-D1QedD5y.mjs → src-njdtejgZ.mjs} +140 -38
- package/dist/{src-CdDTQLdQ.mjs → src-tsuZRu0H.mjs} +2787 -1134
- package/dist/{store-B2OaE4ID.mjs → store-CleF7KeS.mjs} +33 -76
- package/dist/ui/THIRD_PARTY_LICENSES.txt +18 -0
- package/dist/ui/assets/app-D_nAPnHM.css +1 -0
- package/dist/ui/assets/app-DqBAtXSZ.js +111 -0
- package/dist/ui/assets/{index-BL7Ad0OA.js → index-D-_uPI2v.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-C4Ys26oO.mjs → ui-CNO1M0qT.mjs} +4 -4
- package/dist/{usage-C2zx-X6q.mjs → usage-BVXi0iFY.mjs} +13 -141
- package/dist/{verdict-CIy8tAyX.mjs → verdict-CMvPCpWC.mjs} +2 -2
- package/dist/{watch-DzCeqM05.mjs → watch-DVNIciHp.mjs} +10 -8
- package/dist/{workflows-Rr5w90A0.mjs → workflows-B30QkwTk.mjs} +3 -3
- package/dist/{worktrees-f6SAbum5.mjs → worktrees-DD4_TpkH.mjs} +3 -5
- package/package.json +2 -2
- package/dist/clean-D8GI_2K-.mjs +0 -91
- package/dist/decide-DlbyctOE.mjs +0 -50
- package/dist/list-zW2xKuGr.mjs +0 -117
- package/dist/remove-Dh7D_hVn.mjs +0 -201
- package/dist/report-CEN8VoUb.mjs +0 -140
- package/dist/send-MFEQZH31.mjs +0 -163
- package/dist/ui/assets/app-CAoZtku5.js +0 -75
- package/dist/ui/assets/app-QoHVi-mb.css +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $n as maskSecrets, $t as countedTokens, An as END_KINDS, Mn as FEEDBACK_KINDS, Nn as FEEDBACK_SEVERITIES, On as outcomeEnd, Pn as FEEDBACK_TARGETS, Pt as parseReport, Zn as MASK, ii as AGENT_DRIVERS, jn as endFor, ln as lowerChild, un as startAt } from "./src-tsuZRu0H.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { existsSync, linkSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -448,7 +448,8 @@ const classifyProviderError = (text, status) => {
|
|
|
448
448
|
* it can see (a turn cap, an exit code, a provider's error), and the report
|
|
449
449
|
* the session handed in decides the rest. The runner then writes the end in
|
|
450
450
|
* the node's numbers, its detail scrubbed with the feedback redactor. A
|
|
451
|
-
* session the driver could not run ends as `driverFailure` says
|
|
451
|
+
* session the driver could not run ends as `driverFailure` says, and one that
|
|
452
|
+
* reached its token cap as `tokenCapOutcome` says.
|
|
452
453
|
*/
|
|
453
454
|
/** The end a report gives: done, a reported failure, or none handed in. */
|
|
454
455
|
const reportEnd = (report) => {
|
|
@@ -479,6 +480,36 @@ const settleEnd = (outcome, facts, scrub) => {
|
|
|
479
480
|
};
|
|
480
481
|
};
|
|
481
482
|
/**
|
|
483
|
+
* What a session's end is written with: the node's limits and program, and its
|
|
484
|
+
* folder and the home folder taken out of the detail.
|
|
485
|
+
*/
|
|
486
|
+
const scopeOf = (spec, bin, env) => ({
|
|
487
|
+
facts: {
|
|
488
|
+
...spec.maxTurns === void 0 ? {} : { maxTurns: spec.maxTurns },
|
|
489
|
+
...spec.budgetUsd === void 0 ? {} : { budgetUsd: spec.budgetUsd },
|
|
490
|
+
...spec.budgetTokens === void 0 ? {} : { budgetTokens: spec.budgetTokens },
|
|
491
|
+
program: path.basename(bin)
|
|
492
|
+
},
|
|
493
|
+
scrub: {
|
|
494
|
+
roots: [spec.cwd],
|
|
495
|
+
home: env["HOME"] ?? homedir()
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
/**
|
|
499
|
+
* The outcome of a session stopped once its counted tokens (RFC-015) reach
|
|
500
|
+
* `budgetTokens`: `budget_limit`, with what it used so far; `undefined` under
|
|
501
|
+
* the cap, or with none.
|
|
502
|
+
*/
|
|
503
|
+
const tokenCapOutcome = ({ budgetTokens }, usage, sessionId) => budgetTokens === void 0 || usage === void 0 || countedTokens(usage) < budgetTokens ? void 0 : {
|
|
504
|
+
subtype: "error_max_budget_tokens",
|
|
505
|
+
end: endFor("budget_limit"),
|
|
506
|
+
sessionId,
|
|
507
|
+
report: null,
|
|
508
|
+
text: "",
|
|
509
|
+
usage,
|
|
510
|
+
errors: [`Reached the token budget (${String(budgetTokens)})`]
|
|
511
|
+
};
|
|
512
|
+
/**
|
|
482
513
|
* The kind of a failure to run the driver: its program missing, else what a
|
|
483
514
|
* provider's words in it say, else a crash.
|
|
484
515
|
*/
|
|
@@ -534,6 +565,15 @@ const settled = (outcome, input) => settleEnd(input.reported === void 0 ? outcom
|
|
|
534
565
|
...outcome,
|
|
535
566
|
report: input.reported()
|
|
536
567
|
}, input.scope.facts, input.scope.scrub);
|
|
568
|
+
/** The session's end at its token cap, its earlier legs' usage included. */
|
|
569
|
+
const tokenCapEnd = (input, used, sessionId) => {
|
|
570
|
+
const usage = used === void 0 || input.carried === void 0 ? used : input.adapter.usage.combine(input.carried, used);
|
|
571
|
+
const capped = tokenCapOutcome(input.scope.facts, usage, sessionId);
|
|
572
|
+
return capped === void 0 ? void 0 : {
|
|
573
|
+
type: "session.finished",
|
|
574
|
+
outcome: settled(capped, input)
|
|
575
|
+
};
|
|
576
|
+
};
|
|
537
577
|
/** The kinds of a session that ended well, so a queued message continues it. */
|
|
538
578
|
const wentWell = (kind) => kind === "done" || kind === "reported_failure" || kind === "no_report";
|
|
539
579
|
/**
|
|
@@ -639,16 +679,26 @@ const runLeg = async function* (input) {
|
|
|
639
679
|
for (const line of input.pending.splice(0)) write(line);
|
|
640
680
|
if (input.adapter.command.input === void 0) child.stdin.end();
|
|
641
681
|
let outcome;
|
|
682
|
+
let sessionId = "";
|
|
642
683
|
const { decoder } = input;
|
|
643
684
|
const decode = decoder?.decode ?? input.adapter.decode;
|
|
644
685
|
try {
|
|
645
686
|
for await (const line of createInterface({ input: child.stdout })) {
|
|
646
|
-
const
|
|
687
|
+
const decoded = decode(line);
|
|
688
|
+
const { events, ended } = legStep(decoded, input);
|
|
689
|
+
for (const event of decoded.events) if (event.type === "session.started") sessionId = event.sessionId;
|
|
647
690
|
yield* events;
|
|
648
691
|
if (ended !== void 0) {
|
|
649
692
|
child.stdin.end();
|
|
650
693
|
outcome = ended;
|
|
651
694
|
}
|
|
695
|
+
const capped = outcome === void 0 ? tokenCapEnd(input, decoded.usage, sessionId) : void 0;
|
|
696
|
+
if (capped !== void 0) {
|
|
697
|
+
stopped = true;
|
|
698
|
+
child.kill("SIGINT");
|
|
699
|
+
yield capped;
|
|
700
|
+
return { kind: "finished" };
|
|
701
|
+
}
|
|
652
702
|
}
|
|
653
703
|
const end = await Promise.race([exited, spawnError.then((error) => error)]);
|
|
654
704
|
if (outcome !== void 0) return outcome;
|
|
@@ -969,7 +1019,7 @@ const permissionTool = defineTool({
|
|
|
969
1019
|
* kept as the session's report, and the session runner ends the session with
|
|
970
1020
|
* it instead of what the tool's last line says.
|
|
971
1021
|
*/
|
|
972
|
-
const REPORT_TOOL = "report";
|
|
1022
|
+
const REPORT_TOOL$1 = "report";
|
|
973
1023
|
/** Whether the driver holds a session's final answer to its schema itself. */
|
|
974
1024
|
const checksItsReport = (driver) => AGENT_DRIVERS.find((d) => d.id === driver)?.capabilities.reportSchema ?? true;
|
|
975
1025
|
/**
|
|
@@ -985,13 +1035,13 @@ const reportValidator = (schema) => {
|
|
|
985
1035
|
}
|
|
986
1036
|
};
|
|
987
1037
|
const failed = (why) => ({
|
|
988
|
-
...text(`The report was not accepted; fix it and call ${REPORT_TOOL} again.\n${why}`),
|
|
1038
|
+
...text(`The report was not accepted; fix it and call ${REPORT_TOOL$1} again.\n${why}`),
|
|
989
1039
|
isError: true
|
|
990
1040
|
});
|
|
991
1041
|
const bound = (report) => {
|
|
992
1042
|
const schema = reportValidator(report.schema);
|
|
993
1043
|
return {
|
|
994
|
-
name: REPORT_TOOL,
|
|
1044
|
+
name: REPORT_TOOL$1,
|
|
995
1045
|
description: "Hand in your final report: call this once your work is done, as your last step, with the report the task asks for. A report that does not fit comes back with what to fix; call again with the fixed report. The last report accepted is the one your owner gets.",
|
|
996
1046
|
shape: schema instanceof z.ZodObject ? schema.shape : {},
|
|
997
1047
|
schema,
|
|
@@ -1025,7 +1075,7 @@ const ORK_TOOLS = [
|
|
|
1025
1075
|
releaseTool,
|
|
1026
1076
|
feedbackTool,
|
|
1027
1077
|
{
|
|
1028
|
-
name: REPORT_TOOL,
|
|
1078
|
+
name: REPORT_TOOL$1,
|
|
1029
1079
|
bind: (context) => context.report === void 0 || checksItsReport(context.driver) ? null : bound(context.report)
|
|
1030
1080
|
}
|
|
1031
1081
|
];
|
|
@@ -1034,33 +1084,6 @@ const orkTools = (context) => ORK_TOOLS.flatMap((tool) => tool.bind(context) ??
|
|
|
1034
1084
|
/** Their Claude Code names, for the session's allowed tools. */
|
|
1035
1085
|
const preapprovedTools = (tools) => tools.filter((t) => t.preapproved).map((t) => toolId(t.name));
|
|
1036
1086
|
// ../runtime/src/session-runner.ts
|
|
1037
|
-
/**
|
|
1038
|
-
* @file The session runner: one agent CLI session, driven through an adapter's
|
|
1039
|
-
* strategies (`adapter.ts`), written once for every driver. It serves Ork's
|
|
1040
|
-
* tools on a local MCP endpoint, wires the session to it, and runs the tool
|
|
1041
|
-
* as one or more processes (legs). A paused node's tool call is held, and
|
|
1042
|
-
* past the hold window deferred; the next leg resumes the session once the
|
|
1043
|
-
* node continues (ADR-041). A tool that takes no message mid-session gets one
|
|
1044
|
-
* at the next leg, which resumes the session with it. A driver that cannot
|
|
1045
|
-
* hold the final answer to the report schema gets Ork's `report` tool, and
|
|
1046
|
-
* the session ends with the report it accepted. Interrupting stops the
|
|
1047
|
-
* running process.
|
|
1048
|
-
*/
|
|
1049
|
-
/**
|
|
1050
|
-
* What a session's end is written with: the node's limits and program, and its
|
|
1051
|
-
* folder and the home folder taken out of the detail.
|
|
1052
|
-
*/
|
|
1053
|
-
const scopeOf = (spec, bin, env) => ({
|
|
1054
|
-
facts: {
|
|
1055
|
-
...spec.maxTurns === void 0 ? {} : { maxTurns: spec.maxTurns },
|
|
1056
|
-
...spec.budgetUsd === void 0 ? {} : { budgetUsd: spec.budgetUsd },
|
|
1057
|
-
program: path.basename(bin)
|
|
1058
|
-
},
|
|
1059
|
-
scrub: {
|
|
1060
|
-
roots: [spec.cwd],
|
|
1061
|
-
home: env["HOME"] ?? homedir()
|
|
1062
|
-
}
|
|
1063
|
-
});
|
|
1064
1087
|
/** A spec that resumes `sessionId`; a fork's later legs continue the fork. */
|
|
1065
1088
|
const resumed = (spec, sessionId) => ({
|
|
1066
1089
|
...spec,
|
|
@@ -1135,7 +1158,7 @@ const createSessionRuntime = (adapter, options = {}) => ({
|
|
|
1135
1158
|
}
|
|
1136
1159
|
}
|
|
1137
1160
|
});
|
|
1138
|
-
const byTool = tools.some((tool) => tool.name === REPORT_TOOL);
|
|
1161
|
+
const byTool = tools.some((tool) => tool.name === REPORT_TOOL$1);
|
|
1139
1162
|
const mcp = await startOrkMcpHttp(tools, hold === void 0 || hook === void 0 ? void 0 : toolHook({
|
|
1140
1163
|
hold,
|
|
1141
1164
|
heavy,
|
|
@@ -1243,7 +1266,8 @@ const createSessionRuntime = (adapter, options = {}) => ({
|
|
|
1243
1266
|
/**
|
|
1244
1267
|
* @file The `claude-code` adapter's `EventDecoder` and `UsageReader`: maps the
|
|
1245
1268
|
* `claude` CLI's `stream-json` lines to Ork's runtime events, marks the
|
|
1246
|
-
* result of a turn the hold hook deferred, and adds up a session's legs.
|
|
1269
|
+
* result of a turn the hold hook deferred, and adds up a session's legs. Its
|
|
1270
|
+
* leg decoder keeps a report the session handed in and then wrote past.
|
|
1247
1271
|
*/
|
|
1248
1272
|
const isObject$2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1249
1273
|
const get$1 = (value, key) => isObject$2(value) ? value[key] : void 0;
|
|
@@ -1378,6 +1402,56 @@ const decodeClaudeLine = (line) => {
|
|
|
1378
1402
|
deferred: isDeferredResult(message)
|
|
1379
1403
|
};
|
|
1380
1404
|
};
|
|
1405
|
+
/** The tool `claude` hands a `--json-schema` report in with. */
|
|
1406
|
+
const REPORT_TOOL = "StructuredOutput";
|
|
1407
|
+
/**
|
|
1408
|
+
* A leg's decoder that keeps the last report `claude` accepted (a
|
|
1409
|
+
* `StructuredOutput` call whose result was not an error). When the session
|
|
1410
|
+
* writes on after it, `claude`'s result can come without `structured_output`;
|
|
1411
|
+
* the kept report is then the result's, so a session that reported is not read
|
|
1412
|
+
* as one that didn't.
|
|
1413
|
+
*/
|
|
1414
|
+
const claudeDecoder = () => {
|
|
1415
|
+
const calls = /* @__PURE__ */ new Map();
|
|
1416
|
+
let accepted;
|
|
1417
|
+
/** Each model response's usage, by message id: its blocks repeat it. */
|
|
1418
|
+
const responses = /* @__PURE__ */ new Map();
|
|
1419
|
+
/** The leg's usage so far, when `message` is a model response. */
|
|
1420
|
+
const usageSoFar = (message) => {
|
|
1421
|
+
const inner = get$1(message, "message");
|
|
1422
|
+
const id = get$1(inner, "id");
|
|
1423
|
+
if (get$1(message, "type") !== "assistant" || typeof id !== "string") return;
|
|
1424
|
+
responses.set(id, {
|
|
1425
|
+
...usageOf({ usage: get$1(inner, "usage") }),
|
|
1426
|
+
turns: 1
|
|
1427
|
+
});
|
|
1428
|
+
return [...responses.values()].reduce((a, b) => addUsage(a, b));
|
|
1429
|
+
};
|
|
1430
|
+
return {
|
|
1431
|
+
decode: (line) => {
|
|
1432
|
+
const message = parseLine$2(line);
|
|
1433
|
+
const usage = usageSoFar(message);
|
|
1434
|
+
for (const block of blocks(message)) {
|
|
1435
|
+
if (block["type"] === "tool_use" && block["name"] === REPORT_TOOL) calls.set(str$2(block["id"]), block["input"]);
|
|
1436
|
+
const id = str$2(block["tool_use_id"]);
|
|
1437
|
+
if (block["type"] === "tool_result" && calls.has(id)) {
|
|
1438
|
+
if (block["is_error"] !== true) accepted = calls.get(id);
|
|
1439
|
+
calls.delete(id);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
const kept = isObject$2(message) && message["type"] === "result" && (message["structured_output"] ?? null) === null && accepted !== void 0 ? {
|
|
1443
|
+
...message,
|
|
1444
|
+
structured_output: accepted
|
|
1445
|
+
} : message;
|
|
1446
|
+
return {
|
|
1447
|
+
events: normalize(kept),
|
|
1448
|
+
deferred: isDeferredResult(message),
|
|
1449
|
+
...usage === void 0 ? {} : { usage }
|
|
1450
|
+
};
|
|
1451
|
+
},
|
|
1452
|
+
exit: () => []
|
|
1453
|
+
};
|
|
1454
|
+
};
|
|
1381
1455
|
/**
|
|
1382
1456
|
* Two legs of one session, as one: the tokens of both, and the later leg's
|
|
1383
1457
|
* cost, which is already the session's total (ADR-046).
|
|
@@ -1540,6 +1614,7 @@ const claudeCodeAdapter = {
|
|
|
1540
1614
|
input: userLine
|
|
1541
1615
|
},
|
|
1542
1616
|
decode: decodeClaudeLine,
|
|
1617
|
+
legDecoder: claudeDecoder,
|
|
1543
1618
|
mcp: {
|
|
1544
1619
|
kind: "flag",
|
|
1545
1620
|
wire: () => Promise.resolve({
|
|
@@ -1904,6 +1979,26 @@ const commandCodeDecoder = () => {
|
|
|
1904
1979
|
let sessionId = "";
|
|
1905
1980
|
let turns = 0;
|
|
1906
1981
|
let held;
|
|
1982
|
+
/** The leg's tokens so far, from each `model_request_end` frame. */
|
|
1983
|
+
let used;
|
|
1984
|
+
/** A model request's usage, added to the leg's so far. */
|
|
1985
|
+
const requestEnded = (usage) => {
|
|
1986
|
+
const said = isObject$1(usage) ? usage : {};
|
|
1987
|
+
const own = {
|
|
1988
|
+
costUsd: 0,
|
|
1989
|
+
inputTokens: num$1(said["inputTokens"]),
|
|
1990
|
+
outputTokens: num$1(said["outputTokens"]),
|
|
1991
|
+
cacheReadTokens: num$1(said["cacheReadTokens"]),
|
|
1992
|
+
cacheWriteTokens: num$1(said["cacheWriteTokens"]),
|
|
1993
|
+
turns,
|
|
1994
|
+
durationMs: 0
|
|
1995
|
+
};
|
|
1996
|
+
used = used === void 0 ? own : {
|
|
1997
|
+
...addUsage(used, own),
|
|
1998
|
+
turns
|
|
1999
|
+
};
|
|
2000
|
+
return used;
|
|
2001
|
+
};
|
|
1907
2002
|
const frame = (event) => {
|
|
1908
2003
|
const type = event["type"];
|
|
1909
2004
|
const id = str$1(event["toolCallId"]);
|
|
@@ -1980,7 +2075,11 @@ const commandCodeDecoder = () => {
|
|
|
1980
2075
|
return { events: [] };
|
|
1981
2076
|
}
|
|
1982
2077
|
const event = message["event"];
|
|
1983
|
-
|
|
2078
|
+
if (message["type"] !== "event" || !isObject$1(event)) return { events: [] };
|
|
2079
|
+
return {
|
|
2080
|
+
events: frame(event),
|
|
2081
|
+
...event["type"] === "model_request_end" ? { usage: requestEnded(event["usage"]) } : {}
|
|
2082
|
+
};
|
|
1984
2083
|
},
|
|
1985
2084
|
exit: (code) => {
|
|
1986
2085
|
if (held !== void 0) return [result(held, code)];
|
|
@@ -2547,7 +2646,10 @@ const openCodeDecoder = (spec) => {
|
|
|
2547
2646
|
switch (message["type"]) {
|
|
2548
2647
|
case "step_finish":
|
|
2549
2648
|
usage = sumUsage(usage, stepUsage(message["part"]));
|
|
2550
|
-
|
|
2649
|
+
return {
|
|
2650
|
+
events,
|
|
2651
|
+
usage
|
|
2652
|
+
};
|
|
2551
2653
|
case "error":
|
|
2552
2654
|
errors.push(errorText(message["error"]));
|
|
2553
2655
|
failed ??= errorLineEnd(message["error"]);
|