@krapht/ork 1.0.0-alpha.13 → 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.
Files changed (42) hide show
  1. package/dist/{__build_info__-Da73_nBs.mjs → __build_info__-B82-dGJY.mjs} +2 -2
  2. package/dist/{attach-E6NNyA3T.mjs → attach-CdtGX9se.mjs} +5 -5
  3. package/dist/bin.mjs +194 -215
  4. package/dist/{builtin-files-n6o6oWpB.mjs → builtin-files-Bdq23IIi.mjs} +1 -1
  5. package/dist/{chips-CyeB_rhR.mjs → chips-BqcT58qr.mjs} +1 -1
  6. package/dist/{completion-SNNNxnv9.mjs → completion--ywde-56.mjs} +52 -11
  7. package/dist/{context-DHudLA5e.mjs → context-Y_I4Mofq.mjs} +17 -7
  8. package/dist/{find-CjsNYAAf.mjs → find-BVX-bL4u.mjs} +1 -1
  9. package/dist/{format-C60TFpRe.mjs → format-CvTE5CZQ.mjs} +12 -12
  10. package/dist/{help-groups-CyfPWlST.mjs → help-groups-CpR2UzSn.mjs} +16 -6
  11. package/dist/{in-a-run-BYjTXaST.mjs → in-a-run-cL5N9gpH.mjs} +1 -1
  12. package/dist/{limits-C5QKZNLT.mjs → limits-Dhe--wmX.mjs} +1 -1
  13. package/dist/{mcp-bcctR-wc.mjs → mcp-CsmboyXv.mjs} +6 -6
  14. package/dist/{once-DPQu5Q3H.mjs → once-CrwI-ZdN.mjs} +4 -4
  15. package/dist/{output-CnRzrbUM.mjs → output-B1kwo0YU.mjs} +17 -1
  16. package/dist/{pause-BPvlDIvz.mjs → pause-DssrYcda.mjs} +4 -4
  17. package/dist/{relay-C8W0t_zc.mjs → relay-DASRgsTQ.mjs} +2 -2
  18. package/dist/{run-CQIfq918.mjs → run-D8divGCs.mjs} +1 -1
  19. package/dist/send-CXv8bx0i.mjs +105 -0
  20. package/dist/{src-CGJGL1sZ.mjs → src-8Mul0695.mjs} +8 -10
  21. package/dist/{src-D93tHZ5B.mjs → src-C7z_6fhn.mjs} +92 -39
  22. package/dist/{src-CqRqsb2t.mjs → src-njdtejgZ.mjs} +98 -33
  23. package/dist/{src-BeR6f70A.mjs → src-tsuZRu0H.mjs} +2353 -918
  24. package/dist/{store-CM3cERGl.mjs → store-CleF7KeS.mjs} +21 -73
  25. package/dist/ui/assets/app-D_nAPnHM.css +1 -0
  26. package/dist/ui/assets/{app-DYRC0V4p.js → app-DqBAtXSZ.js} +19 -19
  27. package/dist/ui/assets/{index-CWwm8HTG.js → index-D-_uPI2v.js} +2 -2
  28. package/dist/ui/index.html +1 -1
  29. package/dist/{ui-D2Ydofq0.mjs → ui-CNO1M0qT.mjs} +4 -4
  30. package/dist/{usage-6WIowblz.mjs → usage-BVXi0iFY.mjs} +13 -141
  31. package/dist/{verdict-CIy8tAyX.mjs → verdict-CMvPCpWC.mjs} +2 -2
  32. package/dist/{watch-uOU_WeBI.mjs → watch-DVNIciHp.mjs} +10 -8
  33. package/dist/{workflows-7tQdMnrA.mjs → workflows-B30QkwTk.mjs} +3 -3
  34. package/dist/{worktrees-ZCII298F.mjs → worktrees-DD4_TpkH.mjs} +3 -5
  35. package/package.json +2 -2
  36. package/dist/clean-Bh4KZgzc.mjs +0 -91
  37. package/dist/decide-DuIHACvH.mjs +0 -50
  38. package/dist/list-BUb5Uc3H.mjs +0 -117
  39. package/dist/remove-BkFWGVYo.mjs +0 -201
  40. package/dist/report-CEN8VoUb.mjs +0 -140
  41. package/dist/send-CaZlGG5a.mjs +0 -163
  42. package/dist/ui/assets/app-QoHVi-mb.css +0 -1
