@astrosheep/keiyaku 4.5.19 → 4.5.20
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/skills/keiyaku/SKILL.md +11 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +33 -14
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +0 -1
- package/build/src/akuma/akuma-observe.js +1 -0
- package/build/src/akuma/akuma-product.d.ts +1 -0
- package/build/src/akuma/akuma-product.js +3 -0
- package/build/src/akuma/akuma.d.ts +19 -1
- package/build/src/akuma/akuma.js +2 -0
- package/build/src/akuma/allowed.d.ts +20 -0
- package/build/src/akuma/allowed.js +11 -0
- package/build/src/akuma/archetype.js +3 -0
- package/build/src/akuma/body.js +5 -23
- package/build/src/akuma/call-request.d.ts +3 -0
- package/build/src/akuma/call-request.js +12 -4
- package/build/src/akuma/fleet-observation.d.ts +54 -0
- package/build/src/akuma/fleet-request.js +2 -1
- package/build/src/akuma/provider-recipe.d.ts +1 -0
- package/build/src/akuma/provider-recipe.js +5 -0
- package/build/src/akuma/providers/acp/index.js +3 -0
- package/build/src/akuma/providers/claude/index.js +3 -0
- package/build/src/akuma/providers/codex-app-server/index.js +8 -0
- package/build/src/akuma/providers/grok-build/index.js +3 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +2 -0
- package/build/src/akuma/providers/pi/index.js +2 -0
- package/build/src/akuma/request-observation.d.ts +45 -0
- package/build/src/akuma/request-observation.js +162 -0
- package/build/src/akuma/request-rendezvous.d.ts +6 -3
- package/build/src/akuma/request-rendezvous.js +75 -14
- package/build/src/akuma/request-serve.js +27 -4
- package/build/src/akuma/request-wire.d.ts +5 -0
- package/build/src/akuma/request-wire.js +2 -0
- package/build/src/akuma-body.js +3 -0
- package/build/src/cli/commands/akuma-invoke.d.ts +1 -1
- package/build/src/cli/commands/akuma-invoke.js +1 -1
- package/build/src/cli/commands/akuma.js +13 -8
- package/build/src/cli/commands/contract-help.d.ts +15 -15
- package/build/src/cli/commands/contract-help.js +28 -15
- package/build/src/cli/commands/contract-invoke.d.ts +3 -0
- package/build/src/cli/commands/contract-invoke.js +25 -11
- package/build/src/cli/commands/install.d.ts +1 -1
- package/build/src/cli/commands/install.js +1 -1
- package/build/src/cli/commands/task.js +18 -18
- package/build/src/cli/invoke.d.ts +3 -0
- package/build/src/cli/invoke.js +58 -23
- package/build/src/cli/parse.d.ts +1 -0
- package/build/src/cli/parse.js +21 -4
- package/build/src/cli/render/akuma-activity.d.ts +1 -0
- package/build/src/cli/render/akuma-activity.js +1 -0
- package/build/src/cli/render/akuma.js +4 -1
- package/build/src/cli/render/execution-progress.d.ts +4 -0
- package/build/src/cli/render/execution-progress.js +55 -0
- package/build/src/cli/render/receipt.js +1 -1
- package/build/src/cli/runtime.js +27 -1
- package/build/src/git/hooks.d.ts +13 -1
- package/build/src/git/hooks.js +2 -1
- package/build/src/git/verification-environment.d.ts +10 -0
- package/build/src/git/verification-environment.js +281 -0
- package/build/src/library/akuma-creation.js +1 -1
- package/build/src/library/audit.d.ts +2 -0
- package/build/src/library/audit.js +1 -0
- package/build/src/library/composition.d.ts +1 -0
- package/build/src/library/contract-execution.d.ts +2 -0
- package/build/src/library/contract-execution.js +15 -1
- package/build/src/library/contract-forwarding.d.ts +4 -0
- package/build/src/library/contract-forwarding.js +3 -0
- package/build/src/library/contract-handle.d.ts +7 -0
- package/build/src/library/contract-handle.js +25 -0
- package/build/src/library/contract-operations.d.ts +5 -0
- package/build/src/library/contract-operations.js +20 -0
- package/build/src/library/execution-result.d.ts +2 -2
- package/build/src/library/execution.d.ts +8 -0
- package/build/src/library/execution.js +102 -0
- package/build/src/library/keiyaku.d.ts +2 -0
- package/build/src/library/mutation.js +15 -7
- package/build/src/plugin/akuma-signals.js +1 -1
- package/build/src/plugin/public.d.ts +2 -2
- package/build/src/plugin/runtime.d.ts +1 -3
- package/build/src/plugin/runtime.js +91 -102
- package/build/src/protocol/completion.js +28 -10
- package/build/src/protocol/execution-observation.d.ts +185 -0
- package/build/src/protocol/execution-observation.js +45 -0
- package/build/src/protocol/intent.d.ts +3 -2
- package/build/src/protocol/intent.js +44 -34
- package/build/src/protocol/progress.d.ts +5 -1
- package/build/src/protocol/progress.js +10 -1
- package/build/src/protocol/result-codec.js +18 -4
- package/build/src/runtime/proc/run.d.ts +16 -4
- package/build/src/runtime/proc/run.js +64 -22
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/verification/execution.d.ts +11 -2
- package/build/src/verification/execution.js +167 -42
- package/build/src/verification/observation.d.ts +45 -0
- package/build/src/verification/observation.js +30 -0
- package/package.json +1 -1
|
@@ -36,15 +36,22 @@ keiyaku -C <repo> review [<contract>|@<contract>] --satisfied
|
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
keiyaku -C <cwd> call <akuma-name> [--contract <kei/...>] [--alias @name] [--allowed <product.action>]... [--schema <file>] [--wait <duration> | -d | --detach]
|
|
39
|
+
keiyaku -C <cwd> call <akuma-name> [--contract <kei/...>] [--workdir <path>] [--alias @name] [--allowed <product.action>]... [--schema <file>] [--wait <duration> | -d | --detach] (<prompt> | -)
|
|
40
40
|
keiyaku -C <repo> wait <akuma-selector>... [--any | --all]
|
|
41
41
|
keiyaku -C <repo> tell <aku/...|@alias> (<prompt> | -)
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
`-C`
|
|
45
|
-
|
|
44
|
+
`-C` selects the invocation cwd and therefore the World. `--repo <path>` only
|
|
45
|
+
selects the Contract repository; it never retargets that World. `call
|
|
46
|
+
--workdir <path>` selects execution cwd (relative to the effective invocation
|
|
47
|
+
cwd). Without it, a Contract call uses its appointed worktree and an
|
|
48
|
+
unassociated call uses the invocation cwd.
|
|
46
49
|
|
|
47
50
|
Repeated `--allowed` values add actions to the selected Akuma's defaults. A
|
|
48
51
|
nested call can use only actions permitted by its direct parent Soul.
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
`deliver`, `review`, and `audit` may take time after their leading admission.
|
|
54
|
+
Their witnessed progress is ephemeral stderr output; stdout remains one final
|
|
55
|
+
text or JSON result. Ctrl-C asks the owned operation to stop and waits for its
|
|
56
|
+
truthful final receipt, so it is not evidence that an already admitted action
|
|
57
|
+
was rolled back.
|
|
@@ -15,7 +15,7 @@ is accepted; the identity underneath never changes.
|
|
|
15
15
|
## Start One
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
keiyaku -C <cwd> call <akuma-name> [--alias @name] [--allowed <product.action>]... [--schema <file>] [--wait <duration> | -d | --detach]
|
|
18
|
+
keiyaku -C <cwd> call <akuma-name> [--workdir <path>] [--alias @name] [--allowed <product.action>]... [--schema <file>] [--wait <duration> | -d | --detach] (<prompt> | -)
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Give the worker's initial prompt as one argument (quote it when it contains
|
|
@@ -28,20 +28,30 @@ exclusive. Decide up front whether you will stay:
|
|
|
28
28
|
work outlives your attention; come back with `wait`.
|
|
29
29
|
|
|
30
30
|
`--alias @name` assigns that world-local selector to the born Akuma. If the
|
|
31
|
-
Alias already points elsewhere, it moves to the born Akuma.
|
|
32
|
-
|
|
31
|
+
Alias already points elsewhere, it moves to the born Akuma. `-C` selects the
|
|
32
|
+
invocation World; `--workdir <path>` selects the worker execution cwd relative
|
|
33
|
+
to that invocation directory. Without `--workdir`, an unassociated call uses
|
|
34
|
+
the invocation cwd, while a `--contract` call uses its appointed worktree.
|
|
33
35
|
|
|
34
|
-
Repeated `--allowed` values add actions to the selected Akuma's defaults
|
|
35
|
-
|
|
36
|
+
Repeated `--allowed` values add actions to the selected Akuma's defaults; they
|
|
37
|
+
never narrow them. An omitted Archetype default permits the complete action
|
|
38
|
+
vocabulary, while an explicit empty default permits none. A nested call can use
|
|
39
|
+
only actions permitted by its direct parent Soul. Use `status <aku/...|@alias>`
|
|
40
|
+
to inspect the born worker's frozen effective actions.
|
|
36
41
|
|
|
37
42
|
## Akuma Names
|
|
38
43
|
|
|
39
|
-
An Akuma name selects a
|
|
40
|
-
the
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
An Akuma name selects a reusable worker configuration, not an individual worker.
|
|
45
|
+
Calling the same name multiple times creates independent workers with distinct
|
|
46
|
+
AkuIds. Choose different names for different capabilities, not merely to run
|
|
47
|
+
work in parallel.
|
|
48
|
+
|
|
49
|
+
Each name fixes its own capability stance — provider, model, permissions —
|
|
50
|
+
and a born Akuma keeps those selected defaults for its lifetime. `keiyaku ls
|
|
51
|
+
aku/` lists the available names with their providers and descriptions. If none
|
|
52
|
+
grants the permissions and stance the work needs, add a new Akuma name;
|
|
53
|
+
`keiyaku settings --help` says where Akuma definitions live and what they may
|
|
54
|
+
declare.
|
|
45
55
|
|
|
46
56
|
## Commission And Steer
|
|
47
57
|
|
|
@@ -64,6 +74,13 @@ including nested calls, which stay under this Soul's ceiling — and state the
|
|
|
64
74
|
loop as the question. Steering that delegation afterwards goes to the holder,
|
|
65
75
|
not around it.
|
|
66
76
|
|
|
77
|
+
When that whole-loop worker must operate in the main repository rather than its
|
|
78
|
+
Contract worktree, make that execution choice explicit:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
keiyaku -C <repo> call worker --contract <kei/...> --workdir <repo> --allowed contract.deliver -d "Own this Contract loop."
|
|
82
|
+
```
|
|
83
|
+
|
|
67
84
|
## Watch
|
|
68
85
|
|
|
69
86
|
```bash
|
|
@@ -78,9 +95,11 @@ a mode. When observing multiple Akuma, prefer one plural wait over separate
|
|
|
78
95
|
waits and choose exactly one mode:
|
|
79
96
|
|
|
80
97
|
```bash
|
|
81
|
-
keiyaku -C <cwd>
|
|
82
|
-
keiyaku -C <cwd>
|
|
83
|
-
keiyaku -C <cwd> wait @
|
|
98
|
+
keiyaku -C <cwd> call worker --alias @projection -d "Inspect the projection."
|
|
99
|
+
keiyaku -C <cwd> call worker --alias @host-boundary -d "Inspect the host boundary."
|
|
100
|
+
keiyaku -C <cwd> wait @projection --timeout 5m
|
|
101
|
+
keiyaku -C <cwd> wait @projection @host-boundary --all --timeout 5m
|
|
102
|
+
keiyaku -C <cwd> wait @projection @host-boundary --any --timeout 5m
|
|
84
103
|
```
|
|
85
104
|
|
|
86
105
|
`--all` waits until every selected Akuma stops running. `--any` returns when the
|
|
@@ -62,7 +62,6 @@ keiyaku task update <task-id> --title <text>
|
|
|
62
62
|
keiyaku task context [<namespace>]
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
Use `--json` on any command when a script must inspect the typed result.
|
|
66
65
|
Relations are explicit facts: `needs` orders work, `parent` groups it,
|
|
67
66
|
`supersedes` navigates replacement, and `relates` does not affect readiness.
|
|
68
67
|
`task start` accepts one or more complete TaskIds. A single ID keeps the
|
|
@@ -72,6 +72,7 @@ export async function bornStatus(paths, expected, input) {
|
|
|
72
72
|
status: {
|
|
73
73
|
id: soul.id,
|
|
74
74
|
life: currentLife,
|
|
75
|
+
allowed: soul.allowed,
|
|
75
76
|
...(soul.readonly === undefined ? {} : { readonly: soul.readonly }),
|
|
76
77
|
...(resumeUnsupported ? { strandedReason: "resume-unsupported" } : {}),
|
|
77
78
|
timeline: selected.snapshot,
|
|
@@ -26,6 +26,7 @@ async function admitBodyRequest(input) {
|
|
|
26
26
|
world: input.path,
|
|
27
27
|
archetype: input.name,
|
|
28
28
|
...(input.call.body === undefined ? {} : { body: input.call.body }),
|
|
29
|
+
...(input.call.schema === undefined ? {} : { awaitAsleep: true }),
|
|
29
30
|
...(cwd === undefined ? {} : { cwd }),
|
|
30
31
|
recipe: input.recipe,
|
|
31
32
|
});
|
|
@@ -56,6 +57,7 @@ async function admitDirect(input) {
|
|
|
56
57
|
},
|
|
57
58
|
...(input.call.body === undefined ? {} : { initialBody: input.call.body }),
|
|
58
59
|
...(input.call.schema === undefined ? {} : { initialSchemaJson: schemaJsonText(input.call.schema) }),
|
|
60
|
+
...(input.call.schema === undefined ? {} : { awaitAsleep: true }),
|
|
59
61
|
execution: {
|
|
60
62
|
cwd,
|
|
61
63
|
source: input.call.cwd !== undefined ? "input" : initiatorCwd === undefined ? "world" : "process",
|
|
@@ -206,6 +208,7 @@ class AkumaProduct {
|
|
|
206
208
|
}
|
|
207
209
|
const published = await launchAkuma({
|
|
208
210
|
allocated: born.allocated,
|
|
211
|
+
...(born.awaitAsleep === undefined ? {} : { awaitAsleep: born.awaitAsleep }),
|
|
209
212
|
launch: async (allocated) => await spawnAkumaBody({
|
|
210
213
|
paths: allocated.paths,
|
|
211
214
|
seed: born.seed,
|
|
@@ -3,7 +3,7 @@ export type { KillEvidence };
|
|
|
3
3
|
import { type AkuId } from "./identity.js";
|
|
4
4
|
import type { Settings } from "../settings.js";
|
|
5
5
|
import type { WorldRoot } from "../world.js";
|
|
6
|
-
import type
|
|
6
|
+
import { type AllowedAction } from "./allowed.js";
|
|
7
7
|
import type { ExecutionContext } from "./requests.js";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import type { BoundedList } from "../bounded-list.js";
|
|
@@ -32,6 +32,24 @@ export declare const akumaStatusSchema: z.ZodObject<{
|
|
|
32
32
|
asleep: "asleep";
|
|
33
33
|
stranded: "stranded";
|
|
34
34
|
}>;
|
|
35
|
+
allowed: z.ZodPipe<z.ZodArray<z.ZodEnum<{
|
|
36
|
+
"task.add": "task.add";
|
|
37
|
+
"task.addDocument": "task.addDocument";
|
|
38
|
+
"task.compose": "task.compose";
|
|
39
|
+
"task.done": "task.done";
|
|
40
|
+
"task.drop": "task.drop";
|
|
41
|
+
"task.hold": "task.hold";
|
|
42
|
+
"task.resume": "task.resume";
|
|
43
|
+
"task.start": "task.start";
|
|
44
|
+
"task.stop": "task.stop";
|
|
45
|
+
"task.update": "task.update";
|
|
46
|
+
"akuma.call": "akuma.call";
|
|
47
|
+
"akuma.kill": "akuma.kill";
|
|
48
|
+
"akuma.tell": "akuma.tell";
|
|
49
|
+
"contract.audit": "contract.audit";
|
|
50
|
+
"contract.deliver": "contract.deliver";
|
|
51
|
+
"contract.review": "contract.review";
|
|
52
|
+
}>>, z.ZodTransform<import("./allowed.js").AllowedActions, ("task.add" | "task.addDocument" | "task.compose" | "task.done" | "task.drop" | "task.hold" | "task.resume" | "task.start" | "task.stop" | "task.update" | "akuma.call" | "akuma.kill" | "akuma.tell" | "contract.audit" | "contract.deliver" | "contract.review")[]>>;
|
|
35
53
|
readonly: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
36
54
|
enforcement: z.ZodLiteral<"native">;
|
|
37
55
|
}, z.core.$strict>, z.ZodObject<{
|
package/build/src/akuma/akuma.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseAkuId } from "./identity.js";
|
|
2
2
|
import { activitySnapshotSchema } from "./projection.js";
|
|
3
|
+
import { allowedActionsSchema } from "./allowed.js";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
import { createAkumaProduct } from "./akuma-product.js";
|
|
5
6
|
import { killAkumaWithRecovery } from "./akuma-handle.js";
|
|
@@ -25,6 +26,7 @@ export const akumaStatusSchema = z
|
|
|
25
26
|
.object({
|
|
26
27
|
id: akumaIdSchema,
|
|
27
28
|
life: z.enum(["running", "asleep", "stranded", "hung", "untidy", "killed"]),
|
|
29
|
+
allowed: allowedActionsSchema,
|
|
28
30
|
readonly: readonlySchema.optional(),
|
|
29
31
|
timeline: activitySnapshotSchema,
|
|
30
32
|
strandedReason: z.literal("resume-unsupported").optional(),
|
|
@@ -1,8 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
export declare const ALLOWED_ACTIONS: readonly ["akuma.call", "akuma.kill", "akuma.tell", "contract.audit", "contract.deliver", "contract.review", "task.add", "task.addDocument", "task.compose", "task.done", "task.drop", "task.hold", "task.resume", "task.start", "task.stop", "task.update"];
|
|
2
3
|
export type AllowedAction = (typeof ALLOWED_ACTIONS)[number];
|
|
3
4
|
export type AllowedActions = readonly AllowedAction[];
|
|
4
5
|
export declare function isAllowedAction(value: unknown): value is AllowedAction;
|
|
5
6
|
export declare function decodeAllowedActions(value: unknown, label?: string): AllowedActions;
|
|
7
|
+
/** Public codecs retain the Soul's canonical, duplicate-free action membership. */
|
|
8
|
+
export declare const allowedActionsSchema: z.ZodPipe<z.ZodArray<z.ZodEnum<{
|
|
9
|
+
"task.add": "task.add";
|
|
10
|
+
"task.addDocument": "task.addDocument";
|
|
11
|
+
"task.compose": "task.compose";
|
|
12
|
+
"task.done": "task.done";
|
|
13
|
+
"task.drop": "task.drop";
|
|
14
|
+
"task.hold": "task.hold";
|
|
15
|
+
"task.resume": "task.resume";
|
|
16
|
+
"task.start": "task.start";
|
|
17
|
+
"task.stop": "task.stop";
|
|
18
|
+
"task.update": "task.update";
|
|
19
|
+
"akuma.call": "akuma.call";
|
|
20
|
+
"akuma.kill": "akuma.kill";
|
|
21
|
+
"akuma.tell": "akuma.tell";
|
|
22
|
+
"contract.audit": "contract.audit";
|
|
23
|
+
"contract.deliver": "contract.deliver";
|
|
24
|
+
"contract.review": "contract.review";
|
|
25
|
+
}>>, z.ZodTransform<AllowedActions, ("task.add" | "task.addDocument" | "task.compose" | "task.done" | "task.drop" | "task.hold" | "task.resume" | "task.start" | "task.stop" | "task.update" | "akuma.call" | "akuma.kill" | "akuma.tell" | "contract.audit" | "contract.deliver" | "contract.review")[]>>;
|
|
6
26
|
export declare function effectiveAllowedActions(value: unknown): AllowedActions;
|
|
7
27
|
export declare function unionAllowedActions(base: AllowedActions, additions: AllowedActions): AllowedActions;
|
|
8
28
|
export declare function clipAllowedActions(requested: AllowedActions, parent: AllowedActions): AllowedActions;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TASK_MUTATION_ACTIONS } from "../task/mutation.js";
|
|
2
|
+
import { z } from "zod";
|
|
2
3
|
export const ALLOWED_ACTIONS = Object.freeze([
|
|
3
4
|
"akuma.call",
|
|
4
5
|
"akuma.kill",
|
|
@@ -25,6 +26,16 @@ export function decodeAllowedActions(value, label = "allowed") {
|
|
|
25
26
|
}
|
|
26
27
|
return Object.freeze([...seen].sort());
|
|
27
28
|
}
|
|
29
|
+
/** Public codecs retain the Soul's canonical, duplicate-free action membership. */
|
|
30
|
+
export const allowedActionsSchema = z.array(z.enum(ALLOWED_ACTIONS)).transform((value, context) => {
|
|
31
|
+
try {
|
|
32
|
+
return decodeAllowedActions(value);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
context.addIssue({ code: "custom", message: error instanceof Error ? error.message : String(error) });
|
|
36
|
+
return z.NEVER;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
28
39
|
export function effectiveAllowedActions(value) {
|
|
29
40
|
return value === undefined ? ALLOWED_ACTIONS : decodeAllowedActions(value);
|
|
30
41
|
}
|
|
@@ -132,6 +132,7 @@ function decodeArchetypeFields(values) {
|
|
|
132
132
|
const effort = archetypeField(values, "effort");
|
|
133
133
|
const readonly = archetypeReadonly(values);
|
|
134
134
|
const network = archetypeEnum(values, "network", ["disabled", "enabled"]);
|
|
135
|
+
const sandbox = archetypeEnum(values, "sandbox", ["full-access"]);
|
|
135
136
|
const description = archetypeField(values, "description");
|
|
136
137
|
const allowedPresent = "allowed" in values;
|
|
137
138
|
const allowed = allowedPresent ? effectiveAllowedActions(values.allowed) : undefined;
|
|
@@ -143,6 +144,7 @@ function decodeArchetypeFields(values) {
|
|
|
143
144
|
...(effort === undefined ? {} : { effort }),
|
|
144
145
|
...(readonly === undefined ? {} : { readonly }),
|
|
145
146
|
...(network === undefined ? {} : { network }),
|
|
147
|
+
...(sandbox === undefined ? {} : { sandbox }),
|
|
146
148
|
...(description === undefined ? {} : { description }),
|
|
147
149
|
...(allowed === undefined ? {} : { allowed }),
|
|
148
150
|
allowedPresent,
|
|
@@ -166,6 +168,7 @@ function decodeArchetype(name, path, markdown) {
|
|
|
166
168
|
...(fields.model === undefined ? {} : { model: fields.model }),
|
|
167
169
|
...(fields.effort === undefined ? {} : { effort: fields.effort }),
|
|
168
170
|
...(fields.network === undefined ? {} : { network: fields.network }),
|
|
171
|
+
...(fields.sandbox === undefined ? {} : { sandbox: fields.sandbox }),
|
|
169
172
|
...(systemPrompt.length === 0
|
|
170
173
|
? {}
|
|
171
174
|
: {
|
package/build/src/akuma/body.js
CHANGED
|
@@ -231,13 +231,11 @@ async function recoverBodyRequests(input) {
|
|
|
231
231
|
}
|
|
232
232
|
function turnOutcomeEmitter(launch, soul) {
|
|
233
233
|
let plugins;
|
|
234
|
-
const pending = new Set();
|
|
235
234
|
const reportDiagnostic = (message) => {
|
|
236
235
|
void recordPluginDiagnostic(launch.paths, "turn outcome", message);
|
|
237
236
|
};
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
delivery = (async () => {
|
|
237
|
+
return {
|
|
238
|
+
async emit(turnSequence, outcome) {
|
|
241
239
|
try {
|
|
242
240
|
plugins ??= pluginRuntime({
|
|
243
241
|
world: await World.at(worldRootForAkumaPaths(launch.paths)),
|
|
@@ -256,17 +254,8 @@ function turnOutcomeEmitter(launch, soul) {
|
|
|
256
254
|
catch (error) {
|
|
257
255
|
await recordPluginDiagnostic(launch.paths, "turn outcome", error);
|
|
258
256
|
}
|
|
259
|
-
}
|
|
260
|
-
pending.add(delivery);
|
|
261
|
-
return delivery;
|
|
262
|
-
};
|
|
263
|
-
const drain = async () => {
|
|
264
|
-
while (pending.size > 0)
|
|
265
|
-
await Promise.all([...pending]);
|
|
266
|
-
if (plugins !== undefined)
|
|
267
|
-
await (await plugins).drain("akuma.turn-outcome");
|
|
257
|
+
},
|
|
268
258
|
};
|
|
269
|
-
return { emit, drain };
|
|
270
259
|
}
|
|
271
260
|
function bodyEndEmitter(launch, soul) {
|
|
272
261
|
let plugins;
|
|
@@ -288,7 +277,6 @@ function bodyEndEmitter(launch, soul) {
|
|
|
288
277
|
...(diagnostic === undefined ? {} : { diagnostic }),
|
|
289
278
|
...(launch.completion?.contractId === undefined ? {} : { contractId: launch.completion.contractId }),
|
|
290
279
|
}, reportDiagnostic);
|
|
291
|
-
await (await plugins).drain("akuma.body-ended");
|
|
292
280
|
}
|
|
293
281
|
catch (error) {
|
|
294
282
|
await recordPluginDiagnostic(launch.paths, "body end", error);
|
|
@@ -346,7 +334,7 @@ async function runBodyTurns(input) {
|
|
|
346
334
|
return;
|
|
347
335
|
}
|
|
348
336
|
const outcome = await persistTurn(launch.paths, result.turnSequence, result, runtime.now());
|
|
349
|
-
|
|
337
|
+
await turnOutcome.emit(result.turnSequence, outcome);
|
|
350
338
|
if (outcome.outcome === "failed") {
|
|
351
339
|
await failOpenBoundTurnsIfPresent(launch.paths, bodySequence, outcome.diagnostic, runtime.now());
|
|
352
340
|
await breakBody(launch.paths, { sequence: bodySequence, end: "broke-off", at: runtime.now() });
|
|
@@ -508,19 +496,13 @@ export async function driveAkumaBody(launch, adapter, runtimeInput = {}) {
|
|
|
508
496
|
await resolveDecidedPendingTellDisposition(launch.paths, finished.decided, runtime.spawnBody ?? spawnAkumaBody);
|
|
509
497
|
if (finished.notification !== undefined)
|
|
510
498
|
await finished.notification;
|
|
511
|
-
void emitTurnOutcome?.drain();
|
|
512
499
|
}
|
|
513
500
|
}
|
|
514
501
|
export async function spawnAkumaBody(launch) {
|
|
515
502
|
return await spawnDetachedProcess(await bodyProcessInput(launch));
|
|
516
503
|
}
|
|
517
504
|
export async function runAkumaBody(launch, world, externalCommands) {
|
|
518
|
-
|
|
519
|
-
return await driveAkumaBody(launch, undefined, { world, externalCommands });
|
|
520
|
-
}
|
|
521
|
-
finally {
|
|
522
|
-
await (await pluginRuntime({ world })).drain();
|
|
523
|
-
}
|
|
505
|
+
return await driveAkumaBody(launch, undefined, { world, externalCommands });
|
|
524
506
|
}
|
|
525
507
|
const DIRECT_TELL_WAKE = {
|
|
526
508
|
spawn: async (paths) => await spawnAkumaBody({ paths, refuseIfHeld: true }),
|
|
@@ -19,6 +19,7 @@ declare const akumaCallRecipeSchema: z.ZodObject<{
|
|
|
19
19
|
effort?: string;
|
|
20
20
|
readonly?: true;
|
|
21
21
|
network?: "disabled" | "enabled";
|
|
22
|
+
sandbox?: "full-access";
|
|
22
23
|
systemPrompt?: string;
|
|
23
24
|
systemPromptMode?: import("./provider-recipe.js").SystemPromptMode;
|
|
24
25
|
}>, unknown>>;
|
|
@@ -28,6 +29,7 @@ declare const akumaCallPayloadSchema: z.ZodObject<{
|
|
|
28
29
|
world: z.ZodString;
|
|
29
30
|
archetype: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
30
31
|
body: z.ZodOptional<z.ZodString>;
|
|
32
|
+
awaitAsleep: z.ZodOptional<z.ZodLiteral<true>>;
|
|
31
33
|
cwd: z.ZodOptional<z.ZodString>;
|
|
32
34
|
recipe: z.ZodObject<{
|
|
33
35
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -44,6 +46,7 @@ declare const akumaCallPayloadSchema: z.ZodObject<{
|
|
|
44
46
|
effort?: string;
|
|
45
47
|
readonly?: true;
|
|
46
48
|
network?: "disabled" | "enabled";
|
|
49
|
+
sandbox?: "full-access";
|
|
47
50
|
systemPrompt?: string;
|
|
48
51
|
systemPromptMode?: import("./provider-recipe.js").SystemPromptMode;
|
|
49
52
|
}>, unknown>>;
|
|
@@ -4,7 +4,7 @@ import { refuseRequest, reserveRequest } from "./heart/index.js";
|
|
|
4
4
|
import { archetypeName, parseAkuId } from "./identity.js";
|
|
5
5
|
import { publishAkuma } from "./publication.js";
|
|
6
6
|
import { decodeProviderOptions, decodeReadonlyRestraint } from "./provider-recipe.js";
|
|
7
|
-
import { decodeProviderExecution } from "./providers/index.js";
|
|
7
|
+
import { decodeProviderExecution, resolveProviderExecution } from "./providers/index.js";
|
|
8
8
|
import { requestBodyCommand } from "./request-rendezvous.js";
|
|
9
9
|
import { eraseRequestCommand, } from "./request-wire.js";
|
|
10
10
|
import { z } from "zod";
|
|
@@ -67,6 +67,7 @@ const akumaCallPayloadSchema = z
|
|
|
67
67
|
world: absolutePathSchema,
|
|
68
68
|
archetype: archetypeSchema,
|
|
69
69
|
body: z.string().optional(),
|
|
70
|
+
awaitAsleep: z.literal(true).optional(),
|
|
70
71
|
cwd: absolutePathSchema.optional(),
|
|
71
72
|
recipe: akumaCallRecipeSchema,
|
|
72
73
|
})
|
|
@@ -86,17 +87,24 @@ async function executeAkumaCall(request, facts, capabilities) {
|
|
|
86
87
|
await refuseRequest(paths, facts.id, `request world ${requestWorld} does not match ${world}`);
|
|
87
88
|
throw new Error(`request world ${requestWorld} does not match ${world}`);
|
|
88
89
|
}
|
|
90
|
+
const selected = await resolveProviderExecution(request.recipe.provider);
|
|
91
|
+
const admission = selected.adapter.admitOptions(request.recipe.options);
|
|
92
|
+
if (admission.kind === "refused") {
|
|
93
|
+
await refuseRequest(paths, facts.id, admission.diagnostic);
|
|
94
|
+
throw new Error(admission.diagnostic);
|
|
95
|
+
}
|
|
89
96
|
const recipe = {
|
|
90
97
|
...(request.recipe.description === undefined ? {} : { description: request.recipe.description }),
|
|
91
98
|
allowed: clipAllowedActions(request.recipe.allowed, parent.allowed),
|
|
92
|
-
provider:
|
|
93
|
-
options:
|
|
94
|
-
...(
|
|
99
|
+
provider: selected.execution,
|
|
100
|
+
options: admission.options,
|
|
101
|
+
...(admission.readonly === undefined ? {} : { readonly: admission.readonly }),
|
|
95
102
|
};
|
|
96
103
|
const published = await publishAkuma({
|
|
97
104
|
worldPath: world,
|
|
98
105
|
archetype: request.archetype,
|
|
99
106
|
signal: facts.signal,
|
|
107
|
+
...(request.awaitAsleep === undefined ? {} : { awaitAsleep: request.awaitAsleep }),
|
|
100
108
|
launch: async (allocated) => {
|
|
101
109
|
if (!facts.admissionOpen())
|
|
102
110
|
throw new Error("body closed request admission");
|
|
@@ -10,6 +10,24 @@ declare const akumaObservationSchema: z.ZodObject<{
|
|
|
10
10
|
asleep: "asleep";
|
|
11
11
|
stranded: "stranded";
|
|
12
12
|
}>;
|
|
13
|
+
allowed: z.ZodPipe<z.ZodArray<z.ZodEnum<{
|
|
14
|
+
"task.add": "task.add";
|
|
15
|
+
"task.addDocument": "task.addDocument";
|
|
16
|
+
"task.compose": "task.compose";
|
|
17
|
+
"task.done": "task.done";
|
|
18
|
+
"task.drop": "task.drop";
|
|
19
|
+
"task.hold": "task.hold";
|
|
20
|
+
"task.resume": "task.resume";
|
|
21
|
+
"task.start": "task.start";
|
|
22
|
+
"task.stop": "task.stop";
|
|
23
|
+
"task.update": "task.update";
|
|
24
|
+
"akuma.call": "akuma.call";
|
|
25
|
+
"akuma.kill": "akuma.kill";
|
|
26
|
+
"akuma.tell": "akuma.tell";
|
|
27
|
+
"contract.audit": "contract.audit";
|
|
28
|
+
"contract.deliver": "contract.deliver";
|
|
29
|
+
"contract.review": "contract.review";
|
|
30
|
+
}>>, z.ZodTransform<import("./allowed.js").AllowedActions, ("task.add" | "task.addDocument" | "task.compose" | "task.done" | "task.drop" | "task.hold" | "task.resume" | "task.start" | "task.stop" | "task.update" | "akuma.call" | "akuma.kill" | "akuma.tell" | "contract.audit" | "contract.deliver" | "contract.review")[]>>;
|
|
13
31
|
readonly: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
14
32
|
enforcement: z.ZodLiteral<"native">;
|
|
15
33
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -446,6 +464,24 @@ declare const akumaWaitResultSchema: z.ZodObject<{
|
|
|
446
464
|
asleep: "asleep";
|
|
447
465
|
stranded: "stranded";
|
|
448
466
|
}>;
|
|
467
|
+
allowed: z.ZodPipe<z.ZodArray<z.ZodEnum<{
|
|
468
|
+
"task.add": "task.add";
|
|
469
|
+
"task.addDocument": "task.addDocument";
|
|
470
|
+
"task.compose": "task.compose";
|
|
471
|
+
"task.done": "task.done";
|
|
472
|
+
"task.drop": "task.drop";
|
|
473
|
+
"task.hold": "task.hold";
|
|
474
|
+
"task.resume": "task.resume";
|
|
475
|
+
"task.start": "task.start";
|
|
476
|
+
"task.stop": "task.stop";
|
|
477
|
+
"task.update": "task.update";
|
|
478
|
+
"akuma.call": "akuma.call";
|
|
479
|
+
"akuma.kill": "akuma.kill";
|
|
480
|
+
"akuma.tell": "akuma.tell";
|
|
481
|
+
"contract.audit": "contract.audit";
|
|
482
|
+
"contract.deliver": "contract.deliver";
|
|
483
|
+
"contract.review": "contract.review";
|
|
484
|
+
}>>, z.ZodTransform<import("./allowed.js").AllowedActions, ("task.add" | "task.addDocument" | "task.compose" | "task.done" | "task.drop" | "task.hold" | "task.resume" | "task.start" | "task.stop" | "task.update" | "akuma.call" | "akuma.kill" | "akuma.tell" | "contract.audit" | "contract.deliver" | "contract.review")[]>>;
|
|
449
485
|
readonly: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
450
486
|
enforcement: z.ZodLiteral<"native">;
|
|
451
487
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -1001,6 +1037,24 @@ export declare const fleetResultSchemas: {
|
|
|
1001
1037
|
asleep: "asleep";
|
|
1002
1038
|
stranded: "stranded";
|
|
1003
1039
|
}>;
|
|
1040
|
+
allowed: z.ZodPipe<z.ZodArray<z.ZodEnum<{
|
|
1041
|
+
"task.add": "task.add";
|
|
1042
|
+
"task.addDocument": "task.addDocument";
|
|
1043
|
+
"task.compose": "task.compose";
|
|
1044
|
+
"task.done": "task.done";
|
|
1045
|
+
"task.drop": "task.drop";
|
|
1046
|
+
"task.hold": "task.hold";
|
|
1047
|
+
"task.resume": "task.resume";
|
|
1048
|
+
"task.start": "task.start";
|
|
1049
|
+
"task.stop": "task.stop";
|
|
1050
|
+
"task.update": "task.update";
|
|
1051
|
+
"akuma.call": "akuma.call";
|
|
1052
|
+
"akuma.kill": "akuma.kill";
|
|
1053
|
+
"akuma.tell": "akuma.tell";
|
|
1054
|
+
"contract.audit": "contract.audit";
|
|
1055
|
+
"contract.deliver": "contract.deliver";
|
|
1056
|
+
"contract.review": "contract.review";
|
|
1057
|
+
}>>, z.ZodTransform<import("./allowed.js").AllowedActions, ("task.add" | "task.addDocument" | "task.compose" | "task.done" | "task.drop" | "task.hold" | "task.resume" | "task.start" | "task.stop" | "task.update" | "akuma.call" | "akuma.kill" | "akuma.tell" | "contract.audit" | "contract.deliver" | "contract.review")[]>>;
|
|
1004
1058
|
readonly: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
1005
1059
|
enforcement: z.ZodLiteral<"native">;
|
|
1006
1060
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -100,7 +100,8 @@ export function fleetRequestProtocol(action) {
|
|
|
100
100
|
decodeResult: (result) => decodedFleetResult(action, result),
|
|
101
101
|
decodeReference: (reference) => decodeFleetService(action, reference),
|
|
102
102
|
isPermitted: (allowed) => action === "akuma.wait" ||
|
|
103
|
-
((action === "akuma.tell" || action === "akuma.tell-answer") && allowed.includes("akuma.tell"))
|
|
103
|
+
((action === "akuma.tell" || action === "akuma.tell-answer") && allowed.includes("akuma.tell")) ||
|
|
104
|
+
(action === "akuma.kill" && allowed.includes("akuma.kill")),
|
|
104
105
|
};
|
|
105
106
|
}
|
|
106
107
|
export function fleetRequestCommand(action, port) {
|
|
@@ -33,6 +33,10 @@ export function decodeProviderOptions(value) {
|
|
|
33
33
|
if (network !== undefined && network !== "disabled" && network !== "enabled") {
|
|
34
34
|
throw new TypeError("provider option network must be disabled, enabled");
|
|
35
35
|
}
|
|
36
|
+
const sandbox = options.sandbox;
|
|
37
|
+
if (sandbox !== undefined && sandbox !== "full-access") {
|
|
38
|
+
throw new TypeError("provider option sandbox must be full-access");
|
|
39
|
+
}
|
|
36
40
|
const systemPrompt = optionText(options, "systemPrompt", "allow");
|
|
37
41
|
const systemPromptMode = options.systemPromptMode;
|
|
38
42
|
if (systemPromptMode !== undefined) {
|
|
@@ -48,6 +52,7 @@ export function decodeProviderOptions(value) {
|
|
|
48
52
|
...(effort === undefined ? {} : { effort }),
|
|
49
53
|
...(options.readonly === undefined ? {} : { readonly: true }),
|
|
50
54
|
...(network === undefined ? {} : { network }),
|
|
55
|
+
...(sandbox === undefined ? {} : { sandbox }),
|
|
51
56
|
...(systemPrompt === undefined ? {} : { systemPrompt }),
|
|
52
57
|
...(systemPromptMode === undefined ? {} : { systemPromptMode }),
|
|
53
58
|
});
|
|
@@ -3,6 +3,9 @@ import { decodeAcpConfig } from "./config.js";
|
|
|
3
3
|
import { startAcpSession } from "./core.js";
|
|
4
4
|
export { decodeAcpConfig } from "./config.js";
|
|
5
5
|
function optionAdmission(options, config) {
|
|
6
|
+
if (options.sandbox !== undefined) {
|
|
7
|
+
return { kind: "refused", diagnostic: "ACP provider does not support the sandbox option" };
|
|
8
|
+
}
|
|
6
9
|
if (options.network !== undefined) {
|
|
7
10
|
return { kind: "refused", diagnostic: "ACP provider does not support the network option" };
|
|
8
11
|
}
|
|
@@ -38,6 +38,9 @@ class ReceiptChannel {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
function admitClaudeOptions(options) {
|
|
41
|
+
if (options.sandbox !== undefined) {
|
|
42
|
+
return { kind: "refused", diagnostic: "Claude provider does not support the sandbox option" };
|
|
43
|
+
}
|
|
41
44
|
if (options.network !== undefined) {
|
|
42
45
|
return { kind: "refused", diagnostic: "Claude provider does not support the network option" };
|
|
43
46
|
}
|
|
@@ -48,6 +48,8 @@ async function steerTurn(server, state, tell) {
|
|
|
48
48
|
return { kind: "accepted", fence: `${accepted}:${tell.id}` };
|
|
49
49
|
}
|
|
50
50
|
function sandbox(cwd, options, requests) {
|
|
51
|
+
if (options.sandbox === "full-access")
|
|
52
|
+
return { type: "dangerFullAccess" };
|
|
51
53
|
if (options.readonly === true) {
|
|
52
54
|
return { type: "readOnly", networkAccess: options.network === "enabled" };
|
|
53
55
|
}
|
|
@@ -228,6 +230,12 @@ export function createCodexAppServerProvider(input = "codex") {
|
|
|
228
230
|
const execution = typeof input === "string" ? { name: "codex-app-server", kind: "codex-app-server", executable: input } : input;
|
|
229
231
|
return {
|
|
230
232
|
admitOptions(options) {
|
|
233
|
+
if (options.sandbox === "full-access" && options.readonly === true) {
|
|
234
|
+
return { kind: "refused", diagnostic: "Codex full-access sandbox cannot combine with readonly" };
|
|
235
|
+
}
|
|
236
|
+
if (options.sandbox === "full-access" && options.network === "disabled") {
|
|
237
|
+
return { kind: "refused", diagnostic: "Codex full-access sandbox cannot combine with disabled network" };
|
|
238
|
+
}
|
|
231
239
|
return {
|
|
232
240
|
kind: "admitted",
|
|
233
241
|
options: Object.freeze({ ...options }),
|
|
@@ -67,6 +67,9 @@ export const interpretGrokTool = (update) => {
|
|
|
67
67
|
fileChangeCall(name, input));
|
|
68
68
|
};
|
|
69
69
|
function optionAdmission(options) {
|
|
70
|
+
if (options.sandbox !== undefined) {
|
|
71
|
+
return { kind: "refused", diagnostic: "Grok Build does not support the sandbox option" };
|
|
72
|
+
}
|
|
70
73
|
if (options.network !== undefined) {
|
|
71
74
|
return { kind: "refused", diagnostic: "Grok Build does not support the network option" };
|
|
72
75
|
}
|
|
@@ -22,6 +22,8 @@ function opencodeSessionId(coordinateValue) {
|
|
|
22
22
|
return coordinateValue.sessionId;
|
|
23
23
|
}
|
|
24
24
|
function admit(options) {
|
|
25
|
+
if (options.sandbox !== undefined)
|
|
26
|
+
throw new Error("OpenCode does not support the sandbox option");
|
|
25
27
|
if (options.network !== undefined)
|
|
26
28
|
throw new Error("OpenCode does not support explicit network");
|
|
27
29
|
if (options.systemPromptMode === "replace") {
|
|
@@ -7,6 +7,8 @@ function diagnostic(error) {
|
|
|
7
7
|
return error instanceof Error ? error.message : String(error);
|
|
8
8
|
}
|
|
9
9
|
function admitPiOptions(options) {
|
|
10
|
+
if (options.sandbox !== undefined)
|
|
11
|
+
return { kind: "refused", diagnostic: "Pi provider does not support the sandbox option" };
|
|
10
12
|
if (options.network !== undefined)
|
|
11
13
|
return { kind: "refused", diagnostic: "Pi provider does not support the network option" };
|
|
12
14
|
if (options.model !== undefined && !MODEL_PATTERN.test(options.model)) {
|