@qodo/sdk 0.1.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 (303) hide show
  1. package/LICENSE +118 -0
  2. package/README.md +121 -0
  3. package/dist/api/agent.d.ts +69 -0
  4. package/dist/api/agent.d.ts.map +1 -0
  5. package/dist/api/agent.js +1034 -0
  6. package/dist/api/agent.js.map +1 -0
  7. package/dist/api/analytics.d.ts +43 -0
  8. package/dist/api/analytics.d.ts.map +1 -0
  9. package/dist/api/analytics.js +163 -0
  10. package/dist/api/analytics.js.map +1 -0
  11. package/dist/api/http.d.ts +5 -0
  12. package/dist/api/http.d.ts.map +1 -0
  13. package/dist/api/http.js +59 -0
  14. package/dist/api/http.js.map +1 -0
  15. package/dist/api/index.d.ts +12 -0
  16. package/dist/api/index.d.ts.map +1 -0
  17. package/dist/api/index.js +17 -0
  18. package/dist/api/index.js.map +1 -0
  19. package/dist/api/taskTracking.d.ts +54 -0
  20. package/dist/api/taskTracking.d.ts.map +1 -0
  21. package/dist/api/taskTracking.js +208 -0
  22. package/dist/api/taskTracking.js.map +1 -0
  23. package/dist/api/types.d.ts +92 -0
  24. package/dist/api/types.d.ts.map +1 -0
  25. package/dist/api/types.js +2 -0
  26. package/dist/api/types.js.map +1 -0
  27. package/dist/api/utils.d.ts +8 -0
  28. package/dist/api/utils.d.ts.map +1 -0
  29. package/dist/api/utils.js +54 -0
  30. package/dist/api/utils.js.map +1 -0
  31. package/dist/api/websocket.d.ts +74 -0
  32. package/dist/api/websocket.d.ts.map +1 -0
  33. package/dist/api/websocket.js +685 -0
  34. package/dist/api/websocket.js.map +1 -0
  35. package/dist/auth/index.d.ts +25 -0
  36. package/dist/auth/index.d.ts.map +1 -0
  37. package/dist/auth/index.js +85 -0
  38. package/dist/auth/index.js.map +1 -0
  39. package/dist/clients/index.d.ts +8 -0
  40. package/dist/clients/index.d.ts.map +1 -0
  41. package/dist/clients/index.js +7 -0
  42. package/dist/clients/index.js.map +1 -0
  43. package/dist/clients/info/InfoClient.d.ts +37 -0
  44. package/dist/clients/info/InfoClient.d.ts.map +1 -0
  45. package/dist/clients/info/InfoClient.js +69 -0
  46. package/dist/clients/info/InfoClient.js.map +1 -0
  47. package/dist/clients/info/index.d.ts +4 -0
  48. package/dist/clients/info/index.d.ts.map +1 -0
  49. package/dist/clients/info/index.js +2 -0
  50. package/dist/clients/info/index.js.map +1 -0
  51. package/dist/clients/info/types.d.ts +21 -0
  52. package/dist/clients/info/types.d.ts.map +1 -0
  53. package/dist/clients/info/types.js +2 -0
  54. package/dist/clients/info/types.js.map +1 -0
  55. package/dist/clients/sessions/SessionsClient.d.ts +34 -0
  56. package/dist/clients/sessions/SessionsClient.d.ts.map +1 -0
  57. package/dist/clients/sessions/SessionsClient.js +71 -0
  58. package/dist/clients/sessions/SessionsClient.js.map +1 -0
  59. package/dist/clients/sessions/index.d.ts +4 -0
  60. package/dist/clients/sessions/index.d.ts.map +1 -0
  61. package/dist/clients/sessions/index.js +2 -0
  62. package/dist/clients/sessions/index.js.map +1 -0
  63. package/dist/clients/sessions/types.d.ts +20 -0
  64. package/dist/clients/sessions/types.d.ts.map +1 -0
  65. package/dist/clients/sessions/types.js +2 -0
  66. package/dist/clients/sessions/types.js.map +1 -0
  67. package/dist/config/ConfigManager.d.ts +43 -0
  68. package/dist/config/ConfigManager.d.ts.map +1 -0
  69. package/dist/config/ConfigManager.js +472 -0
  70. package/dist/config/ConfigManager.js.map +1 -0
  71. package/dist/config/index.d.ts +6 -0
  72. package/dist/config/index.d.ts.map +1 -0
  73. package/dist/config/index.js +7 -0
  74. package/dist/config/index.js.map +1 -0
  75. package/dist/config/urlConfig.d.ts +15 -0
  76. package/dist/config/urlConfig.d.ts.map +1 -0
  77. package/dist/config/urlConfig.js +75 -0
  78. package/dist/config/urlConfig.js.map +1 -0
  79. package/dist/constants/errors.d.ts +2 -0
  80. package/dist/constants/errors.d.ts.map +1 -0
  81. package/dist/constants/errors.js +2 -0
  82. package/dist/constants/errors.js.map +1 -0
  83. package/dist/constants/index.d.ts +7 -0
  84. package/dist/constants/index.d.ts.map +1 -0
  85. package/dist/constants/index.js +11 -0
  86. package/dist/constants/index.js.map +1 -0
  87. package/dist/constants/tools.d.ts +4 -0
  88. package/dist/constants/tools.d.ts.map +1 -0
  89. package/dist/constants/tools.js +4 -0
  90. package/dist/constants/tools.js.map +1 -0
  91. package/dist/constants/versions.d.ts +2 -0
  92. package/dist/constants/versions.d.ts.map +1 -0
  93. package/dist/constants/versions.js +2 -0
  94. package/dist/constants/versions.js.map +1 -0
  95. package/dist/context/buildUserContext.d.ts +18 -0
  96. package/dist/context/buildUserContext.d.ts.map +1 -0
  97. package/dist/context/buildUserContext.js +34 -0
  98. package/dist/context/buildUserContext.js.map +1 -0
  99. package/dist/context/index.d.ts +9 -0
  100. package/dist/context/index.d.ts.map +1 -0
  101. package/dist/context/index.js +9 -0
  102. package/dist/context/index.js.map +1 -0
  103. package/dist/context/messageManager.d.ts +42 -0
  104. package/dist/context/messageManager.d.ts.map +1 -0
  105. package/dist/context/messageManager.js +322 -0
  106. package/dist/context/messageManager.js.map +1 -0
  107. package/dist/context/taskFocus.d.ts +2 -0
  108. package/dist/context/taskFocus.d.ts.map +1 -0
  109. package/dist/context/taskFocus.js +26 -0
  110. package/dist/context/taskFocus.js.map +1 -0
  111. package/dist/context/userInput.d.ts +3 -0
  112. package/dist/context/userInput.d.ts.map +1 -0
  113. package/dist/context/userInput.js +20 -0
  114. package/dist/context/userInput.js.map +1 -0
  115. package/dist/index.d.ts +18 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +21 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/mcp/MCPManager.d.ts +125 -0
  120. package/dist/mcp/MCPManager.d.ts.map +1 -0
  121. package/dist/mcp/MCPManager.js +616 -0
  122. package/dist/mcp/MCPManager.js.map +1 -0
  123. package/dist/mcp/approvedTools.d.ts +4 -0
  124. package/dist/mcp/approvedTools.d.ts.map +1 -0
  125. package/dist/mcp/approvedTools.js +19 -0
  126. package/dist/mcp/approvedTools.js.map +1 -0
  127. package/dist/mcp/baseServer.d.ts +75 -0
  128. package/dist/mcp/baseServer.d.ts.map +1 -0
  129. package/dist/mcp/baseServer.js +107 -0
  130. package/dist/mcp/baseServer.js.map +1 -0
  131. package/dist/mcp/builtinServers.d.ts +15 -0
  132. package/dist/mcp/builtinServers.d.ts.map +1 -0
  133. package/dist/mcp/builtinServers.js +155 -0
  134. package/dist/mcp/builtinServers.js.map +1 -0
  135. package/dist/mcp/dynamicBEServer.d.ts +20 -0
  136. package/dist/mcp/dynamicBEServer.d.ts.map +1 -0
  137. package/dist/mcp/dynamicBEServer.js +52 -0
  138. package/dist/mcp/dynamicBEServer.js.map +1 -0
  139. package/dist/mcp/index.d.ts +19 -0
  140. package/dist/mcp/index.d.ts.map +1 -0
  141. package/dist/mcp/index.js +24 -0
  142. package/dist/mcp/index.js.map +1 -0
  143. package/dist/mcp/mcpInitialization.d.ts +2 -0
  144. package/dist/mcp/mcpInitialization.d.ts.map +1 -0
  145. package/dist/mcp/mcpInitialization.js +56 -0
  146. package/dist/mcp/mcpInitialization.js.map +1 -0
  147. package/dist/mcp/servers/filesystem.d.ts +75 -0
  148. package/dist/mcp/servers/filesystem.d.ts.map +1 -0
  149. package/dist/mcp/servers/filesystem.js +992 -0
  150. package/dist/mcp/servers/filesystem.js.map +1 -0
  151. package/dist/mcp/servers/gerrit.d.ts +19 -0
  152. package/dist/mcp/servers/gerrit.d.ts.map +1 -0
  153. package/dist/mcp/servers/gerrit.js +515 -0
  154. package/dist/mcp/servers/gerrit.js.map +1 -0
  155. package/dist/mcp/servers/git.d.ts +18 -0
  156. package/dist/mcp/servers/git.d.ts.map +1 -0
  157. package/dist/mcp/servers/git.js +441 -0
  158. package/dist/mcp/servers/git.js.map +1 -0
  159. package/dist/mcp/servers/ripgrep.d.ts +34 -0
  160. package/dist/mcp/servers/ripgrep.d.ts.map +1 -0
  161. package/dist/mcp/servers/ripgrep.js +517 -0
  162. package/dist/mcp/servers/ripgrep.js.map +1 -0
  163. package/dist/mcp/servers/shell.d.ts +20 -0
  164. package/dist/mcp/servers/shell.d.ts.map +1 -0
  165. package/dist/mcp/servers/shell.js +603 -0
  166. package/dist/mcp/servers/shell.js.map +1 -0
  167. package/dist/mcp/serversRegistry.d.ts +55 -0
  168. package/dist/mcp/serversRegistry.d.ts.map +1 -0
  169. package/dist/mcp/serversRegistry.js +410 -0
  170. package/dist/mcp/serversRegistry.js.map +1 -0
  171. package/dist/mcp/toolProcessor.d.ts +42 -0
  172. package/dist/mcp/toolProcessor.d.ts.map +1 -0
  173. package/dist/mcp/toolProcessor.js +200 -0
  174. package/dist/mcp/toolProcessor.js.map +1 -0
  175. package/dist/mcp/types.d.ts +29 -0
  176. package/dist/mcp/types.d.ts.map +1 -0
  177. package/dist/mcp/types.js +2 -0
  178. package/dist/mcp/types.js.map +1 -0
  179. package/dist/parser/index.d.ts +72 -0
  180. package/dist/parser/index.d.ts.map +1 -0
  181. package/dist/parser/index.js +967 -0
  182. package/dist/parser/index.js.map +1 -0
  183. package/dist/parser/types.d.ts +153 -0
  184. package/dist/parser/types.d.ts.map +1 -0
  185. package/dist/parser/types.js +6 -0
  186. package/dist/parser/types.js.map +1 -0
  187. package/dist/parser/utils.d.ts +18 -0
  188. package/dist/parser/utils.d.ts.map +1 -0
  189. package/dist/parser/utils.js +64 -0
  190. package/dist/parser/utils.js.map +1 -0
  191. package/dist/sdk/QodoSDK.d.ts +152 -0
  192. package/dist/sdk/QodoSDK.d.ts.map +1 -0
  193. package/dist/sdk/QodoSDK.js +786 -0
  194. package/dist/sdk/QodoSDK.js.map +1 -0
  195. package/dist/sdk/bootstrap.d.ts +16 -0
  196. package/dist/sdk/bootstrap.d.ts.map +1 -0
  197. package/dist/sdk/bootstrap.js +21 -0
  198. package/dist/sdk/bootstrap.js.map +1 -0
  199. package/dist/sdk/builders.d.ts +54 -0
  200. package/dist/sdk/builders.d.ts.map +1 -0
  201. package/dist/sdk/builders.js +117 -0
  202. package/dist/sdk/builders.js.map +1 -0
  203. package/dist/sdk/defaults.d.ts +11 -0
  204. package/dist/sdk/defaults.d.ts.map +1 -0
  205. package/dist/sdk/defaults.js +39 -0
  206. package/dist/sdk/defaults.js.map +1 -0
  207. package/dist/sdk/discovery.d.ts +2 -0
  208. package/dist/sdk/discovery.d.ts.map +1 -0
  209. package/dist/sdk/discovery.js +25 -0
  210. package/dist/sdk/discovery.js.map +1 -0
  211. package/dist/sdk/events.d.ts +168 -0
  212. package/dist/sdk/events.d.ts.map +1 -0
  213. package/dist/sdk/events.js +52 -0
  214. package/dist/sdk/events.js.map +1 -0
  215. package/dist/sdk/index.d.ts +17 -0
  216. package/dist/sdk/index.d.ts.map +1 -0
  217. package/dist/sdk/index.js +17 -0
  218. package/dist/sdk/index.js.map +1 -0
  219. package/dist/sdk/runner/AgentRunner.d.ts +22 -0
  220. package/dist/sdk/runner/AgentRunner.d.ts.map +1 -0
  221. package/dist/sdk/runner/AgentRunner.js +222 -0
  222. package/dist/sdk/runner/AgentRunner.js.map +1 -0
  223. package/dist/sdk/runner/finalize.d.ts +9 -0
  224. package/dist/sdk/runner/finalize.d.ts.map +1 -0
  225. package/dist/sdk/runner/finalize.js +115 -0
  226. package/dist/sdk/runner/finalize.js.map +1 -0
  227. package/dist/sdk/runner/formats.d.ts +7 -0
  228. package/dist/sdk/runner/formats.d.ts.map +1 -0
  229. package/dist/sdk/runner/formats.js +91 -0
  230. package/dist/sdk/runner/formats.js.map +1 -0
  231. package/dist/sdk/runner/index.d.ts +9 -0
  232. package/dist/sdk/runner/index.d.ts.map +1 -0
  233. package/dist/sdk/runner/index.js +9 -0
  234. package/dist/sdk/runner/index.js.map +1 -0
  235. package/dist/sdk/runner/progress.d.ts +3 -0
  236. package/dist/sdk/runner/progress.d.ts.map +1 -0
  237. package/dist/sdk/runner/progress.js +16 -0
  238. package/dist/sdk/runner/progress.js.map +1 -0
  239. package/dist/sdk/schemas.d.ts +50 -0
  240. package/dist/sdk/schemas.d.ts.map +1 -0
  241. package/dist/sdk/schemas.js +145 -0
  242. package/dist/sdk/schemas.js.map +1 -0
  243. package/dist/session/SessionContext.d.ts +86 -0
  244. package/dist/session/SessionContext.d.ts.map +1 -0
  245. package/dist/session/SessionContext.js +395 -0
  246. package/dist/session/SessionContext.js.map +1 -0
  247. package/dist/session/environment.d.ts +42 -0
  248. package/dist/session/environment.d.ts.map +1 -0
  249. package/dist/session/environment.js +27 -0
  250. package/dist/session/environment.js.map +1 -0
  251. package/dist/session/history.d.ts +3 -0
  252. package/dist/session/history.d.ts.map +1 -0
  253. package/dist/session/history.js +67 -0
  254. package/dist/session/history.js.map +1 -0
  255. package/dist/session/index.d.ts +10 -0
  256. package/dist/session/index.d.ts.map +1 -0
  257. package/dist/session/index.js +9 -0
  258. package/dist/session/index.js.map +1 -0
  259. package/dist/session/serverData.d.ts +38 -0
  260. package/dist/session/serverData.d.ts.map +1 -0
  261. package/dist/session/serverData.js +241 -0
  262. package/dist/session/serverData.js.map +1 -0
  263. package/dist/tracking/Tracker.d.ts +55 -0
  264. package/dist/tracking/Tracker.d.ts.map +1 -0
  265. package/dist/tracking/Tracker.js +217 -0
  266. package/dist/tracking/Tracker.js.map +1 -0
  267. package/dist/tracking/index.d.ts +8 -0
  268. package/dist/tracking/index.d.ts.map +1 -0
  269. package/dist/tracking/index.js +8 -0
  270. package/dist/tracking/index.js.map +1 -0
  271. package/dist/tracking/schemas.d.ts +292 -0
  272. package/dist/tracking/schemas.d.ts.map +1 -0
  273. package/dist/tracking/schemas.js +91 -0
  274. package/dist/tracking/schemas.js.map +1 -0
  275. package/dist/types.d.ts +4 -0
  276. package/dist/types.d.ts.map +1 -0
  277. package/dist/types.js +2 -0
  278. package/dist/types.js.map +1 -0
  279. package/dist/utils/extractSetFlags.d.ts +6 -0
  280. package/dist/utils/extractSetFlags.d.ts.map +1 -0
  281. package/dist/utils/extractSetFlags.js +16 -0
  282. package/dist/utils/extractSetFlags.js.map +1 -0
  283. package/dist/utils/formatTimeAgo.d.ts +2 -0
  284. package/dist/utils/formatTimeAgo.d.ts.map +1 -0
  285. package/dist/utils/formatTimeAgo.js +20 -0
  286. package/dist/utils/formatTimeAgo.js.map +1 -0
  287. package/dist/utils/index.d.ts +12 -0
  288. package/dist/utils/index.d.ts.map +1 -0
  289. package/dist/utils/index.js +12 -0
  290. package/dist/utils/index.js.map +1 -0
  291. package/dist/utils/machineId.d.ts +14 -0
  292. package/dist/utils/machineId.d.ts.map +1 -0
  293. package/dist/utils/machineId.js +66 -0
  294. package/dist/utils/machineId.js.map +1 -0
  295. package/dist/utils/pathUtils.d.ts +22 -0
  296. package/dist/utils/pathUtils.d.ts.map +1 -0
  297. package/dist/utils/pathUtils.js +54 -0
  298. package/dist/utils/pathUtils.js.map +1 -0
  299. package/dist/version.d.ts +2 -0
  300. package/dist/version.d.ts.map +1 -0
  301. package/dist/version.js +23 -0
  302. package/dist/version.js.map +1 -0
  303. package/package.json +93 -0
