@autonav/core 1.6.0 → 1.8.0

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 (247) hide show
  1. package/README.md +2 -2
  2. package/dist/adapter/index.d.ts +3 -3
  3. package/dist/adapter/index.d.ts.map +1 -1
  4. package/dist/adapter/index.js +3 -3
  5. package/dist/adapter/index.js.map +1 -1
  6. package/dist/adapter/{claude-adapter.d.ts → navigator-adapter.d.ts} +18 -11
  7. package/dist/adapter/navigator-adapter.d.ts.map +1 -0
  8. package/dist/adapter/{claude-adapter.js → navigator-adapter.js} +165 -127
  9. package/dist/adapter/navigator-adapter.js.map +1 -0
  10. package/dist/cli/autonav.d.ts +2 -6
  11. package/dist/cli/autonav.d.ts.map +1 -1
  12. package/dist/cli/autonav.js +32 -53
  13. package/dist/cli/autonav.js.map +1 -1
  14. package/dist/cli/nav-chat.d.ts +2 -1
  15. package/dist/cli/nav-chat.d.ts.map +1 -1
  16. package/dist/cli/nav-chat.js +35 -4
  17. package/dist/cli/nav-chat.js.map +1 -1
  18. package/dist/cli/nav-init.d.ts +2 -1
  19. package/dist/cli/nav-init.d.ts.map +1 -1
  20. package/dist/cli/nav-init.js +12 -4
  21. package/dist/cli/nav-init.js.map +1 -1
  22. package/dist/cli/nav-install.d.ts +2 -1
  23. package/dist/cli/nav-install.d.ts.map +1 -1
  24. package/dist/cli/nav-install.js +4 -2
  25. package/dist/cli/nav-install.js.map +1 -1
  26. package/dist/cli/nav-memento.d.ts +3 -2
  27. package/dist/cli/nav-memento.d.ts.map +1 -1
  28. package/dist/cli/nav-memento.js +12 -6
  29. package/dist/cli/nav-memento.js.map +1 -1
  30. package/dist/cli/nav-mend.d.ts +2 -1
  31. package/dist/cli/nav-mend.d.ts.map +1 -1
  32. package/dist/cli/nav-mend.js +4 -1
  33. package/dist/cli/nav-mend.js.map +1 -1
  34. package/dist/cli/nav-migrate.d.ts +2 -1
  35. package/dist/cli/nav-migrate.d.ts.map +1 -1
  36. package/dist/cli/nav-migrate.js +2 -6
  37. package/dist/cli/nav-migrate.js.map +1 -1
  38. package/dist/cli/nav-query.d.ts +2 -1
  39. package/dist/cli/nav-query.d.ts.map +1 -1
  40. package/dist/cli/nav-query.js +12 -6
  41. package/dist/cli/nav-query.js.map +1 -1
  42. package/dist/cli/nav-standup.d.ts +18 -0
  43. package/dist/cli/nav-standup.d.ts.map +1 -0
  44. package/dist/cli/nav-standup.js +151 -0
  45. package/dist/cli/nav-standup.js.map +1 -0
  46. package/dist/cli/nav-uninstall.d.ts +2 -1
  47. package/dist/cli/nav-uninstall.d.ts.map +1 -1
  48. package/dist/cli/nav-uninstall.js +4 -2
  49. package/dist/cli/nav-uninstall.js.map +1 -1
  50. package/dist/cli/nav-update.d.ts +2 -1
  51. package/dist/cli/nav-update.d.ts.map +1 -1
  52. package/dist/cli/nav-update.js +11 -6
  53. package/dist/cli/nav-update.js.map +1 -1
  54. package/dist/conversation/App.d.ts +11 -2
  55. package/dist/conversation/App.d.ts.map +1 -1
  56. package/dist/conversation/App.js +305 -112
  57. package/dist/conversation/App.js.map +1 -1
  58. package/dist/conversation/index.d.ts +7 -0
  59. package/dist/conversation/index.d.ts.map +1 -1
  60. package/dist/conversation/index.js +17 -2
  61. package/dist/conversation/index.js.map +1 -1
  62. package/dist/conversation/prompts.d.ts +1 -1
  63. package/dist/conversation/prompts.d.ts.map +1 -1
  64. package/dist/conversation/prompts.js +42 -1
  65. package/dist/conversation/prompts.js.map +1 -1
  66. package/dist/harness/chibi-harness.d.ts +36 -0
  67. package/dist/harness/chibi-harness.d.ts.map +1 -0
  68. package/dist/harness/chibi-harness.js +383 -0
  69. package/dist/harness/chibi-harness.js.map +1 -0
  70. package/dist/harness/chibi-plugins/get_plugin_config +64 -0
  71. package/dist/harness/chibi-plugins/query_navigator +114 -0
  72. package/dist/harness/chibi-plugins/submit_answer +38 -0
  73. package/dist/harness/chibi-plugins/update_plugin_config +91 -0
  74. package/dist/harness/claude-code-harness.d.ts +24 -0
  75. package/dist/harness/claude-code-harness.d.ts.map +1 -0
  76. package/dist/harness/claude-code-harness.js +242 -0
  77. package/dist/harness/claude-code-harness.js.map +1 -0
  78. package/dist/harness/ephemeral-home.d.ts +34 -0
  79. package/dist/harness/ephemeral-home.d.ts.map +1 -0
  80. package/dist/harness/ephemeral-home.js +56 -0
  81. package/dist/harness/ephemeral-home.js.map +1 -0
  82. package/dist/harness/factory.d.ts +47 -0
  83. package/dist/harness/factory.d.ts.map +1 -0
  84. package/dist/harness/factory.js +84 -0
  85. package/dist/harness/factory.js.map +1 -0
  86. package/dist/harness/helpers.d.ts +58 -0
  87. package/dist/harness/helpers.d.ts.map +1 -0
  88. package/dist/harness/helpers.js +78 -0
  89. package/dist/harness/helpers.js.map +1 -0
  90. package/dist/harness/index.d.ts +14 -0
  91. package/dist/harness/index.d.ts.map +1 -0
  92. package/dist/harness/index.js +13 -0
  93. package/dist/harness/index.js.map +1 -0
  94. package/dist/harness/opencode-harness.d.ts +79 -0
  95. package/dist/harness/opencode-harness.d.ts.map +1 -0
  96. package/dist/harness/opencode-harness.js +537 -0
  97. package/dist/harness/opencode-harness.js.map +1 -0
  98. package/dist/harness/opencode-tools/get_plugin_config.ts +72 -0
  99. package/dist/harness/opencode-tools/query_navigator.ts +126 -0
  100. package/dist/harness/opencode-tools/submit_answer.ts +40 -0
  101. package/dist/harness/opencode-tools/update_plugin_config.ts +105 -0
  102. package/dist/harness/sandbox.d.ts +59 -0
  103. package/dist/harness/sandbox.d.ts.map +1 -0
  104. package/dist/harness/sandbox.js +152 -0
  105. package/dist/harness/sandbox.js.map +1 -0
  106. package/dist/harness/tool-server.d.ts +50 -0
  107. package/dist/harness/tool-server.d.ts.map +1 -0
  108. package/dist/harness/tool-server.js +27 -0
  109. package/dist/harness/tool-server.js.map +1 -0
  110. package/dist/harness/types.d.ts +168 -0
  111. package/dist/harness/types.d.ts.map +1 -0
  112. package/dist/harness/types.js +12 -0
  113. package/dist/harness/types.js.map +1 -0
  114. package/dist/index.d.ts +3 -2
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +4 -2
  117. package/dist/index.js.map +1 -1
  118. package/dist/interview/App.d.ts +4 -2
  119. package/dist/interview/App.d.ts.map +1 -1
  120. package/dist/interview/App.js +36 -56
  121. package/dist/interview/App.js.map +1 -1
  122. package/dist/interview/index.d.ts +3 -0
  123. package/dist/interview/index.d.ts.map +1 -1
  124. package/dist/interview/index.js +1 -0
  125. package/dist/interview/index.js.map +1 -1
  126. package/dist/interview/prompts.d.ts +3 -1
  127. package/dist/interview/prompts.d.ts.map +1 -1
  128. package/dist/interview/prompts.js +14 -1
  129. package/dist/interview/prompts.js.map +1 -1
  130. package/dist/interview/ui/ChatBanner.d.ts +17 -0
  131. package/dist/interview/ui/ChatBanner.d.ts.map +1 -0
  132. package/dist/interview/ui/ChatBanner.js +30 -0
  133. package/dist/interview/ui/ChatBanner.js.map +1 -0
  134. package/dist/interview/ui/ChatInput.d.ts +36 -0
  135. package/dist/interview/ui/ChatInput.d.ts.map +1 -0
  136. package/dist/interview/ui/ChatInput.js +304 -0
  137. package/dist/interview/ui/ChatInput.js.map +1 -0
  138. package/dist/interview/ui/MarkdownText.d.ts +13 -0
  139. package/dist/interview/ui/MarkdownText.d.ts.map +1 -0
  140. package/dist/interview/ui/MarkdownText.js +107 -0
  141. package/dist/interview/ui/MarkdownText.js.map +1 -0
  142. package/dist/interview/ui/index.d.ts +3 -0
  143. package/dist/interview/ui/index.d.ts.map +1 -1
  144. package/dist/interview/ui/index.js +3 -0
  145. package/dist/interview/ui/index.js.map +1 -1
  146. package/dist/memento/implementer-agent.d.ts +31 -0
  147. package/dist/memento/implementer-agent.d.ts.map +1 -0
  148. package/dist/memento/implementer-agent.js +95 -0
  149. package/dist/memento/implementer-agent.js.map +1 -0
  150. package/dist/memento/index.d.ts +6 -5
  151. package/dist/memento/index.d.ts.map +1 -1
  152. package/dist/memento/index.js +7 -5
  153. package/dist/memento/index.js.map +1 -1
  154. package/dist/memento/loop.d.ts +6 -5
  155. package/dist/memento/loop.d.ts.map +1 -1
  156. package/dist/memento/loop.js +872 -180
  157. package/dist/memento/loop.js.map +1 -1
  158. package/dist/memento/matrix-animation.d.ts +26 -0
  159. package/dist/memento/matrix-animation.d.ts.map +1 -1
  160. package/dist/memento/matrix-animation.js +93 -18
  161. package/dist/memento/matrix-animation.js.map +1 -1
  162. package/dist/memento/nav-protocol.d.ts +2 -2
  163. package/dist/memento/nav-protocol.d.ts.map +1 -1
  164. package/dist/memento/nav-protocol.js +39 -43
  165. package/dist/memento/nav-protocol.js.map +1 -1
  166. package/dist/memento/prompts.d.ts +21 -8
  167. package/dist/memento/prompts.d.ts.map +1 -1
  168. package/dist/memento/prompts.js +79 -39
  169. package/dist/memento/prompts.js.map +1 -1
  170. package/dist/memento/rate-limit.d.ts +85 -0
  171. package/dist/memento/rate-limit.d.ts.map +1 -0
  172. package/dist/memento/rate-limit.js +221 -0
  173. package/dist/memento/rate-limit.js.map +1 -0
  174. package/dist/memento/types.d.ts +6 -6
  175. package/dist/memento/types.d.ts.map +1 -1
  176. package/dist/memento/types.js +3 -3
  177. package/dist/registry.d.ts +35 -0
  178. package/dist/registry.d.ts.map +1 -0
  179. package/dist/registry.js +87 -0
  180. package/dist/registry.js.map +1 -0
  181. package/dist/repo-analyzer/index.d.ts +2 -1
  182. package/dist/repo-analyzer/index.d.ts.map +1 -1
  183. package/dist/repo-analyzer/index.js +6 -17
  184. package/dist/repo-analyzer/index.js.map +1 -1
  185. package/dist/standup/config.d.ts +19 -0
  186. package/dist/standup/config.d.ts.map +1 -0
  187. package/dist/standup/config.js +42 -0
  188. package/dist/standup/config.js.map +1 -0
  189. package/dist/standup/index.d.ts +24 -0
  190. package/dist/standup/index.d.ts.map +1 -0
  191. package/dist/standup/index.js +29 -0
  192. package/dist/standup/index.js.map +1 -0
  193. package/dist/standup/loop.d.ts +36 -0
  194. package/dist/standup/loop.d.ts.map +1 -0
  195. package/dist/standup/loop.js +508 -0
  196. package/dist/standup/loop.js.map +1 -0
  197. package/dist/standup/prompts.d.ts +62 -0
  198. package/dist/standup/prompts.d.ts.map +1 -0
  199. package/dist/standup/prompts.js +211 -0
  200. package/dist/standup/prompts.js.map +1 -0
  201. package/dist/standup/standup-protocol.d.ts +33 -0
  202. package/dist/standup/standup-protocol.d.ts.map +1 -0
  203. package/dist/standup/standup-protocol.js +189 -0
  204. package/dist/standup/standup-protocol.js.map +1 -0
  205. package/dist/standup/types.d.ts +185 -0
  206. package/dist/standup/types.d.ts.map +1 -0
  207. package/dist/standup/types.js +67 -0
  208. package/dist/standup/types.js.map +1 -0
  209. package/dist/tools/cross-nav.d.ts +21 -0
  210. package/dist/tools/cross-nav.d.ts.map +1 -0
  211. package/dist/tools/cross-nav.js +93 -0
  212. package/dist/tools/cross-nav.js.map +1 -0
  213. package/dist/tools/index.d.ts +1 -0
  214. package/dist/tools/index.d.ts.map +1 -1
  215. package/dist/tools/index.js +1 -0
  216. package/dist/tools/index.js.map +1 -1
  217. package/dist/tools/related-navs-config.d.ts +15 -0
  218. package/dist/tools/related-navs-config.d.ts.map +1 -0
  219. package/dist/tools/related-navs-config.js +132 -0
  220. package/dist/tools/related-navs-config.js.map +1 -0
  221. package/dist/tools/related-navs.d.ts +23 -0
  222. package/dist/tools/related-navs.d.ts.map +1 -0
  223. package/dist/tools/related-navs.js +107 -0
  224. package/dist/tools/related-navs.js.map +1 -0
  225. package/dist/tools/response.d.ts +3 -2
  226. package/dist/tools/response.d.ts.map +1 -1
  227. package/dist/tools/response.js +7 -11
  228. package/dist/tools/response.js.map +1 -1
  229. package/dist/tools/self-config.d.ts +2 -1
  230. package/dist/tools/self-config.d.ts.map +1 -1
  231. package/dist/tools/self-config.js +5 -9
  232. package/dist/tools/self-config.js.map +1 -1
  233. package/package.json +7 -4
  234. package/dist/adapter/claude-adapter.d.ts.map +0 -1
  235. package/dist/adapter/claude-adapter.js.map +0 -1
  236. package/dist/memento/state.d.ts +0 -56
  237. package/dist/memento/state.d.ts.map +0 -1
  238. package/dist/memento/state.js +0 -156
  239. package/dist/memento/state.js.map +0 -1
  240. package/dist/memento/worker-agent.d.ts +0 -30
  241. package/dist/memento/worker-agent.d.ts.map +0 -1
  242. package/dist/memento/worker-agent.js +0 -109
  243. package/dist/memento/worker-agent.js.map +0 -1
  244. package/dist/migrations/versions/v1.4.0-rfc2119-skills.d.ts +0 -18
  245. package/dist/migrations/versions/v1.4.0-rfc2119-skills.d.ts.map +0 -1
  246. package/dist/migrations/versions/v1.4.0-rfc2119-skills.js +0 -207
  247. package/dist/migrations/versions/v1.4.0-rfc2119-skills.js.map +0 -1
