@astrosheep/keiyaku 4.5.18 → 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-handle.js +10 -10
- package/build/src/akuma/akuma-observe.d.ts +2 -0
- package/build/src/akuma/akuma-observe.js +35 -25
- 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 +20 -3
- package/build/src/akuma/akuma.js +3 -5
- 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 +11 -36
- package/build/src/akuma/call-request.d.ts +3 -0
- package/build/src/akuma/call-request.js +12 -4
- package/build/src/akuma/fleet-execution.js +35 -11
- package/build/src/akuma/fleet-observation.d.ts +54 -0
- package/build/src/akuma/fleet-request.js +2 -1
- package/build/src/akuma/heart/index.d.ts +11 -17
- package/build/src/akuma/heart/index.js +91 -81
- package/build/src/akuma/heart/request-authority.js +19 -19
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +19 -6
- package/build/src/akuma/heart/storage.d.ts +2 -4
- package/build/src/akuma/heart/storage.js +63 -63
- package/build/src/akuma/heart/tells.d.ts +9 -19
- package/build/src/akuma/heart/tells.js +76 -76
- package/build/src/akuma/heart/timeline.d.ts +7 -1
- package/build/src/akuma/heart/timeline.js +62 -53
- 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/integration.js +4 -4
- package/build/src/git/process.d.ts +2 -0
- package/build/src/git/process.js +106 -0
- package/build/src/git/read-observation.js +79 -56
- package/build/src/git/target-placement.d.ts +13 -2
- package/build/src/git/target-placement.js +119 -68
- 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 +5 -3
- 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 -88
- 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/placement.js +47 -29
- 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 +7 -5
|
@@ -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
|
|
@@ -8,17 +8,13 @@ import { resolveProviderExecution } from "./providers/index.js";
|
|
|
8
8
|
import { publishAkuma } from "./publication.js";
|
|
9
9
|
import { spawnAkumaBody } from "./body.js";
|
|
10
10
|
import { AkumaNotBornError } from "./akuma-errors.js";
|
|
11
|
-
import { bornStatus } from "./akuma-observe.js";
|
|
11
|
+
import { bornStatus, defaultWaitComplete, readWaitComplete } from "./akuma-observe.js";
|
|
12
12
|
const CALL_EXECUTION = Symbol("akuma-call-execution");
|
|
13
13
|
const POLL_MS = 100;
|
|
14
14
|
const wait = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
15
15
|
function diagnostic(error) {
|
|
16
16
|
return error instanceof Error ? error.message : String(error);
|
|
17
17
|
}
|
|
18
|
-
function defaultWaitComplete(status) {
|
|
19
|
-
return (status.life !== "running" &&
|
|
20
|
-
!status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
|
|
21
|
-
}
|
|
22
18
|
async function takeLeashUntilSignal(paths, bodySequence, signal, unbounded = false) {
|
|
23
19
|
const leash = await acquireLeash(paths, {
|
|
24
20
|
bodySequence,
|
|
@@ -35,7 +31,7 @@ async function takeLeashUntilSignal(paths, bodySequence, signal, unbounded = fal
|
|
|
35
31
|
return { kind: "unavailable", evidence: "unavailable" };
|
|
36
32
|
}
|
|
37
33
|
export async function settleAkumaKill(paths, signal, retainLeash = false) {
|
|
38
|
-
const request = await requestStop(paths, new Date().toISOString());
|
|
34
|
+
const request = await requestStop(paths, new Date().toISOString(), signal);
|
|
39
35
|
if (request.kind !== "requested") {
|
|
40
36
|
if (!retainLeash)
|
|
41
37
|
return { evidence: request.kind };
|
|
@@ -141,9 +137,13 @@ export class AkumaHandle {
|
|
|
141
137
|
}
|
|
142
138
|
const deadline = options.timeoutMs === undefined ? undefined : performance.now() + options.timeoutMs;
|
|
143
139
|
for (;;) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
140
|
+
if (predicate !== defaultWaitComplete ||
|
|
141
|
+
(deadline !== undefined && performance.now() >= deadline) ||
|
|
142
|
+
(await readWaitComplete(this.worldPath, this.id))) {
|
|
143
|
+
const status = await this.status();
|
|
144
|
+
if (predicate(status) || (deadline !== undefined && performance.now() >= deadline))
|
|
145
|
+
return status;
|
|
146
|
+
}
|
|
147
147
|
await wait(deadline === undefined ? POLL_MS : Math.min(POLL_MS, Math.max(0, deadline - performance.now())));
|
|
148
148
|
}
|
|
149
149
|
}
|
|
@@ -160,7 +160,7 @@ export class AkumaHandle {
|
|
|
160
160
|
return await wakeRecordedTell(this.paths, admitted.tell.id, runtime);
|
|
161
161
|
}
|
|
162
162
|
async interrupt(body, options = {}) {
|
|
163
|
-
const request = await requestPause(this.paths, new Date().toISOString());
|
|
163
|
+
const request = await requestPause(this.paths, new Date().toISOString(), options.signal);
|
|
164
164
|
if (request.kind === "not-born") {
|
|
165
165
|
throw new AkumaNotBornError(this.id);
|
|
166
166
|
}
|
|
@@ -17,5 +17,7 @@ export declare function readBudgetedStatus(worldPath: WorldRoot, id: AkuId, inpu
|
|
|
17
17
|
ordinaryBudget?: number;
|
|
18
18
|
admittedTellId?: string;
|
|
19
19
|
}>): Promise<BudgetedStatusObservation>;
|
|
20
|
+
export declare function defaultWaitComplete(status: AkumaStatus): boolean;
|
|
21
|
+
export declare function readWaitComplete(worldPath: WorldRoot, id: AkuId): Promise<boolean>;
|
|
20
22
|
export declare function readAkumaBirthCwd(worldPath: WorldRoot, id: AkuId): Promise<string>;
|
|
21
23
|
export { selectHistory, type ActivityHistory, type ActivitySnapshot };
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readStatusFacts, readLifeSnapshot, HeldAkumaLeash, isHeartAbsent, life, lifeAt, probeLeash, readHeart, readSeal, readSoul, } from "./heart/index.js";
|
|
2
2
|
import { pathsForAkuId } from "./identity.js";
|
|
3
3
|
import { ordinarySnapshotBudget, projectTurns, selectHistory, selectSnapshot, } from "./projection.js";
|
|
4
4
|
import { resolveProviderExecution } from "./providers/index.js";
|
|
5
5
|
import { AkumaNotBornError } from "./akuma-errors.js";
|
|
6
6
|
export async function fleetListRow(paths, expected) {
|
|
7
7
|
const snapshot = await readHeart(paths);
|
|
8
|
-
if (snapshot.soul !== null)
|
|
9
|
-
|
|
8
|
+
if (snapshot.soul !== null) {
|
|
9
|
+
const observed = await bornObservation(paths, expected, () => readHeart(paths), snapshot);
|
|
10
|
+
return {
|
|
11
|
+
id: observed.soul.id,
|
|
12
|
+
archetype: observed.soul.archetype,
|
|
13
|
+
...(observed.soul.description === undefined ? {} : { description: observed.soul.description }),
|
|
14
|
+
life: observed.currentLife,
|
|
15
|
+
lifeAt: lifeAt(observed.currentLife, observed.snapshot.latestBody, observed.snapshot.latestKill, observed.soul.createdAt),
|
|
16
|
+
lastActivityAt: observed.snapshot.lastActivityAt,
|
|
17
|
+
pending: observed.snapshot.pending.map((tell) => tell.id),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
10
20
|
try {
|
|
11
21
|
if ((await probeLeash(paths)) === "held")
|
|
12
22
|
return { id: expected, life: "unborn" };
|
|
@@ -19,8 +29,8 @@ export async function fleetListRow(paths, expected) {
|
|
|
19
29
|
throw error;
|
|
20
30
|
}
|
|
21
31
|
}
|
|
22
|
-
async function bornObservation(paths, expected, snapshot) {
|
|
23
|
-
snapshot ??= await
|
|
32
|
+
async function bornObservation(paths, expected, read, snapshot) {
|
|
33
|
+
snapshot ??= await read();
|
|
24
34
|
if (snapshot.soul === null)
|
|
25
35
|
throw new AkumaNotBornError(expected);
|
|
26
36
|
const claim = await HeldAkumaLeash.try(paths);
|
|
@@ -28,7 +38,7 @@ async function bornObservation(paths, expected, snapshot) {
|
|
|
28
38
|
// A Body may finish after the first read. Refresh under the free seat so
|
|
29
39
|
// neither its release nor a successor can manufacture an untidy observation.
|
|
30
40
|
if (claim !== null)
|
|
31
|
-
snapshot = await
|
|
41
|
+
snapshot = await read();
|
|
32
42
|
const soul = snapshot.soul;
|
|
33
43
|
if (soul === null)
|
|
34
44
|
throw new AkumaNotBornError(expected);
|
|
@@ -39,19 +49,7 @@ async function bornObservation(paths, expected, snapshot) {
|
|
|
39
49
|
body: snapshot.latestBody,
|
|
40
50
|
kill: snapshot.latestKill,
|
|
41
51
|
});
|
|
42
|
-
return {
|
|
43
|
-
snapshot,
|
|
44
|
-
soul,
|
|
45
|
-
row: {
|
|
46
|
-
id: soul.id,
|
|
47
|
-
archetype: soul.archetype,
|
|
48
|
-
...(soul.description === undefined ? {} : { description: soul.description }),
|
|
49
|
-
life: currentLife,
|
|
50
|
-
lifeAt: lifeAt(currentLife, snapshot.latestBody, snapshot.latestKill, soul.createdAt),
|
|
51
|
-
lastActivityAt: snapshot.lastActivityAt,
|
|
52
|
-
pending: snapshot.pending.map((tell) => tell.id),
|
|
53
|
-
},
|
|
54
|
-
};
|
|
52
|
+
return { snapshot, soul, currentLife };
|
|
55
53
|
}
|
|
56
54
|
finally {
|
|
57
55
|
claim?.release();
|
|
@@ -60,20 +58,21 @@ async function bornObservation(paths, expected, snapshot) {
|
|
|
60
58
|
export async function bornStatus(paths, expected, input) {
|
|
61
59
|
if (input.ordinaryBudget !== undefined && (!Number.isSafeInteger(input.ordinaryBudget) || input.ordinaryBudget < 0))
|
|
62
60
|
throw new TypeError("ordinary budget must be a nonnegative safe integer");
|
|
63
|
-
const { snapshot, soul,
|
|
64
|
-
const resumeUnsupported =
|
|
61
|
+
const { snapshot, soul, currentLife } = await bornObservation(paths, expected, () => readLifeSnapshot(paths));
|
|
62
|
+
const resumeUnsupported = currentLife === "stranded" &&
|
|
65
63
|
snapshot.latestSession?.provider === soul.provider.name &&
|
|
66
64
|
(await resolveProviderExecution(soul.provider)).adapter.resume === undefined;
|
|
67
|
-
const
|
|
68
|
-
const selected = selectSnapshot(projectTurns(
|
|
65
|
+
const facts = await readStatusFacts(paths, input);
|
|
66
|
+
const selected = selectSnapshot(projectTurns(facts), {
|
|
69
67
|
aperture: input.aperture,
|
|
70
68
|
budget: ordinarySnapshotBudget(input.ordinaryBudget),
|
|
71
69
|
...(input.admittedTellId === undefined ? {} : { admittedTellId: input.admittedTellId }),
|
|
72
70
|
});
|
|
73
71
|
return {
|
|
74
72
|
status: {
|
|
75
|
-
id:
|
|
76
|
-
life:
|
|
73
|
+
id: soul.id,
|
|
74
|
+
life: currentLife,
|
|
75
|
+
allowed: soul.allowed,
|
|
77
76
|
...(soul.readonly === undefined ? {} : { readonly: soul.readonly }),
|
|
78
77
|
...(resumeUnsupported ? { strandedReason: "resume-unsupported" } : {}),
|
|
79
78
|
timeline: selected.snapshot,
|
|
@@ -84,6 +83,17 @@ export async function bornStatus(paths, expected, input) {
|
|
|
84
83
|
export async function readBudgetedStatus(worldPath, id, input) {
|
|
85
84
|
return await bornStatus(pathsForAkuId(worldPath, id), id, input);
|
|
86
85
|
}
|
|
86
|
+
function complete(life, pending) {
|
|
87
|
+
return life !== "running" && !pending;
|
|
88
|
+
}
|
|
89
|
+
export function defaultWaitComplete(status) {
|
|
90
|
+
return complete(status.life, status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
|
|
91
|
+
}
|
|
92
|
+
export async function readWaitComplete(worldPath, id) {
|
|
93
|
+
const paths = pathsForAkuId(worldPath, id);
|
|
94
|
+
const observed = await bornObservation(paths, id, () => readLifeSnapshot(paths));
|
|
95
|
+
return complete(observed.currentLife, observed.snapshot.hasPendingTell);
|
|
96
|
+
}
|
|
87
97
|
export async function readAkumaBirthCwd(worldPath, id) {
|
|
88
98
|
const soul = await readSoul(pathsForAkuId(worldPath, id));
|
|
89
99
|
if (soul === null)
|
|
@@ -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<{
|
|
@@ -408,8 +426,7 @@ export declare const akumaStatusSchema: z.ZodObject<{
|
|
|
408
426
|
}, z.core.$strict>;
|
|
409
427
|
export type AkumaStatus = z.infer<typeof akumaStatusSchema>;
|
|
410
428
|
export declare function parseAkumaStatus(value: unknown): AkumaStatus;
|
|
411
|
-
|
|
412
|
-
export declare function defaultWaitComplete(status: AkumaStatus): boolean;
|
|
429
|
+
export { defaultWaitComplete } from "./akuma-observe.js";
|
|
413
430
|
export type { ReadonlyRestraint } from "./provider-recipe.js";
|
|
414
431
|
export type * from "./projection.js";
|
|
415
432
|
export type UnbornAkumaListRow = Readonly<{
|
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(),
|
|
@@ -33,11 +35,7 @@ export const akumaStatusSchema = z
|
|
|
33
35
|
export function parseAkumaStatus(value) {
|
|
34
36
|
return akumaStatusSchema.parse(value);
|
|
35
37
|
}
|
|
36
|
-
|
|
37
|
-
export function defaultWaitComplete(status) {
|
|
38
|
-
return (status.life !== "running" &&
|
|
39
|
-
!status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
|
|
40
|
-
}
|
|
38
|
+
export { defaultWaitComplete } from "./akuma-observe.js";
|
|
41
39
|
export { AkumaNotBornError } from "./akuma-errors.js";
|
|
42
40
|
export function wait(milliseconds) {
|
|
43
41
|
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
@@ -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
|
@@ -3,7 +3,7 @@ import { fileURLToPath } from "node:url";
|
|
|
3
3
|
import { abortableDelay } from "./abort.js";
|
|
4
4
|
import { BodySupervisor } from "./body-supervisor.js";
|
|
5
5
|
import { driveTurn, turnRecipe } from "./turn-drive.js";
|
|
6
|
-
import { HeldAkumaLeash, breakBody, decidePendingTellDisposition, drainPendingTells, endTurn, failOpenBoundTurns, finishBodyIfIdle, heartExists, isHeartAbsent, probeLeash, projectTell,
|
|
6
|
+
import { HeldAkumaLeash, breakBody, decidePendingTellDisposition, drainPendingTells, endTurn, failOpenBoundTurns, finishBodyIfIdle, heartExists, isHeartAbsent, probeLeash, projectTell, readHeart, readOpenBoundTurns, readOpenPendingTellDisposition, readTell, readTurn, readNonterminalRequests, resolvePendingTellDisposition, } from "./heart/index.js";
|
|
7
7
|
import { worldRootForAkumaPaths } from "./identity.js";
|
|
8
8
|
import { pluginRuntime } from "../plugin/runtime.js";
|
|
9
9
|
import { World } from "../world.js";
|
|
@@ -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() });
|
|
@@ -369,15 +357,10 @@ async function settleUndeliveredDisposition(paths, disposition, error) {
|
|
|
369
357
|
if (!(await heartExists(paths)))
|
|
370
358
|
return;
|
|
371
359
|
const at = new Date().toISOString();
|
|
372
|
-
await
|
|
373
|
-
await resolvePendingTellDisposition(paths, disposition.bodySequence, at);
|
|
360
|
+
await resolvePendingTellDisposition(paths, disposition.bodySequence, at, "undelivered");
|
|
374
361
|
}
|
|
375
362
|
async function consumeProvenDisposition(paths, disposition) {
|
|
376
|
-
|
|
377
|
-
if (proof.kind !== "proven")
|
|
378
|
-
return false;
|
|
379
|
-
await resolvePendingTellDisposition(paths, disposition.bodySequence, new Date().toISOString());
|
|
380
|
-
return true;
|
|
363
|
+
return await resolvePendingTellDisposition(paths, disposition.bodySequence, new Date().toISOString());
|
|
381
364
|
}
|
|
382
365
|
/**
|
|
383
366
|
* Wait for Heart custody proof of the frozen Tell-id snapshot, or for the
|
|
@@ -386,7 +369,7 @@ async function consumeProvenDisposition(paths, disposition) {
|
|
|
386
369
|
*/
|
|
387
370
|
async function awaitDispositionCustody(paths, disposition, child, schedule) {
|
|
388
371
|
for (;;) {
|
|
389
|
-
if (
|
|
372
|
+
if (await consumeProvenDisposition(paths, disposition)) {
|
|
390
373
|
child.release();
|
|
391
374
|
return { kind: "proven" };
|
|
392
375
|
}
|
|
@@ -405,7 +388,7 @@ async function awaitDispositionCustody(paths, disposition, child, schedule) {
|
|
|
405
388
|
continue;
|
|
406
389
|
timerController.abort();
|
|
407
390
|
await timer.catch(() => undefined);
|
|
408
|
-
if (
|
|
391
|
+
if (await consumeProvenDisposition(paths, disposition)) {
|
|
409
392
|
child.release();
|
|
410
393
|
return { kind: "proven" };
|
|
411
394
|
}
|
|
@@ -417,10 +400,8 @@ async function resolveDecidedPendingTellDisposition(paths, disposition, spawn) {
|
|
|
417
400
|
if (await consumeProvenDisposition(paths, disposition))
|
|
418
401
|
return;
|
|
419
402
|
const wake = await awaitDispositionCustody(paths, disposition, await spawn({ paths, refuseIfHeld: true }), abortableDelay);
|
|
420
|
-
if (wake.kind === "proven")
|
|
421
|
-
await resolvePendingTellDisposition(paths, disposition.bodySequence, new Date().toISOString());
|
|
403
|
+
if (wake.kind === "proven")
|
|
422
404
|
return;
|
|
423
|
-
}
|
|
424
405
|
// Predecessor still holds the leash: leave the Heart disposition open.
|
|
425
406
|
if (wake.kind === "held")
|
|
426
407
|
return;
|
|
@@ -515,19 +496,13 @@ export async function driveAkumaBody(launch, adapter, runtimeInput = {}) {
|
|
|
515
496
|
await resolveDecidedPendingTellDisposition(launch.paths, finished.decided, runtime.spawnBody ?? spawnAkumaBody);
|
|
516
497
|
if (finished.notification !== undefined)
|
|
517
498
|
await finished.notification;
|
|
518
|
-
void emitTurnOutcome?.drain();
|
|
519
499
|
}
|
|
520
500
|
}
|
|
521
501
|
export async function spawnAkumaBody(launch) {
|
|
522
502
|
return await spawnDetachedProcess(await bodyProcessInput(launch));
|
|
523
503
|
}
|
|
524
504
|
export async function runAkumaBody(launch, world, externalCommands) {
|
|
525
|
-
|
|
526
|
-
return await driveAkumaBody(launch, undefined, { world, externalCommands });
|
|
527
|
-
}
|
|
528
|
-
finally {
|
|
529
|
-
await (await pluginRuntime({ world })).drain();
|
|
530
|
-
}
|
|
505
|
+
return await driveAkumaBody(launch, undefined, { world, externalCommands });
|
|
531
506
|
}
|
|
532
507
|
const DIRECT_TELL_WAKE = {
|
|
533
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>>;
|