@krapht/ork 1.0.0-alpha.6 → 1.0.0-alpha.7

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.
Files changed (30) hide show
  1. package/dist/{__build_info__-CxH89h1r.mjs → __build_info__-BGoaUwLd.mjs} +72 -3
  2. package/dist/bin.mjs +149 -44
  3. package/dist/{clean-BbrkMQQi.mjs → clean-BPITM-6p.mjs} +1 -1
  4. package/dist/{completion-BeS2NCgO.mjs → completion-CCn8xWmO.mjs} +5 -5
  5. package/dist/{context-CHV6aTs7.mjs → context-CZNM454F.mjs} +3 -3
  6. package/dist/{decide-Cnt7o3ya.mjs → decide-DsA6kOT7.mjs} +1 -1
  7. package/dist/{find-Dy2H5IvT.mjs → find-ntyniv2E.mjs} +1 -1
  8. package/dist/{format-OL0E1AjA.mjs → format-DaROJUgG.mjs} +34 -5
  9. package/dist/{in-a-run-emTc-kZI.mjs → in-a-run-D_fnj1Mw.mjs} +1 -1
  10. package/dist/{limits-TxTnWxix.mjs → limits-BKzVMwkt.mjs} +1 -1
  11. package/dist/{list-P5CfcoWx.mjs → list-D9HPWLPH.mjs} +1 -1
  12. package/dist/{mcp-qUwFT9yi.mjs → mcp-BFl3cIDp.mjs} +6 -6
  13. package/dist/{output-CjOPL8W0.mjs → output-CwqlG1Le.mjs} +11 -2
  14. package/dist/{pause-CBSAxtTp.mjs → pause-DhgKQORW.mjs} +4 -4
  15. package/dist/{relay-UgK1Cp9a.mjs → relay-Cp8JGrdv.mjs} +2 -2
  16. package/dist/{remove-ccycC3vI.mjs → remove-CSpT_nJH.mjs} +3 -3
  17. package/dist/{send-B39-Xeo7.mjs → send-CHiYkM6X.mjs} +3 -3
  18. package/dist/{src-DG4dyBqm.mjs → src-BsLHKQRc.mjs} +3902 -3210
  19. package/dist/{src-jyCJE1kd.mjs → src-BwnitlJh.mjs} +8 -77
  20. package/dist/{src-8nec4uoe.mjs → src-CUeMUVwW.mjs} +40 -23
  21. package/dist/{src-5-sCA7cY.mjs → src-DhGLtYR-.mjs} +5 -3
  22. package/dist/ui/assets/{app-C1DAgdU2.js → app-D4CoH-lh.js} +2 -2
  23. package/dist/ui/assets/{index-BZKXPhht.js → index-DxDGdEwz.js} +2 -2
  24. package/dist/ui/index.html +1 -1
  25. package/dist/{ui-DmJWLgxL.mjs → ui-BxE0L7V0.mjs} +4 -4
  26. package/dist/{usage-Bh1lVioA.mjs → usage-BuzDsEhq.mjs} +5 -5
  27. package/dist/{watch-C_vcsn_g.mjs → watch-CCj0vU3B.mjs} +6 -6
  28. package/dist/{workflows-lpexsAYt.mjs → workflows-BNCDD6J-.mjs} +3 -3
  29. package/dist/{worktrees-D4bVVKfY.mjs → worktrees-DBBcaimX.mjs} +4 -4
  30. package/package.json +1 -1