@@ -1,10 +1,9 @@
1
- import { Hn as placeFiles, Nr as AGENT_DRIVERS, Sr as NodeIdSchema, T as storePath, Un as placeFor, _t as liveStatus, w as openStore } from "./src-BeR6f70A.mjs";
2
- import { a as isBuiltinArg, i as builtinWorkflowText, r as builtinWorkflowNames } from "./builtin-files-n6o6oWpB.mjs";
3
- import { n as pendingDecisions } from "./decide-DuIHACvH.mjs";
4
- import { t as findRun } from "./find-CjsNYAAf.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-CyfPWlST.mjs";
6
- import { s as writeErr } from "./output-CnRzrbUM.mjs";
7
- import { a as resolveWorkflowArg, n as WORKFLOW_SUFFIX } from "./workflows-7tQdMnrA.mjs";
1
+ import { U as openStore, Ut as liveStatus, W as storePath, ii as AGENT_DRIVERS, mr as placeFor, pr as placeFiles, qr as NodeIdSchema, ut as pendingDecisions } from "./src-tsuZRu0H.mjs";
2
+ import { a as isBuiltinArg, i as builtinWorkflowText, r as builtinWorkflowNames } from "./builtin-files-Bdq23IIi.mjs";
3
+ import { t as findRun } from "./find-BVX-bL4u.mjs";
4
+ 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-CpR2UzSn.mjs";
5
+ import { l as writeErr } from "./output-B1kwo0YU.mjs";
6
+ import { a as resolveWorkflowArg, n as WORKFLOW_SUFFIX } from "./workflows-B30QkwTk.mjs";
8
7
  import path from "node:path";
9
8
  import { parse } from "yaml";
10
9
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
@@ -40,16 +39,45 @@ const workflowText = (arg, cwd, place) => {
40
39
  const file = path.resolve(cwd, resolveWorkflowArg(arg, cwd, placeFiles(place).workflows));
41
40
  return existsSync(file) && statSync(file).isFile() ? readFileSync(file, "utf8") : void 0;
42
41
  };
42
+ /** A mapping's entries, or none when `value` is not an object. */
43
+ const entriesOf = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? Object.entries(value) : [];
44
+ /** One top-level field of a workflow's text, read without validating it. */
45
+ const fieldOf = (text, field) => {
46
+ const parsed = text === void 0 ? void 0 : parse(text);
47
+ return Object.fromEntries(entriesOf(parsed))[field];
48
+ };
43
49
  /** The node ids of the workflow `arg` names; none when it can't be read. */
