@krapht/ork 1.0.0-alpha.17 → 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__-C1Nm0hlJ.mjs → __build_info__-dPf4cEGL.mjs} +3 -134
- package/dist/{attach-EP374oMP.mjs → attach-BQl8nQz2.mjs} +5 -5
- package/dist/{attach-RQx__RzH.mjs → attach-DhZQ87Nz.mjs} +49 -224
- package/dist/bin.mjs +204 -154
- package/dist/{brief-Bs3cMQU0.mjs → brief-BQbeoPMc.mjs} +19 -9
- package/dist/{builtin-files-yYaNTQRU.mjs → builtin-files-CWL3JEo-.mjs} +1 -1
- package/dist/{command-tree-BkSYWmYJ.mjs → command-tree-B6uvMJq1.mjs} +1 -1
- package/dist/{completion-DIXWlnAl.mjs → completion-DKPuD_Rw.mjs} +47 -14
- package/dist/{context-Dq-VM_sq.mjs → context-Bw6R_EYq.mjs} +3 -3
- package/dist/detached-BQlbmqR0.mjs +38 -0
- package/dist/{find-k489laBa.mjs → find-B30-rd-u.mjs} +1 -1
- package/dist/flags-ByYBx-Xb.mjs +170 -0
- package/dist/{follow-ups-DD8NTPe6.mjs → follow-ups-Cxca1Jgg.mjs} +24 -18
- package/dist/{format-DQc9A_ei.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-D_9GlAlS.mjs → in-a-run-CZFzoT3R.mjs} +2 -2
- package/dist/{install-PVlV2QPq.mjs → install-CsqK1avz.mjs} +2 -183
- package/dist/{limits-CHqBO7wb.mjs → limits-CXh052II.mjs} +1 -1
- package/dist/{mcp-D38Ajb0b.mjs → mcp-B4wME9C4.mjs} +6 -6
- package/dist/{once-DuUzpzL2.mjs → once-BKn3pOtg.mjs} +3 -3
- package/dist/outputs-text-CNTJ7Qq_.mjs +19 -0
- package/dist/{pause-Bx3ePGrn.mjs → pause-B1grR1cl.mjs} +3 -3
- package/dist/{print-n2qetUHc.mjs → print-Bd8MWVJk.mjs} +1 -1
- package/dist/{project-records-Cune1l6I.mjs → project-records-BOEVs69i.mjs} +1 -1
- package/dist/{parse-BzWpMN-a.mjs → refusals-DQQX3AIb.mjs} +10 -1
- package/dist/{relay-D7RN4m68.mjs → relay-CeNiq3GT.mjs} +1 -1
- package/dist/{run-OOWQIKMJ.mjs → run-C0C54UiU.mjs} +116 -137
- package/dist/{run-BfxdsQJk.mjs → run-D6yU2rLf.mjs} +1 -1
- package/dist/{send-CKth_vgn.mjs → send-DqgF58hb.mjs} +2 -2
- package/dist/{src-DLsFsmOD.mjs → src-Ciy7i3se.mjs} +882 -71
- package/dist/{src-BHod38UQ.mjs → src-D2qpd-G7.mjs} +394 -247
- package/dist/{src-DmmrX2_C.mjs → src-DP02RP9O.mjs} +227 -180
- package/dist/{src-DOjTY2ET.mjs → src-n-u4TGev.mjs} +186 -43
- package/dist/{store-DACH768X.mjs → store-2KXzMCEN.mjs} +1 -1
- package/dist/ui/assets/app-C5vO1M-l.css +1 -0
- package/dist/ui/assets/{app-CN3acQ-1.js → app-ICEKpy_C.js} +21 -20
- package/dist/ui/assets/{index-B2uGxA4W.js → index-BGaix5wh.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-CJ-BX12n.mjs → ui-CAvygxTb.mjs} +53 -24
- package/dist/{usage-DxZ6JGd4.mjs → usage-BFBco5OS.mjs} +7 -7
- package/dist/{validate-BS0nCccW.mjs → validate-UrmC5AG1.mjs} +5 -5
- package/dist/{watch-Dp7IB4FR.mjs → watch-DTxkgB8R.mjs} +5 -5
- package/dist/{workflows-Djo1edlK.mjs → workflows-8GV-SeRm.mjs} +28 -4
- package/dist/{worktrees-Drof_Nyx.mjs → worktrees-CUdUvZlO.mjs} +9 -6
- package/package.json +1 -1
- package/dist/flags-B4ZZWspN.mjs +0 -125
- package/dist/post-2CaJz_mV.mjs +0 -46
- package/dist/ui/assets/app-9Q-62Ywz.css +0 -1
|
@@ -1,138 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as parseVersion, T as isNewer, w as compareVersions } from "./src-Ciy7i3se.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
4
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
|
-
kind: "status",
|
|
61
|
-
why: `it is ${f.status}`,
|
|
62
|
-
error
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
|
-
/** Whether `to` names one GitHub issue or pull request by its URL. */
|
|
66
|
-
const isGithubIssueUrl = (to) => /^https:\/\/github\.com\/[^/\s]+\/[^/\s]+\/(?:issues|pull)\/\d+$/u.test(to);
|
|
67
|
-
/**
|
|
68
|
-
* Why `f`'s draft can't be posted to GitHub whatever its status, or
|
|
69
|
-
* `undefined`.
|
|
70
|
-
*/
|
|
71
|
-
const githubDraftRefusal = (f) => {
|
|
72
|
-
if (f.kind !== "message" || f.draft?.channel !== "github") return {
|
|
73
|
-
why: "not drafted for the github channel",
|
|
74
|
-
error: "only a message drafted for the github channel is posted; send the others yourself"
|
|
75
|
-
};
|
|
76
|
-
return isGithubIssueUrl(f.draft.to) ? void 0 : {
|
|
77
|
-
why: "its `to` isn't a GitHub issue or pull request URL",
|
|
78
|
-
error: `${f.id}'s \`to\` (${f.draft.to}) isn't a GitHub issue or pull request URL, so it is not posted; copy the text and send it yourself.`
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
const postCheck = (f) => {
|
|
82
|
-
const open = f.status === "waiting" || f.status === "due";
|
|
83
|
-
const refused = githubDraftRefusal(f);
|
|
84
|
-
if (refused !== void 0) return {
|
|
85
|
-
ok: false,
|
|
86
|
-
kind: "draft",
|
|
87
|
-
...refused
|
|
88
|
-
};
|
|
89
|
-
return open ? { ok: true } : {
|
|
90
|
-
ok: false,
|
|
91
|
-
kind: "status",
|
|
92
|
-
why: `it is ${f.status}`,
|
|
93
|
-
error: `${f.id} is ${f.status}, so it is not posted.`
|
|
94
|
-
};
|
|
95
|
-
};
|
|
96
|
-
const followUpActions = (f) => ({
|
|
97
|
-
done: check(f, "done"),
|
|
98
|
-
drop: check(f, "drop"),
|
|
99
|
-
reopen: check(f, "reopen"),
|
|
100
|
-
due: check(f, "due"),
|
|
101
|
-
post: postCheck(f)
|
|
102
|
-
});
|
|
103
|
-
/** Applies `action` to `followUp`, and keeps it. */
|
|
104
|
-
const changeFollowUp = (rows, followUp, action, now = () => (/* @__PURE__ */ new Date()).toISOString()) => {
|
|
105
|
-
const rule = ACTIONS[action];
|
|
106
|
-
const refused = refusal(followUp, action);
|
|
107
|
-
if (refused !== void 0) return {
|
|
108
|
-
ok: false,
|
|
109
|
-
error: refused
|
|
110
|
-
};
|
|
111
|
-
const { note: _old, ...rest } = followUp;
|
|
112
|
-
const changed = {
|
|
113
|
-
...rest,
|
|
114
|
-
status: rule.to(followUp),
|
|
115
|
-
note: rule.note,
|
|
116
|
-
updatedAt: now()
|
|
117
|
-
};
|
|
118
|
-
rows.putFollowUp(changed);
|
|
119
|
-
return {
|
|
120
|
-
ok: true,
|
|
121
|
-
followUp: changed
|
|
122
|
-
};
|
|
123
|
-
};
|
|
124
|
-
/**
|
|
125
|
-
* Why a due follow-up is due, read from the note `due.ts` left: its ref merged,
|
|
126
|
-
* its date came, its ref closed unmerged, or a person marked it. `undefined`
|
|
127
|
-
* for one that is not due, or was due from the start.
|
|
128
|
-
*/
|
|
129
|
-
const dueCause = (f) => {
|
|
130
|
-
if (f.status !== "due" || f.note === void 0) return void 0;
|
|
131
|
-
if (f.note.includes("closed without merging")) return "closed-unmerged";
|
|
132
|
-
if (f.note.endsWith(" merged")) return "merged";
|
|
133
|
-
if (f.note.startsWith("due on ")) return "overdue";
|
|
134
|
-
return f.note === "marked due" ? "marked" : void 0;
|
|
135
|
-
};
|
|
136
5
|
// ../core/src/remote/session.ts
|
|
137
6
|
const chattable = (type) => type === "agent.leader" || type === "agent.worker";
|
|
138
7
|
/** Reads `node`'s session from a run's events, and every node's last output. */
|
|
@@ -355,5 +224,5 @@ const registryShown = (registry) => {
|
|
|
355
224
|
* fails when it is stale.
|
|
356
225
|
*/
|
|
357
226
|
const ORK_NAME = "@krapht/ork";
|
|
358
|
-
const ORK_VERSION = "1.0.0-alpha.
|
|
359
|
-
export {
|
|
227
|
+
const ORK_VERSION = "1.0.0-alpha.19";
|
|
228
|
+
export { registryShown as a, fetchLatest as c, readUpdateCache as d, refreshUpdateCache as f, 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 };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "./src-
|
|
2
|
-
import {
|
|
3
|
-
import { t as findRun } from "./find-k489laBa.mjs";
|
|
1
|
+
import "./src-Ciy7i3se.mjs";
|
|
2
|
+
import { t as findRun } from "./find-B30-rd-u.mjs";
|
|
4
3
|
import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { l as createTerminalHuman, t as attachRun } from "./attach-DhZQ87Nz.mjs";
|
|
5
|
+
import { n as attachRefusal } from "./in-a-run-CZFzoT3R.mjs";
|
|
6
|
+
import { t as withStore } from "./store-2KXzMCEN.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
// src/commands/attach.ts
|
|
9
9
|
/**
|
|
@@ -1,224 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dr as maskReplacer, L as isNodeEvent, Mt as lockWaitLine, Or as maskSecrets, Rt as slotWaitLine, Tr as TOOL_INPUT_KEYS, at as answerDecision, dt as DETACHED_ENV, er as endOf, it as followRunTree, ot as pendingDecisions, pt as followEvents, rr as END_KINDS, tr as outcomeEnd } from "./src-Ciy7i3se.mjs";
|
|
2
2
|
import { t as applyFilters } from "./apply-Mb0fNpCX.mjs";
|
|
3
|
+
import { t as outputsText } from "./outputs-text-CNTJ7Qq_.mjs";
|
|
3
4
|
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";
|
|
4
5
|
import { n as chip, r as nodeChip, t as CHIP_LABELS } from "./chips-BqcT58qr.mjs";
|
|
5
6
|
import { a as createView, i as formatBusEvent, n as nodeVerdict, o as styler, r as firstLine, t as hasConflict } from "./verdict-CMvPCpWC.mjs";
|
|
7
|
+
import { z } from "zod";
|
|
6
8
|
import { createInterface } from "node:readline/promises";
|
|
7
|
-
// ../core/src/control/queue.ts
|
|
8
|
-
const PERMISSION_OPTIONS = [{
|
|
9
|
-
id: "allow",
|
|
10
|
-
label: "Allow"
|
|
11
|
-
}, {
|
|
12
|
-
id: "deny",
|
|
13
|
-
label: "Deny"
|
|
14
|
-
}];
|
|
15
|
-
const DENIED = "The user did not allow this tool.";
|
|
16
|
-
/** The deny message a session gets, with the person's words when given. */
|
|
17
|
-
const deniedMessage = (note) => note === void 0 ? DENIED : `${DENIED} They said: ${note}`;
|
|
18
|
-
/** The input fields that say what a tool will do, the first one present. */
|
|
19
|
-
const TOOL_INPUT_KEYS = [
|
|
20
|
-
"command",
|
|
21
|
-
"file_path",
|
|
22
|
-
"path",
|
|
23
|
-
"url",
|
|
24
|
-
"pattern"
|
|
25
|
-
];
|
|
26
|
-
/** A tool's input for the decision's context: as written, cut at `max`. */
|
|
27
|
-
const inputContext = (input, max = 4e3) => {
|
|
28
|
-
const key = TOOL_INPUT_KEYS.find((k) => typeof input[k] === "string");
|
|
29
|
-
const text = key === void 0 ? JSON.stringify(input, void 0, 2) : String(input[key]);
|
|
30
|
-
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
31
|
-
};
|
|
32
|
-
const createDecisionQueue = (options) => {
|
|
33
|
-
const { store, runId, emit } = options;
|
|
34
|
-
const earlier = store.decisions({ runId });
|
|
35
|
-
let count = Math.max(0, ...earlier.map(({ id }) => Number(id.slice(runId.length + 1)) || 0));
|
|
36
|
-
for (const { id, node, status } of earlier) {
|
|
37
|
-
if (status !== "open") continue;
|
|
38
|
-
store.withdrawDecision(id);
|
|
39
|
-
emit({
|
|
40
|
-
type: "decision.withdrawn",
|
|
41
|
-
node,
|
|
42
|
-
decision: id
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
/** Opens a decision and settles it with the first answer. */
|
|
46
|
-
const decide = (open, local, withdrawn) => {
|
|
47
|
-
count += 1;
|
|
48
|
-
const id = `${runId}-${String(count)}`;
|
|
49
|
-
const record = store.openDecision({
|
|
50
|
-
...open,
|
|
51
|
-
id,
|
|
52
|
-
runId
|
|
53
|
-
});
|
|
54
|
-
const event = {
|
|
55
|
-
type: "decision.opened",
|
|
56
|
-
node: record.node,
|
|
57
|
-
decision: id,
|
|
58
|
-
kind: record.kind,
|
|
59
|
-
question: record.question,
|
|
60
|
-
options: record.options
|
|
61
|
-
};
|
|
62
|
-
if (record.recommended !== void 0) event.recommended = record.recommended;
|
|
63
|
-
if (record.owner !== void 0) event.owner = record.owner;
|
|
64
|
-
emit(event);
|
|
65
|
-
const { promise, resolve, reject } = Promise.withResolvers();
|
|
66
|
-
const settled = new AbortController();
|
|
67
|
-
/** `note` is the stored one: masked, and absent when blank. */
|
|
68
|
-
const finish = (answer, by, note) => {
|
|
69
|
-
if (settled.signal.aborted) return;
|
|
70
|
-
settled.abort();
|
|
71
|
-
const answered = {
|
|
72
|
-
type: "decision.answered",
|
|
73
|
-
node: open.node,
|
|
74
|
-
decision: id,
|
|
75
|
-
answer,
|
|
76
|
-
by
|
|
77
|
-
};
|
|
78
|
-
if (note !== void 0) answered.note = note;
|
|
79
|
-
emit(answered);
|
|
80
|
-
resolve(note === void 0 ? {
|
|
81
|
-
answer,
|
|
82
|
-
by
|
|
83
|
-
} : {
|
|
84
|
-
answer,
|
|
85
|
-
by,
|
|
86
|
-
note
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
const withdraw = () => {
|
|
90
|
-
if (settled.signal.aborted) return;
|
|
91
|
-
settled.abort();
|
|
92
|
-
store.withdrawDecision(id);
|
|
93
|
-
emit({
|
|
94
|
-
type: "decision.withdrawn",
|
|
95
|
-
node: open.node,
|
|
96
|
-
decision: id
|
|
97
|
-
});
|
|
98
|
-
reject(/* @__PURE__ */ new Error("the question was withdrawn"));
|
|
99
|
-
};
|
|
100
|
-
if (withdrawn?.aborted === true) withdraw();
|
|
101
|
-
withdrawn?.addEventListener("abort", withdraw, { once: true });
|
|
102
|
-
const fromStore = async () => {
|
|
103
|
-
try {
|
|
104
|
-
const closed = await options.waitFor(id, settled.signal);
|
|
105
|
-
if (closed.status === "answered" && closed.answer !== void 0) finish(closed.answer, closed.answeredBy ?? "decide", closed.note);
|
|
106
|
-
} catch {}
|
|
107
|
-
};
|
|
108
|
-
const fromTerminal = async (ask) => {
|
|
109
|
-
try {
|
|
110
|
-
const { answer, note } = await ask(settled.signal);
|
|
111
|
-
if (store.answerDecision(id, answer, "terminal", note)) finish(answer, "terminal", store.decision(id)?.note);
|
|
112
|
-
} catch {}
|
|
113
|
-
};
|
|
114
|
-
fromStore();
|
|
115
|
-
if (local !== void 0) fromTerminal(local);
|
|
116
|
-
return promise;
|
|
117
|
-
};
|
|
118
|
-
return {
|
|
119
|
-
ask: (question) => {
|
|
120
|
-
const open = {
|
|
121
|
-
node: question.nodeId,
|
|
122
|
-
kind: "question",
|
|
123
|
-
question: question.question,
|
|
124
|
-
options: question.options
|
|
125
|
-
};
|
|
126
|
-
if (question.recommended !== void 0) open.recommended = question.recommended;
|
|
127
|
-
if (question.context !== void 0) open.context = question.context;
|
|
128
|
-
if (question.document !== void 0) open.document = question.document;
|
|
129
|
-
if (question.owner !== void 0) open.owner = question.owner;
|
|
130
|
-
const { local } = options;
|
|
131
|
-
return decide(open, local === void 0 ? void 0 : (signal) => {
|
|
132
|
-
let note;
|
|
133
|
-
return local.ask({
|
|
134
|
-
...question,
|
|
135
|
-
question: maskSecrets(question.question),
|
|
136
|
-
...question.context === void 0 ? {} : { context: maskSecrets(question.context) },
|
|
137
|
-
...question.document === void 0 ? {} : { document: maskSecrets(question.document) },
|
|
138
|
-
signal,
|
|
139
|
-
onNote: (given) => {
|
|
140
|
-
note = given;
|
|
141
|
-
}
|
|
142
|
-
}).then((answer) => note === void 0 ? { answer } : {
|
|
143
|
-
answer,
|
|
144
|
-
note
|
|
145
|
-
});
|
|
146
|
-
}, question.signal).then(({ answer, note }) => {
|
|
147
|
-
if (note !== void 0) question.onNote?.(note);
|
|
148
|
-
return answer;
|
|
149
|
-
});
|
|
150
|
-
},
|
|
151
|
-
settled: (question) => {
|
|
152
|
-
count += 1;
|
|
153
|
-
const id = `${runId}-${String(count)}`;
|
|
154
|
-
const { owner } = question;
|
|
155
|
-
const record = store.openDecision({
|
|
156
|
-
id,
|
|
157
|
-
runId,
|
|
158
|
-
node: question.nodeId,
|
|
159
|
-
kind: "question",
|
|
160
|
-
question: question.question,
|
|
161
|
-
options: question.options,
|
|
162
|
-
owner,
|
|
163
|
-
...question.recommended === void 0 ? {} : { recommended: question.recommended },
|
|
164
|
-
...question.context === void 0 ? {} : { context: question.context }
|
|
165
|
-
});
|
|
166
|
-
emit({
|
|
167
|
-
type: "decision.opened",
|
|
168
|
-
node: record.node,
|
|
169
|
-
decision: id,
|
|
170
|
-
kind: "question",
|
|
171
|
-
question: record.question,
|
|
172
|
-
options: record.options,
|
|
173
|
-
owner,
|
|
174
|
-
...record.recommended === void 0 ? {} : { recommended: record.recommended }
|
|
175
|
-
});
|
|
176
|
-
store.answerDecision(id, question.answer, "owner", question.note);
|
|
177
|
-
const note = store.decision(id)?.note;
|
|
178
|
-
emit({
|
|
179
|
-
type: "decision.answered",
|
|
180
|
-
node: record.node,
|
|
181
|
-
decision: id,
|
|
182
|
-
answer: question.answer,
|
|
183
|
-
by: "owner",
|
|
184
|
-
owner,
|
|
185
|
-
...note === void 0 ? {} : { note }
|
|
186
|
-
});
|
|
187
|
-
},
|
|
188
|
-
permit: async (request) => {
|
|
189
|
-
const { local } = options;
|
|
190
|
-
let localMessage = DENIED;
|
|
191
|
-
const { answer, note } = await decide({
|
|
192
|
-
node: request.nodeId,
|
|
193
|
-
kind: "permission",
|
|
194
|
-
question: `Allow ${request.toolName}?`,
|
|
195
|
-
options: PERMISSION_OPTIONS,
|
|
196
|
-
context: inputContext(request.input)
|
|
197
|
-
}, local === void 0 ? void 0 : (signal) => {
|
|
198
|
-
let said;
|
|
199
|
-
return local.permit({
|
|
200
|
-
...request,
|
|
201
|
-
signal,
|
|
202
|
-
onNote: (given) => {
|
|
203
|
-
said = given;
|
|
204
|
-
}
|
|
205
|
-
}).then((result) => {
|
|
206
|
-
if (!result.allow) localMessage = result.message;
|
|
207
|
-
const choice = result.allow ? "allow" : "deny";
|
|
208
|
-
return said === void 0 ? { answer: choice } : {
|
|
209
|
-
answer: choice,
|
|
210
|
-
note: said
|
|
211
|
-
};
|
|
212
|
-
});
|
|
213
|
-
}, request.signal);
|
|
214
|
-
if (note !== void 0) request.onNote?.(note);
|
|
215
|
-
return answer === "allow" ? { allow: true } : {
|
|
216
|
-
allow: false,
|
|
217
|
-
message: note === void 0 ? localMessage : deniedMessage(note)
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
};
|
|
222
9
|
// src/human-card.ts
|
|
223
10
|
/** Lines of context a card shows before `d` (or `--verbose`) shows the rest. */
|
|
224
11
|
const CONTEXT_LINES = 6;
|
|
@@ -684,9 +471,14 @@ const createTerminalHuman = (io) => {
|
|
|
684
471
|
if (noted.kind === "interrupted") await parked(signal);
|
|
685
472
|
if (noted.kind === "text" && noted.value !== "") onNote(noted.value);
|
|
686
473
|
};
|
|
687
|
-
/**
|
|
474
|
+
/**
|
|
475
|
+
* Says where a waiting question is answered, and waits until withdrawn. A
|
|
476
|
+
* foreground run has no one at `ork decide` yet, so it says to start over
|
|
477
|
+
* detached.
|
|
478
|
+
*/
|
|
688
479
|
const waitElsewhere = (q) => {
|
|
689
|
-
|
|
480
|
+
const detached = (io.env ?? process.env)[DETACHED_ENV] === "1";
|
|
481
|
+
say(paint(term(), "muted", ` no terminal; ${plain(q.nodeId)} waits for ork decide or ork ui` + (detached ? "" : ": use --detach and answer with ork decide")));
|
|
690
482
|
return parked(q.signal);
|
|
691
483
|
};
|
|
692
484
|
const oneAtATime = (work) => {
|
|
@@ -887,6 +679,12 @@ const formatOutcome = (nodeId, outcome, verbose = false, term = createView().ter
|
|
|
887
679
|
return lines;
|
|
888
680
|
};
|
|
889
681
|
// src/run/format-result.ts
|
|
682
|
+
/**
|
|
683
|
+
* @file The run summary on the terminal: status, cost, what ran, what a resume
|
|
684
|
+
* kept, what was skipped and which failures an edge handled (G8, L42),
|
|
685
|
+
* branches to look at, why it did not succeed, and mail to nodes that never
|
|
686
|
+
* ran (L91).
|
|
687
|
+
*/
|
|
890
688
|
/** How a run ended: its mark, and its chip's word and role when rich. */
|
|
891
689
|
const RUN_END = {
|
|
892
690
|
succeeded: {
|
|
@@ -928,6 +726,18 @@ const MARK_COLOR = {
|
|
|
928
726
|
/** `1 failure handled`, `2 failures handled`. */
|
|
929
727
|
const failuresHandled = (count) => `${String(count)} ${count === 1 ? "failure" : "failures"} handled`;
|
|
930
728
|
/**
|
|
729
|
+
* The workflow's declared outputs, one per key: a one-line value on the key's
|
|
730
|
+
* line, a longer one under it; a cut value points at the stored full one.
|
|
731
|
+
*/
|
|
732
|
+
const outputLines = (result, style) => outputsText(result.outputs).flatMap(({ name, text, cut }) => {
|
|
733
|
+
const key = style("bold", `${name}:`);
|
|
734
|
+
const tail = cut ? [style("dim", ` … cut; full value: ork logs ${result.runId} --json`)] : [];
|
|
735
|
+
if (text === "") return [` ${key} ${style("dim", "(empty)")}`];
|
|
736
|
+
if (!text.includes("\n")) return [` ${key} ${text}`].concat(tail);
|
|
737
|
+
const body = text.split("\n").map((line) => ` ${line}`);
|
|
738
|
+
return [` ${key}`].concat(body, tail);
|
|
739
|
+
});
|
|
740
|
+
/**
|
|
931
741
|
* The run summary: status, cost, what ran, what was skipped and which failures
|
|
932
742
|
* an edge handled, branches to look at, why, and mail to nodes that never ran.
|
|
933
743
|
*/
|
|
@@ -935,10 +745,15 @@ const formatRunResult = (result, term = createView().term) => {
|
|
|
935
745
|
const style = styler(term);
|
|
936
746
|
const end = RUN_END[result.status];
|
|
937
747
|
const mark = term.rich ? chip(term, end.label, end.ok) : style(MARK_COLOR[end.ok], end.mark);
|
|
938
|
-
const
|
|
939
|
-
const
|
|
748
|
+
const keptCount = result.kept ?? 0;
|
|
749
|
+
const ran = result.nodes.filter((n) => n.runs > 0).length - keptCount;
|
|
750
|
+
const skipped = result.skipped ?? result.nodes.length - ran - keptCount;
|
|
940
751
|
const handled = result.failuresHandled ?? 0;
|
|
941
|
-
const lines = [
|
|
752
|
+
const lines = [
|
|
753
|
+
"",
|
|
754
|
+
`${mark} run ${result.runId} ${result.status.replace("_", " ")} ${style("dim", `· ${costOf(result.costUsd, result.partial, result.tokens)} · ${String(ran)} ran, ${keptCount === 0 ? "" : `${String(keptCount)} kept, `}${String(skipped)} skipped${handled === 0 ? "" : `, ${failuresHandled(handled)}`}`)}`,
|
|
755
|
+
...outputLines(result, style)
|
|
756
|
+
];
|
|
942
757
|
for (const kept of result.worktrees) lines.push(` ${kept.id}: ${kept.branch ?? "detached"} ${style("dim", `at ${kept.path} (${kept.reason})`)}`);
|
|
943
758
|
for (const reason of result.reasons) lines.push(` ${style("red", reason)}`);
|
|
944
759
|
for (const { node, messages } of result.unread ?? []) lines.push(` ${style(["yellow", "bold"], "warning")} ${node} never ran, so ${messages === 1 ? "1 message" : `${String(messages)} messages`} to it went unread`);
|
|
@@ -961,6 +776,10 @@ const wrapped = (text, room) => {
|
|
|
961
776
|
return widthOf(safe) <= width ? [safe] : wrap(safe, width);
|
|
962
777
|
}).map((line) => ` ${line}`);
|
|
963
778
|
};
|
|
779
|
+
/** Ork's `delegate` tool, as each driver names it (`mcp__ork__…`, `ork_…`). */
|
|
780
|
+
const DELEGATE = /(?:^|_)delegate$/u;
|
|
781
|
+
/** The input with every string in it masked. */
|
|
782
|
+
const maskedInput = (input) => z.record(z.string(), z.unknown()).parse(JSON.parse(JSON.stringify(input, maskReplacer)));
|
|
964
783
|
/** A tool's input as the call says it: the key that names its target, whole. */
|
|
965
784
|
const toolText = (input, root) => {
|
|
966
785
|
const key = TOOL_INPUT_KEYS.find((k) => typeof input[k] === "string");
|
|
@@ -973,7 +792,8 @@ const toolText = (input, root) => {
|
|
|
973
792
|
* A tool call: rich, `Tool first line` cut to `room` with `+N lines` when it
|
|
974
793
|
* had more; plain, today's one dim line. `verbose` shows the call whole.
|
|
975
794
|
*/
|
|
976
|
-
const toolLines = (name,
|
|
795
|
+
const toolLines = (name, raw, view, room, verbose, node) => {
|
|
796
|
+
const input = DELEGATE.test(name) ? maskedInput(raw) : raw;
|
|
977
797
|
const { term } = view;
|
|
978
798
|
const style = styler(term);
|
|
979
799
|
if (!term.rich && !verbose) return [style("dim", ` · ${plain(previewInput(name, input))}`)];
|
|
@@ -991,6 +811,11 @@ const toolLines = (name, input, view, room, verbose, node) => {
|
|
|
991
811
|
return [`${styledHead}${style("dim", cut(first.trim(), Math.max(1, room - headWidth - more.length)))}${style("dim", more)}`];
|
|
992
812
|
};
|
|
993
813
|
// src/run/format.ts
|
|
814
|
+
/**
|
|
815
|
+
* @file How runs read on the terminal: session events and run events with node
|
|
816
|
+
* chips or prefixes; the node result is `format-outcome.ts`'s, a tool call
|
|
817
|
+
* `format-tool.ts`'s and the run summary `format-result.ts`'s.
|
|
818
|
+
*/
|
|
994
819
|
/** A line's 2-column indent, after any style codes that open it. */
|
|
995
820
|
const INDENT = /^((?:\u001B\[[0-9;]*m)*) {2}/u;
|
|
996
821
|
/** Who answered a decision, as the log says it. */
|
|
@@ -1039,7 +864,7 @@ const formatRunEvent = (event, width, tools, terminal = false, verbose = false,
|
|
|
1039
864
|
if (event.type === "node.started") {
|
|
1040
865
|
const round = event.round > 1 ? ` (round ${String(event.round)})` : "";
|
|
1041
866
|
const owner = event.owner === void 0 ? "" : `, for ${event.owner}`;
|
|
1042
|
-
const named = event.description === void 0 ? "" : ` · ${event.description}`;
|
|
867
|
+
const named = event.description === void 0 ? "" : ` · ${maskSecrets(event.description)}`;
|
|
1043
868
|
return [`${tag(event.id)} ${style("dim", `${event.nodeType}${round}${owner}${named}`)}`];
|
|
1044
869
|
}
|
|
1045
870
|
if (event.type === "node.event") {
|
|
@@ -1345,4 +1170,4 @@ const attachRun = async (store, root, out, options = {}) => {
|
|
|
1345
1170
|
exitCode: end === "aborted" || seen.succeeded ? 0 : 1
|
|
1346
1171
|
};
|
|
1347
1172
|
};
|
|
1348
|
-
export { unknownNode as a, callsShown as c,
|
|
1173
|
+
export { unknownNode as a, callsShown as c, logListTable as i, createTerminalHuman as l, askStored as n, formatEvent as o, followRun as r, formatRunEvent as s, attachRun as t, readText as u };
|