@krapht/ork 1.0.0-alpha.7 → 1.0.0-alpha.9
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__-BGoaUwLd.mjs → __build_info__-y1TPvZvp.mjs} +2 -2
- package/dist/bin.mjs +598 -51
- package/dist/{clean-BPITM-6p.mjs → clean-BRUXyk87.mjs} +5 -2
- package/dist/{completion-CCn8xWmO.mjs → completion-cpZHtv50.mjs} +5 -5
- package/dist/{context-CZNM454F.mjs → context-Dbay8l7P.mjs} +8 -7
- package/dist/{decide-DsA6kOT7.mjs → decide-BphP3ONM.mjs} +1 -1
- package/dist/{find-ntyniv2E.mjs → find-BXZjliwr.mjs} +1 -1
- package/dist/format-DeT7vL-8.mjs +191 -0
- package/dist/{in-a-run-D_fnj1Mw.mjs → in-a-run-C4E9HfED.mjs} +1 -1
- package/dist/{limits-BKzVMwkt.mjs → limits-CBeoYrUH.mjs} +1 -1
- package/dist/{list-D9HPWLPH.mjs → list-BmxgNyd3.mjs} +11 -4
- package/dist/{mcp-BFl3cIDp.mjs → mcp-DTreb7Nq.mjs} +6 -6
- package/dist/{output-CwqlG1Le.mjs → output-BVkI6ZVv.mjs} +1 -1
- package/dist/{pause-DhgKQORW.mjs → pause-h66SC4rV.mjs} +4 -4
- package/dist/{relay-Cp8JGrdv.mjs → relay-BxRhxL6n.mjs} +2 -2
- package/dist/{remove-CSpT_nJH.mjs → remove-CYGd9Csj.mjs} +14 -7
- package/dist/{send-CHiYkM6X.mjs → send-BskOwN4p.mjs} +3 -3
- package/dist/{src-BsLHKQRc.mjs → src-BwFxTank.mjs} +335 -107
- package/dist/{src-CUeMUVwW.mjs → src-W1i5Bl6N.mjs} +23 -9
- package/dist/{src-DhGLtYR-.mjs → src-bOImrq43.mjs} +30 -11
- package/dist/{src-BwnitlJh.mjs → src-xd9DbQw8.mjs} +8 -8
- package/dist/ui/assets/{app-D4CoH-lh.js → app-BMg0OOv4.js} +19 -19
- package/dist/ui/assets/app-C8uhHVYp.css +1 -0
- package/dist/ui/assets/{index-DxDGdEwz.js → index-DY1q4SDl.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-BxE0L7V0.mjs → ui-B46Z3e9E.mjs} +4 -4
- package/dist/{usage-BuzDsEhq.mjs → usage-DpHXbQEu.mjs} +5 -5
- package/dist/{watch-CCj0vU3B.mjs → watch-CJO1ee6Y.mjs} +6 -6
- package/dist/{workflows-BNCDD6J-.mjs → workflows-BJdSHnkr.mjs} +4 -3
- package/dist/{worktrees-DBBcaimX.mjs → worktrees-Ccf2lUhE.mjs} +72 -19
- package/package.json +1 -1
- package/dist/format-DaROJUgG.mjs +0 -662
- package/dist/ui/assets/app-Dt_tjFj6.css +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as gitOk, O as removeWorktree } from "./src-
|
|
1
|
+
import { A as gitOk, O as removeWorktree } from "./src-BwFxTank.mjs";
|
|
2
2
|
// ../core/src/worktree/clean.ts
|
|
3
3
|
/**
|
|
4
4
|
* @file What `ork worktrees clean` and `ork worktrees remove` do with what
|
|
@@ -11,6 +11,7 @@ const keyOf = (item) => item.branch ?? item.path ?? `${item.runId}/${item.nodeId
|
|
|
11
11
|
/** The reasons no `force` overrides: removing would break something. */
|
|
12
12
|
const MAIN_CHECKOUT = "checked out in the main checkout";
|
|
13
13
|
const RUN_GOING = "its run is still going";
|
|
14
|
+
const NOT_ORKS = "not created by Ork";
|
|
14
15
|
const kept = (item, skip) => ({
|
|
15
16
|
item,
|
|
16
17
|
removeWorktree: false,
|
|
@@ -19,6 +20,7 @@ const kept = (item, skip) => ({
|
|
|
19
20
|
});
|
|
20
21
|
/** What clean does with one item. */
|
|
21
22
|
const cleanStep = (item, options) => {
|
|
23
|
+
if (!item.recorded) return kept(item, NOT_ORKS);
|
|
22
24
|
if (item.inMainCheckout) return kept(item, MAIN_CHECKOUT);
|
|
23
25
|
if (item.heldBy !== void 0) return kept(item, `checked out in ${item.heldBy}`);
|
|
24
26
|
if (options.live?.has(item.runId) === true) return kept(item, RUN_GOING);
|
|
@@ -45,7 +47,8 @@ const stepActs = (step) => step.removeWorktree || step.deleteBranch || stepPrune
|
|
|
45
47
|
* What `ork worktrees clean` would do. A worktree with uncommitted changes, an
|
|
46
48
|
* unmerged branch, or a detached worktree holding commits no branch has, is
|
|
47
49
|
* kept unless `force`; one checked out in the main checkout or in a worktree
|
|
48
|
-
* Ork didn't create,
|
|
50
|
+
* Ork didn't create, whose run is still going, or an `ork/` branch no run
|
|
51
|
+
* recorded creating, is kept even then.
|
|
49
52
|
*/
|
|
50
53
|
const planClean = (items, filter, options) => items.filter((item) => filter.runId === void 0 || item.runId === filter.runId).filter((item) => filter.key === void 0 || keyOf(item) === filter.key).filter((item) => !filter.merged || item.merged).map((item) => cleanStep(item, options));
|
|
51
54
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as builtinWorkflowNames, n as pendingDecisions, o as builtinWorkflowText, s as isBuiltinArg } from "./decide-
|
|
3
|
-
import { t as findRun } from "./find-
|
|
4
|
-
import { c as openStore, l as storePath, o as writeErr } from "./output-
|
|
1
|
+
import { En as placeFor, Tn as placeFiles, bt as liveStatus, rr as NodeIdSchema, ur as CLAUDE_DRIVERS } from "./src-BwFxTank.mjs";
|
|
2
|
+
import { a as builtinWorkflowNames, n as pendingDecisions, o as builtinWorkflowText, s as isBuiltinArg } from "./decide-BphP3ONM.mjs";
|
|
3
|
+
import { t as findRun } from "./find-BXZjliwr.mjs";
|
|
4
|
+
import { c as openStore, l as storePath, o as writeErr } from "./output-BVkI6ZVv.mjs";
|
|
5
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-BwYoAWsh.mjs";
|
|
6
|
-
import { a as resolveWorkflowArg, n as WORKFLOW_SUFFIX } from "./workflows-
|
|
6
|
+
import { a as resolveWorkflowArg, n as WORKFLOW_SUFFIX } from "./workflows-BJdSHnkr.mjs";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { parse } from "yaml";
|
|
9
9
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as workflowTextHash,
|
|
2
|
-
import { a as write, i as style, r as plain } from "./output-
|
|
3
|
-
import { c as registeredProjects, i as refusedBuiltin, o as workflowArg, r as findWorkflowFiles, s as projectAt } from "./workflows-
|
|
1
|
+
import { An as workflowDirOf, C as workflowTextHash, En as placeFor, Nn as LESSON_CAP_TOKENS, S as readProjectTriggers, Tn as placeFiles, ht as walkSummary, mt as walkChecks, pt as checkWorkflowText, st as explainSession } from "./src-BwFxTank.mjs";
|
|
2
|
+
import { a as write, i as style, r as plain } from "./output-BVkI6ZVv.mjs";
|
|
3
|
+
import { c as registeredProjects, i as refusedBuiltin, o as workflowArg, r as findWorkflowFiles, s as projectAt } from "./workflows-BJdSHnkr.mjs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
import { defineCommand } from "citty";
|
|
@@ -10,7 +10,8 @@ import { defineCommand } from "citty";
|
|
|
10
10
|
* and with `--paths`, each way a run can end. A gate's answer that ends the
|
|
11
11
|
* run shows here as an ending, not as a problem.
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
/** The walk's one line; unless `--paths` is on, it points there for each ending. */
|
|
14
|
+
const walkLine = (walk, showsPaths = false) => walk === void 0 ? [] : [style("dim", showsPaths ? walkSummary(walk) : `${walkSummary(walk)} See each with \`ork validate --paths\`.`)];
|
|
14
15
|
const endingLine = ({ status, notRun, paths }) => {
|
|
15
16
|
const ways = `${String(paths)} ${paths === 1 ? "way" : "ways"}`;
|
|
16
17
|
const word = status === "succeeded" ? style("green", status) : style("red", status);
|
|
@@ -109,7 +110,7 @@ const diagnosticLine = (file, d) => {
|
|
|
109
110
|
/** The warnings alone, for a run that goes ahead despite them. */
|
|
110
111
|
const warningLines = (report) => report.diagnostics.filter((d) => d.severity === "warning").map((d) => diagnosticLine(report.file, d));
|
|
111
112
|
/** Human-readable report, one line per diagnostic, compiler style. */
|
|
112
|
-
const formatReport = (report) => {
|
|
113
|
+
const formatReport = (report, showsPaths = false) => {
|
|
113
114
|
const lines = report.diagnostics.map((d) => diagnosticLine(report.file, d));
|
|
114
115
|
const errors = report.diagnostics.filter((d) => d.severity === "error").length;
|
|
115
116
|
const warnings = report.diagnostics.length - errors;
|
|
@@ -119,7 +120,7 @@ const formatReport = (report) => {
|
|
|
119
120
|
const extra = warnings > 0 ? `, ${plural(warnings, "warning")}` : "";
|
|
120
121
|
lines.push(`${style("green", "✓")} ${report.file} ${style("dim", `(${plural(nodes, "node")}, ${plural(edges, "edge")}, starts at ${entries.join(", ")}${extra})`)}`);
|
|
121
122
|
} else lines.push(`${style("red", "✗")} ${report.file} ${style("dim", `(${plural(errors, "error")}, ${plural(warnings, "warning")})`)}`);
|
|
122
|
-
return [...lines, ...walkLine(report.walk)];
|
|
123
|
+
return [...lines, ...walkLine(report.walk, showsPaths)];
|
|
123
124
|
};
|
|
124
125
|
const validate = defineCommand({
|
|
125
126
|
meta: {
|
|
@@ -165,7 +166,7 @@ const validate = defineCommand({
|
|
|
165
166
|
}] : []];
|
|
166
167
|
if (args.json) write(JSON.stringify(reports, void 0, 2));
|
|
167
168
|
else for (const report of reports) {
|
|
168
|
-
for (const line of formatReport(report)) write(line);
|
|
169
|
+
for (const line of formatReport(report, args.paths)) write(line);
|
|
169
170
|
if (args.paths) for (const line of pathLines(report.walk)) write(line);
|
|
170
171
|
}
|
|
171
172
|
if (reports.some((r) => hasErrors(r.diagnostics))) process.exitCode = 1;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fn as guardedBase, In as plainPathInside, Ln as writePlainFile, Tn as placeFiles, bt as liveStatus, cn as wakeRun, on as socketPath } from "./src-BwFxTank.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { Ot as isItem, bt as liveStatus } from "./src-BwFxTank.mjs";
|
|
2
|
+
import { i as style, n as cost } from "./output-BVkI6ZVv.mjs";
|
|
3
|
+
// src/run/format-bus.ts
|
|
4
|
+
/** The first line of a message body, cut to fit one terminal line. */
|
|
5
|
+
const firstLine = (body) => {
|
|
6
|
+
const [line = ""] = body.trim().split("\n");
|
|
7
|
+
return line.length > 100 ? `${line.slice(0, 99)}…` : line;
|
|
8
|
+
};
|
|
9
|
+
/** Messages, owner questions and claims, without the node prefix. */
|
|
10
|
+
const formatBusEvent = (event) => {
|
|
11
|
+
if (event.type === "claim.taken") return [style("dim", `⚑ claimed ${event.resource}`)];
|
|
12
|
+
if (event.type === "claim.refused") {
|
|
13
|
+
const held = event.held === event.resource ? "" : ` (it holds ${event.held})`;
|
|
14
|
+
return [style("yellow", `⚑ ${event.resource} is ${event.holder}'s${held}`)];
|
|
15
|
+
}
|
|
16
|
+
if (event.type === "claim.released") return [style("dim", `⚑ released ${event.resource}`)];
|
|
17
|
+
if (event.type === "message.sent") {
|
|
18
|
+
const how = event.via === void 0 ? "" : ` (${event.via})`;
|
|
19
|
+
return [style("dim", `✉ to ${event.to}${how}: ${firstLine(event.body)}`)];
|
|
20
|
+
}
|
|
21
|
+
if (event.type === "message.received") {
|
|
22
|
+
const how = event.via === void 0 ? "" : ` (${event.via})`;
|
|
23
|
+
return [style("dim", `✉ from ${event.from}${how}: ${firstLine(event.body)}`)];
|
|
24
|
+
}
|
|
25
|
+
if (event.type === "call.started") return [style("dim", `↳ started ${event.workflow} as run ${event.run}`)];
|
|
26
|
+
if (event.type === "link.notice") return [style("dim", `↔ ${event.text}`)];
|
|
27
|
+
if (event.type === "message.read") return [];
|
|
28
|
+
if (event.type === "owner.asked") return [`${style(["yellow", "bold"], "?")} asked as the owner of ${event.about}: ${event.text} ${style("dim", `(${event.question})`)}`];
|
|
29
|
+
if (event.type === "owner.answered") return [style("dim", `→ ${event.answer} (owner)`)];
|
|
30
|
+
return [style("dim", "→ its session ended first; asking you")];
|
|
31
|
+
};
|
|
32
|
+
// src/run/items-ran.ts
|
|
33
|
+
/**
|
|
34
|
+
* @file How a fan-out's finished line counts its items: only the ones that
|
|
35
|
+
* started.
|
|
36
|
+
*/
|
|
37
|
+
/** How many of a fan-out's items started; a skipped one never did. */
|
|
38
|
+
const itemsRan = (count, statuses) => {
|
|
39
|
+
const ran = Array.isArray(statuses) ? statuses.filter((status) => status !== "skipped").length : count;
|
|
40
|
+
return ran === count ? `${String(count)} ran` : `${String(ran)} of ${String(count)} ran`;
|
|
41
|
+
};
|
|
42
|
+
// src/run/verdict.ts
|
|
43
|
+
/**
|
|
44
|
+
* @file The one-line verdict of a finished node: its report's status, unless
|
|
45
|
+
* the node failed or its work did not merge.
|
|
46
|
+
*/
|
|
47
|
+
/** Whether a finished node's work did not merge into its owner. */
|
|
48
|
+
const hasConflict = (output) => {
|
|
49
|
+
const { merge } = output;
|
|
50
|
+
return typeof merge === "object" && merge !== null && "ok" in merge && merge.ok === false;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* A one-line verdict for a finished node, by what its type outputs. A node that
|
|
54
|
+
* failed reads `fail` even when its report said `pass` (a hook refused its
|
|
55
|
+
* commit); a child that did not merge says so.
|
|
56
|
+
*/
|
|
57
|
+
const nodeVerdict = (output, ok = true, error) => {
|
|
58
|
+
const { status, summary, exitCode, choice, answeredBy, count } = output;
|
|
59
|
+
if (typeof status === "string") {
|
|
60
|
+
if (!ok && (status === "pass" || status === "done")) return error === void 0 ? "fail" : `fail: ${firstLine(error)}`;
|
|
61
|
+
const label = hasConflict(output) ? `${status}, merge conflict` : status;
|
|
62
|
+
return typeof summary === "string" && summary !== "" ? `${label}: ${summary}` : label;
|
|
63
|
+
}
|
|
64
|
+
if (typeof exitCode === "number") return `exit ${String(exitCode)}`;
|
|
65
|
+
if (typeof choice === "string") return `${choice} (${String(answeredBy)})`;
|
|
66
|
+
if (typeof count === "number") return itemsRan(count, output["statuses"]);
|
|
67
|
+
return "done";
|
|
68
|
+
};
|
|
69
|
+
// src/runs/format.ts
|
|
70
|
+
/**
|
|
71
|
+
* @file How stored runs read on the terminal: the `ork ps` table and the `ork
|
|
72
|
+
* tree` ownership tree with each node's state, tokens and cost, and what is
|
|
73
|
+
* paused (ADR-041).
|
|
74
|
+
*/
|
|
75
|
+
const STATUS_STYLE = {
|
|
76
|
+
running: "cyan",
|
|
77
|
+
paused: "yellow",
|
|
78
|
+
succeeded: "green",
|
|
79
|
+
failed: "red",
|
|
80
|
+
crashed: "red",
|
|
81
|
+
budget_exhausted: "yellow",
|
|
82
|
+
quota_exhausted: "yellow",
|
|
83
|
+
timed_out: "yellow",
|
|
84
|
+
interrupted: "yellow"
|
|
85
|
+
};
|
|
86
|
+
/** `just now`, `5m ago`, `3h ago`, `2d ago`, then the date. */
|
|
87
|
+
const ago = (iso, now = Date.now()) => {
|
|
88
|
+
const minutes = Math.floor((now - Date.parse(iso)) / 6e4);
|
|
89
|
+
if (minutes < 1) return "just now";
|
|
90
|
+
if (minutes < 60) return `${String(minutes)}m ago`;
|
|
91
|
+
if (minutes < 1440) return `${String(Math.floor(minutes / 60))}h ago`;
|
|
92
|
+
if (minutes < 10080) return `${String(Math.floor(minutes / 1440))}d ago`;
|
|
93
|
+
return iso.slice(0, 10);
|
|
94
|
+
};
|
|
95
|
+
/** `42s`, `3m12s`, `1h05m`. */
|
|
96
|
+
const duration = (ms) => {
|
|
97
|
+
const s = Math.max(0, Math.round(ms / 1e3));
|
|
98
|
+
if (s < 60) return `${String(s)}s`;
|
|
99
|
+
if (s < 3600) return `${String(Math.floor(s / 60))}m${String(s % 60).padStart(2, "0")}s`;
|
|
100
|
+
return `${String(Math.floor(s / 3600))}h${String(Math.floor(s % 3600 / 60)).padStart(2, "0")}m`;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* The `ork ps` table; `withProject` adds each run's project. A called run's
|
|
104
|
+
* cost is dimmed and says its caller's, whose cost already counts it.
|
|
105
|
+
*/
|
|
106
|
+
const formatRuns = (runs, withProject, now = Date.now(), statusOf = liveStatus) => {
|
|
107
|
+
if (runs.length === 0) return ["No runs."];
|
|
108
|
+
const rows = runs.map((run) => {
|
|
109
|
+
const status = statusOf(run);
|
|
110
|
+
const end = run.finishedAt === void 0 ? now : Date.parse(run.finishedAt);
|
|
111
|
+
return {
|
|
112
|
+
id: run.id,
|
|
113
|
+
workflow: run.workflow,
|
|
114
|
+
status,
|
|
115
|
+
when: `${ago(run.startedAt, now)} · ${duration(end - Date.parse(run.startedAt))}`,
|
|
116
|
+
cost: run.parent === void 0 ? cost(run.costUsd) : `${cost(run.costUsd)} in ${run.parent}`,
|
|
117
|
+
called: run.parent !== void 0,
|
|
118
|
+
project: run.project
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
const width = (pick, title) => Math.max(title.length, ...rows.map((r) => pick(r).length));
|
|
122
|
+
const w = {
|
|
123
|
+
id: width((r) => r.id, "RUN"),
|
|
124
|
+
workflow: width((r) => r.workflow, "WORKFLOW"),
|
|
125
|
+
status: width((r) => r.status, "STATUS"),
|
|
126
|
+
when: width((r) => r.when, "STARTED"),
|
|
127
|
+
cost: width((r) => r.cost, "COST")
|
|
128
|
+
};
|
|
129
|
+
const header = [
|
|
130
|
+
"RUN".padEnd(w.id),
|
|
131
|
+
"WORKFLOW".padEnd(w.workflow),
|
|
132
|
+
"STATUS".padEnd(w.status),
|
|
133
|
+
"STARTED".padEnd(w.when),
|
|
134
|
+
"COST".padStart(w.cost),
|
|
135
|
+
...withProject ? ["PROJECT"] : []
|
|
136
|
+
].join(" ");
|
|
137
|
+
return [style("dim", header), ...rows.map((r) => [
|
|
138
|
+
style("bold", r.id.padEnd(w.id)),
|
|
139
|
+
r.workflow.padEnd(w.workflow),
|
|
140
|
+
style(STATUS_STYLE[r.status] ?? "reset", r.status.padEnd(w.status)),
|
|
141
|
+
style("dim", r.when.padEnd(w.when)),
|
|
142
|
+
r.called ? style("dim", r.cost.padStart(w.cost)) : r.cost.padStart(w.cost),
|
|
143
|
+
...withProject ? [style("dim", r.project)] : []
|
|
144
|
+
].join(" "))];
|
|
145
|
+
};
|
|
146
|
+
const STATE_MARK = {
|
|
147
|
+
waiting: style("dim", "·"),
|
|
148
|
+
running: style("cyan", "●"),
|
|
149
|
+
ok: style("green", "✓"),
|
|
150
|
+
failed: style("red", "✗"),
|
|
151
|
+
skipped: style("dim", "-")
|
|
152
|
+
};
|
|
153
|
+
/** `950`, `12.3k`, `1.2M`. */
|
|
154
|
+
const count = (n) => {
|
|
155
|
+
if (n < 1e3) return String(n);
|
|
156
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(1)}k`;
|
|
157
|
+
return `${(n / 1e6).toFixed(1)}M`;
|
|
158
|
+
};
|
|
159
|
+
const stateText = (node) => {
|
|
160
|
+
if (node.state === "running") return node.runs > 1 ? `running (round ${String(node.runs)})` : "running";
|
|
161
|
+
if (node.state === "ok" || node.state === "failed") {
|
|
162
|
+
const verdict = nodeVerdict(node.output ?? {}, node.state === "ok");
|
|
163
|
+
const line = verdict.length > 60 ? `${verdict.slice(0, 59)}…` : verdict;
|
|
164
|
+
return node.runs > 1 ? `${line} (${String(node.runs)} runs)` : line;
|
|
165
|
+
}
|
|
166
|
+
return node.state;
|
|
167
|
+
};
|
|
168
|
+
/** The ownership tree, one line per node, children under their owner. */
|
|
169
|
+
const formatTree = (roots, now = Date.now()) => {
|
|
170
|
+
const lines = [];
|
|
171
|
+
const walk = (node, lead, branch) => {
|
|
172
|
+
lines.push({
|
|
173
|
+
label: `${lead}${branch}${node.id}`,
|
|
174
|
+
node
|
|
175
|
+
});
|
|
176
|
+
const next = lead + (branch === "├─ " ? "│ " : branch === "" ? "" : " ");
|
|
177
|
+
node.children.forEach((child, index) => {
|
|
178
|
+
walk(child, next, index === node.children.length - 1 ? "└─ " : "├─ ");
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
for (const root of roots) walk(root, "", "");
|
|
182
|
+
const label = Math.max(...lines.map((l) => l.label.length));
|
|
183
|
+
const type = Math.max(...lines.map((l) => l.node.type.length));
|
|
184
|
+
return lines.map(({ label: text, node }) => {
|
|
185
|
+
const usage = node.inputTokens + node.outputTokens === 0 ? "" : style("dim", ` ${count(node.inputTokens)} in / ${count(node.outputTokens)} out · ${cost(node.costUsd)}`);
|
|
186
|
+
const state = node.held === true ? `${style("yellow", "‖")} paused` : `${STATE_MARK[node.state]} ${stateText(node)}`;
|
|
187
|
+
const spent = isItem(node) && node.startedAt !== void 0 ? style("dim", ` ${duration((node.finishedAt === void 0 ? now : Date.parse(node.finishedAt)) - Date.parse(node.startedAt))}`) : "";
|
|
188
|
+
return `${text.padEnd(label)} ${style("dim", node.type.padEnd(type))} ${state}${spent}${usage}`;
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
export { nodeVerdict as a, hasConflict as i, formatRuns as n, firstLine as o, formatTree as r, formatBusEvent as s, ago as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as limitsNow, i as NOT_STARTED, o as limitsReport, r as capsHere } from "./src-
|
|
1
|
+
import { a as limitsNow, i as NOT_STARTED, o as limitsReport, r as capsHere } from "./src-BwFxTank.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,4 +1,4 @@
|
|
|
1
|
-
import { A as gitOk, j as lines, k as git } from "./src-
|
|
1
|
+
import { A as gitOk, j as lines, k as git } from "./src-BwFxTank.mjs";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
// ../core/src/worktree/list.ts
|
|
4
4
|
/**
|
|
@@ -56,7 +56,7 @@ const onNoBranch = async (entry) => entry === void 0 ? "0" : (await git(entry.pa
|
|
|
56
56
|
"--remotes"
|
|
57
57
|
])).stdout;
|
|
58
58
|
/** One created worktree or branch, with its state read from git. */
|
|
59
|
-
const stateOf = async (root, entries, item) => {
|
|
59
|
+
const stateOf = async (root, entries, item, recorded) => {
|
|
60
60
|
const { branch } = item;
|
|
61
61
|
const entry = branch === void 0 || item.path !== "" ? entries.find((e) => e.path === item.path) : entries.find((e) => e.branch === branch);
|
|
62
62
|
const holder = branch === void 0 ? void 0 : entries.find((e) => e.branch === branch && e.path !== entry?.path);
|
|
@@ -76,6 +76,7 @@ const stateOf = async (root, entries, item) => {
|
|
|
76
76
|
...checkedOut === void 0 ? {} : { checkedOut },
|
|
77
77
|
runId: item.runId,
|
|
78
78
|
nodeId: item.nodeId,
|
|
79
|
+
recorded,
|
|
79
80
|
path: entry?.path ?? null,
|
|
80
81
|
missing,
|
|
81
82
|
dirty: changes > 0,
|
|
@@ -104,7 +105,13 @@ const listOrkWorktrees = async (root, created = []) => {
|
|
|
104
105
|
"refs/heads/"
|
|
105
106
|
]));
|
|
106
107
|
const recordedBranches = new Set(created.flatMap((c) => c.branch ?? []));
|
|
107
|
-
const items = [...created.filter((c) => c.branch === void 0 ? entries.some((e) => e.path === c.path) : branches.includes(c.branch))
|
|
108
|
-
|
|
108
|
+
const items = [...created.filter((c) => c.branch === void 0 ? entries.some((e) => e.path === c.path) : branches.includes(c.branch)).map((item) => ({
|
|
109
|
+
item,
|
|
110
|
+
recorded: true
|
|
111
|
+
})), ...branches.filter((b) => b.startsWith("ork/") && !recordedBranches.has(b)).map((b) => ({
|
|
112
|
+
item: prefixed(b),
|
|
113
|
+
recorded: false
|
|
114
|
+
}))];
|
|
115
|
+
return Promise.all(items.map(({ item, recorded }) => stateOf(root, entries, item, recorded)));
|
|
109
116
|
};
|
|
110
117
|
export { listOrkWorktrees as n, createdWorktrees as t };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { h as isNewer } from "./src-
|
|
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 { h as isNewer } from "./src-BwFxTank.mjs";
|
|
2
|
+
import { n as ORK_VERSION } from "./__build_info__-y1TPvZvp.mjs";
|
|
3
|
+
import { p as runMarkerIn } from "./src-W1i5Bl6N.mjs";
|
|
4
|
+
import { n as explainNode } from "./context-Dbay8l7P.mjs";
|
|
5
|
+
import { a as openMcp, c as refused, o as tool, s as answer } from "./src-xd9DbQw8.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.9") ? tooOld(all, options.expects) : all;
|
|
47
47
|
const server = new McpServer({
|
|
48
48
|
name: "ork",
|
|
49
49
|
version: ORK_VERSION
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Gt as FEEDBACK_TARGETS, J as backfillUsage, Q as text, Tt as ownProcessStart, Ut as FEEDBACK_KINDS, Wt as FEEDBACK_SEVERITIES, X as eventOf, Y as usageQueries, Z as inTransaction, ln as maskReplacer, un as maskSecrets, xn as PROJECT_MODES } from "./src-BwFxTank.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { mkdirSync } from "node:fs";
|
|
4
4
|
import { homedir } from "node:os";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { G as requestPause, W as requestContinue } from "./src-
|
|
2
|
-
import { t as findRun } from "./find-
|
|
3
|
-
import { a as write, c as openStore, i as style, o as writeErr } from "./output-
|
|
4
|
-
import { r as continueRefusal } from "./in-a-run-
|
|
1
|
+
import { G as requestPause, W as requestContinue } from "./src-BwFxTank.mjs";
|
|
2
|
+
import { t as findRun } from "./find-BXZjliwr.mjs";
|
|
3
|
+
import { a as write, c as openStore, i as style, o as writeErr } from "./output-BVkI6ZVv.mjs";
|
|
4
|
+
import { r as continueRefusal } from "./in-a-run-C4E9HfED.mjs";
|
|
5
5
|
import { defineCommand } from "citty";
|
|
6
6
|
// src/commands/pause.ts
|
|
7
7
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { H as unlinkNodes, I as addressOf, z as linkNodes } from "./src-
|
|
2
|
-
import { a as write, c as openStore, i as style, o as writeErr } from "./output-
|
|
1
|
+
import { H as unlinkNodes, I as addressOf, z as linkNodes } from "./src-BwFxTank.mjs";
|
|
2
|
+
import { a as write, c as openStore, i as style, o as writeErr } from "./output-BVkI6ZVv.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
// src/commands/relay.ts
|
|
5
5
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { bt as liveStatus, j as lines, k as git } from "./src-
|
|
2
|
-
import { n as listOrkWorktrees, t as createdWorktrees } from "./list-
|
|
3
|
-
import { i as keyOf, n as applyStep, r as cleanStep, s as stepPrunes } from "./clean-
|
|
1
|
+
import { bt as liveStatus, j as lines, k as git } from "./src-BwFxTank.mjs";
|
|
2
|
+
import { n as listOrkWorktrees, t as createdWorktrees } from "./list-BmxgNyd3.mjs";
|
|
3
|
+
import { i as keyOf, n as applyStep, r as cleanStep, s as stepPrunes } from "./clean-BRUXyk87.mjs";
|
|
4
4
|
// ../core/src/worktree/words.ts
|
|
5
5
|
/**
|
|
6
6
|
* @file The plain words for what `ork worktrees` shows, in one place, so the
|
|
@@ -45,6 +45,7 @@ const stateParts = (item, into) => {
|
|
|
45
45
|
if (item.ahead > 0) part(`${counted(item.ahead, "commit")} on no branch`, true);
|
|
46
46
|
else if (item.path !== null && !item.missing) part("nothing committed");
|
|
47
47
|
}
|
|
48
|
+
if (!item.recorded) part("not created by Ork");
|
|
48
49
|
if (item.inMainCheckout) part("checked out in the main checkout");
|
|
49
50
|
if (item.heldBy !== void 0) part(`checked out in ${item.heldBy}`);
|
|
50
51
|
return parts;
|
|
@@ -67,11 +68,12 @@ const planLine = (step) => {
|
|
|
67
68
|
};
|
|
68
69
|
};
|
|
69
70
|
/**
|
|
70
|
-
* Why an item can't be removed at all, even forced, if it can't:
|
|
71
|
-
* checkout or a worktree Ork didn't create holds
|
|
72
|
-
* going.
|
|
71
|
+
* Why an item can't be removed at all, even forced, if it can't: no run
|
|
72
|
+
* recorded creating it, the main checkout or a worktree Ork didn't create holds
|
|
73
|
+
* it, or its run is still going.
|
|
73
74
|
*/
|
|
74
75
|
const removeRefusal = (item, live) => {
|
|
76
|
+
if (!item.recorded) return "not created by Ork (no run recorded it); delete it with git if it's yours to delete";
|
|
75
77
|
if (item.inMainCheckout) return "checked out in the main checkout; switch it to another branch first";
|
|
76
78
|
if (item.heldBy !== void 0) return `checked out in ${item.heldBy}, a worktree Ork didn't create; switch it to another branch first`;
|
|
77
79
|
return live ? `run ${item.runId} is still going; stop it first` : void 0;
|
|
@@ -101,6 +103,11 @@ const projectHead = async (root) => {
|
|
|
101
103
|
branch: answer.code === 0 ? answer.stdout.trim() : null
|
|
102
104
|
};
|
|
103
105
|
};
|
|
106
|
+
/** The top of the repository `cwd` is in, even one with no commit yet. */
|
|
107
|
+
const repoRoot = async (cwd) => {
|
|
108
|
+
const top = await git(cwd, ["rev-parse", "--show-toplevel"]);
|
|
109
|
+
return top.code === 0 ? top.stdout.trim() : null;
|
|
110
|
+
};
|
|
104
111
|
/** What Ork created in the repo at `root`, from its runs' records and git. */
|
|
105
112
|
const readWorktrees = async (store, root) => ({
|
|
106
113
|
items: await listOrkWorktrees(root, createdWorktrees(store, root)),
|
|
@@ -191,4 +198,4 @@ const applyRemove = async (root, { step, force }, done = []) => {
|
|
|
191
198
|
await applyStep(root, step, force, done);
|
|
192
199
|
return done;
|
|
193
200
|
};
|
|
194
|
-
export { readWorktrees as a,
|
|
201
|
+
export { readWorktrees as a, mergeStateOf as c, stateParts as d, projectHead as i, planLine as l, lostWork as n, repoRoot as o, planRemove as r, labelOf as s, applyRemove as t, removeRefusal as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { bt as liveStatus,
|
|
2
|
-
import { c as openStore, o as writeErr } from "./output-
|
|
3
|
-
import { u as inheritedScrubber } from "./src-
|
|
1
|
+
import { bt as liveStatus, cn as wakeRun, jt as scriptContactsOf, on as socketPath } from "./src-BwFxTank.mjs";
|
|
2
|
+
import { c as openStore, o as writeErr } from "./output-BVkI6ZVv.mjs";
|
|
3
|
+
import { u as inheritedScrubber } from "./src-W1i5Bl6N.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
// ../core/src/remote/send.ts
|
|
6
6
|
/**
|