@@ -1,86 +1,17 @@
1
- import { B as linkNodes, Bn as readDocument, Cn as placeFiles, Ct as walkChecks, En as runDirOf, G as requestContinue, Gn as EdgeInputSchema, Gt as planPost, Hn as parseWorkflow, In as skillsIn, J as tellLiveRun, Jn as expandEdge, K as requestPause, Kt as runGh, Ln as WorkflowEditSchema, Nt as nodeSays, On as workflowDirOf, Rn as applyEdits, St as checkWorkflowText, U as unlinkNodes, Vn as renderJsonSchema, Wt as DISCUSSIONS, Xn as NodeSchema, _t as runStatus, bt as processAlive, ct as explainWorkflowText, d as runningRunIds, f as runningScript, gt as pausedOf, ht as liveStatus, jn as LESSON_CAP_TOKENS, kn as inside, l as planUpgrade, nn as readCondition, nt as resumable, o as limitsReport, ot as detachRun, p as detectInstaller, q as requestStop, qt as sendPost, r as capsHere, st as followEvents, tt as detachResume, u as releaseNotes, v as triggersReport, vn as loadAgents, vt as runTree, wn as placeFor, wt as walkSummary, zn as newWorkflowText } from "./src-DG4dyBqm.mjs";
2
- import { C as feedbackActions, S as placeOf$1, _ as previewPost, a as registryShown, b as acceptItem, c as checkDue, f as readUpdateCache, g as nodeSession, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, o as updateSwitchOff, p as refreshUpdateCache, s as runInstall, u as newerVersion, w as openFixRun, x as lessonPlaceOf, y as recordNote } from "./__build_info__-CxH89h1r.mjs";
3
- import { n as pendingDecisions, r as builtinProblem, t as answerDecision } from "./decide-Cnt7o3ya.mjs";
4
- import { n as newRunId, t as findRun } from "./find-Dy2H5IvT.mjs";
5
- import { c as openStore, l as storePath, s as nodeOf } from "./output-CjOPL8W0.mjs";
1
+ import { Bn as readDocument, Cn as placeFiles, En as runDirOf, Et as processAlive, G as requestPause, Gt as planPost, H as unlinkNodes, In as skillsIn, K as requestStop, Kt as runGh, Ln as WorkflowEditSchema, Nt as nodeSays, On as workflowDirOf, Qn as NodeSchema, Rn as applyEdits, St as runStatus, Un as renderJsonSchema, W as requestContinue, Wn as parseWorkflow, Wt as DISCUSSIONS, Xn as expandEdge, at as followEvents, bt as liveStatus, d as runningRunIds, et as detachResume, f as runningScript, ht as walkSummary, it as detachRun, jn as LESSON_CAP_TOKENS, kn as inside, l as planUpgrade, mt as walkChecks, nn as readCondition, o as limitsReport, ot as explainWorkflowText, p as detectInstaller, pt as checkWorkflowText, q as tellLiveRun, qn as EdgeInputSchema, qt as sendPost, r as capsHere, tt as resumable, u as releaseNotes, v as triggersReport, vn as loadAgents, wn as placeFor, xt as pausedOf, z as linkNodes, zn as newWorkflowText } from "./src-BsLHKQRc.mjs";
2
+ import { C as placeOf$1, S as lessonPlaceOf, T as openFixRun, _ as nodeSession, a as registryShown, b as recordNote, c as checkDue, f as readUpdateCache, g as activeTree, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, o as updateSwitchOff, p as refreshUpdateCache, s as runInstall, u as newerVersion, v as previewPost, w as feedbackActions, x as acceptItem } from "./__build_info__-BGoaUwLd.mjs";
3
+ import { n as pendingDecisions, r as builtinProblem, t as answerDecision } from "./decide-DsA6kOT7.mjs";
4
+ import { n as newRunId, t as findRun } from "./find-ntyniv2E.mjs";
5
+ import { c as openStore, l as storePath, s as isNodeEvent } from "./output-CwqlG1Le.mjs";
6
6
  import { n as usageReport } from "./report-DK4LGqwF.mjs";