@@ -0,0 +1,537 @@
1
+ /**
2
+ * OpenCode Harness
3
+ *
4
+ * Adapts OpenCode (https://opencode.ai/) into the universal Harness interface
5
+ * via its TypeScript SDK (@opencode-ai/sdk).
6
+ *
7
+ * Architecture:
8
+ * - A shared opencode server process is started lazily on first run()
9
+ * - Each run() creates an SDK session + ephemeral project dir with custom tools
10
+ * - Events stream via SSE (event.subscribe) and translate to AgentEvent
11
+ * - Custom tools live in .opencode/tools/ as TypeScript files (loaded by OpenCode)
12
+ *
13
+ * The server persists across sessions within a single harness instance.
14
+ * Calling close() on the harness kills the server process.
15
+ */
16
+ import * as fs from "node:fs";
17
+ import * as path from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+ // ephemeral-home is not used for OpenCode — we inject tools directly into
20
+ // the navigator directory because OpenCode requires a real git project context.
21
+ // Marker for tool server sentinel objects (same pattern as ChibiHarness)
22
+ const OPENCODE_TOOL_MARKER = "__opencode_tools__";
23
+ /**
24
+ * Parse an autonav model string into OpenCode's { providerID, modelID } format.
25
+ *
26
+ * Supports:
27
+ * - "provider/model" → { providerID: "provider", modelID: "model" }
28
+ * - "model" → undefined (let OpenCode use its default)
29
+ */
30
+ function parseModel(model) {
31
+ if (!model)
32
+ return undefined;
33
+ const slashIdx = model.indexOf("/");
34
+ if (slashIdx > 0) {
35
+ return {
36
+ providerID: model.slice(0, slashIdx),
37
+ modelID: model.slice(slashIdx + 1),
38
+ };
39
+ }
40
+ // No provider prefix — can't construct the required format, skip
41
+ return undefined;
42
+ }
43
+ /**
44
+ * OpenCode harness session.
45
+ *
46
+ * Uses promptAsync + event.subscribe for streaming. Each prompt fires
47
+ * asynchronously and events are consumed from the SSE stream filtered
48
+ * by session ID.
49
+ */
50
+ class OpenCodeSession {
51
+ config;
52
+ sessionId;
53
+ client; // OpencodeClient (imported dynamically)
54
+ cleanupFn;
55
+ closed = false;
56
+ directory;
57
+ abortController;
58
+ currentIterator = null;
59
+ constructor(config, sessionId, client, cleanupFn, directory) {
60
+ this.config = { ...config };
61
+ this.sessionId = sessionId;
62
+ this.client = client;
63
+ this.cleanupFn = cleanupFn;
64
+ this.directory = directory;
65
+ this.abortController = new AbortController();
66
+ }
67
+ /**
68
+ * Send the initial or follow-up prompt and stream events.
69
+ */
70
+ async *streamPrompt(prompt) {
71
+ // Build prompt body
72
+ const body = {
73
+ parts: [{ type: "text", text: prompt }],
74
+ };
75
+ if (this.config.systemPrompt) {
76
+ body.system = this.config.systemPrompt;
77
+ }
78
+ const model = parseModel(this.config.model);
79
+ if (model) {
80
+ body.model = model;
81
+ }
82
+ // Subscribe to events BEFORE sending the prompt
83
+ const { stream } = await this.client.event.subscribe({
84
+ query: { directory: this.directory },
85
+ });
86
+ // Fire the prompt asynchronously (returns immediately)
87
+ await this.client.session.promptAsync({
88
+ path: { id: this.sessionId },
89
+ body,
90
+ query: { directory: this.directory },
91
+ });
92
+ // Consume SSE events, filter by session ID, translate to AgentEvent
93
+ let totalInputTokens = 0;
94
+ let totalOutputTokens = 0;
95
+ let totalCost = 0;
96
+ try {
97
+ for await (const event of stream) {
98
+ if (this.closed || this.abortController.signal.aborted)
99
+ break;
100
+ const evt = event;
101
+ const eventType = evt.type;
102
+ const props = evt.properties;
103
+ if (!props)
104
+ continue;
105
+ // Filter by session ID where available
106
+ const eventSessionId = props.sessionID ??
107
+ props.part?.sessionID;
108
+ if (eventSessionId && eventSessionId !== this.sessionId)
109
+ continue;
110
+ switch (eventType) {
111
+ case "message.part.updated": {
112
+ const part = props.part;
113
+ if (!part)
114
+ break;
115
+ const partType = part.type;
116
+ if (partType === "text") {
117
+ // Only emit completed text parts (time.end is set)
118
+ const time = part.time;
119
+ const text = part.text;
120
+ if (text && time?.end) {
121
+ yield { type: "text", text };
122
+ }
123
+ }
124
+ else if (partType === "tool") {
125
+ const state = part.state;
126
+ const status = state?.status;
127
+ const toolName = part.tool;
128
+ const callID = part.callID;
129
+ if (status === "completed") {
130
+ const input = state.input || {};
131
+ yield {
132
+ type: "tool_use",
133
+ name: toolName,
134
+ id: callID || "",
135
+ input,
136
+ };
137
+ // Also emit the tool result
138
+ const output = state.output;
139
+ if (output !== undefined) {
140
+ yield {
141
+ type: "tool_result",
142
+ toolUseId: callID || "",
143
+ content: output,
144
+ isError: false,
145
+ };
146
+ }
147
+ }
148
+ else if (status === "error") {
149
+ const input = state.input || {};
150
+ yield {
151
+ type: "tool_use",
152
+ name: toolName,
153
+ id: callID || "",
154
+ input,
155
+ };
156
+ const error = state.error;
157
+ yield {
158
+ type: "tool_result",
159
+ toolUseId: callID || "",
160
+ content: error || "Tool error",
161
+ isError: true,
162
+ };
163
+ }
164
+ }
165
+ else if (partType === "step-finish") {
166
+ const tokens = part.tokens;
167
+ const cost = part.cost;
168
+ if (tokens) {
169
+ totalInputTokens += tokens.input || 0;
170
+ totalOutputTokens += tokens.output || 0;
171
+ }
172
+ if (cost) {
173
+ totalCost += cost;
174
+ }
175
+ }
176
+ break;
177
+ }
178
+ case "session.error": {
179
+ const error = props.error;
180
+ const errorMsg = error?.data?.message ??
181
+ error?.name ??
182
+ "Unknown OpenCode error";
183
+ yield {
184
+ type: "error",
185
+ message: String(errorMsg),
186
+ retryable: error?.data?.isRetryable === true,
187
+ };
188
+ break;
189
+ }
190
+ case "session.idle": {
191
+ // Session finished processing — emit result and break
192
+ yield {
193
+ type: "result",
194
+ success: true,
195
+ usage: {
196
+ inputTokens: totalInputTokens,
197
+ outputTokens: totalOutputTokens,
198
+ },
199
+ costUsd: totalCost || undefined,
200
+ sessionId: this.sessionId,
201
+ };
202
+ return;
203
+ }
204
+ case "session.status": {
205
+ const status = props.status;
206
+ if (status?.type === "idle") {
207
+ yield {
208
+ type: "result",
209
+ success: true,
210
+ usage: {
211
+ inputTokens: totalInputTokens,
212
+ outputTokens: totalOutputTokens,
213
+ },
214
+ costUsd: totalCost || undefined,
215
+ sessionId: this.sessionId,
216
+ };
217
+ return;
218
+ }
219
+ break;
220
+ }
221
+ case "permission.updated": {
222
+ // Auto-approve all permissions for autonav sessions
223
+ const permId = props.id;
224
+ const permSessionId = props.sessionID;
225
+ if (permId && permSessionId === this.sessionId) {
226
+ try {
227
+ await this.client.postSessionIdPermissionsPermissionId({
228
+ path: { id: this.sessionId, permissionID: permId },
229
+ body: { response: "always" },
230
+ query: { directory: this.directory },
231
+ });
232
+ }
233
+ catch {
234
+ // Best-effort permission approval
235
+ }
236
+ }
237
+ break;
238
+ }
239
+ }
240
+ }
241
+ }
242
+ catch (err) {
243
+ // SSE stream error — if not deliberately closed, emit error
244
+ if (!this.closed) {
245
+ const msg = err instanceof Error ? err.message : String(err);
246
+ yield { type: "error", message: `SSE stream error: ${msg}` };
247
+ }
248
+ }
249
+ // If we get here without yielding a result, emit a synthetic one
250
+ yield {
251
+ type: "result",
252
+ success: !this.closed,
253
+ usage: {
254
+ inputTokens: totalInputTokens,
255
+ outputTokens: totalOutputTokens,
256
+ },
257
+ costUsd: totalCost || undefined,
258
+ sessionId: this.sessionId,
259
+ };
260
+ }
261
+ async *[Symbol.asyncIterator]() {
262
+ // The first iteration is started by the constructor's initial prompt
263
+ // which is kicked off in run(). The iterator is set up there.
264
+ if (this.currentIterator) {
265
+ yield* this.currentIterator;
266
+ this.currentIterator = null;
267
+ }
268
+ }
269
+ /**
270
+ * Start streaming for the initial prompt.
271
+ */
272
+ startInitialPrompt(prompt) {
273
+ this.currentIterator = this.streamPrompt(prompt);
274
+ }
275
+ send(prompt) {
276
+ if (this.closed) {
277
+ throw new Error("Session is closed");
278
+ }
279
+ const gen = this.streamPrompt(prompt);
280
+ return {
281
+ [Symbol.asyncIterator]() {
282
+ return gen;
283
+ },
284
+ };
285
+ }
286
+ updateConfig(config) {
287
+ Object.assign(this.config, config);
288
+ }
289
+ async close() {
290
+ this.closed = true;
291
+ this.abortController.abort();
292
+ // Delete the session
293
+ try {
294
+ await this.client.session.delete({
295
+ path: { id: this.sessionId },
296
+ query: { directory: this.directory },
297
+ });
298
+ }
299
+ catch {
300
+ // Best-effort cleanup
301
+ }
302
+ // Clean up ephemeral home
303
+ this.cleanupFn?.();
304
+ this.cleanupFn = null;
305
+ }
306
+ }
307
+ /**
308
+ * OpenCode Harness
309
+ *
310
+ * Manages a shared opencode server and creates sessions that delegate
311
+ * to the OpenCode SDK. Custom tools are injected via .opencode/tools/
312
+ * in ephemeral project directories.
313
+ */
314
+ export class OpenCodeHarness {
315
+ displayName = "opencode";
316
+ server = null;
317
+ client = null; // OpencodeClient
318
+ initPromise = null;
319
+ /**
320
+ * Lazily start the shared opencode server.
321
+ */
322
+ async ensureServer(config) {
323
+ if (this.server && this.client)
324
+ return;
325
+ // Prevent concurrent initialization
326
+ if (this.initPromise) {
327
+ await this.initPromise;
328
+ return;
329
+ }
330
+ this.initPromise = (async () => {
331
+ const { createOpencodeServer, createOpencodeClient, } = await import("@opencode-ai/sdk");
332
+ // Find a random available port
333
+ const port = 10000 + Math.floor(Math.random() * 50000);
334
+ const serverConfig = {};
335
+ // Pass model config if available
336
+ if (config?.model) {
337
+ serverConfig.model = config.model;
338
+ }
339
+ // Set permissions based on sandbox config.
340
+ // When sandbox is set with only readPaths (no writePaths), restrict to
341
+ // read-only by denying edit and bash. Otherwise, allow all for headless operation.
342
+ const isReadOnly = config?.sandbox &&
343
+ config.sandbox.readPaths?.length &&
344
+ !config.sandbox.writePaths?.length;
345
+ serverConfig.permission = {
346
+ edit: isReadOnly ? "deny" : "allow",
347
+ bash: isReadOnly ? "deny" : "allow",
348
+ webfetch: "allow",
349
+ doom_loop: "allow",
350
+ external_directory: "allow",
351
+ };
352
+ const stderr = config?.stderr;
353
+ if (stderr) {
354
+ stderr(`[opencode] Starting server on port ${port}...\n`);
355
+ }
356
+ this.server = await createOpencodeServer({
357
+ port,
358
+ config: serverConfig,
359
+ timeout: 15_000,
360
+ });
361
+ this.client = createOpencodeClient({
362
+ baseUrl: this.server.url,
363
+ });
364
+ if (stderr) {
365
+ stderr(`[opencode] Server ready at ${this.server.url}\n`);
366
+ }
367
+ })();
368
+ await this.initPromise;
369
+ }
370
+ run(config, prompt) {
371
+ // Create the session synchronously (returns HarnessSession),
372
+ // but actual setup is async inside the iterator.
373
+ const harness = this;
374
+ const lazySession = new LazyOpenCodeSession(harness, config, prompt);
375
+ return lazySession;
376
+ }
377
+ /**
378
+ * Internal: Create a fully-initialized OpenCodeSession.
379
+ * Called from LazyOpenCodeSession on first iteration.
380
+ */
381
+ async createSession(config, prompt) {
382
+ await this.ensureServer(config);
383
+ // Use the navigator's actual directory as the OpenCode project directory.
384
+ // OpenCode needs direct access to the project's files (knowledge base, etc.)
385
+ // and requires a real git project context. We inject tools and config into
386
+ // the navigator directory and track them for cleanup.
387
+ const directory = config.cwd || process.cwd();
388
+ const injectedPaths = [];
389
+ // Inject .opencode/tools/ into the navigator directory
390
+ const toolsDir = path.join(directory, ".opencode", "tools");
391
+ fs.mkdirSync(toolsDir, { recursive: true });
392
+ injectedPaths.push(path.join(directory, ".opencode"));
393
+ const srcDir = fileURLToPath(new URL("./opencode-tools", import.meta.url));
394
+ if (fs.existsSync(srcDir)) {
395
+ for (const file of fs.readdirSync(srcDir)) {
396
+ const srcPath = path.join(srcDir, file);
397
+ if (fs.statSync(srcPath).isFile()) {
398
+ fs.copyFileSync(srcPath, path.join(toolsDir, file));
399
+ }
400
+ }
401
+ }
402
+ // Write opencode.json project config with model settings
403
+ const opencodeConfigPath = path.join(directory, "opencode.json");
404
+ const hadExistingConfig = fs.existsSync(opencodeConfigPath);
405
+ const opencodeConfig = {
406
+ $schema: "https://opencode.ai/config.json",
407
+ };
408
+ if (config.model) {
409
+ opencodeConfig.model = config.model;
410
+ }
411
+ fs.writeFileSync(opencodeConfigPath, JSON.stringify(opencodeConfig, null, 2));
412
+ if (!hadExistingConfig) {
413
+ injectedPaths.push(opencodeConfigPath);
414
+ }
415
+ // Create a cleanup function for injected files
416
+ const cleanup = () => {
417
+ for (const p of injectedPaths) {
418
+ try {
419
+ const stat = fs.statSync(p);
420
+ if (stat.isDirectory()) {
421
+ fs.rmSync(p, { recursive: true, force: true });
422
+ }
423
+ else {
424
+ fs.unlinkSync(p);
425
+ }
426
+ }
427
+ catch {
428
+ // Best-effort cleanup
429
+ }
430
+ }
431
+ };
432
+ // Build extra env vars for tool scripts
433
+ const extraEnv = {};
434
+ if (config.cwd) {
435
+ const pluginsPath = path.join(config.cwd, ".claude", "plugins.json");
436
+ if (fs.existsSync(pluginsPath)) {
437
+ extraEnv.AUTONAV_PLUGINS_PATH = pluginsPath;
438
+ }
439
+ }
440
+ const currentDepth = process.env.AUTONAV_QUERY_DEPTH || "0";
441
+ extraEnv.AUTONAV_QUERY_DEPTH = currentDepth;
442
+ // Create an OpenCode session via SDK
443
+ const result = await this.client.session.create({
444
+ body: { title: "autonav" },
445
+ query: { directory },
446
+ });
447
+ const sessionId = result.data?.id;
448
+ if (!sessionId) {
449
+ cleanup();
450
+ throw new Error("Failed to create OpenCode session: no session ID returned");
451
+ }
452
+ if (config.stderr) {
453
+ config.stderr(`[opencode] Session ${sessionId} created\n`);
454
+ }
455
+ const session = new OpenCodeSession(config, sessionId, this.client, cleanup, directory);
456
+ // Start streaming the initial prompt
457
+ session.startInitialPrompt(prompt);
458
+ return session;
459
+ }
460
+ createToolServer(name, tools) {
461
+ // Return a sentinel object that OpenCodeSession can detect.
462
+ // Tools are file-based in OpenCode — the tool definitions here are for
463
+ // reference only. Actual tools are in .opencode/tools/ TypeScript files.
464
+ return {
465
+ server: {
466
+ [OPENCODE_TOOL_MARKER]: true,
467
+ name,
468
+ tools,
469
+ },
470
+ };
471
+ }
472
+ /**
473
+ * Stop the shared server and clean up all resources.
474
+ */
475
+ async close() {
476
+ if (this.server) {
477
+ this.server.close();
478
+ this.server = null;
479
+ }
480
+ this.client = null;
481
+ this.initPromise = null;
482
+ }
483
+ }
484
+ /**
485
+ * Lazy wrapper that defers async initialization until first iteration.
486
+ *
487
+ * Harness.run() must return synchronously, but OpenCode session creation
488
+ * is async (server init, SDK session.create). This wrapper bridges the gap.
489
+ */
490
+ class LazyOpenCodeSession {
491
+ harness;
492
+ config;
493
+ initialPrompt;
494
+ realSession = null;
495
+ initPromise = null;
496
+ constructor(harness, config, prompt) {
497
+ this.harness = harness;
498
+ this.config = config;
499
+ this.initialPrompt = prompt;
500
+ }
501
+ async getSession() {
502
+ if (this.realSession)
503
+ return this.realSession;
504
+ if (!this.initPromise) {
505
+ this.initPromise = this.harness.createSession(this.config, this.initialPrompt);
506
+ }
507
+ this.realSession = await this.initPromise;
508
+ return this.realSession;
509
+ }
510
+ async *[Symbol.asyncIterator]() {
511
+ const session = await this.getSession();
512
+ yield* session;
513
+ }
514
+ send(prompt) {
515
+ const self = this;
516
+ return {
517
+ async *[Symbol.asyncIterator]() {
518
+ const session = await self.getSession();
519
+ yield* session.send(prompt);
520
+ },
521
+ };
522
+ }
523
+ updateConfig(config) {
524
+ if (this.realSession) {
525
+ this.realSession.updateConfig(config);
526
+ }
527
+ else {
528
+ Object.assign(this.config, config);
529
+ }
530
+ }
531
+ async close() {
532
+ if (this.realSession) {
533
+ await this.realSession.close();
534
+ }
535
+ }
536
+ }
537
+ //# sourceMappingURL=opencode-harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-harness.js","sourceRoot":"","sources":["../../src/harness/opencode-harness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * get_plugin_config — OpenCode custom tool
3
+ *
4
+ * Reads plugin configuration from $AUTONAV_PLUGINS_PATH.
5
+ *
6
+ * Runs inside OpenCode's Bun runtime via .opencode/tools/.
7
+ */
8
+ import { tool } from "@opencode-ai/plugin"
9
+ import { readFileSync, existsSync } from "node:fs"
10
+
11
+ export default tool({
12
+ name: "get_plugin_config",
13
+ description:
14
+ "Read your current plugin configuration. Use this to check what plugins are enabled, see notification settings, or verify your current schedule.",
15
+ args: {
16
+ plugin: tool.schema
17
+ .string()
18
+ .describe(
19
+ 'The plugin to read configuration for ("slack", "signal", "github", "email", or "all")',
20
+ ),
21
+ },
22
+ async execute(input: { plugin: string }) {
23
+ const { plugin } = input
24
+
25
+ if (!plugin) {
26
+ return JSON.stringify({
27
+ success: false,
28
+ error: "Missing required field: plugin",
29
+ })
30
+ }
31
+
32
+ const configPath = process.env.AUTONAV_PLUGINS_PATH
33
+ if (!configPath) {
34
+ return JSON.stringify({
35
+ success: false,
36
+ error: "AUTONAV_PLUGINS_PATH not set. Plugin configuration unavailable.",
37
+ })
38
+ }
39
+
40
+ if (!existsSync(configPath)) {
41
+ return JSON.stringify({
42
+ success: false,
43
+ error: "Plugin configuration file not found.",
44
+ })
45
+ }
46
+
47
+ try {
48
+ const config = JSON.parse(readFileSync(configPath, "utf-8"))
49
+
50
+ if (plugin === "all") {
51
+ return JSON.stringify({ success: true, plugin: "all", config })
52
+ }
53
+
54
+ const section = config[plugin]
55
+ if (section === undefined || section === null) {
56
+ return JSON.stringify({
57
+ success: true,
58
+ plugin,
59
+ config: { enabled: false, config: {} },
60
+ })
61
+ }
62
+
63
+ return JSON.stringify({ success: true, plugin, config: section })
64
+ } catch (err) {
65
+ const msg = err instanceof Error ? err.message : String(err)
66
+ return JSON.stringify({
67
+ success: false,
68
+ error: `Failed to read plugin config: ${msg}`,
69
+ })
70
+ }
71
+ },
72
+ })