@astrosheep/keiyaku 4.1.1 → 4.1.3
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-errors.d.ts +6 -0
- package/build/src/akuma/akuma-errors.js +9 -0
- package/build/src/akuma/akuma-handle.d.ts +39 -0
- package/build/src/akuma/akuma-handle.js +263 -0
- package/build/src/akuma/akuma-observe.d.ts +19 -0
- package/build/src/akuma/akuma-observe.js +74 -0
- package/build/src/akuma/akuma-product-symbols.d.ts +1 -0
- package/build/src/akuma/akuma-product-symbols.js +1 -0
- package/build/src/akuma/akuma-product.d.ts +18 -0
- package/build/src/akuma/akuma-product.js +154 -0
- package/build/src/akuma/akuma.d.ts +23 -70
- package/build/src/akuma/akuma.js +17 -433
- package/build/src/akuma/body-supervisor.d.ts +26 -0
- package/build/src/akuma/body-supervisor.js +89 -0
- package/build/src/akuma/body.d.ts +1 -1
- package/build/src/akuma/body.js +7 -3
- package/build/src/akuma/heart/index.d.ts +1 -1
- package/build/src/akuma/heart/index.js +1 -1
- package/build/src/akuma/heart/schema.d.ts +1 -0
- package/build/src/akuma/heart/schema.js +9 -0
- package/build/src/akuma/heart/storage.d.ts +1 -0
- package/build/src/akuma/heart/storage.js +18 -1
- package/build/src/akuma/nuke.js +6 -2
- package/build/src/akuma/projection-read.d.ts +17 -0
- package/build/src/akuma/projection-read.js +135 -0
- package/build/src/akuma/projection.d.ts +1 -18
- package/build/src/akuma/projection.js +21 -155
- package/build/src/akuma/providers/claude/index.js +101 -89
- package/build/src/akuma/providers/codex-app-server/index.js +9 -6
- package/build/src/akuma/providers/opencode-sdk/index.js +22 -15
- package/build/src/akuma/providers/pi/index.js +45 -43
- package/build/src/akuma/publication.d.ts +2 -1
- package/build/src/akuma/publication.js +72 -11
- package/build/src/akuma/request-execution.d.ts +8 -0
- package/build/src/akuma/request-execution.js +98 -0
- package/build/src/akuma/request-serve.d.ts +14 -2
- package/build/src/akuma/request-serve.js +3 -103
- package/build/src/akuma/{body-turn.d.ts → turn-drive.d.ts} +4 -26
- package/build/src/akuma/{body-turn.js → turn-drive.js} +14 -100
- package/build/src/cli/commands/akuma.d.ts +0 -6
- package/build/src/cli/commands/akuma.js +1 -11
- package/build/src/cli/commands/contract-invoke.d.ts +25 -0
- package/build/src/cli/commands/contract-invoke.js +193 -0
- package/build/src/cli/commands/contract.d.ts +12 -0
- package/build/src/cli/commands/contract.js +229 -0
- package/build/src/cli/invoke.js +24 -184
- package/build/src/cli/parse.d.ts +1 -1
- package/build/src/cli/parse.js +8 -222
- package/build/src/cli/render/akuma-activity.d.ts +38 -0
- package/build/src/cli/render/akuma-activity.js +362 -0
- package/build/src/cli/render/akuma.d.ts +1 -1
- package/build/src/cli/render/akuma.js +14 -371
- package/build/src/cli/render/contract-history.d.ts +2 -0
- package/build/src/cli/render/contract-history.js +83 -0
- package/build/src/cli/render/contract.d.ts +1 -2
- package/build/src/cli/render/contract.js +1 -83
- package/build/src/git/read-observation.js +15 -10
- package/build/src/git/reconcile.d.ts +8 -1
- package/build/src/git/reconcile.js +13 -301
- package/build/src/git/scratch.d.ts +8 -5
- package/build/src/git/scratch.js +29 -2
- package/build/src/git/terminal-reconcile.d.ts +21 -0
- package/build/src/git/terminal-reconcile.js +278 -0
- package/build/src/kanshi/read.js +32 -27
- package/build/src/library/contract-bind.d.ts +26 -0
- package/build/src/library/contract-bind.js +106 -0
- package/build/src/library/contract-operations.d.ts +77 -0
- package/build/src/library/contract-operations.js +130 -0
- package/build/src/library/contract-types.d.ts +95 -0
- package/build/src/library/contract-types.js +1 -0
- package/build/src/library/contract.d.ts +11 -136
- package/build/src/library/contract.js +9 -222
- package/build/src/library/fleet.js +2 -1
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
async function executeWait(input, request) {
|
|
2
|
+
return {
|
|
3
|
+
result: await input.upstream.wait({
|
|
4
|
+
targets: request.targets,
|
|
5
|
+
completion: request.completion,
|
|
6
|
+
...(request.timeoutMs === undefined ? {} : { timeoutMs: request.timeoutMs }),
|
|
7
|
+
signal: input.signal,
|
|
8
|
+
}),
|
|
9
|
+
service: { action: request.action },
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
async function executeTell(input, request) {
|
|
13
|
+
return {
|
|
14
|
+
result: await input.upstream.tell({
|
|
15
|
+
target: request.target,
|
|
16
|
+
body: request.body,
|
|
17
|
+
tellId: request.id,
|
|
18
|
+
recordedAt: request.admittedAt,
|
|
19
|
+
signal: input.signal,
|
|
20
|
+
}),
|
|
21
|
+
service: { action: request.action, target: request.target, tellId: request.id },
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
async function executeKill(input, request) {
|
|
25
|
+
const served = await input.upstream.kill({ targets: request.targets, signal: input.signal });
|
|
26
|
+
return { result: served.result, service: { action: request.action, results: served.service } };
|
|
27
|
+
}
|
|
28
|
+
async function executeDeliver(input, request) {
|
|
29
|
+
const served = await input.upstream.deliver({
|
|
30
|
+
repoRoot: request.repoRoot,
|
|
31
|
+
contractId: request.contractId,
|
|
32
|
+
...(request.message === undefined ? {} : { message: request.message }),
|
|
33
|
+
includeDirty: request.includeDirty,
|
|
34
|
+
materializeConflict: request.materializeConflict,
|
|
35
|
+
requester: request.requester,
|
|
36
|
+
signal: input.signal,
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
result: served.result,
|
|
40
|
+
...(served.deliveryFactId === undefined
|
|
41
|
+
? {}
|
|
42
|
+
: {
|
|
43
|
+
service: {
|
|
44
|
+
action: request.action,
|
|
45
|
+
repoRoot: request.repoRoot,
|
|
46
|
+
contractId: request.contractId,
|
|
47
|
+
deliveryFactId: served.deliveryFactId,
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function executeReview(input, request) {
|
|
53
|
+
const served = await input.upstream.review({
|
|
54
|
+
repoRoot: request.repoRoot,
|
|
55
|
+
contractId: request.contractId,
|
|
56
|
+
verdict: request.verdict,
|
|
57
|
+
...(request.summary === undefined ? {} : { summary: request.summary }),
|
|
58
|
+
requester: request.requester,
|
|
59
|
+
signal: input.signal,
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
result: served.result,
|
|
63
|
+
...(served.reviewFactId === undefined
|
|
64
|
+
? {}
|
|
65
|
+
: {
|
|
66
|
+
service: {
|
|
67
|
+
action: request.action,
|
|
68
|
+
repoRoot: request.repoRoot,
|
|
69
|
+
contractId: request.contractId,
|
|
70
|
+
reviewFactId: served.reviewFactId,
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export async function executeRequest(input, request) {
|
|
76
|
+
if (input.upstream === undefined)
|
|
77
|
+
throw new Error("upstream execution port is unavailable");
|
|
78
|
+
if (request.action === "akuma.wait")
|
|
79
|
+
return executeWait(input, request);
|
|
80
|
+
if (request.action === "akuma.tell")
|
|
81
|
+
return executeTell(input, request);
|
|
82
|
+
if (request.action === "akuma.kill")
|
|
83
|
+
return executeKill(input, request);
|
|
84
|
+
if (request.action === "contract.deliver")
|
|
85
|
+
return executeDeliver(input, request);
|
|
86
|
+
if (request.action === "contract.review")
|
|
87
|
+
return executeReview(input, request);
|
|
88
|
+
const task = request;
|
|
89
|
+
return {
|
|
90
|
+
result: await input.upstream.task({
|
|
91
|
+
world: task.world,
|
|
92
|
+
request: task.request,
|
|
93
|
+
requester: task.requester,
|
|
94
|
+
signal: input.signal,
|
|
95
|
+
}),
|
|
96
|
+
service: { action: task.action },
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { type KillEvidence, type Soul } from "./heart/index.js";
|
|
1
|
+
import { type KillEvidence, type RequestFact, type Soul } from "./heart/index.js";
|
|
2
2
|
import { type AkuId, type AkumaPaths } from "./identity.js";
|
|
3
|
+
import { type StructuralRequestClaim } from "./request-wire.js";
|
|
3
4
|
import { type TaskMutationRequest } from "../task/mutation.js";
|
|
5
|
+
import type { OwnedProcess } from "../runtime/proc/run.js";
|
|
4
6
|
export type RequestChildLaunch = Readonly<{
|
|
5
7
|
paths: AkumaPaths;
|
|
6
8
|
seed: Omit<Soul, "createdAt">;
|
|
@@ -63,10 +65,20 @@ type PumpInput = Readonly<{
|
|
|
63
65
|
parent: Soul;
|
|
64
66
|
bodySequence: number;
|
|
65
67
|
now(): string;
|
|
66
|
-
spawn(launch: RequestChildLaunch): Promise<void>;
|
|
68
|
+
spawn(launch: RequestChildLaunch): Promise<OwnedProcess | void>;
|
|
67
69
|
upstream?: UpstreamExecutionPort;
|
|
68
70
|
signal: AbortSignal;
|
|
69
71
|
}>;
|
|
72
|
+
export type ServeInput = Omit<PumpInput, "bodySequence"> & Readonly<{
|
|
73
|
+
directory: string;
|
|
74
|
+
claim: StructuralRequestClaim;
|
|
75
|
+
admissionOpen(): boolean;
|
|
76
|
+
}>;
|
|
77
|
+
export type UpstreamFact = Exclude<Extract<RequestFact, {
|
|
78
|
+
state: "admitted";
|
|
79
|
+
}>, Extract<RequestFact, {
|
|
80
|
+
action: "akuma.call";
|
|
81
|
+
}>>;
|
|
70
82
|
export declare class BodyRequestPump {
|
|
71
83
|
private readonly input;
|
|
72
84
|
readonly directory: string;
|
|
@@ -6,6 +6,7 @@ import { pathsForAkuId, worldRootForAkumaPaths } from "./identity.js";
|
|
|
6
6
|
import { BIRTH_TIMEOUT_MS, publishAkuma } from "./publication.js";
|
|
7
7
|
import { atomicJson, canonicalAkuId, decodeClaim, decodeRecipe, receiptPath, } from "./request-wire.js";
|
|
8
8
|
import { isTaskMutationAction } from "../task/mutation.js";
|
|
9
|
+
import { executeRequest } from "./request-execution.js";
|
|
9
10
|
const POLL_MS = 100;
|
|
10
11
|
function diagnostic(error) {
|
|
11
12
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -118,7 +119,7 @@ async function serveCall(input) {
|
|
|
118
119
|
launch: async (allocated) => {
|
|
119
120
|
if (!input.admissionOpen())
|
|
120
121
|
throw new Error("body closed request admission");
|
|
121
|
-
await input.spawn({
|
|
122
|
+
return await input.spawn({
|
|
122
123
|
paths: allocated.paths,
|
|
123
124
|
seed: {
|
|
124
125
|
id: allocated.id,
|
|
@@ -161,107 +162,6 @@ function failure(error) {
|
|
|
161
162
|
}
|
|
162
163
|
return { kind: "failed", diagnostic: diagnostic(error) };
|
|
163
164
|
}
|
|
164
|
-
async function execute(input, request) {
|
|
165
|
-
if (input.upstream === undefined)
|
|
166
|
-
throw new Error("upstream execution port is unavailable");
|
|
167
|
-
if (request.action === "akuma.wait") {
|
|
168
|
-
const result = await input.upstream.wait({
|
|
169
|
-
targets: request.targets,
|
|
170
|
-
completion: request.completion,
|
|
171
|
-
...(request.timeoutMs === undefined ? {} : { timeoutMs: request.timeoutMs }),
|
|
172
|
-
signal: input.signal,
|
|
173
|
-
});
|
|
174
|
-
return { result, service: { action: request.action } };
|
|
175
|
-
}
|
|
176
|
-
if (request.action === "akuma.tell") {
|
|
177
|
-
const result = await input.upstream.tell({
|
|
178
|
-
target: request.target,
|
|
179
|
-
body: request.body,
|
|
180
|
-
tellId: request.id,
|
|
181
|
-
recordedAt: request.admittedAt,
|
|
182
|
-
signal: input.signal,
|
|
183
|
-
});
|
|
184
|
-
return {
|
|
185
|
-
result,
|
|
186
|
-
service: { action: request.action, target: request.target, tellId: request.id },
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
if (request.action === "akuma.kill") {
|
|
190
|
-
const served = await input.upstream.kill({
|
|
191
|
-
targets: request.targets,
|
|
192
|
-
signal: input.signal,
|
|
193
|
-
});
|
|
194
|
-
return {
|
|
195
|
-
result: served.result,
|
|
196
|
-
service: { action: request.action, results: served.service },
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
if (request.action === "contract.deliver") {
|
|
200
|
-
return await executeDeliver(input, request);
|
|
201
|
-
}
|
|
202
|
-
if (request.action === "contract.review") {
|
|
203
|
-
return await executeReview(input, request);
|
|
204
|
-
}
|
|
205
|
-
const task = request;
|
|
206
|
-
const result = await input.upstream.task({
|
|
207
|
-
world: task.world,
|
|
208
|
-
request: task.request,
|
|
209
|
-
requester: task.requester,
|
|
210
|
-
signal: input.signal,
|
|
211
|
-
});
|
|
212
|
-
return { result, service: { action: task.action } };
|
|
213
|
-
}
|
|
214
|
-
async function executeDeliver(input, request) {
|
|
215
|
-
if (input.upstream === undefined)
|
|
216
|
-
throw new Error("upstream execution port is unavailable");
|
|
217
|
-
const served = await input.upstream.deliver({
|
|
218
|
-
repoRoot: request.repoRoot,
|
|
219
|
-
contractId: request.contractId,
|
|
220
|
-
...(request.message === undefined ? {} : { message: request.message }),
|
|
221
|
-
includeDirty: request.includeDirty,
|
|
222
|
-
materializeConflict: request.materializeConflict,
|
|
223
|
-
requester: request.requester,
|
|
224
|
-
signal: input.signal,
|
|
225
|
-
});
|
|
226
|
-
return {
|
|
227
|
-
result: served.result,
|
|
228
|
-
...(served.deliveryFactId === undefined
|
|
229
|
-
? {}
|
|
230
|
-
: {
|
|
231
|
-
service: {
|
|
232
|
-
action: request.action,
|
|
233
|
-
repoRoot: request.repoRoot,
|
|
234
|
-
contractId: request.contractId,
|
|
235
|
-
deliveryFactId: served.deliveryFactId,
|
|
236
|
-
},
|
|
237
|
-
}),
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
async function executeReview(input, request) {
|
|
241
|
-
if (input.upstream === undefined)
|
|
242
|
-
throw new Error("upstream execution port is unavailable");
|
|
243
|
-
const served = await input.upstream.review({
|
|
244
|
-
repoRoot: request.repoRoot,
|
|
245
|
-
contractId: request.contractId,
|
|
246
|
-
verdict: request.verdict,
|
|
247
|
-
...(request.summary === undefined ? {} : { summary: request.summary }),
|
|
248
|
-
requester: request.requester,
|
|
249
|
-
signal: input.signal,
|
|
250
|
-
});
|
|
251
|
-
return {
|
|
252
|
-
result: served.result,
|
|
253
|
-
...(served.reviewFactId === undefined
|
|
254
|
-
? {}
|
|
255
|
-
: {
|
|
256
|
-
service: {
|
|
257
|
-
action: request.action,
|
|
258
|
-
repoRoot: request.repoRoot,
|
|
259
|
-
contractId: request.contractId,
|
|
260
|
-
reviewFactId: served.reviewFactId,
|
|
261
|
-
},
|
|
262
|
-
}),
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
165
|
function pendingService(request) {
|
|
266
166
|
if (request.action === "akuma.wait")
|
|
267
167
|
return { action: request.action };
|
|
@@ -303,7 +203,7 @@ async function serveUpstream(input) {
|
|
|
303
203
|
let outcome;
|
|
304
204
|
let service = pendingService(request);
|
|
305
205
|
try {
|
|
306
|
-
const served = await
|
|
206
|
+
const served = await executeRequest(input, request);
|
|
307
207
|
outcome = { kind: "returned", result: served.result };
|
|
308
208
|
if (served.service !== undefined)
|
|
309
209
|
service = served.service;
|
|
@@ -1,31 +1,9 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ResumeCoordinate, type Soul, type TellFact } from "./heart/index.js";
|
|
2
2
|
import type { AkumaPaths } from "./identity.js";
|
|
3
3
|
import { type ProviderAdapter, type TurnResult } from "./provider.js";
|
|
4
4
|
import { type RequestChildLaunch, type UpstreamExecutionPort } from "./request-serve.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
private readonly paths;
|
|
8
|
-
private readonly bodySequence;
|
|
9
|
-
private readonly leash;
|
|
10
|
-
readonly signal: AbortSignal;
|
|
11
|
-
private readonly controller;
|
|
12
|
-
private readonly finished;
|
|
13
|
-
private readonly observer;
|
|
14
|
-
private waiter;
|
|
15
|
-
private observation;
|
|
16
|
-
private stopping?;
|
|
17
|
-
private constructor();
|
|
18
|
-
static open(paths: AkumaPaths, bodySequence: number, leash: HeldAkumaLeash): Promise<BodySupervisor>;
|
|
19
|
-
get reason(): "control" | "heart-gone" | undefined;
|
|
20
|
-
current(): HeartSnapshot;
|
|
21
|
-
recordHung(diagnostic: string, at: string): Promise<void>;
|
|
22
|
-
refresh(): Promise<HeartSnapshot>;
|
|
23
|
-
next(after: HeartSnapshot): Promise<HeartSnapshot>;
|
|
24
|
-
cancel(reason: "control" | "heart-gone"): void;
|
|
25
|
-
close(): Promise<void>;
|
|
26
|
-
private publish;
|
|
27
|
-
private observe;
|
|
28
|
-
}
|
|
5
|
+
import { BodySupervisor } from "./body-supervisor.js";
|
|
6
|
+
import type { OwnedProcess } from "../runtime/proc/run.js";
|
|
29
7
|
export declare function turnRecipe(paths: AkumaPaths, soul: Soul): Promise<Readonly<{
|
|
30
8
|
cwd: string;
|
|
31
9
|
options: Soul["options"];
|
|
@@ -47,7 +25,7 @@ export type DriveTurnInput = Readonly<{
|
|
|
47
25
|
call?: string;
|
|
48
26
|
launchTells: readonly TellFact[];
|
|
49
27
|
supervisor: BodySupervisor;
|
|
50
|
-
runtimeSpawn(launch: RequestChildLaunch): Promise<void>;
|
|
28
|
+
runtimeSpawn(launch: RequestChildLaunch): Promise<OwnedProcess | void>;
|
|
51
29
|
upstream?: UpstreamExecutionPort;
|
|
52
30
|
now(): string;
|
|
53
31
|
}>;
|
|
@@ -2,93 +2,7 @@ import { abortableDelay } from "./abort.js";
|
|
|
2
2
|
import { appendActivity, beginTurn, breakBody, heartExists, readHeart, recordSession, recordTellDeliveries, recordTellReceipt, } from "./heart/index.js";
|
|
3
3
|
import { encodeAgentEvent } from "./provider.js";
|
|
4
4
|
import { BodyRequestPump } from "./request-serve.js";
|
|
5
|
-
|
|
6
|
-
export const CONTROL_RESPONSE_MS = 1_000;
|
|
7
|
-
export class BodySupervisor {
|
|
8
|
-
paths;
|
|
9
|
-
bodySequence;
|
|
10
|
-
leash;
|
|
11
|
-
signal;
|
|
12
|
-
controller = new AbortController();
|
|
13
|
-
finished = new AbortController();
|
|
14
|
-
observer;
|
|
15
|
-
waiter;
|
|
16
|
-
observation;
|
|
17
|
-
stopping;
|
|
18
|
-
constructor(paths, bodySequence, leash, observation) {
|
|
19
|
-
this.paths = paths;
|
|
20
|
-
this.bodySequence = bodySequence;
|
|
21
|
-
this.leash = leash;
|
|
22
|
-
this.signal = this.controller.signal;
|
|
23
|
-
this.observation = observation;
|
|
24
|
-
this.observer = this.observe();
|
|
25
|
-
}
|
|
26
|
-
static async open(paths, bodySequence, leash) {
|
|
27
|
-
return new BodySupervisor(paths, bodySequence, leash, await readHeart(paths));
|
|
28
|
-
}
|
|
29
|
-
get reason() {
|
|
30
|
-
return this.stopping;
|
|
31
|
-
}
|
|
32
|
-
current() {
|
|
33
|
-
return this.observation;
|
|
34
|
-
}
|
|
35
|
-
async recordHung(diagnostic, at) {
|
|
36
|
-
await this.leash.recordBodyHung(this.paths, { sequence: this.bodySequence, diagnostic, at });
|
|
37
|
-
}
|
|
38
|
-
async refresh() {
|
|
39
|
-
this.publish(await readHeart(this.paths));
|
|
40
|
-
return this.observation;
|
|
41
|
-
}
|
|
42
|
-
next(after) {
|
|
43
|
-
if (this.observation !== after)
|
|
44
|
-
return Promise.resolve(this.observation);
|
|
45
|
-
return new Promise((resolve) => {
|
|
46
|
-
this.waiter = resolve;
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
cancel(reason) {
|
|
50
|
-
if (this.stopping !== undefined)
|
|
51
|
-
return;
|
|
52
|
-
this.stopping = reason;
|
|
53
|
-
this.controller.abort(new Error(reason === "control" ? "Akuma Body interrupted by durable control" : "Akuma Heart disappeared"));
|
|
54
|
-
this.waiter?.(this.observation);
|
|
55
|
-
this.waiter = undefined;
|
|
56
|
-
}
|
|
57
|
-
async close() {
|
|
58
|
-
this.finished.abort();
|
|
59
|
-
await this.observer;
|
|
60
|
-
this.waiter = undefined;
|
|
61
|
-
}
|
|
62
|
-
publish(snapshot) {
|
|
63
|
-
this.observation = snapshot;
|
|
64
|
-
this.waiter?.(snapshot);
|
|
65
|
-
this.waiter = undefined;
|
|
66
|
-
}
|
|
67
|
-
async observe() {
|
|
68
|
-
for (;;) {
|
|
69
|
-
const snapshot = this.observation;
|
|
70
|
-
if (!(await heartExists(this.paths)))
|
|
71
|
-
return this.cancel("heart-gone");
|
|
72
|
-
if (snapshot.stop?.bodySequence === this.bodySequence || snapshot.pause?.bodySequence === this.bodySequence) {
|
|
73
|
-
return this.cancel("control");
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
await abortableDelay(BODY_CONTROL_OBSERVATION_MS, this.finished.signal);
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
try {
|
|
82
|
-
await this.refresh();
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
if (await heartExists(this.paths))
|
|
86
|
-
throw error;
|
|
87
|
-
return this.cancel("heart-gone");
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
5
|
+
import { CONTROL_RESPONSE_MS } from "./body-supervisor.js";
|
|
92
6
|
function serializeEffects() {
|
|
93
7
|
let tail = Promise.resolve();
|
|
94
8
|
let failed = false;
|
|
@@ -132,11 +46,7 @@ async function failedTurnSetup(input, turnSequence, requests, cancelDrive, error
|
|
|
132
46
|
throw error;
|
|
133
47
|
return { kind: "stopped" };
|
|
134
48
|
}
|
|
135
|
-
return {
|
|
136
|
-
kind: "failed",
|
|
137
|
-
turnSequence,
|
|
138
|
-
diagnostic: error instanceof Error ? error.message : String(error),
|
|
139
|
-
};
|
|
49
|
+
return { kind: "failed", turnSequence, diagnostic: error instanceof Error ? error.message : String(error) };
|
|
140
50
|
}
|
|
141
51
|
async function writeProviderEvent(input, active, event) {
|
|
142
52
|
if (input.supervisor.signal.aborted)
|
|
@@ -151,11 +61,7 @@ async function writeProviderEvent(input, active, event) {
|
|
|
151
61
|
admittedAt: at,
|
|
152
62
|
});
|
|
153
63
|
}
|
|
154
|
-
await appendActivity(input.paths, {
|
|
155
|
-
turnSequence: active.turnSequence,
|
|
156
|
-
event: encodeAgentEvent(event),
|
|
157
|
-
at,
|
|
158
|
-
});
|
|
64
|
+
await appendActivity(input.paths, { turnSequence: active.turnSequence, event: encodeAgentEvent(event), at });
|
|
159
65
|
}
|
|
160
66
|
async function startTurnDrive(input) {
|
|
161
67
|
const { cwd, options, session } = await turnRecipe(input.paths, input.soul);
|
|
@@ -212,7 +118,7 @@ async function startTurnDrive(input) {
|
|
|
212
118
|
}
|
|
213
119
|
return { kind: "stopped" };
|
|
214
120
|
}
|
|
215
|
-
if (input.launchTells.length > 0)
|
|
121
|
+
if (input.launchTells.length > 0)
|
|
216
122
|
await recordTellDeliveries(input.paths, input.launchTells.map((tell) => ({
|
|
217
123
|
tellId: tell.id,
|
|
218
124
|
route: "launch",
|
|
@@ -220,8 +126,7 @@ async function startTurnDrive(input) {
|
|
|
220
126
|
fence: selected.admission.fence,
|
|
221
127
|
deliveredAt: input.now(),
|
|
222
128
|
})));
|
|
223
|
-
|
|
224
|
-
void selected.completion.then(() => requests.stopAdmission());
|
|
129
|
+
void selected.completion.then(() => requests.stopAdmission(), () => undefined);
|
|
225
130
|
return {
|
|
226
131
|
turnSequence: turn.sequence,
|
|
227
132
|
drive: selected,
|
|
@@ -289,6 +194,9 @@ function pumpReceipts(writers) {
|
|
|
289
194
|
function observeReceiptFailure(receiptPump) {
|
|
290
195
|
return receiptPump.then(() => new Promise(() => { }), (error) => Promise.reject(error));
|
|
291
196
|
}
|
|
197
|
+
function observeCompletionFailure(drive) {
|
|
198
|
+
return drive.completion.then(() => new Promise(() => { }), (error) => ({ kind: "completion-failed", error }));
|
|
199
|
+
}
|
|
292
200
|
async function submitPendingLiveTells(writers, pending, attempted, tellLive) {
|
|
293
201
|
const { input, turnSequence, drive, writeWitness, mayWrite } = writers;
|
|
294
202
|
for (const tell of pending) {
|
|
@@ -348,6 +256,7 @@ async function consumeTurnDrive(input, active) {
|
|
|
348
256
|
const mayWrite = () => writesOpen && !input.supervisor.signal.aborted;
|
|
349
257
|
const writers = { input, turnSequence, drive, writeWitness, mayWrite };
|
|
350
258
|
const receiptFailure = observeReceiptFailure(pumpReceipts(writers));
|
|
259
|
+
const completionFailure = observeCompletionFailure(drive);
|
|
351
260
|
const iterator = drive.events[Symbol.asyncIterator]();
|
|
352
261
|
let pending = iterator.next();
|
|
353
262
|
let liveTells = true;
|
|
@@ -375,7 +284,12 @@ async function consumeTurnDrive(input, active) {
|
|
|
375
284
|
...(tellObservation === null ? [] : [tellObservation]),
|
|
376
285
|
receiptFailure,
|
|
377
286
|
requests.failure,
|
|
287
|
+
completionFailure,
|
|
378
288
|
]);
|
|
289
|
+
if (next.kind === "completion-failed") {
|
|
290
|
+
requests.stopAdmission();
|
|
291
|
+
throw next.error;
|
|
292
|
+
}
|
|
379
293
|
if (next.kind === "heart") {
|
|
380
294
|
heart = next.observation;
|
|
381
295
|
continue;
|
|
@@ -60,11 +60,5 @@ export declare function isParsedAkumaCommand(command: Readonly<{
|
|
|
60
60
|
export declare function renderAkumaRootRows(): readonly string[];
|
|
61
61
|
export declare function renderAkumaHelp(action: AkumaAction): string;
|
|
62
62
|
export declare function renderAkumaUsage(action: AkumaAction): string;
|
|
63
|
-
export declare function parseAkumaCatalogPath(value: string): Readonly<{
|
|
64
|
-
kind: "archetypes";
|
|
65
|
-
} | {
|
|
66
|
-
kind: "akuma";
|
|
67
|
-
archetype?: string;
|
|
68
|
-
}> | null;
|
|
69
63
|
export declare function parseAkumaCommand(argv: readonly string[]): ParsedAkumaCommand;
|
|
70
64
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CliUsageError, isBlankInput, usageLine } from "../usage.js";
|
|
2
|
-
import {
|
|
2
|
+
import { parseAkuId } from "../../akuma/identity.js";
|
|
3
3
|
import { parseDuration as decodeDuration } from "../../duration.js";
|
|
4
4
|
import { parseAkumaAlias, parseAkumaGlob } from "../../identity/selector.js";
|
|
5
5
|
import { decodeAllowedActions } from "../../akuma/allowed.js";
|
|
@@ -84,16 +84,6 @@ export function renderAkumaHelp(action) {
|
|
|
84
84
|
export function renderAkumaUsage(action) {
|
|
85
85
|
return usageLine(AKUMA_COMMAND_SPECS[action].usage);
|
|
86
86
|
}
|
|
87
|
-
export function parseAkumaCatalogPath(value) {
|
|
88
|
-
if (value === "aku" || value === "aku/")
|
|
89
|
-
return { kind: "archetypes" };
|
|
90
|
-
if (value === "aku/*/*")
|
|
91
|
-
return { kind: "akuma" };
|
|
92
|
-
const match = /^aku\/([^/]+)\/?$/u.exec(value);
|
|
93
|
-
if (match === null)
|
|
94
|
-
return null;
|
|
95
|
-
return { kind: "akuma", archetype: archetypeName(match[1]) };
|
|
96
|
-
}
|
|
97
87
|
function stringFlag(value, diagnostic, fail) {
|
|
98
88
|
if (typeof value !== "string")
|
|
99
89
|
fail(diagnostic);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { InvocationResult } from "../result.js";
|
|
2
|
+
import type { ParsedCommand } from "../parse.js";
|
|
3
|
+
import type { WorktreeHooks } from "../../library/configuration.js";
|
|
4
|
+
import type { Repo } from "../../library/repo.js";
|
|
5
|
+
import type { Settings } from "../../settings.js";
|
|
6
|
+
import type { WorldRoot } from "../../world.js";
|
|
7
|
+
type ContractMutation = Extract<ParsedCommand, {
|
|
8
|
+
command: "bind" | "amend" | "deliver" | "review" | "arc" | "abandon" | "audit";
|
|
9
|
+
}>;
|
|
10
|
+
type InvocationEdge = Readonly<{
|
|
11
|
+
environment: NodeJS.ProcessEnv;
|
|
12
|
+
readStdin: () => Promise<string>;
|
|
13
|
+
}>;
|
|
14
|
+
export type ContractMutationInput = Readonly<{
|
|
15
|
+
parsed: ContractMutation;
|
|
16
|
+
repo: Repo;
|
|
17
|
+
edge: InvocationEdge;
|
|
18
|
+
scope: string;
|
|
19
|
+
configuration?: Settings;
|
|
20
|
+
hooks: WorktreeHooks;
|
|
21
|
+
establishWorld: () => Promise<WorldRoot>;
|
|
22
|
+
forwarded?: true;
|
|
23
|
+
}>;
|
|
24
|
+
export declare function invokeContractMutation(input: ContractMutationInput): Promise<InvocationResult>;
|
|
25
|
+
export {};
|