@kood/claude-code 0.1.2 → 0.1.3

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 (61) hide show
  1. package/dist/index.js +12 -3
  2. package/package.json +2 -2
  3. package/templates/hono/CLAUDE.md +20 -2
  4. package/templates/hono/docs/architecture/architecture.md +909 -0
  5. package/templates/hono/docs/deployment/cloudflare.md +537 -190
  6. package/templates/hono/docs/deployment/docker.md +517 -0
  7. package/templates/hono/docs/deployment/index.md +181 -213
  8. package/templates/hono/docs/deployment/railway.md +416 -0
  9. package/templates/hono/docs/deployment/vercel.md +572 -0
  10. package/templates/hono/docs/git/git.md +285 -0
  11. package/templates/hono/docs/library/ai-sdk/index.md +427 -0
  12. package/templates/hono/docs/library/ai-sdk/openrouter.md +479 -0
  13. package/templates/hono/docs/library/ai-sdk/providers.md +468 -0
  14. package/templates/hono/docs/library/ai-sdk/streaming.md +447 -0
  15. package/templates/hono/docs/library/ai-sdk/structured-output.md +493 -0
  16. package/templates/hono/docs/library/ai-sdk/tools.md +513 -0
  17. package/templates/hono/docs/library/hono/env-setup.md +458 -0
  18. package/templates/hono/docs/library/hono/index.md +1 -0
  19. package/templates/hono/docs/library/pino/index.md +437 -0
  20. package/templates/hono/docs/library/prisma/cloudflare-d1.md +503 -0
  21. package/templates/hono/docs/library/prisma/config.md +362 -0
  22. package/templates/hono/docs/library/prisma/index.md +86 -13
  23. package/templates/hono/docs/skills/gemini-review/SKILL.md +116 -116
  24. package/templates/hono/docs/skills/gemini-review/references/checklists.md +125 -125
  25. package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +191 -191
  26. package/templates/npx/CLAUDE.md +309 -0
  27. package/templates/npx/docs/git/git.md +307 -0
  28. package/templates/npx/docs/library/commander/index.md +164 -0
  29. package/templates/npx/docs/library/fs-extra/index.md +171 -0
  30. package/templates/npx/docs/library/prompts/index.md +253 -0
  31. package/templates/npx/docs/mcp/index.md +60 -0
  32. package/templates/npx/docs/skills/gemini-review/SKILL.md +220 -0
  33. package/templates/npx/docs/skills/gemini-review/references/checklists.md +134 -0
  34. package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +301 -0
  35. package/templates/tanstack-start/CLAUDE.md +43 -5
  36. package/templates/tanstack-start/docs/architecture/architecture.md +134 -4
  37. package/templates/tanstack-start/docs/deployment/cloudflare.md +234 -51
  38. package/templates/tanstack-start/docs/deployment/index.md +322 -32
  39. package/templates/tanstack-start/docs/deployment/nitro.md +201 -20
  40. package/templates/tanstack-start/docs/deployment/railway.md +305 -153
  41. package/templates/tanstack-start/docs/deployment/vercel.md +353 -78
  42. package/templates/tanstack-start/docs/git/{index.md → git.md} +81 -7
  43. package/templates/tanstack-start/docs/guides/best-practices.md +203 -1
  44. package/templates/tanstack-start/docs/guides/env-setup.md +450 -0
  45. package/templates/tanstack-start/docs/library/ai-sdk/hooks.md +472 -0
  46. package/templates/tanstack-start/docs/library/ai-sdk/index.md +264 -0
  47. package/templates/tanstack-start/docs/library/ai-sdk/openrouter.md +371 -0
  48. package/templates/tanstack-start/docs/library/ai-sdk/providers.md +403 -0
  49. package/templates/tanstack-start/docs/library/ai-sdk/streaming.md +320 -0
  50. package/templates/tanstack-start/docs/library/ai-sdk/structured-output.md +454 -0
  51. package/templates/tanstack-start/docs/library/ai-sdk/tools.md +473 -0
  52. package/templates/tanstack-start/docs/library/pino/index.md +320 -0
  53. package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +404 -0
  54. package/templates/tanstack-start/docs/library/prisma/config.md +377 -0
  55. package/templates/tanstack-start/docs/library/prisma/index.md +3 -1
  56. package/templates/tanstack-start/docs/library/prisma/schema.md +123 -25
  57. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +80 -2
  58. package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +116 -116
  59. package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +138 -144
  60. package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +186 -187
  61. package/templates/hono/docs/git/index.md +0 -180
