@astrosheep/keiyaku 4.0.2 → 4.0.4
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 +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +5 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +3 -1
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +9 -8
- package/build/src/akuma/akuma.d.ts +34 -11
- package/build/src/akuma/akuma.js +121 -61
- package/build/src/akuma/allowed.d.ts +7 -0
- package/build/src/akuma/allowed.js +40 -0
- package/build/src/akuma/archetype.d.ts +7 -4
- package/build/src/akuma/archetype.js +15 -16
- package/build/src/akuma/body.d.ts +3 -1
- package/build/src/akuma/body.js +19 -8
- package/build/src/akuma/heart/facts.d.ts +49 -7
- package/build/src/akuma/heart/index.d.ts +4 -8
- package/build/src/akuma/heart/index.js +76 -15
- package/build/src/akuma/heart/rows.d.ts +7 -5
- package/build/src/akuma/heart/rows.js +98 -11
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +15 -10
- package/build/src/akuma/heart/soul.js +3 -1
- package/build/src/akuma/heart/storage.d.ts +2 -0
- package/build/src/akuma/heart/storage.js +20 -0
- package/build/src/akuma/heart/timeline.d.ts +1 -5
- package/build/src/akuma/heart/timeline.js +8 -17
- package/build/src/akuma/index.d.ts +4 -1
- package/build/src/akuma/index.js +1 -0
- package/build/src/akuma/projection.d.ts +17 -3
- package/build/src/akuma/projection.js +40 -3
- package/build/src/akuma/provider.d.ts +1 -1
- package/build/src/akuma/provider.js +2 -1
- package/build/src/akuma/providers/acp/core.d.ts +3 -1
- package/build/src/akuma/providers/acp/core.js +4 -4
- package/build/src/akuma/providers/acp/events.d.ts +11 -3
- package/build/src/akuma/providers/acp/events.js +78 -4
- package/build/src/akuma/providers/claude/events.js +62 -3
- package/build/src/akuma/providers/codex-app-server/events.js +1 -13
- package/build/src/akuma/providers/grok-build/index.d.ts +2 -1
- package/build/src/akuma/providers/grok-build/index.js +72 -2
- package/build/src/akuma/providers/opencode-sdk/events.js +71 -6
- package/build/src/akuma/providers/pi/events.js +17 -3
- package/build/src/akuma/providers/unified-patch.d.ts +4 -0
- package/build/src/akuma/providers/unified-patch.js +14 -0
- package/build/src/akuma/publication.d.ts +1 -1
- package/build/src/akuma/publication.js +36 -7
- package/build/src/akuma/requests.d.ts +70 -4
- package/build/src/akuma/requests.js +288 -77
- package/build/src/akuma-body.d.ts +1 -0
- package/build/src/akuma-body.js +31 -0
- package/build/src/cli/accepted.d.ts +4 -1
- package/build/src/cli/accepted.js +26 -4
- package/build/src/cli/commands/akuma-invoke.d.ts +8 -7
- package/build/src/cli/commands/akuma-invoke.js +18 -10
- package/build/src/cli/commands/akuma.d.ts +11 -2
- package/build/src/cli/commands/akuma.js +67 -28
- package/build/src/cli/commands/amend.d.ts +1 -1
- package/build/src/cli/commands/amend.js +1 -1
- package/build/src/cli/commands/contract.d.ts +3 -3
- package/build/src/cli/commands/contract.js +1 -1
- package/build/src/cli/commands/install.js +4 -4
- package/build/src/cli/commands/task-query.d.ts +1 -1
- package/build/src/cli/commands/task-query.js +11 -5
- package/build/src/cli/commands/task.js +4 -4
- package/build/src/cli/coordinates.d.ts +1 -0
- package/build/src/cli/coordinates.js +5 -1
- package/build/src/cli/invoke.d.ts +1 -0
- package/build/src/cli/invoke.js +90 -73
- package/build/src/cli/main.d.ts +2 -0
- package/build/src/cli/main.js +29 -4
- package/build/src/cli/parse.d.ts +1 -0
- package/build/src/cli/parse.js +8 -4
- package/build/src/cli/render/akuma.d.ts +2 -2
- package/build/src/cli/render/akuma.js +84 -13
- package/build/src/cli/render/audit.js +16 -2
- package/build/src/cli/render/contract.d.ts +2 -0
- package/build/src/cli/render/contract.js +203 -36
- package/build/src/cli/render/kanshi.js +64 -29
- package/build/src/cli/render/receipt.d.ts +2 -1
- package/build/src/cli/render/receipt.js +9 -1
- package/build/src/cli/render/text.js +3 -1
- package/build/src/cli/result.d.ts +38 -3
- package/build/src/cli/selectors.d.ts +1 -0
- package/build/src/cli/selectors.js +9 -6
- package/build/src/cli/usage.d.ts +2 -0
- package/build/src/cli/usage.js +4 -0
- package/build/src/contract-worktree.js +3 -0
- package/build/src/dispatch/index.js +50 -39
- package/build/src/git/hooks.d.ts +0 -4
- package/build/src/git/hooks.js +0 -36
- package/build/src/git/integration.d.ts +2 -6
- package/build/src/git/integration.js +8 -8
- package/build/src/git/read-observation.js +1 -0
- package/build/src/git/reconcile.d.ts +6 -1
- package/build/src/git/reconcile.js +55 -9
- package/build/src/git/tender.d.ts +19 -4
- package/build/src/git/tender.js +44 -13
- package/build/src/git/terminal-seal.d.ts +14 -0
- package/build/src/git/terminal-seal.js +15 -2
- package/build/src/git/workspace.d.ts +1 -0
- package/build/src/git/workspace.js +12 -4
- package/build/src/index.d.ts +1 -1
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +9 -1
- package/build/src/kanshi/read.js +91 -37
- package/build/src/kanshi/report.d.ts +1 -0
- package/build/src/library/address.d.ts +5 -14
- package/build/src/library/address.js +20 -22
- package/build/src/library/akuma-creation.d.ts +4 -2
- package/build/src/library/akuma-creation.js +43 -26
- package/build/src/library/bind.js +3 -3
- package/build/src/library/catalog.d.ts +1 -2
- package/build/src/library/catalog.js +11 -6
- package/build/src/library/configuration.d.ts +4 -0
- package/build/src/library/configuration.js +19 -0
- package/build/src/library/contract.d.ts +15 -1
- package/build/src/library/contract.js +51 -4
- package/build/src/library/fleet.d.ts +47 -9
- package/build/src/library/fleet.js +184 -44
- package/build/src/library/input.js +1 -0
- package/build/src/library/keiyaku.d.ts +4 -4
- package/build/src/library/keiyaku.js +1 -2
- package/build/src/protocol/bind.d.ts +1 -2
- package/build/src/protocol/bind.js +2 -16
- package/build/src/protocol/operations.d.ts +4 -1
- package/build/src/protocol/operations.js +33 -27
- package/build/src/protocol/read/status.d.ts +3 -1
- package/build/src/protocol/read/status.js +24 -14
- package/build/src/runtime/proc/run.d.ts +1 -0
- package/build/src/runtime/proc/run.js +9 -2
- package/build/src/settlement/settle.d.ts +1 -0
- package/build/src/settlement/settle.js +4 -1
- package/build/src/task/board.d.ts +18 -3
- package/build/src/task/board.js +73 -26
- package/build/src/task/index.d.ts +3 -3
- package/build/src/task/index.js +7 -5
- package/build/src/task/operations.d.ts +2 -19
- package/build/src/task/operations.js +29 -7
- package/build/src/task/query.d.ts +9 -2
- package/build/src/task/query.js +32 -64
- package/build/src/verification/execution.js +2 -1
- package/package.json +3 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { noteEvent, unknownEvent, } from "../../provider.js";
|
|
2
|
+
import { diffstatFromUnifiedPatch } from "../unified-patch.js";
|
|
2
3
|
export const CODEX_NOTIFICATION_DISPOSITIONS = {
|
|
3
4
|
"account/login/completed": "drop",
|
|
4
5
|
"account/rateLimits/updated": "drop",
|
|
@@ -135,19 +136,6 @@ function fileChangeOp(value) {
|
|
|
135
136
|
? record.type
|
|
136
137
|
: undefined;
|
|
137
138
|
}
|
|
138
|
-
function diffstatFromUnifiedPatch(patch) {
|
|
139
|
-
if (!patch.split("\n").some((line) => /^@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/u.test(line)))
|
|
140
|
-
return undefined;
|
|
141
|
-
let added = 0;
|
|
142
|
-
let removed = 0;
|
|
143
|
-
for (const line of patch.split("\n")) {
|
|
144
|
-
if (line.startsWith("+") && !line.startsWith("+++"))
|
|
145
|
-
added += 1;
|
|
146
|
-
if (line.startsWith("-") && !line.startsWith("---"))
|
|
147
|
-
removed += 1;
|
|
148
|
-
}
|
|
149
|
-
return { added, removed };
|
|
150
|
-
}
|
|
151
139
|
function itemChanges(item) {
|
|
152
140
|
if (!Array.isArray(item.changes))
|
|
153
141
|
return [];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ProviderAdapter } from "../../provider.js";
|
|
2
2
|
import type { ProviderExecution } from "../../provider-recipe.js";
|
|
3
|
-
import { type AcpDependencies } from "../acp/core.js";
|
|
3
|
+
import { type AcpDependencies, type AcpToolInterpreter } from "../acp/core.js";
|
|
4
|
+
export declare const interpretGrokTool: AcpToolInterpreter;
|
|
4
5
|
export declare function createGrokBuildProvider(execution: ProviderExecution, dependencies?: AcpDependencies): ProviderAdapter;
|
|
@@ -1,5 +1,72 @@
|
|
|
1
|
-
import { startAcpSession } from "../acp/core.js";
|
|
1
|
+
import { startAcpSession, } from "../acp/core.js";
|
|
2
2
|
const INTERJECT_METHOD = "x.ai/interject";
|
|
3
|
+
function nonblank(value) {
|
|
4
|
+
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
5
|
+
}
|
|
6
|
+
function object(value) {
|
|
7
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
8
|
+
? value
|
|
9
|
+
: undefined;
|
|
10
|
+
}
|
|
11
|
+
function nativeName(update) {
|
|
12
|
+
const wire = update;
|
|
13
|
+
return nonblank(update.name) ?? nonblank(wire.toolName);
|
|
14
|
+
}
|
|
15
|
+
function readCall(name, input) {
|
|
16
|
+
if (name !== "read_file" && name !== "hashline_read")
|
|
17
|
+
return undefined;
|
|
18
|
+
const sourcePath = nonblank(input.target_file);
|
|
19
|
+
const capturedPath = name === "read_file" ? nonblank(input.path) : undefined;
|
|
20
|
+
const path = sourcePath ?? capturedPath;
|
|
21
|
+
return path === undefined ? undefined : { kind: "read", path };
|
|
22
|
+
}
|
|
23
|
+
function contentSearchCall(name, input) {
|
|
24
|
+
if (name !== "grep" && name !== "hashline_grep")
|
|
25
|
+
return undefined;
|
|
26
|
+
const query = nonblank(input.pattern);
|
|
27
|
+
if (query === undefined)
|
|
28
|
+
return undefined;
|
|
29
|
+
const path = nonblank(input.path);
|
|
30
|
+
const glob = nonblank(input.glob);
|
|
31
|
+
return {
|
|
32
|
+
kind: "search",
|
|
33
|
+
query,
|
|
34
|
+
scope: "content",
|
|
35
|
+
...(path === undefined ? {} : { path }),
|
|
36
|
+
...(glob === undefined ? {} : { glob }),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function runCall(name, input) {
|
|
40
|
+
if (name !== "run_terminal_cmd")
|
|
41
|
+
return undefined;
|
|
42
|
+
const command = nonblank(input.command);
|
|
43
|
+
return command === undefined ? undefined : { kind: "run", command };
|
|
44
|
+
}
|
|
45
|
+
function webSearchCall(name, input) {
|
|
46
|
+
if (name !== "web_search")
|
|
47
|
+
return undefined;
|
|
48
|
+
const query = nonblank(input.query);
|
|
49
|
+
return query === undefined ? undefined : { kind: "search", query, scope: "web" };
|
|
50
|
+
}
|
|
51
|
+
function fileChangeCall(name, input) {
|
|
52
|
+
if (name !== "search_replace")
|
|
53
|
+
return undefined;
|
|
54
|
+
const path = nonblank(input.file_path);
|
|
55
|
+
return path === undefined
|
|
56
|
+
? undefined
|
|
57
|
+
: { kind: "fileChange", changes: [{ op: "unspecified", path }] };
|
|
58
|
+
}
|
|
59
|
+
export const interpretGrokTool = (update) => {
|
|
60
|
+
const name = nativeName(update);
|
|
61
|
+
const input = object(update.rawInput);
|
|
62
|
+
if (name === undefined || input === undefined)
|
|
63
|
+
return undefined;
|
|
64
|
+
return readCall(name, input)
|
|
65
|
+
?? contentSearchCall(name, input)
|
|
66
|
+
?? runCall(name, input)
|
|
67
|
+
?? webSearchCall(name, input)
|
|
68
|
+
?? fileChangeCall(name, input);
|
|
69
|
+
};
|
|
3
70
|
function optionAdmission(options) {
|
|
4
71
|
if (options.network !== undefined) {
|
|
5
72
|
return { kind: "refused", diagnostic: "Grok Build does not support the network option" };
|
|
@@ -59,7 +126,10 @@ export function createGrokBuildProvider(execution, dependencies = {}) {
|
|
|
59
126
|
argv: argv(execution, input.options),
|
|
60
127
|
...(execution.env === undefined ? {} : { env: execution.env }),
|
|
61
128
|
};
|
|
62
|
-
return withInterject(await startAcpSession(launch, input,
|
|
129
|
+
return withInterject(await startAcpSession(launch, input, {
|
|
130
|
+
...dependencies,
|
|
131
|
+
interpretTool: interpretGrokTool,
|
|
132
|
+
}));
|
|
63
133
|
};
|
|
64
134
|
return {
|
|
65
135
|
confinement: () => ({ kind: "unconfined" }),
|
|
@@ -59,6 +59,61 @@ function diagnostic(value) {
|
|
|
59
59
|
function positiveLine(value) {
|
|
60
60
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 1 ? value : undefined;
|
|
61
61
|
}
|
|
62
|
+
function nonnegativeCount(value) {
|
|
63
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
64
|
+
}
|
|
65
|
+
function diffstat(value) {
|
|
66
|
+
if (value === undefined)
|
|
67
|
+
return undefined;
|
|
68
|
+
const added = nonnegativeCount(value.additions);
|
|
69
|
+
const removed = nonnegativeCount(value.deletions);
|
|
70
|
+
return added === undefined || removed === undefined ? undefined : { added, removed };
|
|
71
|
+
}
|
|
72
|
+
function fileChange(changes) {
|
|
73
|
+
return changes.length === 0 ? undefined : { kind: "fileChange", changes };
|
|
74
|
+
}
|
|
75
|
+
function change(op, path, stats) {
|
|
76
|
+
return stats === undefined ? { op, path } : { op, path, diffstat: stats };
|
|
77
|
+
}
|
|
78
|
+
function editCall(input, metadata) {
|
|
79
|
+
const path = text(input?.filePath);
|
|
80
|
+
if (path === undefined)
|
|
81
|
+
return undefined;
|
|
82
|
+
return fileChange([change("update", path, diffstat(object(metadata?.filediff)))]);
|
|
83
|
+
}
|
|
84
|
+
function writeCall(input, metadata) {
|
|
85
|
+
const path = text(metadata?.filepath) ?? text(input?.filePath);
|
|
86
|
+
const op = metadata?.exists === false ? "add"
|
|
87
|
+
: metadata?.exists === true ? "update" : undefined;
|
|
88
|
+
return path === undefined || op === undefined ? undefined : fileChange([change(op, path, undefined)]);
|
|
89
|
+
}
|
|
90
|
+
function applyPatchFile(value) {
|
|
91
|
+
const file = object(value);
|
|
92
|
+
if (file === undefined)
|
|
93
|
+
return undefined;
|
|
94
|
+
const type = file.type;
|
|
95
|
+
const op = type === "add" ? "add"
|
|
96
|
+
: type === "delete" ? "delete"
|
|
97
|
+
: type === "update" || type === "modify" || type === "move"
|
|
98
|
+
? "update" : undefined;
|
|
99
|
+
const path = type === "move" ? text(file.movePath) : text(file.filePath);
|
|
100
|
+
return op === undefined || path === undefined ? undefined : change(op, path, diffstat(file));
|
|
101
|
+
}
|
|
102
|
+
function applyPatchCall(metadata) {
|
|
103
|
+
if (!Array.isArray(metadata?.files))
|
|
104
|
+
return undefined;
|
|
105
|
+
return fileChange(metadata.files.flatMap((value) => {
|
|
106
|
+
const next = applyPatchFile(value);
|
|
107
|
+
return next === undefined ? [] : [next];
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
function strongerCall(previous, next) {
|
|
111
|
+
if (next === undefined)
|
|
112
|
+
return previous;
|
|
113
|
+
if (previous?.kind === "fileChange" && next.kind !== "fileChange")
|
|
114
|
+
return previous;
|
|
115
|
+
return next;
|
|
116
|
+
}
|
|
62
117
|
function runCall(name, value) {
|
|
63
118
|
return name === "bash" || name === "shell"
|
|
64
119
|
? { kind: "run", command: text(value?.command) ?? name }
|
|
@@ -96,8 +151,9 @@ function searchCall(name, value) {
|
|
|
96
151
|
...(scope === "content" && glob !== undefined ? { glob } : {}),
|
|
97
152
|
};
|
|
98
153
|
}
|
|
99
|
-
function callFor(name, input) {
|
|
154
|
+
function callFor(name, input, metadata) {
|
|
100
155
|
const value = object(input);
|
|
156
|
+
const meta = object(metadata);
|
|
101
157
|
const lower = name.toLowerCase();
|
|
102
158
|
if (lower === "bash" || lower === "shell")
|
|
103
159
|
return runCall(lower, value);
|
|
@@ -105,6 +161,12 @@ function callFor(name, input) {
|
|
|
105
161
|
return readCall(lower, value);
|
|
106
162
|
if (lower === "grep" || lower === "glob" || lower === "search")
|
|
107
163
|
return searchCall(lower, value);
|
|
164
|
+
if (lower === "edit")
|
|
165
|
+
return editCall(value, meta) ?? { kind: "other", display: name };
|
|
166
|
+
if (lower === "write")
|
|
167
|
+
return writeCall(value, meta) ?? { kind: "other", display: name };
|
|
168
|
+
if (lower === "apply_patch")
|
|
169
|
+
return applyPatchCall(meta) ?? { kind: "other", display: name };
|
|
108
170
|
return { kind: "other", display: name };
|
|
109
171
|
}
|
|
110
172
|
function belongs(part, state) {
|
|
@@ -139,12 +201,12 @@ function mapToolPart(part, events, state) {
|
|
|
139
201
|
const toolState = object(part.state);
|
|
140
202
|
if (id === undefined || name === undefined || toolState === undefined)
|
|
141
203
|
return;
|
|
204
|
+
const next = callFor(name, toolState.input, toolState.metadata);
|
|
142
205
|
if ((toolState.status === "pending" || toolState.status === "running")
|
|
143
206
|
&& !state.tools.has(id) && !state.completedTools.has(id)) {
|
|
144
|
-
|
|
145
|
-
if (call === undefined)
|
|
207
|
+
if (next === undefined)
|
|
146
208
|
return;
|
|
147
|
-
const observed = { name, call };
|
|
209
|
+
const observed = { name, call: next };
|
|
148
210
|
state.tools.set(id, observed);
|
|
149
211
|
events.emit({ type: "tool", phase: "started", id, ...observed });
|
|
150
212
|
return;
|
|
@@ -152,14 +214,17 @@ function mapToolPart(part, events, state) {
|
|
|
152
214
|
if ((toolState.status !== "completed" && toolState.status !== "error") || state.completedTools.has(id))
|
|
153
215
|
return;
|
|
154
216
|
const started = state.tools.get(id);
|
|
155
|
-
const call = started?.call
|
|
217
|
+
const call = strongerCall(started?.call, next);
|
|
156
218
|
if (call === undefined)
|
|
157
219
|
return;
|
|
158
|
-
const observed = started ??
|
|
220
|
+
const observed = { name: started?.name ?? name, call };
|
|
159
221
|
if (!state.tools.has(id)) {
|
|
160
222
|
state.tools.set(id, observed);
|
|
161
223
|
events.emit({ type: "tool", phase: "started", id, ...observed });
|
|
162
224
|
}
|
|
225
|
+
else {
|
|
226
|
+
state.tools.set(id, observed);
|
|
227
|
+
}
|
|
163
228
|
state.completedTools.add(id);
|
|
164
229
|
events.emit({
|
|
165
230
|
type: "tool",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { noteEvent, unknownEvent } from "../../provider.js";
|
|
2
|
+
import { diffstatFromUnifiedPatch } from "../unified-patch.js";
|
|
2
3
|
export const PI_EVENT_DISPOSITIONS = {
|
|
3
4
|
agent_end: "drop",
|
|
4
5
|
agent_settled: "drop",
|
|
@@ -82,9 +83,21 @@ function searchCall(name, value) {
|
|
|
82
83
|
};
|
|
83
84
|
}
|
|
84
85
|
function fileChangeCall(name, value) {
|
|
85
|
-
if (
|
|
86
|
+
if (name !== "edit" || typeof value.path !== "string")
|
|
86
87
|
return undefined;
|
|
87
|
-
return { kind: "fileChange", changes: [{ op:
|
|
88
|
+
return { kind: "fileChange", changes: [{ op: "update", path: value.path }] };
|
|
89
|
+
}
|
|
90
|
+
function refineEditCall(call, result) {
|
|
91
|
+
if (call.kind !== "fileChange")
|
|
92
|
+
return call;
|
|
93
|
+
const details = record(record(result)?.details);
|
|
94
|
+
if (typeof details?.patch !== "string")
|
|
95
|
+
return call;
|
|
96
|
+
const diffstat = diffstatFromUnifiedPatch(details.patch);
|
|
97
|
+
const change = call.changes[0];
|
|
98
|
+
if (diffstat === undefined || change === undefined)
|
|
99
|
+
return call;
|
|
100
|
+
return { kind: "fileChange", changes: [{ ...change, diffstat }] };
|
|
88
101
|
}
|
|
89
102
|
function toolCall(name, args) {
|
|
90
103
|
const value = record(args) ?? {};
|
|
@@ -108,9 +121,10 @@ function translateToolEnd(event, state) {
|
|
|
108
121
|
const started = state.tools.get(event.toolCallId);
|
|
109
122
|
state.tools.delete(event.toolCallId);
|
|
110
123
|
const name = started?.name ?? event.toolName;
|
|
124
|
+
const call = started?.call ?? { kind: "other", display: name };
|
|
111
125
|
return [{
|
|
112
126
|
type: "tool", phase: "completed", id: event.toolCallId, name,
|
|
113
|
-
call:
|
|
127
|
+
call: event.isError ? call : refineEditCall(call, event.result),
|
|
114
128
|
result: { status: event.isError ? "error" : "ok" },
|
|
115
129
|
}];
|
|
116
130
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function diffstatFromUnifiedPatch(patch) {
|
|
2
|
+
const lines = patch.split("\n");
|
|
3
|
+
if (!lines.some((line) => /^@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/u.test(line)))
|
|
4
|
+
return undefined;
|
|
5
|
+
let added = 0;
|
|
6
|
+
let removed = 0;
|
|
7
|
+
for (const line of lines) {
|
|
8
|
+
if (line.startsWith("+") && !line.startsWith("+++"))
|
|
9
|
+
added += 1;
|
|
10
|
+
if (line.startsWith("-") && !line.startsWith("---"))
|
|
11
|
+
removed += 1;
|
|
12
|
+
}
|
|
13
|
+
return { added, removed };
|
|
14
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { HeldAkumaLeash, initializeHeart, readHeart, readSoul, } from "./heart/index.js";
|
|
1
|
+
import { HeldAkumaLeash, initializeHeart, readHeart, readSeal, readSoul, } from "./heart/index.js";
|
|
2
2
|
import { allocateAkumaDirectory, } from "./identity.js";
|
|
3
3
|
import { abortableDelay } from "./abort.js";
|
|
4
4
|
const POLL_MS = 25;
|
|
5
|
-
export const BIRTH_TIMEOUT_MS =
|
|
5
|
+
export const BIRTH_TIMEOUT_MS = 30_000;
|
|
6
6
|
function diagnostic(error) {
|
|
7
7
|
return error instanceof Error ? error.message : String(error);
|
|
8
8
|
}
|
|
@@ -10,15 +10,38 @@ async function settleTimedOutBirth(paths) {
|
|
|
10
10
|
const leash = await HeldAkumaLeash.try(paths);
|
|
11
11
|
if (leash === null)
|
|
12
12
|
return null;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
let result;
|
|
14
|
+
try {
|
|
15
|
+
result = await leash.sealIfUnborn(paths, {
|
|
16
|
+
evidence: "call-timeout",
|
|
17
|
+
at: new Date().toISOString(),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
leash.release();
|
|
22
|
+
}
|
|
23
|
+
if (result === "sealed") {
|
|
24
|
+
const seal = await readSeal(paths);
|
|
25
|
+
throw new Error(seal?.evidence === "call-timeout" || seal === null
|
|
26
|
+
? "Akuma body failed before birth"
|
|
27
|
+
: seal.evidence);
|
|
28
|
+
}
|
|
17
29
|
const soul = await readSoul(paths);
|
|
18
30
|
if (soul === null)
|
|
19
31
|
throw new Error("Akuma birth settled without a soul");
|
|
20
32
|
return soul;
|
|
21
33
|
}
|
|
34
|
+
async function observedBirthFailure(paths) {
|
|
35
|
+
const leash = await HeldAkumaLeash.try(paths);
|
|
36
|
+
if (leash === null)
|
|
37
|
+
return null;
|
|
38
|
+
try {
|
|
39
|
+
return leash.readSeal()?.evidence ?? null;
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
leash.release();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
22
45
|
async function awaitBirth(paths, signal) {
|
|
23
46
|
const deadline = performance.now() + BIRTH_TIMEOUT_MS;
|
|
24
47
|
for (;;) {
|
|
@@ -26,6 +49,9 @@ async function awaitBirth(paths, signal) {
|
|
|
26
49
|
const soul = await readSoul(paths);
|
|
27
50
|
if (soul !== null)
|
|
28
51
|
return soul;
|
|
52
|
+
const failure = await observedBirthFailure(paths);
|
|
53
|
+
if (failure !== null)
|
|
54
|
+
throw new Error(failure);
|
|
29
55
|
if (performance.now() >= deadline) {
|
|
30
56
|
const settled = await settleTimedOutBirth(paths);
|
|
31
57
|
if (settled !== null)
|
|
@@ -63,7 +89,10 @@ async function sealLocalFailure(allocated, error) {
|
|
|
63
89
|
if (leash === null)
|
|
64
90
|
return;
|
|
65
91
|
try {
|
|
66
|
-
await leash.sealIfUnborn(allocated.paths, {
|
|
92
|
+
await leash.sealIfUnborn(allocated.paths, {
|
|
93
|
+
evidence: diagnostic(error),
|
|
94
|
+
at: new Date().toISOString(),
|
|
95
|
+
});
|
|
67
96
|
}
|
|
68
97
|
finally {
|
|
69
98
|
leash.release();
|
|
@@ -1,12 +1,65 @@
|
|
|
1
|
-
import { type RequestRecipe, type Soul } from "./heart/index.js";
|
|
1
|
+
import { type KillEvidence, type RequestRecipe, type Soul } from "./heart/index.js";
|
|
2
2
|
import { type AkuId, type AkumaPaths } from "./identity.js";
|
|
3
|
-
type
|
|
3
|
+
type RequestClaimRecipe = Omit<RequestRecipe, "confinement">;
|
|
4
|
+
type CallRequestClaim = Readonly<{
|
|
4
5
|
id: string;
|
|
6
|
+
action: "akuma.call";
|
|
5
7
|
world: string;
|
|
6
8
|
archetype: string;
|
|
7
9
|
body: string;
|
|
8
10
|
cwd?: string;
|
|
9
|
-
recipe:
|
|
11
|
+
recipe: RequestClaimRecipe;
|
|
12
|
+
}>;
|
|
13
|
+
type WaitRequestClaim = Readonly<{
|
|
14
|
+
id: string;
|
|
15
|
+
action: "akuma.wait";
|
|
16
|
+
targets: readonly AkuId[];
|
|
17
|
+
completion: "any" | "all";
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
}>;
|
|
20
|
+
type TellRequestClaim = Readonly<{
|
|
21
|
+
id: string;
|
|
22
|
+
action: "akuma.tell";
|
|
23
|
+
target: AkuId;
|
|
24
|
+
body: string;
|
|
25
|
+
}>;
|
|
26
|
+
type KillRequestClaim = Readonly<{
|
|
27
|
+
id: string;
|
|
28
|
+
action: "akuma.kill";
|
|
29
|
+
targets: readonly AkuId[];
|
|
30
|
+
}>;
|
|
31
|
+
type UpstreamRequestFailure = Readonly<{
|
|
32
|
+
kind: "akuma-not-born";
|
|
33
|
+
id: AkuId;
|
|
34
|
+
}> | Readonly<{
|
|
35
|
+
kind: "failed";
|
|
36
|
+
diagnostic: string;
|
|
37
|
+
}>;
|
|
38
|
+
export type UpstreamRequestOutcome = Readonly<{
|
|
39
|
+
kind: "returned";
|
|
40
|
+
result: unknown;
|
|
41
|
+
}> | Readonly<{
|
|
42
|
+
kind: "failed";
|
|
43
|
+
failure: UpstreamRequestFailure;
|
|
44
|
+
}>;
|
|
45
|
+
export type UpstreamExecutionPort = Readonly<{
|
|
46
|
+
wait(input: Omit<WaitRequestClaim, "id" | "action"> & Readonly<{
|
|
47
|
+
signal: AbortSignal;
|
|
48
|
+
}>): Promise<unknown>;
|
|
49
|
+
tell(input: Omit<TellRequestClaim, "id" | "action"> & Readonly<{
|
|
50
|
+
tellId: string;
|
|
51
|
+
recordedAt: string;
|
|
52
|
+
signal: AbortSignal;
|
|
53
|
+
}>): Promise<unknown>;
|
|
54
|
+
kill(input: Omit<KillRequestClaim, "id" | "action"> & Readonly<{
|
|
55
|
+
signal: AbortSignal;
|
|
56
|
+
}>): Promise<Readonly<{
|
|
57
|
+
result: unknown;
|
|
58
|
+
service: readonly Readonly<{
|
|
59
|
+
id: AkuId;
|
|
60
|
+
evidence: KillEvidence;
|
|
61
|
+
}>[];
|
|
62
|
+
}>>;
|
|
10
63
|
}>;
|
|
11
64
|
export type RequestChildLaunch = Readonly<{
|
|
12
65
|
paths: AkumaPaths;
|
|
@@ -20,9 +73,21 @@ export declare class AkumaBodyRequestError extends Error {
|
|
|
20
73
|
constructor(outcome: "refused" | "voided", diagnostic: string);
|
|
21
74
|
}
|
|
22
75
|
export declare function injectedBodyRequests(): string | null;
|
|
23
|
-
export declare function requestBodyCall(input:
|
|
76
|
+
export declare function requestBodyCall(input: Omit<CallRequestClaim, "action"> & Readonly<{
|
|
24
77
|
directory: string;
|
|
25
78
|
}>): Promise<AkuId>;
|
|
79
|
+
export declare function requestBodyWait(input: Omit<WaitRequestClaim, "action" | "id"> & Readonly<{
|
|
80
|
+
directory: string;
|
|
81
|
+
id?: string;
|
|
82
|
+
}>): Promise<UpstreamRequestOutcome>;
|
|
83
|
+
export declare function requestBodyTell(input: Omit<TellRequestClaim, "action" | "id"> & Readonly<{
|
|
84
|
+
directory: string;
|
|
85
|
+
id?: string;
|
|
86
|
+
}>): Promise<UpstreamRequestOutcome>;
|
|
87
|
+
export declare function requestBodyKill(input: Omit<KillRequestClaim, "action" | "id"> & Readonly<{
|
|
88
|
+
directory: string;
|
|
89
|
+
id?: string;
|
|
90
|
+
}>): Promise<UpstreamRequestOutcome>;
|
|
26
91
|
export declare class BodyRequestPump {
|
|
27
92
|
private readonly input;
|
|
28
93
|
readonly directory: string;
|
|
@@ -38,6 +103,7 @@ export declare class BodyRequestPump {
|
|
|
38
103
|
bodySequence: number;
|
|
39
104
|
now(): string;
|
|
40
105
|
spawn(launch: RequestChildLaunch): Promise<void>;
|
|
106
|
+
upstream?: UpstreamExecutionPort;
|
|
41
107
|
signal: AbortSignal;
|
|
42
108
|
}>): Promise<BodyRequestPump>;
|
|
43
109
|
private run;
|