@astrosheep/keiyaku 4.6.8 → 4.6.9

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 (253) hide show
  1. package/README.md +40 -14
  2. package/build/plugins/claude/.claude-plugin/plugin.json +1 -1
  3. package/build/plugins/claude/skills/keiyaku/SKILL.md +5 -6
  4. package/build/plugins/claude/skills/keiyaku-akuma/SKILL.md +1 -1
  5. package/build/plugins/claude/skills/keiyaku-akuma/references/automation.md +8 -8
  6. package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
  7. package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +9 -9
  8. package/build/plugins/claude/skills/keiyaku-debt/SKILL.md +91 -0
  9. package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +2 -2
  10. package/build/plugins/codex/.codex-plugin/plugin.json +1 -1
  11. package/build/plugins/codex/skills/keiyaku/SKILL.md +5 -6
  12. package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +1 -1
  13. package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +8 -8
  14. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
  15. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +9 -9
  16. package/build/plugins/codex/skills/keiyaku-debt/SKILL.md +91 -0
  17. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +2 -2
  18. package/build/plugins/opencode/index.js +1 -1
  19. package/build/plugins/opencode/skills/keiyaku/SKILL.md +5 -6
  20. package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +1 -1
  21. package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +8 -8
  22. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
  23. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +9 -9
  24. package/build/plugins/opencode/skills/keiyaku-debt/SKILL.md +91 -0
  25. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +2 -2
  26. package/build/skills/keiyaku/SKILL.md +5 -6
  27. package/build/skills/keiyaku-akuma/SKILL.md +1 -1
  28. package/build/skills/keiyaku-akuma/references/automation.md +8 -8
  29. package/build/skills/keiyaku-babysit/SKILL.md +1 -1
  30. package/build/skills/keiyaku-bind/SKILL.md +9 -9
  31. package/build/skills/keiyaku-debt/SKILL.md +91 -0
  32. package/build/skills/keiyaku-workflow/SKILL.md +2 -2
  33. package/build/src/akuma/akuma-instance.d.ts +2 -0
  34. package/build/src/akuma/akuma-instance.js +10 -0
  35. package/build/src/akuma/akuma-observe.d.ts +33 -8
  36. package/build/src/akuma/akuma-observe.js +88 -64
  37. package/build/src/akuma/akuma-owner.d.ts +11 -2
  38. package/build/src/akuma/akuma-owner.js +45 -35
  39. package/build/src/akuma/akuma-selection-execution.js +9 -1
  40. package/build/src/akuma/akuma-stream.d.ts +22 -0
  41. package/build/src/akuma/akuma-stream.js +116 -0
  42. package/build/src/akuma/akuma-wait.d.ts +1 -40
  43. package/build/src/akuma/akuma-wait.js +23 -84
  44. package/build/src/akuma/akuma.d.ts +17 -11
  45. package/build/src/akuma/akuma.js +2 -0
  46. package/build/src/akuma/allowed.d.ts +7 -12
  47. package/build/src/akuma/allowed.js +13 -4
  48. package/build/src/akuma/body-supervisor.d.ts +5 -5
  49. package/build/src/akuma/body-supervisor.js +22 -20
  50. package/build/src/akuma/body.js +28 -1
  51. package/build/src/akuma/call-request.d.ts +12 -22
  52. package/build/src/akuma/heart/activity-schema.d.ts +12 -0
  53. package/build/src/akuma/heart/activity-schema.js +6 -0
  54. package/build/src/akuma/heart/index.d.ts +59 -2
  55. package/build/src/akuma/heart/index.js +87 -8
  56. package/build/src/akuma/heart/rows.js +5 -3
  57. package/build/src/akuma/heart/soul.d.ts +9 -0
  58. package/build/src/akuma/heart/soul.js +29 -0
  59. package/build/src/akuma/heart/storage.d.ts +15 -0
  60. package/build/src/akuma/heart/storage.js +55 -0
  61. package/build/src/akuma/heart/timeline.d.ts +7 -0
  62. package/build/src/akuma/heart/timeline.js +10 -0
  63. package/build/src/akuma/index.d.ts +1 -0
  64. package/build/src/akuma/projection.d.ts +25 -0
  65. package/build/src/akuma/projection.js +24 -7
  66. package/build/src/akuma/provider-recipe.d.ts +11 -0
  67. package/build/src/akuma/provider-recipe.js +23 -0
  68. package/build/src/akuma/provider.d.ts +25 -0
  69. package/build/src/akuma/provider.js +99 -7
  70. package/build/src/akuma/providers/acp/events.js +25 -2
  71. package/build/src/akuma/providers/claude/events.js +76 -10
  72. package/build/src/akuma/providers/claude/index.js +2 -5
  73. package/build/src/akuma/providers/codex-app-server/events.js +17 -2
  74. package/build/src/akuma/providers/codex-app-server/index.js +15 -9
  75. package/build/src/akuma/providers/decode.d.ts +8 -0
  76. package/build/src/akuma/providers/decode.js +21 -0
  77. package/build/src/akuma/providers/grok-build/index.js +10 -26
  78. package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +3 -3
  79. package/build/src/akuma/providers/opencode-sdk/event-stream.js +2 -25
  80. package/build/src/akuma/providers/opencode-sdk/events.d.ts +7 -43
  81. package/build/src/akuma/providers/opencode-sdk/events.js +147 -284
  82. package/build/src/akuma/providers/opencode-sdk/index.js +267 -421
  83. package/build/src/akuma/providers/opencode-sdk/native-http.d.ts +9 -0
  84. package/build/src/akuma/providers/opencode-sdk/native-http.js +69 -0
  85. package/build/src/akuma/providers/opencode-sdk/session.d.ts +42 -36
  86. package/build/src/akuma/providers/opencode-sdk/session.js +75 -82
  87. package/build/src/akuma/providers/paseo/events.d.ts +8 -0
  88. package/build/src/akuma/providers/paseo/events.js +58 -11
  89. package/build/src/akuma/providers/paseo/index.js +11 -7
  90. package/build/src/akuma/providers/pi/events.d.ts +2 -0
  91. package/build/src/akuma/providers/pi/events.js +32 -24
  92. package/build/src/akuma/providers/pi/index.js +21 -35
  93. package/build/src/akuma/request-lifecycle.d.ts +1 -2
  94. package/build/src/akuma/request-lifecycle.js +2 -8
  95. package/build/src/akuma/request-rendezvous.js +38 -55
  96. package/build/src/akuma/request-serve.d.ts +1 -1
  97. package/build/src/akuma/request-serve.js +77 -113
  98. package/build/src/akuma/selection-observation.d.ts +57 -51
  99. package/build/src/akuma/selection-observation.js +3 -3
  100. package/build/src/akuma/turn-drive.d.ts +3 -0
  101. package/build/src/akuma/turn-drive.js +26 -5
  102. package/build/src/akuma-body.js +12 -22
  103. package/build/src/cli/akuma-caller.js +10 -0
  104. package/build/src/cli/commands/akuma-grammar.js +3 -4
  105. package/build/src/cli/commands/akuma.js +13 -51
  106. package/build/src/cli/commands/contract-grammar.d.ts +7 -6
  107. package/build/src/cli/commands/contract-grammar.js +27 -32
  108. package/build/src/cli/commands/contract-help.d.ts +16 -7
  109. package/build/src/cli/commands/contract-help.js +20 -11
  110. package/build/src/cli/commands/contract.js +11 -11
  111. package/build/src/cli/commands/debt-grammar.d.ts +19 -0
  112. package/build/src/cli/commands/debt-grammar.js +323 -0
  113. package/build/src/cli/commands/debt-query.d.ts +5 -0
  114. package/build/src/cli/commands/{task-query.js → debt-query.js} +9 -9
  115. package/build/src/cli/commands/{task.d.ts → debt.d.ts} +2 -2
  116. package/build/src/cli/commands/{task.js → debt.js} +83 -143
  117. package/build/src/cli/coordinates.d.ts +1 -1
  118. package/build/src/cli/coordinates.js +1 -1
  119. package/build/src/cli/parse.d.ts +4 -4
  120. package/build/src/cli/parse.js +17 -16
  121. package/build/src/cli/render/akuma-activity.d.ts +11 -83
  122. package/build/src/cli/render/akuma-activity.js +20 -382
  123. package/build/src/cli/render/catalog.d.ts +2 -2
  124. package/build/src/cli/render/catalog.js +5 -5
  125. package/build/src/cli/render/contract.js +2 -2
  126. package/build/src/cli/render/debt.d.ts +28 -0
  127. package/build/src/cli/render/{task.js → debt.js} +51 -112
  128. package/build/src/cli/render/kanshi.js +28 -28
  129. package/build/src/cli/render/marks.d.ts +5 -5
  130. package/build/src/cli/render/marks.js +4 -10
  131. package/build/src/cli/render/nuke.js +1 -1
  132. package/build/src/cli/runtime.js +3 -3
  133. package/build/src/cli/scan.d.ts +1 -1
  134. package/build/src/cli/usage.d.ts +1 -1
  135. package/build/src/cli/usage.js +4 -4
  136. package/build/src/contract-worktree.js +3 -3
  137. package/build/src/debt/board.d.ts +160 -0
  138. package/build/src/{task → debt}/board.js +89 -89
  139. package/build/src/debt/catalog.d.ts +11 -0
  140. package/build/src/debt/catalog.js +59 -0
  141. package/build/src/{task → debt}/context.d.ts +1 -1
  142. package/build/src/{task → debt}/context.js +1 -1
  143. package/build/src/{task → debt}/created-observation.d.ts +6 -10
  144. package/build/src/{task → debt}/created-observation.js +7 -7
  145. package/build/src/debt/document.d.ts +37 -0
  146. package/build/src/{task → debt}/document.js +37 -37
  147. package/build/src/debt/identity.d.ts +21 -0
  148. package/build/src/{task → debt}/identity.js +35 -35
  149. package/build/src/debt/index.d.ts +111 -0
  150. package/build/src/debt/index.js +203 -0
  151. package/build/src/{task → debt}/input.d.ts +8 -8
  152. package/build/src/{task → debt}/input.js +21 -21
  153. package/build/src/debt/lifecycle-operations.d.ts +6 -0
  154. package/build/src/{task → debt}/lifecycle-operations.js +27 -31
  155. package/build/src/debt/mutation-result.d.ts +981 -0
  156. package/build/src/debt/mutation-result.js +109 -0
  157. package/build/src/debt/mutation.d.ts +424 -0
  158. package/build/src/debt/mutation.js +223 -0
  159. package/build/src/debt/operation-types.d.ts +71 -0
  160. package/build/src/debt/operations.d.ts +28 -0
  161. package/build/src/{task → debt}/operations.js +59 -60
  162. package/build/src/debt/query.d.ts +76 -0
  163. package/build/src/{task → debt}/query.js +55 -55
  164. package/build/src/{task → debt}/store.d.ts +13 -13
  165. package/build/src/{task → debt}/store.js +58 -49
  166. package/build/src/debt/view.d.ts +4 -0
  167. package/build/src/debt/view.js +7 -0
  168. package/build/src/identity/coordinates.d.ts +1 -1
  169. package/build/src/index.d.ts +13 -13
  170. package/build/src/index.js +9 -9
  171. package/build/src/kanshi/index.d.ts +1 -1
  172. package/build/src/kanshi/read.js +33 -33
  173. package/build/src/kanshi/report.d.ts +7 -7
  174. package/build/src/kanshi/select.js +4 -4
  175. package/build/src/library/akumas.d.ts +2 -3
  176. package/build/src/library/bind.d.ts +3 -3
  177. package/build/src/library/bind.js +5 -5
  178. package/build/src/library/contract-creation.js +5 -5
  179. package/build/src/library/contract-execution.js +4 -4
  180. package/build/src/library/contract-types.d.ts +2 -2
  181. package/build/src/library/input.d.ts +2 -2
  182. package/build/src/library/input.js +5 -5
  183. package/build/src/library/invocation.js +2 -2
  184. package/build/src/library/nuke.js +3 -3
  185. package/build/src/library/outcome.d.ts +126 -126
  186. package/build/src/library/outcome.js +3 -3
  187. package/build/src/library/selection.d.ts +1 -4
  188. package/build/src/library/selection.js +11 -62
  189. package/build/src/plugin/public.d.ts +5 -0
  190. package/build/src/plugin/runtime.js +3 -1
  191. package/build/src/runtime/proc/windows-launch.exe +0 -0
  192. package/build/src/settlement/fence.d.ts +3 -3
  193. package/build/src/settlement/fence.js +4 -4
  194. package/build/src/settlement/holder.d.ts +16 -16
  195. package/build/src/settlement/holder.js +69 -63
  196. package/build/src/settlement/settle.d.ts +5 -5
  197. package/build/src/settlement/settle.js +53 -53
  198. package/package.json +12 -6
  199. package/plugins/paseo/plugin/index.server.ts +17 -0
  200. package/plugins/paseo/plugin/paseo-plugin.json +4 -0
  201. package/plugins/paseo/plugin/server/attach.ts +52 -0
  202. package/plugins/paseo/plugin/server/keiyaku.ts +44 -0
  203. package/plugins/paseo/plugin/server/message.ts +60 -0
  204. package/plugins/paseo/plugin/server/mirror.ts +193 -0
  205. package/plugins/paseo/plugin/server/model.ts +14 -0
  206. package/plugins/paseo/plugin/server/provider.ts +276 -0
  207. package/plugins/paseo/plugin/server/sdk-worker.ts +237 -0
  208. package/plugins/paseo/plugin/server/sdk.ts +289 -0
  209. package/plugins/paseo/plugin/server/stop.ts +26 -0
  210. package/plugins/paseo/plugin/server/transport.ts +35 -0
  211. package/plugins/paseo/plugin/shared/attach-rpc.ts +10 -0
  212. package/plugins/paseo/plugin/shared/refresh-rpc.ts +6 -0
  213. package/plugins/paseo/plugin/tsconfig.json +6 -0
  214. package/skills/keiyaku/SKILL.md +5 -6
  215. package/skills/keiyaku-akuma/SKILL.md +1 -1
  216. package/skills/keiyaku-akuma/references/automation.md +8 -8
  217. package/skills/keiyaku-babysit/SKILL.md +1 -1
  218. package/skills/keiyaku-bind/SKILL.md +9 -9
  219. package/skills/keiyaku-debt/SKILL.md +91 -0
  220. package/skills/keiyaku-workflow/SKILL.md +2 -2
  221. package/build/plugins/claude/skills/keiyaku-task/SKILL.md +0 -104
  222. package/build/plugins/codex/skills/keiyaku-task/SKILL.md +0 -104
  223. package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +0 -104
  224. package/build/skills/keiyaku-task/SKILL.md +0 -104
  225. package/build/src/cli/commands/task-grammar.d.ts +0 -19
  226. package/build/src/cli/commands/task-grammar.js +0 -384
  227. package/build/src/cli/commands/task-query.d.ts +0 -5
  228. package/build/src/cli/render/task.d.ts +0 -39
  229. package/build/src/task/board.d.ts +0 -168
  230. package/build/src/task/catalog.d.ts +0 -11
  231. package/build/src/task/catalog.js +0 -59
  232. package/build/src/task/compose-language.d.ts +0 -57
  233. package/build/src/task/compose-language.js +0 -364
  234. package/build/src/task/compose-parser.d.ts +0 -32
  235. package/build/src/task/compose-parser.js +0 -180
  236. package/build/src/task/compose.d.ts +0 -16
  237. package/build/src/task/compose.js +0 -189
  238. package/build/src/task/document.d.ts +0 -39
  239. package/build/src/task/identity.d.ts +0 -21
  240. package/build/src/task/index.d.ts +0 -138
  241. package/build/src/task/index.js +0 -269
  242. package/build/src/task/lifecycle-operations.d.ts +0 -6
  243. package/build/src/task/mutation-result.d.ts +0 -1726
  244. package/build/src/task/mutation-result.js +0 -198
  245. package/build/src/task/mutation.d.ts +0 -590
  246. package/build/src/task/mutation.js +0 -262
  247. package/build/src/task/operation-types.d.ts +0 -71
  248. package/build/src/task/operations.d.ts +0 -28
  249. package/build/src/task/query.d.ts +0 -76
  250. package/build/src/task/view.d.ts +0 -4
  251. package/build/src/task/view.js +0 -7
  252. package/skills/keiyaku-task/SKILL.md +0 -104
  253. /package/build/src/{task → debt}/operation-types.js +0 -0
