@astrosheep/keiyaku 4.0.1 → 4.0.2
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 +137 -5
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -35
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +98 -58
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +152 -53
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +23 -14
- package/build/src/akuma/akuma.js +120 -104
- package/build/src/akuma/archetype.d.ts +7 -6
- package/build/src/akuma/archetype.js +68 -41
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +408 -213
- package/build/src/akuma/heart/facts.d.ts +25 -34
- package/build/src/akuma/heart/facts.js +18 -7
- package/build/src/akuma/heart/index.d.ts +39 -42
- package/build/src/akuma/heart/index.js +134 -93
- package/build/src/akuma/heart/rows.d.ts +9 -31
- package/build/src/akuma/heart/rows.js +26 -44
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +7 -15
- package/build/src/akuma/heart/soul.d.ts +8 -0
- package/build/src/akuma/heart/soul.js +136 -0
- package/build/src/akuma/heart/storage.d.ts +28 -14
- package/build/src/akuma/heart/storage.js +86 -26
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +6 -1
- package/build/src/akuma/index.js +6 -0
- package/build/src/akuma/projection.d.ts +117 -38
- package/build/src/akuma/projection.js +208 -97
- package/build/src/akuma/provider-recipe.d.ts +24 -0
- package/build/src/akuma/provider-recipe.js +100 -0
- package/build/src/akuma/provider.d.ts +12 -4
- package/build/src/akuma/provider.js +117 -70
- package/build/src/akuma/providers/acp/core.d.ts +19 -0
- package/build/src/akuma/providers/acp/core.js +159 -0
- package/build/src/akuma/providers/acp/events.d.ts +20 -0
- package/build/src/akuma/providers/acp/events.js +73 -0
- package/build/src/akuma/providers/acp/index.d.ts +12 -0
- package/build/src/akuma/providers/acp/index.js +94 -0
- package/build/src/akuma/providers/claude/events.js +66 -13
- package/build/src/akuma/providers/claude/index.d.ts +2 -1
- package/build/src/akuma/providers/claude/index.js +35 -21
- package/build/src/akuma/providers/codex-app-server/events.js +4 -1
- package/build/src/akuma/providers/codex-app-server/index.d.ts +3 -3
- package/build/src/akuma/providers/codex-app-server/index.js +24 -31
- package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
- package/build/src/akuma/providers/grok-build/index.js +70 -0
- package/build/src/akuma/providers/index.d.ts +5 -3
- package/build/src/akuma/providers/index.js +24 -59
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +40 -34
- package/build/src/akuma/providers/opencode-sdk/events.js +220 -101
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +3 -2
- package/build/src/akuma/providers/opencode-sdk/index.js +233 -128
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +11 -26
- package/build/src/akuma/providers/opencode-sdk/session.js +10 -9
- package/build/src/akuma/providers/pi/events.js +49 -11
- package/build/src/akuma/providers/pi/index.d.ts +1 -1
- package/build/src/akuma/providers/pi/index.js +50 -21
- package/build/src/akuma/publication.d.ts +3 -3
- package/build/src/akuma/publication.js +28 -40
- package/build/src/akuma/requests.d.ts +9 -7
- package/build/src/akuma/requests.js +92 -65
- package/build/src/alias/index.d.ts +2 -2
- package/build/src/alias/index.js +10 -10
- package/build/src/body/decode.js +7 -1
- package/build/src/body/region.d.ts +2 -0
- package/build/src/body/region.js +77 -7
- package/build/src/cli/accepted.d.ts +17 -13
- package/build/src/cli/accepted.js +72 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +4 -3
- package/build/src/cli/commands/akuma-invoke.js +14 -9
- package/build/src/cli/commands/akuma.d.ts +13 -3
- package/build/src/cli/commands/akuma.js +67 -34
- package/build/src/cli/commands/contract.d.ts +18 -5
- package/build/src/cli/commands/contract.js +9 -3
- package/build/src/cli/commands/task-invoke.d.ts +17 -4
- package/build/src/cli/commands/task-invoke.js +43 -20
- package/build/src/cli/commands/task-query.d.ts +5 -0
- package/build/src/cli/commands/task-query.js +247 -0
- package/build/src/cli/commands/task.d.ts +3 -1
- package/build/src/cli/commands/task.js +51 -13
- package/build/src/cli/coordinates.d.ts +18 -0
- package/build/src/cli/coordinates.js +120 -0
- package/build/src/cli/draft.d.ts +8 -0
- package/build/src/cli/draft.js +96 -0
- package/build/src/cli/invoke.d.ts +4 -3
- package/build/src/cli/invoke.js +160 -179
- package/build/src/cli/main.js +34 -6
- package/build/src/cli/parse.d.ts +9 -2
- package/build/src/cli/parse.js +29 -7
- package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
- package/build/src/cli/render/akuma-tool-command.js +144 -0
- package/build/src/cli/render/akuma-tool.d.ts +2 -2
- package/build/src/cli/render/akuma-tool.js +30 -4
- package/build/src/cli/render/akuma.d.ts +1 -0
- package/build/src/cli/render/akuma.js +211 -116
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +192 -79
- package/build/src/cli/render/kanshi.js +263 -168
- package/build/src/cli/render/receipt.d.ts +19 -0
- package/build/src/cli/render/receipt.js +106 -0
- package/build/src/cli/render/refusal.d.ts +16 -2
- package/build/src/cli/render/refusal.js +88 -20
- package/build/src/cli/render/region.d.ts +2 -0
- package/build/src/cli/render/region.js +17 -0
- package/build/src/cli/render/task.d.ts +2 -1
- package/build/src/cli/render/task.js +223 -60
- package/build/src/cli/render/terminal.d.ts +7 -0
- package/build/src/cli/render/terminal.js +46 -0
- package/build/src/cli/render/text.js +6 -3
- package/build/src/cli/result.d.ts +115 -20
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +6 -5
- package/build/src/contract-worktree.js +95 -57
- package/build/src/coordination/durable-file.d.ts +4 -3
- package/build/src/coordination/durable-file.js +29 -25
- package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
- package/build/src/coordination/sqlite-transaction-lock.js +22 -5
- package/build/src/core/facts/fold.js +1 -6
- package/build/src/core/facts/gate.d.ts +1 -0
- package/build/src/core/facts/gate.js +1 -0
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +0 -11
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +1 -7
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +4 -1
- package/build/src/dispatch/index.d.ts +2 -2
- package/build/src/dispatch/index.js +17 -17
- package/build/src/git/admission.d.ts +1 -1
- package/build/src/git/admission.js +11 -11
- package/build/src/git/hooks.js +13 -13
- package/build/src/git/integration.d.ts +14 -15
- package/build/src/git/integration.js +80 -44
- package/build/src/git/observe.d.ts +5 -3
- package/build/src/git/observe.js +18 -12
- package/build/src/git/read-observation.js +9 -9
- package/build/src/git/reconcile.d.ts +2 -0
- package/build/src/git/reconcile.js +138 -95
- package/build/src/git/repository.d.ts +27 -19
- package/build/src/git/repository.js +155 -83
- package/build/src/git/scratch.d.ts +7 -3
- package/build/src/git/scratch.js +44 -37
- package/build/src/git/target-placement.d.ts +40 -4
- package/build/src/git/target-placement.js +221 -101
- package/build/src/git/tender.d.ts +6 -5
- package/build/src/git/tender.js +24 -43
- package/build/src/git/terminal-seal.d.ts +1 -1
- package/build/src/git/terminal-seal.js +7 -5
- package/build/src/git/workspace.d.ts +36 -4
- package/build/src/git/workspace.js +53 -18
- package/build/src/identity/selector.js +1 -1
- package/build/src/index.d.ts +3 -3
- package/build/src/index.js +1 -1
- package/build/src/kanshi/index.d.ts +2 -2
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +2 -1
- package/build/src/kanshi/read.js +118 -27
- package/build/src/kanshi/report.d.ts +50 -0
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +32 -0
- package/build/src/library/address.d.ts +12 -3
- package/build/src/library/address.js +77 -46
- package/build/src/library/akuma-creation.d.ts +6 -1
- package/build/src/library/akuma-creation.js +86 -13
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.js +4 -4
- package/build/src/library/catalog.d.ts +1 -1
- package/build/src/library/catalog.js +5 -8
- package/build/src/library/contract.d.ts +5 -6
- package/build/src/library/contract.js +11 -35
- package/build/src/library/delivery.d.ts +2 -1
- package/build/src/library/fleet.d.ts +2 -2
- package/build/src/library/fleet.js +35 -71
- package/build/src/library/keiyaku.d.ts +3 -2
- package/build/src/library/keiyaku.js +1 -0
- package/build/src/library/mutation.d.ts +7 -6
- package/build/src/library/mutation.js +23 -25
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/region.d.ts +12 -0
- package/build/src/library/region.js +15 -1
- package/build/src/library/repo.d.ts +4 -16
- package/build/src/library/repo.js +13 -38
- package/build/src/protocol/attempt.js +6 -6
- package/build/src/protocol/bind.js +4 -4
- package/build/src/protocol/intent.d.ts +15 -2
- package/build/src/protocol/intent.js +21 -6
- package/build/src/protocol/operations.d.ts +73 -22
- package/build/src/protocol/operations.js +292 -88
- package/build/src/protocol/outcome.d.ts +9 -3
- package/build/src/protocol/outcome.js +3 -1
- package/build/src/protocol/placement.d.ts +15 -4
- package/build/src/protocol/placement.js +58 -25
- package/build/src/protocol/read/status.d.ts +8 -1
- package/build/src/protocol/read/status.js +61 -14
- package/build/src/runtime/proc/line-rpc.d.ts +3 -8
- package/build/src/runtime/proc/line-rpc.js +16 -43
- package/build/src/runtime/proc/run.d.ts +15 -29
- package/build/src/runtime/proc/run.js +113 -105
- package/build/src/runtime/proc/stdio.d.ts +18 -0
- package/build/src/runtime/proc/stdio.js +58 -0
- package/build/src/settings.d.ts +2 -2
- package/build/src/settings.js +8 -8
- package/build/src/settlement/fence.d.ts +0 -4
- package/build/src/settlement/fence.js +0 -9
- package/build/src/settlement/holder.d.ts +11 -1
- package/build/src/settlement/holder.js +25 -0
- package/build/src/settlement/settle.d.ts +1 -1
- package/build/src/settlement/settle.js +52 -89
- package/build/src/task/board.d.ts +3 -3
- package/build/src/task/board.js +6 -9
- package/build/src/task/compose.d.ts +1 -1
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +14 -14
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +19 -7
- package/build/src/task/index.js +42 -23
- package/build/src/task/operations.d.ts +15 -9
- package/build/src/task/operations.js +78 -48
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +2 -2
- package/build/src/task/store.js +40 -25
- package/build/src/verification/execution.d.ts +4 -2
- package/build/src/verification/execution.js +9 -5
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +13 -2
- package/build/src/world.js +81 -48
- package/package.json +3 -2
- package/build/src/protocol/read/audit.d.ts +0 -31
- package/build/src/protocol/read/audit.js +0 -55
package/build/src/akuma/akuma.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { readdir } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
-
import { spawnAkumaBody } from "./body.js";
|
|
5
|
-
import { HeldAkumaLeash, activitySlice, life, probeLeash, readHeart, readLastAnsweredTurn, readForkPoint, readKill, readSeal, readSoul, recordTell, requestPause, requestStop, } from "./heart/index.js";
|
|
4
|
+
import { CONTROL_RESPONSE_MS, spawnAkumaBody } from "./body.js";
|
|
5
|
+
import { HeldAkumaLeash, activitySlice, life, lifeAt, probeLeash, readHeart, readLastAnsweredTurn, readForkPoint, readKill, readSeal, readSoul, recordTell, requestPause, requestStop, } from "./heart/index.js";
|
|
6
6
|
import { akuIdFromDirectoryName, akumaPaths, akumaRunRoot, parseAkuId, pathsForAkuId, archetypeName, } from "./identity.js";
|
|
7
|
-
import {
|
|
7
|
+
import { ordinarySelectedCount, ordinarySnapshotBudget, projectTurns, selectActivitySnapshot, selectHistory, selectSnapshot, } from "./projection.js";
|
|
8
8
|
import { listArchetypes as readArchetypes, loadArchetype } from "./archetype.js";
|
|
9
9
|
import { publishAkuma } from "./publication.js";
|
|
10
|
-
import {
|
|
10
|
+
import { resolveProviderExecution } from "./providers/index.js";
|
|
11
11
|
import { injectedBodyRequests, requestBodyCall } from "./requests.js";
|
|
12
|
-
import { probeProcessTree, putDownProcessTree } from "../runtime/proc/run.js";
|
|
13
12
|
import { settings as readSettings } from "../settings.js";
|
|
14
13
|
const POLL_MS = 25;
|
|
15
|
-
const KILL_GRACE_MS = 1_000;
|
|
16
14
|
export class AkumaNotBornError extends Error {
|
|
17
15
|
id;
|
|
18
16
|
kind = "akuma-not-born";
|
|
@@ -27,7 +25,7 @@ function wait(milliseconds) {
|
|
|
27
25
|
}
|
|
28
26
|
async function takeLeashUntil(paths, deadline) {
|
|
29
27
|
for (;;) {
|
|
30
|
-
const leash = HeldAkumaLeash.try(paths);
|
|
28
|
+
const leash = await HeldAkumaLeash.try(paths);
|
|
31
29
|
if (leash !== null)
|
|
32
30
|
return leash;
|
|
33
31
|
if (performance.now() >= deadline)
|
|
@@ -35,9 +33,9 @@ async function takeLeashUntil(paths, deadline) {
|
|
|
35
33
|
await wait(POLL_MS);
|
|
36
34
|
}
|
|
37
35
|
}
|
|
38
|
-
function recordTellBody(paths, akuma, body) {
|
|
36
|
+
async function recordTellBody(paths, akuma, body) {
|
|
39
37
|
const id = randomUUID();
|
|
40
|
-
const admitted = recordTell(paths, { kind: "tell", id, body, recordedAt: new Date().toISOString() });
|
|
38
|
+
const admitted = await recordTell(paths, { kind: "tell", id, body, recordedAt: new Date().toISOString() });
|
|
41
39
|
if (admitted.kind === "not-born")
|
|
42
40
|
throw new AkumaNotBornError(akuma);
|
|
43
41
|
return { kind: "recorded", tellId: admitted.tell.id };
|
|
@@ -54,56 +52,57 @@ async function wakeTell(paths, tellId) {
|
|
|
54
52
|
};
|
|
55
53
|
}
|
|
56
54
|
}
|
|
57
|
-
function
|
|
58
|
-
|
|
59
|
-
return { kind: "gone", end: null };
|
|
60
|
-
const probe = probeProcessTree(snapshot.latestBody.collar);
|
|
61
|
-
if (probe.kind === "gone")
|
|
62
|
-
return { kind: "gone", end: snapshot.latestBody.end ?? null };
|
|
63
|
-
return probe;
|
|
64
|
-
}
|
|
65
|
-
function bornListRow(paths, expected, snapshot = readHeart(paths)) {
|
|
55
|
+
async function bornListRow(paths, expected, snapshot) {
|
|
56
|
+
snapshot ??= await readHeart(paths);
|
|
66
57
|
if (snapshot.soul === null)
|
|
67
58
|
throw new AkumaNotBornError(expected);
|
|
68
59
|
if (snapshot.soul.id !== expected)
|
|
69
60
|
throw new Error("Akuma soul does not match its coordinate");
|
|
70
|
-
const
|
|
61
|
+
const currentLife = life({
|
|
62
|
+
leash: await probeLeash(paths),
|
|
63
|
+
body: snapshot.latestBody,
|
|
64
|
+
kill: snapshot.latestKill,
|
|
65
|
+
});
|
|
71
66
|
return {
|
|
72
67
|
id: snapshot.soul.id,
|
|
73
68
|
archetype: snapshot.soul.archetype,
|
|
74
69
|
...(snapshot.soul.description === undefined ? {} : { description: snapshot.soul.description }),
|
|
75
|
-
life:
|
|
76
|
-
|
|
70
|
+
life: currentLife,
|
|
71
|
+
lifeAt: lifeAt(currentLife, snapshot.latestBody, snapshot.latestKill, snapshot.soul.createdAt),
|
|
77
72
|
confinement: snapshot.soul.confinement,
|
|
78
73
|
pending: snapshot.pending.map((tell) => tell.id),
|
|
79
74
|
};
|
|
80
75
|
}
|
|
81
|
-
function bornStatus(paths, expected,
|
|
82
|
-
const snapshot = readHeart(paths);
|
|
76
|
+
async function bornStatus(paths, expected, budget) {
|
|
77
|
+
const snapshot = await readHeart(paths);
|
|
83
78
|
if (snapshot.soul === null)
|
|
84
79
|
throw new AkumaNotBornError(expected);
|
|
85
|
-
const current = bornListRow(paths, expected, snapshot);
|
|
80
|
+
const current = await bornListRow(paths, expected, snapshot);
|
|
86
81
|
const resumeUnsupported = current.life === "stranded"
|
|
87
82
|
&& snapshot.latestSession?.provider === snapshot.soul.provider.name
|
|
88
|
-
&&
|
|
83
|
+
&& resolveProviderExecution(snapshot.soul.provider).adapter.resume === undefined;
|
|
84
|
+
const slice = await activitySlice(paths, { limit: Number.MAX_SAFE_INTEGER });
|
|
89
85
|
return {
|
|
90
86
|
id: current.id,
|
|
91
87
|
life: current.life,
|
|
92
|
-
|
|
88
|
+
...(snapshot.soul.readonly === undefined ? {} : { readonly: snapshot.soul.readonly }),
|
|
93
89
|
...(resumeUnsupported ? { strandedReason: "resume-unsupported" } : {}),
|
|
94
|
-
timeline:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
lowestRetained: slice.lowestRetained,
|
|
98
|
-
highest: slice.highest,
|
|
99
|
-
profile,
|
|
100
|
-
});
|
|
101
|
-
})(),
|
|
90
|
+
timeline: budget === undefined
|
|
91
|
+
? selectActivitySnapshot(slice.rows)
|
|
92
|
+
: selectSnapshot(projectTurns(slice.rows), budget),
|
|
102
93
|
};
|
|
103
94
|
}
|
|
104
|
-
/** Package-internal
|
|
105
|
-
export function readActionFeedbackStatus(worldPath, id) {
|
|
106
|
-
return bornStatus(pathsForAkuId(worldPath, id), id
|
|
95
|
+
/** Package-internal action observation; it uses the same snapshot selector as status. */
|
|
96
|
+
export async function readActionFeedbackStatus(worldPath, id) {
|
|
97
|
+
return await bornStatus(pathsForAkuId(worldPath, id), id);
|
|
98
|
+
}
|
|
99
|
+
/** Package-internal budgeted observation; Fleet allocates, Akuma still selects. */
|
|
100
|
+
export async function readBudgetedStatus(worldPath, id, input) {
|
|
101
|
+
if (!Number.isSafeInteger(input.ordinaryBudget) || input.ordinaryBudget < 0) {
|
|
102
|
+
throw new TypeError("ordinary budget must be a nonnegative safe integer");
|
|
103
|
+
}
|
|
104
|
+
const status = await bornStatus(pathsForAkuId(worldPath, id), id, ordinarySnapshotBudget(input.ordinaryBudget));
|
|
105
|
+
return { status, ordinarySelected: ordinarySelectedCount(status.timeline) };
|
|
107
106
|
}
|
|
108
107
|
function diagnostic(error) {
|
|
109
108
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -118,10 +117,10 @@ export class AkumaHandle {
|
|
|
118
117
|
get paths() {
|
|
119
118
|
return pathsForAkuId(this.worldPath, this.id);
|
|
120
119
|
}
|
|
121
|
-
status() {
|
|
122
|
-
return bornStatus(this.paths, this.id);
|
|
120
|
+
async status() {
|
|
121
|
+
return await bornStatus(this.paths, this.id);
|
|
123
122
|
}
|
|
124
|
-
history(input = {}) {
|
|
123
|
+
async history(input = {}) {
|
|
125
124
|
if (input.before !== undefined && input.since !== undefined) {
|
|
126
125
|
throw new TypeError("Akuma history before and since are mutually exclusive");
|
|
127
126
|
}
|
|
@@ -134,12 +133,15 @@ export class AkumaHandle {
|
|
|
134
133
|
if (!Number.isSafeInteger(limit) || limit <= 0 || limit > 5_000) {
|
|
135
134
|
throw new TypeError("Akuma history limit must be a positive safe integer no greater than 5000");
|
|
136
135
|
}
|
|
137
|
-
const slice = activitySlice(this.paths, {
|
|
136
|
+
const slice = await activitySlice(this.paths, {
|
|
138
137
|
...(input.before === undefined ? {} : { before: input.before }),
|
|
139
138
|
...(input.since === undefined ? {} : { since: input.since }),
|
|
140
139
|
limit: 5_000,
|
|
141
140
|
});
|
|
142
|
-
return
|
|
141
|
+
return selectHistory(projectTurns(slice.rows, {
|
|
142
|
+
lowestRetained: slice.lowestRetained,
|
|
143
|
+
highest: slice.highest,
|
|
144
|
+
}), {
|
|
143
145
|
...(input.before === undefined ? {} : { before: input.before }),
|
|
144
146
|
...(input.since === undefined ? {} : { since: input.since }),
|
|
145
147
|
limit,
|
|
@@ -152,46 +154,49 @@ export class AkumaHandle {
|
|
|
152
154
|
}
|
|
153
155
|
const deadline = options.timeoutMs === undefined ? undefined : performance.now() + options.timeoutMs;
|
|
154
156
|
for (;;) {
|
|
155
|
-
const status = this.status();
|
|
157
|
+
const status = await this.status();
|
|
156
158
|
if (predicate(status) || (deadline !== undefined && performance.now() >= deadline))
|
|
157
159
|
return status;
|
|
158
160
|
await wait(deadline === undefined ? POLL_MS : Math.min(POLL_MS, Math.max(0, deadline - performance.now())));
|
|
159
161
|
}
|
|
160
162
|
}
|
|
161
163
|
async tell(body) {
|
|
162
|
-
const recorded = recordTellBody(this.paths, this.id, body);
|
|
164
|
+
const recorded = await recordTellBody(this.paths, this.id, body);
|
|
163
165
|
return await wakeTell(this.paths, recorded.tellId);
|
|
164
166
|
}
|
|
165
167
|
async interrupt(body) {
|
|
166
|
-
|
|
168
|
+
const request = await requestPause(this.paths, new Date().toISOString());
|
|
169
|
+
if (request.kind === "not-born") {
|
|
167
170
|
throw new AkumaNotBornError(this.id);
|
|
168
171
|
}
|
|
169
172
|
let putDown = "was-idle";
|
|
170
|
-
let leash = HeldAkumaLeash.try(this.paths);
|
|
173
|
+
let leash = await HeldAkumaLeash.try(this.paths);
|
|
171
174
|
if (leash === null) {
|
|
172
|
-
leash = await takeLeashUntil(this.paths, performance.now() +
|
|
175
|
+
leash = await takeLeashUntil(this.paths, performance.now() + CONTROL_RESPONSE_MS);
|
|
173
176
|
putDown = "self-aborted";
|
|
174
177
|
}
|
|
175
178
|
if (leash === null) {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
const body = (await readHeart(this.paths)).latestBody;
|
|
180
|
+
return { kind: "unavailable", evidence: body?.sequence === request.body.sequence && body.hung !== undefined
|
|
181
|
+
? "hung"
|
|
182
|
+
: "unavailable" };
|
|
183
|
+
}
|
|
184
|
+
const settledBody = (await readHeart(this.paths)).latestBody;
|
|
185
|
+
if (settledBody?.sequence !== request.body.sequence || settledBody.end === undefined) {
|
|
186
|
+
try {
|
|
187
|
+
await leash.clearPause(this.paths);
|
|
181
188
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return { kind: "unstoppable", evidence };
|
|
189
|
+
finally {
|
|
190
|
+
leash.release();
|
|
185
191
|
}
|
|
186
|
-
|
|
187
|
-
if (leash === null)
|
|
188
|
-
return { kind: "unstoppable", evidence: "leash-held-after-put-down" };
|
|
189
|
-
putDown = "collar";
|
|
192
|
+
return { kind: "unavailable", evidence: "untidy" };
|
|
190
193
|
}
|
|
194
|
+
if (request.body.end !== undefined || settledBody.end !== "put-down")
|
|
195
|
+
putDown = "was-idle";
|
|
191
196
|
let recorded;
|
|
192
197
|
try {
|
|
193
198
|
const id = randomUUID();
|
|
194
|
-
const admitted = leash.recordInterruptTell(this.paths, {
|
|
199
|
+
const admitted = await leash.recordInterruptTell(this.paths, {
|
|
195
200
|
kind: "tell",
|
|
196
201
|
id,
|
|
197
202
|
body,
|
|
@@ -207,15 +212,15 @@ export class AkumaHandle {
|
|
|
207
212
|
return { kind: "interrupted", putDown, tell: await wakeTell(this.paths, recorded.tellId) };
|
|
208
213
|
}
|
|
209
214
|
async fork(input) {
|
|
210
|
-
const source = readSoul(this.paths);
|
|
215
|
+
const source = await readSoul(this.paths);
|
|
211
216
|
if (source === null)
|
|
212
217
|
throw new AkumaNotBornError(this.id);
|
|
213
218
|
if (source.id !== this.id)
|
|
214
219
|
throw new Error("Akuma soul does not match its coordinate");
|
|
215
|
-
const adapter =
|
|
220
|
+
const adapter = resolveProviderExecution(source.provider).adapter;
|
|
216
221
|
if (adapter.fork === undefined)
|
|
217
222
|
return { kind: "provider-cannot-fork", provider: source.provider.name };
|
|
218
|
-
const point = readForkPoint(this.paths, input.at);
|
|
223
|
+
const point = await readForkPoint(this.paths, input.at);
|
|
219
224
|
if (point === null)
|
|
220
225
|
return { kind: "unknown-history", at: input.at };
|
|
221
226
|
if (point.provider !== source.provider.name)
|
|
@@ -248,6 +253,7 @@ export class AkumaHandle {
|
|
|
248
253
|
...(source.description === undefined ? {} : { description: source.description }),
|
|
249
254
|
provider: source.provider,
|
|
250
255
|
options: source.options,
|
|
256
|
+
...(source.readonly === undefined ? {} : { readonly: source.readonly }),
|
|
251
257
|
cwd: source.cwd,
|
|
252
258
|
origin: { kind: "fork", parent: this.id, at: input.at },
|
|
253
259
|
confinement: source.confinement,
|
|
@@ -263,28 +269,31 @@ export class AkumaHandle {
|
|
|
263
269
|
}
|
|
264
270
|
async kill() {
|
|
265
271
|
const at = new Date().toISOString();
|
|
266
|
-
const request = requestStop(this.paths, at);
|
|
267
|
-
if (request.kind
|
|
268
|
-
return
|
|
272
|
+
const request = await requestStop(this.paths, at);
|
|
273
|
+
if (request.kind !== "requested")
|
|
274
|
+
return request.kind;
|
|
269
275
|
const target = request.body;
|
|
270
|
-
const graceDeadline = performance.now() +
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
276
|
+
const graceDeadline = performance.now() + CONTROL_RESPONSE_MS;
|
|
277
|
+
const leash = await takeLeashUntil(this.paths, graceDeadline);
|
|
278
|
+
if (await readKill(this.paths, target.sequence) !== null) {
|
|
279
|
+
leash?.release();
|
|
274
280
|
return "killed";
|
|
275
|
-
const targetProbe = probeProcessTree(target.collar);
|
|
276
|
-
if (targetProbe.kind === "unverifiable")
|
|
277
|
-
return "unavailable";
|
|
278
|
-
if (targetProbe.kind === "alive") {
|
|
279
|
-
const evidence = await putDownProcessTree(target.collar);
|
|
280
|
-
if (evidence === "unavailable" || evidence === "alive-after-sigkill")
|
|
281
|
-
return evidence;
|
|
282
281
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
282
|
+
if (leash === null) {
|
|
283
|
+
if (await readKill(this.paths, target.sequence) !== null)
|
|
284
|
+
return "killed";
|
|
285
|
+
const body = (await readHeart(this.paths)).latestBody;
|
|
286
|
+
return body?.sequence === target.sequence && body.hung !== undefined ? "hung" : "unavailable";
|
|
287
|
+
}
|
|
286
288
|
try {
|
|
287
|
-
const
|
|
289
|
+
const settledBody = (await readHeart(this.paths)).latestBody;
|
|
290
|
+
if (settledBody?.sequence !== target.sequence)
|
|
291
|
+
return await readKill(this.paths, target.sequence) === null ? "unavailable" : "killed";
|
|
292
|
+
if (settledBody.end !== "put-down") {
|
|
293
|
+
await leash.clearStop(this.paths);
|
|
294
|
+
return "untidy";
|
|
295
|
+
}
|
|
296
|
+
const settled = await leash.settleStop(this.paths, target.sequence);
|
|
288
297
|
if (settled === null)
|
|
289
298
|
return "unavailable";
|
|
290
299
|
return "killed";
|
|
@@ -293,8 +302,8 @@ export class AkumaHandle {
|
|
|
293
302
|
leash.release();
|
|
294
303
|
}
|
|
295
304
|
}
|
|
296
|
-
lastAnswer() {
|
|
297
|
-
const turn = readLastAnsweredTurn(this.paths);
|
|
305
|
+
async lastAnswer() {
|
|
306
|
+
const turn = await readLastAnsweredTurn(this.paths);
|
|
298
307
|
return turn?.end?.outcome.kind === "answered"
|
|
299
308
|
? { kind: "answer", answer: turn.end.outcome.answer }
|
|
300
309
|
: { kind: "no-answer" };
|
|
@@ -312,24 +321,25 @@ export class Akuma {
|
|
|
312
321
|
throw new TypeError("Akuma.of root must be a WorldRoot");
|
|
313
322
|
return new Akuma(root, settings);
|
|
314
323
|
}
|
|
315
|
-
settings() {
|
|
316
|
-
return this.configuredSettings ?? readSettings({ root: this.path });
|
|
324
|
+
async settings() {
|
|
325
|
+
return this.configuredSettings ?? await readSettings({ root: this.path });
|
|
317
326
|
}
|
|
318
327
|
of(input) {
|
|
319
328
|
return new AkumaHandle(parseAkuId(input.id).id, this.path);
|
|
320
329
|
}
|
|
321
|
-
listArchetypes() {
|
|
322
|
-
return readArchetypes({ settings: this.settings() });
|
|
330
|
+
async listArchetypes() {
|
|
331
|
+
return readArchetypes({ settings: await this.settings() });
|
|
323
332
|
}
|
|
324
333
|
async call(input) {
|
|
325
334
|
const name = archetypeName(input.archetype);
|
|
326
|
-
const archetype = loadArchetype({ name, settings: this.settings() });
|
|
335
|
+
const archetype = await loadArchetype({ name, settings: await this.settings() });
|
|
327
336
|
const provider = archetype.adapter;
|
|
328
337
|
const cwd = resolve(input.cwd ?? this.path);
|
|
329
338
|
const recipe = Object.freeze({
|
|
330
339
|
...(archetype.description === undefined ? {} : { description: archetype.description }),
|
|
331
340
|
provider: archetype.provider,
|
|
332
341
|
options: archetype.options,
|
|
342
|
+
...(archetype.readonly === undefined ? {} : { readonly: archetype.readonly }),
|
|
333
343
|
confinement: provider.confinement({ cwd, options: archetype.options }),
|
|
334
344
|
});
|
|
335
345
|
const requests = injectedBodyRequests();
|
|
@@ -356,6 +366,7 @@ export class Akuma {
|
|
|
356
366
|
...(archetype.description === undefined ? {} : { description: archetype.description }),
|
|
357
367
|
provider: archetype.provider,
|
|
358
368
|
options: archetype.options,
|
|
369
|
+
...(archetype.readonly === undefined ? {} : { readonly: archetype.readonly }),
|
|
359
370
|
cwd,
|
|
360
371
|
origin: { kind: "direct" },
|
|
361
372
|
confinement: recipe.confinement,
|
|
@@ -365,7 +376,7 @@ export class Akuma {
|
|
|
365
376
|
});
|
|
366
377
|
return new AkumaHandle(published.id, this.path);
|
|
367
378
|
}
|
|
368
|
-
list(input = {}) {
|
|
379
|
+
async list(input = {}) {
|
|
369
380
|
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
370
381
|
throw new TypeError("Akuma list input must be an object");
|
|
371
382
|
}
|
|
@@ -376,7 +387,7 @@ export class Akuma {
|
|
|
376
387
|
const runRoot = akumaRunRoot(this.path);
|
|
377
388
|
let names;
|
|
378
389
|
try {
|
|
379
|
-
names =
|
|
390
|
+
names = (await readdir(runRoot, { withFileTypes: true }))
|
|
380
391
|
.filter((entry) => entry.isDirectory())
|
|
381
392
|
.map((entry) => entry.name)
|
|
382
393
|
.sort();
|
|
@@ -386,26 +397,31 @@ export class Akuma {
|
|
|
386
397
|
return { rows: [], searched: [runRoot] };
|
|
387
398
|
throw error;
|
|
388
399
|
}
|
|
389
|
-
const rows =
|
|
400
|
+
const rows = [];
|
|
401
|
+
for (const name of names) {
|
|
390
402
|
try {
|
|
391
403
|
const physical = akuIdFromDirectoryName(name);
|
|
392
404
|
if (selected !== undefined && physical.archetype !== selected)
|
|
393
|
-
|
|
405
|
+
continue;
|
|
394
406
|
const paths = akumaPaths({ runRoot, archetype: physical.archetype, suffix: physical.suffix });
|
|
395
|
-
const snapshot = readHeart(paths);
|
|
396
|
-
if (snapshot.soul !== null)
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
407
|
+
const snapshot = await readHeart(paths);
|
|
408
|
+
if (snapshot.soul !== null) {
|
|
409
|
+
rows.push(await bornListRow(paths, physical.id, snapshot));
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
if (await probeLeash(paths) === "held") {
|
|
413
|
+
rows.push({ id: physical.id, life: "unborn" });
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
const seal = await readSeal(paths);
|
|
417
|
+
rows.push(seal === null
|
|
418
|
+
? { id: physical.id, life: "unborn" }
|
|
419
|
+
: { id: physical.id, life: "stillborn", seal });
|
|
404
420
|
}
|
|
405
421
|
catch {
|
|
406
|
-
|
|
422
|
+
continue;
|
|
407
423
|
}
|
|
408
|
-
}
|
|
424
|
+
}
|
|
409
425
|
return {
|
|
410
426
|
rows,
|
|
411
427
|
searched: [runRoot],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Settings } from "../settings.js";
|
|
2
|
-
import {
|
|
3
|
-
import type
|
|
2
|
+
import type { ProviderAdapter } from "./provider.js";
|
|
3
|
+
import { type ProviderExecution, type ProviderOptions, type ReadonlyRestraint } from "./provider-recipe.js";
|
|
4
4
|
type DecodedArchetype = Readonly<{
|
|
5
5
|
name: string;
|
|
6
6
|
path: string;
|
|
@@ -18,22 +18,23 @@ type ArchetypeDefinition = DecodedArchetype & Readonly<{
|
|
|
18
18
|
}>;
|
|
19
19
|
type AdmittedArchetype = Omit<ArchetypeDefinition, "provider"> & Readonly<{
|
|
20
20
|
provider: ProviderExecution;
|
|
21
|
+
readonly?: ReadonlyRestraint;
|
|
21
22
|
}>;
|
|
22
23
|
export declare class AkumaArchetypeError extends Error {
|
|
23
24
|
readonly archetype: string;
|
|
24
25
|
readonly searched: readonly string[];
|
|
25
26
|
readonly reason: string;
|
|
26
27
|
readonly kind = "akuma-archetype";
|
|
27
|
-
constructor(archetype: string, searched: readonly string[], reason: string);
|
|
28
|
+
constructor(archetype: string, searched: readonly string[], reason: string, guidance?: string);
|
|
28
29
|
}
|
|
29
30
|
export declare function listArchetypes(input: Readonly<{
|
|
30
31
|
settings: Settings;
|
|
31
|
-
}>): readonly string[]
|
|
32
|
+
}>): Promise<readonly string[]>;
|
|
32
33
|
export declare function listArchetypeDefinitions(input: Readonly<{
|
|
33
34
|
settings: Settings;
|
|
34
|
-
}>): readonly ArchetypeCatalogRow[]
|
|
35
|
+
}>): Promise<readonly ArchetypeCatalogRow[]>;
|
|
35
36
|
export declare function loadArchetype(input: Readonly<{
|
|
36
37
|
name: string;
|
|
37
38
|
settings: Settings;
|
|
38
|
-
}>): AdmittedArchetype
|
|
39
|
+
}>): Promise<AdmittedArchetype>;
|
|
39
40
|
export {};
|