omkit 0.8.13 → 0.8.14
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
CHANGED
|
@@ -185,7 +185,7 @@ flakyBackgroundJob().result.catch((e) => console.warn("job failed, carrying on",
|
|
|
185
185
|
|
|
186
186
|
Every action's output, events, asserts, snapshots, and lifecycle land on **one timeline** — streamed live to the terminal (curated milestones) and written to a per-run folder:
|
|
187
187
|
|
|
188
|
-
- `result.json` — the run's tree, per-node status, verdict, and curated artifacts. Each node also carries what its definition declared about itself: the `.describe()` summary, the `.mcp()` exposure, and the `.args()` schema as JSON Schema. Each node also records `calledAt`, the line that launched it, so a built-in step (a `prompt`, a `command`) points back at your code rather than omkit's, and a `step(...)` is defined at the line where you wrote it.
|
|
188
|
+
- `result.json` — the run's tree, per-node status, verdict, and curated artifacts. Each node also carries what its definition declared about itself: the `.describe()` summary, the `.mcp()` exposure, and the `.args()` schema as JSON Schema. Each node also records what it returned (`value`, or a `valueNote` when it was too large or not JSON) and `calledAt`, the line that launched it, so a built-in step (a `prompt`, a `command`) points back at your code rather than omkit's, and a `step(...)` is defined at the line where you wrote it.
|
|
189
189
|
- `raw.jsonl` — every entry, machine-readable.
|
|
190
190
|
- `main.log` + one `.log` per action — the human-readable timelines.
|
|
191
191
|
- `events.log` / `asserts.log` / `snapshots.log` / `artifacts.log` — cross-cutting rollups.
|
|
@@ -391,6 +391,7 @@ export class ExecutionTree {
|
|
|
391
391
|
duration: node.duration,
|
|
392
392
|
logFile: this.logFile(node.path),
|
|
393
393
|
...this.metaView(node),
|
|
394
|
+
...valueView(node.value),
|
|
394
395
|
children: node.children.map((child) => this.nodeView(child)),
|
|
395
396
|
};
|
|
396
397
|
}
|
|
@@ -506,6 +507,36 @@ const messageOf = (error) => error instanceof Error ? (error.stack ?? error.mess
|
|
|
506
507
|
* body may hand back anything — a capability handle, a cyclic object — and the run must
|
|
507
508
|
* still write its record; a value that does not survive JSON is dropped, not fatal.
|
|
508
509
|
*/
|
|
510
|
+
/** A node's return value is recorded up to this many characters of JSON. */
|
|
511
|
+
const VALUE_CAP = 512 * 1024;
|
|
512
|
+
/**
|
|
513
|
+
* What a node returned, for the record: the value itself when JSON can carry it and it fits,
|
|
514
|
+
* otherwise a one-line note saying what it was — so "returned a Page" is still on the record.
|
|
515
|
+
*/
|
|
516
|
+
function valueView(value) {
|
|
517
|
+
if (value === undefined)
|
|
518
|
+
return {};
|
|
519
|
+
const kind = value === null
|
|
520
|
+
? "null"
|
|
521
|
+
: typeof value === "object"
|
|
522
|
+
? (value.constructor?.name ?? "object")
|
|
523
|
+
: typeof value;
|
|
524
|
+
let text;
|
|
525
|
+
try {
|
|
526
|
+
text = JSON.stringify(value);
|
|
527
|
+
}
|
|
528
|
+
catch {
|
|
529
|
+
text = undefined;
|
|
530
|
+
}
|
|
531
|
+
if (text === undefined)
|
|
532
|
+
return { valueNote: `${kind} (not JSON)` };
|
|
533
|
+
if (text.length > VALUE_CAP) {
|
|
534
|
+
return {
|
|
535
|
+
valueNote: `${kind}, ${Math.round(text.length / 1024)} KB of JSON — too large to record`,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
return { value: JSON.parse(text) };
|
|
539
|
+
}
|
|
509
540
|
function serialisable(value) {
|
|
510
541
|
if (value === undefined)
|
|
511
542
|
return undefined;
|
|
@@ -337,6 +337,7 @@ a.icon-btn { text-decoration: none; }
|
|
|
337
337
|
.tk-k { color: var(--tk-k); }
|
|
338
338
|
.tk-f { color: var(--tk-f); }
|
|
339
339
|
.tk-t { color: var(--tk-t); }
|
|
340
|
+
.tk-p { color: var(--tk-f); }
|
|
340
341
|
|
|
341
342
|
/* ── popover tabs, prompt panel, flow snapshot strip ───── */
|
|
342
343
|
.code-pop .cp-tabs { display: flex; gap: 2px; padding: 0 8px; border-bottom: 1px solid var(--line); background: var(--panel-2); }
|
|
@@ -355,6 +356,18 @@ a.icon-btn { text-decoration: none; }
|
|
|
355
356
|
.flow-shots .shot:hover rect { stroke: var(--accent); }
|
|
356
357
|
.flow-shots .shot text { fill: var(--text-3); font: 600 9px var(--mono); pointer-events: none; }
|
|
357
358
|
|
|
359
|
+
/* ── returned values ───────────────────────────────────── */
|
|
360
|
+
.code-btn path { fill: none; stroke: var(--text-2); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; pointer-events: none; }
|
|
361
|
+
.code-btn:hover path { stroke: var(--accent); }
|
|
362
|
+
.cp-tools { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 10px 6px 14px; border-bottom: 1px solid var(--line-soft); font-size: 12px; }
|
|
363
|
+
.btn.small { padding: 3px 9px; font-size: 12px; }
|
|
364
|
+
.btn.small svg { width: 13px; height: 13px; }
|
|
365
|
+
.code-box { border: 1px solid var(--line-soft); border-radius: 8px; background: var(--panel-2); overflow: auto; max-height: 60vh; }
|
|
366
|
+
.code-box .cp-code, .code-pop .cp-code { font: 11.5px/1.65 var(--mono); padding: 8px 0; min-width: max-content; }
|
|
367
|
+
.code-box .cl { display: grid; grid-template-columns: 40px auto; white-space: pre; }
|
|
368
|
+
.code-box .ln { color: var(--text-3); text-align: right; padding-right: 12px; user-select: none; }
|
|
369
|
+
.code-box .lc { padding-right: 14px; }
|
|
370
|
+
|
|
358
371
|
@media (max-width: 1100px) {
|
|
359
372
|
.bottom { grid-template-columns: minmax(0, 1fr); }
|
|
360
373
|
.legend, .overview { display: none; }
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
info: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM12 11v5M12 8h.01",
|
|
44
44
|
locate: "M12 5a7 7 0 1 0 0 14 7 7 0 0 0 0-14zM12 2v3M12 19v3M2 12h3M19 12h3M12 10.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z",
|
|
45
45
|
code: "M8 7l-5 5 5 5M16 7l5 5-5 5",
|
|
46
|
+
ret: "M9 10l-4 4 4 4M5 14h11a4 4 0 0 0 4-4V5",
|
|
46
47
|
external: "M14 4h6v6M20 4l-9 9M18 14v6H4V6h6",
|
|
47
48
|
};
|
|
48
49
|
const svgIcon = (name, extra) =>
|
|
@@ -505,9 +506,12 @@
|
|
|
505
506
|
r.append("rect").attr("class", "bar").attr("rx", 5).attr("y", BAR_Y).attr("height", BAR_H);
|
|
506
507
|
r.append("text").attr("class", "bar-label").attr("y", BAR_Y + BAR_H / 2 + 4);
|
|
507
508
|
r.append("g").attr("class", "marks");
|
|
508
|
-
const cb = r.append("g").attr("class", "code-btn");
|
|
509
|
+
const cb = r.append("g").attr("class", "code-btn src");
|
|
509
510
|
cb.append("circle").attr("r", 9);
|
|
510
511
|
cb.append("text").attr("text-anchor", "middle").attr("y", 3.5).text("<>");
|
|
512
|
+
const rb = r.append("g").attr("class", "code-btn ret");
|
|
513
|
+
rb.append("circle").attr("r", 9);
|
|
514
|
+
rb.append("path").attr("d", ICON.ret).attr("transform", "translate(-6,-6) scale(0.5)");
|
|
511
515
|
return r;
|
|
512
516
|
})
|
|
513
517
|
.attr("transform", (_n, i) => `translate(0,${i * ROW_H})`)
|
|
@@ -547,18 +551,33 @@
|
|
|
547
551
|
// …and, for a block spanning the chart, inside it right after its label
|
|
548
552
|
const cx =
|
|
549
553
|
right + 8 <= W - 10 ? right + 8 : left - 8 >= 10 ? left - 8 : Math.min(W - 12, (flip ? x0 : lx + tw) + 14);
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
554
|
+
// buttons stack away from the block: rightward when they sit after it, leftward before it
|
|
555
|
+
const dir = right + 8 <= W - 10 || left - 8 < 10 ? 1 : -1;
|
|
556
|
+
const src = hasCode(n);
|
|
557
|
+
const row = d3.select(this.parentNode);
|
|
558
|
+
row
|
|
559
|
+
.select("g.code-btn.src")
|
|
560
|
+
.style("display", src ? null : "none")
|
|
553
561
|
.attr("transform", `translate(${cx},${BAR_Y + BAR_H / 2})`);
|
|
562
|
+
row
|
|
563
|
+
.select("g.code-btn.ret")
|
|
564
|
+
.style("display", hasValue(n) ? null : "none")
|
|
565
|
+
.attr("transform", `translate(${src ? cx + dir * 21 : cx},${BAR_Y + BAR_H / 2})`);
|
|
554
566
|
});
|
|
555
|
-
g.select("g.code-btn")
|
|
567
|
+
g.select("g.code-btn.src")
|
|
556
568
|
.on("click", (ev, n) => {
|
|
557
569
|
ev.stopPropagation();
|
|
558
570
|
toggleCode(n, ev);
|
|
559
571
|
})
|
|
560
572
|
.on("mouseenter", (ev) => showTip(ev, "Show source"))
|
|
561
573
|
.on("mouseleave", hideTip);
|
|
574
|
+
g.select("g.code-btn.ret")
|
|
575
|
+
.on("click", (ev, n) => {
|
|
576
|
+
ev.stopPropagation();
|
|
577
|
+
toggleCode(n, ev, "value", true);
|
|
578
|
+
})
|
|
579
|
+
.on("mouseenter", (ev, n) => showTip(ev, `Returned: <span class="mono">${esc(valuePreview(n, 80))}</span>`))
|
|
580
|
+
.on("mouseleave", hideTip);
|
|
562
581
|
g.selectAll("rect.hit, text.bar-label").call(bindNode);
|
|
563
582
|
|
|
564
583
|
g.select("g.marks").each(function (n) {
|
|
@@ -802,6 +821,21 @@
|
|
|
802
821
|
});
|
|
803
822
|
fcb.append("circle").attr("r", 9);
|
|
804
823
|
fcb.append("text").attr("text-anchor", "middle").attr("y", 3.5).text("<>");
|
|
824
|
+
const frb = card
|
|
825
|
+
.filter((d) => hasValue(d.data))
|
|
826
|
+
.append("g")
|
|
827
|
+
.attr("class", "code-btn ret")
|
|
828
|
+
.attr("transform", (d) => `translate(${CW / 2 + (hasCode(d.data) ? 22 : 0)},0)`)
|
|
829
|
+
.on("click", (ev, d) => {
|
|
830
|
+
ev.stopPropagation();
|
|
831
|
+
toggleCode(d.data, ev, "value", true);
|
|
832
|
+
})
|
|
833
|
+
.on("mouseenter", (ev, d) => {
|
|
834
|
+
ev.stopPropagation();
|
|
835
|
+
showTip(ev, `Returned: <span class="mono">${esc(valuePreview(d.data, 80))}</span>`);
|
|
836
|
+
});
|
|
837
|
+
frb.append("circle").attr("r", 9);
|
|
838
|
+
frb.append("path").attr("d", ICON.ret).attr("transform", "translate(-6,-6) scale(0.5)");
|
|
805
839
|
const TW = 46;
|
|
806
840
|
const TH = 28;
|
|
807
841
|
const strip = card
|
|
@@ -1004,6 +1038,7 @@
|
|
|
1004
1038
|
const tabs = [
|
|
1005
1039
|
["overview", "Overview"],
|
|
1006
1040
|
["args", "Args"],
|
|
1041
|
+
...(hasValue(n) ? [["value", "Return"]] : []),
|
|
1007
1042
|
["events", `Events`],
|
|
1008
1043
|
["logs", "Logs"],
|
|
1009
1044
|
["snapshots", "Snapshots"],
|
|
@@ -1026,6 +1061,7 @@
|
|
|
1026
1061
|
${userSite(n) ? `<div class="k">${siteLabel(n)}</div><div class="v defined">
|
|
1027
1062
|
<button class="icon-btn" data-copy-source aria-label="Copy relative path">${svgIcon("copy")}</button>
|
|
1028
1063
|
${hasCode(n) ? `<button class="icon-btn" data-show-code aria-label="Show source">${svgIcon("code")}</button>` : ""}
|
|
1064
|
+
${hasValue(n) ? `<button class="icon-btn" data-show-value aria-label="Show returned value">${svgIcon("ret")}</button>` : ""}
|
|
1029
1065
|
<a class="icon-btn" href="${esc(editorUrl(userSite(n)))}" aria-label="Open in VS Code" data-tip-text="Open in VS Code">${svgIcon("external")}</a>
|
|
1030
1066
|
<span class="defined-name" >${esc(basename(sourceOf(n)))}</span>
|
|
1031
1067
|
</div>` : ""}
|
|
@@ -1044,6 +1080,13 @@
|
|
|
1044
1080
|
copySrc.addEventListener("mousemove", (ev) => moveTip(ev));
|
|
1045
1081
|
copySrc.addEventListener("mouseleave", hideTip);
|
|
1046
1082
|
}
|
|
1083
|
+
const showValue = el.details.querySelector("[data-show-value]");
|
|
1084
|
+
if (showValue) {
|
|
1085
|
+
showValue.addEventListener("click", (ev) => toggleCode(n, ev, "value", true));
|
|
1086
|
+
showValue.addEventListener("mouseenter", (ev) => showTip(ev, `Returned: <span class="mono">${esc(valuePreview(n, 80))}</span>`));
|
|
1087
|
+
showValue.addEventListener("mouseleave", hideTip);
|
|
1088
|
+
}
|
|
1089
|
+
wireValue(el.details, n);
|
|
1047
1090
|
const showCode = el.details.querySelector("[data-show-code]");
|
|
1048
1091
|
if (showCode) {
|
|
1049
1092
|
showCode.addEventListener("click", (ev) => toggleCode(n, ev));
|
|
@@ -1070,6 +1113,9 @@
|
|
|
1070
1113
|
|
|
1071
1114
|
function detailTabHtml(n) {
|
|
1072
1115
|
const tab = state.detailTab;
|
|
1116
|
+
if (tab === "value") {
|
|
1117
|
+
return hasValue(n) ? `<div class="code-box">${valueHtml(n)}</div>` : '<div class="muted">Returned nothing.</div>';
|
|
1118
|
+
}
|
|
1073
1119
|
if (tab === "args") {
|
|
1074
1120
|
const params = schemaFields(n.v.inputSchema);
|
|
1075
1121
|
const schema = params.length ? `<div class="section-title">Schema</div><div class="params">${params.map(paramHtml).join("")}</div><div class="section-title">Values</div>` : "";
|
|
@@ -1343,6 +1389,7 @@
|
|
|
1343
1389
|
["When", `${fmtRel(n.start)} → ${fmtRel(n.end)}`],
|
|
1344
1390
|
v.tags.length ? ["Tags", esc(v.tags.join(" · "))] : null,
|
|
1345
1391
|
userSite(n) ? [siteLabel(n) === "Called at" ? "Called" : "Defined", `<span class="mono">${esc(sourceOf(n))}</span>`] : null,
|
|
1392
|
+
hasValue(n) ? ["Returns", `<span class="mono">${esc(valuePreview(n, 90))}</span>`] : null,
|
|
1346
1393
|
n.children.length ? ["Children", String(n.children.length)] : null,
|
|
1347
1394
|
n.marks.length ? ["Events", String(n.marks.length)] : null,
|
|
1348
1395
|
].filter(Boolean);
|
|
@@ -1391,6 +1438,7 @@
|
|
|
1391
1438
|
codeEl.hidden = true;
|
|
1392
1439
|
document.body.appendChild(codeEl);
|
|
1393
1440
|
let codeFor = null;
|
|
1441
|
+
let codeTab = null;
|
|
1394
1442
|
let codeAway = null;
|
|
1395
1443
|
/** A site inside omkit or an installed package — library source, not the user's. */
|
|
1396
1444
|
function isLib(site) {
|
|
@@ -1416,6 +1464,7 @@
|
|
|
1416
1464
|
function codeTabs(n) {
|
|
1417
1465
|
const tabs = [];
|
|
1418
1466
|
if (promptOf(n)) tabs.push({ key: "prompt", label: "Prompt" });
|
|
1467
|
+
if (hasValue(n)) tabs.push({ key: "value", label: "Returned" });
|
|
1419
1468
|
const mine = userSite(n);
|
|
1420
1469
|
if (codeOf(mine)) tabs.push({ key: "user", label: siteLabel(n) === "Called at" ? "Call site" : "Source", site: mine });
|
|
1421
1470
|
const def = n.v.definedAt;
|
|
@@ -1423,11 +1472,36 @@
|
|
|
1423
1472
|
return tabs;
|
|
1424
1473
|
}
|
|
1425
1474
|
function hasCode(n) {
|
|
1426
|
-
return codeTabs(n).
|
|
1475
|
+
return codeTabs(n).some((t) => t.key !== "value");
|
|
1427
1476
|
}
|
|
1428
1477
|
function relOf(site) {
|
|
1429
1478
|
return (model.data.sources && model.data.sources[site]) || String(site).replace(/:\d+(:\d+)?$/, "");
|
|
1430
1479
|
}
|
|
1480
|
+
function hasValue(n) {
|
|
1481
|
+
return n.v.value !== undefined || !!n.v.valueNote;
|
|
1482
|
+
}
|
|
1483
|
+
function valuePreview(n, max) {
|
|
1484
|
+
if (n.v.value === undefined) return n.v.valueNote || "";
|
|
1485
|
+
return truncate(oneLine(n.v.value), max);
|
|
1486
|
+
}
|
|
1487
|
+
/** The returned value in the code view: pretty JSON, highlighted, numbered, copyable. */
|
|
1488
|
+
function valueHtml(n) {
|
|
1489
|
+
if (n.v.value === undefined) {
|
|
1490
|
+
return `<div class="pp"><div class="muted">${esc(n.v.valueNote || "Returned nothing.")}</div></div>`;
|
|
1491
|
+
}
|
|
1492
|
+
const text = json(n.v.value);
|
|
1493
|
+
const lines = highlight(text);
|
|
1494
|
+
const kind = Array.isArray(n.v.value) ? `array · ${n.v.value.length} items` : n.v.value === null ? "null" : typeof n.v.value === "object" ? `object · ${Object.keys(n.v.value).length} keys` : typeof n.v.value;
|
|
1495
|
+
return `<div class="cp-tools"><span class="muted">${esc(kind)} · ${lines.length} line${lines.length > 1 ? "s" : ""} · ${fmtSize(text.length)}</span>
|
|
1496
|
+
<button class="btn solo small" data-a="copy-json">${svgIcon("copy")}Copy JSON</button></div>
|
|
1497
|
+
<div class="cp-code">${lines
|
|
1498
|
+
.map((html, i) => `<div class="cl"><span class="ln">${i + 1}</span><span class="lc">${html || " "}</span></div>`)
|
|
1499
|
+
.join("")}</div>`;
|
|
1500
|
+
}
|
|
1501
|
+
function wireValue(root, n) {
|
|
1502
|
+
const b = root.querySelector('[data-a="copy-json"]');
|
|
1503
|
+
if (b) b.addEventListener("click", () => copy(json(n.v.value), "Copied the returned value"));
|
|
1504
|
+
}
|
|
1431
1505
|
function codeHtml(site) {
|
|
1432
1506
|
const c = codeOf(site);
|
|
1433
1507
|
const line = Number((/:(\d+)(?::\d+)?$/.exec(site) || [])[1]);
|
|
@@ -1464,11 +1538,13 @@
|
|
|
1464
1538
|
${answer}
|
|
1465
1539
|
</div>`;
|
|
1466
1540
|
}
|
|
1467
|
-
function toggleCode(n, ev, want) {
|
|
1468
|
-
|
|
1541
|
+
function toggleCode(n, ev, want, toggle) {
|
|
1542
|
+
// the <> closes whatever is open on its node; the return button closes only its own tab
|
|
1543
|
+
if (codeFor === n.id && (!want || (toggle && codeTab === want))) return closeCode();
|
|
1469
1544
|
const tabs = codeTabs(n);
|
|
1470
1545
|
if (!tabs.length) return;
|
|
1471
|
-
const tab = tabs.find((t) => t.key === want) || tabs[0];
|
|
1546
|
+
const tab = tabs.find((t) => t.key === want) || tabs.find((t) => t.key !== "value") || tabs[0];
|
|
1547
|
+
codeTab = tab.key;
|
|
1472
1548
|
hideTip();
|
|
1473
1549
|
const reopen = codeFor !== n.id;
|
|
1474
1550
|
codeFor = n.id;
|
|
@@ -1483,7 +1559,8 @@
|
|
|
1483
1559
|
<button class="icon-btn" data-a="close" aria-label="Close">${svgIcon("close")}</button>
|
|
1484
1560
|
</div>
|
|
1485
1561
|
${tabs.length > 1 ? `<div class="cp-tabs">${tabs.map((t) => `<button class="tab ${t === tab ? "active" : ""}" data-tab="${t.key}">${esc(t.label)}</button>`).join("")}</div>` : ""}
|
|
1486
|
-
<div class="cp-body">${tab.key === "prompt" ? promptHtml(promptOf(n)) : codeHtml(site)}</div>`;
|
|
1562
|
+
<div class="cp-body">${tab.key === "prompt" ? promptHtml(promptOf(n)) : tab.key === "value" ? valueHtml(n) : codeHtml(site)}</div>`;
|
|
1563
|
+
wireValue(codeEl, n);
|
|
1487
1564
|
const cp = codeEl.querySelector('[data-a="copy"]');
|
|
1488
1565
|
if (cp) cp.addEventListener("click", () => copy(rel, `Copied ${rel}`));
|
|
1489
1566
|
codeEl.querySelector('[data-a="close"]').addEventListener("click", closeCode);
|
|
@@ -1503,7 +1580,7 @@
|
|
|
1503
1580
|
if (at) at.scrollIntoView({ block: "center" });
|
|
1504
1581
|
if (codeAway) document.removeEventListener("mousedown", codeAway, true);
|
|
1505
1582
|
codeAway = (e) => {
|
|
1506
|
-
if (!codeEl.contains(e.target) && !e.target.closest(".code-btn, [data-show-code]")) closeCode();
|
|
1583
|
+
if (!codeEl.contains(e.target) && !e.target.closest(".code-btn, [data-show-code], [data-show-value]")) closeCode();
|
|
1507
1584
|
};
|
|
1508
1585
|
setTimeout(() => codeAway && document.addEventListener("mousedown", codeAway, true), 0);
|
|
1509
1586
|
}
|
|
@@ -1710,7 +1787,7 @@
|
|
|
1710
1787
|
if (m.index > last) parts.push([null, text.slice(last, m.index)]);
|
|
1711
1788
|
let cls = null;
|
|
1712
1789
|
if (m[1]) cls = "tk-c";
|
|
1713
|
-
else if (m[2]) cls = "tk-s";
|
|
1790
|
+
else if (m[2]) cls = /^\s*:/.test(text.slice(TOKEN.lastIndex, TOKEN.lastIndex + 8)) ? "tk-p" : "tk-s";
|
|
1714
1791
|
else if (m[3]) cls = "tk-n";
|
|
1715
1792
|
else if (m[4]) {
|
|
1716
1793
|
if (KEYWORDS.has(m[4])) cls = "tk-k";
|
|
@@ -31,6 +31,10 @@ export interface NodeView {
|
|
|
31
31
|
};
|
|
32
32
|
/** The definition's `.args()` schema as JSON Schema; absent without one. */
|
|
33
33
|
readonly inputSchema?: unknown;
|
|
34
|
+
/** What the node returned, when JSON can carry it; absent for `undefined` and for failures. */
|
|
35
|
+
readonly value?: unknown;
|
|
36
|
+
/** Why a returned value is not in {@link value}: what it was, and that it was too big or not JSON. */
|
|
37
|
+
readonly valueNote?: string;
|
|
34
38
|
readonly children: readonly NodeView[];
|
|
35
39
|
}
|
|
36
40
|
/** A curated artifact, as projected into `result.json`. Data-only — no core import. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omkit",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.14",
|
|
4
4
|
"description": "A tiny runtime for developer workflows: typed actions that pass runtime capabilities and emit typed events, under one run and one shared log. The operational/runtime layer to tskb's knowledge layer.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|