@kood/claude-code 0.1.2 → 0.1.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 (63) hide show
  1. package/dist/index.js +129 -5
  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/commands/git.md +275 -0
  6. package/templates/hono/docs/deployment/cloudflare.md +527 -190
  7. package/templates/hono/docs/deployment/docker.md +514 -0
  8. package/templates/hono/docs/deployment/index.md +179 -214
  9. package/templates/hono/docs/deployment/railway.md +416 -0
  10. package/templates/hono/docs/deployment/vercel.md +567 -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 -3
  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/commands/git.md +275 -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/commands/git.md +275 -0
  38. package/templates/tanstack-start/docs/deployment/cloudflare.md +223 -50
  39. package/templates/tanstack-start/docs/deployment/index.md +320 -30
  40. package/templates/tanstack-start/docs/deployment/nitro.md +195 -14
  41. package/templates/tanstack-start/docs/deployment/railway.md +302 -150
  42. package/templates/tanstack-start/docs/deployment/vercel.md +345 -75
  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 -5
  56. package/templates/tanstack-start/docs/library/prisma/schema.md +123 -25
  57. package/templates/tanstack-start/docs/library/prisma/setup.md +0 -7
  58. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +80 -2
  59. package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +116 -116
  60. package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +138 -144
  61. package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +186 -187
  62. package/templates/hono/docs/git/index.md +0 -180
  63. package/templates/tanstack-start/docs/git/index.md +0 -203