7
- import { a as planClean, i as keyOf, o as stepActs, r as cleanStep, s as stepPrunes, t as applyClean } from "./clean-BbrkMQQi.mjs";
8
- import { a as readWorktrees, c as planLine, i as projectHead, l as removeRefusal, n as lostWork, o as labelOf, r as planRemove, s as mergeStateOf, t as applyRemove, u as stateParts } from "./remove-ccycC3vI.mjs";
7
+ import { a as planClean, i as keyOf, o as stepActs, r as cleanStep, s as stepPrunes, t as applyClean } from "./clean-BPITM-6p.mjs";
8
+ import { a as readWorktrees, c as planLine, i as projectHead, l as removeRefusal, n as lostWork, o as labelOf, r as planRemove, s as mergeStateOf, t as applyRemove, u as stateParts } from "./remove-CSpT_nJH.mjs";
9
9
  import path from "node:path";
10
10
  import { z } from "zod";
11
11
  import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
12
12
  import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
13
13
  import { homedir } from "node:os";
14
14
  import { createServer } from "node:http";
15
- // ../core/src/store/activity.ts
16
- const LONGEST_LINE = 120;
17
- /**
18
- * The fields of a tool's input that say what it's working on, best first. Only
19
- * these are shown, so what else a tool was given stays in the logs.
20
- */
21
- const TARGETS = [
22
- "file_path",
23
- "notebook_path",
24
- "path",
25
- "url",
26
- "pattern",
27
- "query",
28
- "command"
29
- ];
30
- const oneLine = (text) => {
31
- const line = text.replaceAll(/\s+/gu, " ").trim();
32
- return line.length > LONGEST_LINE ? `${line.slice(0, 119)}…` : line;
33
- };
34
- const toolLine = ({ name, input }) => {
35
- const target = TARGETS.map((field) => input[field]).find((value) => typeof value === "string" && value.trim() !== "");
36
- if (typeof target !== "string") return name;
37
- return oneLine(target.startsWith(`${name} `) ? target : `${name} ${target}`);
38
- };
39
- /** What a finished node said, or why it failed. */
40
- const finishedNow = (ok, error, summary) => {
41
- if (!ok) return error === void 0 ? void 0 : oneLine(error);
42
- return typeof summary === "string" && summary.trim() !== "" ? oneLine(summary) : void 0;
43
- };
44
- /** Each node's activity, by id; a node that never started has none. */
45
- const runActivity = (stored) => {
46
- const nodes = /* @__PURE__ */ new Map();
47
- const of = (id) => {
48
- const found = nodes.get(id);
49
- if (found !== void 0) return found;
50
- const fresh = {};
51
- nodes.set(id, fresh);
52
- return fresh;
53
- };
54
- for (const { at, event } of stored) if (event.type === "node.started") {
55
- const node = of(event.id);
56
- node.startedAt ??= at;
57
- delete node.finishedAt;
58
- delete node.now;
59
- } else if (event.type === "node.event") {
60
- if (event.event.type === "tool.called") of(event.id).now = toolLine(event.event);
61
- } else if (event.type === "decision.opened") of(event.node).now = oneLine(`Asked: ${event.question}`);
62
- else if (event.type === "decision.answered") of(event.node).now = oneLine(`Answered: ${event.answer}`);
63
- else if (event.type === "decision.withdrawn") delete of(event.node).now;
64
- else if (event.type === "node.finished") {
65
- const node = of(event.id);
66
- node.finishedAt = at;
67
- const now = finishedNow(event.ok, event.error, event.output["summary"]);
68
- if (now === void 0) delete node.now;
69
- else node.now = now;
70
- }
71
- return nodes;
72
- };
73
- /** The ownership tree, with what each node is doing and when it ran. */
74
- const activeTree = (stored) => {
75
- const activity = runActivity(stored);
76
- const dress = (node) => {
77
- Object.assign(node, activity.get(node.id));
78
- for (const child of node.children) dress(child);
79
- };
80
- const roots = runTree(stored.map(({ event }) => event));
81
- for (const root of roots) dress(root);
82
- return roots;
83
- };
84
15
  // ../server/src/contract-builder.ts
