@astrosheep/keiyaku 2.9.3 → 2.9.5
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/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +14 -94
- package/build/agents/harness/activity-values.js +16 -0
- package/build/agents/harness/event-persistence.js +218 -0
- package/build/agents/harness/execution-handle.js +26 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +68 -5
- package/build/agents/harness/projection.js +179 -124
- package/build/agents/harness/provider-adapter.js +58 -0
- package/build/agents/harness/router.js +11 -187
- package/build/agents/harness/runtime.js +17 -4
- package/build/agents/harness/session.js +15 -0
- package/build/agents/launch-snapshot/model.js +15 -236
- package/build/agents/launch-snapshot/parse-helpers.js +114 -0
- package/build/agents/launch-snapshot/resolve.js +17 -43
- package/build/agents/opencode-sdk.js +45 -12
- package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
- package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
- package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
- package/build/agents/providers/codex-app-server/adapter.js +82 -53
- package/build/agents/providers/codex-app-server/events.js +90 -11
- package/build/agents/providers/codex-app-server/identity.js +1 -0
- package/build/agents/providers/codex-app-server/policy.js +29 -0
- package/build/agents/providers/codex-app-server/registration.js +248 -0
- package/build/agents/providers/codex-app-server/session-schema.js +6 -0
- package/build/agents/providers/codex-app-server/session.js +23 -17
- package/build/agents/providers/codex-app-server/terms.js +1 -0
- package/build/agents/providers/opencode-sdk/adapter.js +94 -50
- package/build/agents/providers/opencode-sdk/events.js +8 -4
- package/build/agents/providers/opencode-sdk/registration.js +135 -0
- package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
- package/build/agents/providers/opencode-sdk/session.js +21 -14
- package/build/agents/providers/opencode-sdk/terms.js +1 -0
- package/build/agents/providers/pi/adapter.js +36 -30
- package/build/agents/providers/pi/events.js +4 -3
- package/build/agents/providers/pi/registration.js +145 -0
- package/build/agents/providers/pi/session-schema.js +6 -0
- package/build/agents/providers/pi/terms.js +1 -0
- package/build/agents/providers/registration.js +7 -0
- package/build/agents/providers/registry.js +76 -0
- package/build/agents/selector.js +2 -29
- package/build/agents/types.js +10 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/akuma/meta.js +1 -1
- package/build/cli/commands/akuma/list/meta-ls.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma/view/meta.js +1 -1
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/amend/meta.js +4 -4
- package/build/cli/commands/contract/arc/handler.js +8 -2
- package/build/cli/commands/contract/arc/meta.js +4 -4
- package/build/cli/commands/contract/audit/handler.js +16 -0
- package/build/cli/commands/contract/audit/meta.js +16 -0
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +44 -8
- package/build/cli/commands/contract/catalog.js +2 -0
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/forfeit/meta.js +1 -1
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/log/meta.js +1 -1
- package/build/cli/commands/contract/petition/handler.js +5 -8
- package/build/cli/commands/contract/petition/meta.js +6 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +6 -5
- package/build/cli/commands/metadata.js +59 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/call/meta.js +4 -1
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/kill/meta.js +1 -1
- package/build/cli/commands/projection/revive/meta.js +4 -1
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/status/meta.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/tell/meta.js +4 -1
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +8 -3
- package/build/cli/commands/registry.js +2 -54
- package/build/cli/commands/shared.js +10 -7
- package/build/cli/commands/skills/install/handler.js +2 -5
- package/build/cli/commands/skills/install/meta.js +1 -1
- package/build/cli/commands/skills/skills/handler.js +1 -1
- package/build/cli/commands/skills/skills/meta.js +1 -1
- package/build/cli/commands/system/completion/meta.js +1 -1
- package/build/cli/commands/system/dump-env/meta.js +1 -1
- package/build/cli/commands/system/guide/meta.js +1 -1
- package/build/cli/commands/task/add/handler.js +7 -15
- package/build/cli/commands/task/add/meta.js +4 -1
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/doctor/meta.js +1 -1
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/done/meta.js +1 -1
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/drop/meta.js +1 -1
- package/build/cli/commands/task/ls/handler.js +12 -8
- package/build/cli/commands/task/ls/meta.js +3 -3
- package/build/cli/commands/task/shared.js +14 -4
- package/build/cli/commands/task/{view → show}/handler.js +7 -8
- package/build/cli/commands/task/show/meta.js +8 -0
- package/build/cli/commands/task/start/handler.js +3 -6
- package/build/cli/commands/task/start/meta.js +1 -1
- package/build/cli/commands/task/stop/handler.js +4 -8
- package/build/cli/commands/task/stop/meta.js +1 -1
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/task/meta.js +1 -1
- package/build/cli/commands/task/update/handler.js +6 -11
- package/build/cli/commands/task/update/meta.js +4 -1
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +37 -6
- package/build/cli/help.js +7 -14
- package/build/cli/index.js +112 -154
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/output-stream-error-policy.js +19 -5
- package/build/cli/parse-flags.js +33 -7
- package/build/cli/parse-metadata.js +3 -9
- package/build/cli/parse-selectors.js +2 -1
- package/build/cli/parse.js +35 -5
- package/build/cli/projection-address.js +12 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- package/build/cli/render/audit.js +121 -0
- package/build/cli/render/call.js +11 -5
- package/build/cli/render/errors.js +36 -1
- package/build/cli/render/format.js +4 -0
- package/build/cli/render/kanshi.js +6 -12
- package/build/cli/render/kill.js +9 -0
- package/build/cli/render/misc.js +58 -13
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +15 -6
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +56 -23
- package/build/cli/render/success-response.js +78 -0
- package/build/cli/render/task.js +66 -57
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +63 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +68 -38
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +3 -1
- package/build/config/env.js +3 -0
- package/build/config/provider-policy-ownership.js +3 -32
- package/build/config/settings/disease.js +8 -1
- package/build/config/settings/loader.js +11 -3
- package/build/config/settings/provider-instance-fields.js +51 -0
- package/build/config/settings/schema.js +6 -176
- package/build/core/addressing.js +66 -16
- package/build/core/amend.js +61 -18
- package/build/core/arc.js +33 -73
- package/build/core/audit.js +650 -0
- package/build/core/bind.js +82 -35
- package/build/core/call/call.js +15 -9
- package/build/core/call/context.js +6 -51
- package/build/core/call/execution.js +22 -22
- package/build/core/call/prompt.js +14 -1
- package/build/core/command-markdown.js +45 -0
- package/build/core/context.js +13 -7
- package/build/core/contract-view.js +22 -6
- package/build/core/draft.js +139 -19
- package/build/core/entry.js +3 -4
- package/build/core/forfeit.js +5 -2
- package/build/core/hints.js +1 -75
- package/build/core/identifier-slug.js +66 -0
- package/build/core/ids.js +25 -11
- package/build/core/ledger.js +20 -68
- package/build/core/markdown/lex.js +2 -1
- package/build/core/markdown/parser.js +0 -68
- package/build/core/markdown/render.js +68 -0
- package/build/core/markdown/sections.js +2 -1
- package/build/core/outcome-base.js +4 -0
- package/build/core/projection/generation/database.js +41 -52
- package/build/core/projection/generation/model.js +63 -2
- package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
- package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +36 -53
- package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
- package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +9 -7
- package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
- package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +19 -3
- package/build/core/projection/generation/store.js +3 -3
- package/build/core/projection/generation/transitions.js +19 -3
- package/build/core/projection/index.js +27 -0
- package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
- package/build/core/{projection-alias.js → projection/projection-alias.js} +13 -13
- package/build/core/projection/projection-coordinate.js +61 -0
- package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
- package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +37 -78
- package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
- package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
- package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +16 -2
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +163 -45
- package/build/core/projection/projection-terminal-failure.js +106 -0
- package/build/core/projection/projection-wait.js +275 -0
- package/build/core/projection/projection-wake.js +227 -0
- package/build/core/provider-loader-ports.js +4 -0
- package/build/core/ref-log.js +65 -40
- package/build/core/registry.js +63 -10
- package/build/core/renew-session.js +128 -0
- package/build/core/renew.js +448 -102
- package/build/core/scope.js +272 -68
- package/build/core/seal.js +165 -40
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +8 -8
- package/build/core/{claim.js → settlement/claim.js} +32 -8
- package/build/core/settlement/index.js +19 -0
- package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +24 -49
- package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
- package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
- package/build/core/settlement/petition-io.js +1 -0
- package/build/core/{petition-preview.js → settlement/petition-preview.js} +2 -2
- package/build/core/{petition.js → settlement/petition.js} +21 -12
- package/build/core/settlement/queue-read-model.js +143 -0
- package/build/core/settlement/queue-seat-allocation.js +156 -0
- package/build/core/settlement/queue.js +6 -0
- package/build/core/settlement/settlement.js +288 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/settlement/verification.js +59 -0
- package/build/core/status/board.js +62 -41
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +6 -2
- package/build/core/task/board.js +41 -4
- package/build/core/task/commands.js +45 -28
- package/build/core/task/document.js +5 -0
- package/build/core/task/index.js +12 -0
- package/build/core/task/model.js +8 -1
- package/build/core/task/query.js +172 -0
- package/build/core/task/settlement-git.js +265 -74
- package/build/core/task/settlement-policy.js +67 -29
- package/build/core/task/source-board.js +1 -0
- package/build/core/task/task-contract.js +444 -0
- package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
- package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
- package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
- package/build/core/{task-git-store.js → task/task-git-store.js} +90 -19
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +6 -4
- package/build/core/task/task-store.js +1 -0
- package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
- package/build/core/task/task.js +7 -0
- package/build/core/task/tree.js +37 -0
- package/build/core/task/validation.js +5 -2
- package/build/core/transcripts.js +15 -3
- package/build/core/worktree-path.js +43 -28
- package/build/flow-error.js +83 -39
- package/build/fs/path-coordinate.js +16 -0
- package/build/generated/version.js +3 -2
- package/build/git/branches.js +2 -1
- package/build/git/core.js +106 -2
- package/build/git/diff/parsers.js +23 -13
- package/build/git/diff/structured.js +127 -0
- package/build/git/path-coordinate.js +17 -0
- package/build/git/refs.js +57 -0
- package/build/git/streaming-batch.js +301 -0
- package/build/git/worktree.js +65 -0
- package/build/index.js +9 -9
- package/build/keiyaku.js +2 -36
- package/build/telemetry/logger.js +4 -2
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +5 -4
- package/skills/keiyaku-akuma/SKILL.md +25 -11
- package/skills/keiyaku-task/SKILL.md +17 -8
- package/skills/keiyaku-workflow/SKILL.md +58 -9
- package/build/agents/providers/codex-sdk.js +0 -329
- package/build/cli/commands/task/view/meta.js +0 -8
- package/build/core/command-io.js +0 -174
- package/build/core/path-coordinate.js +0 -27
- package/build/core/petition-claim.js +0 -117
- package/build/core/petition-run.js +0 -83
- package/build/core/projection-coordinate.js +0 -63
- package/build/core/projection-wait.js +0 -165
- package/build/core/projection-wake.js +0 -136
- package/build/core/queue.js +0 -343
- package/build/core/task-contract.js +0 -237
- package/build/core/task.js +0 -4
- /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
- /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
- /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
- /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
- /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
package/build/cli/render/misc.js
CHANGED
|
@@ -2,19 +2,24 @@ import { assembleResponse, buildPayload, buildSection, colorizeErrorStatus, FORM
|
|
|
2
2
|
import { RESPONSE_MARKERS } from "./response-style.js";
|
|
3
3
|
import { formatReview, HINTS_LIST_MAX_ITEMS, REVIEW_SECTION_TITLE, toReviewPayload, } from "./shared.js";
|
|
4
4
|
import { prependAddressReceipt, renderAddressCarrier } from "./address.js";
|
|
5
|
+
import { commissionSlug } from "../../core/ids.js";
|
|
5
6
|
export function buildErrorResponse(input) {
|
|
6
7
|
const shouldRaiseProtocolError = input.errorType === "runtime_error";
|
|
7
|
-
const text =
|
|
8
|
+
const text = input.errorCode === "PROJECTION_INCOMPATIBLE"
|
|
9
|
+
? `${colorizeErrorStatus(`${RESPONSE_MARKERS.failure} Failed [${input.errorCode}]`)}\n ${input.message}`
|
|
10
|
+
: buildErrorText(input);
|
|
11
|
+
const payload = {
|
|
12
|
+
error: {
|
|
13
|
+
code: input.errorCode,
|
|
14
|
+
message: input.message,
|
|
15
|
+
hints: input.hints,
|
|
16
|
+
...(input.review ? { review: toReviewPayload(input.review) } : {}),
|
|
17
|
+
...(input.facts ? { facts: input.facts } : {}),
|
|
18
|
+
},
|
|
19
|
+
};
|
|
8
20
|
const response = {
|
|
9
21
|
text,
|
|
10
|
-
payload
|
|
11
|
-
error: {
|
|
12
|
-
code: input.errorCode,
|
|
13
|
-
message: input.message,
|
|
14
|
-
hints: input.hints,
|
|
15
|
-
...(input.review ? { review: toReviewPayload(input.review) } : {}),
|
|
16
|
-
},
|
|
17
|
-
},
|
|
22
|
+
payload,
|
|
18
23
|
};
|
|
19
24
|
if (shouldRaiseProtocolError) {
|
|
20
25
|
response.isError = true;
|
|
@@ -23,21 +28,61 @@ export function buildErrorResponse(input) {
|
|
|
23
28
|
}
|
|
24
29
|
function buildErrorText(input) {
|
|
25
30
|
const errorSection = buildSection("Error", input.message);
|
|
31
|
+
const recoverySection = input.facts?.kind === "renew_conflict"
|
|
32
|
+
? buildSection("Recovery", [
|
|
33
|
+
"Conflicting paths:",
|
|
34
|
+
...input.facts.conflictPaths.map((filePath) => ` ${filePath}`),
|
|
35
|
+
...(input.facts.conflictPathCapture.status === "failed"
|
|
36
|
+
? [`Conflict-path capture failed: ${input.facts.conflictPathCapture.diagnostic}`]
|
|
37
|
+
: []),
|
|
38
|
+
"Delivery branch and worktree were restored; no ledger writes were appended.",
|
|
39
|
+
].join("\n"))
|
|
40
|
+
: null;
|
|
26
41
|
const reviewSection = input.review ? buildSection(REVIEW_SECTION_TITLE, formatReview(input.review)) : null;
|
|
27
|
-
const
|
|
28
|
-
|
|
42
|
+
const commissionedCarrier = input.addressCarrier && !("expected" in input.addressCarrier)
|
|
43
|
+
&& input.addressCarrier.binding.kind === "commission"
|
|
44
|
+
? input.addressCarrier
|
|
45
|
+
: undefined;
|
|
46
|
+
const recoveryAddress = commissionedCarrier
|
|
47
|
+
? `@${commissionedCarrier.place.display ?? commissionSlug(commissionedCarrier.binding.commissionId)}`
|
|
48
|
+
: input.facts?.kind === "renew_session"
|
|
49
|
+
? `@${commissionSlug(input.facts.commission)}`
|
|
50
|
+
: undefined;
|
|
51
|
+
const nextActionSection = input.facts?.kind === "renew_session" && recoveryAddress
|
|
52
|
+
? buildSection("Next action", input.facts.nextAction === "resolve-conflicts"
|
|
53
|
+
? [
|
|
54
|
+
"Resolve and stage the conflicting delivery with ordinary Git, then:",
|
|
55
|
+
`» keiyaku ${recoveryAddress} renew --continue`,
|
|
56
|
+
"Or restore the pre-renew delivery:",
|
|
57
|
+
`» keiyaku ${recoveryAddress} renew --abort`,
|
|
58
|
+
]
|
|
59
|
+
: input.facts.nextAction === "continue-or-abort" ? [
|
|
60
|
+
`» keiyaku ${recoveryAddress} renew --continue`,
|
|
61
|
+
`» keiyaku ${recoveryAddress} renew --abort`,
|
|
62
|
+
] : [`» keiyaku ${recoveryAddress} renew --abort`])
|
|
63
|
+
: null;
|
|
64
|
+
const hints = input.facts?.kind === "renew_session"
|
|
65
|
+
? []
|
|
66
|
+
: formatHints(input.hints, { maxItems: HINTS_LIST_MAX_ITEMS, maxItemChars: FORMAT_LIST_MAX_ITEM_CHARS });
|
|
67
|
+
if (input.facts?.kind === "renew_conflict") {
|
|
68
|
+
hints.push("your old head survives:", `» git log ${input.facts.recoveryRef}`);
|
|
69
|
+
}
|
|
70
|
+
const hintsSection = buildSection("Hints", hints);
|
|
71
|
+
const body = assembleResponse(colorizeErrorStatus(`${RESPONSE_MARKERS.failure} Failed [${input.errorCode}]`), "Request could not be completed.", [errorSection, recoverySection, nextActionSection, reviewSection, hintsSection].filter((section) => section !== null));
|
|
29
72
|
return input.addressCarrier ? `${renderAddressCarrier(input.addressCarrier)}\n${body}` : body;
|
|
30
73
|
}
|
|
31
74
|
export function buildHelpResponse(input) {
|
|
75
|
+
const payload = {};
|
|
32
76
|
return {
|
|
33
77
|
text: input.text,
|
|
34
|
-
payload: buildPayload(
|
|
78
|
+
payload: buildPayload(payload),
|
|
35
79
|
};
|
|
36
80
|
}
|
|
37
81
|
export function buildLogResponse(result) {
|
|
38
82
|
const { address: _address, ...resultData } = result;
|
|
83
|
+
const payload = resultData;
|
|
39
84
|
return prependAddressReceipt({
|
|
40
85
|
text: result.markdown,
|
|
41
|
-
payload: buildPayload(
|
|
86
|
+
payload: buildPayload(payload),
|
|
42
87
|
}, result.address);
|
|
43
88
|
}
|
|
@@ -1,16 +1,26 @@
|
|
|
1
|
+
import { commissionSlug } from "../../core/ids.js";
|
|
1
2
|
import { shortCommitHash } from "../../git/commits.js";
|
|
2
3
|
import { assembleResponse, buildPayload, buildSection, formatMaybe, formatWarnings, } from "./format.js";
|
|
3
4
|
import { DIFF_OVERVIEW_SECTION_TITLE, RESPONSE_MARKERS, WARNING_SECTION_TITLE } from "./response-style.js";
|
|
4
|
-
import {
|
|
5
|
+
import { INFO_COMMIT_MAX_CHARS, INFO_PLEA_MAX_CHARS, } from "./shared.js";
|
|
5
6
|
import { prependAddressReceipt } from "./address.js";
|
|
7
|
+
function formatPetitionSealSource(source) {
|
|
8
|
+
return source.arc === null
|
|
9
|
+
? `no open arc · fence ${source.fence}`
|
|
10
|
+
: `a${source.arc} · fence ${source.fence}▸HEAD`;
|
|
11
|
+
}
|
|
6
12
|
export function buildPetitionPreviewResponse(preview, json) {
|
|
13
|
+
const source = formatPetitionSealSource(preview.arc.source);
|
|
14
|
+
const payload = {
|
|
15
|
+
...preview,
|
|
16
|
+
arc: { source },
|
|
17
|
+
};
|
|
7
18
|
const failed = preview.gates.filter((gate) => gate.result === "failed").length;
|
|
8
19
|
const text = json
|
|
9
|
-
? JSON.stringify(
|
|
20
|
+
? JSON.stringify(payload)
|
|
10
21
|
: [
|
|
11
|
-
`contract ${preview.contract}`,
|
|
12
|
-
`
|
|
13
|
-
`arc ${preview.arc.source}`,
|
|
22
|
+
`contract ${commissionSlug(preview.contract)}`,
|
|
23
|
+
`arc ${source}`,
|
|
14
24
|
...preview.gates.map((gate) => {
|
|
15
25
|
if (gate.result === "not_evaluated")
|
|
16
26
|
return `gate ${gate.name} · not evaluated`;
|
|
@@ -22,35 +32,30 @@ export function buildPetitionPreviewResponse(preview, json) {
|
|
|
22
32
|
].join("\n");
|
|
23
33
|
return {
|
|
24
34
|
text,
|
|
25
|
-
payload
|
|
35
|
+
payload,
|
|
26
36
|
...(failed > 0 ? { exitCode: 1 } : {}),
|
|
27
37
|
};
|
|
28
38
|
}
|
|
29
39
|
export function buildPetitionClaimResponse(result, input) {
|
|
30
40
|
const { status: _status, address: _address, ...resultData } = result;
|
|
41
|
+
const payload = resultData;
|
|
31
42
|
const renderedCommit = result.commit ? shortCommitHash(result.commit) : undefined;
|
|
32
43
|
const commitSuffix = renderedCommit ? ` [${renderedCommit}]` : "";
|
|
33
|
-
const summary =
|
|
34
|
-
? `Merged '${result.deletedBranch}' into '${result.mergedInto}'${commitSuffix}. Deleted feature branch.`
|
|
35
|
-
: `Merged contract into '${result.mergedInto}'${commitSuffix}.`;
|
|
44
|
+
const summary = `Claimed contract${commitSuffix}.`;
|
|
36
45
|
const diffSection = result.diff ? buildSection(DIFF_OVERVIEW_SECTION_TITLE, result.diff) : null;
|
|
37
46
|
const ledgerSection = result.ledgerView ? buildSection("Ledger", result.ledgerView) : null;
|
|
38
47
|
const warningSection = buildSection(WARNING_SECTION_TITLE, formatWarnings(result.meta?.warnings ?? []));
|
|
39
48
|
const infoLines = [
|
|
40
49
|
...formatMaybe("Result", result.result, INFO_COMMIT_MAX_CHARS),
|
|
41
|
-
...formatMaybe("Title", input.title
|
|
50
|
+
...formatMaybe("Title", input.title),
|
|
42
51
|
...formatMaybe("Plea", input.plea, INFO_PLEA_MAX_CHARS),
|
|
43
52
|
...formatMaybe("Commit", renderedCommit, INFO_COMMIT_MAX_CHARS),
|
|
44
|
-
...formatMaybe("Merged Into", result.mergedInto, INFO_BRANCH_MAX_CHARS),
|
|
45
|
-
...formatMaybe("Deleted Branch", result.deletedBranch, INFO_BRANCH_MAX_CHARS),
|
|
46
|
-
...formatMaybe(BRANCH_LABEL, result.currentBranch, INFO_BRANCH_MAX_CHARS),
|
|
47
|
-
...formatMaybe("Base Branch", result.baseBranch, INFO_BRANCH_MAX_CHARS),
|
|
48
53
|
"Claim Gates: settlement requirements satisfied.",
|
|
49
54
|
...formatMaybe("Oath", input.oath, INFO_PLEA_MAX_CHARS),
|
|
50
55
|
];
|
|
51
56
|
const text = assembleResponse(`${RESPONSE_MARKERS.claim} Keiyaku Fulfilled (Claim)`, summary, [ledgerSection, diffSection, warningSection].filter((section) => section !== null), infoLines);
|
|
52
57
|
return prependAddressReceipt({
|
|
53
58
|
text,
|
|
54
|
-
payload: buildPayload(
|
|
59
|
+
payload: buildPayload(payload),
|
|
55
60
|
}, result.address);
|
|
56
61
|
}
|
|
@@ -41,6 +41,9 @@ function compactTokens(value) {
|
|
|
41
41
|
}
|
|
42
42
|
function warningText(row) {
|
|
43
43
|
const warning = row.warning;
|
|
44
|
+
if (warning.reason === "rate-limit") {
|
|
45
|
+
return `provider rate limit exhausted${row.count > 1 ? ` (${row.count})` : ""}`;
|
|
46
|
+
}
|
|
44
47
|
if (warning.reason === "retry") {
|
|
45
48
|
const status = warning.errorStatus === null ? "no response" : String(warning.errorStatus);
|
|
46
49
|
return `provider retrying ${warning.attempt}/${warning.maxRetries} · retry in ${formatTimelineDuration(warning.retryDelayMs)} · status ${status}${row.count > 1 ? ` (${row.count})` : ""}`;
|
|
@@ -68,9 +71,19 @@ function summarizeProjectionToolLedger(activity, workspaceRoot) {
|
|
|
68
71
|
function toolCountSegments(summary) {
|
|
69
72
|
return summary.counts.map(({ semanticClass, count }) => `${count} ${rollupCountLabel(semanticClass)}`);
|
|
70
73
|
}
|
|
74
|
+
function projectionSummarySegments(summary) {
|
|
75
|
+
const segments = toolCountSegments(summary);
|
|
76
|
+
if (summary.tokens !== undefined) {
|
|
77
|
+
segments.push(`${compactTokens(summary.tokens)} tok`);
|
|
78
|
+
}
|
|
79
|
+
if (summary.costUsd !== undefined) {
|
|
80
|
+
segments.push(`$${summary.costUsd.toFixed(2)}`);
|
|
81
|
+
}
|
|
82
|
+
return segments;
|
|
83
|
+
}
|
|
71
84
|
export function renderProjectionActivitySummary(activity, input) {
|
|
72
85
|
const summary = summarizeProjectionToolLedger(activity, input.workspaceRoot);
|
|
73
|
-
const segments =
|
|
86
|
+
const segments = projectionSummarySegments(summary);
|
|
74
87
|
if (segments.length === 0)
|
|
75
88
|
return undefined;
|
|
76
89
|
const spine = input.state === "dead" || input.state === "lost" ? "┆" : "│";
|
|
@@ -78,11 +91,7 @@ export function renderProjectionActivitySummary(activity, input) {
|
|
|
78
91
|
}
|
|
79
92
|
function renderTerminalRollup(activity, input) {
|
|
80
93
|
const summary = summarizeProjectionToolLedger(activity, input.workspaceRoot);
|
|
81
|
-
const segments =
|
|
82
|
-
...toolCountSegments(summary),
|
|
83
|
-
...(summary.tokens === undefined ? [] : [`${compactTokens(summary.tokens)} tok`]),
|
|
84
|
-
...(summary.costUsd === undefined ? [] : [`$${summary.costUsd.toFixed(2)}`]),
|
|
85
|
-
];
|
|
94
|
+
const segments = projectionSummarySegments(summary);
|
|
86
95
|
const lines = input.diagnostic
|
|
87
96
|
? [fitVariableLine(`${elapsedLabel(input.anchorMs, input.diagnostic.at).padStart(TIME_GUTTER_WIDTH)}┆ ${"warning".padEnd(VERB_WIDTH)} `, compactText(input.diagnostic.text), input.maxColumns)]
|
|
88
97
|
: [];
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import * as path from "node:path";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
1
|
import { KEIYAKU_FILE } from "../../keiyaku.js";
|
|
2
|
+
import { commissionSlug, formatCommissionCoordinate } from "../../core/ids.js";
|
|
4
3
|
import { assembleResponse, buildSection, DISPLAY_TEXT_MAX_CHARS, FORMAT_LIST_MAX_ITEM_CHARS, FORMAT_LIST_MAX_ITEMS, formatMaybe, formatWarnings, shellQuote, truncateForDisplay, } from "./format.js";
|
|
5
4
|
import { WARNING_SECTION_TITLE } from "./response-style.js";
|
|
6
5
|
import { prependAddressReceipt } from "./address.js";
|
|
7
6
|
export function textResponse(text) {
|
|
7
|
+
const payload = {};
|
|
8
8
|
return {
|
|
9
9
|
text,
|
|
10
|
-
payload
|
|
10
|
+
payload,
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
+
/** Carrier boundary: data must already be a named command payload assignable to JsonObject. */
|
|
13
14
|
export function coreTextResponse(text, data) {
|
|
14
15
|
return {
|
|
15
16
|
text,
|
|
@@ -20,30 +21,61 @@ export async function renderCoreResult(work, render) {
|
|
|
20
21
|
return render(await work);
|
|
21
22
|
}
|
|
22
23
|
export function buildBindDraftResponse(draftPath) {
|
|
23
|
-
|
|
24
|
+
const payload = { draftPath };
|
|
25
|
+
return coreTextResponse(`Draft saved to ${draftPath}.`, payload);
|
|
24
26
|
}
|
|
25
27
|
export function buildBindResponse(result, cwd) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
void cwd;
|
|
29
|
+
const overlapsByCounterparty = new Map();
|
|
30
|
+
for (const overlap of result.scopeOverlaps) {
|
|
31
|
+
const counterparty = overlap.contracts[1];
|
|
32
|
+
const group = overlapsByCounterparty.get(counterparty);
|
|
33
|
+
if (group)
|
|
34
|
+
group.push(overlap);
|
|
35
|
+
else
|
|
36
|
+
overlapsByCounterparty.set(counterparty, [overlap]);
|
|
37
|
+
}
|
|
38
|
+
const overlapWarnings = [...overlapsByCounterparty.entries()].map(([contractId, overlaps]) => renderScopeOverlapGroup(commissionSlug(contractId), overlaps));
|
|
39
|
+
const place = result.place;
|
|
40
|
+
const payload = {
|
|
35
41
|
id: result.id,
|
|
36
42
|
ref: result.ref,
|
|
37
43
|
worktreePath: result.worktreePath,
|
|
38
44
|
workspace: result.workspace,
|
|
45
|
+
place: result.place,
|
|
46
|
+
target: result.target,
|
|
39
47
|
ledgerHead: result.ledgerHead,
|
|
40
|
-
warnings:
|
|
48
|
+
warnings: overlapWarnings,
|
|
49
|
+
scopeOverlaps: result.scopeOverlaps,
|
|
41
50
|
...(result.branch ? { branch: result.branch } : {}),
|
|
51
|
+
};
|
|
52
|
+
return coreTextResponse([
|
|
53
|
+
`Bound${place ? ` @${place}` : ""} · commission ${result.id} · target ${result.target}`,
|
|
54
|
+
...(overlapWarnings.length > 0 ? ["Warnings:", ...overlapWarnings] : []),
|
|
55
|
+
].join("\n"), payload);
|
|
56
|
+
}
|
|
57
|
+
function renderScopeOverlapGroup(contractAddr, overlaps) {
|
|
58
|
+
const pairs = overlaps.map((overlap) => {
|
|
59
|
+
const [nextPattern, existingPattern] = overlap.patterns;
|
|
60
|
+
const evidence = overlap.kind === "potential"
|
|
61
|
+
? "potential; no current tracked path proves it"
|
|
62
|
+
: `concrete; ${overlap.paths.count} current tracked path${overlap.paths.count === 1 ? "" : "s"}: ${overlap.paths.preview.join(", ")}${overlap.paths.truncated ? ", …" : ""}`;
|
|
63
|
+
return ` ${nextPattern} × ${existingPattern} (${evidence})`;
|
|
42
64
|
});
|
|
65
|
+
return [
|
|
66
|
+
`▲ scope overlap with ${contractAddr}:`,
|
|
67
|
+
...pairs,
|
|
68
|
+
` consider --after ${contractAddr}`,
|
|
69
|
+
].join("\n");
|
|
43
70
|
}
|
|
44
71
|
export function buildForfeitResponse(result) {
|
|
45
72
|
const { address: _address, ...resultData } = result;
|
|
46
|
-
const
|
|
73
|
+
const payload = resultData;
|
|
74
|
+
const place = result.address.binding.kind === "commission"
|
|
75
|
+
? (result.address.place?.display ?? null)
|
|
76
|
+
: null;
|
|
77
|
+
const coordinate = formatCommissionCoordinate({ commissionId: result.contractId, place });
|
|
78
|
+
const base = `Forfeited ${coordinate}.`;
|
|
47
79
|
const warnings = [
|
|
48
80
|
...(result.cleanup.worktreeRemoveFailure
|
|
49
81
|
? [
|
|
@@ -52,18 +84,22 @@ export function buildForfeitResponse(result) {
|
|
|
52
84
|
: []),
|
|
53
85
|
...(result.cleanup.branchDeleteFailure
|
|
54
86
|
? [
|
|
55
|
-
`Could not delete contract branch ${result.cleanup.branchDeleteFailure.
|
|
87
|
+
`Could not delete contract branch: ${redactBranchReference(result.cleanup.branchDeleteFailure.reason, result.cleanup.branchDeleteFailure.name)}`,
|
|
56
88
|
]
|
|
57
89
|
: []),
|
|
58
90
|
];
|
|
59
91
|
if (warnings.length === 0) {
|
|
60
|
-
return prependAddressReceipt(coreTextResponse(base,
|
|
92
|
+
return prependAddressReceipt(coreTextResponse(base, payload), result.address);
|
|
61
93
|
}
|
|
62
94
|
const warningSection = buildSection(WARNING_SECTION_TITLE, formatWarnings(warnings));
|
|
63
|
-
return prependAddressReceipt(coreTextResponse(assembleResponse(base, "", [warningSection].filter((section) => section !== null)),
|
|
95
|
+
return prependAddressReceipt(coreTextResponse(assembleResponse(base, "", [warningSection].filter((section) => section !== null)), payload), result.address);
|
|
96
|
+
}
|
|
97
|
+
function redactBranchReference(message, branch) {
|
|
98
|
+
return message
|
|
99
|
+
.replaceAll(`refs/heads/${branch}`, "contract branch")
|
|
100
|
+
.replaceAll(branch, "contract branch");
|
|
64
101
|
}
|
|
65
102
|
export const RULES_SECTION_MAX_CHARS = 5000;
|
|
66
|
-
export const BRANCH_LABEL = "Workspace";
|
|
67
103
|
export const INFO_SECTION_TITLE = "Info";
|
|
68
104
|
export const HINTS_SECTION_TITLE = "Hints";
|
|
69
105
|
export const REVIEW_SECTION_TITLE = "Review";
|
|
@@ -125,12 +161,15 @@ export function formatDurableReviveCommand(input) {
|
|
|
125
161
|
? `keiyaku revive ${input.artifactId} --repo ${shellQuote(input.repositoryCoordinate)}`
|
|
126
162
|
: `keiyaku revive ${input.artifactId}`;
|
|
127
163
|
}
|
|
164
|
+
export function formatTellCommand(projectionId, body) {
|
|
165
|
+
return `keiyaku tell ${projectionId} [--wait DURATION] ${body}`;
|
|
166
|
+
}
|
|
128
167
|
export function projectionRejoinHintLines(projectionId) {
|
|
129
168
|
return [
|
|
130
169
|
"Come back for the result:",
|
|
131
170
|
` » keiyaku wait ${projectionId} [--timeout DURATION]`,
|
|
132
171
|
"Steer it while it works:",
|
|
133
|
-
` »
|
|
172
|
+
` » ${formatTellCommand(projectionId, '"your words"')}`,
|
|
134
173
|
];
|
|
135
174
|
}
|
|
136
175
|
export function formatCallNextAction(input) {
|
|
@@ -142,7 +181,7 @@ export function formatCallNextAction(input) {
|
|
|
142
181
|
"The akuma is back.",
|
|
143
182
|
...(input.artifactId ? [`record: ${input.artifactId}`] : []),
|
|
144
183
|
"talk to it:",
|
|
145
|
-
` »
|
|
184
|
+
` » ${formatTellCommand(input.projection.alias ?? input.projection.id, '"your words"')}`,
|
|
146
185
|
].join("\n");
|
|
147
186
|
}
|
|
148
187
|
return "» keiyaku status";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Skills install success receipt: target rows plus optional warning block. */
|
|
2
|
+
export function renderSkillsInstallReceipt(result) {
|
|
3
|
+
return [
|
|
4
|
+
"Installed official Keiyaku skills:",
|
|
5
|
+
...result.targets.map((target) => `- ${target.path} -> ${target.source} (${target.status})`),
|
|
6
|
+
...(result.warnings.length > 0
|
|
7
|
+
? ["", "## Warning", ...result.warnings.map((warning) => `- ${warning}`)]
|
|
8
|
+
: []),
|
|
9
|
+
].join("\n");
|
|
10
|
+
}
|
|
@@ -3,6 +3,8 @@ import { shortCommitHash } from "../../git/commits.js";
|
|
|
3
3
|
import { formatAgeMs } from "./format.js";
|
|
4
4
|
import { renderKanshiBoard } from "./kanshi.js";
|
|
5
5
|
import { renderProjectionActivitySummary, } from "./projection-activity.js";
|
|
6
|
+
import { renderTerminalFailureFace, terminalFailureCodeSuffix } from "./terminal-failure.js";
|
|
7
|
+
import { formatTellCommand } from "./shared.js";
|
|
6
8
|
export const STATUS_DISEASES_SECTION_TITLE = "Diseases";
|
|
7
9
|
export const STATUS_PROJECTION_SECTION_TITLE = "akuma";
|
|
8
10
|
export const STATUS_CLAIM_RECEIPTS_SECTION_TITLE = "claim receipts";
|
|
@@ -23,6 +25,7 @@ function projectionGlyph(state) {
|
|
|
23
25
|
case "startup-timeout":
|
|
24
26
|
return "!";
|
|
25
27
|
case "unknown":
|
|
28
|
+
case "incompatible":
|
|
26
29
|
return "?";
|
|
27
30
|
}
|
|
28
31
|
}
|
|
@@ -42,38 +45,58 @@ function renderTaskStatusSection(tasks) {
|
|
|
42
45
|
tasks.blocked > 0 ? `${tasks.blocked} blocked` : undefined,
|
|
43
46
|
].filter((segment) => segment !== undefined);
|
|
44
47
|
const lines = [`tasks · ${segments.join(" / ")}`];
|
|
45
|
-
lines.push(...tasks.topTasks.map((task) => ` ${task.id
|
|
48
|
+
lines.push(...tasks.topTasks.map((task) => ` ${task.id} · P${task.pri} · ${task.state === "in_progress" ? "in_progress" : "ready"} · age ${formatAgeMs(task.ageMs)} · active ${formatAgeMs(task.activityAgeMs)} · ${task.title}`));
|
|
49
|
+
if (tasks.omitted > 0) {
|
|
50
|
+
lines.push(` · +${tasks.omitted} more — keiyaku task ls`);
|
|
51
|
+
}
|
|
46
52
|
return `${lines.join("\n")}\n`;
|
|
47
53
|
}
|
|
54
|
+
function projectionDiagnosticDetail(diagnostic) {
|
|
55
|
+
if (diagnostic.kind === "oversized-projection-file" && diagnostic.fileName) {
|
|
56
|
+
return `${diagnostic.fileName} exceeds status read limit · newest complete events retained`;
|
|
57
|
+
}
|
|
58
|
+
return diagnostic.detail ?? diagnostic.kind;
|
|
59
|
+
}
|
|
48
60
|
function renderProjectionDiagnostics(row) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
const details = row.diagnostics.map(projectionDiagnosticDetail);
|
|
62
|
+
return details.length > 0 ? ` · diag ${details.join("; ")}` : "";
|
|
63
|
+
}
|
|
64
|
+
function terminalFailureSuffix(row) {
|
|
65
|
+
return row.terminalFailure
|
|
66
|
+
? ` · ${terminalFailureCodeSuffix(row.terminalFailure.code)}`
|
|
67
|
+
: "";
|
|
52
68
|
}
|
|
53
69
|
function renderProjectionOmission(board) {
|
|
54
70
|
if (!board.omitted)
|
|
55
71
|
return undefined;
|
|
56
|
-
const counts = ["failed", "dead", "done", "killed", "dismissed"]
|
|
72
|
+
const counts = ["failed", "dead", "done", "killed", "dismissed", "incompatible"]
|
|
57
73
|
.flatMap((state) => {
|
|
58
74
|
const count = board.omitted?.byState[state] ?? 0;
|
|
59
75
|
return count > 0 ? [`${count} ${state}`] : [];
|
|
60
76
|
});
|
|
61
|
-
return ` · +${board.omitted.total} not shown (${counts.join(" · ")}) — keiyaku status --all`;
|
|
77
|
+
return ` · +${board.omitted.total} historical projections not shown (${counts.join(" · ")}) — keiyaku status --all`;
|
|
62
78
|
}
|
|
63
79
|
function renderProjectionAge(row) {
|
|
80
|
+
const duration = formatAgeMs(row.durationMs) ?? "?";
|
|
81
|
+
const activity = formatAgeMs(row.activityAgeMs) ?? "?";
|
|
82
|
+
const facts = `dur ${duration} · active ${activity}`;
|
|
64
83
|
if (row.state === "done")
|
|
65
|
-
return
|
|
84
|
+
return `done · ${facts}`;
|
|
66
85
|
if (row.state === "killed")
|
|
67
|
-
return
|
|
86
|
+
return `killed · ${facts}`;
|
|
68
87
|
if (row.state === "dismissed")
|
|
69
|
-
return
|
|
88
|
+
return `dismissed · ${facts}`;
|
|
70
89
|
if (row.state === "failed")
|
|
71
|
-
return
|
|
90
|
+
return `failed · ${facts}`;
|
|
91
|
+
if (row.state === "dead")
|
|
92
|
+
return `dead · ${facts}`;
|
|
72
93
|
if (row.state === "startup-timeout")
|
|
73
|
-
return
|
|
94
|
+
return `startup timed out · ${facts}`;
|
|
74
95
|
if (row.state === "unknown")
|
|
75
|
-
return
|
|
76
|
-
|
|
96
|
+
return `unknown · ${facts}`;
|
|
97
|
+
if (row.state === "incompatible")
|
|
98
|
+
return "incompatible history";
|
|
99
|
+
return facts;
|
|
77
100
|
}
|
|
78
101
|
function renderProjectionTellCounts(row) {
|
|
79
102
|
const { inbox, inflight, submitted, consumed } = row.tellCounts;
|
|
@@ -93,10 +116,11 @@ function projectionActivityState(row) {
|
|
|
93
116
|
case "out": return "running";
|
|
94
117
|
case "startup-timeout": return "stalled";
|
|
95
118
|
case "unknown": return "unknown";
|
|
119
|
+
case "incompatible": return "unknown";
|
|
96
120
|
}
|
|
97
121
|
}
|
|
98
122
|
function renderProjectionActivityLine(row) {
|
|
99
|
-
if (row.state === "startup-timeout" || row.state === "unknown")
|
|
123
|
+
if (row.state === "startup-timeout" || row.state === "unknown" || row.state === "incompatible")
|
|
100
124
|
return undefined;
|
|
101
125
|
if (!row.activity)
|
|
102
126
|
return undefined;
|
|
@@ -115,27 +139,29 @@ function renderProjectionRow(row) {
|
|
|
115
139
|
: row.state);
|
|
116
140
|
const identity = row.alias ? `${row.id} (${row.alias})` : row.id;
|
|
117
141
|
let heading;
|
|
118
|
-
if (row.state === "startup-timeout" || row.state === "unknown") {
|
|
142
|
+
if (row.state === "startup-timeout" || row.state === "unknown" || row.state === "incompatible") {
|
|
119
143
|
const akuma = (row.akuma ?? "(unknown)").padEnd(18);
|
|
120
|
-
heading = ` ${glyph} ${identity} ${akuma} ${renderProjectionAge(row)}${renderProjectionDiagnostics(row)}`.trimEnd();
|
|
144
|
+
heading = ` ${glyph} ${identity} ${akuma} ${renderProjectionAge(row)}${terminalFailureSuffix(row)}${renderProjectionDiagnostics(row)}`.trimEnd();
|
|
121
145
|
}
|
|
122
146
|
else if (row.state === "minting") {
|
|
123
|
-
heading = ` ${glyph} ${identity.padEnd(18)} (minting)${renderProjectionDiagnostics(row)}`.trimEnd();
|
|
147
|
+
heading = ` ${glyph} ${identity.padEnd(18)} (minting) · ${renderProjectionAge(row)}${terminalFailureSuffix(row)}${renderProjectionDiagnostics(row)}`.trimEnd();
|
|
124
148
|
}
|
|
125
149
|
else {
|
|
126
|
-
const age = renderProjectionAge(row)
|
|
150
|
+
const age = renderProjectionAge(row);
|
|
127
151
|
const akuma = (row.akuma ?? "(unknown)").padEnd(18);
|
|
128
|
-
heading = ` ${glyph} ${identity} ${akuma} ${age}${renderProjectionTellCounts(row)}${renderProjectionDiagnostics(row)}`.trimEnd();
|
|
152
|
+
heading = ` ${glyph} ${identity} ${akuma} ${age}${renderProjectionTellCounts(row)}${terminalFailureSuffix(row)}${renderProjectionDiagnostics(row)}`.trimEnd();
|
|
129
153
|
}
|
|
130
154
|
const activity = renderProjectionActivityLine(row);
|
|
131
|
-
|
|
155
|
+
const drillDown = row.terminalFailure ? [` » keiyaku wait ${row.alias ?? row.id}`] : [];
|
|
156
|
+
return activity ? [heading, activity, ...drillDown] : [heading, ...drillDown];
|
|
132
157
|
}
|
|
133
158
|
function isTerminalProjectionStatus(row) {
|
|
134
159
|
return row.state === "done"
|
|
135
160
|
|| row.state === "killed"
|
|
136
161
|
|| row.state === "dismissed"
|
|
137
162
|
|| row.state === "failed"
|
|
138
|
-
|| row.state === "dead"
|
|
163
|
+
|| row.state === "dead"
|
|
164
|
+
|| row.state === "incompatible";
|
|
139
165
|
}
|
|
140
166
|
export function renderProjectionFilteredStatus(board, projectionId) {
|
|
141
167
|
const head = board.defaultHead ? shortCommitHash(board.defaultHead) : "(no HEAD)";
|
|
@@ -143,14 +169,21 @@ export function renderProjectionFilteredStatus(board, projectionId) {
|
|
|
143
169
|
const row = board.projections?.rows.find((candidate) => candidate.id === projectionId);
|
|
144
170
|
if (!row)
|
|
145
171
|
return `${heading}\nno projections on projection ${projectionId}\n`;
|
|
172
|
+
if (row.state === "failed" || row.terminalFailure) {
|
|
173
|
+
// Same face bytes as wait; CLI success write supplies the final newline.
|
|
174
|
+
return renderTerminalFailureFace(projectionId, row.terminalFailure).join("\n");
|
|
175
|
+
}
|
|
146
176
|
const lines = [heading, "", ...renderProjectionRow(row), ""];
|
|
177
|
+
if (row.observation.compatibility === "incompatible") {
|
|
178
|
+
return `${lines.join("\n")}\n`;
|
|
179
|
+
}
|
|
147
180
|
if (!isTerminalProjectionStatus(row))
|
|
148
|
-
lines.push(`»
|
|
181
|
+
lines.push(`» ${formatTellCommand(projectionId, '"..."')}`);
|
|
149
182
|
lines.push(`» keiyaku wait ${projectionId}`);
|
|
150
183
|
return `${lines.join("\n")}\n`;
|
|
151
184
|
}
|
|
152
185
|
export function renderProjectionStatusSection(board) {
|
|
153
|
-
if (!board || board.rows.length === 0)
|
|
186
|
+
if (!board || (board.rows.length === 0 && !board.omitted))
|
|
154
187
|
return "";
|
|
155
188
|
const lines = board.rows.flatMap(renderProjectionRow);
|
|
156
189
|
const omission = renderProjectionOmission(board);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { repositoryCoordinateFromAddress } from "../commands/shared.js";
|
|
2
|
+
import { writeCliOutput } from "../output-stream-error-policy.js";
|
|
3
|
+
import { renderResolvedAddressReceipt } from "./address.js";
|
|
4
|
+
import { formatCallNextAction } from "./shared.js";
|
|
5
|
+
function responseText(response) {
|
|
6
|
+
return response.text;
|
|
7
|
+
}
|
|
8
|
+
function responseData(response) {
|
|
9
|
+
const payload = response.payload;
|
|
10
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload) || "error" in payload)
|
|
11
|
+
return {};
|
|
12
|
+
return payload;
|
|
13
|
+
}
|
|
14
|
+
function isCallProjectionFacts(value) {
|
|
15
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
16
|
+
return false;
|
|
17
|
+
const facts = value;
|
|
18
|
+
return typeof facts.id === "string"
|
|
19
|
+
&& (facts.phase === "active" || facts.phase === "done" || facts.phase === "failed"
|
|
20
|
+
|| facts.phase === "dismissed" || facts.phase === "lost" || facts.phase === "quiescent");
|
|
21
|
+
}
|
|
22
|
+
function conversationalFooter(response) {
|
|
23
|
+
const data = responseData(response);
|
|
24
|
+
const lines = [];
|
|
25
|
+
if (response.address) {
|
|
26
|
+
const projection = data.projection;
|
|
27
|
+
const projectionFacts = isCallProjectionFacts(projection) ? projection : undefined;
|
|
28
|
+
const receiptArtifactId = typeof data.revivedArtifactId === "string"
|
|
29
|
+
? data.revivedArtifactId
|
|
30
|
+
: typeof data.artifactId === "string" ? data.artifactId : undefined;
|
|
31
|
+
lines.push(renderResolvedAddressReceipt(response.address, { artifactId: receiptArtifactId, projectionId: projectionFacts?.id }));
|
|
32
|
+
}
|
|
33
|
+
const responsePath = typeof data.responsePath === "string" ? data.responsePath : undefined;
|
|
34
|
+
const agent = typeof data.agent === "string" ? data.agent : undefined;
|
|
35
|
+
const meta = data.meta && typeof data.meta === "object" && !Array.isArray(data.meta) ? data.meta : undefined;
|
|
36
|
+
const warnings = Array.isArray(meta?.warnings) ? meta.warnings.filter((warning) => typeof warning === "string") : [];
|
|
37
|
+
if (responsePath) {
|
|
38
|
+
lines.push(`Saved to ${responsePath}.`);
|
|
39
|
+
}
|
|
40
|
+
if (agent) {
|
|
41
|
+
lines.push(`Akuma: ${agent}`);
|
|
42
|
+
}
|
|
43
|
+
if (warnings.length > 0) {
|
|
44
|
+
lines.push("Warnings:", ...warnings.map((warning) => `- ${warning}`));
|
|
45
|
+
}
|
|
46
|
+
if (typeof data.summary === "string") {
|
|
47
|
+
const projection = data.projection;
|
|
48
|
+
const projectionFacts = isCallProjectionFacts(projection) ? projection : undefined;
|
|
49
|
+
const artifactId = typeof data.artifactId === "string" ? data.artifactId : undefined;
|
|
50
|
+
lines.push(formatCallNextAction({
|
|
51
|
+
projection: projectionFacts,
|
|
52
|
+
artifactId,
|
|
53
|
+
repositoryCoordinate: repositoryCoordinateFromAddress(response.address),
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
return lines.join("\n");
|
|
57
|
+
}
|
|
58
|
+
export async function writeSuccessResponse(command, flags, response) {
|
|
59
|
+
// Plain tell is always silent; tell --wait owns the ordinary wait response.
|
|
60
|
+
if (command === "tell" && flags.timeoutMs === undefined)
|
|
61
|
+
return;
|
|
62
|
+
if (command === "bind" && flags.dryRun) {
|
|
63
|
+
// Canonical Markdown already ends with exactly one newline.
|
|
64
|
+
await writeCliOutput(process.stdout, responseText(response));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (command !== "revive") {
|
|
68
|
+
await writeCliOutput(process.stdout, `${responseText(response)}\n`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const data = responseData(response);
|
|
72
|
+
const answer = typeof data.summary === "string" ? data.summary.trim() : responseText(response).trim();
|
|
73
|
+
const footer = conversationalFooter(response);
|
|
74
|
+
await writeCliOutput(process.stdout, `${answer}\n`);
|
|
75
|
+
if (footer) {
|
|
76
|
+
await writeCliOutput(process.stderr, `${footer}\n`);
|
|
77
|
+
}
|
|
78
|
+
}
|