@astrosheep/keiyaku 4.5.24 → 4.5.26
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 +10 -0
- package/build/src/akuma/akuma-handle.js +18 -18
- package/build/src/akuma/akuma-instance.d.ts +5 -10
- package/build/src/akuma/akuma-instance.js +55 -40
- package/build/src/akuma/akuma-observe.d.ts +40 -7
- package/build/src/akuma/akuma-observe.js +51 -16
- package/build/src/akuma/akuma-product.d.ts +1 -2
- package/build/src/akuma/akuma-product.js +8 -5
- package/build/src/akuma/akuma.d.ts +2 -0
- package/build/src/akuma/body.d.ts +1 -1
- package/build/src/akuma/body.js +48 -30
- package/build/src/akuma/call-request.d.ts +0 -1
- package/build/src/akuma/call-request.js +1 -2
- package/build/src/akuma/fleet-execution.d.ts +3 -1
- package/build/src/akuma/fleet-execution.js +30 -71
- package/build/src/akuma/fleet-observation.d.ts +13 -2
- package/build/src/akuma/fleet-observation.js +2 -1
- package/build/src/akuma/fleet-request.js +3 -2
- package/build/src/akuma/heart/timeline.d.ts +1 -1
- package/build/src/akuma/heart/timeline.js +5 -5
- package/build/src/akuma/projection-read.js +37 -7
- package/build/src/akuma/projection.d.ts +1 -0
- package/build/src/akuma/projection.js +24 -9
- package/build/src/akuma/providers/pi/index.d.ts +2 -1
- package/build/src/akuma/providers/pi/index.js +2 -1
- package/build/src/akuma/publication.js +7 -4
- package/build/src/akuma-body.js +1 -0
- package/build/src/cli/commands/akuma-invoke.d.ts +1 -0
- package/build/src/cli/commands/akuma-invoke.js +16 -3
- package/build/src/cli/invoke.js +1 -0
- package/build/src/cli/render/akuma-activity.d.ts +13 -5
- package/build/src/cli/render/akuma-activity.js +118 -112
- package/build/src/cli/render/akuma-tool.js +5 -3
- package/build/src/library/address.d.ts +1 -1
- package/build/src/library/address.js +10 -8
- package/build/src/library/akuma-creation.d.ts +3 -0
- package/build/src/library/akuma-creation.js +111 -46
- package/build/src/library/composition.d.ts +3 -1
- package/build/src/library/fleet.d.ts +7 -1
- package/build/src/library/fleet.js +35 -9
- package/build/src/library/keiyaku.d.ts +3 -1
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/package.json +3 -3
|
@@ -51,7 +51,7 @@ export declare function addressAkuma(input: UncheckedAkumaAddressInput): Promise
|
|
|
51
51
|
}>>;
|
|
52
52
|
export declare function addressAkumaSet(input: UncheckedAkumaAddressInput): Promise<Readonly<{
|
|
53
53
|
path: WorldRoot;
|
|
54
|
-
/** The complete selected set in canonical order
|
|
54
|
+
/** The complete selected set in canonical order. */
|
|
55
55
|
ids: readonly AkuId[];
|
|
56
56
|
/** The same set in the caller's selector order, for surfaces that name the selection as chosen. */
|
|
57
57
|
orderedIds: readonly AkuId[];
|
|
@@ -39,12 +39,6 @@ export function resolveNamedAddress(input) {
|
|
|
39
39
|
if (selector.startsWith("aku/"))
|
|
40
40
|
return { kind: "akuma", id: parseAkuId(selector).id };
|
|
41
41
|
const alias = parseAkumaAlias(selector);
|
|
42
|
-
if (input.report.contracts.kind === "failed") {
|
|
43
|
-
throw new TypeError("cannot resolve a named selector while the Contract world is failed");
|
|
44
|
-
}
|
|
45
|
-
if (input.aliases.kind === "failed") {
|
|
46
|
-
throw new TypeError("cannot resolve a named selector while Alias authority is failed");
|
|
47
|
-
}
|
|
48
42
|
const contractMatches = (input.report.contracts.kind === "present" ? input.report.contracts.value.rows : []).filter((row) => row.disposition === "active" &&
|
|
49
43
|
row.workspace === "worktree" &&
|
|
50
44
|
row.worktreePath !== null &&
|
|
@@ -54,12 +48,20 @@ export function resolveNamedAddress(input) {
|
|
|
54
48
|
: null;
|
|
55
49
|
if (contractMatches.length > 0 && aliasId !== null)
|
|
56
50
|
throw new TypeError(`ambiguous selector matches Contract and Akuma: ${selector}`);
|
|
51
|
+
// A readable alias selects its Akuma independently. Contract composition can
|
|
52
|
+
// enrich the subsequent observation, but cannot erase this core address.
|
|
53
|
+
if (aliasId !== null)
|
|
54
|
+
return { kind: "akuma", id: aliasId };
|
|
57
55
|
if (contractMatches.length === 1)
|
|
58
56
|
return { kind: "contract", id: contractMatches[0].id };
|
|
59
57
|
if (contractMatches.length > 1)
|
|
60
58
|
throw new TypeError(`ambiguous Contract selector: ${selector}`);
|
|
61
|
-
if (
|
|
62
|
-
|
|
59
|
+
if (input.report.contracts.kind === "failed") {
|
|
60
|
+
throw new TypeError("cannot resolve a named selector while the Contract world is failed");
|
|
61
|
+
}
|
|
62
|
+
if (input.aliases.kind === "failed") {
|
|
63
|
+
throw new TypeError("cannot resolve a named selector while Alias authority is failed");
|
|
64
|
+
}
|
|
63
65
|
throw new TypeError(`unknown selector: ${selector}`);
|
|
64
66
|
}
|
|
65
67
|
export async function addressAkuma(input) {
|
|
@@ -55,11 +55,13 @@ export type CallInput = Readonly<{
|
|
|
55
55
|
allowed?: readonly AllowedAction[];
|
|
56
56
|
schema?: Schema<unknown>;
|
|
57
57
|
initiator?: string;
|
|
58
|
+
signal?: AbortSignal;
|
|
58
59
|
}>;
|
|
59
60
|
export type CallObservation = Readonly<{
|
|
60
61
|
kind: "detached";
|
|
61
62
|
}> | Readonly<{
|
|
62
63
|
kind: "observed";
|
|
64
|
+
reason: "completed" | "deadline";
|
|
63
65
|
status: AkumaStatus;
|
|
64
66
|
}> | Readonly<{
|
|
65
67
|
kind: "failed";
|
|
@@ -85,6 +87,7 @@ export type BornCall = Readonly<{
|
|
|
85
87
|
execution: CallExecution;
|
|
86
88
|
mode: "wait" | "detach";
|
|
87
89
|
timeoutMs: number;
|
|
90
|
+
signal?: AbortSignal;
|
|
88
91
|
dispatch: DispatchStage;
|
|
89
92
|
alias: AliasStage;
|
|
90
93
|
schemaTell?: Readonly<{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** @architectureCompositionRoot */
|
|
2
2
|
import { appendFile } from "node:fs/promises";
|
|
3
3
|
import { moveAlias } from "../alias/index.js";
|
|
4
|
+
import { defaultWaitComplete } from "../akuma/akuma.js";
|
|
4
5
|
import { createAkumaProduct } from "../akuma/akuma-product.js";
|
|
5
6
|
import { pathsForAkuId } from "../akuma/identity.js";
|
|
6
7
|
import { readSoul } from "../akuma/heart/index.js";
|
|
@@ -83,6 +84,13 @@ function callTimeout(value, mode) {
|
|
|
83
84
|
}
|
|
84
85
|
return value;
|
|
85
86
|
}
|
|
87
|
+
function callSignal(value) {
|
|
88
|
+
if (value === undefined)
|
|
89
|
+
return undefined;
|
|
90
|
+
if (!(value instanceof AbortSignal))
|
|
91
|
+
throw new TypeError("signal must be an AbortSignal");
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
86
94
|
function callSeat(contract) {
|
|
87
95
|
if (contract === undefined)
|
|
88
96
|
return undefined;
|
|
@@ -91,14 +99,17 @@ function callSeat(contract) {
|
|
|
91
99
|
throw new TypeError("contract must be a Keiyaku");
|
|
92
100
|
return seat;
|
|
93
101
|
}
|
|
94
|
-
async function observeCall(handle, mode, timeoutMs) {
|
|
102
|
+
async function observeCall(handle, mode, timeoutMs, signal) {
|
|
95
103
|
if (mode === "detach") {
|
|
96
104
|
return { kind: "detached" };
|
|
97
105
|
}
|
|
98
106
|
try {
|
|
99
|
-
|
|
107
|
+
const observed = await handle.waitReceipt(undefined, { timeoutMs, ...(signal === undefined ? {} : { signal }) });
|
|
108
|
+
return { kind: "observed", reason: observed.reason, status: observed.status };
|
|
100
109
|
}
|
|
101
110
|
catch (error) {
|
|
111
|
+
if (signal?.aborted)
|
|
112
|
+
throw error;
|
|
102
113
|
return { kind: "failed", failure: integrationFailure(error) };
|
|
103
114
|
}
|
|
104
115
|
}
|
|
@@ -257,8 +268,9 @@ const CALL_INPUT_KEYS = [
|
|
|
257
268
|
"allowed",
|
|
258
269
|
"schema",
|
|
259
270
|
"initiator",
|
|
271
|
+
"signal",
|
|
260
272
|
];
|
|
261
|
-
async function
|
|
273
|
+
async function parseCallInput(input) {
|
|
262
274
|
const values = requireInput(input, "Keiyaku.call input");
|
|
263
275
|
onlyKeys(values, CALL_INPUT_KEYS, "Keiyaku.call input");
|
|
264
276
|
const path = await World.prove(nonblank(values.path, "path"));
|
|
@@ -269,55 +281,81 @@ async function prepareCall(input, context) {
|
|
|
269
281
|
const cwd = values.cwd === undefined ? undefined : nonblank(values.cwd, "cwd");
|
|
270
282
|
const mode = callMode(values.mode);
|
|
271
283
|
const timeoutMs = callTimeout(values.timeoutMs, mode);
|
|
284
|
+
const signal = callSignal(values.signal);
|
|
272
285
|
const home = homeOption(values.home);
|
|
273
286
|
const settings = settingsOption(values.settings);
|
|
274
287
|
const alias = values.alias === undefined ? undefined : parseAkumaAlias(nonblank(values.alias, "alias"));
|
|
275
288
|
const seat = callSeat(values.contract);
|
|
276
|
-
|
|
289
|
+
return {
|
|
290
|
+
values,
|
|
277
291
|
path,
|
|
278
|
-
...(cwd === undefined ? {} : { cwd }),
|
|
279
|
-
...(seat === undefined ? {} : { contract: values.contract }),
|
|
280
|
-
});
|
|
281
|
-
const world = akumaWorld(path, home, settings, context);
|
|
282
|
-
const call = {
|
|
283
292
|
archetype,
|
|
284
|
-
|
|
293
|
+
body,
|
|
285
294
|
...(initiator === undefined ? {} : { initiator }),
|
|
286
|
-
...(readonlyRequested === undefined ? {} : {
|
|
287
|
-
...(
|
|
288
|
-
|
|
295
|
+
...(readonlyRequested === undefined ? {} : { readonlyRequested }),
|
|
296
|
+
...(cwd === undefined ? {} : { cwd }),
|
|
297
|
+
mode,
|
|
298
|
+
timeoutMs,
|
|
299
|
+
...(signal === undefined ? {} : { signal }),
|
|
300
|
+
...(home === undefined ? {} : { home }),
|
|
301
|
+
...(settings === undefined ? {} : { settings }),
|
|
302
|
+
...(alias === undefined ? {} : { alias }),
|
|
303
|
+
seat,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function callAdmissionInput(input, execution) {
|
|
307
|
+
return {
|
|
308
|
+
archetype: input.archetype,
|
|
309
|
+
...(input.values.schema === undefined ? { body: input.body } : {}),
|
|
310
|
+
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
311
|
+
...(input.readonlyRequested === undefined ? {} : { readonly: input.readonlyRequested }),
|
|
312
|
+
...(input.values.allowed === undefined ? {} : { allowed: input.values.allowed }),
|
|
313
|
+
...(input.values.schema === undefined ? {} : { schema: input.values.schema }),
|
|
289
314
|
...(execution === undefined ? {} : { cwd: execution.cwd }),
|
|
315
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
290
316
|
};
|
|
317
|
+
}
|
|
318
|
+
function schemaTell(input) {
|
|
319
|
+
if (input.values.schema === undefined)
|
|
320
|
+
return undefined;
|
|
321
|
+
return {
|
|
322
|
+
body: input.body,
|
|
323
|
+
schema: input.values.schema,
|
|
324
|
+
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
async function prepareCall(input, context) {
|
|
328
|
+
const parsed = await parseCallInput(input);
|
|
329
|
+
const execution = await resolveCallExecution({
|
|
330
|
+
path: parsed.path,
|
|
331
|
+
...(parsed.cwd === undefined ? {} : { cwd: parsed.cwd }),
|
|
332
|
+
...(parsed.seat === undefined ? {} : { contract: parsed.values.contract }),
|
|
333
|
+
});
|
|
334
|
+
const world = akumaWorld(parsed.path, parsed.home, parsed.settings, context);
|
|
291
335
|
const { born, akuma } = await admitCall({
|
|
292
|
-
path,
|
|
336
|
+
path: parsed.path,
|
|
293
337
|
world,
|
|
294
|
-
call:
|
|
338
|
+
call: callAdmissionInput(parsed, execution),
|
|
295
339
|
context: execution === undefined ? {} : { cwdCanonical: true },
|
|
296
|
-
...(settings === undefined ? {} : { settings }),
|
|
297
|
-
...(seat === undefined ? {} : { contractId: seat.id }),
|
|
340
|
+
...(parsed.settings === undefined ? {} : { settings: parsed.settings }),
|
|
341
|
+
...(parsed.seat === undefined ? {} : { contractId: parsed.seat.id }),
|
|
298
342
|
});
|
|
299
343
|
const completedExecution = execution ?? born.execution;
|
|
300
|
-
const dispatch = seat === undefined
|
|
344
|
+
const dispatch = parsed.seat === undefined
|
|
301
345
|
? { kind: "none" }
|
|
302
|
-
: await dispatchStage({ repository: seat.scope, akuId: akuma, contractId: seat.id });
|
|
303
|
-
const aliasStage = await resolveAliasStage(path, alias, dispatch, akuma);
|
|
346
|
+
: await dispatchStage({ repository: parsed.seat.scope, akuId: akuma, contractId: parsed.seat.id });
|
|
347
|
+
const aliasStage = await resolveAliasStage(parsed.path, parsed.alias, dispatch, akuma);
|
|
348
|
+
const initialSchemaTell = schemaTell(parsed);
|
|
304
349
|
return {
|
|
305
|
-
path,
|
|
350
|
+
path: parsed.path,
|
|
306
351
|
born,
|
|
307
352
|
execution: completedExecution,
|
|
308
|
-
mode,
|
|
309
|
-
timeoutMs,
|
|
353
|
+
mode: parsed.mode,
|
|
354
|
+
timeoutMs: parsed.timeoutMs,
|
|
355
|
+
...(parsed.signal === undefined ? {} : { signal: parsed.signal }),
|
|
310
356
|
dispatch,
|
|
311
357
|
alias: aliasStage,
|
|
312
|
-
...(
|
|
313
|
-
? {}
|
|
314
|
-
: {
|
|
315
|
-
schemaTell: {
|
|
316
|
-
body,
|
|
317
|
-
schema: values.schema,
|
|
318
|
-
...(initiator === undefined ? {} : { initiator }),
|
|
319
|
-
},
|
|
320
|
-
}),
|
|
358
|
+
...(initialSchemaTell === undefined ? {} : { schemaTell: initialSchemaTell }),
|
|
321
359
|
};
|
|
322
360
|
}
|
|
323
361
|
async function publishCall(born, execution) {
|
|
@@ -325,31 +363,58 @@ async function publishCall(born, execution) {
|
|
|
325
363
|
const contractId = born.dispatch.kind === "dispatched" ? born.dispatch.dispatch.contractId : undefined;
|
|
326
364
|
const handle = await world.publish(born.born, {
|
|
327
365
|
...(contractId === undefined ? {} : { contractId }),
|
|
328
|
-
});
|
|
366
|
+
}, born.signal);
|
|
367
|
+
const deadline = born.mode === "wait" ? performance.now() + born.timeoutMs : undefined;
|
|
368
|
+
const remaining = () => (deadline === undefined ? born.timeoutMs : Math.max(0, deadline - performance.now()));
|
|
369
|
+
const schemaSignal = () => {
|
|
370
|
+
if (deadline === undefined)
|
|
371
|
+
return born.signal;
|
|
372
|
+
const timeout = AbortSignal.timeout(Math.ceil(remaining()));
|
|
373
|
+
return born.signal === undefined ? timeout : AbortSignal.any([born.signal, timeout]);
|
|
374
|
+
};
|
|
329
375
|
const readonly = (await handle.status()).readonly;
|
|
330
376
|
let schemaAnswer;
|
|
331
377
|
if (born.schemaTell !== undefined) {
|
|
332
378
|
const tell = born.schemaTell;
|
|
333
379
|
// Birth publishes Soul before its prompt-free Body has necessarily settled.
|
|
334
380
|
// Schema admission still belongs to Tell, after that initial Body is idle.
|
|
335
|
-
const pending = handle
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
381
|
+
const pending = handle
|
|
382
|
+
.wait(undefined, {
|
|
383
|
+
timeoutMs: remaining(),
|
|
384
|
+
...(born.signal === undefined ? {} : { signal: born.signal }),
|
|
385
|
+
})
|
|
386
|
+
.then(async (initial) => {
|
|
387
|
+
if (initial.life !== "asleep" || !defaultWaitComplete(initial) || (deadline !== undefined && remaining() <= 0))
|
|
388
|
+
return undefined;
|
|
389
|
+
const signal = schemaSignal();
|
|
390
|
+
try {
|
|
391
|
+
return execution.channel.kind === "body-request"
|
|
392
|
+
? await requestForwardedFleetTellAnswer({
|
|
393
|
+
directory: execution.channel.directory,
|
|
394
|
+
target: handle.id,
|
|
395
|
+
body: tell.body,
|
|
396
|
+
schema: tell.schema,
|
|
397
|
+
...(tell.initiator === undefined ? {} : { initiator: tell.initiator }),
|
|
398
|
+
...(signal === undefined ? {} : { signal }),
|
|
399
|
+
})
|
|
400
|
+
: await PublicAkuma.select(born.path, handle.id).tell(tell.body, {
|
|
401
|
+
schema: tell.schema,
|
|
402
|
+
...(tell.initiator === undefined ? {} : { initiator: tell.initiator }),
|
|
403
|
+
...(signal === undefined ? {} : { signal }),
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
catch (error) {
|
|
407
|
+
if (born.signal?.aborted || deadline === undefined || remaining() > 0)
|
|
408
|
+
throw error;
|
|
409
|
+
return undefined;
|
|
410
|
+
}
|
|
411
|
+
});
|
|
347
412
|
if (born.mode === "detach")
|
|
348
413
|
void pending.catch(() => undefined);
|
|
349
414
|
else
|
|
350
415
|
schemaAnswer = await pending;
|
|
351
416
|
}
|
|
352
|
-
const observation = await observeCall(handle, born.mode, born.
|
|
417
|
+
const observation = await observeCall(handle, born.mode, remaining(), born.signal);
|
|
353
418
|
return {
|
|
354
419
|
kind: "called",
|
|
355
420
|
akuma: handle.id,
|
|
@@ -85,7 +85,8 @@ export declare function composeLibrary(context?: ExecutionContext, composition?:
|
|
|
85
85
|
};
|
|
86
86
|
}>;
|
|
87
87
|
wait: (input: Parameters<typeof waitAkuma>[0]) => Promise<{
|
|
88
|
-
|
|
88
|
+
mode: "any" | "all";
|
|
89
|
+
reason: "deadline" | "completed";
|
|
89
90
|
observations: {
|
|
90
91
|
status: {
|
|
91
92
|
id: import("./keiyaku.js").AkuId;
|
|
@@ -238,6 +239,7 @@ export declare function composeLibrary(context?: ExecutionContext, composition?:
|
|
|
238
239
|
};
|
|
239
240
|
})[];
|
|
240
241
|
omitted: number;
|
|
242
|
+
openingSequence?: number | undefined;
|
|
241
243
|
} | {
|
|
242
244
|
reportedChanges: readonly {
|
|
243
245
|
sequence: number;
|
|
@@ -8,10 +8,12 @@ import { type AkumaKillResult, type AkumaObservation, type AkumaObservationStage
|
|
|
8
8
|
export type AkumaWaitInput = AkumaSetAddressInput & Readonly<{
|
|
9
9
|
completion?: "any" | "all";
|
|
10
10
|
timeoutMs?: number;
|
|
11
|
+
signal?: AbortSignal;
|
|
11
12
|
}>;
|
|
12
13
|
export type AkumaTellInput = AkumaAddressInput & Readonly<{
|
|
13
14
|
body: string;
|
|
14
15
|
initiator?: string;
|
|
16
|
+
signal?: AbortSignal;
|
|
15
17
|
}>;
|
|
16
18
|
export type { TellResult, TellWake } from "../akuma/akuma.js";
|
|
17
19
|
export type { CreatedTaskObservation } from "../task/created-observation.js";
|
|
@@ -20,6 +22,10 @@ export type { AkumaKillResult, AkumaObservation, AkumaObservationStage, AkumaTel
|
|
|
20
22
|
export type AkumaInterruptInput = AkumaAddressInput & Readonly<{
|
|
21
23
|
body: string;
|
|
22
24
|
initiator?: string;
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
}>;
|
|
27
|
+
export type AkumaKillInput = AkumaSetAddressInput & Readonly<{
|
|
28
|
+
signal?: AbortSignal;
|
|
23
29
|
}>;
|
|
24
30
|
export type AkumaInterruptResult = Readonly<{
|
|
25
31
|
id: AkumaStatus["id"];
|
|
@@ -60,7 +66,7 @@ export type AkumaHistoryResult = Readonly<{
|
|
|
60
66
|
}>;
|
|
61
67
|
export declare function statusAkuma(input: AkumaAddressInput): Promise<AkumaObservation>;
|
|
62
68
|
export declare function waitAkuma(input: AkumaWaitInput, execution?: ExecutionContext, observer?: WaitObserver): Promise<AkumaWaitResult>;
|
|
63
|
-
export declare function killAkuma(input:
|
|
69
|
+
export declare function killAkuma(input: AkumaKillInput, execution?: ExecutionContext): Promise<AkumaKillResult>;
|
|
64
70
|
export declare function tellAkuma(input: AkumaTellInput, execution?: ExecutionContext): Promise<AkumaTellResult>;
|
|
65
71
|
export declare function interruptAkuma(input: AkumaInterruptInput): Promise<AkumaInterruptResult>;
|
|
66
72
|
export declare function historyAkuma(input: AkumaHistoryInput): Promise<AkumaHistoryResult>;
|
|
@@ -115,6 +115,13 @@ function timeout(value) {
|
|
|
115
115
|
}
|
|
116
116
|
return value;
|
|
117
117
|
}
|
|
118
|
+
function signal(value) {
|
|
119
|
+
if (value === undefined)
|
|
120
|
+
return undefined;
|
|
121
|
+
if (!(value instanceof AbortSignal))
|
|
122
|
+
throw new TypeError("signal must be an AbortSignal");
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
118
125
|
async function attachWaitAssociations(path, repo, result) {
|
|
119
126
|
const created = await createdTasksFor(path, result.observations.map((observation) => observation.status));
|
|
120
127
|
const discharged = placementDischarged(repo);
|
|
@@ -151,7 +158,7 @@ export async function statusAkuma(input) {
|
|
|
151
158
|
export async function waitAkuma(input, execution = localExecutionContext(), observer) {
|
|
152
159
|
const values = requireInput(input, "Keiyaku.wait input");
|
|
153
160
|
for (const key of Object.keys(values)) {
|
|
154
|
-
if (!["path", "akuma", "repo", "completion", "timeoutMs"].includes(key)) {
|
|
161
|
+
if (!["path", "akuma", "repo", "completion", "timeoutMs", "signal"].includes(key)) {
|
|
155
162
|
throw new TypeError(`Keiyaku.wait input has unknown field: ${key}`);
|
|
156
163
|
}
|
|
157
164
|
}
|
|
@@ -163,21 +170,24 @@ export async function waitAkuma(input, execution = localExecutionContext(), obse
|
|
|
163
170
|
// An omitted mode is any: a plural wait returns when any selected Akuma is complete.
|
|
164
171
|
const selected = completion ?? "any";
|
|
165
172
|
const timeoutMs = timeout(values.timeoutMs);
|
|
173
|
+
const callerSignal = signal(values.signal);
|
|
166
174
|
const channel = executionChannel(execution);
|
|
167
175
|
const repo = values.repo;
|
|
168
176
|
if (channel.kind === "body-request") {
|
|
169
177
|
return await attachWaitAssociations(addressed.path, repo, await requestForwardedFleetWait({
|
|
170
178
|
directory: channel.directory,
|
|
171
|
-
targets: addressed.
|
|
179
|
+
targets: addressed.orderedIds,
|
|
172
180
|
completion: selected,
|
|
173
181
|
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
182
|
+
...(callerSignal === undefined ? {} : { signal: callerSignal }),
|
|
174
183
|
}));
|
|
175
184
|
}
|
|
176
185
|
return await attachWaitAssociations(addressed.path, repo, await executeWaitAkuma({
|
|
177
186
|
path: addressed.path,
|
|
178
|
-
ids: addressed.
|
|
187
|
+
ids: addressed.orderedIds,
|
|
179
188
|
completion: selected,
|
|
180
189
|
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
190
|
+
...(callerSignal === undefined ? {} : { signal: callerSignal }),
|
|
181
191
|
identity: waitIdentityFacts(addressed.path, repo),
|
|
182
192
|
selectionOrder: addressed.orderedIds,
|
|
183
193
|
...(observer?.selected === undefined ? {} : { onSelected: observer.selected }),
|
|
@@ -185,28 +195,38 @@ export async function waitAkuma(input, execution = localExecutionContext(), obse
|
|
|
185
195
|
}));
|
|
186
196
|
}
|
|
187
197
|
export async function killAkuma(input, execution = localExecutionContext()) {
|
|
188
|
-
const
|
|
198
|
+
const values = requireInput(input, "Keiyaku.kill input");
|
|
199
|
+
for (const key of Object.keys(values)) {
|
|
200
|
+
if (!["path", "akuma", "repo", "signal"].includes(key)) {
|
|
201
|
+
throw new TypeError(`Keiyaku.kill input has unknown field: ${key}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const callerSignal = signal(values.signal);
|
|
205
|
+
const addressed = await addressAkumaSet(setAddress(values));
|
|
189
206
|
const channel = executionChannel(execution);
|
|
190
207
|
if (channel.kind === "body-request") {
|
|
191
208
|
return await requestForwardedFleetKill({
|
|
192
209
|
directory: channel.directory,
|
|
193
|
-
targets: addressed.
|
|
210
|
+
targets: addressed.orderedIds,
|
|
211
|
+
...(callerSignal === undefined ? {} : { signal: callerSignal }),
|
|
194
212
|
});
|
|
195
213
|
}
|
|
196
214
|
return await executeKillAkuma({
|
|
197
215
|
path: addressed.path,
|
|
198
|
-
ids: addressed.
|
|
216
|
+
ids: addressed.orderedIds,
|
|
217
|
+
...(callerSignal === undefined ? {} : { signal: callerSignal }),
|
|
199
218
|
});
|
|
200
219
|
}
|
|
201
220
|
export async function tellAkuma(input, execution = localExecutionContext()) {
|
|
202
221
|
const values = requireInput(input, "Keiyaku.tell input");
|
|
203
222
|
for (const key of Object.keys(values)) {
|
|
204
|
-
if (!["path", "akuma", "body", "repo", "initiator"].includes(key)) {
|
|
223
|
+
if (!["path", "akuma", "body", "repo", "initiator", "signal"].includes(key)) {
|
|
205
224
|
throw new TypeError(`Keiyaku.tell input has unknown field: ${key}`);
|
|
206
225
|
}
|
|
207
226
|
}
|
|
208
227
|
if (typeof values.body !== "string")
|
|
209
228
|
throw new TypeError("body must be a string");
|
|
229
|
+
const callerSignal = signal(values.signal);
|
|
210
230
|
const addressed = await addressAkuma(directAddress(values));
|
|
211
231
|
const channel = executionChannel(execution);
|
|
212
232
|
if (channel.kind === "body-request") {
|
|
@@ -215,6 +235,7 @@ export async function tellAkuma(input, execution = localExecutionContext()) {
|
|
|
215
235
|
target: addressed.id,
|
|
216
236
|
body: values.body,
|
|
217
237
|
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
238
|
+
...(callerSignal === undefined ? {} : { signal: callerSignal }),
|
|
218
239
|
});
|
|
219
240
|
}
|
|
220
241
|
return await executeTellAkuma({
|
|
@@ -222,20 +243,25 @@ export async function tellAkuma(input, execution = localExecutionContext()) {
|
|
|
222
243
|
id: addressed.id,
|
|
223
244
|
body: values.body,
|
|
224
245
|
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
246
|
+
...(callerSignal === undefined ? {} : { signal: callerSignal }),
|
|
225
247
|
});
|
|
226
248
|
}
|
|
227
249
|
export async function interruptAkuma(input) {
|
|
228
250
|
const values = requireInput(input, "Keiyaku.interrupt input");
|
|
229
251
|
for (const key of Object.keys(values)) {
|
|
230
|
-
if (!["path", "akuma", "body", "repo", "initiator"].includes(key)) {
|
|
252
|
+
if (!["path", "akuma", "body", "repo", "initiator", "signal"].includes(key)) {
|
|
231
253
|
throw new TypeError(`Keiyaku.interrupt input has unknown field: ${key}`);
|
|
232
254
|
}
|
|
233
255
|
}
|
|
234
256
|
if (typeof values.body !== "string")
|
|
235
257
|
throw new TypeError("body must be a string");
|
|
258
|
+
const callerSignal = signal(values.signal);
|
|
236
259
|
const addressed = await addressAkuma(directAddress(values));
|
|
237
260
|
const handle = source(addressed.path).selectHandle({ id: addressed.id });
|
|
238
|
-
const receipt = await handle.interrupt(values.body,
|
|
261
|
+
const receipt = await handle.interrupt(values.body, {
|
|
262
|
+
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
263
|
+
...(callerSignal === undefined ? {} : { signal: callerSignal }),
|
|
264
|
+
});
|
|
239
265
|
const observation = await observeAkumaStage(addressed.path, addressed.id, values.repo);
|
|
240
266
|
return { id: addressed.id, receipt, observation };
|
|
241
267
|
}
|
|
@@ -117,7 +117,8 @@ export declare const Keiyaku: Readonly<{
|
|
|
117
117
|
};
|
|
118
118
|
}>;
|
|
119
119
|
wait: (input: Parameters<typeof import("./fleet.js").waitAkuma>[0]) => Promise<{
|
|
120
|
-
|
|
120
|
+
mode: "any" | "all";
|
|
121
|
+
reason: "deadline" | "completed";
|
|
121
122
|
observations: {
|
|
122
123
|
status: {
|
|
123
124
|
id: import("../akuma/identity.js").AkuId;
|
|
@@ -270,6 +271,7 @@ export declare const Keiyaku: Readonly<{
|
|
|
270
271
|
};
|
|
271
272
|
})[];
|
|
272
273
|
omitted: number;
|
|
274
|
+
openingSequence?: number | undefined;
|
|
273
275
|
} | {
|
|
274
276
|
reportedChanges: readonly {
|
|
275
277
|
sequence: number;
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrosheep/keiyaku",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.26",
|
|
4
4
|
"workspaces": [
|
|
5
5
|
"plugins/*"
|
|
6
6
|
],
|
|
@@ -80,8 +80,8 @@
|
|
|
80
80
|
"dependencies": {
|
|
81
81
|
"@agentclientprotocol/sdk": "^1.3.0",
|
|
82
82
|
"@anthropic-ai/claude-agent-sdk": "^0.3.226",
|
|
83
|
-
"@astrosheep/keiyaku-plugin-square": "0.1.
|
|
84
|
-
"@astrosheep/square": "^0.3.
|
|
83
|
+
"@astrosheep/keiyaku-plugin-square": "0.1.6",
|
|
84
|
+
"@astrosheep/square": "^0.3.57",
|
|
85
85
|
"@earendil-works/pi-coding-agent": "0.85.1",
|
|
86
86
|
"@opencode-ai/sdk": "1.18.3",
|
|
87
87
|
"cross-spawn": "^7.0.6",
|