@codeany/open-agent-sdk 0.2.1 → 0.2.2

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 (232) hide show
  1. package/.env.example +8 -0
  2. package/examples/01-simple-query.ts +43 -0
  3. package/examples/02-multi-tool.ts +44 -0
  4. package/examples/03-multi-turn.ts +39 -0
  5. package/examples/04-prompt-api.ts +29 -0
  6. package/examples/05-custom-system-prompt.ts +26 -0
  7. package/examples/06-mcp-server.ts +49 -0
  8. package/examples/07-custom-tools.ts +87 -0
  9. package/examples/08-official-api-compat.ts +38 -0
  10. package/examples/09-subagents.ts +48 -0
  11. package/examples/10-permissions.ts +40 -0
  12. package/examples/11-custom-mcp-tools.ts +101 -0
  13. package/examples/12-skills.ts +88 -0
  14. package/examples/13-hooks.ts +88 -0
  15. package/examples/14-openai-compat.ts +71 -0
  16. package/examples/web/index.html +365 -0
  17. package/examples/web/server.ts +157 -0
  18. package/package.json +1 -7
  19. package/src/engine.ts +3 -0
  20. package/tsconfig.json +19 -0
  21. package/dist/agent.d.ts +0 -113
  22. package/dist/agent.d.ts.map +0 -1
  23. package/dist/agent.js +0 -446
  24. package/dist/agent.js.map +0 -1
  25. package/dist/engine.d.ts +0 -62
  26. package/dist/engine.d.ts.map +0 -1
  27. package/dist/engine.js +0 -494
  28. package/dist/engine.js.map +0 -1
  29. package/dist/hooks.d.ts +0 -111
  30. package/dist/hooks.d.ts.map +0 -1
  31. package/dist/hooks.js +0 -179
  32. package/dist/hooks.js.map +0 -1
  33. package/dist/index.d.ts +0 -66
  34. package/dist/index.d.ts.map +0 -1
  35. package/dist/index.js +0 -133
  36. package/dist/index.js.map +0 -1
  37. package/dist/mcp/client.d.ts +0 -19
  38. package/dist/mcp/client.d.ts.map +0 -1
  39. package/dist/mcp/client.js +0 -126
  40. package/dist/mcp/client.js.map +0 -1
  41. package/dist/providers/anthropic.d.ts +0 -17
  42. package/dist/providers/anthropic.d.ts.map +0 -1
  43. package/dist/providers/anthropic.js +0 -47
  44. package/dist/providers/anthropic.js.map +0 -1
  45. package/dist/providers/index.d.ts +0 -20
  46. package/dist/providers/index.d.ts.map +0 -1
  47. package/dist/providers/index.js +0 -26
  48. package/dist/providers/index.js.map +0 -1
  49. package/dist/providers/openai.d.ts +0 -26
  50. package/dist/providers/openai.d.ts.map +0 -1
  51. package/dist/providers/openai.js +0 -212
  52. package/dist/providers/openai.js.map +0 -1
  53. package/dist/providers/types.d.ts +0 -84
  54. package/dist/providers/types.d.ts.map +0 -1
  55. package/dist/providers/types.js +0 -11
  56. package/dist/providers/types.js.map +0 -1
  57. package/dist/sdk-mcp-server.d.ts +0 -52
  58. package/dist/sdk-mcp-server.d.ts.map +0 -1
  59. package/dist/sdk-mcp-server.js +0 -57
  60. package/dist/sdk-mcp-server.js.map +0 -1
  61. package/dist/session.d.ts +0 -73
  62. package/dist/session.d.ts.map +0 -1
  63. package/dist/session.js +0 -159
  64. package/dist/session.js.map +0 -1
  65. package/dist/skills/bundled/commit.d.ts +0 -7
  66. package/dist/skills/bundled/commit.d.ts.map +0 -1
  67. package/dist/skills/bundled/commit.js +0 -35
  68. package/dist/skills/bundled/commit.js.map +0 -1
  69. package/dist/skills/bundled/debug.d.ts +0 -7
  70. package/dist/skills/bundled/debug.d.ts.map +0 -1
  71. package/dist/skills/bundled/debug.js +0 -46
  72. package/dist/skills/bundled/debug.js.map +0 -1
  73. package/dist/skills/bundled/index.d.ts +0 -11
  74. package/dist/skills/bundled/index.d.ts.map +0 -1
  75. package/dist/skills/bundled/index.js +0 -26
  76. package/dist/skills/bundled/index.js.map +0 -1
  77. package/dist/skills/bundled/review.d.ts +0 -7
  78. package/dist/skills/bundled/review.d.ts.map +0 -1
  79. package/dist/skills/bundled/review.js +0 -38
  80. package/dist/skills/bundled/review.js.map +0 -1
  81. package/dist/skills/bundled/simplify.d.ts +0 -8
  82. package/dist/skills/bundled/simplify.d.ts.map +0 -1
  83. package/dist/skills/bundled/simplify.js +0 -48
  84. package/dist/skills/bundled/simplify.js.map +0 -1
  85. package/dist/skills/bundled/test.d.ts +0 -7
  86. package/dist/skills/bundled/test.d.ts.map +0 -1
  87. package/dist/skills/bundled/test.js +0 -40
  88. package/dist/skills/bundled/test.js.map +0 -1
  89. package/dist/skills/index.d.ts +0 -7
  90. package/dist/skills/index.d.ts.map +0 -1
  91. package/dist/skills/index.js +0 -8
  92. package/dist/skills/index.js.map +0 -1
  93. package/dist/skills/registry.d.ts +0 -43
  94. package/dist/skills/registry.d.ts.map +0 -1
  95. package/dist/skills/registry.js +0 -111
  96. package/dist/skills/registry.js.map +0 -1
  97. package/dist/skills/types.d.ts +0 -83
  98. package/dist/skills/types.d.ts.map +0 -1
  99. package/dist/skills/types.js +0 -8
  100. package/dist/skills/types.js.map +0 -1
  101. package/dist/tool-helper.d.ts +0 -73
  102. package/dist/tool-helper.d.ts.map +0 -1
  103. package/dist/tool-helper.js +0 -86
  104. package/dist/tool-helper.js.map +0 -1
  105. package/dist/tools/agent-tool.d.ts +0 -17
  106. package/dist/tools/agent-tool.d.ts.map +0 -1
  107. package/dist/tools/agent-tool.js +0 -146
  108. package/dist/tools/agent-tool.js.map +0 -1
  109. package/dist/tools/ask-user.d.ts +0 -18
  110. package/dist/tools/ask-user.d.ts.map +0 -1
  111. package/dist/tools/ask-user.js +0 -72
  112. package/dist/tools/ask-user.js.map +0 -1
  113. package/dist/tools/bash.d.ts +0 -5
  114. package/dist/tools/bash.d.ts.map +0 -1
  115. package/dist/tools/bash.js +0 -67
  116. package/dist/tools/bash.js.map +0 -1
  117. package/dist/tools/config-tool.d.ts +0 -20
  118. package/dist/tools/config-tool.d.ts.map +0 -1
  119. package/dist/tools/config-tool.js +0 -83
  120. package/dist/tools/config-tool.js.map +0 -1
  121. package/dist/tools/cron-tools.d.ts +0 -33
  122. package/dist/tools/cron-tools.d.ts.map +0 -1
  123. package/dist/tools/cron-tools.js +0 -128
  124. package/dist/tools/cron-tools.js.map +0 -1
  125. package/dist/tools/edit.d.ts +0 -5
  126. package/dist/tools/edit.d.ts.map +0 -1
  127. package/dist/tools/edit.js +0 -70
  128. package/dist/tools/edit.js.map +0 -1
  129. package/dist/tools/glob.d.ts +0 -5
  130. package/dist/tools/glob.d.ts.map +0 -1
  131. package/dist/tools/glob.js +0 -75
  132. package/dist/tools/glob.js.map +0 -1
  133. package/dist/tools/grep.d.ts +0 -5
  134. package/dist/tools/grep.d.ts.map +0 -1
  135. package/dist/tools/grep.js +0 -168
  136. package/dist/tools/grep.js.map +0 -1
  137. package/dist/tools/index.d.ts +0 -45
  138. package/dist/tools/index.d.ts.map +0 -1
  139. package/dist/tools/index.js +0 -162
  140. package/dist/tools/index.js.map +0 -1
  141. package/dist/tools/lsp-tool.d.ts +0 -9
  142. package/dist/tools/lsp-tool.d.ts.map +0 -1
  143. package/dist/tools/lsp-tool.js +0 -137
  144. package/dist/tools/lsp-tool.js.map +0 -1
  145. package/dist/tools/mcp-resource-tools.d.ts +0 -14
  146. package/dist/tools/mcp-resource-tools.d.ts.map +0 -1
  147. package/dist/tools/mcp-resource-tools.js +0 -117
  148. package/dist/tools/mcp-resource-tools.js.map +0 -1
  149. package/dist/tools/notebook-edit.d.ts +0 -5
  150. package/dist/tools/notebook-edit.d.ts.map +0 -1
  151. package/dist/tools/notebook-edit.js +0 -85
  152. package/dist/tools/notebook-edit.js.map +0 -1
  153. package/dist/tools/plan-tools.d.ts +0 -12
  154. package/dist/tools/plan-tools.d.ts.map +0 -1
  155. package/dist/tools/plan-tools.js +0 -77
  156. package/dist/tools/plan-tools.js.map +0 -1
  157. package/dist/tools/read.d.ts +0 -5
  158. package/dist/tools/read.d.ts.map +0 -1
  159. package/dist/tools/read.js +0 -66
  160. package/dist/tools/read.js.map +0 -1
  161. package/dist/tools/send-message.d.ts +0 -31
  162. package/dist/tools/send-message.d.ts.map +0 -1
  163. package/dist/tools/send-message.js +0 -77
  164. package/dist/tools/send-message.js.map +0 -1
  165. package/dist/tools/skill-tool.d.ts +0 -9
  166. package/dist/tools/skill-tool.d.ts.map +0 -1
  167. package/dist/tools/skill-tool.js +0 -115
  168. package/dist/tools/skill-tool.js.map +0 -1
  169. package/dist/tools/task-tools.d.ts +0 -48
  170. package/dist/tools/task-tools.d.ts.map +0 -1
  171. package/dist/tools/task-tools.js +0 -242
  172. package/dist/tools/task-tools.js.map +0 -1
  173. package/dist/tools/team-tools.d.ts +0 -34
  174. package/dist/tools/team-tools.d.ts.map +0 -1
  175. package/dist/tools/team-tools.js +0 -103
  176. package/dist/tools/team-tools.js.map +0 -1
  177. package/dist/tools/todo-tool.d.ts +0 -22
  178. package/dist/tools/todo-tool.d.ts.map +0 -1
  179. package/dist/tools/todo-tool.js +0 -93
  180. package/dist/tools/todo-tool.js.map +0 -1
  181. package/dist/tools/tool-search.d.ts +0 -13
  182. package/dist/tools/tool-search.d.ts.map +0 -1
  183. package/dist/tools/tool-search.js +0 -76
  184. package/dist/tools/tool-search.js.map +0 -1
  185. package/dist/tools/types.d.ts +0 -29
  186. package/dist/tools/types.d.ts.map +0 -1
  187. package/dist/tools/types.js +0 -52
  188. package/dist/tools/types.js.map +0 -1
  189. package/dist/tools/web-fetch.d.ts +0 -5
  190. package/dist/tools/web-fetch.d.ts.map +0 -1
  191. package/dist/tools/web-fetch.js +0 -60
  192. package/dist/tools/web-fetch.js.map +0 -1
  193. package/dist/tools/web-search.d.ts +0 -5
  194. package/dist/tools/web-search.d.ts.map +0 -1
  195. package/dist/tools/web-search.js +0 -77
  196. package/dist/tools/web-search.js.map +0 -1
  197. package/dist/tools/worktree-tools.d.ts +0 -10
  198. package/dist/tools/worktree-tools.d.ts.map +0 -1
  199. package/dist/tools/worktree-tools.js +0 -130
  200. package/dist/tools/worktree-tools.js.map +0 -1
  201. package/dist/tools/write.d.ts +0 -5
  202. package/dist/tools/write.d.ts.map +0 -1
  203. package/dist/tools/write.js +0 -40
  204. package/dist/tools/write.js.map +0 -1
  205. package/dist/types.d.ts +0 -423
  206. package/dist/types.d.ts.map +0 -1
  207. package/dist/types.js +0 -5
  208. package/dist/types.js.map +0 -1
  209. package/dist/utils/compact.d.ts +0 -44
  210. package/dist/utils/compact.d.ts.map +0 -1
  211. package/dist/utils/compact.js +0 -162
  212. package/dist/utils/compact.js.map +0 -1
  213. package/dist/utils/context.d.ts +0 -35
  214. package/dist/utils/context.d.ts.map +0 -1
  215. package/dist/utils/context.js +0 -174
  216. package/dist/utils/context.js.map +0 -1
  217. package/dist/utils/fileCache.d.ts +0 -64
  218. package/dist/utils/fileCache.d.ts.map +0 -1
  219. package/dist/utils/fileCache.js +0 -117
  220. package/dist/utils/fileCache.js.map +0 -1
  221. package/dist/utils/messages.d.ts +0 -57
  222. package/dist/utils/messages.d.ts.map +0 -1
  223. package/dist/utils/messages.js +0 -152
  224. package/dist/utils/messages.js.map +0 -1
  225. package/dist/utils/retry.d.ts +0 -48
  226. package/dist/utils/retry.d.ts.map +0 -1
  227. package/dist/utils/retry.js +0 -111
  228. package/dist/utils/retry.js.map +0 -1
  229. package/dist/utils/tokens.d.ts +0 -57
  230. package/dist/utils/tokens.d.ts.map +0 -1
  231. package/dist/utils/tokens.js +0 -134
  232. package/dist/utils/tokens.js.map +0 -1
