@krapht/ork 1.0.0-alpha.18 → 1.0.0-alpha.19
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__-B8TNbFtN.mjs → __build_info__-dPf4cEGL.mjs} +3 -134
- package/dist/{attach-CU4Pk42S.mjs → attach-BQl8nQz2.mjs} +5 -5
- package/dist/{attach-qvfyaQXC.mjs → attach-DhZQ87Nz.mjs} +49 -224
- package/dist/bin.mjs +204 -154
- package/dist/{brief-Bh1FnAHv.mjs → brief-BQbeoPMc.mjs} +19 -9
- package/dist/{builtin-files-dnTP2GaX.mjs → builtin-files-CWL3JEo-.mjs} +1 -1
- package/dist/{command-tree-BkSYWmYJ.mjs → command-tree-B6uvMJq1.mjs} +1 -1
- package/dist/{completion-CzXUGSVn.mjs → completion-DKPuD_Rw.mjs} +47 -14
- package/dist/{context-b4_gPlv3.mjs → context-Bw6R_EYq.mjs} +3 -3
- package/dist/detached-BQlbmqR0.mjs +38 -0
- package/dist/{find-P-VV4B47.mjs → find-B30-rd-u.mjs} +1 -1
- package/dist/flags-ByYBx-Xb.mjs +170 -0
- package/dist/{follow-ups-B_c1DSpA.mjs → follow-ups-Cxca1Jgg.mjs} +24 -18
- package/dist/{format-BS1qzpkf.mjs → format-C-nEZv-P.mjs} +27 -11
- package/dist/{help-groups-hB6kY34d.mjs → help-groups-BpRgBSTh.mjs} +13 -7
- package/dist/{in-a-run-DKoMGTNE.mjs → in-a-run-CZFzoT3R.mjs} +2 -2
- package/dist/{install-B743Bwzz.mjs → install-CsqK1avz.mjs} +2 -183
- package/dist/{limits-DrsKCqaN.mjs → limits-CXh052II.mjs} +1 -1
- package/dist/{mcp-BMwekw38.mjs → mcp-B4wME9C4.mjs} +6 -6
- package/dist/{once-6L8gciJV.mjs → once-BKn3pOtg.mjs} +3 -3
- package/dist/outputs-text-CNTJ7Qq_.mjs +19 -0
- package/dist/{pause-8gnVgICR.mjs → pause-B1grR1cl.mjs} +3 -3
- package/dist/{print-DLe4MHn-.mjs → print-Bd8MWVJk.mjs} +1 -1
- package/dist/{project-records-CsILxwfI.mjs → project-records-BOEVs69i.mjs} +1 -1
- package/dist/{parse-BzWpMN-a.mjs → refusals-DQQX3AIb.mjs} +10 -1
- package/dist/{relay-Bvm9JEoN.mjs → relay-CeNiq3GT.mjs} +1 -1
- package/dist/{run-D4yuTmmJ.mjs → run-C0C54UiU.mjs} +116 -137
- package/dist/{run-y8jI7bAI.mjs → run-D6yU2rLf.mjs} +1 -1
- package/dist/{send-BV9eIxQ7.mjs → send-DqgF58hb.mjs} +2 -2
- package/dist/{src-Frwpx3WF.mjs → src-Ciy7i3se.mjs} +843 -66
- package/dist/{src-ygFMh2eP.mjs → src-D2qpd-G7.mjs} +4 -4
- package/dist/{src-CVeA4tAw.mjs → src-DP02RP9O.mjs} +227 -180
- package/dist/{src-DWAcd3Sy.mjs → src-n-u4TGev.mjs} +186 -43
- package/dist/{store-B0nGqnPq.mjs → store-2KXzMCEN.mjs} +1 -1
- package/dist/ui/assets/app-C5vO1M-l.css +1 -0
- package/dist/ui/assets/{app-C4yxmYQR.js → app-ICEKpy_C.js} +21 -20
- package/dist/ui/assets/{index-CcbJWo5C.js → index-BGaix5wh.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-BZ9BhFw8.mjs → ui-CAvygxTb.mjs} +53 -24
- package/dist/{usage-BIs4j5Rw.mjs → usage-BFBco5OS.mjs} +7 -7
- package/dist/{validate-Xn2ZbJQC.mjs → validate-UrmC5AG1.mjs} +5 -5
- package/dist/{watch-9VM3DFTp.mjs → watch-DTxkgB8R.mjs} +5 -5
- package/dist/{workflows-CBYtycIy.mjs → workflows-8GV-SeRm.mjs} +28 -4
- package/dist/{worktrees-C7vfh7y5.mjs → worktrees-CUdUvZlO.mjs} +9 -6
- package/package.json +1 -1
- package/dist/flags-CqjJ44uW.mjs +0 -125
- package/dist/post-y1qL1Fnj.mjs +0 -46
- package/dist/ui/assets/app-9Q-62Ywz.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-BGaix5wh.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,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { p as scrubberOfRun } from "./src-DP02RP9O.mjs";
|
|
2
|
+
import { n as ORK_VERSION, t as ORK_NAME } from "./__build_info__-dPf4cEGL.mjs";
|
|
2
3
|
import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
|
|
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-
|
|
4
|
+
import { o as mayShowSignIn } from "./in-a-run-CZFzoT3R.mjs";
|
|
5
|
+
import { i as uiFilePath, l as newToken, n as startServer, r as runningServer, t as DEFAULT_PORT, u as createClient } from "./src-n-u4TGev.mjs";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
import { constants } from "node:os";
|
|
7
8
|
import { spawn } from "node:child_process";
|
|
@@ -105,7 +106,8 @@ const childMessage = (value) => {
|
|
|
105
106
|
const startMessage = (value) => isRecord(value) && value["type"] === "ork-ui-start" && typeof value["port"] === "number" && typeof value["token"] === "string" ? {
|
|
106
107
|
type: "ork-ui-start",
|
|
107
108
|
port: value["port"],
|
|
108
|
-
token: value["token"]
|
|
109
|
+
token: value["token"],
|
|
110
|
+
...typeof value["session"] === "string" ? { session: value["session"] } : {}
|
|
109
111
|
} : null;
|
|
110
112
|
// src/browser/serve.ts
|
|
111
113
|
/**
|
|
@@ -190,11 +192,13 @@ const serve = async (start, end) => {
|
|
|
190
192
|
version: ORK_VERSION,
|
|
191
193
|
port: start.port,
|
|
192
194
|
token: start.token,
|
|
195
|
+
...start.session === void 0 ? {} : { sessionSecret: start.session },
|
|
193
196
|
ui: uiFolders(),
|
|
194
197
|
update: { name: ORK_NAME },
|
|
195
198
|
restart: () => {
|
|
196
199
|
send({ type: "ork-ui-restart" }).then(end);
|
|
197
|
-
}
|
|
200
|
+
},
|
|
201
|
+
noteScrub: (run, registered) => scrubberOfRun(run, registered)
|
|
198
202
|
});
|
|
199
203
|
} catch (error) {
|
|
200
204
|
await send({
|
|
@@ -231,13 +235,14 @@ const serveForSupervisor = async () => {
|
|
|
231
235
|
* @file `ork ui`'s process model (ADR-060): the command in the terminal only
|
|
232
236
|
* supervises; its server runs in a child, the launcher the user ran
|
|
233
237
|
* (`process.argv[1]` as given, so after an upgrade it is the new install's)
|
|
234
|
-
* with `ui --serve`. The port
|
|
235
|
-
* When the page asks for a restart,
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
* kills it and exits
|
|
238
|
+
* with `ui --serve`. The port, the token and the session secret (made here,
|
|
239
|
+
* once) go over the child's IPC channel. When the page asks for a restart,
|
|
240
|
+
* the child says so and exits, and the supervisor starts the launcher again
|
|
241
|
+
* on the same port with the same token and session secret, so the open tab
|
|
242
|
+
* stays signed in. There is only ever one child; Ctrl-C (or SIGTERM) stops it
|
|
243
|
+
* and then the supervisor, which exits with its code. The child may wait for
|
|
244
|
+
* an upgrade to finish first; a second Ctrl-C (or SIGTERM) kills it and exits
|
|
245
|
+
* at once.
|
|
241
246
|
*/
|
|
242
247
|
/**
|
|
243
248
|
* How long an exited child's channel may take to close before the supervisor
|
|
@@ -250,6 +255,7 @@ const signalled = (signal) => 128 + constants.signals[signal];
|
|
|
250
255
|
/** Supervises the server until it stops; resolves the exit code. */
|
|
251
256
|
const supervise = (options) => new Promise((resolve) => {
|
|
252
257
|
const { token, say, sayErr } = options;
|
|
258
|
+
const session = newToken();
|
|
253
259
|
let port = options.port;
|
|
254
260
|
let stopping = false;
|
|
255
261
|
let ended = false;
|
|
@@ -288,7 +294,8 @@ const supervise = (options) => new Promise((resolve) => {
|
|
|
288
294
|
if (message?.type === "ork-ui-hello") child.send({
|
|
289
295
|
type: "ork-ui-start",
|
|
290
296
|
port,
|
|
291
|
-
token
|
|
297
|
+
token,
|
|
298
|
+
session
|
|
292
299
|
});
|
|
293
300
|
else if (message?.type === "ork-ui-ready") {
|
|
294
301
|
ready = true;
|
|
@@ -384,26 +391,48 @@ const onStopSignals = (stop) => {
|
|
|
384
391
|
// src/commands/ui.ts
|
|
385
392
|
/**
|
|
386
393
|
* @file `ork ui`: starts the local server (ADR-039) on loopback and opens it in
|
|
387
|
-
* the browser, signed in with
|
|
388
|
-
* running (`~/.ork/ui.json`), opens that one. The
|
|
389
|
-
* server in a child process, so the page can restart
|
|
390
|
-
* installed `ork` (ADR-060). The server runs nothing: runs it
|
|
391
|
-
* running when it stops, and the CLI works without it.
|
|
394
|
+
* the browser, signed in with a single-use code the server mints (RFC-019);
|
|
395
|
+
* or, when one is already running (`~/.ork/ui.json`), opens that one. The
|
|
396
|
+
* command supervises the server in a child process, so the page can restart
|
|
397
|
+
* it onto a newly installed `ork` (ADR-060). The server runs nothing: runs it
|
|
398
|
+
* starts keep running when it stops, and the CLI works without it.
|
|
399
|
+
*/
|
|
400
|
+
/** The link that signs the browser in; the server swaps its code for a cookie. */
|
|
401
|
+
const signInLink = (port, code) => `http://127.0.0.1:${String(port)}/?code=${code}`;
|
|
402
|
+
/** What `ork ui` says when it can't get a sign-in code from the server. */
|
|
403
|
+
const MINT_FAILED_OLDER = "The running UI is from an older Ork; stop it and run `ork ui`.";
|
|
404
|
+
/**
|
|
405
|
+
* Gets a single-use sign-in code from the server with the API token, and
|
|
406
|
+
* returns the link for it, or the reason there is none. The token only goes in
|
|
407
|
+
* this request's header, never in a link or an argument.
|
|
392
408
|
*/
|
|
393
|
-
|
|
394
|
-
const
|
|
409
|
+
const mintSignInLink = async (port, token, fetchFn) => {
|
|
410
|
+
const answer = await createClient({
|
|
411
|
+
base: `http://127.0.0.1:${String(port)}`,
|
|
412
|
+
token,
|
|
413
|
+
...fetchFn === void 0 ? {} : { fetch: fetchFn }
|
|
414
|
+
}).call("signIn");
|
|
415
|
+
if (answer.ok) return { link: signInLink(port, answer.data.code) };
|
|
416
|
+
return { failure: answer.status === 404 || answer.status === 0 ? MINT_FAILED_OLDER : `Could not get a sign-in code: ${answer.error}` };
|
|
417
|
+
};
|
|
395
418
|
/** `--port`: 0 to 65535 (0 picks a free port); `null` when invalid. */
|
|
396
419
|
const portArg = (value) => {
|
|
397
420
|
if (value === void 0) return DEFAULT_PORT;
|
|
398
421
|
const port = Number(value);
|
|
399
422
|
return Number.isInteger(port) && port >= 0 && port <= 65535 ? port : null;
|
|
400
423
|
};
|
|
401
|
-
/** Opens the link, or prints it when there is no browser to open. */
|
|
402
|
-
const show = async (
|
|
424
|
+
/** Opens the sign-in link, or prints it when there is no browser to open. */
|
|
425
|
+
const show = async (port, token, open) => {
|
|
403
426
|
if (!mayShowSignIn()) {
|
|
404
427
|
writeErr("A program or an agent in a run does not get the sign-in link, which acts as you. Run `ork ui` in your own terminal.");
|
|
405
428
|
return;
|
|
406
429
|
}
|
|
430
|
+
const minted = await mintSignInLink(port, token);
|
|
431
|
+
if ("failure" in minted) {
|
|
432
|
+
writeErr(minted.failure);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const { link } = minted;
|
|
407
436
|
if (!(open && process.stdout.isTTY && await openInBrowser(link))) write(`Open it with this link, which signs you in: ${link}`);
|
|
408
437
|
};
|
|
409
438
|
/** What `ork ui` says once its server serves, the first time or again. */
|
|
@@ -415,7 +444,7 @@ const ready = async ({ port, version, restarted }, token, open) => {
|
|
|
415
444
|
}
|
|
416
445
|
write(`Ork's UI is at ${url}`);
|
|
417
446
|
write(style("dim", "Runs keep running when it stops, and every ork command works without it. Ctrl-C stops it."));
|
|
418
|
-
await show(
|
|
447
|
+
await show(port, token, open);
|
|
419
448
|
};
|
|
420
449
|
const ui = defineCommand({
|
|
421
450
|
meta: {
|
|
@@ -452,7 +481,7 @@ const ui = defineCommand({
|
|
|
452
481
|
const running = runningServer(uiFilePath());
|
|
453
482
|
if (running !== null) {
|
|
454
483
|
write(`Ork's UI is already running at http://127.0.0.1:${String(running.port)} (process ${String(running.pid)}).`);
|
|
455
|
-
await show(
|
|
484
|
+
await show(running.port, running.token, args.open);
|
|
456
485
|
return;
|
|
457
486
|
}
|
|
458
487
|
const token = newToken();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { H as applyPrune, R as openStore, U as planPrune, Wr as placeFor, _ as usageReport, g as USAGE_DIMENSIONS, qt as usageListTable } from "./src-Ciy7i3se.mjs";
|
|
2
|
+
import { a as agoTime } from "./refusals-DQQX3AIb.mjs";
|
|
3
3
|
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";
|
|
4
4
|
import { n as chip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
|
|
5
|
-
import { n as limitsHere } from "./limits-
|
|
6
|
-
import { i as readListArgs, n as filterArgs,
|
|
7
|
-
import { a as header, o as table } from "./format-
|
|
5
|
+
import { n as limitsHere } from "./limits-CXh052II.mjs";
|
|
6
|
+
import { i as readListArgs, n as filterArgs, r as projectScope, s as refuseUnknownFlags } from "./flags-ByYBx-Xb.mjs";
|
|
7
|
+
import { a as header, o as table } from "./format-C-nEZv-P.mjs";
|
|
8
8
|
import { defineCommand } from "citty";
|
|
9
9
|
// src/runs/usage.ts
|
|
10
10
|
/** `950`, `12.3k`, `4.5M`. */
|
|
@@ -127,11 +127,11 @@ const usage = defineCommand({
|
|
|
127
127
|
name: "usage",
|
|
128
128
|
description: "Show what this project's runs spent over time"
|
|
129
129
|
},
|
|
130
|
+
plugins: [refuseUnknownFlags],
|
|
130
131
|
args: filterArgs(usageListTable, {
|
|
131
132
|
ids: false,
|
|
132
133
|
limit: false,
|
|
133
134
|
extra: {
|
|
134
|
-
...allAlias,
|
|
135
135
|
"clear-plan-limits": {
|
|
136
136
|
type: "boolean",
|
|
137
137
|
description: "Forget what Claude Code last said of your plan's limits, for one that has lifted",
|
|
@@ -149,7 +149,7 @@ const usage = defineCommand({
|
|
|
149
149
|
const request = readListArgs(usageListTable, {
|
|
150
150
|
...args,
|
|
151
151
|
since
|
|
152
|
-
}
|
|
152
|
+
});
|
|
153
153
|
if (request === void 0) return;
|
|
154
154
|
const rawBy = args["by"];
|
|
155
155
|
const given = typeof rawBy === "string" ? rawBy : void 0;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { d as readUpdateCache, f as refreshUpdateCache, i as registryOf, l as newerVersion, m as writeUpdateCache, n as ORK_VERSION, o as updateSwitchOff, p as updateCachePath, r as isSwitchedOn, s as checkDue, t as ORK_NAME, u as pendingNotice } from "./__build_info__-
|
|
1
|
+
import { $ as driverQueues, Ai as driverChecks, Ct as checkWorkflowText, D as lateTriggers, Ei as INTEGRATIONS, Fi as DRIVER_IDS, Ii as firstLine, Jr as workflowDirOf, Kn as loadProject, Li as EXPERIMENTS, M as readProjectTriggers, N as workflowTextHash, O as triggersReport, Pi as AGENT_DRIVERS, R as openStore, Ri as experimentsOn, Si as DriverSchema, Tt as walkSummary, Ur as placeFiles, Wr as placeFor, X as budgetWarnings, Z as driverRefusals, ji as readyDriver, sn as namingNoDriver, wi as retiredDriverHint, wr as socketRoom, wt as walkChecks, z as storePath, zi as knownExperiments } from "./src-Ciy7i3se.mjs";
|
|
2
|
+
import { d as readUpdateCache, f as refreshUpdateCache, i as registryOf, l as newerVersion, m as writeUpdateCache, n as ORK_VERSION, o as updateSwitchOff, p as updateCachePath, r as isSwitchedOn, s as checkDue, t as ORK_NAME, u as pendingNotice } from "./__build_info__-dPf4cEGL.mjs";
|
|
3
3
|
import { C as termOf, D as wrap, E as widthOf, a as plain, c as write, h as paint, l as writeErr, s as style, w as cut, x as plainEnv } from "./output-B1kwo0YU.mjs";
|
|
4
4
|
import { n as chip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
|
|
5
|
-
import { c as
|
|
5
|
+
import { a as refusedBuiltin, c as projectAt, i as missingWorkflowText, l as registeredProjects, r as findWorkflowFiles } from "./workflows-8GV-SeRm.mjs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { readFileSync } from "node:fs";
|
|
8
8
|
import { execFile, spawn } from "node:child_process";
|
|
9
|
-
import { defineCommand } from "citty";
|
|
10
9
|
import { styleText } from "node:util";
|
|
10
|
+
import { defineCommand } from "citty";
|
|
11
11
|
// src/update/notify.ts
|
|
12
12
|
/**
|
|
13
13
|
* @file The new-version notice (ADR-038). At most once a day a command starts a
|
|
@@ -520,7 +520,7 @@ const loadWorkflow = (file, cwd, home, registered = registeredProjects(home)) =>
|
|
|
520
520
|
diagnostics: [{
|
|
521
521
|
severity: "error",
|
|
522
522
|
code: "file.read",
|
|
523
|
-
message: error instanceof Error && "code" in error && error.code === "ENOENT" ?
|
|
523
|
+
message: error instanceof Error && "code" in error && error.code === "ENOENT" ? missingWorkflowText(file, placeFiles(place).workflows) : "cannot read file",
|
|
524
524
|
path: []
|
|
525
525
|
}]
|
|
526
526
|
},
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import {
|
|
1
|
+
import { A as triggerStanding, Bn as stillTheSameProcess, F as watchingPid, M as readProjectTriggers, Nn as liveStatus, O as triggersReport, P as takeWatchLock, R as openStore, Ti as timeoutMs, Ur as placeFiles, bn as startFollowUpChecks, ft as detachRun, gi as CheckReportSchema, j as declaredTriggers, k as createWatcher, pr as runGh, xi as isToolNode } from "./src-Ciy7i3se.mjs";
|
|
2
|
+
import { c as toolExecutor, o as spawnTool, s as mcpCallExecutor } from "./src-DP02RP9O.mjs";
|
|
3
|
+
import { n as newRunId } from "./find-B30-rd-u.mjs";
|
|
3
4
|
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
5
|
import { n as chip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { t as acceptRefusal } from "./in-a-run-DKoMGTNE.mjs";
|
|
6
|
+
import { i as runLimits, r as limitsRefusal } from "./limits-CXh052II.mjs";
|
|
7
|
+
import { t as acceptRefusal } from "./in-a-run-CZFzoT3R.mjs";
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { mkdirSync } from "node:fs";
|
|
10
10
|
import { homedir } from "node:os";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as isBuiltinArg, n as builtinWorkflowFile, t as builtinProblem } from "./builtin-files-
|
|
1
|
+
import { Kr as runDirOf, R as openStore, Ur as placeFiles, Wr as placeFor, Yr as inside, z as storePath } from "./src-Ciy7i3se.mjs";
|
|
2
|
+
import { a as isBuiltinArg, n as builtinWorkflowFile, t as builtinProblem } from "./builtin-files-CWL3JEo-.mjs";
|
|
3
3
|
import { l as writeErr } from "./output-B1kwo0YU.mjs";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
5
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
6
6
|
// src/project/place.ts
|
|
7
7
|
/**
|
|
8
8
|
* @file Which project a folder belongs to, from the projects the store has
|
|
@@ -86,4 +86,28 @@ const workflowArg = (arg, cwd) => {
|
|
|
86
86
|
runDir: (runId) => runDirOf(place, runId)
|
|
87
87
|
};
|
|
88
88
|
};
|
|
89
|
-
|
|
89
|
+
/**
|
|
90
|
+
* The `name:` line of a workflow file, read without parsing it (it may be
|
|
91
|
+
* broken).
|
|
92
|
+
*/
|
|
93
|
+
const nameOf = (file) => {
|
|
94
|
+
try {
|
|
95
|
+
return /^name:\s*["']?([^\s"'#]+)/mu.exec(readFileSync(file, "utf8"))?.[1];
|
|
96
|
+
} catch {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* The text for a workflow argument that is no file: the workflows the project
|
|
102
|
+
* has, by file name (and `name:` when it differs), and that a file name or path
|
|
103
|
+
* is what the command takes. Empty-handed when the folder is missing.
|
|
104
|
+
*/
|
|
105
|
+
const missingWorkflowText = (arg, workflows) => {
|
|
106
|
+
const listed = (existsSync(workflows) ? readdirSync(workflows).filter((name) => name.endsWith(WORKFLOW_SUFFIX)).toSorted() : []).map((file) => {
|
|
107
|
+
const name = nameOf(path.join(workflows, file));
|
|
108
|
+
const stem = file.slice(0, -9);
|
|
109
|
+
return name === void 0 || name === stem ? file : `${file} (${name})`;
|
|
110
|
+
});
|
|
111
|
+
return `no workflow file ${arg}; a file name or path is meant, not a workflow name (${listed.length === 0 ? "this project has no workflows" : `this project's workflows: ${listed.join(", ")}`})`;
|
|
112
|
+
};
|
|
113
|
+
export { refusedBuiltin as a, projectAt as c, missingWorkflowText as i, registeredProjects as l, WORKFLOW_SUFFIX as n, resolveWorkflowArg as o, findWorkflowFiles as r, workflowArg as s, WORKFLOW_DIR as t };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $t as stepActs, Jt as worktreeListTable, Qt as planClean, R as openStore, Yt as applyClean, Zt as keyOf, a as planRemove, c as repoRoot, d as mergeStateOf, f as planLine, i as lostWork, l as isDetached, m as stateParts, r as applyRemove, s as readWorktrees, tn as inspectProject, u as labelOf } from "./src-Ciy7i3se.mjs";
|
|
2
2
|
import { t as applyFilters } from "./apply-Mb0fNpCX.mjs";
|
|
3
3
|
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";
|
|
4
4
|
import { n as chip } from "./chips-BqcT58qr.mjs";
|
|
5
|
-
import { i as readListArgs, n as filterArgs, r as projectScope } from "./flags-
|
|
6
|
-
import { t as printList } from "./print-
|
|
7
|
-
import { r as withStore } from "./project-records-
|
|
5
|
+
import { i as readListArgs, n as filterArgs, o as resolveRun, r as projectScope, s as refuseUnknownFlags } from "./flags-ByYBx-Xb.mjs";
|
|
6
|
+
import { t as printList } from "./print-Bd8MWVJk.mjs";
|
|
7
|
+
import { r as withStore } from "./project-records-BOEVs69i.mjs";
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { existsSync, realpathSync } from "node:fs";
|
|
10
10
|
import { defineCommand } from "citty";
|
|
@@ -42,7 +42,7 @@ const worktreeState = (item, term = termOf(process.stdout)) => {
|
|
|
42
42
|
return [...head, ...parts].join(" · ");
|
|
43
43
|
};
|
|
44
44
|
/** A name as the list shows it, saying when it's detached. */
|
|
45
|
-
const nameOf = (item) =>
|
|
45
|
+
const nameOf = (item) => isDetached(item) ? `${labelOf(item)} (detached)` : labelOf(item);
|
|
46
46
|
const formatWorktrees = (items, term = termOf(process.stdout)) => {
|
|
47
47
|
if (items.length === 0) return ["No Ork worktrees or branches."];
|
|
48
48
|
const width = Math.max(...items.map((i) => nameOf(i).length));
|
|
@@ -131,13 +131,15 @@ const show = async (args) => {
|
|
|
131
131
|
const projects = withStore((store) => store.projects());
|
|
132
132
|
const scope = projectScope(request.filter, projects);
|
|
133
133
|
if (scope === void 0) return;
|
|
134
|
+
const filter = withStore((store) => resolveRun(store, request.filter));
|
|
135
|
+
if (filter === void 0) return;
|
|
134
136
|
let items;
|
|
135
137
|
if (scope === "here") {
|
|
136
138
|
const found = await here(true);
|
|
137
139
|
if (found === null) return;
|
|
138
140
|
items = found.items;
|
|
139
141
|
} else items = await inProjects(scope === "all" ? projects.map((p) => p.root) : [scope.root]);
|
|
140
|
-
const shown = applyFilters(worktreeListTable, items,
|
|
142
|
+
const shown = applyFilters(worktreeListTable, items, filter).slice(0, request.limit);
|
|
141
143
|
printList(shown, worktreeListTable, args, (rows) => {
|
|
142
144
|
for (const line of formatWorktrees(rows)) write(line);
|
|
143
145
|
});
|
|
@@ -148,6 +150,7 @@ const list = defineCommand({
|
|
|
148
150
|
name: "list",
|
|
149
151
|
description: "List Ork's worktrees and branches (the default)"
|
|
150
152
|
},
|
|
153
|
+
plugins: [refuseUnknownFlags],
|
|
151
154
|
args: listArgs,
|
|
152
155
|
run: ({ args }) => show(args)
|
|
153
156
|
});
|
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.19",
|
|
4
4
|
"description": "Orchestrate coding agents (Claude Code, OpenCode, Command Code) on your machine: hierarchical, serializable workflows with a CLI and a localhost UI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
package/dist/flags-CqjJ44uW.mjs
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import "./src-Frwpx3WF.mjs";
|
|
2
|
-
import { n as parseLimit, t as parseFilters } from "./parse-BzWpMN-a.mjs";
|
|
3
|
-
import { t as INTERNAL } from "./command-tree-BkSYWmYJ.mjs";
|
|
4
|
-
import { l as writeErr } from "./output-B1kwo0YU.mjs";
|
|
5
|
-
// src/list/all-alias.ts
|
|
6
|
-
/**
|
|
7
|
-
* @file The deprecated `--all` of `ps`, `usage`, `decide`, `follow-ups list`
|
|
8
|
-
* and `feedback list` (RFC-017): it stands for `--project all` or `--status
|
|
9
|
-
* all`, is left out of `--help` and Tab completion (an `Internal:` flag), and
|
|
10
|
-
* warns once on stderr. `prune --all` is not this one.
|
|
11
|
-
*/
|
|
12
|
-
/** The hidden `--all` flag, for a command's `args`. */
|
|
13
|
-
const allAlias = { all: {
|
|
14
|
-
type: "boolean",
|
|
15
|
-
description: `${INTERNAL} deprecated, use --project all or --status all`,
|
|
16
|
-
default: false
|
|
17
|
-
} };
|
|
18
|
-
/**
|
|
19
|
-
* `args` with `all` in `--all`'s place when `--all` was given and that flag was
|
|
20
|
-
* not (a given one wins); the warning prints either way. `args` as is when
|
|
21
|
-
* `--all` was not given.
|
|
22
|
-
*/
|
|
23
|
-
const warnAll = (args, flag) => {
|
|
24
|
-
if (args["all"] !== true) return args;
|
|
25
|
-
writeErr(`--all is deprecated; use --${flag} all.`);
|
|
26
|
-
return args[flag] === void 0 ? {
|
|
27
|
-
...args,
|
|
28
|
-
[flag]: "all"
|
|
29
|
-
} : args;
|
|
30
|
-
};
|
|
31
|
-
// src/list/flags.ts
|
|
32
|
-
/**
|
|
33
|
-
* @file The flags every list command shares (RFC-017), made from its field
|
|
34
|
-
* table: one flag per field (an enum field's values as citty `options`, so
|
|
35
|
-
* `--help` and Tab completion read them), `--ids`, `--limit` and `--json`;
|
|
36
|
-
* and reading them back: each value checked by core's `parseFilters`,
|
|
37
|
-
* `--limit` a positive whole number, `--project` a registered one. A refusal
|
|
38
|
-
* says why on stderr and sets the exit code; the command then returns.
|
|
39
|
-
*/
|
|
40
|
-
const fieldArg = (field) => {
|
|
41
|
-
if (field.type !== "enum") return {
|
|
42
|
-
type: "string",
|
|
43
|
-
description: field.description
|
|
44
|
-
};
|
|
45
|
-
return {
|
|
46
|
-
type: "enum",
|
|
47
|
-
options: [...field.values ?? [], ...field.all === true ? ["all"] : []],
|
|
48
|
-
description: field.description
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
/** The citty flags of `table`, then `--ids`, `--limit`, `--json`, `extra`. */
|
|
52
|
-
const filterArgs = (table, options = {}) => ({
|
|
53
|
-
...Object.fromEntries(table.fields.map((field) => [field.name, fieldArg(field)])),
|
|
54
|
-
...options.ids ?? table.id !== void 0 ? { ids: {
|
|
55
|
-
type: "boolean",
|
|
56
|
-
description: "Print only the ids, comma-separated, on one line",
|
|
57
|
-
default: false
|
|
58
|
-
} } : {},
|
|
59
|
-
...options.limit ?? true ? { limit: {
|
|
60
|
-
type: "string",
|
|
61
|
-
description: "Show at most this many (a positive whole number)"
|
|
62
|
-
} } : {},
|
|
63
|
-
...options.json ?? true ? { json: {
|
|
64
|
-
type: "boolean",
|
|
65
|
-
description: "Print JSON",
|
|
66
|
-
default: false
|
|
67
|
-
} } : {},
|
|
68
|
-
...options.extra
|
|
69
|
-
});
|
|
70
|
-
/** Says why, and makes the command exit 1. */
|
|
71
|
-
const fail = (message) => {
|
|
72
|
-
writeErr(message);
|
|
73
|
-
process.exitCode = 1;
|
|
74
|
-
};
|
|
75
|
-
/** The `--ids` with `--json` refusal; `true` when `args` has both. */
|
|
76
|
-
const refuseIdsWithJson = (args) => {
|
|
77
|
-
if (args.ids !== true || args.json !== true) return false;
|
|
78
|
-
fail("--ids and --json can't be used together.");
|
|
79
|
-
return true;
|
|
80
|
-
};
|
|
81
|
-
/**
|
|
82
|
-
* `args` (a command's parsed flags) read against `table`: the filter, and the
|
|
83
|
-
* limit. `all` names the flag `--all` stands for (`project` or `status`):
|
|
84
|
-
* `--all` fills it when it is not given, with one warning. `undefined` when
|
|
85
|
-
* something was refused (already said, exit code set).
|
|
86
|
-
*/
|
|
87
|
-
const readListArgs = (table, args, options = {}) => {
|
|
88
|
-
if (refuseIdsWithJson(args)) return void 0;
|
|
89
|
-
const given = options.all === void 0 ? args : warnAll(args, options.all);
|
|
90
|
-
const parsed = parseFilters(table, given, options.now ?? Date.now());
|
|
91
|
-
if (!parsed.ok) {
|
|
92
|
-
fail(parsed.error);
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
const text = args["limit"];
|
|
96
|
-
if (typeof text !== "string") return {
|
|
97
|
-
filter: parsed.filter,
|
|
98
|
-
limit: void 0
|
|
99
|
-
};
|
|
100
|
-
const limit = parseLimit(text);
|
|
101
|
-
if (limit === null) {
|
|
102
|
-
fail(`--limit takes a positive whole number, not \`${text}\`.`);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
filter: parsed.filter,
|
|
107
|
-
limit
|
|
108
|
-
};
|
|
109
|
-
};
|
|
110
|
-
/**
|
|
111
|
-
* The scope the filter's `project` names, checked against the registered
|
|
112
|
-
* projects (core does not know them): an id or a root, or `all`; none given is
|
|
113
|
-
* `here`. A project not registered is refused, listing the registered ones
|
|
114
|
-
* (said, exit code set, `undefined`).
|
|
115
|
-
*/
|
|
116
|
-
const projectScope = (filter, projects) => {
|
|
117
|
-
const key = filter["project"];
|
|
118
|
-
if (key === void 0) return "here";
|
|
119
|
-
if (key === "all") return "all";
|
|
120
|
-
const found = projects.find((p) => p.id === key || p.root === key);
|
|
121
|
-
if (found !== void 0) return { root: found.root };
|
|
122
|
-
const names = projects.map((p) => p.id);
|
|
123
|
-
fail(`No registered project \`${key}\`; registered: ${names.length === 0 ? "none" : names.join(", ")}.`);
|
|
124
|
-
};
|
|
125
|
-
export { refuseIdsWithJson as a, readListArgs as i, filterArgs as n, allAlias as o, projectScope as r, fail as t };
|
package/dist/post-y1qL1Fnj.mjs
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { ar as redact } from "./src-Frwpx3WF.mjs";
|
|
2
|
-
import { b as githubDraftRefusal } from "./__build_info__-B8TNbFtN.mjs";
|
|
3
|
-
// ../core/src/follow-ups/post.ts
|
|
4
|
-
/** Posts `f`'s draft as a GitHub comment once `confirmed`, and marks it done. */
|
|
5
|
-
const postFollowUpMessage = async (f, options) => {
|
|
6
|
-
const draft = f.draft;
|
|
7
|
-
const refused = githubDraftRefusal(f);
|
|
8
|
-
if (refused !== void 0 || draft === void 0) return {
|
|
9
|
-
ok: false,
|
|
10
|
-
error: refused?.error ?? "it has no draft"
|
|
11
|
-
};
|
|
12
|
-
if (!options.confirmed) return {
|
|
13
|
-
ok: false,
|
|
14
|
-
error: "posting to GitHub needs the maintainer's confirmation"
|
|
15
|
-
};
|
|
16
|
-
const body = redact(draft.text, {
|
|
17
|
-
roots: [f.project],
|
|
18
|
-
home: options.home
|
|
19
|
-
});
|
|
20
|
-
const on = /\/pull\/\d+/u.test(draft.to) ? "pr" : "issue";
|
|
21
|
-
const result = await options.gh([
|
|
22
|
-
on,
|
|
23
|
-
"comment",
|
|
24
|
-
draft.to,
|
|
25
|
-
"--body",
|
|
26
|
-
body
|
|
27
|
-
], { cwd: f.project });
|
|
28
|
-
if (!result.ok) return {
|
|
29
|
-
ok: false,
|
|
30
|
-
error: `gh failed: ${result.stderr.trim() || result.stdout.trim() || "no output"}`
|
|
31
|
-
};
|
|
32
|
-
const url = result.stdout.trim().split("\n").findLast((line) => line.startsWith("https://"));
|
|
33
|
-
const done = {
|
|
34
|
-
...f,
|
|
35
|
-
status: "done",
|
|
36
|
-
note: `posted${url === void 0 ? "" : ` as ${url}`}`,
|
|
37
|
-
updatedAt: options.now?.() ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
38
|
-
};
|
|
39
|
-
options.rows.putFollowUp(done);
|
|
40
|
-
return {
|
|
41
|
-
ok: true,
|
|
42
|
-
followUp: done,
|
|
43
|
-
...url === void 0 ? {} : { url }
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
export { postFollowUpMessage as t };
|