@codeany/open-agent-sdk 0.2.2 → 0.2.4

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 (280) hide show
  1. package/dist/agent.d.ts +113 -0
  2. package/dist/agent.d.ts.map +1 -0
  3. package/dist/agent.js +453 -0
  4. package/dist/agent.js.map +1 -0
  5. package/dist/engine.d.ts +62 -0
  6. package/dist/engine.d.ts.map +1 -0
  7. package/dist/engine.js +496 -0
  8. package/dist/engine.js.map +1 -0
  9. package/dist/hooks.d.ts +111 -0
  10. package/dist/hooks.d.ts.map +1 -0
  11. package/dist/hooks.js +179 -0
  12. package/dist/hooks.js.map +1 -0
  13. package/dist/index.d.ts +66 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +133 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/mcp/client.d.ts +19 -0
  18. package/dist/mcp/client.d.ts.map +1 -0
  19. package/dist/mcp/client.js +126 -0
  20. package/dist/mcp/client.js.map +1 -0
  21. package/dist/providers/anthropic.d.ts +17 -0
  22. package/dist/providers/anthropic.d.ts.map +1 -0
  23. package/dist/providers/anthropic.js +47 -0
  24. package/dist/providers/anthropic.js.map +1 -0
  25. package/dist/providers/index.d.ts +20 -0
  26. package/dist/providers/index.d.ts.map +1 -0
  27. package/dist/providers/index.js +26 -0
  28. package/dist/providers/index.js.map +1 -0
  29. package/dist/providers/openai.d.ts +26 -0
  30. package/dist/providers/openai.d.ts.map +1 -0
  31. package/dist/providers/openai.js +212 -0
  32. package/dist/providers/openai.js.map +1 -0
  33. package/dist/providers/types.d.ts +84 -0
  34. package/dist/providers/types.d.ts.map +1 -0
  35. package/dist/providers/types.js +11 -0
  36. package/dist/providers/types.js.map +1 -0
  37. package/dist/sdk-mcp-server.d.ts +52 -0
  38. package/dist/sdk-mcp-server.d.ts.map +1 -0
  39. package/dist/sdk-mcp-server.js +57 -0
  40. package/dist/sdk-mcp-server.js.map +1 -0
  41. package/dist/session.d.ts +73 -0
  42. package/dist/session.d.ts.map +1 -0
  43. package/dist/session.js +159 -0
  44. package/dist/session.js.map +1 -0
  45. package/dist/skills/bundled/commit.d.ts +7 -0
  46. package/dist/skills/bundled/commit.d.ts.map +1 -0
  47. package/dist/skills/bundled/commit.js +35 -0
  48. package/dist/skills/bundled/commit.js.map +1 -0
  49. package/dist/skills/bundled/debug.d.ts +7 -0
  50. package/dist/skills/bundled/debug.d.ts.map +1 -0
  51. package/{src/skills/bundled/debug.ts → dist/skills/bundled/debug.js} +20 -22
  52. package/dist/skills/bundled/debug.js.map +1 -0
  53. package/dist/skills/bundled/index.d.ts +11 -0
  54. package/dist/skills/bundled/index.d.ts.map +1 -0
  55. package/dist/skills/bundled/index.js +26 -0
  56. package/dist/skills/bundled/index.js.map +1 -0
  57. package/dist/skills/bundled/review.d.ts +7 -0
  58. package/dist/skills/bundled/review.d.ts.map +1 -0
  59. package/{src/skills/bundled/review.ts → dist/skills/bundled/review.js} +18 -21
  60. package/dist/skills/bundled/review.js.map +1 -0
  61. package/dist/skills/bundled/simplify.d.ts +8 -0
  62. package/dist/skills/bundled/simplify.d.ts.map +1 -0
  63. package/{src/skills/bundled/simplify.ts → dist/skills/bundled/simplify.js} +16 -19
  64. package/dist/skills/bundled/simplify.js.map +1 -0
  65. package/dist/skills/bundled/test.d.ts +7 -0
  66. package/dist/skills/bundled/test.d.ts.map +1 -0
  67. package/{src/skills/bundled/test.ts → dist/skills/bundled/test.js} +18 -21
  68. package/dist/skills/bundled/test.js.map +1 -0
  69. package/dist/skills/index.d.ts +7 -0
  70. package/dist/skills/index.d.ts.map +1 -0
  71. package/dist/skills/index.js +8 -0
  72. package/dist/skills/index.js.map +1 -0
  73. package/dist/skills/registry.d.ts +43 -0
  74. package/dist/skills/registry.d.ts.map +1 -0
  75. package/dist/skills/registry.js +111 -0
  76. package/dist/skills/registry.js.map +1 -0
  77. package/dist/skills/types.d.ts +83 -0
  78. package/dist/skills/types.d.ts.map +1 -0
  79. package/dist/skills/types.js +8 -0
  80. package/dist/skills/types.js.map +1 -0
  81. package/dist/tool-helper.d.ts +73 -0
  82. package/dist/tool-helper.d.ts.map +1 -0
  83. package/dist/tool-helper.js +86 -0
  84. package/dist/tool-helper.js.map +1 -0
  85. package/dist/tools/agent-tool.d.ts +17 -0
  86. package/dist/tools/agent-tool.d.ts.map +1 -0
  87. package/dist/tools/agent-tool.js +146 -0
  88. package/dist/tools/agent-tool.js.map +1 -0
  89. package/dist/tools/ask-user.d.ts +18 -0
  90. package/dist/tools/ask-user.d.ts.map +1 -0
  91. package/dist/tools/ask-user.js +72 -0
  92. package/dist/tools/ask-user.js.map +1 -0
  93. package/dist/tools/bash.d.ts +5 -0
  94. package/dist/tools/bash.d.ts.map +1 -0
  95. package/dist/tools/bash.js +67 -0
  96. package/dist/tools/bash.js.map +1 -0
  97. package/dist/tools/config-tool.d.ts +20 -0
  98. package/dist/tools/config-tool.d.ts.map +1 -0
  99. package/dist/tools/config-tool.js +83 -0
  100. package/dist/tools/config-tool.js.map +1 -0
  101. package/dist/tools/cron-tools.d.ts +33 -0
  102. package/dist/tools/cron-tools.d.ts.map +1 -0
  103. package/dist/tools/cron-tools.js +128 -0
  104. package/dist/tools/cron-tools.js.map +1 -0
  105. package/dist/tools/edit.d.ts +5 -0
  106. package/dist/tools/edit.d.ts.map +1 -0
  107. package/dist/tools/edit.js +70 -0
  108. package/dist/tools/edit.js.map +1 -0
  109. package/dist/tools/glob.d.ts +5 -0
  110. package/dist/tools/glob.d.ts.map +1 -0
  111. package/dist/tools/glob.js +75 -0
  112. package/dist/tools/glob.js.map +1 -0
  113. package/dist/tools/grep.d.ts +5 -0
  114. package/dist/tools/grep.d.ts.map +1 -0
  115. package/dist/tools/grep.js +168 -0
  116. package/dist/tools/grep.js.map +1 -0
  117. package/dist/tools/index.d.ts +45 -0
  118. package/dist/tools/index.d.ts.map +1 -0
  119. package/dist/tools/index.js +162 -0
  120. package/dist/tools/index.js.map +1 -0
  121. package/dist/tools/lsp-tool.d.ts +9 -0
  122. package/dist/tools/lsp-tool.d.ts.map +1 -0
  123. package/dist/tools/lsp-tool.js +137 -0
  124. package/dist/tools/lsp-tool.js.map +1 -0
  125. package/dist/tools/mcp-resource-tools.d.ts +14 -0
  126. package/dist/tools/mcp-resource-tools.d.ts.map +1 -0
  127. package/dist/tools/mcp-resource-tools.js +117 -0
  128. package/dist/tools/mcp-resource-tools.js.map +1 -0
  129. package/dist/tools/notebook-edit.d.ts +5 -0
  130. package/dist/tools/notebook-edit.d.ts.map +1 -0
  131. package/dist/tools/notebook-edit.js +85 -0
  132. package/dist/tools/notebook-edit.js.map +1 -0
  133. package/dist/tools/plan-tools.d.ts +12 -0
  134. package/dist/tools/plan-tools.d.ts.map +1 -0
  135. package/dist/tools/plan-tools.js +77 -0
  136. package/dist/tools/plan-tools.js.map +1 -0
  137. package/dist/tools/read.d.ts +5 -0
  138. package/dist/tools/read.d.ts.map +1 -0
  139. package/dist/tools/read.js +66 -0
  140. package/dist/tools/read.js.map +1 -0
  141. package/dist/tools/send-message.d.ts +31 -0
  142. package/dist/tools/send-message.d.ts.map +1 -0
  143. package/dist/tools/send-message.js +77 -0
  144. package/dist/tools/send-message.js.map +1 -0
  145. package/dist/tools/skill-tool.d.ts +9 -0
  146. package/dist/tools/skill-tool.d.ts.map +1 -0
  147. package/dist/tools/skill-tool.js +115 -0
  148. package/dist/tools/skill-tool.js.map +1 -0
  149. package/dist/tools/task-tools.d.ts +48 -0
  150. package/dist/tools/task-tools.d.ts.map +1 -0
  151. package/dist/tools/task-tools.js +242 -0
  152. package/dist/tools/task-tools.js.map +1 -0
  153. package/dist/tools/team-tools.d.ts +34 -0
  154. package/dist/tools/team-tools.d.ts.map +1 -0
  155. package/dist/tools/team-tools.js +103 -0
  156. package/dist/tools/team-tools.js.map +1 -0
  157. package/dist/tools/todo-tool.d.ts +22 -0
  158. package/dist/tools/todo-tool.d.ts.map +1 -0
  159. package/dist/tools/todo-tool.js +93 -0
  160. package/dist/tools/todo-tool.js.map +1 -0
  161. package/dist/tools/tool-search.d.ts +13 -0
  162. package/dist/tools/tool-search.d.ts.map +1 -0
  163. package/dist/tools/tool-search.js +76 -0
  164. package/dist/tools/tool-search.js.map +1 -0
  165. package/dist/tools/types.d.ts +29 -0
  166. package/dist/tools/types.d.ts.map +1 -0
  167. package/dist/tools/types.js +52 -0
  168. package/dist/tools/types.js.map +1 -0
  169. package/dist/tools/web-fetch.d.ts +5 -0
  170. package/dist/tools/web-fetch.d.ts.map +1 -0
  171. package/dist/tools/web-fetch.js +60 -0
  172. package/dist/tools/web-fetch.js.map +1 -0
  173. package/dist/tools/web-search.d.ts +5 -0
  174. package/dist/tools/web-search.d.ts.map +1 -0
  175. package/dist/tools/web-search.js +77 -0
  176. package/dist/tools/web-search.js.map +1 -0
  177. package/dist/tools/worktree-tools.d.ts +10 -0
  178. package/dist/tools/worktree-tools.d.ts.map +1 -0
  179. package/dist/tools/worktree-tools.js +130 -0
  180. package/dist/tools/worktree-tools.js.map +1 -0
  181. package/dist/tools/write.d.ts +5 -0
  182. package/dist/tools/write.d.ts.map +1 -0
  183. package/dist/tools/write.js +40 -0
  184. package/dist/tools/write.js.map +1 -0
  185. package/dist/types.d.ts +432 -0
  186. package/dist/types.d.ts.map +1 -0
  187. package/dist/types.js +5 -0
  188. package/dist/types.js.map +1 -0
  189. package/dist/utils/compact.d.ts +44 -0
  190. package/dist/utils/compact.d.ts.map +1 -0
  191. package/dist/utils/compact.js +162 -0
  192. package/dist/utils/compact.js.map +1 -0
  193. package/dist/utils/context.d.ts +35 -0
  194. package/dist/utils/context.d.ts.map +1 -0
  195. package/dist/utils/context.js +174 -0
  196. package/dist/utils/context.js.map +1 -0
  197. package/dist/utils/fileCache.d.ts +64 -0
  198. package/dist/utils/fileCache.d.ts.map +1 -0
  199. package/dist/utils/fileCache.js +117 -0
  200. package/dist/utils/fileCache.js.map +1 -0
  201. package/dist/utils/messages.d.ts +57 -0
  202. package/dist/utils/messages.d.ts.map +1 -0
  203. package/dist/utils/messages.js +152 -0
  204. package/dist/utils/messages.js.map +1 -0
  205. package/dist/utils/retry.d.ts +48 -0
  206. package/dist/utils/retry.d.ts.map +1 -0
  207. package/dist/utils/retry.js +111 -0
  208. package/dist/utils/retry.js.map +1 -0
  209. package/dist/utils/tokens.d.ts +57 -0
  210. package/dist/utils/tokens.d.ts.map +1 -0
  211. package/dist/utils/tokens.js +134 -0
  212. package/dist/utils/tokens.js.map +1 -0
  213. package/package.json +6 -1
  214. package/.env.example +0 -8
  215. package/examples/01-simple-query.ts +0 -43
  216. package/examples/02-multi-tool.ts +0 -44
  217. package/examples/03-multi-turn.ts +0 -39
  218. package/examples/04-prompt-api.ts +0 -29
  219. package/examples/05-custom-system-prompt.ts +0 -26
  220. package/examples/06-mcp-server.ts +0 -49
  221. package/examples/07-custom-tools.ts +0 -87
  222. package/examples/08-official-api-compat.ts +0 -38
  223. package/examples/09-subagents.ts +0 -48
  224. package/examples/10-permissions.ts +0 -40
  225. package/examples/11-custom-mcp-tools.ts +0 -101
  226. package/examples/12-skills.ts +0 -88
  227. package/examples/13-hooks.ts +0 -88
  228. package/examples/14-openai-compat.ts +0 -71
  229. package/examples/web/index.html +0 -365
  230. package/examples/web/server.ts +0 -157
  231. package/src/agent.ts +0 -516
  232. package/src/engine.ts +0 -633
  233. package/src/hooks.ts +0 -261
  234. package/src/index.ts +0 -426
  235. package/src/mcp/client.ts +0 -150
  236. package/src/providers/anthropic.ts +0 -60
  237. package/src/providers/index.ts +0 -34
  238. package/src/providers/openai.ts +0 -315
  239. package/src/providers/types.ts +0 -85
  240. package/src/sdk-mcp-server.ts +0 -78
  241. package/src/session.ts +0 -227
  242. package/src/skills/bundled/commit.ts +0 -38
  243. package/src/skills/bundled/index.ts +0 -28
  244. package/src/skills/index.ts +0 -25
  245. package/src/skills/registry.ts +0 -133
  246. package/src/skills/types.ts +0 -99
  247. package/src/tool-helper.ts +0 -127
  248. package/src/tools/agent-tool.ts +0 -164
  249. package/src/tools/ask-user.ts +0 -79
  250. package/src/tools/bash.ts +0 -75
  251. package/src/tools/config-tool.ts +0 -89
  252. package/src/tools/cron-tools.ts +0 -153
  253. package/src/tools/edit.ts +0 -74
  254. package/src/tools/glob.ts +0 -77
  255. package/src/tools/grep.ts +0 -168
  256. package/src/tools/index.ts +0 -240
  257. package/src/tools/lsp-tool.ts +0 -163
  258. package/src/tools/mcp-resource-tools.ts +0 -125
  259. package/src/tools/notebook-edit.ts +0 -93
  260. package/src/tools/plan-tools.ts +0 -88
  261. package/src/tools/read.ts +0 -73
  262. package/src/tools/send-message.ts +0 -96
  263. package/src/tools/skill-tool.ts +0 -133
  264. package/src/tools/task-tools.ts +0 -290
  265. package/src/tools/team-tools.ts +0 -128
  266. package/src/tools/todo-tool.ts +0 -112
  267. package/src/tools/tool-search.ts +0 -87
  268. package/src/tools/types.ts +0 -66
  269. package/src/tools/web-fetch.ts +0 -66
  270. package/src/tools/web-search.ts +0 -86
  271. package/src/tools/worktree-tools.ts +0 -140
  272. package/src/tools/write.ts +0 -42
  273. package/src/types.ts +0 -486
  274. package/src/utils/compact.ts +0 -207
  275. package/src/utils/context.ts +0 -191
  276. package/src/utils/fileCache.ts +0 -148
  277. package/src/utils/messages.ts +0 -195
  278. package/src/utils/retry.ts +0 -140
  279. package/src/utils/tokens.ts +0 -145
  280. package/tsconfig.json +0 -19
