@krapht/ork 1.0.0-alpha.10 → 1.0.0-alpha.12
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__-DFF18K8y.mjs → __build_info__-BJbE3Zvp.mjs} +4 -72
- package/dist/attach-BmV5ckb9.mjs +89 -0
- package/dist/bin.mjs +467 -864
- package/dist/{decide-3l9q8UtX.mjs → builtin-files-w0YULJ4c.mjs} +2 -50
- package/dist/chips-CyeB_rhR.mjs +43 -0
- package/dist/{clean-DVaEH9e7.mjs → clean-D8GI_2K-.mjs} +1 -1
- package/dist/{completion-Dv5kf598.mjs → completion-CzElB8nS.mjs} +24 -16
- package/dist/{context-CEaKOVmG.mjs → context-BAwgVSX5.mjs} +43 -31
- package/dist/decide-DlbyctOE.mjs +50 -0
- package/dist/{find-DEjjOlTG.mjs → find-p05wlbmu.mjs} +1 -1
- package/dist/format-Dni98cbh.mjs +206 -0
- package/dist/{help-groups-BwYoAWsh.mjs → help-groups-DYP_zMRP.mjs} +4 -0
- package/dist/{in-a-run-BS9Nc-JW.mjs → in-a-run-BI-hLIl_.mjs} +4 -2
- package/dist/{limits-BSwEjQST.mjs → limits-CElmhowV.mjs} +1 -1
- package/dist/{list-Qxr6rwsY.mjs → list-zW2xKuGr.mjs} +1 -1
- package/dist/{mcp-CslnG5wf.mjs → mcp-CM3b65AZ.mjs} +6 -6
- package/dist/output-CnRzrbUM.mjs +423 -0
- package/dist/{pause-D7OVB5Ac.mjs → pause-BuS83WAI.mjs} +4 -4
- package/dist/{relay-EceRIebO.mjs → relay-DAsJA8wF.mjs} +2 -2
- package/dist/{remove-0IQZVWmI.mjs → remove-Dh7D_hVn.mjs} +3 -3
- package/dist/{report-DK4LGqwF.mjs → report-CEN8VoUb.mjs} +31 -20
- package/dist/{send-C0uwfUYi.mjs → send-MFEQZH31.mjs} +3 -3
- package/dist/{src-cmmXKHn1.mjs → src-BfxkJOYm.mjs} +234 -150
- package/dist/{src-Df6KOIDC.mjs → src-CdDTQLdQ.mjs} +2081 -1035
- package/dist/{src-oaJYIddp.mjs → src-D1QedD5y.mjs} +523 -81
- package/dist/{src-i5k2Y-kf.mjs → src-S9yK2OHU.mjs} +79 -11
- package/dist/store-B2OaE4ID.mjs +1356 -0
- package/dist/ui/assets/{app-qs8Lofv6.js → app-CAoZtku5.js} +16 -16
- package/dist/ui/assets/app-QoHVi-mb.css +1 -0
- package/dist/ui/assets/{index-DV1ZaOk-.js → index-BL7Ad0OA.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-CBkHJdqk.mjs → ui-C4Ys26oO.mjs} +4 -4
- package/dist/{usage-Cd8pEYyK.mjs → usage-C2zx-X6q.mjs} +43 -32
- package/dist/verdict-CIy8tAyX.mjs +84 -0
- package/dist/{watch-DW5R2OPO.mjs → watch-DzCeqM05.mjs} +28 -16
- package/dist/{workflows-BT1gDRIV.mjs → workflows-Rr5w90A0.mjs} +3 -3
- package/dist/{worktrees-g1MQMGie.mjs → worktrees-f6SAbum5.mjs} +11 -10
- package/package.json +1 -1
- package/dist/format-Cb5_m-Qd.mjs +0 -191
- package/dist/output-Bqljtmp_.mjs +0 -40
- package/dist/ui/assets/app-C8uhHVYp.css +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bn as placeFiles, Qn as writePlainFile, Xn as guardedBase, Zn as plainPathInside } from "./src-CdDTQLdQ.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
@@ -62,52 +62,4 @@ const builtinWorkflowFile = (place, arg) => {
|
|
|
62
62
|
if (existsSync(file) && readFileSync(file, "utf8") === text) return file;
|
|
63
63
|
return writePlainFile(base, file, text).ok ? file : void 0;
|
|
64
64
|
};
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* @file The open decisions of live runs, and answering one from another process
|
|
68
|
-
* (`ork decide`, the local server), with the person's note if they gave one.
|
|
69
|
-
* An answer goes to the store (the first one wins), then the run is woken on
|
|
70
|
-
* its socket so it picks the answer up at once (specs/messaging.md).
|
|
71
|
-
*/
|
|
72
|
-
/** Open decisions whose run is still live, oldest first, ANDing the filter. */
|
|
73
|
-
const pendingDecisions = (store, filter) => {
|
|
74
|
-
const live = /* @__PURE__ */ new Map();
|
|
75
|
-
return store.decisions({
|
|
76
|
-
...filter,
|
|
77
|
-
status: "open"
|
|
78
|
-
}).filter((decision) => {
|
|
79
|
-
if (!live.has(decision.runId)) {
|
|
80
|
-
const [run] = store.lookup(decision.runId);
|
|
81
|
-
live.set(decision.runId, run !== void 0 && liveStatus(run) === "running" && (filter.workflow === void 0 || run.workflow === filter.workflow));
|
|
82
|
-
}
|
|
83
|
-
return live.get(decision.runId) === true;
|
|
84
|
-
});
|
|
85
|
-
};
|
|
86
|
-
/**
|
|
87
|
-
* Answers an open decision with one of its options, and wakes its run. `home`
|
|
88
|
-
* is `~`, where the sockets are (tests pass a folder); `by` says who answered;
|
|
89
|
-
* `note` is what they said with it, if anything (blank is nothing).
|
|
90
|
-
*/
|
|
91
|
-
const answerDecision = async (store, id, choice, home, by = "decide", note) => {
|
|
92
|
-
const decision = store.decision(id);
|
|
93
|
-
if (decision === void 0) return {
|
|
94
|
-
ok: false,
|
|
95
|
-
error: `No decision \`${id}\`.`
|
|
96
|
-
};
|
|
97
|
-
if (!decision.options.some((o) => o.id === choice)) return {
|
|
98
|
-
ok: false,
|
|
99
|
-
error: `\`${choice}\` is not an option of \`${id}\`: \`${decision.options.map((o) => o.id).join("`, `")}\``
|
|
100
|
-
};
|
|
101
|
-
if (!store.answerDecision(id, choice, by, note)) {
|
|
102
|
-
const now = store.decision(id);
|
|
103
|
-
return {
|
|
104
|
-
ok: false,
|
|
105
|
-
error: now?.status === "answered" ? `${id} was already answered: ${now.answer ?? ""} (${now.answeredBy ?? ""})` : `${id} was withdrawn`
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
ok: true,
|
|
110
|
-
woke: await wakeRun(socketPath(decision.runId, home))
|
|
111
|
-
};
|
|
112
|
-
};
|
|
113
|
-
export { builtinWorkflowNames as a, builtinWorkflowFile as i, pendingDecisions as n, builtinWorkflowText as o, builtinProblem as r, isBuiltinArg as s, answerDecision as t };
|
|
65
|
+
export { isBuiltinArg as a, builtinWorkflowText as i, builtinWorkflowFile as n, builtinWorkflowNames as r, builtinProblem as t };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { d as apply, l as CHIP, u as NODE_PALETTE } from "./output-CnRzrbUM.mjs";
|
|
2
|
+
// src/term/chips.ts
|
|
3
|
+
/** The chip words the kit's commands use. */
|
|
4
|
+
const CHIP_LABELS = {
|
|
5
|
+
ask: "ASK",
|
|
6
|
+
run: "RUN",
|
|
7
|
+
ok: "OK",
|
|
8
|
+
fail: "FAIL",
|
|
9
|
+
wait: "WAIT",
|
|
10
|
+
warn: "WARN",
|
|
11
|
+
skip: "SKIP",
|
|
12
|
+
error: "ERROR"
|
|
13
|
+
};
|
|
14
|
+
/** A run's or trigger's state word as a chip: its label and role. */
|
|
15
|
+
const statusChip = (status) => {
|
|
16
|
+
const role = status === "running" ? "accent" : status === "succeeded" ? "ok" : status === "failed" || status === "crashed" ? "danger" : [
|
|
17
|
+
"paused",
|
|
18
|
+
"budget_exhausted",
|
|
19
|
+
"quota_exhausted",
|
|
20
|
+
"timed_out",
|
|
21
|
+
"interrupted"
|
|
22
|
+
].includes(status) ? "warn" : "muted";
|
|
23
|
+
return {
|
|
24
|
+
label: status === "running" ? CHIP_LABELS.run : status === "succeeded" ? CHIP_LABELS.ok : status === "failed" ? CHIP_LABELS.fail : status.replaceAll("_", " ").toUpperCase(),
|
|
25
|
+
role
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/** A chip: ` LABEL ` on the role's background; `[LABEL]` when plain. */
|
|
29
|
+
const chip = (term, label, role) => term.rich ? apply(term, CHIP[role], ` ${label} `) : `[${label}]`;
|
|
30
|
+
/** A stable non-negative number for `text` (FNV-1a). */
|
|
31
|
+
const hash = (text) => {
|
|
32
|
+
let h = 2166136261;
|
|
33
|
+
for (const char of text) h = Math.imul(h ^ (char.codePointAt(0) ?? 0), 16777619);
|
|
34
|
+
return h >>> 0;
|
|
35
|
+
};
|
|
36
|
+
/** The palette slot of a node id, 0 to 5, the same on every call. */
|
|
37
|
+
const nodeSlot = (id) => hash(id) % NODE_PALETTE.length;
|
|
38
|
+
/** A node's chip: its id on the color its id picks; `[id]` when plain. */
|
|
39
|
+
const nodeChip = (term, id) => {
|
|
40
|
+
const format = NODE_PALETTE[nodeSlot(id)] ?? CHIP.muted;
|
|
41
|
+
return term.rich ? apply(term, format, ` ${id} `) : `[${id}]`;
|
|
42
|
+
};
|
|
43
|
+
export { statusChip as i, chip as n, nodeChip as r, CHIP_LABELS as t };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { Ar as AGENT_DRIVERS, Bn as placeFiles, C as openStore, Vn as placeFor, w as storePath, xt as liveStatus, yr as NodeIdSchema } from "./src-CdDTQLdQ.mjs";
|
|
2
|
+
import { a as isBuiltinArg, i as builtinWorkflowText, r as builtinWorkflowNames } from "./builtin-files-w0YULJ4c.mjs";
|
|
3
|
+
import { n as pendingDecisions } from "./decide-DlbyctOE.mjs";
|
|
4
|
+
import { t as findRun } from "./find-p05wlbmu.mjs";
|
|
5
|
+
import { a as findEntry, c as subcommandsOf, d as SHELL_SCRIPTS, l as COMPLETE_COMMAND, n as groupedEntries, r as argInfoOf, t as groupOf, u as SHELLS } from "./help-groups-DYP_zMRP.mjs";
|
|
6
|
+
import { s as writeErr } from "./output-CnRzrbUM.mjs";
|
|
7
|
+
import { a as resolveWorkflowArg, n as WORKFLOW_SUFFIX } from "./workflows-Rr5w90A0.mjs";
|
|
7
8
|
import path from "node:path";
|
|
8
9
|
import { parse } from "yaml";
|
|
9
10
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
@@ -184,16 +185,23 @@ const subcommandSections = (position) => {
|
|
|
184
185
|
};
|
|
185
186
|
const flagSection = (position) => ({
|
|
186
187
|
title: "flags",
|
|
187
|
-
candidates: [
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
188
|
+
candidates: [
|
|
189
|
+
...position.flags.flatMap((flag) => [{
|
|
190
|
+
value: `--${flag.name}`,
|
|
191
|
+
description: brief(flag.description)
|
|
192
|
+
}, ...flag.negatable ? [{
|
|
193
|
+
value: `--no-${flag.name}`,
|
|
194
|
+
description: `Turn off --${flag.name}`
|
|
195
|
+
}] : []]),
|
|
196
|
+
{
|
|
197
|
+
value: "--plain",
|
|
198
|
+
description: "Plain output, no color or redraw"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
value: "--help",
|
|
202
|
+
description: "Show this command's help"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
197
205
|
});
|
|
198
206
|
const fromProvider = (provider, context) => provider === void 0 ? NONE : {
|
|
199
207
|
sections: [{
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { c as checkDue, d as pendingNotice, f as readUpdateCache, h as writeUpdateCache, i as registryOf, m as updateCachePath, n as ORK_VERSION, o as updateSwitchOff, p as refreshUpdateCache, r as isSwitchedOn, t as ORK_NAME, u as newerVersion } from "./__build_info__-
|
|
3
|
-
import { a as
|
|
4
|
-
import {
|
|
1
|
+
import { Ar as AGENT_DRIVERS, Bn as placeFiles, C as openStore, Dr as readyDriver, Er as driverChecks, F as driverQueues, Fr as knownExperiments, Gn as workflowDirOf, Jn as LESSON_CAP_TOKENS, Mr as firstLine, Nr as EXPERIMENTS, P as driverRefusals, Pr as experimentsOn, Sn as socketRoom, Sr as INTEGRATIONS, Vn as placeFor, _ as readProjectTriggers, br as retiredDriverHint, ct as explainSession, f as lateTriggers, gt as walkSummary, ht as walkChecks, jr as DRIVER_IDS, mt as checkWorkflowText, p as triggersReport, qt as loadProject, ut as namingNoDriver, v as workflowTextHash, vr as DriverSchema, w as storePath } from "./src-CdDTQLdQ.mjs";
|
|
2
|
+
import { c as checkDue, d as pendingNotice, f as readUpdateCache, h as writeUpdateCache, i as registryOf, m as updateCachePath, n as ORK_VERSION, o as updateSwitchOff, p as refreshUpdateCache, r as isSwitchedOn, t as ORK_NAME, u as newerVersion } from "./__build_info__-BJbE3Zvp.mjs";
|
|
3
|
+
import { S as cut, T as wrap, a as style, i as plain, o as write, p as paint, s as writeErr, w as widthOf, x as termOf, y as plainEnv } from "./output-CnRzrbUM.mjs";
|
|
4
|
+
import { n as chip, t as CHIP_LABELS } from "./chips-CyeB_rhR.mjs";
|
|
5
|
+
import { c as registeredProjects, i as refusedBuiltin, o as workflowArg, r as findWorkflowFiles, s as projectAt } from "./workflows-Rr5w90A0.mjs";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
import { readFileSync } from "node:fs";
|
|
7
8
|
import { execFile, spawn } from "node:child_process";
|
|
@@ -73,7 +74,7 @@ const showUpdateNotice = (file = updateCachePath(), now = /* @__PURE__ */ new Da
|
|
|
73
74
|
const latest = pendingNotice(cache, ORK_VERSION, now);
|
|
74
75
|
if (cache === null || latest === null) return;
|
|
75
76
|
const text = updateNotice(latest, ORK_VERSION);
|
|
76
|
-
process.stderr.write(`\n${styleText("yellow", text, { stream: process.stderr })}\n`);
|
|
77
|
+
process.stderr.write(`\n${plainEnv() ? text : styleText("yellow", text, { stream: process.stderr })}\n`);
|
|
77
78
|
writeUpdateCache(file, {
|
|
78
79
|
...cache,
|
|
79
80
|
notified: {
|
|
@@ -417,6 +418,41 @@ const pathLines = (walk) => {
|
|
|
417
418
|
const endings = walk?.endings ?? [];
|
|
418
419
|
return [...endings.filter(({ status }) => status === "succeeded"), ...endings.filter(({ status }) => status !== "succeeded")].flatMap((ending) => endingLines(ending));
|
|
419
420
|
};
|
|
421
|
+
// src/commands/validate-report.ts
|
|
422
|
+
const plural = (count, word) => `${count} ${word}${count === 1 ? "" : "s"}`;
|
|
423
|
+
const diagnosticLine = (file, d, term) => {
|
|
424
|
+
const where = d.line === void 0 ? file : `${file}:${d.line}:${d.column ?? 1}`;
|
|
425
|
+
if (term.rich) return [
|
|
426
|
+
`${d.severity === "error" ? chip(term, CHIP_LABELS.error, "danger") : chip(term, CHIP_LABELS.warn, "warn")} ${paint(term, "muted", cut(where, term.width - 9))}`,
|
|
427
|
+
...wrap(d.message, term.width - 2).map((line) => ` ${line}`),
|
|
428
|
+
` ${paint(term, "muted", `(${d.code})`)}`
|
|
429
|
+
];
|
|
430
|
+
const severity = d.severity === "error" ? style(["red", "bold"], "error") : style(["yellow", "bold"], "warning");
|
|
431
|
+
return [`${style("dim", where)} ${severity} ${d.message} ${style("dim", `(${d.code})`)}`];
|
|
432
|
+
};
|
|
433
|
+
/** The warnings alone, for a run that goes ahead despite them. */
|
|
434
|
+
const warningLines = (report, term = termOf(process.stderr)) => report.diagnostics.filter((d) => d.severity === "warning").flatMap((d) => diagnosticLine(report.file, d, term));
|
|
435
|
+
/** The verdict line: `OK` or `FAIL` chip when rich, else `✓` or `✗`. */
|
|
436
|
+
const verdictLine = (term, ok, file, note) => {
|
|
437
|
+
const mark = term.rich ? chip(term, ok ? CHIP_LABELS.ok : CHIP_LABELS.fail, ok ? "ok" : "danger") : style(ok ? "green" : "red", ok ? "✓" : "✗");
|
|
438
|
+
const room = term.rich ? Math.max(8, term.width - widthOf(file) - 8) : Infinity;
|
|
439
|
+
return `${mark} ${file}${note === "" ? "" : ` ${style("dim", cut(note, room))}`}`;
|
|
440
|
+
};
|
|
441
|
+
/** Human-readable report, one line per diagnostic, compiler style. */
|
|
442
|
+
const formatReport = (report, showsPaths = false, term = termOf(process.stdout)) => {
|
|
443
|
+
const lines = report.diagnostics.flatMap((d) => diagnosticLine(report.file, d, term));
|
|
444
|
+
const errors = report.diagnostics.filter((d) => d.severity === "error").length;
|
|
445
|
+
const warnings = report.diagnostics.length - errors;
|
|
446
|
+
if (report.summary === void 0 && errors === 0) lines.push(verdictLine(term, true, report.file, warnings === 0 ? "" : `(${plural(warnings, "warning")})`));
|
|
447
|
+
else if (report.summary !== void 0 && errors === 0) {
|
|
448
|
+
const { nodes, edges, entries } = report.summary;
|
|
449
|
+
const extra = warnings > 0 ? `, ${plural(warnings, "warning")}` : "";
|
|
450
|
+
lines.push(verdictLine(term, true, report.file, `(${plural(nodes, "node")}, ${plural(edges, "edge")}, starts at ${entries.join(", ")}${extra})`));
|
|
451
|
+
} else lines.push(verdictLine(term, false, report.file, `(${plural(errors, "error")}, ${plural(warnings, "warning")})`));
|
|
452
|
+
return [...lines, ...walkLine(report.walk, showsPaths)];
|
|
453
|
+
};
|
|
454
|
+
/** A report's lines, and with `showsPaths` each path the walk found. */
|
|
455
|
+
const reportLines = (report, showsPaths) => [...formatReport(report, showsPaths), ...showsPaths ? pathLines(report.walk) : []];
|
|
420
456
|
// src/commands/validate.ts
|
|
421
457
|
/**
|
|
422
458
|
* @file `ork validate`: loads, parses and compiles workflow files with the
|
|
@@ -494,27 +530,6 @@ const walkLoaded = async (loaded) => {
|
|
|
494
530
|
}
|
|
495
531
|
};
|
|
496
532
|
};
|
|
497
|
-
const plural = (count, word) => `${count} ${word}${count === 1 ? "" : "s"}`;
|
|
498
|
-
const diagnosticLine = (file, d) => {
|
|
499
|
-
const where = d.line === void 0 ? file : `${file}:${d.line}:${d.column ?? 1}`;
|
|
500
|
-
const severity = d.severity === "error" ? style(["red", "bold"], "error") : style(["yellow", "bold"], "warning");
|
|
501
|
-
return `${style("dim", where)} ${severity} ${d.message} ${style("dim", `(${d.code})`)}`;
|
|
502
|
-
};
|
|
503
|
-
/** The warnings alone, for a run that goes ahead despite them. */
|
|
504
|
-
const warningLines = (report) => report.diagnostics.filter((d) => d.severity === "warning").map((d) => diagnosticLine(report.file, d));
|
|
505
|
-
/** Human-readable report, one line per diagnostic, compiler style. */
|
|
506
|
-
const formatReport = (report, showsPaths = false) => {
|
|
507
|
-
const lines = report.diagnostics.map((d) => diagnosticLine(report.file, d));
|
|
508
|
-
const errors = report.diagnostics.filter((d) => d.severity === "error").length;
|
|
509
|
-
const warnings = report.diagnostics.length - errors;
|
|
510
|
-
if (report.summary === void 0 && errors === 0) lines.push(`${style("green", "✓")} ${report.file}${warnings === 0 ? "" : style("dim", ` (${plural(warnings, "warning")})`)}`);
|
|
511
|
-
else if (report.summary !== void 0 && errors === 0) {
|
|
512
|
-
const { nodes, edges, entries } = report.summary;
|
|
513
|
-
const extra = warnings > 0 ? `, ${plural(warnings, "warning")}` : "";
|
|
514
|
-
lines.push(`${style("green", "✓")} ${report.file} ${style("dim", `(${plural(nodes, "node")}, ${plural(edges, "edge")}, starts at ${entries.join(", ")}${extra})`)}`);
|
|
515
|
-
} else lines.push(`${style("red", "✗")} ${report.file} ${style("dim", `(${plural(errors, "error")}, ${plural(warnings, "warning")})`)}`);
|
|
516
|
-
return [...lines, ...walkLine(report.walk, showsPaths)];
|
|
517
|
-
};
|
|
518
533
|
const validate = defineCommand({
|
|
519
534
|
meta: {
|
|
520
535
|
name: "validate",
|
|
@@ -573,10 +588,7 @@ const validate = defineCommand({
|
|
|
573
588
|
diagnostics: [...triggers.diagnostics, ...triggers.triggers.flatMap((item) => item.diagnostics)]
|
|
574
589
|
}] : []];
|
|
575
590
|
if (args.json) write(JSON.stringify(reports, void 0, 2));
|
|
576
|
-
else for (const report of reports)
|
|
577
|
-
for (const line of formatReport(report, args.paths)) write(line);
|
|
578
|
-
if (args.paths) for (const line of pathLines(report.walk)) write(line);
|
|
579
|
-
}
|
|
591
|
+
else for (const report of reports) for (const line of reportLines(report, args.paths)) write(line);
|
|
580
592
|
if (reports.some((r) => hasErrors(r.diagnostics))) process.exitCode = 1;
|
|
581
593
|
}
|
|
582
594
|
});
|
|
@@ -680,4 +692,4 @@ const context = defineCommand({
|
|
|
680
692
|
},
|
|
681
693
|
subCommands: { explain }
|
|
682
694
|
});
|
|
683
|
-
export { startUpdateCheck as C, showUpdateNotice as S, runChecks as _,
|
|
695
|
+
export { startUpdateCheck as C, showUpdateNotice as S, runChecks as _, validateFile as a, UPDATE_CHILD_ENV as b, warningLines as c, runReadyDriver as d, unfitLines as f, orkCheck as g, headWarning as h, validate as i, checksHere as l, experimentsCheck as m, explainNode as n, walkLoaded as o, exec as p, loadWorkflow as r, formatReport as s, context as t, chooseReadyDriver as u, socketCheck as v, updateCheckOff as w, runUpdateChild as x, triggerChecks as y };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Cn as wakeRun, xn as socketPath, xt as liveStatus } from "./src-CdDTQLdQ.mjs";
|
|
2
|
+
// ../core/src/remote/decide.ts
|
|
3
|
+
/**
|
|
4
|
+
* @file The open decisions of live runs, and answering one from another process
|
|
5
|
+
* (`ork decide`, the local server), with the person's note if they gave one.
|
|
6
|
+
* An answer goes to the store (the first one wins), then the run is woken on
|
|
7
|
+
* its socket so it picks the answer up at once (specs/messaging.md).
|
|
8
|
+
*/
|
|
9
|
+
/** Open decisions whose run is still live, oldest first, ANDing the filter. */
|
|
10
|
+
const pendingDecisions = (store, filter) => {
|
|
11
|
+
const live = /* @__PURE__ */ new Map();
|
|
12
|
+
return store.decisions({
|
|
13
|
+
...filter,
|
|
14
|
+
status: "open"
|
|
15
|
+
}).filter((decision) => {
|
|
16
|
+
if (!live.has(decision.runId)) {
|
|
17
|
+
const [run] = store.lookup(decision.runId);
|
|
18
|
+
live.set(decision.runId, run !== void 0 && liveStatus(run) === "running" && (filter.workflow === void 0 || run.workflow === filter.workflow));
|
|
19
|
+
}
|
|
20
|
+
return live.get(decision.runId) === true;
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Answers an open decision with one of its options, and wakes its run. `home`
|
|
25
|
+
* is `~`, where the sockets are (tests pass a folder); `by` says who answered;
|
|
26
|
+
* `note` is what they said with it, if anything (blank is nothing).
|
|
27
|
+
*/
|
|
28
|
+
const answerDecision = async (store, id, choice, home, by = "decide", note) => {
|
|
29
|
+
const decision = store.decision(id);
|
|
30
|
+
if (decision === void 0) return {
|
|
31
|
+
ok: false,
|
|
32
|
+
error: `No decision \`${id}\`.`
|
|
33
|
+
};
|
|
34
|
+
if (!decision.options.some((o) => o.id === choice)) return {
|
|
35
|
+
ok: false,
|
|
36
|
+
error: `\`${choice}\` is not an option of \`${id}\`: \`${decision.options.map((o) => o.id).join("`, `")}\``
|
|
37
|
+
};
|
|
38
|
+
if (!store.answerDecision(id, choice, by, note)) {
|
|
39
|
+
const now = store.decision(id);
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
error: now?.status === "answered" ? `${id} was already answered: ${now.answer ?? ""} (${now.answeredBy ?? ""})` : `${id} was withdrawn`
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
ok: true,
|
|
47
|
+
woke: await wakeRun(socketPath(decision.runId, home))
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
export { pendingDecisions as n, answerDecision as t };
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { Ct as runStatus, Tt as slotWaitsOf, kt as isItem, xt as liveStatus } from "./src-CdDTQLdQ.mjs";
|
|
2
|
+
import { S as cut, a as style, n as cost, w as widthOf, x as termOf } from "./output-CnRzrbUM.mjs";
|
|
3
|
+
import { i as statusChip, n as chip } from "./chips-CyeB_rhR.mjs";
|
|
4
|
+
import { n as nodeVerdict } from "./verdict-CIy8tAyX.mjs";
|
|
5
|
+
// src/term/table.ts
|
|
6
|
+
/**
|
|
7
|
+
* @file Aligned columns for the listing commands: each column as wide as its
|
|
8
|
+
* widest cell, a two-space gap, the last column left unpadded. Rich, a cell
|
|
9
|
+
* may be a chip and a table wider than the screen cuts its flexible columns
|
|
10
|
+
* with `…`; plain, nothing is cut or styled, as the listings always printed.
|
|
11
|
+
*/
|
|
12
|
+
/** A dimmed header cell. */
|
|
13
|
+
const header = (text) => ({
|
|
14
|
+
text,
|
|
15
|
+
look: (s) => style("dim", s)
|
|
16
|
+
});
|
|
17
|
+
const GAP = " ";
|
|
18
|
+
/** A flexible column is never cut under this many columns. */
|
|
19
|
+
const MIN_FLEX = 8;
|
|
20
|
+
/** The text a cell shows, and its columns. */
|
|
21
|
+
const shown = (term, cell) => term.rich && cell.chip !== void 0 ? cell.chip.label : cell.text;
|
|
22
|
+
const widthOfCell = (term, cell) => widthOf(shown(term, cell)) + (term.rich && cell.chip !== void 0 ? 2 : 0);
|
|
23
|
+
/** The lines of a table, one per row (a header is a row the caller passes). */
|
|
24
|
+
const table = (term, columns, rows, indent = "") => {
|
|
25
|
+
const widths = columns.map((_, c) => Math.max(0, ...rows.map((row) => widthOfCell(term, row[c] ?? { text: "" }))));
|
|
26
|
+
if (term.rich) {
|
|
27
|
+
const gaps = 2 * (columns.length - 1);
|
|
28
|
+
let over = indent.length + widths.reduce((a, b) => a + b, 0) + gaps - term.width;
|
|
29
|
+
columns.forEach((column, c) => {
|
|
30
|
+
const width = widths[c] ?? 0;
|
|
31
|
+
if (over <= 0 || column.flex !== true || width <= MIN_FLEX) return;
|
|
32
|
+
const next = Math.max(MIN_FLEX, width - over);
|
|
33
|
+
over -= width - next;
|
|
34
|
+
widths[c] = next;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const last = columns.length - 1;
|
|
38
|
+
return rows.map((row) => indent + columns.map((column, c) => {
|
|
39
|
+
const cell = row[c] ?? { text: "" };
|
|
40
|
+
const width = widths[c] ?? 0;
|
|
41
|
+
const look = cell.look ?? ((s) => s);
|
|
42
|
+
if (term.rich && cell.chip !== void 0) {
|
|
43
|
+
const used = widthOfCell(term, cell);
|
|
44
|
+
const pad = " ".repeat(Math.max(0, width - used));
|
|
45
|
+
return column.align === "right" ? pad + chip(term, cell.chip.label, cell.chip.role) : chip(term, cell.chip.label, cell.chip.role) + (c === last ? "" : pad);
|
|
46
|
+
}
|
|
47
|
+
const text = cut(shown(term, cell), width);
|
|
48
|
+
const pad = " ".repeat(Math.max(0, width - widthOf(text)));
|
|
49
|
+
if (column.align === "right") return look(pad + text);
|
|
50
|
+
return c === last ? look(text) : look(text + pad);
|
|
51
|
+
}).join(GAP));
|
|
52
|
+
};
|
|
53
|
+
// src/runs/format.ts
|
|
54
|
+
/**
|
|
55
|
+
* @file How stored runs read on the terminal: the `ork ps` table and the `ork
|
|
56
|
+
* tree` ownership tree with each node's state, tokens and cost, and what is
|
|
57
|
+
* paused (ADR-041).
|
|
58
|
+
*/
|
|
59
|
+
const STATUS_STYLE = {
|
|
60
|
+
running: "cyan",
|
|
61
|
+
paused: "yellow",
|
|
62
|
+
succeeded: "green",
|
|
63
|
+
failed: "red",
|
|
64
|
+
crashed: "red",
|
|
65
|
+
budget_exhausted: "yellow",
|
|
66
|
+
quota_exhausted: "yellow",
|
|
67
|
+
timed_out: "yellow",
|
|
68
|
+
interrupted: "yellow"
|
|
69
|
+
};
|
|
70
|
+
/** `just now`, `5m ago`, `3h ago`, `2d ago`, then the date. */
|
|
71
|
+
const ago = (iso, now = Date.now()) => {
|
|
72
|
+
const minutes = Math.floor((now - Date.parse(iso)) / 6e4);
|
|
73
|
+
if (minutes < 1) return "just now";
|
|
74
|
+
if (minutes < 60) return `${String(minutes)}m ago`;
|
|
75
|
+
if (minutes < 1440) return `${String(Math.floor(minutes / 60))}h ago`;
|
|
76
|
+
if (minutes < 10080) return `${String(Math.floor(minutes / 1440))}d ago`;
|
|
77
|
+
return iso.slice(0, 10);
|
|
78
|
+
};
|
|
79
|
+
/** `42s`, `3m12s`, `1h05m`. */
|
|
80
|
+
const duration = (ms) => {
|
|
81
|
+
const s = Math.max(0, Math.round(ms / 1e3));
|
|
82
|
+
if (s < 60) return `${String(s)}s`;
|
|
83
|
+
if (s < 3600) return `${String(Math.floor(s / 60))}m${String(s % 60).padStart(2, "0")}s`;
|
|
84
|
+
return `${String(Math.floor(s / 3600))}h${String(Math.floor(s % 3600 / 60)).padStart(2, "0")}m`;
|
|
85
|
+
};
|
|
86
|
+
const dim = (s) => style("dim", s);
|
|
87
|
+
/**
|
|
88
|
+
* A run's status as `ork ps` reads it: `waiting for slot` for a running run
|
|
89
|
+
* with a command waiting for a machine-wide slot; `events` are a running
|
|
90
|
+
* run's.
|
|
91
|
+
*/
|
|
92
|
+
const listedStatus = (run, events) => {
|
|
93
|
+
const status = runStatus(run, events);
|
|
94
|
+
return status === "running" && slotWaitsOf(events).length > 0 ? "waiting for slot" : status;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* The `ork ps` table; `withProject` adds each run's project. A called run's
|
|
98
|
+
* cost is dimmed and says its caller's, whose cost already counts it.
|
|
99
|
+
*/
|
|
100
|
+
const formatRuns = (runs, withProject, now = Date.now(), statusOf = liveStatus, term = termOf(process.stdout)) => {
|
|
101
|
+
if (runs.length === 0) return ["No runs."];
|
|
102
|
+
const rows = runs.map((run) => {
|
|
103
|
+
const status = statusOf(run);
|
|
104
|
+
const end = run.finishedAt === void 0 ? now : Date.parse(run.finishedAt);
|
|
105
|
+
return {
|
|
106
|
+
id: run.id,
|
|
107
|
+
workflow: run.workflow,
|
|
108
|
+
status,
|
|
109
|
+
when: `${ago(run.startedAt, now)} · ${duration(end - Date.parse(run.startedAt))}`,
|
|
110
|
+
cost: run.parent === void 0 ? cost(run.costUsd) : `${cost(run.costUsd)} in ${run.parent}`,
|
|
111
|
+
called: run.parent !== void 0,
|
|
112
|
+
project: run.project
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
const rowOf = (r) => {
|
|
116
|
+
const cells = [
|
|
117
|
+
{
|
|
118
|
+
text: r.id,
|
|
119
|
+
look: (s) => style("bold", s)
|
|
120
|
+
},
|
|
121
|
+
{ text: r.workflow },
|
|
122
|
+
{
|
|
123
|
+
text: r.status,
|
|
124
|
+
chip: statusChip(r.status),
|
|
125
|
+
look: (s) => style(STATUS_STYLE[r.status] ?? "reset", s)
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
text: r.when,
|
|
129
|
+
look: dim
|
|
130
|
+
},
|
|
131
|
+
r.called ? {
|
|
132
|
+
text: r.cost,
|
|
133
|
+
look: dim
|
|
134
|
+
} : { text: r.cost }
|
|
135
|
+
];
|
|
136
|
+
if (withProject) cells.push({
|
|
137
|
+
text: r.project,
|
|
138
|
+
look: dim
|
|
139
|
+
});
|
|
140
|
+
return cells;
|
|
141
|
+
};
|
|
142
|
+
const heads = [
|
|
143
|
+
"RUN",
|
|
144
|
+
"WORKFLOW",
|
|
145
|
+
"STATUS",
|
|
146
|
+
"STARTED",
|
|
147
|
+
"COST"
|
|
148
|
+
].map((text) => header(text));
|
|
149
|
+
if (withProject) heads.push(header("PROJECT"));
|
|
150
|
+
const columns = [
|
|
151
|
+
{},
|
|
152
|
+
{ flex: true },
|
|
153
|
+
{},
|
|
154
|
+
{},
|
|
155
|
+
{ align: "right" }
|
|
156
|
+
];
|
|
157
|
+
if (withProject) columns.push({ flex: true });
|
|
158
|
+
return table(term, columns, [heads, ...rows.map((row) => rowOf(row))]);
|
|
159
|
+
};
|
|
160
|
+
/** Marks are made when used, so `--plain` (set after load) is read. */
|
|
161
|
+
const STATE_MARK = {
|
|
162
|
+
waiting: () => style("dim", "·"),
|
|
163
|
+
running: () => style("cyan", "●"),
|
|
164
|
+
ok: () => style("green", "✓"),
|
|
165
|
+
failed: () => style("red", "✗"),
|
|
166
|
+
skipped: () => style("dim", "-")
|
|
167
|
+
};
|
|
168
|
+
/** `950`, `12.3k`, `1.2M`. */
|
|
169
|
+
const count = (n) => {
|
|
170
|
+
if (n < 1e3) return String(n);
|
|
171
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
172
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
173
|
+
};
|
|
174
|
+
const stateText = (node) => {
|
|
175
|
+
if (node.state === "running") return node.runs > 1 ? `running (round ${String(node.runs)})` : "running";
|
|
176
|
+
if (node.state === "ok" || node.state === "failed") {
|
|
177
|
+
const verdict = nodeVerdict(node.output ?? {}, node.state === "ok");
|
|
178
|
+
const line = verdict.length > 60 ? `${verdict.slice(0, 59)}…` : verdict;
|
|
179
|
+
return node.runs > 1 ? `${line} (${String(node.runs)} runs)` : line;
|
|
180
|
+
}
|
|
181
|
+
return node.state;
|
|
182
|
+
};
|
|
183
|
+
/** The ownership tree, one line per node, children under their owner. */
|
|
184
|
+
const formatTree = (roots, now = Date.now()) => {
|
|
185
|
+
const lines = [];
|
|
186
|
+
const walk = (node, lead, branch) => {
|
|
187
|
+
lines.push({
|
|
188
|
+
label: `${lead}${branch}${node.id}`,
|
|
189
|
+
node
|
|
190
|
+
});
|
|
191
|
+
const next = lead + (branch === "├─ " ? "│ " : branch === "" ? "" : " ");
|
|
192
|
+
node.children.forEach((child, index) => {
|
|
193
|
+
walk(child, next, index === node.children.length - 1 ? "└─ " : "├─ ");
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
for (const root of roots) walk(root, "", "");
|
|
197
|
+
const label = Math.max(...lines.map((l) => l.label.length));
|
|
198
|
+
const type = Math.max(...lines.map((l) => l.node.type.length));
|
|
199
|
+
return lines.map(({ label: text, node }) => {
|
|
200
|
+
const usage = node.inputTokens + node.outputTokens === 0 ? "" : style("dim", ` ${count(node.inputTokens)} in / ${count(node.outputTokens)} out · ${cost(node.costUsd)}`);
|
|
201
|
+
const state = node.held === true ? `${style("yellow", "‖")} paused` : `${STATE_MARK[node.state]()} ${stateText(node)}`;
|
|
202
|
+
const spent = isItem(node) && node.startedAt !== void 0 ? style("dim", ` ${duration((node.finishedAt === void 0 ? now : Date.parse(node.finishedAt)) - Date.parse(node.startedAt))}`) : "";
|
|
203
|
+
return `${text.padEnd(label)} ${style("dim", node.type.padEnd(type))} ${state}${spent}${usage}`;
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
export { header as a, listedStatus as i, formatRuns as n, table as o, formatTree as r, ago as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { p as runMarkerIn } from "./src-
|
|
1
|
+
import { p as runMarkerIn } from "./src-BfxkJOYm.mjs";
|
|
2
2
|
// src/commands/in-a-run.ts
|
|
3
3
|
/**
|
|
4
4
|
* @file The commands that act as the user refuse a program or an agent in a run
|
|
@@ -19,4 +19,6 @@ const decideRefusal = (env = process.env) => refusal("`ork decide` answers as yo
|
|
|
19
19
|
const continueRefusal = (env = process.env) => refusal("`ork continue` undoes a pause you set, so a program or an agent in a run cannot use it.", env);
|
|
20
20
|
/** Whether `ork ui` may print its sign-in link, which acts as the user. */
|
|
21
21
|
const mayShowSignIn = (env = process.env) => runMarkerIn(env) === null;
|
|
22
|
-
|
|
22
|
+
/** Why `ork attach` will not answer here, or `null` when it may. */
|
|
23
|
+
const attachRefusal = (env = process.env) => refusal("`ork attach` answers as you, so a program or an agent in a run cannot use it; `ork logs` still shows the run.", env);
|
|
24
|
+
export { decideRefusal as a, continueRefusal as i, attachRefusal as n, mayShowSignIn as o, chatRefusal as r, acceptRefusal as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { it as limitsReport, nt as NOT_STARTED, r as capsHere, rt as limitsNow } from "./src-CdDTQLdQ.mjs";
|
|
2
2
|
// src/run/limits.ts
|
|
3
3
|
/**
|
|
4
4
|
* @file The limits across runs that apply here (RFC-007): the user's settings
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as ORK_VERSION } from "./__build_info__-
|
|
3
|
-
import { p as runMarkerIn } from "./src-
|
|
4
|
-
import { n as explainNode } from "./context-
|
|
5
|
-
import { a as openMcp, c as refused, o as tool, s as answer } from "./src-
|
|
1
|
+
import { u as isNewer } from "./src-CdDTQLdQ.mjs";
|
|
2
|
+
import { n as ORK_VERSION } from "./__build_info__-BJbE3Zvp.mjs";
|
|
3
|
+
import { p as runMarkerIn } from "./src-BfxkJOYm.mjs";
|
|
4
|
+
import { n as explainNode } from "./context-BAwgVSX5.mjs";
|
|
5
|
+
import { a as openMcp, c as refused, o as tool, s as answer } from "./src-S9yK2OHU.mjs";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -43,7 +43,7 @@ const orkMcpServer = (options = {}) => {
|
|
|
43
43
|
...options.script === void 0 ? {} : { script: options.script }
|
|
44
44
|
});
|
|
45
45
|
const all = [...opened.tools, explainTool(opened, options.home)];
|
|
46
|
-
const tools = options.expects !== void 0 && isNewer(options.expects, "1.0.0-alpha.
|
|
46
|
+
const tools = options.expects !== void 0 && isNewer(options.expects, "1.0.0-alpha.12") ? tooOld(all, options.expects) : all;
|
|
47
47
|
const server = new McpServer({
|
|
48
48
|
name: "ork",
|
|
49
49
|
version: ORK_VERSION
|