@krapht/ork 1.0.0-alpha.12 → 1.0.0-alpha.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{__build_info__-BJbE3Zvp.mjs → __build_info__-B82-dGJY.mjs} +3 -3
- package/dist/{attach-BmV5ckb9.mjs → attach-CdtGX9se.mjs} +5 -5
- package/dist/bin.mjs +274 -236
- package/dist/{builtin-files-w0YULJ4c.mjs → builtin-files-Bdq23IIi.mjs} +2 -2
- package/dist/{chips-CyeB_rhR.mjs → chips-BqcT58qr.mjs} +1 -1
- package/dist/{completion-CzElB8nS.mjs → completion--ywde-56.mjs} +52 -11
- package/dist/{context-BAwgVSX5.mjs → context-Y_I4Mofq.mjs} +18 -8
- package/dist/{find-p05wlbmu.mjs → find-BVX-bL4u.mjs} +1 -1
- package/dist/{format-Dni98cbh.mjs → format-CvTE5CZQ.mjs} +12 -12
- package/dist/{help-groups-DYP_zMRP.mjs → help-groups-CpR2UzSn.mjs} +20 -6
- package/dist/{in-a-run-BI-hLIl_.mjs → in-a-run-cL5N9gpH.mjs} +1 -1
- package/dist/{limits-CElmhowV.mjs → limits-Dhe--wmX.mjs} +2 -2
- package/dist/{mcp-CM3b65AZ.mjs → mcp-CsmboyXv.mjs} +6 -6
- package/dist/once-CrwI-ZdN.mjs +76 -0
- package/dist/{output-CnRzrbUM.mjs → output-B1kwo0YU.mjs} +17 -1
- package/dist/{pause-BuS83WAI.mjs → pause-DssrYcda.mjs} +4 -4
- package/dist/{relay-DAsJA8wF.mjs → relay-DASRgsTQ.mjs} +2 -2
- package/dist/run-D8divGCs.mjs +192 -0
- package/dist/send-CXv8bx0i.mjs +105 -0
- package/dist/{src-S9yK2OHU.mjs → src-8Mul0695.mjs} +8 -10
- package/dist/{src-BfxkJOYm.mjs → src-C7z_6fhn.mjs} +200 -72
- package/dist/{src-D1QedD5y.mjs → src-njdtejgZ.mjs} +140 -38
- package/dist/{src-CdDTQLdQ.mjs → src-tsuZRu0H.mjs} +2787 -1134
- package/dist/{store-B2OaE4ID.mjs → store-CleF7KeS.mjs} +33 -76
- package/dist/ui/THIRD_PARTY_LICENSES.txt +18 -0
- package/dist/ui/assets/app-D_nAPnHM.css +1 -0
- package/dist/ui/assets/app-DqBAtXSZ.js +111 -0
- package/dist/ui/assets/{index-BL7Ad0OA.js → index-D-_uPI2v.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-C4Ys26oO.mjs → ui-CNO1M0qT.mjs} +4 -4
- package/dist/{usage-C2zx-X6q.mjs → usage-BVXi0iFY.mjs} +13 -141
- package/dist/{verdict-CIy8tAyX.mjs → verdict-CMvPCpWC.mjs} +2 -2
- package/dist/{watch-DzCeqM05.mjs → watch-DVNIciHp.mjs} +10 -8
- package/dist/{workflows-Rr5w90A0.mjs → workflows-B30QkwTk.mjs} +3 -3
- package/dist/{worktrees-f6SAbum5.mjs → worktrees-DD4_TpkH.mjs} +3 -5
- package/package.json +2 -2
- package/dist/clean-D8GI_2K-.mjs +0 -91
- package/dist/decide-DlbyctOE.mjs +0 -50
- package/dist/list-zW2xKuGr.mjs +0 -117
- package/dist/remove-Dh7D_hVn.mjs +0 -201
- package/dist/report-CEN8VoUb.mjs +0 -140
- package/dist/send-MFEQZH31.mjs +0 -163
- package/dist/ui/assets/app-CAoZtku5.js +0 -75
- package/dist/ui/assets/app-QoHVi-mb.css +0 -1
package/dist/ui/index.html
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
href="/favicon.svg"
|
|
20
20
|
type="image/svg+xml"
|
|
21
21
|
/>
|
|
22
|
-
<script type="module" crossorigin src="/assets/index-
|
|
22
|
+
<script type="module" crossorigin src="/assets/index-D-_uPI2v.js"></script>
|
|
23
23
|
<link rel="modulepreload" crossorigin href="/assets/theme-CdXvqTQ6.js">
|
|
24
24
|
<link rel="stylesheet" crossorigin href="/assets/index-BPIbqRRb.css">
|
|
25
25
|
</head>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { n as ORK_VERSION, t as ORK_NAME } from "./__build_info__-
|
|
2
|
-
import {
|
|
3
|
-
import { o as mayShowSignIn } from "./in-a-run-
|
|
4
|
-
import { i as uiFilePath, l as newToken, n as startServer, r as runningServer, t as DEFAULT_PORT } from "./src-
|
|
1
|
+
import { n as ORK_VERSION, t as ORK_NAME } from "./__build_info__-B82-dGJY.mjs";
|
|
2
|
+
import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
|
|
3
|
+
import { o as mayShowSignIn } from "./in-a-run-cL5N9gpH.mjs";
|
|
4
|
+
import { i as uiFilePath, l as newToken, n as startServer, r as runningServer, t as DEFAULT_PORT } from "./src-8Mul0695.mjs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { constants } from "node:os";
|
|
7
7
|
import { spawn } from "node:child_process";
|
|
@@ -1,137 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as
|
|
3
|
-
import { n as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { n as limitsHere } from "./limits-CElmhowV.mjs";
|
|
7
|
-
import { a as header, o as table } from "./format-Dni98cbh.mjs";
|
|
8
|
-
import { existsSync, rmSync } from "node:fs";
|
|
1
|
+
import { At as usd, G as applyPrune, K as planPrune, S as usageReport, U as openStore, mr as placeFor, x as USAGE_DIMENSIONS } from "./src-tsuZRu0H.mjs";
|
|
2
|
+
import { C as termOf, c as write, l as writeErr, n as cost, o as shortCount, r as costOf, s as style, t as confirm } from "./output-B1kwo0YU.mjs";
|
|
3
|
+
import { n as chip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
|
|
4
|
+
import { n as limitsHere } from "./limits-Dhe--wmX.mjs";
|
|
5
|
+
import { a as header, o as table } from "./format-CvTE5CZQ.mjs";
|
|
9
6
|
import { defineCommand } from "citty";
|
|
10
|
-
// ../core/src/store/prune.ts
|
|
11
|
-
/**
|
|
12
|
-
* @file `ork prune` (ADR-046): which runs may lose their transcript, and doing
|
|
13
|
-
* it. A run goes with the runs it called or was called by, or not at all, and
|
|
14
|
-
* not while it is live, is linked, or has a worktree or branch left: those
|
|
15
|
-
* read the run's events. The usage ledger and feedback records stay.
|
|
16
|
-
*/
|
|
17
|
-
const messageOf = (error) => error instanceof Error ? error.message : String(error);
|
|
18
|
-
/**
|
|
19
|
-
* The runs in a project that still have a worktree or branch. With its folder
|
|
20
|
-
* gone, or no longer a repository, there is nothing left to clean up; any other
|
|
21
|
-
* failure says nothing about them, so it rejects.
|
|
22
|
-
*/
|
|
23
|
-
const runsWithWorktrees = (store) => async (root) => {
|
|
24
|
-
if (!existsSync(root)) return /* @__PURE__ */ new Set();
|
|
25
|
-
try {
|
|
26
|
-
const found = await listOrkWorktrees(root, createdWorktrees(store, root));
|
|
27
|
-
return new Set(found.map((w) => w.runId));
|
|
28
|
-
} catch (error) {
|
|
29
|
-
if (/not a git repository/iu.test(messageOf(error))) return /* @__PURE__ */ new Set();
|
|
30
|
-
throw error;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
/** The run at the top of a run's chain of calls. */
|
|
34
|
-
const callRootOf = (run, byId) => {
|
|
35
|
-
let top = run;
|
|
36
|
-
const seen = /* @__PURE__ */ new Set([run.id]);
|
|
37
|
-
while (top.parent !== void 0) {
|
|
38
|
-
const parent = byId.get(top.parent);
|
|
39
|
-
if (parent === void 0 || seen.has(parent.id)) break;
|
|
40
|
-
seen.add(parent.id);
|
|
41
|
-
top = parent;
|
|
42
|
-
}
|
|
43
|
-
return top.id;
|
|
44
|
-
};
|
|
45
|
-
/** Sorts the runs before the cutoff into those to remove and those to keep. */
|
|
46
|
-
const planPrune = async (store, filter, worktreesOf = runsWithWorktrees(store)) => {
|
|
47
|
-
const all = store.runs();
|
|
48
|
-
const byId = new Map(all.map((run) => [run.id, run]));
|
|
49
|
-
const inScope = (run) => filter.project === void 0 || run.project === filter.project;
|
|
50
|
-
const old = (run) => (store.lastEventAt(run.id) ?? run.finishedAt ?? run.startedAt) < filter.before;
|
|
51
|
-
const trees = /* @__PURE__ */ new Map();
|
|
52
|
-
for (const run of all) {
|
|
53
|
-
const root = callRootOf(run, byId);
|
|
54
|
-
trees.set(root, [...trees.get(root) ?? [], run]);
|
|
55
|
-
}
|
|
56
|
-
const projects = [...new Set(all.filter((r) => old(r) && inScope(r)).map((r) => r.project))];
|
|
57
|
-
const withWorktrees = new Map(await Promise.all(projects.map(async (project) => {
|
|
58
|
-
try {
|
|
59
|
-
return [project, await worktreesOf(project)];
|
|
60
|
-
} catch (error) {
|
|
61
|
-
return [project, messageOf(error)];
|
|
62
|
-
}
|
|
63
|
-
})));
|
|
64
|
-
/** Why this run itself cannot go, or `null` when it can. */
|
|
65
|
-
const blocker = (run) => {
|
|
66
|
-
if (liveStatus(run) === "running") return "it is still running";
|
|
67
|
-
const worktrees = withWorktrees.get(run.project);
|
|
68
|
-
if (typeof worktrees === "string") return `cannot tell whether it has a worktree left: ${worktrees}`;
|
|
69
|
-
if (worktrees?.has(run.id) === true) return "it has a worktree or branch left (ork worktrees clean)";
|
|
70
|
-
if (store.links({
|
|
71
|
-
run: run.id,
|
|
72
|
-
live: true
|
|
73
|
-
}).length > 0) return "it has a live link";
|
|
74
|
-
return null;
|
|
75
|
-
};
|
|
76
|
-
const plan = {
|
|
77
|
-
remove: [],
|
|
78
|
-
keep: []
|
|
79
|
-
};
|
|
80
|
-
for (const tree of trees.values()) {
|
|
81
|
-
const held = tree.map((run) => {
|
|
82
|
-
if (!inScope(run)) return `run ${run.id} of its call is in another project (--all)`;
|
|
83
|
-
if (!old(run)) return `run ${run.id} of its call is newer`;
|
|
84
|
-
const why = blocker(run);
|
|
85
|
-
return why === null ? null : `run ${run.id} of its call stays: ${why}`;
|
|
86
|
-
}).find((why) => why !== null);
|
|
87
|
-
for (const run of tree) {
|
|
88
|
-
if (!inScope(run) || !old(run)) continue;
|
|
89
|
-
if (held === void 0) plan.remove.push(run);
|
|
90
|
-
else plan.keep.push({
|
|
91
|
-
run,
|
|
92
|
-
reason: blocker(run) ?? held
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return plan;
|
|
97
|
-
};
|
|
98
|
-
const SAFE_ID = /^[\w-]+$/u;
|
|
99
|
-
/** Forgets the plan's runs and removes their folders. */
|
|
100
|
-
const applyPrune = (store, plan) => {
|
|
101
|
-
const outcome = {
|
|
102
|
-
removed: 0,
|
|
103
|
-
folders: 0,
|
|
104
|
-
failed: []
|
|
105
|
-
};
|
|
106
|
-
const places = store.projects();
|
|
107
|
-
for (const run of plan.remove) {
|
|
108
|
-
if (!store.deleteRun(run.id)) {
|
|
109
|
-
outcome.failed.push({
|
|
110
|
-
run: run.id,
|
|
111
|
-
reason: "it is running again"
|
|
112
|
-
});
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
outcome.removed += 1;
|
|
116
|
-
if (!SAFE_ID.test(run.id)) continue;
|
|
117
|
-
const place = places.find((p) => p.root === run.project) ?? placeFor(run.project, places);
|
|
118
|
-
const folder = runDirOf(place, run.id);
|
|
119
|
-
if (!existsSync(folder)) continue;
|
|
120
|
-
try {
|
|
121
|
-
rmSync(folder, {
|
|
122
|
-
recursive: true,
|
|
123
|
-
force: true
|
|
124
|
-
});
|
|
125
|
-
outcome.folders += 1;
|
|
126
|
-
} catch (error) {
|
|
127
|
-
outcome.failed.push({
|
|
128
|
-
run: run.id,
|
|
129
|
-
reason: `its folder stays, at ${folder}: ${messageOf(error)}`
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return outcome;
|
|
134
|
-
};
|
|
135
7
|
// src/runs/usage.ts
|
|
136
8
|
/**
|
|
137
9
|
* @file How usage reads on the terminal (`ork usage`, specs/usage.md), and the
|
|
@@ -181,11 +53,7 @@ const sinceTime = (text, now) => {
|
|
|
181
53
|
/** `--until`: the last day it includes. */
|
|
182
54
|
const untilTime = (text) => dayTime(text, 1);
|
|
183
55
|
/** `950`, `12.3k`, `4.5M`. */
|
|
184
|
-
const tokens =
|
|
185
|
-
if (count < 1e3) return String(count);
|
|
186
|
-
if (count < 1e6) return `${(count / 1e3).toFixed(1)}k`;
|
|
187
|
-
return `${(count / 1e6).toFixed(1)}M`;
|
|
188
|
-
};
|
|
56
|
+
const tokens = shortCount;
|
|
189
57
|
const percent = (share) => `${String(Math.round(share * 100))}%`;
|
|
190
58
|
const counted = (count, noun) => `${String(count)} ${noun}${count === 1 ? "" : "s"}`;
|
|
191
59
|
const TITLES = {
|
|
@@ -239,8 +107,8 @@ const shortTime = (iso) => new Date(iso).toLocaleString(void 0, {
|
|
|
239
107
|
/** A warning line: a `WARN` chip when rich, else the line in yellow. */
|
|
240
108
|
const warned = (term, text) => term.rich ? ` ${chip(term, CHIP_LABELS.warn, "warn")} ${text}` : style("yellow", ` ${text}`);
|
|
241
109
|
/** The limits across runs, above a report; nothing with none set. */
|
|
242
|
-
const formatLimits = ({ problems, caps, plan }, term = termOf(process.stdout)) => {
|
|
243
|
-
if (problems.length === 0 && caps.length === 0 && plan.length === 0) return [];
|
|
110
|
+
const formatLimits = ({ problems, caps, tokenCaps = [], plan }, term = termOf(process.stdout)) => {
|
|
111
|
+
if (problems.length === 0 && caps.length === 0 && tokenCaps.length === 0 && plan.length === 0) return [];
|
|
244
112
|
return [
|
|
245
113
|
style("bold", "Limits"),
|
|
246
114
|
...problems.map((problem) => warned(term, problem)),
|
|
@@ -248,6 +116,10 @@ const formatLimits = ({ problems, caps, plan }, term = termOf(process.stdout)) =
|
|
|
248
116
|
const line = ` ${cap.project === void 0 ? "all projects" : "this project"}, this ${cap.window}: ${usd(cap.spentUsd)} of ${usd(cap.capUsd)}, resets ${shortTime(cap.resetsAt)}`;
|
|
249
117
|
return cap.leftUsd <= 0 ? warned(term, line.trimStart()) : line;
|
|
250
118
|
}),
|
|
119
|
+
...tokenCaps.map((cap) => {
|
|
120
|
+
const line = ` ${cap.project === void 0 ? "all projects" : "this project"}, this ${cap.window}: ${tokens(cap.spentTokens)} of ${tokens(cap.capTokens)} tokens, resets ${shortTime(cap.resetsAt)}`;
|
|
121
|
+
return cap.leftTokens <= 0 ? warned(term, line.trimStart()) : line;
|
|
122
|
+
}),
|
|
251
123
|
...plan.map((limit) => warned(term, `Claude plan's ${limit.window.replaceAll("_", " ")} limit ${limit.status === "rejected" ? "was reached" : "is close"}${limit.resetsAt === void 0 ? "" : `, resets ${shortTime(limit.resetsAt)}`}`)),
|
|
252
124
|
""
|
|
253
125
|
];
|
|
@@ -256,7 +128,7 @@ const formatLimits = ({ problems, caps, plan }, term = termOf(process.stdout)) =
|
|
|
256
128
|
const formatUsage = (report, scope, by, term = termOf(process.stdout)) => {
|
|
257
129
|
const { totals } = report;
|
|
258
130
|
if (totals.sessions === 0) return [`No Claude sessions in ${scope}.`];
|
|
259
|
-
const lines = [`${style("bold",
|
|
131
|
+
const lines = [`${style("bold", costOf(totals.costUsd, totals.partial, totals.tokens))} in ${scope}`, `${counted(totals.runs, "run")} · ${counted(totals.sessions, "session")} · ${counted(totals.turns, "turn")} · ${tokens(totals.inputTokens + totals.cacheReadTokens + totals.cacheWriteTokens)} in / ${tokens(totals.outputTokens)} out · ${percent(totals.cacheHitRate)} from cache`];
|
|
260
132
|
for (const dimension of by === void 0 ? OVERVIEW : [by]) {
|
|
261
133
|
const groups = report.groups[dimension];
|
|
262
134
|
const shown = by === void 0 ? dimension === "day" ? groups.slice(-10) : groups.slice(0, OVERVIEW_ROWS) : groups;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as chip, t as CHIP_LABELS } from "./chips-
|
|
1
|
+
import { C as termOf, p as apply } from "./output-B1kwo0YU.mjs";
|
|
2
|
+
import { n as chip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
|
|
3
3
|
// src/run/view.ts
|
|
4
4
|
/**
|
|
5
5
|
* @file How a run's lines are drawn: the terminal kit's {@link Term} for the
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as newRunId } from "./find-
|
|
3
|
-
import {
|
|
4
|
-
import { n as chip, t as CHIP_LABELS } from "./chips-
|
|
5
|
-
import { c as toolExecutor, o as spawnTool, s as mcpCallExecutor } from "./src-
|
|
6
|
-
import { i as runLimits, r as limitsRefusal } from "./limits-
|
|
7
|
-
import { t as acceptRefusal } from "./in-a-run-
|
|
1
|
+
import { B as watchingPid, Br as CheckReportSchema, F as triggerStanding, Gr as isToolNode, I as declaredTriggers, L as readProjectTriggers, N as triggersReport, P as createWatcher, U as openStore, Ut as liveStatus, Xt as stillTheSameProcess, Yr as timeoutMs, pr as placeFiles, wt as detachRun, z as takeWatchLock } from "./src-tsuZRu0H.mjs";
|
|
2
|
+
import { n as newRunId } from "./find-BVX-bL4u.mjs";
|
|
3
|
+
import { C as termOf, E as widthOf, a as plain, c as write, l as writeErr, s as style, t as confirm, w as cut } from "./output-B1kwo0YU.mjs";
|
|
4
|
+
import { n as chip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
|
|
5
|
+
import { c as toolExecutor, o as spawnTool, s as mcpCallExecutor } from "./src-C7z_6fhn.mjs";
|
|
6
|
+
import { i as runLimits, r as limitsRefusal } from "./limits-Dhe--wmX.mjs";
|
|
7
|
+
import { t as acceptRefusal } from "./in-a-run-cL5N9gpH.mjs";
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { mkdirSync } from "node:fs";
|
|
10
10
|
import { homedir } from "node:os";
|
|
@@ -132,7 +132,9 @@ const checkLines = (item) => {
|
|
|
132
132
|
const workflowLines = ({ workflow, workflowFile }) => {
|
|
133
133
|
if (workflow === null) return [];
|
|
134
134
|
const budget = workflow.limits?.budgetUsd;
|
|
135
|
-
|
|
135
|
+
const tokens = workflow.limits?.budgetTokens;
|
|
136
|
+
const caps = [...budget === void 0 ? [] : [`$${String(budget)}`], ...tokens === void 0 ? [] : [`${String(tokens)} tokens`]];
|
|
137
|
+
return [` workflow: ${plain(workflowFile)}${caps.length === 0 ? "" : `, up to ${caps.join(" and ")} a run`}`, ...Object.entries(workflow.nodes).map(([id, node]) => ` ${plain(id)}: ${plain(node.type)}`)];
|
|
136
138
|
};
|
|
137
139
|
const STANDS = {
|
|
138
140
|
new: "new",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as isBuiltinArg, n as builtinWorkflowFile, t as builtinProblem } from "./builtin-files-
|
|
3
|
-
import {
|
|
1
|
+
import { U as openStore, W as storePath, gr as runDirOf, mr as placeFor, pr as placeFiles, yr as inside } from "./src-tsuZRu0H.mjs";
|
|
2
|
+
import { a as isBuiltinArg, n as builtinWorkflowFile, t as builtinProblem } from "./builtin-files-Bdq23IIi.mjs";
|
|
3
|
+
import { l as writeErr } from "./output-B1kwo0YU.mjs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
6
6
|
// src/project/place.ts
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { S as cut, a as style, o as write, p as paint, s as writeErr, t as confirm, x as termOf } from "./output-CnRzrbUM.mjs";
|
|
5
|
-
import { n as chip } from "./chips-CyeB_rhR.mjs";
|
|
1
|
+
import { U as openStore, Y as inspectProject, _ as keyOf, a as planRemove, c as repoRoot, d as planLine, h as applyClean, i as lostWork, l as labelOf, p as stateParts, r as applyRemove, s as readWorktrees, u as mergeStateOf, v as planClean, y as stepActs } from "./src-tsuZRu0H.mjs";
|
|
2
|
+
import { C as termOf, c as write, h as paint, l as writeErr, s as style, t as confirm, w as cut } from "./output-B1kwo0YU.mjs";
|
|
3
|
+
import { n as chip } from "./chips-BqcT58qr.mjs";
|
|
6
4
|
import path from "node:path";
|
|
7
5
|
import { realpathSync } from "node:fs";
|
|
8
6
|
import { defineCommand } from "citty";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@krapht/ork",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.14",
|
|
4
4
|
"description": "Orchestrate Claude agents on your machine: hierarchical, serializable workflows with a CLI and a localhost UI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -54,6 +54,6 @@
|
|
|
54
54
|
"tsdown": "0.23.4"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
|
-
"build": "pnpm --filter @krapht/ork-ui build && node ../../tools/release/build-info.ts && node ../../tools/release/plugin-skills.ts && node ../../tools/release/builtin-workflows.ts && tsdown && cp ../../LICENSE ../../THIRD_PARTY_NOTICES.md . && cp -R ../ui/dist dist/ui"
|
|
57
|
+
"build": "pnpm --filter @krapht/ork-ui build && node ../../tools/release/build-info.ts && node ../../tools/release/plugin-skills.ts && node ../../tools/release/builtin-workflows.ts && node ../../tools/release/issues-workflow.ts && tsdown && cp ../../LICENSE ../../THIRD_PARTY_NOTICES.md . && cp -R ../ui/dist dist/ui"
|
|
58
58
|
}
|
|
59
59
|
}
|
package/dist/clean-D8GI_2K-.mjs
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { D as removeWorktree, k as gitOk } from "./src-CdDTQLdQ.mjs";
|
|
2
|
-
// ../core/src/worktree/clean.ts
|
|
3
|
-
/**
|
|
4
|
-
* @file What `ork worktrees clean` and `ork worktrees remove` do with what
|
|
5
|
-
* list.ts reads: the plan (what goes, what's kept and why), by one rule for
|
|
6
|
-
* every caller, and carrying it out. The CLI and the Worktrees panel both
|
|
7
|
-
* plan here, so neither removes what the other would keep.
|
|
8
|
-
*/
|
|
9
|
-
/** What names an item for `remove`: its branch, or its worktree's path. */
|
|
10
|
-
const keyOf = (item) => item.branch ?? item.path ?? `${item.runId}/${item.nodeId}`;
|
|
11
|
-
/** The reasons no `force` overrides: removing would break something. */
|
|
12
|
-
const MAIN_CHECKOUT = "checked out in the main checkout";
|
|
13
|
-
const RUN_GOING = "its run is still going";
|
|
14
|
-
const NOT_ORKS = "not created by Ork";
|
|
15
|
-
const kept = (item, skip) => ({
|
|
16
|
-
item,
|
|
17
|
-
removeWorktree: false,
|
|
18
|
-
deleteBranch: false,
|
|
19
|
-
skip
|
|
20
|
-
});
|
|
21
|
-
/** What clean does with one item. */
|
|
22
|
-
const cleanStep = (item, options) => {
|
|
23
|
-
if (!item.recorded) return kept(item, NOT_ORKS);
|
|
24
|
-
if (item.inMainCheckout) return kept(item, MAIN_CHECKOUT);
|
|
25
|
-
if (item.heldBy !== void 0) return kept(item, `checked out in ${item.heldBy}`);
|
|
26
|
-
if (options.live?.has(item.runId) === true) return kept(item, RUN_GOING);
|
|
27
|
-
if (item.dirty && !options.force) return kept(item, "uncommitted changes");
|
|
28
|
-
if (item.branch === void 0 && item.checkedOut === void 0 && item.ahead > 0 && !options.force) return kept(item, "commits on no branch");
|
|
29
|
-
const removable = item.path !== null && !item.missing;
|
|
30
|
-
if (options.branches && item.branch !== void 0 && !item.merged && !options.force) return {
|
|
31
|
-
item,
|
|
32
|
-
removeWorktree: removable,
|
|
33
|
-
deleteBranch: false,
|
|
34
|
-
skip: "branch not merged"
|
|
35
|
-
};
|
|
36
|
-
return {
|
|
37
|
-
item,
|
|
38
|
-
removeWorktree: removable,
|
|
39
|
-
deleteBranch: options.branches && item.branch !== void 0
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
/** Whether a step drops a worktree whose folder is gone, by its own path. */
|
|
43
|
-
const stepPrunes = (step) => step.item.missing && step.item.path !== null && step.skip === void 0;
|
|
44
|
-
/** Whether a step does anything. */
|
|
45
|
-
const stepActs = (step) => step.removeWorktree || step.deleteBranch || stepPrunes(step);
|
|
46
|
-
/**
|
|
47
|
-
* What `ork worktrees clean` would do. A worktree with uncommitted changes, an
|
|
48
|
-
* unmerged branch, or a detached worktree holding commits no branch has, is
|
|
49
|
-
* kept unless `force`; one checked out in the main checkout or in a worktree
|
|
50
|
-
* Ork didn't create, whose run is still going, or an `ork/` branch no run
|
|
51
|
-
* recorded creating, is kept even then.
|
|
52
|
-
*/
|
|
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));
|
|
54
|
-
/**
|
|
55
|
-
* Carries out one step; what it did goes into `done` as it goes. It touches
|
|
56
|
-
* only its own item: a missing worktree is dropped by its own path (`git
|
|
57
|
-
* worktree remove`), never by `git worktree prune`, which would drop every
|
|
58
|
-
* missing worktree in the repository, the user's own included.
|
|
59
|
-
*/
|
|
60
|
-
const applyStep = async (root, step, force, done) => {
|
|
61
|
-
const { item } = step;
|
|
62
|
-
if (stepPrunes(step) && !step.removeWorktree && item.path !== null) {
|
|
63
|
-
await gitOk(root, [
|
|
64
|
-
"worktree",
|
|
65
|
-
"remove",
|
|
66
|
-
item.path
|
|
67
|
-
]);
|
|
68
|
-
done.push(`pruned ${item.path}`);
|
|
69
|
-
}
|
|
70
|
-
if (step.removeWorktree && item.path !== null) {
|
|
71
|
-
await removeWorktree(root, item.path, force);
|
|
72
|
-
done.push(`removed ${item.path}`);
|
|
73
|
-
}
|
|
74
|
-
if (step.deleteBranch && item.branch !== void 0) {
|
|
75
|
-
await gitOk(root, [
|
|
76
|
-
"branch",
|
|
77
|
-
force ? "-D" : "-d",
|
|
78
|
-
item.branch
|
|
79
|
-
]);
|
|
80
|
-
done.push(`deleted ${item.branch}`);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
/**
|
|
84
|
-
* Carries out a clean plan, step by step. What it did goes into `done` as it
|
|
85
|
-
* goes, so a caller still has it when git fails halfway.
|
|
86
|
-
*/
|
|
87
|
-
const applyClean = async (root, steps, force, done = []) => {
|
|
88
|
-
for (const step of steps) await applyStep(root, step, force, done);
|
|
89
|
-
return done;
|
|
90
|
-
};
|
|
91
|
-
export { planClean as a, keyOf as i, applyStep as n, stepActs as o, cleanStep as r, stepPrunes as s, applyClean as t };
|
package/dist/decide-DlbyctOE.mjs
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { Cn as wakeRun, xn as socketPath, xt as liveStatus } from "./src-CdDTQLdQ.mjs";
|
|
2
|
-
// ../core/src/remote/decide.ts
|
|
3
|
-
/**
|
|
4
|
-
* @file The open decisions of live runs, and answering one from another process
|
|
5
|
-
* (`ork decide`, the local server), with the person's note if they gave one.
|
|
6
|
-
* An answer goes to the store (the first one wins), then the run is woken on
|
|
7
|
-
* its socket so it picks the answer up at once (specs/messaging.md).
|
|
8
|
-
*/
|
|
9
|
-
/** Open decisions whose run is still live, oldest first, ANDing the filter. */
|
|
10
|
-
const pendingDecisions = (store, filter) => {
|
|
11
|
-
const live = /* @__PURE__ */ new Map();
|
|
12
|
-
return store.decisions({
|
|
13
|
-
...filter,
|
|
14
|
-
status: "open"
|
|
15
|
-
}).filter((decision) => {
|
|
16
|
-
if (!live.has(decision.runId)) {
|
|
17
|
-
const [run] = store.lookup(decision.runId);
|
|
18
|
-
live.set(decision.runId, run !== void 0 && liveStatus(run) === "running" && (filter.workflow === void 0 || run.workflow === filter.workflow));
|
|
19
|
-
}
|
|
20
|
-
return live.get(decision.runId) === true;
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Answers an open decision with one of its options, and wakes its run. `home`
|
|
25
|
-
* is `~`, where the sockets are (tests pass a folder); `by` says who answered;
|
|
26
|
-
* `note` is what they said with it, if anything (blank is nothing).
|
|
27
|
-
*/
|
|
28
|
-
const answerDecision = async (store, id, choice, home, by = "decide", note) => {
|
|
29
|
-
const decision = store.decision(id);
|
|
30
|
-
if (decision === void 0) return {
|
|
31
|
-
ok: false,
|
|
32
|
-
error: `No decision \`${id}\`.`
|
|
33
|
-
};
|
|
34
|
-
if (!decision.options.some((o) => o.id === choice)) return {
|
|
35
|
-
ok: false,
|
|
36
|
-
error: `\`${choice}\` is not an option of \`${id}\`: \`${decision.options.map((o) => o.id).join("`, `")}\``
|
|
37
|
-
};
|
|
38
|
-
if (!store.answerDecision(id, choice, by, note)) {
|
|
39
|
-
const now = store.decision(id);
|
|
40
|
-
return {
|
|
41
|
-
ok: false,
|
|
42
|
-
error: now?.status === "answered" ? `${id} was already answered: ${now.answer ?? ""} (${now.answeredBy ?? ""})` : `${id} was withdrawn`
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
ok: true,
|
|
47
|
-
woke: await wakeRun(socketPath(decision.runId, home))
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
export { pendingDecisions as n, answerDecision as t };
|
package/dist/list-zW2xKuGr.mjs
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { A as lines, O as git, k as gitOk } from "./src-CdDTQLdQ.mjs";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
// ../core/src/worktree/list.ts
|
|
4
|
-
/**
|
|
5
|
-
* @file What `ork worktrees` shows: every worktree and branch Ork's runs
|
|
6
|
-
* recorded creating, whatever the project's git rules named them, and any
|
|
7
|
-
* `ork/*` branch besides, with their state read from git itself. What clean
|
|
8
|
-
* and remove do with them is clean.ts.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* The worktrees the project's runs recorded creating, oldest run first; one
|
|
12
|
-
* entry per branch or folder, from the latest run that created it.
|
|
13
|
-
*/
|
|
14
|
-
const createdWorktrees = (store, project) => {
|
|
15
|
-
const byName = /* @__PURE__ */ new Map();
|
|
16
|
-
for (const run of store.runs({ project }).toReversed()) for (const { event } of store.events(run.id)) {
|
|
17
|
-
if (event.type !== "worktree" || event.action !== "created") continue;
|
|
18
|
-
byName.set(event.branch ?? event.path, {
|
|
19
|
-
runId: run.id,
|
|
20
|
-
nodeId: event.id,
|
|
21
|
-
path: event.path,
|
|
22
|
-
...event.branch === void 0 ? {} : { branch: event.branch }
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
return [...byName.values()];
|
|
26
|
-
};
|
|
27
|
-
const parsePorcelain = (text) => text.split("\n\n").map((block) => lines(block)).map((fields) => {
|
|
28
|
-
const value = (key) => fields.find((f) => f.startsWith(`${key} `))?.slice(key.length + 1);
|
|
29
|
-
return {
|
|
30
|
-
path: value("worktree") ?? "",
|
|
31
|
-
branch: (value("branch") ?? "").replace(/^refs\/heads\//u, ""),
|
|
32
|
-
prunable: fields.some((f) => f.startsWith("prunable"))
|
|
33
|
-
};
|
|
34
|
-
}).filter((entry) => entry.path !== "");
|
|
35
|
-
/**
|
|
36
|
-
* The `ork/<run>/<node>` branches of runs that recorded nothing; with no path
|
|
37
|
-
* recorded, the worktree is whichever has the branch checked out.
|
|
38
|
-
*/
|
|
39
|
-
const prefixed = (branch) => {
|
|
40
|
-
const [, runId = "", ...rest] = branch.split("/");
|
|
41
|
-
return {
|
|
42
|
-
runId,
|
|
43
|
-
nodeId: rest.join("/"),
|
|
44
|
-
path: "",
|
|
45
|
-
branch
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
/** How many commits a detached worktree holds that no branch, tag or remote has. */
|
|
49
|
-
const onNoBranch = async (entry) => entry === void 0 ? "0" : (await git(entry.path, [
|
|
50
|
-
"rev-list",
|
|
51
|
-
"--count",
|
|
52
|
-
"HEAD",
|
|
53
|
-
"--not",
|
|
54
|
-
"--branches",
|
|
55
|
-
"--tags",
|
|
56
|
-
"--remotes"
|
|
57
|
-
])).stdout;
|
|
58
|
-
/** One created worktree or branch, with its state read from git. */
|
|
59
|
-
const stateOf = async (root, entries, item, recorded) => {
|
|
60
|
-
const { branch } = item;
|
|
61
|
-
const entry = branch === void 0 || item.path !== "" ? entries.find((e) => e.path === item.path) : entries.find((e) => e.branch === branch);
|
|
62
|
-
const holder = branch === void 0 ? void 0 : entries.find((e) => e.branch === branch && e.path !== entry?.path);
|
|
63
|
-
const missing = entry !== void 0 && (entry.prunable || !existsSync(entry.path));
|
|
64
|
-
const status = entry === void 0 || missing ? "" : (await git(entry.path, ["status", "--porcelain"])).stdout;
|
|
65
|
-
const checkedOut = branch === void 0 && entry !== void 0 && entry.branch !== "" ? entry.branch : void 0;
|
|
66
|
-
const on = branch ?? checkedOut;
|
|
67
|
-
const counted = on === void 0 ? await onNoBranch(entry === void 0 || missing ? void 0 : entry) : (await git(root, [
|
|
68
|
-
"rev-list",
|
|
69
|
-
"--count",
|
|
70
|
-
`HEAD..${on}`
|
|
71
|
-
])).stdout;
|
|
72
|
-
const ahead = Number(counted);
|
|
73
|
-
const changes = lines(status).length;
|
|
74
|
-
return {
|
|
75
|
-
...branch === void 0 ? {} : { branch },
|
|
76
|
-
...checkedOut === void 0 ? {} : { checkedOut },
|
|
77
|
-
runId: item.runId,
|
|
78
|
-
nodeId: item.nodeId,
|
|
79
|
-
recorded,
|
|
80
|
-
path: entry?.path ?? null,
|
|
81
|
-
missing,
|
|
82
|
-
dirty: changes > 0,
|
|
83
|
-
changes,
|
|
84
|
-
ahead: Number.isNaN(ahead) ? 0 : ahead,
|
|
85
|
-
merged: on !== void 0 && ahead === 0,
|
|
86
|
-
inMainCheckout: entry?.path === root || holder?.path === root,
|
|
87
|
-
...holder === void 0 || holder.path === root ? {} : { heldBy: holder.path }
|
|
88
|
-
};
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* Every worktree and branch Ork's runs created in the repository at `root`,
|
|
92
|
-
* with its state: those the runs recorded (`created`, whatever the project's
|
|
93
|
-
* git rules named them), and any `ork/` branch besides. A recorded one that git
|
|
94
|
-
* no longer has is left out.
|
|
95
|
-
*/
|
|
96
|
-
const listOrkWorktrees = async (root, created = []) => {
|
|
97
|
-
const entries = parsePorcelain(await gitOk(root, [
|
|
98
|
-
"worktree",
|
|
99
|
-
"list",
|
|
100
|
-
"--porcelain"
|
|
101
|
-
]));
|
|
102
|
-
const branches = lines(await gitOk(root, [
|
|
103
|
-
"for-each-ref",
|
|
104
|
-
"--format=%(refname:short)",
|
|
105
|
-
"refs/heads/"
|
|
106
|
-
]));
|
|
107
|
-
const recordedBranches = new Set(created.flatMap((c) => c.branch ?? []));
|
|
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)));
|
|
116
|
-
};
|
|
117
|
-
export { listOrkWorktrees as n, createdWorktrees as t };
|