package/src/agent.ts DELETED
@@ -1,516 +0,0 @@
1
- /**
2
- * Agent - High-level API
3
- *
4
- * Provides createAgent() and query() interfaces compatible with
5
- * open-agent-sdk.
6
- *
7
- * Usage:
8
- * import { createAgent } from 'open-agent-sdk'
9
- * const agent = createAgent({ model: 'claude-sonnet-4-6' })
10
- * for await (const event of agent.query('Hello')) { ... }
11
- *
12
- * // OpenAI-compatible models
13
- * const agent = createAgent({
14
- * apiType: 'openai-completions',
15
- * model: 'gpt-4o',
16
- * apiKey: 'sk-...',
17
- * baseURL: 'https://api.openai.com/v1',
18
- * })
19
- */
20
-
21
- import type {
22
- AgentOptions,
23
- QueryResult,
24
- SDKMessage,
25
- ToolDefinition,
26
- CanUseToolFn,
27
- Message,
28
- PermissionMode,
29
- } from './types.js'
30
- import { QueryEngine } from './engine.js'
31
- import { getAllBaseTools, filterTools } from './tools/index.js'
32
- import { connectMCPServer, type MCPConnection } from './mcp/client.js'
33
- import { isSdkServerConfig } from './sdk-mcp-server.js'
34
- import { registerAgents } from './tools/agent-tool.js'
35
- import {
36
- saveSession,
37
- loadSession,
38
- } from './session.js'
39
- import { createHookRegistry, type HookRegistry } from './hooks.js'
40
- import { initBundledSkills } from './skills/index.js'
41
- import { createProvider, type LLMProvider, type ApiType } from './providers/index.js'
42
- import type { NormalizedMessageParam } from './providers/types.js'
43
-
44
- // --------------------------------------------------------------------------
45
- // Agent class
46
- // --------------------------------------------------------------------------
47
-
48
- export class Agent {
49
- private cfg: AgentOptions
50
- private toolPool: ToolDefinition[]
51
- private modelId: string
52
- private apiType: ApiType
53
- private apiCredentials: { key?: string; baseUrl?: string }
54
- private provider: LLMProvider
55
- private mcpLinks: MCPConnection[] = []
56
- private history: NormalizedMessageParam[] = []
57
- private messageLog: Message[] = []
58
- private setupDone: Promise<void>
59
- private sid: string
60
- private abortCtrl: AbortController | null = null
61
- private currentEngine: QueryEngine | null = null
62
- private hookRegistry: HookRegistry
63
-
64
- constructor(options: AgentOptions = {}) {
65
- // Shallow copy to avoid mutating caller's object
66
- this.cfg = { ...options }
67
-
68
- // Merge credentials from options.env map, direct options, and process.env
69
- this.apiCredentials = this.pickCredentials()
70
- this.modelId = this.cfg.model ?? this.readEnv('CODEANY_MODEL') ?? 'claude-sonnet-4-6'
71
- this.sid = this.cfg.sessionId ?? crypto.randomUUID()
72
-
73
- // Resolve API type
74
- this.apiType = this.resolveApiType()
75
-
76
- // Create LLM provider
77
- this.provider = createProvider(this.apiType, {
78
- apiKey: this.apiCredentials.key,
79
- baseURL: this.apiCredentials.baseUrl,
80
- })
81
-
82
- // Initialize bundled skills
83
- initBundledSkills()
84
-
85
- // Build hook registry from options
86
- this.hookRegistry = createHookRegistry()
87
- if (this.cfg.hooks) {
88
- // Convert AgentOptions hooks format to HookConfig
89
- for (const [event, defs] of Object.entries(this.cfg.hooks)) {
90
- for (const def of defs) {
91
- for (const handler of def.hooks) {
92
- this.hookRegistry.register(event as any, {
93
- matcher: def.matcher,
94
- timeout: def.timeout,
95
- handler: async (input) => {
96
- const result = await handler(input, input.toolUseId || '', {
97
- signal: this.abortCtrl?.signal || new AbortController().signal,
98
- })
99
- return result || undefined
100
- },
101
- })
102
- }
103
- }
104
- }
105
- }
106
-
107
- // Build tool pool from options (supports ToolDefinition[], string[], or preset)
108
- this.toolPool = this.buildToolPool()
109
-
110
- // Kick off async setup (MCP connections, agent registration, session resume)
111
- this.setupDone = this.setup()
112
- }
113
-
114
- /**
115
- * Resolve API type from options, env, or model name heuristic.
116
- */
117
- private resolveApiType(): ApiType {
118
- // Explicit option
119
- if (this.cfg.apiType) return this.cfg.apiType
120
-
121
- // Env var
122
- const envType =
123
- this.cfg.env?.CODEANY_API_TYPE ??
124
- this.readEnv('CODEANY_API_TYPE')
125
- if (envType === 'openai-completions' || envType === 'anthropic-messages') {
126
- return envType
127
- }
128
-
129
- // Heuristic from model name
130
- const model = this.modelId.toLowerCase()
131
- if (
132
- model.includes('gpt-') ||
133
- model.includes('o1') ||
134
- model.includes('o3') ||
135
- model.includes('o4') ||
136
- model.includes('deepseek') ||
137
- model.includes('qwen') ||
138
- model.includes('yi-') ||
139
- model.includes('glm') ||
140
- model.includes('mistral') ||
141
- model.includes('gemma')
142
- ) {
143
- return 'openai-completions'
144
- }
145
-
146
- return 'anthropic-messages'
147
- }
148
-
149
- /** Pick API key and base URL from options or CODEANY_* env vars. */
150
- private pickCredentials(): { key?: string; baseUrl?: string } {
151
- const envMap = this.cfg.env
152
- return {
153
- key:
154
- this.cfg.apiKey ??
155
- envMap?.CODEANY_API_KEY ??
156
- envMap?.CODEANY_AUTH_TOKEN ??
157
- this.readEnv('CODEANY_API_KEY') ??
158
- this.readEnv('CODEANY_AUTH_TOKEN'),
159
- baseUrl:
160
- this.cfg.baseURL ??
161
- envMap?.CODEANY_BASE_URL ??
162
- this.readEnv('CODEANY_BASE_URL'),
163
- }
164
- }
165
-
166
- /** Read a value from process.env (returns undefined if missing). */
167
- private readEnv(key: string): string | undefined {
168
- return process.env[key] || undefined
169
- }
170
-
171
- /** Assemble the available tool set based on options. */
172
- private buildToolPool(): ToolDefinition[] {
173
- const raw = this.cfg.tools
174
- let pool: ToolDefinition[]
175
-
176
- if (!raw || (typeof raw === 'object' && !Array.isArray(raw) && 'type' in raw)) {
177
- pool = getAllBaseTools()
178
- } else if (Array.isArray(raw) && raw.length > 0 && typeof raw[0] === 'string') {
179
- pool = filterTools(getAllBaseTools(), raw as string[])
180
- } else {
181
- pool = raw as ToolDefinition[]
182
- }
183
-
184
- return filterTools(pool, this.cfg.allowedTools, this.cfg.disallowedTools)
185
- }
186
-
187
- /**
188
- * Async initialization: connect MCP servers, register agents, resume sessions.
189
- */
190
- private async setup(): Promise<void> {
191
- // Register custom agent definitions
192
- if (this.cfg.agents) {
193
- registerAgents(this.cfg.agents)
194
- }
195
-
196
- // Connect MCP servers (supports stdio, SSE, HTTP, and in-process SDK servers)
197
- if (this.cfg.mcpServers) {
198
- for (const [name, config] of Object.entries(this.cfg.mcpServers)) {
199
- try {
200
- if (isSdkServerConfig(config)) {
201
- // In-process SDK MCP server - directly add tools
202
- this.toolPool = [...this.toolPool, ...config.tools]
203
- } else {
204
- // External MCP server
205
- const connection = await connectMCPServer(name, config)
206
- this.mcpLinks.push(connection)
207
-
208
- if (connection.status === 'connected' && connection.tools.length > 0) {
209
- this.toolPool = [...this.toolPool, ...connection.tools]
210
- }
211
- }
212
- } catch (err: any) {
213
- console.error(`[MCP] Failed to connect to "${name}": ${err.message}`)
214
- }
215
- }
216
- }
217
-
218
- // Resume or continue session
219
- if (this.cfg.resume) {
220
- const sessionData = await loadSession(this.cfg.resume)
221
- if (sessionData) {
222
- this.history = sessionData.messages
223
- this.sid = this.cfg.resume
224
- }
225
- }
226
- }
227
-
228
- /**
229
- * Run a query with streaming events.
230
- */
231
- async *query(
232
- prompt: string,
233
- overrides?: Partial<AgentOptions>,
234
- ): AsyncGenerator<SDKMessage, void> {
235
- await this.setupDone
236
-
237
- const opts = { ...this.cfg, ...overrides }
238
- const cwd = opts.cwd || process.cwd()
239
-
240
- // Create abort controller for this query
241
- this.abortCtrl = opts.abortController || new AbortController()
242
- if (opts.abortSignal) {
243
- opts.abortSignal.addEventListener('abort', () => this.abortCtrl?.abort(), { once: true })
244
- }
245
-
246
- // Resolve systemPrompt (handle preset object)
247
- let systemPrompt: string | undefined
248
- let appendSystemPrompt = opts.appendSystemPrompt
249
- if (typeof opts.systemPrompt === 'object' && opts.systemPrompt?.type === 'preset') {
250
- systemPrompt = undefined // Use engine default (default style)
251
- if (opts.systemPrompt.append) {
252
- appendSystemPrompt = (appendSystemPrompt || '') + '\n' + opts.systemPrompt.append
253
- }
254
- } else {
255
- systemPrompt = opts.systemPrompt as string | undefined
256
- }
257
-
258
- // Build canUseTool based on permission mode
259
- const permMode = opts.permissionMode ?? 'bypassPermissions'
260
- const canUseTool: CanUseToolFn = opts.canUseTool ?? (async (_tool, _input) => {
261
- if (permMode === 'bypassPermissions' || permMode === 'dontAsk' || permMode === 'auto') {
262
- return { behavior: 'allow' }
263
- }
264
- if (permMode === 'acceptEdits') {
265
- return { behavior: 'allow' }
266
- }
267
- return { behavior: 'allow' }
268
- })
269
-
270
- // Resolve tools with overrides
271
- let tools = this.toolPool
272
- if (overrides?.allowedTools || overrides?.disallowedTools) {
273
- tools = filterTools(tools, overrides.allowedTools, overrides.disallowedTools)
274
- }
275
- if (overrides?.tools) {
276
- const ot = overrides.tools
277
- if (Array.isArray(ot) && ot.length > 0 && typeof ot[0] === 'string') {
278
- tools = filterTools(this.toolPool, ot as string[])
279
- } else if (Array.isArray(ot)) {
280
- tools = ot as ToolDefinition[]
281
- }
282
- }
283
-
284
- // Recreate provider if overrides change credentials or apiType
285
- let provider = this.provider
286
- if (overrides?.apiType || overrides?.apiKey || overrides?.baseURL) {
287
- const resolvedApiType = overrides.apiType ?? this.apiType
288
- provider = createProvider(resolvedApiType, {
289
- apiKey: overrides.apiKey ?? this.apiCredentials.key,
290
- baseURL: overrides.baseURL ?? this.apiCredentials.baseUrl,
291
- })
292
- }
293
-
294
- // Create query engine with current conversation state
295
- const engine = new QueryEngine({
296
- cwd,
297
- model: opts.model || this.modelId,
298
- provider,
299
- tools,
300
- systemPrompt,
301
- appendSystemPrompt,
302
- maxTurns: opts.maxTurns ?? 10,
303
- maxBudgetUsd: opts.maxBudgetUsd,
304
- maxTokens: opts.maxTokens ?? 16384,
305
- thinking: opts.thinking,
306
- jsonSchema: opts.jsonSchema,
307
- canUseTool,
308
- includePartialMessages: opts.includePartialMessages ?? false,
309
- abortSignal: this.abortCtrl.signal,
310
- agents: opts.agents,
311
- hookRegistry: this.hookRegistry,
312
- sessionId: this.sid,
313
- })
314
- this.currentEngine = engine
315
-
316
- // Inject existing conversation history
317
- for (const msg of this.history) {
318
- (engine as any).messages.push(msg)
319
- }
320
-
321
- // Run the engine
322
- for await (const event of engine.submitMessage(prompt)) {
323
- yield event
324
-
325
- // Track assistant messages for multi-turn persistence
326
- if (event.type === 'assistant') {
327
- const uuid = crypto.randomUUID()
328
- const timestamp = new Date().toISOString()
329
- this.messageLog.push({
330
- type: 'assistant',
331
- message: event.message,
332
- uuid,
333
- timestamp,
334
- })
335
- }
336
- }
337
-
338
- // Persist conversation state for multi-turn
339
- this.history = engine.getMessages()
340
-
341
- // Add user message to tracked messages
342
- const userUuid = crypto.randomUUID()
343
- this.messageLog.push({
344
- type: 'user',
345
- message: { role: 'user', content: prompt },
346
- uuid: userUuid,
347
- timestamp: new Date().toISOString(),
348
- })
349
- }
350
-
351
- /**
352
- * Convenience method: send a prompt and collect the final answer as a single object.
353
- * Internally iterates through the streaming query and aggregates the outcome.
354
- */
355
- async prompt(
356
- text: string,
357
- overrides?: Partial<AgentOptions>,
358
- ): Promise<QueryResult> {
359
- const t0 = performance.now()
360
- const collected = { text: '', turns: 0, tokens: { in: 0, out: 0 } }
361
-
362
- for await (const ev of this.query(text, overrides)) {
363
- switch (ev.type) {
364
- case 'assistant': {
365
- // Extract the last assistant text (multi-turn: only final answer matters)
366
- const fragments = (ev.message.content as any[])
367
- .filter((c: any) => c.type === 'text')
368
- .map((c: any) => c.text)
369
- if (fragments.length) collected.text = fragments.join('')
370
- break
371
- }
372
- case 'result':
373
- collected.turns = ev.num_turns ?? 0
374
- collected.tokens.in = ev.usage?.input_tokens ?? 0
375
- collected.tokens.out = ev.usage?.output_tokens ?? 0
376
- break
377
- }
378
- }
379
-
380
- return {
381
- text: collected.text,
382
- usage: { input_tokens: collected.tokens.in, output_tokens: collected.tokens.out },
383
- num_turns: collected.turns,
384
- duration_ms: Math.round(performance.now() - t0),
385
- messages: [...this.messageLog],
386
- }
387
- }
388
-
389
- /**
390
- * Get conversation messages.
391
- */
392
- getMessages(): Message[] {
393
- return [...this.messageLog]
394
- }
395
-
396
- /**
397
- * Reset conversation history.
398
- */
399
- clear(): void {
400
- this.history = []
401
- this.messageLog = []
402
- }
403
-
404
- /**
405
- * Interrupt the current query.
406
- */
407
- async interrupt(): Promise<void> {
408
- this.abortCtrl?.abort()
409
- }
410
-
411
- /**
412
- * Change the model during a session.
413
- */
414
- async setModel(model?: string): Promise<void> {
415
- if (model) {
416
- this.modelId = model
417
- this.cfg.model = model
418
- }
419
- }
420
-
421
- /**
422
- * Change the permission mode during a session.
423
- */
424
- async setPermissionMode(mode: PermissionMode): Promise<void> {
425
- this.cfg.permissionMode = mode
426
- }
427
-
428
- /**
429
- * Set maximum thinking tokens.
430
- */
431
- async setMaxThinkingTokens(maxThinkingTokens: number | null): Promise<void> {
432
- if (maxThinkingTokens === null) {
433
- this.cfg.thinking = { type: 'disabled' }
434
- } else {
435
- this.cfg.thinking = { type: 'enabled', budgetTokens: maxThinkingTokens }
436
- }
437
- }
438
-
439
- /**
440
- * Get the session ID.
441
- */
442
- getSessionId(): string {
443
- return this.sid
444
- }
445
-
446
- /**
447
- * Get the current API type.
448
- */
449
- getApiType(): ApiType {
450
- return this.apiType
451
- }
452
-
453
- /**
454
- * Stop a background task.
455
- */
456
- async stopTask(taskId: string): Promise<void> {
457
- const { getTask } = await import('./tools/task-tools.js')
458
- const task = getTask(taskId)
459
- if (task) {
460
- task.status = 'cancelled'
461
- }
462
- }
463
-
464
- /**
465
- * Close MCP connections and clean up.
466
- * Optionally persist session to disk.
467
- */
468
- async close(): Promise<void> {
469
- // Persist session if enabled
470
- if (this.cfg.persistSession !== false && this.history.length > 0) {
471
- try {
472
- await saveSession(this.sid, this.history, {
473
- cwd: this.cfg.cwd || process.cwd(),
474
- model: this.modelId,
475
- summary: undefined,
476
- })
477
- } catch {
478
- // Session persistence is best-effort
479
- }
480
- }
481
-
482
- for (const conn of this.mcpLinks) {
483
- await conn.close()
484
- }
485
- this.mcpLinks = []
486
- }
487
- }
488
-
489
- // --------------------------------------------------------------------------
490
- // Factory function
491
- // --------------------------------------------------------------------------
492
-
493
- /** Factory: shorthand for `new Agent(options)`. */
494
- export function createAgent(options: AgentOptions = {}): Agent {
495
- return new Agent(options)
496
- }
497
-
498
- // --------------------------------------------------------------------------
499
- // Standalone query — one-shot convenience wrapper
500
- // --------------------------------------------------------------------------
501
-
502
- /**
503
- * Execute a single agentic query without managing an Agent instance.
504
- * The agent is created, used, and cleaned up automatically.
505
- */
506
- export async function* query(params: {
507
- prompt: string
508
- options?: AgentOptions
509
- }): AsyncGenerator<SDKMessage, void> {
510
- const ephemeral = createAgent(params.options)
511
- try {
512
- yield* ephemeral.query(params.prompt)
513
- } finally {
514
- await ephemeral.close()
515
- }
516
- }