@astrosheep/keiyaku 4.5.19 → 4.5.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +14 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +53 -20
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/references/automation.md +237 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +6 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +2 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -3
- package/build/src/akuma/akuma-handle.d.ts +5 -1
- package/build/src/akuma/akuma-handle.js +4 -1
- package/build/src/akuma/akuma-instance.d.ts +7 -2
- package/build/src/akuma/akuma-instance.js +14 -7
- package/build/src/akuma/akuma-observe.d.ts +11 -0
- package/build/src/akuma/akuma-observe.js +23 -0
- package/build/src/akuma/akuma-product.d.ts +2 -0
- package/build/src/akuma/akuma-product.js +6 -0
- package/build/src/akuma/akuma.d.ts +20 -1
- package/build/src/akuma/akuma.js +2 -0
- package/build/src/akuma/allowed.d.ts +20 -0
- package/build/src/akuma/allowed.js +11 -0
- package/build/src/akuma/archetype.js +3 -0
- package/build/src/akuma/body.d.ts +25 -5
- package/build/src/akuma/body.js +70 -31
- package/build/src/akuma/call-request.d.ts +5 -0
- package/build/src/akuma/call-request.js +14 -4
- package/build/src/akuma/fleet-execution.d.ts +28 -0
- package/build/src/akuma/fleet-execution.js +36 -4
- package/build/src/akuma/fleet-observation.d.ts +54 -0
- package/build/src/akuma/fleet-request.d.ts +10 -0
- package/build/src/akuma/fleet-request.js +13 -3
- package/build/src/akuma/heart/facts.d.ts +2 -0
- package/build/src/akuma/heart/index.d.ts +1 -0
- package/build/src/akuma/heart/index.js +4 -1
- package/build/src/akuma/heart/rows.d.ts +2 -0
- package/build/src/akuma/heart/rows.js +7 -5
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +3 -1
- package/build/src/akuma/heart/tells.js +6 -5
- package/build/src/akuma/heart/timeline.js +1 -1
- package/build/src/akuma/provider-recipe.d.ts +1 -0
- package/build/src/akuma/provider-recipe.js +5 -0
- package/build/src/akuma/provider.d.ts +1 -1
- package/build/src/akuma/provider.js +1 -1
- package/build/src/akuma/providers/acp/core.js +3 -6
- package/build/src/akuma/providers/acp/index.js +3 -0
- package/build/src/akuma/providers/claude/index.js +10 -10
- package/build/src/akuma/providers/codex-app-server/index.js +12 -11
- package/build/src/akuma/providers/execution-environment.d.ts +6 -0
- package/build/src/akuma/providers/execution-environment.js +24 -0
- package/build/src/akuma/providers/grok-build/index.js +3 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +32 -23
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +8 -1
- package/build/src/akuma/providers/opencode-sdk/session.js +6 -5
- package/build/src/akuma/providers/pi/events.js +7 -2
- package/build/src/akuma/providers/pi/index.js +5 -2
- package/build/src/akuma/request-observation.d.ts +45 -0
- package/build/src/akuma/request-observation.js +162 -0
- package/build/src/akuma/request-rendezvous.d.ts +6 -3
- package/build/src/akuma/request-rendezvous.js +80 -14
- package/build/src/akuma/request-serve.js +27 -4
- package/build/src/akuma/request-wire.d.ts +5 -0
- package/build/src/akuma/request-wire.js +2 -0
- package/build/src/akuma/turn-drive.d.ts +1 -0
- package/build/src/akuma/turn-drive.js +2 -0
- package/build/src/akuma-body.js +5 -0
- package/build/src/body/amend.js +6 -4
- package/build/src/body/decode.d.ts +3 -1
- package/build/src/body/decode.js +53 -17
- package/build/src/body/region.d.ts +9 -1
- package/build/src/body/region.js +87 -12
- package/build/src/body/render.js +1 -1
- package/build/src/body/verification.d.ts +3 -1
- package/build/src/body/verification.js +4 -1
- package/build/src/cli/accepted.js +19 -2
- package/build/src/cli/commands/akuma-invoke.d.ts +3 -1
- package/build/src/cli/commands/akuma-invoke.js +134 -14
- package/build/src/cli/commands/akuma.js +24 -12
- package/build/src/cli/commands/contract-help.d.ts +15 -15
- package/build/src/cli/commands/contract-help.js +45 -19
- package/build/src/cli/commands/contract-invoke.d.ts +3 -0
- package/build/src/cli/commands/contract-invoke.js +25 -11
- package/build/src/cli/commands/contract.js +6 -4
- package/build/src/cli/commands/install.d.ts +1 -1
- package/build/src/cli/commands/install.js +1 -1
- package/build/src/cli/commands/status-set.js +15 -24
- package/build/src/cli/commands/task.js +18 -18
- package/build/src/cli/invoke.d.ts +3 -0
- package/build/src/cli/invoke.js +58 -23
- package/build/src/cli/main.js +5 -0
- package/build/src/cli/parse.d.ts +3 -0
- package/build/src/cli/parse.js +26 -4
- package/build/src/cli/render/akuma-activity.d.ts +100 -2
- package/build/src/cli/render/akuma-activity.js +485 -40
- package/build/src/cli/render/akuma.d.ts +10 -0
- package/build/src/cli/render/akuma.js +31 -21
- package/build/src/cli/render/audit.js +1 -1
- package/build/src/cli/render/board.js +1 -1
- package/build/src/cli/render/catalog.js +16 -13
- package/build/src/cli/render/contract-history.js +39 -10
- package/build/src/cli/render/contract-observation.js +10 -6
- package/build/src/cli/render/contract.js +109 -106
- package/build/src/cli/render/execution-progress.d.ts +26 -0
- package/build/src/cli/render/execution-progress.js +178 -0
- package/build/src/cli/render/kanshi-akuma.js +27 -39
- package/build/src/cli/render/kanshi.js +33 -26
- package/build/src/cli/render/nuke.js +1 -1
- package/build/src/cli/render/receipt.d.ts +1 -1
- package/build/src/cli/render/receipt.js +6 -6
- package/build/src/cli/render/refusal.js +10 -7
- package/build/src/cli/render/region.js +1 -1
- package/build/src/cli/render/settings.js +12 -2
- package/build/src/cli/render/status-line.d.ts +30 -0
- package/build/src/cli/render/status-line.js +58 -0
- package/build/src/cli/render/status-set.js +1 -1
- package/build/src/cli/render/task.d.ts +2 -0
- package/build/src/cli/render/task.js +11 -7
- package/build/src/cli/render/terminal.d.ts +0 -1
- package/build/src/cli/render/terminal.js +47 -15
- package/build/src/cli/result.d.ts +1 -0
- package/build/src/cli/runtime.d.ts +2 -0
- package/build/src/cli/runtime.js +36 -4
- package/build/src/cli/usage.js +2 -2
- package/build/src/cli/version.d.ts +1 -0
- package/build/src/cli/version.js +25 -0
- package/build/src/git/hooks.d.ts +13 -1
- package/build/src/git/hooks.js +2 -1
- package/build/src/git/workspace.d.ts +1 -1
- package/build/src/git/workspace.js +1 -1
- package/build/src/identity/mint.d.ts +13 -0
- package/build/src/identity/mint.js +26 -0
- package/build/src/identity/normalize.d.ts +4 -0
- package/build/src/identity/normalize.js +30 -0
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +1 -0
- package/build/src/kanshi/read.js +17 -4
- package/build/src/kanshi/report.d.ts +1 -0
- package/build/src/library/akuma-creation.d.ts +2 -0
- package/build/src/library/akuma-creation.js +34 -18
- package/build/src/library/audit.d.ts +2 -0
- package/build/src/library/audit.js +1 -0
- package/build/src/library/bind.js +18 -16
- package/build/src/library/composition.d.ts +1 -0
- package/build/src/library/contract-bind.d.ts +3 -1
- package/build/src/library/contract-bind.js +5 -3
- package/build/src/library/contract-execution.d.ts +2 -0
- package/build/src/library/contract-execution.js +15 -1
- package/build/src/library/contract-forwarding.d.ts +4 -0
- package/build/src/library/contract-forwarding.js +3 -0
- package/build/src/library/contract-handle.d.ts +7 -0
- package/build/src/library/contract-handle.js +25 -0
- package/build/src/library/contract-operations.d.ts +7 -2
- package/build/src/library/contract-operations.js +21 -1
- package/build/src/library/contract-types.d.ts +1 -0
- package/build/src/library/execution-result.d.ts +2 -2
- package/build/src/library/execution.d.ts +8 -0
- package/build/src/library/execution.js +102 -0
- package/build/src/library/fleet.d.ts +4 -1
- package/build/src/library/fleet.js +32 -8
- package/build/src/library/keiyaku.d.ts +2 -0
- package/build/src/library/mutation.js +15 -7
- package/build/src/plugin/akuma-signals.d.ts +6 -0
- package/build/src/plugin/akuma-signals.js +9 -1
- package/build/src/plugin/public.d.ts +6 -2
- package/build/src/plugin/runtime.d.ts +1 -3
- package/build/src/plugin/runtime.js +95 -103
- package/build/src/protocol/amend.js +4 -3
- package/build/src/protocol/attempt.d.ts +2 -0
- package/build/src/protocol/bind.js +41 -14
- package/build/src/protocol/completion.d.ts +3 -0
- package/build/src/protocol/completion.js +35 -11
- package/build/src/protocol/deliver.js +165 -92
- package/build/src/protocol/execution-observation.d.ts +181 -0
- package/build/src/protocol/execution-observation.js +45 -0
- package/build/src/protocol/intent.d.ts +18 -22
- package/build/src/protocol/intent.js +63 -41
- package/build/src/protocol/operations.d.ts +2 -0
- package/build/src/protocol/placement.js +5 -1
- package/build/src/protocol/progress.d.ts +5 -1
- package/build/src/protocol/progress.js +10 -1
- package/build/src/protocol/read/status.d.ts +1 -0
- package/build/src/protocol/read/status.js +10 -2
- package/build/src/protocol/reintegrate.d.ts +1 -1
- package/build/src/protocol/reintegrate.js +70 -43
- package/build/src/protocol/result-codec.js +27 -11
- package/build/src/protocol/review.js +53 -30
- package/build/src/protocol/run.d.ts +83 -36
- package/build/src/protocol/run.js +90 -75
- package/build/src/runtime/proc/run.d.ts +16 -4
- package/build/src/runtime/proc/run.js +64 -22
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settings.js +5 -14
- package/build/src/task/document.d.ts +5 -1
- package/build/src/task/document.js +6 -1
- package/build/src/verification/execution.d.ts +10 -2
- package/build/src/verification/execution.js +143 -42
- package/build/src/verification/observation.d.ts +41 -0
- package/build/src/verification/observation.js +29 -0
- package/package.json +3 -1
package/build/src/cli/runtime.js
CHANGED
|
@@ -5,6 +5,30 @@ import { safeText } from "./render/terminal.js";
|
|
|
5
5
|
function writeCliStream(stream, body) {
|
|
6
6
|
stream.write(body.endsWith("\n") ? body : `${body}\n`);
|
|
7
7
|
}
|
|
8
|
+
export async function writeExecutionProgress(events, stream = process.stderr) {
|
|
9
|
+
const { renderExecutionProgress } = await import("./render/execution-progress.js");
|
|
10
|
+
const terminal = stream;
|
|
11
|
+
await renderExecutionProgress(events, {
|
|
12
|
+
stream: terminal,
|
|
13
|
+
context: {
|
|
14
|
+
columns: terminal.isTTY === true && Number.isInteger(terminal.columns) ? (terminal.columns ?? 80) : 80,
|
|
15
|
+
color: false,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function cliCancellation() {
|
|
20
|
+
const controller = new AbortController();
|
|
21
|
+
const cancel = () => controller.abort(new Error("CLI cancellation requested"));
|
|
22
|
+
process.once("SIGINT", cancel);
|
|
23
|
+
process.once("SIGTERM", cancel);
|
|
24
|
+
return {
|
|
25
|
+
signal: controller.signal,
|
|
26
|
+
close() {
|
|
27
|
+
process.removeListener("SIGINT", cancel);
|
|
28
|
+
process.removeListener("SIGTERM", cancel);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
8
32
|
export async function writeTask(command, result) {
|
|
9
33
|
const { renderTaskIncompleteDiagnostic, renderTaskText, taskExitCode } = await import("./render/task.js");
|
|
10
34
|
const context = {
|
|
@@ -114,7 +138,7 @@ function writeWorldScopeRefusal(error, command) {
|
|
|
114
138
|
const body = command.output === "json"
|
|
115
139
|
? JSON.stringify(error.refusal)
|
|
116
140
|
: [
|
|
117
|
-
|
|
141
|
+
`× selector ${error.refusal.kind}`,
|
|
118
142
|
` world ${safeText(error.refusal.world)}`,
|
|
119
143
|
...error.refusal.ids.map((id) => ` given ${safeText(id)}`),
|
|
120
144
|
` accepts ${guide.accepts}`,
|
|
@@ -136,15 +160,20 @@ async function commandFailureText(error, command) {
|
|
|
136
160
|
}, "selector");
|
|
137
161
|
}
|
|
138
162
|
const { renderRefusalFacts } = await import("./render/refusal.js");
|
|
139
|
-
return [
|
|
163
|
+
return [`× ${command.command} refused`, ...renderRefusalFacts(error.refusal, " ", displayContext().columns)].join("\n");
|
|
140
164
|
}
|
|
141
|
-
return
|
|
165
|
+
return `× ${command.command} failed\n diagnostic ${safeText(diagnostic)}`;
|
|
142
166
|
}
|
|
143
167
|
export async function runCliCommand(invocation) {
|
|
144
168
|
const command = invocation.command;
|
|
169
|
+
const cancellation = cliCancellation();
|
|
145
170
|
try {
|
|
146
171
|
const { invoke } = await import("./invoke.js");
|
|
147
|
-
const result = await invoke(invocation, {
|
|
172
|
+
const result = await invoke(invocation, {
|
|
173
|
+
cwd: process.cwd(),
|
|
174
|
+
signal: cancellation.signal,
|
|
175
|
+
progress: writeExecutionProgress,
|
|
176
|
+
});
|
|
148
177
|
return await writeResult(command, result);
|
|
149
178
|
}
|
|
150
179
|
catch (error) {
|
|
@@ -177,4 +206,7 @@ export async function runCliCommand(invocation) {
|
|
|
177
206
|
writeCliStream(process.stderr, await commandFailureText(error, command));
|
|
178
207
|
return error instanceof CliUsageError ? 1 : 3;
|
|
179
208
|
}
|
|
209
|
+
finally {
|
|
210
|
+
cancellation.close();
|
|
211
|
+
}
|
|
180
212
|
}
|
package/build/src/cli/usage.js
CHANGED
|
@@ -34,9 +34,9 @@ export function unknownCommandGuide(guide, given) {
|
|
|
34
34
|
}
|
|
35
35
|
export function renderUsageMessage(diagnostic, guide, kind = "usage") {
|
|
36
36
|
if (guide === undefined) {
|
|
37
|
-
return
|
|
37
|
+
return `× ${kind}\n diagnostic ${diagnostic}`;
|
|
38
38
|
}
|
|
39
|
-
const lines = [
|
|
39
|
+
const lines = [`× ${kind} ${guide.scope}`];
|
|
40
40
|
if (!guide.hideDiagnostic && diagnostic.length > 0) {
|
|
41
41
|
lines.push(` diagnostic ${diagnostic}`);
|
|
42
42
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function installedPackageVersion(): Promise<string>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
const PACKAGE_NAME = "@astrosheep/keiyaku";
|
|
3
|
+
export async function installedPackageVersion() {
|
|
4
|
+
const manifest = JSON.parse(await readFile(owningManifestUrl(), "utf8"));
|
|
5
|
+
if (!isOwningManifest(manifest)) {
|
|
6
|
+
throw new Error(`Keiyaku package manifest must name ${PACKAGE_NAME} and contain a nonempty version`);
|
|
7
|
+
}
|
|
8
|
+
return manifest.version;
|
|
9
|
+
}
|
|
10
|
+
function owningManifestUrl() {
|
|
11
|
+
const relativePath = import.meta.url.endsWith("/src/cli/version.ts")
|
|
12
|
+
? "../../package.json"
|
|
13
|
+
: import.meta.url.endsWith("/build/src/cli/version.js")
|
|
14
|
+
? "../../../package.json"
|
|
15
|
+
: undefined;
|
|
16
|
+
if (relativePath === undefined)
|
|
17
|
+
throw new Error("Keiyaku package metadata has an unsupported module layout");
|
|
18
|
+
return new URL(relativePath, import.meta.url);
|
|
19
|
+
}
|
|
20
|
+
function isOwningManifest(value) {
|
|
21
|
+
if (typeof value !== "object" || value === null)
|
|
22
|
+
return false;
|
|
23
|
+
const manifest = value;
|
|
24
|
+
return manifest.name === PACKAGE_NAME && typeof manifest.version === "string" && manifest.version.trim().length > 0;
|
|
25
|
+
}
|
package/build/src/git/hooks.d.ts
CHANGED
|
@@ -16,11 +16,17 @@ export type HookFailure = Readonly<{
|
|
|
16
16
|
truncated: boolean;
|
|
17
17
|
}> | Readonly<{
|
|
18
18
|
kind: "timeout";
|
|
19
|
+
stdout?: string;
|
|
20
|
+
stderr?: string;
|
|
21
|
+
truncated?: boolean;
|
|
19
22
|
}> | Readonly<{
|
|
20
23
|
kind: "spawn-error";
|
|
21
24
|
diagnostic: string;
|
|
22
25
|
}> | Readonly<{
|
|
23
26
|
kind: "unknown-exit";
|
|
27
|
+
stdout?: string;
|
|
28
|
+
stderr?: string;
|
|
29
|
+
truncated?: boolean;
|
|
24
30
|
}>;
|
|
25
31
|
export type WorktreeHookLag = Readonly<{
|
|
26
32
|
kind: "worktree-hook-failed";
|
|
@@ -42,13 +48,19 @@ export type HookCommandRun = Readonly<{
|
|
|
42
48
|
kind: "ok";
|
|
43
49
|
}> | Readonly<{
|
|
44
50
|
kind: "cancelled";
|
|
51
|
+
stdout?: string;
|
|
52
|
+
stderr?: string;
|
|
53
|
+
truncated?: boolean;
|
|
45
54
|
}> | Readonly<{
|
|
46
55
|
kind: "failed";
|
|
47
56
|
name: string;
|
|
48
57
|
failure: HookFailure;
|
|
49
58
|
}>;
|
|
50
59
|
/** Execute an ordered command list without lifecycle state. Scratch owns this policy. */
|
|
51
|
-
export declare function runHookCommands(worktree: string, commands: readonly HookCommand[], signal?: AbortSignal, environment?: NodeJS.ProcessEnv
|
|
60
|
+
export declare function runHookCommands(worktree: string, commands: readonly HookCommand[], signal?: AbortSignal, environment?: NodeJS.ProcessEnv, onOutput?: (output: Readonly<{
|
|
61
|
+
stream: "stdout" | "stderr";
|
|
62
|
+
text: string;
|
|
63
|
+
}>) => void): Promise<HookCommandRun>;
|
|
52
64
|
export type HookPhaseRun = Readonly<{
|
|
53
65
|
lag: WorktreeHookLag | null;
|
|
54
66
|
runs: readonly string[];
|
package/build/src/git/hooks.js
CHANGED
|
@@ -98,7 +98,7 @@ function failedOutcome(outcome) {
|
|
|
98
98
|
return outcome;
|
|
99
99
|
}
|
|
100
100
|
/** Execute an ordered command list without lifecycle state. Scratch owns this policy. */
|
|
101
|
-
export async function runHookCommands(worktree, commands, signal, environment) {
|
|
101
|
+
export async function runHookCommands(worktree, commands, signal, environment, onOutput) {
|
|
102
102
|
for (const value of commands) {
|
|
103
103
|
const outcome = await runProcess({
|
|
104
104
|
argv: value.argv,
|
|
@@ -106,6 +106,7 @@ export async function runHookCommands(worktree, commands, signal, environment) {
|
|
|
106
106
|
cwd: worktree,
|
|
107
107
|
...(signal === undefined ? {} : { signal }),
|
|
108
108
|
...(environment === undefined ? {} : { env: environment }),
|
|
109
|
+
...(onOutput === undefined ? {} : { onOutput }),
|
|
109
110
|
});
|
|
110
111
|
if (outcome.kind === "cancelled")
|
|
111
112
|
return outcome;
|
|
@@ -49,7 +49,7 @@ export type WorkspaceChangeCounts = Readonly<{
|
|
|
49
49
|
}>;
|
|
50
50
|
export type ConflictRecovery = Readonly<{
|
|
51
51
|
materialize: "deliver --materialize-conflict --include-dirty";
|
|
52
|
-
|
|
52
|
+
deliver: "deliver --include-dirty";
|
|
53
53
|
staging: "not-required";
|
|
54
54
|
}>;
|
|
55
55
|
export declare const conflictRecovery: ConflictRecovery;
|
|
@@ -195,7 +195,7 @@ export async function unmergedWorkspacePaths(repository, workspace) {
|
|
|
195
195
|
}
|
|
196
196
|
export const conflictRecovery = Object.freeze({
|
|
197
197
|
materialize: "deliver --materialize-conflict --include-dirty",
|
|
198
|
-
|
|
198
|
+
deliver: "deliver --include-dirty",
|
|
199
199
|
staging: "not-required",
|
|
200
200
|
});
|
|
201
201
|
function countsOf(changes) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mint one identity segment from a fitted stem by drawing a fresh random suffix
|
|
3
|
+
* and letting the caller admit the candidate. A collision redraws the suffix
|
|
4
|
+
* within the attempt budget; exhaustion returns the last collision rather than
|
|
5
|
+
* lengthening the identity.
|
|
6
|
+
*/
|
|
7
|
+
export declare function mintIdentitySegment<Value>(input: Readonly<{
|
|
8
|
+
stem: string;
|
|
9
|
+
attempts: number;
|
|
10
|
+
drawSuffix: () => string;
|
|
11
|
+
attempt: (segment: string) => Promise<Value>;
|
|
12
|
+
collision: (value: Value) => boolean;
|
|
13
|
+
}>): Promise<Value>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const IDENTITY_SUFFIX_PATTERN = /^[0-9a-f]{4}$/u;
|
|
2
|
+
function requireIdentitySuffix(value) {
|
|
3
|
+
if (!IDENTITY_SUFFIX_PATTERN.test(value)) {
|
|
4
|
+
throw new Error("identity suffix must be four lowercase hexadecimal digits");
|
|
5
|
+
}
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Mint one identity segment from a fitted stem by drawing a fresh random suffix
|
|
10
|
+
* and letting the caller admit the candidate. A collision redraws the suffix
|
|
11
|
+
* within the attempt budget; exhaustion returns the last collision rather than
|
|
12
|
+
* lengthening the identity.
|
|
13
|
+
*/
|
|
14
|
+
export async function mintIdentitySegment(input) {
|
|
15
|
+
if (!Number.isSafeInteger(input.attempts) || input.attempts < 1) {
|
|
16
|
+
throw new Error("identity mint attempt budget must be a positive safe integer");
|
|
17
|
+
}
|
|
18
|
+
let result;
|
|
19
|
+
for (let index = 0; index < input.attempts; index += 1) {
|
|
20
|
+
const suffix = requireIdentitySuffix(input.drawSuffix());
|
|
21
|
+
result = await input.attempt(`${input.stem}-${suffix}`);
|
|
22
|
+
if (!input.collision(result))
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export declare function normalizeIdentityStem(input: Readonly<{
|
|
2
2
|
source: string;
|
|
3
3
|
}>): string;
|
|
4
|
+
export declare function fitIdentityStemWords(input: Readonly<{
|
|
5
|
+
stem: string;
|
|
6
|
+
maxCodePoints: number;
|
|
7
|
+
}>): string;
|
|
4
8
|
export declare function fitIdentityStem(input: Readonly<{
|
|
5
9
|
stem: string;
|
|
6
10
|
maxBytes: number;
|
|
@@ -21,6 +21,36 @@ export function normalizeIdentityStem(input) {
|
|
|
21
21
|
}
|
|
22
22
|
return result;
|
|
23
23
|
}
|
|
24
|
+
export function fitIdentityStemWords(input) {
|
|
25
|
+
if (!Number.isSafeInteger(input.maxCodePoints) || input.maxCodePoints < 1) {
|
|
26
|
+
throw new Error("identity stem code point budget must be a positive safe integer");
|
|
27
|
+
}
|
|
28
|
+
const words = input.stem.split("-");
|
|
29
|
+
let fitted = truncateGraphemes(words[0], input.maxCodePoints);
|
|
30
|
+
let count = [...fitted].length;
|
|
31
|
+
for (const word of words.slice(1)) {
|
|
32
|
+
const candidate = count + 1 + [...word].length;
|
|
33
|
+
if (candidate > input.maxCodePoints)
|
|
34
|
+
break;
|
|
35
|
+
fitted += `-${word}`;
|
|
36
|
+
count = candidate;
|
|
37
|
+
}
|
|
38
|
+
if (fitted.length === 0)
|
|
39
|
+
throw new Error("identity stem is empty after fitting");
|
|
40
|
+
return fitted;
|
|
41
|
+
}
|
|
42
|
+
function truncateGraphemes(value, maxCodePoints) {
|
|
43
|
+
let result = "";
|
|
44
|
+
let count = 0;
|
|
45
|
+
for (const { segment } of GRAPHEMES.segment(value)) {
|
|
46
|
+
const size = [...segment].length;
|
|
47
|
+
if (count + size > maxCodePoints)
|
|
48
|
+
break;
|
|
49
|
+
result += segment;
|
|
50
|
+
count += size;
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
24
54
|
export function fitIdentityStem(input) {
|
|
25
55
|
if (!Number.isSafeInteger(input.maxBytes) || input.maxBytes < 1) {
|
|
26
56
|
throw new Error("identity stem byte budget must be a positive safe integer");
|
package/build/src/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from "./library/keiyaku.js";
|
|
2
|
+
export { Akuma, Schema, ALLOWED_ACTIONS, AkumaBusyError, AkumaDecodeError, AkumaNotBornError, AkumaProviderError, } from "./akuma/index.js";
|
|
3
|
+
export type { AkumaBirthInput, AkumaHistoryOptions, AkumaIdleOptions, AkumaSignalOptions, AkumaTellOptions, InterruptReceipt, KillEvidence, JsonSchema, JsonSchemaDocument, AkuId, AkumaStatus, ActivityHistory, ActivityRow, AllowedAction, AllowedActions, } from "./akuma/index.js";
|
|
2
4
|
export { settings } from "./settings.js";
|
|
3
5
|
export { World, WorldError } from "./world.js";
|
|
4
6
|
export type { WorldResolution, WorldResolutionInput, WorldRoot } from "./world.js";
|
package/build/src/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export * from "./library/keiyaku.js";
|
|
2
|
+
export { Akuma, Schema, ALLOWED_ACTIONS, AkumaBusyError, AkumaDecodeError, AkumaNotBornError, AkumaProviderError, } from "./akuma/index.js";
|
|
2
3
|
export { settings } from "./settings.js";
|
|
3
4
|
export { World, WorldError } from "./world.js";
|
package/build/src/kanshi/read.js
CHANGED
|
@@ -15,7 +15,7 @@ import { readDocuments } from "../protocol/read/documents.js";
|
|
|
15
15
|
import { contractId } from "../core/facts/types.js";
|
|
16
16
|
import { selectKanshi, selectRegion } from "./select.js";
|
|
17
17
|
import { FLEET_SNAPSHOT_ROWS, FLEET_VISIBLE_ROWS } from "./fleet.js";
|
|
18
|
-
import { observeRecentTaskStatus } from "../task/index.js";
|
|
18
|
+
import { observeRecentTaskStatus, TaskAuthorityCorruptionError } from "../task/index.js";
|
|
19
19
|
function diagnostic(error) {
|
|
20
20
|
let source;
|
|
21
21
|
if (error instanceof Error)
|
|
@@ -224,6 +224,15 @@ function joinTasks(rows, holders, observeContract) {
|
|
|
224
224
|
return { ...row, contract: { id: contractId, observed: observeContract(contractId) } };
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
|
+
/** Attribute a Task board failure to the malformed document that caused it, when one is known. */
|
|
228
|
+
function taskFailure(error) {
|
|
229
|
+
return {
|
|
230
|
+
message: diagnostic(error),
|
|
231
|
+
...(error instanceof TaskAuthorityCorruptionError && error.coordinate !== undefined
|
|
232
|
+
? { coordinate: error.coordinate }
|
|
233
|
+
: {}),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
227
236
|
async function readTaskWorld(path) {
|
|
228
237
|
if (path === null)
|
|
229
238
|
return { kind: "absent" };
|
|
@@ -231,14 +240,18 @@ async function readTaskWorld(path) {
|
|
|
231
240
|
return { kind: "present", observation: await observeTaskBoard(path) };
|
|
232
241
|
}
|
|
233
242
|
catch (error) {
|
|
234
|
-
return { kind: "failed", failure:
|
|
243
|
+
return { kind: "failed", failure: taskFailure(error) };
|
|
235
244
|
}
|
|
236
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* A selected Contract's own Task namespace view. A failed Task board is reported once by the
|
|
248
|
+
* board's Task section, so the entity block omits it rather than repeating the same row.
|
|
249
|
+
*/
|
|
237
250
|
function namespaceTaskSection(board, id) {
|
|
238
251
|
if (board.kind === "absent")
|
|
239
252
|
return { kind: "absent" };
|
|
240
253
|
if (board.kind === "failed")
|
|
241
|
-
return
|
|
254
|
+
return undefined;
|
|
242
255
|
return { kind: "present", value: board.observation.selectNamespace(contractNamespace(id)) };
|
|
243
256
|
}
|
|
244
257
|
async function readTasks(path, holders, observeContract) {
|
|
@@ -247,7 +260,7 @@ async function readTasks(path, holders, observeContract) {
|
|
|
247
260
|
return observeRecentTaskStatus(path, { limit: 10 }).then((recent) => ({
|
|
248
261
|
kind: "present",
|
|
249
262
|
value: { root: path, hasMore: recent.hasMore, rows: joinTasks(recent.rows, holders, observeContract) },
|
|
250
|
-
}), (error) => ({ kind: "failed", failure:
|
|
263
|
+
}), (error) => ({ kind: "failed", failure: taskFailure(error) }));
|
|
251
264
|
}
|
|
252
265
|
async function joinAkuma(path, observeContract, dispatches, aliases) {
|
|
253
266
|
if (aliases.kind !== "present")
|
|
@@ -54,6 +54,7 @@ export type CallInput = Readonly<{
|
|
|
54
54
|
alias?: AkumaAlias;
|
|
55
55
|
allowed?: readonly AllowedAction[];
|
|
56
56
|
schema?: Schema<unknown>;
|
|
57
|
+
initiator?: string;
|
|
57
58
|
}>;
|
|
58
59
|
export type CallObservation = Readonly<{
|
|
59
60
|
kind: "detached";
|
|
@@ -89,6 +90,7 @@ export type BornCall = Readonly<{
|
|
|
89
90
|
schemaTell?: Readonly<{
|
|
90
91
|
body: string;
|
|
91
92
|
schema: Schema<unknown>;
|
|
93
|
+
initiator?: string;
|
|
92
94
|
}>;
|
|
93
95
|
}>;
|
|
94
96
|
export type ForkInput = Readonly<{
|
|
@@ -148,7 +148,7 @@ async function emitCalledSignal(input) {
|
|
|
148
148
|
async function admitCall(input) {
|
|
149
149
|
const born = await input.world.admit(input.call, input.context);
|
|
150
150
|
const akuma = born.kind === "requested" ? born.id : born.allocated.id;
|
|
151
|
-
|
|
151
|
+
await emitCalledSignal({
|
|
152
152
|
path: input.path,
|
|
153
153
|
...(input.settings === undefined ? {} : { settings: input.settings }),
|
|
154
154
|
born,
|
|
@@ -242,26 +242,29 @@ async function resolveAliasStage(path, alias, dispatch, akuma) {
|
|
|
242
242
|
return { kind: "failed", failure: integrationFailure(error) };
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
|
+
const CALL_INPUT_KEYS = [
|
|
246
|
+
"path",
|
|
247
|
+
"archetype",
|
|
248
|
+
"body",
|
|
249
|
+
"cwd",
|
|
250
|
+
"readonly",
|
|
251
|
+
"mode",
|
|
252
|
+
"timeoutMs",
|
|
253
|
+
"home",
|
|
254
|
+
"settings",
|
|
255
|
+
"contract",
|
|
256
|
+
"alias",
|
|
257
|
+
"allowed",
|
|
258
|
+
"schema",
|
|
259
|
+
"initiator",
|
|
260
|
+
];
|
|
245
261
|
async function prepareCall(input, context) {
|
|
246
262
|
const values = requireInput(input, "Keiyaku.call input");
|
|
247
|
-
onlyKeys(values,
|
|
248
|
-
"path",
|
|
249
|
-
"archetype",
|
|
250
|
-
"body",
|
|
251
|
-
"cwd",
|
|
252
|
-
"readonly",
|
|
253
|
-
"mode",
|
|
254
|
-
"timeoutMs",
|
|
255
|
-
"home",
|
|
256
|
-
"settings",
|
|
257
|
-
"contract",
|
|
258
|
-
"alias",
|
|
259
|
-
"allowed",
|
|
260
|
-
"schema",
|
|
261
|
-
], "Keiyaku.call input");
|
|
263
|
+
onlyKeys(values, CALL_INPUT_KEYS, "Keiyaku.call input");
|
|
262
264
|
const path = await World.prove(nonblank(values.path, "path"));
|
|
263
265
|
const archetype = nonblank(values.archetype, "archetype");
|
|
264
266
|
const body = text(values.body, "body");
|
|
267
|
+
const initiator = values.initiator === undefined ? undefined : text(values.initiator, "initiator");
|
|
265
268
|
const readonlyRequested = callReadonly(values.readonly, "readonly must be true").readonly;
|
|
266
269
|
const cwd = values.cwd === undefined ? undefined : nonblank(values.cwd, "cwd");
|
|
267
270
|
const mode = callMode(values.mode);
|
|
@@ -279,6 +282,7 @@ async function prepareCall(input, context) {
|
|
|
279
282
|
const call = {
|
|
280
283
|
archetype,
|
|
281
284
|
...(values.schema === undefined ? { body } : {}),
|
|
285
|
+
...(initiator === undefined ? {} : { initiator }),
|
|
282
286
|
...(readonlyRequested === undefined ? {} : { readonly: readonlyRequested }),
|
|
283
287
|
...(values.allowed === undefined ? {} : { allowed: values.allowed }),
|
|
284
288
|
...(values.schema === undefined ? {} : { schema: values.schema }),
|
|
@@ -305,7 +309,15 @@ async function prepareCall(input, context) {
|
|
|
305
309
|
timeoutMs,
|
|
306
310
|
dispatch,
|
|
307
311
|
alias: aliasStage,
|
|
308
|
-
...(values.schema === undefined
|
|
312
|
+
...(values.schema === undefined
|
|
313
|
+
? {}
|
|
314
|
+
: {
|
|
315
|
+
schemaTell: {
|
|
316
|
+
body,
|
|
317
|
+
schema: values.schema,
|
|
318
|
+
...(initiator === undefined ? {} : { initiator }),
|
|
319
|
+
},
|
|
320
|
+
}),
|
|
309
321
|
};
|
|
310
322
|
}
|
|
311
323
|
async function publishCall(born, execution) {
|
|
@@ -326,8 +338,12 @@ async function publishCall(born, execution) {
|
|
|
326
338
|
target: handle.id,
|
|
327
339
|
body: tell.body,
|
|
328
340
|
schema: tell.schema,
|
|
341
|
+
...(tell.initiator === undefined ? {} : { initiator: tell.initiator }),
|
|
329
342
|
})
|
|
330
|
-
: PublicAkuma.select(born.path, handle.id).tell(tell.body, {
|
|
343
|
+
: PublicAkuma.select(born.path, handle.id).tell(tell.body, {
|
|
344
|
+
schema: tell.schema,
|
|
345
|
+
...(tell.initiator === undefined ? {} : { initiator: tell.initiator }),
|
|
346
|
+
}));
|
|
331
347
|
if (born.mode === "detach")
|
|
332
348
|
void pending.catch(() => undefined);
|
|
333
349
|
else
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ExecutionObserver } from "../protocol/execution-observation.js";
|
|
1
2
|
import type { ActorId, ContractId } from "../core/facts/types.js";
|
|
2
3
|
import { type AuditReport } from "../protocol/audit.js";
|
|
3
4
|
import { type RepositoryScope } from "../protocol/operations.js";
|
|
@@ -24,4 +25,5 @@ export declare function auditContract(input: Readonly<{
|
|
|
24
25
|
contractId: ContractId;
|
|
25
26
|
input: AuditOptions;
|
|
26
27
|
composition?: AuditComposition;
|
|
28
|
+
observe?: ExecutionObserver;
|
|
27
29
|
}>): Promise<MutationResult<AuditReport>>;
|
|
@@ -11,6 +11,7 @@ export async function auditContract(input) {
|
|
|
11
11
|
return withContractExecution({
|
|
12
12
|
scope: input.scope,
|
|
13
13
|
contractId: input.contractId,
|
|
14
|
+
...(input.observe === undefined ? {} : { observe: input.observe }),
|
|
14
15
|
hooks: composition?.hooks ?? worktreeHooksOption(undefined),
|
|
15
16
|
...(input.input.signal === undefined ? {} : { signal: input.input.signal }),
|
|
16
17
|
}, "audit", async ({ scope, channel, progress }) => {
|
|
@@ -2,16 +2,17 @@ import { randomBytes } from "node:crypto";
|
|
|
2
2
|
import { decodeContractDocument } from "../body/decode.js";
|
|
3
3
|
import { contractIdFromSegment } from "../core/facts/types.js";
|
|
4
4
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
5
|
-
import {
|
|
5
|
+
import { mintIdentitySegment } from "../identity/mint.js";
|
|
6
|
+
import { fitIdentityStemWords, normalizeIdentityStem } from "../identity/normalize.js";
|
|
6
7
|
import { bindOperation } from "../protocol/bind.js";
|
|
7
8
|
import { stateOperation } from "../protocol/operations.js";
|
|
8
9
|
import { claimTaskHolder, claimTaskHolderWithFence } from "../settlement/holder.js";
|
|
9
10
|
import { KeiyakuRefused } from "./refusal.js";
|
|
10
11
|
import { contractTerms, documentDerivation } from "./input.js";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return
|
|
12
|
+
const CONTRACT_ID_CODE_POINTS = 32;
|
|
13
|
+
const CONTRACT_ID_ATTEMPTS = 4;
|
|
14
|
+
function drawContractSuffix() {
|
|
15
|
+
return randomBytes(2).toString("hex");
|
|
15
16
|
}
|
|
16
17
|
async function attempt(input, id) {
|
|
17
18
|
return bindOperation({
|
|
@@ -33,16 +34,17 @@ async function attempt(input, id) {
|
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
36
|
async function attemptCandidates(input) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
const stem = fitIdentityStemWords({
|
|
38
|
+
stem: normalizeIdentityStem({ source: input.title }) || "contract",
|
|
39
|
+
maxCodePoints: CONTRACT_ID_CODE_POINTS,
|
|
40
|
+
});
|
|
41
|
+
return await mintIdentitySegment({
|
|
42
|
+
stem,
|
|
43
|
+
attempts: CONTRACT_ID_ATTEMPTS,
|
|
44
|
+
drawSuffix: drawContractSuffix,
|
|
45
|
+
attempt: (segment) => attempt(input, contractIdFromSegment(segment)),
|
|
46
|
+
collision: (result) => result.kind === "refused" && result.refusal.kind === "contract-exists",
|
|
47
|
+
});
|
|
46
48
|
}
|
|
47
49
|
export async function admitBindWithAppointment(input) {
|
|
48
50
|
return await attemptCandidates(input);
|
|
@@ -86,7 +88,7 @@ export async function admitForkBindWithAppointment(input) {
|
|
|
86
88
|
throw error;
|
|
87
89
|
}
|
|
88
90
|
const markdown = sourceDocument.document.bytes.replace(/^\s*#\s*[^\r\n]*(?:\r?\n|$)/u, `# Fork · ${sourceDocument.title}${sourceDocument.document.bytes.includes("\r\n") ? "\r\n" : "\n"}`);
|
|
89
|
-
const document = decodeContractDocument(markdown);
|
|
91
|
+
const document = decodeContractDocument(markdown, { requireTimeout: true });
|
|
90
92
|
const terms = contractTerms(document, source.terms.gates, source.terms.after);
|
|
91
93
|
const admission = await attemptCandidates({
|
|
92
94
|
scope: input.scope,
|
|
@@ -90,6 +90,7 @@ export declare function composeLibrary(context?: ExecutionContext, composition?:
|
|
|
90
90
|
status: {
|
|
91
91
|
id: import("./keiyaku.js").AkuId;
|
|
92
92
|
life: "killed" | "hung" | "untidy" | "running" | "asleep" | "stranded";
|
|
93
|
+
allowed: import("./keiyaku.js").AllowedActions;
|
|
93
94
|
timeline: {
|
|
94
95
|
reportedChanges: readonly {
|
|
95
96
|
sequence: number;
|
|
@@ -20,7 +20,9 @@ type BindInput = Readonly<{
|
|
|
20
20
|
type BindResult<Handle> = Readonly<Omit<MutationResult<Handle>, "value"> & {
|
|
21
21
|
keiyaku: Handle;
|
|
22
22
|
workspace?: ContractWorkspaceLocation;
|
|
23
|
-
} & RegionObservation
|
|
23
|
+
} & RegionObservation & {
|
|
24
|
+
warnings?: readonly string[];
|
|
25
|
+
}>;
|
|
24
26
|
type HandleFactory<Handle> = (contractId: ContractId, scope: RepositoryScope) => Handle;
|
|
25
27
|
export declare function bindKeiyaku<Handle>(input: BindInput, createHandle: HandleFactory<Handle>): Promise<BindResult<Handle>>;
|
|
26
28
|
export declare function parseMarkdownBindDocument(markdown: string): import("../body/types.js").DecodedContractDocument;
|
|
@@ -7,10 +7,11 @@ import { completionInput, completeHolderMutation, completeMutation } from "./mut
|
|
|
7
7
|
import { reconcileLagScope } from "./reconcile.js";
|
|
8
8
|
import { requireAccepted } from "./refusal.js";
|
|
9
9
|
import { observeRegion } from "./region.js";
|
|
10
|
+
import { regionWarnings } from "../body/region.js";
|
|
10
11
|
import { scopeForRepo } from "./repo.js";
|
|
11
12
|
import { worktreeHooksOption } from "./configuration.js";
|
|
12
13
|
import { placeRegisterPath, readManagedWorktreeAppointment, } from "../workspace-place.js";
|
|
13
|
-
async function acceptedBindResult(result, region, scope, contractId) {
|
|
14
|
+
async function acceptedBindResult(result, region, scope, contractId, warnings = []) {
|
|
14
15
|
const { value: keiyaku, ...base } = result;
|
|
15
16
|
const appointment = await readManagedWorktreeAppointment(scope, contractId);
|
|
16
17
|
const registerPath = placeRegisterPath(scope);
|
|
@@ -34,6 +35,7 @@ async function acceptedBindResult(result, region, scope, contractId) {
|
|
|
34
35
|
pending: scopedAppointmentLag.length === 0
|
|
35
36
|
? base.pending
|
|
36
37
|
: [...base.pending, { surface: "reconciliation", required: true }],
|
|
38
|
+
...(warnings.length === 0 ? {} : { warnings }),
|
|
37
39
|
...region,
|
|
38
40
|
};
|
|
39
41
|
}
|
|
@@ -85,7 +87,7 @@ export async function bindKeiyaku(input, createHandle) {
|
|
|
85
87
|
return bindMarkdownFromValues(values, "targetless", createHandle);
|
|
86
88
|
}
|
|
87
89
|
export function parseMarkdownBindDocument(markdown) {
|
|
88
|
-
return decodeContractDocument(requireMarkdown(markdown));
|
|
90
|
+
return decodeContractDocument(requireMarkdown(markdown), { requireTimeout: true });
|
|
89
91
|
}
|
|
90
92
|
/** Internal CLI composition; not exported from the package root. */
|
|
91
93
|
export async function bindFromCli(input, createHandle) {
|
|
@@ -133,6 +135,6 @@ async function bindMarkdownFromValues(values, omittedTarget, createHandle) {
|
|
|
133
135
|
admission: admission.admission,
|
|
134
136
|
requireAccepted,
|
|
135
137
|
});
|
|
136
|
-
return await acceptedBindResult(result, await observeRegion(scope, channel, id, document.region), scope, id);
|
|
138
|
+
return await acceptedBindResult(result, await observeRegion(scope, channel, id, document.region), scope, id, regionWarnings(document.region));
|
|
137
139
|
});
|
|
138
140
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ExecutionObserver } from "../protocol/execution-observation.js";
|
|
1
2
|
import type { ActorId, ContractId } from "../core/facts/types.js";
|
|
2
3
|
import { type GitDecodeChannel } from "../git/read-observation.js";
|
|
3
4
|
import { type IntegrationConflictMaterialized } from "../protocol/deliver.js";
|
|
@@ -13,6 +14,7 @@ type CommonExecutionInput = Readonly<{
|
|
|
13
14
|
actor?: ActorId;
|
|
14
15
|
signal?: AbortSignal;
|
|
15
16
|
hooks: WorktreeHooks;
|
|
17
|
+
observe?: ExecutionObserver;
|
|
16
18
|
}>;
|
|
17
19
|
export type DeliveryExecutionInput = CommonExecutionInput & Readonly<{
|
|
18
20
|
message?: string;
|