@astrosheep/keiyaku 4.0.3 → 4.0.5

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.
Files changed (238) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +1 -1
  3. package/build/integrations/marketplace/plugins/keiyaku/package.json +1 -1
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +4 -4
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +1 -1
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +15 -1
  7. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +3 -1
  8. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +34 -13
  9. package/build/src/akuma/akuma.d.ts +34 -12
  10. package/build/src/akuma/akuma.js +118 -63
  11. package/build/src/akuma/allowed.d.ts +7 -0
  12. package/build/src/akuma/allowed.js +33 -0
  13. package/build/src/akuma/archetype.d.ts +7 -4
  14. package/build/src/akuma/archetype.js +15 -16
  15. package/build/src/akuma/body.d.ts +6 -1
  16. package/build/src/akuma/body.js +36 -27
  17. package/build/src/akuma/heart/facts.d.ts +82 -14
  18. package/build/src/akuma/heart/index.d.ts +5 -18
  19. package/build/src/akuma/heart/index.js +14 -84
  20. package/build/src/akuma/heart/request-authority.d.ts +12 -0
  21. package/build/src/akuma/heart/request-authority.js +119 -0
  22. package/build/src/akuma/heart/request-rows.d.ts +16 -0
  23. package/build/src/akuma/heart/request-rows.js +88 -0
  24. package/build/src/akuma/heart/rows.d.ts +1 -26
  25. package/build/src/akuma/heart/rows.js +0 -50
  26. package/build/src/akuma/heart/schema.d.ts +1 -1
  27. package/build/src/akuma/heart/schema.js +22 -10
  28. package/build/src/akuma/heart/soul.js +2 -36
  29. package/build/src/akuma/heart/storage.d.ts +1 -0
  30. package/build/src/akuma/heart/storage.js +15 -0
  31. package/build/src/akuma/heart/timeline.d.ts +1 -5
  32. package/build/src/akuma/heart/timeline.js +8 -17
  33. package/build/src/akuma/index.d.ts +5 -2
  34. package/build/src/akuma/index.js +1 -0
  35. package/build/src/akuma/projection.d.ts +17 -3
  36. package/build/src/akuma/projection.js +40 -3
  37. package/build/src/akuma/provider-recipe.js +1 -11
  38. package/build/src/akuma/provider.d.ts +2 -7
  39. package/build/src/akuma/provider.js +2 -1
  40. package/build/src/akuma/providers/acp/core.d.ts +3 -1
  41. package/build/src/akuma/providers/acp/core.js +10 -6
  42. package/build/src/akuma/providers/acp/events.d.ts +11 -3
  43. package/build/src/akuma/providers/acp/events.js +78 -4
  44. package/build/src/akuma/providers/acp/index.js +0 -1
  45. package/build/src/akuma/providers/claude/events.js +62 -3
  46. package/build/src/akuma/providers/claude/index.d.ts +0 -4
  47. package/build/src/akuma/providers/claude/index.js +7 -3
  48. package/build/src/akuma/providers/codex-app-server/events.js +1 -13
  49. package/build/src/akuma/providers/codex-app-server/index.d.ts +2 -27
  50. package/build/src/akuma/providers/codex-app-server/index.js +0 -2
  51. package/build/src/akuma/providers/grok-build/index.d.ts +2 -1
  52. package/build/src/akuma/providers/grok-build/index.js +72 -3
  53. package/build/src/akuma/providers/opencode-sdk/events.js +71 -6
  54. package/build/src/akuma/providers/opencode-sdk/index.d.ts +2 -28
  55. package/build/src/akuma/providers/opencode-sdk/index.js +8 -4
  56. package/build/src/akuma/providers/opencode-sdk/session.d.ts +1 -1
  57. package/build/src/akuma/providers/opencode-sdk/session.js +1 -1
  58. package/build/src/akuma/providers/pi/events.js +17 -3
  59. package/build/src/akuma/providers/pi/index.js +11 -4
  60. package/build/src/akuma/providers/unified-patch.d.ts +4 -0
  61. package/build/src/akuma/providers/unified-patch.js +14 -0
  62. package/build/src/akuma/publication.d.ts +1 -1
  63. package/build/src/akuma/publication.js +1 -1
  64. package/build/src/akuma/request-serve.d.ts +87 -0
  65. package/build/src/akuma/request-serve.js +484 -0
  66. package/build/src/akuma/request-wire.d.ts +124 -0
  67. package/build/src/akuma/request-wire.js +380 -0
  68. package/build/src/akuma/requests.d.ts +41 -41
  69. package/build/src/akuma/requests.js +75 -374
  70. package/build/src/akuma-body.d.ts +8 -0
  71. package/build/src/akuma-body.js +84 -0
  72. package/build/src/body/arc.js +4 -29
  73. package/build/src/body/decode.js +5 -39
  74. package/build/src/body/envelope.d.ts +7 -0
  75. package/build/src/body/envelope.js +37 -0
  76. package/build/src/cli/accepted.d.ts +4 -1
  77. package/build/src/cli/accepted.js +39 -9
  78. package/build/src/cli/commands/akuma-invoke.d.ts +8 -7
  79. package/build/src/cli/commands/akuma-invoke.js +18 -10
  80. package/build/src/cli/commands/akuma.d.ts +11 -2
  81. package/build/src/cli/commands/akuma.js +67 -28
  82. package/build/src/cli/commands/amend.d.ts +1 -1
  83. package/build/src/cli/commands/amend.js +1 -1
  84. package/build/src/cli/commands/contract.d.ts +8 -8
  85. package/build/src/cli/commands/contract.js +3 -3
  86. package/build/src/cli/commands/install.js +2 -2
  87. package/build/src/cli/commands/task-invoke.js +98 -9
  88. package/build/src/cli/commands/task-query.d.ts +1 -1
  89. package/build/src/cli/commands/task-query.js +11 -5
  90. package/build/src/cli/coordinates.d.ts +2 -0
  91. package/build/src/cli/coordinates.js +12 -5
  92. package/build/src/cli/invoke.d.ts +1 -0
  93. package/build/src/cli/invoke.js +116 -75
  94. package/build/src/cli/main.d.ts +2 -0
  95. package/build/src/cli/main.js +29 -4
  96. package/build/src/cli/parse.d.ts +3 -2
  97. package/build/src/cli/parse.js +25 -8
  98. package/build/src/cli/render/akuma.d.ts +2 -2
  99. package/build/src/cli/render/akuma.js +138 -24
  100. package/build/src/cli/render/audit.js +18 -8
  101. package/build/src/cli/render/contract.d.ts +2 -0
  102. package/build/src/cli/render/contract.js +243 -36
  103. package/build/src/cli/render/kanshi.js +64 -29
  104. package/build/src/cli/render/receipt.d.ts +2 -1
  105. package/build/src/cli/render/receipt.js +37 -2
  106. package/build/src/cli/render/terminal.d.ts +0 -2
  107. package/build/src/cli/render/terminal.js +0 -29
  108. package/build/src/cli/render/text.js +3 -1
  109. package/build/src/cli/result.d.ts +52 -9
  110. package/build/src/cli/selectors.d.ts +1 -0
  111. package/build/src/cli/selectors.js +9 -6
  112. package/build/src/contract-worktree.d.ts +1 -2
  113. package/build/src/contract-worktree.js +7 -9
  114. package/build/src/core/facts/codec.js +9 -0
  115. package/build/src/core/facts/fold.js +13 -1
  116. package/build/src/core/facts/types.d.ts +8 -1
  117. package/build/src/core/subject.js +4 -3
  118. package/build/src/core/verbs/placement.d.ts +9 -1
  119. package/build/src/core/verbs/placement.js +24 -6
  120. package/build/src/core/verbs/reintegrate.d.ts +13 -0
  121. package/build/src/core/verbs/reintegrate.js +24 -0
  122. package/build/src/dispatch/index.d.ts +1 -1
  123. package/build/src/dispatch/index.js +50 -39
  124. package/build/src/git/admission.d.ts +2 -1
  125. package/build/src/git/hooks.d.ts +0 -4
  126. package/build/src/git/hooks.js +0 -36
  127. package/build/src/git/integration.d.ts +7 -8
  128. package/build/src/git/integration.js +62 -9
  129. package/build/src/git/observe.d.ts +2 -1
  130. package/build/src/git/observe.js +6 -5
  131. package/build/src/git/process.d.ts +26 -0
  132. package/build/src/git/process.js +94 -0
  133. package/build/src/git/read-observation.d.ts +2 -1
  134. package/build/src/git/read-observation.js +3 -2
  135. package/build/src/git/reconcile.d.ts +8 -2
  136. package/build/src/git/reconcile.js +63 -14
  137. package/build/src/git/repository.d.ts +2 -29
  138. package/build/src/git/repository.js +4 -118
  139. package/build/src/git/scratch.d.ts +1 -1
  140. package/build/src/git/scratch.js +1 -1
  141. package/build/src/git/target-placement.d.ts +1 -1
  142. package/build/src/git/target-placement.js +9 -7
  143. package/build/src/git/tender.d.ts +20 -5
  144. package/build/src/git/tender.js +45 -13
  145. package/build/src/git/terminal-seal.d.ts +16 -2
  146. package/build/src/git/terminal-seal.js +15 -5
  147. package/build/src/git/workspace.d.ts +2 -1
  148. package/build/src/git/workspace.js +13 -5
  149. package/build/src/index.d.ts +1 -2
  150. package/build/src/index.js +1 -1
  151. package/build/src/kanshi/index.d.ts +1 -1
  152. package/build/src/kanshi/index.js +1 -1
  153. package/build/src/kanshi/read.d.ts +9 -1
  154. package/build/src/kanshi/read.js +91 -37
  155. package/build/src/kanshi/report.d.ts +1 -0
  156. package/build/src/library/address.d.ts +5 -14
  157. package/build/src/library/address.js +27 -23
  158. package/build/src/library/akuma-creation.d.ts +4 -2
  159. package/build/src/library/akuma-creation.js +43 -26
  160. package/build/src/library/audit.d.ts +2 -1
  161. package/build/src/library/audit.js +1 -1
  162. package/build/src/library/bind.d.ts +2 -1
  163. package/build/src/library/bind.js +4 -4
  164. package/build/src/library/catalog.d.ts +1 -2
  165. package/build/src/library/catalog.js +11 -6
  166. package/build/src/library/configuration.d.ts +5 -1
  167. package/build/src/library/configuration.js +71 -18
  168. package/build/src/library/contract.d.ts +70 -3
  169. package/build/src/library/contract.js +213 -27
  170. package/build/src/library/delivery.d.ts +1 -1
  171. package/build/src/library/fleet.d.ts +70 -12
  172. package/build/src/library/fleet.js +236 -56
  173. package/build/src/library/input.d.ts +0 -1
  174. package/build/src/library/input.js +1 -5
  175. package/build/src/library/keiyaku.d.ts +4 -4
  176. package/build/src/library/keiyaku.js +1 -2
  177. package/build/src/library/mutation.d.ts +2 -1
  178. package/build/src/library/reconcile.d.ts +2 -1
  179. package/build/src/library/reconcile.js +3 -1
  180. package/build/src/library/region.d.ts +1 -1
  181. package/build/src/library/repo.d.ts +3 -1
  182. package/build/src/library/repo.js +8 -4
  183. package/build/src/protocol/abandon.d.ts +9 -0
  184. package/build/src/protocol/abandon.js +15 -0
  185. package/build/src/protocol/amend.d.ts +16 -0
  186. package/build/src/protocol/amend.js +77 -0
  187. package/build/src/protocol/arc.d.ts +6 -0
  188. package/build/src/protocol/arc.js +12 -0
  189. package/build/src/protocol/attempt.d.ts +2 -1
  190. package/build/src/protocol/audit.d.ts +53 -0
  191. package/build/src/protocol/audit.js +140 -0
  192. package/build/src/protocol/bind.d.ts +2 -3
  193. package/build/src/protocol/bind.js +2 -16
  194. package/build/src/protocol/completion.d.ts +32 -0
  195. package/build/src/protocol/completion.js +130 -0
  196. package/build/src/protocol/deliver.d.ts +37 -0
  197. package/build/src/protocol/deliver.js +160 -0
  198. package/build/src/protocol/intent.d.ts +1 -1
  199. package/build/src/protocol/intent.js +1 -1
  200. package/build/src/protocol/operations.d.ts +65 -198
  201. package/build/src/protocol/operations.js +21 -634
  202. package/build/src/protocol/placement.d.ts +4 -13
  203. package/build/src/protocol/placement.js +3 -15
  204. package/build/src/protocol/read/status.d.ts +4 -2
  205. package/build/src/protocol/read/status.js +27 -15
  206. package/build/src/protocol/reconcile.d.ts +35 -0
  207. package/build/src/protocol/reconcile.js +41 -0
  208. package/build/src/protocol/reintegrate.d.ts +31 -0
  209. package/build/src/protocol/reintegrate.js +74 -0
  210. package/build/src/protocol/review.d.ts +33 -0
  211. package/build/src/protocol/review.js +148 -0
  212. package/build/src/protocol/run.d.ts +1 -1
  213. package/build/src/runtime/proc/run.d.ts +1 -0
  214. package/build/src/runtime/proc/run.js +9 -2
  215. package/build/src/settlement/fence.d.ts +1 -1
  216. package/build/src/settlement/holder.d.ts +1 -1
  217. package/build/src/settlement/settle.d.ts +2 -1
  218. package/build/src/settlement/settle.js +4 -1
  219. package/build/src/task/board.d.ts +18 -4
  220. package/build/src/task/board.js +73 -29
  221. package/build/src/task/compose.d.ts +1 -1
  222. package/build/src/task/compose.js +11 -4
  223. package/build/src/task/index.d.ts +4 -4
  224. package/build/src/task/index.js +8 -131
  225. package/build/src/task/input.d.ts +18 -0
  226. package/build/src/task/input.js +189 -0
  227. package/build/src/task/mutation.d.ts +39 -0
  228. package/build/src/task/mutation.js +85 -0
  229. package/build/src/task/operations.d.ts +4 -19
  230. package/build/src/task/operations.js +64 -18
  231. package/build/src/task/query.d.ts +9 -2
  232. package/build/src/task/query.js +32 -64
  233. package/build/src/task/store.js +0 -2
  234. package/build/src/verification/execution.d.ts +1 -1
  235. package/build/src/verification/execution.js +2 -1
  236. package/build/src/workspace-place.d.ts +1 -4
  237. package/build/src/workspace-place.js +0 -15
  238. package/package.json +5 -3
