@clawnet/template-minimal 0.0.1

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 (67) hide show
  1. package/.agents/skills/claude-agent-sdk/.claude-plugin/plugin.json +13 -0
  2. package/.agents/skills/claude-agent-sdk/SKILL.md +954 -0
  3. package/.agents/skills/claude-agent-sdk/references/mcp-servers-guide.md +387 -0
  4. package/.agents/skills/claude-agent-sdk/references/permissions-guide.md +429 -0
  5. package/.agents/skills/claude-agent-sdk/references/query-api-reference.md +437 -0
  6. package/.agents/skills/claude-agent-sdk/references/session-management.md +419 -0
  7. package/.agents/skills/claude-agent-sdk/references/subagents-patterns.md +464 -0
  8. package/.agents/skills/claude-agent-sdk/references/top-errors.md +503 -0
  9. package/.agents/skills/claude-agent-sdk/rules/claude-agent-sdk.md +96 -0
  10. package/.agents/skills/claude-agent-sdk/scripts/check-versions.sh +55 -0
  11. package/.agents/skills/claude-agent-sdk/templates/basic-query.ts +55 -0
  12. package/.agents/skills/claude-agent-sdk/templates/custom-mcp-server.ts +161 -0
  13. package/.agents/skills/claude-agent-sdk/templates/error-handling.ts +283 -0
  14. package/.agents/skills/claude-agent-sdk/templates/filesystem-settings.ts +211 -0
  15. package/.agents/skills/claude-agent-sdk/templates/multi-agent-workflow.ts +318 -0
  16. package/.agents/skills/claude-agent-sdk/templates/package.json +30 -0
  17. package/.agents/skills/claude-agent-sdk/templates/permission-control.ts +211 -0
  18. package/.agents/skills/claude-agent-sdk/templates/query-with-tools.ts +54 -0
  19. package/.agents/skills/claude-agent-sdk/templates/session-management.ts +151 -0
  20. package/.agents/skills/claude-agent-sdk/templates/subagents-orchestration.ts +166 -0
  21. package/.agents/skills/claude-agent-sdk/templates/tsconfig.json +22 -0
  22. package/.claude/settings.local.json +70 -0
  23. package/.claude/skills/moltbook-example/SKILL.md +79 -0
  24. package/.claude/skills/post/SKILL.md +130 -0
  25. package/.env.example +4 -0
  26. package/.vercel/README.txt +11 -0
  27. package/.vercel/project.json +1 -0
  28. package/AGENTS.md +114 -0
  29. package/CLAUDE.md +532 -0
  30. package/README.md +44 -0
  31. package/api/index.ts +3 -0
  32. package/biome.json +14 -0
  33. package/clark_avatar.jpeg +0 -0
  34. package/package.json +21 -0
  35. package/scripts/wake.ts +38 -0
  36. package/skills/clawbook/HEARTBEAT.md +142 -0
  37. package/skills/clawbook/SKILL.md +219 -0
  38. package/skills/moltbook-example/SKILL.md +79 -0
  39. package/skills/moltbook-example/bot/index.ts +61 -0
  40. package/src/agent/prompts.ts +98 -0
  41. package/src/agent/runner.ts +526 -0
  42. package/src/agent/tool-definitions.ts +1151 -0
  43. package/src/agent-options.ts +14 -0
  44. package/src/bot-identity.ts +41 -0
  45. package/src/constants.ts +15 -0
  46. package/src/handlers/heartbeat.ts +21 -0
  47. package/src/handlers/openai-compat.ts +95 -0
  48. package/src/handlers/post.ts +21 -0
  49. package/src/identity.ts +83 -0
  50. package/src/index.ts +30 -0
  51. package/src/middleware/cron-auth.ts +53 -0
  52. package/src/middleware/sigma-auth.ts +147 -0
  53. package/src/runs.ts +49 -0
  54. package/tests/agent/prompts.test.ts +172 -0
  55. package/tests/agent/runner.test.ts +353 -0
  56. package/tests/agent/tool-definitions.test.ts +171 -0
  57. package/tests/constants.test.ts +24 -0
  58. package/tests/handlers/openai-compat.test.ts +128 -0
  59. package/tests/handlers.test.ts +133 -0
  60. package/tests/identity.test.ts +66 -0
  61. package/tests/index.test.ts +108 -0
  62. package/tests/middleware/cron-auth.test.ts +99 -0
  63. package/tests/middleware/sigma-auth.test.ts +198 -0
  64. package/tests/runs.test.ts +56 -0
  65. package/tests/skill.test.ts +71 -0
  66. package/tsconfig.json +14 -0
  67. package/vercel.json +9 -0
