indusagi-coding-agent 0.1.23 → 0.1.25

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 (236) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/README.md +2 -0
  3. package/dist/cli/args.d.ts +117 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +221 -52
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/config-selector.d.ts +58 -2
  8. package/dist/cli/config-selector.d.ts.map +1 -1
  9. package/dist/cli/config-selector.js +130 -12
  10. package/dist/cli/config-selector.js.map +1 -1
  11. package/dist/cli/file-processor.d.ts +70 -2
  12. package/dist/cli/file-processor.d.ts.map +1 -1
  13. package/dist/cli/file-processor.js +240 -15
  14. package/dist/cli/file-processor.js.map +1 -1
  15. package/dist/cli/list-models.d.ts +63 -3
  16. package/dist/cli/list-models.d.ts.map +1 -1
  17. package/dist/cli/list-models.js +202 -27
  18. package/dist/cli/list-models.js.map +1 -1
  19. package/dist/cli/login-handler.d.ts +82 -8
  20. package/dist/cli/login-handler.d.ts.map +1 -1
  21. package/dist/cli/login-handler.js +410 -77
  22. package/dist/cli/login-handler.js.map +1 -1
  23. package/dist/cli/session-picker.d.ts +74 -2
  24. package/dist/cli/session-picker.d.ts.map +1 -1
  25. package/dist/cli/session-picker.js +236 -12
  26. package/dist/cli/session-picker.js.map +1 -1
  27. package/dist/core/agent-session.d.ts +214 -9
  28. package/dist/core/agent-session.d.ts.map +1 -1
  29. package/dist/core/agent-session.js +214 -9
  30. package/dist/core/agent-session.js.map +1 -1
  31. package/dist/core/bash-executor.d.ts +302 -12
  32. package/dist/core/bash-executor.d.ts.map +1 -1
  33. package/dist/core/bash-executor.js +302 -12
  34. package/dist/core/bash-executor.js.map +1 -1
  35. package/dist/core/diagnostics.d.ts +191 -0
  36. package/dist/core/diagnostics.d.ts.map +1 -1
  37. package/dist/core/diagnostics.js +142 -0
  38. package/dist/core/diagnostics.js.map +1 -1
  39. package/dist/core/discover-packages.d.ts +6 -0
  40. package/dist/core/discover-packages.d.ts.map +1 -0
  41. package/dist/core/discover-packages.js +62 -0
  42. package/dist/core/discover-packages.js.map +1 -0
  43. package/dist/core/event-bus.d.ts +146 -0
  44. package/dist/core/event-bus.d.ts.map +1 -1
  45. package/dist/core/event-bus.js +93 -0
  46. package/dist/core/event-bus.js.map +1 -1
  47. package/dist/core/export-html/ansi-to-html.d.ts +4 -0
  48. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  49. package/dist/core/export-html/ansi-to-html.js +4 -0
  50. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  51. package/dist/core/export-html/index.d.ts +128 -0
  52. package/dist/core/export-html/index.d.ts.map +1 -1
  53. package/dist/core/export-html/index.js +128 -0
  54. package/dist/core/export-html/index.js.map +1 -1
  55. package/dist/core/export-html/tool-renderer.d.ts +4 -0
  56. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  57. package/dist/core/export-html/tool-renderer.js +4 -0
  58. package/dist/core/export-html/tool-renderer.js.map +1 -1
  59. package/dist/core/keybindings.d.ts +142 -0
  60. package/dist/core/keybindings.d.ts.map +1 -1
  61. package/dist/core/keybindings.js +142 -0
  62. package/dist/core/keybindings.js.map +1 -1
  63. package/dist/core/model-registry.d.ts +98 -1
  64. package/dist/core/model-registry.d.ts.map +1 -1
  65. package/dist/core/model-registry.js +98 -1
  66. package/dist/core/model-registry.js.map +1 -1
  67. package/dist/core/model-resolver.d.ts +99 -1
  68. package/dist/core/model-resolver.d.ts.map +1 -1
  69. package/dist/core/model-resolver.js +99 -1
  70. package/dist/core/model-resolver.js.map +1 -1
  71. package/dist/core/prompt-templates.js.map +1 -1
  72. package/dist/core/sdk.d.ts.map +1 -1
  73. package/dist/core/sdk.js +2 -0
  74. package/dist/core/sdk.js.map +1 -1
  75. package/dist/core/session-manager.d.ts +127 -0
  76. package/dist/core/session-manager.d.ts.map +1 -1
  77. package/dist/core/session-manager.js +125 -0
  78. package/dist/core/session-manager.js.map +1 -1
  79. package/dist/core/skills.js.map +1 -1
  80. package/dist/core/subagents.js.map +1 -1
  81. package/dist/core/tools/bash.d.ts +391 -11
  82. package/dist/core/tools/bash.d.ts.map +1 -1
  83. package/dist/core/tools/bash.js +269 -2
  84. package/dist/core/tools/bash.js.map +1 -1
  85. package/dist/core/tools/bg-process.d.ts +49 -0
  86. package/dist/core/tools/bg-process.d.ts.map +1 -0
  87. package/dist/core/tools/bg-process.js +69 -0
  88. package/dist/core/tools/bg-process.js.map +1 -0
  89. package/dist/core/tools/edit.d.ts +284 -6
  90. package/dist/core/tools/edit.d.ts.map +1 -1
  91. package/dist/core/tools/edit.js +238 -0
  92. package/dist/core/tools/edit.js.map +1 -1
  93. package/dist/core/tools/find.d.ts +169 -5
  94. package/dist/core/tools/find.d.ts.map +1 -1
  95. package/dist/core/tools/find.js +136 -0
  96. package/dist/core/tools/find.js.map +1 -1
  97. package/dist/core/tools/grep.d.ts +285 -5
  98. package/dist/core/tools/grep.d.ts.map +1 -1
  99. package/dist/core/tools/grep.js +247 -0
  100. package/dist/core/tools/grep.js.map +1 -1
  101. package/dist/core/tools/index.d.ts +45 -0
  102. package/dist/core/tools/index.d.ts.map +1 -1
  103. package/dist/core/tools/index.js +15 -0
  104. package/dist/core/tools/index.js.map +1 -1
  105. package/dist/core/tools/ls.d.ts +6 -0
  106. package/dist/core/tools/ls.d.ts.map +1 -1
  107. package/dist/core/tools/ls.js +6 -0
  108. package/dist/core/tools/ls.js.map +1 -1
  109. package/dist/core/tools/read.d.ts +308 -7
  110. package/dist/core/tools/read.d.ts.map +1 -1
  111. package/dist/core/tools/read.js +231 -0
  112. package/dist/core/tools/read.js.map +1 -1
  113. package/dist/core/tools/registry.d.ts +17 -0
  114. package/dist/core/tools/registry.d.ts.map +1 -0
  115. package/dist/core/tools/registry.js +108 -0
  116. package/dist/core/tools/registry.js.map +1 -0
  117. package/dist/core/tools/webfetch.d.ts +118 -3
  118. package/dist/core/tools/webfetch.d.ts.map +1 -1
  119. package/dist/core/tools/webfetch.js +118 -3
  120. package/dist/core/tools/webfetch.js.map +1 -1
  121. package/dist/core/tools/websearch.d.ts +130 -3
  122. package/dist/core/tools/websearch.d.ts.map +1 -1
  123. package/dist/core/tools/websearch.js +130 -3
  124. package/dist/core/tools/websearch.js.map +1 -1
  125. package/dist/core/tools/write.d.ts +251 -5
  126. package/dist/core/tools/write.d.ts.map +1 -1
  127. package/dist/core/tools/write.js +210 -0
  128. package/dist/core/tools/write.js.map +1 -1
  129. package/dist/main.d.ts.map +1 -1
  130. package/dist/main.js +12 -1
  131. package/dist/main.js.map +1 -1
  132. package/dist/modes/interactive/components/assistant-message.d.ts +164 -1
  133. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  134. package/dist/modes/interactive/components/assistant-message.js +164 -1
  135. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  136. package/dist/modes/interactive/components/bash-execution.d.ts +297 -1
  137. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  138. package/dist/modes/interactive/components/bash-execution.js +297 -1
  139. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  140. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  141. package/dist/modes/interactive/components/tool-execution.js +251 -1
  142. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  143. package/dist/modes/interactive/components/user-message.d.ts +186 -1
  144. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  145. package/dist/modes/interactive/components/user-message.js +186 -1
  146. package/dist/modes/interactive/components/user-message.js.map +1 -1
  147. package/dist/modes/interactive/interactive-mode.d.ts +1567 -13
  148. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  149. package/dist/modes/interactive/interactive-mode.js +1567 -13
  150. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  151. package/dist/modes/interactive/theme/theme.d.ts +422 -0
  152. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  153. package/dist/modes/interactive/theme/theme.js +422 -0
  154. package/dist/modes/interactive/theme/theme.js.map +1 -1
  155. package/dist/modes/print-mode.d.ts +538 -5
  156. package/dist/modes/print-mode.d.ts.map +1 -1
  157. package/dist/modes/print-mode.js +538 -5
  158. package/dist/modes/print-mode.js.map +1 -1
  159. package/dist/modes/rpc/rpc-client.d.ts +921 -8
  160. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  161. package/dist/modes/rpc/rpc-client.js +921 -8
  162. package/dist/modes/rpc/rpc-client.js.map +1 -1
  163. package/dist/modes/rpc/rpc-mode.d.ts +802 -9
  164. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  165. package/dist/modes/rpc/rpc-mode.js +802 -9
  166. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  167. package/dist/modes/rpc/rpc-types.d.ts +356 -3
  168. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  169. package/dist/modes/rpc/rpc-types.js +356 -3
  170. package/dist/modes/rpc/rpc-types.js.map +1 -1
  171. package/dist/modes/shared.d.ts +386 -0
  172. package/dist/modes/shared.d.ts.map +1 -0
  173. package/dist/modes/shared.js +543 -0
  174. package/dist/modes/shared.js.map +1 -0
  175. package/dist/utils/array.d.ts +389 -0
  176. package/dist/utils/array.d.ts.map +1 -0
  177. package/dist/utils/array.js +585 -0
  178. package/dist/utils/array.js.map +1 -0
  179. package/dist/utils/color-formatter.d.ts +318 -0
  180. package/dist/utils/color-formatter.d.ts.map +1 -0
  181. package/dist/utils/color-formatter.js +442 -0
  182. package/dist/utils/color-formatter.js.map +1 -0
  183. package/dist/utils/data-transformer.d.ts +326 -0
  184. package/dist/utils/data-transformer.d.ts.map +1 -0
  185. package/dist/utils/data-transformer.js +512 -0
  186. package/dist/utils/data-transformer.js.map +1 -0
  187. package/dist/utils/date-formatter.d.ts +281 -0
  188. package/dist/utils/date-formatter.d.ts.map +1 -0
  189. package/dist/utils/date-formatter.js +503 -0
  190. package/dist/utils/date-formatter.js.map +1 -0
  191. package/dist/utils/error-handler.d.ts +541 -0
  192. package/dist/utils/error-handler.d.ts.map +1 -0
  193. package/dist/utils/error-handler.js +726 -0
  194. package/dist/utils/error-handler.js.map +1 -0
  195. package/dist/utils/file-operations.d.ts +297 -0
  196. package/dist/utils/file-operations.d.ts.map +1 -0
  197. package/dist/utils/file-operations.js +505 -0
  198. package/dist/utils/file-operations.js.map +1 -0
  199. package/dist/utils/frontmatter.d.ts +268 -6
  200. package/dist/utils/frontmatter.d.ts.map +1 -1
  201. package/dist/utils/frontmatter.js +500 -21
  202. package/dist/utils/frontmatter.js.map +1 -1
  203. package/dist/utils/json-formatter.d.ts +259 -0
  204. package/dist/utils/json-formatter.d.ts.map +1 -0
  205. package/dist/utils/json-formatter.js +517 -0
  206. package/dist/utils/json-formatter.js.map +1 -0
  207. package/dist/utils/logger.d.ts +176 -0
  208. package/dist/utils/logger.d.ts.map +1 -0
  209. package/dist/utils/logger.js +346 -0
  210. package/dist/utils/logger.js.map +1 -0
  211. package/dist/utils/markdown-formatter.d.ts +211 -0
  212. package/dist/utils/markdown-formatter.d.ts.map +1 -0
  213. package/dist/utils/markdown-formatter.js +482 -0
  214. package/dist/utils/markdown-formatter.js.map +1 -0
  215. package/dist/utils/path-validator.d.ts +603 -0
  216. package/dist/utils/path-validator.d.ts.map +1 -0
  217. package/dist/utils/path-validator.js +870 -0
  218. package/dist/utils/path-validator.js.map +1 -0
  219. package/dist/utils/string-formatter.d.ts +609 -0
  220. package/dist/utils/string-formatter.d.ts.map +1 -0
  221. package/dist/utils/string-formatter.js +806 -0
  222. package/dist/utils/string-formatter.js.map +1 -0
  223. package/dist/utils/type-guards.d.ts +629 -0
  224. package/dist/utils/type-guards.d.ts.map +1 -0
  225. package/dist/utils/type-guards.js +662 -0
  226. package/dist/utils/type-guards.js.map +1 -0
  227. package/docs/COMPLETE-GUIDE.md +300 -0
  228. package/docs/COMPREHENSIVE-CLI-SUMMARY.md +900 -0
  229. package/docs/MODES-ARCHITECTURE.md +565 -0
  230. package/docs/PRINT-MODE-GUIDE.md +456 -0
  231. package/docs/RPC-GUIDE.md +705 -0
  232. package/docs/UTILS-IMPLEMENTATION-SUMMARY.md +647 -0
  233. package/docs/UTILS-MODULE-OVERVIEW.md +1480 -0
  234. package/docs/UTILS-QA-CHECKLIST.md +1061 -0
  235. package/docs/UTILS-USAGE-GUIDE.md +1419 -0
  236. package/package.json +7 -3
