@astrosheep/keiyaku 4.5.19 → 4.5.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +14 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +53 -20
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/references/automation.md +237 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +6 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +2 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -3
- package/build/src/akuma/akuma-handle.d.ts +5 -1
- package/build/src/akuma/akuma-handle.js +4 -1
- package/build/src/akuma/akuma-instance.d.ts +7 -2
- package/build/src/akuma/akuma-instance.js +14 -7
- package/build/src/akuma/akuma-observe.d.ts +11 -0
- package/build/src/akuma/akuma-observe.js +23 -0
- package/build/src/akuma/akuma-product.d.ts +2 -0
- package/build/src/akuma/akuma-product.js +6 -0
- package/build/src/akuma/akuma.d.ts +20 -1
- package/build/src/akuma/akuma.js +2 -0
- package/build/src/akuma/allowed.d.ts +20 -0
- package/build/src/akuma/allowed.js +11 -0
- package/build/src/akuma/archetype.js +3 -0
- package/build/src/akuma/body.d.ts +25 -5
- package/build/src/akuma/body.js +70 -31
- package/build/src/akuma/call-request.d.ts +5 -0
- package/build/src/akuma/call-request.js +14 -4
- package/build/src/akuma/fleet-execution.d.ts +28 -0
- package/build/src/akuma/fleet-execution.js +36 -4
- package/build/src/akuma/fleet-observation.d.ts +54 -0
- package/build/src/akuma/fleet-request.d.ts +10 -0
- package/build/src/akuma/fleet-request.js +13 -3
- package/build/src/akuma/heart/facts.d.ts +2 -0
- package/build/src/akuma/heart/index.d.ts +1 -0
- package/build/src/akuma/heart/index.js +4 -1
- package/build/src/akuma/heart/rows.d.ts +2 -0
- package/build/src/akuma/heart/rows.js +7 -5
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +3 -1
- package/build/src/akuma/heart/tells.js +6 -5
- package/build/src/akuma/heart/timeline.js +1 -1
- package/build/src/akuma/provider-recipe.d.ts +1 -0
- package/build/src/akuma/provider-recipe.js +5 -0
- package/build/src/akuma/provider.d.ts +1 -1
- package/build/src/akuma/provider.js +1 -1
- package/build/src/akuma/providers/acp/core.js +3 -6
- package/build/src/akuma/providers/acp/index.js +3 -0
- package/build/src/akuma/providers/claude/index.js +10 -10
- package/build/src/akuma/providers/codex-app-server/index.js +12 -11
- package/build/src/akuma/providers/execution-environment.d.ts +6 -0
- package/build/src/akuma/providers/execution-environment.js +24 -0
- package/build/src/akuma/providers/grok-build/index.js +3 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +32 -23
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +8 -1
- package/build/src/akuma/providers/opencode-sdk/session.js +6 -5
- package/build/src/akuma/providers/pi/events.js +7 -2
- package/build/src/akuma/providers/pi/index.js +5 -2
- package/build/src/akuma/request-observation.d.ts +45 -0
- package/build/src/akuma/request-observation.js +162 -0
- package/build/src/akuma/request-rendezvous.d.ts +6 -3
- package/build/src/akuma/request-rendezvous.js +80 -14
- package/build/src/akuma/request-serve.js +27 -4
- package/build/src/akuma/request-wire.d.ts +5 -0
- package/build/src/akuma/request-wire.js +2 -0
- package/build/src/akuma/turn-drive.d.ts +1 -0
- package/build/src/akuma/turn-drive.js +2 -0
- package/build/src/akuma-body.js +5 -0
- package/build/src/body/amend.js +6 -4
- package/build/src/body/decode.d.ts +3 -1
- package/build/src/body/decode.js +53 -17
- package/build/src/body/region.d.ts +9 -1
- package/build/src/body/region.js +87 -12
- package/build/src/body/render.js +1 -1
- package/build/src/body/verification.d.ts +3 -1
- package/build/src/body/verification.js +4 -1
- package/build/src/cli/accepted.js +19 -2
- package/build/src/cli/commands/akuma-invoke.d.ts +3 -1
- package/build/src/cli/commands/akuma-invoke.js +134 -14
- package/build/src/cli/commands/akuma.js +24 -12
- package/build/src/cli/commands/contract-help.d.ts +15 -15
- package/build/src/cli/commands/contract-help.js +45 -19
- package/build/src/cli/commands/contract-invoke.d.ts +3 -0
- package/build/src/cli/commands/contract-invoke.js +25 -11
- package/build/src/cli/commands/contract.js +6 -4
- package/build/src/cli/commands/install.d.ts +1 -1
- package/build/src/cli/commands/install.js +1 -1
- package/build/src/cli/commands/status-set.js +15 -24
- package/build/src/cli/commands/task.js +18 -18
- package/build/src/cli/invoke.d.ts +3 -0
- package/build/src/cli/invoke.js +58 -23
- package/build/src/cli/main.js +5 -0
- package/build/src/cli/parse.d.ts +3 -0
- package/build/src/cli/parse.js +26 -4
- package/build/src/cli/render/akuma-activity.d.ts +100 -2
- package/build/src/cli/render/akuma-activity.js +485 -40
- package/build/src/cli/render/akuma.d.ts +10 -0
- package/build/src/cli/render/akuma.js +31 -21
- package/build/src/cli/render/audit.js +1 -1
- package/build/src/cli/render/board.js +1 -1
- package/build/src/cli/render/catalog.js +16 -13
- package/build/src/cli/render/contract-history.js +39 -10
- package/build/src/cli/render/contract-observation.js +10 -6
- package/build/src/cli/render/contract.js +109 -106
- package/build/src/cli/render/execution-progress.d.ts +26 -0
- package/build/src/cli/render/execution-progress.js +178 -0
- package/build/src/cli/render/kanshi-akuma.js +27 -39
- package/build/src/cli/render/kanshi.js +33 -26
- package/build/src/cli/render/nuke.js +1 -1
- package/build/src/cli/render/receipt.d.ts +1 -1
- package/build/src/cli/render/receipt.js +6 -6
- package/build/src/cli/render/refusal.js +10 -7
- package/build/src/cli/render/region.js +1 -1
- package/build/src/cli/render/settings.js +12 -2
- package/build/src/cli/render/status-line.d.ts +30 -0
- package/build/src/cli/render/status-line.js +58 -0
- package/build/src/cli/render/status-set.js +1 -1
- package/build/src/cli/render/task.d.ts +2 -0
- package/build/src/cli/render/task.js +11 -7
- package/build/src/cli/render/terminal.d.ts +0 -1
- package/build/src/cli/render/terminal.js +47 -15
- package/build/src/cli/result.d.ts +1 -0
- package/build/src/cli/runtime.d.ts +2 -0
- package/build/src/cli/runtime.js +36 -4
- package/build/src/cli/usage.js +2 -2
- package/build/src/cli/version.d.ts +1 -0
- package/build/src/cli/version.js +25 -0
- package/build/src/git/hooks.d.ts +13 -1
- package/build/src/git/hooks.js +2 -1
- package/build/src/git/workspace.d.ts +1 -1
- package/build/src/git/workspace.js +1 -1
- package/build/src/identity/mint.d.ts +13 -0
- package/build/src/identity/mint.js +26 -0
- package/build/src/identity/normalize.d.ts +4 -0
- package/build/src/identity/normalize.js +30 -0
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +1 -0
- package/build/src/kanshi/read.js +17 -4
- package/build/src/kanshi/report.d.ts +1 -0
- package/build/src/library/akuma-creation.d.ts +2 -0
- package/build/src/library/akuma-creation.js +34 -18
- package/build/src/library/audit.d.ts +2 -0
- package/build/src/library/audit.js +1 -0
- package/build/src/library/bind.js +18 -16
- package/build/src/library/composition.d.ts +1 -0
- package/build/src/library/contract-bind.d.ts +3 -1
- package/build/src/library/contract-bind.js +5 -3
- package/build/src/library/contract-execution.d.ts +2 -0
- package/build/src/library/contract-execution.js +15 -1
- package/build/src/library/contract-forwarding.d.ts +4 -0
- package/build/src/library/contract-forwarding.js +3 -0
- package/build/src/library/contract-handle.d.ts +7 -0
- package/build/src/library/contract-handle.js +25 -0
- package/build/src/library/contract-operations.d.ts +7 -2
- package/build/src/library/contract-operations.js +21 -1
- package/build/src/library/contract-types.d.ts +1 -0
- package/build/src/library/execution-result.d.ts +2 -2
- package/build/src/library/execution.d.ts +8 -0
- package/build/src/library/execution.js +102 -0
- package/build/src/library/fleet.d.ts +4 -1
- package/build/src/library/fleet.js +32 -8
- package/build/src/library/keiyaku.d.ts +2 -0
- package/build/src/library/mutation.js +15 -7
- package/build/src/plugin/akuma-signals.d.ts +6 -0
- package/build/src/plugin/akuma-signals.js +9 -1
- package/build/src/plugin/public.d.ts +6 -2
- package/build/src/plugin/runtime.d.ts +1 -3
- package/build/src/plugin/runtime.js +95 -103
- package/build/src/protocol/amend.js +4 -3
- package/build/src/protocol/attempt.d.ts +2 -0
- package/build/src/protocol/bind.js +41 -14
- package/build/src/protocol/completion.d.ts +3 -0
- package/build/src/protocol/completion.js +35 -11
- package/build/src/protocol/deliver.js +165 -92
- package/build/src/protocol/execution-observation.d.ts +181 -0
- package/build/src/protocol/execution-observation.js +45 -0
- package/build/src/protocol/intent.d.ts +18 -22
- package/build/src/protocol/intent.js +63 -41
- package/build/src/protocol/operations.d.ts +2 -0
- package/build/src/protocol/placement.js +5 -1
- package/build/src/protocol/progress.d.ts +5 -1
- package/build/src/protocol/progress.js +10 -1
- package/build/src/protocol/read/status.d.ts +1 -0
- package/build/src/protocol/read/status.js +10 -2
- package/build/src/protocol/reintegrate.d.ts +1 -1
- package/build/src/protocol/reintegrate.js +70 -43
- package/build/src/protocol/result-codec.js +27 -11
- package/build/src/protocol/review.js +53 -30
- package/build/src/protocol/run.d.ts +83 -36
- package/build/src/protocol/run.js +90 -75
- package/build/src/runtime/proc/run.d.ts +16 -4
- package/build/src/runtime/proc/run.js +64 -22
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settings.js +5 -14
- package/build/src/task/document.d.ts +5 -1
- package/build/src/task/document.js +6 -1
- package/build/src/verification/execution.d.ts +10 -2
- package/build/src/verification/execution.js +143 -42
- package/build/src/verification/observation.d.ts +41 -0
- package/build/src/verification/observation.js +29 -0
- package/package.json +3 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { abbreviateGitIds, afterWording, candidateFact, dependentWording, displayGitId, gateFact, gitIdsInRow, mergeSummary, verificationFact, targetFacts, } from "./contract-observation.js";
|
|
2
2
|
import { entityLines, elapsedMilliseconds, identityLine, plumbFacts, RECENT_TONE_MS, renderSectionBlock, linkedEntityLines, safeText, tone, } from "./terminal.js";
|
|
3
3
|
import { akumaMark, endpointFact, formatAge, NARROW_COLUMNS, renderAkuma } from "./kanshi-akuma.js";
|
|
4
|
+
import { dispositionText } from "./task.js";
|
|
4
5
|
const REVIEW_ATTENTION_MS = 15 * 60 * 1_000;
|
|
5
6
|
const PENDING_ATTENTION_MS = 60 * 60 * 1_000;
|
|
6
7
|
function contractHasError(row) {
|
|
@@ -26,22 +27,22 @@ function contractMark(row) {
|
|
|
26
27
|
if (row.phase === "claimed")
|
|
27
28
|
return "✓";
|
|
28
29
|
if (row.phase === "abandoned")
|
|
29
|
-
return "
|
|
30
|
+
return "×";
|
|
30
31
|
if (row.title === null)
|
|
31
32
|
return "?";
|
|
32
33
|
if (row.gates.reports.some((report) => report.current.kind === "attested" && report.current.verdict === "unsatisfied"))
|
|
33
34
|
return "!";
|
|
34
35
|
if (row.targetLag.kind === "unknown")
|
|
35
36
|
return "?";
|
|
36
|
-
if (row.phase === "waiting")
|
|
37
|
-
return "
|
|
37
|
+
if (row.phase === "waiting" || row.phase === "tendered")
|
|
38
|
+
return "⧗";
|
|
38
39
|
return "●";
|
|
39
40
|
}
|
|
40
41
|
function taskMark(row) {
|
|
41
42
|
if (row.disposition === "done")
|
|
42
43
|
return "✓";
|
|
43
44
|
if (row.disposition === "drop")
|
|
44
|
-
return "
|
|
45
|
+
return "×";
|
|
45
46
|
if (row.disposition === "on_hold")
|
|
46
47
|
return "⧗";
|
|
47
48
|
return row.disposition === "in_progress" ? "●" : row.disposition === "blocked" ? "‖" : "○";
|
|
@@ -93,7 +94,9 @@ function linkedTask(report, taskId) {
|
|
|
93
94
|
if (report.tasks.kind !== "present")
|
|
94
95
|
return `! ${taskId} · unavailable`;
|
|
95
96
|
const task = report.tasks.value.rows.find((candidate) => candidate.id === taskId);
|
|
96
|
-
return task === undefined
|
|
97
|
+
return task === undefined
|
|
98
|
+
? `! ${taskId} · unavailable`
|
|
99
|
+
: `${taskMark(task)} ${task.id} · ${dispositionText(task.disposition)}`;
|
|
97
100
|
}
|
|
98
101
|
function linkedAkuma(report, id, aliases) {
|
|
99
102
|
const alias = aliases.length === 0 ? "" : ` (${aliases.join(" ")})`;
|
|
@@ -139,13 +142,10 @@ function linkedAkumaSummary(row, report) {
|
|
|
139
142
|
facts.push(`${row.fleet.length - known.length} unavailable`);
|
|
140
143
|
return facts.join(" · ");
|
|
141
144
|
}
|
|
142
|
-
function semanticBlock(
|
|
145
|
+
function semanticBlock(_name, facts, _context) {
|
|
143
146
|
if (facts.length === 0)
|
|
144
147
|
return [];
|
|
145
|
-
|
|
146
|
-
for (const fact of facts)
|
|
147
|
-
lines.push(` ${safeText(fact)}`);
|
|
148
|
-
return lines;
|
|
148
|
+
return facts.map((fact) => ` ${safeText(fact)}`);
|
|
149
149
|
}
|
|
150
150
|
function namespaceTaskFacts(row) {
|
|
151
151
|
if (row.namespaceTasks === undefined)
|
|
@@ -155,7 +155,7 @@ function namespaceTaskFacts(row) {
|
|
|
155
155
|
if (row.namespaceTasks.kind === "failed") {
|
|
156
156
|
return [`failed ${row.namespaceTasks.failure.message}`];
|
|
157
157
|
}
|
|
158
|
-
return row.namespaceTasks.value.map((task) => `${taskMark(task)} ${task.id} · ${task.disposition} · P${task.priority} · ${task.title}`);
|
|
158
|
+
return row.namespaceTasks.value.map((task) => `${taskMark(task)} ${task.id} · ${dispositionText(task.disposition)} · P${task.priority} · ${task.title}`);
|
|
159
159
|
}
|
|
160
160
|
function renderSelectedContractRow(row, report, context, abbreviations) {
|
|
161
161
|
const title = row.title ?? "title unavailable";
|
|
@@ -195,7 +195,7 @@ function renderSelectedContractRow(row, report, context, abbreviations) {
|
|
|
195
195
|
lines.push(...semanticBlock("namespace tasks", namespaceTaskFacts(row), context));
|
|
196
196
|
const observation = row.workspaceObservation;
|
|
197
197
|
if ((observation.kind === "clean" || observation.kind === "dirty") && observation.merge?.recovery !== undefined) {
|
|
198
|
-
lines.push(` deliver ${safeText(observation.merge.recovery.
|
|
198
|
+
lines.push(` deliver ${safeText(observation.merge.recovery.deliver)} · reads worktree bytes, not index`);
|
|
199
199
|
}
|
|
200
200
|
return lines;
|
|
201
201
|
}
|
|
@@ -218,7 +218,7 @@ function renderWorldContractRow(row, report, context) {
|
|
|
218
218
|
const contractFacts = [
|
|
219
219
|
candidateFact(row.delivery),
|
|
220
220
|
...targetFacts(row, gitAbbreviations(report)),
|
|
221
|
-
...
|
|
221
|
+
...[],
|
|
222
222
|
...(linkedAkumaSummary(row, report) === undefined ? [] : [linkedAkumaSummary(row, report)]),
|
|
223
223
|
...row.after.map(afterWording),
|
|
224
224
|
...(row.dependents.length === 0 ? [] : [`dependents ${row.dependents.map(dependentWording).join(" · ")}`]),
|
|
@@ -245,6 +245,8 @@ function renderContracts(report, context) {
|
|
|
245
245
|
return ["CONTRACTS // absent", "", " contracts absent"];
|
|
246
246
|
if (section.kind === "failed")
|
|
247
247
|
return ["CONTRACTS // unavailable", "", tone(`! ${safeText(section.failure.message)}`, "alert", context.color)];
|
|
248
|
+
if (section.value.rows.length === 0)
|
|
249
|
+
return [];
|
|
248
250
|
const rendered = renderSectionBlock({
|
|
249
251
|
name: "CONTRACTS",
|
|
250
252
|
rows: section.value.rows.map((row) => renderWorldContractRow(row, report, context)),
|
|
@@ -263,27 +265,37 @@ function renderSelectedContract(report, context) {
|
|
|
263
265
|
? [" keiyaku absent"]
|
|
264
266
|
: renderSelectedContractRow(row, report, context, gitAbbreviations(report));
|
|
265
267
|
}
|
|
268
|
+
function taskFailureFact(failure) {
|
|
269
|
+
return failure.coordinate === undefined ? failure.message : `${failure.coordinate} · failed ${failure.message}`;
|
|
270
|
+
}
|
|
266
271
|
function renderTasks(report, context) {
|
|
267
272
|
const section = report.tasks;
|
|
268
273
|
if (section.kind === "absent")
|
|
269
274
|
return ["TASKS // absent", "", " tasks absent"];
|
|
270
275
|
if (section.kind === "failed")
|
|
271
|
-
return [
|
|
276
|
+
return [
|
|
277
|
+
"TASKS // unavailable",
|
|
278
|
+
"",
|
|
279
|
+
tone(`! ${safeText(taskFailureFact(section.failure))}`, "alert", context.color),
|
|
280
|
+
];
|
|
272
281
|
const rows = section.value.rows;
|
|
282
|
+
if (rows.length === 0)
|
|
283
|
+
return [];
|
|
273
284
|
const rowLines = rows.map((row) => {
|
|
274
|
-
const relation = row.contract === undefined ? [
|
|
285
|
+
const relation = row.contract === undefined ? [] : [endpointFact(row.contract.id, row.contract.observed)];
|
|
275
286
|
const childFacts = row.children === undefined ? [] : [`children ${row.children.live} live · ${row.children.total} total`];
|
|
276
287
|
const blockerFacts = (row.blockers ?? []).map((blocker) => `blocked ${blocker.id}`);
|
|
288
|
+
const association = relation.length === 0 ? "" : ` · ${relation.join(" · ")}`;
|
|
277
289
|
if (context.columns > NARROW_COLUMNS) {
|
|
278
290
|
return [
|
|
279
|
-
identityLine(taskMark(row), row.id, `· ${row.disposition} · P${row.priority} · ${row.title}
|
|
291
|
+
identityLine(taskMark(row), row.id, `· ${dispositionText(row.disposition)} · P${row.priority} · ${row.title}${association}`),
|
|
280
292
|
...plumbFacts([...childFacts, ...blockerFacts], context.columns),
|
|
281
293
|
];
|
|
282
294
|
}
|
|
283
295
|
return entityLines({
|
|
284
296
|
mark: taskMark(row),
|
|
285
297
|
identity: row.id,
|
|
286
|
-
state: `${row.disposition} · P${row.priority}`,
|
|
298
|
+
state: `${dispositionText(row.disposition)} · P${row.priority}`,
|
|
287
299
|
title: row.title,
|
|
288
300
|
facts: [...relation, ...childFacts, ...blockerFacts],
|
|
289
301
|
context,
|
|
@@ -301,13 +313,8 @@ function renderTasks(report, context) {
|
|
|
301
313
|
export function renderKanshiText(report, context = { columns: 80, color: false }, selection = "world") {
|
|
302
314
|
if (selection === "contract")
|
|
303
315
|
return renderSelectedContract(report, context).join("\n");
|
|
304
|
-
return [
|
|
305
|
-
|
|
306
|
-
""
|
|
307
|
-
|
|
308
|
-
"",
|
|
309
|
-
...renderAkuma(report, context),
|
|
310
|
-
"",
|
|
311
|
-
...renderTasks(report, context),
|
|
312
|
-
].join("\n");
|
|
316
|
+
return [renderContracts(report, context), renderAkuma(report, context), renderTasks(report, context)]
|
|
317
|
+
.filter((block) => block.length > 0)
|
|
318
|
+
.map((block) => block.join("\n"))
|
|
319
|
+
.join("\n\n");
|
|
313
320
|
}
|
|
@@ -5,7 +5,7 @@ export function renderNukeText(result) {
|
|
|
5
5
|
if (result.kind === "success") {
|
|
6
6
|
return [`✓ nuke ${result.world}`, ...seatClose].join("\n");
|
|
7
7
|
}
|
|
8
|
-
return [
|
|
8
|
+
return [`× nuke ${result.world}`, ` diagnostic ${result.diagnostic}`, ...seatClose].join("\n");
|
|
9
9
|
}
|
|
10
10
|
export function nukeExitCode(result) {
|
|
11
11
|
return result.kind === "failed" ? 2 : 0;
|
|
@@ -10,7 +10,7 @@ type HookFailure = Extract<Lag, {
|
|
|
10
10
|
}>["failure"];
|
|
11
11
|
export declare function receiptRow(lines: string[], mark: string, label: string, segments: readonly ReceiptSegment[], columns: number): void;
|
|
12
12
|
export declare function receiptPayload(lines: string[], label: string, payload: string): void;
|
|
13
|
-
export declare function outcomeLines(mark: "✓" | "
|
|
13
|
+
export declare function outcomeLines(mark: "✓" | "×" | "!" | "?", verb: string, word: "accepted" | "refused" | "retry", contract: string | undefined, columns?: number): string[];
|
|
14
14
|
export declare function titleLines(mark: string, title: string, contract: string, columns?: number): string[];
|
|
15
15
|
export declare function hookFailureSummary(failure: HookFailure): string;
|
|
16
16
|
export declare function appendHookPayload(lines: string[], failure: HookFailure): void;
|
|
@@ -21,7 +21,7 @@ export function receiptRow(lines, mark, label, segments, columns) {
|
|
|
21
21
|
lines.push(current);
|
|
22
22
|
}
|
|
23
23
|
export function receiptPayload(lines, label, payload) {
|
|
24
|
-
lines.push(label, "",
|
|
24
|
+
lines.push(label, ...renderOpaqueBlock(payload, " ", 80), "");
|
|
25
25
|
}
|
|
26
26
|
export function outcomeLines(mark, verb, word, contract, columns = 80) {
|
|
27
27
|
const base = `${mark} ${verb} ${word}`;
|
|
@@ -53,13 +53,13 @@ export function appendHookPayload(lines, failure) {
|
|
|
53
53
|
return;
|
|
54
54
|
if (failure.stdout.length > 0)
|
|
55
55
|
receiptPayload(lines, "stdout", failure.stdout);
|
|
56
|
-
if (failure.stderr.length > 0)
|
|
56
|
+
if (failure.stderr !== undefined && failure.stderr.length > 0)
|
|
57
57
|
receiptPayload(lines, "stderr", failure.stderr);
|
|
58
58
|
}
|
|
59
59
|
export function reuseLines(reuse, columns) {
|
|
60
60
|
if (reuse === undefined)
|
|
61
61
|
return [];
|
|
62
|
-
return renderOpaqueBlock(`reuse
|
|
62
|
+
return renderOpaqueBlock(`reuse verified · ${reuse.verdict} · ${reuse.entry}`, " ", columns);
|
|
63
63
|
}
|
|
64
64
|
function prerequisiteRows(stop, columns) {
|
|
65
65
|
if (!("refusal" in stop) || stop.refusal?.kind !== "prerequisites-unsatisfied")
|
|
@@ -131,10 +131,10 @@ function refusalEvidence(stop, columns) {
|
|
|
131
131
|
recovery !== null &&
|
|
132
132
|
"materialize" in recovery &&
|
|
133
133
|
typeof recovery.materialize === "string" &&
|
|
134
|
-
"
|
|
135
|
-
typeof recovery.
|
|
134
|
+
"deliver" in recovery &&
|
|
135
|
+
typeof recovery.deliver === "string") {
|
|
136
136
|
receiptRow(lines, " ", "materialize", [{ text: recovery.materialize }], columns);
|
|
137
|
-
receiptRow(lines, " ", "deliver", [{ text: recovery.
|
|
137
|
+
receiptRow(lines, " ", "deliver", [{ text: recovery.deliver }], columns);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
else if (refusal.kind === "integration-unsupported") {
|
|
@@ -7,9 +7,12 @@ function wrap(lines, text, indent, columns) {
|
|
|
7
7
|
}
|
|
8
8
|
function collectionLines(name, members, indent) {
|
|
9
9
|
if (members.length === 0)
|
|
10
|
-
return [
|
|
10
|
+
return [];
|
|
11
11
|
return [`${indent}${name}`, ...members.map((member) => `${indent} ${safeText(member)}`)];
|
|
12
12
|
}
|
|
13
|
+
function shortGitId(value) {
|
|
14
|
+
return /^[0-9a-f]{40}$/iu.test(value) ? value.slice(0, 7) : value;
|
|
15
|
+
}
|
|
13
16
|
function skipAddressedContract(addressed, contractId) {
|
|
14
17
|
return addressed !== undefined && contractId === addressed;
|
|
15
18
|
}
|
|
@@ -66,7 +69,7 @@ export function renderRefusalFacts(refusal, indent, columns, addressed) {
|
|
|
66
69
|
lines.push(...collectionLines("conflicts", refusal.conflictPaths, indent));
|
|
67
70
|
if ("recovery" in refusal && refusal.recovery !== undefined) {
|
|
68
71
|
lines.push(`${indent}materialize ${safeText(refusal.recovery.materialize)}`);
|
|
69
|
-
lines.push(`${indent}deliver ${safeText(refusal.recovery.
|
|
72
|
+
lines.push(`${indent}deliver ${safeText(refusal.recovery.deliver)}`);
|
|
70
73
|
}
|
|
71
74
|
return lines;
|
|
72
75
|
}
|
|
@@ -90,7 +93,7 @@ export function renderRefusalFacts(refusal, indent, columns, addressed) {
|
|
|
90
93
|
}
|
|
91
94
|
export function renderRefusal(result, context) {
|
|
92
95
|
const columns = context?.columns ?? 80;
|
|
93
|
-
const base =
|
|
96
|
+
const base = `× ${result.verb} refused`;
|
|
94
97
|
const lines = result.contract === undefined
|
|
95
98
|
? [base]
|
|
96
99
|
: displayColumns(`${base} ${result.contract}`) <= columns
|
|
@@ -106,14 +109,14 @@ export function renderConflictMaterialized(result, _context) {
|
|
|
106
109
|
const indent = " ";
|
|
107
110
|
return [
|
|
108
111
|
"! integration-conflict-materialized",
|
|
109
|
-
`${indent}target ${
|
|
110
|
-
`${indent}
|
|
112
|
+
`${indent}target ${shortGitId(result.targetHead)}`,
|
|
113
|
+
`${indent}delivery none`,
|
|
111
114
|
`${indent}index unmerged`,
|
|
112
115
|
`${indent}saved worktree bytes before projection`,
|
|
113
|
-
`${indent}handoff base ${
|
|
116
|
+
`${indent}handoff base ${shortGitId(result.handoffBase)}`,
|
|
114
117
|
...collectionLines("conflicts", result.conflictPaths, indent),
|
|
115
118
|
`${indent}workspace ${safeText(result.workspace.path)}`,
|
|
116
|
-
`${indent}deliver ${safeText(result.recovery.
|
|
119
|
+
`${indent}deliver ${safeText(result.recovery.deliver)} · reads worktree bytes, not index`,
|
|
117
120
|
].join("\n");
|
|
118
121
|
}
|
|
119
122
|
export function renderBindDraftReceipt(receipt) {
|
|
@@ -14,7 +14,7 @@ function rows(section) {
|
|
|
14
14
|
if (section.kind === "absent")
|
|
15
15
|
return [];
|
|
16
16
|
if (section.kind === "failed")
|
|
17
|
-
return [
|
|
17
|
+
return [`× region`, ` diagnostic ${section.failure.message}`];
|
|
18
18
|
const value = section.value;
|
|
19
19
|
if (value.kind === "declarations") {
|
|
20
20
|
if (value.declarations.length === 0)
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { displayColumns, renderTextBlock } from "./terminal.js";
|
|
2
|
-
import { fieldName
|
|
2
|
+
import { fieldName } from "./value.js";
|
|
3
|
+
function settingValueLines(name, value, indent) {
|
|
4
|
+
const secret = /(?:key|token|secret|password|credential)/iu.test(name);
|
|
5
|
+
if (secret && value !== undefined && value !== null && String(value).length > 0)
|
|
6
|
+
return [`${indent}${fieldName(name)} [redacted]`];
|
|
7
|
+
if (value === null || typeof value !== "object")
|
|
8
|
+
return [`${indent}${fieldName(name)} ${String(value)}`];
|
|
9
|
+
if (Array.isArray(value))
|
|
10
|
+
return value.flatMap((item, index) => settingValueLines(`${name}.${index}`, item, indent));
|
|
11
|
+
return Object.entries(value).flatMap(([key, item]) => settingValueLines(`${name}.${key}`, item, indent));
|
|
12
|
+
}
|
|
3
13
|
function namespaceNames(value) {
|
|
4
14
|
return [
|
|
5
15
|
...new Set([value.scopes.user, value.scopes.project].flatMap((scope) => (scope.kind === "read" ? scope.namespaces : []))),
|
|
@@ -38,7 +48,7 @@ export function renderSettingsText(value, columns = 80) {
|
|
|
38
48
|
}
|
|
39
49
|
for (const entry of view.entries) {
|
|
40
50
|
lines.push(` entry ${fieldName(entry.name)} · ${entry.source}${entry.shadows ? " · shadows user" : ""}`);
|
|
41
|
-
lines.push(...
|
|
51
|
+
lines.push(...settingValueLines("value", entry.value, " "));
|
|
42
52
|
}
|
|
43
53
|
}
|
|
44
54
|
return lines.join("\n");
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type StatusLineStream = NodeJS.WritableStream & Readonly<{
|
|
2
|
+
isTTY?: boolean;
|
|
3
|
+
}>;
|
|
4
|
+
type IntervalHandle = ReturnType<typeof setInterval>;
|
|
5
|
+
export type StatusLineOptions = Readonly<{
|
|
6
|
+
now?: () => number;
|
|
7
|
+
intervalMs?: number;
|
|
8
|
+
schedule?: (tick: () => void, every: number) => IntervalHandle;
|
|
9
|
+
cancel?: (handle: IntervalHandle) => void;
|
|
10
|
+
}>;
|
|
11
|
+
/** A terminal-only, ephemeral line. It owns neither execution nor its outcome. */
|
|
12
|
+
export declare class StatusLine {
|
|
13
|
+
private readonly stream;
|
|
14
|
+
readonly isTTY: boolean;
|
|
15
|
+
private readonly now;
|
|
16
|
+
private readonly intervalMs;
|
|
17
|
+
private readonly schedule;
|
|
18
|
+
private readonly cancel;
|
|
19
|
+
private timer;
|
|
20
|
+
private format;
|
|
21
|
+
private startedAt;
|
|
22
|
+
constructor(stream: StatusLineStream, options?: StatusLineOptions);
|
|
23
|
+
show(format: (elapsedMs: number) => string): void;
|
|
24
|
+
writeBlock(lines: readonly string[]): void;
|
|
25
|
+
finish(line: string): void;
|
|
26
|
+
private redraw;
|
|
27
|
+
private erase;
|
|
28
|
+
private stop;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** A terminal-only, ephemeral line. It owns neither execution nor its outcome. */
|
|
2
|
+
export class StatusLine {
|
|
3
|
+
stream;
|
|
4
|
+
isTTY;
|
|
5
|
+
now;
|
|
6
|
+
intervalMs;
|
|
7
|
+
schedule;
|
|
8
|
+
cancel;
|
|
9
|
+
timer;
|
|
10
|
+
format;
|
|
11
|
+
startedAt;
|
|
12
|
+
constructor(stream, options = {}) {
|
|
13
|
+
this.stream = stream;
|
|
14
|
+
this.isTTY = stream.isTTY === true;
|
|
15
|
+
this.now = options.now ?? (() => performance.now());
|
|
16
|
+
this.intervalMs = options.intervalMs ?? 1_000;
|
|
17
|
+
this.schedule = options.schedule ?? ((tick, every) => setInterval(tick, every));
|
|
18
|
+
this.cancel = options.cancel ?? ((handle) => clearInterval(handle));
|
|
19
|
+
}
|
|
20
|
+
show(format) {
|
|
21
|
+
if (!this.isTTY)
|
|
22
|
+
return;
|
|
23
|
+
this.format = format;
|
|
24
|
+
this.startedAt ??= this.now();
|
|
25
|
+
this.redraw();
|
|
26
|
+
this.timer ??= this.schedule(() => this.redraw(), this.intervalMs);
|
|
27
|
+
}
|
|
28
|
+
writeBlock(lines) {
|
|
29
|
+
if (lines.length === 0)
|
|
30
|
+
return;
|
|
31
|
+
if (this.isTTY)
|
|
32
|
+
this.erase();
|
|
33
|
+
this.stream.write(`${lines.join("\n")}\n`);
|
|
34
|
+
if (this.isTTY && this.format !== undefined)
|
|
35
|
+
this.redraw();
|
|
36
|
+
}
|
|
37
|
+
finish(line) {
|
|
38
|
+
if (!this.isTTY)
|
|
39
|
+
return;
|
|
40
|
+
this.erase();
|
|
41
|
+
this.stop();
|
|
42
|
+
this.stream.write(`${line}\n`);
|
|
43
|
+
}
|
|
44
|
+
redraw() {
|
|
45
|
+
if (!this.isTTY || this.format === undefined || this.startedAt === undefined)
|
|
46
|
+
return;
|
|
47
|
+
this.stream.write(`\r\u001b[2K${this.format(Math.max(0, this.now() - this.startedAt))}`);
|
|
48
|
+
}
|
|
49
|
+
erase() {
|
|
50
|
+
if (this.isTTY && this.format !== undefined)
|
|
51
|
+
this.stream.write("\r\u001b[2K");
|
|
52
|
+
}
|
|
53
|
+
stop() {
|
|
54
|
+
if (this.timer !== undefined)
|
|
55
|
+
this.cancel(this.timer);
|
|
56
|
+
this.timer = undefined;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -13,7 +13,7 @@ export function renderStatusSetText(result, context) {
|
|
|
13
13
|
status: entry.status,
|
|
14
14
|
...(entry.alias === undefined ? {} : { alias: entry.alias }),
|
|
15
15
|
}, context);
|
|
16
|
-
return
|
|
16
|
+
return body;
|
|
17
17
|
})
|
|
18
18
|
.join("\n\n");
|
|
19
19
|
}
|
|
@@ -3,6 +3,8 @@ import type { TaskInvocationResult } from "../commands/task-invoke.js";
|
|
|
3
3
|
import type { ParsedTaskCommand } from "../commands/task.js";
|
|
4
4
|
import { type TextRenderContext } from "./terminal.js";
|
|
5
5
|
export declare function taskMark(word: string): string;
|
|
6
|
+
/** Task dispositions and relation states are snake_case facts; people read them as words. */
|
|
7
|
+
export declare function dispositionText(word: string): string;
|
|
6
8
|
export declare function renderTaskText(command: ParsedTaskCommand, result: TaskInvocationResult, context?: TextRenderContext): string;
|
|
7
9
|
export declare function renderTaskIncompleteDiagnostic(result: TaskCompositionResult): string;
|
|
8
10
|
export declare function taskExitCode(result: TaskInvocationResult): number;
|
|
@@ -21,16 +21,20 @@ export function taskMark(word) {
|
|
|
21
21
|
if (word === "done")
|
|
22
22
|
return "✓";
|
|
23
23
|
if (word === "drop")
|
|
24
|
-
return "
|
|
24
|
+
return "×";
|
|
25
25
|
return "?";
|
|
26
26
|
}
|
|
27
|
+
/** Task dispositions and relation states are snake_case facts; people read them as words. */
|
|
28
|
+
export function dispositionText(word) {
|
|
29
|
+
return word.replaceAll("_", " ");
|
|
30
|
+
}
|
|
27
31
|
function priorityText(priority) {
|
|
28
32
|
return priority === null ? "P?" : `P${priority}`;
|
|
29
33
|
}
|
|
30
34
|
function scanUnit(id, priority, word) {
|
|
31
35
|
return word === undefined
|
|
32
36
|
? `${taskMark("ready")} ${id} · ${priorityText(priority)}`
|
|
33
|
-
: `${taskMark(word)} ${id} · ${word} · ${priorityText(priority)}`;
|
|
37
|
+
: `${taskMark(word)} ${id} · ${dispositionText(word)} · ${priorityText(priority)}`;
|
|
34
38
|
}
|
|
35
39
|
function entityLines(entity, columns, indent = "") {
|
|
36
40
|
const scan = `${indent}${scanUnit(entity.id, entity.priority, entity.word)}${entity.facts === undefined ? "" : ` · ${entity.facts}`}`;
|
|
@@ -74,7 +78,7 @@ function renderFailure(verb, result, columns) {
|
|
|
74
78
|
if (result.kind === "retry") {
|
|
75
79
|
return [...outcomeLines("?", verb, "retry", undefined, columns), result.reason].join("\n");
|
|
76
80
|
}
|
|
77
|
-
const lines = [...outcomeLines("
|
|
81
|
+
const lines = [...outcomeLines("×", verb, "refused", undefined, columns)];
|
|
78
82
|
const facts = projectRefusal(result.refusal);
|
|
79
83
|
lines.push(facts.line);
|
|
80
84
|
appendDiagnostic(lines, facts.diagnostic);
|
|
@@ -85,7 +89,7 @@ function renderFailure(verb, result, columns) {
|
|
|
85
89
|
}
|
|
86
90
|
function edge(label, ref, mark) {
|
|
87
91
|
const prefix = mark === undefined ? ` ${label}` : ` ${mark} ${label}`;
|
|
88
|
-
return `${prefix} ${ref.id} · ${ref.state}`;
|
|
92
|
+
return `${prefix} ${ref.id} · ${dispositionText(ref.state)}`;
|
|
89
93
|
}
|
|
90
94
|
function pageHeading(view) {
|
|
91
95
|
return view;
|
|
@@ -120,7 +124,7 @@ function renderListRow(item, columns, omitDisposition) {
|
|
|
120
124
|
const lines = [...entityLines(listEntity(item, omitDisposition), columns)];
|
|
121
125
|
if ("blockers" in item) {
|
|
122
126
|
for (const blocker of item.blockers)
|
|
123
|
-
lines.push(` needs ${blocker.id} · ${blocker.state}`);
|
|
127
|
+
lines.push(` needs ${blocker.id} · ${dispositionText(blocker.state)}`);
|
|
124
128
|
}
|
|
125
129
|
return lines;
|
|
126
130
|
}
|
|
@@ -223,7 +227,7 @@ function renderBatchItem(verb, item) {
|
|
|
223
227
|
if (item.outcome.kind === "retry")
|
|
224
228
|
return `? ${verb} ${item.id} ${item.outcome.reason}`;
|
|
225
229
|
const facts = projectRefusal(item.outcome.refusal);
|
|
226
|
-
const lines = [
|
|
230
|
+
const lines = [`× ${verb} ${item.id} ${facts.line}`];
|
|
227
231
|
appendDiagnostic(lines, facts.diagnostic);
|
|
228
232
|
return lines.join("\n");
|
|
229
233
|
}
|
|
@@ -238,7 +242,7 @@ function stoppedLines(stopped) {
|
|
|
238
242
|
if (stopped.kind === "retry")
|
|
239
243
|
return [`? stopped ${stopped.reason}`];
|
|
240
244
|
const facts = projectRefusal(stopped);
|
|
241
|
-
const lines = [
|
|
245
|
+
const lines = [`× stopped ${facts.line}`];
|
|
242
246
|
appendDiagnostic(lines, facts.diagnostic);
|
|
243
247
|
return lines;
|
|
244
248
|
}
|
|
@@ -37,7 +37,6 @@ export type SemanticTone = "dim" | "recent" | "attention" | "alert";
|
|
|
37
37
|
export declare const RECENT_TONE_MS: number;
|
|
38
38
|
export declare function elapsedMilliseconds(source: string | null | undefined, observedAt: string): number | null;
|
|
39
39
|
export declare function tone(value: string, kind: SemanticTone, color: boolean): string;
|
|
40
|
-
export declare function boundedActivity(value: string, columns: number, prefix: string): string;
|
|
41
40
|
export declare function plumbFacts(facts: readonly string[], columns: number): readonly string[];
|
|
42
41
|
export declare function linkedEntityLines(facts: readonly string[], _columns: number): readonly string[];
|
|
43
42
|
export declare function identityLine(mark: string, identity: string, extra?: string): string;
|
|
@@ -12,6 +12,16 @@ export function gitShortStat(stat) {
|
|
|
12
12
|
return parts.join(", ");
|
|
13
13
|
}
|
|
14
14
|
const GRAPHEMES = new Intl.Segmenter("und", { granularity: "grapheme" });
|
|
15
|
+
const NON_ASCII = /[^\x20-\x7e]/u;
|
|
16
|
+
const MARK = /\p{Mark}/u;
|
|
17
|
+
const PICTOGRAPHIC = /\p{Extended_Pictographic}/u;
|
|
18
|
+
const EMOJI_DEFAULT = /\p{Emoji_Presentation}/u;
|
|
19
|
+
const ZWJ = 0x200d;
|
|
20
|
+
const TEXT_PRESENTATION = 0xfe0e;
|
|
21
|
+
const EMOJI_PRESENTATION = 0xfe0f;
|
|
22
|
+
const REGIONAL_FIRST = 0x1f1e6;
|
|
23
|
+
const REGIONAL_LAST = 0x1f1ff;
|
|
24
|
+
const ZERO_WIDTH = new Set([0x200b, 0x200c, 0x200d, 0x200e, 0x200f, 0x2060, 0xfeff]);
|
|
15
25
|
const WIDE_RANGES = [
|
|
16
26
|
[0x1100, 0x115f],
|
|
17
27
|
[0x2329, 0x232a],
|
|
@@ -25,33 +35,59 @@ const WIDE_RANGES = [
|
|
|
25
35
|
[0x1f300, 0x1faff],
|
|
26
36
|
[0x20000, 0x3fffd],
|
|
27
37
|
];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (point ===
|
|
38
|
+
/** Columns one code point occupies when its grapheme cluster gives it no wider form. */
|
|
39
|
+
function baseColumns(point) {
|
|
40
|
+
if (point === 0 || point < 0x20 || (point >= 0x7f && point < 0xa0))
|
|
31
41
|
return 0;
|
|
32
|
-
if (point
|
|
42
|
+
if (ZERO_WIDTH.has(point) || MARK.test(String.fromCodePoint(point)))
|
|
33
43
|
return 0;
|
|
34
44
|
if (point === 0x303f)
|
|
35
45
|
return 1;
|
|
36
46
|
return WIDE_RANGES.some(([first, last]) => point >= first && point <= last) ? 2 : 1;
|
|
37
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Columns one grapheme cluster occupies. A cluster is one terminal cell group even
|
|
50
|
+
* when it is built from many code points, so ZWJ sequences, flags, keycaps and
|
|
51
|
+
* variation selectors never count the width of their parts.
|
|
52
|
+
*/
|
|
53
|
+
function graphemeColumns(cluster) {
|
|
54
|
+
const points = [...cluster].map((character) => character.codePointAt(0));
|
|
55
|
+
if (points.every((point) => point === EMOJI_PRESENTATION || point === TEXT_PRESENTATION))
|
|
56
|
+
return 0;
|
|
57
|
+
const first = points[0];
|
|
58
|
+
if (points.length > 1 && points.every((point) => point >= REGIONAL_FIRST && point <= REGIONAL_LAST))
|
|
59
|
+
return 2;
|
|
60
|
+
// A presentation selector decides a text-default symbol: text stays narrow, emoji widens it.
|
|
61
|
+
if (points.includes(TEXT_PRESENTATION))
|
|
62
|
+
return baseColumns(first);
|
|
63
|
+
if (points.includes(EMOJI_PRESENTATION))
|
|
64
|
+
return 2;
|
|
65
|
+
// A joined pictographic sequence is one wide cluster; a plain text symbol is not.
|
|
66
|
+
if (points.includes(ZWJ) && PICTOGRAPHIC.test(cluster))
|
|
67
|
+
return 2;
|
|
68
|
+
if (EMOJI_DEFAULT.test(cluster))
|
|
69
|
+
return 2;
|
|
70
|
+
return baseColumns(first);
|
|
71
|
+
}
|
|
38
72
|
export function displayColumns(value) {
|
|
73
|
+
if (!NON_ASCII.test(value))
|
|
74
|
+
return value.length;
|
|
39
75
|
let columns = 0;
|
|
40
|
-
for (const
|
|
41
|
-
columns +=
|
|
76
|
+
for (const { segment } of GRAPHEMES.segment(value))
|
|
77
|
+
columns += graphemeColumns(segment);
|
|
42
78
|
return columns;
|
|
43
79
|
}
|
|
44
80
|
export function takeDisplayColumns(value, maximum) {
|
|
45
|
-
const
|
|
81
|
+
const clusters = [...GRAPHEMES.segment(value)].map(({ segment }) => segment);
|
|
46
82
|
let columns = 0;
|
|
47
83
|
let index = 0;
|
|
48
|
-
for (; index <
|
|
49
|
-
const width =
|
|
84
|
+
for (; index < clusters.length; index += 1) {
|
|
85
|
+
const width = graphemeColumns(clusters[index]);
|
|
50
86
|
if (columns + width > maximum)
|
|
51
87
|
break;
|
|
52
88
|
columns += width;
|
|
53
89
|
}
|
|
54
|
-
return { text:
|
|
90
|
+
return { text: clusters.slice(0, index).join(""), rest: clusters.slice(index).join("") };
|
|
55
91
|
}
|
|
56
92
|
export function truncateDisplayText(value, maximum) {
|
|
57
93
|
const clean = safeText(value);
|
|
@@ -210,10 +246,6 @@ export function tone(value, kind, color) {
|
|
|
210
246
|
const code = kind === "dim" ? 2 : kind === "recent" ? 32 : kind === "attention" ? 33 : 31;
|
|
211
247
|
return `\u001b[${code}m${value}\u001b[0m`;
|
|
212
248
|
}
|
|
213
|
-
export function boundedActivity(value, columns, prefix) {
|
|
214
|
-
const budget = Math.max(1, columns - displayColumns(prefix));
|
|
215
|
-
return `activity "${truncateDisplayText(value, Math.max(1, budget - displayColumns('activity ""')))}` + `"`;
|
|
216
|
-
}
|
|
217
249
|
export function plumbFacts(facts, columns) {
|
|
218
250
|
const lines = [];
|
|
219
251
|
let current = " ";
|
|
@@ -255,7 +287,7 @@ export function entityLines(entity) {
|
|
|
255
287
|
];
|
|
256
288
|
}
|
|
257
289
|
export function renderSectionBlock({ name, rows, hasMore = false, }) {
|
|
258
|
-
const lines = [
|
|
290
|
+
const lines = [`${name}`, "", ...rows.flat()];
|
|
259
291
|
if (hasMore)
|
|
260
292
|
lines.push("…");
|
|
261
293
|
return lines;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { TaskInvocationResult } from "./commands/task-invoke.js";
|
|
2
2
|
import type { ParsedCommand, ParsedExecution } from "./parse.js";
|
|
3
|
+
import type { ExecutionEvent } from "../library/execution.js";
|
|
4
|
+
export declare function writeExecutionProgress(events: AsyncIterable<ExecutionEvent>, stream?: NodeJS.WritableStream): Promise<void>;
|
|
3
5
|
export declare function writeTask(command: Extract<ParsedCommand, {
|
|
4
6
|
command: "task";
|
|
5
7
|
}>, result: TaskInvocationResult): Promise<number>;
|