44
50
  const workflowNodes = (arg, cwd, place) => {
45
- const text = workflowText(arg, cwd, place);
46
- const parsed = text === void 0 ? void 0 : parse(text);
47
- const nodes = parsed !== null && typeof parsed === "object" && "nodes" in parsed ? parsed.nodes : void 0;
48
- return (nodes !== null && typeof nodes === "object" ? Object.keys(nodes) : []).filter((key) => NodeIdSchema.safeParse(key).success).map((value) => ({
51
+ return entriesOf(fieldOf(workflowText(arg, cwd, place), "nodes")).map(([key]) => key).filter((key) => NodeIdSchema.safeParse(key).success).map((value) => ({
49
52
  value,
50
53
  description: arg
51
54
  }));
52
55
  };
56
+ /** What a menu says of an input: its description, else its type. */
57
+ const inputDescription = (definition) => {
58
+ const fields = Object.fromEntries(entriesOf(definition));
59
+ const said = fields["description"] ?? fields["type"];
60
+ const what = typeof said === "string" ? said : "";
61
+ return fields["required"] === true && !("default" in fields) ? `${what} (required)` : what;
62
+ };
63
+ /**
64
+ * `name=` for each input a workflow's text declares, for `--input`; a name that
65
+ * isn't a valid id is left out, as a node's is.
66
+ */
67
+ const inputsOf = (text, workflow) => entriesOf(fieldOf(text, "inputs")).filter(([name]) => NodeIdSchema.safeParse(name).success).map(([name, definition]) => ({
68
+ value: `${name}=`,
69
+ description: inputDescription(definition) || workflow
70
+ }));
71
+ /** The inputs of the workflow `arg` names; none when it can't be read. */
72
+ const workflowInputs = (arg, cwd, place) => inputsOf(workflowText(arg, cwd, place), arg);
73
+ /** The inputs of the run `arg` names (else the project's newest run). */
74
+ const runInputs = (store, arg, cwd) => {
75
+ const found = findRun(store, arg, cwd);
76
+ if (!found.ok) return [];
77
+ const { file, workflow } = found.run;
78
+ const text = existsSync(file) && statSync(file).isFile() ? readFileSync(file, "utf8") : void 0;
79
+ return inputsOf(text, workflow);
80
+ };
53
81
  /**
54
82
  * Runs whose id starts with `prefix`, newest first: the project's, else any
55
83
  * project's, at most `RUN_LIMIT`.
@@ -112,6 +140,18 @@ const nodes = {
112
140
  return withStore(context, (store) => runNodes(store, context.given["run"], context.cwd));
113
141
  }
114
142
  };
143
+ /**
144
+ * `name=` for each input, for `--input`: the workflow given's when the command
145
+ * takes a workflow (none before it is), else the run given's (`ork resume`).
146
+ */
147
+ const inputs = {
148
+ group: "inputs",
149
+ values: (context) => {
150
+ const workflow = context.given["workflow"];
151
+ if (context.positionals.includes("workflow")) return workflow === void 0 ? [] : workflowInputs(workflow, context.cwd, placeOf(context.cwd, context.store()));
152
+ return withStore(context, (store) => runInputs(store, context.given["run"], context.cwd));
153
+ }
154
+ };
115
155
  const decisions = {
116
156
  group: "decisions",
117
157
  values: (context) => withStore(context, (store) => decisionCandidates(store, context.given["run"], context.cwd, placeOf(context.cwd, store)))
@@ -144,6 +184,7 @@ const VALUE_PROVIDERS = {
144
184
  files: true
145
185
  },
146
186
  node: nodes,
187
+ input: inputs,
147
188
  "decide id": decisions,
148
189
  "completion shell": shells,
149
190
  driver: drivers,
@@ -1,8 +1,8 @@
1
- import { Ar as readyDriver, Cr as retiredDriverHint, Fr as firstLine, Hn as placeFiles, Ir as EXPERIMENTS, Lr as experimentsOn, N as driverQueues, Nr as AGENT_DRIVERS, Pr as DRIVER_IDS, Rr as knownExperiments, T as storePath, Tr as INTEGRATIONS, Un as placeFor, Ut as namingNoDriver, Xn as LESSON_CAP_TOKENS, Yt as loadProject, dt as walkChecks, ft as walkSummary, j as driverRefusals, kr as driverChecks, m as triggersReport, ot as explainSession, p as lateTriggers, qn as workflowDirOf, ut as checkWorkflowText, v as readProjectTriggers, w as openStore, wn as socketRoom, xr as DriverSchema, y as workflowTextHash } from "./src-BeR6f70A.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__-Da73_nBs.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-7tQdMnrA.mjs";
1
+ import { It as checkWorkflowText, Jr as retiredDriverHint, Kr as DriverSchema, L as readProjectTriggers, Lt as walkChecks, M as lateTriggers, Mt as explainSession, N as triggersReport, R as workflowTextHash, Rt as walkSummary, U as openStore, W as storePath, Xn as socketRoom, Xr as INTEGRATIONS, ai as DRIVER_IDS, ci as experimentsOn, ei as driverChecks, et as budgetWarnings, hn as namingNoDriver, ii as AGENT_DRIVERS, li as knownExperiments, mr as placeFor, oi as firstLine, pr as placeFiles, rt as driverQueues, si as EXPERIMENTS, ti as readyDriver, tt as driverRefusals, vr as workflowDirOf, xn as loadProject, xr as LESSON_CAP_TOKENS } from "./src-tsuZRu0H.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__-B82-dGJY.mjs";
3
+ import { C as termOf, D as wrap, E as widthOf, a as plain, c as write, h as paint, l as writeErr, s as style, w as cut, x as plainEnv } from "./output-B1kwo0YU.mjs";
4
+ import { n as chip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
5
+ import { c as registeredProjects, i as refusedBuiltin, o as workflowArg, r as findWorkflowFiles, s as projectAt } from "./workflows-B30QkwTk.mjs";
6
6
  import path from "node:path";
7
7
  import { readFileSync } from "node:fs";
8
8
  import { execFile, spawn } from "node:child_process";
@@ -356,6 +356,12 @@ const runReadyDriver = async (workflow, options) => {
356
356
  * (`drivers` default: the real descriptors; tests pass their own).
357
357
  */
358
358
  const unfitLines = (workflow, drivers, choice) => driverRefusals(workflow, drivers ?? AGENT_DRIVERS, choice).map(({ message }) => message);
359
+ /**
360
+ * What a dollar budget can't see on a session node's driver, one line each
361
+ * (RFC-015): warnings, never a reason to refuse. Same arguments as
362
+ * `unfitLines`.
363
+ */
364
+ const budgetWarningLines = (workflow, drivers, choice) => budgetWarnings(workflow, drivers ?? AGENT_DRIVERS, choice).map(({ message }) => message);
359
365
  // src/run/driver-check.ts
360
366
  /**
361
367
  * @file `ork validate`'s driver check: each session node against what its
@@ -384,7 +390,11 @@ const driverDiagnostics = async (workflow, options) => {
384
390
  }
385
391
  return found;
386
392
  };
387
- return [...driverRefusals(workflow, drivers, choice).map(({ node, message }) => at(node, "error", "driver.unfit", message)), ...driverQueues(workflow, drivers, choice).filter((found) => found.owner === void 0).flatMap(({ nodes, message }) => nodes.slice(0, 1).map((node) => at(node, "warning", "driver.queues", message)))];
393
+ return [
394
+ ...driverRefusals(workflow, drivers, choice).map(({ node, message }) => at(node, "error", "driver.unfit", message)),
395
+ ...budgetWarnings(workflow, drivers, choice).map(({ node, message }) => at(node, "warning", "driver.budget", message)),
396
+ ...driverQueues(workflow, drivers, choice).filter((found) => found.owner === void 0).flatMap(({ nodes, message }) => nodes.slice(0, 1).map((node) => at(node, "warning", "driver.queues", message)))
397
+ ];
388
398
  };
389
399
  /** The `--driver` value, or why it is not a driver. */
390
400
  const driverArg = (value) => {
@@ -692,4 +702,4 @@ const context = defineCommand({
692
702
  },
693
703
  subCommands: { explain }
694
704
  });
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 };
705
+ export { showUpdateNotice as C, runUpdateChild as S, updateCheckOff as T, orkCheck as _, validateFile as a, triggerChecks as b, warningLines as c, chooseReadyDriver as d, runReadyDriver as f, headWarning as g, experimentsCheck as h, validate as i, budgetWarningLines as l, exec as m, explainNode as n, walkLoaded as o, unfitLines as p, loadWorkflow as r, formatReport as s, context as t, checksHere as u, runChecks as v, startUpdateCheck as w, UPDATE_CHILD_ENV as x, socketCheck as y };
@@ -1,4 +1,4 @@
1
- import { Un as placeFor } from "./src-BeR6f70A.mjs";
1
+ import { mr as placeFor } from "./src-tsuZRu0H.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  // ../core/src/remote/find.ts
4
4
  /**
@@ -1,7 +1,7 @@
1
- import { Tt as isItem, _t as liveStatus, xt as slotWaitsOf, yt as runStatus } from "./src-BeR6f70A.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";
1
+ import { Kt as runStatus, Ut as liveStatus, Wt as lockWaitsOf, Zt as isItem, nn as lockWaitLine, qt as slotWaitsOf } from "./src-tsuZRu0H.mjs";
2
+ import { C as termOf, E as widthOf, n as cost, o as shortCount, r as costOf, s as style, w as cut } from "./output-B1kwo0YU.mjs";
3
+ import { i as statusChip, n as chip } from "./chips-BqcT58qr.mjs";
4
+ import { n as nodeVerdict } from "./verdict-CMvPCpWC.mjs";
5
5
  // src/term/table.ts
6
6
  /**
7
7
  * @file Aligned columns for the listing commands: each column as wide as its
@@ -85,13 +85,17 @@ const duration = (ms) => {
85
85
  };
86
86
  const dim = (s) => style("dim", s);
87
87
  /**
88
- * A run's status as `ork ps` reads it: `waiting for slot` for a running run
88
+ * A run's status as `ork ps` reads it: for a running run, `waiting for <lock>,
89
+ * held by <run>/<node>` with a node waiting for a lock, or `waiting for slot`
89
90
  * with a command waiting for a machine-wide slot; `events` are a running
90
91
  * run's.
91
92
  */
92
93
  const listedStatus = (run, events) => {
93
94
  const status = runStatus(run, events);
94
- return status === "running" && slotWaitsOf(events).length > 0 ? "waiting for slot" : status;
95
+ if (status !== "running") return status;
96
+ const [lock] = lockWaitsOf(events);
97
+ if (lock !== void 0) return lockWaitLine(lock.lock, lock.holders);
98
+ return slotWaitsOf(events).length > 0 ? "waiting for slot" : status;
95
99
  };
96
100
  /**
97
101
  * The `ork ps` table; `withProject` adds each run's project. A called run's
@@ -107,7 +111,7 @@ const formatRuns = (runs, withProject, now = Date.now(), statusOf = liveStatus,
107
111
  workflow: run.workflow,
108
112
  status,
109
113
  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}`,
114
+ cost: run.parent === void 0 ? costOf(run.costUsd, run.partial, run.tokens) : `${costOf(run.costUsd, run.partial, run.tokens)} in ${run.parent}`,
111
115
  called: run.parent !== void 0,
112
116
  project: run.project
113
117
  };
@@ -166,11 +170,7 @@ const STATE_MARK = {
166
170
  skipped: () => style("dim", "-")
167
171
  };
168
172
  /** `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
- };
173
+ const count = shortCount;
174
174
  const stateText = (node) => {
175
175
  if (node.state === "running") return node.runs > 1 ? `running (round ${String(node.runs)})` : "running";
176
176
  if (node.state === "ok" || node.state === "failed") {
@@ -4,7 +4,9 @@
4
4
  * shell. Each is thin: it runs `ork __complete -- <words…>` with the word
5
5
  * under the cursor last, and offers the lines it prints, `value<TAB>
6
6
  * description`. A line `:group <title>` starts a group (zsh labels the menu
7
- * with it); `:files` asks for file names too. A new shell is one more entry.
7
+ * with it); `:files` asks for file names too. A value ending in `=` (an
8
+ * input's `name=`) takes no space after it, so its value is typed next. A new
9
+ * shell is one more entry.
8
10
  */
9
11
  /** The hidden command the scripts run. */
10
12
  const COMPLETE_COMMAND = "__complete";
@@ -15,9 +17,11 @@ const SHELL_SCRIPTS = {
15
17
  # (ork completion zsh > ~/.zsh/completions/_ork), or source it.
16
18
 
17
19
  _ork() {
18
- local -a lines cands
20
+ local -a lines cands opens
19
21
  local line group=commands files=0 n=0 ret=1
20
22
  lines=("\${(@f)$("\${words[1]}" ${COMPLETE_COMMAND} -- "\${(@)words[2,CURRENT]}" 2>/dev/null)}")
23
+ # A last group line offers what the last group gathered.
24
+ lines+=(":group end")
21
25
  for line in "\${lines[@]}"; do
22
26
  case $line in
23
27
  (:files) files=1 ;;
@@ -25,15 +29,17 @@ _ork() {
25
29
  if (( \${#cands} )); then
26
30
  _describe -V -t "ork-$(( ++n ))" "$group" cands && ret=0
27
31
  fi
28
- cands=()
32
+ # name= is followed by its value, not a space.
33
+ if (( \${#opens} )); then
34
+ _describe -V -t "ork-$(( ++n ))" "$group" opens -S '' && ret=0
35
+ fi
36
+ cands=() opens=()
29
37
  group=\${line#:group }
30
38
  ;;
39
+ (*=$'\\t'*) opens+=("\${\${line%%$'\\t'*}//:/\\\\:}:\${line#*$'\\t'}") ;;
31
40
  (?*) cands+=("\${\${line%%$'\\t'*}//:/\\\\:}:\${line#*$'\\t'}") ;;
32
41
  esac
33
42
  done
34
- if (( \${#cands} )); then
35
- _describe -V -t "ork-$(( ++n ))" "$group" cands && ret=0
36
- fi
37
43
  if (( files )); then
38
44
  _files && ret=0
39
45
  fi
@@ -71,6 +77,10 @@ _ork() {
71
77
  *)
72
78
  line="\${line%%$'\\t'*}"
73
79
  COMPREPLY+=("\${line#"$strip"}")
80
+ # name= is followed by its value, not a space (bash 4 and later).
81
+ if [[ "$line" == *= ]] && type compopt &>/dev/null; then
82
+ compopt -o nospace
83
+ fi
74
84
  ;;
75
85
  esac
76
86
  done <<< "$out"
@@ -1,4 +1,4 @@
1
- import { p as runMarkerIn } from "./src-D93tHZ5B.mjs";
1
+ import { p as runMarkerIn } from "./src-C7z_6fhn.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
@@ -1,4 +1,4 @@
1
- import { et as NOT_STARTED, i as capsHere, nt as limitsReport, tt as limitsNow } from "./src-BeR6f70A.mjs";
1
+ import { C as capsHere, Dt as limitsNow, Et as NOT_STARTED, Ot as limitsReport } from "./src-tsuZRu0H.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 { d as isNewer } from "./src-BeR6f70A.mjs";
2
- import { n as ORK_VERSION } from "./__build_info__-Da73_nBs.mjs";
3
- import { p as runMarkerIn } from "./src-D93tHZ5B.mjs";
4
- import { n as explainNode } from "./context-DHudLA5e.mjs";
5
- import { a as openMcp, c as refused, o as tool, s as answer } from "./src-CGJGL1sZ.mjs";
1
+ import { A as isNewer } from "./src-tsuZRu0H.mjs";
2
+ import { n as ORK_VERSION } from "./__build_info__-B82-dGJY.mjs";
3
+ import { p as runMarkerIn } from "./src-C7z_6fhn.mjs";
4
+ import { n as explainNode } from "./context-Y_I4Mofq.mjs";
5
+ import { a as openMcp, c as refused, o as tool, s as answer } from "./src-8Mul0695.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.13") ? tooOld(all, options.expects) : all;
46
+ const tools = options.expects !== void 0 && isNewer(options.expects, "1.0.0-alpha.14") ? tooOld(all, options.expects) : all;
47
47
  const server = new McpServer({
48
48
  name: "ork",
49
49
  version: ORK_VERSION
@@ -1,7 +1,7 @@
1
- import "./src-BeR6f70A.mjs";
2
- import { t as runOnce } from "./run-CQIfq918.mjs";
3
- import { a as style, o as write, s as writeErr } from "./output-CnRzrbUM.mjs";
4
- import { t as ago } from "./format-C60TFpRe.mjs";
1
+ import "./src-tsuZRu0H.mjs";
2
+ import { t as runOnce } from "./run-D8divGCs.mjs";
3
+ import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
4
+ import { t as ago } from "./format-CvTE5CZQ.mjs";
5
5
  import { spawn } from "node:child_process";
6
6
  import { defineCommand, parseArgs } from "citty";
7
7
  // src/commands/once.ts
@@ -412,6 +412,22 @@ const detachHint = (id) => `ork attach ${id} · ork logs ${id} -f · ork tree ${
412
412
  /** What a run spent: `$0.0312`, or `$0.00` for nothing. */
413
413
  const cost = (usd) => usd === 0 ? "$0.00" : `$${usd.toFixed(4)}`;
414
414
  /**
415
+ * A dollar total that misses sessions on a driver with no dollars (RFC-015),
416
+ * said so, with the counted tokens beside it: `$1.2000 (partial) · 3.0k
417
+ * tokens`. A complete total reads as `cost` does.
418
+ */
419
+ const costOf = (usd, partial, tokens) => {
420
+ if (partial !== true) return cost(usd);
421
+ const units = tokens === void 0 ? "" : ` · ${shortCount(tokens)} tokens`;
422
+ return `${cost(usd)} (partial)${units}`;
423
+ };
424
+ /** `950`, `12.3k`, `1.2M`. */
425
+ const shortCount = (n) => {
426
+ if (n < 1e3) return String(n);
427
+ if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
428
+ return `${(n / 1e6).toFixed(1)}M`;
429
+ };
430
+ /**
415
431
  * Asks a yes-or-no question on the terminal (stderr), through the kit's confirm
416
432
  * prompt; anything but yes is no. A trailing `[y/N]` in `question` is dropped:
417
433
  * the prompt adds its own.
@@ -420,4 +436,4 @@ const confirm = (question) => confirm$1({
420
436
  input: process.stdin,
421
437
  output: process.stderr
422
438
  }, { question: question.replace(/\s*\[y\/N\]\s*$/u, "") });
423
- export { hang as C, readKeys as E, cut as S, wrap as T, withdrawn as _, style as a, takePlainFlag as b, confirmOrStop as c, apply as d, bold as f, readLine as g, interrupt as h, plain as i, CHIP as l, createRegion as m, cost as n, write as o, paint as p, detachHint as r, writeErr as s, confirm as t, NODE_PALETTE as u, canKey as v, widthOf as w, termOf as x, plainEnv as y };
439
+ export { termOf as C, wrap as D, widthOf as E, readKeys as O, takePlainFlag as S, hang as T, interrupt as _, plain as a, canKey as b, write as c, CHIP as d, NODE_PALETTE as f, createRegion as g, paint as h, detachHint as i, writeErr as l, bold as m, cost as n, shortCount as o, apply as p, costOf as r, style as s, confirm as t, confirmOrStop as u, readLine as v, cut as w, plainEnv as x, withdrawn as y };
@@ -1,7 +1,7 @@
1
- import { U as requestContinue, W as requestPause, w as openStore } from "./src-BeR6f70A.mjs";
2
- import { t as findRun } from "./find-CjsNYAAf.mjs";
3
- import { a as style, o as write, s as writeErr } from "./output-CnRzrbUM.mjs";
4
- import { i as continueRefusal } from "./in-a-run-BYjTXaST.mjs";
1
+ import { U as openStore, _t as requestPause, gt as requestContinue } from "./src-tsuZRu0H.mjs";
2
+ import { t as findRun } from "./find-BVX-bL4u.mjs";
3
+ import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
4
+ import { i as continueRefusal } from "./in-a-run-cL5N9gpH.mjs";
5
5
  import { defineCommand } from "citty";
6
6
  // src/commands/pause.ts
7
7
  /**
@@ -1,5 +1,5 @@
1
- import { F as addressOf, R as linkNodes, V as unlinkNodes, w as openStore } from "./src-BeR6f70A.mjs";
2
- import { a as style, o as write, s as writeErr } from "./output-CnRzrbUM.mjs";
1
+ import { U as openStore, ft as addressOf, ht as unlinkNodes, mt as linkNodes } from "./src-tsuZRu0H.mjs";
2
+ import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  // src/commands/relay.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { Rt as git, zt as gitOk } from "./src-BeR6f70A.mjs";
1
+ import { dn as git, fn as gitOk } from "./src-tsuZRu0H.mjs";
2
2
  import path from "node:path";
3
3
  import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { createHash, randomUUID } from "node:crypto";
@@ -0,0 +1,105 @@
1
+ import { U as openStore, at as scriptRefusal, it as TOO_LONG, ot as sendFromScript } from "./src-tsuZRu0H.mjs";
2
+ import { l as writeErr } from "./output-B1kwo0YU.mjs";
3
+ import { u as inheritedScrubber } from "./src-C7z_6fhn.mjs";
4
+ import { defineCommand } from "citty";
5
+ // src/commands/send.ts
6
+ /**
7
+ * @file `ork send` (RFC-005): a program in a tool node writes to a session on
8
+ * its run's bus. It prints nothing when it works, as what a program prints is
9
+ * its node's output, and says why on stderr, with exit 1, when it is refused:
10
+ * before reading a message it could not send, and for anything wrong with the
11
+ * command itself, which would otherwise go to stdout as usage.
12
+ */
13
+ const refuse = (message) => {
14
+ writeErr(message);
15
+ process.exitCode = 1;
16
+ };
17
+ /** Stdin, up to the limit: past it, the rest is not worth holding. */
18
+ const readBounded = async () => {
19
+ const chunks = [];
20
+ let size = 0;
21
+ for await (const chunk of process.stdin) {
22
+ const part = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
23
+ size += part.length;
24
+ if (size > 65536) return null;
25
+ chunks.push(part);
26
+ }
27
+ return Buffer.concat(chunks);
28
+ };
29
+ /** The message, or why it can't go. */
30
+ const bodyOf = async (given) => {
31
+ if (given !== void 0) return { body: given };
32
+ const read = await readBounded();
33
+ if (read === null) return { refused: TOO_LONG };
34
+ try {
35
+ return { body: new TextDecoder("utf-8", { fatal: true }).decode(read) };
36
+ } catch {
37
+ return { refused: "The message is not UTF-8 text." };
38
+ }
39
+ };
40
+ const deliver = async (store, to, given) => {
41
+ const sender = {
42
+ run: process.env["ORK_RUN"],
43
+ node: process.env["ORK_NODE"],
44
+ to
45
+ };
46
+ const refused = scriptRefusal(store, sender);
47
+ if (refused !== null) {
48
+ refuse(refused);
49
+ return;
50
+ }
51
+ const message = await bodyOf(given);
52
+ if ("refused" in message) {
53
+ refuse(message.refused);
54
+ return;
55
+ }
56
+ if (message.body.replaceAll(/[\p{Cc}\s]/gu, "") === "") {
57
+ refuse("The message is empty.");
58
+ return;
59
+ }
60
+ const sent = await sendFromScript(store, {
61
+ ...sender,
62
+ body: inheritedScrubber(process.env)(message.body)
63
+ });
64
+ if (!sent.ok) refuse(sent.error);
65
+ };
66
+ const send = defineCommand({
67
+ meta: {
68
+ name: "send",
69
+ description: "From a tool node's program: write to a session in its run"
70
+ },
71
+ args: {
72
+ to: {
73
+ type: "positional",
74
+ description: "The node to write to: the owner, or a channel",
75
+ required: false
76
+ },
77
+ message: {
78
+ type: "string",
79
+ alias: "m",
80
+ description: "The message"
81
+ },
82
+ stdin: {
83
+ type: "boolean",
84
+ description: "Read the message from stdin",
85
+ default: false
86
+ }
87
+ },
88
+ run: async ({ args }) => {
89
+ if (args.to === void 0 || args._.length !== 1) {
90
+ refuse("Give one node to write to: ork send <to> -m <body>.");
91
+ return;
92
+ }
93
+ if (args.message === void 0 === !args.stdin) {
94
+ refuse("Give the message with -m or --stdin, one of them.");
95
+ return;
96
+ }
97
+ const store = openStore();
98
+ try {
99
+ await deliver(store, args.to, args.message);
100
+ } finally {
101
+ store.close();
102
+ }
103
+ }
104
+ });
105
+ export { send };
@@ -1,11 +1,7 @@
1
- import { $ as followEvents, C as isNodeEvent, Ct as processAlive, Et as nestItems, G as requestStop, Gn as runDirOf, Gt as nodeSays, Hn as placeFiles, J as detachResume, Jn as inside, K as tellLiveRun, Q as detachRun, R as linkNodes, Rn as loadAgents, S as activeTree, T as storePath, U as requestContinue, Un as placeFor, V as unlinkNodes, W as requestPause, Xn as LESSON_CAP_TOKENS, Y as resumable, _t as liveStatus, a as planUpgrade, ar as readDocument, at as explainWorkflowText, c as runningScript, dn as runGh, dt as walkChecks, fn as sendPost, ft as walkSummary, gr as expandEdge, i as capsHere, in as END_KINDS, ir as newWorkflowText, l as detectInstaller, ln as DISCUSSIONS, lr as renderJsonSchema, m as triggersReport, nr as WorkflowEditSchema, nt as limitsReport, o as releaseNotes, pr as EdgeInputSchema, qn as workflowDirOf, rr as applyEdits, s as runningRunIds, tn as endOf, tr as skillsIn, un as planPost, ur as parseWorkflow, ut as checkWorkflowText, vr as NodeSchema, vt as pausedOf, w as openStore, xn as readCondition, yt as runStatus } from "./src-BeR6f70A.mjs";
2
- import { C as feedbackActions, S as placeOf$1, _ as previewPost, a as registryShown, b as acceptItem, c as checkDue, f as readUpdateCache, g as nodeSession, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, o as updateSwitchOff, p as refreshUpdateCache, s as runInstall, u as newerVersion, w as openFixRun, x as lessonPlaceOf, y as recordNote } from "./__build_info__-Da73_nBs.mjs";
3
- import { t as builtinProblem } from "./builtin-files-n6o6oWpB.mjs";
4
- import { n as pendingDecisions, t as answerDecision } from "./decide-DuIHACvH.mjs";
5
- import { n as newRunId, t as findRun } from "./find-CjsNYAAf.mjs";
6
- import { n as usageReport } from "./report-CEN8VoUb.mjs";
7
- import { a as planClean, i as keyOf, o as stepActs, r as cleanStep, s as stepPrunes, t as applyClean } from "./clean-Bh4KZgzc.mjs";
8
- import { a as readWorktrees, c as mergeStateOf, d as stateParts, i as projectHead, l as planLine, n as lostWork, r as planRemove, s as labelOf, t as applyRemove, u as removeRefusal } from "./remove-BkFWGVYo.mjs";
1
+ import { An as END_KINDS, Ar as readDocument, C as capsHere, D as runningScript, Dn as endOf, Dr as WorkflowEditSchema, E as runningRunIds, Er as skillsIn, Fn as DISCUSSIONS, Fr as parseWorkflow, Gt as pausedOf, H as isNodeEvent, In as planPost, It as checkWorkflowText, Kt as runStatus, Ln as runGh, Lt as walkChecks, N as triggersReport, O as detectInstaller, Or as applyEdits, Ot as limitsReport, Pr as renderJsonSchema, Qt as nestItems, Rn as sendPost, Rr as EdgeInputSchema, Rt as walkSummary, S as usageReport, St as resumable, T as releaseNotes, Tt as followEvents, U as openStore, Ur as NodeSchema, Ut as liveStatus, V as activeTree, Vr as expandEdge, W as storePath, Yt as processAlive, _ as keyOf, _n as nodeSays, _t as requestPause, a as planRemove, b as stepPrunes, d as planLine, f as removeRefusal, g as cleanStep, gr as runDirOf, gt as requestContinue, h as applyClean, ht as unlinkNodes, i as lostWork, jt as explainWorkflowText, kr as newWorkflowText, l as labelOf, lr as loadAgents, lt as answerDecision, mr as placeFor, mt as linkNodes, o as projectHead, p as stateParts, pr as placeFiles, qn as readCondition, r as applyRemove, s as readWorktrees, u as mergeStateOf, ut as pendingDecisions, v as planClean, vr as workflowDirOf, vt as requestStop, w as planUpgrade, wt as detachRun, xr as LESSON_CAP_TOKENS, xt as detachResume, y as stepActs, yr as inside, yt as tellLiveRun } from "./src-tsuZRu0H.mjs";
2
+ import { C as feedbackActions, S as placeOf$1, _ as previewPost, a as registryShown, b as acceptItem, c as checkDue, f as readUpdateCache, g as nodeSession, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, o as updateSwitchOff, p as refreshUpdateCache, s as runInstall, u as newerVersion, w as openFixRun, x as lessonPlaceOf, y as recordNote } from "./__build_info__-B82-dGJY.mjs";
3
+ import { t as builtinProblem } from "./builtin-files-Bdq23IIi.mjs";
4
+ import { n as newRunId, t as findRun } from "./find-BVX-bL4u.mjs";
9
5
  import path from "node:path";
10
6
  import { z } from "zod";
11
7
  import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
@@ -448,7 +444,8 @@ const workflowGraph = (workflow) => ({
448
444
  maxRounds
449
445
  })) : [];
450
446
  }),
451
- channels: (workflow.messages ?? []).map(({ between: [a, b] }) => [a, b])
447
+ channels: (workflow.messages ?? []).map(({ between: [a, b] }) => [a, b]),
448
+ ...workflow.limits?.budgetTokens === void 0 ? {} : { budgetTokens: workflow.limits.budgetTokens }
452
449
  });
453
450
  /** The graph of a workflow file, or `null` if it is gone or does not parse. */
454
451
  const readWorkflowGraph = (file) => {
@@ -475,7 +472,8 @@ const runGraph = (events, file) => {
475
472
  })),
476
473
  edges: edges ?? onFile?.edges ?? [],
477
474
  channels: channels ?? onFile?.channels ?? [],
478
- ...started?.type === "run.started" && started.budgetUsd !== void 0 ? { budgetUsd: started.budgetUsd } : {}
475
+ ...started?.type === "run.started" && started.budgetUsd !== void 0 ? { budgetUsd: started.budgetUsd } : {},
476
+ ...onFile?.budgetTokens === void 0 ? {} : { budgetTokens: onFile.budgetTokens }
479
477
  };
480
478
  };
481
479
  // ../server/src/guards.ts