ryugi-artifacts 1.63.0 → 1.65.0
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/cli.cjs +1234 -878
- package/dist/output-bootstrap.cjs +179 -63
- package/dist/server.cjs +218 -41
- package/dist/viewer/{ArtboardLayout-A9_5F0R5.js → ArtboardLayout-CL7CeJtR.js} +2 -2
- package/dist/viewer/SplitShell-Dm7Po2-x.js +1 -0
- package/dist/viewer/index.js +2 -2
- package/dist/viewer-lib/index.js +250 -245
- package/package.json +1 -1
- package/dist/viewer/SplitShell-BaDxDo-I.js +0 -1
package/dist/cli.cjs
CHANGED
|
@@ -84,10 +84,10 @@ function normalize(command, result2, options, policy) {
|
|
|
84
84
|
const keys = [.../* @__PURE__ */ new Set([...options.fields, ...policy.requiredFields ?? []])];
|
|
85
85
|
if (policy.collection && data && typeof data === "object") {
|
|
86
86
|
const record = data;
|
|
87
|
-
const
|
|
87
|
+
const rows2 = record[policy.collection];
|
|
88
88
|
data = {
|
|
89
89
|
...record,
|
|
90
|
-
[policy.collection]: Array.isArray(
|
|
90
|
+
[policy.collection]: Array.isArray(rows2) ? rows2.map((row, i) => project(row, keys, `data.${policy.collection}.${i}`, omitted)) : rows2
|
|
91
91
|
};
|
|
92
92
|
} else data = project(data, keys, "data", omitted);
|
|
93
93
|
}
|
|
@@ -275,9 +275,9 @@ function wantsHelp(args) {
|
|
|
275
275
|
const end = args.indexOf("--");
|
|
276
276
|
return (end === -1 ? args : args.slice(0, end)).some((arg) => arg === "--help" || arg === "-h");
|
|
277
277
|
}
|
|
278
|
-
function table(
|
|
279
|
-
const width = Math.max(...
|
|
280
|
-
return
|
|
278
|
+
function table(rows2) {
|
|
279
|
+
const width = Math.max(...rows2.map(([left]) => left.length)) + 2;
|
|
280
|
+
return rows2.map(
|
|
281
281
|
([left, right]) => ` ${left.padEnd(width)}${right.replaceAll("\n", `
|
|
282
282
|
${" ".repeat(width)}`)}`.trimEnd()
|
|
283
283
|
).join("\n");
|
|
@@ -290,7 +290,7 @@ function optionRows(options) {
|
|
|
290
290
|
}
|
|
291
291
|
function commandHelp(command) {
|
|
292
292
|
const usage = (command.usage ?? ["[options]"]).map(
|
|
293
|
-
(
|
|
293
|
+
(line2, index) => `${index ? " " : "Usage: "}${BIN} ${command.name} ${line2}`
|
|
294
294
|
);
|
|
295
295
|
return [
|
|
296
296
|
usage.join("\n"),
|
|
@@ -494,19 +494,33 @@ var EffectJournal = class {
|
|
|
494
494
|
this.entries.push({ operation, target, state: "unknown" });
|
|
495
495
|
return this.entries.length - 1;
|
|
496
496
|
}
|
|
497
|
-
confirm(
|
|
498
|
-
this.set(
|
|
497
|
+
confirm(id2, details) {
|
|
498
|
+
this.set(id2, "confirmed", details);
|
|
499
499
|
}
|
|
500
|
-
set(
|
|
501
|
-
const entry = this.entries[
|
|
500
|
+
set(id2, state, details) {
|
|
501
|
+
const entry = this.entries[id2];
|
|
502
502
|
if (!entry) throw new Error("Unknown effect");
|
|
503
|
-
this.entries[
|
|
503
|
+
this.entries[id2] = { ...entry, state, ...details === void 0 ? {} : { details } };
|
|
504
504
|
}
|
|
505
505
|
snapshot() {
|
|
506
506
|
return this.entries.map((entry) => ({ ...entry }));
|
|
507
507
|
}
|
|
508
508
|
};
|
|
509
509
|
|
|
510
|
+
// src/cli/output/time.ts
|
|
511
|
+
var ISO = /^\d{4}-\d\d-\d\dT\d\d:\d\d(?::\d\d(?:\.\d+)?)?(?:Z|[+-]\d\d:?\d\d)$/;
|
|
512
|
+
var two = (n) => String(n).padStart(2, "0");
|
|
513
|
+
var isIsoTime = (value3) => typeof value3 === "string" && ISO.test(value3) && !Number.isNaN(Date.parse(value3));
|
|
514
|
+
function formatTime(iso, now = /* @__PURE__ */ new Date()) {
|
|
515
|
+
const at = new Date(iso);
|
|
516
|
+
if (Number.isNaN(at.getTime())) return iso;
|
|
517
|
+
const clock = `${two(at.getHours())}:${two(at.getMinutes())}`;
|
|
518
|
+
if (at.getFullYear() !== now.getFullYear())
|
|
519
|
+
return `${at.getFullYear()}-${two(at.getMonth() + 1)}-${two(at.getDate())}`;
|
|
520
|
+
if (at.getMonth() === now.getMonth() && at.getDate() === now.getDate()) return clock;
|
|
521
|
+
return `${two(at.getMonth() + 1)}-${two(at.getDate())} ${clock}`;
|
|
522
|
+
}
|
|
523
|
+
|
|
510
524
|
// src/cli/output/view.ts
|
|
511
525
|
function recoveryActions(error, subject) {
|
|
512
526
|
const details = error.details;
|
|
@@ -526,13 +540,57 @@ var fact = (label, binding, required = false) => ({
|
|
|
526
540
|
});
|
|
527
541
|
|
|
528
542
|
// src/cli/output/render.ts
|
|
529
|
-
var clean = (
|
|
530
|
-
function clip(
|
|
531
|
-
const segments = [...new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(
|
|
532
|
-
return segments.length > size ? `${segments.slice(0, size).map((s) => s.segment).join("")}\u2026` :
|
|
543
|
+
var clean = (text2) => text2.replaceAll(new RegExp("\\p{Cc}", "gu"), " ");
|
|
544
|
+
function clip(text2, size = 160) {
|
|
545
|
+
const segments = [...new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(text2)];
|
|
546
|
+
return segments.length > size ? `${segments.slice(0, size).map((s) => s.segment).join("")}\u2026` : text2;
|
|
547
|
+
}
|
|
548
|
+
function flatten(value3, nested = false) {
|
|
549
|
+
if (value3 === null || value3 === void 0) return "";
|
|
550
|
+
if (Array.isArray(value3)) return value3.map((item) => flatten(item, true)).join(", ");
|
|
551
|
+
if (typeof value3 === "object") {
|
|
552
|
+
const text2 = Object.entries(value3).filter(([, item]) => !absent(item)).map(([key, item]) => `${key} ${flatten(item, true)}`).join(nested ? ", " : " \xB7 ");
|
|
553
|
+
return nested ? `(${text2})` : text2;
|
|
554
|
+
}
|
|
555
|
+
return isIsoTime(value3) ? formatTime(value3) : String(value3);
|
|
556
|
+
}
|
|
557
|
+
var scalar = (value3, path18, loose) => {
|
|
558
|
+
if (value3 !== null && typeof value3 === "object") {
|
|
559
|
+
if (!loose)
|
|
560
|
+
throw new Error(`Brief cannot print the object at ${path18}; flatten it in the view.`);
|
|
561
|
+
return flatten(value3);
|
|
562
|
+
}
|
|
563
|
+
return flatten(value3);
|
|
564
|
+
};
|
|
565
|
+
var absent = (value3, fallback) => value3 === void 0 || value3 === null || value3 === "" || value3 === false || fallback !== void 0 && value3 === fallback;
|
|
566
|
+
var EXIT_WORDS = {
|
|
567
|
+
1: "FAILED",
|
|
568
|
+
2: "NEEDS YOU",
|
|
569
|
+
3: "ISSUES",
|
|
570
|
+
4: "INCOMPLETE",
|
|
571
|
+
5: "PARTIAL",
|
|
572
|
+
130: "INTERRUPTED",
|
|
573
|
+
143: "INTERRUPTED"
|
|
574
|
+
};
|
|
575
|
+
var RECOVERY = {
|
|
576
|
+
E_ARTIFACT_NOT_FOUND: "check --artifact and --project-dir; artifacts live in <project>/.ryugi/artifacts/<type>/<id>/",
|
|
577
|
+
E_ARGUMENT_INVALID: "run the command with --help for its options",
|
|
578
|
+
E_CURSOR_EXPIRED: "run the read again without --cursor or --snapshot",
|
|
579
|
+
E_CURSOR_MISMATCH: "run the read again without --cursor or --snapshot"
|
|
580
|
+
};
|
|
581
|
+
var statusWord = (status, code) => code ? EXIT_WORDS[code] ?? "FAILED" : clean(status).replaceAll("_", " ").toUpperCase();
|
|
582
|
+
var commandName = (id2) => {
|
|
583
|
+
const words2 = id2.replaceAll(/[._]/g, " ").trim();
|
|
584
|
+
return words2 ? words2[0].toUpperCase() + words2.slice(1) : "Command";
|
|
585
|
+
};
|
|
586
|
+
function pageText(page) {
|
|
587
|
+
const offset = page.offset ?? 0;
|
|
588
|
+
if (!page.hasMore && offset === 0) return null;
|
|
589
|
+
const of = page.total === null ? "" : ` of ${page.total}`;
|
|
590
|
+
if (page.offset === void 0)
|
|
591
|
+
return `${page.returned}${of} shown${page.total === null && page.hasMore ? " \xB7 more available" : ""}`;
|
|
592
|
+
return `${page.returned ? `${offset + 1}\u2013${offset + page.returned}` : "none"}${of}`;
|
|
533
593
|
}
|
|
534
|
-
var scalar = (value3) => value3 === null ? "none" : typeof value3 === "object" ? JSON.stringify(value3) : String(value3);
|
|
535
|
-
var scopeText = (page) => `${clean(page.scope)} \xB7 ${page.returned} shown${page.total === null ? "" : ` / ${page.total} matched`}${page.hasMore ? " \xB7 more available" : ""}`;
|
|
536
594
|
var quote = (value3) => /^[\w./:@=+-]+$/.test(value3) ? value3 : `'${value3.replaceAll("'", "'\\''")}'`;
|
|
537
595
|
function actionText(action) {
|
|
538
596
|
return action.kind === "command" ? action.argv.map(quote).join(" ") : action.url;
|
|
@@ -540,38 +598,72 @@ function actionText(action) {
|
|
|
540
598
|
var effectLines = (effects) => effects.map(
|
|
541
599
|
(effect) => `Effect: ${clean(effect.operation)} ${clean(effect.target)} \xB7 ${effect.state}`
|
|
542
600
|
);
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
601
|
+
var lastSegment = (path18) => path18.split(".").filter(Boolean).at(-1) ?? path18;
|
|
602
|
+
function renderText(view, wire, options, collection, requiredFields = [], code = 0) {
|
|
603
|
+
const head = [
|
|
604
|
+
statusWord(view.status, code),
|
|
605
|
+
view.subject && clean(view.subject),
|
|
606
|
+
view.summary && clean(view.summary)
|
|
607
|
+
].filter(Boolean);
|
|
608
|
+
const lines = [head.length ? `${clean(view.heading)}: ${head.join(" \xB7 ")}` : clean(view.heading)];
|
|
547
609
|
const omissions = [...wire.omitted ?? []];
|
|
548
610
|
const selected = (key, required = false) => required || requiredFields.includes(key) || !options.fields || options.fields.includes(key);
|
|
549
|
-
const value3 = (input, path18) => {
|
|
550
|
-
const
|
|
551
|
-
const shown = options.detail ?
|
|
552
|
-
if (shown !==
|
|
611
|
+
const value3 = (input, path18, loose = false) => {
|
|
612
|
+
const text2 = clean(scalar(input, path18, loose));
|
|
613
|
+
const shown = options.detail ? text2 : clip(text2);
|
|
614
|
+
if (shown !== text2) omissions.push({ path: path18, reason: "preview" });
|
|
553
615
|
return shown;
|
|
554
616
|
};
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
617
|
+
const cell = (label, key, input, path18, positional2, fallback, loose = false) => {
|
|
618
|
+
if (absent(input, fallback)) return null;
|
|
619
|
+
const name = clean(label ?? key);
|
|
620
|
+
if (input === true) return name;
|
|
621
|
+
const text2 = value3(input, path18, loose);
|
|
622
|
+
return positional2 ? text2 : `${name} ${text2}`;
|
|
623
|
+
};
|
|
624
|
+
const facts = (items, loose = false) => {
|
|
625
|
+
for (const item of items) {
|
|
626
|
+
if (!collection && !selected(item.binding.key, item.required)) continue;
|
|
627
|
+
if (absent(item.binding.value)) continue;
|
|
628
|
+
const text2 = item.binding.value === true ? "yes" : value3(item.binding.value, `data.${item.binding.key}`, loose);
|
|
629
|
+
lines.push(`${clean(item.label)}: ${text2}`);
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
const metadata = (items, path18) => items.map(
|
|
633
|
+
(item) => cell(
|
|
634
|
+
item.label,
|
|
635
|
+
item.binding.key,
|
|
636
|
+
item.binding.value,
|
|
637
|
+
`${path18}.${item.binding.key}`,
|
|
638
|
+
item.positional
|
|
639
|
+
)
|
|
640
|
+
).filter((text2) => text2 !== null).join(" \xB7 ");
|
|
641
|
+
const title2 = (text2, summary) => {
|
|
642
|
+
if (text2) lines.push(summary ? `${clean(text2)} \xB7 ${clean(summary)}` : clean(text2));
|
|
643
|
+
};
|
|
644
|
+
const pageLine = (page) => {
|
|
645
|
+
const text2 = page && pageText(page);
|
|
646
|
+
if (text2) lines.push(text2);
|
|
561
647
|
};
|
|
562
648
|
facts(view.facts);
|
|
563
649
|
const errorActions = wire.error ? recoveryActions(wire.error) : [];
|
|
564
650
|
if (wire.error) {
|
|
565
651
|
lines.push(`${clean(wire.error.code)}: ${clean(wire.error.message)}`);
|
|
566
|
-
if (wire.error.httpStatus !== void 0
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
652
|
+
if (wire.error.httpStatus !== void 0 && wire.error.httpStatus >= 500)
|
|
653
|
+
lines.push(`HTTP: ${wire.error.httpStatus}`);
|
|
654
|
+
const hint = RECOVERY[wire.error.code];
|
|
655
|
+
if (hint) lines.push(`Next: ${hint}`);
|
|
656
|
+
const details2 = wire.error.details;
|
|
657
|
+
if (details2 && typeof details2 === "object" && !Array.isArray(details2)) {
|
|
658
|
+
for (const [key, detail] of Object.entries(details2)) {
|
|
570
659
|
if (!errorActions.some((action) => action.label === key))
|
|
571
|
-
facts([{ label: key, binding: { key, value: detail }, required: true }]);
|
|
660
|
+
facts([{ label: key, binding: { key, value: detail }, required: true }], true);
|
|
572
661
|
}
|
|
573
|
-
} else if (
|
|
574
|
-
facts(
|
|
662
|
+
} else if (details2 !== void 0)
|
|
663
|
+
facts(
|
|
664
|
+
[{ label: "Details", binding: { key: "details", value: details2 }, required: true }],
|
|
665
|
+
true
|
|
666
|
+
);
|
|
575
667
|
}
|
|
576
668
|
if (!collection && options.fields && wire.data && typeof wire.data === "object") {
|
|
577
669
|
const bound = /* @__PURE__ */ new Set([
|
|
@@ -582,7 +674,8 @@ function renderText(view, wire, options, collection, requiredFields = []) {
|
|
|
582
674
|
]);
|
|
583
675
|
const data = wire.data;
|
|
584
676
|
facts(
|
|
585
|
-
[.../* @__PURE__ */ new Set([...options.fields, ...requiredFields])].filter((key) => !bound.has(key) && Object.hasOwn(data, key)).map((key) => ({ label: key, binding: { key, value: data[key] } }))
|
|
677
|
+
[.../* @__PURE__ */ new Set([...options.fields, ...requiredFields])].filter((key) => !bound.has(key) && Object.hasOwn(data, key)).map((key) => ({ label: key, binding: { key, value: data[key] } })),
|
|
678
|
+
true
|
|
586
679
|
);
|
|
587
680
|
}
|
|
588
681
|
for (const section of view.sections) {
|
|
@@ -591,59 +684,66 @@ function renderText(view, wire, options, collection, requiredFields = []) {
|
|
|
591
684
|
continue;
|
|
592
685
|
}
|
|
593
686
|
if (!collection && !selected(section.key)) continue;
|
|
594
|
-
|
|
595
|
-
lines.push(
|
|
596
|
-
`${clean("title" in section && section.title || section.key)}: ${section.status ? `${clean(section.status)} \xB7 ` : ""}${scopeText(section.page)}`
|
|
597
|
-
);
|
|
687
|
+
const named = "title" in section && section.title ? section.title : void 0;
|
|
598
688
|
if (section.kind === "records") {
|
|
599
|
-
|
|
689
|
+
title2(named ?? (section.page ? section.key : void 0), section.summary);
|
|
600
690
|
const declared = new Set(section.columns.map((column) => column.key));
|
|
601
|
-
const extra = section.key === collection ? [.../* @__PURE__ */ new Set([...options.fields ?? [], ...requiredFields])].filter((key) => !declared.has(key)).map((key) => ({ key, label: key })) : [];
|
|
602
|
-
const
|
|
691
|
+
const extra = section.key === collection ? [.../* @__PURE__ */ new Set([...options.fields ?? [], ...options.fields ? requiredFields : []])].filter((key) => !declared.has(key)).map((key) => ({ key, label: key })) : [];
|
|
692
|
+
const loose = new Set(extra.map((column) => column.key));
|
|
693
|
+
const columns = [...section.columns, ...extra].filter(
|
|
603
694
|
(column) => section.key !== collection || selected(column.key, column.required)
|
|
604
695
|
);
|
|
605
|
-
const rows = section.rows.map(
|
|
606
|
-
(row, i) => columns2.map(
|
|
607
|
-
(column) => value3(
|
|
608
|
-
row[column.key] === void 0 ? "" : row[column.key],
|
|
609
|
-
`data.${section.key}.${i}.${column.key}`
|
|
610
|
-
)
|
|
611
|
-
)
|
|
612
|
-
);
|
|
613
696
|
if (options.format === "table") {
|
|
614
|
-
const labels =
|
|
697
|
+
const labels = columns.map((column) => column.label ?? column.key);
|
|
698
|
+
const rows2 = section.rows.map(
|
|
699
|
+
(row, i) => columns.map(
|
|
700
|
+
(column) => absent(row[column.key], column.default) ? "" : value3(
|
|
701
|
+
row[column.key],
|
|
702
|
+
`data.${section.key}.${i}.${column.key}`,
|
|
703
|
+
loose.has(column.key)
|
|
704
|
+
)
|
|
705
|
+
)
|
|
706
|
+
);
|
|
615
707
|
const widths = labels.map(
|
|
616
|
-
(label, i) => Math.max(label.length, ...
|
|
708
|
+
(label, i) => Math.max(label.length, ...rows2.map((row) => row[i]?.length ?? 0))
|
|
617
709
|
);
|
|
618
710
|
lines.push(
|
|
619
|
-
...[labels, ...
|
|
620
|
-
(row) => row.map((
|
|
711
|
+
...[labels, ...rows2].map(
|
|
712
|
+
(row) => row.map((text2, i) => text2.padEnd(widths[i] ?? text2.length)).join(" ").trimEnd()
|
|
621
713
|
)
|
|
622
714
|
);
|
|
623
715
|
} else
|
|
624
|
-
for (const row of rows)
|
|
716
|
+
for (const [i, row] of section.rows.entries())
|
|
625
717
|
lines.push(
|
|
626
|
-
` ${
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
718
|
+
` ${columns.map(
|
|
719
|
+
(column) => cell(
|
|
720
|
+
column.label,
|
|
721
|
+
column.key,
|
|
722
|
+
row[column.key],
|
|
723
|
+
`data.${section.key}.${i}.${column.key}`,
|
|
724
|
+
column.positional,
|
|
725
|
+
column.default,
|
|
726
|
+
loose.has(column.key)
|
|
727
|
+
)
|
|
728
|
+
).filter((text2) => text2 !== null).join(" \xB7 ")}`
|
|
630
729
|
);
|
|
631
|
-
if (!rows.length && !section.page) lines.push("No records.");
|
|
730
|
+
if (!section.rows.length && !named && !section.page) lines.push("No records.");
|
|
731
|
+
pageLine(section.page);
|
|
632
732
|
} else if (section.kind === "messages") {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
lines.push(` ${metadata(message.facts)}`);
|
|
733
|
+
title2(named, section.summary);
|
|
734
|
+
for (const [g, group] of section.groups.entries()) {
|
|
735
|
+
lines.push(` ${metadata(group.facts, `data.${section.key}.${g}`)}`);
|
|
736
|
+
for (const [m, message] of group.messages.entries()) {
|
|
737
|
+
lines.push(` ${metadata(message.facts, `data.${section.key}.${g}.messages.${m}`)}`);
|
|
639
738
|
lines.push(
|
|
640
739
|
...message.text.split("\n").map(
|
|
641
|
-
(
|
|
740
|
+
(line2) => ` ${line2.replaceAll(new RegExp("\\p{Cc}", "gu"), (char) => char === " " ? char : "")}`
|
|
642
741
|
)
|
|
643
742
|
);
|
|
644
743
|
}
|
|
645
744
|
}
|
|
646
|
-
if (!section.groups.length && !section.page) lines.push("No messages.");
|
|
745
|
+
if (!section.groups.length && !named && !section.page) lines.push("No messages.");
|
|
746
|
+
pageLine(section.page);
|
|
647
747
|
} else if (section.kind === "diagnostics") {
|
|
648
748
|
const limit = options.detail ? section.items.length : section.preview ?? 3;
|
|
649
749
|
for (const item of section.items.slice(0, limit))
|
|
@@ -657,34 +757,50 @@ function renderText(view, wire, options, collection, requiredFields = []) {
|
|
|
657
757
|
count: section.items.length - limit
|
|
658
758
|
});
|
|
659
759
|
} else {
|
|
660
|
-
|
|
760
|
+
title2(named && `${named}:`, section.summary);
|
|
661
761
|
lines.push(
|
|
662
762
|
...section.text.trimEnd().split("\n").map(
|
|
663
|
-
(
|
|
763
|
+
(line2) => ` ${line2.replaceAll(new RegExp("\\p{Cc}", "gu"), (char) => char === " " || char === "\n" ? char : "")}`
|
|
664
764
|
)
|
|
665
765
|
);
|
|
666
766
|
}
|
|
667
767
|
}
|
|
668
|
-
if (wire.page)
|
|
669
|
-
|
|
768
|
+
if (wire.page) pageLine(wire.page);
|
|
769
|
+
if (code || (wire.effects ?? []).some((effect) => effect.state !== "confirmed"))
|
|
770
|
+
lines.push(...effectLines(wire.effects ?? []));
|
|
670
771
|
for (const warning of wire.warnings ?? []) lines.push(`Warning: ${clean(warning.message)}`);
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
772
|
+
const actions = [...view.actions ?? wire.next ?? [], ...errorActions];
|
|
773
|
+
const used = /* @__PURE__ */ new Set();
|
|
774
|
+
const details = actions.find((action) => action.label === "Details");
|
|
775
|
+
for (const omission of omissions) {
|
|
776
|
+
if (omission.count === void 0) continue;
|
|
777
|
+
const more = `${omission.count} more ${lastSegment(omission.path)}`;
|
|
778
|
+
if (details && !used.has(details)) {
|
|
779
|
+
used.add(details);
|
|
780
|
+
lines.push(`${more} \xB7 Details: ${actionText(details)}`);
|
|
781
|
+
} else lines.push(more);
|
|
782
|
+
}
|
|
783
|
+
if (!details && !options.detail && omissions.some((item) => item.reason === "preview" && item.count === void 0))
|
|
784
|
+
lines.push("Some values are clipped; add --detail to see them in full.");
|
|
785
|
+
for (const action of actions)
|
|
786
|
+
if (!used.has(action))
|
|
787
|
+
lines.push(
|
|
788
|
+
`${clean(action.label ?? "Next")}: ${action.reason ? `${clean(action.reason)} \xB7 ` : ""}${actionText(action)}`
|
|
789
|
+
);
|
|
677
790
|
return `${lines.join("\n")}
|
|
678
791
|
`;
|
|
679
792
|
}
|
|
680
|
-
function renderFailure(wire, options) {
|
|
793
|
+
function renderFailure(wire, options, code = 1) {
|
|
681
794
|
return renderText(
|
|
682
|
-
{ heading: wire.command, status:
|
|
795
|
+
{ heading: commandName(wire.command), status: "", facts: [], sections: [] },
|
|
683
796
|
wire,
|
|
684
797
|
{
|
|
685
798
|
...options,
|
|
686
799
|
fields: void 0
|
|
687
|
-
}
|
|
800
|
+
},
|
|
801
|
+
void 0,
|
|
802
|
+
[],
|
|
803
|
+
code
|
|
688
804
|
);
|
|
689
805
|
}
|
|
690
806
|
|
|
@@ -725,8 +841,8 @@ async function runCommand(definition, input, options, writer, signal) {
|
|
|
725
841
|
return `${JSON.stringify({ schema: "ryugi.cli/v1", ...value3, seq: seq++, kind })}
|
|
726
842
|
`;
|
|
727
843
|
}
|
|
728
|
-
function enqueue(channel,
|
|
729
|
-
queue = queue.then(() => writer.write(channel,
|
|
844
|
+
function enqueue(channel, text2) {
|
|
845
|
+
queue = queue.then(() => writer.write(channel, text2)).catch((err) => {
|
|
730
846
|
queueError = err;
|
|
731
847
|
abort.abort(err);
|
|
732
848
|
});
|
|
@@ -736,14 +852,14 @@ async function runCommand(definition, input, options, writer, signal) {
|
|
|
736
852
|
if (queueError) throw queueError;
|
|
737
853
|
}
|
|
738
854
|
const maxBytes = 8 * 1024 * 1024;
|
|
739
|
-
async function write(channel,
|
|
740
|
-
if ((typeof
|
|
855
|
+
async function write(channel, text2) {
|
|
856
|
+
if ((typeof text2 === "string" ? new TextEncoder().encode(text2).byteLength : text2.byteLength) > maxBytes)
|
|
741
857
|
throw new OutputError({
|
|
742
858
|
code: "E_RESULT_TOO_LARGE",
|
|
743
859
|
message: "Result exceeds 8 MiB; read one object or save it to a file."
|
|
744
860
|
});
|
|
745
861
|
await drain();
|
|
746
|
-
await writer.write(channel,
|
|
862
|
+
await writer.write(channel, text2);
|
|
747
863
|
}
|
|
748
864
|
async function output(value3, kind = "result") {
|
|
749
865
|
const full = {
|
|
@@ -759,9 +875,9 @@ async function runCommand(definition, input, options, writer, signal) {
|
|
|
759
875
|
const key = definition.output.collection;
|
|
760
876
|
if (key && kind === "result") {
|
|
761
877
|
const record = wire.data;
|
|
762
|
-
const
|
|
763
|
-
if (Array.isArray(
|
|
764
|
-
for (const item of
|
|
878
|
+
const rows2 = record[key];
|
|
879
|
+
if (Array.isArray(rows2)) {
|
|
880
|
+
for (const item of rows2)
|
|
765
881
|
await write("stdout", eventLine("item", { collection: key, data: item }));
|
|
766
882
|
const data = { ...record };
|
|
767
883
|
delete data[key];
|
|
@@ -793,7 +909,8 @@ async function runCommand(definition, input, options, writer, signal) {
|
|
|
793
909
|
wire,
|
|
794
910
|
options,
|
|
795
911
|
definition.output.collection,
|
|
796
|
-
definition.output.requiredFields
|
|
912
|
+
definition.output.requiredFields,
|
|
913
|
+
completionState(full.completion).code
|
|
797
914
|
)
|
|
798
915
|
);
|
|
799
916
|
return completionState(full.completion).code;
|
|
@@ -877,7 +994,11 @@ async function runCommand(definition, input, options, writer, signal) {
|
|
|
877
994
|
);
|
|
878
995
|
else if (options.format === "raw" && ctx.payloads.raw !== void 0 && error.code !== "E_RESULT_TOO_LARGE" && Buffer.byteLength(ctx.payloads.raw) <= maxBytes)
|
|
879
996
|
await writer.write("stdout", ctx.payloads.raw);
|
|
880
|
-
else
|
|
997
|
+
else
|
|
998
|
+
await writer.write(
|
|
999
|
+
"stderr",
|
|
1000
|
+
renderFailure(wire, options, completionState(failure.completion).code)
|
|
1001
|
+
);
|
|
881
1002
|
if (options.verbose && err instanceof Error && err.stack)
|
|
882
1003
|
await writer.write("stderr", `${err.stack}
|
|
883
1004
|
`);
|
|
@@ -952,8 +1073,8 @@ function commandLine(pid) {
|
|
|
952
1073
|
if (direct.status === 0 && direct.stdout.trim()) return direct.stdout.trim().split(/\s+/);
|
|
953
1074
|
const full = (0, import_node_child_process.spawnSync)("ps", ["-f", "-p", String(pid)], { encoding: "utf8" });
|
|
954
1075
|
if (full.status !== 0) return null;
|
|
955
|
-
const
|
|
956
|
-
return
|
|
1076
|
+
const line2 = full.stdout.split("\n").slice(1).join(" ").trim();
|
|
1077
|
+
return line2 ? line2.split(/\s+/) : null;
|
|
957
1078
|
}
|
|
958
1079
|
var isNodeImage = (tasklistLine) => /^"node\.exe"/i.test(tasklistLine.trim());
|
|
959
1080
|
function windowsNodeAt(pid) {
|
|
@@ -963,10 +1084,10 @@ function windowsNodeAt(pid) {
|
|
|
963
1084
|
});
|
|
964
1085
|
return result2.status === 0 && isNodeImage(result2.stdout);
|
|
965
1086
|
}
|
|
966
|
-
function hasServerId(pid,
|
|
1087
|
+
function hasServerId(pid, id2) {
|
|
967
1088
|
if (!alive(pid)) return false;
|
|
968
1089
|
if (process.platform === "win32") return windowsNodeAt(pid);
|
|
969
|
-
return commandLine(pid)?.includes(`--artifacts-server-id=${
|
|
1090
|
+
return commandLine(pid)?.includes(`--artifacts-server-id=${id2}`) ?? false;
|
|
970
1091
|
}
|
|
971
1092
|
async function waitForExit(pid, ms) {
|
|
972
1093
|
for (let waited = 0; waited < ms && alive(pid); waited += 100) await sleep(100);
|
|
@@ -1046,24 +1167,263 @@ function serverClient(projectDir) {
|
|
|
1046
1167
|
};
|
|
1047
1168
|
}
|
|
1048
1169
|
|
|
1170
|
+
// src/cli/output/configuration.ts
|
|
1171
|
+
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
1172
|
+
var import_node_os3 = __toESM(require("node:os"), 1);
|
|
1173
|
+
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
1174
|
+
|
|
1175
|
+
// src/server/config.ts
|
|
1176
|
+
var import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
1177
|
+
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
1178
|
+
|
|
1179
|
+
// src/shared/cloud.ts
|
|
1180
|
+
var MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
|
|
1181
|
+
var isVisibility = (value3) => value3 === "private" || value3 === "public";
|
|
1182
|
+
|
|
1183
|
+
// src/server/state.ts
|
|
1184
|
+
var import_node_fs4 = __toESM(require("node:fs"), 1);
|
|
1185
|
+
var import_node_path3 = __toESM(require("node:path"), 1);
|
|
1186
|
+
|
|
1187
|
+
// src/shared/types.ts
|
|
1188
|
+
var ARTIFACT_TYPES = ["artboard", "document", "html", "whiteboard"];
|
|
1189
|
+
|
|
1190
|
+
// src/shared/validate.ts
|
|
1191
|
+
var BOARD_NUMBERS = ["x", "y", "w", "h"];
|
|
1192
|
+
var BOARD_REQUIRED = ["file", "page", ...BOARD_NUMBERS];
|
|
1193
|
+
var MEDIA_REQUIRED = ["src", "page", ...BOARD_NUMBERS];
|
|
1194
|
+
|
|
1195
|
+
// src/server/state.ts
|
|
1196
|
+
function writeJsonAtomic(file, value3) {
|
|
1197
|
+
import_node_fs4.default.mkdirSync(import_node_path3.default.dirname(file), { recursive: true });
|
|
1198
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
1199
|
+
import_node_fs4.default.writeFileSync(tmp, `${JSON.stringify(value3, null, 2)}
|
|
1200
|
+
`, { mode: 384 });
|
|
1201
|
+
import_node_fs4.default.renameSync(tmp, file);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// src/server/config.ts
|
|
1205
|
+
var defaults = () => ({ version: 1, artifacts: {} });
|
|
1206
|
+
function isCloudRecord(value3) {
|
|
1207
|
+
if (typeof value3 !== "object" || value3 === null) return false;
|
|
1208
|
+
const { id: id2, url, publishedAt, visibility } = value3;
|
|
1209
|
+
return typeof id2 === "string" && typeof url === "string" && (typeof publishedAt === "string" || publishedAt === null) && isVisibility(visibility);
|
|
1210
|
+
}
|
|
1211
|
+
function cloudRecord({ id: id2, url, publishedAt, visibility, fingerprint }) {
|
|
1212
|
+
return {
|
|
1213
|
+
id: id2,
|
|
1214
|
+
url,
|
|
1215
|
+
publishedAt,
|
|
1216
|
+
visibility,
|
|
1217
|
+
...typeof fingerprint === "string" ? { fingerprint } : {}
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
function normalize2(raw) {
|
|
1221
|
+
const config = defaults();
|
|
1222
|
+
if (typeof raw !== "object" || raw === null) return config;
|
|
1223
|
+
const output = raw.output;
|
|
1224
|
+
if (output && typeof output === "object" && "format" in output && ["brief", "json", "jsonl"].includes(String(output.format)))
|
|
1225
|
+
config.output = { format: output.format };
|
|
1226
|
+
const { autoPublish } = raw;
|
|
1227
|
+
if (typeof autoPublish === "boolean") config.autoPublish = autoPublish;
|
|
1228
|
+
const artifacts = raw.artifacts;
|
|
1229
|
+
if (typeof artifacts !== "object" || artifacts === null) return config;
|
|
1230
|
+
for (const [key, value3] of Object.entries(artifacts)) {
|
|
1231
|
+
if (typeof value3 !== "object" || value3 === null) continue;
|
|
1232
|
+
const { visibility, cloud, autoPublish: autoPublish2 } = value3;
|
|
1233
|
+
if (visibility !== void 0 && !isVisibility(visibility)) continue;
|
|
1234
|
+
const entry = {};
|
|
1235
|
+
if (visibility) entry.visibility = visibility;
|
|
1236
|
+
if (isCloudRecord(cloud)) entry.cloud = cloudRecord(cloud);
|
|
1237
|
+
if (autoPublish2 === false) entry.autoPublish = false;
|
|
1238
|
+
config.artifacts[key] = entry;
|
|
1239
|
+
}
|
|
1240
|
+
return config;
|
|
1241
|
+
}
|
|
1242
|
+
function readConfig(file) {
|
|
1243
|
+
let text2;
|
|
1244
|
+
try {
|
|
1245
|
+
text2 = import_node_fs5.default.readFileSync(file, "utf8");
|
|
1246
|
+
} catch {
|
|
1247
|
+
return { config: defaults() };
|
|
1248
|
+
}
|
|
1249
|
+
try {
|
|
1250
|
+
return { config: normalize2(JSON.parse(text2)) };
|
|
1251
|
+
} catch (err) {
|
|
1252
|
+
return {
|
|
1253
|
+
config: defaults(),
|
|
1254
|
+
warning: `config.json is not valid JSON: ${err.message}`
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
var IGNORED = ["config.json", "artifacts/*", "!artifacts/document/", "artifacts/document/*/.artifact-id"];
|
|
1259
|
+
function ensureGitignore(dir) {
|
|
1260
|
+
const file = import_node_path4.default.join(dir, ".gitignore");
|
|
1261
|
+
let current = "";
|
|
1262
|
+
try {
|
|
1263
|
+
current = import_node_fs5.default.readFileSync(file, "utf8");
|
|
1264
|
+
} catch {
|
|
1265
|
+
}
|
|
1266
|
+
const present = new Set(current.split(/\r?\n/).map((line2) => line2.trim()));
|
|
1267
|
+
const missing = IGNORED.filter((line2) => !present.has(line2));
|
|
1268
|
+
if (missing.length === 0) return;
|
|
1269
|
+
import_node_fs5.default.writeFileSync(file, `${current}${current === "" || current.endsWith("\n") ? "" : "\n"}${missing.join("\n")}
|
|
1270
|
+
`);
|
|
1271
|
+
}
|
|
1272
|
+
function ensureConfig(file) {
|
|
1273
|
+
import_node_fs5.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
|
|
1274
|
+
ensureGitignore(import_node_path4.default.dirname(file));
|
|
1275
|
+
if (!import_node_fs5.default.existsSync(file)) writeJsonAtomic(file, defaults());
|
|
1276
|
+
}
|
|
1277
|
+
function setProjectAutoPublish(file, value3) {
|
|
1278
|
+
const { config, warning } = readConfig(file);
|
|
1279
|
+
if (warning) throw new Error(warning);
|
|
1280
|
+
if (value3 === null) delete config.autoPublish;
|
|
1281
|
+
else config.autoPublish = value3;
|
|
1282
|
+
import_node_fs5.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
|
|
1283
|
+
writeJsonAtomic(file, config);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// src/server/credentials.ts
|
|
1287
|
+
var import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
1288
|
+
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
1289
|
+
function credentialsFile(env, platform, home) {
|
|
1290
|
+
if (platform === "win32" && env.APPDATA)
|
|
1291
|
+
return import_node_path5.default.join(env.APPDATA, "ryugi", "credentials.json");
|
|
1292
|
+
return import_node_path5.default.join(env.XDG_CONFIG_HOME || import_node_path5.default.join(home, ".config"), "ryugi", "credentials.json");
|
|
1293
|
+
}
|
|
1294
|
+
function readCredentials(file, origin) {
|
|
1295
|
+
let raw;
|
|
1296
|
+
try {
|
|
1297
|
+
raw = JSON.parse(import_node_fs6.default.readFileSync(file, "utf8"));
|
|
1298
|
+
} catch {
|
|
1299
|
+
return null;
|
|
1300
|
+
}
|
|
1301
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
1302
|
+
const { origin: savedOrigin, token, login } = raw;
|
|
1303
|
+
if (typeof savedOrigin !== "string" || typeof token !== "string" || typeof login !== "string")
|
|
1304
|
+
return null;
|
|
1305
|
+
if (savedOrigin !== origin) return null;
|
|
1306
|
+
return { origin: savedOrigin, token, login };
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
// src/server/settings.ts
|
|
1310
|
+
var import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
1311
|
+
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
1312
|
+
var settingsFileFor = (credentialsFile2) => import_node_path6.default.join(import_node_path6.default.dirname(credentialsFile2), "config.json");
|
|
1313
|
+
function readSettings(file) {
|
|
1314
|
+
try {
|
|
1315
|
+
const raw = JSON.parse(import_node_fs7.default.readFileSync(file, "utf8"));
|
|
1316
|
+
return typeof raw === "object" && raw !== null && !Array.isArray(raw) ? raw : {};
|
|
1317
|
+
} catch {
|
|
1318
|
+
return {};
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
function readGlobalAutoPublish(file) {
|
|
1322
|
+
const value3 = readSettings(file).autoPublish;
|
|
1323
|
+
return typeof value3 === "boolean" ? value3 : void 0;
|
|
1324
|
+
}
|
|
1325
|
+
function writeGlobalAutoPublish(file, value3) {
|
|
1326
|
+
import_node_fs7.default.mkdirSync(import_node_path6.default.dirname(file), { recursive: true, mode: 448 });
|
|
1327
|
+
writeJsonAtomic(file, { ...readSettings(file), autoPublish: value3 });
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
// src/cli/output/configuration.ts
|
|
1331
|
+
var PERSISTED_FORMATS = ["brief", "json", "jsonl"];
|
|
1332
|
+
function outputFiles(projectDir) {
|
|
1333
|
+
return {
|
|
1334
|
+
global: settingsFileFor(credentialsFile(process.env, process.platform, import_node_os3.default.homedir())),
|
|
1335
|
+
project: import_node_path7.default.join(import_node_path7.default.dirname(projectPaths(projectDir).root), "config.json")
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
function read(file) {
|
|
1339
|
+
try {
|
|
1340
|
+
const raw = JSON.parse(import_node_fs8.default.readFileSync(file, "utf8"));
|
|
1341
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new Error("Expected an object");
|
|
1342
|
+
return raw;
|
|
1343
|
+
} catch (error) {
|
|
1344
|
+
if (error.code === "ENOENT") return {};
|
|
1345
|
+
throw new OutputError({
|
|
1346
|
+
code: "E_CONFIG_INVALID",
|
|
1347
|
+
message: `Cannot read ${file}: ${error.message}`
|
|
1348
|
+
});
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
function outputValues(projectDir) {
|
|
1352
|
+
const files = outputFiles(projectDir);
|
|
1353
|
+
const get = (file) => {
|
|
1354
|
+
const output = read(file).output;
|
|
1355
|
+
if (output?.format !== void 0 && !PERSISTED_FORMATS.includes(output.format))
|
|
1356
|
+
throw new OutputError({
|
|
1357
|
+
code: "E_FORMAT_UNSUPPORTED",
|
|
1358
|
+
message: `Unsupported output format in ${file}: ${String(output.format)}`
|
|
1359
|
+
});
|
|
1360
|
+
return output && PERSISTED_FORMATS.includes(output.format) ? output.format : null;
|
|
1361
|
+
};
|
|
1362
|
+
const global = get(files.global), project2 = get(files.project);
|
|
1363
|
+
return {
|
|
1364
|
+
global,
|
|
1365
|
+
project: project2,
|
|
1366
|
+
effective: project2 ?? global ?? "brief",
|
|
1367
|
+
source: project2 ? "project" : global ? "global" : "default"
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
function writeOutputFormat(projectDir, isProject, value3) {
|
|
1371
|
+
if (value3 === "inherit" && !isProject || value3 !== "inherit" && !PERSISTED_FORMATS.includes(value3))
|
|
1372
|
+
throw new OutputError({
|
|
1373
|
+
code: "E_ARGUMENT_INVALID",
|
|
1374
|
+
message: "--output-format takes brief, json, jsonl, or inherit with --project."
|
|
1375
|
+
});
|
|
1376
|
+
const files = outputFiles(projectDir), file = isProject ? files.project : files.global, raw = read(file);
|
|
1377
|
+
if (value3 === "inherit") delete raw.output;
|
|
1378
|
+
else raw.output = { format: value3 };
|
|
1379
|
+
if (isProject) ensureConfig(file);
|
|
1380
|
+
else import_node_fs8.default.mkdirSync(import_node_path7.default.dirname(file), { recursive: true, mode: 448 });
|
|
1381
|
+
writeJsonAtomic(file, raw);
|
|
1382
|
+
}
|
|
1383
|
+
function configuredEnvironment(argv, specs, env = process.env) {
|
|
1384
|
+
if (env.RYUGI_ARTIFACTS_FORMAT !== void 0) return env;
|
|
1385
|
+
const values = scanOptions(argv, specs);
|
|
1386
|
+
if (["format", "json", "quiet", "source"].some((key) => values[key] !== void 0)) return env;
|
|
1387
|
+
let project2 = typeof values["project-dir"] === "string" ? values["project-dir"] : process.cwd();
|
|
1388
|
+
if (!values["project-dir"] && argv[0] && !argv[0].startsWith("-")) {
|
|
1389
|
+
try {
|
|
1390
|
+
if (import_node_fs8.default.statSync(argv[0]).isDirectory()) project2 = argv[0];
|
|
1391
|
+
} catch {
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
const config = outputValues(project2);
|
|
1395
|
+
return { ...env, RYUGI_ARTIFACTS_FORMAT: config.effective };
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1049
1398
|
// src/cli/semantic/actions.ts
|
|
1399
|
+
var words = (command) => [...command.matchAll(/"([^"]*)"|'([^']*)'|(\S+)/g)].map((m) => m[1] ?? m[2] ?? m[3]);
|
|
1400
|
+
function prefix() {
|
|
1401
|
+
const command = process.env.RYUGI_ARTIFACTS_COMMAND?.trim();
|
|
1402
|
+
return command ? words(command) : [process.execPath, process.argv[1]];
|
|
1403
|
+
}
|
|
1404
|
+
function configuredFormat(args) {
|
|
1405
|
+
if (process.env.RYUGI_ARTIFACTS_FORMAT) return process.env.RYUGI_ARTIFACTS_FORMAT;
|
|
1406
|
+
const at = args.indexOf("--project-dir");
|
|
1407
|
+
try {
|
|
1408
|
+
return outputValues(at >= 0 && args[at + 1] ? args[at + 1] : process.cwd()).effective;
|
|
1409
|
+
} catch {
|
|
1410
|
+
return "brief";
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1050
1413
|
function commandAction(args, label = "Details") {
|
|
1051
1414
|
const explicit = args.some((arg) => ["--format", "--source", "--quiet"].includes(arg));
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
argv: [process.execPath, process.argv[1], ...args, ...explicit ? [] : ["--format", "brief"]],
|
|
1055
|
-
label
|
|
1056
|
-
};
|
|
1415
|
+
const format = explicit || configuredFormat(args) === "brief" ? [] : ["--format", "brief"];
|
|
1416
|
+
return { kind: "command", argv: [...prefix(), ...args, ...format], label };
|
|
1057
1417
|
}
|
|
1058
1418
|
|
|
1059
1419
|
// src/cli/semantic/files.ts
|
|
1060
|
-
var
|
|
1061
|
-
var
|
|
1420
|
+
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
1421
|
+
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
1062
1422
|
function saveExclusive(target, value3) {
|
|
1063
|
-
const absolute =
|
|
1423
|
+
const absolute = import_node_path8.default.resolve(target);
|
|
1064
1424
|
let fd;
|
|
1065
1425
|
try {
|
|
1066
|
-
fd =
|
|
1426
|
+
fd = import_node_fs9.default.openSync(absolute, "wx", 384);
|
|
1067
1427
|
} catch (error) {
|
|
1068
1428
|
throw new OutputError({
|
|
1069
1429
|
code: error.code === "EEXIST" ? "E_FILE_EXISTS" : "E_FILE_WRITE_FAILED",
|
|
@@ -1071,33 +1431,281 @@ function saveExclusive(target, value3) {
|
|
|
1071
1431
|
});
|
|
1072
1432
|
}
|
|
1073
1433
|
try {
|
|
1074
|
-
|
|
1434
|
+
import_node_fs9.default.writeFileSync(fd, value3);
|
|
1075
1435
|
} catch (error) {
|
|
1076
|
-
|
|
1077
|
-
|
|
1436
|
+
import_node_fs9.default.closeSync(fd);
|
|
1437
|
+
import_node_fs9.default.unlinkSync(absolute);
|
|
1078
1438
|
throw new OutputError({
|
|
1079
1439
|
code: "E_FILE_WRITE_FAILED",
|
|
1080
1440
|
message: `Could not save ${absolute}: ${error.message}`
|
|
1081
1441
|
});
|
|
1082
1442
|
}
|
|
1083
|
-
|
|
1443
|
+
import_node_fs9.default.closeSync(fd);
|
|
1084
1444
|
return {
|
|
1085
1445
|
file: absolute,
|
|
1086
1446
|
bytes: typeof value3 === "string" ? Buffer.byteLength(value3) : value3.byteLength
|
|
1087
1447
|
};
|
|
1088
1448
|
}
|
|
1089
1449
|
|
|
1090
|
-
// src/cli/semantic/review.ts
|
|
1091
|
-
var
|
|
1092
|
-
var
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1450
|
+
// src/cli/semantic/review-view.ts
|
|
1451
|
+
var text = (value3) => typeof value3 === "string" ? value3 : "";
|
|
1452
|
+
var flat = (value3) => value3.replaceAll(/\s*\n\s*/g, " / ").trim();
|
|
1453
|
+
var plural = (n, word) => `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
1454
|
+
var title = (name) => name[0].toUpperCase() + name.slice(1);
|
|
1455
|
+
var counts = (summary, skip = []) => Object.entries(summary ?? {}).filter(
|
|
1456
|
+
([key, n]) => key !== "waitingOnAgent" && !skip.includes(key) && typeof n === "number" && n > 0
|
|
1457
|
+
).map(([key, n]) => `${n} ${key}`).join(", ");
|
|
1458
|
+
var bracket = (text2) => text2 ? ` (${text2})` : "";
|
|
1459
|
+
var ACTION = {
|
|
1460
|
+
asks: { word: "to apply", none: "nothing to apply", listed: ["submitted"] },
|
|
1461
|
+
groups: { word: "to act on", none: "nothing to act on", listed: [] },
|
|
1462
|
+
rounds: { word: "open or submitted", none: "nothing open", listed: ["open", "submitted"] }
|
|
1463
|
+
};
|
|
1464
|
+
function sectionSummary(section, report2, page, narrowed = false) {
|
|
1465
|
+
const total = page?.total ?? report2.items.length;
|
|
1466
|
+
const summary = report2.summary;
|
|
1467
|
+
if (narrowed) {
|
|
1468
|
+
const head2 = `${total} matched`;
|
|
1469
|
+
return { head: head2, full: `${head2}${bracket(counts(summary))}`, count: total };
|
|
1470
|
+
}
|
|
1471
|
+
if (section === "threads") {
|
|
1472
|
+
const waiting = Number(summary?.waitingOnAgent ?? 0);
|
|
1473
|
+
const head2 = total ? `${total} unread${waiting ? `, ${waiting} waiting on you` : ""}` : "nothing unread";
|
|
1474
|
+
const resolved = Number(summary?.resolved ?? 0);
|
|
1475
|
+
return {
|
|
1476
|
+
head: head2,
|
|
1477
|
+
full: `${head2}${resolved ? ` (${resolved} resolved)` : ""}`,
|
|
1478
|
+
count: total
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
const words2 = ACTION[section];
|
|
1482
|
+
const head = total ? `${total} ${words2.word}` : words2.none;
|
|
1483
|
+
const others = section === "groups" ? Object.entries(summary ?? {}).reduce(
|
|
1484
|
+
(sum, [key, n]) => key === "waitingOnAgent" || typeof n !== "number" ? sum : sum + n,
|
|
1485
|
+
0
|
|
1486
|
+
) - total : 0;
|
|
1487
|
+
const rest = section === "groups" ? others > 0 ? plural(others, "other") : "" : counts(summary, words2.listed);
|
|
1488
|
+
return { head, full: `${head}${bracket(rest)}`, count: total };
|
|
1489
|
+
}
|
|
1490
|
+
function location(anchor) {
|
|
1491
|
+
if (!anchor || typeof anchor !== "object") return "";
|
|
1492
|
+
const a = anchor;
|
|
1493
|
+
if (typeof a.blockId === "string") {
|
|
1494
|
+
const blocks = Array.isArray(a.blockIds) && a.blockIds.length > 1 ? a.blockIds : [a.blockId];
|
|
1495
|
+
return `${blocks.length > 1 ? "blocks" : "block"} ${blocks.join(", ")}${text(a.quote) ? ` "${flat(text(a.quote))}"` : ""}`;
|
|
1496
|
+
}
|
|
1497
|
+
if (Array.isArray(a.elements) && a.elements.length) return `element ${a.elements.join(", ")}`;
|
|
1498
|
+
const page = text(a.page);
|
|
1499
|
+
if (typeof a.board === "string") return `${page ? `page ${page} ` : ""}board ${a.board}`;
|
|
1500
|
+
const point = typeof a.x === "number" && typeof a.y === "number" ? ` ${Math.round(a.x)},${Math.round(a.y)}` : "";
|
|
1501
|
+
return `page ${page || "main"}${point}`;
|
|
1502
|
+
}
|
|
1503
|
+
var id = { key: "id", positional: true, required: true };
|
|
1504
|
+
var line = { key: "line", positional: true, required: true };
|
|
1505
|
+
var tail = { key: "tail", positional: true, required: true };
|
|
1506
|
+
var picked = (item) => item.choice ? ` \u2192 ${item.choice}${item.byRecommendation ? " (recommended)" : ""}` : "";
|
|
1507
|
+
function rows(section, items) {
|
|
1508
|
+
if (section === "asks")
|
|
1509
|
+
return {
|
|
1510
|
+
columns: [
|
|
1511
|
+
id,
|
|
1512
|
+
line,
|
|
1513
|
+
{ key: "note", label: "note" },
|
|
1514
|
+
{ key: "staleChoice", label: "stale choice" }
|
|
1515
|
+
],
|
|
1516
|
+
rows: items.map((item) => ({
|
|
1517
|
+
...item,
|
|
1518
|
+
line: `${text(item.state)}${item.choice ? picked(item) : text(item.text) ? ` \xB7 "${flat(text(item.text))}"` : "choice" in item || "text" in item ? " \xB7 no answer" : ""}`,
|
|
1519
|
+
note: text(item.note) && `"${flat(text(item.note))}"`
|
|
1520
|
+
}))
|
|
1521
|
+
};
|
|
1522
|
+
if (section === "threads")
|
|
1523
|
+
return {
|
|
1524
|
+
columns: [
|
|
1525
|
+
id,
|
|
1526
|
+
{ key: "status", positional: true, required: true },
|
|
1527
|
+
{ key: "waiting", positional: true },
|
|
1528
|
+
{ key: "where", positional: true },
|
|
1529
|
+
{ key: "stale", label: "stale" },
|
|
1530
|
+
{ key: "orphan", label: "orphan" },
|
|
1531
|
+
{ key: "draft", label: "draft" },
|
|
1532
|
+
{ key: "messageCount", positional: true },
|
|
1533
|
+
{ key: "preview", positional: true }
|
|
1534
|
+
],
|
|
1535
|
+
rows: items.map((item) => ({
|
|
1536
|
+
...threadFacts(item),
|
|
1537
|
+
messageCount: typeof item.messageCount === "number" && item.messageCount ? plural(item.messageCount, "message") : "",
|
|
1538
|
+
preview: text(item.preview) && `"${flat(text(item.preview))}"`
|
|
1539
|
+
}))
|
|
1540
|
+
};
|
|
1541
|
+
if (section === "groups")
|
|
1542
|
+
return {
|
|
1543
|
+
columns: [
|
|
1544
|
+
id,
|
|
1545
|
+
{ key: "kind", positional: true, required: true },
|
|
1546
|
+
line,
|
|
1547
|
+
{ key: "evidenceUpdated", label: "evidence updated" },
|
|
1548
|
+
{ key: "rejects", positional: true },
|
|
1549
|
+
{ key: "threadCount", positional: true },
|
|
1550
|
+
tail
|
|
1551
|
+
],
|
|
1552
|
+
rows: items.map((item) => ({
|
|
1553
|
+
...item,
|
|
1554
|
+
line: item.kind === "verify" ? text(item.verdict) : `${item.round ? `round ${item.round}` : ""}${item.choice ? picked(item) : " \xB7 no pick"}`.replace(
|
|
1555
|
+
/^ · /,
|
|
1556
|
+
""
|
|
1557
|
+
),
|
|
1558
|
+
rejects: typeof item.rejectThreads === "number" && item.rejectThreads ? plural(item.rejectThreads, "reject thread") : "",
|
|
1559
|
+
threadCount: typeof item.threads === "number" && item.threads ? plural(item.threads, "thread") : "",
|
|
1560
|
+
tail: text(item.title)
|
|
1561
|
+
}))
|
|
1562
|
+
};
|
|
1563
|
+
return {
|
|
1564
|
+
columns: [
|
|
1565
|
+
id,
|
|
1566
|
+
{ key: "state", positional: true, required: true },
|
|
1567
|
+
{ key: "groupList", positional: true },
|
|
1568
|
+
tail
|
|
1569
|
+
],
|
|
1570
|
+
rows: items.map((item) => ({
|
|
1571
|
+
...item,
|
|
1572
|
+
groupList: Array.isArray(item.groups) && item.groups.length ? `groups ${item.groups.join(", ")}` : "",
|
|
1573
|
+
tail: text(item.title)
|
|
1574
|
+
}))
|
|
1575
|
+
};
|
|
1576
|
+
}
|
|
1577
|
+
function threadFacts(item) {
|
|
1578
|
+
return {
|
|
1579
|
+
id: item.id,
|
|
1580
|
+
status: item.status,
|
|
1581
|
+
waiting: item.waitingOn ? `waiting on ${item.waitingOn}` : "",
|
|
1582
|
+
where: location(
|
|
1583
|
+
item.anchor && typeof item.anchor === "object" && typeof item.page === "string" ? { page: item.page, ...item.anchor } : item.anchor
|
|
1584
|
+
),
|
|
1585
|
+
stale: item.stale === true,
|
|
1586
|
+
orphan: item.orphan === true,
|
|
1587
|
+
draft: item.draft === true
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
var positional = (key, value3) => ({
|
|
1591
|
+
label: key,
|
|
1592
|
+
binding: { key, value: value3 },
|
|
1593
|
+
positional: true
|
|
1594
|
+
});
|
|
1595
|
+
function threadMessages(items, key = "items") {
|
|
1596
|
+
return {
|
|
1597
|
+
kind: "messages",
|
|
1598
|
+
key,
|
|
1599
|
+
groups: items.map((item) => {
|
|
1600
|
+
const facts = threadFacts(item);
|
|
1601
|
+
return {
|
|
1602
|
+
facts: [
|
|
1603
|
+
positional("id", facts.id),
|
|
1604
|
+
positional("status", facts.status),
|
|
1605
|
+
positional("waiting", facts.waiting),
|
|
1606
|
+
positional("where", facts.where),
|
|
1607
|
+
{ label: "stale", binding: { key: "stale", value: facts.stale } },
|
|
1608
|
+
{ label: "orphan", binding: { key: "orphan", value: facts.orphan } },
|
|
1609
|
+
{ label: "draft", binding: { key: "draft", value: facts.draft } }
|
|
1610
|
+
],
|
|
1611
|
+
messages: (Array.isArray(item.messages) ? item.messages : []).map(
|
|
1612
|
+
(message) => ({
|
|
1613
|
+
facts: [
|
|
1614
|
+
positional(
|
|
1615
|
+
"message",
|
|
1616
|
+
[
|
|
1617
|
+
message.id,
|
|
1618
|
+
`${text(message.name) || text(message.author)}${message.author === "agent" ? " (agent)" : ""}`,
|
|
1619
|
+
text(message.at) && formatTime(text(message.at)),
|
|
1620
|
+
message.deleted ? "(deleted)" : "",
|
|
1621
|
+
text(message.editedAt) && `edited ${formatTime(text(message.editedAt))}`
|
|
1622
|
+
].filter(Boolean).join(" ")
|
|
1623
|
+
)
|
|
1624
|
+
],
|
|
1625
|
+
text: typeof message.text === "string" ? message.text : ""
|
|
1626
|
+
})
|
|
1627
|
+
)
|
|
1628
|
+
};
|
|
1629
|
+
})
|
|
1630
|
+
};
|
|
1631
|
+
}
|
|
1632
|
+
function sectionView(name, report2, page, inBundle, narrowed) {
|
|
1633
|
+
const summary = sectionSummary(name, report2, page, narrowed);
|
|
1634
|
+
const base = { key: inBundle ? name : "items", title: title(name), summary: summary.full };
|
|
1635
|
+
if (name === "threads" && report2.evidence === "complete")
|
|
1636
|
+
return { ...threadMessages(report2.items), ...base, ...inBundle ? { page } : {} };
|
|
1637
|
+
return {
|
|
1638
|
+
kind: "records",
|
|
1639
|
+
...rows(name, report2.items),
|
|
1640
|
+
...base,
|
|
1641
|
+
...inBundle ? { page } : {}
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
var COLLECTIONS = ["threads", "asks", "groups", "rounds"];
|
|
1645
|
+
function summaryView(data, actions) {
|
|
1646
|
+
const summary = data.summary ?? {};
|
|
1647
|
+
const command = (name) => actions.find((action) => action.label === title(name));
|
|
1648
|
+
const listed = COLLECTIONS.filter((name) => command(name));
|
|
1649
|
+
return {
|
|
1650
|
+
heading: "Comment list",
|
|
1651
|
+
status: "",
|
|
1652
|
+
subject: data.artifact,
|
|
1653
|
+
facts: [],
|
|
1654
|
+
sections: listed.map((name) => {
|
|
1655
|
+
const value3 = summary[name];
|
|
1656
|
+
const counted = name === "threads" ? sectionSummary(
|
|
1657
|
+
"threads",
|
|
1658
|
+
{ items: [], summary: { waitingOnAgent: summary.waitingOnAgent } },
|
|
1659
|
+
{ total: Number(value3 ?? 0) }
|
|
1660
|
+
).head : counts(value3) || "none";
|
|
1661
|
+
return {
|
|
1662
|
+
kind: "records",
|
|
1663
|
+
key: name,
|
|
1664
|
+
title: title(name),
|
|
1665
|
+
summary: `${counted} \xB7 ${actionText(command(name))}`,
|
|
1666
|
+
columns: [],
|
|
1667
|
+
rows: []
|
|
1668
|
+
};
|
|
1669
|
+
}),
|
|
1670
|
+
actions: actions.filter((action) => !listed.some((name) => title(name) === action.label))
|
|
1671
|
+
};
|
|
1672
|
+
}
|
|
1673
|
+
function presentRead({ data, actions, coverage }, heading = "Comment list", narrowed = false) {
|
|
1674
|
+
if (data.section === "summary") return summaryView(data, actions);
|
|
1675
|
+
const page = coverage.page;
|
|
1676
|
+
return {
|
|
1677
|
+
heading,
|
|
1678
|
+
status: "",
|
|
1679
|
+
subject: data.artifact,
|
|
1680
|
+
summary: sectionSummary(data.section, data, page, narrowed).head,
|
|
1681
|
+
facts: [],
|
|
1682
|
+
sections: [sectionView(data.section, data, page, false, narrowed)]
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
function presentBundle({ data }, narrowed = false) {
|
|
1686
|
+
const entries = Object.entries(data.sections);
|
|
1687
|
+
const heads = entries.map(([name, entry]) => sectionSummary(name, entry, entry.page, narrowed)).filter((item) => item.count > 0).map((item) => item.head);
|
|
1688
|
+
return {
|
|
1689
|
+
heading: "Comment list",
|
|
1690
|
+
status: "",
|
|
1691
|
+
subject: data.artifact,
|
|
1692
|
+
summary: heads.join(" \xB7 ") || "nothing new",
|
|
1693
|
+
facts: [],
|
|
1694
|
+
sections: entries.map(([name, entry]) => sectionView(name, entry, entry.page, true, narrowed))
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
// src/cli/semantic/review.ts
|
|
1699
|
+
var value = (input, key) => typeof input.values[key] === "string" ? input.values[key] : void 0;
|
|
1700
|
+
var formats = ["brief", "table", "json", "jsonl", "raw"];
|
|
1701
|
+
function artifactOf(input, documentOnly = false) {
|
|
1702
|
+
const artifact = value(input, "artifact");
|
|
1703
|
+
if (!artifact || !(documentOnly ? /^document\/[a-z0-9][a-z0-9-]*$/ : /^(document|artboard|whiteboard)\/[a-z0-9][a-z0-9-]*$/).test(artifact))
|
|
1704
|
+
throw new OutputError({
|
|
1705
|
+
code: "E_ARGUMENT_INVALID",
|
|
1706
|
+
message: documentOnly ? "--artifact must be document/<id>." : "--artifact must be document/<id>, artboard/<id> or whiteboard/<id>."
|
|
1707
|
+
});
|
|
1708
|
+
return artifact;
|
|
1101
1709
|
}
|
|
1102
1710
|
function query(input) {
|
|
1103
1711
|
const limit = value(input, "limit");
|
|
@@ -1161,83 +1769,11 @@ function ack(input, artifact, endpoint) {
|
|
|
1161
1769
|
const response = await call(input, ctx, artifact, endpoint, { op: "ack", receipt });
|
|
1162
1770
|
return result({ artifact, receipt, status: response.status });
|
|
1163
1771
|
},
|
|
1164
|
-
present(
|
|
1165
|
-
return {
|
|
1166
|
-
heading: "Read acknowledgement",
|
|
1167
|
-
status: data.status,
|
|
1168
|
-
subject: data.artifact,
|
|
1169
|
-
facts: [fact("Receipt", field(data, "receipt"), true)],
|
|
1170
|
-
sections: []
|
|
1171
|
-
};
|
|
1172
|
-
}
|
|
1772
|
+
present: presentAck(endpoint === "review" ? "comment" : "changes")
|
|
1173
1773
|
},
|
|
1174
1774
|
input
|
|
1175
1775
|
);
|
|
1176
1776
|
}
|
|
1177
|
-
function columns(section, items) {
|
|
1178
|
-
const keys = section === "threads" ? [
|
|
1179
|
-
"id",
|
|
1180
|
-
"status",
|
|
1181
|
-
"waitingOn",
|
|
1182
|
-
"anchor",
|
|
1183
|
-
"preview",
|
|
1184
|
-
"messageCount",
|
|
1185
|
-
"stale",
|
|
1186
|
-
...items.some((item) => "messages" in item) ? ["messages"] : []
|
|
1187
|
-
] : section === "asks" ? ["id", "state", "choice", "text", "byRecommendation", "staleChoice", "note"] : section === "groups" ? [
|
|
1188
|
-
"id",
|
|
1189
|
-
"kind",
|
|
1190
|
-
"title",
|
|
1191
|
-
"round",
|
|
1192
|
-
"verdict",
|
|
1193
|
-
"choice",
|
|
1194
|
-
"byRecommendation",
|
|
1195
|
-
"by",
|
|
1196
|
-
"evidenceUpdated",
|
|
1197
|
-
"rejectThreads",
|
|
1198
|
-
"threads"
|
|
1199
|
-
] : ["id", "state", "title", "groups", "submitted"];
|
|
1200
|
-
return keys.map((key) => ({
|
|
1201
|
-
key,
|
|
1202
|
-
label: key,
|
|
1203
|
-
required: ["id", "status", "state", "verdict"].includes(key)
|
|
1204
|
-
}));
|
|
1205
|
-
}
|
|
1206
|
-
function presentRead({ data }) {
|
|
1207
|
-
return {
|
|
1208
|
-
heading: "Review",
|
|
1209
|
-
status: data.evidence,
|
|
1210
|
-
subject: data.artifact,
|
|
1211
|
-
facts: [
|
|
1212
|
-
fact("Section", field(data, "section"), true),
|
|
1213
|
-
...data.summary ? [fact("Summary", field(data, "summary"))] : []
|
|
1214
|
-
],
|
|
1215
|
-
sections: data.section === "summary" ? [] : data.evidence === "complete" ? [messageSection(data.items)] : [
|
|
1216
|
-
{
|
|
1217
|
-
kind: "records",
|
|
1218
|
-
key: "items",
|
|
1219
|
-
rows: data.items,
|
|
1220
|
-
columns: columns(data.section, data.items)
|
|
1221
|
-
}
|
|
1222
|
-
]
|
|
1223
|
-
};
|
|
1224
|
-
}
|
|
1225
|
-
function messageSection(items) {
|
|
1226
|
-
const metadata = (item, excluded) => Object.entries(item).filter(([key]) => key !== excluded).map(([key, value3]) => ({ label: key, binding: { key, value: value3 } }));
|
|
1227
|
-
return {
|
|
1228
|
-
kind: "messages",
|
|
1229
|
-
key: "items",
|
|
1230
|
-
groups: items.map((item) => ({
|
|
1231
|
-
facts: metadata(item, "messages"),
|
|
1232
|
-
messages: (Array.isArray(item.messages) ? item.messages : []).map(
|
|
1233
|
-
(message) => ({
|
|
1234
|
-
facts: metadata(message, "text"),
|
|
1235
|
-
text: typeof message.text === "string" ? message.text : JSON.stringify(message.text ?? null)
|
|
1236
|
-
})
|
|
1237
|
-
)
|
|
1238
|
-
}))
|
|
1239
|
-
};
|
|
1240
|
-
}
|
|
1241
1777
|
function bundledReview(input, artifact, operation) {
|
|
1242
1778
|
if (operation !== "list")
|
|
1243
1779
|
throw new OutputError({
|
|
@@ -1268,9 +1804,6 @@ function bundledReview(input, artifact, operation) {
|
|
|
1268
1804
|
output: { formats, detail: true },
|
|
1269
1805
|
async run(_input, ctx) {
|
|
1270
1806
|
const json = await call(input, ctx, artifact, "review", { op: "list", sections, ...read2 });
|
|
1271
|
-
const data = {};
|
|
1272
|
-
const actions = [];
|
|
1273
|
-
const omitted = [];
|
|
1274
1807
|
for (const name of sections) {
|
|
1275
1808
|
const raw = json.sections?.[name];
|
|
1276
1809
|
if (!raw || !Array.isArray(raw.items) || typeof raw.snapshot !== "string" || !raw.page || typeof raw.page.scope !== "string" || typeof raw.page.hasMore !== "boolean" || !Number.isInteger(raw.page.returned) || !(raw.page.total === null || Number.isInteger(raw.page.total)))
|
|
@@ -1283,41 +1816,69 @@ function bundledReview(input, artifact, operation) {
|
|
|
1283
1816
|
code: "E_PROTOCOL_MISMATCH",
|
|
1284
1817
|
message: "The server returned inconsistent combined review coverage."
|
|
1285
1818
|
});
|
|
1286
|
-
const report2 = readResult(input, artifact, name, raw, read2);
|
|
1287
|
-
const { artifact: _artifact, section: _section, ...entry } = report2.data;
|
|
1288
|
-
data[name] = { ...entry, page: raw.page };
|
|
1289
|
-
actions.push(
|
|
1290
|
-
...report2.actions.map((action) => ({
|
|
1291
|
-
...action,
|
|
1292
|
-
label: `${name} ${action.label ?? "Next"}`
|
|
1293
|
-
}))
|
|
1294
|
-
);
|
|
1295
|
-
if (entry.evidence === "preview" && name === "threads")
|
|
1296
|
-
omitted.push({ path: "data.sections.threads.items.messages", reason: "summary" });
|
|
1297
1819
|
}
|
|
1298
|
-
return
|
|
1820
|
+
return bundleResult(input, artifact, sections, json, read2);
|
|
1299
1821
|
},
|
|
1300
|
-
present(
|
|
1301
|
-
return {
|
|
1302
|
-
heading: "Review",
|
|
1303
|
-
status: read2.detail ? "complete" : "preview",
|
|
1304
|
-
subject: artifact,
|
|
1305
|
-
facts: [],
|
|
1306
|
-
sections: Object.entries(data.sections).flatMap(
|
|
1307
|
-
([name, entry]) => presentRead(result({ ...entry, artifact, section: name })).sections.map((section) => ({
|
|
1308
|
-
...section,
|
|
1309
|
-
key: name,
|
|
1310
|
-
title: name[0].toUpperCase() + name.slice(1),
|
|
1311
|
-
page: entry.page,
|
|
1312
|
-
status: entry.evidence
|
|
1313
|
-
}))
|
|
1314
|
-
)
|
|
1315
|
-
};
|
|
1316
|
-
}
|
|
1822
|
+
present: (value3) => presentBundle(value3, read2.all)
|
|
1317
1823
|
},
|
|
1318
1824
|
input
|
|
1319
1825
|
);
|
|
1320
1826
|
}
|
|
1827
|
+
var presentAck = (kind) => ({ data }) => ({
|
|
1828
|
+
heading: kind === "comment" ? "Comment ack" : "Changes ack",
|
|
1829
|
+
status: data.status,
|
|
1830
|
+
subject: data.artifact,
|
|
1831
|
+
facts: [],
|
|
1832
|
+
sections: []
|
|
1833
|
+
});
|
|
1834
|
+
function presentChanges({ data }) {
|
|
1835
|
+
const count = data.blocks.length;
|
|
1836
|
+
return {
|
|
1837
|
+
heading: "Changes",
|
|
1838
|
+
status: data.saved ? "saved" : "",
|
|
1839
|
+
subject: data.artifact,
|
|
1840
|
+
summary: data.empty ? "no human edits" : data.diff === void 0 ? `${count} block${count === 1 ? "" : "s"} changed` : "complete diff",
|
|
1841
|
+
facts: data.saved ? [fact("File", field(data, "saved"), true)] : [],
|
|
1842
|
+
sections: data.empty || data.saved ? [] : data.diff === void 0 ? [
|
|
1843
|
+
{
|
|
1844
|
+
kind: "records",
|
|
1845
|
+
key: "blocks",
|
|
1846
|
+
rows: data.blocks.map((block) => ({
|
|
1847
|
+
id: block.id,
|
|
1848
|
+
size: [
|
|
1849
|
+
block.additions && `+${block.additions}`,
|
|
1850
|
+
block.deletions && `-${block.deletions}`
|
|
1851
|
+
].filter(Boolean).join(" "),
|
|
1852
|
+
preview: block.preview && `"${block.preview.replaceAll(/\s*\n\s*/g, " / ")}"`
|
|
1853
|
+
})),
|
|
1854
|
+
columns: [
|
|
1855
|
+
{ key: "id", positional: true, required: true },
|
|
1856
|
+
{ key: "size", positional: true },
|
|
1857
|
+
{ key: "preview", positional: true }
|
|
1858
|
+
]
|
|
1859
|
+
}
|
|
1860
|
+
] : [{ kind: "diff", key: "diff", text: data.diff }]
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
function bundleResult(input, artifact, sections, json, read2) {
|
|
1864
|
+
const data = {};
|
|
1865
|
+
const actions = [];
|
|
1866
|
+
const omitted = [];
|
|
1867
|
+
for (const name of sections) {
|
|
1868
|
+
const raw = json.sections[name];
|
|
1869
|
+
const report2 = readResult(input, artifact, name, raw, read2);
|
|
1870
|
+
const { artifact: _artifact, section: _section, ...entry } = report2.data;
|
|
1871
|
+
data[name] = { ...entry, page: raw.page };
|
|
1872
|
+
actions.push(
|
|
1873
|
+
...report2.actions.map(
|
|
1874
|
+
(action) => action.label === "More" ? { ...action, label: `More (${name})` } : action
|
|
1875
|
+
)
|
|
1876
|
+
);
|
|
1877
|
+
if (entry.evidence === "preview" && name === "threads")
|
|
1878
|
+
omitted.push({ path: "data.sections.threads.items.messages", reason: "summary" });
|
|
1879
|
+
}
|
|
1880
|
+
return result({ artifact, sections: data }, void 0, { actions, coverage: { omitted } });
|
|
1881
|
+
}
|
|
1321
1882
|
function readResult(input, artifact, section, json, read2, thread) {
|
|
1322
1883
|
const page = json.page;
|
|
1323
1884
|
const data = {
|
|
@@ -1373,14 +1934,18 @@ function readResult(input, artifact, section, json, read2, thread) {
|
|
|
1373
1934
|
...read2.all ? ["--all"] : [],
|
|
1374
1935
|
...value(input, "limit") ? ["--limit", value(input, "limit")] : []
|
|
1375
1936
|
],
|
|
1376
|
-
"Review"
|
|
1937
|
+
"Review all"
|
|
1938
|
+
)
|
|
1939
|
+
);
|
|
1940
|
+
const collections = artifact.startsWith("document/") ? ["threads", "asks"] : artifact.startsWith("artboard/") ? ["threads", "groups", "rounds"] : ["threads"];
|
|
1941
|
+
actions.unshift(
|
|
1942
|
+
...collections.map(
|
|
1943
|
+
(name) => commandAction(
|
|
1944
|
+
["comment", "list", ...args, "--section", name, ...name === "asks" ? ["--detail"] : []],
|
|
1945
|
+
name[0].toUpperCase() + name.slice(1)
|
|
1946
|
+
)
|
|
1377
1947
|
)
|
|
1378
1948
|
);
|
|
1379
|
-
actions.push(commandAction(["comment", "list", ...args, "--section", "threads"], "Threads"));
|
|
1380
|
-
if (artifact.startsWith("document/"))
|
|
1381
|
-
actions.push(
|
|
1382
|
-
commandAction(["comment", "list", ...args, "--section", "asks", "--detail"], "Answers")
|
|
1383
|
-
);
|
|
1384
1949
|
} else if (section === "threads" && data.evidence === "preview" && data.items[0])
|
|
1385
1950
|
actions.push(
|
|
1386
1951
|
commandAction(
|
|
@@ -1397,6 +1962,16 @@ function readResult(input, artifact, section, json, read2, thread) {
|
|
|
1397
1962
|
"Read"
|
|
1398
1963
|
)
|
|
1399
1964
|
);
|
|
1965
|
+
if (section === "asks" && data.items.some((item) => item.state === "submitted"))
|
|
1966
|
+
actions.unshift({
|
|
1967
|
+
...commandAction(["comment", "note", ...args, "--ask", "<id>"], "Next"),
|
|
1968
|
+
reason: "apply each answer, then settle it"
|
|
1969
|
+
});
|
|
1970
|
+
if (section === "groups" && data.items.some((item) => item.kind === "choose" && item.choice || item.verdict === "reject"))
|
|
1971
|
+
actions.unshift({
|
|
1972
|
+
...commandAction(["comment", "list", ...args, "--section", "threads", "--detail"], "Next"),
|
|
1973
|
+
reason: "read the threads on these groups too, then act on each"
|
|
1974
|
+
});
|
|
1400
1975
|
return result(data, void 0, {
|
|
1401
1976
|
actions,
|
|
1402
1977
|
coverage: {
|
|
@@ -1455,7 +2030,11 @@ function reviewSemantic(input) {
|
|
|
1455
2030
|
});
|
|
1456
2031
|
return readResult(input, artifact, section, json, read2, thread);
|
|
1457
2032
|
},
|
|
1458
|
-
present: presentRead
|
|
2033
|
+
present: (report2) => presentRead(
|
|
2034
|
+
report2,
|
|
2035
|
+
operation === "read" ? "Comment read" : "Comment list",
|
|
2036
|
+
read2.all || !!value(input, "status") && !(section === "asks" && value(input, "status") === "submitted") || !!value(input, "choice-state")
|
|
2037
|
+
)
|
|
1459
2038
|
},
|
|
1460
2039
|
input
|
|
1461
2040
|
);
|
|
@@ -1534,31 +2113,7 @@ function changesSemantic(input) {
|
|
|
1534
2113
|
}
|
|
1535
2114
|
});
|
|
1536
2115
|
},
|
|
1537
|
-
present
|
|
1538
|
-
return {
|
|
1539
|
-
heading: "Changes",
|
|
1540
|
-
status: data.empty ? "unchanged" : data.saved ? "saved" : data.diff === void 0 ? "preview" : "complete",
|
|
1541
|
-
subject: data.artifact,
|
|
1542
|
-
facts: [
|
|
1543
|
-
...data.saved ? [fact("File", field(data, "saved"), true)] : [],
|
|
1544
|
-
...data.receipt ? [fact("Receipt", field(data, "receipt"), true)] : []
|
|
1545
|
-
],
|
|
1546
|
-
sections: data.diff === void 0 ? [
|
|
1547
|
-
{
|
|
1548
|
-
kind: "records",
|
|
1549
|
-
key: "blocks",
|
|
1550
|
-
rows: data.blocks.map((block) => ({ ...block })),
|
|
1551
|
-
columns: [
|
|
1552
|
-
{ key: "id", label: "ID", required: true },
|
|
1553
|
-
{ key: "kind", label: "Kind" },
|
|
1554
|
-
{ key: "additions", label: "+" },
|
|
1555
|
-
{ key: "deletions", label: "-" },
|
|
1556
|
-
{ key: "preview", label: "Preview" }
|
|
1557
|
-
]
|
|
1558
|
-
}
|
|
1559
|
-
] : [{ kind: "diff", key: "diff", title: "Complete diff", text: data.diff }]
|
|
1560
|
-
};
|
|
1561
|
-
}
|
|
2116
|
+
present: presentChanges
|
|
1562
2117
|
},
|
|
1563
2118
|
input
|
|
1564
2119
|
);
|
|
@@ -1630,15 +2185,15 @@ function analyzeCheck(artifact, evidence) {
|
|
|
1630
2185
|
}));
|
|
1631
2186
|
const pending = [...evidence.pending ?? []];
|
|
1632
2187
|
if (evidence.merging) pending.push("merging");
|
|
1633
|
-
for (const [
|
|
2188
|
+
for (const [id2, state] of Object.entries(evidence.recordings ?? {})) {
|
|
1634
2189
|
if (state.warning)
|
|
1635
2190
|
issues.push({
|
|
1636
2191
|
code: "W_RECORDING",
|
|
1637
2192
|
severity: "warning",
|
|
1638
2193
|
message: state.warning,
|
|
1639
|
-
location:
|
|
2194
|
+
location: id2
|
|
1640
2195
|
});
|
|
1641
|
-
if (state.status === "processing") pending.push(`recording:${
|
|
2196
|
+
if (state.status === "processing") pending.push(`recording:${id2}`);
|
|
1642
2197
|
}
|
|
1643
2198
|
const dynamic = Object.entries(evidence.dynamic ?? {});
|
|
1644
2199
|
const required = evidence.evidence?.required ?? (artifact.startsWith("html/") || artifact.startsWith("artboard/") || dynamic.length > 0);
|
|
@@ -1732,26 +2287,28 @@ var checkCommand = {
|
|
|
1732
2287
|
];
|
|
1733
2288
|
return value3;
|
|
1734
2289
|
},
|
|
1735
|
-
present
|
|
1736
|
-
return {
|
|
1737
|
-
heading: "Check",
|
|
1738
|
-
status: data.status,
|
|
1739
|
-
subject: data.artifact,
|
|
1740
|
-
facts: [
|
|
1741
|
-
fact("Static", field(data, "static")),
|
|
1742
|
-
fact("Browser", field(data, "runtime")),
|
|
1743
|
-
...data.pending.length ? [fact("Pending", field(data, "pending"))] : []
|
|
1744
|
-
],
|
|
1745
|
-
sections: [{ kind: "diagnostics", key: "issues", items: data.issues, preview: 3 }]
|
|
1746
|
-
};
|
|
1747
|
-
}
|
|
2290
|
+
present: presentCheck
|
|
1748
2291
|
},
|
|
1749
2292
|
input
|
|
1750
2293
|
)
|
|
1751
2294
|
};
|
|
2295
|
+
function presentCheck({ data }) {
|
|
2296
|
+
const count = data.issues.length;
|
|
2297
|
+
return {
|
|
2298
|
+
heading: "Check",
|
|
2299
|
+
status: data.status,
|
|
2300
|
+
subject: data.artifact,
|
|
2301
|
+
summary: count ? `${count} issue${count === 1 ? "" : "s"}` : "",
|
|
2302
|
+
facts: [
|
|
2303
|
+
...data.runtime === "not_run" || data.runtime === "unknown" ? [fact("Browser", { key: "runtime", value: data.runtime.replaceAll("_", " ") })] : [],
|
|
2304
|
+
...data.pending.length ? [fact("Pending", { key: "pending", value: data.pending.join(", ") })] : []
|
|
2305
|
+
],
|
|
2306
|
+
sections: [{ kind: "diagnostics", key: "issues", items: data.issues, preview: 3 }]
|
|
2307
|
+
};
|
|
2308
|
+
}
|
|
1752
2309
|
|
|
1753
2310
|
// src/cli/comment.ts
|
|
1754
|
-
var
|
|
2311
|
+
var import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
1755
2312
|
|
|
1756
2313
|
// src/cli/comment-asks.ts
|
|
1757
2314
|
function askRequest(action, options, message, optionalText) {
|
|
@@ -1770,6 +2327,20 @@ function askRequest(action, options, message, optionalText) {
|
|
|
1770
2327
|
}
|
|
1771
2328
|
|
|
1772
2329
|
// src/cli/semantic/comment.ts
|
|
2330
|
+
function presentWrite({ data }) {
|
|
2331
|
+
const target = data.threadId ? `thread ${data.threadId}` : data.ask ? `ask ${data.ask}` : data.group ? `group ${data.group}${data.board ? ` \u2192 ${data.board}` : ""}` : data.round ? `round ${data.round}` : "";
|
|
2332
|
+
return {
|
|
2333
|
+
heading: `Comment ${data.operation}`,
|
|
2334
|
+
status: data.status,
|
|
2335
|
+
subject: data.artifact,
|
|
2336
|
+
summary: `${target}${data.operation === "answer" && data.choice ? ` \u2192 ${data.choice}` : ""}`,
|
|
2337
|
+
facts: [
|
|
2338
|
+
...data.messageId ? [fact("Message", field(data, "messageId"))] : [],
|
|
2339
|
+
...data.groups?.length ? [fact("Groups", { key: "groups", value: data.groups.join(", ") })] : []
|
|
2340
|
+
],
|
|
2341
|
+
sections: []
|
|
2342
|
+
};
|
|
2343
|
+
}
|
|
1773
2344
|
function commentOptions(input) {
|
|
1774
2345
|
const options = {
|
|
1775
2346
|
action: input.positionals[0],
|
|
@@ -1870,22 +2441,7 @@ function commentSemantic(input) {
|
|
|
1870
2441
|
};
|
|
1871
2442
|
return result(data, void 0, { effects: ctx.effects.snapshot() });
|
|
1872
2443
|
},
|
|
1873
|
-
present
|
|
1874
|
-
return {
|
|
1875
|
-
heading: data.operation === "pass" || data.operation === "reject" ? "Verdict" : "Review",
|
|
1876
|
-
status: data.status,
|
|
1877
|
-
subject: data.artifact,
|
|
1878
|
-
facts: [
|
|
1879
|
-
fact("Operation", field(data, "operation"), true),
|
|
1880
|
-
fact("By", field(data, "by"), true),
|
|
1881
|
-
...data.threadId ? [fact("Thread", field(data, "threadId"), true)] : [],
|
|
1882
|
-
...data.messageId ? [fact("Message", field(data, "messageId"))] : [],
|
|
1883
|
-
...data.ask ? [fact("Question", field(data, "ask"), true)] : [],
|
|
1884
|
-
...data.group ? [fact("Group", field(data, "group"), true)] : []
|
|
1885
|
-
],
|
|
1886
|
-
sections: []
|
|
1887
|
-
};
|
|
1888
|
-
}
|
|
2444
|
+
present: presentWrite
|
|
1889
2445
|
},
|
|
1890
2446
|
input
|
|
1891
2447
|
);
|
|
@@ -1908,15 +2464,15 @@ var VERDICTS = /* @__PURE__ */ new Set(["pass", "reject"]);
|
|
|
1908
2464
|
function readStdin() {
|
|
1909
2465
|
if (process.stdin.isTTY) return "";
|
|
1910
2466
|
try {
|
|
1911
|
-
return
|
|
2467
|
+
return import_node_fs10.default.readFileSync(0, "utf8");
|
|
1912
2468
|
} catch {
|
|
1913
2469
|
return "";
|
|
1914
2470
|
}
|
|
1915
2471
|
}
|
|
1916
2472
|
function messageText(options) {
|
|
1917
|
-
const
|
|
1918
|
-
if (!
|
|
1919
|
-
return
|
|
2473
|
+
const text2 = (options.text ?? readStdin()).trim();
|
|
2474
|
+
if (!text2) throw new CliError("The message is empty: pass --text <text> or pipe it on stdin");
|
|
2475
|
+
return text2;
|
|
1920
2476
|
}
|
|
1921
2477
|
function coordinate(value3, flag) {
|
|
1922
2478
|
if (value3 === void 0) return void 0;
|
|
@@ -1937,12 +2493,12 @@ function requestOf(options, action, type) {
|
|
|
1937
2493
|
throw new CliError(
|
|
1938
2494
|
action === "pass" ? "comment pass needs --group <groupId>, or --all" : "comment reject needs --group <groupId>"
|
|
1939
2495
|
);
|
|
1940
|
-
const
|
|
2496
|
+
const text2 = action === "reject" ? messageText(options) : options.text?.trim();
|
|
1941
2497
|
return {
|
|
1942
2498
|
op: "verdict",
|
|
1943
2499
|
verdict: action,
|
|
1944
2500
|
...all ? { all: true } : { group: options.group },
|
|
1945
|
-
...
|
|
2501
|
+
...text2 ? { text: text2 } : {}
|
|
1946
2502
|
};
|
|
1947
2503
|
}
|
|
1948
2504
|
if (action === "choose") {
|
|
@@ -1987,378 +2543,151 @@ function requestOf(options, action, type) {
|
|
|
1987
2543
|
op: "add",
|
|
1988
2544
|
blockId: options.block,
|
|
1989
2545
|
...options.quote ? { quote: options.quote } : {},
|
|
1990
|
-
text: messageText(options)
|
|
1991
|
-
};
|
|
1992
|
-
}
|
|
1993
|
-
if (!options.thread) throw new CliError(`comment ${action} needs --thread <threadId>`);
|
|
1994
|
-
return action === "reply" ? { op: "reply", threadId: options.thread, text: messageText(options) } : { op: "resolve", threadId: options.thread };
|
|
1995
|
-
}
|
|
1996
|
-
function prepareComment(options) {
|
|
1997
|
-
const action = COMMENT_ACTIONS.find((name) => name === options.action);
|
|
1998
|
-
if (!action)
|
|
1999
|
-
throw new CliError(
|
|
2000
|
-
"comment needs an action: list, add, reply, resolve, choose, submit, answer, note, pass or reject"
|
|
2001
|
-
);
|
|
2002
|
-
if (!options.artifact || !ARTIFACT.test(options.artifact))
|
|
2003
|
-
throw new CliError("--artifact must be document/<id>, artboard/<id> or whiteboard/<id>");
|
|
2004
|
-
const [type, id] = options.artifact.split("/");
|
|
2005
|
-
const request = requestOf(options, action, type);
|
|
2006
|
-
return { action, type, id, request, artifact: options.artifact };
|
|
2007
|
-
}
|
|
2008
|
-
async function callComment(options, prepared, signal) {
|
|
2009
|
-
const { type, id, request } = prepared;
|
|
2010
|
-
const server = serverClient(options.projectDir);
|
|
2011
|
-
const agent = detectAgent(process.env);
|
|
2012
|
-
return server.call(
|
|
2013
|
-
"POST",
|
|
2014
|
-
`/api/agent/${type}/${id}/comments`,
|
|
2015
|
-
{
|
|
2016
|
-
...request,
|
|
2017
|
-
...agent ? { agent } : {}
|
|
2018
|
-
},
|
|
2019
|
-
signal
|
|
2020
|
-
);
|
|
2021
|
-
}
|
|
2022
|
-
var commentCommand = {
|
|
2023
|
-
semantic: commentSemantic,
|
|
2024
|
-
name: "comment",
|
|
2025
|
-
summary: "Read and answer comments on a document, artboard or whiteboard (needs a running server)",
|
|
2026
|
-
usage: [
|
|
2027
|
-
"list --artifact <document|artboard|whiteboard>/<id> --sections all|<names> [--detail] [--all]",
|
|
2028
|
-
"list --artifact <document|artboard|whiteboard>/<id> [--section threads|asks|groups|rounds] [--all]",
|
|
2029
|
-
"read --artifact <document|artboard|whiteboard>/<id> --thread <threadId> [--snapshot <token>]",
|
|
2030
|
-
"ack --artifact <document|artboard|whiteboard>/<id> --receipt <receipt>",
|
|
2031
|
-
"add --artifact document/<id> --block <blockId> [--quote <text>] [--text <text>]",
|
|
2032
|
-
"add --artifact artboard/<id> --board <boardId> [--x <px> --y <px>] [--text <text>]",
|
|
2033
|
-
"add --artifact whiteboard/<id> (--element <elementId> | --x <px> --y <px> [--page <pageId>]) [--text <text>]",
|
|
2034
|
-
"reply --artifact <document|artboard|whiteboard>/<id> --thread <threadId> [--text <text>]",
|
|
2035
|
-
"resolve --artifact <document|artboard|whiteboard>/<id> --thread <threadId>",
|
|
2036
|
-
"choose --artifact artboard/<id> --group <groupId> (--board <boardId> | --clear)",
|
|
2037
|
-
"submit --artifact artboard/<id> --round <roundId> [--withdraw]",
|
|
2038
|
-
"submit --artifact document/<id> [--withdraw]",
|
|
2039
|
-
"answer --artifact document/<id> --ask <questionId> (--choice <value> | --text <answer> | --clear)",
|
|
2040
|
-
"note --artifact document/<id> --ask <questionId> [--text <note>]",
|
|
2041
|
-
"pass --artifact artboard/<id> (--group <groupId> | --all) [--text <text>]",
|
|
2042
|
-
"reject --artifact artboard/<id> --group <groupId> [--text <text>]"
|
|
2043
|
-
],
|
|
2044
|
-
details: "list returns a summary; select threads, asks, groups or rounds to read one collection. Previews do not consume evidence. read returns a complete thread and receipt; use ack after applying that evidence. asks, groups and rounds are independent state reads without receipts. Without --text, add, reply, note and reject read the message from stdin. answer records what your human partner said in the terminal; note settles a question once its answer is applied. pass and reject record a verdict on a verify group only when your human partner asks for it; the board shows the agent recorded it.",
|
|
2045
|
-
options: {
|
|
2046
|
-
"sections": {
|
|
2047
|
-
type: "string",
|
|
2048
|
-
value: "<all|threads,asks|threads,groups,rounds>",
|
|
2049
|
-
help: "Read multiple bounded review collections in one request"
|
|
2050
|
-
},
|
|
2051
|
-
"section": {
|
|
2052
|
-
type: "string",
|
|
2053
|
-
value: "<threads|asks|groups|rounds>",
|
|
2054
|
-
help: "Semantic list: select one review collection"
|
|
2055
|
-
},
|
|
2056
|
-
"limit": {
|
|
2057
|
-
type: "string",
|
|
2058
|
-
value: "<n>",
|
|
2059
|
-
help: "Semantic reads: records per page (1\u2013100, default 10)"
|
|
2060
|
-
},
|
|
2061
|
-
"cursor": { type: "string", value: "<cursor>", help: "Continue a semantic snapshot page" },
|
|
2062
|
-
"snapshot": { type: "string", value: "<snapshot>", help: "Read an existing semantic snapshot" },
|
|
2063
|
-
"receipt": {
|
|
2064
|
-
type: "string",
|
|
2065
|
-
value: "<receipt>",
|
|
2066
|
-
help: "ack: confirm exactly the complete evidence delivered"
|
|
2067
|
-
},
|
|
2068
|
-
"status": {
|
|
2069
|
-
type: "string",
|
|
2070
|
-
value: "<status>",
|
|
2071
|
-
help: "Filter the selected semantic review collection"
|
|
2072
|
-
},
|
|
2073
|
-
"waiting-on": {
|
|
2074
|
-
type: "string",
|
|
2075
|
-
value: "<agent|human|any>",
|
|
2076
|
-
help: "Filter unread threads by who should reply"
|
|
2077
|
-
},
|
|
2078
|
-
"kind": { type: "string", value: "<verify|choose>", help: "Filter review groups by kind" },
|
|
2079
|
-
"choice-state": { type: "string", value: "<chosen|empty>", help: "Filter choice groups" },
|
|
2080
|
-
"artifact": { type: "string", value: "<type>/<id>", help: "The document or artboard" },
|
|
2081
|
-
"all": {
|
|
2082
|
-
type: "boolean",
|
|
2083
|
-
help: "list: every thread, not only what changed; pass: every verify group not yet passed"
|
|
2084
|
-
},
|
|
2085
|
-
"block": { type: "string", value: "<blockId>", help: "add: the document block to comment on" },
|
|
2086
|
-
"quote": {
|
|
2087
|
-
type: "string",
|
|
2088
|
-
value: "<text>",
|
|
2089
|
-
help: "add: the text in the block the comment is about"
|
|
2090
|
-
},
|
|
2091
|
-
"board": { type: "string", value: "<boardId>", help: "add: the artboard board to comment on" },
|
|
2092
|
-
"element": {
|
|
2093
|
-
type: "string",
|
|
2094
|
-
value: "<elementId>",
|
|
2095
|
-
help: "add: the whiteboard element to comment on"
|
|
2096
|
-
},
|
|
2097
|
-
"page": {
|
|
2098
|
-
type: "string",
|
|
2099
|
-
value: "<pageId>",
|
|
2100
|
-
help: "add: the whiteboard page --x and --y are on (default main)"
|
|
2101
|
-
},
|
|
2102
|
-
"x": { type: "string", value: "<px>", help: "add: horizontal position on the board" },
|
|
2103
|
-
"y": { type: "string", value: "<px>", help: "add: vertical position on the board" },
|
|
2104
|
-
"thread": { type: "string", value: "<threadId>", help: "reply, resolve: the thread" },
|
|
2105
|
-
"text": {
|
|
2106
|
-
type: "string",
|
|
2107
|
-
value: "<text>",
|
|
2108
|
-
help: "add, reply, note: the message; answer: a written answer; reject: the reason; pass: an optional note"
|
|
2109
|
-
},
|
|
2110
|
-
"group": {
|
|
2111
|
-
type: "string",
|
|
2112
|
-
value: "<groupId>",
|
|
2113
|
-
help: "choose: the choice group; pass, reject: the verify group"
|
|
2114
|
-
},
|
|
2115
|
-
"clear": { type: "boolean", help: "choose, answer: clear the choice or answer" },
|
|
2116
|
-
"ask": { type: "string", value: "<questionId>", help: "answer, note: the question id" },
|
|
2117
|
-
"choice": { type: "string", value: "<value>", help: "answer: the option value" },
|
|
2118
|
-
"round": { type: "string", value: "<roundId>", help: "submit: the round" },
|
|
2119
|
-
"withdraw": { type: "boolean", help: "submit: withdraw the submission" }
|
|
2120
|
-
},
|
|
2121
|
-
positionals: 1
|
|
2122
|
-
};
|
|
2123
|
-
|
|
2124
|
-
// src/cli/config.ts
|
|
2125
|
-
var import_node_os4 = __toESM(require("node:os"), 1);
|
|
2126
|
-
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
2127
|
-
|
|
2128
|
-
// src/server/config.ts
|
|
2129
|
-
var import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
2130
|
-
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
2131
|
-
|
|
2132
|
-
// src/shared/cloud.ts
|
|
2133
|
-
var MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
|
|
2134
|
-
var isVisibility = (value3) => value3 === "private" || value3 === "public";
|
|
2135
|
-
|
|
2136
|
-
// src/server/state.ts
|
|
2137
|
-
var import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
2138
|
-
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
2139
|
-
|
|
2140
|
-
// src/shared/types.ts
|
|
2141
|
-
var ARTIFACT_TYPES = ["artboard", "document", "html", "whiteboard"];
|
|
2142
|
-
|
|
2143
|
-
// src/shared/validate.ts
|
|
2144
|
-
var BOARD_NUMBERS = ["x", "y", "w", "h"];
|
|
2145
|
-
var BOARD_REQUIRED = ["file", "page", ...BOARD_NUMBERS];
|
|
2146
|
-
var MEDIA_REQUIRED = ["src", "page", ...BOARD_NUMBERS];
|
|
2147
|
-
|
|
2148
|
-
// src/server/state.ts
|
|
2149
|
-
function writeJsonAtomic(file, value3) {
|
|
2150
|
-
import_node_fs6.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
|
|
2151
|
-
const tmp = `${file}.${process.pid}.tmp`;
|
|
2152
|
-
import_node_fs6.default.writeFileSync(tmp, `${JSON.stringify(value3, null, 2)}
|
|
2153
|
-
`, { mode: 384 });
|
|
2154
|
-
import_node_fs6.default.renameSync(tmp, file);
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
|
-
// src/server/config.ts
|
|
2158
|
-
var defaults = () => ({ version: 1, artifacts: {} });
|
|
2159
|
-
function isCloudRecord(value3) {
|
|
2160
|
-
if (typeof value3 !== "object" || value3 === null) return false;
|
|
2161
|
-
const { id, url, publishedAt, visibility } = value3;
|
|
2162
|
-
return typeof id === "string" && typeof url === "string" && (typeof publishedAt === "string" || publishedAt === null) && isVisibility(visibility);
|
|
2163
|
-
}
|
|
2164
|
-
function cloudRecord({ id, url, publishedAt, visibility, fingerprint }) {
|
|
2165
|
-
return {
|
|
2166
|
-
id,
|
|
2167
|
-
url,
|
|
2168
|
-
publishedAt,
|
|
2169
|
-
visibility,
|
|
2170
|
-
...typeof fingerprint === "string" ? { fingerprint } : {}
|
|
2171
|
-
};
|
|
2172
|
-
}
|
|
2173
|
-
function normalize2(raw) {
|
|
2174
|
-
const config = defaults();
|
|
2175
|
-
if (typeof raw !== "object" || raw === null) return config;
|
|
2176
|
-
const output = raw.output;
|
|
2177
|
-
if (output && typeof output === "object" && "format" in output && ["brief", "json", "jsonl"].includes(String(output.format)))
|
|
2178
|
-
config.output = { format: output.format };
|
|
2179
|
-
const { autoPublish } = raw;
|
|
2180
|
-
if (typeof autoPublish === "boolean") config.autoPublish = autoPublish;
|
|
2181
|
-
const artifacts = raw.artifacts;
|
|
2182
|
-
if (typeof artifacts !== "object" || artifacts === null) return config;
|
|
2183
|
-
for (const [key, value3] of Object.entries(artifacts)) {
|
|
2184
|
-
if (typeof value3 !== "object" || value3 === null) continue;
|
|
2185
|
-
const { visibility, cloud, autoPublish: autoPublish2 } = value3;
|
|
2186
|
-
if (visibility !== void 0 && !isVisibility(visibility)) continue;
|
|
2187
|
-
const entry = {};
|
|
2188
|
-
if (visibility) entry.visibility = visibility;
|
|
2189
|
-
if (isCloudRecord(cloud)) entry.cloud = cloudRecord(cloud);
|
|
2190
|
-
if (autoPublish2 === false) entry.autoPublish = false;
|
|
2191
|
-
config.artifacts[key] = entry;
|
|
2192
|
-
}
|
|
2193
|
-
return config;
|
|
2194
|
-
}
|
|
2195
|
-
function readConfig(file) {
|
|
2196
|
-
let text;
|
|
2197
|
-
try {
|
|
2198
|
-
text = import_node_fs7.default.readFileSync(file, "utf8");
|
|
2199
|
-
} catch {
|
|
2200
|
-
return { config: defaults() };
|
|
2201
|
-
}
|
|
2202
|
-
try {
|
|
2203
|
-
return { config: normalize2(JSON.parse(text)) };
|
|
2204
|
-
} catch (err) {
|
|
2205
|
-
return {
|
|
2206
|
-
config: defaults(),
|
|
2207
|
-
warning: `config.json is not valid JSON: ${err.message}`
|
|
2208
|
-
};
|
|
2209
|
-
}
|
|
2210
|
-
}
|
|
2211
|
-
var IGNORED = ["config.json", "artifacts/*", "!artifacts/document/", "artifacts/document/*/.artifact-id"];
|
|
2212
|
-
function ensureGitignore(dir) {
|
|
2213
|
-
const file = import_node_path5.default.join(dir, ".gitignore");
|
|
2214
|
-
let current = "";
|
|
2215
|
-
try {
|
|
2216
|
-
current = import_node_fs7.default.readFileSync(file, "utf8");
|
|
2217
|
-
} catch {
|
|
2218
|
-
}
|
|
2219
|
-
const present2 = new Set(current.split(/\r?\n/).map((line) => line.trim()));
|
|
2220
|
-
const missing = IGNORED.filter((line) => !present2.has(line));
|
|
2221
|
-
if (missing.length === 0) return;
|
|
2222
|
-
import_node_fs7.default.writeFileSync(file, `${current}${current === "" || current.endsWith("\n") ? "" : "\n"}${missing.join("\n")}
|
|
2223
|
-
`);
|
|
2224
|
-
}
|
|
2225
|
-
function ensureConfig(file) {
|
|
2226
|
-
import_node_fs7.default.mkdirSync(import_node_path5.default.dirname(file), { recursive: true });
|
|
2227
|
-
ensureGitignore(import_node_path5.default.dirname(file));
|
|
2228
|
-
if (!import_node_fs7.default.existsSync(file)) writeJsonAtomic(file, defaults());
|
|
2229
|
-
}
|
|
2230
|
-
function setProjectAutoPublish(file, value3) {
|
|
2231
|
-
const { config, warning } = readConfig(file);
|
|
2232
|
-
if (warning) throw new Error(warning);
|
|
2233
|
-
if (value3 === null) delete config.autoPublish;
|
|
2234
|
-
else config.autoPublish = value3;
|
|
2235
|
-
import_node_fs7.default.mkdirSync(import_node_path5.default.dirname(file), { recursive: true });
|
|
2236
|
-
writeJsonAtomic(file, config);
|
|
2237
|
-
}
|
|
2238
|
-
|
|
2239
|
-
// src/server/credentials.ts
|
|
2240
|
-
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
2241
|
-
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
2242
|
-
function credentialsFile(env, platform, home) {
|
|
2243
|
-
if (platform === "win32" && env.APPDATA)
|
|
2244
|
-
return import_node_path6.default.join(env.APPDATA, "ryugi", "credentials.json");
|
|
2245
|
-
return import_node_path6.default.join(env.XDG_CONFIG_HOME || import_node_path6.default.join(home, ".config"), "ryugi", "credentials.json");
|
|
2246
|
-
}
|
|
2247
|
-
function readCredentials(file, origin) {
|
|
2248
|
-
let raw;
|
|
2249
|
-
try {
|
|
2250
|
-
raw = JSON.parse(import_node_fs8.default.readFileSync(file, "utf8"));
|
|
2251
|
-
} catch {
|
|
2252
|
-
return null;
|
|
2253
|
-
}
|
|
2254
|
-
if (typeof raw !== "object" || raw === null) return null;
|
|
2255
|
-
const { origin: savedOrigin, token, login } = raw;
|
|
2256
|
-
if (typeof savedOrigin !== "string" || typeof token !== "string" || typeof login !== "string")
|
|
2257
|
-
return null;
|
|
2258
|
-
if (savedOrigin !== origin) return null;
|
|
2259
|
-
return { origin: savedOrigin, token, login };
|
|
2260
|
-
}
|
|
2261
|
-
|
|
2262
|
-
// src/server/settings.ts
|
|
2263
|
-
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
2264
|
-
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
2265
|
-
var settingsFileFor = (credentialsFile2) => import_node_path7.default.join(import_node_path7.default.dirname(credentialsFile2), "config.json");
|
|
2266
|
-
function readSettings(file) {
|
|
2267
|
-
try {
|
|
2268
|
-
const raw = JSON.parse(import_node_fs9.default.readFileSync(file, "utf8"));
|
|
2269
|
-
return typeof raw === "object" && raw !== null && !Array.isArray(raw) ? raw : {};
|
|
2270
|
-
} catch {
|
|
2271
|
-
return {};
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
function readGlobalAutoPublish(file) {
|
|
2275
|
-
const value3 = readSettings(file).autoPublish;
|
|
2276
|
-
return typeof value3 === "boolean" ? value3 : void 0;
|
|
2277
|
-
}
|
|
2278
|
-
function writeGlobalAutoPublish(file, value3) {
|
|
2279
|
-
import_node_fs9.default.mkdirSync(import_node_path7.default.dirname(file), { recursive: true, mode: 448 });
|
|
2280
|
-
writeJsonAtomic(file, { ...readSettings(file), autoPublish: value3 });
|
|
2281
|
-
}
|
|
2282
|
-
|
|
2283
|
-
// src/cli/output/configuration.ts
|
|
2284
|
-
var import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
2285
|
-
var import_node_os3 = __toESM(require("node:os"), 1);
|
|
2286
|
-
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
2287
|
-
var PERSISTED_FORMATS = ["brief", "json", "jsonl"];
|
|
2288
|
-
function outputFiles(projectDir) {
|
|
2289
|
-
return {
|
|
2290
|
-
global: settingsFileFor(credentialsFile(process.env, process.platform, import_node_os3.default.homedir())),
|
|
2291
|
-
project: import_node_path8.default.join(import_node_path8.default.dirname(projectPaths(projectDir).root), "config.json")
|
|
2292
|
-
};
|
|
2293
|
-
}
|
|
2294
|
-
function read(file) {
|
|
2295
|
-
try {
|
|
2296
|
-
const raw = JSON.parse(import_node_fs10.default.readFileSync(file, "utf8"));
|
|
2297
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new Error("Expected an object");
|
|
2298
|
-
return raw;
|
|
2299
|
-
} catch (error) {
|
|
2300
|
-
if (error.code === "ENOENT") return {};
|
|
2301
|
-
throw new OutputError({
|
|
2302
|
-
code: "E_CONFIG_INVALID",
|
|
2303
|
-
message: `Cannot read ${file}: ${error.message}`
|
|
2304
|
-
});
|
|
2305
|
-
}
|
|
2306
|
-
}
|
|
2307
|
-
function outputValues(projectDir) {
|
|
2308
|
-
const files = outputFiles(projectDir);
|
|
2309
|
-
const get = (file) => {
|
|
2310
|
-
const output = read(file).output;
|
|
2311
|
-
if (output?.format !== void 0 && !PERSISTED_FORMATS.includes(output.format))
|
|
2312
|
-
throw new OutputError({
|
|
2313
|
-
code: "E_FORMAT_UNSUPPORTED",
|
|
2314
|
-
message: `Unsupported output format in ${file}: ${String(output.format)}`
|
|
2315
|
-
});
|
|
2316
|
-
return output && PERSISTED_FORMATS.includes(output.format) ? output.format : null;
|
|
2317
|
-
};
|
|
2318
|
-
const global = get(files.global), project2 = get(files.project);
|
|
2319
|
-
return {
|
|
2320
|
-
global,
|
|
2321
|
-
project: project2,
|
|
2322
|
-
effective: project2 ?? global ?? "brief",
|
|
2323
|
-
source: project2 ? "project" : global ? "global" : "default"
|
|
2324
|
-
};
|
|
2546
|
+
text: messageText(options)
|
|
2547
|
+
};
|
|
2548
|
+
}
|
|
2549
|
+
if (!options.thread) throw new CliError(`comment ${action} needs --thread <threadId>`);
|
|
2550
|
+
return action === "reply" ? { op: "reply", threadId: options.thread, text: messageText(options) } : { op: "resolve", threadId: options.thread };
|
|
2325
2551
|
}
|
|
2326
|
-
function
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
writeJsonAtomic(file, raw);
|
|
2552
|
+
function prepareComment(options) {
|
|
2553
|
+
const action = COMMENT_ACTIONS.find((name) => name === options.action);
|
|
2554
|
+
if (!action)
|
|
2555
|
+
throw new CliError(
|
|
2556
|
+
"comment needs an action: list, add, reply, resolve, choose, submit, answer, note, pass or reject"
|
|
2557
|
+
);
|
|
2558
|
+
if (!options.artifact || !ARTIFACT.test(options.artifact))
|
|
2559
|
+
throw new CliError("--artifact must be document/<id>, artboard/<id> or whiteboard/<id>");
|
|
2560
|
+
const [type, id2] = options.artifact.split("/");
|
|
2561
|
+
const request = requestOf(options, action, type);
|
|
2562
|
+
return { action, type, id: id2, request, artifact: options.artifact };
|
|
2338
2563
|
}
|
|
2339
|
-
function
|
|
2340
|
-
|
|
2341
|
-
const
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2564
|
+
async function callComment(options, prepared, signal) {
|
|
2565
|
+
const { type, id: id2, request } = prepared;
|
|
2566
|
+
const server = serverClient(options.projectDir);
|
|
2567
|
+
const agent = detectAgent(process.env);
|
|
2568
|
+
return server.call(
|
|
2569
|
+
"POST",
|
|
2570
|
+
`/api/agent/${type}/${id2}/comments`,
|
|
2571
|
+
{
|
|
2572
|
+
...request,
|
|
2573
|
+
...agent ? { agent } : {}
|
|
2574
|
+
},
|
|
2575
|
+
signal
|
|
2576
|
+
);
|
|
2352
2577
|
}
|
|
2578
|
+
var commentCommand = {
|
|
2579
|
+
semantic: commentSemantic,
|
|
2580
|
+
name: "comment",
|
|
2581
|
+
summary: "Read and answer comments on a document, artboard or whiteboard (needs a running server)",
|
|
2582
|
+
usage: [
|
|
2583
|
+
"list --artifact <document|artboard|whiteboard>/<id> --sections all|<names> [--detail] [--all]",
|
|
2584
|
+
"list --artifact <document|artboard|whiteboard>/<id> [--section threads|asks|groups|rounds] [--all]",
|
|
2585
|
+
"read --artifact <document|artboard|whiteboard>/<id> --thread <threadId> [--snapshot <token>]",
|
|
2586
|
+
"ack --artifact <document|artboard|whiteboard>/<id> --receipt <receipt>",
|
|
2587
|
+
"add --artifact document/<id> --block <blockId> [--quote <text>] [--text <text>]",
|
|
2588
|
+
"add --artifact artboard/<id> --board <boardId> [--x <px> --y <px>] [--text <text>]",
|
|
2589
|
+
"add --artifact whiteboard/<id> (--element <elementId> | --x <px> --y <px> [--page <pageId>]) [--text <text>]",
|
|
2590
|
+
"reply --artifact <document|artboard|whiteboard>/<id> --thread <threadId> [--text <text>]",
|
|
2591
|
+
"resolve --artifact <document|artboard|whiteboard>/<id> --thread <threadId>",
|
|
2592
|
+
"choose --artifact artboard/<id> --group <groupId> (--board <boardId> | --clear)",
|
|
2593
|
+
"submit --artifact artboard/<id> --round <roundId> [--withdraw]",
|
|
2594
|
+
"submit --artifact document/<id> [--withdraw]",
|
|
2595
|
+
"answer --artifact document/<id> --ask <questionId> (--choice <value> | --text <answer> | --clear)",
|
|
2596
|
+
"note --artifact document/<id> --ask <questionId> [--text <note>]",
|
|
2597
|
+
"pass --artifact artboard/<id> (--group <groupId> | --all) [--text <text>]",
|
|
2598
|
+
"reject --artifact artboard/<id> --group <groupId> [--text <text>]"
|
|
2599
|
+
],
|
|
2600
|
+
details: "list returns a summary; select threads, asks, groups or rounds to read one collection. Previews do not consume evidence. read returns a complete thread and receipt; use ack after applying that evidence. asks, groups and rounds are independent state reads without receipts. Without --text, add, reply, note and reject read the message from stdin. answer records what your human partner said in the terminal; note settles a question once its answer is applied. pass and reject record a verdict on a verify group only when your human partner asks for it; the board shows the agent recorded it.",
|
|
2601
|
+
options: {
|
|
2602
|
+
"sections": {
|
|
2603
|
+
type: "string",
|
|
2604
|
+
value: "<all|threads,asks|threads,groups,rounds>",
|
|
2605
|
+
help: "Read multiple bounded review collections in one request"
|
|
2606
|
+
},
|
|
2607
|
+
"section": {
|
|
2608
|
+
type: "string",
|
|
2609
|
+
value: "<threads|asks|groups|rounds>",
|
|
2610
|
+
help: "Semantic list: select one review collection"
|
|
2611
|
+
},
|
|
2612
|
+
"limit": {
|
|
2613
|
+
type: "string",
|
|
2614
|
+
value: "<n>",
|
|
2615
|
+
help: "Semantic reads: records per page (1\u2013100, default 10)"
|
|
2616
|
+
},
|
|
2617
|
+
"cursor": { type: "string", value: "<cursor>", help: "Continue a semantic snapshot page" },
|
|
2618
|
+
"snapshot": { type: "string", value: "<snapshot>", help: "Read an existing semantic snapshot" },
|
|
2619
|
+
"receipt": {
|
|
2620
|
+
type: "string",
|
|
2621
|
+
value: "<receipt>",
|
|
2622
|
+
help: "ack: confirm exactly the complete evidence delivered"
|
|
2623
|
+
},
|
|
2624
|
+
"status": {
|
|
2625
|
+
type: "string",
|
|
2626
|
+
value: "<status>",
|
|
2627
|
+
help: "Filter the selected semantic review collection"
|
|
2628
|
+
},
|
|
2629
|
+
"waiting-on": {
|
|
2630
|
+
type: "string",
|
|
2631
|
+
value: "<agent|human|any>",
|
|
2632
|
+
help: "Filter unread threads by who should reply"
|
|
2633
|
+
},
|
|
2634
|
+
"kind": { type: "string", value: "<verify|choose>", help: "Filter review groups by kind" },
|
|
2635
|
+
"choice-state": { type: "string", value: "<chosen|empty>", help: "Filter choice groups" },
|
|
2636
|
+
"artifact": { type: "string", value: "<type>/<id>", help: "The document or artboard" },
|
|
2637
|
+
"all": {
|
|
2638
|
+
type: "boolean",
|
|
2639
|
+
help: "list: every thread, not only what changed; pass: every verify group not yet passed"
|
|
2640
|
+
},
|
|
2641
|
+
"block": { type: "string", value: "<blockId>", help: "add: the document block to comment on" },
|
|
2642
|
+
"quote": {
|
|
2643
|
+
type: "string",
|
|
2644
|
+
value: "<text>",
|
|
2645
|
+
help: "add: the text in the block the comment is about"
|
|
2646
|
+
},
|
|
2647
|
+
"board": { type: "string", value: "<boardId>", help: "add: the artboard board to comment on" },
|
|
2648
|
+
"element": {
|
|
2649
|
+
type: "string",
|
|
2650
|
+
value: "<elementId>",
|
|
2651
|
+
help: "add: the whiteboard element to comment on"
|
|
2652
|
+
},
|
|
2653
|
+
"page": {
|
|
2654
|
+
type: "string",
|
|
2655
|
+
value: "<pageId>",
|
|
2656
|
+
help: "add: the whiteboard page --x and --y are on (default main)"
|
|
2657
|
+
},
|
|
2658
|
+
"x": { type: "string", value: "<px>", help: "add: horizontal position on the board" },
|
|
2659
|
+
"y": { type: "string", value: "<px>", help: "add: vertical position on the board" },
|
|
2660
|
+
"thread": { type: "string", value: "<threadId>", help: "reply, resolve: the thread" },
|
|
2661
|
+
"text": {
|
|
2662
|
+
type: "string",
|
|
2663
|
+
value: "<text>",
|
|
2664
|
+
help: "add, reply, note: the message; answer: a written answer; reject: the reason; pass: an optional note"
|
|
2665
|
+
},
|
|
2666
|
+
"group": {
|
|
2667
|
+
type: "string",
|
|
2668
|
+
value: "<groupId>",
|
|
2669
|
+
help: "choose: the choice group; pass, reject: the verify group"
|
|
2670
|
+
},
|
|
2671
|
+
"clear": { type: "boolean", help: "choose, answer: clear the choice or answer" },
|
|
2672
|
+
"ask": { type: "string", value: "<questionId>", help: "answer, note: the question id" },
|
|
2673
|
+
"choice": { type: "string", value: "<value>", help: "answer: the option value" },
|
|
2674
|
+
"round": { type: "string", value: "<roundId>", help: "submit: the round" },
|
|
2675
|
+
"withdraw": { type: "boolean", help: "submit: withdraw the submission" }
|
|
2676
|
+
},
|
|
2677
|
+
positionals: 1
|
|
2678
|
+
};
|
|
2353
2679
|
|
|
2354
2680
|
// src/cli/config.ts
|
|
2681
|
+
var import_node_os4 = __toESM(require("node:os"), 1);
|
|
2682
|
+
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
2355
2683
|
var VALUES = { on: true, off: false, inherit: null };
|
|
2356
2684
|
function configure(options) {
|
|
2357
2685
|
const globalFile = settingsFileFor(credentialsFile(process.env, process.platform, import_node_os4.default.homedir()));
|
|
2358
2686
|
const projectFile = import_node_path9.default.join(import_node_path9.default.dirname(projectPaths(options.projectDir).root), "config.json");
|
|
2359
2687
|
if (options.autoPublish !== void 0) {
|
|
2360
2688
|
const value3 = VALUES[options.autoPublish];
|
|
2361
|
-
if (value3 === void 0)
|
|
2689
|
+
if (value3 === void 0)
|
|
2690
|
+
throw new CliError("--auto-publish takes on, off, or (with --project) inherit");
|
|
2362
2691
|
if (options.project) {
|
|
2363
2692
|
ensureConfig(projectFile);
|
|
2364
2693
|
setProjectAutoPublish(projectFile, value3);
|
|
@@ -2386,7 +2715,7 @@ var configCommand = {
|
|
|
2386
2715
|
value: "on|off|inherit",
|
|
2387
2716
|
help: "Turn auto-publish on or off; inherit (with --project) drops the override"
|
|
2388
2717
|
},
|
|
2389
|
-
project: { type: "boolean", help: "Set it for this project only instead of every project" }
|
|
2718
|
+
"project": { type: "boolean", help: "Set it for this project only instead of every project" }
|
|
2390
2719
|
},
|
|
2391
2720
|
semantic: (input) => bindCommand(
|
|
2392
2721
|
{
|
|
@@ -2400,7 +2729,11 @@ var configCommand = {
|
|
|
2400
2729
|
if (input.values["auto-publish"] !== void 0 && input.values["output-format"] !== void 0)
|
|
2401
2730
|
throw new CliError("Choose auto-publish or output-format.");
|
|
2402
2731
|
if (typeof input.values["output-format"] === "string")
|
|
2403
|
-
writeOutputFormat(
|
|
2732
|
+
writeOutputFormat(
|
|
2733
|
+
input.projectDir,
|
|
2734
|
+
!!input.values.project,
|
|
2735
|
+
input.values["output-format"]
|
|
2736
|
+
);
|
|
2404
2737
|
const values = configure({
|
|
2405
2738
|
projectDir: input.projectDir,
|
|
2406
2739
|
autoPublish: input.values["auto-publish"],
|
|
@@ -2414,24 +2747,29 @@ var configCommand = {
|
|
|
2414
2747
|
applies: "supported_turn_end_hook"
|
|
2415
2748
|
});
|
|
2416
2749
|
},
|
|
2417
|
-
present
|
|
2418
|
-
return {
|
|
2419
|
-
heading: input.values["output-format"] !== void 0 ? "Output" : "Auto-publish",
|
|
2420
|
-
status: data.effective === null ? "undecided" : data.effective ? "on" : "off",
|
|
2421
|
-
facts: [
|
|
2422
|
-
fact("Output", field(data, "output"), true),
|
|
2423
|
-
fact("Source", field(data, "source"), true),
|
|
2424
|
-
fact("Global", field(data, "global")),
|
|
2425
|
-
fact("Project", field(data, "project")),
|
|
2426
|
-
fact("Applies", field(data, "applies"))
|
|
2427
|
-
],
|
|
2428
|
-
sections: []
|
|
2429
|
-
};
|
|
2430
|
-
}
|
|
2750
|
+
present: presentConfig
|
|
2431
2751
|
},
|
|
2432
2752
|
input
|
|
2433
2753
|
)
|
|
2434
2754
|
};
|
|
2755
|
+
function presentConfig({ data }) {
|
|
2756
|
+
const on = data.effective === null ? "undecided" : data.effective ? "on" : "off";
|
|
2757
|
+
return {
|
|
2758
|
+
heading: "Config",
|
|
2759
|
+
status: "",
|
|
2760
|
+
facts: [
|
|
2761
|
+
fact("Auto-publish", {
|
|
2762
|
+
key: "autoPublish",
|
|
2763
|
+
value: data.source === "undecided" ? on : `${on} (${data.source})`
|
|
2764
|
+
}),
|
|
2765
|
+
fact("Output format", {
|
|
2766
|
+
key: "output",
|
|
2767
|
+
value: `${data.output.effective} (${data.output.source})`
|
|
2768
|
+
})
|
|
2769
|
+
],
|
|
2770
|
+
sections: []
|
|
2771
|
+
};
|
|
2772
|
+
}
|
|
2435
2773
|
|
|
2436
2774
|
// src/cli/semantic/get.ts
|
|
2437
2775
|
var import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
@@ -2458,6 +2796,39 @@ function stripRuntime(html) {
|
|
|
2458
2796
|
}
|
|
2459
2797
|
|
|
2460
2798
|
// src/cli/semantic/get.ts
|
|
2799
|
+
function presentGet({ data }) {
|
|
2800
|
+
return {
|
|
2801
|
+
heading: "Cloud artifact",
|
|
2802
|
+
status: data.status === "downloaded" || data.status === "partial" ? data.status : "",
|
|
2803
|
+
subject: data.id,
|
|
2804
|
+
summary: [data.type, `v${data.version}`, data.visibility].join(" \xB7 "),
|
|
2805
|
+
facts: [
|
|
2806
|
+
fact("Title", field(data, "title")),
|
|
2807
|
+
...data.dir ? [fact("Downloaded", field(data, "dir"), true)] : data.files ? [fact("Files available", { key: "files", value: data.files.join(", ") })] : []
|
|
2808
|
+
],
|
|
2809
|
+
sections: [
|
|
2810
|
+
...data.outline ? [
|
|
2811
|
+
{
|
|
2812
|
+
kind: "records",
|
|
2813
|
+
key: "outline",
|
|
2814
|
+
rows: data.outline,
|
|
2815
|
+
columns: [
|
|
2816
|
+
{ key: "id", positional: true, required: true },
|
|
2817
|
+
{ key: "type", positional: true },
|
|
2818
|
+
{ key: "preview", positional: true }
|
|
2819
|
+
]
|
|
2820
|
+
}
|
|
2821
|
+
] : [],
|
|
2822
|
+
...data.content !== void 0 ? [{ kind: "content", key: "content", title: "LiteXML", text: data.content }] : [],
|
|
2823
|
+
...data.comments ? [
|
|
2824
|
+
{
|
|
2825
|
+
...threadMessages(data.comments.threads, "comments"),
|
|
2826
|
+
title: "Published snapshot comments"
|
|
2827
|
+
}
|
|
2828
|
+
] : []
|
|
2829
|
+
]
|
|
2830
|
+
};
|
|
2831
|
+
}
|
|
2461
2832
|
var value2 = (input, key) => typeof input.values[key] === "string" ? input.values[key] : void 0;
|
|
2462
2833
|
var safePath = (file) => !!file && !file.includes("\\") && !file.includes("\0") && !import_node_path10.default.posix.isAbsolute(file) && file.split("/").every((p) => !!p && p !== "." && p !== "..");
|
|
2463
2834
|
async function downloadFiles(data, dir, ctx) {
|
|
@@ -2512,7 +2883,7 @@ function getSemantic(input) {
|
|
|
2512
2883
|
code: "E_ARGUMENT_INVALID",
|
|
2513
2884
|
message: "Give a Cloud link or artifact ID."
|
|
2514
2885
|
});
|
|
2515
|
-
const { origin, id } = parseTarget(
|
|
2886
|
+
const { origin, id: id2 } = parseTarget(
|
|
2516
2887
|
target,
|
|
2517
2888
|
(process.env.RYUGI_CLOUD_ORIGIN || "https://ryugi.innei.dev").replace(/\/+$/, "")
|
|
2518
2889
|
);
|
|
@@ -2579,7 +2950,7 @@ function getSemantic(input) {
|
|
|
2579
2950
|
credentialsFile(process.env, process.platform, import_node_os5.default.homedir()),
|
|
2580
2951
|
origin
|
|
2581
2952
|
);
|
|
2582
|
-
const response = await fetch(`${origin}/api/a/${
|
|
2953
|
+
const response = await fetch(`${origin}/api/a/${id2}?${query2}`, {
|
|
2583
2954
|
headers: credentials ? { Authorization: `Bearer ${credentials.token}` } : {},
|
|
2584
2955
|
signal: ctx.signal
|
|
2585
2956
|
});
|
|
@@ -2629,7 +3000,7 @@ function getSemantic(input) {
|
|
|
2629
3000
|
process.env.XDG_CACHE_HOME || import_node_path10.default.join(import_node_os5.default.homedir(), ".cache"),
|
|
2630
3001
|
"ryugi",
|
|
2631
3002
|
"get",
|
|
2632
|
-
|
|
3003
|
+
id2,
|
|
2633
3004
|
`v${data.version}`
|
|
2634
3005
|
)
|
|
2635
3006
|
);
|
|
@@ -2670,43 +3041,7 @@ function getSemantic(input) {
|
|
|
2670
3041
|
]
|
|
2671
3042
|
});
|
|
2672
3043
|
},
|
|
2673
|
-
present
|
|
2674
|
-
return {
|
|
2675
|
-
heading: "Cloud artifact",
|
|
2676
|
-
status: data.status,
|
|
2677
|
-
subject: data.id,
|
|
2678
|
-
facts: [
|
|
2679
|
-
fact("Type", field(data, "type"), true),
|
|
2680
|
-
fact("Title", field(data, "title")),
|
|
2681
|
-
fact("Version", field(data, "version"), true),
|
|
2682
|
-
fact("Visibility", field(data, "visibility"), true),
|
|
2683
|
-
...data.dir ? [fact("Downloaded", field(data, "dir"), true)] : data.files ? [fact("Files available", field(data, "files"))] : []
|
|
2684
|
-
],
|
|
2685
|
-
sections: [
|
|
2686
|
-
...data.outline ? [
|
|
2687
|
-
{
|
|
2688
|
-
kind: "records",
|
|
2689
|
-
key: "outline",
|
|
2690
|
-
rows: data.outline,
|
|
2691
|
-
columns: [
|
|
2692
|
-
{ key: "id", label: "ID", required: true },
|
|
2693
|
-
{ key: "type", label: "Type" },
|
|
2694
|
-
{ key: "preview", label: "Preview" }
|
|
2695
|
-
]
|
|
2696
|
-
}
|
|
2697
|
-
] : [],
|
|
2698
|
-
...data.content !== void 0 ? [{ kind: "content", key: "content", title: "LiteXML", text: data.content }] : [],
|
|
2699
|
-
...data.comments ? [
|
|
2700
|
-
{
|
|
2701
|
-
kind: "content",
|
|
2702
|
-
key: "comments",
|
|
2703
|
-
title: "Published snapshot comments",
|
|
2704
|
-
text: JSON.stringify(data.comments.threads)
|
|
2705
|
-
}
|
|
2706
|
-
] : []
|
|
2707
|
-
]
|
|
2708
|
-
};
|
|
2709
|
-
}
|
|
3044
|
+
present: presentGet
|
|
2710
3045
|
},
|
|
2711
3046
|
input
|
|
2712
3047
|
);
|
|
@@ -2724,10 +3059,10 @@ function parseTarget(target, defaultOrigin) {
|
|
|
2724
3059
|
} catch {
|
|
2725
3060
|
throw new CliError(TARGET_ERROR);
|
|
2726
3061
|
}
|
|
2727
|
-
const
|
|
2728
|
-
if (!
|
|
3062
|
+
const id2 = LINK_PATH.exec(url.pathname)?.[1];
|
|
3063
|
+
if (!id2 || url.protocol !== "https:" && url.protocol !== "http:")
|
|
2729
3064
|
throw new CliError(TARGET_ERROR);
|
|
2730
|
-
return { origin: url.origin, id };
|
|
3065
|
+
return { origin: url.origin, id: id2 };
|
|
2731
3066
|
}
|
|
2732
3067
|
var getCommand = {
|
|
2733
3068
|
name: "get",
|
|
@@ -2781,6 +3116,74 @@ function acceptCloud(response) {
|
|
|
2781
3116
|
}
|
|
2782
3117
|
|
|
2783
3118
|
// src/cli/semantic/publish.ts
|
|
3119
|
+
function presentPublish({ data }) {
|
|
3120
|
+
return {
|
|
3121
|
+
heading: "Publish",
|
|
3122
|
+
status: data.status,
|
|
3123
|
+
subject: data.artifact,
|
|
3124
|
+
facts: [
|
|
3125
|
+
fact("ID", field(data, "id"), true),
|
|
3126
|
+
fact("URL", field(data, "url"), true),
|
|
3127
|
+
fact(
|
|
3128
|
+
"Visibility",
|
|
3129
|
+
{ key: "visibility", value: `${data.visibility} (${data.visibilitySource})` },
|
|
3130
|
+
true
|
|
3131
|
+
),
|
|
3132
|
+
...data.version === void 0 ? [] : [fact("Version", field(data, "version"))],
|
|
3133
|
+
fact("Unpublished references", { key: "unpublished", value: data.unpublished.join(", ") }),
|
|
3134
|
+
fact("Private references", { key: "private", value: data.private.join(", ") })
|
|
3135
|
+
],
|
|
3136
|
+
sections: data.references.length ? [
|
|
3137
|
+
{
|
|
3138
|
+
kind: "records",
|
|
3139
|
+
key: "references",
|
|
3140
|
+
title: "Referenced artifacts",
|
|
3141
|
+
rows: data.references.map((ref) => ({
|
|
3142
|
+
artifact: ref.artifact,
|
|
3143
|
+
status: ref.status,
|
|
3144
|
+
error: ref.error ? `${ref.error.code}: ${ref.error.message}` : "",
|
|
3145
|
+
recovery: ref.status === "unknown" ? "inspect the remote artifact before retrying" : ""
|
|
3146
|
+
})),
|
|
3147
|
+
columns: [
|
|
3148
|
+
{ key: "artifact", positional: true, required: true },
|
|
3149
|
+
{ key: "status", positional: true, required: true },
|
|
3150
|
+
{ key: "error", positional: true },
|
|
3151
|
+
{ key: "recovery", positional: true }
|
|
3152
|
+
]
|
|
3153
|
+
}
|
|
3154
|
+
] : []
|
|
3155
|
+
};
|
|
3156
|
+
}
|
|
3157
|
+
function presentCloudList({
|
|
3158
|
+
data,
|
|
3159
|
+
coverage
|
|
3160
|
+
}) {
|
|
3161
|
+
const total = coverage.page?.total ?? data.artifacts.length;
|
|
3162
|
+
return {
|
|
3163
|
+
heading: "Cloud artifacts",
|
|
3164
|
+
status: "",
|
|
3165
|
+
summary: `${total} on account`,
|
|
3166
|
+
facts: [],
|
|
3167
|
+
sections: [
|
|
3168
|
+
{
|
|
3169
|
+
kind: "records",
|
|
3170
|
+
key: "artifacts",
|
|
3171
|
+
rows: data.artifacts.map((row) => ({
|
|
3172
|
+
...row,
|
|
3173
|
+
version: row.version === void 0 ? "" : `v${row.version}`
|
|
3174
|
+
})),
|
|
3175
|
+
columns: [
|
|
3176
|
+
{ key: "id", positional: true, required: true },
|
|
3177
|
+
{ key: "type", positional: true },
|
|
3178
|
+
{ key: "visibility", positional: true, required: true },
|
|
3179
|
+
{ key: "version", positional: true },
|
|
3180
|
+
{ key: "updatedAt", positional: true },
|
|
3181
|
+
{ key: "title", positional: true }
|
|
3182
|
+
]
|
|
3183
|
+
}
|
|
3184
|
+
]
|
|
3185
|
+
};
|
|
3186
|
+
}
|
|
2784
3187
|
var formats2 = ["brief", "json", "jsonl", "quiet"];
|
|
2785
3188
|
function optionsOf(input) {
|
|
2786
3189
|
const { values } = input;
|
|
@@ -2841,8 +3244,8 @@ async function publishReport(input, ctx, artifact, visibility) {
|
|
|
2841
3244
|
const published = await send(artifact, visibility);
|
|
2842
3245
|
const boards = published.boards;
|
|
2843
3246
|
const pending = [...boards?.unpublished ?? []];
|
|
2844
|
-
const references = (boards?.published ?? []).map((
|
|
2845
|
-
artifact: `artboard/${
|
|
3247
|
+
const references = (boards?.published ?? []).map((id2) => ({
|
|
3248
|
+
artifact: `artboard/${id2}`,
|
|
2846
3249
|
status: "published"
|
|
2847
3250
|
}));
|
|
2848
3251
|
let partial = false;
|
|
@@ -2858,10 +3261,10 @@ async function publishReport(input, ctx, artifact, visibility) {
|
|
|
2858
3261
|
status: errorOf(error).httpStatus && errorOf(error).httpStatus < 500 ? "failed" : "unknown",
|
|
2859
3262
|
error: errorOf(error)
|
|
2860
3263
|
});
|
|
2861
|
-
for (const
|
|
2862
|
-
const effect = ctx.effects.begin("publish", `artboard/${
|
|
3264
|
+
for (const id2 of pending.slice(i + 1)) {
|
|
3265
|
+
const effect = ctx.effects.begin("publish", `artboard/${id2}`);
|
|
2863
3266
|
ctx.effects.set(effect, "not_attempted");
|
|
2864
|
-
references.push({ artifact: `artboard/${
|
|
3267
|
+
references.push({ artifact: `artboard/${id2}`, status: "not_attempted" });
|
|
2865
3268
|
}
|
|
2866
3269
|
partial = true;
|
|
2867
3270
|
break;
|
|
@@ -2880,7 +3283,7 @@ async function publishReport(input, ctx, artifact, visibility) {
|
|
|
2880
3283
|
...published.version === void 0 ? {} : { version: published.version },
|
|
2881
3284
|
visibilitySource: visibility ? "requested" : "preserved",
|
|
2882
3285
|
references,
|
|
2883
|
-
unpublished: pending.filter((
|
|
3286
|
+
unpublished: pending.filter((id2) => !succeeded.has(`artboard/${id2}`)),
|
|
2884
3287
|
private: boards?.private ?? []
|
|
2885
3288
|
};
|
|
2886
3289
|
return result(report2, partial ? { kind: "partial" } : { kind: "succeeded" }, {
|
|
@@ -2918,41 +3321,7 @@ function publishSemantic(input) {
|
|
|
2918
3321
|
mode: "finite",
|
|
2919
3322
|
output: { formats: formats2, scalar: (data) => data.id },
|
|
2920
3323
|
run: (_input, ctx) => publishReport(input, ctx, artifact, visibility),
|
|
2921
|
-
present
|
|
2922
|
-
return {
|
|
2923
|
-
heading: "Publish",
|
|
2924
|
-
status: data.status,
|
|
2925
|
-
subject: data.artifact,
|
|
2926
|
-
facts: [
|
|
2927
|
-
fact("ID", field(data, "id"), true),
|
|
2928
|
-
fact("URL", field(data, "url"), true),
|
|
2929
|
-
fact("Visibility", field(data, "visibility"), true),
|
|
2930
|
-
fact("Visibility source", field(data, "visibilitySource")),
|
|
2931
|
-
...data.version === void 0 ? [] : [fact("Version", field(data, "version"))],
|
|
2932
|
-
...data.unpublished.length ? [fact("Unpublished references", field(data, "unpublished"))] : [],
|
|
2933
|
-
...data.private.length ? [fact("Private references", field(data, "private"))] : []
|
|
2934
|
-
],
|
|
2935
|
-
sections: data.references.length ? [
|
|
2936
|
-
{
|
|
2937
|
-
kind: "records",
|
|
2938
|
-
key: "references",
|
|
2939
|
-
title: "Referenced artifacts",
|
|
2940
|
-
rows: data.references.map((ref) => ({
|
|
2941
|
-
artifact: ref.artifact,
|
|
2942
|
-
status: ref.status,
|
|
2943
|
-
error: ref.error ? `${ref.error.code}: ${ref.error.message}` : "",
|
|
2944
|
-
recovery: ref.status === "unknown" ? "Inspect the remote artifact before retrying" : ""
|
|
2945
|
-
})),
|
|
2946
|
-
columns: [
|
|
2947
|
-
{ key: "artifact", label: "Artifact", required: true },
|
|
2948
|
-
{ key: "status", label: "Status", required: true },
|
|
2949
|
-
{ key: "error", label: "Reason" },
|
|
2950
|
-
{ key: "recovery", label: "Recovery" }
|
|
2951
|
-
]
|
|
2952
|
-
}
|
|
2953
|
-
] : []
|
|
2954
|
-
};
|
|
2955
|
-
}
|
|
3324
|
+
present: presentPublish
|
|
2956
3325
|
},
|
|
2957
3326
|
input
|
|
2958
3327
|
);
|
|
@@ -3012,27 +3381,7 @@ function publishSemantic(input) {
|
|
|
3012
3381
|
] : []
|
|
3013
3382
|
});
|
|
3014
3383
|
},
|
|
3015
|
-
present
|
|
3016
|
-
return {
|
|
3017
|
-
heading: "Cloud artifacts",
|
|
3018
|
-
status: "listed",
|
|
3019
|
-
facts: [],
|
|
3020
|
-
sections: [
|
|
3021
|
-
{
|
|
3022
|
-
kind: "records",
|
|
3023
|
-
key: "artifacts",
|
|
3024
|
-
rows: data.artifacts.map((row) => ({ ...row })),
|
|
3025
|
-
columns: [
|
|
3026
|
-
{ key: "id", label: "ID", required: true },
|
|
3027
|
-
{ key: "type", label: "Type" },
|
|
3028
|
-
{ key: "title", label: "Title" },
|
|
3029
|
-
{ key: "visibility", label: "Visibility", required: true },
|
|
3030
|
-
{ key: "updatedAt", label: "Updated" }
|
|
3031
|
-
]
|
|
3032
|
-
}
|
|
3033
|
-
]
|
|
3034
|
-
};
|
|
3035
|
-
}
|
|
3384
|
+
present: presentCloudList
|
|
3036
3385
|
},
|
|
3037
3386
|
input
|
|
3038
3387
|
);
|
|
@@ -3228,26 +3577,27 @@ var sceneCommand = {
|
|
|
3228
3577
|
}
|
|
3229
3578
|
);
|
|
3230
3579
|
},
|
|
3231
|
-
present
|
|
3232
|
-
return {
|
|
3233
|
-
heading: "Scene",
|
|
3234
|
-
status: data.problem ? "invalid" : "read",
|
|
3235
|
-
subject: data.artifact,
|
|
3236
|
-
facts: [
|
|
3237
|
-
...data.page ? [fact("Page", field(data, "page"))] : [],
|
|
3238
|
-
fact("Version", field(data, "sceneVersion")),
|
|
3239
|
-
fact("Render", field(data, "render")),
|
|
3240
|
-
...data.renderPath ? [fact("Image", field(data, "renderPath"))] : [],
|
|
3241
|
-
...data.problem ? [fact("Problem", field(data, "problem"))] : [],
|
|
3242
|
-
...data.conflicts.length ? [fact("Conflicts", field(data, "conflicts"))] : []
|
|
3243
|
-
],
|
|
3244
|
-
sections: [{ kind: "content", key: "lines", text: data.lines.join("\n") }]
|
|
3245
|
-
};
|
|
3246
|
-
}
|
|
3580
|
+
present: presentScene
|
|
3247
3581
|
},
|
|
3248
3582
|
input
|
|
3249
3583
|
)
|
|
3250
3584
|
};
|
|
3585
|
+
function presentScene({ data }) {
|
|
3586
|
+
return {
|
|
3587
|
+
heading: "Scene",
|
|
3588
|
+
status: data.problem ? "invalid" : "",
|
|
3589
|
+
subject: data.artifact,
|
|
3590
|
+
facts: [
|
|
3591
|
+
...data.page ? [fact("Page", field(data, "page"))] : [],
|
|
3592
|
+
fact("Version", field(data, "sceneVersion")),
|
|
3593
|
+
fact("Render", field(data, "render")),
|
|
3594
|
+
...data.renderPath ? [fact("Image", field(data, "renderPath"))] : [],
|
|
3595
|
+
...data.problem ? [fact("Problem", field(data, "problem"))] : [],
|
|
3596
|
+
fact("Conflicts", { key: "conflicts", value: data.conflicts.join(", ") })
|
|
3597
|
+
],
|
|
3598
|
+
sections: [{ kind: "content", key: "lines", text: data.lines.join("\n") }]
|
|
3599
|
+
};
|
|
3600
|
+
}
|
|
3251
3601
|
|
|
3252
3602
|
// src/cli/start.ts
|
|
3253
3603
|
var import_node_child_process3 = require("node:child_process");
|
|
@@ -3271,48 +3621,48 @@ var MINT_LENGTH = 21;
|
|
|
3271
3621
|
var MINTED_PATTERN = new RegExp(`^[a-z0-9]{${MINT_LENGTH}}$`, "i");
|
|
3272
3622
|
var MINT_BYTE_LIMIT = 248;
|
|
3273
3623
|
function mintArtifactId() {
|
|
3274
|
-
let
|
|
3624
|
+
let id2 = "";
|
|
3275
3625
|
const bytes = new Uint8Array(MINT_LENGTH * 2);
|
|
3276
|
-
while (
|
|
3626
|
+
while (id2.length < MINT_LENGTH) {
|
|
3277
3627
|
crypto.getRandomValues(bytes);
|
|
3278
3628
|
for (const byte of bytes) {
|
|
3279
3629
|
if (byte >= MINT_BYTE_LIMIT) continue;
|
|
3280
|
-
|
|
3281
|
-
if (
|
|
3630
|
+
id2 += MINT_ALPHABET[byte % MINT_ALPHABET.length];
|
|
3631
|
+
if (id2.length === MINT_LENGTH) break;
|
|
3282
3632
|
}
|
|
3283
3633
|
}
|
|
3284
|
-
return
|
|
3634
|
+
return id2;
|
|
3285
3635
|
}
|
|
3286
|
-
var isArtifactId = (
|
|
3287
|
-
var isArtifactAddress = (
|
|
3636
|
+
var isArtifactId = (id2) => ID_PATTERN.test(id2);
|
|
3637
|
+
var isArtifactAddress = (id2) => ADDRESS_PATTERN.test(id2);
|
|
3288
3638
|
var isArtifactType = (type) => ARTIFACT_TYPES.includes(type);
|
|
3289
3639
|
|
|
3290
3640
|
// src/server/artifacts.ts
|
|
3291
3641
|
function artifactKeyOf(relative, isId = isArtifactId) {
|
|
3292
|
-
const [type,
|
|
3293
|
-
if (!type || !
|
|
3294
|
-
return { type, id };
|
|
3642
|
+
const [type, id2] = relative.split("/");
|
|
3643
|
+
if (!type || !id2 || !isArtifactType(type) || !isId(id2)) return null;
|
|
3644
|
+
return { type, id: id2 };
|
|
3295
3645
|
}
|
|
3296
3646
|
|
|
3297
3647
|
// src/server/artifact-address.ts
|
|
3298
3648
|
function artifactId(dir) {
|
|
3299
3649
|
const file = import_node_path11.default.join(dir, ".artifact-id");
|
|
3300
|
-
let
|
|
3650
|
+
let id2;
|
|
3301
3651
|
try {
|
|
3302
|
-
|
|
3652
|
+
id2 = import_node_fs12.default.readFileSync(file, "utf8").trim();
|
|
3303
3653
|
} catch (err) {
|
|
3304
3654
|
if (err.code !== "ENOENT") throw err;
|
|
3305
|
-
|
|
3655
|
+
id2 = mintArtifactId();
|
|
3306
3656
|
try {
|
|
3307
|
-
import_node_fs12.default.writeFileSync(file, `${
|
|
3657
|
+
import_node_fs12.default.writeFileSync(file, `${id2}
|
|
3308
3658
|
`, { flag: "wx" });
|
|
3309
3659
|
} catch (writeError) {
|
|
3310
3660
|
if (writeError.code !== "EEXIST") throw writeError;
|
|
3311
3661
|
return artifactId(dir);
|
|
3312
3662
|
}
|
|
3313
3663
|
}
|
|
3314
|
-
if (!isArtifactAddress(
|
|
3315
|
-
return
|
|
3664
|
+
if (!isArtifactAddress(id2)) throw new Error(`Invalid artifact ID in ${file}`);
|
|
3665
|
+
return id2;
|
|
3316
3666
|
}
|
|
3317
3667
|
function artifactPath(root, type, slug) {
|
|
3318
3668
|
if (!isArtifactType(type) || !isArtifactId(slug)) throw new Error("Invalid artifact locator");
|
|
@@ -3507,13 +3857,12 @@ function report(options, info) {
|
|
|
3507
3857
|
cloud: info?.cloudLink ? "live_link_reserved" : "local_only"
|
|
3508
3858
|
};
|
|
3509
3859
|
}
|
|
3510
|
-
function
|
|
3860
|
+
function presentServer({ data }) {
|
|
3511
3861
|
return {
|
|
3512
3862
|
heading: "Server",
|
|
3513
3863
|
status: data.status,
|
|
3514
3864
|
subject: data.reused ? "reused" : void 0,
|
|
3515
3865
|
facts: [
|
|
3516
|
-
fact("Scope", field(data, "scope"), true),
|
|
3517
3866
|
fact("Project", field(data, "project"), true),
|
|
3518
3867
|
...data.artifact ? [fact("Artifact", field(data, "artifact"), true)] : [],
|
|
3519
3868
|
...data.url ? [fact("Open", field(data, "url"), true)] : [],
|
|
@@ -3566,7 +3915,7 @@ async function* lifecycle(options, ctx) {
|
|
|
3566
3915
|
failure(value3) {
|
|
3567
3916
|
startupError = String(value3.error ?? "Server failed");
|
|
3568
3917
|
},
|
|
3569
|
-
log: (
|
|
3918
|
+
log: (text2) => ctx.diagnostic(text2)
|
|
3570
3919
|
}).then((code) => {
|
|
3571
3920
|
if (ctx.signal.aborted) {
|
|
3572
3921
|
const signal = ctx.signal.reason === "SIGINT" ? "SIGINT" : "SIGTERM";
|
|
@@ -3624,7 +3973,7 @@ function startSemantic(input, operation = "start") {
|
|
|
3624
3973
|
mode: "live",
|
|
3625
3974
|
output: { formats: ["brief", "jsonl"] },
|
|
3626
3975
|
run: (_input, ctx) => lifecycle(options, ctx),
|
|
3627
|
-
present
|
|
3976
|
+
present: presentServer
|
|
3628
3977
|
},
|
|
3629
3978
|
input
|
|
3630
3979
|
);
|
|
@@ -3646,7 +3995,7 @@ function startSemantic(input, operation = "start") {
|
|
|
3646
3995
|
failure(error) {
|
|
3647
3996
|
failure = String(error.error ?? "Server failed");
|
|
3648
3997
|
},
|
|
3649
|
-
log: (
|
|
3998
|
+
log: (text2) => ctx.diagnostic(text2)
|
|
3650
3999
|
});
|
|
3651
4000
|
if (code !== 0 || !value3)
|
|
3652
4001
|
throw new OutputError({
|
|
@@ -3655,7 +4004,7 @@ function startSemantic(input, operation = "start") {
|
|
|
3655
4004
|
});
|
|
3656
4005
|
return started(options, value3);
|
|
3657
4006
|
},
|
|
3658
|
-
present
|
|
4007
|
+
present: presentServer
|
|
3659
4008
|
},
|
|
3660
4009
|
input
|
|
3661
4010
|
);
|
|
@@ -3738,9 +4087,9 @@ async function acquireLock(lock) {
|
|
|
3738
4087
|
}
|
|
3739
4088
|
function runningPid(machine) {
|
|
3740
4089
|
const pid = Number(readText(machine.pid));
|
|
3741
|
-
const
|
|
3742
|
-
if (!Number.isInteger(pid) || pid <= 0 || !
|
|
3743
|
-
return hasServerId(pid,
|
|
4090
|
+
const id2 = readText(machine.serverId);
|
|
4091
|
+
if (!Number.isInteger(pid) || pid <= 0 || !id2) return null;
|
|
4092
|
+
return hasServerId(pid, id2) ? pid : null;
|
|
3744
4093
|
}
|
|
3745
4094
|
function readInfo(machine) {
|
|
3746
4095
|
try {
|
|
@@ -3813,8 +4162,8 @@ function serverEnv(options) {
|
|
|
3813
4162
|
delete env[key];
|
|
3814
4163
|
return env;
|
|
3815
4164
|
}
|
|
3816
|
-
var startedLine = (
|
|
3817
|
-
var errorLine = (
|
|
4165
|
+
var startedLine = (text2) => text2.split("\n").find((line2) => line2.includes('"server-started"'));
|
|
4166
|
+
var errorLine = (text2) => text2.split("\n").find((line2) => line2.includes('"server-error"'));
|
|
3818
4167
|
async function register(info, paths, open) {
|
|
3819
4168
|
const res = await fetch(apiUrl(info, "/api/hub/projects"), {
|
|
3820
4169
|
method: "POST",
|
|
@@ -3841,7 +4190,7 @@ async function startServer(options, hooks) {
|
|
|
3841
4190
|
import_node_fs15.default.mkdirSync(paths.state, { recursive: true });
|
|
3842
4191
|
if (!import_node_fs15.default.existsSync(import_node_path15.default.join(paths.state, ".gitignore")))
|
|
3843
4192
|
import_node_fs15.default.writeFileSync(import_node_path15.default.join(paths.state, ".gitignore"), "*\n");
|
|
3844
|
-
const cliVersion = process.env.RYUGI_ARTIFACTS_VERSION || (true ? "1.
|
|
4193
|
+
const cliVersion = process.env.RYUGI_ARTIFACTS_VERSION || (true ? "1.65.0" : "");
|
|
3845
4194
|
const known = readProjects(machine.projects).some((entry) => entry.dir === paths.project);
|
|
3846
4195
|
const finish = async (info, reused) => {
|
|
3847
4196
|
recordAgent(paths);
|
|
@@ -3900,13 +4249,13 @@ async function startServer(options, hooks) {
|
|
|
3900
4249
|
}
|
|
3901
4250
|
await stopOldProjectServers();
|
|
3902
4251
|
import_node_fs15.default.rmSync(machine.info, { force: true });
|
|
3903
|
-
const
|
|
3904
|
-
import_node_fs15.default.writeFileSync(machine.serverId, `${
|
|
4252
|
+
const id2 = import_node_crypto2.default.randomBytes(24).toString("hex");
|
|
4253
|
+
import_node_fs15.default.writeFileSync(machine.serverId, `${id2}
|
|
3905
4254
|
`);
|
|
3906
4255
|
import_node_fs15.default.writeFileSync(machine.version, `${cliVersion}
|
|
3907
4256
|
`);
|
|
3908
4257
|
const server = import_node_path15.default.join(__dirname, "server.cjs");
|
|
3909
|
-
const args = [server, `--artifacts-server-id=${
|
|
4258
|
+
const args = [server, `--artifacts-server-id=${id2}`, ...options.port ? [`--port=${options.port}`] : []];
|
|
3910
4259
|
const env = serverEnv(options);
|
|
3911
4260
|
const foreground = options.foreground || !options.background && !!process.env.CODEX_CI;
|
|
3912
4261
|
if (foreground) {
|
|
@@ -3918,16 +4267,16 @@ async function startServer(options, hooks) {
|
|
|
3918
4267
|
};
|
|
3919
4268
|
if (hooks.signal) hooks.signal.addEventListener("abort", terminate, { once: true });
|
|
3920
4269
|
else for (const signal of ["SIGINT", "SIGTERM"]) process.on(signal, terminate);
|
|
3921
|
-
import_node_readline.default.createInterface({ input: child2.stderr }).on("line", (
|
|
4270
|
+
import_node_readline.default.createInterface({ input: child2.stderr }).on("line", (line2) => hooks.log(line2, "stderr"));
|
|
3922
4271
|
const exited = new Promise((resolve) => child2.on("close", (code) => resolve(code ?? 1)));
|
|
3923
4272
|
let announced = false;
|
|
3924
4273
|
let startup;
|
|
3925
|
-
import_node_readline.default.createInterface({ input: child2.stdout }).on("line", (
|
|
4274
|
+
import_node_readline.default.createInterface({ input: child2.stdout }).on("line", (line2) => {
|
|
3926
4275
|
let value3;
|
|
3927
4276
|
try {
|
|
3928
|
-
value3 = JSON.parse(
|
|
4277
|
+
value3 = JSON.parse(line2);
|
|
3929
4278
|
} catch {
|
|
3930
|
-
hooks.log(
|
|
4279
|
+
hooks.log(line2, "stdout");
|
|
3931
4280
|
return;
|
|
3932
4281
|
}
|
|
3933
4282
|
if (value3.type !== "server-started" || announced) {
|
|
@@ -3966,8 +4315,8 @@ async function startServer(options, hooks) {
|
|
|
3966
4315
|
import_node_fs15.default.writeFileSync(machine.pid, `${child.pid}
|
|
3967
4316
|
`);
|
|
3968
4317
|
for (let waited = 0; waited < START_TIMEOUT_MS; waited += 100) {
|
|
3969
|
-
const
|
|
3970
|
-
const started2 = startedLine(
|
|
4318
|
+
const text2 = readText(machine.log) ?? "";
|
|
4319
|
+
const started2 = startedLine(text2);
|
|
3971
4320
|
if (started2) {
|
|
3972
4321
|
for (let check = 0; check < 10; check++) {
|
|
3973
4322
|
if (!alive(child.pid))
|
|
@@ -3980,7 +4329,7 @@ async function startServer(options, hooks) {
|
|
|
3980
4329
|
await finish(JSON.parse(started2), false);
|
|
3981
4330
|
return 0;
|
|
3982
4331
|
}
|
|
3983
|
-
const failed = errorLine(
|
|
4332
|
+
const failed = errorLine(text2);
|
|
3984
4333
|
if (failed) {
|
|
3985
4334
|
hooks.failure(JSON.parse(failed));
|
|
3986
4335
|
return 1;
|
|
@@ -4037,6 +4386,15 @@ function clearCompatInfo(projectsFile) {
|
|
|
4037
4386
|
for (const entry of readProjects(projectsFile))
|
|
4038
4387
|
import_node_fs16.default.rmSync(import_node_path16.default.join(artifactsRootOf(entry.dir), ".state", "server-info"), { force: true });
|
|
4039
4388
|
}
|
|
4389
|
+
function presentStop({ data }) {
|
|
4390
|
+
return {
|
|
4391
|
+
heading: "Server",
|
|
4392
|
+
status: data.status,
|
|
4393
|
+
summary: data.status === data.reason ? "" : data.reason.replaceAll("_", " "),
|
|
4394
|
+
facts: [fact("Artifacts", field(data, "artifacts"))],
|
|
4395
|
+
sections: []
|
|
4396
|
+
};
|
|
4397
|
+
}
|
|
4040
4398
|
async function stopServer() {
|
|
4041
4399
|
const machine = machinePaths();
|
|
4042
4400
|
const markStopped = (reason) => {
|
|
@@ -4053,8 +4411,8 @@ async function stopServer() {
|
|
|
4053
4411
|
return { status: "not_running" };
|
|
4054
4412
|
}
|
|
4055
4413
|
const pid = Number(readText(machine.pid));
|
|
4056
|
-
const
|
|
4057
|
-
if (!Number.isInteger(pid) || pid <= 0 || !/^[\w-]{32,64}$/.test(
|
|
4414
|
+
const id2 = readText(machine.serverId) ?? "";
|
|
4415
|
+
if (!Number.isInteger(pid) || pid <= 0 || !/^[\w-]{32,64}$/.test(id2) || !hasServerId(pid, id2)) {
|
|
4058
4416
|
import_node_fs16.default.rmSync(machine.pid, { force: true });
|
|
4059
4417
|
import_node_fs16.default.rmSync(machine.serverId, { force: true });
|
|
4060
4418
|
markStopped("stale_pid");
|
|
@@ -4100,18 +4458,7 @@ var stopCommand = {
|
|
|
4100
4458
|
state.status === "failed" ? { kind: "failed", error: { code: "E_SERVER_STOP_FAILED", message: state.error } } : { kind: "succeeded" }
|
|
4101
4459
|
);
|
|
4102
4460
|
},
|
|
4103
|
-
present
|
|
4104
|
-
return {
|
|
4105
|
-
heading: "Server",
|
|
4106
|
-
status: data.status,
|
|
4107
|
-
facts: [
|
|
4108
|
-
fact("Scope", field(data, "scope"), true),
|
|
4109
|
-
fact("Reason", field(data, "reason")),
|
|
4110
|
-
fact("Artifacts", field(data, "artifacts"))
|
|
4111
|
-
],
|
|
4112
|
-
sections: []
|
|
4113
|
-
};
|
|
4114
|
-
}
|
|
4461
|
+
present: presentStop
|
|
4115
4462
|
},
|
|
4116
4463
|
input
|
|
4117
4464
|
)
|
|
@@ -4185,7 +4532,9 @@ async function fetchLatest(registry) {
|
|
|
4185
4532
|
if (res.ok && typeof version === "string" && /^\d+\.\d+\.\d+/.test(version)) return version;
|
|
4186
4533
|
throw new Error(`registry returned ${res.status}`);
|
|
4187
4534
|
} catch (err) {
|
|
4188
|
-
throw new CliError(
|
|
4535
|
+
throw new CliError(
|
|
4536
|
+
`Could not get the latest ${PACKAGE} version from ${base}: ${err.message}`
|
|
4537
|
+
);
|
|
4189
4538
|
}
|
|
4190
4539
|
}
|
|
4191
4540
|
function advice(install, latest) {
|
|
@@ -4235,8 +4584,10 @@ or run \`${PACKAGE} update --pm <${PMS.join("|")}>\`.`
|
|
|
4235
4584
|
const result2 = windows ? (0, import_node_child_process4.spawnSync)(commandLine2(command), { stdio: [...stdio], env: options.env, shell: true }) : (0, import_node_child_process4.spawnSync)(command.cmd, command.args, { stdio: [...stdio], env: options.env });
|
|
4236
4585
|
if (result2.stdout?.length) hooks.log?.(result2.stdout.toString());
|
|
4237
4586
|
if (result2.stderr?.length) hooks.log?.(result2.stderr.toString());
|
|
4238
|
-
if (result2.error)
|
|
4239
|
-
|
|
4587
|
+
if (result2.error)
|
|
4588
|
+
throw new CliError(`Could not run ${commandLine2(command)}: ${result2.error.message}`);
|
|
4589
|
+
if (result2.status !== 0)
|
|
4590
|
+
throw new CliError(`${commandLine2(command)} exited with ${result2.status ?? result2.signal}`);
|
|
4240
4591
|
return {
|
|
4241
4592
|
type: "updated",
|
|
4242
4593
|
from: options.current,
|
|
@@ -4270,7 +4621,7 @@ var updateCommand = {
|
|
|
4270
4621
|
try {
|
|
4271
4622
|
report2 = await performUpdate(
|
|
4272
4623
|
{
|
|
4273
|
-
current: "1.
|
|
4624
|
+
current: "1.65.0",
|
|
4274
4625
|
file: __filename,
|
|
4275
4626
|
env: process.env,
|
|
4276
4627
|
registry: process.env.npm_config_registry || "https://registry.npmjs.org/",
|
|
@@ -4286,7 +4637,10 @@ var updateCommand = {
|
|
|
4286
4637
|
);
|
|
4287
4638
|
} catch (error) {
|
|
4288
4639
|
if (error instanceof InstallUnknownError)
|
|
4289
|
-
throw new OutputError(
|
|
4640
|
+
throw new OutputError(
|
|
4641
|
+
{ code: "E_INSTALL_UNKNOWN", message: error.message },
|
|
4642
|
+
"action_required"
|
|
4643
|
+
);
|
|
4290
4644
|
throw error;
|
|
4291
4645
|
}
|
|
4292
4646
|
if (report2.type === "updated" && effect !== void 0)
|
|
@@ -4309,24 +4663,26 @@ var updateCommand = {
|
|
|
4309
4663
|
};
|
|
4310
4664
|
return result(data, void 0, { effects: ctx.effects.snapshot() });
|
|
4311
4665
|
},
|
|
4312
|
-
present
|
|
4313
|
-
return {
|
|
4314
|
-
heading: "Update",
|
|
4315
|
-
status: data.status,
|
|
4316
|
-
facts: [
|
|
4317
|
-
fact("Current", field(data, "current"), true),
|
|
4318
|
-
fact("Latest", field(data, "latest")),
|
|
4319
|
-
fact("Install", field(data, "install")),
|
|
4320
|
-
fact("Installed", field(data, "installed")),
|
|
4321
|
-
...data.message ? [fact("Advice", field(data, "message"))] : []
|
|
4322
|
-
],
|
|
4323
|
-
sections: []
|
|
4324
|
-
};
|
|
4325
|
-
}
|
|
4666
|
+
present: presentUpdate
|
|
4326
4667
|
},
|
|
4327
4668
|
input
|
|
4328
4669
|
)
|
|
4329
4670
|
};
|
|
4671
|
+
function presentUpdate({
|
|
4672
|
+
data
|
|
4673
|
+
}) {
|
|
4674
|
+
return {
|
|
4675
|
+
heading: "Update",
|
|
4676
|
+
status: data.status,
|
|
4677
|
+
facts: [
|
|
4678
|
+
fact("Current", field(data, "current"), true),
|
|
4679
|
+
fact("Latest", field(data, "latest")),
|
|
4680
|
+
fact("Install", field(data, "install")),
|
|
4681
|
+
...data.message ? [fact("Advice", field(data, "message"))] : []
|
|
4682
|
+
],
|
|
4683
|
+
sections: []
|
|
4684
|
+
};
|
|
4685
|
+
}
|
|
4330
4686
|
|
|
4331
4687
|
// src/cli/commands.ts
|
|
4332
4688
|
var COMMANDS = [
|
|
@@ -4379,9 +4735,9 @@ async function semanticFailure(command, error, options, writer) {
|
|
|
4379
4735
|
writer
|
|
4380
4736
|
);
|
|
4381
4737
|
}
|
|
4382
|
-
function textDefinition(
|
|
4738
|
+
function textDefinition(id2, data) {
|
|
4383
4739
|
return {
|
|
4384
|
-
id,
|
|
4740
|
+
id: id2,
|
|
4385
4741
|
mode: "finite",
|
|
4386
4742
|
output: {
|
|
4387
4743
|
formats: ["brief", "json", "jsonl"],
|
|
@@ -4391,11 +4747,11 @@ function textDefinition(id, data) {
|
|
|
4391
4747
|
return result(data);
|
|
4392
4748
|
},
|
|
4393
4749
|
present({ data: data2 }) {
|
|
4394
|
-
return {
|
|
4395
|
-
heading:
|
|
4396
|
-
status: "
|
|
4397
|
-
facts:
|
|
4398
|
-
sections:
|
|
4750
|
+
return data2.version ? { heading: `ryugi-artifacts ${data2.version}`, status: "", facts: [], sections: [] } : {
|
|
4751
|
+
heading: "Help",
|
|
4752
|
+
status: "",
|
|
4753
|
+
facts: [],
|
|
4754
|
+
sections: [{ kind: "content", key: "text", text: data2.text }]
|
|
4399
4755
|
};
|
|
4400
4756
|
}
|
|
4401
4757
|
};
|
|
@@ -4413,10 +4769,10 @@ async function dispatchSemantic(argv, commands, browseOptions, version, options,
|
|
|
4413
4769
|
}
|
|
4414
4770
|
if (name === "--help" || name === "-h" || command && wantsHelp(rest)) {
|
|
4415
4771
|
if (!command) parse(rest, {}, 0);
|
|
4416
|
-
const
|
|
4772
|
+
const text2 = command ? commandHelp(command) : rootHelp(commands, browseOptions);
|
|
4417
4773
|
return await bindCommand(
|
|
4418
4774
|
textDefinition("help", {
|
|
4419
|
-
text,
|
|
4775
|
+
text: text2,
|
|
4420
4776
|
commands: commands.map(({ name: name2, summary }) => ({ name: name2, summary }))
|
|
4421
4777
|
}),
|
|
4422
4778
|
void 0
|
|
@@ -4474,7 +4830,7 @@ async function main(argv) {
|
|
|
4474
4830
|
process.on("SIGINT", interrupt);
|
|
4475
4831
|
process.on("SIGTERM", terminate);
|
|
4476
4832
|
try {
|
|
4477
|
-
return await dispatchSemantic(argv, COMMANDS, BROWSE_OPTIONS, "1.
|
|
4833
|
+
return await dispatchSemantic(argv, COMMANDS, BROWSE_OPTIONS, "1.65.0", selection.options, writer, abort.signal);
|
|
4478
4834
|
} finally {
|
|
4479
4835
|
process.removeListener("SIGINT", interrupt);
|
|
4480
4836
|
process.removeListener("SIGTERM", terminate);
|