@astrosheep/keiyaku 4.0.6 → 4.1.1

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 (251) hide show
  1. package/README.md +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -0
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +3 -0
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -6
  5. package/build/src/akuma/akuma.d.ts +17 -14
  6. package/build/src/akuma/akuma.js +122 -114
  7. package/build/src/akuma/allowed.d.ts +1 -0
  8. package/build/src/akuma/allowed.js +6 -0
  9. package/build/src/akuma/archetype.js +12 -2
  10. package/build/src/akuma/body-turn.js +27 -15
  11. package/build/src/akuma/body.d.ts +44 -3
  12. package/build/src/akuma/body.js +142 -33
  13. package/build/src/akuma/coordinate.js +17 -7
  14. package/build/src/akuma/heart/facts.js +1 -1
  15. package/build/src/akuma/heart/index.d.ts +1 -1
  16. package/build/src/akuma/heart/index.js +2 -4
  17. package/build/src/akuma/heart/request-authority.js +4 -4
  18. package/build/src/akuma/heart/request-rows.js +27 -16
  19. package/build/src/akuma/heart/rows.js +79 -41
  20. package/build/src/akuma/heart/soul.js +1 -1
  21. package/build/src/akuma/heart/storage.d.ts +1 -0
  22. package/build/src/akuma/heart/storage.js +76 -11
  23. package/build/src/akuma/heart/tells.js +35 -18
  24. package/build/src/akuma/heart/timeline.js +19 -11
  25. package/build/src/akuma/identity.d.ts +1 -0
  26. package/build/src/akuma/identity.js +1 -0
  27. package/build/src/akuma/index.d.ts +3 -3
  28. package/build/src/akuma/index.js +1 -1
  29. package/build/src/akuma/nuke.js +106 -14
  30. package/build/src/akuma/projection.d.ts +11 -9
  31. package/build/src/akuma/projection.js +110 -53
  32. package/build/src/akuma/provider-recipe.d.ts +2 -0
  33. package/build/src/akuma/provider-recipe.js +21 -5
  34. package/build/src/akuma/provider.js +105 -62
  35. package/build/src/akuma/providers/acp/config.d.ts +2 -0
  36. package/build/src/akuma/providers/acp/config.js +13 -6
  37. package/build/src/akuma/providers/acp/core.d.ts +5 -2
  38. package/build/src/akuma/providers/acp/core.js +45 -25
  39. package/build/src/akuma/providers/acp/events.js +38 -29
  40. package/build/src/akuma/providers/acp/index.js +18 -8
  41. package/build/src/akuma/providers/claude/events.js +8 -12
  42. package/build/src/akuma/providers/claude/index.d.ts +2 -1
  43. package/build/src/akuma/providers/claude/index.js +59 -26
  44. package/build/src/akuma/providers/claude/input.js +6 -2
  45. package/build/src/akuma/providers/codex-app-server/events.js +61 -36
  46. package/build/src/akuma/providers/codex-app-server/index.js +29 -14
  47. package/build/src/akuma/providers/grok-build/index.js +28 -17
  48. package/build/src/akuma/providers/index.js +3 -19
  49. package/build/src/akuma/providers/opencode-sdk/events.js +32 -18
  50. package/build/src/akuma/providers/opencode-sdk/index.js +29 -17
  51. package/build/src/akuma/providers/opencode-sdk/session.js +21 -5
  52. package/build/src/akuma/providers/pi/events.js +26 -19
  53. package/build/src/akuma/providers/pi/index.js +58 -38
  54. package/build/src/akuma/publication.js +9 -9
  55. package/build/src/akuma/request-serve.js +37 -40
  56. package/build/src/akuma/request-wire.d.ts +2 -2
  57. package/build/src/akuma/request-wire.js +75 -102
  58. package/build/src/akuma/requests.js +2 -2
  59. package/build/src/akuma-body.js +6 -5
  60. package/build/src/body/amend.d.ts +4 -1
  61. package/build/src/body/amend.js +14 -15
  62. package/build/src/body/decode.js +2 -4
  63. package/build/src/body/envelope.js +2 -4
  64. package/build/src/body/region.d.ts +1 -2
  65. package/build/src/body/region.js +4 -72
  66. package/build/src/body/render.js +17 -12
  67. package/build/src/body/shape.js +1 -7
  68. package/build/src/cli/accepted.d.ts +1 -1
  69. package/build/src/cli/accepted.js +10 -1
  70. package/build/src/cli/commands/akuma-invoke.js +18 -6
  71. package/build/src/cli/commands/akuma.js +10 -13
  72. package/build/src/cli/commands/amend.d.ts +2 -2
  73. package/build/src/cli/commands/amend.js +2 -4
  74. package/build/src/cli/commands/bind.d.ts +4 -4
  75. package/build/src/cli/commands/bind.js +16 -6
  76. package/build/src/cli/commands/contract.d.ts +99 -10
  77. package/build/src/cli/commands/contract.js +128 -24
  78. package/build/src/cli/commands/install.d.ts +1 -1
  79. package/build/src/cli/commands/install.js +23 -15
  80. package/build/src/cli/commands/task-invoke.d.ts +4 -1
  81. package/build/src/cli/commands/task-invoke.js +191 -68
  82. package/build/src/cli/commands/task-query.js +48 -24
  83. package/build/src/cli/commands/task.js +150 -30
  84. package/build/src/cli/coordinates.js +2 -4
  85. package/build/src/cli/invoke.js +88 -44
  86. package/build/src/cli/main.js +4 -2
  87. package/build/src/cli/parse.d.ts +2 -89
  88. package/build/src/cli/parse.js +87 -79
  89. package/build/src/cli/render/akuma-tool-command.js +6 -7
  90. package/build/src/cli/render/akuma-tool.js +10 -8
  91. package/build/src/cli/render/akuma.js +149 -53
  92. package/build/src/cli/render/audit.js +5 -15
  93. package/build/src/cli/render/board.d.ts +1 -0
  94. package/build/src/cli/render/board.js +17 -0
  95. package/build/src/cli/render/catalog.js +84 -7
  96. package/build/src/cli/render/contract-observation.d.ts +10 -0
  97. package/build/src/cli/render/contract-observation.js +58 -0
  98. package/build/src/cli/render/contract.js +57 -54
  99. package/build/src/cli/render/kanshi.js +281 -209
  100. package/build/src/cli/render/receipt.d.ts +1 -0
  101. package/build/src/cli/render/receipt.js +20 -23
  102. package/build/src/cli/render/refusal.js +16 -15
  103. package/build/src/cli/render/region.js +22 -6
  104. package/build/src/cli/render/settings.js +4 -4
  105. package/build/src/cli/render/task.js +93 -21
  106. package/build/src/cli/render/terminal.js +16 -5
  107. package/build/src/cli/result.d.ts +11 -4
  108. package/build/src/cli/runtime.d.ts +6 -1
  109. package/build/src/cli/runtime.js +84 -63
  110. package/build/src/cli/selectors.js +2 -4
  111. package/build/src/cli/usage.js +6 -5
  112. package/build/src/contract-worktree.d.ts +1 -25
  113. package/build/src/contract-worktree.js +87 -174
  114. package/build/src/coordination/durable-file.js +7 -3
  115. package/build/src/coordination/sqlite-transaction-lock.js +29 -12
  116. package/build/src/core/facts/codec.js +7 -3
  117. package/build/src/core/facts/types.d.ts +1 -1
  118. package/build/src/core/subject.js +16 -9
  119. package/build/src/core/verbs/abandon.d.ts +1 -1
  120. package/build/src/core/verbs/abandon.js +1 -1
  121. package/build/src/core/verbs/amend.d.ts +1 -1
  122. package/build/src/core/verbs/amend.js +7 -7
  123. package/build/src/core/verbs/attestation.js +4 -1
  124. package/build/src/core/verbs/bind.d.ts +1 -1
  125. package/build/src/core/verbs/bind.js +1 -1
  126. package/build/src/core/verbs/placement.d.ts +1 -1
  127. package/build/src/core/verbs/placement.js +10 -8
  128. package/build/src/dispatch/index.js +8 -6
  129. package/build/src/duration.js +5 -1
  130. package/build/src/git/admission.js +5 -3
  131. package/build/src/git/hooks.d.ts +8 -0
  132. package/build/src/git/hooks.js +63 -14
  133. package/build/src/git/identity.js +1 -4
  134. package/build/src/git/integration.d.ts +2 -3
  135. package/build/src/git/integration.js +32 -39
  136. package/build/src/git/nuke.d.ts +1 -1
  137. package/build/src/git/nuke.js +110 -62
  138. package/build/src/git/observe.d.ts +13 -1
  139. package/build/src/git/observe.js +51 -44
  140. package/build/src/git/process.js +4 -2
  141. package/build/src/git/read-observation.js +10 -8
  142. package/build/src/git/reconcile.d.ts +14 -3
  143. package/build/src/git/reconcile.js +123 -102
  144. package/build/src/git/repository.d.ts +2 -0
  145. package/build/src/git/repository.js +13 -22
  146. package/build/src/git/target-placement.d.ts +9 -10
  147. package/build/src/git/target-placement.js +59 -62
  148. package/build/src/git/tender.d.ts +13 -2
  149. package/build/src/git/tender.js +28 -22
  150. package/build/src/git/terminal-seal.js +15 -12
  151. package/build/src/git/tree.js +5 -2
  152. package/build/src/git/workspace.d.ts +24 -2
  153. package/build/src/git/workspace.js +120 -16
  154. package/build/src/identity/coordinates.js +3 -1
  155. package/build/src/identity/selector.js +6 -3
  156. package/build/src/kanshi/fleet.d.ts +6 -0
  157. package/build/src/kanshi/fleet.js +27 -0
  158. package/build/src/kanshi/index.d.ts +1 -1
  159. package/build/src/kanshi/read.js +77 -45
  160. package/build/src/kanshi/report.d.ts +13 -24
  161. package/build/src/kanshi/select.js +25 -24
  162. package/build/src/library/address.d.ts +2 -1
  163. package/build/src/library/address.js +7 -8
  164. package/build/src/library/akuma-creation.js +20 -12
  165. package/build/src/library/audit.d.ts +0 -1
  166. package/build/src/library/audit.js +1 -2
  167. package/build/src/library/bind.d.ts +53 -5
  168. package/build/src/library/bind.js +98 -22
  169. package/build/src/library/catalog.d.ts +1 -0
  170. package/build/src/library/catalog.js +6 -3
  171. package/build/src/library/configuration.js +3 -1
  172. package/build/src/library/continuation.d.ts +37 -0
  173. package/build/src/library/continuation.js +86 -0
  174. package/build/src/library/contract.d.ts +39 -45
  175. package/build/src/library/contract.js +141 -118
  176. package/build/src/library/delivery.d.ts +18 -13
  177. package/build/src/library/fleet.d.ts +1 -1
  178. package/build/src/library/fleet.js +19 -11
  179. package/build/src/library/input.d.ts +2 -0
  180. package/build/src/library/input.js +14 -0
  181. package/build/src/library/keiyaku.d.ts +8 -7
  182. package/build/src/library/keiyaku.js +3 -3
  183. package/build/src/library/mutation.js +11 -4
  184. package/build/src/library/nuke.js +14 -5
  185. package/build/src/library/reconcile.d.ts +9 -4
  186. package/build/src/library/reconcile.js +30 -24
  187. package/build/src/library/refusal.d.ts +13 -5
  188. package/build/src/library/refusal.js +7 -0
  189. package/build/src/library/region.d.ts +8 -7
  190. package/build/src/library/region.js +31 -11
  191. package/build/src/library/repo.js +2 -2
  192. package/build/src/markdown/lex.js +9 -2
  193. package/build/src/markdown/parse.js +11 -7
  194. package/build/src/markdown/query.js +4 -2
  195. package/build/src/protocol/amend.js +3 -1
  196. package/build/src/protocol/attempt.d.ts +7 -3
  197. package/build/src/protocol/attempt.js +9 -5
  198. package/build/src/protocol/audit.d.ts +1 -1
  199. package/build/src/protocol/audit.js +4 -14
  200. package/build/src/protocol/bind.d.ts +19 -6
  201. package/build/src/protocol/bind.js +28 -13
  202. package/build/src/protocol/completion.d.ts +0 -1
  203. package/build/src/protocol/completion.js +1 -3
  204. package/build/src/protocol/deliver.d.ts +12 -4
  205. package/build/src/protocol/deliver.js +60 -51
  206. package/build/src/protocol/intent.d.ts +1 -0
  207. package/build/src/protocol/intent.js +9 -7
  208. package/build/src/protocol/operations.d.ts +10 -9
  209. package/build/src/protocol/operations.js +5 -3
  210. package/build/src/protocol/placement.d.ts +0 -1
  211. package/build/src/protocol/placement.js +6 -6
  212. package/build/src/protocol/read/observation.d.ts +11 -0
  213. package/build/src/protocol/read/observation.js +37 -0
  214. package/build/src/protocol/read/status.d.ts +23 -12
  215. package/build/src/protocol/read/status.js +90 -72
  216. package/build/src/protocol/reconcile.d.ts +1 -0
  217. package/build/src/protocol/reconcile.js +2 -3
  218. package/build/src/protocol/reintegrate.js +1 -1
  219. package/build/src/protocol/review.d.ts +0 -1
  220. package/build/src/protocol/review.js +15 -22
  221. package/build/src/protocol/run.d.ts +1 -0
  222. package/build/src/protocol/run.js +4 -5
  223. package/build/src/runtime/proc/launch.d.ts +33 -0
  224. package/build/src/runtime/proc/launch.js +98 -0
  225. package/build/src/runtime/proc/line-rpc.js +9 -3
  226. package/build/src/runtime/proc/run.d.ts +12 -6
  227. package/build/src/runtime/proc/run.js +78 -21
  228. package/build/src/runtime/proc/stdio.js +7 -10
  229. package/build/src/settings.js +6 -2
  230. package/build/src/settlement/fence.d.ts +0 -2
  231. package/build/src/settlement/fence.js +0 -24
  232. package/build/src/settlement/holder.js +13 -10
  233. package/build/src/settlement/settle.js +39 -6
  234. package/build/src/task/board.d.ts +21 -2
  235. package/build/src/task/board.js +35 -16
  236. package/build/src/task/compose.js +85 -22
  237. package/build/src/task/context.js +21 -8
  238. package/build/src/task/document.js +46 -10
  239. package/build/src/task/identity.js +19 -6
  240. package/build/src/task/index.js +118 -27
  241. package/build/src/task/input.js +29 -7
  242. package/build/src/task/mutation.js +61 -19
  243. package/build/src/task/operations.d.ts +8 -2
  244. package/build/src/task/operations.js +97 -32
  245. package/build/src/task/query.js +57 -28
  246. package/build/src/task/store.d.ts +5 -1
  247. package/build/src/task/store.js +88 -95
  248. package/build/src/verification/execution.js +14 -11
  249. package/build/src/workspace-place.js +19 -7
  250. package/build/src/world.js +16 -6
  251. package/package.json +8 -3