@@ -1,14 +1,467 @@
1
1
  /**
2
- * RPC Client for programmatic access to the coding agent.
2
+ * RPC CLIENT - TYPED INTERFACE FOR AGENT RPC PROTOCOL
3
+ *
4
+ * ============================================================================
5
+ * OVERVIEW
6
+ * ============================================================================
7
+ *
8
+ * This module provides a complete TypeScript/Node.js client for the coding
9
+ * agent's RPC protocol. It:
10
+ *
11
+ * - Spawns the agent in RPC mode as a subprocess
12
+ * - Handles JSON serialization/deserialization automatically
13
+ * - Provides a fully-typed API matching rpc-types.ts
14
+ * - Manages request/response correlation with unique IDs
15
+ * - Supports event subscription for streaming responses
16
+ * - Handles errors gracefully with type-safe responses
17
+ *
18
+ * ============================================================================
19
+ * CLIENT LIFECYCLE
20
+ * ============================================================================
21
+ *
22
+ * Creation:
23
+ * const client = new RpcClient({ cliPath: "dist/cli.js" });
24
+ *
25
+ * Startup:
26
+ * await client.start();
27
+ * // Spawns agent in RPC mode, waits for initialization
28
+ *
29
+ * Usage:
30
+ * const state = await client.getState();
31
+ * await client.prompt("Your prompt here");
32
+ * const events = await client.collectEvents();
33
+ *
34
+ * Shutdown:
35
+ * await client.stop();
36
+ * // Terminates agent process, cleans up resources
37
+ *
38
+ * ============================================================================
39
+ * USAGE PATTERNS
40
+ * ============================================================================
41
+ *
42
+ * PATTERN 1: Simple Command
43
+ * ──────────────────────────────────────────────────────────────────────
44
+ * // Execute a command and wait for response
45
+ * const client = new RpcClient();
46
+ * await client.start();
47
+ * const state = await client.getState();
48
+ * console.log(`Session ID: ${state.sessionId}`);
49
+ * await client.stop();
50
+ *
51
+ * PATTERN 2: Prompt with Event Subscription
52
+ * ──────────────────────────────────────────────────────────────────────
53
+ * // Send prompt and listen for events
54
+ * const client = new RpcClient();
55
+ * await client.start();
56
+ *
57
+ * client.onEvent((event) => {
58
+ * if (event.type === "message" && event.role === "assistant") {
59
+ * console.log("Assistant:", event.content[0].text);
60
+ * }
61
+ * if (event.type === "tool_call") {
62
+ * console.log("Calling tool:", event.toolName);
63
+ * }
64
+ * });
65
+ *
66
+ * await client.prompt("What files are in /tmp?");
67
+ * await client.waitForIdle();
68
+ * await client.stop();
69
+ *
70
+ * PATTERN 3: Prompt and Collect All Events
71
+ * ──────────────────────────────────────────────────────────────────────
72
+ * // Send prompt and get all events in one call
73
+ * const client = new RpcClient();
74
+ * await client.start();
75
+ *
76
+ * const events = await client.promptAndWait("Explain the code", undefined, 30000);
77
+ * events.forEach((event) => {
78
+ * console.log(`Event: ${event.type}`);
79
+ * });
80
+ *
81
+ * await client.stop();
82
+ *
83
+ * PATTERN 4: Model Switching
84
+ * ──────────────────────────────────────────────────────────────────────
85
+ * // Get available models and switch
86
+ * const client = new RpcClient({ provider: "anthropic" });
87
+ * await client.start();
88
+ *
89
+ * const models = await client.getAvailableModels();
90
+ * console.log(`Available models: ${models.length}`);
91
+ *
92
+ * if (models.length > 0) {
93
+ * await client.setModel(models[0].provider, models[0].id);
94
+ * const state = await client.getState();
95
+ * console.log(`Switched to: ${state.model?.id}`);
96
+ * }
97
+ *
98
+ * await client.stop();
99
+ *
100
+ * PATTERN 5: Sequential Prompts
101
+ * ──────────────────────────────────────────────────────────────────────
102
+ * // Send multiple prompts sequentially
103
+ * const client = new RpcClient();
104
+ * await client.start();
105
+ *
106
+ * const prompts = ["First question", "Follow-up", "Another question"];
107
+ * for (const prompt of prompts) {
108
+ * const events = await client.promptAndWait(prompt);
109
+ * const lastMsg = events
110
+ * .filter(e => e.type === "message" && e.role === "assistant")
111
+ * .pop();
112
+ * console.log("Response:", lastMsg?.content[0]?.text);
113
+ * }
114
+ *
115
+ * await client.stop();
116
+ *
117
+ * PATTERN 6: Error Handling
118
+ * ──────────────────────────────────────────────────────────────────────
119
+ * // Gracefully handle errors
120
+ * const client = new RpcClient();
121
+ * try {
122
+ * await client.start();
123
+ * await client.setModel("anthropic", "nonexistent-model");
124
+ * } catch (error) {
125
+ * console.error(`Client error: ${error.message}`);
126
+ * // Error includes stderr output for debugging
127
+ * } finally {
128
+ * await client.stop();
129
+ * }
130
+ *
131
+ * PATTERN 7: Timeout Handling
132
+ * ──────────────────────────────────────────────────────────────────────
133
+ * // Prompt with custom timeout
134
+ * const client = new RpcClient();
135
+ * await client.start();
136
+ * try {
137
+ * const events = await client.promptAndWait(
138
+ * "Long-running operation",
139
+ * undefined,
140
+ * 120000 // 2 minute timeout
141
+ * );
142
+ * } catch (error) {
143
+ * console.error("Timeout or error:", error.message);
144
+ * }
145
+ * await client.stop();
146
+ *
147
+ * PATTERN 8: Export and Save Session
148
+ * ──────────────────────────────────────────────────────────────────────
149
+ * // Export session to HTML
150
+ * const client = new RpcClient();
151
+ * await client.start();
152
+ * await client.prompt("Test prompt");
153
+ * await client.waitForIdle();
154
+ * const result = await client.exportHtml("/tmp/session.html");
155
+ * console.log(`Exported to: ${result.path}`);
156
+ * await client.stop();
157
+ *
158
+ * ============================================================================
159
+ * CONFIGURATION OPTIONS (RpcClientOptions)
160
+ * ============================================================================
161
+ *
162
+ * interface RpcClientOptions {
163
+ * // Path to CLI entry point
164
+ * // Default: searches for "dist/cli.js"
165
+ * // Can be absolute or relative path
166
+ * cliPath?: string;
167
+ *
168
+ * // Working directory for agent process
169
+ * // Default: current working directory
170
+ * // Used for relative path resolution in agent
171
+ * cwd?: string;
172
+ *
173
+ * // Environment variables for agent process
174
+ * // Merged with process.env
175
+ * // Can override API keys, model settings, etc.
176
+ * env?: Record<string, string>;
177
+ *
178
+ * // Provider to use
179
+ * // Options: "anthropic", "openai", "google", etc.
180
+ * // Passed to agent via CLI arguments
181
+ * provider?: string;
182
+ *
183
+ * // Model ID to use initially
184
+ * // Provider-specific format
185
+ * // Passed to agent via CLI arguments
186
+ * model?: string;
187
+ *
188
+ * // Additional CLI arguments
189
+ * // Passed to agent process as-is
190
+ * // Example: ["--session", "abc123"]
191
+ * args?: string[];
192
+ * }
193
+ *
194
+ * Usage:
195
+ * const client = new RpcClient({
196
+ * cliPath: "/opt/agent/dist/cli.js",
197
+ * cwd: "/home/user/project",
198
+ * env: { ANTHROPIC_API_KEY: "sk-..." },
199
+ * provider: "anthropic",
200
+ * model: "claude-3-5-sonnet",
201
+ * args: ["--thinking", "max"]
202
+ * });
203
+ *
204
+ * ============================================================================
205
+ * EVENT SUBSCRIPTION
206
+ * ============================================================================
207
+ *
208
+ * Subscribe to all agent events:
209
+ * const unsubscribe = client.onEvent((event) => {
210
+ * console.log("Event:", event.type);
211
+ * });
212
+ * // Later, to unsubscribe:
213
+ * unsubscribe();
214
+ *
215
+ * Event Types:
216
+ * - agent_start: Agent began processing
217
+ * - message: User or assistant message
218
+ * - tool_call: Agent called a tool
219
+ * - tool_output: Tool returned output
220
+ * - tool_error: Tool failed
221
+ * - agent_end: Agent finished processing
222
+ * - compaction_start: Context compaction began
223
+ * - compaction_complete: Context compaction finished
224
+ * - extension_ui_request: Extension requesting user input
225
+ * - extension_error: Extension threw error
226
+ * - hook_error: Hook threw error
227
+ *
228
+ * Filtering Events:
229
+ * client.onEvent((event) => {
230
+ * if (event.type === "message" && event.role === "assistant") {
231
+ * // Handle assistant message
232
+ * }
233
+ * if (event.type === "tool_call") {
234
+ * // Handle tool execution
235
+ * }
236
+ * });
237
+ *
238
+ * ============================================================================
239
+ * HELPER METHODS
240
+ * ============================================================================
3
241
  *
4
- * Spawns the agent in RPC mode and provides a typed API for all operations.
242
+ * waitForIdle(timeout?: number): Promise<void>
243
+ * Wait for agent to finish processing.
244
+ * Resolves when agent_end event received.
245
+ * Timeout default: 60 seconds
246
+ * Throws: Error if timeout exceeded
247
+ * Use Case: Waiting for prompt completion
248
+ *
249
+ * collectEvents(timeout?: number): Promise<AgentEvent[]>
250
+ * Collect all events until agent becomes idle.
251
+ * Returns: Array of events in order
252
+ * Timeout default: 60 seconds
253
+ * Throws: Error if timeout exceeded
254
+ * Use Case: Getting full event history of prompt
255
+ *
256
+ * promptAndWait(message, images?, timeout?): Promise<AgentEvent[]>
257
+ * Send prompt and wait for completion in one call.
258
+ * Returns: All events from that prompt
259
+ * Equivalent to:
260
+ * const eventsPromise = client.collectEvents(timeout);
261
+ * await client.prompt(message, images);
262
+ * return eventsPromise;
263
+ * Use Case: Simple prompt-response pattern
264
+ *
265
+ * getStderr(): string
266
+ * Get collected stderr output from agent process.
267
+ * Useful for debugging client startup failures.
268
+ * Example:
269
+ * try { await client.start(); }
270
+ * catch (e) { console.log(client.getStderr()); }
271
+ *
272
+ * ============================================================================
273
+ * ERROR HANDLING
274
+ * ============================================================================
275
+ *
276
+ * Command Errors:
277
+ * // RPC commands that fail throw with error.message
278
+ * try {
279
+ * await client.setModel("anthropic", "nonexistent");
280
+ * } catch (error) {
281
+ * console.error(error.message); // "Model not found: anthropic/nonexistent"
282
+ * }
283
+ *
284
+ * Startup Errors:
285
+ * // Process failures throw error with stderr
286
+ * try {
287
+ * await client.start();
288
+ * } catch (error) {
289
+ * console.error(error.message); // Includes stderr output
290
+ * console.error(client.getStderr()); // Additional debugging
291
+ * }
292
+ *
293
+ * Timeout Errors:
294
+ * // Operations that exceed timeout throw error
295
+ * try {
296
+ * await client.waitForIdle(5000);
297
+ * } catch (error) {
298
+ * console.error(error.message); // "Timeout waiting for agent to become idle"
299
+ * }
300
+ *
301
+ * Graceful Degradation:
302
+ * // Always try to stop client even if errors occur
303
+ * const client = new RpcClient();
304
+ * try {
305
+ * await client.start();
306
+ * // ... use client ...
307
+ * } finally {
308
+ * await client.stop(); // Safe even if not started
309
+ * }
310
+ *
311
+ * ============================================================================
312
+ * INTERNAL IMPLEMENTATION DETAILS
313
+ * ============================================================================
314
+ *
315
+ * Spawn Configuration:
316
+ * - Spawns "node" with CLI path and --mode rpc
317
+ * - stdio: ["pipe", "pipe", "pipe"] (captures all streams)
318
+ * - Inherits environment variables with custom merges
319
+ * - Works directory: configurable via options.cwd
320
+ *
321
+ * Communication Protocol:
322
+ * - Sends commands as JSON lines on stdin
323
+ * - Reads responses and events as JSON lines on stdout
324
+ * - Errors/diagnostics on stderr (collected)
325
+ * - readline interface handles line buffering
326
+ *
327
+ * Request Correlation:
328
+ * - Each command gets unique ID: "req_" + incrementing number
329
+ * - Responses matched to commands by ID
330
+ * - Pending requests stored in Map<id, {resolve, reject}>
331
+ * - 30-second timeout per command by default
332
+ *
333
+ * Event Routing:
334
+ * - Non-response messages routed to event listeners
335
+ * - Listeners called synchronously when event arrives
336
+ * - Multiple listeners supported
337
+ * - All events delivered even if listener throws
338
+ *
339
+ * Subprocess Cleanup:
340
+ * - Graceful: kill("SIGTERM") with 1-second wait
341
+ * - Force: kill("SIGKILL") if SIGTERM fails
342
+ * - Exit event waits for process cleanup
343
+ * - Pending requests rejected on force kill
344
+ *
345
+ * ============================================================================
346
+ * BASED ON RPCLIENT IMPLEMENTATION
347
+ * ============================================================================
348
+ *
349
+ * This client provides a complete, type-safe TypeScript interface to the
350
+ * agent's RPC protocol. It handles all JSON marshaling, process management,
351
+ * and error handling transparently.
352
+ *
353
+ * Use this in Node.js applications, tools, or servers that need programmatic
354
+ * access to the agent's capabilities.
5
355
  */