85
16
  /** A new workflow's name, as its file and its `name:` take it. */
86
17
  const NewWorkflowSchema = z.strictObject({ name: z.string().min(1) });
@@ -1623,7 +1554,7 @@ const readRoutes = (context) => ({
1623
1554
  events: ({ params, query }) => {
1624
1555
  const found = runOf(context, params.id);
1625
1556
  if (!found.ok) return found.refusal;
1626
- const events = context.store.events(found.run.id, query.after ?? 0).filter((s) => query.node === void 0 || nodeOf(s.event) === query.node);
1557
+ const events = context.store.events(found.run.id, query.after ?? 0).filter((s) => query.node === void 0 || isNodeEvent(s.event, query.node));
1627
1558
  const newest = query.last === void 0 ? events : events.slice(-query.last);
1628
1559
  return ok(query.limit === void 0 ? newest : newest.slice(0, query.limit));
1629
1560
  },
@@ -1,4 +1,4 @@
1
- import { $n as isToolNode, $t as evaluate, At as runScope, Bt as serversIn, F as declaredProblem, Mt as envReadsOf, Ot as heldTimeout, Pt as declaredOutputOf, Rt as MCP_FILE, Wn as markValue, Zn as beforeOf, ar as integrationFor, en as parseTemplate, er as programsRunBy, ft as sessionDriver, ir as TOOL_PREFIX, jt as calledWorkflows, mt as reportSchemaFor, nr as timeoutMs, rr as INTEGRATIONS, s as planReason, tn as renderTemplate, ut as planNodeSession, zt as mcpNotText } from "./src-DG4dyBqm.mjs";
1
+ import { $t as evaluate, At as declaredProblem, Bt as serversIn, Hn as programsRunBy, Kn as markValue, Mt as envReadsOf, Ot as runScope, Pt as declaredOutputOf, Rt as MCP_FILE, Vn as beforeOf, ar as integrationFor, ct as planNodeSession, en as parseTemplate, er as isToolNode, ft as reportSchemaFor, ir as TOOL_PREFIX, jt as calledWorkflows, nr as timeoutMs, rr as INTEGRATIONS, s as planReason, tn as renderTemplate, ut as sessionDriver, yt as heldTimeout, zt as mcpNotText } from "./src-BsLHKQRc.mjs";
2
2
  import path from "node:path";
3
3
  import { accessSync, constants, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { spawn } from "node:child_process";
@@ -35,7 +35,7 @@ const callExecutor = (context) => {
35
35
  output: { status: "fail" },
36
36
  error: "This run cannot call workflows."
37
37
  });
38
- const scope = runScope(context.inputs, context.outputs, context.runId);
38
+ const scope = runScope(context.inputs, context.outputs, context.runId, context.item);
39
39
  const render = (text) => {
40
40
  const template = parseTemplate(text);
41
41
  return template.ok ? renderTemplate(template.parts, scope) : text;
@@ -61,6 +61,32 @@ const callExecutor = (context) => {
61
61
  }
62
62
  }, context.signal).then(limitedCall);
63
63
  };
64
+ // ../nodes/src/claude-plan.ts
65
+ /**
66
+ * @file What a Claude node's session is planned with, read from the node's
67
+ * context.
68
+ */
69
+ /** The plan options every session of a node starts from. */
70
+ const planOptionsOf = (context, inPlace) => {
71
+ const planOptions = {
72
+ cwd: context.cwd,
73
+ inputs: context.inputs,
74
+ outputs: context.outputs,
75
+ inPlace,
76
+ workflowDir: context.workflowDir,
77
+ projectRoot: context.projectRoot,
78
+ ...context.orkDir === void 0 ? {} : { orkDir: context.orkDir },
79
+ pluginDir: path.join(context.runDir, "plugins", context.id)
80
+ };
81
+ if (context.checkout !== void 0) planOptions.checkout = context.checkout;
82
+ if (context.brief !== void 0) planOptions.brief = context.brief;
83
+ if (context.template !== void 0) planOptions.template = context.template;
84
+ if (context.item !== void 0) planOptions.item = context.item;
85
+ if (context.ownership !== void 0) planOptions.ownership = context.ownership;
86
+ if (context.mailbox !== void 0) planOptions.mailbox = context.mailbox;
87
+ if (context.claims !== void 0) planOptions.claims = context.claims;
88
+ return planOptions;
89
+ };
64
90
  // ../nodes/src/claude-result.ts
