@astrosheep/keiyaku 4.0.0 → 4.0.2
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 +133 -8
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +50 -33
- package/build/src/akuma/akuma.js +175 -127
- package/build/src/akuma/archetype.d.ts +14 -5
- package/build/src/akuma/archetype.js +85 -39
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +490 -183
- package/build/src/akuma/coordinate.d.ts +9 -0
- package/build/src/akuma/coordinate.js +22 -0
- package/build/src/akuma/heart/facts.d.ts +88 -45
- package/build/src/akuma/heart/facts.js +19 -8
- package/build/src/akuma/heart/index.d.ts +64 -55
- package/build/src/akuma/heart/index.js +172 -252
- package/build/src/akuma/heart/rows.d.ts +38 -83
- package/build/src/akuma/heart/rows.js +117 -155
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +61 -22
- package/build/src/akuma/heart/soul.d.ts +8 -0
- package/build/src/akuma/heart/soul.js +136 -0
- package/build/src/akuma/heart/storage.d.ts +47 -0
- package/build/src/akuma/heart/storage.js +224 -0
- package/build/src/akuma/heart/tells.d.ts +12 -0
- package/build/src/akuma/heart/tells.js +79 -0
- package/build/src/akuma/heart/timeline.d.ts +15 -0
- package/build/src/akuma/heart/timeline.js +86 -0
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +10 -3
- package/build/src/akuma/index.js +7 -1
- package/build/src/akuma/projection.d.ts +176 -0
- package/build/src/akuma/projection.js +256 -0
- package/build/src/akuma/provider-recipe.d.ts +24 -0
- package/build/src/akuma/provider-recipe.js +100 -0
- package/build/src/akuma/provider.d.ts +67 -13
- package/build/src/akuma/provider.js +172 -105
- package/build/src/akuma/providers/acp/core.d.ts +19 -0
- package/build/src/akuma/providers/acp/core.js +159 -0
- package/build/src/akuma/providers/acp/events.d.ts +20 -0
- package/build/src/akuma/providers/acp/events.js +73 -0
- package/build/src/akuma/providers/acp/index.d.ts +12 -0
- package/build/src/akuma/providers/acp/index.js +94 -0
- package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
- package/build/src/akuma/providers/claude/events.js +238 -0
- package/build/src/akuma/providers/claude/index.d.ts +47 -0
- package/build/src/akuma/providers/claude/index.js +279 -0
- package/build/src/akuma/providers/claude/input.d.ts +13 -0
- package/build/src/akuma/providers/claude/input.js +109 -0
- package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
- package/build/src/akuma/providers/codex-app-server/events.js +15 -12
- package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
- package/build/src/akuma/providers/codex-app-server/index.js +77 -33
- package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
- package/build/src/akuma/providers/grok-build/index.js +70 -0
- package/build/src/akuma/providers/index.d.ts +5 -3
- package/build/src/akuma/providers/index.js +35 -56
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
- package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
- package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
- package/build/src/akuma/providers/pi/events.d.ts +33 -0
- package/build/src/akuma/providers/pi/events.js +166 -0
- package/build/src/akuma/providers/pi/index.d.ts +11 -0
- package/build/src/akuma/providers/pi/index.js +191 -0
- package/build/src/akuma/publication.d.ts +3 -3
- package/build/src/akuma/publication.js +28 -40
- package/build/src/akuma/requests.d.ts +9 -6
- package/build/src/akuma/requests.js +95 -65
- package/build/src/alias/index.d.ts +4 -3
- package/build/src/alias/index.js +12 -13
- package/build/src/body/decode.js +7 -1
- package/build/src/body/region.d.ts +2 -0
- package/build/src/body/region.js +77 -7
- package/build/src/body/render.js +2 -1
- package/build/src/body/shape.js +7 -1
- package/build/src/body/verification.js +19 -4
- package/build/src/cli/accepted.d.ts +18 -12
- package/build/src/cli/accepted.js +73 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
- package/build/src/cli/commands/akuma-invoke.js +101 -52
- package/build/src/cli/commands/akuma.d.ts +27 -9
- package/build/src/cli/commands/akuma.js +151 -80
- package/build/src/cli/commands/contract.d.ts +155 -0
- package/build/src/cli/commands/contract.js +20 -0
- package/build/src/cli/commands/install.js +2 -0
- package/build/src/cli/commands/task-invoke.d.ts +19 -4
- package/build/src/cli/commands/task-invoke.js +65 -17
- package/build/src/cli/commands/task-query.d.ts +5 -0
- package/build/src/cli/commands/task-query.js +247 -0
- package/build/src/cli/commands/task.d.ts +3 -1
- package/build/src/cli/commands/task.js +52 -14
- package/build/src/cli/coordinates.d.ts +18 -0
- package/build/src/cli/coordinates.js +120 -0
- package/build/src/cli/draft.d.ts +8 -0
- package/build/src/cli/draft.js +96 -0
- package/build/src/cli/invoke.d.ts +9 -3
- package/build/src/cli/invoke.js +287 -108
- package/build/src/cli/main.js +54 -7
- package/build/src/cli/parse.d.ts +21 -117
- package/build/src/cli/parse.js +79 -84
- package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
- package/build/src/cli/render/akuma-tool-command.js +144 -0
- package/build/src/cli/render/akuma-tool.d.ts +4 -2
- package/build/src/cli/render/akuma-tool.js +35 -5
- package/build/src/cli/render/akuma.d.ts +3 -1
- package/build/src/cli/render/akuma.js +247 -212
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/catalog.d.ts +2 -0
- package/build/src/cli/render/catalog.js +16 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +200 -54
- package/build/src/cli/render/kanshi.js +272 -129
- package/build/src/cli/render/receipt.d.ts +19 -0
- package/build/src/cli/render/receipt.js +106 -0
- package/build/src/cli/render/refusal.d.ts +16 -2
- package/build/src/cli/render/refusal.js +88 -3
- package/build/src/cli/render/region.d.ts +2 -0
- package/build/src/cli/render/region.js +17 -0
- package/build/src/cli/render/task.d.ts +2 -1
- package/build/src/cli/render/task.js +223 -60
- package/build/src/cli/render/terminal.d.ts +20 -0
- package/build/src/cli/render/terminal.js +121 -0
- package/build/src/cli/render/text.js +11 -3
- package/build/src/cli/result.d.ts +126 -19
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +44 -0
- package/build/src/contract-worktree.js +251 -0
- package/build/src/coordination/durable-file.d.ts +5 -1
- package/build/src/coordination/durable-file.js +57 -10
- package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
- package/build/src/coordination/sqlite-transaction-lock.js +22 -5
- package/build/src/core/facts/codec.js +23 -4
- package/build/src/core/facts/eligibility.d.ts +1 -10
- package/build/src/core/facts/eligibility.js +0 -49
- package/build/src/core/facts/fold.js +1 -6
- package/build/src/core/facts/gate.d.ts +1 -0
- package/build/src/core/facts/gate.js +1 -0
- package/build/src/core/facts/observation.d.ts +3 -0
- package/build/src/core/facts/observation.js +12 -0
- package/build/src/core/facts/types.d.ts +10 -3
- package/build/src/core/subject.js +2 -2
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +3 -18
- package/build/src/core/verbs/bind.js +2 -16
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +14 -4
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +7 -9
- package/build/src/dispatch/index.d.ts +5 -3
- package/build/src/dispatch/index.js +30 -21
- package/build/src/duration.d.ts +10 -0
- package/build/src/duration.js +22 -0
- package/build/src/git/admission.d.ts +2 -2
- package/build/src/git/admission.js +33 -23
- package/build/src/git/hooks.d.ts +15 -0
- package/build/src/git/hooks.js +70 -18
- package/build/src/git/identity.d.ts +5 -1
- package/build/src/git/identity.js +23 -4
- package/build/src/git/integration.d.ts +48 -0
- package/build/src/git/integration.js +250 -0
- package/build/src/git/observe.d.ts +29 -15
- package/build/src/git/observe.js +185 -76
- package/build/src/git/read-observation.d.ts +41 -0
- package/build/src/git/read-observation.js +361 -0
- package/build/src/git/reconcile.d.ts +17 -5
- package/build/src/git/reconcile.js +305 -109
- package/build/src/git/repository.d.ts +41 -18
- package/build/src/git/repository.js +220 -114
- package/build/src/git/scratch.d.ts +17 -0
- package/build/src/git/scratch.js +73 -0
- package/build/src/git/target-placement.d.ts +92 -0
- package/build/src/git/target-placement.js +375 -0
- package/build/src/git/tender.d.ts +49 -0
- package/build/src/git/tender.js +63 -0
- package/build/src/git/terminal-seal.d.ts +24 -0
- package/build/src/git/terminal-seal.js +89 -0
- package/build/src/git/tree.d.ts +2 -2
- package/build/src/git/tree.js +4 -0
- package/build/src/git/workspace.d.ts +53 -0
- package/build/src/git/workspace.js +139 -0
- package/build/src/identity/selector.d.ts +6 -0
- package/build/src/identity/selector.js +19 -0
- package/build/src/index.d.ts +4 -2
- package/build/src/index.js +2 -1
- package/build/src/kanshi/index.d.ts +2 -2
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +7 -3
- package/build/src/kanshi/read.js +245 -45
- package/build/src/kanshi/report.d.ts +81 -6
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +33 -1
- package/build/src/library/address.d.ts +57 -0
- package/build/src/library/address.js +165 -0
- package/build/src/library/akuma-creation.d.ts +16 -7
- package/build/src/library/akuma-creation.js +96 -22
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.d.ts +21 -0
- package/build/src/library/bind.js +56 -0
- package/build/src/library/catalog.d.ts +58 -0
- package/build/src/library/catalog.js +69 -0
- package/build/src/library/configuration.d.ts +6 -15
- package/build/src/library/configuration.js +14 -17
- package/build/src/library/contract.d.ts +23 -49
- package/build/src/library/contract.js +171 -185
- package/build/src/library/delivery.d.ts +24 -0
- package/build/src/library/delivery.js +21 -0
- package/build/src/library/fleet.d.ts +65 -0
- package/build/src/library/fleet.js +153 -0
- package/build/src/library/input.d.ts +3 -0
- package/build/src/library/input.js +19 -0
- package/build/src/library/keiyaku.d.ts +18 -3
- package/build/src/library/keiyaku.js +12 -1
- package/build/src/library/mutation.d.ts +39 -0
- package/build/src/library/mutation.js +37 -0
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/refusal.d.ts +21 -0
- package/build/src/library/refusal.js +29 -0
- package/build/src/library/region.d.ts +14 -1
- package/build/src/library/region.js +18 -4
- package/build/src/library/repo.d.ts +4 -13
- package/build/src/library/repo.js +14 -24
- package/build/src/protocol/attempt.d.ts +16 -3
- package/build/src/protocol/attempt.js +41 -10
- package/build/src/protocol/bind.d.ts +9 -2
- package/build/src/protocol/bind.js +48 -40
- package/build/src/protocol/intent.d.ts +57 -20
- package/build/src/protocol/intent.js +55 -79
- package/build/src/protocol/operations.d.ts +152 -43
- package/build/src/protocol/operations.js +482 -166
- package/build/src/protocol/outcome.d.ts +14 -3
- package/build/src/protocol/outcome.js +11 -3
- package/build/src/protocol/placement.d.ts +41 -0
- package/build/src/protocol/placement.js +147 -0
- package/build/src/protocol/read/documents.d.ts +2 -2
- package/build/src/protocol/read/documents.js +4 -4
- package/build/src/protocol/read/status.d.ts +18 -5
- package/build/src/protocol/read/status.js +73 -13
- package/build/src/protocol/run.d.ts +49 -7
- package/build/src/protocol/run.js +53 -25
- package/build/src/runtime/proc/line-rpc.d.ts +4 -8
- package/build/src/runtime/proc/line-rpc.js +22 -28
- package/build/src/runtime/proc/run.d.ts +23 -21
- package/build/src/runtime/proc/run.js +123 -89
- package/build/src/runtime/proc/stdio.d.ts +18 -0
- package/build/src/runtime/proc/stdio.js +58 -0
- package/build/src/settings.d.ts +7 -1
- package/build/src/settings.js +32 -17
- package/build/src/settlement/fence.d.ts +5 -0
- package/build/src/settlement/fence.js +14 -0
- package/build/src/settlement/holder.d.ts +35 -4
- package/build/src/settlement/holder.js +127 -28
- package/build/src/settlement/settle.d.ts +9 -1
- package/build/src/settlement/settle.js +74 -37
- package/build/src/task/board.d.ts +23 -5
- package/build/src/task/board.js +17 -10
- package/build/src/task/compose.d.ts +2 -2
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +15 -20
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +27 -15
- package/build/src/task/index.js +57 -35
- package/build/src/task/operations.d.ts +38 -13
- package/build/src/task/operations.js +80 -46
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +5 -7
- package/build/src/task/store.js +43 -28
- package/build/src/verification/declaration.d.ts +1 -0
- package/build/src/verification/execution.d.ts +51 -0
- package/build/src/verification/execution.js +108 -0
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +24 -0
- package/build/src/world.js +136 -0
- package/package.json +8 -4
- package/build/src/akuma/activity.d.ts +0 -66
- package/build/src/akuma/activity.js +0 -139
- package/build/src/akuma/providers/claude.js +0 -305
- package/build/src/context-root.d.ts +0 -4
- package/build/src/context-root.js +0 -15
- package/build/src/git/delivery.d.ts +0 -20
- package/build/src/git/delivery.js +0 -109
- package/build/src/git/verification.d.ts +0 -14
- package/build/src/git/verification.js +0 -56
- package/build/src/protocol/read/audit.d.ts +0 -25
- package/build/src/protocol/read/audit.js +0 -39
- package/build/src/verification/producer.d.ts +0 -23
- package/build/src/verification/producer.js +0 -54
package/build/src/cli/invoke.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { gatesFrom, Keiyaku, NoGitWorldError, Repo, settings, SettingsError, worktreeHooksFrom } from "../index.js";
|
|
4
|
-
import { kanshi, selectKanshi } from "../kanshi/index.js";
|
|
1
|
+
import { AkumaWorldScopeError, gatesFrom, Keiyaku, requireBranchesToBeUpToDateFrom, settings, SettingsError, worktreeHooksFrom } from "../index.js";
|
|
2
|
+
import { kanshi, selectKanshi, selectRegion } from "../kanshi/index.js";
|
|
5
3
|
import { resolveActor } from "./actor.js";
|
|
6
|
-
import { resultFromMutationCall } from "./accepted.js";
|
|
4
|
+
import { acceptedAbandon, acceptedAmend, acceptedArc, acceptedAudit, acceptedBind, acceptedDeliver, acceptedReview, resultFromMutationCall, } from "./accepted.js";
|
|
7
5
|
import { amendFromCommand } from "./commands/amend.js";
|
|
8
6
|
import { invokeAkuma, invokeAkumaStatus } from "./commands/akuma-invoke.js";
|
|
9
7
|
import { isParsedAkumaCommand } from "./commands/akuma.js";
|
|
@@ -11,10 +9,53 @@ import { bindFromCommand } from "./commands/bind.js";
|
|
|
11
9
|
import { installHarnesses } from "./commands/install.js";
|
|
12
10
|
import { invokeTask } from "./commands/task-invoke.js";
|
|
13
11
|
import { CliUsageError, renderCommandUsage } from "./parse.js";
|
|
12
|
+
import { isBlankInput } from "./usage.js";
|
|
14
13
|
import { contractFromInput, resolveContextualContract, resolveKanshiContract } from "./selectors.js";
|
|
14
|
+
import { resolveNamedAddress } from "../library/address.js";
|
|
15
|
+
import { assertExplicitRepoUse, resolveCliCoordinates } from "./coordinates.js";
|
|
16
|
+
import { BindDraftError, preserveBindDraft } from "./draft.js";
|
|
17
|
+
async function readStdin() {
|
|
18
|
+
const chunks = [];
|
|
19
|
+
for await (const chunk of process.stdin)
|
|
20
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
21
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
22
|
+
}
|
|
23
|
+
function selectedStdinDiagnostic(command) {
|
|
24
|
+
switch (command.command) {
|
|
25
|
+
case "bind":
|
|
26
|
+
case "amend":
|
|
27
|
+
case "arc":
|
|
28
|
+
return `${command.command} requires a nonblank stdin document`;
|
|
29
|
+
case "review":
|
|
30
|
+
return command.summaryFromStdin === true ? "review requires a nonblank summary" : undefined;
|
|
31
|
+
case "call":
|
|
32
|
+
case "tell":
|
|
33
|
+
return command.prompt.kind === "stdin" ? `${command.command} requires a nonblank prompt` : undefined;
|
|
34
|
+
case "task":
|
|
35
|
+
switch (command.stdin) {
|
|
36
|
+
case "document": return "task add requires a nonblank stdin document";
|
|
37
|
+
case "compose": return "task compose requires a nonblank stdin document";
|
|
38
|
+
case "body": return "task update --body requires a nonblank value";
|
|
39
|
+
case "append": return "task update --append requires a nonblank value";
|
|
40
|
+
case "note": return "task update --note requires a nonblank value";
|
|
41
|
+
default: return undefined;
|
|
42
|
+
}
|
|
43
|
+
default:
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function withAcquiredStdin(command, runtime) {
|
|
48
|
+
const diagnostic = selectedStdinDiagnostic(command);
|
|
49
|
+
if (diagnostic === undefined)
|
|
50
|
+
return runtime;
|
|
51
|
+
const bytes = await (runtime.readStdin ?? readStdin)();
|
|
52
|
+
if (isBlankInput(bytes))
|
|
53
|
+
throw new CliUsageError(diagnostic);
|
|
54
|
+
return { ...runtime, readStdin: async () => bytes };
|
|
55
|
+
}
|
|
15
56
|
function settingsAt(root, environment) {
|
|
16
57
|
const home = environment.KEIYAKU_HOME?.trim();
|
|
17
|
-
return settings({ root, ...(home === undefined || home.length === 0 ? {} : { home }) });
|
|
58
|
+
return settings({ ...(root === undefined ? {} : { root }), ...(home === undefined || home.length === 0 ? {} : { home }) });
|
|
18
59
|
}
|
|
19
60
|
function selectedGates(value, name) {
|
|
20
61
|
try {
|
|
@@ -36,6 +77,16 @@ function selectedHooks(value) {
|
|
|
36
77
|
throw error;
|
|
37
78
|
}
|
|
38
79
|
}
|
|
80
|
+
function selectedGitPolicy(value) {
|
|
81
|
+
try {
|
|
82
|
+
return requireBranchesToBeUpToDateFrom({ settings: value });
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error instanceof SettingsError)
|
|
86
|
+
throw new CliUsageError(error.message);
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
39
90
|
function actorFromEdge(actor, environment) {
|
|
40
91
|
let resolved;
|
|
41
92
|
try {
|
|
@@ -46,88 +97,84 @@ function actorFromEdge(actor, environment) {
|
|
|
46
97
|
}
|
|
47
98
|
return resolved;
|
|
48
99
|
}
|
|
49
|
-
function repoAt(coordinate) {
|
|
50
|
-
return coordinate === undefined ? Repo.at() : Repo.at({ path: coordinate });
|
|
51
|
-
}
|
|
52
100
|
async function selectContract(repo, selector, scope) {
|
|
53
101
|
if (selector !== undefined && !selector.startsWith("@"))
|
|
54
102
|
return contractFromInput(repo, selector);
|
|
55
103
|
const id = resolveContextualContract(await Keiyaku.list({ repo }), selector, scope);
|
|
56
104
|
return contractFromInput(repo, id);
|
|
57
105
|
}
|
|
58
|
-
async function
|
|
59
|
-
|
|
106
|
+
async function bindDraftReceipt(establishWorld, markdown) {
|
|
107
|
+
try {
|
|
108
|
+
return preserveBindDraft(await establishWorld(), markdown);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return { warning: `bind draft could not be preserved: ${error instanceof Error ? error.message : String(error)}` };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async function invokeBind({ parsed, repo, edge, configuration, hooks, establishWorld }) {
|
|
115
|
+
const markdown = await edge.readStdin();
|
|
60
116
|
const gates = selectedGates(configuration, parsed.gates);
|
|
61
117
|
const actor = actorFromEdge(parsed.actor, edge.environment);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const bound =
|
|
118
|
+
try {
|
|
119
|
+
const result = await resultFromMutationCall("bind", () => bindFromCommand({
|
|
120
|
+
command: parsed,
|
|
121
|
+
repo,
|
|
122
|
+
markdown,
|
|
123
|
+
gates,
|
|
124
|
+
...(actor === undefined ? {} : { actor }),
|
|
125
|
+
hooks,
|
|
126
|
+
}), (accepted) => {
|
|
127
|
+
const bound = accepted.facts.find((fact) => fact.kind === "bind");
|
|
72
128
|
if (bound === undefined || bound.kind !== "bind")
|
|
73
129
|
throw new Error("accepted bind is missing its bind fact");
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
|
|
130
|
+
return acceptedBind(accepted, bound.data.coordinates.target ?? null);
|
|
131
|
+
});
|
|
132
|
+
if (result.kind !== "refused")
|
|
133
|
+
return result;
|
|
134
|
+
return { ...result, draft: await bindDraftReceipt(establishWorld, markdown) };
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (!(error instanceof TypeError))
|
|
138
|
+
throw error;
|
|
139
|
+
throw new BindDraftError(error, await bindDraftReceipt(establishWorld, markdown));
|
|
140
|
+
}
|
|
77
141
|
}
|
|
78
|
-
function
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
};
|
|
142
|
+
function deliverRefusal(refusal) {
|
|
143
|
+
if (typeof refusal !== "object" || refusal === null || !("kind" in refusal) || refusal.kind !== "dirty-workspace") {
|
|
144
|
+
return refusal;
|
|
145
|
+
}
|
|
146
|
+
const submodules = "submodules" in refusal && Array.isArray(refusal.submodules) ? refusal.submodules : [];
|
|
147
|
+
return { ...refusal, option: { flag: "--include-dirty", available: submodules.length === 0 } };
|
|
84
148
|
}
|
|
85
|
-
async function invokeDeliver(parsed, seat) {
|
|
149
|
+
async function invokeDeliver(parsed, seat, requireBranchesToBeUpToDate) {
|
|
86
150
|
return resultFromMutationCall("deliver", () => seat.contract.deliver({
|
|
87
151
|
...(seat.actor === undefined ? {} : { actor: seat.actor }),
|
|
88
152
|
...(parsed.message === undefined ? {} : { message: parsed.message }),
|
|
153
|
+
requireBranchesToBeUpToDate,
|
|
154
|
+
includeDirty: parsed.includeDirty,
|
|
89
155
|
hooks: seat.hooks,
|
|
90
|
-
}), {
|
|
156
|
+
}), (result) => acceptedDeliver(result, seat.id), {
|
|
91
157
|
coordinate: seat.id,
|
|
92
|
-
|
|
93
|
-
obligations: {
|
|
94
|
-
...(result.value.verification === undefined ? {} : { verification: result.value.verification }),
|
|
95
|
-
...(result.value.placement === undefined ? {} : { placement: result.value.placement }),
|
|
96
|
-
...(result.value.leak === undefined ? {} : { leak: result.value.leak }),
|
|
97
|
-
},
|
|
98
|
-
}),
|
|
158
|
+
projectRefusal: deliverRefusal,
|
|
99
159
|
});
|
|
100
160
|
}
|
|
101
161
|
async function invokeReview(parsed, seat, readStdin) {
|
|
102
|
-
const summary = parsed.summaryFromStdin === true ? readStdin() : parsed.summary;
|
|
162
|
+
const summary = parsed.summaryFromStdin === true ? await readStdin() : parsed.summary;
|
|
103
163
|
return resultFromMutationCall("review", () => seat.contract.review({
|
|
104
164
|
verdict: parsed.verdict,
|
|
105
165
|
...(seat.actor === undefined ? {} : { actor: seat.actor }),
|
|
106
166
|
...(summary === undefined ? {} : { summary }),
|
|
107
167
|
hooks: seat.hooks,
|
|
108
|
-
}), {
|
|
109
|
-
coordinate: seat.id,
|
|
110
|
-
project: (result) => ({
|
|
111
|
-
obligations: result.value.placement === undefined ? {} : { placement: result.value.placement },
|
|
112
|
-
}),
|
|
113
|
-
});
|
|
168
|
+
}), (result) => acceptedReview(result, seat.id), { coordinate: seat.id });
|
|
114
169
|
}
|
|
115
|
-
async function invokeAudit(parsed, seat) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
renderedDiff = diff === null ? unavailableDiff(delivery) : diff;
|
|
124
|
-
}
|
|
125
|
-
return {
|
|
126
|
-
report: result.value,
|
|
127
|
-
...(renderedDiff === undefined ? {} : { diff: renderedDiff }),
|
|
128
|
-
};
|
|
129
|
-
},
|
|
130
|
-
});
|
|
170
|
+
async function invokeAudit(parsed, seat, requireBranchesToBeUpToDate) {
|
|
171
|
+
return resultFromMutationCall("audit", () => seat.contract.audit({
|
|
172
|
+
...(seat.actor === undefined ? {} : { actor: seat.actor }),
|
|
173
|
+
includeDirty: parsed.includeDirty,
|
|
174
|
+
showDiff: parsed.showDiff,
|
|
175
|
+
requireBranchesToBeUpToDate,
|
|
176
|
+
hooks: seat.hooks,
|
|
177
|
+
}), (result) => acceptedAudit(result, seat.id), { coordinate: seat.id });
|
|
131
178
|
}
|
|
132
179
|
async function invokeExisting({ parsed, repo, edge, scope, configuration, hooks }) {
|
|
133
180
|
const { id, contract } = await selectContract(repo, parsed.contract, scope);
|
|
@@ -135,77 +182,192 @@ async function invokeExisting({ parsed, repo, edge, scope, configuration, hooks
|
|
|
135
182
|
const seat = { contract, id, ...(actor === undefined ? {} : { actor }), hooks };
|
|
136
183
|
switch (parsed.command) {
|
|
137
184
|
case "amend": {
|
|
138
|
-
const markdown = edge.readStdin();
|
|
185
|
+
const markdown = await edge.readStdin();
|
|
139
186
|
const gates = parsed.gates === undefined
|
|
140
187
|
? undefined
|
|
141
188
|
: selectedGates(configuration, parsed.gates);
|
|
142
|
-
return resultFromMutationCall("amend", () => amendFromCommand({ command: parsed, repo, contract, markdown, gates, ...(actor === undefined ? {} : { actor }), hooks }), { coordinate: id });
|
|
189
|
+
return resultFromMutationCall("amend", () => amendFromCommand({ command: parsed, repo, contract, markdown, gates, ...(actor === undefined ? {} : { actor }), hooks }), (result) => acceptedAmend(result, id), { coordinate: id });
|
|
143
190
|
}
|
|
144
191
|
case "deliver":
|
|
145
|
-
return invokeDeliver(parsed, seat);
|
|
192
|
+
return invokeDeliver(parsed, seat, selectedGitPolicy(configuration));
|
|
146
193
|
case "review":
|
|
147
194
|
return invokeReview(parsed, seat, edge.readStdin);
|
|
148
195
|
case "arc": {
|
|
149
|
-
const markdown = edge.readStdin();
|
|
196
|
+
const markdown = await edge.readStdin();
|
|
150
197
|
return resultFromMutationCall("arc", () => contract.arc({
|
|
151
198
|
markdown,
|
|
152
199
|
...(actor === undefined ? {} : { actor }),
|
|
153
200
|
hooks,
|
|
154
|
-
}), { coordinate: id });
|
|
201
|
+
}), (result) => acceptedArc(result, id), { coordinate: id });
|
|
155
202
|
}
|
|
156
203
|
case "abandon":
|
|
157
204
|
return resultFromMutationCall("abandon", () => contract.abandon({
|
|
158
205
|
...(actor === undefined ? {} : { actor }),
|
|
159
206
|
...(parsed.note === undefined ? {} : { note: parsed.note }),
|
|
160
207
|
hooks,
|
|
161
|
-
}), { coordinate: id });
|
|
208
|
+
}), (result) => acceptedAbandon(result, id), { coordinate: id });
|
|
162
209
|
case "audit":
|
|
163
|
-
return invokeAudit(parsed, seat);
|
|
210
|
+
return invokeAudit(parsed, seat, selectedGitPolicy(configuration));
|
|
164
211
|
default:
|
|
165
212
|
return parsed;
|
|
166
213
|
}
|
|
167
214
|
}
|
|
168
|
-
async function invokeAkumaCommand(parsed,
|
|
215
|
+
async function invokeAkumaCommand(parsed, input) {
|
|
216
|
+
const { path, executionCwd, repo, configuration, edge } = input;
|
|
169
217
|
if (parsed.command === "call" && parsed.contract !== undefined) {
|
|
170
|
-
|
|
218
|
+
if (repo === undefined)
|
|
219
|
+
throw new Error("call with Contract requires a resolved Repo");
|
|
220
|
+
const selected = contractFromInput(repo, parsed.contract);
|
|
171
221
|
return await invokeAkuma(parsed, {
|
|
172
222
|
path,
|
|
223
|
+
...(executionCwd === undefined ? {} : { executionCwd }),
|
|
173
224
|
settings: configuration,
|
|
174
225
|
contract: selected.contract,
|
|
175
226
|
readStdin: edge.readStdin,
|
|
176
227
|
});
|
|
177
228
|
}
|
|
178
|
-
|
|
179
|
-
|
|
229
|
+
return await invokeAkuma(parsed, {
|
|
230
|
+
path,
|
|
231
|
+
...(executionCwd === undefined ? {} : { executionCwd }),
|
|
232
|
+
settings: configuration,
|
|
233
|
+
...(repo === undefined ? {} : { repo }),
|
|
234
|
+
readStdin: edge.readStdin,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
async function invokeAkumaFromEdge(parsed, input) {
|
|
238
|
+
try {
|
|
239
|
+
return await invokeAkumaCommand(parsed, input);
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
if (error instanceof AkumaWorldScopeError)
|
|
243
|
+
throw error;
|
|
244
|
+
if (error instanceof TypeError)
|
|
245
|
+
throw new CliUsageError(error.message);
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function akumaWorldFor(parsed, located, candidate, establish) {
|
|
250
|
+
const world = parsed.command === "call" ? candidate ?? await establish() : located;
|
|
251
|
+
if (world === null)
|
|
252
|
+
throw new CliUsageError("no Keiyaku world contains the invocation cwd");
|
|
253
|
+
return world;
|
|
254
|
+
}
|
|
255
|
+
async function invokeCatalog(parsed, world, repo, edge) {
|
|
256
|
+
try {
|
|
257
|
+
if (parsed.query.kind === "contracts") {
|
|
258
|
+
if (repo === undefined)
|
|
259
|
+
throw new Error("Contract catalog requires a resolved Repo");
|
|
260
|
+
return { kind: "catalog", catalog: await Keiyaku.ls({ query: parsed.query, repo }) };
|
|
261
|
+
}
|
|
262
|
+
if (parsed.query.kind === "archetypes") {
|
|
263
|
+
return {
|
|
264
|
+
kind: "catalog",
|
|
265
|
+
catalog: await Keiyaku.ls({ query: parsed.query, settings: await settingsAt(undefined, edge.environment) }),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
if (world === null)
|
|
269
|
+
throw new CliUsageError("no Keiyaku world contains the invocation cwd");
|
|
270
|
+
if (parsed.query.kind === "tasks") {
|
|
271
|
+
return { kind: "catalog", catalog: await Keiyaku.ls({ query: parsed.query, path: world }) };
|
|
272
|
+
}
|
|
273
|
+
return { kind: "catalog", catalog: await Keiyaku.ls({ query: parsed.query, path: world }) };
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
if (error instanceof TypeError)
|
|
277
|
+
throw new CliUsageError(error.message);
|
|
278
|
+
throw error;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async function invokeStatus(parsed, world, repo, edge) {
|
|
282
|
+
const configuration = await settingsAt(world ?? undefined, edge.environment);
|
|
283
|
+
if (parsed.akuma === true) {
|
|
284
|
+
if (world === null)
|
|
285
|
+
throw new CliUsageError("no Keiyaku world contains the invocation cwd");
|
|
286
|
+
return invokeAkumaStatus(world, parsed.contract, configuration, undefined, repo);
|
|
287
|
+
}
|
|
288
|
+
if (parsed.contract === undefined) {
|
|
289
|
+
const report = await kanshi({ world, ...(repo === undefined ? {} : { repo }) });
|
|
290
|
+
return { kind: "status", report, selection: "world" };
|
|
291
|
+
}
|
|
292
|
+
if (parsed.contract.startsWith("@")) {
|
|
293
|
+
try {
|
|
294
|
+
const address = await resolveNamedAddress({
|
|
295
|
+
path: world,
|
|
296
|
+
selector: parsed.contract,
|
|
297
|
+
contracts: repo === undefined ? [] : (await Keiyaku.list({ repo })).rows,
|
|
298
|
+
});
|
|
299
|
+
if (address.kind === "akuma") {
|
|
300
|
+
if (world === null)
|
|
301
|
+
throw new CliUsageError("no Keiyaku world contains the invocation cwd");
|
|
302
|
+
return invokeAkumaStatus(world, address.id, configuration, parsed.contract, repo);
|
|
303
|
+
}
|
|
304
|
+
const report = await kanshi({ world, ...(repo === undefined ? {} : { repo }) });
|
|
305
|
+
return { kind: "status", report: selectKanshi({ report, contract: address.id }), selection: "contract" };
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
if (error instanceof TypeError)
|
|
309
|
+
throw new CliUsageError(error.message);
|
|
310
|
+
throw error;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const report = await kanshi({ world, ...(repo === undefined ? {} : { repo }) });
|
|
314
|
+
const contract = resolveKanshiContract(report, parsed.contract);
|
|
315
|
+
return { kind: "status", report: selectKanshi({ report, contract }), selection: "contract" };
|
|
316
|
+
}
|
|
317
|
+
async function invokeRegion(parsed, world, repo) {
|
|
318
|
+
const read = async (region) => {
|
|
180
319
|
try {
|
|
181
|
-
repo
|
|
320
|
+
return await kanshi({ world, repo, region });
|
|
182
321
|
}
|
|
183
322
|
catch (error) {
|
|
184
|
-
if (
|
|
185
|
-
throw error;
|
|
323
|
+
if (error instanceof TypeError)
|
|
324
|
+
throw new CliUsageError(error.message);
|
|
325
|
+
throw error;
|
|
186
326
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
327
|
+
};
|
|
328
|
+
if (parsed.contract === undefined) {
|
|
329
|
+
const selection = parsed.path !== undefined
|
|
330
|
+
? { kind: "path", path: parsed.path }
|
|
331
|
+
: parsed.overlap ? { kind: "overlap" } : { kind: "declarations" };
|
|
332
|
+
const report = await read(selection);
|
|
333
|
+
return { kind: "region", region: report.region ?? { kind: "absent" } };
|
|
334
|
+
}
|
|
335
|
+
const report = await read({ kind: "declarations" });
|
|
336
|
+
const contract = resolveKanshiContract(report, parsed.contract);
|
|
337
|
+
if (report.contracts.kind !== "present" || report.contracts.value.rows.every((row) => row.id !== contract || row.disposition !== "active")) {
|
|
338
|
+
throw new CliUsageError(`unknown contract selector: ${parsed.contract}`);
|
|
339
|
+
}
|
|
340
|
+
if (report.region?.kind !== "present" || report.region.value.kind !== "declarations") {
|
|
341
|
+
return { kind: "region", region: report.region ?? { kind: "absent" } };
|
|
193
342
|
}
|
|
194
|
-
|
|
343
|
+
const selection = parsed.overlap ? { kind: "overlap", contract } : { kind: "contract", contract };
|
|
344
|
+
return { kind: "region", region: { kind: "present", value: selectRegion({ declarations: report.region.value.declarations, selection }) } };
|
|
195
345
|
}
|
|
346
|
+
// eslint-disable-next-line complexity -- command dispatch keeps the CLI's existing boundary in one place.
|
|
196
347
|
async function invokeParsed(invocation, runtime) {
|
|
197
|
-
const
|
|
348
|
+
const coordinates = await resolveCliCoordinates({
|
|
349
|
+
...(runtime.cwd === undefined ? {} : { processCwd: runtime.cwd }),
|
|
350
|
+
...(invocation.cwd === undefined ? {} : { cwd: invocation.cwd }),
|
|
351
|
+
...(invocation.repo === undefined ? {} : { repo: invocation.repo }),
|
|
352
|
+
command: invocation.command,
|
|
353
|
+
});
|
|
354
|
+
const { cwd, repo, world, candidateWorld, establishWorld } = coordinates;
|
|
198
355
|
const edge = {
|
|
199
356
|
environment: runtime.environment ?? process.env,
|
|
200
|
-
readStdin: runtime.readStdin ??
|
|
357
|
+
readStdin: runtime.readStdin ?? readStdin,
|
|
201
358
|
};
|
|
202
359
|
const parsed = invocation.command;
|
|
203
360
|
if (parsed.command === "settings") {
|
|
204
|
-
return { kind: "settings", value: settingsAt(
|
|
361
|
+
return { kind: "settings", value: await settingsAt(world ?? undefined, edge.environment) };
|
|
205
362
|
}
|
|
206
363
|
if (parsed.command === "task") {
|
|
207
364
|
try {
|
|
208
|
-
return await invokeTask(parsed, {
|
|
365
|
+
return await invokeTask(parsed, {
|
|
366
|
+
world,
|
|
367
|
+
establish: coordinates.establishWorld,
|
|
368
|
+
readStdin: edge.readStdin,
|
|
369
|
+
...(runtime.actor === undefined ? {} : { actor: runtime.actor }),
|
|
370
|
+
});
|
|
209
371
|
}
|
|
210
372
|
catch (error) {
|
|
211
373
|
if (error instanceof TypeError)
|
|
@@ -214,24 +376,33 @@ async function invokeParsed(invocation, runtime) {
|
|
|
214
376
|
}
|
|
215
377
|
}
|
|
216
378
|
if (isParsedAkumaCommand(parsed)) {
|
|
217
|
-
const
|
|
218
|
-
const configuration = settingsAt(
|
|
219
|
-
return await
|
|
379
|
+
const akumaWorld = await akumaWorldFor(parsed, world, candidateWorld, coordinates.establishWorld);
|
|
380
|
+
const configuration = await settingsAt(akumaWorld, edge.environment);
|
|
381
|
+
return await invokeAkumaFromEdge(parsed, {
|
|
382
|
+
path: akumaWorld,
|
|
383
|
+
...(parsed.command === "call" && parsed.contract !== undefined && invocation.cwd === undefined
|
|
384
|
+
? {}
|
|
385
|
+
: { executionCwd: cwd }),
|
|
386
|
+
...(repo === undefined ? {} : { repo }),
|
|
387
|
+
configuration,
|
|
388
|
+
edge,
|
|
389
|
+
});
|
|
220
390
|
}
|
|
221
|
-
if (parsed.command === "
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const repo = repoAt(coordinate);
|
|
232
|
-
const scope = coordinate ?? repo.root;
|
|
233
|
-
const configuration = settingsAt(repo.root, edge.environment);
|
|
391
|
+
if (parsed.command === "ls")
|
|
392
|
+
return await invokeCatalog(parsed, world, repo, edge);
|
|
393
|
+
if (parsed.command === "status")
|
|
394
|
+
return await invokeStatus(parsed, world, repo, edge);
|
|
395
|
+
if (repo === undefined)
|
|
396
|
+
throw new Error(`${parsed.command} requires a resolved Repo`);
|
|
397
|
+
if (parsed.command === "region")
|
|
398
|
+
return invokeRegion(parsed, world, repo);
|
|
399
|
+
const scope = cwd;
|
|
400
|
+
const configuration = await settingsAt(world ?? undefined, edge.environment);
|
|
234
401
|
const hooks = selectedHooks(configuration);
|
|
402
|
+
if (parsed.command === "show") {
|
|
403
|
+
const selected = await selectContract(repo, parsed.contract, scope);
|
|
404
|
+
return { kind: "guidance", contract: selected.id, guidance: await selected.contract.guidance() };
|
|
405
|
+
}
|
|
235
406
|
switch (parsed.command) {
|
|
236
407
|
case "reconcile": {
|
|
237
408
|
if (parsed.contract === undefined) {
|
|
@@ -241,20 +412,28 @@ async function invokeParsed(invocation, runtime) {
|
|
|
241
412
|
return { kind: "observation", command: "reconcile", ...await contract.reconcile({ hooks, retryHooks: parsed.retryHooks }) };
|
|
242
413
|
}
|
|
243
414
|
case "bind":
|
|
244
|
-
return invokeBind(parsed, repo, edge, configuration, hooks);
|
|
415
|
+
return invokeBind({ parsed, repo, edge, configuration, hooks, establishWorld });
|
|
245
416
|
default:
|
|
246
417
|
return invokeExisting({ parsed, repo, edge, scope, configuration, hooks });
|
|
247
418
|
}
|
|
248
419
|
}
|
|
249
|
-
|
|
250
|
-
|
|
420
|
+
function withResolvedTaskActor(command, runtime) {
|
|
421
|
+
if (command.command !== "task" || (command.action !== "add" && command.action !== "compose"))
|
|
422
|
+
return runtime;
|
|
423
|
+
const actor = actorFromEdge(typeof command.flags.actor === "string" ? command.flags.actor : undefined, runtime.environment ?? process.env);
|
|
424
|
+
return actor === undefined ? runtime : { ...runtime, actor };
|
|
251
425
|
}
|
|
252
426
|
export async function invoke(invocation, runtime = {}) {
|
|
253
427
|
try {
|
|
254
428
|
const command = invocation.command;
|
|
429
|
+
assertExplicitRepoUse(command, invocation.repo);
|
|
255
430
|
if (command.command === "install")
|
|
256
|
-
return
|
|
257
|
-
return await invokeParsed({
|
|
431
|
+
return installHarnesses(command.harnesses, runtime.environment ?? process.env);
|
|
432
|
+
return await invokeParsed({
|
|
433
|
+
...(invocation.cwd === undefined ? {} : { cwd: invocation.cwd }),
|
|
434
|
+
...(invocation.repo === undefined ? {} : { repo: invocation.repo }),
|
|
435
|
+
command,
|
|
436
|
+
}, await withAcquiredStdin(command, withResolvedTaskActor(command, runtime)));
|
|
258
437
|
}
|
|
259
438
|
catch (error) {
|
|
260
439
|
if (error instanceof CliUsageError && error.projection === undefined) {
|
package/build/src/cli/main.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
import { AkumaWorldScopeError } from "../index.js";
|
|
1
2
|
import { CliUsageError, parseArgv, renderContractHelp, renderRootHelp, } from "./parse.js";
|
|
2
3
|
import { renderText } from "./render/text.js";
|
|
3
4
|
import { renderTaskIncompleteDiagnostic, renderTaskText, taskExitCode } from "./render/task.js";
|
|
4
|
-
import { akumaExitCode, renderAkumaJson, renderAkumaText } from "./render/akuma.js";
|
|
5
|
+
import { akumaExitCode, akumaRawAnswer, renderAkumaJson, renderAkumaText } from "./render/akuma.js";
|
|
5
6
|
import { isParsedAkumaCommand, renderAkumaHelp } from "./commands/akuma.js";
|
|
6
7
|
import { installExitCode, renderInstallHelp, renderInstallText } from "./commands/install.js";
|
|
7
8
|
import { renderTaskHelp } from "./commands/task.js";
|
|
8
9
|
import { renderSettingsText, settingsJsonValue } from "./render/settings.js";
|
|
10
|
+
import { renderCatalogText } from "./render/catalog.js";
|
|
11
|
+
import { BindDraftError } from "./draft.js";
|
|
12
|
+
import { renderBindDraftReceipt } from "./render/refusal.js";
|
|
9
13
|
function writeTask(command, result) {
|
|
14
|
+
const context = {
|
|
15
|
+
columns: process.stdout.isTTY === true && Number.isInteger(process.stdout.columns) ? process.stdout.columns : 80,
|
|
16
|
+
color: false,
|
|
17
|
+
};
|
|
10
18
|
if (command.output === "json")
|
|
11
19
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
12
20
|
else if (command.action === "compose" && typeof result === "object" && result !== null && "kind" in result && result.kind === "incomplete") {
|
|
@@ -16,13 +24,17 @@ function writeTask(command, result) {
|
|
|
16
24
|
process.stdout.write(result.draft);
|
|
17
25
|
}
|
|
18
26
|
else
|
|
19
|
-
process.stdout.write(`${renderTaskText(command, result)}\n`);
|
|
27
|
+
process.stdout.write(`${renderTaskText(command, result, context)}\n`);
|
|
20
28
|
return taskExitCode(result);
|
|
21
29
|
}
|
|
22
30
|
function writeAkuma(command, result) {
|
|
23
|
-
const output = command.output === "json" ? renderAkumaJson(command, result) : renderAkumaText(command, result
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
const output = command.output === "json" ? renderAkumaJson(command, result) : renderAkumaText(command, result, {
|
|
32
|
+
columns: process.stdout.isTTY === true && Number.isInteger(process.stdout.columns) ? process.stdout.columns : 80,
|
|
33
|
+
color: process.stdout.isTTY === true && process.env.NO_COLOR === undefined,
|
|
34
|
+
});
|
|
35
|
+
const raw = command.output === "text"
|
|
36
|
+
&& ((command.command === "history" && command.last) || akumaRawAnswer(result) !== undefined);
|
|
37
|
+
process.stdout.write(raw ? output : `${output}\n`);
|
|
26
38
|
return akumaExitCode(result);
|
|
27
39
|
}
|
|
28
40
|
function renderHelp(coordinate) {
|
|
@@ -34,6 +46,18 @@ function renderHelp(coordinate) {
|
|
|
34
46
|
case "akuma": return renderAkumaHelp(coordinate.action);
|
|
35
47
|
}
|
|
36
48
|
}
|
|
49
|
+
function writeGuidance(command, result) {
|
|
50
|
+
if (command.output === "json")
|
|
51
|
+
process.stdout.write(`${JSON.stringify({ contract: result.contract, guidance: result.guidance })}\n`);
|
|
52
|
+
else
|
|
53
|
+
process.stdout.write(result.guidance.endsWith("\n") ? result.guidance : `${result.guidance}\n`);
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
function writeCatalog(command, result) {
|
|
57
|
+
process.stdout.write(`${command.output === "json" ? JSON.stringify(result.catalog) : renderCatalogText(result.catalog)}\n`);
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
// eslint-disable-next-line complexity -- output dispatch is the single CLI presentation boundary.
|
|
37
61
|
function writeResult(command, result) {
|
|
38
62
|
if (command.command === "install") {
|
|
39
63
|
const value = result;
|
|
@@ -52,6 +76,15 @@ function writeResult(command, result) {
|
|
|
52
76
|
return writeAkuma(command, result);
|
|
53
77
|
}
|
|
54
78
|
const contractResult = result;
|
|
79
|
+
if (contractResult.kind === "guidance")
|
|
80
|
+
return writeGuidance(command, contractResult);
|
|
81
|
+
if (contractResult.kind === "catalog")
|
|
82
|
+
return writeCatalog(command, contractResult);
|
|
83
|
+
if (contractResult.kind === "region") {
|
|
84
|
+
const output = command.output === "json" ? JSON.stringify(contractResult.region) : renderText(contractResult);
|
|
85
|
+
process.stdout.write(`${output}\n`);
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
55
88
|
const output = command.output === "json"
|
|
56
89
|
? JSON.stringify(contractResult.kind === "status" ? contractResult.report : contractResult)
|
|
57
90
|
: renderText(contractResult, {
|
|
@@ -61,19 +94,33 @@ function writeResult(command, result) {
|
|
|
61
94
|
process.stdout.write(`${output}\n`);
|
|
62
95
|
return contractResult.kind === "refused" ? 1 : contractResult.kind === "retry" ? 2 : 0;
|
|
63
96
|
}
|
|
97
|
+
function writeWorldScopeRefusal(error, output) {
|
|
98
|
+
const body = output === "json"
|
|
99
|
+
? JSON.stringify(error.refusal)
|
|
100
|
+
: `${error.refusal.kind} ${error.refusal.world} ${error.refusal.ids.join(" ")}`;
|
|
101
|
+
process.stderr.write(`${body}\n`);
|
|
102
|
+
return 1;
|
|
103
|
+
}
|
|
64
104
|
export async function main(argv = process.argv.slice(2)) {
|
|
105
|
+
let output = "text";
|
|
65
106
|
try {
|
|
66
107
|
const parsed = parseArgv(argv);
|
|
67
108
|
if ("help" in parsed) {
|
|
68
109
|
process.stdout.write(`${renderHelp(parsed.help)}\n`);
|
|
69
110
|
return 0;
|
|
70
111
|
}
|
|
112
|
+
output = parsed.command.output;
|
|
71
113
|
const { invoke } = await import("./invoke.js");
|
|
72
114
|
const result = await invoke(parsed, { cwd: process.cwd() });
|
|
73
115
|
return writeResult(parsed.command, result);
|
|
74
116
|
}
|
|
75
117
|
catch (error) {
|
|
76
|
-
|
|
77
|
-
|
|
118
|
+
if (error instanceof AkumaWorldScopeError)
|
|
119
|
+
return writeWorldScopeRefusal(error, output);
|
|
120
|
+
const original = error instanceof BindDraftError ? error.original : error;
|
|
121
|
+
process.stderr.write(`${original instanceof Error ? original.message : String(original)}\n`);
|
|
122
|
+
if (error instanceof BindDraftError)
|
|
123
|
+
process.stderr.write(`${renderBindDraftReceipt(error.draft)}\n`);
|
|
124
|
+
return original instanceof CliUsageError ? 1 : 3;
|
|
78
125
|
}
|
|
79
126
|
}
|