6
356
  import { spawn } from "node:child_process";
7
357
  import * as readline from "node:readline";
8
358
  // ============================================================================
9
359
  // RPC Client
10
360
  // ============================================================================
361
+ /**
362
+ * RPC Client for programmatic access to the coding agent.
363
+ *
364
+ * Manages the agent subprocess, handles JSON-RPC protocol communication,
365
+ * correlates requests/responses, and provides a fully-typed API.
366
+ *
367
+ * ============================================================================
368
+ * LIFECYCLE
369
+ * ============================================================================
370
+ *
371
+ * 1. Constructor: Create client with optional configuration
372
+ * const client = new RpcClient({ cliPath: "dist/cli.js" });
373
+ *
374
+ * 2. start(): Spawn agent process, wait for initialization
375
+ * await client.start(); // Agent ready to accept commands
376
+ *
377
+ * 3. Use: Send commands, subscribe to events
378
+ * await client.prompt("Your prompt");
379
+ * client.onEvent(handler);
380
+ *
381
+ * 4. stop(): Gracefully terminate subprocess
382
+ * await client.stop(); // Clean shutdown
383
+ *
384
+ * ============================================================================
385
+ * STATE MACHINE
386
+ * ============================================================================
387
+ *
388
+ * [NOT_STARTED]
389
+ * ↓ constructor()
390
+ * [STOPPED]
391
+ * ↓ start()
392
+ * [RUNNING] ← Can send commands, subscribe to events
393
+ * ↓ stop()
394
+ * [STOPPED]
395
+ * ↓ (error during start)
396
+ * [FAILED]
397
+ *
398
+ * ============================================================================
399
+ * PROPERTY DESCRIPTIONS
400
+ * ============================================================================
401
+ *
402
+ * process: ChildProcess | null
403
+ * The spawned agent subprocess.
404
+ * Non-null while running, null before start() or after stop().
405
+ * Access via process.stdin for writing commands.
406
+ * Access via process.stdout for reading responses/events.
407
+ *
408
+ * rl: readline.Interface | null
409
+ * Line reader for parsing JSON lines from agent stdout.
410
+ * Non-null while running.
411
+ * Used internally for line buffering and JSON parsing.
412
+ *
413
+ * eventListeners: RpcEventListener[]
414
+ * Array of callback functions subscribed to events.
415
+ * Added via onEvent(), removed via returned unsubscribe function.
416
+ * Called synchronously as events arrive.
417
+ * Can be modified during event handling.
418
+ *
419
+ * pendingRequests: Map<id, {resolve, reject}>
420
+ * Maps request ID → response handler.
421
+ * Used to correlate responses to commands.
422
+ * Entries added when command sent, removed when response received.
423
+ * 30-second timeout per request.
424
+ *
425
+ * requestId: number
426
+ * Counter for generating unique request IDs.
427
+ * Incremented for each command sent.
428
+ * Format: "req_" + requestId
429
+ *
430
+ * stderr: string
431
+ * Accumulated stderr output from agent process.
432
+ * Appended as data received from process.stderr.
433
+ * Used for debugging client startup failures.
434
+ * Accessible via getStderr() method.
435
+ *
436
+ * options: RpcClientOptions
437
+ * Configuration passed to constructor.
438
+ * Used during start() to configure subprocess.
439
+ * Immutable after construction.
440
+ *
441
+ * ============================================================================
442
+ */
11
443
  export class RpcClient {
444
+ /**
445
+ * Create a new RPC client.
446
+ *
447
+ * @param options - Configuration for the agent subprocess
448
+ *
449
+ * Configuration Options:
450
+ * cliPath: Path to agent CLI entry point (default: "dist/cli.js")
451
+ * cwd: Working directory for subprocess
452
+ * env: Additional environment variables
453
+ * provider: Model provider to use initially
454
+ * model: Model ID to use initially
455
+ * args: Additional CLI arguments
456
+ *
457
+ * Example:
458
+ * const client = new RpcClient({
459
+ * cliPath: "/opt/agent/cli.js",
460
+ * env: { ANTHROPIC_API_KEY: "sk-..." },
461
+ * provider: "anthropic",
462
+ * model: "claude-3-5-sonnet"
463
+ * });
464
+ */
12
465
  constructor(options = {}) {
13
466
  this.options = options;
14
467
  this.process = null;
@@ -20,6 +473,56 @@ export class RpcClient {
20
473
  }
21
474
  /**
22
475
  * Start the RPC agent process.
476
+ *
477
+ * Spawns the agent subprocess in RPC mode and waits for initialization.
478
+ * Must be called before sending commands.
479
+ *
480
+ * Process Configuration:
481
+ * - Command: node [cliPath] --mode rpc [additional args]
482
+ * - Stdin: Piped (for sending commands)
483
+ * - Stdout: Piped (for receiving responses/events)
484
+ * - Stderr: Piped (for error collection)
485
+ * - CWD: options.cwd or current working directory
486
+ * - Env: process.env merged with options.env
487
+ *
488
+ * CLI Arguments:
489
+ * --mode rpc (always included)
490
+ * --provider [provider] (if options.provider set)
491
+ * --model [model] (if options.model set)
492
+ * [additional args] (from options.args)
493
+ *
494
+ * Initialization Steps:
495
+ * 1. Spawn subprocess with configuration
496
+ * 2. Set up stderr collection for debugging
497
+ * 3. Create readline interface on stdout
498
+ * 4. Wait 100ms for process initialization
499
+ * 5. Check if process exited early (error condition)
500
+ * 6. Set up event/response line handler
501
+ * 7. Resolve promise when ready
502
+ *
503
+ * Errors:
504
+ * - Already started: "Client already started"
505
+ * - Process exited immediately: "Agent process exited immediately..."
506
+ * (Includes stderr output for debugging)
507
+ *
508
+ * Examples:
509
+ * const client = new RpcClient();
510
+ * try {
511
+ * await client.start();
512
+ * console.log("Agent started");
513
+ * } catch (error) {
514
+ * console.error("Failed to start:", error.message);
515
+ * console.error("Stderr:", client.getStderr());
516
+ * }
517
+ *
518
+ * Success Criteria:
519
+ * - Subprocess spawned successfully
520
+ * - Subprocess not exited (exitCode is null)
521
+ * - Readline interface created
522
+ * - Ready to send commands
523
+ *
524
+ * @throws Error if process already started
525
+ * @throws Error if subprocess exited immediately
23
526
  */
24
527
  async start() {
25
528
  if (this.process) {
@@ -61,6 +564,58 @@ export class RpcClient {
61
564
  }
62
565
  /**
63
566
  * Stop the RPC agent process.
567
+ *
568
+ * Gracefully terminates the agent subprocess and cleans up resources.
569
+ * Safe to call even if client is not started.
570
+ *
571
+ * Shutdown Sequence:
572
+ * 1. Check if process running (return early if not)
573
+ * 2. Close readline interface (stops listening)
574
+ * 3. Send SIGTERM signal (graceful shutdown)
575
+ * 4. Set up 1-second timeout
576
+ * 5. Wait for process exit event
577
+ * 6. If timeout: send SIGKILL signal (force kill)
578
+ * 7. Clear process and rl references
579
+ * 8. Clear pending requests map
580
+ *
581
+ * Process States:
582
+ * - Running: SIGTERM → wait for graceful exit
583
+ * - Stuck: SIGTERM timeout → SIGKILL (force kill)
584
+ * - Already stopped: return immediately
585
+ * - Already exited: clean up references
586
+ *
587
+ * Resource Cleanup:
588
+ * - process: set to null
589
+ * - rl: closed and set to null
590
+ * - pendingRequests: cleared (all rejected)
591
+ * - eventListeners: preserved (can be reused on next start)
592
+ *
593
+ * Examples:
594
+ * // Basic shutdown
595
+ * await client.stop();
596
+ *
597
+ * // Always stop in finally block
598
+ * try {
599
+ * await client.start();
600
+ * await client.prompt("prompt");
601
+ * } finally {
602
+ * await client.stop();
603
+ * }
604
+ *
605
+ * // Stop is safe to call multiple times
606
+ * await client.stop();
607
+ * await client.stop(); // No error
608
+ *
609
+ * Timeout Behavior:
610
+ * - SIGTERM: 1 second grace period
611
+ * - After timeout: SIGKILL sent
612
+ * - Ensures process eventually terminates
613
+ * - Prevents hanging indefinitely
614
+ *
615
+ * Note: Event listeners are NOT cleared, allowing reuse of client.
616
+ * Create new client instance if you want fresh state.
617
+ *
618
+ * @returns Promise that resolves when process stopped
64
619
  */
65
620
  async stop() {
66
621
  if (!this.process)
@@ -84,6 +639,67 @@ export class RpcClient {
84
639
  }
85
640
  /**
86
641
  * Subscribe to agent events.
642
+ *
643
+ * Registers a callback to be called for each agent event.
644
+ * Events are delivered asynchronously as they arrive from the agent.
645
+ *
646
+ * Event Types:
647
+ * - agent_start: Agent began processing
648
+ * - message: User or assistant message
649
+ * - tool_call: Agent called a tool
650
+ * - tool_output: Tool returned output/result
651
+ * - tool_error: Tool failed
652
+ * - agent_end: Agent finished processing
653
+ * - compaction_start: Context compaction began
654
+ * - compaction_complete: Context compaction finished
655
+ * - extension_ui_request: Extension needs user input
656
+ * - extension_error: Extension threw error
657
+ * - hook_error: Hook threw error
658
+ *
659
+ * Callback Behavior:
660
+ * - Called synchronously when event parsed
661
+ * - Multiple listeners all called for same event
662
+ * - Exceptions in callback are logged but don't affect others
663
+ * - Can be registered/unregistered during event handling
664
+ *
665
+ * Unsubscription:
666
+ * - Returns unsubscribe function
667
+ * - Call returned function to remove listener
668
+ * - Safe to call multiple times
669
+ *
670
+ * Examples:
671
+ * // Subscribe to all events
672
+ * const unsubscribe = client.onEvent((event) => {
673
+ * console.log("Event:", event.type);
674
+ * });
675
+ *
676
+ * // Unsubscribe later
677
+ * unsubscribe();
678
+ *
679
+ * // Filter by event type
680
+ * client.onEvent((event) => {
681
+ * if (event.type === "message" && event.role === "assistant") {
682
+ * console.log("Assistant:", event.content[0].text);
683
+ * }
684
+ * });
685
+ *
686
+ * // Track tool calls
687
+ * client.onEvent((event) => {
688
+ * if (event.type === "tool_call") {
689
+ * console.log(`Tool: ${event.toolName}`);
690
+ * console.log(`Input:`, event.toolInput);
691
+ * }
692
+ * });
693
+ *
694
+ * // Multiple subscribers
695
+ * const unsub1 = client.onEvent(handler1);
696
+ * const unsub2 = client.onEvent(handler2);
697
+ * // Both called for each event
698
+ * unsub1(); // Remove first listener
699
+ * // Only handler2 called now
700
+ *
701
+ * @param listener - Callback function for events
702
+ * @returns Unsubscribe function to remove listener
87
703
  */
88
704
  onEvent(listener) {
89
705
  this.eventListeners.push(listener);
@@ -95,7 +711,49 @@ export class RpcClient {
95
711
  };
96
712
  }
97
713
  /**
98
- * Get collected stderr output (useful for debugging).
714
+ * Get collected stderr output from agent process.
715
+ *
716
+ * Returns all stderr output accumulated from the agent subprocess.
717
+ * Useful for debugging startup failures or agent errors.
718
+ *
719
+ * Accumulated Stderr:
720
+ * - Collected from process startup
721
+ * - Includes initialization errors
722
+ * - Agent logs and warnings
723
+ * - Extension errors
724
+ * - Unhandled exceptions
725
+ *
726
+ * Use Cases:
727
+ * - Debug start() failures
728
+ * - Diagnose connection issues
729
+ * - Investigate agent crashes
730
+ * - Extension debugging
731
+ *
732
+ * Examples:
733
+ * // Debug startup failure
734
+ * try {
735
+ * await client.start();
736
+ * } catch (error) {
737
+ * console.error("Error:", error.message);
738
+ * console.error("Agent stderr:", client.getStderr());
739
+ * }
740
+ *
741
+ * // Check for warnings during operation
742
+ * await client.start();
743
+ * await client.prompt("test");
744
+ * const stderr = client.getStderr();
745
+ * if (stderr.includes("WARNING")) {
746
+ * console.warn("Agent warnings detected:", stderr);
747
+ * }
748
+ *
749
+ * Note:
750
+ * - Does NOT include stdout (responses/events)
751
+ * - Accumulated text (not cleared per call)
752
+ * - Can grow large if agent produces lots of stderr
753
+ * - Call before stop() to get latest output
754
+ * - Empty string if no stderr produced
755
+ *
756
+ * @returns String containing all stderr output
99
757
  */
100
758
  getStderr() {
101
759
  return this.stderr;
@@ -105,8 +763,77 @@ export class RpcClient {
105
763
  // =========================================================================
106
764
  /**
107
765
  * Send a prompt to the agent.
108
- * Returns immediately after sending; use onEvent() to receive streaming events.
109
- * Use waitForIdle() to wait for completion.
766
+ *
767
+ * Sends a new prompt to the agent and returns immediately.
768
+ * Events are streamed asynchronously (use onEvent() to listen).
769
+ * Use waitForIdle() or promptAndWait() to wait for completion.
770
+ *
771
+ * Execution Model:
772
+ * 1. Command sent to agent
773
+ * 2. Response received immediately (success: true)
774
+ * 3. Agent starts processing asynchronously
775
+ * 4. Events streamed as they occur
776
+ * 5. agent_end event signals completion
777
+ *
778
+ * Parameters:
779
+ * message (required): The prompt text
780
+ * - Can contain instructions, questions, code
781
+ * - No special formatting required
782
+ * - Supports @ file inclusion (handled by agent)
783
+ *
784
+ * images (optional): Array of image content
785
+ * - Format: { mimeType: "image/png", data: "base64" }
786
+ * - Supported: PNG, JPEG, GIF, WebP
787
+ * - Attached to message and sent to model
788
+ *
789
+ * Return Value:
790
+ * Resolves when command sent (not when processing complete).
791
+ * To wait for completion, use:
792
+ * await client.prompt(message);
793
+ * await client.waitForIdle();
794
+ * Or use promptAndWait() for both in one call.
795
+ *
796
+ * Event Sequence:
797
+ * 1. Response: { success: true }
798
+ * 2. agent_start event
799
+ * 3. message event (user message)
800
+ * 4. message event (assistant response)
801
+ * 5. Optional: tool_call, tool_output events
802
+ * 6. agent_end event
803
+ *
804
+ * Error Handling:
805
+ * - Validation errors thrown immediately
806
+ * - Invalid arguments throw Error
807
+ * - Agent execution errors in events
808
+ *
809
+ * Examples:
810
+ * // Simple prompt
811
+ * await client.prompt("What is 2+2?");
812
+ *
813
+ * // Prompt with images
814
+ * await client.prompt("Describe this image", [
815
+ * { mimeType: "image/png", data: "base64-data" }
816
+ * ]);
817
+ *
818
+ * // Fire and forget
819
+ * client.prompt("Background task").catch(console.error);
820
+ *
821
+ * // With event listener
822
+ * client.onEvent((event) => {
823
+ * if (event.type === "agent_end") {
824
+ * console.log("Prompt completed");
825
+ * }
826
+ * });
827
+ * await client.prompt("Your prompt");
828
+ *
829
+ * // Wait for completion
830
+ * const eventsPromise = client.collectEvents();
831
+ * await client.prompt("Your prompt");
832
+ * const events = await eventsPromise;
833
+ *
834
+ * @param message - The prompt text to send
835
+ * @param images - Optional images to attach
836
+ * @throws Error if client not started or invalid input
110
837
  */
111
838
  async prompt(message, images) {
112
839
  await this.send({ type: "prompt", message, images });
@@ -285,7 +1012,49 @@ export class RpcClient {
285
1012
  // =========================================================================
286
1013
  /**
287
1014
  * Wait for agent to become idle (no streaming).
288
- * Resolves when agent_end event is received.
1015
+ *
1016
+ * Blocks until the agent finishes processing.
1017
+ * Resolves when agent_end event received.
1018
+ * Useful for waiting after prompt() before sending next command.
1019
+ *
1020
+ * Behavior:
1021
+ * - Listens for agent_end event
1022
+ * - Resolves immediately if event already received
1023
+ * - Rejects if timeout exceeded
1024
+ * - Automatically unsubscribes when done
1025
+ *
1026
+ * Timeout:
1027
+ * - Default: 60,000 ms (60 seconds)
1028
+ * - Can be customized per call
1029
+ * - Thrown as Error if exceeded
1030
+ * - Error includes stderr for debugging
1031
+ *
1032
+ * Usage Pattern:
1033
+ * await client.prompt("Your prompt");
1034
+ * await client.waitForIdle();
1035
+ * // Agent processing complete
1036
+ * const state = await client.getState();
1037
+ *
1038
+ * With Timeout:
1039
+ * await client.waitForIdle(120000); // 2 minutes
1040
+ * // For long-running operations
1041
+ *
1042
+ * Error Handling:
1043
+ * try {
1044
+ * await client.waitForIdle(5000);
1045
+ * } catch (error) {
1046
+ * console.error("Timeout:", error.message);
1047
+ * }
1048
+ *
1049
+ * Notes:
1050
+ * - Does not return any data
1051
+ * - Use collectEvents() to get event list
1052
+ * - Use onEvent() if you need individual events
1053
+ * - Safe to call multiple times concurrently
1054
+ *
1055
+ * @param timeout - Timeout in milliseconds (default: 60000)
1056
+ * @returns Promise that resolves when agent_end event received
1057
+ * @throws Error if timeout exceeded or client not started
289
1058
  */
290
1059
  waitForIdle(timeout = 60000) {
291
1060
  return new Promise((resolve, reject) => {
@@ -303,7 +1072,67 @@ export class RpcClient {
303
1072
  });
304
1073
  }
305
1074
  /**
306
- * Collect events until agent becomes idle.
1075
+ * Collect all events until agent becomes idle.
1076
+ *
1077
+ * Listens for all events and collects them into an array.
1078
+ * Resolves when agent_end event received.
1079
+ * Returns complete event history for analysis/debugging.
1080
+ *
1081
+ * Behavior:
1082
+ * - Creates new listener for this collection only
1083
+ * - Accumulates all events in order
1084
+ * - Unsubscribes when agent_end received
1085
+ * - Other listeners still receive events
1086
+ *
1087
+ * Return Value:
1088
+ * Array of AgentEvent in chronological order:
1089
+ * 1. agent_start
1090
+ * 2. message (user)
1091
+ * 3. message (assistant) or tool events
1092
+ * 4. agent_end
1093
+ *
1094
+ * Timeout:
1095
+ * - Default: 60,000 ms (60 seconds)
1096
+ * - Customizable per call
1097
+ * - Error includes stderr for debugging
1098
+ *
1099
+ * Usage Pattern:
1100
+ * const eventsPromise = client.collectEvents();
1101
+ * await client.prompt("Your prompt");
1102
+ * const events = await eventsPromise;
1103
+ * events.forEach(e => console.log(e.type));
1104
+ *
1105
+ * Analysis Examples:
1106
+ * // Count tool calls
1107
+ * const toolCalls = events.filter(e => e.type === "tool_call").length;
1108
+ *
1109
+ * // Get assistant messages
1110
+ * const responses = events
1111
+ * .filter(e => e.type === "message" && e.role === "assistant")
1112
+ * .map(e => e.content[0]?.text);
1113
+ *
1114
+ * // Find errors
1115
+ * const errors = events.filter(e => e.type === "tool_error");
1116
+ *
1117
+ * // Get compaction info
1118
+ * const compactions = events.filter(e =>
1119
+ * e.type === "compaction_start" || e.type === "compaction_complete"
1120
+ * );
1121
+ *
1122
+ * Multiple Collection:
1123
+ * // Safe to call multiple times
1124
+ * const events1 = await client.collectEvents();
1125
+ * const events2 = await client.collectEvents();
1126
+ * // Each gets complete event sequence
1127
+ *
1128
+ * Performance:
1129
+ * - Array allocation: O(n) where n = event count
1130
+ * - Each event appended: O(1)
1131
+ * - Full history available immediately after completion
1132
+ *
1133
+ * @param timeout - Timeout in milliseconds (default: 60000)
1134
+ * @returns Promise resolving to array of all events
1135
+ * @throws Error if timeout exceeded or client not started
307
1136
  */
308
1137
  collectEvents(timeout = 60000) {
309
1138
  return new Promise((resolve, reject) => {
@@ -323,7 +1152,91 @@ export class RpcClient {
323
1152
  });
324
1153
  }
325
1154
  /**
326
- * Send prompt and wait for completion, returning all events.
1155
+ * Send prompt and wait for completion in a single call.
1156
+ *
1157
+ * Convenience method combining prompt() + collectEvents().
1158
+ * Sends prompt and returns all events from that execution.
1159
+ * Cleaner than managing event collection separately.
1160
+ *
1161
+ * Behavior:
1162
+ * 1. Start collecting events
1163
+ * 2. Send prompt to agent
1164
+ * 3. Wait for completion (agent_end event)
1165
+ * 4. Return all collected events
1166
+ *
1167
+ * Equivalent To:
1168
+ * const eventsPromise = client.collectEvents(timeout);
1169
+ * await client.prompt(message, images);
1170
+ * return eventsPromise;
1171
+ *
1172
+ * Parameters:
1173
+ * message (required): Prompt text
1174
+ * images (optional): Array of image content
1175
+ * timeout (optional): Timeout in milliseconds (default: 60000)
1176
+ *
1177
+ * Return Value:
1178
+ * Array of all events from prompt execution in order:
1179
+ * - agent_start
1180
+ * - message events (user, assistant)
1181
+ * - tool events (if tools called)
1182
+ * - agent_end
1183
+ *
1184
+ * Usage Pattern:
1185
+ * const events = await client.promptAndWait("Your question");
1186
+ * console.log(`Got ${events.length} events`);
1187
+ *
1188
+ * Single Prompt Extraction:
1189
+ * const events = await client.promptAndWait("What is 2+2?");
1190
+ * const response = events
1191
+ * .filter(e => e.type === "message" && e.role === "assistant")
1192
+ * .map(e => e.content[0]?.text)
1193
+ * .join("\\n");
1194
+ * console.log("Response:", response);
1195
+ *
1196
+ * Tool Tracking:
1197
+ * const events = await client.promptAndWait("Find files in /tmp");
1198
+ * const tools = events
1199
+ * .filter(e => e.type === "tool_call")
1200
+ * .map(e => e.toolName);
1201
+ * console.log("Tools used:", tools);
1202
+ *
1203
+ * With Images:
1204
+ * const events = await client.promptAndWait(
1205
+ * "Analyze this image",
1206
+ * [{ mimeType: "image/png", data: "base64..." }]
1207
+ * );
1208
+ *
1209
+ * With Custom Timeout:
1210
+ * const events = await client.promptAndWait(
1211
+ * "Long running task",
1212
+ * undefined,
1213
+ * 120000 // 2 minute timeout
1214
+ * );
1215
+ *
1216
+ * Sequential Prompts:
1217
+ * for (const prompt of prompts) {
1218
+ * const events = await client.promptAndWait(prompt);
1219
+ * processEvents(events);
1220
+ * }
1221
+ *
1222
+ * Error Handling:
1223
+ * try {
1224
+ * const events = await client.promptAndWait(prompt, undefined, 30000);
1225
+ * } catch (error) {
1226
+ * console.error("Failed:", error.message);
1227
+ * console.error("Debug info:", client.getStderr());
1228
+ * }
1229
+ *
1230
+ * Note:
1231
+ * - Simplest API for single prompt→response cycle
1232
+ * - Not suitable for steering/follow-up (those are fire-and-forget)
1233
+ * - Use prompt() + onEvent() for interactive scenarios
1234
+ *
1235
+ * @param message - Prompt text to send
1236
+ * @param images - Optional image attachments
1237
+ * @param timeout - Timeout in milliseconds (default: 60000)
1238
+ * @returns Promise resolving to array of all events
1239
+ * @throws Error if timeout exceeded or client not started
327
1240
  */
328
1241
  async promptAndWait(message, images, timeout = 60000) {
329
1242
  const eventsPromise = this.collectEvents(timeout);