@@ -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,10 +126,12 @@ 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, dependencies));
129
+ return withInterject(await startAcpSession(launch, input, {
130
+ ...dependencies,
131
+ interpretTool: interpretGrokTool,
132
+ }));
63
133
  };
64
134
  return {
65
- confinement: () => ({ kind: "unconfined" }),
66
135
  admitOptions: optionAdmission,
67
136
  start: async (input) => await drive(input),
68
137
  resume: async (input) => await drive(input),
@@ -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
- const call = callFor(name, toolState.input);
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 ?? callFor(name, toolState.input);
217
+ const call = strongerCall(started?.call, next);
156
218
  if (call === undefined)
157
219
  return;
158
- const observed = started ?? { name, call };
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,33 +1,7 @@
1
- import { type ProviderAdapter, type Session } from "../../provider.js";
2
- import type { ResumeCoordinate } from "../../heart/index.js";
3
- import type { ProviderExecution, ProviderOptions } from "../../provider-recipe.js";
1
+ import { type ProviderAdapter } from "../../provider.js";
2
+ import type { ProviderExecution } from "../../provider-recipe.js";
4
3
  import { type OpencodeSdkLoader } from "./session.js";
5
4
  export type OpencodeProviderTestOptions = Readonly<{
6
5
  loader?: OpencodeSdkLoader;
7
6
  }>;
8
7
  export declare function createOpencodeProvider(input?: ProviderExecution | OpencodeProviderTestOptions): ProviderAdapter;
9
- export declare const opencodeProvider: Readonly<{
10
- confinement(input: Readonly<{
11
- cwd: string;
12
- options: ProviderOptions;
13
- }>): import("../../heart/facts.js").Confinement;
14
- admitOptions(options: ProviderOptions): import("../../provider.js").ProviderOptionAdmission;
15
- fork?(input: Readonly<{
16
- session: ResumeCoordinate;
17
- at: string;
18
- cwd: string;
19
- }>): Promise<Readonly<{
20
- session: ResumeCoordinate;
21
- }>>;
22
- start(input: import("../../provider.js").DriveInput & Readonly<{
23
- session: Readonly<{
24
- kind: "fresh";
25
- }>;
26
- }>): Promise<Session>;
27
- resume?(input: import("../../provider.js").DriveInput & Readonly<{
28
- session: Readonly<{
29
- kind: "resume";
30
- coordinate: ResumeCoordinate;
31
- }>;
32
- }>): Promise<Session>;
33
- }>;
@@ -1,6 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { abortable } from "../../abort.js";
3
- import { AgentEventChannel } from "../../provider.js";
3
+ import { AKUMA_REQUESTS_ENV, AgentEventChannel, } from "../../provider.js";
4
4
  import { createEventState, mapEvent } from "./events.js";
5
5
  import { coordinate, loadOpencode, OPENCODE_SDK_PROVIDER, parseModel } from "./session.js";
6
6
  function object(value) {
@@ -205,7 +205,13 @@ async function drive(execution, input, loader) {
205
205
  const abortSetup = () => abortController.abort(signal.reason);
206
206
  signal.addEventListener("abort", abortSetup, { once: true });
207
207
  signal.throwIfAborted();
208
- const runtime = await abortable(loadOpencode(execution, input.cwd, abortController.signal, loader), abortController.signal, async (late) => await late.close());
208
+ const runtime = await abortable(loadOpencode({
209
+ ...execution,
210
+ env: {
211
+ ...execution.env,
212
+ ...(input.requests === undefined ? {} : { [AKUMA_REQUESTS_ENV]: input.requests.dir }),
213
+ },
214
+ }, input.cwd, abortController.signal, loader), abortController.signal, async (late) => await late.close());
209
215
  let closing;
210
216
  let iterator;
211
217
  const closeOnce = () => {
@@ -263,7 +269,6 @@ export function createOpencodeProvider(input = { name: OPENCODE_SDK_PROVIDER, ki
263
269
  const execution = "kind" in input ? input : { name: OPENCODE_SDK_PROVIDER, kind: "opencode-sdk" };
264
270
  const loader = "loader" in input ? input.loader : undefined;
265
271
  return {
266
- confinement: ({ cwd }) => ({ kind: "declared", writableRoots: [cwd] }),
267
272
  admitOptions(options) {
268
273
  try {
269
274
  admit(options);
@@ -305,4 +310,3 @@ export function createOpencodeProvider(input = { name: OPENCODE_SDK_PROVIDER, ki
305
310
  },
306
311
  };
307
312
  }
308
- export const opencodeProvider = createOpencodeProvider();
@@ -3,7 +3,7 @@ import type { ResumeCoordinate } from "../../heart/index.js";
3
3
  import type { ProviderExecution } from "../../provider-recipe.js";
4
4
  export type OpencodeSdkSession = Pick<OpencodeClient["session"], "create" | "get" | "fork" | "abort" | "promptAsync" | "messages">;
5
5
  export type OpencodeSdkEvent = Pick<OpencodeClient["event"], "subscribe">;
6
- export type OpencodeSdkLoader = (cwd: string) => Promise<Readonly<{
6
+ export type OpencodeSdkLoader = (cwd: string, execution: ProviderExecution) => Promise<Readonly<{
7
7
  client: {
8
8
  session: OpencodeSdkSession;
9
9
  event: OpencodeSdkEvent;
@@ -40,7 +40,7 @@ async function availablePort() {
40
40
  }
41
41
  export async function loadOpencode(execution, cwd, signal, loader) {
42
42
  if (loader) {
43
- const loaded = await loader(cwd);
43
+ const loaded = await loader(cwd, execution);
44
44
  return { client: loaded.client, close: async () => { await loaded.close?.(); } };
45
45
  }
46
46
  const port = await availablePort();
@@ -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 ((name !== "edit" && name !== "write") || typeof value.path !== "string")
86
+ if (name !== "edit" || typeof value.path !== "string")
86
87
  return undefined;
87
- return { kind: "fileChange", changes: [{ op: name === "write" ? "add" : "update", path: value.path }] };
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: started?.call ?? { kind: "other", display: name },
127
+ call: event.isError ? call : refineEditCall(call, event.result),
114
128
  result: { status: event.isError ? "error" : "ok" },
115
129
  }];
116
130
  }
@@ -1,9 +1,9 @@
1
- import { createAgentSession, DefaultResourceLoader, getAgentDir, ModelRuntime, SessionManager, } from "@earendil-works/pi-coding-agent";
1
+ import { createAgentSession, createBashToolDefinition, DefaultResourceLoader, getAgentDir, ModelRuntime, SessionManager, } from "@earendil-works/pi-coding-agent";
2
2
  import { abortable } from "../../abort.js";
3
- import { AgentEventChannel } from "../../provider.js";
3
+ import { AKUMA_REQUESTS_ENV, AgentEventChannel, } from "../../provider.js";
4
4
  import { piTerminalFailure, translatePiEvent } from "./events.js";
5
5
  const PI_THINKING_LEVELS = new Set(["minimal", "low", "medium", "high", "xhigh", "max"]);
6
- const MODEL_PATTERN = /^[^/\s]+\/[^/\s]+$/u;
6
+ const MODEL_PATTERN = /^[^/\s]+\/[^\s]+$/u;
7
7
  function diagnostic(error) { return error instanceof Error ? error.message : String(error); }
8
8
  function admitPiOptions(options) {
9
9
  if (options.network !== undefined)
@@ -48,6 +48,14 @@ async function piCreateOptions(sdk, input) {
48
48
  ...(resourceLoader === undefined ? {} : { resourceLoader }),
49
49
  ...(input.options.effort === undefined ? {} : { thinkingLevel: input.options.effort }),
50
50
  ...(input.options.readonly === undefined ? {} : { tools: ["read", "grep", "find", "ls"] }),
51
+ ...(input.requests === undefined || input.options.readonly === true
52
+ ? {}
53
+ : { customTools: [createBashToolDefinition(input.cwd, {
54
+ spawnHook: (context) => ({
55
+ ...context,
56
+ env: { ...context.env, [AKUMA_REQUESTS_ENV]: input.requests.dir },
57
+ }),
58
+ })] }),
51
59
  };
52
60
  }
53
61
  async function createPiSession(sdk, input, signal) {
@@ -176,7 +184,6 @@ export function createPiProvider(execution = { name: "pi", kind: "pi" }, load =
176
184
  return drivePi(await abortable(load(), signal), input, signal);
177
185
  };
178
186
  return {
179
- confinement: ({ cwd }) => ({ kind: "declared", writableRoots: [cwd] }),
180
187
  admitOptions: admitPiOptions,
181
188
  start: drive,
182
189
  resume: async (input) => {
@@ -0,0 +1,4 @@
1
+ export declare function diffstatFromUnifiedPatch(patch: string): Readonly<{
2
+ added: number;
3
+ removed: number;
4
+ }> | undefined;
@@ -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,5 +1,5 @@
1
1
  import { type AllocatedAkuma } from "./identity.js";
2
- export declare const BIRTH_TIMEOUT_MS = 5000;
2
+ export declare const BIRTH_TIMEOUT_MS = 30000;
3
3
  export declare function publishAkuma(input: Readonly<{
4
4
  worldPath: string;
5
5
  archetype: string;
@@ -2,7 +2,7 @@ import { HeldAkumaLeash, initializeHeart, readHeart, readSeal, readSoul, } from
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_000;
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
  }
@@ -0,0 +1,87 @@
1
+ import { type KillEvidence, type Soul } from "./heart/index.js";
2
+ import { type AkuId, type AkumaPaths } from "./identity.js";
3
+ import { type TaskMutationRequest } from "../task/mutation.js";
4
+ export type RequestChildLaunch = Readonly<{
5
+ paths: AkumaPaths;
6
+ seed: Omit<Soul, "createdAt">;
7
+ initialBody: string;
8
+ }>;
9
+ type UpstreamCall = Readonly<{
10
+ signal: AbortSignal;
11
+ }>;
12
+ type RequesterCall = UpstreamCall & Readonly<{
13
+ requester: AkuId;
14
+ }>;
15
+ type ContractCall = RequesterCall & Readonly<{
16
+ repoRoot: string;
17
+ contractId: string;
18
+ }>;
19
+ export type UpstreamExecutionPort = Readonly<{
20
+ wait(input: UpstreamCall & Readonly<{
21
+ targets: readonly AkuId[];
22
+ completion: "any" | "all";
23
+ timeoutMs?: number;
24
+ }>): Promise<unknown>;
25
+ tell(input: UpstreamCall & Readonly<{
26
+ target: AkuId;
27
+ body: string;
28
+ tellId: string;
29
+ recordedAt: string;
30
+ }>): Promise<unknown>;
31
+ kill(input: Readonly<{
32
+ targets: readonly AkuId[];
33
+ signal: AbortSignal;
34
+ }>): Promise<Readonly<{
35
+ result: unknown;
36
+ service: readonly Readonly<{
37
+ id: AkuId;
38
+ evidence: KillEvidence;
39
+ }>[];
40
+ }>>;
41
+ deliver(input: ContractCall & Readonly<{
42
+ message?: string;
43
+ includeDirty: boolean;
44
+ }>): Promise<Readonly<{
45
+ result: unknown;
46
+ deliveryFactId?: string;
47
+ }>>;
48
+ review(input: ContractCall & Readonly<{
49
+ verdict: "satisfied" | "unsatisfied";
50
+ summary?: string;
51
+ }>): Promise<Readonly<{
52
+ result: unknown;
53
+ reviewFactId?: string;
54
+ }>>;
55
+ task(input: RequesterCall & Readonly<{
56
+ world: string;
57
+ request: TaskMutationRequest;
58
+ }>): Promise<unknown>;
59
+ }>;
60
+ type PumpInput = Readonly<{
61
+ paths: AkumaPaths;
62
+ parent: Soul;
63
+ bodySequence: number;
64
+ now(): string;
65
+ spawn(launch: RequestChildLaunch): Promise<void>;
66
+ upstream?: UpstreamExecutionPort;
67
+ signal: AbortSignal;
68
+ }>;
69
+ export declare class BodyRequestPump {
70
+ private readonly input;
71
+ readonly directory: string;
72
+ readonly failure: Promise<never>;
73
+ private readonly closeSignal;
74
+ private readonly executionSignal;
75
+ private readonly handled;
76
+ private readonly running;
77
+ private readonly cancelBody;
78
+ private admissionClosed;
79
+ private constructor();
80
+ static open(input: PumpInput): Promise<BodyRequestPump>;
81
+ private run;
82
+ close(): Promise<void>;
83
+ stopAdmission(): void;
84
+ }
85
+ export declare function clearBodyRequestTransport(paths: AkumaPaths): Promise<void>;
86
+ export declare function settleBodyRequests(paths: AkumaPaths, parent: Soul, now: () => string, signal?: AbortSignal): Promise<"settled" | "pending">;
87
+ export {};