@krapht/ork 1.0.0-alpha.13 → 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-CM3cERGl.mjs → attach-BHO3X3cf.mjs} +36 -91
- package/dist/{attach-E6NNyA3T.mjs → attach-CPespxlQ.mjs} +6 -5
- package/dist/bin.mjs +148 -1444
- package/dist/brief-za0ozN_E.mjs +58 -0
- package/dist/{builtin-files-n6o6oWpB.mjs → builtin-files-2bHf76x-.mjs} +1 -1
- package/dist/{chips-CyeB_rhR.mjs → chips-BqcT58qr.mjs} +1 -1
- package/dist/{completion-SNNNxnv9.mjs → completion-CQ2UYKuJ.mjs} +52 -11
- package/dist/context-BNqDw9z1.mjs +106 -0
- package/dist/{find-CjsNYAAf.mjs → find-BYLlszqj.mjs} +1 -1
- package/dist/follow-ups-B4GJ3Vzw.mjs +461 -0
- package/dist/{format-C60TFpRe.mjs → format-C8MsFj8_.mjs} +30 -16
- package/dist/{help-groups-CyfPWlST.mjs → help-groups-CQ98mLjF.mjs} +20 -6
- package/dist/{in-a-run-BYjTXaST.mjs → in-a-run-Bp0k0J09.mjs} +1 -1
- package/dist/{__build_info__-Da73_nBs.mjs → install-DWtXTq4y.mjs} +3 -227
- package/dist/{limits-C5QKZNLT.mjs → limits-B1qzS4cX.mjs} +1 -1
- package/dist/{mcp-bcctR-wc.mjs → mcp-BOrVkyhN.mjs} +6 -6
- package/dist/{once-DPQu5Q3H.mjs → once-C1fL3GVo.mjs} +4 -4
- package/dist/orphan-guard-BFKg8VSd.mjs +58 -0
- package/dist/{output-CnRzrbUM.mjs → output-B1kwo0YU.mjs} +17 -1
- package/dist/{pause-BPvlDIvz.mjs → pause-DOMK-R8V.mjs} +4 -4
- package/dist/post-BzA6Qobq.mjs +44 -0
- package/dist/{relay-C8W0t_zc.mjs → relay-OWuu4fib.mjs} +2 -2
- package/dist/run--4-1xAF2.mjs +1451 -0
- package/dist/{run-CQIfq918.mjs → run-CiPsW9Kf.mjs} +1 -1
- package/dist/send-CnNNW-ot.mjs +105 -0
- package/dist/{src-CqRqsb2t.mjs → src-B9zWIVqo.mjs} +226 -44
- package/dist/{src-CGJGL1sZ.mjs → src-DQKz2eOH.mjs} +326 -81
- package/dist/{src-D93tHZ5B.mjs → src-DcrhgipG.mjs} +107 -47
- package/dist/{src-BeR6f70A.mjs → src-Dr_fTSu-.mjs} +5858 -3746
- 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-CWwm8HTG.js → index-BtwkftKe.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-D2Ydofq0.mjs → ui-CzKlsCnm.mjs} +4 -4
- package/dist/{usage-6WIowblz.mjs → usage-DHGNk2JL.mjs} +13 -141
- package/dist/{context-DHudLA5e.mjs → validate-Bs_gg22g.mjs} +17 -107
- package/dist/{verdict-CIy8tAyX.mjs → verdict-CMvPCpWC.mjs} +2 -2
- package/dist/{watch-uOU_WeBI.mjs → watch-CCCfw3n7.mjs} +24 -8
- package/dist/{workflows-7tQdMnrA.mjs → workflows-CW28ZU-z.mjs} +3 -3
- package/dist/{worktrees-ZCII298F.mjs → worktrees-CyE8aF6j.mjs} +3 -5
- package/package.json +2 -2
- package/dist/clean-Bh4KZgzc.mjs +0 -91
- package/dist/decide-DuIHACvH.mjs +0 -50
- package/dist/list-BUb5Uc3H.mjs +0 -117
- package/dist/remove-BkFWGVYo.mjs +0 -201
- package/dist/report-CEN8VoUb.mjs +0 -140
- package/dist/send-CaZlGG5a.mjs +0 -163
- package/dist/ui/assets/app-DYRC0V4p.js +0 -111
- package/dist/ui/assets/app-QoHVi-mb.css +0 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { un as takeFollowUps } from "./src-Dr_fTSu-.mjs";
|
|
2
|
+
import { l as briefOf, n as flagValues, u as checkTakeable } from "./run--4-1xAF2.mjs";
|
|
3
|
+
import { n as newRunId } from "./find-BYLlszqj.mjs";
|
|
4
|
+
import { l as writeErr } from "./output-B1kwo0YU.mjs";
|
|
5
|
+
import { t as loadWorkflow } from "./validate-Bs_gg22g.mjs";
|
|
6
|
+
// src/follow-ups/brief.ts
|
|
7
|
+
/**
|
|
8
|
+
* @file `ork run --follow-ups <ids>`: the `agent` follow-ups become the run's
|
|
9
|
+
* `brief` input, and are marked taken by the run, which finishes them when it
|
|
10
|
+
* publishes (`ork follow-ups published`). Everything that could refuse them
|
|
11
|
+
* (an unknown id, one for someone else, a workflow with no `brief` input) is
|
|
12
|
+
* checked before any is marked, so a run that doesn't start leaves them be.
|
|
13
|
+
*/
|
|
14
|
+
/** The ids `--follow-ups` was given, one per comma or repeat. */
|
|
15
|
+
const idsOf = (rawArgs) => flagValues(rawArgs, "--follow-ups").flatMap((value) => value.split(",")).map((id) => id.trim()).filter((id) => id !== "");
|
|
16
|
+
/**
|
|
17
|
+
* What stops `--follow-ups` from starting a run, one line each; none when
|
|
18
|
+
* nothing does.
|
|
19
|
+
*/
|
|
20
|
+
const problemsOf = (loaded, inputs) => {
|
|
21
|
+
const name = loaded.workflow?.name ?? "";
|
|
22
|
+
if (loaded.workflow?.inputs?.["brief"] === void 0) return [`--follow-ups fills a workflow's \`brief\` input, and ${name} has none.`];
|
|
23
|
+
return inputs.some((input) => input.startsWith("brief=")) ? ["--follow-ups and --input brief=… both set the brief."] : [];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The inputs and run id `ork run` starts with: those it was given and, for
|
|
27
|
+
* `--follow-ups`, a `brief` made of the follow-ups with the id of the run that
|
|
28
|
+
* takes them. `undefined` after saying why it can't start.
|
|
29
|
+
*/
|
|
30
|
+
const prepareFollowUps = (store, rawArgs, runId, target) => {
|
|
31
|
+
const inputs = flagValues(rawArgs, "--input");
|
|
32
|
+
const ids = idsOf(rawArgs);
|
|
33
|
+
const plain = {
|
|
34
|
+
inputs,
|
|
35
|
+
...runId === void 0 ? {} : { runId }
|
|
36
|
+
};
|
|
37
|
+
if (ids.length === 0) return plain;
|
|
38
|
+
const loaded = loadWorkflow(target.file, process.cwd(), void 0, store.projects());
|
|
39
|
+
if (loaded.workflow === null) return plain;
|
|
40
|
+
const takeable = checkTakeable(store, loaded.place.root, ids);
|
|
41
|
+
const problems = [...problemsOf(loaded, inputs), ...takeable.ok ? [] : takeable.lines];
|
|
42
|
+
if (!takeable.ok || problems.length > 0) {
|
|
43
|
+
for (const line of problems) writeErr(line);
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const taker = runId ?? newRunId(store);
|
|
48
|
+
takeFollowUps(store, {
|
|
49
|
+
project: loaded.place.root,
|
|
50
|
+
run: taker,
|
|
51
|
+
ids: takeable.followUps.map((f) => f.id)
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
inputs: [...inputs, `brief=${briefOf(takeable.followUps)}`],
|
|
55
|
+
runId: taker
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
export { prepareFollowUps };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Er as placeFiles, Ir as guardedBase, Lr as plainPathInside, Rr as writePlainFile } from "./src-Dr_fTSu-.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as isBuiltinArg, i as builtinWorkflowText, r as builtinWorkflowNames } from "./builtin-files-
|
|
3
|
-
import {
|
|
4
|
-
import { t as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { a as resolveWorkflowArg, n as WORKFLOW_SUFFIX } from "./workflows-7tQdMnrA.mjs";
|
|
1
|
+
import { Cn as liveStatus, Dr as placeFor, Er as placeFiles, U as openStore, W as storePath, _i as AGENT_DRIVERS, oi as NodeIdSchema, ut as pendingDecisions } from "./src-Dr_fTSu-.mjs";
|
|
2
|
+
import { a as isBuiltinArg, i as builtinWorkflowText, r as builtinWorkflowNames } from "./builtin-files-2bHf76x-.mjs";
|
|
3
|
+
import { t as findRun } from "./find-BYLlszqj.mjs";
|
|
4
|
+
import { a as findEntry, c as subcommandsOf, d as SHELL_SCRIPTS, l as COMPLETE_COMMAND, n as groupedEntries, r as argInfoOf, t as groupOf, u as SHELLS } from "./help-groups-CQ98mLjF.mjs";
|
|
5
|
+
import { l as writeErr } from "./output-B1kwo0YU.mjs";
|
|
6
|
+
import { a as resolveWorkflowArg, n as WORKFLOW_SUFFIX } from "./workflows-CW28ZU-z.mjs";
|
|
8
7
|
import path from "node:path";
|
|
9
8
|
import { parse } from "yaml";
|
|
10
9
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
@@ -40,16 +39,45 @@ const workflowText = (arg, cwd, place) => {
|
|
|
40
39
|
const file = path.resolve(cwd, resolveWorkflowArg(arg, cwd, placeFiles(place).workflows));
|
|
41
40
|
return existsSync(file) && statSync(file).isFile() ? readFileSync(file, "utf8") : void 0;
|
|
42
41
|
};
|
|
42
|
+
/** A mapping's entries, or none when `value` is not an object. */
|
|
43
|
+
const entriesOf = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? Object.entries(value) : [];
|
|
44
|
+
/** One top-level field of a workflow's text, read without validating it. */
|
|
45
|
+
const fieldOf = (text, field) => {
|
|
46
|
+
const parsed = text === void 0 ? void 0 : parse(text);
|
|
47
|
+
return Object.fromEntries(entriesOf(parsed))[field];
|
|
48
|
+
};
|
|
43
49
|
/** The node ids of the workflow `arg` names; none when it can't be read. */
|
|
44
50
|
const workflowNodes = (arg, cwd, place) => {
|
|
45
|
-
|
|
46
|
-
const parsed = text === void 0 ? void 0 : parse(text);
|
|
47
|
-
const nodes = parsed !== null && typeof parsed === "object" && "nodes" in parsed ? parsed.nodes : void 0;
|
|
48
|
-
return (nodes !== null && typeof nodes === "object" ? Object.keys(nodes) : []).filter((key) => NodeIdSchema.safeParse(key).success).map((value) => ({
|
|
51
|
+
return entriesOf(fieldOf(workflowText(arg, cwd, place), "nodes")).map(([key]) => key).filter((key) => NodeIdSchema.safeParse(key).success).map((value) => ({
|
|
49
52
|
value,
|
|
50
53
|
description: arg
|
|
51
54
|
}));
|
|
52
55
|
};
|
|
56
|
+
/** What a menu says of an input: its description, else its type. */
|
|
57
|
+
const inputDescription = (definition) => {
|
|
58
|
+
const fields = Object.fromEntries(entriesOf(definition));
|
|
59
|
+
const said = fields["description"] ?? fields["type"];
|
|
60
|
+
const what = typeof said === "string" ? said : "";
|
|
61
|
+
return fields["required"] === true && !("default" in fields) ? `${what} (required)` : what;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* `name=` for each input a workflow's text declares, for `--input`; a name that
|
|
65
|
+
* isn't a valid id is left out, as a node's is.
|
|
66
|
+
*/
|
|
67
|
+
const inputsOf = (text, workflow) => entriesOf(fieldOf(text, "inputs")).filter(([name]) => NodeIdSchema.safeParse(name).success).map(([name, definition]) => ({
|
|
68
|
+
value: `${name}=`,
|
|
69
|
+
description: inputDescription(definition) || workflow
|
|
70
|
+
}));
|
|
71
|
+
/** The inputs of the workflow `arg` names; none when it can't be read. */
|
|
72
|
+
const workflowInputs = (arg, cwd, place) => inputsOf(workflowText(arg, cwd, place), arg);
|
|
73
|
+
/** The inputs of the run `arg` names (else the project's newest run). */
|
|
74
|
+
const runInputs = (store, arg, cwd) => {
|
|
75
|
+
const found = findRun(store, arg, cwd);
|
|
76
|
+
if (!found.ok) return [];
|
|
77
|
+
const { file, workflow } = found.run;
|
|
78
|
+
const text = existsSync(file) && statSync(file).isFile() ? readFileSync(file, "utf8") : void 0;
|
|
79
|
+
return inputsOf(text, workflow);
|
|
80
|
+
};
|
|
53
81
|
/**
|
|
54
82
|
* Runs whose id starts with `prefix`, newest first: the project's, else any
|
|
55
83
|
* project's, at most `RUN_LIMIT`.
|
|
@@ -112,6 +140,18 @@ const nodes = {
|
|
|
112
140
|
return withStore(context, (store) => runNodes(store, context.given["run"], context.cwd));
|
|
113
141
|
}
|
|
114
142
|
};
|
|
143
|
+
/**
|
|
144
|
+
* `name=` for each input, for `--input`: the workflow given's when the command
|
|
145
|
+
* takes a workflow (none before it is), else the run given's (`ork resume`).
|
|
146
|
+
*/
|
|
147
|
+
const inputs = {
|
|
148
|
+
group: "inputs",
|
|
149
|
+
values: (context) => {
|
|
150
|
+
const workflow = context.given["workflow"];
|
|
151
|
+
if (context.positionals.includes("workflow")) return workflow === void 0 ? [] : workflowInputs(workflow, context.cwd, placeOf(context.cwd, context.store()));
|
|
152
|
+
return withStore(context, (store) => runInputs(store, context.given["run"], context.cwd));
|
|
153
|
+
}
|
|
154
|
+
};
|
|
115
155
|
const decisions = {
|
|
116
156
|
group: "decisions",
|
|
117
157
|
values: (context) => withStore(context, (store) => decisionCandidates(store, context.given["run"], context.cwd, placeOf(context.cwd, store)))
|
|
@@ -144,6 +184,7 @@ const VALUE_PROVIDERS = {
|
|
|
144
184
|
files: true
|
|
145
185
|
},
|
|
146
186
|
node: nodes,
|
|
187
|
+
input: inputs,
|
|
147
188
|
"decide id": decisions,
|
|
148
189
|
"completion shell": shells,
|
|
149
190
|
driver: drivers,
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Pr as LESSON_CAP_TOKENS, wt as explainSession } from "./src-Dr_fTSu-.mjs";
|
|
2
|
+
import { c as write, s as style } from "./output-B1kwo0YU.mjs";
|
|
3
|
+
import { i as refusedBuiltin, o as workflowArg } from "./workflows-CW28ZU-z.mjs";
|
|
4
|
+
import { a as formatReport, t as loadWorkflow } from "./validate-Bs_gg22g.mjs";
|
|
5
|
+
import { defineCommand } from "citty";
|
|
6
|
+
// src/commands/context.ts
|
|
7
|
+
/**
|
|
8
|
+
* @file `ork context explain <wf> <node>`: what one node's session would load,
|
|
9
|
+
* layer by layer, as core's `explainSession` plans it without writing
|
|
10
|
+
* anything (one of Ork's own `ork:` workflows is written into the project's
|
|
11
|
+
* run folder first, as `ork run` does): its project instructions, every skill
|
|
12
|
+
* with the layer it came from and whether it is live, shadowed or switched
|
|
13
|
+
* off, its context files, its practices, and estimated tokens.
|
|
14
|
+
*/
|
|
15
|
+
/** Loads a workflow file and plans one node's session in it, in place. */
|
|
16
|
+
const explainNode = (file, nodeId, cwd, home) => {
|
|
17
|
+
const { report, workflow, graph, place, workflowDir } = loadWorkflow(file, cwd, home);
|
|
18
|
+
if (workflow === null) return {
|
|
19
|
+
ok: false,
|
|
20
|
+
lines: formatReport(report)
|
|
21
|
+
};
|
|
22
|
+
const result = explainSession(workflow, graph, nodeId, {
|
|
23
|
+
root: place.root,
|
|
24
|
+
orkDir: place.dir,
|
|
25
|
+
workflowDir,
|
|
26
|
+
...home === void 0 ? {} : { home }
|
|
27
|
+
});
|
|
28
|
+
return result.ok ? result : {
|
|
29
|
+
ok: false,
|
|
30
|
+
lines: [result.error]
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const approx = (count) => style("dim", `≈${count.toLocaleString("en")} tokens`);
|
|
34
|
+
const formatExplanation = (e) => {
|
|
35
|
+
const width = Math.max(8, ...e.skills.map((s) => s.name.length));
|
|
36
|
+
const sourceWidth = Math.max(0, ...e.skills.map((s) => s.source.length));
|
|
37
|
+
const lines = [
|
|
38
|
+
`${style("bold", e.node)} ${style("dim", `(${e.type}) in ${e.workflow}`)}${e.template === void 0 ? "" : style("dim", `, planned as ${e.template}, the node it was spawned from`)}`,
|
|
39
|
+
"",
|
|
40
|
+
...e.agent === void 0 ? [] : [`${style("bold", "Agent")} ${e.agent.name} ${style("dim", `(${e.agent.where})`)} ${approx(e.agent.tokens)}`],
|
|
41
|
+
`${style("bold", "Instructions")} ${e.instructions}`,
|
|
42
|
+
"",
|
|
43
|
+
style("bold", "Skills")
|
|
44
|
+
];
|
|
45
|
+
if (e.skills.length === 0) lines.push(style("dim", " none"));
|
|
46
|
+
for (const s of e.skills) {
|
|
47
|
+
const mark = s.state === "live" ? style("green", "✓") : style("dim", "−");
|
|
48
|
+
const state = s.why === void 0 ? approx(s.tokens).replace("tokens", "tokens when used") : style("yellow", `off: ${s.why}`);
|
|
49
|
+
lines.push(` ${mark} ${s.name.padEnd(width)} ${s.layer.padEnd(8)} ${style("dim", s.source.padEnd(sourceWidth))} ${state}`);
|
|
50
|
+
}
|
|
51
|
+
lines.push("", style("bold", "Context files"));
|
|
52
|
+
if (e.files.length === 0) lines.push(style("dim", " none"));
|
|
53
|
+
for (const f of e.files) {
|
|
54
|
+
const cut = f.cutFrom === void 0 ? "" : ` ${style("yellow", `cut at the ${LESSON_CAP_TOKENS.toLocaleString("en")}-token cap; the whole file is ${approx(f.cutFrom)}`)}`;
|
|
55
|
+
lines.push(` ${f.layer.padEnd(8)} ${f.name} ${approx(f.tokens)}${cut}`);
|
|
56
|
+
}
|
|
57
|
+
lines.push("", style("bold", "Practices"));
|
|
58
|
+
for (const p of e.practices) lines.push(` ${p.name.padEnd(8)} ${approx(p.tokens)}`);
|
|
59
|
+
for (const name of e.skippedPractices) lines.push(` ${name.padEnd(8)} ${style("dim", "the project's own skill wins")}`);
|
|
60
|
+
if (e.practices.length === 0 && e.skippedPractices.length === 0) lines.push(style("dim", " off"));
|
|
61
|
+
lines.push("", `Appended to Claude Code's system prompt: ${approx(e.appendedTokens)}`);
|
|
62
|
+
return lines;
|
|
63
|
+
};
|
|
64
|
+
const explain = defineCommand({
|
|
65
|
+
meta: {
|
|
66
|
+
name: "explain",
|
|
67
|
+
description: "Show what one node's session loads, layer by layer"
|
|
68
|
+
},
|
|
69
|
+
args: {
|
|
70
|
+
workflow: {
|
|
71
|
+
type: "positional",
|
|
72
|
+
description: "A workflow file, the name of one in the project's workflows (.ork/workflows/), or one of Ork's own (ork:feedback-apply)",
|
|
73
|
+
required: true
|
|
74
|
+
},
|
|
75
|
+
node: {
|
|
76
|
+
type: "positional",
|
|
77
|
+
description: "Node id",
|
|
78
|
+
required: true
|
|
79
|
+
},
|
|
80
|
+
json: {
|
|
81
|
+
type: "boolean",
|
|
82
|
+
description: "Print JSON",
|
|
83
|
+
default: false
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
run: ({ args }) => {
|
|
87
|
+
const cwd = process.cwd();
|
|
88
|
+
if (refusedBuiltin([args.workflow], cwd)) return;
|
|
89
|
+
const result = explainNode(workflowArg(args.workflow, cwd).file, args.node, cwd);
|
|
90
|
+
if (!result.ok) {
|
|
91
|
+
for (const line of result.lines) process.stderr.write(`${line}\n`);
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (args.json) write(JSON.stringify(result.explanation, void 0, 2));
|
|
96
|
+
else for (const line of formatExplanation(result.explanation)) write(line);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const context = defineCommand({
|
|
100
|
+
meta: {
|
|
101
|
+
name: "context",
|
|
102
|
+
description: "Inspect the context Ork compiles for each node"
|
|
103
|
+
},
|
|
104
|
+
subCommands: { explain }
|
|
105
|
+
});
|
|
106
|
+
export { explainNode as n, context as t };
|