package/.env.example ADDED
@@ -0,0 +1,8 @@
1
+ # Required: your LLM API key
2
+ CODEANY_API_KEY=sk-or-...
3
+
4
+ # Optional: override model
5
+ # CODEANY_MODEL=anthropic/claude-sonnet-4
6
+
7
+ # Optional: custom API endpoint (e.g. third-party proxy)
8
+ # CODEANY_BASE_URL=https://openrouter.ai/api
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Example 1: Simple Query with Streaming
3
+ *
4
+ * Demonstrates the basic createAgent() + query() flow with
5
+ * real-time event streaming.
6
+ *
7
+ * Run: npx tsx examples/01-simple-query.ts
8
+ */
9
+ import { createAgent } from '../src/index.js'
10
+
11
+ async function main() {
12
+ console.log('--- Example 1: Simple Query ---\n')
13
+
14
+ const agent = createAgent({
15
+ model: process.env.CODEANY_MODEL || 'claude-sonnet-4-6',
16
+ maxTurns: 10,
17
+ })
18
+
19
+ for await (const event of agent.query(
20
+ 'Read package.json and tell me the project name and version in one sentence.',
21
+ )) {
22
+ const msg = event as any
23
+
24
+ if (msg.type === 'assistant') {
25
+ // Print tool calls
26
+ for (const block of msg.message?.content || []) {
27
+ if (block.type === 'tool_use') {
28
+ console.log(`[Tool] ${block.name}(${JSON.stringify(block.input).slice(0, 80)})`)
29
+ }
30
+ if (block.type === 'text') {
31
+ console.log(`\nAssistant: ${block.text}`)
32
+ }
33
+ }
34
+ }
35
+
36
+ if (msg.type === 'result') {
37
+ console.log(`\n--- Result: ${msg.subtype} ---`)
38
+ console.log(`Tokens: ${msg.usage?.input_tokens} in / ${msg.usage?.output_tokens} out`)
39
+ }
40
+ }
41
+ }
42
+
43
+ main().catch(console.error)
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Example 2: Multi-Tool Orchestration
3
+ *
4
+ * The agent autonomously uses Glob, Bash, and Read tools to
5
+ * accomplish a multi-step task.
6
+ *
7
+ * Run: npx tsx examples/02-multi-tool.ts
8
+ */
9
+ import { createAgent } from '../src/index.js'
10
+
11
+ async function main() {
12
+ console.log('--- Example 2: Multi-Tool Orchestration ---\n')
13
+
14
+ const agent = createAgent({
15
+ model: process.env.CODEANY_MODEL || 'claude-sonnet-4-6',
16
+ maxTurns: 15,
17
+ })
18
+
19
+ for await (const event of agent.query(
20
+ 'Do these steps: ' +
21
+ '1) Use Glob to find all .ts files in src/ (pattern "src/*.ts"). ' +
22
+ '2) Use Bash to count lines in src/agent.ts with `wc -l`. ' +
23
+ '3) Give a brief summary.',
24
+ )) {
25
+ const msg = event as any
26
+
27
+ if (msg.type === 'assistant') {
28
+ for (const block of msg.message?.content || []) {
29
+ if (block.type === 'tool_use') {
30
+ console.log(`[${block.name}] ${JSON.stringify(block.input).slice(0, 100)}`)
31
+ }
32
+ if (block.type === 'text' && block.text.trim()) {
33
+ console.log(`\n${block.text}`)
34
+ }
35
+ }
36
+ }
37
+
38
+ if (msg.type === 'result') {
39
+ console.log(`\n--- ${msg.subtype} | ${msg.usage?.input_tokens}/${msg.usage?.output_tokens} tokens ---`)
40
+ }
41
+ }
42
+ }
43
+
44
+ main().catch(console.error)
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Example 3: Multi-Turn Conversation
3
+ *
4
+ * Demonstrates session persistence across multiple turns.
5
+ * The agent remembers context from previous interactions.
6
+ *
7
+ * Run: npx tsx examples/03-multi-turn.ts
8
+ */
9
+ import { createAgent } from '../src/index.js'
10
+
11
+ async function main() {
12
+ console.log('--- Example 3: Multi-Turn Conversation ---\n')
13
+
14
+ const agent = createAgent({
15
+ model: process.env.CODEANY_MODEL || 'claude-sonnet-4-6',
16
+ maxTurns: 5,
17
+ })
18
+
19
+ // Turn 1: Create a file
20
+ console.log('> Turn 1: Create a file')
21
+ const r1 = await agent.prompt(
22
+ 'Use Bash to run: echo "Hello Open Agent SDK" > /tmp/oas-test.txt. Confirm briefly.',
23
+ )
24
+ console.log(` ${r1.text}\n`)
25
+
26
+ // Turn 2: Read back (should remember context)
27
+ console.log('> Turn 2: Read the file back')
28
+ const r2 = await agent.prompt('Read the file you just created and tell me its contents.')
29
+ console.log(` ${r2.text}\n`)
30
+
31
+ // Turn 3: Clean up
32
+ console.log('> Turn 3: Cleanup')
33
+ const r3 = await agent.prompt('Delete that file with Bash. Confirm.')
34
+ console.log(` ${r3.text}\n`)
35
+
36
+ console.log(`Session history: ${agent.getMessages().length} messages`)
37
+ }
38
+
39
+ main().catch(console.error)
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Example 4: Simple Prompt API
3
+ *
4
+ * Uses the blocking prompt() method for quick one-shot queries.
5
+ * No need to iterate over streaming events.
6
+ *
7
+ * Run: npx tsx examples/04-prompt-api.ts
8
+ */
9
+ import { createAgent } from '../src/index.js'
10
+
11
+ async function main() {
12
+ console.log('--- Example 4: Simple Prompt API ---\n')
13
+
14
+ const agent = createAgent({
15
+ model: process.env.CODEANY_MODEL || 'claude-sonnet-4-6',
16
+ maxTurns: 5,
17
+ })
18
+
19
+ const result = await agent.prompt(
20
+ 'Use Bash to run `node --version` and `npm --version`, then tell me the versions.',
21
+ )
22
+
23
+ console.log(`Answer: ${result.text}`)
24
+ console.log(`Turns: ${result.num_turns}`)
25
+ console.log(`Tokens: ${result.usage.input_tokens} in / ${result.usage.output_tokens} out`)
26
+ console.log(`Duration: ${result.duration_ms}ms`)
27
+ }
28
+
29
+ main().catch(console.error)
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Example 5: Custom System Prompt
3
+ *
4
+ * Shows how to customize the agent's behavior with a system prompt.
5
+ *
6
+ * Run: npx tsx examples/05-custom-system-prompt.ts
7
+ */
8
+ import { createAgent } from '../src/index.js'
9
+
10
+ async function main() {
11
+ console.log('--- Example 5: Custom System Prompt ---\n')
12
+
13
+ const agent = createAgent({
14
+ model: process.env.CODEANY_MODEL || 'claude-sonnet-4-6',
15
+ maxTurns: 5,
16
+ systemPrompt:
17
+ 'You are a senior code reviewer. When asked to review code, focus on: ' +
18
+ '1) Security issues, 2) Performance concerns, 3) Maintainability. ' +
19
+ 'Be concise and use bullet points.',
20
+ })
21
+
22
+ const result = await agent.prompt('Read src/agent.ts and give a brief code review.')
23
+ console.log(result.text)
24
+ }
25
+
26
+ main().catch(console.error)
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Example 6: MCP Server Integration
3
+ *
4
+ * Connects to an MCP (Model Context Protocol) server and uses
5
+ * its tools through the agent. This example uses the filesystem
6
+ * MCP server as a demonstration.
7
+ *
8
+ * Prerequisites:
9
+ * npm install -g @modelcontextprotocol/server-filesystem
10
+ *
11
+ * Run: npx tsx examples/06-mcp-server.ts
12
+ */
13
+ import { createAgent } from '../src/index.js'
14
+
15
+ async function main() {
16
+ console.log('--- Example 6: MCP Server Integration ---\n')
17
+
18
+ const agent = createAgent({
19
+ model: process.env.CODEANY_MODEL || 'claude-sonnet-4-6',
20
+ maxTurns: 10,
21
+ mcpServers: {
22
+ filesystem: {
23
+ command: 'npx',
24
+ args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
25
+ },
26
+ },
27
+ })
28
+
29
+ console.log('Connecting to MCP filesystem server...\n')
30
+
31
+ const result = await agent.prompt(
32
+ 'Use the filesystem MCP tools to list files in /tmp. Be brief.',
33
+ )
34
+
35
+ console.log(`Answer: ${result.text}`)
36
+ console.log(`Turns: ${result.num_turns}`)
37
+
38
+ await agent.close()
39
+ }
40
+
41
+ main().catch(e => {
42
+ console.error('Error:', e.message)
43
+ if (e.message.includes('ENOENT') || e.message.includes('not found')) {
44
+ console.error(
45
+ '\nMCP server not found. Install it with:\n' +
46
+ ' npm install -g @modelcontextprotocol/server-filesystem\n',
47
+ )
48
+ }
49
+ })
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Example 7: Custom Tools
3
+ *
4
+ * Shows how to define and use custom tools alongside built-in tools.
5
+ *
6
+ * Run: npx tsx examples/07-custom-tools.ts
7
+ */
8
+ import { createAgent, getAllBaseTools, defineTool } from '../src/index.js'
9
+
10
+ const weatherTool = defineTool({
11
+ name: 'GetWeather',
12
+ description: 'Get current weather for a city. Returns temperature and conditions.',
13
+ inputSchema: {
14
+ type: 'object',
15
+ properties: {
16
+ city: { type: 'string', description: 'City name (e.g., "Tokyo", "London")' },
17
+ },
18
+ required: ['city'],
19
+ },
20
+ isReadOnly: true,
21
+ isConcurrencySafe: true,
22
+ async call(input) {
23
+ const temps: Record<string, number> = {
24
+ tokyo: 22, london: 14, beijing: 25, 'new york': 18, paris: 16,
25
+ }
26
+ const temp = temps[input.city?.toLowerCase()] ?? 20
27
+ return `Weather in ${input.city}: ${temp}°C, partly cloudy`
28
+ },
29
+ })
30
+
31
+ const calculatorTool = defineTool({
32
+ name: 'Calculator',
33
+ description: 'Evaluate a mathematical expression. Use ** for exponentiation.',
34
+ inputSchema: {
35
+ type: 'object',
36
+ properties: {
37
+ expression: { type: 'string', description: 'Math expression (e.g., "42 * 17 + 3", "2 ** 10")' },
38
+ },
39
+ required: ['expression'],
40
+ },
41
+ isReadOnly: true,
42
+ isConcurrencySafe: true,
43
+ async call(input) {
44
+ try {
45
+ const result = Function(`'use strict'; return (${input.expression})`)()
46
+ return `${input.expression} = ${result}`
47
+ } catch (e: any) {
48
+ return { data: `Error: ${e.message}`, is_error: true }
49
+ }
50
+ },
51
+ })
52
+
53
+ async function main() {
54
+ console.log('--- Example 7: Custom Tools ---\n')
55
+
56
+ const builtinTools = getAllBaseTools()
57
+ const allTools = [...builtinTools, weatherTool, calculatorTool]
58
+
59
+ const agent = createAgent({
60
+ model: process.env.CODEANY_MODEL || 'claude-sonnet-4-6',
61
+ maxTurns: 10,
62
+ tools: allTools,
63
+ })
64
+
65
+ console.log(`Loaded ${allTools.length} tools (${builtinTools.length} built-in + 2 custom)\n`)
66
+
67
+ for await (const event of agent.query(
68
+ 'What is the weather in Tokyo and London? Also calculate 2**10 * 3. Be brief.',
69
+ )) {
70
+ const msg = event as any
71
+ if (msg.type === 'assistant') {
72
+ for (const block of msg.message?.content || []) {
73
+ if (block.type === 'tool_use') {
74
+ console.log(`[${block.name}] ${JSON.stringify(block.input)}`)
75
+ }
76
+ if (block.type === 'text' && block.text.trim()) {
77
+ console.log(`\n${block.text}`)
78
+ }
79
+ }
80
+ }
81
+ if (msg.type === 'result') {
82
+ console.log(`\n--- ${msg.subtype} ---`)
83
+ }
84
+ }
85
+ }
86
+
87
+ main().catch(console.error)
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Example 8: Official SDK-Compatible API
3
+ *
4
+ * Demonstrates the query() function with the same API pattern
5
+ * as open-agent-sdk. Drop-in compatible.
6
+ *
7
+ * Run: npx tsx examples/08-official-api-compat.ts
8
+ */
9
+ import { query } from '../src/index.js'
10
+
11
+ async function main() {
12
+ console.log('--- Example 8: Official SDK-Compatible API ---\n')
13
+
14
+ // Standard SDK query pattern
15
+ for await (const message of query({
16
+ prompt: 'What files are in this directory? Be brief.',
17
+ options: {
18
+ allowedTools: ['Bash', 'Glob'],
19
+ permissionMode: 'bypassPermissions',
20
+ },
21
+ })) {
22
+ const msg = message as any
23
+
24
+ if (msg.type === 'assistant' && msg.message?.content) {
25
+ for (const block of msg.message.content) {
26
+ if ('text' in block && block.text) {
27
+ console.log(block.text)
28
+ } else if ('name' in block) {
29
+ console.log(`Tool: ${block.name}`)
30
+ }
31
+ }
32
+ } else if (msg.type === 'result') {
33
+ console.log(`\nDone: ${msg.subtype}`)
34
+ }
35
+ }
36
+ }
37
+
38
+ main().catch(console.error)
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Example 9: Subagents
3
+ *
4
+ * Define specialized subagents that the main agent can delegate
5
+ * tasks to. Matches the official SDK's agents option.
6
+ *
7
+ * Run: npx tsx examples/09-subagents.ts
8
+ */
9
+ import { query } from '../src/index.js'
10
+
11
+ async function main() {
12
+ console.log('--- Example 9: Subagents ---\n')
13
+
14
+ for await (const message of query({
15
+ prompt: 'Use the code-reviewer agent to review src/agent.ts',
16
+ options: {
17
+ allowedTools: ['Read', 'Glob', 'Grep', 'Agent'],
18
+ agents: {
19
+ 'code-reviewer': {
20
+ description: 'Expert code reviewer for quality and security reviews.',
21
+ prompt:
22
+ 'Analyze code quality and suggest improvements. Focus on ' +
23
+ 'security, performance, and maintainability. Be concise.',
24
+ tools: ['Read', 'Glob', 'Grep'],
25
+ },
26
+ },
27
+ },
28
+ })) {
29
+ const msg = message as any
30
+
31
+ if (msg.type === 'assistant') {
32
+ for (const block of msg.message?.content || []) {
33
+ if ('text' in block && block.text?.trim()) {
34
+ console.log(block.text)
35
+ }
36
+ if ('name' in block) {
37
+ console.log(`[${block.name}] ${JSON.stringify(block.input || {}).slice(0, 80)}`)
38
+ }
39
+ }
40
+ }
41
+
42
+ if (msg.type === 'result') {
43
+ console.log(`\n--- ${msg.subtype} ---`)
44
+ }
45
+ }
46
+ }
47
+
48
+ main().catch(console.error)
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Example 10: Permissions and Allowed Tools
3
+ *
4
+ * Shows how to restrict which tools the agent can use.
5
+ * Creates a read-only agent that can analyze but not modify code.
6
+ *
7
+ * Run: npx tsx examples/10-permissions.ts
8
+ */
9
+ import { query } from '../src/index.js'
10
+
11
+ async function main() {
12
+ console.log('--- Example 10: Read-Only Agent ---\n')
13
+
14
+ // Read-only agent: can only use Read, Glob, Grep
15
+ for await (const message of query({
16
+ prompt: 'Review the code in src/agent.ts for best practices. Be concise.',
17
+ options: {
18
+ allowedTools: ['Read', 'Glob', 'Grep'],
19
+ },
20
+ })) {
21
+ const msg = message as any
22
+
23
+ if (msg.type === 'assistant') {
24
+ for (const block of msg.message?.content || []) {
25
+ if ('text' in block && block.text?.trim()) {
26
+ console.log(block.text)
27
+ }
28
+ if ('name' in block) {
29
+ console.log(`[${block.name}]`)
30
+ }
31
+ }
32
+ }
33
+
34
+ if (msg.type === 'result') {
35
+ console.log(`\n--- ${msg.subtype} ---`)
36
+ }
37
+ }
38
+ }
39
+
40
+ main().catch(console.error)
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Example 11: Custom Tools with tool() + createSdkMcpServer()
3
+ *
4
+ * Shows the Zod-based tool() helper and in-process MCP server creation.
5
+ * This is the recommended way to add custom tools.
6
+ *
7
+ * Run: npx tsx examples/11-custom-mcp-tools.ts
8
+ */
9
+ import { z } from 'zod'
10
+ import { query, tool, createSdkMcpServer } from '../src/index.js'
11
+
12
+ // Define tools using Zod schemas for type-safe input validation
13
+ const getTemperature = tool(
14
+ 'get_temperature',
15
+ 'Get the current temperature at a location',
16
+ {
17
+ city: z.string().describe('City name'),
18
+ unit: z.enum(['celsius', 'fahrenheit']).default('celsius').describe('Temperature unit'),
19
+ },
20
+ async ({ city, unit }) => {
21
+ // Mock weather data
22
+ const temps: Record<string, number> = {
23
+ tokyo: 22, london: 14, paris: 16, 'new york': 18, beijing: 25,
24
+ }
25
+ const tempC = temps[city.toLowerCase()] ?? 20
26
+ const temp = unit === 'fahrenheit' ? tempC * 9 / 5 + 32 : tempC
27
+ const symbol = unit === 'fahrenheit' ? '°F' : '°C'
28
+
29
+ return {
30
+ content: [{ type: 'text' as const, text: `Temperature in ${city}: ${temp}${symbol}` }],
31
+ }
32
+ },
33
+ { annotations: { readOnlyHint: true } },
34
+ )
35
+
36
+ const convertUnits = tool(
37
+ 'convert_units',
38
+ 'Convert between measurement units',
39
+ {
40
+ value: z.number().describe('Value to convert'),
41
+ from_unit: z.string().describe('Source unit'),
42
+ to_unit: z.string().describe('Target unit'),
43
+ },
44
+ async ({ value, from_unit, to_unit }) => {
45
+ const conversions: Record<string, Record<string, (v: number) => number>> = {
46
+ km: { miles: (v) => v * 0.621371, m: (v) => v * 1000 },
47
+ miles: { km: (v) => v * 1.60934, m: (v) => v * 1609.34 },
48
+ kg: { lbs: (v) => v * 2.20462, g: (v) => v * 1000 },
49
+ lbs: { kg: (v) => v * 0.453592, g: (v) => v * 453.592 },
50
+ }
51
+
52
+ const fn = conversions[from_unit]?.[to_unit]
53
+ if (!fn) {
54
+ return {
55
+ content: [{ type: 'text' as const, text: `Cannot convert from ${from_unit} to ${to_unit}` }],
56
+ isError: true,
57
+ }
58
+ }
59
+
60
+ const result = fn(value)
61
+ return {
62
+ content: [{ type: 'text' as const, text: `${value} ${from_unit} = ${result.toFixed(2)} ${to_unit}` }],
63
+ }
64
+ },
65
+ )
66
+
67
+ // Bundle tools into an in-process MCP server
68
+ const utilityServer = createSdkMcpServer({
69
+ name: 'utilities',
70
+ version: '1.0.0',
71
+ tools: [getTemperature, convertUnits],
72
+ })
73
+
74
+ async function main() {
75
+ console.log('--- Example 11: Custom MCP Tools (tool + createSdkMcpServer) ---\n')
76
+
77
+ for await (const message of query({
78
+ prompt: 'What is the temperature in Tokyo and Paris? Also convert 10 km to miles. Be brief.',
79
+ options: {
80
+ mcpServers: { utilities: utilityServer as any },
81
+ allowedTools: ['mcp__utilities__*'],
82
+ permissionMode: 'bypassPermissions',
83
+ },
84
+ })) {
85
+ const msg = message as any
86
+
87
+ if (msg.type === 'assistant' && msg.message?.content) {
88
+ for (const block of msg.message.content) {
89
+ if ('text' in block && block.text?.trim()) {
90
+ console.log(block.text)
91
+ } else if ('name' in block) {
92
+ console.log(`[${block.name}] ${JSON.stringify(block.input || {})}`)
93
+ }
94
+ }
95
+ } else if (msg.type === 'result') {
96
+ console.log(`\nDone: ${msg.subtype} (cost: $${msg.total_cost_usd?.toFixed(4) || '0'})`)
97
+ }
98
+ }
99
+ }
100
+
101
+ main().catch(console.error)
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Example 12: Skills
3
+ *
4
+ * Shows how to use the skill system: bundled skills, custom skills,
5
+ * and invoking skills programmatically.
6
+ *
7
+ * Run: npx tsx examples/12-skills.ts
8
+ */
9
+ import {
10
+ createAgent,
11
+ registerSkill,
12
+ getAllSkills,
13
+ getUserInvocableSkills,
14
+ getSkill,
15
+ initBundledSkills,
16
+ } from '../src/index.js'
17
+ import type { SkillContentBlock } from '../src/index.js'
18
+
19
+ async function main() {
20
+ console.log('--- Example 12: Skills ---\n')
21
+
22
+ // Bundled skills are auto-initialized when creating an Agent,
23
+ // but you can also init them explicitly:
24
+ initBundledSkills()
25
+
26
+ // List all registered skills
27
+ const all = getAllSkills()
28
+ console.log(`Registered skills (${all.length}):`)
29
+ for (const skill of all) {
30
+ console.log(` - ${skill.name}: ${skill.description.slice(0, 80)}...`)
31
+ }
32
+
33
+ // Register a custom skill
34
+ registerSkill({
35
+ name: 'explain',
36
+ description: 'Explain a concept or piece of code in simple terms.',
37
+ aliases: ['eli5'],
38
+ userInvocable: true,
39
+ async getPrompt(args): Promise<SkillContentBlock[]> {
40
+ return [{
41
+ type: 'text',
42
+ text: `Explain the following in simple, clear terms that a beginner could understand. Use analogies where helpful.\n\nTopic: ${args || 'Ask the user what they want explained.'}`,
43
+ }]
44
+ },
45
+ })
46
+
47
+ console.log(`\nAfter registering custom skill: ${getAllSkills().length} total`)
48
+ console.log(`User-invocable: ${getUserInvocableSkills().length}`)
49
+
50
+ // Get a specific skill
51
+ const commitSkill = getSkill('commit')
52
+ if (commitSkill) {
53
+ const blocks = await commitSkill.getPrompt('', { cwd: process.cwd() })
54
+ console.log(`\nCommit skill prompt (first 200 chars):`)
55
+ console.log(blocks[0]?.type === 'text' ? blocks[0].text.slice(0, 200) + '...' : '(non-text)')
56
+ }
57
+
58
+ // Use skills with an agent - the model can invoke them via the Skill tool
59
+ console.log('\n--- Using skills with an agent ---\n')
60
+
61
+ const agent = createAgent({
62
+ model: process.env.CODEANY_MODEL || 'claude-sonnet-4-6',
63
+ maxTurns: 5,
64
+ })
65
+
66
+ for await (const event of agent.query(
67
+ 'Use the "explain" skill to explain what git rebase does.',
68
+ )) {
69
+ const msg = event as any
70
+ if (msg.type === 'assistant') {
71
+ for (const block of msg.message?.content || []) {
72
+ if (block.type === 'tool_use') {
73
+ console.log(`[Tool: ${block.name}] ${JSON.stringify(block.input)}`)
74
+ }
75
+ if (block.type === 'text' && block.text.trim()) {
76
+ console.log(block.text)
77
+ }
78
+ }
79
+ }
80
+ if (msg.type === 'result') {
81
+ console.log(`\n--- ${msg.subtype} ---`)
82
+ }
83
+ }
84
+
85
+ await agent.close()
86
+ }
87
+
88
+ main().catch(console.error)