@@ -87,9 +87,9 @@ function decodeDiffstat(value) {
87
87
  }
88
88
  function decodeFileChangeMember(value) {
89
89
  const change = object(value);
90
- if (change === null || (change.op !== "add" && change.op !== "update"
91
- && change.op !== "delete" && change.op !== "unspecified")
92
- || typeof change.path !== "string")
90
+ if (change === null ||
91
+ (change.op !== "add" && change.op !== "update" && change.op !== "delete" && change.op !== "unspecified") ||
92
+ typeof change.path !== "string")
93
93
  return null;
94
94
  const diffstat = decodeDiffstat(change.diffstat);
95
95
  if (diffstat === null)
@@ -114,12 +114,18 @@ function decodeToolCall(value) {
114
114
  if (call === null)
115
115
  return null;
116
116
  switch (call.kind) {
117
- case "run": return decodeRunCall(call);
118
- case "read": return decodeReadCall(call);
119
- case "search": return decodeSearchCall(call);
120
- case "fileChange": return decodeFileChangeCall(call);
121
- case "other": return decodeOtherCall(call);
122
- default: return null;
117
+ case "run":
118
+ return decodeRunCall(call);
119
+ case "read":
120
+ return decodeReadCall(call);
121
+ case "search":
122
+ return decodeSearchCall(call);
123
+ case "fileChange":
124
+ return decodeFileChangeCall(call);
125
+ case "other":
126
+ return decodeOtherCall(call);
127
+ default:
128
+ return null;
123
129
  }
124
130
  }
125
131
  function decodeToolResult(value) {
@@ -143,13 +149,26 @@ function decodeToolEvent(event) {
143
149
  return null;
144
150
  const call = decodeToolCall(event.call);
145
151
  if (call !== null && event.phase === "started" && event.result === undefined) {
146
- return { type: "tool", phase: "started", id: event.id, name: event.name, call,
147
- ...(event.truncated === true ? { truncated: true } : {}) };
152
+ return {
153
+ type: "tool",
154
+ phase: "started",
155
+ id: event.id,
156
+ name: event.name,
157
+ call,
158
+ ...(event.truncated === true ? { truncated: true } : {}),
159
+ };
148
160
  }
149
161
  const result = decodeToolResult(event.result);
150
162
  if (call !== null && event.phase === "completed" && result !== null) {
151
- return { type: "tool", phase: "completed", id: event.id, name: event.name, call, result,
152
- ...(event.truncated === true ? { truncated: true } : {}) };
163
+ return {
164
+ type: "tool",
165
+ phase: "completed",
166
+ id: event.id,
167
+ name: event.name,
168
+ call,
169
+ result,
170
+ ...(event.truncated === true ? { truncated: true } : {}),
171
+ };
153
172
  }
154
173
  return null;
155
174
  }
@@ -159,15 +178,20 @@ function decodeTypedEvent(type, event) {
159
178
  const truncated = event.truncated === true ? { truncated: true } : {};
160
179
  switch (type) {
161
180
  case "assistant":
162
- case "thought": return typeof event.text === "string" ? { type, text: event.text, ...truncated } : null;
163
- case "note": return typeof event.text === "string" ? { type, text: event.text, ...truncated } : null;
164
- case "unknown": return typeof event.kind === "string" ? { type, kind: event.kind, ...truncated } : null;
181
+ case "thought":
182
+ return typeof event.text === "string" ? { type, text: event.text, ...truncated } : null;
183
+ case "note":
184
+ return typeof event.text === "string" ? { type, text: event.text, ...truncated } : null;
185
+ case "unknown":
186
+ return typeof event.kind === "string" ? { type, kind: event.kind, ...truncated } : null;
165
187
  case "session": {
166
188
  const coordinate = decodeResumeCoordinate(event.coordinate);
167
189
  return coordinate === null ? null : { type, coordinate };
168
190
  }
169
- case "tool": return decodeToolEvent(event);
170
- default: return type;
191
+ case "tool":
192
+ return decodeToolEvent(event);
193
+ default:
194
+ return type;
171
195
  }
172
196
  }
173
197
  export function decodeAgentEvent(value) {
@@ -181,37 +205,49 @@ export function decodeAgentEvent(value) {
181
205
  }
182
206
  function boundedToolCall(call) {
183
207
  switch (call.kind) {
184
- case "run": return { value: { kind: call.kind, command: boundedEventText(call.command) }, truncated: call.command.length > AGENT_EVENT_TEXT_LIMIT };
185
- case "read": return {
186
- value: {
187
- kind: call.kind,
188
- path: boundedEventText(call.path),
189
- ...(call.offset === undefined ? {} : { offset: call.offset }),
190
- ...(call.limit === undefined ? {} : { limit: call.limit }),
191
- },
192
- truncated: call.path.length > AGENT_EVENT_TEXT_LIMIT,
193
- };
194
- case "search": return {
195
- value: {
196
- kind: call.kind,
197
- query: boundedEventText(call.query),
198
- ...(call.scope === undefined ? {} : { scope: call.scope }),
199
- ...(call.path === undefined ? {} : { path: boundedEventText(call.path) }),
200
- ...(call.glob === undefined ? {} : { glob: boundedEventText(call.glob) }),
201
- },
202
- truncated: call.query.length > AGENT_EVENT_TEXT_LIMIT
203
- || (call.path !== undefined && call.path.length > AGENT_EVENT_TEXT_LIMIT)
204
- || (call.glob !== undefined && call.glob.length > AGENT_EVENT_TEXT_LIMIT),
205
- };
206
- case "fileChange": return {
207
- value: {
208
- kind: call.kind,
209
- changes: call.changes.map((change) => ({ ...change, path: boundedEventText(change.path) })),
210
- },
211
- truncated: call.changes.some((change) => change.path.length > AGENT_EVENT_TEXT_LIMIT),
212
- };
213
- case "other": return { value: { kind: call.kind, display: boundedEventText(call.display) }, truncated: call.display.length > AGENT_EVENT_TEXT_LIMIT };
214
- default: return call;
208
+ case "run":
209
+ return {
210
+ value: { kind: call.kind, command: boundedEventText(call.command) },
211
+ truncated: call.command.length > AGENT_EVENT_TEXT_LIMIT,
212
+ };
213
+ case "read":
214
+ return {
215
+ value: {
216
+ kind: call.kind,
217
+ path: boundedEventText(call.path),
218
+ ...(call.offset === undefined ? {} : { offset: call.offset }),
219
+ ...(call.limit === undefined ? {} : { limit: call.limit }),
220
+ },
221
+ truncated: call.path.length > AGENT_EVENT_TEXT_LIMIT,
222
+ };
223
+ case "search":
224
+ return {
225
+ value: {
226
+ kind: call.kind,
227
+ query: boundedEventText(call.query),
228
+ ...(call.scope === undefined ? {} : { scope: call.scope }),
229
+ ...(call.path === undefined ? {} : { path: boundedEventText(call.path) }),
230
+ ...(call.glob === undefined ? {} : { glob: boundedEventText(call.glob) }),
231
+ },
232
+ truncated: call.query.length > AGENT_EVENT_TEXT_LIMIT ||
233
+ (call.path !== undefined && call.path.length > AGENT_EVENT_TEXT_LIMIT) ||
234
+ (call.glob !== undefined && call.glob.length > AGENT_EVENT_TEXT_LIMIT),
235
+ };
236
+ case "fileChange":
237
+ return {
238
+ value: {
239
+ kind: call.kind,
240
+ changes: call.changes.map((change) => ({ ...change, path: boundedEventText(change.path) })),
241
+ },
242
+ truncated: call.changes.some((change) => change.path.length > AGENT_EVENT_TEXT_LIMIT),
243
+ };
244
+ case "other":
245
+ return {
246
+ value: { kind: call.kind, display: boundedEventText(call.display) },
247
+ truncated: call.display.length > AGENT_EVENT_TEXT_LIMIT,
248
+ };
249
+ default:
250
+ return call;
215
251
  }
216
252
  }
217
253
  function boundedToolResult(result) {
@@ -230,22 +266,28 @@ export function encodeAgentEvent(event) {
230
266
  ...(changed || ("truncated" in event && event.truncated === true) ? { truncated: true } : {}),
231
267
  });
232
268
  switch (event.type) {
233
- case "session": return { type: event.type, coordinate: encodeResumeCoordinate(event.coordinate) };
234
- case "assistant": return marked({ type: event.type, text: boundedEventText(event.text) }, event.text.length > AGENT_EVENT_TEXT_LIMIT);
235
- case "thought": return marked({ type: event.type, text: boundedThoughtText(event.text) }, event.text.length > AGENT_THOUGHT_TEXT_LIMIT);
236
- case "note": return marked({ type: event.type, text: boundedEventText(event.text) }, event.text.length > AGENT_EVENT_TEXT_LIMIT);
237
- case "unknown": return marked({ type: event.type, kind: boundedEventText(event.kind) }, event.kind.length > AGENT_EVENT_TEXT_LIMIT);
269
+ case "session":
270
+ return { type: event.type, coordinate: encodeResumeCoordinate(event.coordinate) };
271
+ case "assistant":
272
+ return marked({ type: event.type, text: boundedEventText(event.text) }, event.text.length > AGENT_EVENT_TEXT_LIMIT);
273
+ case "thought":
274
+ return marked({ type: event.type, text: boundedThoughtText(event.text) }, event.text.length > AGENT_THOUGHT_TEXT_LIMIT);
275
+ case "note":
276
+ return marked({ type: event.type, text: boundedEventText(event.text) }, event.text.length > AGENT_EVENT_TEXT_LIMIT);
277
+ case "unknown":
278
+ return marked({ type: event.type, kind: boundedEventText(event.kind) }, event.kind.length > AGENT_EVENT_TEXT_LIMIT);
238
279
  case "tool": {
239
280
  const call = boundedToolCall(event.call);
240
281
  const name = boundedEventText(event.name);
241
282
  const result = event.phase === "completed" ? boundedToolResult(event.result) : undefined;
242
- return marked(event.phase === "started" ? {
243
- type: event.type,
244
- id: event.id,
245
- phase: event.phase,
246
- name,
247
- call: call.value,
248
- }
283
+ return marked(event.phase === "started"
284
+ ? {
285
+ type: event.type,
286
+ id: event.id,
287
+ phase: event.phase,
288
+ name,
289
+ call: call.value,
290
+ }
249
291
  : {
250
292
  type: event.type,
251
293
  id: event.id,
@@ -255,7 +297,8 @@ export function encodeAgentEvent(event) {
255
297
  result: result.value,
256
298
  }, name !== event.name || call.truncated || result?.truncated === true);
257
299
  }
258
- default: return event;
300
+ default:
301
+ return event;
259
302
  }
260
303
  }
261
304
  export function boundedEventText(value) {
@@ -1,8 +1,10 @@
1
+ import type { SystemPromptMode } from "../../provider-recipe.js";
1
2
  export type AcpExecutionConfig = Readonly<{
2
3
  argvBefore: readonly string[];
3
4
  argvAfter: readonly string[];
4
5
  modelArg?: string;
5
6
  effortArg?: string;
6
7
  systemPromptArg?: string;
8
+ systemPromptMode?: SystemPromptMode;
7
9
  }>;
8
10
  export declare function decodeAcpConfig(value: unknown): AcpExecutionConfig;
@@ -12,26 +12,33 @@ export function decodeAcpConfig(value) {
12
12
  throw new TypeError("ACP provider config must be an object");
13
13
  }
14
14
  const config = value;
15
- const unknown = Object.keys(config)
16
- .find((key) => !["argvBefore", "argvAfter", "effortArg", "modelArg", "systemPromptArg"].includes(key));
15
+ const unknown = Object.keys(config).find((key) => !["argvBefore", "argvAfter", "effortArg", "modelArg", "systemPromptArg", "systemPromptMode"].includes(key));
17
16
  if (unknown !== undefined)
18
17
  throw new TypeError(`ACP provider config has unknown field ${unknown}`);
19
- if (!Array.isArray(config.argvBefore)
20
- || config.argvBefore.some((arg) => typeof arg !== "string" || arg.trim().length === 0)) {
18
+ if (!Array.isArray(config.argvBefore) ||
19
+ config.argvBefore.some((arg) => typeof arg !== "string" || arg.trim().length === 0)) {
21
20
  throw new TypeError("ACP provider config argvBefore must be an array of nonblank strings");
22
21
  }
23
- if (!Array.isArray(config.argvAfter)
24
- || config.argvAfter.some((arg) => typeof arg !== "string" || arg.trim().length === 0)) {
22
+ if (!Array.isArray(config.argvAfter) ||
23
+ config.argvAfter.some((arg) => typeof arg !== "string" || arg.trim().length === 0)) {
25
24
  throw new TypeError("ACP provider config argvAfter must be an array of nonblank strings");
26
25
  }
27
26
  const modelArg = argumentName(config, "modelArg");
28
27
  const effortArg = argumentName(config, "effortArg");
29
28
  const systemPromptArg = argumentName(config, "systemPromptArg");
29
+ const systemPromptMode = config.systemPromptMode;
30
+ if (systemPromptMode !== undefined && systemPromptMode !== "append" && systemPromptMode !== "replace") {
31
+ throw new TypeError("ACP provider config systemPromptMode must be append, replace");
32
+ }
33
+ if (systemPromptMode !== undefined && systemPromptArg === undefined) {
34
+ throw new TypeError("ACP provider config systemPromptMode requires systemPromptArg");
35
+ }
30
36
  return Object.freeze({
31
37
  argvBefore: Object.freeze([...config.argvBefore]),
32
38
  argvAfter: Object.freeze([...config.argvAfter]),
33
39
  ...(modelArg === undefined ? {} : { modelArg }),
34
40
  ...(effortArg === undefined ? {} : { effortArg }),
35
41
  ...(systemPromptArg === undefined ? {} : { systemPromptArg }),
42
+ ...(systemPromptMode === undefined ? {} : { systemPromptMode }),
36
43
  });
37
44
  }
@@ -1,16 +1,19 @@
1
- import * as acp from "@agentclientprotocol/sdk";
1
+ import type * as AcpSdk from "@agentclientprotocol/sdk";
2
2
  import { spawnStdioProcess } from "../../../runtime/proc/stdio.js";
3
3
  import { type ProviderAdapter, type Session } from "../../provider.js";
4
4
  import { type AcpToolInterpreter, type AcpToolUpdate } from "./events.js";
5
5
  export type { AcpToolInterpreter, AcpToolUpdate };
6
6
  export type AcpStartInput = Parameters<ProviderAdapter["start"]>[0] | Parameters<NonNullable<ProviderAdapter["resume"]>>[0];
7
+ export type AcpSessionMeta = Readonly<Record<string, unknown>>;
7
8
  export type AcpDependencies = Readonly<{
8
9
  spawnProcess?: typeof spawnStdioProcess;
9
10
  interpretTool?: AcpToolInterpreter;
11
+ freshSessionMeta?: AcpSessionMeta;
12
+ loadSessionMeta?: AcpSessionMeta;
10
13
  }>;
11
14
  export type AcpLiveSession = Readonly<{
12
15
  session: Session;
13
- agent: acp.ClientContext;
16
+ agent: AcpSdk.ClientContext;
14
17
  sessionId: string;
15
18
  open(): boolean;
16
19
  }>;
@@ -1,10 +1,9 @@
1
- import * as acp from "@agentclientprotocol/sdk";
2
1
  import { Readable, Writable } from "node:stream";
3
2
  import { spawnStdioProcess } from "../../../runtime/proc/stdio.js";
4
3
  import { abortable } from "../../abort.js";
5
4
  import { AKUMA_REQUESTS_ENV, AgentEventChannel, } from "../../provider.js";
6
5
  import { EMPTY_ACP_EVENT_STATE, flushAcpEvents, mapAcpUpdate, } from "./events.js";
7
- function diagnostic(error) {
6
+ function diagnostic(acp, error) {
8
7
  if (!(error instanceof Error))
9
8
  return String(error);
10
9
  if (!(error instanceof acp.RequestError) || error.data === undefined)
@@ -18,18 +17,23 @@ function diagnostic(error) {
18
17
  }
19
18
  return data.length === 0 ? `${error.message} [${error.code}]` : `${error.message} [${error.code}]: ${data}`;
20
19
  }
21
- function createAcpClient(onUpdate) {
22
- return acp.client({ name: "keiyaku" })
20
+ function createAcpClient(acp, onUpdate) {
21
+ return acp
22
+ .client({ name: "keiyaku" })
23
23
  .onNotification(acp.methods.client.session.update, ({ params }) => onUpdate(params));
24
24
  }
25
25
  function promptResult(response) {
26
- if (response.stopReason === "end_turn" || response.stopReason === "max_tokens"
27
- || response.stopReason === "max_turn_requests") {
26
+ if (response.stopReason === "end_turn" ||
27
+ response.stopReason === "max_tokens" ||
28
+ response.stopReason === "max_turn_requests") {
28
29
  return { kind: "answered", answer: "" };
29
30
  }
30
31
  return { kind: "failed", diagnostic: `ACP prompt ended ${response.stopReason}` };
31
32
  }
32
- async function establishSession(agent, input) {
33
+ function requestMeta(meta) {
34
+ return meta === undefined || Object.keys(meta).length === 0 ? {} : { _meta: meta };
35
+ }
36
+ async function establishSession(acp, agent, input, dependencies) {
33
37
  const initialized = await agent.request(acp.methods.agent.initialize, {
34
38
  protocolVersion: acp.PROTOCOL_VERSION,
35
39
  clientInfo: { name: "keiyaku", version: "4" },
@@ -38,20 +42,31 @@ async function establishSession(agent, input) {
38
42
  throw new Error("ACP agent does not advertise session/load");
39
43
  }
40
44
  if (input.session.kind === "fresh") {
41
- return (await agent.request(acp.methods.agent.session.new, { cwd: input.cwd, mcpServers: [] })).sessionId;
45
+ return (await agent.request(acp.methods.agent.session.new, {
46
+ cwd: input.cwd,
47
+ mcpServers: [],
48
+ ...requestMeta(dependencies.freshSessionMeta),
49
+ })).sessionId;
42
50
  }
43
51
  const sessionId = input.session.coordinate.sessionId;
44
52
  if (sessionId === undefined)
45
53
  throw new Error("ACP resume coordinate has no session id");
46
- await agent.request(acp.methods.agent.session.load, { cwd: input.cwd, mcpServers: [], sessionId });
54
+ await agent.request(acp.methods.agent.session.load, {
55
+ cwd: input.cwd,
56
+ mcpServers: [],
57
+ sessionId,
58
+ ...requestMeta(dependencies.loadSessionMeta),
59
+ });
47
60
  return sessionId;
48
61
  }
49
- function createAcpTurn(connection, interpret) {
62
+ function createAcpTurn(acp, connection, interpret) {
50
63
  const events = new AgentEventChannel();
51
64
  let state = EMPTY_ACP_EVENT_STATE;
52
65
  let terminal = false;
53
66
  let resolveCompletion;
54
- const completion = new Promise((resolve) => { resolveCompletion = resolve; });
67
+ const completion = new Promise((resolve) => {
68
+ resolveCompletion = resolve;
69
+ });
55
70
  const update = (next) => {
56
71
  if (terminal)
57
72
  return;
@@ -66,7 +81,7 @@ function createAcpTurn(connection, interpret) {
66
81
  terminal = true;
67
82
  let completionResult = result;
68
83
  const failCleanup = (error) => {
69
- completionResult = { kind: "failed", diagnostic: `ACP cleanup failed: ${diagnostic(error)}` };
84
+ completionResult = { kind: "failed", diagnostic: `ACP cleanup failed: ${diagnostic(acp, error)}` };
70
85
  };
71
86
  try {
72
87
  await cleanup();
@@ -84,9 +99,7 @@ function createAcpTurn(connection, interpret) {
84
99
  for (const event of flushed.events)
85
100
  events.emit(event);
86
101
  events.end();
87
- resolveCompletion(completionResult.kind === "answered"
88
- ? { ...completionResult, answer: flushed.state.answer }
89
- : completionResult);
102
+ resolveCompletion(completionResult.kind === "answered" ? { ...completionResult, answer: flushed.state.answer } : completionResult);
90
103
  };
91
104
  return {
92
105
  events,
@@ -96,11 +109,17 @@ function createAcpTurn(connection, interpret) {
96
109
  open: () => !terminal,
97
110
  };
98
111
  }
99
- function beginAcpPrompt(agent, child, turn, sessionId, input) {
100
- void agent.request(acp.methods.agent.session.prompt, {
112
+ function beginAcpPrompt(context, child, turn, sessionId, input) {
113
+ const { acp, agent } = context;
114
+ void agent
115
+ .request(acp.methods.agent.session.prompt, {
101
116
  sessionId,
102
- prompt: [{ type: "text", text: input.body }, ...input.launchTells.map(({ text }) => ({ type: "text", text }))],
103
- }).then((response) => turn.finish(promptResult(response), () => child.endInputAndDrain()), (error) => turn.finish({ kind: "failed", diagnostic: diagnostic(error) }, () => child.endInputAndDrain()));
117
+ prompt: [
118
+ { type: "text", text: input.body },
119
+ ...input.launchTells.map(({ text }) => ({ type: "text", text })),
120
+ ],
121
+ })
122
+ .then((response) => turn.finish(promptResult(response), () => child.endInputAndDrain()), (error) => turn.finish({ kind: "failed", diagnostic: diagnostic(acp, error) }, () => child.endInputAndDrain()));
104
123
  void child.exited.then((exit) => turn.finish({
105
124
  kind: "failed",
106
125
  diagnostic: exit.stderr || `ACP process exited${exit.code === null ? "" : ` with code ${exit.code}`}`,
@@ -115,7 +134,7 @@ function beginAcpPrompt(agent, child, turn, sessionId, input) {
115
134
  await agent.notify(acp.methods.agent.session.cancel, { sessionId });
116
135
  }
117
136
  catch (error) {
118
- result = { kind: "failed", diagnostic: diagnostic(error) };
137
+ result = { kind: "failed", diagnostic: diagnostic(acp, error) };
119
138
  }
120
139
  if (!turn.open())
121
140
  await child.close(true);
@@ -131,6 +150,7 @@ function beginAcpPrompt(agent, child, turn, sessionId, input) {
131
150
  };
132
151
  }
133
152
  export async function startAcpSession(launch, input, dependencies = {}) {
153
+ const acp = await import("@agentclientprotocol/sdk");
134
154
  const signal = input.signal ?? new AbortController().signal;
135
155
  signal.throwIfAborted();
136
156
  const child = (dependencies.spawnProcess ?? spawnStdioProcess)({
@@ -144,15 +164,15 @@ export async function startAcpSession(launch, input, dependencies = {}) {
144
164
  });
145
165
  let sessionId;
146
166
  let turn;
147
- const connection = createAcpClient((notification) => {
167
+ const connection = createAcpClient(acp, (notification) => {
148
168
  if (notification.sessionId === sessionId)
149
169
  turn.update(notification.update);
150
170
  }).connect(acp.ndJsonStream(Writable.toWeb(child.input), Readable.toWeb(child.output)));
151
- turn = createAcpTurn(connection, dependencies.interpretTool);
171
+ turn = createAcpTurn(acp, connection, dependencies.interpretTool);
152
172
  try {
153
- sessionId = await abortable(establishSession(connection.agent, input), signal);
173
+ sessionId = await abortable(establishSession(acp, connection.agent, input, dependencies), signal);
154
174
  turn.events.emit({ type: "session", coordinate: { sessionId } });
155
- const session = beginAcpPrompt(connection.agent, child, turn, sessionId, input);
175
+ const session = beginAcpPrompt({ acp, agent: connection.agent }, child, turn, sessionId, input);
156
176
  return { session, agent: connection.agent, sessionId, open: turn.open };
157
177
  }
158
178
  catch (error) {
@@ -161,7 +181,7 @@ export async function startAcpSession(launch, input, dependencies = {}) {
161
181
  await child.close(true);
162
182
  }
163
183
  catch (cleanup) {
164
- throw new Error(`${diagnostic(error)}; ACP cleanup failed: ${diagnostic(cleanup)}`, { cause: error });
184
+ throw new Error(`${diagnostic(acp, error)}; ACP cleanup failed: ${diagnostic(acp, cleanup)}`, { cause: error });
165
185
  }
166
186
  turn.events.end();
167
187
  throw error;
@@ -13,9 +13,7 @@ export function flushAcpEvents(state, boundary = []) {
13
13
  };
14
14
  }
15
15
  function appendBlock(state, type, text, messageId) {
16
- const newAssistantMessage = type === "assistant"
17
- && messageId !== undefined
18
- && state.assistantMessageId !== messageId;
16
+ const newAssistantMessage = type === "assistant" && messageId !== undefined && state.assistantMessageId !== messageId;
19
17
  const flushed = state.open === null || (state.open.type === type && !newAssistantMessage)
20
18
  ? { events: [], state }
21
19
  : flushAcpEvents(state);
@@ -23,12 +21,8 @@ function appendBlock(state, type, text, messageId) {
23
21
  events: flushed.events,
24
22
  state: {
25
23
  ...flushed.state,
26
- answer: type === "assistant"
27
- ? `${newAssistantMessage ? "" : flushed.state.answer}${text}`
28
- : flushed.state.answer,
29
- assistantMessageId: type === "assistant" && messageId !== undefined
30
- ? messageId
31
- : flushed.state.assistantMessageId,
24
+ answer: type === "assistant" ? `${newAssistantMessage ? "" : flushed.state.answer}${text}` : flushed.state.answer,
25
+ assistantMessageId: type === "assistant" && messageId !== undefined ? messageId : flushed.state.assistantMessageId,
32
26
  open: { type, text: `${flushed.state.open?.text ?? ""}${text}` },
33
27
  },
34
28
  };
@@ -42,9 +36,7 @@ function object(value) {
42
36
  : undefined;
43
37
  }
44
38
  function positiveLine(value) {
45
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 1
46
- ? value
47
- : undefined;
39
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 1 ? value : undefined;
48
40
  }
49
41
  function otherCall(name) {
50
42
  return { kind: "other", display: name };
@@ -84,9 +76,7 @@ function standardCall(update, name) {
84
76
  const path = nonblank(input?.path);
85
77
  const glob = nonblank(input?.glob);
86
78
  const scope = input?.scope;
87
- const searchScope = scope === "content" || scope === "files" || scope === "web"
88
- ? scope
89
- : undefined;
79
+ const searchScope = scope === "content" || scope === "files" || scope === "web" ? scope : undefined;
90
80
  return {
91
81
  kind: "search",
92
82
  query,
@@ -115,33 +105,52 @@ export function mapAcpUpdate(update, previous, interpret) {
115
105
  const text = update.content.type === "text" ? update.content.text : undefined;
116
106
  if (text === undefined)
117
107
  return flushAcpEvents(previous, [unknownEvent(`${update.sessionUpdate}/${update.content.type}`)]);
118
- return appendBlock(previous, update.sessionUpdate === "agent_message_chunk" ? "assistant" : "thought", text, update.sessionUpdate === "agent_message_chunk" && update.messageId !== null
119
- ? update.messageId
120
- : undefined);
108
+ return appendBlock(previous, update.sessionUpdate === "agent_message_chunk" ? "assistant" : "thought", text, update.sessionUpdate === "agent_message_chunk" && update.messageId !== null ? update.messageId : undefined);
121
109
  }
122
- case "user_message_chunk": return flushAcpEvents(previous);
110
+ case "user_message_chunk":
111
+ return flushAcpEvents(previous);
123
112
  case "tool_call":
124
113
  case "tool_call_update": {
125
114
  const observed = observeTool(update, previous.tools.get(update.toolCallId), interpret);
126
115
  const tools = new Map(previous.tools);
127
116
  if (update.status === "completed" || update.status === "failed") {
128
117
  tools.delete(update.toolCallId);
129
- return flushAcpEvents({ ...previous, tools }, [{ type: "tool", phase: "completed", id: update.toolCallId, ...observed, result: { status: update.status === "completed" ? "ok" : "error" } }]);
118
+ return flushAcpEvents({ ...previous, tools }, [
119
+ {
120
+ type: "tool",
121
+ phase: "completed",
122
+ id: update.toolCallId,
123
+ ...observed,
124
+ result: { status: update.status === "completed" ? "ok" : "error" },
125
+ },
126
+ ]);
130
127
  }
131
128
  const started = tools.has(update.toolCallId);
132
129
  tools.set(update.toolCallId, observed);
133
130
  return started
134
131
  ? flushAcpEvents({ ...previous, tools })
135
- : flushAcpEvents({ ...previous, tools }, [{ type: "tool", phase: "started", id: update.toolCallId, ...observed }]);
132
+ : flushAcpEvents({ ...previous, tools }, [
133
+ { type: "tool", phase: "started", id: update.toolCallId, ...observed },
134
+ ]);
136
135
  }
137
- case "plan": return flushAcpEvents(previous, [noteEvent(`Plan updated: ${update.entries.map((entry) => entry.content).join("; ")}`)]);
138
- case "available_commands_update": return flushAcpEvents(previous, [noteEvent("ACP commands updated")]);
139
- case "current_mode_update": return flushAcpEvents(previous, [noteEvent("ACP mode updated")]);
140
- case "config_option_update": return flushAcpEvents(previous, [noteEvent("ACP configuration updated")]);
141
- case "session_info_update": return flushAcpEvents(previous, [noteEvent("ACP session metadata updated")]);
142
- case "usage_update": return flushAcpEvents(previous);
136
+ case "plan":
137
+ return flushAcpEvents(previous, [
138
+ noteEvent(`Plan updated: ${update.entries.map((entry) => entry.content).join("; ")}`),
139
+ ]);
140
+ case "available_commands_update":
141
+ return flushAcpEvents(previous, [noteEvent("ACP commands updated")]);
142
+ case "current_mode_update":
143
+ return flushAcpEvents(previous, [noteEvent("ACP mode updated")]);
144
+ case "config_option_update":
145
+ return flushAcpEvents(previous, [noteEvent("ACP configuration updated")]);
146
+ case "session_info_update":
147
+ return flushAcpEvents(previous, [noteEvent("ACP session metadata updated")]);
148
+ case "usage_update":
149
+ return flushAcpEvents(previous);
143
150
  case "plan_update":
144
- case "plan_removed": return flushAcpEvents(previous, [unknownEvent(update.sessionUpdate)]);
145
- default: return { events: [unknownEvent(String(update.sessionUpdate))], state: previous };
151
+ case "plan_removed":
152
+ return flushAcpEvents(previous, [unknownEvent(update.sessionUpdate)]);
153
+ default:
154
+ return { events: [unknownEvent(String(update.sessionUpdate))], state: previous };
146
155
  }
147
156
  }
@@ -11,18 +11,28 @@ function optionAdmission(options, config) {
11
11
  if (options.effort !== undefined && config.effortArg === undefined) {
12
12
  return { kind: "refused", diagnostic: "ACP provider has no effort argument mapping" };
13
13
  }
14
- if (options.systemPrompt !== undefined && options.systemPrompt.length > 0 && config.systemPromptArg === undefined) {
15
- return { kind: "refused", diagnostic: "ACP provider has no systemPrompt argument mapping" };
14
+ if (options.systemPrompt !== undefined && options.systemPrompt.length > 0) {
15
+ if (config.systemPromptArg === undefined) {
16
+ return { kind: "refused", diagnostic: "ACP provider has no systemPrompt argument mapping" };
17
+ }
18
+ if (options.systemPromptMode !== undefined && options.systemPromptMode !== (config.systemPromptMode ?? "replace")) {
19
+ return {
20
+ kind: "refused",
21
+ diagnostic: "ACP provider systemPromptMode does not match the configured argument mode",
22
+ };
23
+ }
16
24
  }
17
25
  return {
18
26
  kind: "admitted",
19
27
  options,
20
- ...(options.readonly === undefined ? {} : {
21
- readonly: {
22
- enforcement: "none",
23
- diagnostic: "ACP cannot remove task-surface mutation capabilities",
24
- },
25
- }),
28
+ ...(options.readonly === undefined
29
+ ? {}
30
+ : {
31
+ readonly: {
32
+ enforcement: "none",
33
+ diagnostic: "ACP cannot remove task-surface mutation capabilities",
34
+ },
35
+ }),
26
36
  };
27
37
  }
28
38
  function argv(execution, config, options) {