@@ -0,0 +1,473 @@
1
+ # AI SDK - Tool Calling
2
+
3
+ > **상위 문서**: [AI SDK](./index.md)
4
+
5
+ ---
6
+
7
+ ## 개요
8
+
9
+ AI SDK의 도구(Tool)를 사용하면 AI 모델이 외부 함수를 호출할 수 있습니다. 날씨 조회, 데이터베이스 검색, API 호출 등 다양한 작업을 수행할 수 있습니다.
10
+
11
+ ---
12
+
13
+ ## 기본 도구 정의
14
+
15
+ ```typescript
16
+ import { generateText, tool } from 'ai'
17
+ import { openai } from '@ai-sdk/openai'
18
+ import { z } from 'zod'
19
+
20
+ const { text, toolCalls, toolResults } = await generateText({
21
+ model: openai('gpt-4o'),
22
+ prompt: 'What is the weather in Seoul?',
23
+ tools: {
24
+ getWeather: tool({
25
+ description: 'Get the weather for a location',
26
+ inputSchema: z.object({
27
+ location: z.string().describe('The city name'),
28
+ }),
29
+ execute: async ({ location }) => {
30
+ // 실제 날씨 API 호출
31
+ return {
32
+ location,
33
+ temperature: 22,
34
+ condition: 'Sunny',
35
+ }
36
+ },
37
+ }),
38
+ },
39
+ })
40
+ ```
41
+
42
+ ---
43
+
44
+ ## tool() 함수 구조
45
+
46
+ ```typescript
47
+ import { tool } from 'ai'
48
+ import { z } from 'zod'
49
+
50
+ const myTool = tool({
51
+ // 도구 설명 (모델이 언제 사용할지 결정하는데 사용)
52
+ description: 'Tool description for the AI model',
53
+
54
+ // 입력 스키마 (Zod로 정의)
55
+ inputSchema: z.object({
56
+ param1: z.string().describe('Parameter description'),
57
+ param2: z.number().optional(),
58
+ }),
59
+
60
+ // 실행 함수
61
+ execute: async (args, context) => {
62
+ // args: 스키마에 맞는 입력 값
63
+ // context: { toolCallId, messages } 등 컨텍스트 정보
64
+ return { result: 'success' }
65
+ },
66
+ })
67
+ ```
68
+
69
+ ---
70
+
71
+ ## 여러 도구 정의
72
+
73
+ ```typescript
74
+ import { generateText, tool } from 'ai'
75
+ import { openai } from '@ai-sdk/openai'
76
+ import { z } from 'zod'
77
+
78
+ const result = await generateText({
79
+ model: openai('gpt-4o'),
80
+ prompt: 'What is the weather in Seoul and what attractions should I visit?',
81
+ tools: {
82
+ getWeather: tool({
83
+ description: 'Get the weather for a location',
84
+ inputSchema: z.object({
85
+ location: z.string(),
86
+ }),
87
+ execute: async ({ location }) => ({
88
+ temperature: 22,
89
+ condition: 'Sunny',
90
+ }),
91
+ }),
92
+
93
+ getAttractions: tool({
94
+ description: 'Get tourist attractions for a city',
95
+ inputSchema: z.object({
96
+ city: z.string(),
97
+ }),
98
+ execute: async ({ city }) => ({
99
+ attractions: ['Gyeongbokgung Palace', 'N Seoul Tower', 'Bukchon Hanok Village'],
100
+ }),
101
+ }),
102
+ },
103
+ })
104
+
105
+ console.log(result.text)
106
+ console.log(result.toolResults)
107
+ ```
108
+
109
+ ---
110
+
111
+ ## 도구 호출 결과 접근
112
+
113
+ ```typescript
114
+ const result = await generateText({
115
+ model: openai('gpt-4o'),
116
+ prompt: 'Get the weather in Tokyo',
117
+ tools: { /* ... */ },
118
+ })
119
+
120
+ // 도구 호출 목록
121
+ for (const toolCall of result.toolCalls) {
122
+ console.log('Tool:', toolCall.toolName)
123
+ console.log('Input:', toolCall.input)
124
+ }
125
+
126
+ // 도구 실행 결과
127
+ for (const toolResult of result.toolResults) {
128
+ console.log('Tool:', toolResult.toolName)
129
+ console.log('Output:', toolResult.output)
130
+ }
131
+ ```
132
+
133
+ ---
134
+
135
+ ## 스트리밍에서 도구 사용
136
+
137
+ ```typescript
138
+ import { streamText, tool } from 'ai'
139
+ import { openai } from '@ai-sdk/openai'
140
+ import { z } from 'zod'
141
+
142
+ const result = streamText({
143
+ model: openai('gpt-4o'),
144
+ prompt: 'What is the weather?',
145
+ tools: {
146
+ getWeather: tool({
147
+ description: 'Get weather',
148
+ inputSchema: z.object({ location: z.string() }),
149
+ execute: async ({ location }) => ({ temp: 22 }),
150
+ }),
151
+ },
152
+ })
153
+
154
+ // fullStream으로 도구 이벤트 처리
155
+ for await (const event of result.fullStream) {
156
+ switch (event.type) {
157
+ case 'text-delta':
158
+ process.stdout.write(event.textDelta)
159
+ break
160
+ case 'tool-call':
161
+ console.log('Tool called:', event.toolName)
162
+ break
163
+ case 'tool-result':
164
+ console.log('Tool result:', event.output)
165
+ break
166
+ }
167
+ }
168
+ ```
169
+
170
+ ---
171
+
172
+ ## API Route에서 도구 사용
173
+
174
+ ```typescript
175
+ // app/api/chat/route.ts
176
+ import { streamText, tool, convertToModelMessages } from 'ai'
177
+ import { openai } from '@ai-sdk/openai'
178
+ import { z } from 'zod'
179
+
180
+ export async function POST(req: Request) {
181
+ const { messages } = await req.json()
182
+
183
+ const result = streamText({
184
+ model: openai('gpt-4o'),
185
+ messages: convertToModelMessages(messages),
186
+ tools: {
187
+ getWeather: tool({
188
+ description: 'Get weather for a location',
189
+ inputSchema: z.object({
190
+ location: z.string(),
191
+ }),
192
+ execute: async ({ location }) => {
193
+ // 날씨 API 호출
194
+ const weather = await fetchWeather(location)
195
+ return weather
196
+ },
197
+ }),
198
+ searchDatabase: tool({
199
+ description: 'Search the database',
200
+ inputSchema: z.object({
201
+ query: z.string(),
202
+ }),
203
+ execute: async ({ query }) => {
204
+ // 데이터베이스 검색
205
+ const results = await db.search(query)
206
+ return results
207
+ },
208
+ }),
209
+ },
210
+ })
211
+
212
+ return result.toUIMessageStreamResponse()
213
+ }
214
+ ```
215
+
216
+ ---
217
+
218
+ ## 도구 컨텍스트 접근
219
+
220
+ 도구 실행 시 추가 컨텍스트 정보에 접근할 수 있습니다:
221
+
222
+ ```typescript
223
+ const result = await generateText({
224
+ model: openai('gpt-4o'),
225
+ prompt: 'Hello',
226
+ tools: {
227
+ myTool: tool({
228
+ description: 'My tool',
229
+ inputSchema: z.object({ input: z.string() }),
230
+ execute: async (args, context) => {
231
+ // 도구 호출 ID
232
+ console.log('Tool call ID:', context.toolCallId)
233
+
234
+ // 전체 메시지 히스토리
235
+ console.log('Messages:', context.messages)
236
+
237
+ return { success: true }
238
+ },
239
+ }),
240
+ },
241
+ })
242
+ ```
243
+
244
+ ---
245
+
246
+ ## 다중 단계 실행
247
+
248
+ AI가 여러 도구를 순차적으로 호출하도록 허용:
249
+
250
+ ```typescript
251
+ import { generateText, stepCountIs } from 'ai'
252
+
253
+ const result = await generateText({
254
+ model: openai('gpt-4o'),
255
+ prompt: 'Plan a trip to Seoul',
256
+ tools: { /* ... */ },
257
+ stopWhen: stepCountIs(5), // 최대 5단계
258
+ })
259
+
260
+ // 각 단계 정보 접근
261
+ for (const step of result.steps) {
262
+ console.log('Step:', step.toolCalls)
263
+ }
264
+
265
+ // 모든 도구 호출 추출
266
+ const allToolCalls = result.steps.flatMap(step => step.toolCalls)
267
+ ```
268
+
269
+ ---
270
+
271
+ ## 도구 호출 복구
272
+
273
+ 잘못된 도구 호출을 자동으로 복구:
274
+
275
+ ```typescript
276
+ import { generateText, generateObject, NoSuchToolError, tool } from 'ai'
277
+ import { openai } from '@ai-sdk/openai'
278
+
279
+ const result = await generateText({
280
+ model: openai('gpt-4o'),
281
+ prompt: 'Get weather',
282
+ tools: { /* ... */ },
283
+
284
+ experimental_repairToolCall: async ({ toolCall, tools, inputSchema, error }) => {
285
+ // 존재하지 않는 도구면 복구 시도 안함
286
+ if (NoSuchToolError.isInstance(error)) {
287
+ return null
288
+ }
289
+
290
+ // 더 강력한 모델로 입력 재생성
291
+ const tool = tools[toolCall.toolName as keyof typeof tools]
292
+
293
+ const { object: repairedArgs } = await generateObject({
294
+ model: openai('gpt-4o'),
295
+ schema: tool.inputSchema,
296
+ prompt: [
297
+ `The tool "${toolCall.toolName}" was called with invalid inputs:`,
298
+ JSON.stringify(toolCall.input),
299
+ 'Please fix the inputs according to the schema.',
300
+ ].join('\n'),
301
+ })
302
+
303
+ return { ...toolCall, input: JSON.stringify(repairedArgs) }
304
+ },
305
+ })
306
+ ```
307
+
308
+ ---
309
+
310
+ ## 도구 상태 스트리밍
311
+
312
+ 도구 실행 중 상태를 UI로 전송:
313
+
314
+ ```typescript
315
+ import { streamText, tool, createUIMessageStream, createUIMessageStreamResponse } from 'ai'
316
+
317
+ export async function POST(req: Request) {
318
+ const { messages } = await req.json()
319
+
320
+ const stream = createUIMessageStream({
321
+ execute: ({ writer }) => {
322
+ const result = streamText({
323
+ model: openai('gpt-4o'),
324
+ messages,
325
+ tools: {
326
+ longRunningTask: tool({
327
+ description: 'A long running task',
328
+ inputSchema: z.object({ input: z.string() }),
329
+ execute: async (args, { toolCallId }) => {
330
+ // 진행 상태 전송
331
+ writer.write({
332
+ type: 'data-tool-status',
333
+ id: toolCallId,
334
+ data: { status: 'started' },
335
+ })
336
+
337
+ // 작업 수행...
338
+ await doSomething()
339
+
340
+ writer.write({
341
+ type: 'data-tool-status',
342
+ id: toolCallId,
343
+ data: { status: 'completed' },
344
+ })
345
+
346
+ return { result: 'done' }
347
+ },
348
+ }),
349
+ },
350
+ })
351
+
352
+ writer.merge(result.toUIMessageStream())
353
+ },
354
+ })
355
+
356
+ return createUIMessageStreamResponse({ stream })
357
+ }
358
+ ```
359
+
360
+ ---
361
+
362
+ ## 타입 안전한 도구
363
+
364
+ ```typescript
365
+ import { tool, TypedToolCall, TypedToolResult } from 'ai'
366
+ import { z } from 'zod'
367
+
368
+ const myToolSet = {
369
+ greet: tool({
370
+ description: 'Greet a user',
371
+ inputSchema: z.object({ name: z.string() }),
372
+ execute: async ({ name }) => `Hello, ${name}!`,
373
+ }),
374
+ calculate: tool({
375
+ description: 'Calculate',
376
+ inputSchema: z.object({
377
+ a: z.number(),
378
+ b: z.number(),
379
+ }),
380
+ execute: async ({ a, b }) => a + b,
381
+ }),
382
+ }
383
+
384
+ // 타입 추출
385
+ type MyToolCall = TypedToolCall<typeof myToolSet>
386
+ type MyToolResult = TypedToolResult<typeof myToolSet>
387
+
388
+ // 타입 안전한 함수
389
+ async function generate(prompt: string): Promise<{
390
+ text: string
391
+ toolCalls: MyToolCall[]
392
+ toolResults: MyToolResult[]
393
+ }> {
394
+ return generateText({
395
+ model: openai('gpt-4o'),
396
+ tools: myToolSet,
397
+ prompt,
398
+ })
399
+ }
400
+ ```
401
+
402
+ ---
403
+
404
+ ## 클라이언트에서 도구 결과 표시
405
+
406
+ ```tsx
407
+ 'use client'
408
+
409
+ import { useChat } from '@ai-sdk/react'
410
+
411
+ export default function Chat() {
412
+ const { messages } = useChat({ api: '/api/chat' })
413
+
414
+ return (
415
+ <div>
416
+ {messages.map((m) => (
417
+ <div key={m.id}>
418
+ {/* 텍스트 */}
419
+ {m.content && <p>{m.content}</p>}
420
+
421
+ {/* 도구 호출 */}
422
+ {m.toolInvocations?.map((tool, i) => (
423
+ <div key={i} className="tool-invocation">
424
+ <h4>Tool: {tool.toolName}</h4>
425
+ <pre>Args: {JSON.stringify(tool.args, null, 2)}</pre>
426
+
427
+ {tool.state === 'result' && (
428
+ <pre>Result: {JSON.stringify(tool.result, null, 2)}</pre>
429
+ )}
430
+
431
+ {tool.state === 'partial-call' && (
432
+ <span>Calling...</span>
433
+ )}
434
+ </div>
435
+ ))}
436
+ </div>
437
+ ))}
438
+ </div>
439
+ )
440
+ }
441
+ ```
442
+
443
+ ---
444
+
445
+ ## 도구 정의 팁
446
+
447
+ 1. **명확한 설명**: 모델이 언제 도구를 사용할지 이해하도록 상세히 작성
448
+ 2. **스키마 설명**: 각 파라미터에 `.describe()` 추가
449
+ 3. **에러 처리**: execute 함수에서 적절한 에러 처리
450
+ 4. **반환값**: 모델이 이해할 수 있는 구조화된 데이터 반환
451
+
452
+ ```typescript
453
+ const goodTool = tool({
454
+ description: `
455
+ Search for products in the database.
456
+ Use this when the user asks about available products,
457
+ product prices, or product availability.
458
+ `,
459
+ inputSchema: z.object({
460
+ query: z.string().describe('Search query for product name or category'),
461
+ maxResults: z.number().default(10).describe('Maximum number of results'),
462
+ category: z.string().optional().describe('Filter by category'),
463
+ }),
464
+ execute: async ({ query, maxResults, category }) => {
465
+ try {
466
+ const results = await db.products.search({ query, maxResults, category })
467
+ return { success: true, products: results }
468
+ } catch (error) {
469
+ return { success: false, error: 'Failed to search products' }
470
+ }
471
+ },
472
+ })
473
+ ```