@astrosheep/keiyaku 4.6.19 → 4.6.20
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 +7 -3
- package/build/plugins/pi/README.md +111 -0
- package/build/plugins/pi/akuma-tools.ts +310 -0
- package/build/plugins/pi/keiyaku.ts +2 -0
- package/build/src/akuma/akuma-call.d.ts +4 -1
- package/build/src/akuma/akuma-call.js +24 -7
- package/build/src/akuma/akuma-instance.d.ts +28 -8
- package/build/src/akuma/akuma-instance.js +85 -42
- package/build/src/akuma/akuma-owner.d.ts +18 -9
- package/build/src/akuma/akuma-owner.js +31 -25
- package/build/src/akuma/akuma-selection-execution.d.ts +4 -1
- package/build/src/akuma/akuma-selection-execution.js +8 -4
- package/build/src/akuma/akuma.d.ts +17 -0
- package/build/src/akuma/body-launch.d.ts +107 -0
- package/build/src/akuma/body-launch.js +57 -0
- package/build/src/akuma/body-supervisor.d.ts +7 -6
- package/build/src/akuma/body-supervisor.js +17 -12
- package/build/src/akuma/body.d.ts +13 -94
- package/build/src/akuma/body.js +124 -296
- package/build/src/akuma/call-input.d.ts +2 -0
- package/build/src/akuma/call-input.js +21 -1
- package/build/src/akuma/call-request.d.ts +6 -2
- package/build/src/akuma/call-request.js +9 -1
- package/build/src/akuma/detached-body.d.ts +9 -0
- package/build/src/akuma/detached-body.js +94 -0
- package/build/src/akuma/execution-instructions.d.ts +8 -0
- package/build/src/akuma/execution-instructions.js +17 -0
- package/build/src/akuma/heart/facts.d.ts +21 -1
- package/build/src/akuma/heart/facts.js +10 -0
- package/build/src/akuma/heart/index.d.ts +16 -1
- package/build/src/akuma/heart/index.js +95 -30
- package/build/src/akuma/heart/rows.d.ts +14 -2
- package/build/src/akuma/heart/rows.js +48 -4
- package/build/src/akuma/heart/schema.d.ts +4 -1
- package/build/src/akuma/heart/schema.js +87 -30
- package/build/src/akuma/heart/soul.js +4 -0
- package/build/src/akuma/heart/storage.d.ts +1 -0
- package/build/src/akuma/heart/storage.js +59 -15
- package/build/src/akuma/heart/timeline.d.ts +6 -4
- package/build/src/akuma/heart/timeline.js +14 -4
- package/build/src/akuma/in-process-body.d.ts +5 -0
- package/build/src/akuma/in-process-body.js +57 -0
- package/build/src/akuma/index.d.ts +1 -1
- package/build/src/akuma/projection.d.ts +44 -1
- package/build/src/akuma/projection.js +13 -1
- package/build/src/akuma/provider.d.ts +4 -0
- package/build/src/akuma/providers/acp/core.js +1 -1
- package/build/src/akuma/providers/acp/index.js +3 -0
- package/build/src/akuma/providers/claude/index.js +8 -5
- package/build/src/akuma/providers/codex-app-server/configuration.d.ts +5 -0
- package/build/src/akuma/providers/codex-app-server/configuration.js +72 -0
- package/build/src/akuma/providers/codex-app-server/index.js +7 -10
- package/build/src/akuma/providers/execution-environment.d.ts +8 -2
- package/build/src/akuma/providers/execution-environment.js +10 -1
- package/build/src/akuma/providers/grok-build/index.js +23 -16
- package/build/src/akuma/providers/index.d.ts +1 -0
- package/build/src/akuma/providers/index.js +8 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +9 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +6 -0
- package/build/src/akuma/providers/opencode-sdk/session.js +4 -3
- package/build/src/akuma/providers/paseo/index.js +8 -2
- package/build/src/akuma/providers/pi/index.js +27 -10
- package/build/src/akuma/publication.d.ts +4 -3
- package/build/src/akuma/publication.js +21 -18
- package/build/src/akuma/selection-observation.d.ts +51 -0
- package/build/src/akuma/selection-owner-port.d.ts +2 -1
- package/build/src/akuma/selection-owner-port.js +4 -3
- package/build/src/akuma/turn-drive.d.ts +4 -2
- package/build/src/akuma/turn-drive.js +58 -21
- package/build/src/akuma-body.d.ts +0 -10
- package/build/src/akuma-body.js +13 -118
- package/build/src/body-host.d.ts +28 -0
- package/build/src/body-host.js +86 -0
- package/build/src/body-requests.d.ts +13 -0
- package/build/src/body-requests.js +131 -0
- package/build/src/cli/commands/akuma-grammar.d.ts +8 -1
- package/build/src/cli/commands/akuma-grammar.js +36 -6
- package/build/src/cli/commands/akuma.js +11 -0
- package/build/src/cli/commands/report.d.ts +6 -0
- package/build/src/cli/commands/report.js +31 -0
- package/build/src/cli/parse.js +1 -0
- package/build/src/cli/render/akuma-activity.js +27 -17
- package/build/src/cli/render/terminal.d.ts +5 -0
- package/build/src/cli/render/terminal.js +7 -0
- package/build/src/cli/runtime.js +4 -1
- package/build/src/index.d.ts +3 -1
- package/build/src/index.js +1 -0
- package/build/src/library/akuma-creation.d.ts +7 -3
- package/build/src/library/akuma-creation.js +23 -11
- package/build/src/library/akumas.d.ts +4 -1
- package/build/src/library/akumas.js +13 -5
- package/build/src/library/selection.d.ts +2 -1
- package/build/src/library/selection.js +6 -3
- package/build/src/plugin/public.d.ts +11 -0
- package/build/src/plugin/runtime.js +1 -0
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/package.json +2 -2
- package/plugins/paseo/plugin/server/keiyaku.ts +1 -0
- package/plugins/paseo/plugin/server/mirror.ts +2 -2
- package/plugins/pi/README.md +111 -0
- package/plugins/pi/akuma-tools.ts +310 -0
- package/plugins/pi/keiyaku.ts +2 -0
|
@@ -1,24 +1,15 @@
|
|
|
1
|
-
import { outcomePluginObserver, stderrPluginDiagnostic, withAkumaWaitDeferrals } from "../plugin/akuma-signals.js";
|
|
1
|
+
import { emitPluginSignal, outcomePluginObserver, stderrPluginDiagnostic, withAkumaWaitDeferrals, } from "../plugin/akuma-signals.js";
|
|
2
2
|
import { abortable } from "./abort.js";
|
|
3
3
|
import { admitAkumaCall } from "./akuma-call.js";
|
|
4
4
|
import { defaultWaitComplete } from "./akuma-observe.js";
|
|
5
5
|
import { AkumaOwner } from "./akuma-owner.js";
|
|
6
6
|
import { decodeAskObservation, executeAskAkuma, executeTellAkuma } from "./akuma-selection-execution.js";
|
|
7
|
+
import { captureAkumaHost } from "../body-host.js";
|
|
7
8
|
import { parseAkuId } from "./identity.js";
|
|
8
9
|
import { schemaFromStandard, schemaJsonText } from "./schema.js";
|
|
9
10
|
/** Capture the observer capability, not the caller's mutable options object. */
|
|
10
11
|
export function captureAkumaHostDiagnostic(host) {
|
|
11
|
-
|
|
12
|
-
return undefined;
|
|
13
|
-
if (typeof host !== "object" || host === null || Array.isArray(host))
|
|
14
|
-
throw new TypeError("Akuma host options must be an object");
|
|
15
|
-
const unknown = Object.keys(host).find((key) => key !== "reportDiagnostic");
|
|
16
|
-
if (unknown !== undefined)
|
|
17
|
-
throw new TypeError(`Akuma host options has unknown field: ${unknown}`);
|
|
18
|
-
const reportDiagnostic = host.reportDiagnostic;
|
|
19
|
-
if (reportDiagnostic !== undefined && typeof reportDiagnostic !== "function")
|
|
20
|
-
throw new TypeError("Akuma host reportDiagnostic must be a function");
|
|
21
|
-
return reportDiagnostic;
|
|
12
|
+
return captureAkumaHost(host).reportDiagnostic;
|
|
22
13
|
}
|
|
23
14
|
function signalOption(value) {
|
|
24
15
|
if (value === undefined)
|
|
@@ -27,46 +18,21 @@ function signalOption(value) {
|
|
|
27
18
|
throw new TypeError("signal must be an AbortSignal");
|
|
28
19
|
return value;
|
|
29
20
|
}
|
|
30
|
-
|
|
21
|
+
class AkumaHandle {
|
|
31
22
|
id;
|
|
32
23
|
root;
|
|
33
24
|
reportDiagnostic;
|
|
34
|
-
|
|
25
|
+
spawn;
|
|
26
|
+
constructor(id, root, reportDiagnostic, spawn) {
|
|
35
27
|
this.id = id;
|
|
36
28
|
this.root = root;
|
|
37
29
|
this.reportDiagnostic = reportDiagnostic;
|
|
30
|
+
this.spawn = spawn;
|
|
38
31
|
Object.freeze(this);
|
|
39
32
|
}
|
|
40
33
|
owner(observing = false) {
|
|
41
34
|
return new AkumaOwner(this.id, this.root, observing ? outcomePluginObserver({ world: this.root, reportDiagnostic: this.reportDiagnostic }) : undefined);
|
|
42
35
|
}
|
|
43
|
-
static async birth(archetype, input) {
|
|
44
|
-
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
45
|
-
throw new TypeError("Akuma birth input must be an object");
|
|
46
|
-
}
|
|
47
|
-
if (typeof input.root !== "string")
|
|
48
|
-
throw new TypeError("Akuma birth root must be a WorldRoot");
|
|
49
|
-
const reportDiagnostic = captureAkumaHostDiagnostic(input.host) ?? stderrPluginDiagnostic;
|
|
50
|
-
const admitted = await admitAkumaCall(input.root, {
|
|
51
|
-
...(input.home === undefined ? {} : { home: input.home }),
|
|
52
|
-
...(input.settings === undefined ? {} : { settings: input.settings }),
|
|
53
|
-
}, {
|
|
54
|
-
archetype,
|
|
55
|
-
...(input.cwd === undefined ? {} : { cwd: input.cwd }),
|
|
56
|
-
...(input.allowed === undefined ? {} : { allowed: input.allowed }),
|
|
57
|
-
...(input.caller === undefined ? {} : { caller: input.caller }),
|
|
58
|
-
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
59
|
-
}, {});
|
|
60
|
-
if (admitted.failure !== undefined)
|
|
61
|
-
throw admitted.failure;
|
|
62
|
-
return new Akuma(admitted.id, input.root, reportDiagnostic);
|
|
63
|
-
}
|
|
64
|
-
static select(root, selector, host) {
|
|
65
|
-
if (typeof root !== "string")
|
|
66
|
-
throw new TypeError("Akuma.select root must be a WorldRoot");
|
|
67
|
-
const reportDiagnostic = captureAkumaHostDiagnostic(host) ?? stderrPluginDiagnostic;
|
|
68
|
-
return new Akuma(parseAkuId(selector).id, root, reportDiagnostic);
|
|
69
|
-
}
|
|
70
36
|
async tell(text, options = {}) {
|
|
71
37
|
if (typeof text !== "string")
|
|
72
38
|
throw new TypeError("Akuma tell text must be a string");
|
|
@@ -80,6 +46,7 @@ export class Akuma {
|
|
|
80
46
|
const signal = signalOption(options.signal);
|
|
81
47
|
signal?.throwIfAborted();
|
|
82
48
|
return await executeTellAkuma({
|
|
49
|
+
spawn: this.spawn,
|
|
83
50
|
path: this.root,
|
|
84
51
|
id: this.id,
|
|
85
52
|
body: text,
|
|
@@ -103,6 +70,7 @@ export class Akuma {
|
|
|
103
70
|
signal?.throwIfAborted();
|
|
104
71
|
const schema = options.schema === undefined ? undefined : schemaFromStandard(options.schema);
|
|
105
72
|
const result = await executeAskAkuma({
|
|
73
|
+
spawn: this.spawn,
|
|
106
74
|
path: this.root,
|
|
107
75
|
id: this.id,
|
|
108
76
|
outcomeObserved: outcomePluginObserver({ world: this.root, reportDiagnostic: this.reportDiagnostic }),
|
|
@@ -115,6 +83,40 @@ export class Akuma {
|
|
|
115
83
|
});
|
|
116
84
|
return (schema === undefined ? result : { ...result, observation: decodeAskObservation(result.observation, schema) });
|
|
117
85
|
}
|
|
86
|
+
async report(text, options) {
|
|
87
|
+
if (typeof text !== "string" || text.trim() === "")
|
|
88
|
+
throw new TypeError("Akuma report text must be nonblank");
|
|
89
|
+
if (typeof options !== "object" || options === null || Array.isArray(options))
|
|
90
|
+
throw new TypeError("Akuma report requires exact execution options");
|
|
91
|
+
const unknown = Object.keys(options).find((key) => !["bodySequence", "turnSequence", "signal"].includes(key));
|
|
92
|
+
if (unknown !== undefined)
|
|
93
|
+
throw new TypeError(`Akuma report options has unknown field: ${unknown}`);
|
|
94
|
+
for (const key of ["bodySequence", "turnSequence"]) {
|
|
95
|
+
if (!Number.isSafeInteger(options[key]) || options[key] <= 0)
|
|
96
|
+
throw new TypeError(`Akuma report ${key} must be a positive safe integer`);
|
|
97
|
+
}
|
|
98
|
+
const signal = signalOption(options.signal);
|
|
99
|
+
const result = await this.owner().report({
|
|
100
|
+
bodySequence: options.bodySequence,
|
|
101
|
+
turnSequence: options.turnSequence,
|
|
102
|
+
text,
|
|
103
|
+
at: new Date().toISOString(),
|
|
104
|
+
}, signal);
|
|
105
|
+
if (result.kind !== "recorded")
|
|
106
|
+
return result;
|
|
107
|
+
const { report, initiator } = result;
|
|
108
|
+
await emitPluginSignal({ world: this.root, reportDiagnostic: this.reportDiagnostic }, {
|
|
109
|
+
kind: "akuma.reported",
|
|
110
|
+
akumaId: this.id,
|
|
111
|
+
bodySequence: report.bodySequence,
|
|
112
|
+
turnSequence: report.turnSequence,
|
|
113
|
+
reportSequence: report.sequence,
|
|
114
|
+
text: report.text,
|
|
115
|
+
at: report.at,
|
|
116
|
+
...(initiator === undefined ? {} : { initiator }),
|
|
117
|
+
});
|
|
118
|
+
return { kind: "recorded", report };
|
|
119
|
+
}
|
|
118
120
|
async status() {
|
|
119
121
|
return await this.owner(true).status();
|
|
120
122
|
}
|
|
@@ -169,6 +171,47 @@ export class Akuma {
|
|
|
169
171
|
}
|
|
170
172
|
const signal = signalOption(options.signal);
|
|
171
173
|
signal?.throwIfAborted();
|
|
172
|
-
return await abortable(this.owner().kill(signal === undefined ? {} : { signal }), signal ?? new AbortController().signal);
|
|
174
|
+
return await abortable(this.owner().kill(this.spawn, signal === undefined ? {} : { signal }), signal ?? new AbortController().signal);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export class Akuma extends AkumaHandle {
|
|
178
|
+
constructor(id, root, reportDiagnostic, spawn) {
|
|
179
|
+
super(id, root, reportDiagnostic, spawn);
|
|
173
180
|
}
|
|
181
|
+
static async birth(archetype, input) {
|
|
182
|
+
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
183
|
+
throw new TypeError("Akuma birth input must be an object");
|
|
184
|
+
}
|
|
185
|
+
if (typeof input.root !== "string")
|
|
186
|
+
throw new TypeError("Akuma birth root must be a WorldRoot");
|
|
187
|
+
const { spawn, reportDiagnostic = stderrPluginDiagnostic } = captureAkumaHost(input.host);
|
|
188
|
+
const admitted = await admitAkumaCall(input.root, {
|
|
189
|
+
...(input.home === undefined ? {} : { home: input.home }),
|
|
190
|
+
...(input.settings === undefined ? {} : { settings: input.settings }),
|
|
191
|
+
}, {
|
|
192
|
+
archetype,
|
|
193
|
+
...(input.cwd === undefined ? {} : { cwd: input.cwd }),
|
|
194
|
+
...(input.allowed === undefined ? {} : { allowed: input.allowed }),
|
|
195
|
+
...(input.writableDirectories === undefined ? {} : { writableDirectories: input.writableDirectories }),
|
|
196
|
+
...(input.bare === undefined ? {} : { bare: input.bare }),
|
|
197
|
+
...(input.caller === undefined ? {} : { caller: input.caller }),
|
|
198
|
+
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
199
|
+
}, {}, spawn);
|
|
200
|
+
if (admitted.failure !== undefined)
|
|
201
|
+
throw admitted.failure;
|
|
202
|
+
return new Akuma(admitted.id, input.root, reportDiagnostic, spawn);
|
|
203
|
+
}
|
|
204
|
+
static select(root, selector, host) {
|
|
205
|
+
if (typeof root !== "string")
|
|
206
|
+
throw new TypeError("Akuma.select root must be a WorldRoot");
|
|
207
|
+
const { spawn, reportDiagnostic = stderrPluginDiagnostic } = captureAkumaHost(host);
|
|
208
|
+
return new Akuma(parseAkuId(selector).id, root, reportDiagnostic, spawn);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/** Internal product composition; hosting is captured independently of public operation inputs. */
|
|
212
|
+
export function akumaWithLauncher(root, selector, spawn, host) {
|
|
213
|
+
if (typeof root !== "string")
|
|
214
|
+
throw new TypeError("Akuma.select root must be a WorldRoot");
|
|
215
|
+
const reportDiagnostic = captureAkumaHostDiagnostic(host) ?? stderrPluginDiagnostic;
|
|
216
|
+
return new AkumaHandle(parseAkuId(selector).id, root, reportDiagnostic, spawn);
|
|
174
217
|
}
|
|
@@ -3,10 +3,12 @@ import type { WorldRoot } from "../world.js";
|
|
|
3
3
|
import { type OutcomeObserver, type LiveStatusObservation, type WaitReason } from "./akuma-observe.js";
|
|
4
4
|
import { type AkumaStreamSnapshot } from "./akuma-stream.js";
|
|
5
5
|
import type { AkumaStatus } from "./akuma.js";
|
|
6
|
+
import type { BodyLauncher } from "./body-launch.js";
|
|
6
7
|
import { type TellResult, type TellWakeRuntime } from "./body.js";
|
|
7
8
|
import { type CallInitialTell, type CallInitialTellAdmission } from "./call-initial-tell.js";
|
|
8
9
|
import { HeldAkumaLeash, type InterruptTellAdmission, type KillEvidence, type ResumeCoordinate, type TellFact, type TurnOutcome } from "./heart/index.js";
|
|
9
10
|
import { type AkuId, type AkumaPaths } from "./identity.js";
|
|
11
|
+
import type { ReportAdmission } from "./heart/facts.js";
|
|
10
12
|
import type { ActivityHistory, ExactHistory } from "./projection.js";
|
|
11
13
|
export type InterruptReceipt = TellResult | Extract<InterruptTellAdmission, {
|
|
12
14
|
kind: "unavailable";
|
|
@@ -68,6 +70,12 @@ export declare class AkumaOwner {
|
|
|
68
70
|
private get paths();
|
|
69
71
|
private projectHistoryTurns;
|
|
70
72
|
private exactHistory;
|
|
73
|
+
report(input: Readonly<{
|
|
74
|
+
bodySequence: number;
|
|
75
|
+
turnSequence: number;
|
|
76
|
+
text: string;
|
|
77
|
+
at: string;
|
|
78
|
+
}>, signal?: AbortSignal): Promise<ReportAdmission>;
|
|
71
79
|
status(): Promise<AkumaStatus>;
|
|
72
80
|
history(input?: Readonly<{
|
|
73
81
|
id?: string;
|
|
@@ -94,11 +102,11 @@ export declare class AkumaOwner {
|
|
|
94
102
|
timeoutMs?: number;
|
|
95
103
|
signal?: AbortSignal;
|
|
96
104
|
}>): Promise<AkumaStatus>;
|
|
97
|
-
admitInitialTell(initialTell: CallInitialTell, options
|
|
105
|
+
admitInitialTell(initialTell: CallInitialTell, options: Readonly<{
|
|
98
106
|
signal?: AbortSignal;
|
|
99
|
-
runtime
|
|
107
|
+
runtime: TellWakeRuntime;
|
|
100
108
|
}>): Promise<InitialTellAdmission>;
|
|
101
|
-
tell(body: string, tellId
|
|
109
|
+
tell(body: string, tellId: string | undefined, recordedAt: string | undefined, runtime: TellWakeRuntime, options?: Readonly<{
|
|
102
110
|
schemaJson?: string;
|
|
103
111
|
initiator?: string;
|
|
104
112
|
signal?: AbortSignal;
|
|
@@ -108,7 +116,7 @@ export declare class AkumaOwner {
|
|
|
108
116
|
* caller starts its own deadline at this admission boundary while the wake
|
|
109
117
|
* continues in the background; the unbounded public Tell awaits `wake`.
|
|
110
118
|
*/
|
|
111
|
-
admitTell(body: string, tellId
|
|
119
|
+
admitTell(body: string, tellId: string | undefined, recordedAt: string | undefined, runtime: TellWakeRuntime, options?: Readonly<{
|
|
112
120
|
schemaJson?: string;
|
|
113
121
|
initiator?: string;
|
|
114
122
|
signal?: AbortSignal;
|
|
@@ -130,13 +138,13 @@ export declare class AkumaOwner {
|
|
|
130
138
|
outcome: TurnOutcome | null;
|
|
131
139
|
completedAt: string | null;
|
|
132
140
|
}>>;
|
|
133
|
-
interrupt(body: string, options
|
|
141
|
+
interrupt(body: string, options: Readonly<{
|
|
134
142
|
tellId?: string;
|
|
135
143
|
recordedAt?: string;
|
|
136
144
|
schemaJson?: string;
|
|
137
145
|
initiator?: string;
|
|
138
146
|
signal?: AbortSignal;
|
|
139
|
-
runtime
|
|
147
|
+
runtime: TellWakeRuntime;
|
|
140
148
|
}>): Promise<InterruptReceipt>;
|
|
141
149
|
/** Atomic Tell-plus-barrier admission; no leash wait or completion observation occurs here. */
|
|
142
150
|
admitInterrupt(body: string, options?: Readonly<{
|
|
@@ -149,13 +157,14 @@ export declare class AkumaOwner {
|
|
|
149
157
|
/** Complete only the exact admitted predecessor barrier, then wake the stable Tell. */
|
|
150
158
|
completeInterruptAdmission(admission: Extract<InterruptAdmission, {
|
|
151
159
|
kind: "admitted";
|
|
152
|
-
}>, runtime
|
|
160
|
+
}>, runtime: TellWakeRuntime, signal?: AbortSignal): Promise<TellResult>;
|
|
153
161
|
fork(input: Readonly<{
|
|
154
162
|
at: string;
|
|
163
|
+
bare?: boolean;
|
|
155
164
|
caller?: AkumaCaller;
|
|
156
165
|
initiator?: string;
|
|
157
|
-
}
|
|
158
|
-
kill(options?: Readonly<{
|
|
166
|
+
}>, spawn: BodyLauncher): Promise<ForkReceipt>;
|
|
167
|
+
kill(spawn: BodyLauncher, options?: Readonly<{
|
|
159
168
|
signal?: AbortSignal;
|
|
160
169
|
}>): Promise<KillEvidence>;
|
|
161
170
|
lastAnswer(): Promise<LastAnswer>;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { bareOption } from "./call-input.js";
|
|
1
2
|
import { decodeAkumaCaller } from "./caller.js";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
import { AkumaNotBornError, AkumaProviderError } from "./akuma-errors.js";
|
|
4
5
|
import { createLiveStatusReader, bornStatus, defaultWaitComplete, executionProgress, observeOutcomeRows, observeStatusOutcome, waitForObservation, } from "./akuma-observe.js";
|
|
5
6
|
import { executeWaitAkuma } from "./akuma-wait.js";
|
|
6
7
|
import { createAkumaStream } from "./akuma-stream.js";
|
|
7
|
-
import { handoffPendingTells,
|
|
8
|
+
import { handoffPendingTells, wakeRecordedTell } from "./body.js";
|
|
8
9
|
import { admitCallInitialTell } from "./call-initial-tell.js";
|
|
9
10
|
import { acquireLeash } from "./control.js";
|
|
10
|
-
import { activitySlice, projectTell, readForkPoint, readHeart, readInterruptCompletion, readKill, readLastAnsweredTurn, readSoul, readTell, recordTell, requestStop, } from "./heart/index.js";
|
|
11
|
+
import { activitySlice, projectTell, readForkPoint, readHeart, readInterruptCompletion, readKill, readLastAnsweredTurn, readSoul, readTell, recordReport, recordTell, requestStop, } from "./heart/index.js";
|
|
11
12
|
import { parsePublicHistoryId, pathsForAkuId } from "./identity.js";
|
|
12
13
|
import { projectTurns, selectExactHistory, selectHistory } from "./projection.js";
|
|
13
14
|
import { resolveProviderExecution } from "./providers/index.js";
|
|
@@ -73,6 +74,8 @@ export async function settleAkumaKill(paths, signal, retainLeash = false) {
|
|
|
73
74
|
if (settledBody?.sequence !== target.sequence) {
|
|
74
75
|
return { evidence: (await readKill(paths, target.sequence)) === null ? "unavailable" : "killed" };
|
|
75
76
|
}
|
|
77
|
+
if (settledBody.hung !== undefined)
|
|
78
|
+
return { evidence: "hung" };
|
|
76
79
|
if (settledBody.end !== "put-down") {
|
|
77
80
|
await leash.clearStop(paths);
|
|
78
81
|
return { evidence: "untidy" };
|
|
@@ -128,6 +131,9 @@ export class AkumaOwner {
|
|
|
128
131
|
throw new TypeError("Akuma history id must match turn/<positive safe integer>");
|
|
129
132
|
return selectExactHistory((await this.projectHistoryTurns()).rows, input.id);
|
|
130
133
|
}
|
|
134
|
+
async report(input, signal) {
|
|
135
|
+
return await recordReport(this.paths, input, signal);
|
|
136
|
+
}
|
|
131
137
|
async status() {
|
|
132
138
|
const { status } = await bornStatus(this.paths, this.id, { aperture: "monitoring" });
|
|
133
139
|
await observeStatusOutcome(status, this.outcomeObserved);
|
|
@@ -190,7 +196,7 @@ export class AkumaOwner {
|
|
|
190
196
|
async wait(predicate = defaultWaitComplete, options = {}) {
|
|
191
197
|
return (await this.waitReceipt(predicate, options)).status;
|
|
192
198
|
}
|
|
193
|
-
async admitInitialTell(initialTell, options
|
|
199
|
+
async admitInitialTell(initialTell, options) {
|
|
194
200
|
return await admitCallInitialTell({
|
|
195
201
|
world: this.worldPath,
|
|
196
202
|
id: this.id,
|
|
@@ -284,7 +290,7 @@ export class AkumaOwner {
|
|
|
284
290
|
reader.clear();
|
|
285
291
|
}
|
|
286
292
|
}
|
|
287
|
-
async interrupt(body, options
|
|
293
|
+
async interrupt(body, options) {
|
|
288
294
|
const admitted = await this.admitInterrupt(body, options);
|
|
289
295
|
if (admitted.kind === "unavailable")
|
|
290
296
|
return admitted;
|
|
@@ -332,7 +338,8 @@ export class AkumaOwner {
|
|
|
332
338
|
},
|
|
333
339
|
};
|
|
334
340
|
}
|
|
335
|
-
async fork(input) {
|
|
341
|
+
async fork(input, spawn) {
|
|
342
|
+
const bare = bareOption(input.bare);
|
|
336
343
|
const caller = decodeAkumaCaller(input.caller);
|
|
337
344
|
const source = await readSoul(this.paths);
|
|
338
345
|
if (source === null)
|
|
@@ -369,24 +376,23 @@ export class AkumaOwner {
|
|
|
369
376
|
worldPath: this.worldPath,
|
|
370
377
|
archetype: source.archetype,
|
|
371
378
|
awaitAsleep: true,
|
|
372
|
-
launch: async (allocated) => {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
},
|
|
379
|
+
launch: async (allocated) => await spawn({
|
|
380
|
+
paths: allocated.paths,
|
|
381
|
+
seed: {
|
|
382
|
+
id: allocated.id,
|
|
383
|
+
archetype: source.archetype,
|
|
384
|
+
...(source.description === undefined ? {} : { description: source.description }),
|
|
385
|
+
provider: source.provider,
|
|
386
|
+
options: source.options,
|
|
387
|
+
allowed: source.allowed,
|
|
388
|
+
bare: source.bare === true || bare === true,
|
|
389
|
+
cwd: source.cwd,
|
|
390
|
+
origin: { kind: "fork", parent: this.id, at: input.at },
|
|
391
|
+
...(caller === undefined ? {} : { caller }),
|
|
392
|
+
},
|
|
393
|
+
birthSession,
|
|
394
|
+
...(input.initiator === undefined ? {} : { birthInitiator: input.initiator }),
|
|
395
|
+
}),
|
|
390
396
|
});
|
|
391
397
|
return { kind: "forked", child: child.id };
|
|
392
398
|
}
|
|
@@ -398,8 +404,8 @@ export class AkumaOwner {
|
|
|
398
404
|
};
|
|
399
405
|
}
|
|
400
406
|
}
|
|
401
|
-
async kill(options = {}) {
|
|
402
|
-
return await killAkumaWithRecovery(this.paths, handoffPendingTells, options.signal);
|
|
407
|
+
async kill(spawn, options = {}) {
|
|
408
|
+
return await killAkumaWithRecovery(this.paths, (paths) => handoffPendingTells(paths, spawn), options.signal);
|
|
403
409
|
}
|
|
404
410
|
async lastAnswer() {
|
|
405
411
|
const turn = await readLastAnsweredTurn(this.paths);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { WorldRoot } from "../world.js";
|
|
2
2
|
import type { LiveStatusObservation, OutcomeObserver } from "./akuma-observe.js";
|
|
3
3
|
import type { AkumaStatus } from "./akuma.js";
|
|
4
|
-
import type
|
|
4
|
+
import { type TellResult } from "./body.js";
|
|
5
|
+
import type { BodyLauncher } from "./body-launch.js";
|
|
5
6
|
import type { Schema } from "./schema.js";
|
|
6
7
|
import type { AkumaAskObservation, AkumaAskResult, AkumaKillResult, AkumaTellResult } from "./selection-observation.js";
|
|
7
8
|
export type AskObserver = Readonly<{
|
|
@@ -9,6 +10,7 @@ export type AskObserver = Readonly<{
|
|
|
9
10
|
observe?: (observation: LiveStatusObservation) => void | Promise<void>;
|
|
10
11
|
}>;
|
|
11
12
|
type TellExecutionInput = Readonly<{
|
|
13
|
+
spawn: BodyLauncher;
|
|
12
14
|
path: WorldRoot;
|
|
13
15
|
id: AkumaStatus["id"];
|
|
14
16
|
body: string;
|
|
@@ -46,6 +48,7 @@ export declare function observeAdmittedAskAkuma(input: Readonly<{
|
|
|
46
48
|
}>): Promise<AkumaAskResult>;
|
|
47
49
|
export declare function executeAskAkuma(input: AskExecutionInput): Promise<AkumaAskResult>;
|
|
48
50
|
type KillExecutionInput = Readonly<{
|
|
51
|
+
spawn: BodyLauncher;
|
|
49
52
|
path: WorldRoot;
|
|
50
53
|
ids: readonly AkumaStatus["id"][];
|
|
51
54
|
signal?: AbortSignal;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { AkumaNotBornError, AkumaProviderError } from "./akuma-errors.js";
|
|
2
2
|
import { AkumaOwner } from "./akuma-owner.js";
|
|
3
|
+
import { tellWakeRuntime } from "./body.js";
|
|
3
4
|
export async function executeTellAkuma(input) {
|
|
4
5
|
input.signal?.throwIfAborted();
|
|
5
6
|
const owner = new AkumaOwner(input.id, input.path);
|
|
6
7
|
let tell;
|
|
7
8
|
if (input.interrupt === true) {
|
|
8
9
|
const interrupted = await owner.interrupt(input.body, {
|
|
10
|
+
runtime: tellWakeRuntime(input.spawn),
|
|
9
11
|
...(input.tellId === undefined ? {} : { tellId: input.tellId }),
|
|
10
12
|
...(input.recordedAt === undefined ? {} : { recordedAt: input.recordedAt }),
|
|
11
13
|
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
@@ -16,7 +18,7 @@ export async function executeTellAkuma(input) {
|
|
|
16
18
|
tell = interrupted;
|
|
17
19
|
}
|
|
18
20
|
else {
|
|
19
|
-
tell = await owner.tell(input.body, input.tellId, input.recordedAt,
|
|
21
|
+
tell = await owner.tell(input.body, input.tellId, input.recordedAt, tellWakeRuntime(input.spawn), {
|
|
20
22
|
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
21
23
|
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
22
24
|
});
|
|
@@ -27,6 +29,8 @@ export async function executeTellAkuma(input) {
|
|
|
27
29
|
function askObservation(observed) {
|
|
28
30
|
if (observed.outcome === null)
|
|
29
31
|
return observed.reason === "deadline" ? { reason: "deadline" } : { reason: "unanswered" };
|
|
32
|
+
if (observed.outcome.kind === "canceled")
|
|
33
|
+
return { reason: "unanswered" };
|
|
30
34
|
if (observed.outcome.kind === "answered")
|
|
31
35
|
return { reason: "answered", answer: observed.outcome.answerJson ?? observed.outcome.answer };
|
|
32
36
|
if (observed.outcome.kind === "failed")
|
|
@@ -120,7 +124,7 @@ async function executeInterruptAskAkuma(input, owner) {
|
|
|
120
124
|
throw new AkumaProviderError(`Tell interrupt unavailable: ${admission.evidence}`);
|
|
121
125
|
const observing = new AbortController();
|
|
122
126
|
const signal = input.signal === undefined ? observing.signal : AbortSignal.any([input.signal, observing.signal]);
|
|
123
|
-
const wake = owner.completeInterruptAdmission(admission,
|
|
127
|
+
const wake = owner.completeInterruptAdmission(admission, tellWakeRuntime(input.spawn), signal);
|
|
124
128
|
try {
|
|
125
129
|
const receipt = admission.barrier === undefined
|
|
126
130
|
? undefined
|
|
@@ -152,7 +156,7 @@ export async function executeAskAkuma(input) {
|
|
|
152
156
|
const owner = new AkumaOwner(input.id, input.path);
|
|
153
157
|
if (input.interrupt === true)
|
|
154
158
|
return await executeInterruptAskAkuma(input, owner);
|
|
155
|
-
const admission = await owner.admitTell(input.body, input.tellId, input.recordedAt,
|
|
159
|
+
const admission = await owner.admitTell(input.body, input.tellId, input.recordedAt, tellWakeRuntime(input.spawn), {
|
|
156
160
|
...(input.schemaJson === undefined ? {} : { schemaJson: input.schemaJson }),
|
|
157
161
|
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
158
162
|
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
@@ -174,7 +178,7 @@ export async function executeAskAkuma(input) {
|
|
|
174
178
|
export async function executeKillAkuma(input) {
|
|
175
179
|
input.signal?.throwIfAborted();
|
|
176
180
|
const owners = input.ids.map((id) => new AkumaOwner(id, input.path));
|
|
177
|
-
const evidence = await Promise.all(owners.map(async (owner) => await owner.kill(input.signal === undefined ? {} : { signal: input.signal })));
|
|
181
|
+
const evidence = await Promise.all(owners.map(async (owner) => await owner.kill(input.spawn, input.signal === undefined ? {} : { signal: input.signal })));
|
|
178
182
|
input.signal?.throwIfAborted();
|
|
179
183
|
return {
|
|
180
184
|
results: input.ids.map((id, index) => ({ id, evidence: evidence[index] })),
|
|
@@ -135,6 +135,13 @@ export declare const akumaStatusSchema: z.ZodObject<{
|
|
|
135
135
|
}, z.core.$strict>, z.ZodObject<{
|
|
136
136
|
kind: z.ZodLiteral<"row">;
|
|
137
137
|
row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
|
|
138
|
+
kind: z.ZodLiteral<"report">;
|
|
139
|
+
sequence: z.ZodNumber;
|
|
140
|
+
bodySequence: z.ZodNumber;
|
|
141
|
+
turnSequence: z.ZodNumber;
|
|
142
|
+
text: z.ZodString;
|
|
143
|
+
at: z.ZodString;
|
|
144
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
138
145
|
kind: z.ZodLiteral<"call">;
|
|
139
146
|
sequence: z.ZodNumber;
|
|
140
147
|
turnSequence: z.ZodNumber;
|
|
@@ -340,6 +347,9 @@ export declare const akumaStatusSchema: z.ZodObject<{
|
|
|
340
347
|
kind: z.ZodLiteral<"failed">;
|
|
341
348
|
historyId: z.ZodString;
|
|
342
349
|
diagnostic: z.ZodString;
|
|
350
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
351
|
+
kind: z.ZodLiteral<"canceled">;
|
|
352
|
+
historyId: z.ZodString;
|
|
343
353
|
}, z.core.$strict>]>;
|
|
344
354
|
}, z.core.$strict>>;
|
|
345
355
|
entries: z.ZodReadonly<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
@@ -348,6 +358,13 @@ export declare const akumaStatusSchema: z.ZodObject<{
|
|
|
348
358
|
}, z.core.$strict>, z.ZodObject<{
|
|
349
359
|
kind: z.ZodLiteral<"row">;
|
|
350
360
|
row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
|
|
361
|
+
kind: z.ZodLiteral<"report">;
|
|
362
|
+
sequence: z.ZodNumber;
|
|
363
|
+
bodySequence: z.ZodNumber;
|
|
364
|
+
turnSequence: z.ZodNumber;
|
|
365
|
+
text: z.ZodString;
|
|
366
|
+
at: z.ZodString;
|
|
367
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
351
368
|
kind: z.ZodLiteral<"call">;
|
|
352
369
|
sequence: z.ZodNumber;
|
|
353
370
|
turnSequence: z.ZodNumber;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { TellWake } from "./call-initial-tell.js";
|
|
3
|
+
export declare const bodyLaunchSchema: z.ZodObject<{
|
|
4
|
+
paths: z.ZodObject<{
|
|
5
|
+
directory: z.ZodString;
|
|
6
|
+
heart: z.ZodString;
|
|
7
|
+
leash: z.ZodString;
|
|
8
|
+
log: z.ZodString;
|
|
9
|
+
requests: z.ZodString;
|
|
10
|
+
}, z.core.$strict>;
|
|
11
|
+
seed: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodTransform<Omit<Readonly<{
|
|
12
|
+
id: import("./identity.js").AkuId;
|
|
13
|
+
archetype: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
provider: import("./provider-recipe.js").ProviderExecution;
|
|
16
|
+
options: import("./provider-recipe.js").ProviderOptions;
|
|
17
|
+
cwd: string;
|
|
18
|
+
origin: import("./index.js").AkumaOrigin;
|
|
19
|
+
caller?: import("./caller.js").AkumaCaller;
|
|
20
|
+
allowed: import("./allowed.js").AllowedActions;
|
|
21
|
+
bare?: boolean;
|
|
22
|
+
createdAt: string;
|
|
23
|
+
}>, "createdAt">, unknown>>>;
|
|
24
|
+
birthSession: z.ZodOptional<z.ZodObject<{
|
|
25
|
+
provider: z.ZodString;
|
|
26
|
+
coordinate: z.ZodUnion<readonly [z.ZodPipe<z.ZodObject<{
|
|
27
|
+
sessionFile: z.ZodString;
|
|
28
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
29
|
+
}, z.core.$strict>, z.ZodTransform<{
|
|
30
|
+
sessionFile: string;
|
|
31
|
+
sessionId?: never;
|
|
32
|
+
} | {
|
|
33
|
+
sessionFile: string;
|
|
34
|
+
sessionId: string;
|
|
35
|
+
}, {
|
|
36
|
+
sessionFile: string;
|
|
37
|
+
sessionId?: string | undefined;
|
|
38
|
+
}>>, z.ZodObject<{
|
|
39
|
+
sessionId: z.ZodString;
|
|
40
|
+
}, z.core.$strict>]>;
|
|
41
|
+
cwd: z.ZodString;
|
|
42
|
+
options: z.ZodPipe<z.ZodObject<{
|
|
43
|
+
model: z.ZodOptional<z.ZodString>;
|
|
44
|
+
effort: z.ZodOptional<z.ZodString>;
|
|
45
|
+
network: z.ZodOptional<z.ZodEnum<{
|
|
46
|
+
disabled: "disabled";
|
|
47
|
+
enabled: "enabled";
|
|
48
|
+
}>>;
|
|
49
|
+
systemPrompt: z.ZodOptional<z.ZodString>;
|
|
50
|
+
systemPromptMode: z.ZodOptional<z.ZodEnum<{
|
|
51
|
+
replace: "replace";
|
|
52
|
+
append: "append";
|
|
53
|
+
}>>;
|
|
54
|
+
}, z.core.$strip>, z.ZodTransform<Readonly<{
|
|
55
|
+
systemPromptMode?: "replace" | "append";
|
|
56
|
+
systemPrompt?: string;
|
|
57
|
+
network?: "disabled" | "enabled";
|
|
58
|
+
effort?: string;
|
|
59
|
+
model?: string;
|
|
60
|
+
}>, {
|
|
61
|
+
model?: string | undefined;
|
|
62
|
+
effort?: string | undefined;
|
|
63
|
+
network?: "disabled" | "enabled" | undefined;
|
|
64
|
+
systemPrompt?: string | undefined;
|
|
65
|
+
systemPromptMode?: "replace" | "append" | undefined;
|
|
66
|
+
}>>;
|
|
67
|
+
admittedAt: z.ZodString;
|
|
68
|
+
}, z.core.$strict>>;
|
|
69
|
+
initialBody: z.ZodOptional<z.ZodString>;
|
|
70
|
+
initiator: z.ZodOptional<z.ZodString>;
|
|
71
|
+
birthInitiator: z.ZodOptional<z.ZodString>;
|
|
72
|
+
initialSchemaJson: z.ZodOptional<z.ZodString>;
|
|
73
|
+
refuseIfHeld: z.ZodOptional<z.ZodBoolean>;
|
|
74
|
+
handoffFromBodySequence: z.ZodOptional<z.ZodNumber>;
|
|
75
|
+
completion: z.ZodOptional<z.ZodObject<{
|
|
76
|
+
contractId: z.ZodOptional<z.ZodString>;
|
|
77
|
+
}, z.core.$strict>>;
|
|
78
|
+
}, z.core.$strict>;
|
|
79
|
+
export type BodyLaunch = z.infer<typeof bodyLaunchSchema>;
|
|
80
|
+
/** Live launch evidence only; Heart and leash alone judge birth and settlement. */
|
|
81
|
+
export type BodyLaunchEnd = Readonly<{
|
|
82
|
+
diagnostic: string;
|
|
83
|
+
held?: boolean;
|
|
84
|
+
child?: Extract<TellWake, {
|
|
85
|
+
child: unknown;
|
|
86
|
+
}>["child"];
|
|
87
|
+
}>;
|
|
88
|
+
export type LiveBodyLaunch = Readonly<{
|
|
89
|
+
/** Launch completion evidence, never a product outcome or closure proof. */
|
|
90
|
+
completed: Promise<BodyLaunchEnd>;
|
|
91
|
+
/** Ask owned resources to retire; force requests supported disposal, not shared-host termination or rollback. */
|
|
92
|
+
cancel(force?: boolean): Promise<void>;
|
|
93
|
+
/** Relinquish this holder's custody, not kill or closure, with no guarantee of host survival. */
|
|
94
|
+
release(): void;
|
|
95
|
+
}>;
|
|
96
|
+
export type BodyLauncher = (launch: BodyLaunch) => Promise<LiveBodyLaunch>;
|
|
97
|
+
/** Observe durable custody first, including once more after live launch completion. */
|
|
98
|
+
export declare function observeBodyLaunch<T>(child: LiveBodyLaunch, observe: () => Promise<T | null>, schedule?: (milliseconds: number, signal: AbortSignal) => Promise<void>, signal?: AbortSignal): Promise<Readonly<{
|
|
99
|
+
kind: "observed";
|
|
100
|
+
value: T;
|
|
101
|
+
}> | Readonly<{
|
|
102
|
+
kind: "completed";
|
|
103
|
+
end: BodyLaunchEnd;
|
|
104
|
+
}>>;
|
|
105
|
+
export declare function launchEndWake(end: BodyLaunchEnd): Extract<TellWake, {
|
|
106
|
+
kind: "held" | "failed";
|
|
107
|
+
}>;
|