@astrosheep/keiyaku 1.0.0 → 1.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 +73 -56
- package/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms_v2.js +103 -0
- package/build/agents/harness/activity-values.js +54 -0
- package/build/agents/harness/event-channel.js +55 -20
- package/build/agents/harness/events.js +47 -1
- package/build/agents/harness/execution-handle.js +292 -61
- package/build/agents/harness/index.js +103 -121
- package/build/agents/harness/pump.js +36 -47
- package/build/agents/harness/runtime.js +3 -0
- package/build/agents/launch-snapshot_v2.js +348 -0
- package/build/agents/opencode-sdk.js +42 -169
- package/build/agents/providers/claude-agent-sdk.js +240 -79
- package/build/agents/providers/codex-app-server.js +280 -72
- package/build/agents/providers/codex-sdk.js +159 -41
- package/build/agents/providers/event-type-tail.js +16 -0
- package/build/agents/providers/opencode-sdk.js +165 -59
- package/build/agents/providers/pi.js +254 -42
- package/build/agents/selector_v2.js +122 -0
- package/build/cli/commands/akuma.js +120 -42
- package/build/cli/completion.js +6 -7
- package/build/cli/flags.js +36 -10
- package/build/cli/help.js +42 -26
- package/build/cli/index.js +225 -93
- package/build/cli/parse.js +194 -75
- package/build/cli/projection-address.js +11 -0
- package/build/cli/render/address.js +88 -0
- package/build/cli/render/arc.js +10 -10
- package/build/cli/render/call.js +59 -0
- package/build/cli/render/compact-text.js +3 -0
- package/build/cli/render/errors.js +4 -2
- package/build/cli/render/format.js +6 -0
- package/build/cli/render/line-width.js +70 -0
- package/build/cli/render/misc.js +7 -4
- package/build/cli/render/petition.js +4 -3
- package/build/cli/render/projection-activity.js +201 -0
- package/build/cli/render/shared.js +46 -12
- package/build/cli/render/status.js +59 -10
- package/build/cli/render/tool-ledger-rollup.js +74 -0
- package/build/cli/render/tool-presentation.js +97 -0
- package/build/cli/render/wait.js +229 -0
- package/build/cli/skills-install.js +42 -24
- package/build/cli/subagent-guard.js +1 -1
- package/build/config/akuma-loader_v2.js +222 -0
- package/build/config/env-keys.js +0 -4
- package/build/config/env.js +0 -6
- package/build/config/settings.js +325 -12
- package/build/core/addressing.js +224 -0
- package/build/core/amend.js +30 -47
- package/build/core/arc.js +68 -60
- package/build/core/bind.js +105 -25
- package/build/core/call-persist.js +69 -0
- package/build/core/call.js +658 -0
- package/build/core/claim.js +72 -44
- package/build/core/command-io.js +19 -19
- package/build/core/context.js +11 -36
- package/build/core/draft.js +2 -3
- package/build/core/entry.js +101 -6
- package/build/core/execution-coordinate.js +62 -0
- package/build/core/execution-pact.js +141 -0
- package/build/core/forfeit.js +2 -3
- package/build/core/hints.js +10 -10
- package/build/core/ids.js +6 -0
- package/build/core/ledger.js +16 -1
- package/build/core/petition-claim-gates.js +14 -12
- package/build/core/petition-claim.js +1 -0
- package/build/core/petition-run.js +6 -2
- package/build/core/petition.js +63 -21
- package/build/core/places.js +106 -13
- package/build/core/projection/generation.js +412 -0
- package/build/core/projection/heart.js +316 -0
- package/build/core/projection/identity.js +81 -0
- package/build/core/projection/leash.js +87 -0
- package/build/core/projection/mint.js +154 -0
- package/build/core/projection-activity.js +219 -0
- package/build/core/projection-coordinate.js +35 -0
- package/build/core/projection-core.js +69 -463
- package/build/core/projection-generation-continuation.js +31 -0
- package/build/core/projection-generation-execution.js +148 -0
- package/build/core/projection-generation-identity.js +17 -0
- package/build/core/projection-generation-launcher.js +90 -0
- package/build/core/projection-generation-process.js +43 -0
- package/build/core/projection-generation-runner.js +144 -0
- package/build/core/projection-generation-runtime.js +15 -0
- package/build/core/projection-generation-store.js +707 -0
- package/build/core/projection-identity.js +11 -0
- package/build/core/projection-life-observer.js +87 -0
- package/build/core/projection-life-protocol.js +95 -0
- package/build/core/projection-mint.js +96 -24
- package/build/core/projection-runner-lock.js +230 -0
- package/build/core/projection-status.js +207 -107
- package/build/core/projection-tells.js +401 -0
- package/build/core/projection-wait.js +155 -0
- package/build/core/projection-wake.js +109 -231
- package/build/core/queue_v2.js +342 -0
- package/build/core/registry.js +6 -3
- package/build/core/render.js +63 -1
- package/build/core/renew.js +80 -53
- package/build/core/scope.js +186 -137
- package/build/core/seal.js +16 -19
- package/build/core/status.js +88 -25
- package/build/core/stored-agent-event.js +101 -0
- package/build/core/transcripts.js +214 -228
- package/build/core/verdict.js +27 -15
- package/build/core/worktree-bootstrap.js +187 -0
- package/build/core/worktree-path.js +72 -18
- package/build/flow-error.js +4 -6
- package/build/generated/version.js +1 -1
- package/build/git/branches.js +6 -1
- package/build/index.js +8 -5
- package/build/keiyaku.js +1 -3
- package/package.json +6 -5
- package/skills/keiyaku/SKILL.md +6 -47
- package/skills/keiyaku-akuma/SKILL.md +75 -0
- package/build/agents/effective-policy.js +0 -32
- package/build/agents/index.js +0 -114
- package/build/agents/selector.js +0 -28
- package/build/cli/render/summon.js +0 -17
- package/build/cli/render/tell.js +0 -11
- package/build/config/akuma-loader.js +0 -268
- package/build/core/queue.js +0 -73
- package/build/core/summon-persist.js +0 -73
- package/build/core/summon.js +0 -377
package/build/cli/index.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
+
import * as fs from "node:fs/promises";
|
|
2
3
|
import { FlowError, asMessage } from "../flow-error.js";
|
|
3
4
|
import { writeDraftArtifact } from "./draft-artifact.js";
|
|
4
5
|
import { amendKeiyaku } from "../core/amend.js";
|
|
5
6
|
import { arcKeiyaku, buildArcInput } from "../core/arc.js";
|
|
6
7
|
import { bindContract } from "../core/bind.js";
|
|
7
8
|
import { buildAmendInput, defaultActorClock } from "../core/command-io.js";
|
|
8
|
-
import { resolveContractAddress } from "../core/
|
|
9
|
+
import { AddressResolutionError, buildResolutionAttempt, resolveContractAddress, withResolvedAddress, } from "../core/addressing.js";
|
|
9
10
|
import { forfeitContractCommand } from "../core/forfeit.js";
|
|
10
11
|
import { readContractLog } from "../core/log.js";
|
|
11
12
|
import { buildPetitionClaimInput } from "../core/petition.js";
|
|
12
13
|
import { petitionKeiyaku } from "../core/petition-run.js";
|
|
13
14
|
import { renewKeiyaku } from "../core/renew.js";
|
|
14
|
-
import { readKanshiBoard } from "../core/status.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { normalizeTargetRef, readKanshiBoard } from "../core/status.js";
|
|
16
|
+
import { runCallAndPersist } from "../core/call-persist.js";
|
|
17
|
+
import { locateResponseArtifact } from "../core/transcripts.js";
|
|
17
18
|
import { renderEnvExample } from "../config/env-keys.js";
|
|
18
19
|
import { assertSettingsKnobUsable, loadKeiyakuSettings } from "../config/settings.js";
|
|
19
20
|
import { handleCliError } from "./render/errors.js";
|
|
@@ -21,121 +22,209 @@ import { renderStatusBoard } from "./render/status.js";
|
|
|
21
22
|
import { VERSION } from "../generated/version.js";
|
|
22
23
|
import { FLAG_SPECS } from "./flags.js";
|
|
23
24
|
import { renderAkumaList, renderAkumaShow } from "./commands/akuma.js";
|
|
24
|
-
import {
|
|
25
|
+
import { loadAkumaCatalogV2 } from "../config/akuma-loader_v2.js";
|
|
25
26
|
import { renderCompletionCandidates, renderCompletionScript } from "./completion.js";
|
|
26
27
|
import { CLI_COMMAND_METADATA, buildKeiyakuGuide, missingSubcommandError, renderCliCommandHelp as renderCliCommandHelpText, renderCliHelp as renderCliHelpText, } from "./help.js";
|
|
27
|
-
import { commandUsesPromptInput,
|
|
28
|
+
import { commandUsesPromptInput, isCallCommand, parseCliArgs } from "./parse.js";
|
|
28
29
|
import { buildAmendResponse, buildArcResponse, buildRenewResponse } from "./render/arc.js";
|
|
29
30
|
import { buildLogResponse } from "./render/misc.js";
|
|
30
31
|
import { buildPetitionClaimResponse } from "./render/petition.js";
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
32
|
+
import { shellQuote } from "./render/format.js";
|
|
33
|
+
import { buildBindDraftResponse, buildBindResponse, buildForfeitResponse, formatCallNextAction, renderCoreResult, textResponse } from "./render/shared.js";
|
|
34
|
+
import { buildCallResponse, renderAdoptedLaunchReceipt } from "./render/call.js";
|
|
35
|
+
import { projectionDir, writeInboxTell } from "../core/projection-core.js";
|
|
36
|
+
import { assertTellEffortSupported, tellProjection } from "../core/projection-wake.js";
|
|
37
|
+
import { resolveProjectionAddress } from "./projection-address.js";
|
|
38
|
+
import { waitForProjection } from "../core/projection-wait.js";
|
|
39
|
+
import { buildWaitResponse } from "./render/wait.js";
|
|
40
|
+
import { prependAddressReceipt, renderResolvedAddressReceipt } from "./render/address.js";
|
|
36
41
|
import { installOfficialSkills } from "./skills-install.js";
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
import { isGitRepo } from "../git/branches.js";
|
|
43
|
+
import { stableRepoRoot } from "../core/worktree-path.js";
|
|
44
|
+
const CALL_INPUT_HINTS = [
|
|
45
|
+
"Call input can be a prompt argument, `-` to read stdin, or omitted to read stdin.",
|
|
46
|
+
"Use `keiyaku call NAME \"prompt\"`, `keiyaku call NAME - < prompt.md`, or `keiyaku revive ARTIFACT_ID`.",
|
|
40
47
|
];
|
|
41
|
-
function
|
|
48
|
+
function titleFromCallPrompt(prompt) {
|
|
42
49
|
const firstLine = prompt
|
|
43
50
|
.split(/\r?\n/)
|
|
44
51
|
.map((line) => line.trim())
|
|
45
52
|
.find((line) => line.length > 0);
|
|
46
53
|
if (!firstLine)
|
|
47
|
-
return "
|
|
48
|
-
return firstLine.replace(/^#+\s*/, "").slice(0, 80) || "
|
|
54
|
+
return "Call";
|
|
55
|
+
return firstLine.replace(/^#+\s*/, "").slice(0, 80) || "Call";
|
|
49
56
|
}
|
|
50
|
-
function
|
|
57
|
+
function repositoryCoordinateFromAddress(address) {
|
|
58
|
+
return address?.repo.kind === "repository" ? address.repo.stableRoot : undefined;
|
|
59
|
+
}
|
|
60
|
+
function buildCallInput(content, flags, mode = "call") {
|
|
51
61
|
const cwd = flags.cwd ?? process.cwd();
|
|
52
62
|
const task = content.trim();
|
|
53
63
|
if (!task) {
|
|
54
|
-
throw new FlowError("EMPTY_PARAM", "
|
|
55
|
-
hints:
|
|
64
|
+
throw new FlowError("EMPTY_PARAM", "call requires a prompt argument, `-` with stdin, or prompt text on stdin.", {
|
|
65
|
+
hints: CALL_INPUT_HINTS,
|
|
56
66
|
});
|
|
57
67
|
}
|
|
58
68
|
return {
|
|
59
69
|
cwd,
|
|
60
|
-
|
|
70
|
+
repo: flags.repo,
|
|
71
|
+
mode,
|
|
72
|
+
contractId: flags.contractId,
|
|
73
|
+
contractAddressSource: flags.contractAddressSource,
|
|
74
|
+
title: titleFromCallPrompt(task),
|
|
61
75
|
task,
|
|
62
|
-
agent: flags.
|
|
76
|
+
agent: flags.akuma,
|
|
63
77
|
model: flags.model,
|
|
64
78
|
effort: flags.effort,
|
|
65
|
-
resumePath: flags.resumePath,
|
|
66
79
|
incognito: flags.incognito,
|
|
67
80
|
bare: flags.bare,
|
|
81
|
+
detach: flags.detach,
|
|
68
82
|
};
|
|
69
83
|
}
|
|
70
|
-
function
|
|
84
|
+
function revivePrompt(stdin) {
|
|
71
85
|
return stdin.trim() ? stdin : "Continue from the previous response.";
|
|
72
86
|
}
|
|
73
87
|
function commandSpec(command, run) {
|
|
74
88
|
return { ...CLI_COMMAND_METADATA[command], run };
|
|
75
89
|
}
|
|
90
|
+
function effectiveDirectory(flags) {
|
|
91
|
+
return flags.cwd ?? process.cwd();
|
|
92
|
+
}
|
|
93
|
+
async function repositoryDirectory(flags) {
|
|
94
|
+
const candidate = flags.repo ?? effectiveDirectory(flags);
|
|
95
|
+
if (!(await isGitRepo(candidate))) {
|
|
96
|
+
if (flags.contractId) {
|
|
97
|
+
const asTyped = flags.contractAddressSource === "at-address"
|
|
98
|
+
? `@${flags.contractId}`
|
|
99
|
+
: flags.contractId;
|
|
100
|
+
throw new AddressResolutionError("EMPTY_PARAM", `${asTyped} is a commission address, but ${candidate} has no repository ledger; contract addressing requires a ledger`, buildResolutionAttempt({
|
|
101
|
+
repo: { kind: "user" },
|
|
102
|
+
workdir: effectiveDirectory(flags),
|
|
103
|
+
spelling: {
|
|
104
|
+
asTyped,
|
|
105
|
+
source: flags.contractAddressSource ?? "explicit-flag",
|
|
106
|
+
},
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
throw new FlowError("NOT_GIT_REPO", `${candidate} is not a git repository`);
|
|
110
|
+
}
|
|
111
|
+
return flags.repo ? await stableRepoRoot(candidate) : candidate;
|
|
112
|
+
}
|
|
113
|
+
async function projectDirectory(flags) {
|
|
114
|
+
if (flags.repo)
|
|
115
|
+
return await repositoryDirectory(flags);
|
|
116
|
+
return effectiveDirectory(flags);
|
|
117
|
+
}
|
|
76
118
|
const CLI_COMMAND_SPECS = {
|
|
77
119
|
bind: commandSpec("bind", async (stdin, flags) => {
|
|
78
|
-
const cwd =
|
|
120
|
+
const cwd = await repositoryDirectory(flags);
|
|
79
121
|
if (flags.draftOnly) {
|
|
80
122
|
return buildBindDraftResponse(await writeDraftArtifact({ cwd, title: "bind-draft", content: stdin }));
|
|
81
123
|
}
|
|
82
124
|
const result = await bindContract({
|
|
83
|
-
cwd, draft: stdin, ...defaultActorClock(), workspace:
|
|
125
|
+
cwd, draft: stdin, ...defaultActorClock(), workspace: "worktree",
|
|
84
126
|
after: flags.after ?? [], exclusive: flags.exclusive,
|
|
127
|
+
onProgress: (line) => {
|
|
128
|
+
process.stdout.write(`${line}\n`);
|
|
129
|
+
},
|
|
85
130
|
});
|
|
86
131
|
return buildBindResponse(result, cwd);
|
|
87
132
|
}),
|
|
88
|
-
arc: commandSpec("arc", async (stdin, flags) =>
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
return
|
|
133
|
+
arc: commandSpec("arc", async (stdin, flags) => {
|
|
134
|
+
const parsed = buildArcInput(stdin, effectiveDirectory(flags), flags.waivePaths, flags.contractId, flags.contractAddressSource);
|
|
135
|
+
const cwd = await repositoryDirectory(flags);
|
|
136
|
+
return renderCoreResult(arcKeiyaku({ ...parsed, cwd }), buildArcResponse);
|
|
92
137
|
}),
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return textResponse(`Projection ${resolved.id} recovery started.\n`);
|
|
138
|
+
call: commandSpec("call", async (stdin, flags, signal) => {
|
|
139
|
+
const outcome = await runCallAndPersist({
|
|
140
|
+
...buildCallInput(stdin, flags, "call"),
|
|
141
|
+
signal,
|
|
142
|
+
...(!flags.detach
|
|
143
|
+
? {
|
|
144
|
+
onLaunch: ({ address, projection }) => {
|
|
145
|
+
process.stdout.write(`${renderAdoptedLaunchReceipt(address, projection.id)}\n`);
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
: {}),
|
|
149
|
+
});
|
|
150
|
+
if (outcome.result.foregroundWait && outcome.result.projection) {
|
|
151
|
+
return buildWaitResponse(outcome.result.projection.id, outcome.result.foregroundWait);
|
|
108
152
|
}
|
|
109
|
-
|
|
110
|
-
|
|
153
|
+
return buildCallResponse(outcome.result, {
|
|
154
|
+
responsePath: outcome.responsePath,
|
|
155
|
+
artifactId: outcome.artifactId,
|
|
156
|
+
addressPlacement: flags.detach ? "stdout" : "none",
|
|
157
|
+
});
|
|
158
|
+
}),
|
|
159
|
+
revive: commandSpec("revive", async (stdin, flags, signal, positional) => {
|
|
160
|
+
const cwd = effectiveDirectory(flags);
|
|
161
|
+
const artifactCwd = await projectDirectory(flags);
|
|
162
|
+
const artifactId = positional[0];
|
|
163
|
+
const responseStoreCwd = await isGitRepo(artifactCwd) ? await stableRepoRoot(artifactCwd) : await fs.realpath(artifactCwd);
|
|
164
|
+
const artifact = await locateResponseArtifact(responseStoreCwd, artifactId);
|
|
165
|
+
let executionCwd;
|
|
166
|
+
let repo;
|
|
167
|
+
if (artifact.provenance.authority.kind === "repository") {
|
|
168
|
+
executionCwd = responseStoreCwd;
|
|
169
|
+
repo = responseStoreCwd;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
if (!("workdir" in artifact.provenance.evidence)) {
|
|
173
|
+
throw new FlowError("INVALID_RESPONSE_PATH", `Invalid response artifact '${artifactId}': field 'provenance.evidence.workdir' is missing.`);
|
|
174
|
+
}
|
|
175
|
+
executionCwd = artifact.provenance.evidence.workdir;
|
|
176
|
+
repo = undefined;
|
|
177
|
+
}
|
|
178
|
+
const outcome = await runCallAndPersist({
|
|
179
|
+
...buildCallInput(revivePrompt(stdin), { ...flags, cwd: executionCwd, repo }, "revive"),
|
|
180
|
+
reviveArtifact: artifact,
|
|
181
|
+
signal,
|
|
182
|
+
});
|
|
183
|
+
return buildCallResponse(outcome.result, { responsePath: outcome.responsePath, artifactId: outcome.artifactId, addressPlacement: "footer" });
|
|
184
|
+
}),
|
|
185
|
+
wait: commandSpec("wait", async (_stdin, flags, signal, positional) => {
|
|
186
|
+
const cwd = flags.contractId ? await repositoryDirectory(flags) : await projectDirectory(flags);
|
|
187
|
+
const address = flags.contractId ? await resolveContractAddress(cwd, flags.contractId, flags.contractAddressSource) : undefined;
|
|
188
|
+
const operation = async () => {
|
|
189
|
+
const projectionId = resolveProjectionAddress(cwd, positional[0], address?.binding.commissionId);
|
|
190
|
+
return prependAddressReceipt(buildWaitResponse(projectionId, await waitForProjection({ projectionDirectory: projectionDir(cwd, projectionId), timeoutMs: flags.timeoutMs, signal })), address, { projectionId });
|
|
191
|
+
};
|
|
192
|
+
return address ? await withResolvedAddress(address, operation) : await operation();
|
|
111
193
|
}),
|
|
112
194
|
tell: commandSpec("tell", async (_stdin, flags, _signal, positional) => {
|
|
113
|
-
const cwd = flags.
|
|
195
|
+
const cwd = flags.contractId ? await repositoryDirectory(flags) : await projectDirectory(flags);
|
|
114
196
|
const [prefix, message] = positional;
|
|
115
197
|
if (!prefix || !message)
|
|
116
198
|
throw new FlowError("EMPTY_PARAM", "tell requires a projection and message");
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
199
|
+
const address = flags.contractId ? await resolveContractAddress(cwd, flags.contractId, flags.contractAddressSource) : undefined;
|
|
200
|
+
const operation = async () => {
|
|
201
|
+
const projectionId = resolveProjectionAddress(cwd, prefix, address?.binding.commissionId);
|
|
202
|
+
const directory = projectionDir(cwd, projectionId);
|
|
203
|
+
assertTellEffortSupported(directory, flags.effort);
|
|
204
|
+
// Mailbox first: do not inspect phase before this immutable write.
|
|
205
|
+
writeInboxTell(directory, message, Date.now(), { effort: flags.effort });
|
|
206
|
+
await tellProjection(directory, flags.effort);
|
|
207
|
+
return textResponse("");
|
|
208
|
+
};
|
|
209
|
+
return address ? await withResolvedAddress(address, operation) : await operation();
|
|
125
210
|
}),
|
|
126
|
-
log: commandSpec("log", async (_stdin, flags
|
|
127
|
-
const cwd =
|
|
128
|
-
const
|
|
129
|
-
return
|
|
211
|
+
log: commandSpec("log", async (_stdin, flags) => {
|
|
212
|
+
const cwd = await repositoryDirectory(flags);
|
|
213
|
+
const address = await resolveContractAddress(cwd, flags.contractId, flags.contractAddressSource);
|
|
214
|
+
return await withResolvedAddress(address, async () => {
|
|
215
|
+
const result = await readContractLog({ cwd, contractId: address.binding.commissionId });
|
|
216
|
+
return buildLogResponse({ ...result, address });
|
|
217
|
+
});
|
|
130
218
|
}),
|
|
131
219
|
akuma: commandSpec("akuma", async () => { throw missingSubcommandError("akuma", CLI_COMMAND_METADATA.akuma.subcommands ?? []); }),
|
|
132
220
|
"akuma list": commandSpec("akuma list", async (_stdin, flags) => {
|
|
133
|
-
const
|
|
221
|
+
const cwd = await projectDirectory(flags);
|
|
222
|
+
const loaded = await loadKeiyakuSettings(cwd);
|
|
134
223
|
// Role markers need settings pointers; catalog consumers keep legacy agents disease actionable.
|
|
135
224
|
assertSettingsKnobUsable(loaded, "agents");
|
|
136
225
|
assertSettingsKnobUsable(loaded, "default");
|
|
137
226
|
assertSettingsKnobUsable(loaded, "reviewer");
|
|
138
|
-
return textResponse(renderAkumaList(await
|
|
227
|
+
return textResponse(renderAkumaList(await loadAkumaCatalogV2(cwd), loaded.providerInstances, loaded.knobs));
|
|
139
228
|
}),
|
|
140
229
|
"akuma ls": commandSpec("akuma ls", async (_stdin, flags, signal, positional) => CLI_COMMAND_SPECS["akuma list"].run(_stdin, flags, signal, positional)),
|
|
141
230
|
"akuma show": commandSpec("akuma show", async (_stdin, flags, _signal, positional) => {
|
|
@@ -143,48 +232,64 @@ const CLI_COMMAND_SPECS = {
|
|
|
143
232
|
if (!name) {
|
|
144
233
|
throw new FlowError("EMPTY_PARAM", "akuma show requires an Akuma name");
|
|
145
234
|
}
|
|
146
|
-
const
|
|
235
|
+
const cwd = await projectDirectory(flags);
|
|
236
|
+
const loaded = await loadKeiyakuSettings(cwd);
|
|
147
237
|
// Role markers need settings pointers; catalog consumers keep legacy agents disease actionable.
|
|
148
238
|
assertSettingsKnobUsable(loaded, "agents");
|
|
149
239
|
assertSettingsKnobUsable(loaded, "default");
|
|
150
240
|
assertSettingsKnobUsable(loaded, "reviewer");
|
|
151
|
-
return textResponse(renderAkumaShow(await
|
|
241
|
+
return textResponse(renderAkumaShow(await loadAkumaCatalogV2(cwd), loaded.providerInstances, loaded.knobs, name));
|
|
152
242
|
}),
|
|
153
243
|
skills: commandSpec("skills", async () => { throw missingSubcommandError("skills", CLI_COMMAND_METADATA.skills.subcommands ?? []); }),
|
|
154
244
|
"skills install": commandSpec("skills install", async (_stdin, flags) => {
|
|
155
245
|
const result = await installOfficialSkills(flags.force);
|
|
156
246
|
return textResponse([
|
|
157
|
-
"Installed official Keiyaku
|
|
158
|
-
...result.targets.map((target) => `- ${target.path} -> ${
|
|
247
|
+
"Installed official Keiyaku skills:",
|
|
248
|
+
...result.targets.map((target) => `- ${target.path} -> ${target.source} (${target.status})`),
|
|
159
249
|
...(result.warnings.length > 0 ? ["", "## Warning", ...result.warnings.map((warning) => `- ${warning}`)] : []),
|
|
160
250
|
].join("\n"));
|
|
161
251
|
}),
|
|
162
|
-
amend: commandSpec("amend", async (stdin, flags) =>
|
|
252
|
+
amend: commandSpec("amend", async (stdin, flags) => {
|
|
253
|
+
const parsed = buildAmendInput(stdin, effectiveDirectory(flags), flags.contractId, flags.contractAddressSource);
|
|
254
|
+
const cwd = await repositoryDirectory(flags);
|
|
255
|
+
return renderCoreResult(amendKeiyaku({ ...parsed, cwd }), buildAmendResponse);
|
|
256
|
+
}),
|
|
163
257
|
renew: commandSpec("renew", async (_stdin, flags) => {
|
|
164
|
-
const cwd =
|
|
165
|
-
const
|
|
166
|
-
return renderCoreResult(renewKeiyaku({ cwd,
|
|
258
|
+
const cwd = await repositoryDirectory(flags);
|
|
259
|
+
const address = await resolveContractAddress(cwd, flags.contractId, flags.contractAddressSource);
|
|
260
|
+
return renderCoreResult(renewKeiyaku({ cwd, address, waivePaths: flags.waivePaths }), buildRenewResponse);
|
|
167
261
|
}),
|
|
168
262
|
petition: commandSpec("petition", async (stdin, flags, signal) => {
|
|
169
|
-
const cwd =
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
263
|
+
const cwd = await repositoryDirectory(flags);
|
|
264
|
+
const address = await resolveContractAddress(cwd, flags.contractId, flags.contractAddressSource);
|
|
265
|
+
return await withResolvedAddress(address, async () => {
|
|
266
|
+
const input = buildPetitionClaimInput({ cwd, contractId: address.binding.commissionId, stdin, signal, waivePaths: flags.waivePaths });
|
|
267
|
+
return buildPetitionClaimResponse({ ...await petitionKeiyaku(input), address }, input);
|
|
268
|
+
});
|
|
173
269
|
}),
|
|
174
270
|
forfeit: commandSpec("forfeit", async (_stdin, flags) => {
|
|
175
|
-
const cwd =
|
|
176
|
-
const
|
|
177
|
-
return
|
|
271
|
+
const cwd = await repositoryDirectory(flags);
|
|
272
|
+
const address = await resolveContractAddress(cwd, flags.contractId, flags.contractAddressSource);
|
|
273
|
+
return await withResolvedAddress(address, async () => buildForfeitResponse({
|
|
274
|
+
...await forfeitContractCommand({ cwd, contractId: address.binding.commissionId, ...defaultActorClock(), note: flags.reason }),
|
|
275
|
+
address,
|
|
276
|
+
}));
|
|
178
277
|
}),
|
|
179
278
|
guide: commandSpec("guide", async () => textResponse(buildKeiyakuGuide(VERSION))),
|
|
180
279
|
completion: commandSpec("completion", async (_stdin, flags) => {
|
|
181
|
-
const cwd =
|
|
280
|
+
const cwd = await projectDirectory(flags);
|
|
182
281
|
if (flags.complete) {
|
|
183
282
|
return textResponse(await renderCompletionCandidates({ cwd, word: flags.word, previous: flags.previous }));
|
|
184
283
|
}
|
|
185
284
|
return textResponse(renderCompletionScript(flags.shell));
|
|
186
285
|
}),
|
|
187
|
-
status: commandSpec("status", async (_stdin, flags) =>
|
|
286
|
+
status: commandSpec("status", async (_stdin, flags) => {
|
|
287
|
+
// Status is read-only and must open outside Git. projectDirectory still
|
|
288
|
+
// honors --repo as a repository coordinate when the operator names one.
|
|
289
|
+
const cwd = await projectDirectory(flags);
|
|
290
|
+
const target = flags.target === undefined ? undefined : normalizeTargetRef(flags.target);
|
|
291
|
+
return textResponse(renderStatusBoard(await readKanshiBoard(cwd, Date.now(), target === undefined ? undefined : { target })));
|
|
292
|
+
}),
|
|
188
293
|
"dump-env": commandSpec("dump-env", async () => textResponse(renderEnvExample())),
|
|
189
294
|
};
|
|
190
295
|
function getCliCommandSpec(command) {
|
|
@@ -194,7 +299,7 @@ function commandRequiresStdin(command) {
|
|
|
194
299
|
return getCliCommandSpec(command).stdin === "required";
|
|
195
300
|
}
|
|
196
301
|
function commandSavesFailedStdin(command) {
|
|
197
|
-
return commandRequiresStdin(command) && command !== "
|
|
302
|
+
return commandRequiresStdin(command) && command !== "call";
|
|
198
303
|
}
|
|
199
304
|
async function readStdin() {
|
|
200
305
|
if (process.stdin.isTTY)
|
|
@@ -219,9 +324,25 @@ function responseData(response) {
|
|
|
219
324
|
return {};
|
|
220
325
|
return payload;
|
|
221
326
|
}
|
|
327
|
+
function isCallProjectionFacts(value) {
|
|
328
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
329
|
+
return false;
|
|
330
|
+
const facts = value;
|
|
331
|
+
return typeof facts.id === "string"
|
|
332
|
+
&& (facts.phase === "active" || facts.phase === "done" || facts.phase === "failed"
|
|
333
|
+
|| facts.phase === "dismissed" || facts.phase === "lost" || facts.phase === "quiescent");
|
|
334
|
+
}
|
|
222
335
|
function conversationalFooter(response) {
|
|
223
336
|
const data = responseData(response);
|
|
224
337
|
const lines = [];
|
|
338
|
+
if (response.address) {
|
|
339
|
+
const projection = data.projection;
|
|
340
|
+
const projectionFacts = isCallProjectionFacts(projection) ? projection : undefined;
|
|
341
|
+
const receiptArtifactId = typeof data.revivedArtifactId === "string"
|
|
342
|
+
? data.revivedArtifactId
|
|
343
|
+
: typeof data.artifactId === "string" ? data.artifactId : undefined;
|
|
344
|
+
lines.push(renderResolvedAddressReceipt(response.address, { artifactId: receiptArtifactId, projectionId: projectionFacts?.id }));
|
|
345
|
+
}
|
|
225
346
|
const responsePath = typeof data.responsePath === "string" ? data.responsePath : undefined;
|
|
226
347
|
const agent = typeof data.agent === "string" ? data.agent : undefined;
|
|
227
348
|
const meta = data.meta && typeof data.meta === "object" && !Array.isArray(data.meta) ? data.meta : undefined;
|
|
@@ -230,15 +351,28 @@ function conversationalFooter(response) {
|
|
|
230
351
|
lines.push(`Saved to ${responsePath}.`);
|
|
231
352
|
}
|
|
232
353
|
if (agent) {
|
|
233
|
-
lines.push(`
|
|
354
|
+
lines.push(`Akuma: ${agent}`);
|
|
234
355
|
}
|
|
235
356
|
if (warnings.length > 0) {
|
|
236
357
|
lines.push("Warnings:", ...warnings.map((warning) => `- ${warning}`));
|
|
237
358
|
}
|
|
359
|
+
if (typeof data.summary === "string") {
|
|
360
|
+
const projection = data.projection;
|
|
361
|
+
const projectionFacts = isCallProjectionFacts(projection) ? projection : undefined;
|
|
362
|
+
const artifactId = typeof data.artifactId === "string" ? data.artifactId : undefined;
|
|
363
|
+
lines.push(formatCallNextAction({
|
|
364
|
+
projection: projectionFacts,
|
|
365
|
+
artifactId,
|
|
366
|
+
repositoryCoordinate: repositoryCoordinateFromAddress(response.address),
|
|
367
|
+
}));
|
|
368
|
+
}
|
|
238
369
|
return lines.join("\n");
|
|
239
370
|
}
|
|
240
371
|
function writeSuccessResponse(command, response) {
|
|
241
|
-
|
|
372
|
+
// Successful tell is always silent: zero stdout bytes, even if text regresses.
|
|
373
|
+
if (command === "tell")
|
|
374
|
+
return;
|
|
375
|
+
if (command !== "revive") {
|
|
242
376
|
process.stdout.write(`${responseText(response)}\n`);
|
|
243
377
|
return;
|
|
244
378
|
}
|
|
@@ -259,11 +393,6 @@ async function saveFailedStdin(input) {
|
|
|
259
393
|
content: input.content,
|
|
260
394
|
});
|
|
261
395
|
}
|
|
262
|
-
function shellQuote(value) {
|
|
263
|
-
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(value))
|
|
264
|
-
return value;
|
|
265
|
-
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
266
|
-
}
|
|
267
396
|
function retryHint(command, draftPath, cwd, cwdFlag) {
|
|
268
397
|
if (!cwdFlag) {
|
|
269
398
|
return `Retry: keiyaku ${command} < ${shellQuote(draftPath)}`;
|
|
@@ -279,6 +408,9 @@ async function printFailure(error, cwd) {
|
|
|
279
408
|
});
|
|
280
409
|
process.stderr.write(`${responseText(response)}\n`);
|
|
281
410
|
}
|
|
411
|
+
function failureExitCode(error) {
|
|
412
|
+
return error instanceof Error && error.name === "AbortError" ? 130 : 1;
|
|
413
|
+
}
|
|
282
414
|
async function handleFailureAfterStdin(input) {
|
|
283
415
|
if (input.response) {
|
|
284
416
|
process.stderr.write(`${responseText(input.response)}\n`);
|
|
@@ -309,9 +441,9 @@ async function runResponse(command, flags, stdin, positional) {
|
|
|
309
441
|
return await getCliCommandSpec(command).run(stdin, flags, signal, positional);
|
|
310
442
|
}
|
|
311
443
|
function positionalPrompt(command, positional) {
|
|
312
|
-
if (
|
|
444
|
+
if (isCallCommand(command))
|
|
313
445
|
return positional[0];
|
|
314
|
-
if (command === "
|
|
446
|
+
if (command === "revive")
|
|
315
447
|
return positional[1];
|
|
316
448
|
return undefined;
|
|
317
449
|
}
|
|
@@ -323,11 +455,11 @@ async function readPromptInput(command, positional, cwd) {
|
|
|
323
455
|
return prompt;
|
|
324
456
|
const stdin = await readStdin();
|
|
325
457
|
if (!stdin.trim()) {
|
|
326
|
-
if (command === "
|
|
458
|
+
if (command === "revive") {
|
|
327
459
|
return "";
|
|
328
460
|
}
|
|
329
461
|
await printFailure(new FlowError("EMPTY_PARAM", `${command} requires a prompt argument, \`-\` with stdin, or prompt text on stdin.`, {
|
|
330
|
-
hints:
|
|
462
|
+
hints: CALL_INPUT_HINTS,
|
|
331
463
|
}), cwd);
|
|
332
464
|
return undefined;
|
|
333
465
|
}
|
|
@@ -385,12 +517,12 @@ export async function runCliCommand(tokens) {
|
|
|
385
517
|
});
|
|
386
518
|
}
|
|
387
519
|
await printFailure(error, cwd);
|
|
388
|
-
return
|
|
520
|
+
return failureExitCode(error);
|
|
389
521
|
}
|
|
390
522
|
const success = !response.payload || !("error" in response.payload);
|
|
391
523
|
if (success) {
|
|
392
524
|
writeSuccessResponse(parsed.command, response);
|
|
393
|
-
return 0;
|
|
525
|
+
return response.exitCode ?? 0;
|
|
394
526
|
}
|
|
395
527
|
if (commandRequiresStdin(parsed.command)) {
|
|
396
528
|
return await handleFailureAfterStdin({
|