@astrosheep/keiyaku 4.0.4 → 4.0.6
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/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 +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +15 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +5 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +24 -4
- package/build/src/akuma/akuma.d.ts +2 -1
- package/build/src/akuma/akuma.js +27 -9
- package/build/src/akuma/allowed.d.ts +1 -1
- package/build/src/akuma/allowed.js +3 -10
- package/build/src/akuma/archetype.d.ts +3 -1
- package/build/src/akuma/archetype.js +11 -6
- package/build/src/akuma/body-turn.d.ts +64 -0
- package/build/src/akuma/body-turn.js +449 -0
- package/build/src/akuma/body.d.ts +4 -5
- package/build/src/akuma/body.js +9 -414
- package/build/src/akuma/heart/facts.d.ts +37 -9
- package/build/src/akuma/heart/facts.js +3 -1
- package/build/src/akuma/heart/index.d.ts +4 -13
- package/build/src/akuma/heart/index.js +14 -135
- package/build/src/akuma/heart/request-authority.d.ts +12 -0
- package/build/src/akuma/heart/request-authority.js +119 -0
- package/build/src/akuma/heart/request-rows.d.ts +16 -0
- package/build/src/akuma/heart/request-rows.js +88 -0
- package/build/src/akuma/heart/rows.d.ts +1 -28
- package/build/src/akuma/heart/rows.js +4 -138
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +11 -3
- package/build/src/akuma/heart/soul.js +0 -36
- package/build/src/akuma/heart/timeline.d.ts +1 -0
- package/build/src/akuma/heart/timeline.js +19 -0
- package/build/src/akuma/index.d.ts +1 -1
- package/build/src/akuma/nuke.d.ts +2 -0
- package/build/src/akuma/nuke.js +152 -0
- package/build/src/akuma/provider-recipe.js +1 -11
- package/build/src/akuma/provider.d.ts +4 -7
- package/build/src/akuma/providers/acp/config.d.ts +8 -0
- package/build/src/akuma/providers/acp/config.js +37 -0
- package/build/src/akuma/providers/acp/core.js +12 -2
- package/build/src/akuma/providers/acp/index.d.ts +1 -8
- package/build/src/akuma/providers/acp/index.js +2 -38
- package/build/src/akuma/providers/claude/index.d.ts +0 -4
- package/build/src/akuma/providers/claude/index.js +12 -3
- package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
- package/build/src/akuma/providers/codex-app-server/index.js +5 -2
- package/build/src/akuma/providers/grok-build/index.js +1 -2
- package/build/src/akuma/providers/index.d.ts +3 -2
- package/build/src/akuma/providers/index.js +36 -36
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
- package/build/src/akuma/providers/opencode-sdk/index.js +14 -4
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +2 -2
- package/build/src/akuma/providers/opencode-sdk/session.js +2 -2
- package/build/src/akuma/providers/pi/index.d.ts +1 -1
- package/build/src/akuma/providers/pi/index.js +29 -6
- package/build/src/akuma/request-serve.d.ts +88 -0
- package/build/src/akuma/request-serve.js +484 -0
- package/build/src/akuma/request-wire.d.ts +125 -0
- package/build/src/akuma/request-wire.js +383 -0
- package/build/src/akuma/requests.d.ts +28 -94
- package/build/src/akuma/requests.js +52 -562
- package/build/src/akuma-body.d.ts +7 -0
- package/build/src/akuma-body.js +69 -2
- package/build/src/alias/index.d.ts +1 -0
- package/build/src/alias/index.js +34 -1
- package/build/src/body/arc.js +4 -29
- package/build/src/body/decode.js +5 -39
- package/build/src/body/envelope.d.ts +7 -0
- package/build/src/body/envelope.js +37 -0
- package/build/src/cli/accepted.js +21 -9
- package/build/src/cli/commands/akuma-invoke.js +1 -0
- package/build/src/cli/commands/akuma.d.ts +1 -0
- package/build/src/cli/commands/akuma.js +13 -10
- package/build/src/cli/commands/contract.d.ts +28 -17
- package/build/src/cli/commands/contract.js +23 -17
- package/build/src/cli/commands/install.d.ts +2 -2
- package/build/src/cli/commands/install.js +6 -6
- package/build/src/cli/commands/nuke.d.ts +10 -0
- package/build/src/cli/commands/nuke.js +20 -0
- package/build/src/cli/commands/task-invoke.d.ts +15 -0
- package/build/src/cli/commands/task-invoke.js +144 -24
- package/build/src/cli/commands/task-query.d.ts +2 -2
- package/build/src/cli/commands/task-query.js +1 -2
- package/build/src/cli/commands/task.js +22 -22
- package/build/src/cli/coordinates.d.ts +6 -2
- package/build/src/cli/coordinates.js +12 -56
- package/build/src/cli/invoke.d.ts +5 -4
- package/build/src/cli/invoke.js +112 -58
- package/build/src/cli/main.d.ts +0 -2
- package/build/src/cli/main.js +4 -140
- package/build/src/cli/parse.d.ts +17 -4
- package/build/src/cli/parse.js +93 -15
- package/build/src/cli/render/akuma.js +111 -53
- package/build/src/cli/render/audit.js +2 -6
- package/build/src/cli/render/contract.js +61 -20
- package/build/src/cli/render/kanshi.js +15 -5
- package/build/src/cli/render/nuke.d.ts +3 -0
- package/build/src/cli/render/nuke.js +8 -0
- package/build/src/cli/render/receipt.js +28 -1
- package/build/src/cli/render/refusal.d.ts +2 -1
- package/build/src/cli/render/refusal.js +31 -0
- package/build/src/cli/render/terminal.d.ts +0 -2
- package/build/src/cli/render/terminal.js +0 -29
- package/build/src/cli/render/text.js +6 -1
- package/build/src/cli/result.d.ts +36 -9
- package/build/src/cli/runtime.d.ts +2 -0
- package/build/src/cli/runtime.js +140 -0
- package/build/src/cli/usage.d.ts +0 -2
- package/build/src/cli/usage.js +0 -4
- package/build/src/contract-worktree.d.ts +29 -14
- package/build/src/contract-worktree.js +131 -70
- package/build/src/core/facts/codec.js +9 -0
- package/build/src/core/facts/fold.js +13 -1
- package/build/src/core/facts/types.d.ts +8 -1
- package/build/src/core/subject.js +4 -3
- package/build/src/core/verbs/placement.d.ts +9 -1
- package/build/src/core/verbs/placement.js +24 -6
- package/build/src/core/verbs/reintegrate.d.ts +13 -0
- package/build/src/core/verbs/reintegrate.js +24 -0
- package/build/src/dispatch/index.d.ts +1 -1
- package/build/src/git/admission.d.ts +2 -1
- package/build/src/git/hooks.d.ts +2 -0
- package/build/src/git/hooks.js +34 -1
- package/build/src/git/integration.d.ts +9 -2
- package/build/src/git/integration.js +92 -1
- package/build/src/git/nuke.d.ts +2 -0
- package/build/src/git/nuke.js +97 -0
- package/build/src/git/observe.d.ts +2 -1
- package/build/src/git/observe.js +6 -5
- package/build/src/git/process.d.ts +28 -0
- package/build/src/git/process.js +94 -0
- package/build/src/git/read-observation.d.ts +2 -1
- package/build/src/git/read-observation.js +3 -2
- package/build/src/git/reconcile.d.ts +4 -1
- package/build/src/git/reconcile.js +42 -8
- package/build/src/git/repository.d.ts +2 -29
- package/build/src/git/repository.js +7 -118
- package/build/src/git/scratch.d.ts +1 -1
- package/build/src/git/scratch.js +1 -1
- package/build/src/git/target-placement.d.ts +3 -2
- package/build/src/git/target-placement.js +15 -14
- package/build/src/git/tender.d.ts +2 -1
- package/build/src/git/tender.js +4 -3
- package/build/src/git/terminal-seal.d.ts +2 -2
- package/build/src/git/terminal-seal.js +3 -6
- package/build/src/git/workspace.d.ts +4 -1
- package/build/src/git/workspace.js +1 -1
- package/build/src/index.d.ts +1 -2
- package/build/src/index.js +1 -1
- package/build/src/kanshi/read.js +5 -1
- package/build/src/library/address.js +7 -1
- package/build/src/library/akuma-creation.d.ts +1 -0
- package/build/src/library/akuma-creation.js +8 -1
- package/build/src/library/audit.d.ts +3 -1
- package/build/src/library/audit.js +2 -1
- package/build/src/library/bind.d.ts +2 -1
- package/build/src/library/bind.js +1 -1
- package/build/src/library/configuration.d.ts +1 -1
- package/build/src/library/configuration.js +52 -18
- package/build/src/library/contract.d.ts +59 -4
- package/build/src/library/contract.js +195 -34
- package/build/src/library/delivery.d.ts +4 -2
- package/build/src/library/fleet.d.ts +27 -7
- package/build/src/library/fleet.js +79 -39
- package/build/src/library/input.d.ts +0 -1
- package/build/src/library/input.js +0 -5
- package/build/src/library/keiyaku.d.ts +6 -2
- package/build/src/library/keiyaku.js +2 -0
- package/build/src/library/mutation.d.ts +3 -1
- package/build/src/library/mutation.js +3 -0
- package/build/src/library/nuke.d.ts +14 -0
- package/build/src/library/nuke.js +54 -0
- package/build/src/library/reconcile.d.ts +2 -1
- package/build/src/library/reconcile.js +8 -3
- package/build/src/library/refusal.d.ts +10 -1
- package/build/src/library/region.d.ts +1 -1
- package/build/src/library/repo.d.ts +4 -1
- package/build/src/library/repo.js +10 -4
- package/build/src/protocol/abandon.d.ts +9 -0
- package/build/src/protocol/abandon.js +15 -0
- package/build/src/protocol/amend.d.ts +16 -0
- package/build/src/protocol/amend.js +77 -0
- package/build/src/protocol/arc.d.ts +6 -0
- package/build/src/protocol/arc.js +12 -0
- package/build/src/protocol/attempt.d.ts +2 -1
- package/build/src/protocol/audit.d.ts +53 -0
- package/build/src/protocol/audit.js +147 -0
- package/build/src/protocol/bind.d.ts +1 -1
- package/build/src/protocol/completion.d.ts +42 -0
- package/build/src/protocol/completion.js +183 -0
- package/build/src/protocol/deliver.d.ts +49 -0
- package/build/src/protocol/deliver.js +261 -0
- package/build/src/protocol/intent.d.ts +2 -1
- package/build/src/protocol/intent.js +8 -2
- package/build/src/protocol/operations.d.ts +93 -202
- package/build/src/protocol/operations.js +23 -642
- package/build/src/protocol/placement.d.ts +12 -13
- package/build/src/protocol/placement.js +8 -19
- package/build/src/protocol/read/status.d.ts +17 -5
- package/build/src/protocol/read/status.js +57 -13
- package/build/src/protocol/reconcile.d.ts +35 -0
- package/build/src/protocol/reconcile.js +41 -0
- package/build/src/protocol/reintegrate.d.ts +31 -0
- package/build/src/protocol/reintegrate.js +74 -0
- package/build/src/protocol/review.d.ts +34 -0
- package/build/src/protocol/review.js +156 -0
- package/build/src/protocol/run.d.ts +1 -1
- package/build/src/runtime/proc/run.js +9 -5
- package/build/src/settlement/fence.d.ts +3 -1
- package/build/src/settlement/fence.js +24 -0
- package/build/src/settlement/holder.d.ts +1 -1
- package/build/src/settlement/settle.d.ts +1 -1
- package/build/src/settlement/settle.js +1 -2
- package/build/src/task/board.d.ts +0 -1
- package/build/src/task/board.js +0 -3
- package/build/src/task/compose.d.ts +2 -2
- package/build/src/task/compose.js +13 -11
- package/build/src/task/context.d.ts +14 -2
- package/build/src/task/context.js +30 -7
- package/build/src/task/index.d.ts +7 -6
- package/build/src/task/index.js +17 -145
- package/build/src/task/input.d.ts +18 -0
- package/build/src/task/input.js +189 -0
- package/build/src/task/mutation.d.ts +44 -0
- package/build/src/task/mutation.js +93 -0
- package/build/src/task/operations.d.ts +14 -6
- package/build/src/task/operations.js +57 -57
- package/build/src/task/store.d.ts +1 -0
- package/build/src/task/store.js +91 -3
- package/build/src/verification/execution.d.ts +1 -1
- package/build/src/workspace-place.d.ts +3 -4
- package/build/src/workspace-place.js +26 -15
- package/package.json +3 -3
package/build/src/akuma/body.js
CHANGED
|
@@ -1,159 +1,20 @@
|
|
|
1
1
|
import { fileURLToPath } from "node:url";
|
|
2
2
|
import { abortableDelay } from "./abort.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { BodySupervisor, driveTurn, turnRecipe } from "./body-turn.js";
|
|
4
|
+
import { HeldAkumaLeash, breakBody, endTurn, finishBodyIfIdle, heartExists, isHeartAbsent, readHeart, } from "./heart/index.js";
|
|
5
5
|
import { resolveProviderExecution } from "./providers/index.js";
|
|
6
|
-
import {
|
|
6
|
+
import { clearBodyRequestTransport, settleBodyRequests, } from "./request-serve.js";
|
|
7
7
|
import { spawnDetachedProcess, } from "../runtime/proc/run.js";
|
|
8
8
|
const LEASH_RETRY_MS = 25;
|
|
9
|
-
|
|
10
|
-
export const CONTROL_RESPONSE_MS = 1_000;
|
|
11
|
-
class BodySupervisor {
|
|
12
|
-
paths;
|
|
13
|
-
bodySequence;
|
|
14
|
-
leash;
|
|
15
|
-
signal;
|
|
16
|
-
controller = new AbortController();
|
|
17
|
-
finished = new AbortController();
|
|
18
|
-
observer;
|
|
19
|
-
waiter;
|
|
20
|
-
observation;
|
|
21
|
-
stopping;
|
|
22
|
-
constructor(paths, bodySequence, leash, observation) {
|
|
23
|
-
this.paths = paths;
|
|
24
|
-
this.bodySequence = bodySequence;
|
|
25
|
-
this.leash = leash;
|
|
26
|
-
this.signal = this.controller.signal;
|
|
27
|
-
this.observation = observation;
|
|
28
|
-
this.observer = this.observe();
|
|
29
|
-
}
|
|
30
|
-
static async open(paths, bodySequence, leash) {
|
|
31
|
-
return new BodySupervisor(paths, bodySequence, leash, await readHeart(paths));
|
|
32
|
-
}
|
|
33
|
-
get reason() { return this.stopping; }
|
|
34
|
-
current() { return this.observation; }
|
|
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) => { this.waiter = resolve; });
|
|
46
|
-
}
|
|
47
|
-
cancel(reason) {
|
|
48
|
-
if (this.stopping !== undefined)
|
|
49
|
-
return;
|
|
50
|
-
this.stopping = reason;
|
|
51
|
-
this.controller.abort(new Error(reason === "control"
|
|
52
|
-
? "Akuma Body interrupted by durable control"
|
|
53
|
-
: "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
|
-
this.cancel("heart-gone");
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (bodyControlRequested(snapshot, this.bodySequence)) {
|
|
75
|
-
this.cancel("control");
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
try {
|
|
79
|
-
await abortableDelay(BODY_CONTROL_OBSERVATION_MS, this.finished.signal);
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
await this.refresh();
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
if (await heartExists(this.paths))
|
|
89
|
-
throw error;
|
|
90
|
-
this.cancel("heart-gone");
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
function serializeEffects() {
|
|
97
|
-
let tail = Promise.resolve();
|
|
98
|
-
let failed = false;
|
|
99
|
-
let failure;
|
|
100
|
-
const serialize = async (effect) => {
|
|
101
|
-
const result = tail.then(effect);
|
|
102
|
-
tail = result.then(() => undefined, (error) => {
|
|
103
|
-
if (!failed)
|
|
104
|
-
failure = error;
|
|
105
|
-
failed = true;
|
|
106
|
-
});
|
|
107
|
-
return await result;
|
|
108
|
-
};
|
|
109
|
-
serialize.drain = async () => {
|
|
110
|
-
await tail;
|
|
111
|
-
if (failed)
|
|
112
|
-
throw failure;
|
|
113
|
-
};
|
|
114
|
-
return serialize;
|
|
115
|
-
}
|
|
9
|
+
export { CONTROL_RESPONSE_MS } from "./body-turn.js";
|
|
116
10
|
function missing(error) {
|
|
117
11
|
return isHeartAbsent(error) || error.code === "ENOENT";
|
|
118
12
|
}
|
|
119
|
-
async function writeProviderEvent(input, active, event) {
|
|
120
|
-
if (input.supervisor.signal.aborted)
|
|
121
|
-
return;
|
|
122
|
-
const at = input.now();
|
|
123
|
-
if (event.type === "session") {
|
|
124
|
-
await recordSession(input.paths, {
|
|
125
|
-
provider: input.soul.provider.name,
|
|
126
|
-
coordinate: event.coordinate,
|
|
127
|
-
cwd: active.cwd,
|
|
128
|
-
options: active.options,
|
|
129
|
-
admittedAt: at,
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
await appendActivity(input.paths, {
|
|
133
|
-
turnSequence: active.turnSequence,
|
|
134
|
-
event: encodeAgentEvent(event),
|
|
135
|
-
at,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
function bodyControlRequested(snapshot, bodySequence) {
|
|
139
|
-
return snapshot.stop?.bodySequence === bodySequence
|
|
140
|
-
|| snapshot.pause?.bodySequence === bodySequence;
|
|
141
|
-
}
|
|
142
13
|
async function putDownIfControlled(paths, supervisor, bodySequence, now) {
|
|
143
14
|
if (supervisor.reason === "control" && await heartExists(paths)) {
|
|
144
15
|
await breakBody(paths, { sequence: bodySequence, end: "put-down", at: now() });
|
|
145
16
|
}
|
|
146
17
|
}
|
|
147
|
-
async function turnRecipe(paths, soul) {
|
|
148
|
-
const latest = (await readHeart(paths)).latestSession;
|
|
149
|
-
const admitted = latest?.provider === soul.provider.name ? latest : undefined;
|
|
150
|
-
const session = admitted?.coordinate;
|
|
151
|
-
return {
|
|
152
|
-
cwd: admitted?.cwd ?? soul.cwd,
|
|
153
|
-
options: admitted?.options ?? soul.options,
|
|
154
|
-
...(session === undefined ? {} : { session }),
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
18
|
async function takeLeash(paths) {
|
|
158
19
|
for (;;) {
|
|
159
20
|
try {
|
|
@@ -169,270 +30,6 @@ async function takeLeash(paths) {
|
|
|
169
30
|
await abortableDelay(LEASH_RETRY_MS);
|
|
170
31
|
}
|
|
171
32
|
}
|
|
172
|
-
async function startTurnDrive(input) {
|
|
173
|
-
const { cwd, options, session } = await turnRecipe(input.paths, input.soul);
|
|
174
|
-
if (session !== undefined && input.adapter.resume === undefined)
|
|
175
|
-
return { kind: "resume-unsupported" };
|
|
176
|
-
const turn = await beginTurn(input.paths, {
|
|
177
|
-
bodySequence: input.bodySequence,
|
|
178
|
-
startedAt: input.now(),
|
|
179
|
-
...(input.call === undefined ? {} : { call: input.call }),
|
|
180
|
-
});
|
|
181
|
-
const requests = input.soul.confinement.kind === "declared"
|
|
182
|
-
? await BodyRequestPump.open({
|
|
183
|
-
paths: input.paths,
|
|
184
|
-
parent: input.soul,
|
|
185
|
-
bodySequence: input.bodySequence,
|
|
186
|
-
now: input.now,
|
|
187
|
-
spawn: input.runtimeSpawn,
|
|
188
|
-
...(input.upstream === undefined ? {} : { upstream: input.upstream }),
|
|
189
|
-
signal: input.supervisor.signal,
|
|
190
|
-
})
|
|
191
|
-
: null;
|
|
192
|
-
const driveInput = {
|
|
193
|
-
body: input.body,
|
|
194
|
-
launchTells: input.launchTells.map((tell) => ({ id: tell.id, text: tell.body })),
|
|
195
|
-
cwd,
|
|
196
|
-
options,
|
|
197
|
-
signal: input.supervisor.signal,
|
|
198
|
-
...(requests === null ? {} : { requests: { dir: requests.directory } }),
|
|
199
|
-
};
|
|
200
|
-
const setup = session === undefined
|
|
201
|
-
? input.adapter.start({ ...driveInput, session: { kind: "fresh" } })
|
|
202
|
-
: input.adapter.resume({ ...driveInput, session: { kind: "resume", coordinate: session } });
|
|
203
|
-
try {
|
|
204
|
-
const selected = await setup;
|
|
205
|
-
if (input.supervisor.signal.aborted) {
|
|
206
|
-
await retireProviderCustody(input, turn.sequence, selected);
|
|
207
|
-
await requests?.close();
|
|
208
|
-
return { kind: "stopped" };
|
|
209
|
-
}
|
|
210
|
-
if (input.launchTells.length > 0) {
|
|
211
|
-
await recordTellDeliveries(input.paths, input.launchTells.map((tell) => ({
|
|
212
|
-
tellId: tell.id,
|
|
213
|
-
route: "launch",
|
|
214
|
-
turnSequence: turn.sequence,
|
|
215
|
-
fence: selected.admission.fence,
|
|
216
|
-
deliveredAt: input.now(),
|
|
217
|
-
})));
|
|
218
|
-
}
|
|
219
|
-
if (requests !== null)
|
|
220
|
-
void selected.completion.then(() => requests.stopAdmission());
|
|
221
|
-
return { turnSequence: turn.sequence, drive: selected, requests, cwd, options,
|
|
222
|
-
...(session === undefined ? {} : { resume: session }) };
|
|
223
|
-
}
|
|
224
|
-
catch (error) {
|
|
225
|
-
await requests?.close();
|
|
226
|
-
if (input.supervisor.signal.aborted) {
|
|
227
|
-
if (input.supervisor.reason === "heart-gone")
|
|
228
|
-
throw error;
|
|
229
|
-
return { kind: "stopped" };
|
|
230
|
-
}
|
|
231
|
-
return {
|
|
232
|
-
kind: "failed",
|
|
233
|
-
turnSequence: turn.sequence,
|
|
234
|
-
diagnostic: error instanceof Error ? error.message : String(error),
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
async function retireProviderCustody(input, turnSequence, drive) {
|
|
239
|
-
const outcome = await Promise.race([
|
|
240
|
-
drive.abort().then(() => ({ kind: "retired" }), (error) => ({ kind: "held", error })),
|
|
241
|
-
abortableDelay(CONTROL_RESPONSE_MS).then(() => ({
|
|
242
|
-
kind: "held",
|
|
243
|
-
error: new Error(`provider custody remained live after ${CONTROL_RESPONSE_MS}ms`),
|
|
244
|
-
})),
|
|
245
|
-
]);
|
|
246
|
-
if (outcome.kind === "retired")
|
|
247
|
-
return;
|
|
248
|
-
if (await heartExists(input.paths)) {
|
|
249
|
-
const diagnostic = outcome.error instanceof Error ? outcome.error.message : String(outcome.error);
|
|
250
|
-
const at = input.now();
|
|
251
|
-
try {
|
|
252
|
-
await input.supervisor.recordHung(diagnostic, at);
|
|
253
|
-
await appendActivity(input.paths, {
|
|
254
|
-
turnSequence,
|
|
255
|
-
event: encodeAgentEvent({ type: "note", text: `Provider custody was not retired: ${diagnostic}` }),
|
|
256
|
-
at,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
catch { /* undisposed provider custody still owns the leash */ }
|
|
260
|
-
}
|
|
261
|
-
for (;;)
|
|
262
|
-
await abortableDelay(60_000);
|
|
263
|
-
}
|
|
264
|
-
function pumpReceipts(writers) {
|
|
265
|
-
const { input, turnSequence, drive, writeWitness, mayWrite } = writers;
|
|
266
|
-
return (async () => {
|
|
267
|
-
if (drive.receipts === undefined)
|
|
268
|
-
return;
|
|
269
|
-
for await (const receipt of drive.receipts) {
|
|
270
|
-
if (!mayWrite())
|
|
271
|
-
return;
|
|
272
|
-
await writeWitness(async () => {
|
|
273
|
-
if (!mayWrite())
|
|
274
|
-
return;
|
|
275
|
-
await recordTellReceipt(input.paths, receipt.evidence === "exact"
|
|
276
|
-
? { ...receipt, receivedAt: input.now() }
|
|
277
|
-
: { ...receipt, turnSequence, receivedAt: input.now() });
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
})();
|
|
281
|
-
}
|
|
282
|
-
function observeReceiptFailure(receiptPump) {
|
|
283
|
-
return receiptPump.then(() => new Promise(() => { }), (error) => Promise.reject(error));
|
|
284
|
-
}
|
|
285
|
-
async function submitPendingLiveTells(writers, pending, attempted, tellLive) {
|
|
286
|
-
const { input, turnSequence, drive, writeWitness, mayWrite } = writers;
|
|
287
|
-
for (const tell of pending) {
|
|
288
|
-
if (attempted.has(tell.id))
|
|
289
|
-
continue;
|
|
290
|
-
attempted.add(tell.id);
|
|
291
|
-
const outcome = await writeWitness(async () => {
|
|
292
|
-
const submission = await tellLive({ id: tell.id, text: tell.body });
|
|
293
|
-
if (!mayWrite())
|
|
294
|
-
return "turn-ended";
|
|
295
|
-
if (submission.kind === "turn-ended")
|
|
296
|
-
return "turn-ended";
|
|
297
|
-
await recordTellDeliveries(input.paths, [{
|
|
298
|
-
tellId: tell.id,
|
|
299
|
-
route: "live",
|
|
300
|
-
turnSequence,
|
|
301
|
-
fence: submission.fence,
|
|
302
|
-
receipt: drive.receipts === undefined ? "unavailable" : "required",
|
|
303
|
-
deliveredAt: input.now(),
|
|
304
|
-
}]);
|
|
305
|
-
return "accepted";
|
|
306
|
-
});
|
|
307
|
-
if (outcome === "turn-ended")
|
|
308
|
-
return "turn-ended";
|
|
309
|
-
}
|
|
310
|
-
return "live";
|
|
311
|
-
}
|
|
312
|
-
async function stopActiveDrive(input, active) {
|
|
313
|
-
await retireProviderCustody(input, active.turnSequence, active.drive);
|
|
314
|
-
await active.requests?.close();
|
|
315
|
-
}
|
|
316
|
-
function hasUnattemptedTell(liveTells, tellPump, pending, attempted) {
|
|
317
|
-
return liveTells && tellPump === null && pending.some((tell) => !attempted.has(tell.id));
|
|
318
|
-
}
|
|
319
|
-
function persistProviderEvent(_input, _active, event) {
|
|
320
|
-
return event.type === "session" ? event.coordinate : undefined;
|
|
321
|
-
}
|
|
322
|
-
async function settleCompletion(result, session, requests) {
|
|
323
|
-
await requests?.close();
|
|
324
|
-
return result.kind === "answered" ? { ...result, ...(session === undefined ? {} : { session }) } : result;
|
|
325
|
-
}
|
|
326
|
-
async function consumeTurnDrive(input, active) {
|
|
327
|
-
const { turnSequence, drive, requests, resume } = active;
|
|
328
|
-
let heart = input.supervisor.current();
|
|
329
|
-
let turnSession = resume;
|
|
330
|
-
const attempted = new Set(input.launchTells.map((tell) => tell.id));
|
|
331
|
-
const writeWitness = serializeEffects();
|
|
332
|
-
let writesOpen = true;
|
|
333
|
-
const mayWrite = () => writesOpen && !input.supervisor.signal.aborted;
|
|
334
|
-
const writers = { input, turnSequence, drive, writeWitness, mayWrite };
|
|
335
|
-
const receiptPump = pumpReceipts(writers);
|
|
336
|
-
const receiptFailure = observeReceiptFailure(receiptPump);
|
|
337
|
-
const iterator = drive.events[Symbol.asyncIterator]();
|
|
338
|
-
let pending = iterator.next();
|
|
339
|
-
let liveTells = true;
|
|
340
|
-
let tellPump = null;
|
|
341
|
-
let tellObservation = null;
|
|
342
|
-
try {
|
|
343
|
-
for (;;) {
|
|
344
|
-
if (input.supervisor.signal.aborted) {
|
|
345
|
-
writesOpen = false;
|
|
346
|
-
await stopActiveDrive(input, active);
|
|
347
|
-
return { kind: "stopped" };
|
|
348
|
-
}
|
|
349
|
-
if (hasUnattemptedTell(liveTells, tellPump, heart.pending, attempted)) {
|
|
350
|
-
if (drive.tell === undefined) {
|
|
351
|
-
writesOpen = false;
|
|
352
|
-
await stopActiveDrive(input, active);
|
|
353
|
-
return { kind: "handoff" };
|
|
354
|
-
}
|
|
355
|
-
tellPump = submitPendingLiveTells(writers, heart.pending, attempted, drive.tell);
|
|
356
|
-
tellObservation = tellPump.then((result) => ({ kind: "tell", result }));
|
|
357
|
-
}
|
|
358
|
-
const next = await Promise.race([
|
|
359
|
-
pending.then((event) => ({ kind: "event", event })),
|
|
360
|
-
input.supervisor.next(heart).then((observation) => ({ kind: "heart", observation })),
|
|
361
|
-
...(tellObservation === null ? [] : [tellObservation]),
|
|
362
|
-
receiptFailure,
|
|
363
|
-
...(requests === null ? [] : [requests.failure]),
|
|
364
|
-
]);
|
|
365
|
-
if (next.kind === "event" && !next.event.done) {
|
|
366
|
-
await writeProviderEvent(input, active, next.event.value);
|
|
367
|
-
}
|
|
368
|
-
if (next.kind === "heart") {
|
|
369
|
-
heart = next.observation;
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
if (next.kind === "tell") {
|
|
373
|
-
tellPump = null;
|
|
374
|
-
tellObservation = null;
|
|
375
|
-
liveTells = next.result === "live";
|
|
376
|
-
continue;
|
|
377
|
-
}
|
|
378
|
-
if (next.event.done)
|
|
379
|
-
break;
|
|
380
|
-
turnSession = persistProviderEvent(input, active, next.event.value) ?? turnSession;
|
|
381
|
-
pending = iterator.next();
|
|
382
|
-
}
|
|
383
|
-
const result = await drive.completion;
|
|
384
|
-
if (tellPump !== null)
|
|
385
|
-
await tellPump;
|
|
386
|
-
await writeWitness.drain();
|
|
387
|
-
writesOpen = false;
|
|
388
|
-
return await settleCompletion(result, turnSession, requests);
|
|
389
|
-
}
|
|
390
|
-
catch (error) {
|
|
391
|
-
writesOpen = false;
|
|
392
|
-
if (input.supervisor.signal.aborted) {
|
|
393
|
-
await stopActiveDrive(input, active);
|
|
394
|
-
return { kind: "stopped" };
|
|
395
|
-
}
|
|
396
|
-
await retireProviderCustody(input, turnSequence, drive);
|
|
397
|
-
try {
|
|
398
|
-
await requests?.close();
|
|
399
|
-
}
|
|
400
|
-
catch { /* preserve the first pump failure */ }
|
|
401
|
-
return { kind: "failed", diagnostic: error instanceof Error ? error.message : String(error) };
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
async function driveTurn(input) {
|
|
405
|
-
let active;
|
|
406
|
-
try {
|
|
407
|
-
const started = await startTurnDrive(input);
|
|
408
|
-
if ("kind" in started)
|
|
409
|
-
return started;
|
|
410
|
-
active = started;
|
|
411
|
-
}
|
|
412
|
-
catch (error) {
|
|
413
|
-
if (!await heartExists(input.paths)) {
|
|
414
|
-
input.supervisor.cancel("heart-gone");
|
|
415
|
-
return { kind: "stopped" };
|
|
416
|
-
}
|
|
417
|
-
throw error;
|
|
418
|
-
}
|
|
419
|
-
try {
|
|
420
|
-
const result = await consumeTurnDrive(input, active);
|
|
421
|
-
return result.kind === "stopped" || result.kind === "handoff"
|
|
422
|
-
? result
|
|
423
|
-
: { ...result, turnSequence: active.turnSequence };
|
|
424
|
-
}
|
|
425
|
-
catch (error) {
|
|
426
|
-
if (await heartExists(input.paths)) {
|
|
427
|
-
await active.requests?.close();
|
|
428
|
-
return { kind: "failed", diagnostic: error instanceof Error ? error.message : String(error),
|
|
429
|
-
turnSequence: active.turnSequence };
|
|
430
|
-
}
|
|
431
|
-
input.supervisor.cancel("heart-gone");
|
|
432
|
-
await stopActiveDrive(input, active);
|
|
433
|
-
return { kind: "stopped" };
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
33
|
async function bornSoul(launch, leash, now) {
|
|
437
34
|
const before = await readHeart(launch.paths);
|
|
438
35
|
if (before.soul !== null)
|
|
@@ -542,6 +139,8 @@ async function runBodyTurns(input) {
|
|
|
542
139
|
...(runtime.upstream === undefined ? {} : { upstream: runtime.upstream }),
|
|
543
140
|
now: runtime.now,
|
|
544
141
|
});
|
|
142
|
+
if (result.kind === "hung")
|
|
143
|
+
return;
|
|
545
144
|
if (result.kind === "stopped") {
|
|
546
145
|
await putDownIfControlled(launch.paths, supervisor, bodySequence, runtime.now);
|
|
547
146
|
return;
|
|
@@ -567,7 +166,7 @@ export async function driveAkumaBody(launch, adapter, runtime = defaultRuntime()
|
|
|
567
166
|
const soul = await bornSoul(launch, leash, runtime.now());
|
|
568
167
|
if (soul === null)
|
|
569
168
|
return;
|
|
570
|
-
const selected = adapter ?? resolveProviderExecution(soul.provider).adapter;
|
|
169
|
+
const selected = adapter ?? (await resolveProviderExecution(soul.provider)).adapter;
|
|
571
170
|
if (!await prepareBodyStart(launch.paths, leash))
|
|
572
171
|
return;
|
|
573
172
|
const body = await leash.recordBody(launch.paths, { leashTakenAt: runtime.now() });
|
|
@@ -610,14 +209,10 @@ export async function spawnAkumaBody(launch) {
|
|
|
610
209
|
});
|
|
611
210
|
owned.release();
|
|
612
211
|
}
|
|
613
|
-
export async function runAkumaBody(
|
|
614
|
-
const encoded = process.argv[2];
|
|
615
|
-
if (encoded === undefined)
|
|
616
|
-
throw new TypeError("Akuma body launch payload is missing");
|
|
617
|
-
const launch = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
|
|
212
|
+
export async function runAkumaBody(launch, upstream) {
|
|
618
213
|
await driveAkumaBody(launch, undefined, {
|
|
619
214
|
now: () => new Date().toISOString(),
|
|
620
215
|
spawnChild: spawnAkumaBody,
|
|
621
|
-
upstream
|
|
216
|
+
upstream,
|
|
622
217
|
});
|
|
623
218
|
}
|
|
@@ -2,13 +2,8 @@ import type { AkuId } from "../identity.js";
|
|
|
2
2
|
import type { ResumeCoordinate } from "../coordinate.js";
|
|
3
3
|
import type { ProviderExecution, ProviderOptions, ReadonlyRestraint } from "../provider-recipe.js";
|
|
4
4
|
import type { AllowedActions } from "../allowed.js";
|
|
5
|
+
import type { TaskMutationAction, TaskMutationRequest } from "../../task/mutation.js";
|
|
5
6
|
export type { ResumeCoordinate } from "../coordinate.js";
|
|
6
|
-
export type Confinement = Readonly<{
|
|
7
|
-
kind: "unconfined";
|
|
8
|
-
}> | Readonly<{
|
|
9
|
-
kind: "declared";
|
|
10
|
-
writableRoots: readonly string[];
|
|
11
|
-
}>;
|
|
12
7
|
export type AkumaOrigin = Readonly<{
|
|
13
8
|
kind: "direct";
|
|
14
9
|
}> | Readonly<{
|
|
@@ -29,11 +24,10 @@ export type Soul = Readonly<{
|
|
|
29
24
|
readonly?: ReadonlyRestraint;
|
|
30
25
|
cwd: string;
|
|
31
26
|
origin: AkumaOrigin;
|
|
32
|
-
confinement: Confinement;
|
|
33
27
|
allowed: AllowedActions;
|
|
34
28
|
createdAt: string;
|
|
35
29
|
}>;
|
|
36
|
-
export type RequestRecipe = Pick<Soul, "description" | "provider" | "options" | "readonly" | "
|
|
30
|
+
export type RequestRecipe = Pick<Soul, "description" | "provider" | "options" | "readonly" | "allowed">;
|
|
37
31
|
export type BodyEnd = "exited" | "broke-off" | "put-down";
|
|
38
32
|
export type BodyFact = Readonly<{
|
|
39
33
|
sequence: number;
|
|
@@ -129,6 +123,12 @@ export type TellReceiptInput = Readonly<{
|
|
|
129
123
|
turnSequence: number;
|
|
130
124
|
fence: string;
|
|
131
125
|
}>);
|
|
126
|
+
export type TaskRequestInput = Readonly<{
|
|
127
|
+
id: string;
|
|
128
|
+
action: TaskMutationAction;
|
|
129
|
+
world: string;
|
|
130
|
+
request: TaskMutationRequest;
|
|
131
|
+
}>;
|
|
132
132
|
export type RequestInput = Readonly<{
|
|
133
133
|
id: string;
|
|
134
134
|
action: "akuma.call";
|
|
@@ -152,7 +152,22 @@ export type RequestInput = Readonly<{
|
|
|
152
152
|
id: string;
|
|
153
153
|
action: "akuma.kill";
|
|
154
154
|
targets: readonly AkuId[];
|
|
155
|
-
}
|
|
155
|
+
}> | Readonly<{
|
|
156
|
+
id: string;
|
|
157
|
+
action: "contract.deliver";
|
|
158
|
+
repoRoot: string;
|
|
159
|
+
contractId: string;
|
|
160
|
+
message?: string;
|
|
161
|
+
includeDirty: boolean;
|
|
162
|
+
materializeConflict: boolean;
|
|
163
|
+
}> | Readonly<{
|
|
164
|
+
id: string;
|
|
165
|
+
action: "contract.review";
|
|
166
|
+
repoRoot: string;
|
|
167
|
+
contractId: string;
|
|
168
|
+
verdict: "satisfied" | "unsatisfied";
|
|
169
|
+
summary?: string;
|
|
170
|
+
}> | TaskRequestInput;
|
|
156
171
|
export type UpstreamRequestService = Readonly<{
|
|
157
172
|
action: "akuma.wait";
|
|
158
173
|
}> | Readonly<{
|
|
@@ -165,6 +180,18 @@ export type UpstreamRequestService = Readonly<{
|
|
|
165
180
|
id: AkuId;
|
|
166
181
|
evidence: KillEvidence;
|
|
167
182
|
}>[];
|
|
183
|
+
}> | Readonly<{
|
|
184
|
+
action: "contract.deliver";
|
|
185
|
+
repoRoot: string;
|
|
186
|
+
contractId: string;
|
|
187
|
+
deliveryFactId: string;
|
|
188
|
+
}> | Readonly<{
|
|
189
|
+
action: "contract.review";
|
|
190
|
+
repoRoot: string;
|
|
191
|
+
contractId: string;
|
|
192
|
+
reviewFactId: string;
|
|
193
|
+
}> | Readonly<{
|
|
194
|
+
action: TaskMutationRequest["action"];
|
|
168
195
|
}>;
|
|
169
196
|
type AdmittedRequest = RequestInput & Readonly<{
|
|
170
197
|
requester: AkuId;
|
|
@@ -223,6 +250,7 @@ export type HeartSnapshot = Readonly<{
|
|
|
223
250
|
latestKill: KillFact | null;
|
|
224
251
|
stop: StopFact | null;
|
|
225
252
|
pause: PauseFact | null;
|
|
253
|
+
lastActivityAt: string | null;
|
|
226
254
|
}>;
|
|
227
255
|
export declare function life(input: Readonly<{
|
|
228
256
|
leash: LeashProbe;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export function life(input) {
|
|
2
|
+
if (input.body?.hung !== undefined)
|
|
3
|
+
return "hung";
|
|
2
4
|
if (input.leash === "held")
|
|
3
|
-
return
|
|
5
|
+
return "running";
|
|
4
6
|
if (input.body === null || input.body.end === undefined)
|
|
5
7
|
return "untidy";
|
|
6
8
|
if (input.kill?.bodySequence === input.body.sequence)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { BodyEnd, BodyFact, ForkPoint, HeartSnapshot, KillFact,
|
|
1
|
+
import type { AkumaPaths } from "../identity.js";
|
|
2
|
+
import type { BodyEnd, BodyFact, ForkPoint, HeartSnapshot, KillFact, SealFact, SessionFact, Soul, TellDeliveryInput, TellFact, TellReceiptInput, TurnEndFact, TurnFact, TurnOutcome, TurnStartFact } from "./facts.js";
|
|
3
3
|
export type { CallFact } from "./facts.js";
|
|
4
4
|
import type { ActivityFact } from "./rows.js";
|
|
5
5
|
import { type ActivityFactSlice } from "./timeline.js";
|
|
6
6
|
export { HeartAbsentError, HeldAkumaLeash, initializeHeart, isHeartAbsent, probeLeash } from "./storage.js";
|
|
7
|
+
export { admitRequest, readNonterminalRequests, readRequest, refuseRequest, reserveRequest, serveRequest, serveUpstreamRequest, voidRequest, } from "./request-authority.js";
|
|
7
8
|
export { life, lifeAt } from "./facts.js";
|
|
8
|
-
export type { AkumaLife, AkumaOrigin, BodyEnd, BodyFact,
|
|
9
|
+
export type { AkumaLife, AkumaOrigin, BodyEnd, BodyFact, HeartSnapshot, ForkPoint, KillEvidence, KillFact, LeashProbe, PauseFact, RequestFact, RequestInput, RequestRecipe, UpstreamRequestService, SealFact, SessionFact, Soul, StopFact, TellFact, TellDelivery, TellDeliveryInput, TellReceiptInput, TurnEndFact, TurnFact, TurnOutcome, TurnStartFact, } from "./facts.js";
|
|
9
10
|
export type { ResumeCoordinate } from "../coordinate.js";
|
|
10
11
|
export declare function readSoul(paths: AkumaPaths): Promise<Soul | null>;
|
|
11
12
|
export declare function heartExists(paths: AkumaPaths): Promise<boolean>;
|
|
@@ -28,16 +29,6 @@ export declare function recordTell(paths: AkumaPaths, tell: Omit<TellFact, "sequ
|
|
|
28
29
|
}>>;
|
|
29
30
|
export declare function recordTellDeliveries(paths: AkumaPaths, inputs: readonly TellDeliveryInput[]): Promise<void>;
|
|
30
31
|
export declare function recordTellReceipt(paths: AkumaPaths, input: TellReceiptInput): Promise<void>;
|
|
31
|
-
export declare function admitRequest(paths: AkumaPaths, input: RequestInput & Readonly<{
|
|
32
|
-
admittedAt: string;
|
|
33
|
-
}>): Promise<RequestFact>;
|
|
34
|
-
export declare function reserveRequest(paths: AkumaPaths, id: string, child: AkuId): Promise<RequestFact>;
|
|
35
|
-
export declare function serveRequest(paths: AkumaPaths, id: string, child: AkuId): Promise<RequestFact>;
|
|
36
|
-
export declare function serveUpstreamRequest(paths: AkumaPaths, id: string, service: UpstreamRequestService): Promise<RequestFact>;
|
|
37
|
-
export declare function refuseRequest(paths: AkumaPaths, id: string, diagnostic: string): Promise<RequestFact>;
|
|
38
|
-
export declare function voidRequest(paths: AkumaPaths, id: string, evidence: string): Promise<RequestFact>;
|
|
39
|
-
export declare function readRequest(paths: AkumaPaths, id: string): Promise<RequestFact | null>;
|
|
40
|
-
export declare function readNonterminalRequests(paths: AkumaPaths): Promise<readonly RequestFact[]>;
|
|
41
32
|
export declare function readKill(paths: AkumaPaths, bodySequence: number): Promise<KillFact | null>;
|
|
42
33
|
export declare function requestStop(paths: AkumaPaths, at: string): Promise<Readonly<{
|
|
43
34
|
kind: "requested";
|