@astrosheep/keiyaku 4.0.1 → 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 +137 -5
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -35
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +98 -58
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +152 -53
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +23 -14
- package/build/src/akuma/akuma.js +120 -104
- package/build/src/akuma/archetype.d.ts +7 -6
- package/build/src/akuma/archetype.js +68 -41
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +408 -213
- package/build/src/akuma/heart/facts.d.ts +25 -34
- package/build/src/akuma/heart/facts.js +18 -7
- package/build/src/akuma/heart/index.d.ts +39 -42
- package/build/src/akuma/heart/index.js +134 -93
- package/build/src/akuma/heart/rows.d.ts +9 -31
- package/build/src/akuma/heart/rows.js +26 -44
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +7 -15
- 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 +28 -14
- package/build/src/akuma/heart/storage.js +86 -26
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +6 -1
- package/build/src/akuma/index.js +6 -0
- package/build/src/akuma/projection.d.ts +117 -38
- package/build/src/akuma/projection.js +208 -97
- 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 +12 -4
- package/build/src/akuma/provider.js +117 -70
- 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/events.js +66 -13
- package/build/src/akuma/providers/claude/index.d.ts +2 -1
- package/build/src/akuma/providers/claude/index.js +35 -21
- package/build/src/akuma/providers/codex-app-server/events.js +4 -1
- package/build/src/akuma/providers/codex-app-server/index.d.ts +3 -3
- package/build/src/akuma/providers/codex-app-server/index.js +24 -31
- 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 +24 -59
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +40 -34
- package/build/src/akuma/providers/opencode-sdk/events.js +220 -101
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +3 -2
- package/build/src/akuma/providers/opencode-sdk/index.js +233 -128
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +11 -26
- package/build/src/akuma/providers/opencode-sdk/session.js +10 -9
- package/build/src/akuma/providers/pi/events.js +49 -11
- package/build/src/akuma/providers/pi/index.d.ts +1 -1
- package/build/src/akuma/providers/pi/index.js +50 -21
- 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 -7
- package/build/src/akuma/requests.js +92 -65
- package/build/src/alias/index.d.ts +2 -2
- package/build/src/alias/index.js +10 -10
- 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/cli/accepted.d.ts +17 -13
- package/build/src/cli/accepted.js +72 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +4 -3
- package/build/src/cli/commands/akuma-invoke.js +14 -9
- package/build/src/cli/commands/akuma.d.ts +13 -3
- package/build/src/cli/commands/akuma.js +67 -34
- package/build/src/cli/commands/contract.d.ts +18 -5
- package/build/src/cli/commands/contract.js +9 -3
- package/build/src/cli/commands/task-invoke.d.ts +17 -4
- package/build/src/cli/commands/task-invoke.js +43 -20
- 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 +51 -13
- 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 +4 -3
- package/build/src/cli/invoke.js +160 -179
- package/build/src/cli/main.js +34 -6
- package/build/src/cli/parse.d.ts +9 -2
- package/build/src/cli/parse.js +29 -7
- 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 +2 -2
- package/build/src/cli/render/akuma-tool.js +30 -4
- package/build/src/cli/render/akuma.d.ts +1 -0
- package/build/src/cli/render/akuma.js +211 -116
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +192 -79
- package/build/src/cli/render/kanshi.js +263 -168
- 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 -20
- 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 +7 -0
- package/build/src/cli/render/terminal.js +46 -0
- package/build/src/cli/render/text.js +6 -3
- package/build/src/cli/result.d.ts +115 -20
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +6 -5
- package/build/src/contract-worktree.js +95 -57
- package/build/src/coordination/durable-file.d.ts +4 -3
- package/build/src/coordination/durable-file.js +29 -25
- 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/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/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +0 -11
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +1 -7
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +4 -1
- package/build/src/dispatch/index.d.ts +2 -2
- package/build/src/dispatch/index.js +17 -17
- package/build/src/git/admission.d.ts +1 -1
- package/build/src/git/admission.js +11 -11
- package/build/src/git/hooks.js +13 -13
- package/build/src/git/integration.d.ts +14 -15
- package/build/src/git/integration.js +80 -44
- package/build/src/git/observe.d.ts +5 -3
- package/build/src/git/observe.js +18 -12
- package/build/src/git/read-observation.js +9 -9
- package/build/src/git/reconcile.d.ts +2 -0
- package/build/src/git/reconcile.js +138 -95
- package/build/src/git/repository.d.ts +27 -19
- package/build/src/git/repository.js +155 -83
- package/build/src/git/scratch.d.ts +7 -3
- package/build/src/git/scratch.js +44 -37
- package/build/src/git/target-placement.d.ts +40 -4
- package/build/src/git/target-placement.js +221 -101
- package/build/src/git/tender.d.ts +6 -5
- package/build/src/git/tender.js +24 -43
- package/build/src/git/terminal-seal.d.ts +1 -1
- package/build/src/git/terminal-seal.js +7 -5
- package/build/src/git/workspace.d.ts +36 -4
- package/build/src/git/workspace.js +53 -18
- package/build/src/identity/selector.js +1 -1
- package/build/src/index.d.ts +3 -3
- package/build/src/index.js +1 -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 +2 -1
- package/build/src/kanshi/read.js +118 -27
- package/build/src/kanshi/report.d.ts +50 -0
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +32 -0
- package/build/src/library/address.d.ts +12 -3
- package/build/src/library/address.js +77 -46
- package/build/src/library/akuma-creation.d.ts +6 -1
- package/build/src/library/akuma-creation.js +86 -13
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.js +4 -4
- package/build/src/library/catalog.d.ts +1 -1
- package/build/src/library/catalog.js +5 -8
- package/build/src/library/contract.d.ts +5 -6
- package/build/src/library/contract.js +11 -35
- package/build/src/library/delivery.d.ts +2 -1
- package/build/src/library/fleet.d.ts +2 -2
- package/build/src/library/fleet.js +35 -71
- package/build/src/library/keiyaku.d.ts +3 -2
- package/build/src/library/keiyaku.js +1 -0
- package/build/src/library/mutation.d.ts +7 -6
- package/build/src/library/mutation.js +23 -25
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/region.d.ts +12 -0
- package/build/src/library/region.js +15 -1
- package/build/src/library/repo.d.ts +4 -16
- package/build/src/library/repo.js +13 -38
- package/build/src/protocol/attempt.js +6 -6
- package/build/src/protocol/bind.js +4 -4
- package/build/src/protocol/intent.d.ts +15 -2
- package/build/src/protocol/intent.js +21 -6
- package/build/src/protocol/operations.d.ts +73 -22
- package/build/src/protocol/operations.js +292 -88
- package/build/src/protocol/outcome.d.ts +9 -3
- package/build/src/protocol/outcome.js +3 -1
- package/build/src/protocol/placement.d.ts +15 -4
- package/build/src/protocol/placement.js +58 -25
- package/build/src/protocol/read/status.d.ts +8 -1
- package/build/src/protocol/read/status.js +61 -14
- package/build/src/runtime/proc/line-rpc.d.ts +3 -8
- package/build/src/runtime/proc/line-rpc.js +16 -43
- package/build/src/runtime/proc/run.d.ts +15 -29
- package/build/src/runtime/proc/run.js +113 -105
- 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 +2 -2
- package/build/src/settings.js +8 -8
- package/build/src/settlement/fence.d.ts +0 -4
- package/build/src/settlement/fence.js +0 -9
- package/build/src/settlement/holder.d.ts +11 -1
- package/build/src/settlement/holder.js +25 -0
- package/build/src/settlement/settle.d.ts +1 -1
- package/build/src/settlement/settle.js +52 -89
- package/build/src/task/board.d.ts +3 -3
- package/build/src/task/board.js +6 -9
- package/build/src/task/compose.d.ts +1 -1
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +14 -14
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +19 -7
- package/build/src/task/index.js +42 -23
- package/build/src/task/operations.d.ts +15 -9
- package/build/src/task/operations.js +78 -48
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +2 -2
- package/build/src/task/store.js +40 -25
- package/build/src/verification/execution.d.ts +4 -2
- package/build/src/verification/execution.js +9 -5
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +13 -2
- package/build/src/world.js +81 -48
- package/package.json +3 -2
- package/build/src/protocol/read/audit.d.ts +0 -31
- package/build/src/protocol/read/audit.js +0 -55
package/build/src/cli/main.js
CHANGED
|
@@ -1,13 +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";
|
|
9
10
|
import { renderCatalogText } from "./render/catalog.js";
|
|
11
|
+
import { BindDraftError } from "./draft.js";
|
|
12
|
+
import { renderBindDraftReceipt } from "./render/refusal.js";
|
|
10
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
|
+
};
|
|
11
18
|
if (command.output === "json")
|
|
12
19
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
13
20
|
else if (command.action === "compose" && typeof result === "object" && result !== null && "kind" in result && result.kind === "incomplete") {
|
|
@@ -17,7 +24,7 @@ function writeTask(command, result) {
|
|
|
17
24
|
process.stdout.write(result.draft);
|
|
18
25
|
}
|
|
19
26
|
else
|
|
20
|
-
process.stdout.write(`${renderTaskText(command, result)}\n`);
|
|
27
|
+
process.stdout.write(`${renderTaskText(command, result, context)}\n`);
|
|
21
28
|
return taskExitCode(result);
|
|
22
29
|
}
|
|
23
30
|
function writeAkuma(command, result) {
|
|
@@ -25,8 +32,9 @@ function writeAkuma(command, result) {
|
|
|
25
32
|
columns: process.stdout.isTTY === true && Number.isInteger(process.stdout.columns) ? process.stdout.columns : 80,
|
|
26
33
|
color: process.stdout.isTTY === true && process.env.NO_COLOR === undefined,
|
|
27
34
|
});
|
|
28
|
-
const
|
|
29
|
-
|
|
35
|
+
const raw = command.output === "text"
|
|
36
|
+
&& ((command.command === "history" && command.last) || akumaRawAnswer(result) !== undefined);
|
|
37
|
+
process.stdout.write(raw ? output : `${output}\n`);
|
|
30
38
|
return akumaExitCode(result);
|
|
31
39
|
}
|
|
32
40
|
function renderHelp(coordinate) {
|
|
@@ -49,6 +57,7 @@ function writeCatalog(command, result) {
|
|
|
49
57
|
process.stdout.write(`${command.output === "json" ? JSON.stringify(result.catalog) : renderCatalogText(result.catalog)}\n`);
|
|
50
58
|
return 0;
|
|
51
59
|
}
|
|
60
|
+
// eslint-disable-next-line complexity -- output dispatch is the single CLI presentation boundary.
|
|
52
61
|
function writeResult(command, result) {
|
|
53
62
|
if (command.command === "install") {
|
|
54
63
|
const value = result;
|
|
@@ -71,6 +80,11 @@ function writeResult(command, result) {
|
|
|
71
80
|
return writeGuidance(command, contractResult);
|
|
72
81
|
if (contractResult.kind === "catalog")
|
|
73
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
|
+
}
|
|
74
88
|
const output = command.output === "json"
|
|
75
89
|
? JSON.stringify(contractResult.kind === "status" ? contractResult.report : contractResult)
|
|
76
90
|
: renderText(contractResult, {
|
|
@@ -80,19 +94,33 @@ function writeResult(command, result) {
|
|
|
80
94
|
process.stdout.write(`${output}\n`);
|
|
81
95
|
return contractResult.kind === "refused" ? 1 : contractResult.kind === "retry" ? 2 : 0;
|
|
82
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
|
+
}
|
|
83
104
|
export async function main(argv = process.argv.slice(2)) {
|
|
105
|
+
let output = "text";
|
|
84
106
|
try {
|
|
85
107
|
const parsed = parseArgv(argv);
|
|
86
108
|
if ("help" in parsed) {
|
|
87
109
|
process.stdout.write(`${renderHelp(parsed.help)}\n`);
|
|
88
110
|
return 0;
|
|
89
111
|
}
|
|
112
|
+
output = parsed.command.output;
|
|
90
113
|
const { invoke } = await import("./invoke.js");
|
|
91
114
|
const result = await invoke(parsed, { cwd: process.cwd() });
|
|
92
115
|
return writeResult(parsed.command, result);
|
|
93
116
|
}
|
|
94
117
|
catch (error) {
|
|
95
|
-
|
|
96
|
-
|
|
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;
|
|
97
125
|
}
|
|
98
126
|
}
|
package/build/src/cli/parse.d.ts
CHANGED
|
@@ -67,7 +67,8 @@ export type ParsedLs = Output & Readonly<{
|
|
|
67
67
|
export type ParsedAudit = Output & Readonly<{
|
|
68
68
|
command: "audit";
|
|
69
69
|
contract?: string;
|
|
70
|
-
|
|
70
|
+
includeDirty: boolean;
|
|
71
|
+
showDiff: boolean;
|
|
71
72
|
actor?: string;
|
|
72
73
|
}>;
|
|
73
74
|
type ParsedReconcile = Output & Readonly<{
|
|
@@ -78,10 +79,16 @@ type ParsedReconcile = Output & Readonly<{
|
|
|
78
79
|
export type ParsedSettings = Output & Readonly<{
|
|
79
80
|
command: "settings";
|
|
80
81
|
}>;
|
|
82
|
+
export type ParsedRegion = Output & Readonly<{
|
|
83
|
+
command: "region";
|
|
84
|
+
contract?: string;
|
|
85
|
+
overlap: boolean;
|
|
86
|
+
path?: string;
|
|
87
|
+
}>;
|
|
81
88
|
export type ParsedCommand = ParsedBind | ParsedAmend | ParsedDeliver | ParsedReview | ParsedArc | ParsedAbandon | ParsedStatus | (Output & Readonly<{
|
|
82
89
|
command: "show";
|
|
83
90
|
contract?: string;
|
|
84
|
-
}>) | ParsedLs | ParsedAudit | ParsedReconcile | ParsedSettings | ParsedInstallCommand | ParsedAkumaCommand | ParsedTaskCommand;
|
|
91
|
+
}>) | ParsedLs | ParsedAudit | ParsedReconcile | ParsedSettings | ParsedRegion | ParsedInstallCommand | ParsedAkumaCommand | ParsedTaskCommand;
|
|
85
92
|
export type CliHelpCoordinate = Readonly<{
|
|
86
93
|
kind: "root";
|
|
87
94
|
}> | Readonly<{
|
package/build/src/cli/parse.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isTaskAction, parseTaskCommand, renderTaskUsage, } from "./commands/task.js";
|
|
2
2
|
import { isAkumaAction, parseAkumaCatalogPath, parseAkumaCommand, renderAkumaRootRows, renderAkumaUsage, } from "./commands/akuma.js";
|
|
3
3
|
import { INSTALL_USAGE, parseInstallCommand, renderInstallHelp } from "./commands/install.js";
|
|
4
|
-
import { CONTRACT_COMMAND_SPECS } from "./commands/contract.js";
|
|
5
|
-
import { CliUsageError, usageLine } from "./usage.js";
|
|
4
|
+
import { AMEND_MINIMAL_STDIN_HELP, CONTRACT_COMMAND_SPECS } from "./commands/contract.js";
|
|
5
|
+
import { CliUsageError, isBlankInput, usageLine } from "./usage.js";
|
|
6
6
|
export { CliUsageError } from "./usage.js";
|
|
7
7
|
const ROOT_USAGE = "usage: keiyaku [-C <path>] [--repo <path>] <command> [<contract>|@<contract>] [--flag ...] [-]";
|
|
8
8
|
export function renderRootHelp() {
|
|
@@ -24,7 +24,8 @@ export function renderRootHelp() {
|
|
|
24
24
|
}
|
|
25
25
|
export function renderContractHelp(command) {
|
|
26
26
|
const spec = CONTRACT_COMMAND_SPECS[command];
|
|
27
|
-
|
|
27
|
+
const help = `${spec.purpose}\n\n${usageLine(spec.usage)}`;
|
|
28
|
+
return command === "amend" ? `${help}\n\n${AMEND_MINIMAL_STDIN_HELP}` : help;
|
|
28
29
|
}
|
|
29
30
|
function contractUsage(command) {
|
|
30
31
|
return usageLine(CONTRACT_COMMAND_SPECS[command].usage);
|
|
@@ -70,6 +71,8 @@ function scanOption(command, argv, state, index) {
|
|
|
70
71
|
const value = argv[index + 1];
|
|
71
72
|
if (value === undefined || value === "-" || value.startsWith("--"))
|
|
72
73
|
refuse(command, `${token} requires a value`);
|
|
74
|
+
if (isBlankInput(value))
|
|
75
|
+
refuse(command, `${token} requires a nonblank value`);
|
|
73
76
|
if (kind === "repeat-value") {
|
|
74
77
|
const values = state.flags[name];
|
|
75
78
|
state.flags[name] = [...(Array.isArray(values) ? values : values === undefined ? [] : [values]), value];
|
|
@@ -97,6 +100,8 @@ function scanArgv(argv) {
|
|
|
97
100
|
index = scanOption(command, argv, state, index);
|
|
98
101
|
continue;
|
|
99
102
|
}
|
|
103
|
+
if (isBlankInput(token))
|
|
104
|
+
refuse(command, `${command} requires a nonblank value`);
|
|
100
105
|
state.positionals.push(token);
|
|
101
106
|
}
|
|
102
107
|
if (spec.positional === "none" && state.positionals.length > 0) {
|
|
@@ -161,8 +166,9 @@ function parseReview(parts) {
|
|
|
161
166
|
refuse("review", "review requires exactly one verdict flag");
|
|
162
167
|
}
|
|
163
168
|
const summary = optionalFlag(parts.flags, "summary");
|
|
164
|
-
if (parts.stdin
|
|
165
|
-
refuse("review", "review
|
|
169
|
+
if (parts.stdin === (summary !== undefined)) {
|
|
170
|
+
refuse("review", "review requires exactly one of --summary <text> or stdin '-'");
|
|
171
|
+
}
|
|
166
172
|
const contract = parts.positionals[0];
|
|
167
173
|
return {
|
|
168
174
|
command: "review",
|
|
@@ -214,6 +220,20 @@ function parseShow(parts) {
|
|
|
214
220
|
const contract = parts.positionals[0];
|
|
215
221
|
return { command: "show", ...(contract === undefined ? {} : { contract }), output: parts.output };
|
|
216
222
|
}
|
|
223
|
+
function parseRegion(parts) {
|
|
224
|
+
const contract = parts.positionals[0];
|
|
225
|
+
const path = optionalFlag(parts.flags, "path");
|
|
226
|
+
const overlap = parts.flags.overlap === true;
|
|
227
|
+
if (path !== undefined && (contract !== undefined || overlap))
|
|
228
|
+
refuse("region", "--path cannot combine with a contract or --overlap");
|
|
229
|
+
return {
|
|
230
|
+
command: "region",
|
|
231
|
+
...(contract === undefined ? {} : { contract }),
|
|
232
|
+
...(path === undefined ? {} : { path }),
|
|
233
|
+
overlap,
|
|
234
|
+
output: parts.output,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
217
237
|
function parseLs(parts) {
|
|
218
238
|
const path = parts.positionals[0];
|
|
219
239
|
if (path === "task/")
|
|
@@ -254,7 +274,7 @@ function invocationOptions(argv) {
|
|
|
254
274
|
throw new CliUsageError("-C/--cwd may appear only once", renderRootHelp());
|
|
255
275
|
}
|
|
256
276
|
const value = argv[index + 1];
|
|
257
|
-
if (value === undefined || value === "-" || value.startsWith("-")) {
|
|
277
|
+
if (value === undefined || value === "-" || value.startsWith("-") || isBlankInput(value)) {
|
|
258
278
|
throw new CliUsageError(`${token} requires a path`, renderRootHelp());
|
|
259
279
|
}
|
|
260
280
|
if (token === "--repo")
|
|
@@ -304,7 +324,8 @@ function parseCommand(parts) {
|
|
|
304
324
|
return {
|
|
305
325
|
command: "audit",
|
|
306
326
|
...(contract === undefined ? {} : { contract }),
|
|
307
|
-
|
|
327
|
+
includeDirty: parts.flags["include-dirty"] === true,
|
|
328
|
+
showDiff: parts.flags.diff === true,
|
|
308
329
|
...(parts.actor === undefined ? {} : { actor: parts.actor }),
|
|
309
330
|
output: parts.output,
|
|
310
331
|
};
|
|
@@ -319,6 +340,7 @@ function parseCommand(parts) {
|
|
|
319
340
|
};
|
|
320
341
|
}
|
|
321
342
|
case "settings": return { command: "settings", output: parts.output };
|
|
343
|
+
case "region": return parseRegion(parts);
|
|
322
344
|
}
|
|
323
345
|
}
|
|
324
346
|
export function parseArgv(argv) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unwrap only complete provider transport launchers. This is deliberately not
|
|
3
|
+
* a shell parser: uncertainty preserves the persisted command's presentation.
|
|
4
|
+
*/
|
|
5
|
+
/** Return a display subject only when the full transport shape is unambiguous. */
|
|
6
|
+
export declare function normalizeToolCommand(command: string): string;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unwrap only complete provider transport launchers. This is deliberately not
|
|
3
|
+
* a shell parser: uncertainty preserves the persisted command's presentation.
|
|
4
|
+
*/
|
|
5
|
+
const HORIZONTAL_WHITESPACE = new Set([" ", "\t"]);
|
|
6
|
+
const UNSUPPORTED_UNQUOTED = new Set(["$", "`", "|", "&", ";", "<", ">", "(", ")"]);
|
|
7
|
+
const DOUBLE_QUOTE_ESCAPES = new Set(["\"", "\\", "$", "`"]);
|
|
8
|
+
const POWERSHELL_OPTION_FLAGS = new Set(["-nologo", "-noprofile"]);
|
|
9
|
+
const POWERSHELL_COMMAND_FLAGS = new Set(["-command", "-c"]);
|
|
10
|
+
const SCAN_FAIL = { ok: false };
|
|
11
|
+
function scanned(index, value) {
|
|
12
|
+
return { ok: true, index, value };
|
|
13
|
+
}
|
|
14
|
+
function isLineBoundary(character) {
|
|
15
|
+
return character === "\n" || character === "\r";
|
|
16
|
+
}
|
|
17
|
+
function isAbsoluteExecutable(value) {
|
|
18
|
+
return value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value);
|
|
19
|
+
}
|
|
20
|
+
function executableName(value) {
|
|
21
|
+
const segments = value.split(/[\\/]/u);
|
|
22
|
+
return segments[segments.length - 1].toLowerCase();
|
|
23
|
+
}
|
|
24
|
+
function isBashOrZsh(value) {
|
|
25
|
+
const name = executableName(value);
|
|
26
|
+
return (value === "bash" || value === "zsh" || isAbsoluteExecutable(value))
|
|
27
|
+
&& (name === "bash" || name === "zsh");
|
|
28
|
+
}
|
|
29
|
+
function isPowerShell(value) {
|
|
30
|
+
const name = executableName(value);
|
|
31
|
+
return (value.toLowerCase() === "powershell" || value.toLowerCase() === "pwsh" || isAbsoluteExecutable(value))
|
|
32
|
+
&& (name === "powershell" || name === "powershell.exe" || name === "pwsh" || name === "pwsh.exe");
|
|
33
|
+
}
|
|
34
|
+
function scanSingleQuoted(command, index) {
|
|
35
|
+
const end = command.indexOf("'", index + 1);
|
|
36
|
+
return end < 0 ? SCAN_FAIL : scanned(end + 1, command.slice(index + 1, end));
|
|
37
|
+
}
|
|
38
|
+
function scanDoubleQuotedEscape(command, index) {
|
|
39
|
+
const next = command[index + 1];
|
|
40
|
+
if (next === undefined || isLineBoundary(next))
|
|
41
|
+
return SCAN_FAIL;
|
|
42
|
+
return scanned(index + 2, DOUBLE_QUOTE_ESCAPES.has(next) ? next : `\\${next}`);
|
|
43
|
+
}
|
|
44
|
+
function scanDoubleQuoted(command, index) {
|
|
45
|
+
let cursor = index + 1;
|
|
46
|
+
let value = "";
|
|
47
|
+
while (cursor < command.length) {
|
|
48
|
+
const quoted = command[cursor];
|
|
49
|
+
if (quoted === "\"")
|
|
50
|
+
return scanned(cursor + 1, value);
|
|
51
|
+
if (quoted === "$" || quoted === "`")
|
|
52
|
+
return SCAN_FAIL;
|
|
53
|
+
if (quoted === "\\") {
|
|
54
|
+
const escaped = scanDoubleQuotedEscape(command, cursor);
|
|
55
|
+
if (!escaped.ok)
|
|
56
|
+
return SCAN_FAIL;
|
|
57
|
+
value += escaped.value;
|
|
58
|
+
cursor = escaped.index;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
value += quoted;
|
|
62
|
+
cursor += 1;
|
|
63
|
+
}
|
|
64
|
+
return SCAN_FAIL;
|
|
65
|
+
}
|
|
66
|
+
function scanUnquotedEscape(command, index) {
|
|
67
|
+
const next = command[index + 1];
|
|
68
|
+
if (next === undefined || isLineBoundary(next))
|
|
69
|
+
return SCAN_FAIL;
|
|
70
|
+
return scanned(index + 2, next);
|
|
71
|
+
}
|
|
72
|
+
function scanTokenSegment(command, index) {
|
|
73
|
+
const character = command[index];
|
|
74
|
+
if (isLineBoundary(character) || UNSUPPORTED_UNQUOTED.has(character))
|
|
75
|
+
return SCAN_FAIL;
|
|
76
|
+
if (character === "'")
|
|
77
|
+
return scanSingleQuoted(command, index);
|
|
78
|
+
if (character === "\"")
|
|
79
|
+
return scanDoubleQuoted(command, index);
|
|
80
|
+
if (character === "\\")
|
|
81
|
+
return scanUnquotedEscape(command, index);
|
|
82
|
+
return scanned(index + 1, character);
|
|
83
|
+
}
|
|
84
|
+
function scanToken(command, index) {
|
|
85
|
+
let cursor = index;
|
|
86
|
+
let value = "";
|
|
87
|
+
let consumed = false;
|
|
88
|
+
while (cursor < command.length && !HORIZONTAL_WHITESPACE.has(command[cursor])) {
|
|
89
|
+
const segment = scanTokenSegment(command, cursor);
|
|
90
|
+
if (!segment.ok)
|
|
91
|
+
return SCAN_FAIL;
|
|
92
|
+
value += segment.value;
|
|
93
|
+
cursor = segment.index;
|
|
94
|
+
consumed = true;
|
|
95
|
+
}
|
|
96
|
+
return consumed ? scanned(cursor, value) : SCAN_FAIL;
|
|
97
|
+
}
|
|
98
|
+
function parseTransportArgv(command) {
|
|
99
|
+
const argv = [];
|
|
100
|
+
let index = 0;
|
|
101
|
+
while (index < command.length) {
|
|
102
|
+
while (HORIZONTAL_WHITESPACE.has(command[index]))
|
|
103
|
+
index += 1;
|
|
104
|
+
if (index === command.length)
|
|
105
|
+
break;
|
|
106
|
+
if (isLineBoundary(command[index]))
|
|
107
|
+
return undefined;
|
|
108
|
+
const token = scanToken(command, index);
|
|
109
|
+
if (!token.ok)
|
|
110
|
+
return undefined;
|
|
111
|
+
argv.push(token.value);
|
|
112
|
+
index = token.index;
|
|
113
|
+
}
|
|
114
|
+
return argv;
|
|
115
|
+
}
|
|
116
|
+
function unwrapBashOrZsh(argv) {
|
|
117
|
+
const [shell, flag, script] = argv;
|
|
118
|
+
if (argv.length !== 3 || !shell || !script || !isBashOrZsh(shell))
|
|
119
|
+
return undefined;
|
|
120
|
+
return flag === "-c" || flag === "-lc" ? script : undefined;
|
|
121
|
+
}
|
|
122
|
+
function unwrapPowerShell(argv) {
|
|
123
|
+
const [shell, ...arguments_] = argv;
|
|
124
|
+
if (!shell || !isPowerShell(shell) || arguments_.length < 2)
|
|
125
|
+
return undefined;
|
|
126
|
+
const options = new Set();
|
|
127
|
+
for (let index = 0; index < arguments_.length - 1; index += 1) {
|
|
128
|
+
const flag = arguments_[index].toLowerCase();
|
|
129
|
+
if (POWERSHELL_COMMAND_FLAGS.has(flag)) {
|
|
130
|
+
return index === arguments_.length - 2 && arguments_[index + 1] ? arguments_[index + 1] : undefined;
|
|
131
|
+
}
|
|
132
|
+
if (!POWERSHELL_OPTION_FLAGS.has(flag) || options.has(flag))
|
|
133
|
+
return undefined;
|
|
134
|
+
options.add(flag);
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
/** Return a display subject only when the full transport shape is unambiguous. */
|
|
139
|
+
export function normalizeToolCommand(command) {
|
|
140
|
+
const argv = parseTransportArgv(command);
|
|
141
|
+
if (!argv)
|
|
142
|
+
return command;
|
|
143
|
+
return unwrapBashOrZsh(argv) ?? unwrapPowerShell(argv) ?? command;
|
|
144
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ActivityRow } from "../../akuma/index.js";
|
|
2
|
-
type ToolRow = Extract<ActivityRow, {
|
|
1
|
+
import type { ActivityRow, SnapshotRow } from "../../akuma/index.js";
|
|
2
|
+
type ToolRow = Extract<ActivityRow | SnapshotRow, {
|
|
3
3
|
kind: "tool";
|
|
4
4
|
}>;
|
|
5
5
|
export type ToolRepr = Readonly<{
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeToolCommand } from "./akuma-tool-command.js";
|
|
1
2
|
function oneLine(value) {
|
|
2
3
|
return value.replace(/\s+/gu, " ").trim();
|
|
3
4
|
}
|
|
@@ -12,7 +13,7 @@ function duration(milliseconds) {
|
|
|
12
13
|
return remainder === 0 ? `${minutes}m` : `${minutes}m ${remainder}s`;
|
|
13
14
|
}
|
|
14
15
|
function result(row) {
|
|
15
|
-
if (row.state === "
|
|
16
|
+
if (row.state === "active" || row.state === "unsettled")
|
|
16
17
|
return undefined;
|
|
17
18
|
const disposition = row.state.exitCode !== undefined
|
|
18
19
|
? row.state.exitCode === 0 ? "ok" : `exit ${row.state.exitCode}`
|
|
@@ -24,6 +25,31 @@ function result(row) {
|
|
|
24
25
|
];
|
|
25
26
|
return parts.length === 0 ? undefined : parts.join(" · ");
|
|
26
27
|
}
|
|
28
|
+
function readText(call) {
|
|
29
|
+
const path = oneLine(call.path);
|
|
30
|
+
if (call.offset !== undefined && call.limit !== undefined) {
|
|
31
|
+
return `${path} · L${call.offset}-${call.offset + call.limit - 1}`;
|
|
32
|
+
}
|
|
33
|
+
if (call.offset !== undefined)
|
|
34
|
+
return `${path} · from L${call.offset}`;
|
|
35
|
+
if (call.limit !== undefined)
|
|
36
|
+
return `${path} · ${call.limit} lines`;
|
|
37
|
+
return path;
|
|
38
|
+
}
|
|
39
|
+
function searchLabel(scope) {
|
|
40
|
+
if (scope === "files")
|
|
41
|
+
return "find";
|
|
42
|
+
if (scope === "web")
|
|
43
|
+
return "web";
|
|
44
|
+
return "search";
|
|
45
|
+
}
|
|
46
|
+
function searchText(call) {
|
|
47
|
+
return [
|
|
48
|
+
oneLine(call.query),
|
|
49
|
+
...(call.path === undefined ? [] : [oneLine(call.path)]),
|
|
50
|
+
...(call.glob === undefined ? [] : [oneLine(call.glob)]),
|
|
51
|
+
].join(" · ");
|
|
52
|
+
}
|
|
27
53
|
function fileChange(call) {
|
|
28
54
|
const first = call.changes[0];
|
|
29
55
|
if (first === undefined)
|
|
@@ -48,13 +74,13 @@ export function toolRepr(row) {
|
|
|
48
74
|
let core;
|
|
49
75
|
switch (row.call.kind) {
|
|
50
76
|
case "run":
|
|
51
|
-
core = { label: "run", text: `$ ${oneLine(row.call.command)}`, overflow: "middle-ellipsis" };
|
|
77
|
+
core = { label: "run", text: `$ ${oneLine(normalizeToolCommand(row.call.command))}`, overflow: "middle-ellipsis" };
|
|
52
78
|
break;
|
|
53
79
|
case "read":
|
|
54
|
-
core = { label: "read", text:
|
|
80
|
+
core = { label: "read", text: readText(row.call) };
|
|
55
81
|
break;
|
|
56
82
|
case "search":
|
|
57
|
-
core = { label:
|
|
83
|
+
core = { label: searchLabel(row.call.scope), text: searchText(row.call) };
|
|
58
84
|
break;
|
|
59
85
|
case "fileChange":
|
|
60
86
|
core = fileChange(row.call);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AkumaInvocationResult } from "../commands/akuma-invoke.js";
|
|
2
2
|
import type { ParsedCommand } from "../parse.js";
|
|
3
3
|
import { type TextRenderContext } from "./terminal.js";
|
|
4
|
+
export declare function akumaRawAnswer(result: AkumaInvocationResult): string | undefined;
|
|
4
5
|
export declare function renderAkumaText(command: ParsedCommand, result: AkumaInvocationResult, context?: TextRenderContext): string;
|
|
5
6
|
export declare function akumaExitCode(result: AkumaInvocationResult): number;
|
|
6
7
|
export declare function akumaJsonValue(command: ParsedCommand, result: AkumaInvocationResult): unknown;
|