@krapht/ork 1.0.0-alpha.19 → 1.0.0-alpha.20
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__-dPf4cEGL.mjs → __build_info__-D6mXC4cD.mjs} +2 -2
- package/dist/argument-error-CihH46Le.mjs +27 -0
- package/dist/{attach-BQl8nQz2.mjs → attach-C1OnxyMh.mjs} +7 -5
- package/dist/{attach-DhZQ87Nz.mjs → attach-CEGbRg1D.mjs} +126 -69
- package/dist/bin.mjs +556 -119
- package/dist/{brief-BQbeoPMc.mjs → brief-DH66xmj8.mjs} +11 -6
- package/dist/{builtin-files-CWL3JEo-.mjs → builtin-files-Cf-NZDqM.mjs} +1 -1
- package/dist/{command-tree-B6uvMJq1.mjs → command-tree-CEkzWNy6.mjs} +1 -1
- package/dist/{completion-DKPuD_Rw.mjs → completion-DS0gCZRm.mjs} +19 -12
- package/dist/{context-Bw6R_EYq.mjs → context-CGPh12HV.mjs} +3 -3
- package/dist/{detached-BQlbmqR0.mjs → detached-Dakw5RZj.mjs} +3 -3
- package/dist/extra-arguments-BxQMXARO.mjs +13 -0
- package/dist/{find-B30-rd-u.mjs → find-BTikxc54.mjs} +1 -1
- package/dist/{flags-ByYBx-Xb.mjs → flags-C8yCq0j5.mjs} +7 -32
- package/dist/{follow-ups-Cxca1Jgg.mjs → follow-ups-CtlhHbwe.mjs} +87 -26
- package/dist/{format-C-nEZv-P.mjs → format-BB4E-T6x.mjs} +1 -1
- package/dist/{in-a-run-CZFzoT3R.mjs → in-a-run-CbnKjO7t.mjs} +2 -2
- package/dist/{install-CsqK1avz.mjs → install-CWcpX5g4.mjs} +1 -1
- package/dist/{limits-CXh052II.mjs → limits-VQqsBoQk.mjs} +1 -1
- package/dist/{mcp-B4wME9C4.mjs → mcp-wGfkMCVF.mjs} +6 -6
- package/dist/{once-BKn3pOtg.mjs → once-BHxSdZz_.mjs} +43 -7
- package/dist/{pause-B1grR1cl.mjs → pause-C_Wxh-KM.mjs} +6 -3
- package/dist/{print-Bd8MWVJk.mjs → print-DNYzq4Rr.mjs} +1 -1
- package/dist/{project-records-BOEVs69i.mjs → project-records-XY3ku95x.mjs} +4 -1
- package/dist/{relay-CeNiq3GT.mjs → relay-BA6tsnpc.mjs} +1 -1
- package/dist/{run-D6yU2rLf.mjs → run-Bvvg-fiF.mjs} +61 -19
- package/dist/{run-C0C54UiU.mjs → run-DBUAq-Uu.mjs} +29 -20
- package/dist/{send-DqgF58hb.mjs → send-nrKtak5F.mjs} +2 -2
- package/dist/{src-Ciy7i3se.mjs → src-8cOPOgrT.mjs} +155 -32
- package/dist/{src-n-u4TGev.mjs → src-CmEvHdju.mjs} +28 -28
- package/dist/{src-D2qpd-G7.mjs → src-D4JSymhK.mjs} +11 -2
- package/dist/{src-DP02RP9O.mjs → src-I_RyKu6_.mjs} +2 -2
- package/dist/{store-2KXzMCEN.mjs → store-CDpk8Wtz.mjs} +1 -1
- package/dist/ui/assets/app--FijEXiJ.css +1 -0
- package/dist/ui/assets/{app-ICEKpy_C.js → app-BowhjEAe.js} +12 -12
- package/dist/ui/assets/{index-BGaix5wh.js → index-CrMa2oHB.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-CAvygxTb.mjs → ui-DY3Dnpho.mjs} +4 -4
- package/dist/{usage-BFBco5OS.mjs → usage-1VwSg_Qt.mjs} +4 -4
- package/dist/{validate-UrmC5AG1.mjs → validate-BxayjjkV.mjs} +3 -3
- package/dist/{watch-DTxkgB8R.mjs → watch-CT0EtLPZ.mjs} +5 -5
- package/dist/{workflows-8GV-SeRm.mjs → workflows-DHHi-APg.mjs} +2 -2
- package/dist/{worktrees-CUdUvZlO.mjs → worktrees-CZvbHzbN.mjs} +4 -4
- package/package.json +1 -1
- package/dist/ui/assets/app-C5vO1M-l.css +0 -1
package/dist/bin.mjs
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { i as placeOf, n as acceptItem, t as runInstall } from "./install-
|
|
4
|
-
import { _ as machineSlotLedger, a as onInterrupt, c as runWorkflowFile, g as sweepLocks, h as machineLocksDir, i as loadRuntime, m as resumeChat, n as flagValues, o as run, r as isDriver, s as terminalHuman, t as badDriver } from "./run-
|
|
2
|
+
import { $t as planClean, Ar as planAgentMigration, Br as loadAgents, Fr as toolsInUse, G as listOrkWorktrees, Gn as PROJECT_FILE, Gr as placeFor, Gt as feedbackListTable, Hr as inRepoPlace, I as activeTree, Ii as DRIVER_IDS, Ir as createAgent, Jr as shownPath, Ln as runStatus, Lr as deleteAgent, Mi as readyDriver, Mn as requestStop, Mr as planMoveInto, Ni as AGENT_TOOL_LAYOUTS, Nn as tellLiveRun, Nr as linkTools, Pi as ORK_LAYOUT, Pn as liveStatus, Pr as toolLinks, R as openStore, Rr as AGENT_SOURCES, S as runningScript, T as isNewer, Un as nestItems, W as createdWorktrees, Wr as placeFiles, Wt as decisionListTable, Xt as applyClean, _r as normalizeTitle, an as clearGitLocalEnv, at as followRunTree, b as releaseNotes, ci as renameNodeTypes, cr as recordNote, dr as FEEDBACK_TARGETS, dt as resumable, fi as parseWorkflow, gi as WorkflowSchema, hr as sendPost, it as followRuns, ji as driverChecks, jr as applySteps, lr as FEEDBACK_KINDS, or as previewPost, ot as answerDecision, pi as serializeWorkflow, pr as planPost, qn as loadProject, qt as runListTable, sn as modelDriver, sr as checkNote, st as pendingDecisions, ur as FEEDBACK_SEVERITIES, ut as detachResume, vr as feedbackActions, x as runningRunIds, y as planUpgrade, yi as settingsOf, yr as openFixRun, zr as catalogAgent } from "./src-8cOPOgrT.mjs";
|
|
3
|
+
import { i as placeOf, n as acceptItem, t as runInstall } from "./install-CWcpX5g4.mjs";
|
|
4
|
+
import { _ as machineSlotLedger, a as onInterrupt, c as runWorkflowFile, g as sweepLocks, h as machineLocksDir, i as loadRuntime, m as resumeChat, n as flagValues, o as run, r as isDriver, s as terminalHuman, t as badDriver } from "./run-DBUAq-Uu.mjs";
|
|
5
5
|
import { t as applyFilters } from "./apply-Mb0fNpCX.mjs";
|
|
6
|
-
import { n as builtinWorkflowFile, t as builtinProblem } from "./builtin-files-
|
|
7
|
-
import { p as scrubberOfRun } from "./src-
|
|
8
|
-
import { t as findRun } from "./find-
|
|
9
|
-
import { c as fetchLatest, d as readUpdateCache, h as nodeSession, i as registryOf, m as writeUpdateCache, n as ORK_VERSION, p as updateCachePath, t as ORK_NAME } from "./__build_info__-
|
|
6
|
+
import { n as builtinWorkflowFile, t as builtinProblem } from "./builtin-files-Cf-NZDqM.mjs";
|
|
7
|
+
import { p as scrubberOfRun } from "./src-I_RyKu6_.mjs";
|
|
8
|
+
import { t as findRun } from "./find-BTikxc54.mjs";
|
|
9
|
+
import { c as fetchLatest, d as readUpdateCache, h as nodeSession, i as registryOf, m as writeUpdateCache, n as ORK_VERSION, p as updateCachePath, t as ORK_NAME } from "./__build_info__-D6mXC4cD.mjs";
|
|
10
10
|
import { n as groupedEntries, t as groupOf } from "./help-groups-BpRgBSTh.mjs";
|
|
11
|
-
import { a as resolved, i as publicArgs, n as argsOf, o as subcommandsOf } from "./command-tree-
|
|
11
|
+
import { a as resolved, i as publicArgs, n as argsOf, o as subcommandsOf } from "./command-tree-CEkzWNy6.mjs";
|
|
12
12
|
import { C as termOf, D as wrap, E as widthOf, S as takePlainFlag, T as hang, a as plain, b as canKey, c as write, h as paint, l as writeErr, m as bold, s as style, t as confirm, w as cut } from "./output-B1kwo0YU.mjs";
|
|
13
13
|
import { n as chip, r as nodeChip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
|
|
14
|
-
import { a as
|
|
15
|
-
import { c as projectAt, l as registeredProjects, n as WORKFLOW_SUFFIX, t as WORKFLOW_DIR } from "./workflows-
|
|
16
|
-
import { C as startUpdateCheck, S as showUpdateNotice, _ as runChecks, a as formatReport, c as checksHere, g as orkCheck, h as headWarning, m as experimentsCheck, n as validate, p as exec, r as validateFile, v as socketCheck, w as updateCheckOff, x as runUpdateChild, y as triggerChecks } from "./validate-
|
|
17
|
-
import { a as
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { t as
|
|
22
|
-
import {
|
|
23
|
-
import { t as
|
|
14
|
+
import { a as printerFor, c as logListTable, h as readText, i as printUnder, l as matcher, m as createTerminalHuman, n as createPrompts, o as createLogPrinter, r as askStored, s as followRun, u as unknownNode } from "./attach-CEGbRg1D.mjs";
|
|
15
|
+
import { c as projectAt, l as registeredProjects, n as WORKFLOW_SUFFIX, t as WORKFLOW_DIR } from "./workflows-DHHi-APg.mjs";
|
|
16
|
+
import { C as startUpdateCheck, S as showUpdateNotice, _ as runChecks, a as formatReport, c as checksHere, g as orkCheck, h as headWarning, m as experimentsCheck, n as validate, p as exec, r as validateFile, v as socketCheck, w as updateCheckOff, x as runUpdateChild, y as triggerChecks } from "./validate-BxayjjkV.mjs";
|
|
17
|
+
import { a as createView, o as styler } from "./verdict-CMvPCpWC.mjs";
|
|
18
|
+
import { a as decideRefusal, r as chatRefusal } from "./in-a-run-CbnKjO7t.mjs";
|
|
19
|
+
import { t as context } from "./context-CGPh12HV.mjs";
|
|
20
|
+
import { t as refuseExtraArguments } from "./extra-arguments-BxQMXARO.mjs";
|
|
21
|
+
import { c as refuseUnknownFlags, i as readListArgs, n as filterArgs, o as resolveRun, r as projectScope, s as rootOf, t as fail$1 } from "./flags-C8yCq0j5.mjs";
|
|
22
|
+
import { i as listedStatus, n as formatRuns, r as formatTreeView, t as ago } from "./format-BB4E-T6x.mjs";
|
|
23
|
+
import { t as printList } from "./print-DNYzq4Rr.mjs";
|
|
24
|
+
import { a as formatRegistered, i as formatProjects, n as move, o as recordInRepo, r as withStore, s as registerProject, t as forget } from "./project-records-XY3ku95x.mjs";
|
|
25
|
+
import { t as withStore$1 } from "./store-CDpk8Wtz.mjs";
|
|
24
26
|
import path from "node:path";
|
|
25
27
|
import { stringify } from "yaml";
|
|
26
28
|
import { z } from "zod";
|
|
@@ -358,6 +360,97 @@ const noteRun = (store, cwd, args) => {
|
|
|
358
360
|
* file names (by pattern only when the file is gone or no longer parses).
|
|
359
361
|
*/
|
|
360
362
|
const noteOn = (store, run, ask) => recordNote(store, run, ask, "--", scrubberOfRun(run, store.projects()));
|
|
363
|
+
// src/runs/follow-decisions.ts
|
|
364
|
+
/**
|
|
365
|
+
* @file `ork decide --follow`: ask the open decisions of the live runs in scope
|
|
366
|
+
* on this terminal, then each one a run opens later, one prompt at a time
|
|
367
|
+
* (specs/cli.md). Runs are followed with core's `followRuns`, so a run
|
|
368
|
+
* started after this one, and a called run, are found; a decision answered
|
|
369
|
+
* elsewhere withdraws its prompt. Ctrl-C and `--until-idle` end it; no
|
|
370
|
+
* decision is closed by either.
|
|
371
|
+
*/
|
|
372
|
+
const scopeOf$1 = ({ project, runId, workflow }) => ({
|
|
373
|
+
...project === void 0 ? {} : { project },
|
|
374
|
+
...runId === void 0 ? {} : { run: runId },
|
|
375
|
+
...workflow === void 0 ? {} : { workflow }
|
|
376
|
+
});
|
|
377
|
+
/**
|
|
378
|
+
* Asks `open` (the decisions open now, in the store's order) and then each
|
|
379
|
+
* decision the runs in `filter` open, until `session.signal` aborts or, with
|
|
380
|
+
* `untilIdle`, nothing is live and nothing is being asked. Says why it stopped
|
|
381
|
+
* and returns.
|
|
382
|
+
*/
|
|
383
|
+
const followDecisions = async (store, open, filter, session) => {
|
|
384
|
+
const stop = new AbortController();
|
|
385
|
+
session.signal?.addEventListener("abort", () => {
|
|
386
|
+
stop.abort();
|
|
387
|
+
});
|
|
388
|
+
const human = createTerminalHuman({
|
|
389
|
+
...session.terminal,
|
|
390
|
+
interrupt: () => {
|
|
391
|
+
stop.abort();
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
const term = termOf(session.terminal.output, session.terminal.env);
|
|
395
|
+
const say = styler(term);
|
|
396
|
+
const prompts = createPrompts(store, human, {
|
|
397
|
+
by: "decide",
|
|
398
|
+
out: session.out,
|
|
399
|
+
term,
|
|
400
|
+
...session.home === void 0 ? {} : { home: session.home }
|
|
401
|
+
});
|
|
402
|
+
stop.signal.addEventListener("abort", () => {
|
|
403
|
+
prompts.abort();
|
|
404
|
+
});
|
|
405
|
+
/**
|
|
406
|
+
* Every decision put to the person: one that was left (`q`) isn't asked
|
|
407
|
+
* again.
|
|
408
|
+
*/
|
|
409
|
+
const asked = /* @__PURE__ */ new Set();
|
|
410
|
+
const workflowOf = (run) => store.lookup(run).find((r) => r.id === run)?.workflow;
|
|
411
|
+
const ask = (run, decision, path) => {
|
|
412
|
+
if (asked.has(decision)) return;
|
|
413
|
+
asked.add(decision);
|
|
414
|
+
const workflow = workflowOf(run);
|
|
415
|
+
prompts.ask({
|
|
416
|
+
run,
|
|
417
|
+
...workflow === void 0 ? {} : { workflow },
|
|
418
|
+
...path === void 0 ? {} : { path }
|
|
419
|
+
}, decision);
|
|
420
|
+
};
|
|
421
|
+
try {
|
|
422
|
+
for (const d of open) ask(d.runId, d.id);
|
|
423
|
+
let end;
|
|
424
|
+
for (;;) {
|
|
425
|
+
end = await followRuns(store, scopeOf$1(filter), ({ run, workflow, path, stored }) => {
|
|
426
|
+
const { event } = stored;
|
|
427
|
+
if (prompts.seen(event)) return;
|
|
428
|
+
if (event.type === "decision.opened" && (filter.runId === void 0 || run === filter.runId) && (filter.workflow === void 0 || workflow === filter.workflow) && pendingDecisions(store, { runId: run }).some((d) => d.id === event.decision)) ask(run, event.decision, path);
|
|
429
|
+
}, {
|
|
430
|
+
untilIdle: session.untilIdle === true,
|
|
431
|
+
...session.home === void 0 ? {} : { home: session.home },
|
|
432
|
+
...session.intervalMs === void 0 ? {} : { intervalMs: session.intervalMs },
|
|
433
|
+
signal: stop.signal
|
|
434
|
+
});
|
|
435
|
+
if (end === "aborted" || prompts.open() === 0) break;
|
|
436
|
+
await prompts.settled();
|
|
437
|
+
if (stop.signal.aborted) {
|
|
438
|
+
end = "aborted";
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
prompts.abort();
|
|
443
|
+
await prompts.settled();
|
|
444
|
+
if (end === "idle") session.out(say("dim", "no live runs"));
|
|
445
|
+
else {
|
|
446
|
+
const left = (/* @__PURE__ */ new Set([...pendingDecisions(store, filter).map((d) => d.id), ...[...asked].filter((id) => store.decision(id)?.status === "open")])).size;
|
|
447
|
+
session.out(say("dim", `stopped following; ${left} decision(s) still open`));
|
|
448
|
+
}
|
|
449
|
+
return end;
|
|
450
|
+
} finally {
|
|
451
|
+
human.close();
|
|
452
|
+
}
|
|
453
|
+
};
|
|
361
454
|
// src/commands/decide-list.ts
|
|
362
455
|
/**
|
|
363
456
|
* @file The list `ork decide --list` prints: one line per open decision, and
|
|
@@ -426,7 +519,8 @@ const selectDecisions = (store, args) => {
|
|
|
426
519
|
const pending = pendingDecisions(store, filter);
|
|
427
520
|
return {
|
|
428
521
|
open: request.limit === void 0 ? pending : pending.slice(0, request.limit),
|
|
429
|
-
workflow
|
|
522
|
+
workflow,
|
|
523
|
+
filter
|
|
430
524
|
};
|
|
431
525
|
};
|
|
432
526
|
/** Prints `open` as `--ids`, `--json` or the lines of `formatDecisions`. */
|
|
@@ -445,6 +539,95 @@ const decisionHint = (store, arg) => {
|
|
|
445
539
|
if (decision === void 0 || decision.status !== "open") return void 0;
|
|
446
540
|
return `${arg} is a decision id, not a run: answer it with \`ork decide --id ${arg} --choose ${decision.recommended ?? decision.options[0]?.id ?? "<option>"}\``;
|
|
447
541
|
};
|
|
542
|
+
/** The flags that list or answer one decision, which `--follow` can't take. */
|
|
543
|
+
const NOT_WITH_FOLLOW = [
|
|
544
|
+
"list",
|
|
545
|
+
"json",
|
|
546
|
+
"ids",
|
|
547
|
+
"limit",
|
|
548
|
+
"id",
|
|
549
|
+
"choose",
|
|
550
|
+
"document",
|
|
551
|
+
"say",
|
|
552
|
+
"note",
|
|
553
|
+
"rating"
|
|
554
|
+
];
|
|
555
|
+
/** Why the flags can't follow decisions, or `undefined` when they can. */
|
|
556
|
+
const followRefusal = (args) => {
|
|
557
|
+
if (args["follow"] !== true) return args["until-idle"] === true ? "--until-idle goes with --follow." : void 0;
|
|
558
|
+
const given = NOT_WITH_FOLLOW.filter((name) => args[name] !== void 0 && args[name] !== false);
|
|
559
|
+
return given.length === 0 ? void 0 : `--follow asks decisions as they open; it can't go with ${given.map((name) => `--${name}`).join(", ")}.`;
|
|
560
|
+
};
|
|
561
|
+
// src/commands/decide-ask.ts
|
|
562
|
+
/**
|
|
563
|
+
* @file `ork decide` answering on a terminal: the open decisions one at a time
|
|
564
|
+
* (`askOpen`), or those and every one a live run opens later (`--follow`,
|
|
565
|
+
* `followCommand`), with the line a plain terminal gets after an answer.
|
|
566
|
+
*/
|
|
567
|
+
/** What the answer said, as stored (masked), after the answer's line. */
|
|
568
|
+
const saidLine = (store, id) => {
|
|
569
|
+
const note = store.decision(id)?.note;
|
|
570
|
+
return note === void 0 ? "" : style("dim", ` · said: ${note}`);
|
|
571
|
+
};
|
|
572
|
+
/** The workflow a card names for a run, when the store knows it. */
|
|
573
|
+
const workflowOf = (store, run) => {
|
|
574
|
+
const workflow = store.lookup(run).find((r) => r.id === run)?.workflow;
|
|
575
|
+
return workflow === void 0 ? {} : { workflow };
|
|
576
|
+
};
|
|
577
|
+
/** Asks `open` on `human`, one question at a time, in order. */
|
|
578
|
+
const askOpen = async (store, human, open) => {
|
|
579
|
+
const collapses = canKey(process.stdin, process.stdout);
|
|
580
|
+
for (const [index, d] of open.entries()) {
|
|
581
|
+
const asked = await askStored(store, human, d, {
|
|
582
|
+
by: "decide",
|
|
583
|
+
place: {
|
|
584
|
+
run: d.runId,
|
|
585
|
+
...workflowOf(store, d.runId),
|
|
586
|
+
decision: d.id,
|
|
587
|
+
index: index + 1,
|
|
588
|
+
total: open.length
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
if (asked.kind === "refused") write(`${style("yellow", "!")} ${asked.message}\n`);
|
|
592
|
+
else if (asked.kind === "answered" && !collapses) write(`${style("green", "✓")} ${d.id}: ${asked.choice}${saidLine(store, d.id)}\n`);
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
/** `ork decide --follow`: the person at this terminal answers as decisions open. */
|
|
596
|
+
const followCommand = async (args) => {
|
|
597
|
+
const refusal = decideRefusal();
|
|
598
|
+
if (refusal !== null) {
|
|
599
|
+
fail$1(refusal);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
if (!process.stdin.isTTY) {
|
|
603
|
+
fail$1("--follow needs a terminal to answer on; `ork decide --list` shows what is open.");
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
const store = openStore();
|
|
607
|
+
const stop = new AbortController();
|
|
608
|
+
const onSigint = () => {
|
|
609
|
+
stop.abort();
|
|
610
|
+
};
|
|
611
|
+
try {
|
|
612
|
+
const selected = selectDecisions(store, args);
|
|
613
|
+
if (selected === void 0) return;
|
|
614
|
+
process.once("SIGINT", onSigint);
|
|
615
|
+
await followDecisions(store, selected.open, selected.filter, {
|
|
616
|
+
out: write,
|
|
617
|
+
signal: stop.signal,
|
|
618
|
+
untilIdle: args["until-idle"] === true,
|
|
619
|
+
terminal: {
|
|
620
|
+
input: process.stdin,
|
|
621
|
+
output: process.stdout,
|
|
622
|
+
interactive: true,
|
|
623
|
+
verbose: args["verbose"] === true
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
} finally {
|
|
627
|
+
process.off("SIGINT", onSigint);
|
|
628
|
+
store.close();
|
|
629
|
+
}
|
|
630
|
+
};
|
|
448
631
|
// src/commands/decide.ts
|
|
449
632
|
/**
|
|
450
633
|
* @file `ork decide`: answer a live run's open decisions from any terminal (it
|
|
@@ -485,11 +668,6 @@ const noteProblem = (note, rating) => {
|
|
|
485
668
|
}, "--");
|
|
486
669
|
return checked.ok ? void 0 : checked.error;
|
|
487
670
|
};
|
|
488
|
-
/** What the answer said, as stored (masked), after the answer's line. */
|
|
489
|
-
const saidLine = (store, id) => {
|
|
490
|
-
const note = store.decision(id)?.note;
|
|
491
|
-
return note === void 0 ? "" : style("dim", ` · said: ${note}`);
|
|
492
|
-
};
|
|
493
671
|
const decide = defineCommand({
|
|
494
672
|
meta: {
|
|
495
673
|
name: "decide",
|
|
@@ -532,9 +710,29 @@ const decide = defineCommand({
|
|
|
532
710
|
type: "boolean",
|
|
533
711
|
description: "Show each question's whole context, not its first lines",
|
|
534
712
|
default: false
|
|
713
|
+
},
|
|
714
|
+
follow: {
|
|
715
|
+
type: "boolean",
|
|
716
|
+
alias: ["watch"],
|
|
717
|
+
description: "Ask the open decisions, then each new one of any live run (Ctrl-C stops)",
|
|
718
|
+
default: false
|
|
719
|
+
},
|
|
720
|
+
"until-idle": {
|
|
721
|
+
type: "boolean",
|
|
722
|
+
description: "With --follow, stop once no live run is left",
|
|
723
|
+
default: false
|
|
535
724
|
}
|
|
536
725
|
},
|
|
537
726
|
run: async ({ args }) => {
|
|
727
|
+
const conflict = followRefusal(args);
|
|
728
|
+
if (conflict !== void 0) {
|
|
729
|
+
failed$2(conflict);
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
if (args.follow) {
|
|
733
|
+
await followCommand(args);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
538
736
|
const listing = asksForList(args);
|
|
539
737
|
const refusal = !args.document && (args.id !== void 0 || args.choose !== void 0 || process.stdin.isTTY && !listing) ? decideRefusal() : null;
|
|
540
738
|
if (refusal !== null) {
|
|
@@ -596,20 +794,7 @@ const decide = defineCommand({
|
|
|
596
794
|
printDecisions(open, args, workflow);
|
|
597
795
|
return;
|
|
598
796
|
}
|
|
599
|
-
|
|
600
|
-
for (const [index, d] of open.entries()) {
|
|
601
|
-
const asked = await askStored(store, human, d, {
|
|
602
|
-
by: "decide",
|
|
603
|
-
place: {
|
|
604
|
-
run: d.runId,
|
|
605
|
-
decision: d.id,
|
|
606
|
-
index: index + 1,
|
|
607
|
-
total: open.length
|
|
608
|
-
}
|
|
609
|
-
});
|
|
610
|
-
if (asked.kind === "refused") write(`${style("yellow", "!")} ${asked.message}\n`);
|
|
611
|
-
else if (asked.kind === "answered" && !collapses) write(`${style("green", "✓")} ${d.id}: ${asked.choice}${saidLine(store, d.id)}\n`);
|
|
612
|
-
}
|
|
797
|
+
await askOpen(store, human, open);
|
|
613
798
|
} finally {
|
|
614
799
|
human?.close();
|
|
615
800
|
store.close();
|
|
@@ -634,6 +819,7 @@ const stop = defineCommand({
|
|
|
634
819
|
name: "stop",
|
|
635
820
|
description: "Stop a live run, or one of its nodes"
|
|
636
821
|
},
|
|
822
|
+
plugins: [refuseExtraArguments],
|
|
637
823
|
args: {
|
|
638
824
|
run: {
|
|
639
825
|
type: "positional",
|
|
@@ -683,6 +869,7 @@ const resume = defineCommand({
|
|
|
683
869
|
name: "resume",
|
|
684
870
|
description: "Continue a run that didn't succeed (stopped, failed or crashed): finished nodes keep their results"
|
|
685
871
|
},
|
|
872
|
+
plugins: [refuseExtraArguments],
|
|
686
873
|
args: {
|
|
687
874
|
run: {
|
|
688
875
|
type: "positional",
|
|
@@ -822,7 +1009,7 @@ const formatCheck = (result, term = termOf(process.stdout)) => {
|
|
|
822
1009
|
* folder. Says nothing when there were none. `bin` is the `cmd` program.
|
|
823
1010
|
*/
|
|
824
1011
|
const leaseChecks = async (place, env = process.env, bin = "cmd") => {
|
|
825
|
-
const { cleanStaleLeases, leaseLedger } = await import("./src-
|
|
1012
|
+
const { cleanStaleLeases, leaseLedger } = await import("./src-D4JSymhK.mjs");
|
|
826
1013
|
const { cleaned, failed } = await cleanStaleLeases({
|
|
827
1014
|
bin,
|
|
828
1015
|
ledger: leaseLedger(placeFiles(place).runs),
|
|
@@ -1935,12 +2122,57 @@ const triageSummary = ({ merged, declined, triaged }) => {
|
|
|
1935
2122
|
`${String(triaged)} new item(s) triaged`
|
|
1936
2123
|
].join("; ");
|
|
1937
2124
|
};
|
|
2125
|
+
// src/commands/feedback-resolve.ts
|
|
2126
|
+
/**
|
|
2127
|
+
* @file `ork feedback resolve`: marks items resolved that were fixed by hand,
|
|
2128
|
+
* outside `ork feedback apply`, so they leave the list (specs/feedback.md).
|
|
2129
|
+
* Takes several ids, space or comma separated, and changes none when one is
|
|
2130
|
+
* unknown or can't be resolved (dismissed, or resolved or published already).
|
|
2131
|
+
* An item seen again after it was resolved opens again.
|
|
2132
|
+
*/
|
|
2133
|
+
const resolve = defineCommand({
|
|
2134
|
+
meta: {
|
|
2135
|
+
name: "resolve",
|
|
2136
|
+
description: "Mark items fixed by hand resolved: they leave the list, and open again if they recur"
|
|
2137
|
+
},
|
|
2138
|
+
args: { item: {
|
|
2139
|
+
type: "positional",
|
|
2140
|
+
description: "A feedback item's id, or a prefix of one; several allowed, space or comma separated",
|
|
2141
|
+
required: true
|
|
2142
|
+
} },
|
|
2143
|
+
run: ({ args }) => withStore$1((store) => {
|
|
2144
|
+
const named = [...new Set(args._.flatMap((word) => word.split(",")).map((word) => word.trim()).filter((word) => word !== ""))];
|
|
2145
|
+
const items = /* @__PURE__ */ new Map();
|
|
2146
|
+
const refusals = [];
|
|
2147
|
+
for (const prefix of named) {
|
|
2148
|
+
const found = findFeedbackItem(store, prefix);
|
|
2149
|
+
if (!found.ok) {
|
|
2150
|
+
refusals.push(found.error);
|
|
2151
|
+
continue;
|
|
2152
|
+
}
|
|
2153
|
+
const allowed = feedbackActions(found.item).resolve;
|
|
2154
|
+
if (allowed.ok) items.set(found.item.id, found.item);
|
|
2155
|
+
else refusals.push(allowed.error);
|
|
2156
|
+
}
|
|
2157
|
+
if (refusals.length > 0 || items.size === 0) {
|
|
2158
|
+
for (const refusal of refusals) writeErr(refusal);
|
|
2159
|
+
if (items.size === 0 && refusals.length === 0) writeErr("Give a feedback item's id.");
|
|
2160
|
+
process.exitCode = 1;
|
|
2161
|
+
return;
|
|
2162
|
+
}
|
|
2163
|
+
for (const item of items.values()) {
|
|
2164
|
+
store.setFeedbackStatus(item.id, "resolved");
|
|
2165
|
+
write(`${style("green", "✓")} resolved ${item.id.slice(0, 12)}: ${item.title}`);
|
|
2166
|
+
}
|
|
2167
|
+
})
|
|
2168
|
+
});
|
|
1938
2169
|
// src/commands/feedback-loop.ts
|
|
1939
2170
|
/**
|
|
1940
2171
|
* @file The `ork feedback` subcommands that close the loop (ADR-059): `apply`
|
|
1941
2172
|
* runs Ork's own workflow to propose a fix for an item, `triage` merges items
|
|
1942
2173
|
* about the same problem by rules after asking, and `split` takes a merge
|
|
1943
|
-
* apart.
|
|
2174
|
+
* apart. `resolve` (marking items fixed by hand) is passed on from its own
|
|
2175
|
+
* file.
|
|
1944
2176
|
*/
|
|
1945
2177
|
const itemArg$1 = {
|
|
1946
2178
|
type: "positional",
|
|
@@ -2276,10 +2508,10 @@ const importFeedback = defineCommand({
|
|
|
2276
2508
|
/**
|
|
2277
2509
|
* @file `ork feedback`: the feedback every run recorded, grouped into items
|
|
2278
2510
|
* (specs/feedback.md): list and show them, note a run, dismiss and restore an
|
|
2279
|
-
* item,
|
|
2280
|
-
*
|
|
2281
|
-
*
|
|
2282
|
-
* `feedback-share.ts`.
|
|
2511
|
+
* item, accept one, as a lesson its workflow reads from then on, and resolve
|
|
2512
|
+
* ones fixed by hand (`feedback-resolve.ts`). What closes the loop further
|
|
2513
|
+
* (apply, triage, split) is in `feedback-loop.ts`, and what moves feedback
|
|
2514
|
+
* off the machine (publish, export, import) in `feedback-share.ts`.
|
|
2283
2515
|
*/
|
|
2284
2516
|
/** Runs `body` on the item `prefix` names, or says why there's none. */
|
|
2285
2517
|
const withItem = (prefix, body) => withStore$1((store) => {
|
|
@@ -2299,7 +2531,7 @@ const itemArg = {
|
|
|
2299
2531
|
const feedback = defineCommand({
|
|
2300
2532
|
meta: {
|
|
2301
2533
|
name: "feedback",
|
|
2302
|
-
description: "What got in the way in your runs, grouped: list, show, note, dismiss, restore, accept, apply, triage, split, publish, export, import"
|
|
2534
|
+
description: "What got in the way in your runs, grouped: list, show, note, dismiss, restore, accept, resolve, apply, triage, split, publish, export, import"
|
|
2303
2535
|
},
|
|
2304
2536
|
subCommands: {
|
|
2305
2537
|
list,
|
|
@@ -2308,6 +2540,7 @@ const feedback = defineCommand({
|
|
|
2308
2540
|
name: "show",
|
|
2309
2541
|
description: "Show an item and its records"
|
|
2310
2542
|
},
|
|
2543
|
+
plugins: [refuseExtraArguments],
|
|
2311
2544
|
args: {
|
|
2312
2545
|
item: itemArg,
|
|
2313
2546
|
json: {
|
|
@@ -2333,6 +2566,7 @@ const feedback = defineCommand({
|
|
|
2333
2566
|
name: "note",
|
|
2334
2567
|
description: "Note how a run or one of its nodes went; it joins the feedback"
|
|
2335
2568
|
},
|
|
2569
|
+
plugins: [refuseExtraArguments],
|
|
2336
2570
|
args: {
|
|
2337
2571
|
run: {
|
|
2338
2572
|
type: "positional",
|
|
@@ -2381,6 +2615,7 @@ const feedback = defineCommand({
|
|
|
2381
2615
|
name: "accept",
|
|
2382
2616
|
description: "Accept an item; with --lesson, every later session of its workflow reads it"
|
|
2383
2617
|
},
|
|
2618
|
+
plugins: [refuseExtraArguments],
|
|
2384
2619
|
args: {
|
|
2385
2620
|
item: itemArg,
|
|
2386
2621
|
lesson: {
|
|
@@ -2414,17 +2649,31 @@ const feedback = defineCommand({
|
|
|
2414
2649
|
for (const line of rest) write(` ${line}`);
|
|
2415
2650
|
})
|
|
2416
2651
|
}),
|
|
2417
|
-
|
|
2652
|
+
resolve,
|
|
2653
|
+
apply: {
|
|
2654
|
+
...apply,
|
|
2655
|
+
plugins: [refuseExtraArguments]
|
|
2656
|
+
},
|
|
2418
2657
|
triage,
|
|
2419
|
-
split
|
|
2420
|
-
|
|
2658
|
+
split: {
|
|
2659
|
+
...split,
|
|
2660
|
+
plugins: [refuseExtraArguments]
|
|
2661
|
+
},
|
|
2662
|
+
publish: {
|
|
2663
|
+
...publish,
|
|
2664
|
+
plugins: [refuseExtraArguments]
|
|
2665
|
+
},
|
|
2421
2666
|
export: exportFeedback,
|
|
2422
|
-
import:
|
|
2667
|
+
import: {
|
|
2668
|
+
...importFeedback,
|
|
2669
|
+
plugins: [refuseExtraArguments]
|
|
2670
|
+
},
|
|
2423
2671
|
dismiss: defineCommand({
|
|
2424
2672
|
meta: {
|
|
2425
2673
|
name: "dismiss",
|
|
2426
2674
|
description: "Dismiss an item: it leaves the list, and stays dismissed"
|
|
2427
2675
|
},
|
|
2676
|
+
plugins: [refuseExtraArguments],
|
|
2428
2677
|
args: { item: itemArg },
|
|
2429
2678
|
run: ({ args }) => withItem(args.item, (store, item) => {
|
|
2430
2679
|
store.setFeedbackStatus(item.id, "dismissed");
|
|
@@ -2436,6 +2685,7 @@ const feedback = defineCommand({
|
|
|
2436
2685
|
name: "restore",
|
|
2437
2686
|
description: "Bring a dismissed item back to the list, as new"
|
|
2438
2687
|
},
|
|
2688
|
+
plugins: [refuseExtraArguments],
|
|
2439
2689
|
args: { item: itemArg },
|
|
2440
2690
|
run: ({ args }) => withItem(args.item, (store, item) => {
|
|
2441
2691
|
store.setFeedbackStatus(item.id, "new");
|
|
@@ -2444,57 +2694,144 @@ const feedback = defineCommand({
|
|
|
2444
2694
|
})
|
|
2445
2695
|
}
|
|
2446
2696
|
});
|
|
2447
|
-
// src/
|
|
2697
|
+
// src/runs/logs-many.ts
|
|
2448
2698
|
/**
|
|
2449
|
-
* @file `ork
|
|
2450
|
-
*
|
|
2699
|
+
* @file `ork logs` over several runs: a run with the runs it called inline
|
|
2700
|
+
* under their call paths, and every live run of a project interleaved behind
|
|
2701
|
+
* a `<id> <workflow> › ` prefix (`logs -f --all`; specs/cli.md,
|
|
2702
|
+
* specs/scheduler/calls.md).
|
|
2451
2703
|
*/
|
|
2452
|
-
/**
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
const
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2704
|
+
/**
|
|
2705
|
+
* The stored events of `roots` and of the runs they called, at any depth, in
|
|
2706
|
+
* the order they print: a called run's right after its `call.started`.
|
|
2707
|
+
*/
|
|
2708
|
+
const treeEvents = (store, roots) => {
|
|
2709
|
+
const seen = new Set(roots);
|
|
2710
|
+
const walk = (id, into) => {
|
|
2711
|
+
for (const stored of store.events(id)) {
|
|
2712
|
+
into.push(stored);
|
|
2713
|
+
const { event } = stored;
|
|
2714
|
+
if (event.type === "call.started" && !seen.has(event.run)) {
|
|
2715
|
+
seen.add(event.run);
|
|
2716
|
+
walk(event.run, into);
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
return into;
|
|
2720
|
+
};
|
|
2721
|
+
return roots.flatMap((id) => walk(id, []));
|
|
2722
|
+
};
|
|
2723
|
+
/** `run:seq` of an event, to name it in a set. */
|
|
2724
|
+
const keyOf = (stored) => `${stored.runId}:${stored.seq}`;
|
|
2725
|
+
/**
|
|
2726
|
+
* The stored events (in print order, over all of `roots`' runs) that `--limit`
|
|
2727
|
+
* cuts: all but the last `limit` that pass the filters. Events stored after
|
|
2728
|
+
* this read are not in it, so they always print.
|
|
2729
|
+
*/
|
|
2730
|
+
const droppedBy = (store, roots, options) => {
|
|
2731
|
+
if (options.limit === void 0) return /* @__PURE__ */ new Set();
|
|
2732
|
+
const matches = matcher(options);
|
|
2733
|
+
const kept = treeEvents(store, roots).filter((stored) => matches(stored));
|
|
2734
|
+
return new Set(kept.slice(0, -options.limit).map((stored) => keyOf(stored)));
|
|
2735
|
+
};
|
|
2736
|
+
/** A run's printer: JSON lines as stored, or text laid out behind `path`. */
|
|
2737
|
+
const printerOf = (term, options, path) => options.json ? createLogPrinter({ json: true }) : printerFor(term, path, {
|
|
2738
|
+
...options.verbose === void 0 ? {} : { verbose: options.verbose },
|
|
2739
|
+
...options.node === void 0 ? {} : { node: options.node }
|
|
2740
|
+
});
|
|
2741
|
+
/** Prints a run's `lines` behind `path`'s gutter; JSON lines have none. */
|
|
2742
|
+
const show = (out, term, options, path, lines) => {
|
|
2743
|
+
if (options.json) for (const line of lines) out(line);
|
|
2744
|
+
else printUnder(out, term, path, lines);
|
|
2745
|
+
};
|
|
2746
|
+
/** What the clock-free options of a follower are, as `followRuns` takes them. */
|
|
2747
|
+
const pollOf = (options) => ({
|
|
2748
|
+
...options.home === void 0 ? {} : { home: options.home },
|
|
2749
|
+
...options.intervalMs === void 0 ? {} : { intervalMs: options.intervalMs },
|
|
2750
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
2492
2751
|
});
|
|
2493
|
-
|
|
2752
|
+
/**
|
|
2753
|
+
* Whether `--node` names nothing in `root` or the runs it called (none of them
|
|
2754
|
+
* has such an event or declares it), as `unknownNode` says for one run.
|
|
2755
|
+
*/
|
|
2756
|
+
const unknownCallNode = (store, root, node, live) => unknownNode(treeEvents(store, [root]), node, live);
|
|
2757
|
+
/**
|
|
2758
|
+
* Prints `root`'s events and those of the runs it called, each called run's
|
|
2759
|
+
* right after the `call.started` that started it, under its call path. With
|
|
2760
|
+
* `follow`, goes on until the root ends (or `signal` aborts), then names the
|
|
2761
|
+
* called runs still running.
|
|
2762
|
+
*/
|
|
2763
|
+
const printCalls = async (store, root, out, options) => {
|
|
2764
|
+
const { term } = options.view ?? createView();
|
|
2765
|
+
const say = styler(term);
|
|
2766
|
+
const matches = matcher(options);
|
|
2767
|
+
const dropped = droppedBy(store, [root.id], options);
|
|
2768
|
+
const printers = /* @__PURE__ */ new Map();
|
|
2769
|
+
const { end, stillRunning } = await followRunTree(store, root.id, ({ run, path, stored }) => {
|
|
2770
|
+
let print = printers.get(run);
|
|
2771
|
+
if (print === void 0) {
|
|
2772
|
+
print = printerOf(term, options, path);
|
|
2773
|
+
printers.set(run, print);
|
|
2774
|
+
}
|
|
2775
|
+
const lines = print(stored);
|
|
2776
|
+
if (matches(stored) && !dropped.has(keyOf(stored))) show(out, term, options, path, lines);
|
|
2777
|
+
}, {
|
|
2778
|
+
follow: options.follow,
|
|
2779
|
+
...pollOf(options)
|
|
2780
|
+
});
|
|
2781
|
+
if (end === "crashed") out(style("red", `run ${root.id} stopped without finishing (its process is gone)`));
|
|
2782
|
+
if (!options.follow || options.json) return;
|
|
2783
|
+
for (const id of stillRunning) out(say("dim", `↳ run ${id} still running · ork attach ${id}`));
|
|
2784
|
+
};
|
|
2785
|
+
/**
|
|
2786
|
+
* Prints the events of every live run in `scope` (a called run too, once), each
|
|
2787
|
+
* line behind `<4-char id> <workflow> › `: the stored events first, then new
|
|
2788
|
+
* ones, runs that start later included. Ends when `signal` aborts, or with
|
|
2789
|
+
* `untilIdle` once no run is live.
|
|
2790
|
+
*/
|
|
2791
|
+
const printAll = async (store, scope, out, options) => {
|
|
2792
|
+
const { term } = options.view ?? createView();
|
|
2793
|
+
const matches = matcher(options);
|
|
2794
|
+
const { project } = scope;
|
|
2795
|
+
const live = store.runs(project === void 0 || project === "all" ? {} : { project }).filter((run) => liveStatus(run) === "running");
|
|
2796
|
+
const dropped = droppedBy(store, live.map((run) => run.id), options);
|
|
2797
|
+
const printers = /* @__PURE__ */ new Map();
|
|
2798
|
+
await followRuns(store, scope, ({ run, workflow, stored }) => {
|
|
2799
|
+
const path = [`${run.slice(0, 4)} ${workflow}`];
|
|
2800
|
+
let print = printers.get(run);
|
|
2801
|
+
if (print === void 0) {
|
|
2802
|
+
print = printerOf(term, options, path);
|
|
2803
|
+
printers.set(run, print);
|
|
2804
|
+
}
|
|
2805
|
+
const lines = print(stored);
|
|
2806
|
+
if (matches(stored) && !dropped.has(keyOf(stored))) show(out, term, options, path, lines);
|
|
2807
|
+
}, {
|
|
2808
|
+
...options.untilIdle === true ? { untilIdle: true } : {},
|
|
2809
|
+
...pollOf(options)
|
|
2810
|
+
});
|
|
2811
|
+
};
|
|
2812
|
+
// src/commands/logs.ts
|
|
2813
|
+
/**
|
|
2814
|
+
* @file `ork logs`: prints a run's transcript (with the runs it called inline),
|
|
2815
|
+
* or follows every live run of a project (`--all`), from `~/.ork/state.db`
|
|
2816
|
+
* (specs/event-store.md, specs/cli.md).
|
|
2817
|
+
*/
|
|
2818
|
+
const runArg$1 = {
|
|
2494
2819
|
type: "positional",
|
|
2495
2820
|
description: "A run id or a prefix of one (default: this project's newest)",
|
|
2496
2821
|
required: false
|
|
2497
2822
|
};
|
|
2823
|
+
/** Why `ork logs`'s flags can't go together, or `null`. */
|
|
2824
|
+
const logsRefusal = (args) => {
|
|
2825
|
+
if (args.all) {
|
|
2826
|
+
if (!args.follow) return "--all needs -f.";
|
|
2827
|
+
if (args.run !== void 0) return "--all can't be used with a run.";
|
|
2828
|
+
if (args.calls !== void 0) return "--calls and --no-calls don't apply to --all (a called run prints as its own).";
|
|
2829
|
+
return null;
|
|
2830
|
+
}
|
|
2831
|
+
if (args.project !== void 0) return "--project needs --all.";
|
|
2832
|
+
if (args["until-idle"]) return "--until-idle needs --all.";
|
|
2833
|
+
return null;
|
|
2834
|
+
};
|
|
2498
2835
|
const logs = defineCommand({
|
|
2499
2836
|
meta: {
|
|
2500
2837
|
name: "logs",
|
|
@@ -2502,7 +2839,7 @@ const logs = defineCommand({
|
|
|
2502
2839
|
},
|
|
2503
2840
|
plugins: [refuseUnknownFlags],
|
|
2504
2841
|
args: {
|
|
2505
|
-
run: runArg,
|
|
2842
|
+
run: runArg$1,
|
|
2506
2843
|
...filterArgs(logListTable, {
|
|
2507
2844
|
ids: false,
|
|
2508
2845
|
json: false,
|
|
@@ -2510,7 +2847,7 @@ const logs = defineCommand({
|
|
|
2510
2847
|
}),
|
|
2511
2848
|
limit: {
|
|
2512
2849
|
type: "string",
|
|
2513
|
-
description: "Print only the last this many stored events, a positive whole number (a live follow goes on past it)"
|
|
2850
|
+
description: "Print only the last this many stored events, a positive whole number, counted overall in print order, not per run (a live follow goes on past it)"
|
|
2514
2851
|
},
|
|
2515
2852
|
node: {
|
|
2516
2853
|
type: "string",
|
|
@@ -2531,27 +2868,79 @@ const logs = defineCommand({
|
|
|
2531
2868
|
type: "boolean",
|
|
2532
2869
|
description: "Show each tool call whole, and why each failed node stopped, with its scrubbed details (always on with --node)",
|
|
2533
2870
|
default: false
|
|
2871
|
+
},
|
|
2872
|
+
all: {
|
|
2873
|
+
type: "boolean",
|
|
2874
|
+
description: "With -f: every live run of the project, interleaved, each line behind its run id and workflow (a called run too, once; runs that start later join)",
|
|
2875
|
+
default: false
|
|
2876
|
+
},
|
|
2877
|
+
project: {
|
|
2878
|
+
type: "string",
|
|
2879
|
+
description: "With --all: a registered project (id or root), or all (default: this one)"
|
|
2880
|
+
},
|
|
2881
|
+
"until-idle": {
|
|
2882
|
+
type: "boolean",
|
|
2883
|
+
description: "With --all: end once no live run is left",
|
|
2884
|
+
default: false
|
|
2885
|
+
},
|
|
2886
|
+
calls: {
|
|
2887
|
+
type: "boolean",
|
|
2888
|
+
description: "Print the runs a run called inline under their call paths (default in text; --no-calls prints the run alone; --json needs --calls to include them)",
|
|
2889
|
+
negativeDescription: "Print the run alone, without the runs it called"
|
|
2534
2890
|
}
|
|
2535
2891
|
},
|
|
2536
2892
|
run: ({ args }) => withStore$1(async (store) => {
|
|
2893
|
+
const refusal = logsRefusal(args);
|
|
2894
|
+
if (refusal !== null) {
|
|
2895
|
+
fail$1(refusal);
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2537
2898
|
const req = readListArgs(logListTable, args);
|
|
2538
2899
|
if (req === void 0) return;
|
|
2900
|
+
const abort = new AbortController();
|
|
2901
|
+
process.once("SIGINT", () => {
|
|
2902
|
+
abort.abort();
|
|
2903
|
+
});
|
|
2904
|
+
if (args.all) {
|
|
2905
|
+
const scope = projectScope(args.project === void 0 ? {} : { project: args.project }, store.projects());
|
|
2906
|
+
if (scope === void 0) return;
|
|
2907
|
+
await printAll(store, scope === "all" ? {} : { project: rootOf(scope, store.projects()) }, write, {
|
|
2908
|
+
json: args.json,
|
|
2909
|
+
verbose: args.verbose,
|
|
2910
|
+
filter: req.filter,
|
|
2911
|
+
...req.limit === void 0 ? {} : { limit: req.limit },
|
|
2912
|
+
...args.node === void 0 ? {} : { node: args.node },
|
|
2913
|
+
...args["until-idle"] ? { untilIdle: true } : {},
|
|
2914
|
+
signal: abort.signal
|
|
2915
|
+
});
|
|
2916
|
+
return;
|
|
2917
|
+
}
|
|
2539
2918
|
const found = findRun(store, args.run, process.cwd());
|
|
2540
2919
|
if (!found.ok) {
|
|
2541
2920
|
writeErr(found.error);
|
|
2542
2921
|
process.exitCode = 1;
|
|
2543
2922
|
return;
|
|
2544
2923
|
}
|
|
2545
|
-
const
|
|
2924
|
+
const calls = args.calls ?? !args.json;
|
|
2925
|
+
const live = args.follow && found.run.status === "running";
|
|
2926
|
+
const problem = args.node === void 0 ? null : calls ? unknownCallNode(store, found.run.id, args.node, live) : unknownNode(store.events(found.run.id), args.node, live);
|
|
2546
2927
|
if (problem !== null) {
|
|
2547
2928
|
writeErr(problem);
|
|
2548
2929
|
process.exitCode = 1;
|
|
2549
2930
|
return;
|
|
2550
2931
|
}
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2932
|
+
if (calls) {
|
|
2933
|
+
await printCalls(store, found.run, write, {
|
|
2934
|
+
follow: args.follow,
|
|
2935
|
+
json: args.json,
|
|
2936
|
+
verbose: args.verbose,
|
|
2937
|
+
filter: req.filter,
|
|
2938
|
+
...req.limit === void 0 ? {} : { limit: req.limit },
|
|
2939
|
+
signal: abort.signal,
|
|
2940
|
+
...args.node === void 0 ? {} : { node: args.node }
|
|
2941
|
+
});
|
|
2942
|
+
return;
|
|
2943
|
+
}
|
|
2555
2944
|
await followRun(store, found.run, write, {
|
|
2556
2945
|
follow: args.follow,
|
|
2557
2946
|
json: args.json,
|
|
@@ -2563,13 +2952,61 @@ const logs = defineCommand({
|
|
|
2563
2952
|
});
|
|
2564
2953
|
})
|
|
2565
2954
|
});
|
|
2955
|
+
// src/commands/runs.ts
|
|
2956
|
+
/**
|
|
2957
|
+
* @file `ork ps`, `ork logs` and `ork tree`: read what every project's runs
|
|
2958
|
+
* recorded in `~/.ork/state.db` (specs/event-store.md).
|
|
2959
|
+
*/
|
|
2960
|
+
/** How many runs `ork ps` shows without `--limit`. */
|
|
2961
|
+
const PS_LIMIT = 20;
|
|
2962
|
+
const ps = defineCommand({
|
|
2963
|
+
meta: {
|
|
2964
|
+
name: "ps",
|
|
2965
|
+
description: "List this project's runs, newest first"
|
|
2966
|
+
},
|
|
2967
|
+
plugins: [refuseUnknownFlags],
|
|
2968
|
+
args: { ...filterArgs(runListTable, { extra: { limit: {
|
|
2969
|
+
type: "string",
|
|
2970
|
+
description: `Show at most this many, a positive whole number (default ${String(PS_LIMIT)})`
|
|
2971
|
+
} } }) },
|
|
2972
|
+
run: ({ args }) => withStore$1((store) => {
|
|
2973
|
+
const req = readListArgs(runListTable, args);
|
|
2974
|
+
if (req === void 0) return;
|
|
2975
|
+
const scope = projectScope(req.filter, store.projects());
|
|
2976
|
+
if (scope === void 0) return;
|
|
2977
|
+
const stored = store.runs(scope === "all" ? {} : { project: rootOf(scope, store.projects()) });
|
|
2978
|
+
const rows = req.filter["status"] === void 0 ? stored : stored.map((run) => run.status === "running" ? {
|
|
2979
|
+
...run,
|
|
2980
|
+
listed: runStatus(run, store.events(run.id).map((s) => s.event))
|
|
2981
|
+
} : run);
|
|
2982
|
+
const shown = applyFilters(runListTable, rows, req.filter).slice(0, req.limit ?? PS_LIMIT);
|
|
2983
|
+
const byId = new Map(stored.map((run) => [run.id, run]));
|
|
2984
|
+
const statusOf = (run) => listedStatus(run, run.status === "running" ? store.events(run.id).map((s) => s.event) : []);
|
|
2985
|
+
printList(shown, runListTable, {
|
|
2986
|
+
ids: args["ids"],
|
|
2987
|
+
json: args["json"]
|
|
2988
|
+
}, (runs) => {
|
|
2989
|
+
for (const line of formatRuns(runs, scope === "all", Date.now(), statusOf)) write(line);
|
|
2990
|
+
}, (runs) => runs.map((run) => {
|
|
2991
|
+
const record = byId.get(run.id) ?? run;
|
|
2992
|
+
return {
|
|
2993
|
+
...record,
|
|
2994
|
+
live: statusOf(record)
|
|
2995
|
+
};
|
|
2996
|
+
}));
|
|
2997
|
+
})
|
|
2998
|
+
});
|
|
2566
2999
|
const tree = defineCommand({
|
|
2567
3000
|
meta: {
|
|
2568
3001
|
name: "tree",
|
|
2569
3002
|
description: "Show a run's ownership tree with status, tokens and cost. A delegated task shows its task label: the lead's short description, whitespace folded, clipped to 80 characters, secrets masked"
|
|
2570
3003
|
},
|
|
2571
3004
|
args: {
|
|
2572
|
-
run:
|
|
3005
|
+
run: {
|
|
3006
|
+
type: "positional",
|
|
3007
|
+
description: "A run id or a prefix of one (default: this project's newest)",
|
|
3008
|
+
required: false
|
|
3009
|
+
},
|
|
2573
3010
|
json: {
|
|
2574
3011
|
type: "boolean",
|
|
2575
3012
|
description: "Print JSON",
|
|
@@ -3035,31 +3472,31 @@ const main = defineCommand({
|
|
|
3035
3472
|
run,
|
|
3036
3473
|
ps,
|
|
3037
3474
|
logs,
|
|
3038
|
-
attach: () => import("./attach-
|
|
3475
|
+
attach: () => import("./attach-C1OnxyMh.mjs").then((module) => module.attach),
|
|
3039
3476
|
tree,
|
|
3040
|
-
usage: () => import("./usage-
|
|
3041
|
-
prune: () => import("./usage-
|
|
3477
|
+
usage: () => import("./usage-1VwSg_Qt.mjs").then((module) => module.usage),
|
|
3478
|
+
prune: () => import("./usage-1VwSg_Qt.mjs").then((module) => module.prune),
|
|
3042
3479
|
decide,
|
|
3043
|
-
relay: () => import("./relay-
|
|
3044
|
-
pause: () => import("./pause-
|
|
3045
|
-
continue: () => import("./pause-
|
|
3480
|
+
relay: () => import("./relay-BA6tsnpc.mjs").then((module) => module.relay),
|
|
3481
|
+
pause: () => import("./pause-C_Wxh-KM.mjs").then((module) => module.pause),
|
|
3482
|
+
continue: () => import("./pause-C_Wxh-KM.mjs").then((module) => module.continueRun),
|
|
3046
3483
|
stop,
|
|
3047
3484
|
chat,
|
|
3048
|
-
once: () => import("./once-
|
|
3049
|
-
send: () => import("./send-
|
|
3485
|
+
once: () => import("./once-BHxSdZz_.mjs").then((module) => module.once),
|
|
3486
|
+
send: () => import("./send-nrKtak5F.mjs").then((module) => module.send),
|
|
3050
3487
|
resume,
|
|
3051
3488
|
feedback,
|
|
3052
|
-
"follow-ups": () => import("./follow-ups-
|
|
3489
|
+
"follow-ups": () => import("./follow-ups-CtlhHbwe.mjs").then((module) => module.followUps),
|
|
3053
3490
|
context,
|
|
3054
|
-
worktrees: () => import("./worktrees-
|
|
3055
|
-
wt: () => import("./worktrees-
|
|
3056
|
-
watch: () => import("./watch-
|
|
3057
|
-
mcp: () => import("./mcp-
|
|
3058
|
-
ui: () => import("./ui-
|
|
3491
|
+
worktrees: () => import("./worktrees-CZvbHzbN.mjs").then((module) => module.worktrees),
|
|
3492
|
+
wt: () => import("./worktrees-CZvbHzbN.mjs").then((module) => module.worktrees),
|
|
3493
|
+
watch: () => import("./watch-CT0EtLPZ.mjs").then((module) => module.watch),
|
|
3494
|
+
mcp: () => import("./mcp-wGfkMCVF.mjs").then((module) => module.mcp),
|
|
3495
|
+
ui: () => import("./ui-DY3Dnpho.mjs").then((module) => module.ui),
|
|
3059
3496
|
doctor,
|
|
3060
3497
|
upgrade,
|
|
3061
|
-
completion: () => import("./completion-
|
|
3062
|
-
__complete: () => import("./completion-
|
|
3498
|
+
completion: () => import("./completion-DS0gCZRm.mjs").then((module) => module.completion),
|
|
3499
|
+
__complete: () => import("./completion-DS0gCZRm.mjs").then((module) => module.completeCommand(main))
|
|
3063
3500
|
}
|
|
3064
3501
|
});
|
|
3065
3502
|
// src/bin.ts
|
|
@@ -3081,7 +3518,7 @@ const main = defineCommand({
|
|
|
3081
3518
|
clearGitLocalEnv();
|
|
3082
3519
|
const argv = takePlainFlag(process.argv.slice(2));
|
|
3083
3520
|
if (argv[0] === "__complete") {
|
|
3084
|
-
const { printCompletions } = await import("./completion-
|
|
3521
|
+
const { printCompletions } = await import("./completion-DS0gCZRm.mjs");
|
|
3085
3522
|
await printCompletions(main, argv.slice(1));
|
|
3086
3523
|
} else if (process.env["ORK_UPDATE_CHECK_CHILD"] === "1") await runUpdateChild();
|
|
3087
3524
|
else {
|
|
@@ -3094,7 +3531,7 @@ else {
|
|
|
3094
3531
|
const dash = argv.indexOf("--");
|
|
3095
3532
|
const askedHelp = argv.slice(1, dash === -1 ? 0 : dash).some((arg) => arg === "--help" || arg === "-h");
|
|
3096
3533
|
if (argv[0] === "once" && dash !== -1 && !askedHelp) try {
|
|
3097
|
-
const { once } = await import("./once-
|
|
3534
|
+
const { once } = await import("./once-BHxSdZz_.mjs");
|
|
3098
3535
|
await runCommand(once, { rawArgs: argv.slice(1) });
|
|
3099
3536
|
} catch (error) {
|
|
3100
3537
|
console.error(error);
|