@astrosheep/keiyaku 4.5.28 → 4.5.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/src/akuma/akuma-handle.d.ts +7 -0
- package/build/src/akuma/akuma-handle.js +19 -6
- package/build/src/akuma/akuma-instance.d.ts +0 -1
- package/build/src/akuma/akuma-instance.js +2 -4
- package/build/src/akuma/akuma-observe.js +0 -1
- package/build/src/akuma/akuma-product.d.ts +4 -8
- package/build/src/akuma/akuma-product.js +3 -20
- package/build/src/akuma/akuma.d.ts +0 -8
- package/build/src/akuma/akuma.js +0 -5
- package/build/src/akuma/archetype.d.ts +6 -6
- package/build/src/akuma/archetype.js +18 -28
- package/build/src/akuma/body.d.ts +4 -26
- package/build/src/akuma/body.js +18 -2
- package/build/src/akuma/call-initial-tell.d.ts +55 -0
- package/build/src/akuma/call-initial-tell.js +32 -0
- package/build/src/akuma/call-input.d.ts +0 -3
- package/build/src/akuma/call-input.js +0 -7
- package/build/src/akuma/call-request.d.ts +13 -10
- package/build/src/akuma/call-request.js +26 -14
- package/build/src/akuma/fleet-execution.d.ts +13 -1
- package/build/src/akuma/fleet-execution.js +67 -14
- package/build/src/akuma/fleet-observation.d.ts +26 -18
- package/build/src/akuma/fleet-observation.js +7 -1
- package/build/src/akuma/heart/facts.d.ts +2 -3
- package/build/src/akuma/heart/soul.js +1 -6
- package/build/src/akuma/projection-read.js +1 -2
- package/build/src/akuma/provider-recipe.d.ts +0 -10
- package/build/src/akuma/provider-recipe.js +0 -23
- package/build/src/akuma/provider.d.ts +1 -2
- package/build/src/akuma/providers/acp/index.js +0 -11
- package/build/src/akuma/providers/claude/index.js +2 -14
- package/build/src/akuma/providers/codex-app-server/index.js +0 -22
- package/build/src/akuma/providers/grok-build/index.js +0 -11
- package/build/src/akuma/providers/opencode-sdk/index.js +0 -10
- package/build/src/akuma/providers/pi/index.js +1 -5
- package/build/src/akuma/requests.d.ts +0 -1
- package/build/src/akuma/requests.js +0 -7
- package/build/src/akuma/turn-drive.d.ts +3 -0
- package/build/src/akuma/turn-drive.js +2 -2
- package/build/src/{library → cli}/catalog.d.ts +7 -30
- package/build/src/cli/catalog.js +1 -0
- package/build/src/cli/commands/akuma-invoke.d.ts +3 -3
- package/build/src/cli/commands/akuma-invoke.js +70 -97
- package/build/src/cli/commands/akuma.js +28 -21
- package/build/src/cli/commands/bind.js +4 -5
- package/build/src/cli/commands/contract-help.d.ts +21 -18
- package/build/src/cli/commands/contract-help.js +44 -84
- package/build/src/cli/commands/contract-invoke.js +6 -6
- package/build/src/cli/commands/contract.d.ts +1 -1
- package/build/src/cli/commands/contract.js +1 -6
- package/build/src/cli/commands/install.d.ts +1 -1
- package/build/src/cli/commands/install.js +1 -1
- package/build/src/cli/commands/nuke.js +2 -2
- package/build/src/cli/commands/task.js +48 -16
- package/build/src/cli/invoke.js +48 -11
- package/build/src/cli/parse.js +2 -0
- package/build/src/cli/render/akuma-activity.d.ts +42 -11
- package/build/src/cli/render/akuma-activity.js +307 -125
- package/build/src/cli/render/akuma-tool.d.ts +7 -1
- package/build/src/cli/render/akuma-tool.js +35 -23
- package/build/src/cli/render/akuma.d.ts +5 -9
- package/build/src/cli/render/akuma.js +68 -98
- package/build/src/cli/render/audit.js +2 -2
- package/build/src/cli/render/catalog.d.ts +1 -1
- package/build/src/cli/render/catalog.js +1 -0
- package/build/src/cli/render/contract.js +3 -3
- package/build/src/cli/render/kanshi.js +2 -2
- package/build/src/cli/render/receipt.js +4 -4
- package/build/src/cli/render/refusal.js +2 -2
- package/build/src/cli/render/settings.js +2 -2
- package/build/src/cli/render/task.js +2 -2
- package/build/src/cli/render/terminal.d.ts +5 -0
- package/build/src/cli/render/terminal.js +13 -0
- package/build/src/cli/result.d.ts +1 -1
- package/build/src/cli/runtime.js +10 -4
- package/build/src/cli/selectors.js +2 -2
- package/build/src/index.d.ts +1 -0
- package/build/src/index.js +1 -0
- package/build/src/library/akuma-creation.d.ts +28 -15
- package/build/src/library/akuma-creation.js +141 -107
- package/build/src/library/akumas.d.ts +42 -0
- package/build/src/library/akumas.js +61 -0
- package/build/src/library/composition.d.ts +14 -402
- package/build/src/library/composition.js +24 -25
- package/build/src/library/contract-handle.d.ts +7 -2
- package/build/src/library/contract-handle.js +14 -2
- package/build/src/library/contract-types.d.ts +9 -2
- package/build/src/library/contract.d.ts +8 -15
- package/build/src/library/contract.js +21 -39
- package/build/src/library/fleet.js +12 -12
- package/build/src/library/keiyaku.d.ts +8 -424
- package/build/src/library/keiyaku.js +3 -17
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/package.json +5 -1
- package/build/src/akuma/akuma-product-symbols.d.ts +0 -1
- package/build/src/akuma/akuma-product-symbols.js +0 -1
- package/build/src/library/catalog.js +0 -130
|
@@ -39,24 +39,14 @@ class ReceiptChannel {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
function admitClaudeOptions(options) {
|
|
42
|
-
if (options.sandbox === "full-access" && options.readonly === true) {
|
|
43
|
-
return { kind: "refused", diagnostic: "Claude full-access sandbox cannot combine with readonly" };
|
|
44
|
-
}
|
|
45
|
-
if (options.sandbox === "full-access" && options.network === "disabled") {
|
|
46
|
-
return { kind: "refused", diagnostic: "Claude full-access sandbox cannot combine with disabled network" };
|
|
47
|
-
}
|
|
48
42
|
if (options.network !== undefined) {
|
|
49
43
|
return { kind: "refused", diagnostic: "Claude provider does not support the network option" };
|
|
50
44
|
}
|
|
51
45
|
return {
|
|
52
46
|
kind: "admitted",
|
|
53
47
|
options: Object.freeze({ ...options }),
|
|
54
|
-
...(options.readonly === undefined ? {} : { readonly: { enforcement: "native" } }),
|
|
55
48
|
};
|
|
56
49
|
}
|
|
57
|
-
function permissionMode(readonly) {
|
|
58
|
-
return readonly === true ? "plan" : "bypassPermissions";
|
|
59
|
-
}
|
|
60
50
|
function claudeSessionId(coordinate) {
|
|
61
51
|
if (!("sessionId" in coordinate) || coordinate.sessionId === undefined) {
|
|
62
52
|
throw new Error("Claude resume requires sessionId");
|
|
@@ -64,7 +54,6 @@ function claudeSessionId(coordinate) {
|
|
|
64
54
|
return coordinate.sessionId;
|
|
65
55
|
}
|
|
66
56
|
function claudeQueryOptions(input, execution, abortController) {
|
|
67
|
-
const mode = permissionMode(input.options.readonly);
|
|
68
57
|
return {
|
|
69
58
|
...(execution.config ?? {}),
|
|
70
59
|
cwd: input.cwd,
|
|
@@ -72,10 +61,9 @@ function claudeQueryOptions(input, execution, abortController) {
|
|
|
72
61
|
...(input.requests === undefined ? {} : { additionalDirectories: [input.requests.dir] }),
|
|
73
62
|
...(execution.executable === undefined ? {} : { pathToClaudeCodeExecutable: execution.executable }),
|
|
74
63
|
env: akumaExecutionEnvironment(process.env, execution.env, input.requests?.dir),
|
|
75
|
-
permissionMode:
|
|
76
|
-
|
|
64
|
+
permissionMode: "bypassPermissions",
|
|
65
|
+
allowDangerouslySkipPermissions: true,
|
|
77
66
|
settingSources: ["user", "project", "local"],
|
|
78
|
-
...(input.options.sandbox === "full-access" ? { sandbox: { enabled: false } } : {}),
|
|
79
67
|
...(input.options.model === undefined ? {} : { model: input.options.model }),
|
|
80
68
|
...(input.options.effort === undefined ? {} : { effort: input.options.effort }),
|
|
81
69
|
...(input.options.systemPrompt === undefined || input.options.systemPrompt.length === 0
|
|
@@ -48,20 +48,6 @@ async function steerTurn(server, state, tell) {
|
|
|
48
48
|
throw new Error("codex app-server steer acknowledged a different turn");
|
|
49
49
|
return { kind: "accepted", fence: `${accepted}:${tell.id}` };
|
|
50
50
|
}
|
|
51
|
-
function sandbox(cwd, options, requests) {
|
|
52
|
-
if (options.sandbox === "full-access")
|
|
53
|
-
return { type: "dangerFullAccess" };
|
|
54
|
-
if (options.readonly === true) {
|
|
55
|
-
return { type: "readOnly", networkAccess: options.network === "enabled" };
|
|
56
|
-
}
|
|
57
|
-
return {
|
|
58
|
-
type: "workspaceWrite",
|
|
59
|
-
writableRoots: [cwd, ...(requests === undefined ? [] : [requests.dir])],
|
|
60
|
-
networkAccess: options.network === "enabled",
|
|
61
|
-
excludeTmpdirEnvVar: false,
|
|
62
|
-
excludeSlashTmp: false,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
51
|
async function admitTurn(server, input, state, events, config) {
|
|
66
52
|
await initialize(server);
|
|
67
53
|
const threadParams = {
|
|
@@ -97,7 +83,6 @@ async function admitTurn(server, input, state, events, config) {
|
|
|
97
83
|
...(input.options.model === undefined ? {} : { model: input.options.model }),
|
|
98
84
|
...(input.options.effort === undefined ? {} : { effort: input.options.effort }),
|
|
99
85
|
approvalPolicy: "never",
|
|
100
|
-
sandboxPolicy: sandbox(input.cwd, input.options, input.requests),
|
|
101
86
|
...(input.schemaJson === undefined ? {} : { outputSchema: JSON.parse(input.schemaJson) }),
|
|
102
87
|
}));
|
|
103
88
|
}
|
|
@@ -223,16 +208,9 @@ export function createCodexAppServerProvider(input = "codex") {
|
|
|
223
208
|
const execution = typeof input === "string" ? { name: "codex-app-server", kind: "codex-app-server", executable: input } : input;
|
|
224
209
|
return {
|
|
225
210
|
admitOptions(options) {
|
|
226
|
-
if (options.sandbox === "full-access" && options.readonly === true) {
|
|
227
|
-
return { kind: "refused", diagnostic: "Codex full-access sandbox cannot combine with readonly" };
|
|
228
|
-
}
|
|
229
|
-
if (options.sandbox === "full-access" && options.network === "disabled") {
|
|
230
|
-
return { kind: "refused", diagnostic: "Codex full-access sandbox cannot combine with disabled network" };
|
|
231
|
-
}
|
|
232
211
|
return {
|
|
233
212
|
kind: "admitted",
|
|
234
213
|
options: Object.freeze({ ...options }),
|
|
235
|
-
...(options.readonly === undefined ? {} : { readonly: { enforcement: "native" } }),
|
|
236
214
|
};
|
|
237
215
|
},
|
|
238
216
|
fork: (input) => createProviderAttempt(new AbortController().signal, async (custody) => await forkCodex(execution, input, custody)),
|
|
@@ -67,9 +67,6 @@ export const interpretGrokTool = (update) => {
|
|
|
67
67
|
fileChangeCall(name, input));
|
|
68
68
|
};
|
|
69
69
|
function optionAdmission(options) {
|
|
70
|
-
if (options.sandbox !== undefined) {
|
|
71
|
-
return { kind: "refused", diagnostic: "Grok Build does not support the sandbox option" };
|
|
72
|
-
}
|
|
73
70
|
if (options.network !== undefined) {
|
|
74
71
|
return { kind: "refused", diagnostic: "Grok Build does not support the network option" };
|
|
75
72
|
}
|
|
@@ -79,14 +76,6 @@ function optionAdmission(options) {
|
|
|
79
76
|
return {
|
|
80
77
|
kind: "admitted",
|
|
81
78
|
options,
|
|
82
|
-
...(options.readonly === undefined
|
|
83
|
-
? {}
|
|
84
|
-
: {
|
|
85
|
-
readonly: {
|
|
86
|
-
enforcement: "none",
|
|
87
|
-
diagnostic: "Grok Build cannot remove task-surface mutation capabilities",
|
|
88
|
-
},
|
|
89
|
-
}),
|
|
90
79
|
};
|
|
91
80
|
}
|
|
92
81
|
function grokSessionMeta(config, options) {
|
|
@@ -22,8 +22,6 @@ function opencodeSessionId(coordinateValue) {
|
|
|
22
22
|
return coordinateValue.sessionId;
|
|
23
23
|
}
|
|
24
24
|
function admit(options) {
|
|
25
|
-
if (options.sandbox !== undefined)
|
|
26
|
-
throw new Error("OpenCode does not support the sandbox option");
|
|
27
25
|
if (options.network !== undefined)
|
|
28
26
|
throw new Error("OpenCode does not support explicit network");
|
|
29
27
|
if (options.systemPromptMode === "replace") {
|
|
@@ -329,14 +327,6 @@ export function createOpencodeProvider(input = { name: OPENCODE_SDK_PROVIDER, ki
|
|
|
329
327
|
return {
|
|
330
328
|
kind: "admitted",
|
|
331
329
|
options: Object.freeze({ ...options }),
|
|
332
|
-
...(options.readonly === undefined
|
|
333
|
-
? {}
|
|
334
|
-
: {
|
|
335
|
-
readonly: {
|
|
336
|
-
enforcement: "none",
|
|
337
|
-
diagnostic: "OpenCode V1 cannot remove task-surface mutation capabilities",
|
|
338
|
-
},
|
|
339
|
-
}),
|
|
340
330
|
};
|
|
341
331
|
},
|
|
342
332
|
start: (input) => createProviderAttempt(input.signal, async (custody) => await drive(execution, { ...input, signal: custody.signal }, loader, custody)),
|
|
@@ -8,8 +8,6 @@ function diagnostic(error) {
|
|
|
8
8
|
return error instanceof Error ? error.message : String(error);
|
|
9
9
|
}
|
|
10
10
|
function admitPiOptions(options) {
|
|
11
|
-
if (options.sandbox !== undefined)
|
|
12
|
-
return { kind: "refused", diagnostic: "Pi provider does not support the sandbox option" };
|
|
13
11
|
if (options.network !== undefined)
|
|
14
12
|
return { kind: "refused", diagnostic: "Pi provider does not support the network option" };
|
|
15
13
|
if (options.model !== undefined && !MODEL_PATTERN.test(options.model)) {
|
|
@@ -21,7 +19,6 @@ function admitPiOptions(options) {
|
|
|
21
19
|
return {
|
|
22
20
|
kind: "admitted",
|
|
23
21
|
options: Object.freeze({ ...options }),
|
|
24
|
-
...(options.readonly === undefined ? {} : { readonly: { enforcement: "native" } }),
|
|
25
22
|
};
|
|
26
23
|
}
|
|
27
24
|
async function piCreateOptions(sdk, input) {
|
|
@@ -51,7 +48,7 @@ async function piCreateOptions(sdk, input) {
|
|
|
51
48
|
: (() => {
|
|
52
49
|
throw new Error("Pi resume requires sessionFile");
|
|
53
50
|
})();
|
|
54
|
-
const customTools = input.requests === undefined
|
|
51
|
+
const customTools = input.requests === undefined
|
|
55
52
|
? undefined
|
|
56
53
|
: [
|
|
57
54
|
sdk.createBashToolDefinition(input.cwd, {
|
|
@@ -67,7 +64,6 @@ async function piCreateOptions(sdk, input) {
|
|
|
67
64
|
...(model === undefined || modelRuntime === undefined ? {} : { model, modelRuntime }),
|
|
68
65
|
...(resourceLoader === undefined ? {} : { resourceLoader }),
|
|
69
66
|
...(input.options.effort === undefined ? {} : { thinkingLevel: input.options.effort }),
|
|
70
|
-
...(input.options.readonly === undefined ? {} : { tools: ["read", "grep", "find", "ls"] }),
|
|
71
67
|
...(customTools === undefined ? {} : { customTools }),
|
|
72
68
|
};
|
|
73
69
|
}
|
|
@@ -17,5 +17,4 @@ export declare function bodyRequestExecution(input: Readonly<{
|
|
|
17
17
|
}>): LibraryExecution;
|
|
18
18
|
/** Normalizes the public carrier before a composition captures its immutable channel. */
|
|
19
19
|
export declare function libraryExecution(value: unknown): LibraryExecution;
|
|
20
|
-
export declare function libraryExecutionInput(input: unknown): LibraryExecution;
|
|
21
20
|
export declare function executionChannel(context?: ExecutionContext): ExecutionChannel;
|
|
@@ -52,13 +52,6 @@ export function libraryExecution(value) {
|
|
|
52
52
|
}
|
|
53
53
|
throw new TypeError("execution channel must be local or body-request");
|
|
54
54
|
}
|
|
55
|
-
export function libraryExecutionInput(input) {
|
|
56
|
-
const value = valueRecord(input, "Keiyaku.withExecution input");
|
|
57
|
-
closed(value, ["execution"], "Keiyaku.withExecution input");
|
|
58
|
-
if (value.execution === undefined)
|
|
59
|
-
throw new TypeError("Keiyaku.withExecution input requires execution");
|
|
60
|
-
return libraryExecution(value.execution);
|
|
61
|
-
}
|
|
62
55
|
export function executionChannel(context) {
|
|
63
56
|
return context?.channel ?? LOCAL_CHANNEL;
|
|
64
57
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ResumeCoordinate, type Soul, type TellFact } from "./heart/index.js";
|
|
2
2
|
import type { AkumaPaths } from "./identity.js";
|
|
3
|
+
import type { CallInitialTellAdmission } from "./call-initial-tell.js";
|
|
4
|
+
import type { InitialTellAdmissionRequest } from "./call-request.js";
|
|
3
5
|
import { type ProviderAdapter, type TurnResult } from "./provider.js";
|
|
4
6
|
import { type AkumaCallRequestChildLaunch } from "./call-request.js";
|
|
5
7
|
import { type ErasedRequestCommand } from "./request-wire.js";
|
|
@@ -29,6 +31,7 @@ export type DriveTurnInput = Readonly<{
|
|
|
29
31
|
schemaJson?: string;
|
|
30
32
|
supervisor: BodySupervisor;
|
|
31
33
|
runtimeSpawn(launch: AkumaCallRequestChildLaunch): Promise<OwnedProcess | void>;
|
|
34
|
+
admitInitialTell(input: InitialTellAdmissionRequest): Promise<CallInitialTellAdmission>;
|
|
32
35
|
world: import("../world.js").WorldRoot;
|
|
33
36
|
externalCommands: Readonly<Record<string, ErasedRequestCommand>>;
|
|
34
37
|
now(): string;
|
|
@@ -87,8 +87,8 @@ async function startTurnDrive(input) {
|
|
|
87
87
|
boundAt: input.now(),
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
|
-
const { world, paths, soul: parent, runtimeSpawn: spawn, externalCommands } = input;
|
|
91
|
-
const commands = composeRequestCommands(akumaCallRequestCommands({ world, paths, parent, spawn }), externalCommands);
|
|
90
|
+
const { world, paths, soul: parent, runtimeSpawn: spawn, externalCommands, admitInitialTell } = input;
|
|
91
|
+
const commands = composeRequestCommands(akumaCallRequestCommands({ world, paths, parent, spawn, admitInitialTell }), externalCommands);
|
|
92
92
|
const requests = await BodyRequestPump.open({
|
|
93
93
|
paths: input.paths,
|
|
94
94
|
allowed: input.soul.allowed,
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { type ArchetypeCatalogRow } from "../akuma/archetype.js";
|
|
1
|
+
import type { AkumaList } from "../akuma/akuma.js";
|
|
2
|
+
import type { ArchetypeCatalogRow } from "../akuma/archetype.js";
|
|
4
3
|
import type { TaskRow } from "../task/index.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { type WorldRoot } from "../world.js";
|
|
4
|
+
import type { ContractRow } from "../library/contract.js";
|
|
5
|
+
import type { WorldRoot } from "../world.js";
|
|
8
6
|
export type CatalogQuery = Readonly<{
|
|
9
7
|
kind: "tasks";
|
|
10
8
|
namespace?: readonly string[];
|
|
@@ -14,33 +12,12 @@ export type CatalogQuery = Readonly<{
|
|
|
14
12
|
limit?: number;
|
|
15
13
|
}> | Readonly<{
|
|
16
14
|
kind: "archetypes";
|
|
15
|
+
limit?: number;
|
|
17
16
|
}> | Readonly<{
|
|
18
17
|
kind: "akuma";
|
|
19
18
|
archetype?: string;
|
|
20
19
|
limit?: number;
|
|
21
20
|
}>;
|
|
22
|
-
export type CatalogInput = Readonly<{
|
|
23
|
-
query: Extract<CatalogQuery, {
|
|
24
|
-
kind: "tasks";
|
|
25
|
-
}>;
|
|
26
|
-
path: WorldRoot;
|
|
27
|
-
}> | Readonly<{
|
|
28
|
-
query: Extract<CatalogQuery, {
|
|
29
|
-
kind: "contracts";
|
|
30
|
-
}>;
|
|
31
|
-
repo: Repo;
|
|
32
|
-
}> | Readonly<{
|
|
33
|
-
query: Extract<CatalogQuery, {
|
|
34
|
-
kind: "archetypes";
|
|
35
|
-
}>;
|
|
36
|
-
path?: WorldRoot;
|
|
37
|
-
home?: string;
|
|
38
|
-
}> | Readonly<{
|
|
39
|
-
query: Extract<CatalogQuery, {
|
|
40
|
-
kind: "akuma";
|
|
41
|
-
}>;
|
|
42
|
-
path: WorldRoot;
|
|
43
|
-
}>;
|
|
44
21
|
export type Catalog = Readonly<{
|
|
45
22
|
kind: "tasks";
|
|
46
23
|
root: WorldRoot;
|
|
@@ -51,11 +28,12 @@ export type Catalog = Readonly<{
|
|
|
51
28
|
root: string;
|
|
52
29
|
state: string | null;
|
|
53
30
|
observedAt: string;
|
|
54
|
-
rows:
|
|
31
|
+
rows: readonly ContractRow[];
|
|
55
32
|
hasMore: boolean;
|
|
56
33
|
}> | Readonly<{
|
|
57
34
|
kind: "archetypes";
|
|
58
35
|
rows: readonly ArchetypeCatalogRow[];
|
|
36
|
+
hasMore: boolean;
|
|
59
37
|
}> | Readonly<{
|
|
60
38
|
kind: "akuma";
|
|
61
39
|
root: WorldRoot;
|
|
@@ -65,4 +43,3 @@ export type Catalog = Readonly<{
|
|
|
65
43
|
searched: readonly string[];
|
|
66
44
|
hasMore: boolean;
|
|
67
45
|
}>;
|
|
68
|
-
export declare function listCatalog(input: CatalogInput): Promise<Catalog>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AkuId } from "../../akuma/identity.js";
|
|
2
2
|
import { type ActivityHistory } from "../../akuma/akuma.js";
|
|
3
|
-
import {
|
|
3
|
+
import { type AkumaInterruptResult, type AkumaKillResult, type AkumaHistoryResult, type AkumaObservation, type AkumaTellResult, type AkumaWaitResult, type CallResult, type ForkResult, type Keiyaku as KeiyakuContract, type Repo } from "../../index.js";
|
|
4
4
|
import { type WaitSelectedIdentity } from "../render/akuma-activity.js";
|
|
5
5
|
import type { Settings } from "../../settings.js";
|
|
6
6
|
import type { WorldRoot } from "../../world.js";
|
|
@@ -12,7 +12,6 @@ export type AkumaInvocationResult = Readonly<{
|
|
|
12
12
|
action: "call";
|
|
13
13
|
result: CallResult;
|
|
14
14
|
world: WorldRoot;
|
|
15
|
-
schemaAnswer?: unknown;
|
|
16
15
|
streamed?: boolean;
|
|
17
16
|
}> | Readonly<{
|
|
18
17
|
kind: "akuma";
|
|
@@ -50,11 +49,12 @@ export type AkumaInvocationResult = Readonly<{
|
|
|
50
49
|
result: AkumaTellWaitResult;
|
|
51
50
|
body: string;
|
|
52
51
|
alias?: string;
|
|
52
|
+
structured?: true;
|
|
53
53
|
}> | Readonly<{
|
|
54
54
|
kind: "akuma";
|
|
55
55
|
action: "tell";
|
|
56
56
|
mode: "interrupt";
|
|
57
|
-
result:
|
|
57
|
+
result: AkumaInterruptResult;
|
|
58
58
|
body: string;
|
|
59
59
|
alias?: string;
|
|
60
60
|
}> | Readonly<{
|
|
@@ -1,72 +1,36 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { squareAssignedParticipantName } from "@astrosheep/square";
|
|
3
3
|
import { emitInitiatingPluginSignal } from "../../plugin/akuma-signals.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { callObservationStream, waitObservationStream } from "../render/akuma-activity.js";
|
|
7
|
-
import { callObservationHead, tellWaitProgressStream } from "../render/akuma.js";
|
|
8
|
-
import {
|
|
4
|
+
import { decodeTellWaitObservation } from "../../akuma/fleet-execution.js";
|
|
5
|
+
import { Akumas, } from "../../index.js";
|
|
6
|
+
import { callObservationStream, inputWaitStream, waitObservationStream, } from "../render/akuma-activity.js";
|
|
7
|
+
import { callObservationHead, tellWaitProgressStream, waitedTellProgress } from "../render/akuma.js";
|
|
8
|
+
import { DEFAULT_CLI_COLUMNS } from "../render/terminal.js";
|
|
9
|
+
import { tellWaitAkuma, waitAkuma } from "../../library/fleet.js";
|
|
9
10
|
import { localExecutionContext } from "../../akuma/requests.js";
|
|
10
11
|
import { Akuma, Schema } from "../../akuma/index.js";
|
|
11
12
|
import { addressAkuma, resolveAkuma } from "../../library/address.js";
|
|
12
13
|
import { executionChannel } from "../../akuma/requests.js";
|
|
13
|
-
import { AkumaDecodeError } from "../../akuma/akuma-errors.js";
|
|
14
14
|
import { requestForwardedFleetTellAnswer } from "../../akuma/fleet-request.js";
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
function akumas(input) {
|
|
16
|
+
return Akumas.of(input.path, { execution: input.execution ?? localExecutionContext() });
|
|
17
|
+
}
|
|
17
18
|
function callSignalOption(signal) {
|
|
18
19
|
return signal === undefined ? {} : { signal };
|
|
19
20
|
}
|
|
20
|
-
function integrationFailure(error) {
|
|
21
|
-
return {
|
|
22
|
-
kind: error instanceof AuthorityCorruptionError ? "authority-corruption" : "infrastructure",
|
|
23
|
-
diagnostic: error instanceof Error ? error.message : String(error),
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
21
|
/** The display context the command result renders with, so live progress rows match the result. */
|
|
27
22
|
function resultContext() {
|
|
28
23
|
const tty = process.stderr.isTTY === true;
|
|
29
24
|
return {
|
|
30
|
-
columns: tty && Number.isInteger(process.stderr.columns) ? process.stderr.columns :
|
|
25
|
+
columns: tty && Number.isInteger(process.stderr.columns) ? process.stderr.columns : DEFAULT_CLI_COLUMNS,
|
|
31
26
|
color: tty && process.env.NO_COLOR === undefined,
|
|
32
27
|
};
|
|
33
28
|
}
|
|
34
29
|
function writeProgress(body) {
|
|
30
|
+
if (body.length === 0)
|
|
31
|
+
return;
|
|
35
32
|
process.stderr.write(body.endsWith("\n") ? body : `${body}\n`);
|
|
36
33
|
}
|
|
37
|
-
/**
|
|
38
|
-
* The live half of an observe-mode call: the resolved birth opens one identity
|
|
39
|
-
* frame (never the detached receipt's cwd row), each later observation prints
|
|
40
|
-
* the settled rows that arrived since the previous one, and the return appends
|
|
41
|
-
* one conclusion. The stream is append-only, so no final snapshot replays.
|
|
42
|
-
*/
|
|
43
|
-
async function observeCallUntilComplete(command, input, born) {
|
|
44
|
-
const stream = callObservationStream(resultContext(), callObservationHead(born));
|
|
45
|
-
try {
|
|
46
|
-
const observed = await observeAkumaStatus(input.path, born.akuma, {
|
|
47
|
-
timeoutMs: command.timeoutMs ?? CALL_TIMEOUT_MS,
|
|
48
|
-
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
49
|
-
observe: (observed) => {
|
|
50
|
-
const lines = stream.observe(observed);
|
|
51
|
-
if (lines.length > 0)
|
|
52
|
-
writeProgress(lines.join("\n"));
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
const conclusion = stream.conclude({ kind: "observed", reason: observed.reason, status: observed.status });
|
|
56
|
-
if (conclusion.length > 0)
|
|
57
|
-
writeProgress(conclusion);
|
|
58
|
-
return { kind: "observed", reason: observed.reason, status: observed.status };
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
if (input.signal?.aborted)
|
|
62
|
-
throw error;
|
|
63
|
-
const failure = integrationFailure(error);
|
|
64
|
-
const conclusion = stream.conclude({ kind: "failed", failure });
|
|
65
|
-
if (conclusion.length > 0)
|
|
66
|
-
writeProgress(conclusion);
|
|
67
|
-
return { kind: "failed", failure };
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
34
|
async function schemaFromFile(path) {
|
|
71
35
|
try {
|
|
72
36
|
const parsed = JSON.parse(await readFile(path, "utf8"));
|
|
@@ -166,30 +130,13 @@ async function inputInitiator(input) {
|
|
|
166
130
|
}
|
|
167
131
|
return { initiator };
|
|
168
132
|
}
|
|
169
|
-
function decodeWaitedTellSchema(result, schema) {
|
|
170
|
-
if (result.observation.reason !== "answered")
|
|
171
|
-
return result;
|
|
172
|
-
if (typeof result.observation.answer !== "string") {
|
|
173
|
-
throw new AkumaDecodeError("Answer is not valid JSON", String(result.observation.answer));
|
|
174
|
-
}
|
|
175
|
-
let parsed;
|
|
176
|
-
try {
|
|
177
|
-
parsed = JSON.parse(result.observation.answer);
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
throw new AkumaDecodeError(error instanceof Error ? error.message : "Answer is not valid JSON", result.observation.answer);
|
|
181
|
-
}
|
|
182
|
-
try {
|
|
183
|
-
return { ...result, observation: { reason: "answered", answer: schema.decode(parsed) } };
|
|
184
|
-
}
|
|
185
|
-
catch (error) {
|
|
186
|
-
throw new AkumaDecodeError(error instanceof Error ? error.message : "Answer failed schema decode", result.observation.answer);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
133
|
async function invokeWaitedTell(command, input, body) {
|
|
190
134
|
const schema = command.schema === undefined ? undefined : await schemaFromFile(command.schema);
|
|
191
135
|
const alias = inputAlias(command.akuma);
|
|
192
|
-
const
|
|
136
|
+
const channel = executionChannel(input.execution);
|
|
137
|
+
const progress = command.output === "text" && channel.kind === "local"
|
|
138
|
+
? tellWaitProgressStream(undefined, alias, resultContext())
|
|
139
|
+
: undefined;
|
|
193
140
|
const result = await tellWaitAkuma({
|
|
194
141
|
...(await inputInitiator(input)),
|
|
195
142
|
path: input.path,
|
|
@@ -209,9 +156,11 @@ async function invokeWaitedTell(command, input, body) {
|
|
|
209
156
|
},
|
|
210
157
|
}),
|
|
211
158
|
}, input.execution ?? localExecutionContext());
|
|
212
|
-
const rendered = schema === undefined ? result :
|
|
159
|
+
const rendered = schema === undefined ? result : { ...result, observation: decodeTellWaitObservation(result.observation, schema) };
|
|
213
160
|
if (progress !== undefined)
|
|
214
161
|
writeProgress(progress.conclude(rendered).join("\n"));
|
|
162
|
+
else if (command.output === "text" && channel.kind === "body-request")
|
|
163
|
+
writeProgress(waitedTellProgress(rendered, alias, resultContext()));
|
|
215
164
|
return {
|
|
216
165
|
kind: "akuma",
|
|
217
166
|
action: "tell",
|
|
@@ -219,6 +168,7 @@ async function invokeWaitedTell(command, input, body) {
|
|
|
219
168
|
result: rendered,
|
|
220
169
|
body,
|
|
221
170
|
...(alias === undefined ? {} : { alias }),
|
|
171
|
+
...(schema === undefined ? {} : { structured: true }),
|
|
222
172
|
};
|
|
223
173
|
}
|
|
224
174
|
async function invokeTell(command, input) {
|
|
@@ -265,9 +215,8 @@ async function invokeTell(command, input) {
|
|
|
265
215
|
}
|
|
266
216
|
const initiator = await inputInitiator(input);
|
|
267
217
|
if (command.interrupt) {
|
|
268
|
-
const result = await
|
|
218
|
+
const result = await akumas(input).interrupt({
|
|
269
219
|
...initiator,
|
|
270
|
-
path: input.path,
|
|
271
220
|
akuma: command.akuma,
|
|
272
221
|
body,
|
|
273
222
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
@@ -283,20 +232,18 @@ async function invokeTell(command, input) {
|
|
|
283
232
|
...(alias === undefined ? {} : { alias }),
|
|
284
233
|
};
|
|
285
234
|
}
|
|
286
|
-
const result = await
|
|
235
|
+
const result = await akumas(input).tell({
|
|
287
236
|
...initiator,
|
|
288
|
-
path: input.path,
|
|
289
237
|
akuma: command.akuma,
|
|
290
238
|
body,
|
|
291
239
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
292
240
|
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
293
|
-
}
|
|
241
|
+
});
|
|
294
242
|
const alias = inputAlias(command.akuma);
|
|
295
243
|
return { kind: "akuma", action: "tell", mode: "ordinary", result, body, ...(alias === undefined ? {} : { alias }) };
|
|
296
244
|
}
|
|
297
245
|
async function invokeHistory(command, input) {
|
|
298
|
-
const result = await
|
|
299
|
-
path: input.path,
|
|
246
|
+
const result = await akumas(input).history({
|
|
300
247
|
akuma: command.akuma,
|
|
301
248
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
302
249
|
...(command.before === undefined ? {} : { before: command.before }),
|
|
@@ -324,8 +271,7 @@ async function invokeFork(command, input) {
|
|
|
324
271
|
return {
|
|
325
272
|
kind: "akuma",
|
|
326
273
|
action: "fork",
|
|
327
|
-
receipt: await
|
|
328
|
-
path: input.path,
|
|
274
|
+
receipt: await akumas(input).fork({
|
|
329
275
|
akuma: command.akuma,
|
|
330
276
|
at: command.at,
|
|
331
277
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
@@ -337,12 +283,11 @@ async function invokeKill(command, input) {
|
|
|
337
283
|
return {
|
|
338
284
|
kind: "akuma",
|
|
339
285
|
action: "kill",
|
|
340
|
-
result: await
|
|
341
|
-
path: input.path,
|
|
286
|
+
result: await akumas(input).kill({
|
|
342
287
|
akuma: command.akuma,
|
|
343
288
|
...(input.repo === undefined ? {} : { repo: input.repo }),
|
|
344
289
|
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
345
|
-
}
|
|
290
|
+
}),
|
|
346
291
|
...(alias === undefined ? {} : { alias }),
|
|
347
292
|
};
|
|
348
293
|
}
|
|
@@ -351,10 +296,9 @@ export async function invokeAkuma(command, input) {
|
|
|
351
296
|
case "call": {
|
|
352
297
|
const body = await promptBody(command, input);
|
|
353
298
|
const schema = command.schema === undefined ? undefined : await schemaFromFile(command.schema);
|
|
354
|
-
const caller =
|
|
299
|
+
const caller = akumas(input);
|
|
355
300
|
const request = {
|
|
356
301
|
...(await inputInitiator(input)),
|
|
357
|
-
path: input.path,
|
|
358
302
|
archetype: command.archetype,
|
|
359
303
|
body,
|
|
360
304
|
...(input.home === undefined ? {} : { home: input.home }),
|
|
@@ -366,19 +310,48 @@ export async function invokeAkuma(command, input) {
|
|
|
366
310
|
...(schema === undefined ? {} : { schema }),
|
|
367
311
|
...callSignalOption(input.signal),
|
|
368
312
|
};
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
313
|
+
let stream;
|
|
314
|
+
const observing = command.mode === "wait" && command.output === "text";
|
|
315
|
+
const observe = observing
|
|
316
|
+
? {
|
|
317
|
+
admitted: (tell, id, head) => {
|
|
318
|
+
stream = callObservationStream(resultContext(), callObservationHead({ akuma: id, ...head }), {
|
|
319
|
+
admittedAt: tell.row.at,
|
|
320
|
+
});
|
|
321
|
+
},
|
|
322
|
+
observe: (observation) => {
|
|
323
|
+
const lines = stream?.observe(observation) ?? [];
|
|
324
|
+
if (lines.length > 0)
|
|
325
|
+
writeProgress(lines.join("\n"));
|
|
326
|
+
},
|
|
327
|
+
}
|
|
328
|
+
: undefined;
|
|
329
|
+
const result = await caller.call({
|
|
330
|
+
...request,
|
|
331
|
+
mode: command.mode,
|
|
332
|
+
...(command.timeoutMs === undefined ? {} : { timeoutMs: command.timeoutMs }),
|
|
333
|
+
...(observe === undefined ? {} : { observe }),
|
|
334
|
+
});
|
|
335
|
+
let streamed = stream !== undefined;
|
|
336
|
+
if (stream !== undefined) {
|
|
337
|
+
writeProgress(stream.conclude(result.observation));
|
|
380
338
|
}
|
|
381
|
-
|
|
339
|
+
else if (observing && result.observation.kind === "failed") {
|
|
340
|
+
const fallback = inputWaitStream(resultContext(), () => callObservationHead({
|
|
341
|
+
akuma: result.akuma,
|
|
342
|
+
dispatch: result.dispatch,
|
|
343
|
+
alias: result.alias,
|
|
344
|
+
}), { cursor: "empty", answerSeparator: true });
|
|
345
|
+
writeProgress(fallback.conclude({ kind: "failed", diagnostic: result.observation.failure.diagnostic }));
|
|
346
|
+
streamed = true;
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
kind: "akuma",
|
|
350
|
+
action: "call",
|
|
351
|
+
result,
|
|
352
|
+
world: input.path,
|
|
353
|
+
...(streamed ? { streamed: true } : {}),
|
|
354
|
+
};
|
|
382
355
|
}
|
|
383
356
|
case "wait":
|
|
384
357
|
return await invokeWait(command, input);
|
|
@@ -396,7 +369,7 @@ export async function invokeAkumaStatus(path, akuma, alias, repo) {
|
|
|
396
369
|
return {
|
|
397
370
|
kind: "akuma",
|
|
398
371
|
action: "status",
|
|
399
|
-
status: await
|
|
372
|
+
status: await Akumas.of(path).status({ akuma, ...(repo === undefined ? {} : { repo }) }),
|
|
400
373
|
...(alias === undefined ? {} : { alias }),
|
|
401
374
|
};
|
|
402
375
|
}
|