@@ -0,0 +1,786 @@
1
+ import { ConfigManager } from '../config/index.js';
2
+ import { v4 as uuid } from 'uuid';
3
+ import { findNearestAgentConfig } from './discovery.js';
4
+ import { buildDefaultSdkAgentConfig } from './defaults.js';
5
+ import { mcpInitialization, ServerRegistry } from '../mcp/index.js';
6
+ import { runWithEnvironment, ServerData, SessionContext } from '../session/index.js';
7
+ import { MessageManager } from '../context/index.js';
8
+ import { AgentAPI } from '../api/agent.js';
9
+ import { AgentRunnerCore } from './runner/index.js';
10
+ import { BackendBootstrap } from './bootstrap.js';
11
+ import { QodoInfoClient, QodoSessionsClient } from '../clients/index.js';
12
+ import { canonicalizePathSync, extractSetFlags } from '../utils/index.js';
13
+ import * as path from 'path';
14
+ import { extractProgress } from './runner/progress.js';
15
+ import { toLangChainDict, toOpenAIChat } from './runner/formats.js';
16
+ import { buildFinalResult } from './runner/finalize.js';
17
+ import { createSdkEvent, getSdkVersion, SdkEventType, } from './events.js';
18
+ export class QodoSDK {
19
+ options;
20
+ /** Backend info (get-things) facade */
21
+ info;
22
+ /** Session history facade */
23
+ sessions;
24
+ initialized = false;
25
+ // Environment for AsyncLocalStorage-scoped singletons.
26
+ // Mark as sdkMode to avoid process.exit in SDK code paths.
27
+ env = {
28
+ sdkMode: true,
29
+ sdkDebug: false,
30
+ };
31
+ // SDK is headless by default. We avoid writing to stdout/stderr unless
32
+ // explicitly enabled via options.debug or a provided logger.
33
+ logger;
34
+ // Per-run envelope metadata
35
+ runId = '';
36
+ seq = 0;
37
+ runStartMs = 0;
38
+ sessionContext;
39
+ lastInitMeta = null;
40
+ messageManager;
41
+ agent;
42
+ core;
43
+ eventQueue = [];
44
+ pendingResolvers = [];
45
+ done = false;
46
+ activeRuns = 0;
47
+ // For `sdk.message.delta`
48
+ lastAiText = '';
49
+ lastAiMessageId = '';
50
+ // Deduplication for tool lifecycle
51
+ toolRequestedEmitted = new Set();
52
+ toolApprovalEmitted = new Set();
53
+ toolApprovalInFlight = new Set();
54
+ toolExecutedEmitted = new Set();
55
+ // Track tool names by call id so sdk.tool.executed can include tool_name
56
+ toolRegistry = new Map();
57
+ constructor(options = {}) {
58
+ this.options = options;
59
+ this.info = QodoInfoClient.fromSdkOptions(options);
60
+ this.sessions = QodoSessionsClient.fromSdkOptions(options);
61
+ // If debug is enabled, allow verbose logs in this SDK environment.
62
+ if (this.options.debug === true) {
63
+ this.env.sdkDebug = true;
64
+ }
65
+ const noop = () => { };
66
+ const fallback = this.options.debug
67
+ ? {
68
+ debug: console.debug.bind(console),
69
+ info: console.info.bind(console),
70
+ warn: console.warn.bind(console),
71
+ error: console.error.bind(console),
72
+ }
73
+ : { debug: noop, info: noop, warn: noop, error: noop };
74
+ this.logger = {
75
+ debug: this.options.logger?.debug ?? fallback.debug,
76
+ info: this.options.logger?.info ?? fallback.info,
77
+ warn: this.options.logger?.warn ?? fallback.warn,
78
+ error: this.options.logger?.error ?? fallback.error,
79
+ };
80
+ }
81
+ static fromAgent(agentObject, options = {}) {
82
+ return new QodoSDK({ ...options, agentObject });
83
+ }
84
+ /**
85
+ * Create a new SDK instance that will run using a specific backend session id.
86
+ *
87
+ * This is useful for:
88
+ * - resuming or continuing a known session
89
+ * - binding a run to a session id created via `sdk.sessions.createSessionId()`
90
+ *
91
+ * Note: this returns a NEW SDK instance (does not mutate the current one).
92
+ */
93
+ withSession(sessionId) {
94
+ const nextFlags = { ...(this.options.flags || {}), sid: sessionId };
95
+ return new QodoSDK({ ...this.options, flags: nextFlags });
96
+ }
97
+ pushEvent(type, sessionId, data, opts) {
98
+ const evt = createSdkEvent({
99
+ type,
100
+ run_id: this.runId,
101
+ seq: ++this.seq,
102
+ session_id: sessionId,
103
+ data,
104
+ ...(opts?.request_id ? { request_id: opts.request_id } : {}),
105
+ elapsed_ms: this.runStartMs ? Date.now() - this.runStartMs : undefined,
106
+ });
107
+ if (this.pendingResolvers.length > 0) {
108
+ const resolve = this.pendingResolvers.shift();
109
+ resolve({ value: evt, done: false });
110
+ }
111
+ else {
112
+ this.eventQueue.push(evt);
113
+ }
114
+ }
115
+ async ensureInitialized(desiredCommandName) {
116
+ if (this.initialized) {
117
+ // Return previously computed summary; best-effort fallback.
118
+ if (this.lastInitMeta)
119
+ return this.lastInitMeta;
120
+ return { commandName: '', promptMode: false, cwd: this.options.cwd ? canonicalizePathSync(this.options.cwd) : canonicalizePathSync(process.cwd()), agentSource: { source: 'default' } };
121
+ }
122
+ // Init backend get-things (supports baseUrl override)
123
+ const bootstrap = new BackendBootstrap({ baseUrlOverride: this.options?.backend?.baseUrl });
124
+ await bootstrap.init();
125
+ const flags = {
126
+ ...(this.options.flags || {}),
127
+ sdk: true,
128
+ ...(this.options.debug ? { debug: true } : {}),
129
+ };
130
+ if (this.options.model)
131
+ flags.model = this.options.model;
132
+ // Resolve effective cwd first (used for agent discovery and tool defaults)
133
+ const explicitCwd = this.options.cwd ? canonicalizePathSync(this.options.cwd) : undefined;
134
+ const agentFilePathOpt = this.options.agentFile ? canonicalizePathSync(this.options.agentFile) : undefined;
135
+ const derivedCwd = !explicitCwd && agentFilePathOpt ? path.dirname(agentFilePathOpt) : undefined;
136
+ const effectiveCwd = explicitCwd || derivedCwd || canonicalizePathSync(process.cwd());
137
+ // SDK-first agent resolution:
138
+ // 1) agentObject / agentContent / explicit agentFile
139
+ // 2) auto-discover agent.toml|yaml|yml from cwd
140
+ // 3) fallback to built-in minimal config
141
+ let configInput = this.options.agentObject ?? this.options.agentContent ?? this.options.agentFile;
142
+ let isFileContent = !!this.options.agentContent || !!this.options.agentObject;
143
+ let agentSource = { source: 'file' };
144
+ if (this.options.agentObject)
145
+ agentSource = { source: 'object' };
146
+ else if (this.options.agentContent)
147
+ agentSource = { source: 'content' };
148
+ else if (this.options.agentFile)
149
+ agentSource = { source: 'file', path: String(this.options.agentFile) };
150
+ if (!configInput) {
151
+ const discovered = await findNearestAgentConfig(effectiveCwd);
152
+ if (discovered) {
153
+ configInput = discovered;
154
+ isFileContent = false;
155
+ agentSource = { source: 'discovered', path: discovered };
156
+ }
157
+ else {
158
+ configInput = buildDefaultSdkAgentConfig();
159
+ isFileContent = true;
160
+ agentSource = { source: 'default' };
161
+ }
162
+ }
163
+ const configManager = await ConfigManager.init(configInput, isFileContent);
164
+ // Resolve command or mode
165
+ let modeCommand;
166
+ if (flags.mode) {
167
+ modeCommand = configManager.resolveModeAsCommand(flags.mode);
168
+ }
169
+ // Determine whether the caller passed a command name or a free-form prompt.
170
+ // SDK should be "prompt-first": if the provided string is not a known command,
171
+ // we still build a command config via getCommandConfig(prompt) (which returns
172
+ // a default config inheriting top-level model/tools) and treat the string as
173
+ // user prompt.
174
+ const allCommands = configManager.listCommands();
175
+ const desiredIsCommand = !!(desiredCommandName && allCommands.includes(desiredCommandName));
176
+ // If the user provided a command name but there are no commands configured,
177
+ // we treat it as a prompt (prompt-first behavior). We also synthesize an
178
+ // internal default command config so execution can proceed.
179
+ const hasAnyCommands = allCommands.length > 0;
180
+ // Choose command:
181
+ // 1) mode (explicit)
182
+ // 2) if desired name is a known command -> use that command
183
+ // 3) else if a non-empty prompt was provided -> treat as prompt and build a default command config
184
+ // 4) else if commands exist -> fallback to flags.command or a single command
185
+ // 5) else (no commands) -> synthesize default command
186
+ let command;
187
+ let cmdName = typeof flags.command === 'string' ? flags.command : configManager.getSingleCommand() || '';
188
+ let promptMode = false;
189
+ if (flags.mode) {
190
+ command = modeCommand;
191
+ cmdName = flags.mode;
192
+ }
193
+ else if (desiredIsCommand) {
194
+ cmdName = desiredCommandName;
195
+ command = configManager.getCommandConfig(cmdName);
196
+ }
197
+ else if (desiredCommandName && String(desiredCommandName).trim().length > 0) {
198
+ cmdName = ''; // prompt flow
199
+ promptMode = true;
200
+ command = configManager.getCommandConfig(desiredCommandName);
201
+ }
202
+ else if (hasAnyCommands) {
203
+ command = configManager.getCommandConfig(cmdName);
204
+ }
205
+ else {
206
+ // No commands exist: synthesize a default command that inherits top-level
207
+ // model/tools/mcpServers/etc. Prompt() uses this path.
208
+ cmdName = '';
209
+ promptMode = true;
210
+ command = configManager.getCommandConfig('');
211
+ }
212
+ // Tool allow/deny flags
213
+ if (flags.tools) {
214
+ command.available_tools = Array.isArray(flags.tools) ? flags.tools : String(flags.tools).split(',').map((s) => s.trim());
215
+ }
216
+ if (flags.subagents === true) {
217
+ const list = command.available_tools;
218
+ if (Array.isArray(list) && list.length > 0) {
219
+ const hasSubagents = list.some((t) => String(t).split('.')[0] === 'subagents');
220
+ if (!hasSubagents) {
221
+ command.available_tools = [...list, 'subagents'];
222
+ }
223
+ }
224
+ }
225
+ if (flags.noTools) {
226
+ command.ignore_tools = Array.isArray(flags.noTools) ? flags.noTools : String(flags.noTools).split(',').map((s) => s.trim());
227
+ }
228
+ // MCP servers
229
+ const serverRegistry = ServerRegistry.init(this.options.mcpFile);
230
+ const mcpServers = {
231
+ ...configManager.getMCPServers(),
232
+ ...(command?.mcpServers || {}),
233
+ ...(this.options.mcpServers || {}),
234
+ };
235
+ const disableMcp = command.disable_mcp === true || configManager.getRawConfig()?.disable_mcp === true;
236
+ if (!disableMcp) {
237
+ serverRegistry.setTomlMCPConfigs(mcpServers);
238
+ }
239
+ const generalInstructions = configManager.getGeneralInstructions();
240
+ const systemPrompt = configManager.getSystemPrompt();
241
+ this.sessionContext = await SessionContext.newSessionContext(flags, command, generalInstructions, systemPrompt, undefined, flags.sid);
242
+ // Determine effective working directory
243
+ // Prefer the earlier effectiveCwd we already computed for agent discovery.
244
+ const agentFilePath = this.options.agentFile ? canonicalizePathSync(this.options.agentFile) : undefined;
245
+ const derivedCwd2 = !explicitCwd && agentFilePath ? path.dirname(agentFilePath) : undefined;
246
+ const effectiveCwd2 = effectiveCwd || derivedCwd2 || canonicalizePathSync(process.cwd());
247
+ try {
248
+ this.sessionContext.setExecutionCwd?.(effectiveCwd2);
249
+ }
250
+ catch { }
251
+ const roots = [effectiveCwd2, ...((this.options.projectRoots || []).map((r) => canonicalizePathSync(r)))];
252
+ try {
253
+ await this.sessionContext.setProjectRootPaths(roots);
254
+ }
255
+ catch { }
256
+ if (!disableMcp) {
257
+ await mcpInitialization();
258
+ }
259
+ // Prefetch context summaries from other sessions (equivalent to CLI --with)
260
+ if (this.options.contextSessionIds && this.options.contextSessionIds.length > 0) {
261
+ try {
262
+ const agentTmp = new AgentAPI(this.sessionContext);
263
+ const { computeNextTaskFocus } = await import('../context/taskFocus.js');
264
+ const taskFocus = computeNextTaskFocus(command.instructions, '', extractSetFlags(flags));
265
+ const summaries = await agentTmp.tryPrefetchSummarization(this.options.contextSessionIds, taskFocus);
266
+ for (const [sid, summary] of Object.entries(summaries)) {
267
+ this.sessionContext.addPreviousSessionSummarization(sid, summary);
268
+ }
269
+ }
270
+ catch { }
271
+ }
272
+ // Per-client message manager and agent
273
+ this.messageManager = new MessageManager();
274
+ this.agent = new AgentAPI(this.sessionContext);
275
+ const backend = ServerData.getInstance();
276
+ this.pushEvent(SdkEventType.Init, this.sessionContext.getSessionId(), {
277
+ sdk_version: getSdkVersion(),
278
+ protocol: 'qodo.sdk.v2',
279
+ pid: process.pid,
280
+ backend: {
281
+ base_url: backend.getBaseUrl(),
282
+ source: backend.getBaseUrlSource(),
283
+ },
284
+ model: this.sessionContext.getModel(),
285
+ });
286
+ // Observe message list changes to emit:
287
+ // - sdk.message.full
288
+ // - sdk.message.delta (best effort from last AI message)
289
+ this.messageManager.addMessageListener((messages) => {
290
+ const lc = toLangChainDict(messages);
291
+ const openai = toOpenAIChat(messages);
292
+ const sid = this.sessionContext.getSessionId();
293
+ this.pushEvent(SdkEventType.MessageFull, sid, {
294
+ messages: { langchain: lc, openai },
295
+ });
296
+ // progress extraction
297
+ try {
298
+ const progress = extractProgress(messages);
299
+ if (progress) {
300
+ this.pushEvent(SdkEventType.Progress, sid, { ...progress });
301
+ }
302
+ }
303
+ catch { }
304
+ // tool lifecycle extraction from LangChain dict (AIMessage tool_calls + ToolMessage results)
305
+ try {
306
+ this.extractToolLifecycleFromLangChain(lc, sid);
307
+ }
308
+ catch { }
309
+ // delta: compare last AI message string
310
+ try {
311
+ const lastAi = messages
312
+ .slice()
313
+ .reverse()
314
+ .find((m) => m?.constructor?.name === 'AIMessage');
315
+ const content = lastAi?.content;
316
+ const text = typeof content === 'string' ? content : '';
317
+ const messageId = lastAi?.additional_kwargs?.id || lastAi?.id || 'ai';
318
+ if (messageId !== this.lastAiMessageId) {
319
+ this.lastAiMessageId = messageId;
320
+ this.lastAiText = '';
321
+ }
322
+ if (text.length > this.lastAiText.length && text.startsWith(this.lastAiText)) {
323
+ const delta = text.slice(this.lastAiText.length);
324
+ if (delta && delta.length > 0) {
325
+ this.pushEvent(SdkEventType.MessageDelta, sid, {
326
+ message_id: String(messageId),
327
+ role: 'assistant',
328
+ delta,
329
+ });
330
+ }
331
+ }
332
+ this.lastAiText = text;
333
+ }
334
+ catch { }
335
+ });
336
+ // Finalization
337
+ this.messageManager.addLoadingListener(async (isLoading) => {
338
+ const sid = this.sessionContext.getSessionId();
339
+ if (!isLoading) {
340
+ try {
341
+ await this.agent.finishCurrentTask(false);
342
+ }
343
+ catch { }
344
+ // AgentRunnerCore already emits final for old SDK, but we produce our own terminal sdk.final here
345
+ // by reading the message manager state.
346
+ try {
347
+ const finalized = buildFinalResult(this.messageManager);
348
+ this.pushEvent(SdkEventType.Final, sid, {
349
+ success: true,
350
+ model: this.sessionContext.getModel(),
351
+ result: {
352
+ ...(finalized.structured_output ? { structured_output: finalized.structured_output } : {}),
353
+ ...(finalized.final_output ? { final_output: finalized.final_output } : {}),
354
+ },
355
+ messages: { langchain: finalized.messagesLC, openai: finalized.messagesOpenAI },
356
+ meta: {
357
+ tools_auto_approved: this.options.autoApproveTools !== false,
358
+ subagents_used: finalized.subagentsUsed,
359
+ },
360
+ });
361
+ this.done = true;
362
+ }
363
+ catch (e) {
364
+ this.pushEvent(SdkEventType.Error, sid, { message: e?.message || 'Failed to finalize' });
365
+ this.pushEvent(SdkEventType.Final, sid, {
366
+ success: false,
367
+ error: e?.message || 'Failed to finalize',
368
+ model: this.sessionContext.getModel(),
369
+ result: {},
370
+ messages: { langchain: [], openai: [] },
371
+ meta: { tools_auto_approved: this.options.autoApproveTools !== false, subagents_used: false },
372
+ });
373
+ this.done = true;
374
+ }
375
+ }
376
+ });
377
+ this.messageManager.addErrorListener(async (error) => {
378
+ if (!error)
379
+ return;
380
+ const sid = this.sessionContext.getSessionId();
381
+ this.pushEvent(SdkEventType.Error, sid, { message: error });
382
+ try {
383
+ await this.agent.finishCurrentTask(true);
384
+ }
385
+ catch { }
386
+ });
387
+ this.core = new AgentRunnerCore(this.sessionContext, this.messageManager, this.agent,
388
+ // No-op emit: we emit via message manager listeners
389
+ () => { }, this.options.autoApproveTools !== false);
390
+ this.initialized = true;
391
+ this.lastInitMeta = {
392
+ commandName: cmdName,
393
+ promptMode,
394
+ cwd: effectiveCwd2,
395
+ agentSource,
396
+ };
397
+ return this.lastInitMeta;
398
+ }
399
+ async maybeApproveTool(req) {
400
+ const { sid, tool_call_id } = req;
401
+ if (this.toolApprovalEmitted.has(tool_call_id) || this.toolApprovalInFlight.has(tool_call_id)) {
402
+ return;
403
+ }
404
+ this.toolApprovalInFlight.add(tool_call_id);
405
+ let approved = this.options.autoApproveTools !== false;
406
+ let reason = undefined;
407
+ if (this.options.autoApproveTools === false) {
408
+ if (this.options.toolApproval) {
409
+ try {
410
+ const res = await this.options.toolApproval({
411
+ tool_call_id: req.tool_call_id,
412
+ server_name: req.server_name,
413
+ tool_name: req.tool_name,
414
+ tool_args: req.tool_args,
415
+ reasoning: req.reasoning,
416
+ });
417
+ approved = !!res;
418
+ if (!approved)
419
+ reason = 'Declined by toolApproval callback';
420
+ }
421
+ catch (e) {
422
+ approved = false;
423
+ reason = e?.message || 'toolApproval callback threw';
424
+ }
425
+ }
426
+ else {
427
+ approved = false;
428
+ reason = 'Auto-approval disabled and no toolApproval callback provided';
429
+ }
430
+ }
431
+ // Emit decision
432
+ this.pushEvent(SdkEventType.ToolApproved, sid, {
433
+ tool_call_id,
434
+ approved,
435
+ ...(approved ? {} : { reason }),
436
+ });
437
+ this.toolApprovalEmitted.add(tool_call_id);
438
+ // IMPORTANT: respond to backend so the run can continue.
439
+ try {
440
+ await this.agent.toolApproval(tool_call_id, approved);
441
+ }
442
+ catch (e) {
443
+ // Surface approval send failures as sdk.error but do not crash the stream.
444
+ this.pushEvent(SdkEventType.Error, sid, {
445
+ message: `Failed to submit tool approval for ${tool_call_id}`,
446
+ cause: e?.message || e,
447
+ });
448
+ }
449
+ finally {
450
+ this.toolApprovalInFlight.delete(tool_call_id);
451
+ }
452
+ }
453
+ extractToolLifecycleFromLangChain(lcMessages, sid) {
454
+ for (const msg of lcMessages) {
455
+ const type = msg?.type;
456
+ const data = msg?.data;
457
+ if (!type || !data)
458
+ continue;
459
+ // Tool request is represented as AI message with tool_calls
460
+ if (type === 'ai' && Array.isArray(data.tool_calls) && data.tool_calls.length > 0) {
461
+ // Determine pending approval from additional_kwargs
462
+ const pendingApproval = !!data.additional_kwargs?.pending_approval;
463
+ const serverName = data.additional_kwargs?.server_name || 'unknown';
464
+ for (const call of data.tool_calls) {
465
+ const toolCallId = String(call?.id || data.id || 'unknown');
466
+ const toolName = String(call?.name || 'unknown');
467
+ const serverStr = String(serverName);
468
+ // Record mapping for later sdk.tool.executed
469
+ if (toolCallId && toolCallId !== 'unknown') {
470
+ this.toolRegistry.set(toolCallId, { server_name: serverStr, tool_name: toolName });
471
+ }
472
+ // Emit tool.requested once per tool_call_id
473
+ if (!this.toolRequestedEmitted.has(toolCallId)) {
474
+ this.pushEvent(SdkEventType.ToolRequested, sid, {
475
+ tool_call_id: toolCallId,
476
+ server_name: serverStr,
477
+ tool_name: toolName,
478
+ tool_args: call?.args,
479
+ reasoning: typeof data.content === 'string' ? data.content : undefined,
480
+ pending_approval: pendingApproval,
481
+ });
482
+ this.toolRequestedEmitted.add(toolCallId);
483
+ }
484
+ // Approval handling
485
+ if (!this.toolApprovalEmitted.has(toolCallId)) {
486
+ if (pendingApproval) {
487
+ // Approval required: decide and respond via AgentAPI.toolApproval
488
+ void this.maybeApproveTool({
489
+ sid,
490
+ tool_call_id: toolCallId,
491
+ server_name: serverStr,
492
+ tool_name: toolName,
493
+ tool_args: call?.args,
494
+ reasoning: typeof data.content === 'string' ? data.content : undefined,
495
+ });
496
+ }
497
+ else {
498
+ // No approval required (auto-approved / read-only)
499
+ this.pushEvent(SdkEventType.ToolApproved, sid, {
500
+ tool_call_id: toolCallId,
501
+ approved: true,
502
+ });
503
+ this.toolApprovalEmitted.add(toolCallId);
504
+ }
505
+ }
506
+ }
507
+ }
508
+ // Tool execution result is represented as ToolMessage
509
+ if (type === 'tool') {
510
+ const toolCallId = String(data.tool_call_id || data.id || 'unknown');
511
+ if (!this.toolExecutedEmitted.has(toolCallId)) {
512
+ const serverName = String(data.additional_kwargs?.server_name || this.toolRegistry.get(toolCallId)?.server_name || 'unknown');
513
+ const toolName = String(this.toolRegistry.get(toolCallId)?.tool_name || 'unknown');
514
+ const status = data.status;
515
+ this.pushEvent(SdkEventType.ToolExecuted, sid, {
516
+ tool_call_id: toolCallId,
517
+ server_name: serverName,
518
+ tool_name: toolName,
519
+ result: {
520
+ isError: status === 'error',
521
+ content: data.content,
522
+ raw: data,
523
+ },
524
+ });
525
+ this.toolExecutedEmitted.add(toolCallId);
526
+ }
527
+ }
528
+ }
529
+ }
530
+ async *stream(commandOrPrompt, options) {
531
+ if (this.activeRuns > 0) {
532
+ const delegated = new QodoSDK(this.options);
533
+ try {
534
+ yield* delegated.stream(commandOrPrompt, options);
535
+ }
536
+ finally {
537
+ try {
538
+ await delegated.dispose();
539
+ }
540
+ catch { }
541
+ }
542
+ return;
543
+ }
544
+ this.activeRuns++;
545
+ try {
546
+ this.done = false;
547
+ this.eventQueue = [];
548
+ this.pendingResolvers = [];
549
+ this.lastAiText = '';
550
+ this.lastAiMessageId = '';
551
+ this.toolRequestedEmitted.clear();
552
+ this.toolApprovalEmitted.clear();
553
+ this.toolApprovalInFlight.clear();
554
+ this.toolExecutedEmitted.clear();
555
+ this.toolRegistry.clear();
556
+ // Initialize per-run metadata
557
+ this.runId = uuid();
558
+ this.seq = 0;
559
+ this.runStartMs = Date.now();
560
+ const env = this.env;
561
+ const self = this;
562
+ async function* inner() {
563
+ // If already initialized and user passed a different command name, reinit (same behavior as old QodoClient)
564
+ if (self.initialized) {
565
+ try {
566
+ const cm = ConfigManager.getInstance();
567
+ const cmds = cm.listCommands();
568
+ const isCommand = commandOrPrompt && cmds.includes(commandOrPrompt);
569
+ if (isCommand) {
570
+ const currentName = (self.sessionContext?.getCommand()?.name) || '';
571
+ if (commandOrPrompt !== currentName) {
572
+ await self.dispose();
573
+ }
574
+ }
575
+ }
576
+ catch { }
577
+ }
578
+ let initMeta = null;
579
+ let initFailed = false;
580
+ try {
581
+ initMeta = await self.ensureInitialized(commandOrPrompt);
582
+ }
583
+ catch (e) {
584
+ initFailed = true;
585
+ // Event-first: initialization errors should produce sdk.error + sdk.final
586
+ const sid = '';
587
+ self.pushEvent(SdkEventType.Error, sid, {
588
+ message: e?.message || String(e),
589
+ cause: e?.cause || e,
590
+ });
591
+ self.pushEvent(SdkEventType.Final, sid, {
592
+ success: false,
593
+ error: e?.message || String(e),
594
+ model: self.options.model || '',
595
+ result: {},
596
+ messages: { langchain: [], openai: [] },
597
+ meta: { tools_auto_approved: self.options.autoApproveTools !== false, subagents_used: false },
598
+ });
599
+ // Do NOT return here – we still want to drain the queued events below.
600
+ }
601
+ if (!initFailed) {
602
+ // Emit run.started
603
+ try {
604
+ const sid = self.sessionContext.getSessionId();
605
+ self.pushEvent(SdkEventType.RunStarted, sid, {
606
+ session_id: sid,
607
+ command: initMeta.commandName,
608
+ prompt_mode: initMeta.promptMode,
609
+ cwd: initMeta.cwd,
610
+ agent: initMeta.agentSource,
611
+ tools_auto_approved: self.options.autoApproveTools !== false,
612
+ });
613
+ }
614
+ catch { }
615
+ }
616
+ const extra = options?.extraInstructions || '';
617
+ const args = options?.args || {};
618
+ // Prompt-first behavior:
619
+ // - If commandOrPrompt matches a configured command name -> run that command.
620
+ // - Otherwise treat it as a free-form prompt and pass it as extraInstructions.
621
+ let prompt;
622
+ let promptExtra;
623
+ try {
624
+ const cm = ConfigManager.getInstance();
625
+ const cmds = cm.listCommands();
626
+ if (commandOrPrompt && cmds.includes(commandOrPrompt)) {
627
+ prompt = commandOrPrompt;
628
+ promptExtra = extra;
629
+ }
630
+ else {
631
+ prompt = '';
632
+ promptExtra = commandOrPrompt ? `${commandOrPrompt}${extra ? ` ${extra}` : ''}` : extra;
633
+ }
634
+ }
635
+ catch {
636
+ prompt = '';
637
+ promptExtra = commandOrPrompt ? `${commandOrPrompt}${extra ? ` ${extra}` : ''}` : extra;
638
+ }
639
+ if (!initFailed) {
640
+ try {
641
+ // If the command was built with sdkCommand({ args: <zod schema> }), validate args here.
642
+ // This keeps v2 behavior strict and provides actionable errors.
643
+ try {
644
+ const cmdAny = self.sessionContext?.getCommand?.();
645
+ const schema = cmdAny?.__sdk?.argsSchema;
646
+ if (schema) {
647
+ const { parseArgsWithSchema } = await import('./schemas.js');
648
+ parseArgsWithSchema(schema, args);
649
+ }
650
+ }
651
+ catch (e) {
652
+ throw e;
653
+ }
654
+ await self.core.start(prompt, promptExtra, args, options?.outputSchema);
655
+ }
656
+ catch (e) {
657
+ const sid = self.sessionContext?.getSessionId() || '';
658
+ self.pushEvent(SdkEventType.Error, sid, { message: e?.message || String(e) });
659
+ self.pushEvent(SdkEventType.Final, sid, {
660
+ success: false,
661
+ error: e?.message || String(e),
662
+ model: self.sessionContext?.getModel() || '',
663
+ result: {},
664
+ messages: { langchain: [], openai: [] },
665
+ meta: { tools_auto_approved: self.options.autoApproveTools !== false, subagents_used: false },
666
+ });
667
+ // Do not set done=true here; allow the event drain loop to see sdk.final and terminate.
668
+ }
669
+ }
670
+ while (true) {
671
+ if (self.eventQueue.length > 0) {
672
+ const ev = self.eventQueue.shift();
673
+ // SDK default: keep internal logs muted for the entire stream.
674
+ // (Consumers can still write to stdout directly if they need streaming output.)
675
+ yield ev;
676
+ if (ev.type === SdkEventType.Final) {
677
+ self.done = true;
678
+ // drain
679
+ while (self.eventQueue.length > 0) {
680
+ const drained = self.eventQueue.shift();
681
+ yield drained;
682
+ }
683
+ break;
684
+ }
685
+ }
686
+ else {
687
+ const next = await new Promise((resolve) => {
688
+ self.pendingResolvers.push((res) => {
689
+ if (res.done)
690
+ resolve(null);
691
+ else
692
+ resolve(res.value);
693
+ });
694
+ if (self.eventQueue.length > 0) {
695
+ const ev = self.eventQueue.shift();
696
+ const r = self.pendingResolvers.shift();
697
+ if (r)
698
+ r({ value: ev, done: false });
699
+ }
700
+ });
701
+ if (next) {
702
+ yield next;
703
+ if (next.type === SdkEventType.Final) {
704
+ self.done = true;
705
+ while (self.eventQueue.length > 0) {
706
+ const drained = self.eventQueue.shift();
707
+ yield drained;
708
+ }
709
+ break;
710
+ }
711
+ }
712
+ }
713
+ // Only terminate once we've yielded sdk.final and there are no queued events left.
714
+ // (self.done may flip to true from internal listeners before sdk.final is drained.)
715
+ if (self.done && self.eventQueue.length === 0)
716
+ break;
717
+ }
718
+ }
719
+ const innerGen = inner();
720
+ while (true) {
721
+ const { value, done } = await runWithEnvironment(env, () => innerGen.next());
722
+ if (done)
723
+ return;
724
+ yield value;
725
+ }
726
+ }
727
+ finally {
728
+ this.activeRuns = Math.max(0, this.activeRuns - 1);
729
+ }
730
+ }
731
+ async run(commandOrPrompt, options) {
732
+ let final = null;
733
+ for await (const ev of this.stream(commandOrPrompt, options)) {
734
+ if (ev.type === SdkEventType.Final)
735
+ final = ev.data;
736
+ }
737
+ await new Promise((r) => setTimeout(r, 10));
738
+ return final;
739
+ }
740
+ /**
741
+ * SDK-first friendly API: treat input as a free-form prompt (never a command name).
742
+ */
743
+ prompt(text, options) {
744
+ const extraInstructions = text;
745
+ return this.run('', { ...options, extraInstructions });
746
+ }
747
+ /**
748
+ * SDK-first friendly API: stream events for a free-form prompt.
749
+ */
750
+ streamPrompt(text, options) {
751
+ const extraInstructions = text;
752
+ return this.stream('', { ...options, extraInstructions });
753
+ }
754
+ cancel() {
755
+ if (!this.initialized)
756
+ return;
757
+ this.core.cancel();
758
+ }
759
+ async dispose() {
760
+ if (!this.initialized) {
761
+ return;
762
+ }
763
+ const env = this.env;
764
+ await runWithEnvironment(env, async () => {
765
+ try {
766
+ await this.core.dispose();
767
+ try {
768
+ this.agent.cleanup?.();
769
+ }
770
+ catch { }
771
+ try {
772
+ const { MCPManager } = await import('../mcp/MCPManager.js');
773
+ try {
774
+ await MCPManager.getInstance().dispose();
775
+ }
776
+ catch { }
777
+ }
778
+ catch { }
779
+ }
780
+ finally {
781
+ this.initialized = false;
782
+ }
783
+ });
784
+ }
785
+ }
786
+ //# sourceMappingURL=QodoSDK.js.map