@astrosheep/keiyaku 4.5.26 → 4.5.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +82 -162
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +153 -76
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +68 -64
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +115 -146
- package/build/src/akuma/akuma-errors.d.ts +6 -0
- package/build/src/akuma/akuma-errors.js +11 -0
- package/build/src/akuma/akuma-handle.d.ts +54 -1
- package/build/src/akuma/akuma-handle.js +79 -8
- package/build/src/akuma/akuma-instance.js +6 -22
- package/build/src/akuma/akuma-observe.d.ts +6 -0
- package/build/src/akuma/akuma-observe.js +3 -1
- package/build/src/akuma/akuma-probe.d.ts +20 -1
- package/build/src/akuma/akuma-probe.js +20 -3
- package/build/src/akuma/akuma.d.ts +13 -0
- package/build/src/akuma/akuma.js +1 -0
- package/build/src/akuma/allowed.d.ts +2 -1
- package/build/src/akuma/allowed.js +9 -4
- package/build/src/akuma/archetype.js +3 -3
- package/build/src/akuma/body.js +8 -3
- package/build/src/akuma/fleet-execution.d.ts +13 -2
- package/build/src/akuma/fleet-execution.js +45 -0
- package/build/src/akuma/fleet-observation.d.ts +241 -0
- package/build/src/akuma/fleet-observation.js +13 -0
- package/build/src/akuma/fleet-owner-port.d.ts +12 -0
- package/build/src/akuma/fleet-owner-port.js +46 -0
- package/build/src/akuma/fleet-request.d.ts +55 -4
- package/build/src/akuma/fleet-request.js +101 -6
- package/build/src/akuma/heart/index.d.ts +1 -0
- package/build/src/akuma/heart/index.js +4 -1
- package/build/src/akuma/heart/rows.d.ts +1 -0
- package/build/src/akuma/heart/rows.js +8 -0
- package/build/src/akuma/heart/soul.js +2 -2
- package/build/src/akuma/identity.js +11 -9
- package/build/src/akuma/projection.d.ts +36 -0
- package/build/src/akuma/projection.js +2 -1
- package/build/src/akuma/provider.d.ts +14 -0
- package/build/src/akuma/provider.js +66 -4
- package/build/src/akuma/providers/acp/events.js +16 -8
- package/build/src/akuma/providers/claude/events.js +5 -7
- package/build/src/akuma/providers/opencode-sdk/events.js +9 -5
- package/build/src/akuma/providers/pi/events.js +4 -3
- package/build/src/akuma/request-lifecycle.js +10 -1
- package/build/src/akuma-body.js +1 -33
- package/build/src/alias/index.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +8 -0
- package/build/src/cli/commands/akuma-invoke.js +67 -6
- package/build/src/cli/commands/akuma.d.ts +1 -0
- package/build/src/cli/commands/akuma.js +19 -30
- package/build/src/cli/commands/contract-help.d.ts +1 -0
- package/build/src/cli/commands/contract-help.js +9 -5
- package/build/src/cli/invoke.js +1 -1
- package/build/src/cli/render/akuma-activity.d.ts +7 -1
- package/build/src/cli/render/akuma-activity.js +164 -50
- package/build/src/cli/render/akuma-tool.d.ts +5 -0
- package/build/src/cli/render/akuma-tool.js +118 -14
- package/build/src/cli/render/akuma.d.ts +12 -1
- package/build/src/cli/render/akuma.js +74 -2
- package/build/src/cli/render/catalog.js +2 -3
- package/build/src/cli/render/contract-observation.d.ts +1 -0
- package/build/src/cli/render/contract-observation.js +20 -1
- package/build/src/cli/render/contract.js +4 -4
- package/build/src/cli/render/execution-progress.d.ts +1 -0
- package/build/src/cli/render/execution-progress.js +77 -3
- package/build/src/cli/render/kanshi.js +5 -19
- package/build/src/cli/render/terminal.js +3 -1
- package/build/src/cli/runtime.d.ts +6 -0
- package/build/src/cli/runtime.js +35 -17
- package/build/src/core/facts/offer.d.ts +1 -2
- package/build/src/core/verbs/abandon.js +1 -1
- package/build/src/core/verbs/amend.js +1 -1
- package/build/src/core/verbs/arc.js +1 -1
- package/build/src/core/verbs/attestation.js +1 -1
- package/build/src/core/verbs/bind.js +1 -1
- package/build/src/core/verbs/deliver.js +1 -1
- package/build/src/core/verbs/placement.js +1 -1
- package/build/src/core/verbs/reintegrate.js +1 -1
- package/build/src/git/admission.js +18 -7
- package/build/src/identity/coordinates.js +1 -1
- package/build/src/identity/normalize.d.ts +3 -0
- package/build/src/identity/normalize.js +10 -0
- package/build/src/identity/selector.d.ts +1 -0
- package/build/src/identity/selector.js +15 -4
- package/build/src/library/address.d.ts +33 -3
- package/build/src/library/address.js +90 -29
- package/build/src/library/akuma-creation.d.ts +1 -1
- package/build/src/library/akuma-creation.js +10 -52
- package/build/src/library/composition.d.ts +14 -1
- package/build/src/library/fleet.d.ts +13 -2
- package/build/src/library/fleet.js +142 -48
- package/build/src/library/keiyaku.d.ts +14 -1
- package/build/src/plugin/public.d.ts +2 -0
- package/build/src/protocol/completion.js +9 -2
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/package.json +1 -1
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import { MAX_AKUMA_NAME_BYTES, normalizeIdentityStem, validateAkumaName } from "./normalize.js";
|
|
2
2
|
const AKUMA_GLOB_SUFFIX = /^[0-9a-f*]+$/u;
|
|
3
|
+
const LEGACY_AKUMA_ALIAS_PATTERN = /^@[a-z][a-z0-9-]{0,63}$/u;
|
|
4
|
+
// Old alias spellings remain readable, but new bindings use canonical Akuma names.
|
|
5
|
+
export function parseReadableAkumaAlias(value) {
|
|
6
|
+
if (LEGACY_AKUMA_ALIAS_PATTERN.test(value))
|
|
7
|
+
return value;
|
|
8
|
+
return parseAkumaAlias(value);
|
|
9
|
+
}
|
|
3
10
|
export function parseAkumaAlias(value) {
|
|
4
|
-
if (!
|
|
5
|
-
throw new TypeError("Akuma alias must
|
|
11
|
+
if (!value.startsWith("@"))
|
|
12
|
+
throw new TypeError("Akuma alias selector must start with @");
|
|
13
|
+
try {
|
|
14
|
+
validateAkumaName(value.slice(1));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
throw new TypeError(`Akuma alias name must be a normalized Akuma name of at most ${MAX_AKUMA_NAME_BYTES} UTF-8 bytes`);
|
|
6
18
|
}
|
|
7
19
|
return value;
|
|
8
20
|
}
|
|
@@ -26,4 +38,3 @@ export function matchesAkumaGlob(glob, value) {
|
|
|
26
38
|
.replaceAll("*", "[^/]*");
|
|
27
39
|
return new RegExp(`^${pattern}$`, "u").test(value);
|
|
28
40
|
}
|
|
29
|
-
import { normalizeIdentityStem } from "./normalize.js";
|
|
@@ -28,6 +28,17 @@ export type AkumaWorldScopeRefusal = Readonly<{
|
|
|
28
28
|
ids: readonly AkuId[];
|
|
29
29
|
world: WorldRoot;
|
|
30
30
|
}>;
|
|
31
|
+
export type AkumaAddressRefusal = Readonly<{
|
|
32
|
+
kind: "akuma-alias-not-found";
|
|
33
|
+
alias: AkumaAlias;
|
|
34
|
+
}> | Readonly<{
|
|
35
|
+
kind: "invalid-akuma";
|
|
36
|
+
selector: string;
|
|
37
|
+
}>;
|
|
38
|
+
export declare class AkumaAddressError extends Error {
|
|
39
|
+
readonly refusal: AkumaAddressRefusal;
|
|
40
|
+
constructor(refusal: AkumaAddressRefusal);
|
|
41
|
+
}
|
|
31
42
|
export declare class AkumaWorldScopeError extends TypeError {
|
|
32
43
|
readonly refusal: AkumaWorldScopeRefusal;
|
|
33
44
|
constructor(refusal: AkumaWorldScopeRefusal);
|
|
@@ -45,15 +56,34 @@ export type NamedAddressInput = Readonly<{
|
|
|
45
56
|
aliases: Section<readonly AliasBinding[]>;
|
|
46
57
|
}>;
|
|
47
58
|
export declare function resolveNamedAddress(input: NamedAddressInput): NamedAddress;
|
|
48
|
-
|
|
59
|
+
type AddressedAkuma = Readonly<{
|
|
49
60
|
path: WorldRoot;
|
|
50
61
|
id: AkuId;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Resolves one selector to a complete identity without proving it born. The
|
|
65
|
+
* caller is a forwarding boundary: the parent Fleet answers for the target, so
|
|
66
|
+
* this process must not read its own Heart files to decide.
|
|
67
|
+
*/
|
|
68
|
+
export declare function resolveAkuma(input: UncheckedAkumaAddressInput): Promise<AddressedAkuma>;
|
|
69
|
+
/**
|
|
70
|
+
* Resolves one selector against this World, where a local caller is answered
|
|
71
|
+
* for the target's birth by the one addressability normalization.
|
|
72
|
+
*/
|
|
73
|
+
export declare function addressAkuma(input: UncheckedAkumaAddressInput): Promise<AddressedAkuma>;
|
|
74
|
+
/**
|
|
75
|
+
* Resolves a selector set to complete identities without proving any born. The
|
|
76
|
+
* caller is a forwarding boundary, the parent Fleet owns the answer, and no
|
|
77
|
+
* member's Heart is read here.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resolveAkumaSet(input: UncheckedAkumaAddressInput): Promise<Readonly<{
|
|
80
|
+
path: WorldRoot;
|
|
81
|
+
ids: readonly AkuId[];
|
|
82
|
+
orderedIds: readonly AkuId[];
|
|
51
83
|
}>>;
|
|
52
84
|
export declare function addressAkumaSet(input: UncheckedAkumaAddressInput): Promise<Readonly<{
|
|
53
85
|
path: WorldRoot;
|
|
54
|
-
/** The complete selected set in canonical order. */
|
|
55
86
|
ids: readonly AkuId[];
|
|
56
|
-
/** The same set in the caller's selector order, for surfaces that name the selection as chosen. */
|
|
57
87
|
orderedIds: readonly AkuId[];
|
|
58
88
|
}>>;
|
|
59
89
|
export {};
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
/** @architectureCompositionRoot */
|
|
2
2
|
import { readAliases } from "../alias/index.js";
|
|
3
3
|
import { createAkumaProduct } from "../akuma/akuma-product.js";
|
|
4
|
-
import {
|
|
4
|
+
import { akumaAddressability, requireBornAkuma } from "../akuma/akuma-probe.js";
|
|
5
5
|
import { parseAkuId } from "../akuma/identity.js";
|
|
6
6
|
import { contractId } from "../core/facts/types.js";
|
|
7
7
|
import { readDispatches } from "../dispatch/index.js";
|
|
8
|
-
import { matchesAkumaGlob,
|
|
8
|
+
import { matchesAkumaGlob, parseReadableAkumaAlias, parseAkumaGlob, } from "../identity/selector.js";
|
|
9
9
|
import { World } from "../world.js";
|
|
10
10
|
import { requireInput } from "./input.js";
|
|
11
11
|
import { scopeForRepo } from "./repo.js";
|
|
12
|
+
export class AkumaAddressError extends Error {
|
|
13
|
+
refusal;
|
|
14
|
+
constructor(refusal) {
|
|
15
|
+
super(refusal.kind === "akuma-alias-not-found"
|
|
16
|
+
? `unknown Akuma alias: ${refusal.alias}`
|
|
17
|
+
: `invalid Akuma: ${refusal.selector}`);
|
|
18
|
+
this.refusal = refusal;
|
|
19
|
+
this.name = "AkumaAddressError";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
12
22
|
export class AkumaWorldScopeError extends TypeError {
|
|
13
23
|
refusal;
|
|
14
24
|
constructor(refusal) {
|
|
@@ -22,23 +32,43 @@ function nonblank(value, label) {
|
|
|
22
32
|
throw new TypeError(`${label} must be a nonblank string`);
|
|
23
33
|
return value;
|
|
24
34
|
}
|
|
35
|
+
function parseAddressAlias(selector) {
|
|
36
|
+
try {
|
|
37
|
+
return parseReadableAkumaAlias(selector);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (!(error instanceof TypeError))
|
|
41
|
+
throw error;
|
|
42
|
+
throw new AkumaAddressError({ kind: "invalid-akuma", selector });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function parseAddressId(selector) {
|
|
46
|
+
try {
|
|
47
|
+
return parseAkuId(selector);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (!(error instanceof TypeError))
|
|
51
|
+
throw error;
|
|
52
|
+
throw new AkumaAddressError({ kind: "invalid-akuma", selector });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
25
55
|
async function directId(path, selector) {
|
|
26
56
|
if (selector.startsWith("@")) {
|
|
27
|
-
const alias =
|
|
57
|
+
const alias = parseAddressAlias(selector);
|
|
28
58
|
const resolved = (await readAliases(path)).find((binding) => binding.alias === alias)?.akuId ?? null;
|
|
29
59
|
if (resolved === null)
|
|
30
|
-
throw new
|
|
60
|
+
throw new AkumaAddressError({ kind: "akuma-alias-not-found", alias });
|
|
31
61
|
return resolved;
|
|
32
62
|
}
|
|
33
|
-
return
|
|
63
|
+
return parseAddressId(selector).id;
|
|
34
64
|
}
|
|
35
65
|
export function resolveNamedAddress(input) {
|
|
36
66
|
const selector = nonblank(input.selector, "selector");
|
|
37
67
|
if (selector.startsWith("kei/"))
|
|
38
68
|
return { kind: "contract", id: contractId(selector) };
|
|
39
69
|
if (selector.startsWith("aku/"))
|
|
40
|
-
return { kind: "akuma", id:
|
|
41
|
-
const alias =
|
|
70
|
+
return { kind: "akuma", id: parseAddressId(selector).id };
|
|
71
|
+
const alias = parseAddressAlias(selector);
|
|
42
72
|
const contractMatches = (input.report.contracts.kind === "present" ? input.report.contracts.value.rows : []).filter((row) => row.disposition === "active" &&
|
|
43
73
|
row.workspace === "worktree" &&
|
|
44
74
|
row.worktreePath !== null &&
|
|
@@ -62,9 +92,14 @@ export function resolveNamedAddress(input) {
|
|
|
62
92
|
if (input.aliases.kind === "failed") {
|
|
63
93
|
throw new TypeError("cannot resolve a named selector while Alias authority is failed");
|
|
64
94
|
}
|
|
65
|
-
throw new
|
|
95
|
+
throw new AkumaAddressError({ kind: "akuma-alias-not-found", alias });
|
|
66
96
|
}
|
|
67
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Resolves one selector to a complete identity without proving it born. The
|
|
99
|
+
* caller is a forwarding boundary: the parent Fleet answers for the target, so
|
|
100
|
+
* this process must not read its own Heart files to decide.
|
|
101
|
+
*/
|
|
102
|
+
export async function resolveAkuma(input) {
|
|
68
103
|
const values = requireInput(input, "Akuma address input");
|
|
69
104
|
for (const key of Object.keys(values)) {
|
|
70
105
|
if (!["path", "akuma", "repo"].includes(key)) {
|
|
@@ -74,7 +109,17 @@ export async function addressAkuma(input) {
|
|
|
74
109
|
if (values.repo !== undefined)
|
|
75
110
|
scopeForRepo(values.repo);
|
|
76
111
|
const path = await World.prove(nonblank(values.path, "path"));
|
|
77
|
-
|
|
112
|
+
const id = await directId(path, nonblank(values.akuma, "akuma"));
|
|
113
|
+
return { path, id };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Resolves one selector against this World, where a local caller is answered
|
|
117
|
+
* for the target's birth by the one addressability normalization.
|
|
118
|
+
*/
|
|
119
|
+
export async function addressAkuma(input) {
|
|
120
|
+
const addressed = await resolveAkuma(input);
|
|
121
|
+
await requireBornAkuma(addressed.path, addressed.id);
|
|
122
|
+
return addressed;
|
|
78
123
|
}
|
|
79
124
|
function parseSetSelector(raw) {
|
|
80
125
|
const selector = nonblank(raw, "akuma selector");
|
|
@@ -83,13 +128,13 @@ function parseSetSelector(raw) {
|
|
|
83
128
|
if (selector.includes("*"))
|
|
84
129
|
return { kind: "glob", value: parseAkumaGlob(selector) };
|
|
85
130
|
if (selector.startsWith("@"))
|
|
86
|
-
return { kind: "alias", value:
|
|
87
|
-
return { kind: "direct", value:
|
|
131
|
+
return { kind: "alias", value: parseAddressAlias(selector) };
|
|
132
|
+
return { kind: "direct", value: parseAddressId(selector).id };
|
|
88
133
|
}
|
|
89
134
|
function hasSelectorKind(selectors, kind) {
|
|
90
135
|
return selectors.some((selector) => selector.kind === kind);
|
|
91
136
|
}
|
|
92
|
-
function addSelectorIds(selector, sources, selected, contractMembers) {
|
|
137
|
+
function addSelectorIds(selector, sources, selected, contractMembers, explicit) {
|
|
93
138
|
if (selector.kind === "contract") {
|
|
94
139
|
for (const dispatch of sources.dispatches) {
|
|
95
140
|
if (dispatch.contractId !== selector.value)
|
|
@@ -108,20 +153,18 @@ function addSelectorIds(selector, sources, selected, contractMembers) {
|
|
|
108
153
|
if (selector.kind === "alias") {
|
|
109
154
|
const id = sources.aliases.get(selector.value);
|
|
110
155
|
if (id === undefined)
|
|
111
|
-
throw new
|
|
156
|
+
throw new AkumaAddressError({ kind: "akuma-alias-not-found", alias: selector.value });
|
|
112
157
|
selected.add(id);
|
|
158
|
+
explicit.add(id);
|
|
113
159
|
return;
|
|
114
160
|
}
|
|
115
161
|
selected.add(selector.value);
|
|
162
|
+
explicit.add(selector.value);
|
|
116
163
|
}
|
|
117
164
|
async function contractMemberInWorld(path, id) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
catch {
|
|
122
|
-
// A dispatched physical member remains selected when its Heart cannot be read.
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
165
|
+
// A dispatched physical member stays selected when its Heart cannot be read:
|
|
166
|
+
// the World, not this reader, remains the authority on its membership.
|
|
167
|
+
return (await akumaAddressability(path, id)).kind !== "absent";
|
|
125
168
|
}
|
|
126
169
|
async function refuseForeignContractMembers(path, ids, contractMembers) {
|
|
127
170
|
const foreign = [];
|
|
@@ -132,7 +175,13 @@ async function refuseForeignContractMembers(path, ids, contractMembers) {
|
|
|
132
175
|
if (foreign.length > 0)
|
|
133
176
|
throw new AkumaWorldScopeError({ kind: "akuma-not-in-world", ids: foreign, world: path });
|
|
134
177
|
}
|
|
135
|
-
|
|
178
|
+
function canonicalAkumaOrder(selected) {
|
|
179
|
+
const ids = [...selected].sort((left, right) => Buffer.compare(Buffer.from(left), Buffer.from(right)));
|
|
180
|
+
if (ids.length === 0)
|
|
181
|
+
throw new TypeError("Akuma selector snapshot is empty");
|
|
182
|
+
return ids;
|
|
183
|
+
}
|
|
184
|
+
async function readAkumaSet(input) {
|
|
136
185
|
const values = requireInput(input, "Akuma set address input");
|
|
137
186
|
for (const key of Object.keys(values)) {
|
|
138
187
|
if (!["path", "akuma", "repo"].includes(key)) {
|
|
@@ -157,13 +206,25 @@ export async function addressAkumaSet(input) {
|
|
|
157
206
|
: [];
|
|
158
207
|
const selected = new Set();
|
|
159
208
|
const contractMembers = new Set();
|
|
209
|
+
const explicit = new Set();
|
|
160
210
|
const sources = { fleetIds, aliases, dispatches };
|
|
161
211
|
for (const selector of selectors)
|
|
162
|
-
addSelectorIds(selector, sources, selected, contractMembers);
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
212
|
+
addSelectorIds(selector, sources, selected, contractMembers, explicit);
|
|
213
|
+
return { path, orderedIds: [...selected], ids: canonicalAkumaOrder(selected), contractMembers, explicit };
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Resolves a selector set to complete identities without proving any born. The
|
|
217
|
+
* caller is a forwarding boundary, the parent Fleet owns the answer, and no
|
|
218
|
+
* member's Heart is read here.
|
|
219
|
+
*/
|
|
220
|
+
export async function resolveAkumaSet(input) {
|
|
221
|
+
const resolved = await readAkumaSet(input);
|
|
222
|
+
return { path: resolved.path, ids: resolved.ids, orderedIds: resolved.orderedIds };
|
|
223
|
+
}
|
|
224
|
+
export async function addressAkumaSet(input) {
|
|
225
|
+
const resolved = await readAkumaSet(input);
|
|
226
|
+
for (const id of resolved.explicit)
|
|
227
|
+
await requireBornAkuma(resolved.path, id);
|
|
228
|
+
await refuseForeignContractMembers(resolved.path, resolved.ids, resolved.contractMembers);
|
|
229
|
+
return { path: resolved.path, ids: resolved.ids, orderedIds: resolved.orderedIds };
|
|
169
230
|
}
|
|
@@ -73,7 +73,7 @@ export type CallResult = Readonly<{
|
|
|
73
73
|
readonly?: ReadonlyRestraint;
|
|
74
74
|
execution: Readonly<{
|
|
75
75
|
cwd: string;
|
|
76
|
-
source: "input" | "
|
|
76
|
+
source: "input" | "caller" | "process" | "world";
|
|
77
77
|
}>;
|
|
78
78
|
dispatch: DispatchStage;
|
|
79
79
|
alias: AliasStage;
|
|
@@ -9,7 +9,6 @@ import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
|
9
9
|
import { publishDispatch, readDispatch } from "../dispatch/index.js";
|
|
10
10
|
import { parseAkumaAlias } from "../identity/selector.js";
|
|
11
11
|
import { emitCalledPluginSignal } from "../plugin/akuma-signals.js";
|
|
12
|
-
import { readManagedWorktreeAppointment } from "../workspace-place.js";
|
|
13
12
|
import { World } from "../world.js";
|
|
14
13
|
import { Akuma as PublicAkuma } from "../akuma/akuma-instance.js";
|
|
15
14
|
import { requestForwardedFleetTellAnswer } from "../akuma/fleet-request.js";
|
|
@@ -17,7 +16,6 @@ import { localExecutionContext } from "../akuma/requests.js";
|
|
|
17
16
|
import { callReadonly, canonicalBirthCwd } from "../akuma/call-input.js";
|
|
18
17
|
import { requireInput } from "./input.js";
|
|
19
18
|
import { addressAkuma } from "./address.js";
|
|
20
|
-
import { KeiyakuRefused } from "./contract.js";
|
|
21
19
|
import { seatForKeiyaku } from "./contract-handle.js";
|
|
22
20
|
import { scopeForRepo } from "./repo.js";
|
|
23
21
|
function nonblank(value, label) {
|
|
@@ -67,10 +65,10 @@ function integrationFailure(error) {
|
|
|
67
65
|
};
|
|
68
66
|
}
|
|
69
67
|
function callMode(value) {
|
|
70
|
-
if (value === undefined || value === "
|
|
71
|
-
return "wait";
|
|
72
|
-
if (value === "detach")
|
|
68
|
+
if (value === undefined || value === "detach")
|
|
73
69
|
return "detach";
|
|
70
|
+
if (value === "wait")
|
|
71
|
+
return "wait";
|
|
74
72
|
throw new TypeError("mode must be wait or detach");
|
|
75
73
|
}
|
|
76
74
|
function callTimeout(value, mode) {
|
|
@@ -196,49 +194,13 @@ async function forkDispatchStage(input) {
|
|
|
196
194
|
return { kind: "failed", failure: integrationFailure(error) };
|
|
197
195
|
}
|
|
198
196
|
}
|
|
199
|
-
function unavailableWorkspace(contractId, detail) {
|
|
200
|
-
return new Error(`Contract workspace is unavailable: ${contractId} ${detail}`);
|
|
201
|
-
}
|
|
202
|
-
async function currentManagedContract(contract, contractId) {
|
|
203
|
-
let state;
|
|
204
|
-
try {
|
|
205
|
-
state = await contract.state();
|
|
206
|
-
}
|
|
207
|
-
catch (error) {
|
|
208
|
-
if (error instanceof Error && error.message === `contract does not exist: ${contractId}`) {
|
|
209
|
-
throw new KeiyakuRefused({ kind: "contract-missing", contractId });
|
|
210
|
-
}
|
|
211
|
-
throw error;
|
|
212
|
-
}
|
|
213
|
-
if (state.terminal !== null)
|
|
214
|
-
throw new KeiyakuRefused({ kind: "terminal", contractId: state.id });
|
|
215
|
-
return state;
|
|
216
|
-
}
|
|
217
197
|
async function resolveCallExecution(input) {
|
|
218
|
-
if (input.cwd
|
|
219
|
-
return
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
if (input.contract !== undefined) {
|
|
225
|
-
const seat = seatForKeiyaku(input.contract);
|
|
226
|
-
if (seat === null)
|
|
227
|
-
throw new TypeError("contract must be a Keiyaku");
|
|
228
|
-
const state = await currentManagedContract(input.contract, seat.id);
|
|
229
|
-
const appointment = await readManagedWorktreeAppointment(seat.scope, state.id);
|
|
230
|
-
if (appointment.kind === "unappointed") {
|
|
231
|
-
throw unavailableWorkspace(state.id, "is unappointed; use reconcile");
|
|
232
|
-
}
|
|
233
|
-
if (appointment.kind === "failed") {
|
|
234
|
-
throw new Error(`${appointment.diagnostic}; use reconcile`);
|
|
235
|
-
}
|
|
236
|
-
return {
|
|
237
|
-
cwd: await canonicalBirthCwd(appointment.path, `Contract workspace is unavailable: ${appointment.path}`),
|
|
238
|
-
source: "contract-worktree",
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
return undefined;
|
|
198
|
+
if (input.cwd === undefined)
|
|
199
|
+
return undefined;
|
|
200
|
+
return {
|
|
201
|
+
cwd: await canonicalBirthCwd(input.cwd),
|
|
202
|
+
source: "input",
|
|
203
|
+
};
|
|
242
204
|
}
|
|
243
205
|
async function resolveAliasStage(path, alias, dispatch, akuma) {
|
|
244
206
|
if (alias === undefined)
|
|
@@ -326,11 +288,7 @@ function schemaTell(input) {
|
|
|
326
288
|
}
|
|
327
289
|
async function prepareCall(input, context) {
|
|
328
290
|
const parsed = await parseCallInput(input);
|
|
329
|
-
const execution = await resolveCallExecution({
|
|
330
|
-
path: parsed.path,
|
|
331
|
-
...(parsed.cwd === undefined ? {} : { cwd: parsed.cwd }),
|
|
332
|
-
...(parsed.seat === undefined ? {} : { contract: parsed.values.contract }),
|
|
333
|
-
});
|
|
291
|
+
const execution = await resolveCallExecution(parsed.cwd === undefined ? {} : { cwd: parsed.cwd });
|
|
334
292
|
const world = akumaWorld(parsed.path, parsed.home, parsed.settings, context);
|
|
335
293
|
const { born, akuma } = await admitCall({
|
|
336
294
|
path: parsed.path,
|
|
@@ -16,7 +16,7 @@ export declare function composeLibrary(context?: ExecutionContext, composition?:
|
|
|
16
16
|
readonly?: import("../akuma/provider-recipe.js").ReadonlyRestraint;
|
|
17
17
|
execution: Readonly<{
|
|
18
18
|
cwd: string;
|
|
19
|
-
source: "input" | "
|
|
19
|
+
source: "input" | "caller" | "process" | "world";
|
|
20
20
|
}>;
|
|
21
21
|
dispatch: import("./akuma-creation.js").DispatchStage;
|
|
22
22
|
alias: import("./akuma-creation.js").AliasStage;
|
|
@@ -191,6 +191,10 @@ export declare function composeLibrary(context?: ExecutionContext, composition?:
|
|
|
191
191
|
} | {
|
|
192
192
|
kind: "other";
|
|
193
193
|
display: string;
|
|
194
|
+
input?: {
|
|
195
|
+
json: string;
|
|
196
|
+
truncated: boolean;
|
|
197
|
+
} | undefined;
|
|
194
198
|
};
|
|
195
199
|
state: "active";
|
|
196
200
|
truncated?: true | undefined;
|
|
@@ -227,6 +231,10 @@ export declare function composeLibrary(context?: ExecutionContext, composition?:
|
|
|
227
231
|
} | {
|
|
228
232
|
kind: "other";
|
|
229
233
|
display: string;
|
|
234
|
+
input?: {
|
|
235
|
+
json: string;
|
|
236
|
+
truncated: boolean;
|
|
237
|
+
} | undefined;
|
|
230
238
|
};
|
|
231
239
|
state: {
|
|
232
240
|
status: "error" | "ok";
|
|
@@ -317,6 +325,10 @@ export declare function composeLibrary(context?: ExecutionContext, composition?:
|
|
|
317
325
|
} | {
|
|
318
326
|
kind: "other";
|
|
319
327
|
display: string;
|
|
328
|
+
input?: {
|
|
329
|
+
json: string;
|
|
330
|
+
truncated: boolean;
|
|
331
|
+
} | undefined;
|
|
320
332
|
};
|
|
321
333
|
state: {
|
|
322
334
|
status: "error" | "ok";
|
|
@@ -345,6 +357,7 @@ export declare function composeLibrary(context?: ExecutionContext, composition?:
|
|
|
345
357
|
};
|
|
346
358
|
} | undefined;
|
|
347
359
|
};
|
|
360
|
+
cwd?: string | undefined;
|
|
348
361
|
readonly?: {
|
|
349
362
|
enforcement: "native";
|
|
350
363
|
} | {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/** @architectureCompositionRoot */
|
|
2
2
|
import { type ActivityHistory, type OutcomeRow, type AkumaStatus, type InterruptReceipt } from "../akuma/akuma.js";
|
|
3
3
|
import { type ExecutionContext } from "../akuma/requests.js";
|
|
4
|
-
import type { WaitObserver } from "../akuma/fleet-execution.js";
|
|
4
|
+
import type { TellWaitObserver, WaitObserver } from "../akuma/fleet-execution.js";
|
|
5
5
|
import { type DispatchAssociation } from "../dispatch/index.js";
|
|
6
|
+
import { type Schema } from "../akuma/schema.js";
|
|
6
7
|
import { type AkumaAddressInput, type AkumaSetAddressInput } from "./address.js";
|
|
7
|
-
import { type AkumaKillResult, type AkumaObservation, type AkumaObservationStage, type AkumaTellResult, type AkumaWaitResult } from "../akuma/fleet-observation.js";
|
|
8
|
+
import { type AkumaKillResult, type AkumaObservation, type AkumaObservationStage, type AkumaTellResult, type AkumaTellWaitResult, type AkumaWaitResult } from "../akuma/fleet-observation.js";
|
|
8
9
|
export type AkumaWaitInput = AkumaSetAddressInput & Readonly<{
|
|
9
10
|
completion?: "any" | "all";
|
|
10
11
|
timeoutMs?: number;
|
|
@@ -15,6 +16,15 @@ export type AkumaTellInput = AkumaAddressInput & Readonly<{
|
|
|
15
16
|
initiator?: string;
|
|
16
17
|
signal?: AbortSignal;
|
|
17
18
|
}>;
|
|
19
|
+
export type AkumaTellWaitInput = AkumaAddressInput & Readonly<{
|
|
20
|
+
body: string;
|
|
21
|
+
timeoutMs: number;
|
|
22
|
+
schema?: Schema<unknown>;
|
|
23
|
+
interrupt?: boolean;
|
|
24
|
+
initiator?: string;
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
observe?: TellWaitObserver;
|
|
27
|
+
}>;
|
|
18
28
|
export type { TellResult, TellWake } from "../akuma/akuma.js";
|
|
19
29
|
export type { CreatedTaskObservation } from "../task/created-observation.js";
|
|
20
30
|
export type { DispatchAssociation } from "../dispatch/association.js";
|
|
@@ -68,5 +78,6 @@ export declare function statusAkuma(input: AkumaAddressInput): Promise<AkumaObse
|
|
|
68
78
|
export declare function waitAkuma(input: AkumaWaitInput, execution?: ExecutionContext, observer?: WaitObserver): Promise<AkumaWaitResult>;
|
|
69
79
|
export declare function killAkuma(input: AkumaKillInput, execution?: ExecutionContext): Promise<AkumaKillResult>;
|
|
70
80
|
export declare function tellAkuma(input: AkumaTellInput, execution?: ExecutionContext): Promise<AkumaTellResult>;
|
|
81
|
+
export declare function tellWaitAkuma(input: AkumaTellWaitInput, execution?: ExecutionContext): Promise<AkumaTellWaitResult>;
|
|
71
82
|
export declare function interruptAkuma(input: AkumaInterruptInput): Promise<AkumaInterruptResult>;
|
|
72
83
|
export declare function historyAkuma(input: AkumaHistoryInput): Promise<AkumaHistoryResult>;
|