@@ -1,309 +1,172 @@
1
- import { noteEvent, otherToolCall } from "../../provider.js";
2
- import { nonnegativeCount, object, positiveLine, text } from "../decode.js";
3
- export const OPENCODE_EVENT_DISPOSITIONS = {
4
- "server.instance.disposed": "dropped",
5
- "installation.updated": "dropped",
6
- "installation.update-available": "dropped",
7
- "lsp.client.diagnostics": "dropped",
8
- "lsp.updated": "dropped",
9
- "message.updated": "mapped",
10
- "message.removed": "dropped",
11
- "message.part.updated": "mapped",
12
- "message.part.removed": "dropped",
13
- "permission.updated": "dropped",
14
- "permission.replied": "dropped",
15
- "session.status": "dropped",
16
- "session.idle": "dropped",
17
- "session.compacted": "note",
18
- "file.edited": "dropped",
19
- "todo.updated": "mapped",
20
- "command.executed": "dropped",
21
- "session.created": "dropped",
22
- "session.updated": "dropped",
23
- "session.deleted": "dropped",
24
- "session.diff": "dropped",
25
- "session.error": "mapped",
26
- "file.watcher.updated": "dropped",
27
- "vcs.branch.updated": "dropped",
28
- "tui.prompt.append": "dropped",
29
- "tui.command.execute": "dropped",
30
- "tui.toast.show": "dropped",
31
- "pty.created": "dropped",
32
- "pty.updated": "dropped",
33
- "pty.exited": "dropped",
34
- "pty.deleted": "dropped",
35
- "server.connected": "dropped",
36
- };
37
- // OpenCode may emit these server-side metadata events before the generated
38
- // SDK union catches up. They are all non-narrative and therefore remain drop
39
- // dispositions; genuinely new execution events still use the unknown arm.
40
- const RUNTIME_DROPPED_EVENT_KINDS = new Set([
41
- "plugin.added",
42
- "catalog.updated",
43
- "reference.updated",
44
- "integration.updated",
45
- "server.heartbeat",
46
- "message.part.delta",
47
- ]);
48
- function diagnostic(value) {
1
+ import { modelEvent, noteEvent, otherToolCall, } from "../../provider.js";
2
+ import { nonnegativeCount, object, positiveLine, stringValue, text } from "../decode.js";
3
+ export function diagnostic(value) {
49
4
  const data = object(value);
50
- const nested = object(data?.data);
51
- return text(nested?.message) ?? text(data?.message) ?? "OpenCode session failed";
52
- }
53
- function diffstat(value) {
54
- if (value === undefined)
55
- return undefined;
56
- const added = nonnegativeCount(value.additions);
57
- const removed = nonnegativeCount(value.deletions);
58
- return added === undefined || removed === undefined ? undefined : { added, removed };
59
- }
60
- function fileChange(changes) {
61
- return changes.length === 0 ? undefined : { kind: "fileChange", changes };
62
- }
63
- function change(op, path, stats) {
64
- return stats === undefined ? { op, path } : { op, path, diffstat: stats };
65
- }
66
- function editCall(input, metadata) {
67
- const path = text(input?.filePath);
68
- if (path === undefined)
69
- return undefined;
70
- return fileChange([change("update", path, diffstat(object(metadata?.filediff)))]);
71
- }
72
- function writeCall(input, metadata) {
73
- const path = text(metadata?.filepath) ?? text(input?.filePath);
74
- const op = metadata?.exists === false ? "add" : metadata?.exists === true ? "update" : undefined;
75
- return path === undefined || op === undefined ? undefined : fileChange([change(op, path, undefined)]);
76
- }
77
- function applyPatchFile(value) {
78
- const file = object(value);
79
- if (file === undefined)
80
- return undefined;
81
- const type = file.type;
82
- const op = type === "add"
83
- ? "add"
84
- : type === "delete"
85
- ? "delete"
86
- : type === "update" || type === "modify" || type === "move"
87
- ? "update"
88
- : undefined;
89
- const path = type === "move" ? text(file.movePath) : text(file.filePath);
90
- return op === undefined || path === undefined ? undefined : change(op, path, diffstat(file));
91
- }
92
- function applyPatchCall(metadata) {
93
- if (!Array.isArray(metadata?.files))
94
- return undefined;
95
- return fileChange(metadata.files.flatMap((value) => {
96
- const next = applyPatchFile(value);
97
- return next === undefined ? [] : [next];
98
- }));
99
- }
100
- function strongerCall(previous, next) {
101
- if (next === undefined)
102
- return previous;
103
- if (previous?.kind === "fileChange" && next.kind !== "fileChange")
104
- return previous;
105
- // The correlated start's admitted preview is authority: a later update never
106
- // overwrites it, empty or conflicting, while a start without one adopts supplied evidence.
107
- if (next.kind === "other" && previous?.kind === "other" && previous.input !== undefined)
108
- return { ...next, input: previous.input };
109
- return next;
5
+ return text(data?.message) ?? text(object(data?.data)?.message) ?? "OpenCode execution failed";
110
6
  }
111
- function runCall(name, value) {
112
- return name === "bash" || name === "shell" ? { kind: "run", command: text(value?.command) ?? name } : undefined;
113
- }
114
- function readCall(name, value) {
115
- if (name !== "read")
116
- return undefined;
117
- const path = text(value?.filePath) ?? text(value?.path);
118
- if (path === undefined)
119
- return undefined;
120
- const offset = positiveLine(value?.offset);
121
- const limit = positiveLine(value?.limit);
122
- return {
123
- kind: "read",
124
- path,
125
- ...(offset === undefined ? {} : { offset }),
126
- ...(limit === undefined ? {} : { limit }),
127
- };
128
- }
129
- function searchCall(name, value) {
130
- if (name !== "grep" && name !== "glob" && name !== "search")
131
- return undefined;
132
- const query = text(value?.pattern) ?? text(value?.query);
133
- if (query === undefined)
134
- return undefined;
135
- const path = text(value?.path) ?? text(value?.filePath);
136
- const glob = text(value?.glob);
137
- const scope = name === "glob" ? "files" : "content";
138
- return {
139
- kind: "search",
140
- query,
141
- scope,
142
- ...(path === undefined ? {} : { path }),
143
- ...(scope === "content" && glob !== undefined ? { glob } : {}),
144
- };
145
- }
146
- function callFor(name, input, metadata) {
7
+ function callFor(name, input) {
147
8
  const value = object(input);
148
- const meta = object(metadata);
149
- const lower = name.toLowerCase();
150
- if (lower === "bash" || lower === "shell")
151
- return runCall(lower, value);
152
- if (lower === "read")
153
- return readCall(lower, value);
154
- if (lower === "grep" || lower === "glob" || lower === "search")
155
- return searchCall(lower, value);
156
- if (lower === "edit")
157
- return editCall(value, meta) ?? otherToolCall(name, input);
158
- if (lower === "write")
159
- return writeCall(value, meta) ?? otherToolCall(name, input);
160
- if (lower === "apply_patch")
161
- return applyPatchCall(meta) ?? otherToolCall(name, input);
9
+ if (name === "shell")
10
+ return { kind: "run", command: text(value?.command) ?? name };
11
+ if (name === "read") {
12
+ const path = text(value?.filePath) ?? text(value?.path);
13
+ if (path !== undefined)
14
+ return {
15
+ kind: "read",
16
+ path,
17
+ ...(positiveLine(value?.offset) === undefined ? {} : { offset: positiveLine(value?.offset) }),
18
+ ...(positiveLine(value?.limit) === undefined ? {} : { limit: positiveLine(value?.limit) }),
19
+ };
20
+ }
21
+ if (name === "grep" || name === "glob") {
22
+ const query = text(value?.pattern);
23
+ const path = text(value?.path);
24
+ if (query !== undefined)
25
+ return {
26
+ kind: "search",
27
+ scope: name === "glob" ? "files" : "content",
28
+ query,
29
+ ...(path === undefined ? {} : { path }),
30
+ };
31
+ }
32
+ if (name === "edit") {
33
+ const path = text(value?.path);
34
+ if (path !== undefined)
35
+ return { kind: "fileChange", changes: [{ op: "update", path }] };
36
+ }
162
37
  return otherToolCall(name, input);
163
38
  }
164
- function belongs(part, state) {
165
- return state.sessionId === undefined || part.sessionID === state.sessionId;
166
- }
167
- function mapTextPart(part, events, state, thought) {
168
- const id = text(part.id);
169
- const time = object(part.time);
170
- const content = text(part.text);
171
- const seen = thought ? state.reasoningParts : state.assistantParts;
172
- if (!belongs(part, state) || id === undefined || content === undefined || time?.end === undefined || seen.has(id))
173
- return;
174
- seen.add(id);
175
- if (thought)
176
- events.emit({ type: "thought", text: content });
177
- else
178
- events.emit({ type: "assistant", text: content });
39
+ function observedChanges(metadata) {
40
+ const files = object(metadata)?.files;
41
+ if (!Array.isArray(files))
42
+ return undefined;
43
+ const changes = files.flatMap((item) => {
44
+ const file = object(item);
45
+ const path = text(file?.file);
46
+ const status = file?.status;
47
+ if (path === undefined || (status !== "added" && status !== "deleted" && status !== "modified"))
48
+ return [];
49
+ const added = nonnegativeCount(file?.additions);
50
+ const removed = nonnegativeCount(file?.deletions);
51
+ const patch = stringValue(file?.patch);
52
+ return [
53
+ {
54
+ op: status === "added" ? "add" : status === "deleted" ? "delete" : "update",
55
+ path,
56
+ ...(added === undefined || removed === undefined ? {} : { diffstat: { added, removed } }),
57
+ ...(patch === undefined ? {} : { patch }),
58
+ },
59
+ ];
60
+ });
61
+ return changes.length === 0 ? undefined : { kind: "fileChange", changes };
179
62
  }
180
- function resultFor(state, failed) {
181
- const exit = object(state.metadata)?.exit;
182
- const exitCode = typeof exit === "number" && Number.isInteger(exit) ? exit : undefined;
183
- if (failed) {
184
- return {
185
- status: "error",
186
- message: text(state.error) ?? "OpenCode tool failed",
187
- ...(exitCode === undefined ? {} : { exitCode }),
188
- };
189
- }
190
- return {
191
- status: exitCode !== undefined && exitCode !== 0 ? "error" : "ok",
192
- ...(exitCode === undefined ? {} : { exitCode }),
193
- };
63
+ function output(content) {
64
+ if (!Array.isArray(content))
65
+ return undefined;
66
+ const parts = content.flatMap((part) => {
67
+ const value = object(part);
68
+ const text = value?.type === "text" ? stringValue(value.text) : undefined;
69
+ return text === undefined ? [] : [text];
70
+ });
71
+ return parts.length === 0 ? undefined : parts.join("\n\n");
194
72
  }
195
- function mapToolPart(part, events, state) {
196
- if (!belongs(part, state))
73
+ const DROPPED = new Set([
74
+ "server.connected",
75
+ "server.heartbeat",
76
+ "session.created",
77
+ "session.forked",
78
+ "session.deleted",
79
+ "session.inbox.enqueued",
80
+ "session.inbox.delivered",
81
+ "session.inbox.cancelled",
82
+ "session.inbox.delivery.changed",
83
+ "session.execution.started",
84
+ "session.execution.succeeded",
85
+ "session.execution.failed",
86
+ "session.execution.interrupted",
87
+ "session.model.selected",
88
+ "session.agent.selected",
89
+ "session.instructions.updated",
90
+ "session.permissions",
91
+ "session.step.streamed",
92
+ "session.step.ended",
93
+ "session.usage.updated",
94
+ "session.usage.recorded",
95
+ "session.text.started",
96
+ "session.text.delta",
97
+ "session.reasoning.started",
98
+ "session.reasoning.delta",
99
+ "session.tool.input.delta",
100
+ "session.tool.input.ended",
101
+ "session.tool.progress",
102
+ "session.retry.scheduled",
103
+ ]);
104
+ /** Only complete native values enter narration. The caller enforces submission/step correlation. */
105
+ export function mapEvent(value, events, state) {
106
+ const event = object(value);
107
+ if (event === undefined || typeof event.type !== "string")
197
108
  return;
198
- const id = text(part.callID);
199
- const name = text(part.tool);
200
- const toolState = object(part.state);
201
- if (id === undefined || name === undefined || toolState === undefined)
109
+ const data = object(event.data) ?? {};
110
+ if (state.sessionId !== undefined && data.sessionID !== state.sessionId)
202
111
  return;
203
- const next = callFor(name, toolState.input, toolState.metadata);
204
- if ((toolState.status === "pending" || toolState.status === "running") &&
205
- !state.tools.has(id) &&
206
- !state.completedTools.has(id)) {
207
- if (next === undefined)
208
- return;
209
- const observed = { name, call: next };
210
- state.tools.set(id, observed);
211
- events.emit({ type: "tool", phase: "started", id, ...observed });
112
+ const type = event.type;
113
+ if (type === "session.step.started") {
114
+ const model = object(data.model);
115
+ const provider = text(model?.providerID);
116
+ const id = text(model?.id);
117
+ if (provider !== undefined && id !== undefined)
118
+ events.emit(modelEvent(`${provider}/${id}`));
212
119
  return;
213
120
  }
214
- if ((toolState.status !== "completed" && toolState.status !== "error") || state.completedTools.has(id))
121
+ if (type === "session.text.ended" || type === "session.reasoning.ended") {
122
+ if (typeof data.text === "string")
123
+ events.emit({ type: type === "session.text.ended" ? "assistant" : "thought", text: data.text });
215
124
  return;
216
- const started = state.tools.get(id);
217
- const call = strongerCall(started?.call, next);
218
- if (call === undefined)
219
- return;
220
- const observed = { name: started?.name ?? name, call };
221
- if (!state.tools.has(id)) {
222
- state.tools.set(id, observed);
223
- events.emit({ type: "tool", phase: "started", id, ...observed });
224
- }
225
- else {
226
- state.tools.set(id, observed);
227
125
  }
228
- state.completedTools.add(id);
229
- events.emit({
230
- type: "tool",
231
- phase: "completed",
232
- id,
233
- ...observed,
234
- result: resultFor(toolState, toolState.status === "error"),
235
- });
236
- }
237
- function mapPart(part, events, state) {
238
- if (part.type === "text")
239
- return mapTextPart(part, events, state, false);
240
- if (part.type === "reasoning")
241
- return mapTextPart(part, events, state, true);
242
- if (part.type === "tool")
243
- mapToolPart(part, events, state);
244
- }
245
- function mapSessionError(properties, events, state) {
246
- if (state.sessionId !== undefined && properties.sessionID !== state.sessionId)
247
- return;
248
- state.failure = diagnostic(properties.error);
249
- events.emit(noteEvent(state.failure));
250
- }
251
- function mapTodo(properties, events, state) {
252
- if (properties.sessionID !== state.sessionId || !Array.isArray(properties.todos))
253
- return;
254
- const summary = properties.todos
255
- .flatMap((value) => {
256
- const todo = object(value);
257
- const content = text(todo?.content);
258
- return content === undefined ? [] : [`${text(todo?.status) ?? "todo"}: ${content}`];
259
- })
260
- .join("; ");
261
- if (summary.length > 0)
262
- events.emit(noteEvent(summary));
263
- }
264
- function ignoredEvent(type) {
265
- return (typeof type === "string" &&
266
- (OPENCODE_EVENT_DISPOSITIONS[type] === "dropped" || RUNTIME_DROPPED_EVENT_KINDS.has(type)));
267
- }
268
- export function mapEvent(value, events, state) {
269
- const event = object(value);
270
- if (event === undefined)
271
- return;
272
- const properties = object(event.properties) ?? {};
273
- if (event.type === "message.part.updated") {
274
- const part = object(properties.part);
275
- if (part !== undefined)
276
- mapPart(part, events, state);
126
+ if (type === "session.tool.input.started") {
127
+ if (typeof data.id === "string" && typeof data.name === "string")
128
+ state.tools.set(data.id, { name: data.name });
277
129
  return;
278
130
  }
279
- if (event.type === "message.updated") {
280
- const info = object(properties.info);
281
- if (info !== undefined &&
282
- info.sessionID === state.sessionId &&
283
- info.role === "assistant" &&
284
- info.error !== undefined) {
285
- state.failure = diagnostic(info.error);
131
+ if (type === "session.tool.called" || type === "session.tool.success" || type === "session.tool.failed") {
132
+ const id = text(data.id);
133
+ const started = id === undefined ? undefined : state.tools.get(id);
134
+ if (id === undefined || started === undefined || state.completed.has(id))
135
+ return;
136
+ if (started.call === undefined) {
137
+ started.call = callFor(started.name, data.input);
138
+ events.emit({ type: "tool", phase: "started", id, name: started.name, call: started.call });
139
+ }
140
+ if (type === "session.tool.called")
141
+ return;
142
+ if (started.name === "edit" || started.name === "patch" || started.name === "write") {
143
+ started.call = observedChanges(data.metadata) ?? started.call;
286
144
  }
145
+ const observed = output(data.content);
146
+ const nativeExit = object(data.metadata)?.exit;
147
+ const exit = typeof nativeExit === "number" && Number.isInteger(nativeExit) ? nativeExit : undefined;
148
+ const result = {
149
+ status: type === "session.tool.failed" || (exit !== undefined && exit !== 0) ? "error" : "ok",
150
+ ...(type === "session.tool.failed" ? { message: diagnostic(data.error) } : {}),
151
+ ...(observed === undefined ? {} : { output: observed }),
152
+ ...(exit === undefined ? {} : { exitCode: exit }),
153
+ };
154
+ state.completed.add(id);
155
+ events.emit({ type: "tool", phase: "completed", id, name: started.name, call: started.call, result });
287
156
  return;
288
157
  }
289
- if (event.type === "session.error")
290
- return mapSessionError(properties, events, state);
291
- if (event.type === "session.compacted") {
158
+ if (type === "session.compaction.ended") {
292
159
  events.emit(noteEvent("Context compacted"));
293
160
  return;
294
161
  }
295
- if (event.type === "todo.updated")
296
- return mapTodo(properties, events, state);
297
- if (ignoredEvent(event.type))
162
+ if (type === "session.compaction.failed") {
163
+ events.emit(noteEvent(diagnostic(data.error)));
164
+ return;
165
+ }
166
+ if (type === "session.compaction.started" || type === "session.compaction.delta" || DROPPED.has(type))
298
167
  return;
299
- events.emit({ type: "unknown", kind: typeof event.type === "string" ? event.type : "unknown" });
168
+ events.emit({ type: "unknown", kind: type });
300
169
  }
301
170
  export function createEventState(sessionId) {
302
- return {
303
- ...(sessionId === undefined ? {} : { sessionId }),
304
- assistantParts: new Set(),
305
- reasoningParts: new Set(),
306
- tools: new Map(),
307
- completedTools: new Set(),
308
- };
171
+ return { ...(sessionId === undefined ? {} : { sessionId }), tools: new Map(), completed: new Set() };
309
172
  }