65
91
  /**
66
92
  * @file A finished session as a node's result: its report is the output, held
@@ -991,7 +1017,9 @@ const IDENTITY_KEYS = /* @__PURE__ */ new Set([
991
1017
  "ORK_WORKFLOW",
992
1018
  "ORK_BIN",
993
1019
  OUTPUT_ENV,
994
- STATE_ENV
1020
+ STATE_ENV,
1021
+ "ORK_ITEM",
1022
+ "ORK_INDEX"
995
1023
  ]);
996
1024
  /**
997
1025
  * `env` without Ork's identity variables. A run started by a program in another
@@ -1019,7 +1047,11 @@ const identityOf = (context, orkBin) => ({
1019
1047
  ORK_RUN_DIR: context.runDir,
1020
1048
  ORK_PROJECT: context.projectRoot,
1021
1049
  ORK_WORKFLOW: context.workflow.name,
1022
- ...orkBin === void 0 ? {} : { ORK_BIN: orkBin }
1050
+ ...orkBin === void 0 ? {} : { ORK_BIN: orkBin },
1051
+ ...context.item === void 0 ? {} : {
1052
+ ORK_ITEM: typeof context.item.value === "string" ? context.item.value : JSON.stringify(context.item.value),
1053
+ ORK_INDEX: String(context.item.index)
1054
+ }
1023
1055
  });
1024
1056
  /** The variables a workflow's nodes read that no `plainEnv` excuses. */
