@krapht/ork 1.0.0-alpha.15 → 1.0.0-alpha.17
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/README.md +10 -4
- package/dist/{__build_info__-Bsb1kjgF.mjs → __build_info__-C1Nm0hlJ.mjs} +25 -6
- package/dist/apply-Mb0fNpCX.mjs +17 -0
- package/dist/{attach-CPespxlQ.mjs → attach-EP374oMP.mjs} +5 -5
- package/dist/{attach-BHO3X3cf.mjs → attach-RQx__RzH.mjs} +46 -8
- package/dist/bin.mjs +238 -369
- package/dist/brief-Bs3cMQU0.mjs +100 -0
- package/dist/{builtin-files-2bHf76x-.mjs → builtin-files-yYaNTQRU.mjs} +1 -1
- package/dist/command-tree-BkSYWmYJ.mjs +63 -0
- package/dist/{completion-CQ2UYKuJ.mjs → completion-DIXWlnAl.mjs} +87 -6
- package/dist/{context-BNqDw9z1.mjs → context-Dq-VM_sq.mjs} +3 -3
- package/dist/{find-BYLlszqj.mjs → find-k489laBa.mjs} +2 -2
- package/dist/flags-B4ZZWspN.mjs +125 -0
- package/dist/{follow-ups-B4GJ3Vzw.mjs → follow-ups-DD8NTPe6.mjs} +59 -24
- package/dist/{format-C8MsFj8_.mjs → format-DQc9A_ei.mjs} +17 -4
- package/dist/{help-groups-CQ98mLjF.mjs → help-groups-hB6kY34d.mjs} +1 -63
- package/dist/in-a-run-D_9GlAlS.mjs +27 -0
- package/dist/{install-DWtXTq4y.mjs → install-PVlV2QPq.mjs} +1 -1
- package/dist/{limits-B1qzS4cX.mjs → limits-CHqBO7wb.mjs} +1 -1
- package/dist/{mcp-BOrVkyhN.mjs → mcp-D38Ajb0b.mjs} +6 -6
- package/dist/{once-C1fL3GVo.mjs → once-DuUzpzL2.mjs} +3 -3
- package/dist/parse-BzWpMN-a.mjs +107 -0
- package/dist/{pause-DOMK-R8V.mjs → pause-Bx3ePGrn.mjs} +3 -3
- package/dist/{post-BzA6Qobq.mjs → post-2CaJz_mV.mjs} +5 -3
- package/dist/print-n2qetUHc.mjs +19 -0
- package/dist/project-records-Cune1l6I.mjs +230 -0
- package/dist/{relay-OWuu4fib.mjs → relay-D7RN4m68.mjs} +1 -1
- package/dist/{run-CiPsW9Kf.mjs → run-BfxdsQJk.mjs} +1 -1
- package/dist/{run--4-1xAF2.mjs → run-OOWQIKMJ.mjs} +33 -20
- package/dist/{send-CnNNW-ot.mjs → send-CKth_vgn.mjs} +2 -2
- package/dist/{src-B9zWIVqo.mjs → src-BHod38UQ.mjs} +104 -72
- package/dist/{src-Dr_fTSu-.mjs → src-DLsFsmOD.mjs} +790 -502
- package/dist/{src-DQKz2eOH.mjs → src-DOjTY2ET.mjs} +238 -79
- package/dist/{src-DcrhgipG.mjs → src-DmmrX2_C.mjs} +162 -58
- package/dist/{store-oKJ-cCf3.mjs → store-DACH768X.mjs} +1 -1
- package/dist/ui/assets/app-9Q-62Ywz.css +1 -0
- package/dist/ui/assets/app-CN3acQ-1.js +111 -0
- package/dist/ui/assets/{index-BtwkftKe.js → index-B2uGxA4W.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-CzKlsCnm.mjs → ui-CJ-BX12n.mjs} +3 -3
- package/dist/{usage-DHGNk2JL.mjs → usage-DxZ6JGd4.mjs} +62 -107
- package/dist/{validate-Bs_gg22g.mjs → validate-BS0nCccW.mjs} +35 -8
- package/dist/{watch-CCCfw3n7.mjs → watch-Dp7IB4FR.mjs} +5 -5
- package/dist/{workflows-CW28ZU-z.mjs → workflows-Djo1edlK.mjs} +2 -2
- package/dist/{worktrees-CyE8aF6j.mjs → worktrees-Drof_Nyx.mjs} +49 -20
- package/package.json +8 -4
- package/dist/brief-za0ozN_E.mjs +0 -58
- package/dist/in-a-run-Bp0k0J09.mjs +0 -24
- package/dist/ui/assets/app-Bdc6OBeZ.css +0 -1
- package/dist/ui/assets/app-Drp8Dm9y.js +0 -111
|
@@ -1,15 +1,87 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as acceptItem, c as feedbackActions, i as recordNote, l as openFixRun, n as previewPost, o as lessonPlaceOf, s as placeOf$1, t as runInstall } from "./install-
|
|
3
|
-
import { _ as dueCause, a as registryShown, c as fetchLatest, d as readUpdateCache, f as refreshUpdateCache, g as changeFollowUp, h as nodeSession, i as registryOf, l as newerVersion, m as writeUpdateCache, o as updateSwitchOff, p as updateCachePath, s as checkDue, v as findFollowUp, y as followUpActions } from "./__build_info__-
|
|
4
|
-
import { t as postFollowUpMessage } from "./post-
|
|
5
|
-
import { t as
|
|
6
|
-
import {
|
|
1
|
+
import { An as liveStatus, Ar as loadAgents, Br as inside, Bt as decisionListTable, D as triggersReport, Dn as requestPause, En as requestContinue, F as activeTree, Fr as placeFor, Gt as worktreeListTable, Hr as LESSON_CAP_TOKENS, Ht as followUpListTable, I as isNodeEvent, In as processAlive, Jr as WorkflowEditSchema, Jt as keyOf, Kn as endOf, Kt as applyClean, L as openStore, Lr as runDirOf, Mn as pausedOf, Nn as runStatus, On as requestStop, Pr as placeFiles, R as storePath, S as detectInstaller, St as walkSummary, Tn as unlinkNodes, Un as loadProject, Ut as runListTable, Vt as feedbackListTable, Wt as usageListTable, Xr as newWorkflowText, Xt as stepActs, Yn as END_KINDS, Yr as applyEdits, Yt as planClean, Zr as readDocument, Zt as stepPrunes, _ as capsHere, a as planRemove, ai as EdgeInputSchema, b as runningRunIds, bn as liveSessionOf, bt as checkWorkflowText, ci as expandEdge, d as planLine, er as DISCUSSIONS, f as removeRefusal, g as usageReport, gn as startFollowUpChecks, ht as explainWorkflowText, i as lostWork, kn as tellLiveRun, l as labelOf, lt as detachRun, ni as parseWorkflow, nr as runGh, nt as answerDecision, o as projectHead, on as nodeSays, ot as detachResume, p as stateParts, pn as checkFollowUpsDue, pr as readCondition, pt as limitsReport, qr as skillsIn, qt as cleanStep, r as applyRemove, rr as sendPost, rt as pendingDecisions, s as readWorktrees, st as resumable, ti as renderJsonSchema, tr as planPost, u as mergeStateOf, ui as NodeSchema, ut as followEvents, v as planUpgrade, wn as linkNodes, x as runningScript, xn as DEFAULT_FOLLOW_UPS_RULE, xt as walkChecks, y as releaseNotes, zn as nestItems, zr as workflowDirOf, zt as LIST_TABLES } from "./src-DLsFsmOD.mjs";
|
|
2
|
+
import { a as acceptItem, c as feedbackActions, i as recordNote, l as openFixRun, n as previewPost, o as lessonPlaceOf, s as placeOf$1, t as runInstall } from "./install-PVlV2QPq.mjs";
|
|
3
|
+
import { _ as dueCause, a as registryShown, c as fetchLatest, d as readUpdateCache, f as refreshUpdateCache, g as changeFollowUp, h as nodeSession, i as registryOf, l as newerVersion, m as writeUpdateCache, o as updateSwitchOff, p as updateCachePath, s as checkDue, v as findFollowUp, y as followUpActions } from "./__build_info__-C1Nm0hlJ.mjs";
|
|
4
|
+
import { t as postFollowUpMessage } from "./post-2CaJz_mV.mjs";
|
|
5
|
+
import { t as applyFilters } from "./apply-Mb0fNpCX.mjs";
|
|
6
|
+
import { t as parseFilters } from "./parse-BzWpMN-a.mjs";
|
|
7
|
+
import { t as builtinProblem } from "./builtin-files-yYaNTQRU.mjs";
|
|
8
|
+
import { n as newRunId, t as findRun } from "./find-k489laBa.mjs";
|
|
7
9
|
import path from "node:path";
|
|
8
10
|
import { z } from "zod";
|
|
9
11
|
import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
10
12
|
import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
11
13
|
import { homedir } from "node:os";
|
|
12
14
|
import { createServer } from "node:http";
|
|
15
|
+
// ../server/src/contract-lists.ts
|
|
16
|
+
/** A filter's value: any text; the handler checks it with core. */
|
|
17
|
+
const text = () => z.string().min(1).optional();
|
|
18
|
+
/**
|
|
19
|
+
* A `since` or `until`: `all`, an age (`24h`), a day, or an ISO time. Read with
|
|
20
|
+
* core by the handler, so a bad one is refused in the CLI's words.
|
|
21
|
+
*/
|
|
22
|
+
const time = text;
|
|
23
|
+
/** Each list's filter fields, by flag name, in its core table's order. */
|
|
24
|
+
const LIST_SHAPES = {
|
|
25
|
+
runs: {
|
|
26
|
+
status: text(),
|
|
27
|
+
workflow: text(),
|
|
28
|
+
project: text(),
|
|
29
|
+
since: time(),
|
|
30
|
+
until: time()
|
|
31
|
+
},
|
|
32
|
+
feedback: {
|
|
33
|
+
status: text(),
|
|
34
|
+
kind: text(),
|
|
35
|
+
severity: text(),
|
|
36
|
+
workflow: text(),
|
|
37
|
+
run: text()
|
|
38
|
+
},
|
|
39
|
+
"follow-ups": {
|
|
40
|
+
status: text(),
|
|
41
|
+
for: text(),
|
|
42
|
+
kind: text(),
|
|
43
|
+
due: text(),
|
|
44
|
+
project: text()
|
|
45
|
+
},
|
|
46
|
+
decisions: {
|
|
47
|
+
workflow: text(),
|
|
48
|
+
run: text(),
|
|
49
|
+
project: text()
|
|
50
|
+
},
|
|
51
|
+
worktrees: {
|
|
52
|
+
run: text(),
|
|
53
|
+
project: text()
|
|
54
|
+
},
|
|
55
|
+
usage: {
|
|
56
|
+
workflow: text(),
|
|
57
|
+
project: text(),
|
|
58
|
+
since: time(),
|
|
59
|
+
until: time()
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/** A list's filter fields as query params: its core table's, each optional. */
|
|
63
|
+
const listShape = (list) => LIST_SHAPES[list];
|
|
64
|
+
Object.keys(LIST_SHAPES.runs), Object.keys(LIST_SHAPES.feedback), Object.keys(LIST_SHAPES["follow-ups"]), Object.keys(LIST_SHAPES.decisions), Object.keys(LIST_SHAPES.worktrees), Object.keys(LIST_SHAPES.usage);
|
|
65
|
+
const Count$1 = z.coerce.number().int().positive();
|
|
66
|
+
/** `GET /api/runs`: `runListTable`'s fields, and the newest `limit`. */
|
|
67
|
+
const RunsQuerySchema = z.strictObject({
|
|
68
|
+
limit: Count$1.optional(),
|
|
69
|
+
...LIST_SHAPES.runs
|
|
70
|
+
});
|
|
71
|
+
/**
|
|
72
|
+
* `GET /api/usage`: `usageListTable`'s fields; `since` and `until` also take
|
|
73
|
+
* ISO times (`since` included, `until` not), as before.
|
|
74
|
+
*/
|
|
75
|
+
const UsageQuerySchema = z.strictObject(LIST_SHAPES.usage);
|
|
76
|
+
/**
|
|
77
|
+
* `GET /api/decisions`: `decisionListTable`'s fields; `workflow` is ANDed with
|
|
78
|
+
* `run` or `project`.
|
|
79
|
+
*/
|
|
80
|
+
const DecisionsQuerySchema = z.strictObject(LIST_SHAPES.decisions);
|
|
81
|
+
const LISTS_API = { listFields: {
|
|
82
|
+
method: "GET",
|
|
83
|
+
path: "/api/list-fields"
|
|
84
|
+
} };
|
|
13
85
|
// ../server/src/contract-feedback.ts
|
|
14
86
|
const NoteSchema = z.strictObject({
|
|
15
87
|
/** Its first line is the title. */
|
|
@@ -45,6 +117,11 @@ const PublishSchema = z.strictObject({
|
|
|
45
117
|
/** The preview's digest: what the person saw, so nothing else is sent. */
|
|
46
118
|
digest: z.string().min(1)
|
|
47
119
|
});
|
|
120
|
+
/**
|
|
121
|
+
* The filters are core's `feedbackListTable` fields; with none, every item
|
|
122
|
+
* comes, dismissed too (the panel hides them itself).
|
|
123
|
+
*/
|
|
124
|
+
const FeedbackItemsQuerySchema = z.strictObject(listShape("feedback"));
|
|
48
125
|
const FEEDBACK_API = {
|
|
49
126
|
note: {
|
|
50
127
|
method: "POST",
|
|
@@ -53,7 +130,8 @@ const FEEDBACK_API = {
|
|
|
53
130
|
},
|
|
54
131
|
feedbackItems: {
|
|
55
132
|
method: "GET",
|
|
56
|
-
path: "/api/feedback"
|
|
133
|
+
path: "/api/feedback",
|
|
134
|
+
query: FeedbackItemsQuerySchema
|
|
57
135
|
},
|
|
58
136
|
feedbackItem: {
|
|
59
137
|
method: "GET",
|
|
@@ -90,19 +168,11 @@ const FEEDBACK_API = {
|
|
|
90
168
|
}
|
|
91
169
|
};
|
|
92
170
|
// ../server/src/contract-follow-ups.ts
|
|
93
|
-
/**
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"due",
|
|
99
|
-
"waiting",
|
|
100
|
-
"done",
|
|
101
|
-
"dropped"
|
|
102
|
-
]).optional(),
|
|
103
|
-
/** Only those for this: `agent`, `me`, `project:<name>` or `person:<name>`. */
|
|
104
|
-
for: z.string().min(1).optional()
|
|
105
|
-
});
|
|
171
|
+
/**
|
|
172
|
+
* The filters are core's `followUpListTable` fields. `status` is `open` (due
|
|
173
|
+
* and waiting, the default), `all` (adds done and dropped), or the table's.
|
|
174
|
+
*/
|
|
175
|
+
const FollowUpsQuerySchema = z.strictObject(listShape("follow-ups"));
|
|
106
176
|
const FollowUpChangeSchema = z.strictObject({ action: z.enum([
|
|
107
177
|
"done",
|
|
108
178
|
"drop",
|
|
@@ -271,9 +341,11 @@ planId: z.string().min(1) })
|
|
|
271
341
|
};
|
|
272
342
|
// ../server/src/contract-worktrees.ts
|
|
273
343
|
const Root = z.string().min(1);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
project
|
|
344
|
+
/**
|
|
345
|
+
* The filters are core's `worktreeListTable` fields (`project`: a root; every
|
|
346
|
+
* project without one).
|
|
347
|
+
*/
|
|
348
|
+
const WorktreesQuerySchema = z.strictObject(listShape("worktrees"));
|
|
277
349
|
const RemovePlanSchema = z.strictObject({
|
|
278
350
|
project: Root,
|
|
279
351
|
/** The item's branch, or a detached worktree's path. */
|
|
@@ -323,17 +395,6 @@ const WORKTREES_API = {
|
|
|
323
395
|
// ../server/src/contract.ts
|
|
324
396
|
const Count = z.coerce.number().int().positive();
|
|
325
397
|
const Seq = z.coerce.number().int().nonnegative();
|
|
326
|
-
const RunsQuerySchema = z.strictObject({
|
|
327
|
-
project: z.string().min(1).optional(),
|
|
328
|
-
limit: Count.optional()
|
|
329
|
-
});
|
|
330
|
-
const UsageQuerySchema = z.strictObject({
|
|
331
|
-
project: z.string().min(1).optional(),
|
|
332
|
-
workflow: z.string().min(1).optional(),
|
|
333
|
-
/** ISO times: `since` included, `until` not. */
|
|
334
|
-
since: z.iso.datetime().optional(),
|
|
335
|
-
until: z.iso.datetime().optional()
|
|
336
|
-
});
|
|
337
398
|
const EventsQuerySchema = z.strictObject({
|
|
338
399
|
after: Seq.optional(),
|
|
339
400
|
node: z.string().min(1).optional(),
|
|
@@ -342,12 +403,6 @@ const EventsQuerySchema = z.strictObject({
|
|
|
342
403
|
/** Only the newest this many, still oldest first. */
|
|
343
404
|
last: Count.optional()
|
|
344
405
|
});
|
|
345
|
-
const DecisionsQuerySchema = z.strictObject({
|
|
346
|
-
run: z.string().min(1).optional(),
|
|
347
|
-
project: z.string().min(1).optional(),
|
|
348
|
-
/** Only runs of this workflow, by name; ANDed with `run` or `project`. */
|
|
349
|
-
workflow: z.string().min(1).optional()
|
|
350
|
-
});
|
|
351
406
|
/** An answer: the option, and what the person said with it, if anything. */
|
|
352
407
|
const AnswerSchema = z.strictObject({
|
|
353
408
|
choose: z.string().min(1),
|
|
@@ -385,6 +440,7 @@ const API = {
|
|
|
385
440
|
...CONTEXT_API,
|
|
386
441
|
...AFTER_API,
|
|
387
442
|
...WORKTREES_API,
|
|
443
|
+
...LISTS_API,
|
|
388
444
|
...UPDATE_API,
|
|
389
445
|
projects: {
|
|
390
446
|
method: "GET",
|
|
@@ -1108,17 +1164,14 @@ const checkTool = (context) => tool("check", "Checks a workflow as `ork validate
|
|
|
1108
1164
|
return answer({
|
|
1109
1165
|
errors: count("error"),
|
|
1110
1166
|
warnings: count("warning"),
|
|
1111
|
-
diagnostics: diagnostics.map(({ severity, code, message, line, column }) =>
|
|
1167
|
+
diagnostics: diagnostics.map(({ severity, code, message, file, line, column }) => Object.assign({
|
|
1112
1168
|
severity,
|
|
1113
1169
|
code,
|
|
1114
1170
|
message
|
|
1115
|
-
} : {
|
|
1116
|
-
severity,
|
|
1117
|
-
code,
|
|
1118
|
-
message,
|
|
1171
|
+
}, file === void 0 ? {} : { file }, line === void 0 ? {} : {
|
|
1119
1172
|
line,
|
|
1120
1173
|
column
|
|
1121
|
-
}),
|
|
1174
|
+
})),
|
|
1122
1175
|
walk: walk === void 0 ? null : walkSummary(walk),
|
|
1123
1176
|
...args.paths === true && walk !== void 0 ? { endings: walk.endings.slice(0, MOST_ENDINGS) } : {}
|
|
1124
1177
|
});
|
|
@@ -1578,6 +1631,76 @@ const treeWithEnds = (roots, stored) => {
|
|
|
1578
1631
|
};
|
|
1579
1632
|
return roots.map((node) => dress(node));
|
|
1580
1633
|
};
|
|
1634
|
+
// ../server/src/list-fields-routes.ts
|
|
1635
|
+
/**
|
|
1636
|
+
* @file `GET /api/list-fields`: the filter fields of each list, from core's
|
|
1637
|
+
* tables (RFC-017), as text without their functions, so the UI builds its
|
|
1638
|
+
* filter bar without importing core.
|
|
1639
|
+
*/
|
|
1640
|
+
const infoOf = (field) => ({
|
|
1641
|
+
name: field.name,
|
|
1642
|
+
description: field.description,
|
|
1643
|
+
type: field.type,
|
|
1644
|
+
...field.values === void 0 ? {} : { values: [...field.values] },
|
|
1645
|
+
...field.all === true ? { all: true } : {}
|
|
1646
|
+
});
|
|
1647
|
+
/** The answer, built once: the tables do not change while the server runs. */
|
|
1648
|
+
const listFields = () => ({
|
|
1649
|
+
runs: LIST_TABLES.ps.fields.map(infoOf),
|
|
1650
|
+
feedback: LIST_TABLES["feedback list"].fields.map(infoOf),
|
|
1651
|
+
"follow-ups": LIST_TABLES["follow-ups list"].fields.map(infoOf),
|
|
1652
|
+
decisions: LIST_TABLES["decide --list"].fields.map(infoOf),
|
|
1653
|
+
worktrees: LIST_TABLES["worktrees list"].fields.map(infoOf),
|
|
1654
|
+
usage: LIST_TABLES.usage.fields.map(infoOf)
|
|
1655
|
+
});
|
|
1656
|
+
const listFieldsRoutes = () => ({ listFields: () => ok(listFields()) });
|
|
1657
|
+
// ../server/src/list-query.ts
|
|
1658
|
+
/**
|
|
1659
|
+
* @file Reads a list route's filter fields the way the CLI reads its flags
|
|
1660
|
+
* (RFC-017, ADR-088): each value checked by core's `parseFilters` against the
|
|
1661
|
+
* list's table, a refused one answered as 400 in the CLI's words. A full ISO
|
|
1662
|
+
* time in `since` or `until` is taken as given (the form `usage` had before
|
|
1663
|
+
* the tables), the rest are an age, a day or `all`.
|
|
1664
|
+
*/
|
|
1665
|
+
/** A `2026-11-01T10:00:00Z`-style time, as an ISO time; else `undefined`. */
|
|
1666
|
+
const isoTime = (value) => {
|
|
1667
|
+
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T/u.test(value)) return;
|
|
1668
|
+
const time = Date.parse(value);
|
|
1669
|
+
return Number.isNaN(time) ? void 0 : new Date(time).toISOString();
|
|
1670
|
+
};
|
|
1671
|
+
/**
|
|
1672
|
+
* The filter `query` asks for, checked against `table`; a value the table
|
|
1673
|
+
* refuses is a 400.
|
|
1674
|
+
*/
|
|
1675
|
+
const filterOf = (table, query) => {
|
|
1676
|
+
const times = {};
|
|
1677
|
+
const rest = { ...query };
|
|
1678
|
+
for (const name of ["since", "until"]) {
|
|
1679
|
+
const iso = isoTime(query[name]);
|
|
1680
|
+
if (iso === void 0) continue;
|
|
1681
|
+
times[name] = iso;
|
|
1682
|
+
delete rest[name];
|
|
1683
|
+
}
|
|
1684
|
+
const parsed = parseFilters(table, rest, Date.now());
|
|
1685
|
+
return parsed.ok ? {
|
|
1686
|
+
ok: true,
|
|
1687
|
+
filter: {
|
|
1688
|
+
...parsed.filter,
|
|
1689
|
+
...times
|
|
1690
|
+
}
|
|
1691
|
+
} : {
|
|
1692
|
+
ok: false,
|
|
1693
|
+
refusal: fail(400, parsed.error)
|
|
1694
|
+
};
|
|
1695
|
+
};
|
|
1696
|
+
/**
|
|
1697
|
+
* The root a filter's `project` names (a registered project's id or root, else
|
|
1698
|
+
* the value as a root); `undefined` without one or for `all`.
|
|
1699
|
+
*/
|
|
1700
|
+
const projectRootOf = (context, filter) => {
|
|
1701
|
+
const key = filter["project"];
|
|
1702
|
+
return key === void 0 || key === "all" ? void 0 : projectOf(context, key)?.root ?? key;
|
|
1703
|
+
};
|
|
1581
1704
|
// ../server/src/workflows.ts
|
|
1582
1705
|
/**
|
|
1583
1706
|
* @file A project's workflows, for the UI's Run workflow dialog: each
|
|
@@ -1636,14 +1759,18 @@ const projectWorkflows = (project) => {
|
|
|
1636
1759
|
* decisions, and usage. Each reads the store as the matching CLI command does
|
|
1637
1760
|
* (`ork projects`, `ps`, `tree`, `logs`, `decide --list`, `usage`).
|
|
1638
1761
|
*/
|
|
1639
|
-
/** A project filter's root: a registered project's, or the value as a root. */
|
|
1640
1762
|
/** A registered project's place; caps are only known for one. */
|
|
1641
1763
|
const placeOf = (context, key) => {
|
|
1642
1764
|
const known = key === void 0 ? void 0 : projectOf(context, key);
|
|
1643
1765
|
return known === void 0 ? void 0 : placeFor(known.root, context.store.projects());
|
|
1644
1766
|
};
|
|
1645
|
-
|
|
1767
|
+
/** `ork ps`'s table, matching `--status` on the live status the API shows. */
|
|
1768
|
+
const liveRunTable = {
|
|
1769
|
+
...runListTable,
|
|
1770
|
+
fields: runListTable.fields.map((field) => field.name === "status" ? Object.assign({}, field, { get: (run) => run.live }) : field)
|
|
1771
|
+
};
|
|
1646
1772
|
const readRoutes = (context) => ({
|
|
1773
|
+
...listFieldsRoutes(),
|
|
1647
1774
|
health: () => ok({
|
|
1648
1775
|
version: context.version,
|
|
1649
1776
|
pid: context.pid,
|
|
@@ -1652,23 +1779,38 @@ const readRoutes = (context) => ({
|
|
|
1652
1779
|
projects: () => ok(context.store.projects()),
|
|
1653
1780
|
triggers: () => ok(triggersReport(context.store, context.store.projects(), context.home)),
|
|
1654
1781
|
links: ({ query }) => ok(context.store.links(query.run === void 0 ? {} : { run: query.run })),
|
|
1655
|
-
usage: ({ query }) =>
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1782
|
+
usage: ({ query }) => {
|
|
1783
|
+
const read = filterOf(usageListTable, query);
|
|
1784
|
+
if (!read.ok) return read.refusal;
|
|
1785
|
+
const { filter } = read;
|
|
1786
|
+
const { workflow, since, until } = filter;
|
|
1787
|
+
const root = projectRootOf(context, filter);
|
|
1788
|
+
return ok({
|
|
1789
|
+
...usageReport(context.store.usage({
|
|
1790
|
+
...root === void 0 ? {} : { project: root },
|
|
1791
|
+
...workflow === void 0 ? {} : { workflow },
|
|
1792
|
+
...since === void 0 || since === "all" ? {} : { since },
|
|
1793
|
+
...until === void 0 ? {} : { until }
|
|
1794
|
+
})),
|
|
1795
|
+
limits: limitsReport(context.store, capsHere(context.home, placeOf(context, root)), /* @__PURE__ */ new Date())
|
|
1796
|
+
});
|
|
1797
|
+
},
|
|
1664
1798
|
workflows: ({ params }) => {
|
|
1665
1799
|
const project = projectOf(context, params.id);
|
|
1666
1800
|
return project === void 0 ? fail(404, `No registered project \`${params.id}\`.`) : ok(projectWorkflows(project));
|
|
1667
1801
|
},
|
|
1668
|
-
runs: ({ query }) =>
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1802
|
+
runs: ({ query }) => {
|
|
1803
|
+
const read = filterOf(liveRunTable, query);
|
|
1804
|
+
if (!read.ok) return read.refusal;
|
|
1805
|
+
const root = projectRootOf(context, read.filter);
|
|
1806
|
+
const limit = query.limit ?? 20;
|
|
1807
|
+
const narrowed = Object.keys(read.filter).some((name) => name !== "project");
|
|
1808
|
+
const views = context.store.runs({
|
|
1809
|
+
...root === void 0 ? {} : { project: root },
|
|
1810
|
+
...narrowed ? {} : { limit }
|
|
1811
|
+
}).map((run) => viewOf$2(context, run));
|
|
1812
|
+
return ok(applyFilters(liveRunTable, views, read.filter).slice(0, limit));
|
|
1813
|
+
},
|
|
1672
1814
|
run: ({ params }) => {
|
|
1673
1815
|
const found = runOf(context, params.id);
|
|
1674
1816
|
return found.ok ? ok(viewOf$2(context, found.run)) : found.refusal;
|
|
@@ -1692,12 +1834,18 @@ const readRoutes = (context) => ({
|
|
|
1692
1834
|
return ok((query.limit === void 0 ? newest : newest.slice(0, query.limit)).map((stored) => servedEvent(stored)));
|
|
1693
1835
|
},
|
|
1694
1836
|
decisions: ({ query }) => {
|
|
1695
|
-
const
|
|
1696
|
-
if (
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1837
|
+
const read = filterOf(decisionListTable, query);
|
|
1838
|
+
if (!read.ok) return read.refusal;
|
|
1839
|
+
const { run, workflow: named } = read.filter;
|
|
1840
|
+
const workflow = named === void 0 ? {} : { workflow: named };
|
|
1841
|
+
if (run === void 0) {
|
|
1842
|
+
const root = projectRootOf(context, read.filter);
|
|
1843
|
+
return ok(pendingDecisions(context.store, {
|
|
1844
|
+
...workflow,
|
|
1845
|
+
...root === void 0 ? {} : { project: root }
|
|
1846
|
+
}));
|
|
1847
|
+
}
|
|
1848
|
+
const found = runOf(context, run);
|
|
1701
1849
|
if (!found.ok) return found.refusal;
|
|
1702
1850
|
return ok(pendingDecisions(context.store, {
|
|
1703
1851
|
...workflow,
|
|
@@ -1742,7 +1890,7 @@ const mcpTools = (context) => {
|
|
|
1742
1890
|
...NO_QUERY,
|
|
1743
1891
|
params: { id: args.project }
|
|
1744
1892
|
}))),
|
|
1745
|
-
tool("runs", "Runs, newest first, with their live status and cost. 10 unless a limit is given.", RunsQuerySchema.shape, (args) => fromReply(read.runs({
|
|
1893
|
+
tool("runs", "Runs, newest first, with their live status and cost. 10 unless a limit is given. Narrow them with `status` (running, paused, crashed, succeeded, failed, … or all), `workflow`, `project` (or all), `since` (24h, 30d, 2026-11-01, all) and `until` (a day).", RunsQuerySchema.shape, (args) => fromReply(read.runs({
|
|
1746
1894
|
...NO_QUERY,
|
|
1747
1895
|
query: {
|
|
1748
1896
|
limit: 10,
|
|
@@ -1778,11 +1926,11 @@ const mcpTools = (context) => {
|
|
|
1778
1926
|
}
|
|
1779
1927
|
}));
|
|
1780
1928
|
}),
|
|
1781
|
-
tool("usage", "What runs spent, by workflow and model, and how close the limits are. `since` and `until
|
|
1929
|
+
tool("usage", "What runs spent, by workflow and model, and how close the limits are. Narrow it with `workflow`, `project` (or all), `since` and `until`: an age (24h, 30d), a day (2026-11-01) or an ISO time; `since` also takes all.", UsageQuerySchema.shape, (args) => fromReply(read.usage({
|
|
1782
1930
|
...NO_QUERY,
|
|
1783
1931
|
query: args
|
|
1784
1932
|
}))),
|
|
1785
|
-
tool("decisions", "The decisions open in live runs, waiting on a person. This server can't answer them.", DecisionsQuerySchema.shape, (args) => fromReply(read.decisions({
|
|
1933
|
+
tool("decisions", "The decisions open in live runs, waiting on a person. This server can't answer them. Narrow them with `workflow`, `run` (an id or a start of one) and `project` (or all).", DecisionsQuerySchema.shape, (args) => fromReply(read.decisions({
|
|
1786
1934
|
...NO_QUERY,
|
|
1787
1935
|
query: args
|
|
1788
1936
|
}), (open) => ({
|
|
@@ -2183,7 +2331,10 @@ const feedbackRoutes = (context) => {
|
|
|
2183
2331
|
const noted = recordNote(store, found.run, body);
|
|
2184
2332
|
return noted.ok ? ok({ item: noted.item }) : fail(400, noted.error);
|
|
2185
2333
|
},
|
|
2186
|
-
feedbackItems: () =>
|
|
2334
|
+
feedbackItems: ({ query }) => {
|
|
2335
|
+
const read = filterOf(feedbackListTable, query);
|
|
2336
|
+
return read.ok ? ok(applyFilters(feedbackListTable, store.feedbackItems({ all: true }), read.filter)) : read.refusal;
|
|
2337
|
+
},
|
|
2187
2338
|
feedbackItem: ({ params }) => {
|
|
2188
2339
|
const found = itemOf(store, params.id);
|
|
2189
2340
|
if (!found.ok) return found.refusal;
|
|
@@ -2352,13 +2503,15 @@ const followUpRoutes = (context) => {
|
|
|
2352
2503
|
gh
|
|
2353
2504
|
}).then((checked) => checked.errors).catch((error) => [error instanceof Error ? error.message : String(error)]);
|
|
2354
2505
|
const all = store.followUps(root);
|
|
2355
|
-
const
|
|
2356
|
-
const
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
if (status === "open") return OPEN.some((s) => s === f.status);
|
|
2360
|
-
return f.status === status;
|
|
2506
|
+
const open = (query.status ?? "open") === "open";
|
|
2507
|
+
const read = filterOf(followUpListTable, {
|
|
2508
|
+
...query,
|
|
2509
|
+
...open ? { status: "all" } : {}
|
|
2361
2510
|
});
|
|
2511
|
+
if (!read.ok) return read.refusal;
|
|
2512
|
+
const other = projectRootOf(context, read.filter);
|
|
2513
|
+
const matched = other === void 0 || other === root ? applyFilters(followUpListTable, all, read.filter) : [];
|
|
2514
|
+
const shown = open ? matched.filter((f) => OPEN.some((s) => s === f.status)) : matched;
|
|
2362
2515
|
return ok({
|
|
2363
2516
|
project: root,
|
|
2364
2517
|
followUps: shown,
|
|
@@ -2908,9 +3061,15 @@ const worktreesRoutes = (context) => {
|
|
|
2908
3061
|
};
|
|
2909
3062
|
return {
|
|
2910
3063
|
worktrees: async ({ query }) => {
|
|
2911
|
-
const
|
|
3064
|
+
const filtered = filterOf(worktreeListTable, query);
|
|
3065
|
+
if (!filtered.ok) return filtered.refusal;
|
|
3066
|
+
const all = await readAll(projectRootOf(context, filtered.filter));
|
|
2912
3067
|
if (!all.ok) return all.refusal;
|
|
2913
|
-
return ok({ projects: all.reads.map((read) =>
|
|
3068
|
+
return ok({ projects: all.reads.map((read) => {
|
|
3069
|
+
const project = listed(context, read);
|
|
3070
|
+
project.items = applyFilters(worktreeListTable, project.items, filtered.filter);
|
|
3071
|
+
return project;
|
|
3072
|
+
}) });
|
|
2914
3073
|
},
|
|
2915
3074
|
worktreeRemovePlan: async ({ body }) => {
|
|
2916
3075
|
const planned = await removePlanOf(context, body);
|