@krapht/ork 1.0.0-alpha.14 → 1.0.0-alpha.15
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__-Bsb1kjgF.mjs +340 -0
- package/dist/{store-CleF7KeS.mjs → attach-BHO3X3cf.mjs} +16 -19
- package/dist/{attach-CdtGX9se.mjs → attach-CPespxlQ.mjs} +5 -4
- package/dist/bin.mjs +64 -1339
- package/dist/brief-za0ozN_E.mjs +58 -0
- package/dist/{builtin-files-Bdq23IIi.mjs → builtin-files-2bHf76x-.mjs} +1 -1
- package/dist/{completion--ywde-56.mjs → completion-CQ2UYKuJ.mjs} +5 -5
- package/dist/context-BNqDw9z1.mjs +106 -0
- package/dist/{find-BVX-bL4u.mjs → find-BYLlszqj.mjs} +1 -1
- package/dist/follow-ups-B4GJ3Vzw.mjs +461 -0
- package/dist/{format-CvTE5CZQ.mjs → format-C8MsFj8_.mjs} +19 -5
- package/dist/{help-groups-CpR2UzSn.mjs → help-groups-CQ98mLjF.mjs} +4 -0
- package/dist/{in-a-run-cL5N9gpH.mjs → in-a-run-Bp0k0J09.mjs} +1 -1
- package/dist/{__build_info__-B82-dGJY.mjs → install-DWtXTq4y.mjs} +3 -227
- package/dist/{limits-Dhe--wmX.mjs → limits-B1qzS4cX.mjs} +1 -1
- package/dist/{mcp-CsmboyXv.mjs → mcp-BOrVkyhN.mjs} +6 -6
- package/dist/{once-CrwI-ZdN.mjs → once-C1fL3GVo.mjs} +3 -3
- package/dist/orphan-guard-BFKg8VSd.mjs +58 -0
- package/dist/{pause-DssrYcda.mjs → pause-DOMK-R8V.mjs} +3 -3
- package/dist/post-BzA6Qobq.mjs +44 -0
- package/dist/{relay-DASRgsTQ.mjs → relay-OWuu4fib.mjs} +1 -1
- package/dist/run--4-1xAF2.mjs +1451 -0
- package/dist/{run-D8divGCs.mjs → run-CiPsW9Kf.mjs} +1 -1
- package/dist/{send-CXv8bx0i.mjs → send-CnNNW-ot.mjs} +2 -2
- package/dist/{src-njdtejgZ.mjs → src-B9zWIVqo.mjs} +129 -12
- package/dist/{src-8Mul0695.mjs → src-DQKz2eOH.mjs} +322 -75
- package/dist/{src-C7z_6fhn.mjs → src-DcrhgipG.mjs} +17 -10
- package/dist/{src-tsuZRu0H.mjs → src-Dr_fTSu-.mjs} +4832 -4155
- package/dist/store-oKJ-cCf3.mjs +16 -0
- package/dist/ui/assets/app-Bdc6OBeZ.css +1 -0
- package/dist/ui/assets/app-Drp8Dm9y.js +111 -0
- package/dist/ui/assets/{index-D-_uPI2v.js → index-BtwkftKe.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-CNO1M0qT.mjs → ui-CzKlsCnm.mjs} +3 -3
- package/dist/{usage-BVXi0iFY.mjs → usage-DHGNk2JL.mjs} +3 -3
- package/dist/{context-Y_I4Mofq.mjs → validate-Bs_gg22g.mjs} +4 -104
- package/dist/{watch-DVNIciHp.mjs → watch-CCCfw3n7.mjs} +19 -5
- package/dist/{workflows-B30QkwTk.mjs → workflows-CW28ZU-z.mjs} +2 -2
- package/dist/{worktrees-DD4_TpkH.mjs → worktrees-CyE8aF6j.mjs} +1 -1
- package/package.json +1 -1
- package/dist/ui/assets/app-D_nAPnHM.css +0 -1
- package/dist/ui/assets/app-DqBAtXSZ.js +0 -111
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { A as isNewer, j as parseVersion, k as compareVersions } from "./src-Dr_fTSu-.mjs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
// ../core/src/follow-ups/change.ts
|
|
6
|
+
/** The project's follow-up whose id is, or starts with, `prefix`. */
|
|
7
|
+
const findFollowUp = (rows, project, prefix) => {
|
|
8
|
+
const exact = rows.followUp(project, prefix);
|
|
9
|
+
if (exact !== void 0) return {
|
|
10
|
+
ok: true,
|
|
11
|
+
followUp: exact
|
|
12
|
+
};
|
|
13
|
+
const matches = prefix === "" ? [] : rows.followUps(project).filter((f) => f.id.startsWith(prefix));
|
|
14
|
+
const [only, other] = matches;
|
|
15
|
+
if (only === void 0) return {
|
|
16
|
+
ok: false,
|
|
17
|
+
error: `No follow-up \`${prefix}\` in this project.`
|
|
18
|
+
};
|
|
19
|
+
if (other !== void 0) return {
|
|
20
|
+
ok: false,
|
|
21
|
+
error: `\`${prefix}\` matches ${matches.map((f) => f.id).join(", ")}; give more of the id.`
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
ok: true,
|
|
25
|
+
followUp: only
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/** Which statuses each action starts from, and where it goes. */
|
|
29
|
+
const ACTIONS = {
|
|
30
|
+
done: {
|
|
31
|
+
from: ["waiting", "due"],
|
|
32
|
+
to: () => "done",
|
|
33
|
+
note: "done"
|
|
34
|
+
},
|
|
35
|
+
drop: {
|
|
36
|
+
from: ["waiting", "due"],
|
|
37
|
+
to: () => "dropped",
|
|
38
|
+
note: "dropped"
|
|
39
|
+
},
|
|
40
|
+
reopen: {
|
|
41
|
+
from: ["done", "dropped"],
|
|
42
|
+
to: (f) => f.due === "now" ? "due" : "waiting",
|
|
43
|
+
note: "reopened"
|
|
44
|
+
},
|
|
45
|
+
due: {
|
|
46
|
+
from: ["waiting"],
|
|
47
|
+
to: () => "due",
|
|
48
|
+
note: "marked due"
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
/** Why `action` can't be done to `f` now, or `undefined`. */
|
|
52
|
+
const refusal = (f, action) => {
|
|
53
|
+
const rule = ACTIONS[action];
|
|
54
|
+
return rule.from.includes(f.status) ? void 0 : `${f.id} is ${f.status}, so it can't be ${rule.note}.`;
|
|
55
|
+
};
|
|
56
|
+
const check = (f, action) => {
|
|
57
|
+
const error = refusal(f, action);
|
|
58
|
+
return error === void 0 ? { ok: true } : {
|
|
59
|
+
ok: false,
|
|
60
|
+
why: `it is ${f.status}`,
|
|
61
|
+
error
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
const postCheck = (f) => {
|
|
65
|
+
const open = f.status === "waiting" || f.status === "due";
|
|
66
|
+
if (f.kind !== "message" || f.draft?.channel !== "github") return {
|
|
67
|
+
ok: false,
|
|
68
|
+
why: "not drafted for the github channel",
|
|
69
|
+
error: "only a message drafted for the github channel is posted; send the others yourself"
|
|
70
|
+
};
|
|
71
|
+
return open ? { ok: true } : {
|
|
72
|
+
ok: false,
|
|
73
|
+
why: `it is ${f.status}`,
|
|
74
|
+
error: `${f.id} is ${f.status}, so it is not posted.`
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
const followUpActions = (f) => ({
|
|
78
|
+
done: check(f, "done"),
|
|
79
|
+
drop: check(f, "drop"),
|
|
80
|
+
reopen: check(f, "reopen"),
|
|
81
|
+
due: check(f, "due"),
|
|
82
|
+
post: postCheck(f)
|
|
83
|
+
});
|
|
84
|
+
/** Applies `action` to `followUp`, and keeps it. */
|
|
85
|
+
const changeFollowUp = (rows, followUp, action, now = () => (/* @__PURE__ */ new Date()).toISOString()) => {
|
|
86
|
+
const rule = ACTIONS[action];
|
|
87
|
+
const refused = refusal(followUp, action);
|
|
88
|
+
if (refused !== void 0) return {
|
|
89
|
+
ok: false,
|
|
90
|
+
error: refused
|
|
91
|
+
};
|
|
92
|
+
const { note: _old, ...rest } = followUp;
|
|
93
|
+
const changed = {
|
|
94
|
+
...rest,
|
|
95
|
+
status: rule.to(followUp),
|
|
96
|
+
note: rule.note,
|
|
97
|
+
updatedAt: now()
|
|
98
|
+
};
|
|
99
|
+
rows.putFollowUp(changed);
|
|
100
|
+
return {
|
|
101
|
+
ok: true,
|
|
102
|
+
followUp: changed
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Why a due follow-up is due, read from the note `due.ts` left: its ref merged,
|
|
107
|
+
* its date came, its ref closed unmerged, or a person marked it. `undefined`
|
|
108
|
+
* for one that is not due, or was due from the start.
|
|
109
|
+
*/
|
|
110
|
+
const dueCause = (f) => {
|
|
111
|
+
if (f.status !== "due" || f.note === void 0) return void 0;
|
|
112
|
+
if (f.note.includes("closed without merging")) return "closed-unmerged";
|
|
113
|
+
if (f.note.endsWith(" merged")) return "merged";
|
|
114
|
+
if (f.note.startsWith("due on ")) return "overdue";
|
|
115
|
+
return f.note === "marked due" ? "marked" : void 0;
|
|
116
|
+
};
|
|
117
|
+
// ../core/src/remote/session.ts
|
|
118
|
+
const chattable = (type) => type === "agent.leader" || type === "agent.worker";
|
|
119
|
+
/** Reads `node`'s session from a run's events, and every node's last output. */
|
|
120
|
+
const nodeSession = (events, node) => {
|
|
121
|
+
const session = {
|
|
122
|
+
known: false,
|
|
123
|
+
chattable: false,
|
|
124
|
+
running: false
|
|
125
|
+
};
|
|
126
|
+
const outputs = {};
|
|
127
|
+
for (const { event } of events) {
|
|
128
|
+
if (event.type === "run.started") {
|
|
129
|
+
const declared = event.nodes.find((n) => n.id === node);
|
|
130
|
+
if (declared !== void 0) {
|
|
131
|
+
session.known = true;
|
|
132
|
+
session.chattable = chattable(declared.type);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (event.type === "node.finished") outputs[event.id] = event.output;
|
|
136
|
+
if (!("id" in event) || event.id !== node) continue;
|
|
137
|
+
if (event.type === "node.started") {
|
|
138
|
+
session.known = true;
|
|
139
|
+
session.chattable = chattable(event.nodeType);
|
|
140
|
+
session.running = true;
|
|
141
|
+
}
|
|
142
|
+
if (event.type === "node.finished") session.running = false;
|
|
143
|
+
if (event.type === "worktree" && event.action === "created") session.checkout = {
|
|
144
|
+
path: event.path,
|
|
145
|
+
...event.branch === void 0 ? {} : { branch: event.branch },
|
|
146
|
+
own: true,
|
|
147
|
+
owner: node
|
|
148
|
+
};
|
|
149
|
+
if (event.type !== "node.event") continue;
|
|
150
|
+
const inner = event.event;
|
|
151
|
+
if (inner.fork === true) continue;
|
|
152
|
+
if (inner.type === "session.started") {
|
|
153
|
+
session.sessionId = inner.sessionId;
|
|
154
|
+
if (inner.cwd !== void 0) session.cwd = inner.cwd;
|
|
155
|
+
if (inner.driver !== void 0) session.driver = inner.driver;
|
|
156
|
+
if (inner.model !== "") session.model = inner.model;
|
|
157
|
+
}
|
|
158
|
+
if (inner.type === "session.finished" && inner.outcome.sessionId !== "") session.sessionId = inner.outcome.sessionId;
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
session,
|
|
162
|
+
outputs
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
/** The dist-tags every install follows, toward and after 1.0.0. */
|
|
166
|
+
const CHANNEL_TAGS = [
|
|
167
|
+
"latest",
|
|
168
|
+
"alpha",
|
|
169
|
+
"beta",
|
|
170
|
+
"rc"
|
|
171
|
+
];
|
|
172
|
+
/** The dist-tag of snapshots from `main`, followed only by a canary. */
|
|
173
|
+
const CANARY_TAG = "canary";
|
|
174
|
+
const updateCachePath = (home = homedir()) => path.join(home, ".ork", "update-check.json");
|
|
175
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
176
|
+
const text = (record, key) => {
|
|
177
|
+
const value = record[key];
|
|
178
|
+
return typeof value === "string" ? value : void 0;
|
|
179
|
+
};
|
|
180
|
+
const notifiedOf = (value) => {
|
|
181
|
+
if (!isRecord(value)) return void 0;
|
|
182
|
+
const version = text(value, "version");
|
|
183
|
+
const at = text(value, "at");
|
|
184
|
+
return version === void 0 || at === void 0 ? void 0 : {
|
|
185
|
+
version,
|
|
186
|
+
at
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
/** The cache, or `null` when there is none or it cannot be read. */
|
|
190
|
+
const readUpdateCache = (file) => {
|
|
191
|
+
let parsed;
|
|
192
|
+
try {
|
|
193
|
+
parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
194
|
+
} catch {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
if (!isRecord(parsed)) return null;
|
|
198
|
+
const checkedAt = text(parsed, "checkedAt");
|
|
199
|
+
if (checkedAt === void 0) return null;
|
|
200
|
+
const latest = text(parsed, "latest");
|
|
201
|
+
const notified = notifiedOf(parsed["notified"]);
|
|
202
|
+
return {
|
|
203
|
+
checkedAt,
|
|
204
|
+
...latest === void 0 ? {} : { latest },
|
|
205
|
+
...notified === void 0 ? {} : { notified }
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
/** Writes the cache whole (a temporary file, then a rename). */
|
|
209
|
+
const writeUpdateCache = (file, cache) => {
|
|
210
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
211
|
+
const temporary = `${file}.${process.pid}.tmp`;
|
|
212
|
+
writeFileSync(temporary, `${JSON.stringify(cache, null, 2)}\n`);
|
|
213
|
+
renameSync(temporary, file);
|
|
214
|
+
};
|
|
215
|
+
const age = (iso, now) => {
|
|
216
|
+
const time = Date.parse(iso);
|
|
217
|
+
return Number.isNaN(time) ? Infinity : now.getTime() - time;
|
|
218
|
+
};
|
|
219
|
+
/** Whether it is time to ask the registry again. */
|
|
220
|
+
const checkDue = (cache, now) => cache === null || age(cache.checkedAt, now) >= 864e5;
|
|
221
|
+
/** Whether `version` is a canary snapshot: its pre-release starts `canary`. */
|
|
222
|
+
const isCanary = (version) => parseVersion(version)?.pre[0]?.startsWith(CANARY_TAG) === true;
|
|
223
|
+
/**
|
|
224
|
+
* The newest version, by semver precedence, among the dist-tags `current`
|
|
225
|
+
* follows: the channel tags, and `canary` too when `current` is a canary. A tag
|
|
226
|
+
* whose value doesn't parse is skipped; `null` when none does.
|
|
227
|
+
*/
|
|
228
|
+
const newestTagged = (tags, current) => {
|
|
229
|
+
return (current !== void 0 && isCanary(current) ? [...CHANNEL_TAGS, "canary"] : CHANNEL_TAGS).flatMap((tag) => {
|
|
230
|
+
const value = tags[tag];
|
|
231
|
+
const version = typeof value === "string" ? parseVersion(value) : null;
|
|
232
|
+
return typeof value === "string" && version !== null ? [{
|
|
233
|
+
value,
|
|
234
|
+
version
|
|
235
|
+
}] : [];
|
|
236
|
+
}).reduce((best, candidate) => best === null || compareVersions(candidate.version, best.version) > 0 ? candidate : best, null)?.value ?? null;
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* The newest version on the registry that the running version follows ({@link
|
|
240
|
+
* newestTagged}), or `null` on any failure.
|
|
241
|
+
*/
|
|
242
|
+
const fetchLatest = async (name, options = {}) => {
|
|
243
|
+
const registry = (options.registry ?? "https://registry.npmjs.org").replace(/\/+$/u, "");
|
|
244
|
+
const get = options.fetch ?? globalThis.fetch;
|
|
245
|
+
try {
|
|
246
|
+
const response = await get(`${registry}/-/package/${name}/dist-tags`, {
|
|
247
|
+
headers: { accept: "application/json" },
|
|
248
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? 5e3)
|
|
249
|
+
});
|
|
250
|
+
if (!response.ok) return null;
|
|
251
|
+
const tags = await response.json();
|
|
252
|
+
return isRecord(tags) ? newestTagged(tags, options.current) : null;
|
|
253
|
+
} catch {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* Asks the registry and records the answer. A failed check is recorded too, so
|
|
259
|
+
* an offline machine is not asked again until the interval passes; the last
|
|
260
|
+
* known version is kept. `options.current` is the running version.
|
|
261
|
+
*/
|
|
262
|
+
const refreshUpdateCache = async (file, name, now, options = {}) => {
|
|
263
|
+
const before = readUpdateCache(file);
|
|
264
|
+
const latest = await fetchLatest(name, options) ?? before?.latest;
|
|
265
|
+
const cache = {
|
|
266
|
+
...before,
|
|
267
|
+
checkedAt: now.toISOString(),
|
|
268
|
+
...latest === void 0 ? {} : { latest }
|
|
269
|
+
};
|
|
270
|
+
writeUpdateCache(file, cache);
|
|
271
|
+
return cache;
|
|
272
|
+
};
|
|
273
|
+
/** The newer version the cache knows of, if any. */
|
|
274
|
+
const newerVersion = (cache, current) => cache?.latest !== void 0 && isNewer(cache.latest, current) ? cache.latest : null;
|
|
275
|
+
/**
|
|
276
|
+
* The version to tell the user about now: newer than theirs, and not already
|
|
277
|
+
* told today. `null` when there is nothing to say.
|
|
278
|
+
*/
|
|
279
|
+
const pendingNotice = (cache, current, now) => {
|
|
280
|
+
const newer = newerVersion(cache, current);
|
|
281
|
+
if (newer === null) return null;
|
|
282
|
+
const told = cache?.notified;
|
|
283
|
+
return told?.version === newer && age(told.at, now) < 864e5 ? null : newer;
|
|
284
|
+
};
|
|
285
|
+
// ../core/src/update/switches.ts
|
|
286
|
+
/**
|
|
287
|
+
* @file The environment's say over the update check (ADR-038): the variables
|
|
288
|
+
* that turn it off (`ORK_NO_UPDATE_CHECK`, the common `NO_UPDATE_NOTIFIER`,
|
|
289
|
+
* and `CI`), and the registry to ask instead of npm's. The CLI adds its own
|
|
290
|
+
* rules about where a notice may go; the server behind `ork ui` uses only
|
|
291
|
+
* these.
|
|
292
|
+
*/
|
|
293
|
+
/** Turns the automatic check and its notice off. */
|
|
294
|
+
const NO_UPDATE_ENV = "ORK_NO_UPDATE_CHECK";
|
|
295
|
+
/** A registry to ask instead of npm's, e.g. a company mirror. */
|
|
296
|
+
const UPDATE_REGISTRY_ENV = "ORK_UPDATE_REGISTRY";
|
|
297
|
+
/** The variables that turn the check off, in the order they are looked at. */
|
|
298
|
+
const UPDATE_SWITCHES = [
|
|
299
|
+
NO_UPDATE_ENV,
|
|
300
|
+
"NO_UPDATE_NOTIFIER",
|
|
301
|
+
"CI"
|
|
302
|
+
];
|
|
303
|
+
/** Set to anything but empty, `0` or `false`. */
|
|
304
|
+
const isSwitchedOn = (value) => value !== void 0 && value !== "" && value !== "0" && value.toLowerCase() !== "false";
|
|
305
|
+
/** The variable that turns the check off in `env`, or `null` when none does. */
|
|
306
|
+
const updateSwitchOff = (env) => UPDATE_SWITCHES.find((name) => isSwitchedOn(env[name])) ?? null;
|
|
307
|
+
/** The registry `ORK_UPDATE_REGISTRY` names, if it names one. */
|
|
308
|
+
const registryOf = (env) => {
|
|
309
|
+
const registry = env[UPDATE_REGISTRY_ENV];
|
|
310
|
+
return registry === void 0 || registry === "" ? void 0 : registry;
|
|
311
|
+
};
|
|
312
|
+
/** The host of a registry that isn't an http(s) URL, past any `user:pass@`. */
|
|
313
|
+
const hostOf = (registry) => registry.replace(/^[a-z][\w+.-]*:\/\//iu, "").replace(/^[^/?#]*@/u, "").split(/[/?#]/u)[0] ?? "";
|
|
314
|
+
/**
|
|
315
|
+
* The registry as it may be shown (on a page, in a message): an http(s) URL
|
|
316
|
+
* without its user name and password, which a mirror's URL may carry; anything
|
|
317
|
+
* else only as its host.
|
|
318
|
+
*/
|
|
319
|
+
const registryShown = (registry) => {
|
|
320
|
+
try {
|
|
321
|
+
const url = new URL(registry);
|
|
322
|
+
if (url.protocol === "http:" || url.protocol === "https:") {
|
|
323
|
+
if (url.username === "" && url.password === "") return registry;
|
|
324
|
+
url.username = "";
|
|
325
|
+
url.password = "";
|
|
326
|
+
return url.href;
|
|
327
|
+
}
|
|
328
|
+
} catch {}
|
|
329
|
+
return hostOf(registry);
|
|
330
|
+
};
|
|
331
|
+
// src/__build_info__.ts
|
|
332
|
+
/**
|
|
333
|
+
* @file The published package's name and version, bound to
|
|
334
|
+
* `packages/cli/package.json`. Do not edit by hand: `pnpm changesets:version`
|
|
335
|
+
* and `pnpm build` rewrite it (`tools/release/build-info.ts`), and a test
|
|
336
|
+
* fails when it is stale.
|
|
337
|
+
*/
|
|
338
|
+
const ORK_NAME = "@krapht/ork";
|
|
339
|
+
const ORK_VERSION = "1.0.0-alpha.15";
|
|
340
|
+
export { dueCause as _, registryShown as a, fetchLatest as c, readUpdateCache as d, refreshUpdateCache as f, changeFollowUp as g, nodeSession as h, registryOf as i, newerVersion as l, writeUpdateCache as m, ORK_VERSION as n, updateSwitchOff as o, updateCachePath as p, isSwitchedOn as r, checkDue as s, ORK_NAME as t, pendingNotice as u, findFollowUp as v, followUpActions as y };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bn as outcomeEnd, H as isNodeEvent, Hn as END_KINDS, Lt as lockWaitLine, Ut as slotWaitLine, _t as followEvents, ct as followRunTree, fr as maskSecrets, lt as answerDecision, ut as pendingDecisions, zn as endOf } from "./src-Dr_fTSu-.mjs";
|
|
2
2
|
import { C as termOf, D as wrap, E as widthOf, O as readKeys, _ as interrupt, a as plain, b as canKey, g as createRegion, h as paint, m as bold, n as cost, p as apply, r as costOf, s as style, u as confirmOrStop, v as readLine, w as cut, x as plainEnv, y as withdrawn } from "./output-B1kwo0YU.mjs";
|
|
3
3
|
import { n as chip, r as nodeChip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
|
|
4
4
|
import { a as createView, i as formatBusEvent, n as nodeVerdict, o as styler, r as firstLine, t as hasConflict } from "./verdict-CMvPCpWC.mjs";
|
|
@@ -769,8 +769,9 @@ const createTerminalHuman = (io) => {
|
|
|
769
769
|
/**
|
|
770
770
|
* @file How a node's end reads on the terminal (specs/runtime/session-ends.md):
|
|
771
771
|
* its kind's label and Ork's own message, a note for a kind that may pass,
|
|
772
|
-
* the setup hint for an account or provider end,
|
|
773
|
-
* only when asked for. Never
|
|
772
|
+
* the setup hint for an account or provider end, the last line of a failed
|
|
773
|
+
* tool's own stderr, and the scrubbed raw detail only when asked for. Never
|
|
774
|
+
* the provider's own words first.
|
|
774
775
|
*/
|
|
775
776
|
/** What a transient kind says in place of its hint on the log line. */
|
|
776
777
|
const MAY_PASS = "(may pass; ork resume retries)";
|
|
@@ -779,11 +780,17 @@ const endHeadline = (end) => {
|
|
|
779
780
|
const { label, transient } = END_KINDS[end.kind];
|
|
780
781
|
return `${label}: ${end.message}${transient ? ` ${MAY_PASS}` : ""}`;
|
|
781
782
|
};
|
|
783
|
+
/** The longest a script's last stderr line is shown on the log line. */
|
|
784
|
+
const LAST_LINE_LIMIT = 200;
|
|
785
|
+
/** The last non-empty line of a scrubbed detail, cut; "" when there is none. */
|
|
786
|
+
const lastLine = (detail) => (detail ?? "").split("\n").map((line) => line.trim()).findLast((line) => line !== "")?.slice(0, LAST_LINE_LIMIT) ?? "";
|
|
782
787
|
/**
|
|
783
788
|
* The lines under a headline: the hint for an account or provider end (what to
|
|
784
789
|
* set up) or whenever `full` (`--verbose`, one node's log), and the detail only
|
|
785
790
|
* when `full`. A transient kind's hint is its retry wording, which the headline
|
|
786
|
-
* already says, so it is not printed twice.
|
|
791
|
+
* already says, so it is not printed twice. A failed tool (`command_failed`)
|
|
792
|
+
* also shows the last line of its detail without `full`: a script's stderr is
|
|
793
|
+
* the workflow's own message, not the provider's.
|
|
787
794
|
*/
|
|
788
795
|
const endLines = (end, full, term = createView().term) => {
|
|
789
796
|
const style = styler(term);
|
|
@@ -792,6 +799,10 @@ const endLines = (end, full, term = createView().term) => {
|
|
|
792
799
|
const lines = [];
|
|
793
800
|
if (hint !== "" && !transient && (full || setup)) lines.push(` ${style("dim", hint)}`);
|
|
794
801
|
if (full && end.detail !== void 0) lines.push(style("dim", " details:"), ...end.detail.split("\n").map((line) => style("dim", ` ${line}`)));
|
|
802
|
+
else if (end.kind === "command_failed") {
|
|
803
|
+
const last = lastLine(end.detail);
|
|
804
|
+
if (last !== "") lines.push(` ${style("dim", last)}`);
|
|
805
|
+
}
|
|
795
806
|
return lines;
|
|
796
807
|
};
|
|
797
808
|
/**
|
|
@@ -1296,18 +1307,4 @@ const attachRun = async (store, root, out, options = {}) => {
|
|
|
1296
1307
|
exitCode: end === "aborted" || seen.succeeded ? 0 : 1
|
|
1297
1308
|
};
|
|
1298
1309
|
};
|
|
1299
|
-
|
|
1300
|
-
/**
|
|
1301
|
-
* @file Opening the user's store (`~/.ork/state.db`) for the length of one
|
|
1302
|
-
* command, and closing it after, whatever happens.
|
|
1303
|
-
*/
|
|
1304
|
-
/** Runs `body` with the user's store open, and closes it after. */
|
|
1305
|
-
const withStore = async (body) => {
|
|
1306
|
-
const store = openStore();
|
|
1307
|
-
try {
|
|
1308
|
-
await body(store);
|
|
1309
|
-
} finally {
|
|
1310
|
-
store.close();
|
|
1311
|
-
}
|
|
1312
|
-
};
|
|
1313
|
-
export { unknownNode as a, callsShown as c, createDecisionQueue as d, followRun as i, createTerminalHuman as l, attachRun as n, formatEvent as o, askStored as r, formatRunEvent as s, withStore as t, readText as u };
|
|
1310
|
+
export { formatEvent as a, createTerminalHuman as c, unknownNode as i, readText as l, askStored as n, formatRunEvent as o, followRun as r, callsShown as s, attachRun as t, createDecisionQueue as u };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import "./src-
|
|
2
|
-
import {
|
|
3
|
-
import { t as findRun } from "./find-
|
|
1
|
+
import "./src-Dr_fTSu-.mjs";
|
|
2
|
+
import { c as createTerminalHuman, t as attachRun } from "./attach-BHO3X3cf.mjs";
|
|
3
|
+
import { t as findRun } from "./find-BYLlszqj.mjs";
|
|
4
4
|
import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
|
|
5
|
-
import { n as attachRefusal } from "./in-a-run-
|
|
5
|
+
import { n as attachRefusal } from "./in-a-run-Bp0k0J09.mjs";
|
|
6
|
+
import { t as withStore } from "./store-oKJ-cCf3.mjs";
|
|
6
7
|
import { defineCommand } from "citty";
|
|
7
8
|
// src/commands/attach.ts
|
|
8
9
|
/**
|