1025
1057
  const secretNamesOf = (workflow) => Object.values(workflow.nodes).flatMap((node) => programsRunBy(node, workflow.defaults)).flatMap(({ program }) => {
@@ -1061,7 +1093,7 @@ const secretsOf = (workflow, environ, also = []) => valuesOf(namesToMask(workflo
1061
1093
  const renderEnv = (node, context, environ) => {
1062
1094
  const values = {};
1063
1095
  const scope = {
1064
- ...runScope(context.inputs, context.outputs, context.runId),
1096
+ ...runScope(context.inputs, context.outputs, context.runId, context.item),
1065
1097
  output: { env: environ }
1066
1098
  };
1067
1099
  for (const [key, text] of Object.entries(node.env ?? {})) {
@@ -1151,7 +1183,7 @@ const render = (text, context) => {
1151
1183
  };
1152
1184
  return {
1153
1185
  ok: true,
1154
- value: renderTemplate(template.parts, runScope(context.inputs, context.outputs, context.runId))
1186
+ value: renderTemplate(template.parts, runScope(context.inputs, context.outputs, context.runId, context.item))
1155
1187
  };
1156
1188
  };
1157
1189
  /** The program and arguments a tool node runs, before the allow check. */
@@ -1538,22 +1570,7 @@ const specFor = (spec, context) => {
1538
1570
  };
1539
1571
  /** Runs a `claude.leader` or `claude.worker` as one session. */
1540
1572
  const claudeExecutor = (options) => async (context) => {
1541
- const planOptions = {
1542
- cwd: context.cwd,
1543
- inputs: context.inputs,
1544
- outputs: context.outputs,
1545
- inPlace: options.inPlace,
1546
- workflowDir: context.workflowDir,
1547
- projectRoot: context.projectRoot,
1548
- ...context.orkDir === void 0 ? {} : { orkDir: context.orkDir },
1549
- pluginDir: path.join(context.runDir, "plugins", context.id)
1550
- };
1551
- if (context.checkout !== void 0) planOptions.checkout = context.checkout;
1552
- if (context.brief !== void 0) planOptions.brief = context.brief;
1553
- if (context.template !== void 0) planOptions.template = context.template;
1554
- if (context.ownership !== void 0) planOptions.ownership = context.ownership;
1555
- if (context.mailbox !== void 0) planOptions.mailbox = context.mailbox;
1556
- if (context.claims !== void 0) planOptions.claims = context.claims;
1573
+ const planOptions = planOptionsOf(context, options.inPlace);
1557
1574
  const before = beforeOf(context.node, context.workflow.defaults);
1558
1575
  if (before !== void 0) {
1559
1576
  const ran = await runStep(options.steps ?? noSteps, context, before, {
@@ -1853,7 +1870,7 @@ const mcpCallExecutor = (options = {}) => async (context) => {
1853
1870
  }, node.plainEnv);
1854
1871
  if (!expanded.ok) return failed(expanded.error);
1855
1872
  const scrub = scrubberOf([...secretsOf(context.workflow, environ, options.maskedNames), ...expanded.value.values]);
1856
- const scope = runScope(context.inputs, context.outputs, context.runId);
1873
+ const scope = runScope(context.inputs, context.outputs, context.runId, context.item);
1857
1874
  const args = Object.fromEntries(Object.entries(node.arguments ?? {}).map(([key, value]) => [key, renderValue(value, scope)]));
1858
1875
  const name = `${node.server}.${node.tool}`;
1859
1876
  context.emit({
@@ -1,4 +1,4 @@
1
- import { Ht as FEEDBACK_SEVERITIES, Ut as FEEDBACK_TARGETS, Vt as FEEDBACK_KINDS, pt as parseReport } from "./src-DG4dyBqm.mjs";
1
+ import { Ht as FEEDBACK_SEVERITIES, Ut as FEEDBACK_TARGETS, Vt as FEEDBACK_KINDS, dt as parseReport } from "./src-BsLHKQRc.mjs";
2
2
  import { z } from "zod";
3
3
  import { randomBytes, timingSafeEqual } from "node:crypto";
4
4
  import { createInterface } from "node:readline";
@@ -361,7 +361,7 @@ const defineTool = (definition) => ({
361
361
  const schema = z.object(shape);
362
362
  return {
363
363
  name: definition.name,
364
- description: definition.description,
364
+ description: typeof definition.description === "function" ? definition.description(context) : definition.description,
365
365
  shape,
366
366
  schema,
367
367
  preapproved: definition.preapproved ?? true,
@@ -643,9 +643,11 @@ const delegationText = (delegation) => text(JSON.stringify({
643
643
  reports: delegation.reports.map(reportLine),
644
644
  ...delegation.notes.length > 0 ? { notes: delegation.notes } : {}
645
645
  }));
646
+ /** Why a child the leader owns isn't offered, so it doesn't go looking. */
647
+ const fannedNote = (fanned) => fanned.length === 0 ? "" : ` Not listed: ${fanned.join(", ")}; such a node runs once per item of a list, from its edges, so it can't be delegated to.`;
646
648
  const delegateTool = defineTool({
647
649
  name: "delegate",
648
- description: "Hand tasks to nodes you own. Tasks in one call run in parallel; the call returns every child's report when all are done. Ork merges a passing child's branch into yours.",
650
+ description: ({ ports }) => `Hand tasks to nodes you own. Tasks in one call run in parallel; the call returns every child's report when all are done. Ork merges a passing child's branch into yours.${fannedNote(ports.ownership?.fanned ?? [])}`,
649
651
  shape: ({ ports }) => {
650
652
  const ids = ports.ownership?.children.map((child) => child.id) ?? [];
651
653
  return { tasks: z.array(z.strictObject({