@astrosheep/keiyaku 4.0.6 → 4.1.1
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 +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +3 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -6
- package/build/src/akuma/akuma.d.ts +17 -14
- package/build/src/akuma/akuma.js +122 -114
- package/build/src/akuma/allowed.d.ts +1 -0
- package/build/src/akuma/allowed.js +6 -0
- package/build/src/akuma/archetype.js +12 -2
- package/build/src/akuma/body-turn.js +27 -15
- package/build/src/akuma/body.d.ts +44 -3
- package/build/src/akuma/body.js +142 -33
- package/build/src/akuma/coordinate.js +17 -7
- package/build/src/akuma/heart/facts.js +1 -1
- package/build/src/akuma/heart/index.d.ts +1 -1
- package/build/src/akuma/heart/index.js +2 -4
- package/build/src/akuma/heart/request-authority.js +4 -4
- package/build/src/akuma/heart/request-rows.js +27 -16
- package/build/src/akuma/heart/rows.js +79 -41
- package/build/src/akuma/heart/soul.js +1 -1
- package/build/src/akuma/heart/storage.d.ts +1 -0
- package/build/src/akuma/heart/storage.js +76 -11
- package/build/src/akuma/heart/tells.js +35 -18
- package/build/src/akuma/heart/timeline.js +19 -11
- package/build/src/akuma/identity.d.ts +1 -0
- package/build/src/akuma/identity.js +1 -0
- package/build/src/akuma/index.d.ts +3 -3
- package/build/src/akuma/index.js +1 -1
- package/build/src/akuma/nuke.js +106 -14
- package/build/src/akuma/projection.d.ts +11 -9
- package/build/src/akuma/projection.js +110 -53
- package/build/src/akuma/provider-recipe.d.ts +2 -0
- package/build/src/akuma/provider-recipe.js +21 -5
- package/build/src/akuma/provider.js +105 -62
- package/build/src/akuma/providers/acp/config.d.ts +2 -0
- package/build/src/akuma/providers/acp/config.js +13 -6
- package/build/src/akuma/providers/acp/core.d.ts +5 -2
- package/build/src/akuma/providers/acp/core.js +45 -25
- package/build/src/akuma/providers/acp/events.js +38 -29
- package/build/src/akuma/providers/acp/index.js +18 -8
- package/build/src/akuma/providers/claude/events.js +8 -12
- package/build/src/akuma/providers/claude/index.d.ts +2 -1
- package/build/src/akuma/providers/claude/index.js +59 -26
- package/build/src/akuma/providers/claude/input.js +6 -2
- package/build/src/akuma/providers/codex-app-server/events.js +61 -36
- package/build/src/akuma/providers/codex-app-server/index.js +29 -14
- package/build/src/akuma/providers/grok-build/index.js +28 -17
- package/build/src/akuma/providers/index.js +3 -19
- package/build/src/akuma/providers/opencode-sdk/events.js +32 -18
- package/build/src/akuma/providers/opencode-sdk/index.js +29 -17
- package/build/src/akuma/providers/opencode-sdk/session.js +21 -5
- package/build/src/akuma/providers/pi/events.js +26 -19
- package/build/src/akuma/providers/pi/index.js +58 -38
- package/build/src/akuma/publication.js +9 -9
- package/build/src/akuma/request-serve.js +37 -40
- package/build/src/akuma/request-wire.d.ts +2 -2
- package/build/src/akuma/request-wire.js +75 -102
- package/build/src/akuma/requests.js +2 -2
- package/build/src/akuma-body.js +6 -5
- package/build/src/body/amend.d.ts +4 -1
- package/build/src/body/amend.js +14 -15
- package/build/src/body/decode.js +2 -4
- package/build/src/body/envelope.js +2 -4
- package/build/src/body/region.d.ts +1 -2
- package/build/src/body/region.js +4 -72
- package/build/src/body/render.js +17 -12
- package/build/src/body/shape.js +1 -7
- package/build/src/cli/accepted.d.ts +1 -1
- package/build/src/cli/accepted.js +10 -1
- package/build/src/cli/commands/akuma-invoke.js +18 -6
- package/build/src/cli/commands/akuma.js +10 -13
- package/build/src/cli/commands/amend.d.ts +2 -2
- package/build/src/cli/commands/amend.js +2 -4
- package/build/src/cli/commands/bind.d.ts +4 -4
- package/build/src/cli/commands/bind.js +16 -6
- package/build/src/cli/commands/contract.d.ts +99 -10
- package/build/src/cli/commands/contract.js +128 -24
- package/build/src/cli/commands/install.d.ts +1 -1
- package/build/src/cli/commands/install.js +23 -15
- package/build/src/cli/commands/task-invoke.d.ts +4 -1
- package/build/src/cli/commands/task-invoke.js +191 -68
- package/build/src/cli/commands/task-query.js +48 -24
- package/build/src/cli/commands/task.js +150 -30
- package/build/src/cli/coordinates.js +2 -4
- package/build/src/cli/invoke.js +88 -44
- package/build/src/cli/main.js +4 -2
- package/build/src/cli/parse.d.ts +2 -89
- package/build/src/cli/parse.js +87 -79
- package/build/src/cli/render/akuma-tool-command.js +6 -7
- package/build/src/cli/render/akuma-tool.js +10 -8
- package/build/src/cli/render/akuma.js +149 -53
- package/build/src/cli/render/audit.js +5 -15
- package/build/src/cli/render/board.d.ts +1 -0
- package/build/src/cli/render/board.js +17 -0
- package/build/src/cli/render/catalog.js +84 -7
- package/build/src/cli/render/contract-observation.d.ts +10 -0
- package/build/src/cli/render/contract-observation.js +58 -0
- package/build/src/cli/render/contract.js +57 -54
- package/build/src/cli/render/kanshi.js +281 -209
- package/build/src/cli/render/receipt.d.ts +1 -0
- package/build/src/cli/render/receipt.js +20 -23
- package/build/src/cli/render/refusal.js +16 -15
- package/build/src/cli/render/region.js +22 -6
- package/build/src/cli/render/settings.js +4 -4
- package/build/src/cli/render/task.js +93 -21
- package/build/src/cli/render/terminal.js +16 -5
- package/build/src/cli/result.d.ts +11 -4
- package/build/src/cli/runtime.d.ts +6 -1
- package/build/src/cli/runtime.js +84 -63
- package/build/src/cli/selectors.js +2 -4
- package/build/src/cli/usage.js +6 -5
- package/build/src/contract-worktree.d.ts +1 -25
- package/build/src/contract-worktree.js +87 -174
- package/build/src/coordination/durable-file.js +7 -3
- package/build/src/coordination/sqlite-transaction-lock.js +29 -12
- package/build/src/core/facts/codec.js +7 -3
- package/build/src/core/facts/types.d.ts +1 -1
- package/build/src/core/subject.js +16 -9
- package/build/src/core/verbs/abandon.d.ts +1 -1
- package/build/src/core/verbs/abandon.js +1 -1
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +7 -7
- package/build/src/core/verbs/attestation.js +4 -1
- package/build/src/core/verbs/bind.d.ts +1 -1
- package/build/src/core/verbs/bind.js +1 -1
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +10 -8
- package/build/src/dispatch/index.js +8 -6
- package/build/src/duration.js +5 -1
- package/build/src/git/admission.js +5 -3
- package/build/src/git/hooks.d.ts +8 -0
- package/build/src/git/hooks.js +63 -14
- package/build/src/git/identity.js +1 -4
- package/build/src/git/integration.d.ts +2 -3
- package/build/src/git/integration.js +32 -39
- package/build/src/git/nuke.d.ts +1 -1
- package/build/src/git/nuke.js +110 -62
- package/build/src/git/observe.d.ts +13 -1
- package/build/src/git/observe.js +51 -44
- package/build/src/git/process.js +4 -2
- package/build/src/git/read-observation.js +10 -8
- package/build/src/git/reconcile.d.ts +14 -3
- package/build/src/git/reconcile.js +123 -102
- package/build/src/git/repository.d.ts +2 -0
- package/build/src/git/repository.js +13 -22
- package/build/src/git/target-placement.d.ts +9 -10
- package/build/src/git/target-placement.js +59 -62
- package/build/src/git/tender.d.ts +13 -2
- package/build/src/git/tender.js +28 -22
- package/build/src/git/terminal-seal.js +15 -12
- package/build/src/git/tree.js +5 -2
- package/build/src/git/workspace.d.ts +24 -2
- package/build/src/git/workspace.js +120 -16
- package/build/src/identity/coordinates.js +3 -1
- package/build/src/identity/selector.js +6 -3
- package/build/src/kanshi/fleet.d.ts +6 -0
- package/build/src/kanshi/fleet.js +27 -0
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +77 -45
- package/build/src/kanshi/report.d.ts +13 -24
- package/build/src/kanshi/select.js +25 -24
- package/build/src/library/address.d.ts +2 -1
- package/build/src/library/address.js +7 -8
- package/build/src/library/akuma-creation.js +20 -12
- package/build/src/library/audit.d.ts +0 -1
- package/build/src/library/audit.js +1 -2
- package/build/src/library/bind.d.ts +53 -5
- package/build/src/library/bind.js +98 -22
- package/build/src/library/catalog.d.ts +1 -0
- package/build/src/library/catalog.js +6 -3
- package/build/src/library/configuration.js +3 -1
- package/build/src/library/continuation.d.ts +37 -0
- package/build/src/library/continuation.js +86 -0
- package/build/src/library/contract.d.ts +39 -45
- package/build/src/library/contract.js +141 -118
- package/build/src/library/delivery.d.ts +18 -13
- package/build/src/library/fleet.d.ts +1 -1
- package/build/src/library/fleet.js +19 -11
- package/build/src/library/input.d.ts +2 -0
- package/build/src/library/input.js +14 -0
- package/build/src/library/keiyaku.d.ts +8 -7
- package/build/src/library/keiyaku.js +3 -3
- package/build/src/library/mutation.js +11 -4
- package/build/src/library/nuke.js +14 -5
- package/build/src/library/reconcile.d.ts +9 -4
- package/build/src/library/reconcile.js +30 -24
- package/build/src/library/refusal.d.ts +13 -5
- package/build/src/library/refusal.js +7 -0
- package/build/src/library/region.d.ts +8 -7
- package/build/src/library/region.js +31 -11
- package/build/src/library/repo.js +2 -2
- package/build/src/markdown/lex.js +9 -2
- package/build/src/markdown/parse.js +11 -7
- package/build/src/markdown/query.js +4 -2
- package/build/src/protocol/amend.js +3 -1
- package/build/src/protocol/attempt.d.ts +7 -3
- package/build/src/protocol/attempt.js +9 -5
- package/build/src/protocol/audit.d.ts +1 -1
- package/build/src/protocol/audit.js +4 -14
- package/build/src/protocol/bind.d.ts +19 -6
- package/build/src/protocol/bind.js +28 -13
- package/build/src/protocol/completion.d.ts +0 -1
- package/build/src/protocol/completion.js +1 -3
- package/build/src/protocol/deliver.d.ts +12 -4
- package/build/src/protocol/deliver.js +60 -51
- package/build/src/protocol/intent.d.ts +1 -0
- package/build/src/protocol/intent.js +9 -7
- package/build/src/protocol/operations.d.ts +10 -9
- package/build/src/protocol/operations.js +5 -3
- package/build/src/protocol/placement.d.ts +0 -1
- package/build/src/protocol/placement.js +6 -6
- package/build/src/protocol/read/observation.d.ts +11 -0
- package/build/src/protocol/read/observation.js +37 -0
- package/build/src/protocol/read/status.d.ts +23 -12
- package/build/src/protocol/read/status.js +90 -72
- package/build/src/protocol/reconcile.d.ts +1 -0
- package/build/src/protocol/reconcile.js +2 -3
- package/build/src/protocol/reintegrate.js +1 -1
- package/build/src/protocol/review.d.ts +0 -1
- package/build/src/protocol/review.js +15 -22
- package/build/src/protocol/run.d.ts +1 -0
- package/build/src/protocol/run.js +4 -5
- package/build/src/runtime/proc/launch.d.ts +33 -0
- package/build/src/runtime/proc/launch.js +98 -0
- package/build/src/runtime/proc/line-rpc.js +9 -3
- package/build/src/runtime/proc/run.d.ts +12 -6
- package/build/src/runtime/proc/run.js +78 -21
- package/build/src/runtime/proc/stdio.js +7 -10
- package/build/src/settings.js +6 -2
- package/build/src/settlement/fence.d.ts +0 -2
- package/build/src/settlement/fence.js +0 -24
- package/build/src/settlement/holder.js +13 -10
- package/build/src/settlement/settle.js +39 -6
- package/build/src/task/board.d.ts +21 -2
- package/build/src/task/board.js +35 -16
- package/build/src/task/compose.js +85 -22
- package/build/src/task/context.js +21 -8
- package/build/src/task/document.js +46 -10
- package/build/src/task/identity.js +19 -6
- package/build/src/task/index.js +118 -27
- package/build/src/task/input.js +29 -7
- package/build/src/task/mutation.js +61 -19
- package/build/src/task/operations.d.ts +8 -2
- package/build/src/task/operations.js +97 -32
- package/build/src/task/query.js +57 -28
- package/build/src/task/store.d.ts +5 -1
- package/build/src/task/store.js +88 -95
- package/build/src/verification/execution.js +14 -11
- package/build/src/workspace-place.js +19 -7
- package/build/src/world.js +16 -6
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ did not land until the gates had current evidence.
|
|
|
94
94
|
kanshi ─ 7 keiyaku · 18 akuma · 286 task ─ /Users/astrosheep/Developer/keiyaku-v4 main 9cfdca6017633e51827b9b2eba3c76a7fe08e05f
|
|
95
95
|
|
|
96
96
|
keiyaku 7
|
|
97
|
-
⧗ kei/add-acp-provider-and-grok-build-profile
|
|
97
|
+
⧗ kei/add-acp-provider-and-grok-build-profile tendered
|
|
98
98
|
worktree · integration c5cafef6 · -> refs/heads/main
|
|
99
99
|
! reviewed
|
|
100
100
|
⧗ kei/align-task-cli-truth-promises waiting
|
|
@@ -39,4 +39,7 @@ keiyaku -C <repo> tell <aku/...|@alias> (<prompt> | -)
|
|
|
39
39
|
`-C` is the invocation and Akuma execution cwd. Add `--repo <path>` only when
|
|
40
40
|
a Contract or Dispatch reader must use a different Git repository.
|
|
41
41
|
|
|
42
|
+
Repeated `--allowed` values add actions to the Archetype defaults. Restriction
|
|
43
|
+
comes from the Archetype base and, for nested calls, the direct parent Soul.
|
|
44
|
+
|
|
42
45
|
Use text by default; add `--json` when a script needs structured output.
|
|
@@ -29,6 +29,9 @@ exclusive. Decide up front whether you will stay:
|
|
|
29
29
|
Alias already points elsewhere, it moves to the born Akuma. The worker's
|
|
30
30
|
execution cwd is exactly `-C <path>`, or your own cwd when `-C` is omitted.
|
|
31
31
|
|
|
32
|
+
Repeated `--allowed` values add actions to the Archetype defaults. Restriction
|
|
33
|
+
comes from the Archetype base and, for nested calls, the direct parent Soul.
|
|
34
|
+
|
|
32
35
|
## Archetypes
|
|
33
36
|
|
|
34
37
|
An Archetype is a Markdown file at `~/.keiyaku/akuma/<name>.md`. Its
|
|
@@ -17,7 +17,7 @@ contract document -> bind -> work -> audit -> deliver -> review gates
|
|
|
17
17
|
\-> abandoned
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
The lifecycle is `waiting -> bound ->
|
|
20
|
+
The lifecycle is `waiting -> bound -> tendered -> claimed | abandoned`;
|
|
21
21
|
the last two are terminal. Reserve `--after` for true logical ordering: one
|
|
22
22
|
Contract's result must ultimately build on another's settled outcome, or their
|
|
23
23
|
intended work has a large or irreconcilable interaction that should be
|
|
@@ -219,7 +219,7 @@ included. Read the receipt:
|
|
|
219
219
|
delivery is done.
|
|
220
220
|
- When a gate is not current, the receipt shows the recorded candidate and the
|
|
221
221
|
placement stop. This is not a failed delivery. The Contract stays
|
|
222
|
-
`
|
|
222
|
+
`tendered` while you complete the gates.
|
|
223
223
|
- A lag row reports an accepted physical effect that has not finished. The
|
|
224
224
|
delivery stands; `reconcile` completes the effect later. It never changes
|
|
225
225
|
the verdict.
|
|
@@ -283,10 +283,7 @@ Placement follows the Git mental model you already have:
|
|
|
283
283
|
The deliver or review you just ran still counts: the recorded candidate and
|
|
284
284
|
any `✓ reviewed` verdict are kept, but nothing claims and nothing moves.
|
|
285
285
|
The target ref, its checkout, and your bytes stay exactly where they were,
|
|
286
|
-
and the Contract stays `
|
|
287
|
-
- A `--here` Contract behaves like a commit with gates: it lands on the current
|
|
288
|
-
branch and cannot deliver to a foreign checked-out target.
|
|
289
|
-
|
|
286
|
+
and the Contract stays `tendered`.
|
|
290
287
|
After a refusal, handle the listed paths, then `deliver` again or record a
|
|
291
288
|
satisfied review; either command requests placement again.
|
|
292
289
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { type TellResult, type TellWakeRuntime } from "./body.js";
|
|
1
2
|
import { type AkumaLife, type KillEvidence, type ResumeCoordinate, type Soul } from "./heart/index.js";
|
|
2
|
-
import { type AkuId } from "./identity.js";
|
|
3
|
+
import { type AkuId, type AkumaPaths } from "./identity.js";
|
|
3
4
|
import { type ActivityHistory, type ActivitySnapshot } from "./projection.js";
|
|
4
5
|
import { type Settings } from "../settings.js";
|
|
5
6
|
import type { WorldRoot } from "../world.js";
|
|
@@ -20,6 +21,8 @@ export type AkumaStatus = Readonly<{
|
|
|
20
21
|
timeline: ActivitySnapshot;
|
|
21
22
|
strandedReason?: "resume-unsupported";
|
|
22
23
|
}>;
|
|
24
|
+
/** The default completion judgment over one complete status snapshot. */
|
|
25
|
+
export declare function defaultWaitComplete(status: AkumaStatus): boolean;
|
|
23
26
|
export type { ReadonlyRestraint } from "./provider-recipe.js";
|
|
24
27
|
export type * from "./projection.js";
|
|
25
28
|
export type UnbornAkumaListRow = Readonly<{
|
|
@@ -54,16 +57,7 @@ type AkumaCallContext = Readonly<{
|
|
|
54
57
|
initiatorCwd?: string;
|
|
55
58
|
cwdCanonical?: true;
|
|
56
59
|
}>;
|
|
57
|
-
export type TellResult
|
|
58
|
-
admission: Readonly<{
|
|
59
|
-
tellId: string;
|
|
60
|
-
fact: "recorded";
|
|
61
|
-
}>;
|
|
62
|
-
wake: "spawned" | Readonly<{
|
|
63
|
-
kind: "failed";
|
|
64
|
-
diagnostic: string;
|
|
65
|
-
}>;
|
|
66
|
-
}>;
|
|
60
|
+
export type { TellResult, TellWake } from "./body.js";
|
|
67
61
|
export type InterruptReceipt = Readonly<{
|
|
68
62
|
kind: "unavailable";
|
|
69
63
|
evidence: "hung" | "untidy" | "unavailable";
|
|
@@ -94,14 +88,23 @@ export declare class AkumaNotBornError extends Error {
|
|
|
94
88
|
readonly kind = "akuma-not-born";
|
|
95
89
|
constructor(id: AkuId);
|
|
96
90
|
}
|
|
97
|
-
export declare function tellAkumaWithId(
|
|
91
|
+
export declare function tellAkumaWithId(input: Readonly<{
|
|
92
|
+
worldPath: WorldRoot;
|
|
93
|
+
id: AkuId;
|
|
94
|
+
body: string;
|
|
95
|
+
tellId: string;
|
|
96
|
+
recordedAt?: string;
|
|
97
|
+
runtime?: TellWakeRuntime;
|
|
98
|
+
}>): Promise<TellResult>;
|
|
99
|
+
export declare function killAkumaWithRecovery(paths: AkumaPaths, recover?: (paths: AkumaPaths) => Promise<void>): Promise<KillEvidence>;
|
|
98
100
|
export type BudgetedStatusObservation = Readonly<{
|
|
99
101
|
status: AkumaStatus;
|
|
100
102
|
ordinarySelected: number;
|
|
101
103
|
}>;
|
|
102
|
-
/** Package-internal
|
|
104
|
+
/** Package-internal observation; Fleet chooses the aperture and ordinary budget. */
|
|
103
105
|
export declare function readBudgetedStatus(worldPath: WorldRoot, id: AkuId, input: Readonly<{
|
|
104
|
-
|
|
106
|
+
aperture: "monitoring" | "receipt";
|
|
107
|
+
ordinaryBudget?: number;
|
|
105
108
|
}>): Promise<BudgetedStatusObservation>;
|
|
106
109
|
/** Package-internal birth projection used by the composed Library call result. */
|
|
107
110
|
export declare function readAkumaBirthCwd(worldPath: WorldRoot, id: AkuId): Promise<string>;
|
package/build/src/akuma/akuma.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { readdir, realpath, stat } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
-
import { CONTROL_RESPONSE_MS, spawnAkumaBody } from "./body.js";
|
|
4
|
+
import { CONTROL_RESPONSE_MS, handoffPendingTells, spawnAkumaBody, wakeRecordedTell, } from "./body.js";
|
|
5
5
|
import { HeldAkumaLeash, activitySlice, isHeartAbsent, 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 { ordinarySnapshotBudget, projectTurns, selectHistory, selectSnapshot, } from "./projection.js";
|
|
8
8
|
import { listArchetypes as readArchetypes, loadArchetype } from "./archetype.js";
|
|
9
9
|
import { publishAkuma } from "./publication.js";
|
|
10
10
|
import { resolveProviderExecution } from "./providers/index.js";
|
|
11
11
|
import { injectedBodyRequests, requestBodyCall } from "./requests.js";
|
|
12
12
|
import { settings as readSettings } from "../settings.js";
|
|
13
|
-
import { decodeAllowedActions, } from "./allowed.js";
|
|
14
|
-
const POLL_MS =
|
|
13
|
+
import { decodeAllowedActions, unionAllowedActions } from "./allowed.js";
|
|
14
|
+
const POLL_MS = 100;
|
|
15
15
|
async function canonicalBirthCwd(input) {
|
|
16
16
|
const selected = resolve(input);
|
|
17
17
|
try {
|
|
@@ -31,6 +31,11 @@ function callReadonly(value) {
|
|
|
31
31
|
throw new TypeError("Akuma call readonly must be true");
|
|
32
32
|
return { readonly: true };
|
|
33
33
|
}
|
|
34
|
+
/** The default completion judgment over one complete status snapshot. */
|
|
35
|
+
export function defaultWaitComplete(status) {
|
|
36
|
+
return (status.life !== "running" &&
|
|
37
|
+
!status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
|
|
38
|
+
}
|
|
34
39
|
const CALL_EXECUTION = Symbol("akuma-call-execution");
|
|
35
40
|
const CALL_WITH_CONTEXT = Symbol("akuma-call-with-context");
|
|
36
41
|
export class AkumaNotBornError extends Error {
|
|
@@ -52,7 +57,7 @@ async function takeLeashUntil(paths, deadline) {
|
|
|
52
57
|
return leash;
|
|
53
58
|
if (performance.now() >= deadline)
|
|
54
59
|
return null;
|
|
55
|
-
await wait(POLL_MS);
|
|
60
|
+
await wait(Math.min(POLL_MS, Math.max(0, deadline - performance.now())));
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
async function recordTellBody(paths, akuma, body, id = randomUUID(), recordedAt = new Date().toISOString()) {
|
|
@@ -61,32 +66,56 @@ async function recordTellBody(paths, akuma, body, id = randomUUID(), recordedAt
|
|
|
61
66
|
throw new AkumaNotBornError(akuma);
|
|
62
67
|
return { kind: "recorded", tellId: admitted.tell.id };
|
|
63
68
|
}
|
|
64
|
-
async function
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
return {
|
|
71
|
-
admission: { tellId, fact: "recorded" },
|
|
72
|
-
wake: { kind: "failed", diagnostic: diagnostic(error) },
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
export async function tellAkumaWithId(worldPath, id, body, tellId, recordedAt = new Date().toISOString()) {
|
|
77
|
-
const paths = pathsForAkuId(worldPath, id);
|
|
78
|
-
const recorded = await recordTellBody(paths, id, body, tellId, recordedAt);
|
|
79
|
-
return await wakeTell(paths, recorded.tellId);
|
|
69
|
+
export async function tellAkumaWithId(input) {
|
|
70
|
+
const paths = pathsForAkuId(input.worldPath, input.id);
|
|
71
|
+
const recorded = await recordTellBody(paths, input.id, input.body, input.tellId, input.recordedAt);
|
|
72
|
+
return await wakeRecordedTell(paths, recorded.tellId, input.runtime);
|
|
80
73
|
}
|
|
81
74
|
function diagnostic(error) {
|
|
82
75
|
return error instanceof Error ? error.message : String(error);
|
|
83
76
|
}
|
|
77
|
+
export async function killAkumaWithRecovery(paths, recover = handoffPendingTells) {
|
|
78
|
+
try {
|
|
79
|
+
const request = await requestStop(paths, new Date().toISOString());
|
|
80
|
+
if (request.kind !== "requested")
|
|
81
|
+
return request.kind;
|
|
82
|
+
const target = request.body;
|
|
83
|
+
const leash = await takeLeashUntil(paths, performance.now() + CONTROL_RESPONSE_MS);
|
|
84
|
+
if ((await readKill(paths, target.sequence)) !== null) {
|
|
85
|
+
leash?.release();
|
|
86
|
+
return "killed";
|
|
87
|
+
}
|
|
88
|
+
if (leash === null) {
|
|
89
|
+
if ((await readKill(paths, target.sequence)) !== null)
|
|
90
|
+
return "killed";
|
|
91
|
+
const body = (await readHeart(paths)).latestBody;
|
|
92
|
+
return body?.sequence === target.sequence && body.hung !== undefined ? "hung" : "unavailable";
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const settledBody = (await readHeart(paths)).latestBody;
|
|
96
|
+
if (settledBody?.sequence !== target.sequence)
|
|
97
|
+
return (await readKill(paths, target.sequence)) === null ? "unavailable" : "killed";
|
|
98
|
+
if (settledBody.end !== "put-down") {
|
|
99
|
+
await leash.clearStop(paths);
|
|
100
|
+
return "untidy";
|
|
101
|
+
}
|
|
102
|
+
const settled = await leash.settleStop(paths, target.sequence);
|
|
103
|
+
return settled === null ? "unavailable" : "killed";
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
leash.release();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
void recover(paths).catch(() => undefined);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
84
113
|
async function fleetListRow(paths, expected) {
|
|
85
114
|
const snapshot = await readHeart(paths);
|
|
86
115
|
if (snapshot.soul !== null)
|
|
87
116
|
return await bornListRow(paths, expected, snapshot);
|
|
88
117
|
try {
|
|
89
|
-
if (await probeLeash(paths) === "held")
|
|
118
|
+
if ((await probeLeash(paths)) === "held")
|
|
90
119
|
return { id: expected, life: "unborn" };
|
|
91
120
|
const seal = await readSeal(paths);
|
|
92
121
|
return seal === null ? { id: expected, life: "unborn" } : { id: expected, life: "stillborn", seal };
|
|
@@ -118,32 +147,36 @@ async function bornListRow(paths, expected, snapshot) {
|
|
|
118
147
|
pending: snapshot.pending.map((tell) => tell.id),
|
|
119
148
|
};
|
|
120
149
|
}
|
|
121
|
-
async function bornStatus(paths, expected,
|
|
150
|
+
async function bornStatus(paths, expected, input) {
|
|
151
|
+
if (input.ordinaryBudget !== undefined && (!Number.isSafeInteger(input.ordinaryBudget) || input.ordinaryBudget < 0)) {
|
|
152
|
+
throw new TypeError("ordinary budget must be a nonnegative safe integer");
|
|
153
|
+
}
|
|
122
154
|
const snapshot = await readHeart(paths);
|
|
123
155
|
if (snapshot.soul === null)
|
|
124
156
|
throw new AkumaNotBornError(expected);
|
|
125
157
|
const current = await bornListRow(paths, expected, snapshot);
|
|
126
|
-
const resumeUnsupported = current.life === "stranded"
|
|
127
|
-
|
|
128
|
-
|
|
158
|
+
const resumeUnsupported = current.life === "stranded" &&
|
|
159
|
+
snapshot.latestSession?.provider === snapshot.soul.provider.name &&
|
|
160
|
+
(await resolveProviderExecution(snapshot.soul.provider)).adapter.resume === undefined;
|
|
129
161
|
const slice = await activitySlice(paths);
|
|
162
|
+
const selected = selectSnapshot(projectTurns(slice.rows), {
|
|
163
|
+
aperture: input.aperture,
|
|
164
|
+
budget: ordinarySnapshotBudget(input.ordinaryBudget),
|
|
165
|
+
});
|
|
130
166
|
return {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
167
|
+
status: {
|
|
168
|
+
id: current.id,
|
|
169
|
+
life: current.life,
|
|
170
|
+
...(snapshot.soul.readonly === undefined ? {} : { readonly: snapshot.soul.readonly }),
|
|
171
|
+
...(resumeUnsupported ? { strandedReason: "resume-unsupported" } : {}),
|
|
172
|
+
timeline: selected.snapshot,
|
|
173
|
+
},
|
|
174
|
+
ordinarySelected: selected.ordinaryCount,
|
|
138
175
|
};
|
|
139
176
|
}
|
|
140
|
-
/** Package-internal
|
|
177
|
+
/** Package-internal observation; Fleet chooses the aperture and ordinary budget. */
|
|
141
178
|
export async function readBudgetedStatus(worldPath, id, input) {
|
|
142
|
-
|
|
143
|
-
throw new TypeError("ordinary budget must be a nonnegative safe integer");
|
|
144
|
-
}
|
|
145
|
-
const status = await bornStatus(pathsForAkuId(worldPath, id), id, ordinarySnapshotBudget(input.ordinaryBudget));
|
|
146
|
-
return { status, ordinarySelected: ordinarySelectedCount(status.timeline) };
|
|
179
|
+
return await bornStatus(pathsForAkuId(worldPath, id), id, input);
|
|
147
180
|
}
|
|
148
181
|
/** Package-internal birth projection used by the composed Library call result. */
|
|
149
182
|
export async function readAkumaBirthCwd(worldPath, id) {
|
|
@@ -166,13 +199,16 @@ export class AkumaHandle {
|
|
|
166
199
|
return pathsForAkuId(this.worldPath, this.id);
|
|
167
200
|
}
|
|
168
201
|
async status() {
|
|
169
|
-
return await bornStatus(this.paths, this.id);
|
|
202
|
+
return (await bornStatus(this.paths, this.id, { aperture: "monitoring" })).status;
|
|
170
203
|
}
|
|
171
204
|
async history(input = {}) {
|
|
172
205
|
if (input.before !== undefined && input.since !== undefined) {
|
|
173
206
|
throw new TypeError("Akuma history before and since are mutually exclusive");
|
|
174
207
|
}
|
|
175
|
-
for (const [name, value] of [
|
|
208
|
+
for (const [name, value] of [
|
|
209
|
+
["before", input.before],
|
|
210
|
+
["since", input.since],
|
|
211
|
+
]) {
|
|
176
212
|
if (value !== undefined && (!Number.isSafeInteger(value) || value <= 0)) {
|
|
177
213
|
throw new TypeError(`Akuma history ${name} must be a positive safe integer`);
|
|
178
214
|
}
|
|
@@ -191,9 +227,8 @@ export class AkumaHandle {
|
|
|
191
227
|
limit,
|
|
192
228
|
});
|
|
193
229
|
}
|
|
194
|
-
async wait(predicate =
|
|
195
|
-
if (options.timeoutMs !== undefined
|
|
196
|
-
&& (!Number.isFinite(options.timeoutMs) || options.timeoutMs < 0)) {
|
|
230
|
+
async wait(predicate = defaultWaitComplete, options = {}) {
|
|
231
|
+
if (options.timeoutMs !== undefined && (!Number.isFinite(options.timeoutMs) || options.timeoutMs < 0)) {
|
|
197
232
|
throw new TypeError("Akuma wait timeoutMs must be a nonnegative finite millisecond duration");
|
|
198
233
|
}
|
|
199
234
|
const deadline = options.timeoutMs === undefined ? undefined : performance.now() + options.timeoutMs;
|
|
@@ -206,7 +241,7 @@ export class AkumaHandle {
|
|
|
206
241
|
}
|
|
207
242
|
async tell(body) {
|
|
208
243
|
const recorded = await recordTellBody(this.paths, this.id, body);
|
|
209
|
-
return await
|
|
244
|
+
return await wakeRecordedTell(this.paths, recorded.tellId);
|
|
210
245
|
}
|
|
211
246
|
async interrupt(body) {
|
|
212
247
|
const request = await requestPause(this.paths, new Date().toISOString());
|
|
@@ -221,9 +256,10 @@ export class AkumaHandle {
|
|
|
221
256
|
}
|
|
222
257
|
if (leash === null) {
|
|
223
258
|
const body = (await readHeart(this.paths)).latestBody;
|
|
224
|
-
return {
|
|
225
|
-
|
|
226
|
-
|
|
259
|
+
return {
|
|
260
|
+
kind: "unavailable",
|
|
261
|
+
evidence: body?.sequence === request.body.sequence && body.hung !== undefined ? "hung" : "unavailable",
|
|
262
|
+
};
|
|
227
263
|
}
|
|
228
264
|
const settledBody = (await readHeart(this.paths)).latestBody;
|
|
229
265
|
if (settledBody?.sequence === request.body.sequence && settledBody.hung !== undefined) {
|
|
@@ -262,7 +298,7 @@ export class AkumaHandle {
|
|
|
262
298
|
finally {
|
|
263
299
|
leash.release();
|
|
264
300
|
}
|
|
265
|
-
return { kind: "interrupted", putDown, tell: await
|
|
301
|
+
return { kind: "interrupted", putDown, tell: await wakeRecordedTell(this.paths, recorded.tellId) };
|
|
266
302
|
}
|
|
267
303
|
async fork(input) {
|
|
268
304
|
const source = await readSoul(this.paths);
|
|
@@ -298,21 +334,23 @@ export class AkumaHandle {
|
|
|
298
334
|
worldPath: this.worldPath,
|
|
299
335
|
archetype: source.archetype,
|
|
300
336
|
awaitAsleep: true,
|
|
301
|
-
launch: async (allocated) =>
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
337
|
+
launch: async (allocated) => {
|
|
338
|
+
(await spawnAkumaBody({
|
|
339
|
+
paths: allocated.paths,
|
|
340
|
+
seed: {
|
|
341
|
+
id: allocated.id,
|
|
342
|
+
archetype: source.archetype,
|
|
343
|
+
...(source.description === undefined ? {} : { description: source.description }),
|
|
344
|
+
provider: source.provider,
|
|
345
|
+
options: source.options,
|
|
346
|
+
...(source.readonly === undefined ? {} : { readonly: source.readonly }),
|
|
347
|
+
allowed: source.allowed,
|
|
348
|
+
cwd: source.cwd,
|
|
349
|
+
origin: { kind: "fork", parent: this.id, at: input.at },
|
|
350
|
+
},
|
|
351
|
+
birthSession,
|
|
352
|
+
})).release();
|
|
353
|
+
},
|
|
316
354
|
});
|
|
317
355
|
return { kind: "forked", child: child.id };
|
|
318
356
|
}
|
|
@@ -325,39 +363,7 @@ export class AkumaHandle {
|
|
|
325
363
|
}
|
|
326
364
|
}
|
|
327
365
|
async kill() {
|
|
328
|
-
|
|
329
|
-
const request = await requestStop(this.paths, at);
|
|
330
|
-
if (request.kind !== "requested")
|
|
331
|
-
return request.kind;
|
|
332
|
-
const target = request.body;
|
|
333
|
-
const graceDeadline = performance.now() + CONTROL_RESPONSE_MS;
|
|
334
|
-
const leash = await takeLeashUntil(this.paths, graceDeadline);
|
|
335
|
-
if (await readKill(this.paths, target.sequence) !== null) {
|
|
336
|
-
leash?.release();
|
|
337
|
-
return "killed";
|
|
338
|
-
}
|
|
339
|
-
if (leash === null) {
|
|
340
|
-
if (await readKill(this.paths, target.sequence) !== null)
|
|
341
|
-
return "killed";
|
|
342
|
-
const body = (await readHeart(this.paths)).latestBody;
|
|
343
|
-
return body?.sequence === target.sequence && body.hung !== undefined ? "hung" : "unavailable";
|
|
344
|
-
}
|
|
345
|
-
try {
|
|
346
|
-
const settledBody = (await readHeart(this.paths)).latestBody;
|
|
347
|
-
if (settledBody?.sequence !== target.sequence)
|
|
348
|
-
return await readKill(this.paths, target.sequence) === null ? "unavailable" : "killed";
|
|
349
|
-
if (settledBody.end !== "put-down") {
|
|
350
|
-
await leash.clearStop(this.paths);
|
|
351
|
-
return "untidy";
|
|
352
|
-
}
|
|
353
|
-
const settled = await leash.settleStop(this.paths, target.sequence);
|
|
354
|
-
if (settled === null)
|
|
355
|
-
return "unavailable";
|
|
356
|
-
return "killed";
|
|
357
|
-
}
|
|
358
|
-
finally {
|
|
359
|
-
leash.release();
|
|
360
|
-
}
|
|
366
|
+
return await killAkumaWithRecovery(this.paths);
|
|
361
367
|
}
|
|
362
368
|
async lastAnswer() {
|
|
363
369
|
const turn = await readLastAnsweredTurn(this.paths);
|
|
@@ -395,7 +401,7 @@ export class Akuma {
|
|
|
395
401
|
const readonly = callReadonly(input.readonly);
|
|
396
402
|
const name = archetypeName(input.archetype);
|
|
397
403
|
const home = this.configuration.home === undefined ? {} : { home: this.configuration.home };
|
|
398
|
-
const settings = this.configuration.settings ?? await readSettings({ root: this.path, ...home });
|
|
404
|
+
const settings = this.configuration.settings ?? (await readSettings({ root: this.path, ...home }));
|
|
399
405
|
const archetype = await loadArchetype({
|
|
400
406
|
name,
|
|
401
407
|
...home,
|
|
@@ -404,7 +410,7 @@ export class Akuma {
|
|
|
404
410
|
});
|
|
405
411
|
const allowed = input.allowed === undefined
|
|
406
412
|
? archetype.allowed
|
|
407
|
-
: decodeAllowedActions(input.allowed, "Akuma call allowed");
|
|
413
|
+
: unionAllowedActions(archetype.allowed, decodeAllowedActions(input.allowed, "Akuma call allowed"));
|
|
408
414
|
const requests = injectedBodyRequests();
|
|
409
415
|
const requestRecipe = Object.freeze({
|
|
410
416
|
...(archetype.description === undefined ? {} : { description: archetype.description }),
|
|
@@ -416,7 +422,9 @@ export class Akuma {
|
|
|
416
422
|
if (requests !== null) {
|
|
417
423
|
const cwd = input.cwd === undefined
|
|
418
424
|
? undefined
|
|
419
|
-
: context?.cwdCanonical === true
|
|
425
|
+
: context?.cwdCanonical === true
|
|
426
|
+
? input.cwd
|
|
427
|
+
: await canonicalBirthCwd(input.cwd);
|
|
420
428
|
const child = await requestBodyCall({
|
|
421
429
|
directory: requests,
|
|
422
430
|
id: randomUUID(),
|
|
@@ -434,24 +442,24 @@ export class Akuma {
|
|
|
434
442
|
}
|
|
435
443
|
const initiatorCwd = context.initiatorCwd;
|
|
436
444
|
const selectedCwd = input.cwd ?? initiatorCwd ?? this.path;
|
|
437
|
-
const cwd = input.cwd !== undefined && context?.cwdCanonical === true
|
|
438
|
-
? input.cwd
|
|
439
|
-
: await canonicalBirthCwd(selectedCwd);
|
|
445
|
+
const cwd = input.cwd !== undefined && context?.cwdCanonical === true ? input.cwd : await canonicalBirthCwd(selectedCwd);
|
|
440
446
|
const recipe = requestRecipe;
|
|
441
447
|
const published = await publishAkuma({
|
|
442
448
|
worldPath: this.path,
|
|
443
449
|
archetype: archetype.name,
|
|
444
|
-
launch: async (allocated) =>
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
450
|
+
launch: async (allocated) => {
|
|
451
|
+
(await spawnAkumaBody({
|
|
452
|
+
paths: allocated.paths,
|
|
453
|
+
seed: {
|
|
454
|
+
id: allocated.id,
|
|
455
|
+
archetype: allocated.archetype,
|
|
456
|
+
...recipe,
|
|
457
|
+
cwd,
|
|
458
|
+
origin: { kind: "direct" },
|
|
459
|
+
},
|
|
460
|
+
initialBody: input.body,
|
|
461
|
+
})).release();
|
|
462
|
+
},
|
|
455
463
|
});
|
|
456
464
|
return new AkumaHandle(published.id, this.path, {
|
|
457
465
|
cwd,
|
|
@@ -4,4 +4,5 @@ export type AllowedActions = readonly AllowedAction[];
|
|
|
4
4
|
export declare function isAllowedAction(value: unknown): value is AllowedAction;
|
|
5
5
|
export declare function decodeAllowedActions(value: unknown, label?: string): AllowedActions;
|
|
6
6
|
export declare function effectiveAllowedActions(value: unknown): AllowedActions;
|
|
7
|
+
export declare function unionAllowedActions(base: AllowedActions, additions: AllowedActions): AllowedActions;
|
|
7
8
|
export declare function clipAllowedActions(requested: AllowedActions, parent: AllowedActions): AllowedActions;
|
|
@@ -27,6 +27,12 @@ export function decodeAllowedActions(value, label = "allowed") {
|
|
|
27
27
|
export function effectiveAllowedActions(value) {
|
|
28
28
|
return value === undefined ? ALLOWED_ACTIONS : decodeAllowedActions(value);
|
|
29
29
|
}
|
|
30
|
+
export function unionAllowedActions(base, additions) {
|
|
31
|
+
const merged = new Set(base);
|
|
32
|
+
for (const action of additions)
|
|
33
|
+
merged.add(action);
|
|
34
|
+
return Object.freeze([...merged].sort());
|
|
35
|
+
}
|
|
30
36
|
export function clipAllowedActions(requested, parent) {
|
|
31
37
|
const ceiling = new Set(parent);
|
|
32
38
|
return Object.freeze(requested.filter((action) => ceiling.has(action)));
|
|
@@ -96,7 +96,11 @@ function decodeArchetype(name, path, markdown) {
|
|
|
96
96
|
const network = archetypeEnum(values, "network", ["disabled", "enabled"]);
|
|
97
97
|
const description = archetypeField(values, "description");
|
|
98
98
|
const allowed = effectiveAllowedActions(values.allowed);
|
|
99
|
+
const systemPromptMode = archetypeEnum(values, "systemPromptMode", ["append", "replace"]);
|
|
99
100
|
const systemPrompt = lines.slice(closing + 1).join("\n");
|
|
101
|
+
if (systemPromptMode !== undefined && systemPrompt.length === 0) {
|
|
102
|
+
throw new TypeError("Akuma systemPromptMode requires a nonempty Markdown body");
|
|
103
|
+
}
|
|
100
104
|
return Object.freeze({
|
|
101
105
|
name,
|
|
102
106
|
path,
|
|
@@ -106,7 +110,12 @@ function decodeArchetype(name, path, markdown) {
|
|
|
106
110
|
...(model === undefined ? {} : { model }),
|
|
107
111
|
...(effort === undefined ? {} : { effort }),
|
|
108
112
|
...(network === undefined ? {} : { network }),
|
|
109
|
-
...(systemPrompt.length === 0
|
|
113
|
+
...(systemPrompt.length === 0
|
|
114
|
+
? {}
|
|
115
|
+
: {
|
|
116
|
+
systemPrompt,
|
|
117
|
+
systemPromptMode: systemPromptMode ?? "append",
|
|
118
|
+
}),
|
|
110
119
|
}),
|
|
111
120
|
...(readonly === undefined ? {} : { readonly }),
|
|
112
121
|
allowed,
|
|
@@ -135,7 +144,8 @@ export async function listArchetypeDefinitions(input = {}) {
|
|
|
135
144
|
}
|
|
136
145
|
function record(value) {
|
|
137
146
|
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
138
|
-
? value
|
|
147
|
+
? value
|
|
148
|
+
: null;
|
|
139
149
|
}
|
|
140
150
|
function optionalProviderText(value, name, field) {
|
|
141
151
|
const selected = value[field];
|