@@ -0,0 +1,318 @@
1
+ import { query, createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
2
+ import { z } from "zod";
3
+
4
+ /**
5
+ * Complete Multi-Agent Workflow Template
6
+ *
7
+ * Demonstrates:
8
+ * - Complex multi-agent orchestration
9
+ * - Custom tools for agents
10
+ * - Environment-based configuration
11
+ * - Production-ready error handling
12
+ * - Comprehensive monitoring
13
+ */
14
+
15
+ // Custom tools for notification and logging
16
+ const appTools = createSdkMcpServer({
17
+ name: "app-services",
18
+ version: "1.0.0",
19
+ tools: [
20
+ tool(
21
+ "send_notification",
22
+ "Send notification to users or teams",
23
+ {
24
+ userId: z.string().optional(),
25
+ teamId: z.string().optional(),
26
+ message: z.string(),
27
+ priority: z.enum(["low", "medium", "high", "critical"]).default("medium")
28
+ },
29
+ async (args) => {
30
+ // Simulate notification service
31
+ console.log(`šŸ“§ Notification (${args.priority}): ${args.message}`);
32
+ return {
33
+ content: [{ type: "text", text: "Notification sent successfully" }]
34
+ };
35
+ }
36
+ ),
37
+ tool(
38
+ "log_event",
39
+ "Log application events for monitoring",
40
+ {
41
+ event: z.string(),
42
+ data: z.record(z.any()).optional(),
43
+ severity: z.enum(["debug", "info", "warning", "error", "critical"]).default("info")
44
+ },
45
+ async (args) => {
46
+ console.log(`šŸ“ [${args.severity.toUpperCase()}] ${args.event}:`, args.data || '');
47
+ return {
48
+ content: [{ type: "text", text: "Event logged" }]
49
+ };
50
+ }
51
+ ),
52
+ tool(
53
+ "check_health",
54
+ "Check system health metrics",
55
+ {
56
+ service: z.string(),
57
+ metrics: z.array(z.enum(["cpu", "memory", "disk", "network"])).optional()
58
+ },
59
+ async (args) => {
60
+ // Simulate health check
61
+ const health = {
62
+ service: args.service,
63
+ status: "healthy",
64
+ uptime: "99.9%",
65
+ responseTime: "50ms"
66
+ };
67
+ return {
68
+ content: [{ type: "text", text: JSON.stringify(health, null, 2) }]
69
+ };
70
+ }
71
+ )
72
+ ]
73
+ });
74
+
75
+ // Main DevOps agent orchestrator
76
+ async function runDevOpsAgent(task: string) {
77
+ console.log(`šŸš€ Starting DevOps Agent for: ${task}\n`);
78
+
79
+ const response = query({
80
+ prompt: task,
81
+ options: {
82
+ model: "claude-sonnet-4-5",
83
+ workingDirectory: process.cwd(),
84
+ systemPrompt: `You are a DevOps automation expert and orchestrator.
85
+
86
+ Your responsibilities:
87
+ - Monitor system health
88
+ - Deploy applications safely
89
+ - Handle incidents and alerts
90
+ - Maintain infrastructure
91
+ - Coordinate specialized agents
92
+
93
+ Always log your actions and notify relevant stakeholders.
94
+ Follow the principle of least privilege for tool access.`,
95
+
96
+ // Custom tools
97
+ mcpServers: {
98
+ "app-services": appTools
99
+ },
100
+
101
+ // Specialized agents for different tasks
102
+ agents: {
103
+ "deployment-agent": {
104
+ description: "Handles application deployments, rollbacks, and release management",
105
+ prompt: `You manage deployments.
106
+
107
+ Deployment checklist:
108
+ 1. Verify all tests pass
109
+ 2. Deploy to staging first
110
+ 3. Run smoke tests
111
+ 4. Deploy to production
112
+ 5. Create rollback plan
113
+ 6. Monitor for issues
114
+
115
+ Always notify stakeholders of deployment status.`,
116
+ tools: [
117
+ "Bash",
118
+ "Read",
119
+ "mcp__app-services__log_event",
120
+ "mcp__app-services__send_notification",
121
+ "mcp__app-services__check_health"
122
+ ],
123
+ model: "sonnet"
124
+ },
125
+
126
+ "incident-responder": {
127
+ description: "Responds to production incidents, outages, and performance issues",
128
+ prompt: `You handle incidents.
129
+
130
+ Incident response process:
131
+ 1. Assess impact (users affected, services down)
132
+ 2. Identify root cause
133
+ 3. Implement immediate fixes
134
+ 4. Communicate status updates
135
+ 5. Document incident for post-mortem
136
+
137
+ Work quickly but carefully. User experience is critical.`,
138
+ tools: [
139
+ "Bash",
140
+ "Read",
141
+ "Grep",
142
+ "mcp__app-services__log_event",
143
+ "mcp__app-services__send_notification",
144
+ "mcp__app-services__check_health"
145
+ ],
146
+ model: "sonnet"
147
+ },
148
+
149
+ "monitoring-agent": {
150
+ description: "Monitors system metrics, health checks, and alerts on issues",
151
+ prompt: `You monitor systems.
152
+
153
+ Monitoring tasks:
154
+ - Check application metrics
155
+ - Analyze error rates
156
+ - Monitor response times
157
+ - Verify system health
158
+ - Alert on anomalies
159
+
160
+ Report issues immediately.`,
161
+ tools: [
162
+ "Bash",
163
+ "Read",
164
+ "mcp__app-services__log_event",
165
+ "mcp__app-services__send_notification",
166
+ "mcp__app-services__check_health"
167
+ ],
168
+ model: "haiku" // Fast, cost-effective for monitoring
169
+ },
170
+
171
+ "security-agent": {
172
+ description: "Performs security audits, vulnerability scanning, and compliance checks",
173
+ prompt: `You ensure security.
174
+
175
+ Security checks:
176
+ - Scan for exposed secrets
177
+ - Check dependency vulnerabilities
178
+ - Verify access controls
179
+ - Validate compliance (OWASP, SOC2)
180
+ - Audit infrastructure config
181
+
182
+ Block deployments if critical issues found.`,
183
+ tools: [
184
+ "Bash",
185
+ "Read",
186
+ "Grep",
187
+ "mcp__app-services__log_event",
188
+ "mcp__app-services__send_notification"
189
+ ],
190
+ model: "sonnet"
191
+ },
192
+
193
+ "performance-agent": {
194
+ description: "Analyzes performance metrics, identifies bottlenecks, and suggests optimizations",
195
+ prompt: `You optimize performance.
196
+
197
+ Performance analysis:
198
+ - Database query times
199
+ - API response times
200
+ - Memory/CPU usage
201
+ - Network latency
202
+ - Caching effectiveness
203
+
204
+ Identify bottlenecks and optimization opportunities.`,
205
+ tools: [
206
+ "Bash",
207
+ "Read",
208
+ "Grep",
209
+ "mcp__app-services__log_event",
210
+ "mcp__app-services__check_health"
211
+ ],
212
+ model: "sonnet"
213
+ }
214
+ },
215
+
216
+ // Permission control
217
+ permissionMode: "default",
218
+ canUseTool: async (toolName, input) => {
219
+ // Log all tool usage
220
+ console.log(`šŸ”§ [${new Date().toISOString()}] ${toolName}`);
221
+
222
+ // Prevent destructive operations
223
+ if (toolName === 'Bash') {
224
+ const dangerous = ['rm -rf', 'dd if=', 'mkfs', '> /dev/', 'shutdown'];
225
+ if (dangerous.some(pattern => input.command.includes(pattern))) {
226
+ return {
227
+ behavior: "deny",
228
+ message: `Destructive command blocked: ${input.command}`
229
+ };
230
+ }
231
+ }
232
+
233
+ // Require confirmation for production deployments
234
+ if (input.command?.includes('deploy --production') ||
235
+ input.command?.includes('kubectl apply -n production')) {
236
+ return {
237
+ behavior: "ask",
238
+ message: `āš ļø PRODUCTION DEPLOYMENT: ${input.command}\n\nConfirm?`
239
+ };
240
+ }
241
+
242
+ return { behavior: "allow" };
243
+ }
244
+ }
245
+ });
246
+
247
+ // Track execution
248
+ const agentsUsed = new Set<string>();
249
+ const toolsExecuted: string[] = [];
250
+ let sessionId: string | undefined;
251
+
252
+ try {
253
+ for await (const message of response) {
254
+ switch (message.type) {
255
+ case 'system':
256
+ if (message.subtype === 'init') {
257
+ sessionId = message.session_id;
258
+ console.log(`✨ Session: ${sessionId}\n`);
259
+ }
260
+ break;
261
+
262
+ case 'assistant':
263
+ console.log('šŸ“‹ Orchestrator:', message.content);
264
+ break;
265
+
266
+ case 'tool_call':
267
+ console.log(`\nšŸ”§ Executing: ${message.tool_name}`);
268
+ toolsExecuted.push(message.tool_name);
269
+ break;
270
+
271
+ case 'tool_result':
272
+ console.log(`āœ… ${message.tool_name} completed`);
273
+ break;
274
+
275
+ case 'error':
276
+ console.error('āŒ Error:', message.error.message);
277
+ break;
278
+ }
279
+ }
280
+
281
+ console.log(`\n\nāœ… Task completed successfully`);
282
+ console.log(`Session ID: ${sessionId}`);
283
+ console.log(`Tools executed: ${toolsExecuted.length}`);
284
+ } catch (error) {
285
+ console.error('šŸ’„ Fatal error:', error);
286
+ throw error;
287
+ }
288
+ }
289
+
290
+ // Usage examples
291
+ async function main() {
292
+ try {
293
+ // Example 1: Deployment
294
+ await runDevOpsAgent(
295
+ "Deploy version 2.5.0 to production with full validation and monitoring"
296
+ );
297
+
298
+ // Example 2: Incident Response
299
+ // await runDevOpsAgent(
300
+ // "API response time increased by 300% in last hour. Investigate, identify root cause, and fix"
301
+ // );
302
+
303
+ // Example 3: Security Audit
304
+ // await runDevOpsAgent(
305
+ // "Perform comprehensive security audit of the application and infrastructure"
306
+ // );
307
+
308
+ // Example 4: Performance Optimization
309
+ // await runDevOpsAgent(
310
+ // "Analyze application performance and implement optimizations for the checkout flow"
311
+ // );
312
+ } catch (error) {
313
+ console.error('Workflow failed:', error);
314
+ process.exit(1);
315
+ }
316
+ }
317
+
318
+ main();
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "claude-agent-sdk-examples",
3
+ "version": "1.0.0",
4
+ "description": "Claude Agent SDK usage examples",
5
+ "type": "module",
6
+ "scripts": {
7
+ "basic-query": "tsx templates/basic-query.ts",
8
+ "query-with-tools": "tsx templates/query-with-tools.ts",
9
+ "custom-mcp-server": "tsx templates/custom-mcp-server.ts",
10
+ "subagents": "tsx templates/subagents-orchestration.ts",
11
+ "sessions": "tsx templates/session-management.ts",
12
+ "permissions": "tsx templates/permission-control.ts",
13
+ "settings": "tsx templates/filesystem-settings.ts",
14
+ "errors": "tsx templates/error-handling.ts",
15
+ "workflow": "tsx templates/multi-agent-workflow.ts"
16
+ },
17
+ "dependencies": {
18
+ "@anthropic-ai/claude-agent-sdk": "^0.2.12",
19
+ "zod": "^3.24.0 || ^4.0.0",
20
+ "zod-to-json-schema": "^3.24.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^20.0.0",
24
+ "tsx": "^4.0.0",
25
+ "typescript": "^5.3.0"
26
+ },
27
+ "engines": {
28
+ "node": ">=18.0.0"
29
+ }
30
+ }
@@ -0,0 +1,211 @@
1
+ import { query } from "@anthropic-ai/claude-agent-sdk";
2
+
3
+ /**
4
+ * Permission Control Template
5
+ *
6
+ * Demonstrates:
7
+ * - Permission modes (default, acceptEdits, bypassPermissions)
8
+ * - Custom canUseTool callback
9
+ * - Safety controls for dangerous operations
10
+ * - Conditional tool approval
11
+ */
12
+
13
+ // Example 1: Accept Edits Mode (auto-approve file edits)
14
+ async function autoApproveEdits() {
15
+ const response = query({
16
+ prompt: "Refactor the user service to use async/await throughout",
17
+ options: {
18
+ model: "claude-sonnet-4-5",
19
+ workingDirectory: "/path/to/project",
20
+ permissionMode: "acceptEdits" // Auto-approve file edits
21
+ }
22
+ });
23
+
24
+ for await (const message of response) {
25
+ if (message.type === 'assistant') {
26
+ console.log(message.content);
27
+ }
28
+ }
29
+ }
30
+
31
+ // Example 2: Bypass Permissions (use with caution!)
32
+ async function bypassAllPermissions() {
33
+ const response = query({
34
+ prompt: "Run comprehensive test suite and fix all failures",
35
+ options: {
36
+ model: "claude-sonnet-4-5",
37
+ permissionMode: "bypassPermissions"
38
+ // āš ļø CAUTION: Skips ALL permission checks
39
+ // Use only in trusted, sandboxed environments
40
+ }
41
+ });
42
+
43
+ for await (const message of response) {
44
+ if (message.type === 'assistant') {
45
+ console.log(message.content);
46
+ }
47
+ }
48
+ }
49
+
50
+ // Example 3: Custom Permission Logic
51
+ async function customPermissions() {
52
+ const response = query({
53
+ prompt: "Deploy the application to production",
54
+ options: {
55
+ model: "claude-sonnet-4-5",
56
+ permissionMode: "default",
57
+ canUseTool: async (toolName, input) => {
58
+ // Allow read-only operations
59
+ if (['Read', 'Grep', 'Glob'].includes(toolName)) {
60
+ return { behavior: "allow" };
61
+ }
62
+
63
+ // Deny destructive bash commands
64
+ if (toolName === 'Bash') {
65
+ const dangerous = [
66
+ 'rm -rf',
67
+ 'dd if=',
68
+ 'mkfs',
69
+ '> /dev/',
70
+ 'shutdown',
71
+ 'reboot'
72
+ ];
73
+
74
+ if (dangerous.some(pattern => input.command.includes(pattern))) {
75
+ return {
76
+ behavior: "deny",
77
+ message: `Destructive command blocked: ${input.command}`
78
+ };
79
+ }
80
+ }
81
+
82
+ // Require confirmation for deployments
83
+ if (input.command?.includes('deploy') ||
84
+ input.command?.includes('kubectl apply') ||
85
+ input.command?.includes('terraform apply')) {
86
+ return {
87
+ behavior: "ask",
88
+ message: `Confirm deployment: ${input.command}?`
89
+ };
90
+ }
91
+
92
+ // Require confirmation for file writes to sensitive paths
93
+ if (toolName === 'Write' || toolName === 'Edit') {
94
+ const sensitivePaths = [
95
+ '/etc/',
96
+ '/root/',
97
+ '.env',
98
+ 'credentials',
99
+ 'secrets',
100
+ 'config/production'
101
+ ];
102
+
103
+ if (sensitivePaths.some(path => input.file_path?.includes(path))) {
104
+ return {
105
+ behavior: "ask",
106
+ message: `Modify sensitive file ${input.file_path}?`
107
+ };
108
+ }
109
+ }
110
+
111
+ // Allow by default
112
+ return { behavior: "allow" };
113
+ }
114
+ }
115
+ });
116
+
117
+ for await (const message of response) {
118
+ if (message.type === 'assistant') {
119
+ console.log(message.content);
120
+ }
121
+ }
122
+ }
123
+
124
+ // Example 4: Environment-Based Permissions
125
+ async function environmentBasedPermissions(environment: 'development' | 'staging' | 'production') {
126
+ const response = query({
127
+ prompt: "Deploy the latest changes",
128
+ options: {
129
+ model: "claude-sonnet-4-5",
130
+ permissionMode: "default",
131
+ canUseTool: async (toolName, input) => {
132
+ // Production requires approval for everything
133
+ if (environment === 'production') {
134
+ if (toolName === 'Bash' || toolName === 'Write' || toolName === 'Edit') {
135
+ return {
136
+ behavior: "ask",
137
+ message: `PRODUCTION: Approve ${toolName}?`
138
+ };
139
+ }
140
+ }
141
+
142
+ // Staging auto-approves edits
143
+ if (environment === 'staging') {
144
+ if (toolName === 'Write' || toolName === 'Edit') {
145
+ return { behavior: "allow" };
146
+ }
147
+ }
148
+
149
+ // Development bypasses most checks
150
+ if (environment === 'development') {
151
+ return { behavior: "allow" };
152
+ }
153
+
154
+ return { behavior: "allow" };
155
+ }
156
+ }
157
+ });
158
+
159
+ for await (const message of response) {
160
+ if (message.type === 'assistant') {
161
+ console.log(message.content);
162
+ }
163
+ }
164
+ }
165
+
166
+ // Example 5: Logging & Auditing
167
+ async function loggingPermissions() {
168
+ const toolLog: Array<{ tool: string; input: any; decision: string; timestamp: Date }> = [];
169
+
170
+ const response = query({
171
+ prompt: "Implement new feature X",
172
+ options: {
173
+ model: "claude-sonnet-4-5",
174
+ permissionMode: "default",
175
+ canUseTool: async (toolName, input) => {
176
+ // Log all tool usage
177
+ console.log(`[${new Date().toISOString()}] Tool requested: ${toolName}`);
178
+
179
+ const decision = { behavior: "allow" as const };
180
+
181
+ // Audit log
182
+ toolLog.push({
183
+ tool: toolName,
184
+ input,
185
+ decision: decision.behavior,
186
+ timestamp: new Date()
187
+ });
188
+
189
+ // Could also send to external logging service
190
+ // await logToDatabase(toolName, input, decision);
191
+
192
+ return decision;
193
+ }
194
+ }
195
+ });
196
+
197
+ for await (const message of response) {
198
+ if (message.type === 'assistant') {
199
+ console.log(message.content);
200
+ }
201
+ }
202
+
203
+ // Print audit log
204
+ console.log('\n\n=== Audit Log ===');
205
+ toolLog.forEach(entry => {
206
+ console.log(`${entry.timestamp.toISOString()} - ${entry.tool} - ${entry.decision}`);
207
+ });
208
+ }
209
+
210
+ // Run
211
+ customPermissions().catch(console.error);
@@ -0,0 +1,54 @@
1
+ import { query } from "@anthropic-ai/claude-agent-sdk";
2
+
3
+ /**
4
+ * Query with Tool Control Template
5
+ *
6
+ * Demonstrates:
7
+ * - Allowing/disallowing tools
8
+ * - System prompts
9
+ * - Tool execution monitoring
10
+ */
11
+
12
+ async function queryWithTools() {
13
+ const response = query({
14
+ prompt: "Review the authentication module for security issues and fix any vulnerabilities",
15
+ options: {
16
+ model: "claude-sonnet-4-5",
17
+ workingDirectory: "/path/to/project",
18
+ systemPrompt: `You are a security-focused code reviewer.
19
+
20
+ Analyze code for:
21
+ - SQL injection vulnerabilities
22
+ - XSS vulnerabilities
23
+ - Authentication bypass issues
24
+ - Insecure direct object references
25
+ - Security misconfiguration
26
+
27
+ Provide detailed recommendations and fix critical issues.`,
28
+
29
+ // Allow reading and modification, but not bash execution
30
+ allowedTools: ["Read", "Grep", "Glob", "Write", "Edit"],
31
+ disallowedTools: ["Bash"]
32
+ }
33
+ });
34
+
35
+ // Track tool usage
36
+ const toolsUsed = new Set<string>();
37
+
38
+ for await (const message of response) {
39
+ if (message.type === 'assistant') {
40
+ console.log('\nAssistant:', message.content);
41
+ } else if (message.type === 'tool_call') {
42
+ console.log(`\nšŸ”§ Executing: ${message.tool_name}`);
43
+ console.log(`Input:`, JSON.stringify(message.input, null, 2));
44
+ toolsUsed.add(message.tool_name);
45
+ } else if (message.type === 'tool_result') {
46
+ console.log(`āœ… ${message.tool_name} completed`);
47
+ }
48
+ }
49
+
50
+ console.log(`\n\nTools used: ${Array.from(toolsUsed).join(', ')}`);
51
+ }
52
+
53
+ // Run
54
+ queryWithTools().catch(console.error);