@@ -0,0 +1,454 @@
1
+ # AI SDK - 구조화된 출력
2
+
3
+ > **상위 문서**: [AI SDK](./index.md)
4
+
5
+ ---
6
+
7
+ ## 개요
8
+
9
+ AI SDK의 `generateObject`와 `streamObject`를 사용하면 타입 안전한 구조화된 데이터를 생성할 수 있습니다. Zod 스키마를 사용하여 출력 형식을 정의합니다.
10
+
11
+ ---
12
+
13
+ ## generateObject
14
+
15
+ ### 기본 사용
16
+
17
+ ```typescript
18
+ import { generateObject } from 'ai'
19
+ import { openai } from '@ai-sdk/openai'
20
+ import { z } from 'zod'
21
+
22
+ const { object } = await generateObject({
23
+ model: openai('gpt-4o'),
24
+ schema: z.object({
25
+ name: z.string(),
26
+ age: z.number(),
27
+ email: z.string().email(),
28
+ }),
29
+ prompt: 'Generate a random user profile.',
30
+ })
31
+
32
+ console.log(object.name) // 타입 안전: string
33
+ console.log(object.age) // 타입 안전: number
34
+ ```
35
+
36
+ ### 복잡한 스키마
37
+
38
+ ```typescript
39
+ import { generateObject } from 'ai'
40
+ import { openai } from '@ai-sdk/openai'
41
+ import { z } from 'zod'
42
+
43
+ const recipeSchema = z.object({
44
+ name: z.string().describe('Recipe name'),
45
+ ingredients: z.array(
46
+ z.object({
47
+ name: z.string(),
48
+ amount: z.string(),
49
+ unit: z.string().optional(),
50
+ })
51
+ ),
52
+ steps: z.array(z.string()),
53
+ prepTime: z.number().describe('Preparation time in minutes'),
54
+ cookTime: z.number().describe('Cooking time in minutes'),
55
+ servings: z.number(),
56
+ difficulty: z.enum(['easy', 'medium', 'hard']),
57
+ })
58
+
59
+ const { object: recipe } = await generateObject({
60
+ model: openai('gpt-4o'),
61
+ schema: recipeSchema,
62
+ prompt: 'Generate a lasagna recipe.',
63
+ })
64
+
65
+ console.log(recipe.name)
66
+ console.log(recipe.ingredients)
67
+ console.log(recipe.steps)
68
+ ```
69
+
70
+ ---
71
+
72
+ ## 출력 모드
73
+
74
+ ### Object (기본)
75
+
76
+ ```typescript
77
+ const { object } = await generateObject({
78
+ model: openai('gpt-4o'),
79
+ schema: z.object({
80
+ name: z.string(),
81
+ age: z.number(),
82
+ }),
83
+ prompt: 'Generate a user.',
84
+ })
85
+ ```
86
+
87
+ ### Array
88
+
89
+ 배열 형태의 출력:
90
+
91
+ ```typescript
92
+ const { object } = await generateObject({
93
+ model: openai('gpt-4o'),
94
+ output: 'array',
95
+ schema: z.object({
96
+ name: z.string(),
97
+ class: z.string().describe('Character class'),
98
+ description: z.string(),
99
+ }),
100
+ prompt: 'Generate 3 RPG characters.',
101
+ })
102
+
103
+ // object는 배열
104
+ for (const character of object) {
105
+ console.log(character.name)
106
+ }
107
+ ```
108
+
109
+ ### Enum
110
+
111
+ 분류 작업에 유용:
112
+
113
+ ```typescript
114
+ const { object } = await generateObject({
115
+ model: openai('gpt-4o'),
116
+ output: 'enum',
117
+ enum: ['action', 'comedy', 'drama', 'horror', 'sci-fi'],
118
+ prompt: `
119
+ Classify this movie:
120
+ "A group of astronauts travel through a wormhole
121
+ in search of a new habitable planet."
122
+ `,
123
+ })
124
+
125
+ console.log(object) // 'sci-fi'
126
+ ```
127
+
128
+ ### No Schema
129
+
130
+ 스키마 없이 자유 형식 JSON 생성:
131
+
132
+ ```typescript
133
+ const { object } = await generateObject({
134
+ model: openai('gpt-4o'),
135
+ output: 'no-schema',
136
+ prompt: 'Generate a recipe for pasta.',
137
+ })
138
+
139
+ // object는 any 타입
140
+ console.log(object)
141
+ ```
142
+
143
+ ---
144
+
145
+ ## streamObject
146
+
147
+ 스트리밍으로 객체를 점진적으로 생성:
148
+
149
+ ```typescript
150
+ import { streamObject } from 'ai'
151
+ import { openai } from '@ai-sdk/openai'
152
+ import { z } from 'zod'
153
+
154
+ const schema = z.object({
155
+ name: z.string(),
156
+ bio: z.string(),
157
+ skills: z.array(z.string()),
158
+ })
159
+
160
+ const result = streamObject({
161
+ model: openai('gpt-4o'),
162
+ schema,
163
+ prompt: 'Generate a developer profile.',
164
+ })
165
+
166
+ // 부분 객체 스트리밍
167
+ for await (const partialObject of result.partialObjectStream) {
168
+ console.log(partialObject)
169
+ // { name: 'J' }
170
+ // { name: 'John' }
171
+ // { name: 'John', bio: 'A' }
172
+ // ...
173
+ }
174
+
175
+ // 최종 객체
176
+ const finalObject = await result.object
177
+ ```
178
+
179
+ ---
180
+
181
+ ## generateText에서 구조화된 출력
182
+
183
+ `generateText`에서도 구조화된 출력을 사용할 수 있습니다:
184
+
185
+ ```typescript
186
+ import { generateText, Output } from 'ai'
187
+ import { openai } from '@ai-sdk/openai'
188
+ import { z } from 'zod'
189
+
190
+ const { output } = await generateText({
191
+ model: openai('gpt-4o'),
192
+ prompt: 'Generate a random user.',
193
+ output: Output.object({
194
+ schema: z.object({
195
+ name: z.string(),
196
+ age: z.number(),
197
+ labels: z.array(z.string()),
198
+ }),
199
+ }),
200
+ })
201
+
202
+ console.log(output.name)
203
+ console.log(output.age)
204
+ ```
205
+
206
+ ---
207
+
208
+ ## 도구와 구조화된 출력 결합
209
+
210
+ ```typescript
211
+ import { generateText, tool, Output, stepCountIs } from 'ai'
212
+ import { openai } from '@ai-sdk/openai'
213
+ import { z } from 'zod'
214
+
215
+ const result = await generateText({
216
+ model: openai('gpt-4o'),
217
+ prompt: 'Analyze this data and provide a summary.',
218
+ output: Output.object({
219
+ schema: z.object({
220
+ summary: z.string(),
221
+ sentiment: z.enum(['positive', 'neutral', 'negative']),
222
+ }),
223
+ }),
224
+ tools: {
225
+ analyzeData: tool({
226
+ description: 'Analyze data',
227
+ inputSchema: z.object({ data: z.string() }),
228
+ execute: async ({ data }) => ({ result: 'analyzed' }),
229
+ }),
230
+ },
231
+ // 구조화된 출력을 위해 추가 단계 필요
232
+ stopWhen: stepCountIs(3),
233
+ })
234
+
235
+ console.log(result.output)
236
+ ```
237
+
238
+ ---
239
+
240
+ ## API Route에서 사용
241
+
242
+ ### generateObject
243
+
244
+ ```typescript
245
+ // app/api/generate-profile/route.ts
246
+ import { generateObject } from 'ai'
247
+ import { openai } from '@ai-sdk/openai'
248
+ import { z } from 'zod'
249
+
250
+ const profileSchema = z.object({
251
+ name: z.string(),
252
+ bio: z.string(),
253
+ skills: z.array(z.string()),
254
+ })
255
+
256
+ export async function POST(req: Request) {
257
+ const { prompt } = await req.json()
258
+
259
+ const { object } = await generateObject({
260
+ model: openai('gpt-4o'),
261
+ schema: profileSchema,
262
+ prompt,
263
+ })
264
+
265
+ return Response.json(object)
266
+ }
267
+ ```
268
+
269
+ ### streamObject
270
+
271
+ ```typescript
272
+ // app/api/stream-profile/route.ts
273
+ import { streamObject } from 'ai'
274
+ import { openai } from '@ai-sdk/openai'
275
+ import { z } from 'zod'
276
+
277
+ const profileSchema = z.object({
278
+ name: z.string(),
279
+ bio: z.string(),
280
+ skills: z.array(z.string()),
281
+ })
282
+
283
+ export async function POST(req: Request) {
284
+ const { prompt } = await req.json()
285
+
286
+ const result = streamObject({
287
+ model: openai('gpt-4o'),
288
+ schema: profileSchema,
289
+ prompt,
290
+ })
291
+
292
+ return result.toTextStreamResponse()
293
+ }
294
+ ```
295
+
296
+ ---
297
+
298
+ ## 클라이언트에서 사용 (useObject)
299
+
300
+ ```tsx
301
+ 'use client'
302
+
303
+ import { experimental_useObject as useObject } from '@ai-sdk/react'
304
+ import { z } from 'zod'
305
+
306
+ const profileSchema = z.object({
307
+ name: z.string(),
308
+ bio: z.string(),
309
+ skills: z.array(z.string()),
310
+ })
311
+
312
+ export default function ProfileGenerator() {
313
+ const { object, submit, isLoading, error } = useObject({
314
+ api: '/api/stream-profile',
315
+ schema: profileSchema,
316
+ })
317
+
318
+ return (
319
+ <div>
320
+ <button
321
+ onClick={() => submit('Generate a developer profile')}
322
+ disabled={isLoading}
323
+ >
324
+ {isLoading ? 'Generating...' : 'Generate Profile'}
325
+ </button>
326
+
327
+ {error && <p className="error">{error.message}</p>}
328
+
329
+ {object && (
330
+ <div className="profile">
331
+ <h2>{object.name}</h2>
332
+ <p>{object.bio}</p>
333
+ <ul>
334
+ {object.skills?.map((skill, i) => (
335
+ <li key={i}>{skill}</li>
336
+ ))}
337
+ </ul>
338
+ </div>
339
+ )}
340
+ </div>
341
+ )
342
+ }
343
+ ```
344
+
345
+ ---
346
+
347
+ ## 스키마 설계 팁
348
+
349
+ ### 필드 설명 추가
350
+
351
+ ```typescript
352
+ const schema = z.object({
353
+ title: z.string().describe('A catchy title for the article'),
354
+ summary: z.string().describe('A 2-3 sentence summary'),
355
+ tags: z.array(z.string()).describe('Relevant topic tags'),
356
+ })
357
+ ```
358
+
359
+ ### Optional 필드
360
+
361
+ ```typescript
362
+ const schema = z.object({
363
+ name: z.string(),
364
+ nickname: z.string().optional(),
365
+ age: z.number().nullable(),
366
+ })
367
+ ```
368
+
369
+ ### 기본값
370
+
371
+ ```typescript
372
+ const schema = z.object({
373
+ name: z.string(),
374
+ role: z.string().default('user'),
375
+ isActive: z.boolean().default(true),
376
+ })
377
+ ```
378
+
379
+ ### Enum 사용
380
+
381
+ ```typescript
382
+ const schema = z.object({
383
+ status: z.enum(['pending', 'approved', 'rejected']),
384
+ priority: z.enum(['low', 'medium', 'high', 'critical']),
385
+ })
386
+ ```
387
+
388
+ ### 중첩 객체
389
+
390
+ ```typescript
391
+ const schema = z.object({
392
+ user: z.object({
393
+ name: z.string(),
394
+ email: z.string().email(),
395
+ }),
396
+ address: z.object({
397
+ street: z.string(),
398
+ city: z.string(),
399
+ country: z.string(),
400
+ }),
401
+ })
402
+ ```
403
+
404
+ ---
405
+
406
+ ## 반환값
407
+
408
+ ### generateObject
409
+
410
+ ```typescript
411
+ const result = await generateObject({
412
+ model: openai('gpt-4o'),
413
+ schema,
414
+ prompt,
415
+ })
416
+
417
+ result.object // 생성된 객체 (타입 안전)
418
+ result.usage // 토큰 사용량
419
+ result.finishReason // 완료 이유
420
+ ```
421
+
422
+ ### streamObject
423
+
424
+ ```typescript
425
+ const result = streamObject({
426
+ model: openai('gpt-4o'),
427
+ schema,
428
+ prompt,
429
+ })
430
+
431
+ result.partialObjectStream // AsyncIterable<PartialObject>
432
+ result.object // Promise<FinalObject>
433
+ result.usage // Promise<Usage>
434
+ ```
435
+
436
+ ---
437
+
438
+ ## 에러 처리
439
+
440
+ ```typescript
441
+ try {
442
+ const { object } = await generateObject({
443
+ model: openai('gpt-4o'),
444
+ schema,
445
+ prompt,
446
+ })
447
+ } catch (error) {
448
+ if (error instanceof z.ZodError) {
449
+ console.error('Validation error:', error.errors)
450
+ } else {
451
+ console.error('Generation error:', error)
452
+ }
453
+ }
454
+ ```