ai-wingman 0.0.4 → 1.0.0

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 (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +232 -163
  3. package/dist/index.d.ts +117 -0
  4. package/dist/index.js +4052 -0
  5. package/dist/templates/README.md +8 -0
  6. package/dist/templates/agent-page.tsx +111 -0
  7. package/dist/templates/agent-route.ts +49 -0
  8. package/dist/templates/api-route-interrupt.ts +35 -0
  9. package/dist/templates/api-route-storage.ts +41 -0
  10. package/dist/templates/api-route.ts +24 -0
  11. package/dist/templates/audio-page-both.tsx +119 -0
  12. package/dist/templates/audio-page-speech-only.tsx +60 -0
  13. package/dist/templates/audio-page-transcribe-only.tsx +78 -0
  14. package/dist/templates/audio-speech-route.ts +32 -0
  15. package/dist/templates/audio-transcribe-route.ts +34 -0
  16. package/dist/templates/background-agent-enqueue-route.ts +28 -0
  17. package/dist/templates/background-agent-job-store.ts +55 -0
  18. package/dist/templates/background-agent-status-route.ts +24 -0
  19. package/dist/templates/background-agent-worker.ts +25 -0
  20. package/dist/templates/content-moderation-policy.ts +31 -0
  21. package/dist/templates/content-moderation-route.ts +44 -0
  22. package/dist/templates/conversation-by-id-route.ts +15 -0
  23. package/dist/templates/conversations-route.ts +16 -0
  24. package/dist/templates/document-processing-hook.ts +29 -0
  25. package/dist/templates/document-processing-route.ts +49 -0
  26. package/dist/templates/document-processing-schema.ts +17 -0
  27. package/dist/templates/eval-dataset-jsonl.ts +5 -0
  28. package/dist/templates/eval-dataset-runner.ts +99 -0
  29. package/dist/templates/eval-dataset-workflow.yml +30 -0
  30. package/dist/templates/eval-script.ts +112 -0
  31. package/dist/templates/generative-ui-page.tsx +98 -0
  32. package/dist/templates/generative-ui-route.ts +45 -0
  33. package/dist/templates/hybrid-search-bm25.ts +70 -0
  34. package/dist/templates/hybrid-search-reranker.ts +39 -0
  35. package/dist/templates/hybrid-search-route.ts +67 -0
  36. package/dist/templates/hybrid-search-store.ts +53 -0
  37. package/dist/templates/image-gen-page.tsx +82 -0
  38. package/dist/templates/image-gen-route.ts +25 -0
  39. package/dist/templates/interrupt-approval-widget.tsx +45 -0
  40. package/dist/templates/interrupt-page.tsx +73 -0
  41. package/dist/templates/interrupt-route.ts +32 -0
  42. package/dist/templates/interrupt-tools.ts +22 -0
  43. package/dist/templates/memory-inject.ts +35 -0
  44. package/dist/templates/memory-retrieve-route.ts +26 -0
  45. package/dist/templates/memory-save-route.ts +32 -0
  46. package/dist/templates/memory-store.ts +58 -0
  47. package/dist/templates/multi-agent-handoff-tools.ts +34 -0
  48. package/dist/templates/multi-agent-orchestrator-route.ts +35 -0
  49. package/dist/templates/multi-agent-specialists.ts +32 -0
  50. package/dist/templates/multi-agent-types.ts +11 -0
  51. package/dist/templates/multimodal-page.tsx +151 -0
  52. package/dist/templates/multimodal-route.ts +25 -0
  53. package/dist/templates/page-component-storage.tsx +356 -0
  54. package/dist/templates/page-component.tsx +273 -0
  55. package/dist/templates/rag-chunker.ts +64 -0
  56. package/dist/templates/rag-embed-route-chunked.ts +30 -0
  57. package/dist/templates/rag-embed-route.ts +27 -0
  58. package/dist/templates/rag-hook-streaming.ts +48 -0
  59. package/dist/templates/rag-hook.ts +31 -0
  60. package/dist/templates/rag-memory-store.ts +25 -0
  61. package/dist/templates/rag-pgvector-store.ts +30 -0
  62. package/dist/templates/rag-query-route-streaming.ts +34 -0
  63. package/dist/templates/rag-query-route.ts +34 -0
  64. package/dist/templates/rag-schema-sql.sql +14 -0
  65. package/dist/templates/rag-sqlite-store.ts +61 -0
  66. package/dist/templates/rag-store-pgvector.ts +28 -0
  67. package/dist/templates/rag-store-sqlite.ts +28 -0
  68. package/dist/templates/rag-store.ts +22 -0
  69. package/dist/templates/storage.ts +30 -0
  70. package/dist/templates/stream-object-hook.ts +24 -0
  71. package/dist/templates/stream-object-route.ts +20 -0
  72. package/dist/templates/structured-output-hook.ts +30 -0
  73. package/dist/templates/structured-output-route.ts +20 -0
  74. package/dist/templates/structured-output-schema.ts +12 -0
  75. package/dist/templates/tools-route.ts +30 -0
  76. package/dist/templates/tools-stub.ts +18 -0
  77. package/dist/wingman.js +2684 -5516
  78. package/package.json +12 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yonatan Katz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,228 +1,297 @@
1
- # ai-wingman
1
+ <p align="center">
2
+ <img src=".github/logo.svg" alt="ai-wingman logo" width="128" />
3
+ </p>
2
4
 
3
- Scaffold production-ready AI patterns into your existing Next.js app — one command per pattern.
5
+ <h1 align="center">ai-wingman</h1>
4
6
 
5
- ```bash
6
- npx ai-wingman add chat
7
- ```
7
+ <p align="center">
8
+ <strong>The right way to wire AI into your Next.js app.</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/ai-wingman"><img src="https://img.shields.io/npm/v/ai-wingman.svg" alt="npm version" /></a>
13
+ <a href="https://www.npmjs.com/package/ai-wingman"><img src="https://img.shields.io/npm/dm/ai-wingman.svg" alt="npm downloads" /></a>
14
+ <a href="https://github.com/yontn-oss/ai-wingman/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/ai-wingman.svg" alt="license" /></a>
15
+ <a href="https://github.com/yontn-oss/ai-wingman/blob/main/CONTRIBUTING.md"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs welcome" /></a>
16
+ </p>
17
+
18
+ <p align="center">
19
+ <a href="https://ai-wingman-psi.vercel.app/">Website</a>
20
+ </p>
8
21
 
9
- ai-wingman wires together the right SDK primitives, generates plain TypeScript files you own, and exits. There is no runtime dependency on ai-wingman after scaffolding.
22
+ <p align="center">
23
+ <code>npx ai-wingman add chat</code>
24
+ </p>
25
+
26
+ <p align="center">
27
+ ai-wingman writes the API route, UI component, and all the wiring into your existing project — then exits.<br />
28
+ No runtime dependency. No lock-in. Just clean, typed TypeScript you own.
29
+ </p>
10
30
 
11
31
  ---
12
32
 
13
- ## Patterns
14
-
15
- | Command | Core primitive | What you get |
16
- |---------|---------------|-------------|
17
- | `wingman add chat` | `streamText` | Streaming chat route, conversation storage, multi-turn page |
18
- | `wingman add structured-output` | `generateText + Output.object` | Typed JSON route, Zod schema, React hook |
19
- | `wingman add tools` | `streamText + tools` | Tool-calling route, typed tool stubs |
20
- | `wingman add stream-object` | `streamObject + useObject` | Streaming structured JSON route and hook |
21
- | `wingman add rag` | `embed + cosineSimilarity` | Embed route, query route, vector store, client hook |
22
- | `wingman add interrupt` | `tool({ needsApproval: true }) + addToolApprovalResponse` | Human-in-the-loop approval route, widget, page |
23
- | `wingman add agent` | `streamText + stopWhen: stepCountIs(N)` | Autonomous agent route, tool stubs, storage, page |
24
- | `wingman add multimodal` | `convertToModelMessages` | Vision-aware chat route and page with image upload |
25
- | `wingman add audio` | `experimental_transcribe` / `experimental_generateSpeech` | Transcription route, TTS route, recording page |
26
- | `wingman add eval` | `generateText` (LLM judge) | Runnable eval script with string-match and judge scoring |
27
- | `wingman add image-gen` | `generateImage` | Prompt-to-image route (DALL·E), display page with download |
28
- | `wingman add generative-ui` | `streamUI` (ai/rsc) | Server action that streams React component trees to the client |
29
- | `wingman add document-processing` | `generateText + Output.object` | File upload route, schema, and hook for PDF / document extraction |
33
+ ## Table of contents
34
+
35
+ - [The problem it solves](#the-problem-it-solves)
36
+ - [How it works](#how-it-works)
37
+ - [18 patterns across 4 categories](#18-patterns-across-4-categories)
38
+ - [New to AI development?](#new-to-ai-development)
39
+ - [Quick start](#quick-start)
40
+ - [Prerequisites](#prerequisites)
41
+ - [Under the hood](#under-the-hood)
42
+ - [Contributing](#contributing)
43
+ - [License](#license)
30
44
 
31
45
  ---
32
46
 
33
- ## Quick start
47
+ ## The problem it solves
34
48
 
35
- Run inside an existing Next.js + TypeScript project:
49
+ Calling an AI API is three lines of code. Shipping a production AI feature is not.
36
50
 
37
- ```bash
38
- npx ai-wingman add chat
51
+ You need to handle streaming tokens to the UI, structure outputs as typed JSON, store conversation history, let the model call your own functions, guard against bad content, measure quality over time, and do it all without turning your codebase into a mess of `fetch` calls and `any` types.
52
+
53
+ Every team figures this out from scratch. ai-wingman packages 18 of those patterns — each one the right way to wire that use-case — and scaffolds them with a single command.
54
+
55
+ ---
56
+
57
+ ## How it works
58
+
59
+ ```
60
+ $ npx ai-wingman add rag
39
61
  ```
40
62
 
41
- The CLI will:
63
+ ```
64
+ ┌ ai-wingman
65
+
66
+ ◆ Next.js 16.2.1 found
67
+
68
+ ◇ AI provider?
69
+ │ Anthropic
70
+
71
+ ◇ RAG storage backend?
72
+ │ SQLite + sqlite-vec
73
+
74
+ ◇ Embedding model ID?
75
+ │ voyage-3
76
+
77
+ ◇ Stream the query response?
78
+ │ Yes
79
+
80
+ ◇ Plan ─────────────────────────╮
81
+ │ │
82
+ │ Install packages: │
83
+ │ @ai-sdk/anthropic │
84
+ │ ai │
85
+ │ better-sqlite3 │
86
+ │ sqlite-vec │
87
+ │ │
88
+ │ Create files: │
89
+ │ app/api/rag/embed/route.ts │
90
+ │ app/api/rag/query/route.ts │
91
+ │ lib/rag/store.ts │
92
+ │ lib/rag/sqlite-store.ts │
93
+ │ lib/rag/chunker.ts │
94
+ │ hooks/use-rag-query.ts │
95
+ │ │
96
+ ├────────────────────────────────╯
97
+
98
+ ◇ Proceed?
99
+ │ Yes
100
+
101
+ ◆ Installed @ai-sdk/anthropic, ai, better-sqlite3, sqlite-vec
102
+
103
+ ◆ Created app/api/rag/embed/route.ts
104
+ ◆ Created app/api/rag/query/route.ts
105
+ ◆ Created lib/rag/store.ts
106
+ ◆ Created lib/rag/sqlite-store.ts
107
+ ◆ Created lib/rag/chunker.ts
108
+ ◆ Created hooks/use-rag-query.ts
109
+
110
+ ◇ Add to .env.local ───────────╮
111
+ │ │
112
+ │ ANTHROPIC_API_KEY= │
113
+ │ SQLITE_RAG_PATH= │
114
+ │ │
115
+ ├───────────────────────────────╯
116
+
117
+ └ Done! Start your dev server: npm run dev
118
+ ```
42
119
 
43
- 1. Detect Next.js, TypeScript, and shadcn/ui prerequisites
44
- 2. Ask which provider (Anthropic / OpenAI / Google)
45
- 3. Ask pattern-specific questions (storage, auth, output paths)
46
- 4. Show the full plan and ask for confirmation
47
- 5. Install packages, run `npx ai-elements@latest` and `npx shadcn@latest add`
48
- 6. Write your files
49
- 7. Print the env vars you need to set
120
+ The CLI detects your project, asks targeted questions, shows the full plan before touching anything, installs packages, writes files, and exits. No runtime dependency on ai-wingman after that point.
121
+
122
+ ```
123
+ your project
124
+
125
+
126
+ detect ──── Next.js · TypeScript · shadcn/ui
127
+
128
+
129
+ ◇ prompt ──── provider · storage · model · options
130
+
131
+
132
+ ◇ plan ──── packages to install · files to create
133
+
134
+
135
+ ◇ confirm ──── review before anything is written
136
+
137
+
138
+ ◆ execute ──── install · write · done
139
+
140
+
141
+ your project + production-ready AI feature
142
+ ```
50
143
 
51
144
  ---
52
145
 
53
- ## CLI commands
146
+ ## 18 patterns across 4 categories
54
147
 
55
- ```bash
56
- wingman add <pattern> # scaffold a pattern interactively
57
- wingman list # list all available patterns
58
- wingman add <pattern> --overwrite # re-scaffold, overwriting existing files
59
- ```
148
+ ### Generate
60
149
 
61
- Pass flags to skip prompts. `-y` / `--yes` accepts all defaults.
150
+ Text, images, audio, structured data, and UI anything the model produces directly.
62
151
 
63
- ```bash
64
- # Fully non-interactive
65
- npx ai-wingman add chat --provider anthropic --storage memory --yes
152
+ | Command | What it builds | What that means |
153
+ |---------|---------------|-----------------|
154
+ | `ai-wingman add chat` | Streaming chat with conversation history | A ChatGPT-style interface backed by your own API route. Responses appear word-by-word instead of all at once. |
155
+ | `ai-wingman add structured-output` | AI that returns typed JSON, not prose | Ask the model a question; get back a strongly-typed object with named fields. Ready to store, display, or pass to the next function. |
156
+ | `ai-wingman add tools` | AI route that can call your functions | You expose functions like `searchDatabase()` or `sendEmail()`. The model decides when to call them and with what arguments. Your code executes them. |
157
+ | `ai-wingman add stream-object` | Progressively streamed typed JSON | The same typed object, but fields fill in one by one as the model generates them — good for long extractions where you want the UI to feel alive. |
158
+ | `ai-wingman add multimodal` | Vision-aware chat with image upload | The same chat interface, but users can attach images. The model can see, describe, and reason about them. |
159
+ | `ai-wingman add audio` | Speech-to-text input + text-to-speech replies | Users speak; the model transcribes, responds, and reads the answer back aloud. |
160
+ | `ai-wingman add image-gen` | Prompt-to-image route with display page | Generate images from a text prompt (DALL·E 3 by default). Includes a download button and swappable model flag. |
161
+ | `ai-wingman add generative-ui` | AI that streams back live React components | Instead of returning text, the model returns actual UI — charts, cards, forms — rendered in real time as they arrive. |
162
+ | `ai-wingman add document-processing` | Upload a file, extract structured data | Drop in a PDF; get back a typed object. Useful for invoice parsing, resume extraction, contract review. |
66
163
 
67
- # Custom output paths
68
- npx ai-wingman add chat --provider anthropic --api-route app/api/assistant/route.ts --yes
164
+ ### Retrieval
69
165
 
70
- # Different storage backend
71
- npx ai-wingman add rag --provider openai --storage pgvector --yes
166
+ Patterns for grounding the model in your own data.
72
167
 
73
- # Re-scaffold after an update
74
- npx ai-wingman add chat --provider anthropic --overwrite --yes
75
- ```
168
+ | Command | What it builds | What that means |
169
+ |---------|---------------|-----------------|
170
+ | `ai-wingman add rag` | Embed → store → retrieve → answer pipeline | Let the AI answer questions about *your* documents. It converts text to vectors, finds the most relevant chunks at query time, and uses them as context. This is how "chat with your PDF" products work. |
171
+ | `ai-wingman add hybrid-search` | Keyword + semantic search, merged | Runs a BM25 keyword search and a vector similarity search in parallel, then blends the rankings. More accurate than either approach alone — a drop-in upgrade to `rag`. |
172
+ | `ai-wingman add memory` | Per-user long-term memory across sessions | Saves facts about each user as embeddings, retrieves the most relevant ones at the start of each conversation, and injects them into the system prompt automatically. |
76
173
 
77
- ---
174
+ ### Agents
78
175
 
79
- ## Providers
176
+ Patterns where the model takes multiple steps or hands off to humans or other models.
80
177
 
81
- | Flag | Package installed | Env var |
82
- |------|------------------|---------|
83
- | `anthropic` | `@ai-sdk/anthropic` | `ANTHROPIC_API_KEY` |
84
- | `openai` | `@ai-sdk/openai` | `OPENAI_API_KEY` |
85
- | `google` | `@ai-sdk/google` | `GOOGLE_GENERATIVE_AI_API_KEY` |
178
+ | Command | What it builds | What that means |
179
+ |---------|---------------|-----------------|
180
+ | `ai-wingman add agent` | Autonomous multi-step agent loop | The model thinks, calls a tool, sees the result, thinks again — repeating until the task is done. You set the step limit and define the tools. |
181
+ | `ai-wingman add interrupt` | Agent with human-in-the-loop approval gates | Like the agent pattern, but the model pauses and asks a human to confirm before taking any action that can't be undone. |
182
+ | `ai-wingman add multi-agent` | Orchestrator that delegates to specialist sub-agents | A coordinator model breaks work into sub-tasks and hands each off to a focused specialist. Results are synthesized into a single response. |
183
+ | `ai-wingman add background-agent` | Agent that runs outside the HTTP request cycle | Enqueue a task, get a job ID back immediately, then poll for status and result. For work that takes too long to complete in a single HTTP request. |
86
184
 
87
- ---
185
+ ### Quality & Safety
88
186
 
89
- ## Common flags
187
+ Patterns that judge, classify, or score AI inputs and outputs.
90
188
 
91
- | Flag | Applies to | Description |
92
- |------|-----------|-------------|
93
- | `--provider <id>` | all | `anthropic` / `openai` / `google` |
94
- | `--auth` | all | Include NextAuth v5 session check (default: off) |
95
- | `--no-page` | patterns with pages | Omit the generated page component |
96
- | `--storage <id>` | `rag` | `memory` / `sqlite` / `pgvector` |
97
- | `--storage memory` | `chat` | Include conversation storage (default: off) |
98
- | `--interrupt` | `chat` | Embed a human-in-the-loop approval gate in the chat route |
99
- | `--stream` | `rag` | Use `streamText` instead of `generateText` in query route |
100
- | `--schema-name <name>` | `structured-output`, `stream-object` | Name for the schema, hook, and type |
101
- | `--no-hook` | `structured-output`, `stream-object` | Omit the generated client hook |
102
- | `--tool-name <name>` | `tools` | Name for the generated tool stub file |
103
- | `--image-model <model>` | `image-gen` | `dall-e-3` (default) or `dall-e-2` |
104
- | `--overwrite` | all | Overwrite existing files without prompting |
105
- | `-y, --yes` | all | Accept all defaults |
189
+ | Command | What it builds | What that means |
190
+ |---------|---------------|-----------------|
191
+ | `ai-wingman add eval` | LLM-as-judge evaluation harness | A test suite for AI outputs. You write test cases; a judge model scores each answer. Catch regressions when you change prompts or swap models — the same way unit tests catch bugs in regular code. |
192
+ | `ai-wingman add content-moderation` | LLM-based content classifier | Classifies any input or output against a policy you define. Returns `{ allowed, category, reason }` — drop it in front of any route. |
106
193
 
107
194
  ---
108
195
 
109
- ## File conflict handling
196
+ ## New to AI development?
110
197
 
111
- Before writing each file, the CLI checks if it already exists:
198
+ These terms come up constantly. Here's what they actually mean:
112
199
 
113
- - If taken, a warning appears inline
114
- - You can overwrite, enter a different path, or skip the component
115
- - `--overwrite` bypasses this prompt silently
116
- - The CLI never silently overwrites without permission
200
+ **Streaming** the model generates one token (roughly one word) at a time. Streaming means sending each token to the browser as it arrives, so the UI updates live. Without streaming, you wait for the full response before showing anything.
117
201
 
118
- ---
202
+ **Structured output** — by default, models return plain text. Structured output forces the model to return a JSON object that matches a schema you define — so you get typed fields instead of a paragraph you'd have to parse.
119
203
 
120
- ## Prerequisites
204
+ **Tool calling** — you define functions in your code and tell the model they exist. The model decides when to call them and what arguments to pass. Your code runs the function and returns the result. The model incorporates that result and keeps going. This is the foundation of all agent behavior.
121
205
 
122
- | Requirement | Check | Auto-install |
123
- |-------------|-------|-------------|
124
- | React in `package.json` | Required — exits if missing | No |
125
- | `tsconfig.json` | Required — exits if missing | No |
126
- | shadcn/ui (`components.json`) | Required for page components | Prompted |
206
+ **RAG** Retrieval-Augmented Generation. Your documents are converted to vectors (lists of numbers that capture meaning), stored in a vector database, and searched at query time. The most relevant chunks are included in the prompt alongside the user's question. The model answers using your data, not just what it learned during training.
127
207
 
128
- ---
208
+ **Eval** — AI outputs are non-deterministic. An eval harness measures quality by running your prompts against test cases and scoring the outputs — usually with a second model acting as a judge. It's how you tell whether a prompt change made things better or worse.
129
209
 
130
- ## Development
210
+ ---
131
211
 
132
- ### Local dev loop
212
+ ## Quick start
133
213
 
134
214
  ```bash
135
- # 1. Build and link the CLI globally (run once)
136
- bash scripts/dev-link.sh
215
+ npx ai-wingman add chat
216
+ ```
137
217
 
138
- # 2. Start watch mode
139
- pnpm --filter ai-wingman watch
218
+ Add `--yes` to accept all defaults non-interactively:
140
219
 
141
- # 3. Create a fresh test project
142
- bash scripts/new-fixture.sh
143
- cd /tmp/wingman-fixture
220
+ ### AI coding assistant integration
144
221
 
145
- # 4. Run against it
146
- ai-wingman add chat --provider anthropic --storage memory --yes
222
+ If you use Claude Code, Cursor, or another AI coding assistant, run:
223
+
224
+ ```bash
225
+ npx ai-wingman skill
147
226
  ```
148
227
 
149
- Or point directly at the built binary from any project:
228
+ This downloads a `SKILL.md` into your project that tells your assistant about ai-wingman — what patterns are available, when to use them, and how to invoke them. Once it's there, your assistant will automatically reach for `ai-wingman add` instead of writing AI boilerplate by hand.
150
229
 
151
230
  ```bash
152
- node /path/to/wingman/packages/ai-wingman/dist/wingman.js add chat --yes
231
+ npx ai-wingman skill # saves to ./SKILL.md (default)
232
+ npx ai-wingman skill --output .cursorrules # custom output path
153
233
  ```
154
234
 
155
- ### Tests
156
-
157
235
  ```bash
158
- pnpm --filter ai-wingman test
236
+ npx ai-wingman add chat --provider anthropic --yes
237
+ npx ai-wingman add rag --provider openai --storage pgvector --yes
238
+ npx ai-wingman add chat --provider anthropic --overwrite --yes # re-scaffold
159
239
  ```
160
240
 
161
- 330 tests across all 13 generators. Generators are pure `(config) => string` functions — fast, deterministic, snapshot-tested.
241
+ ### Providers
162
242
 
163
- ### Project structure
243
+ | Value | Package installed | Env var required |
244
+ |-------|------------------|-----------------|
245
+ | `anthropic` | `@ai-sdk/anthropic` | `ANTHROPIC_API_KEY` |
246
+ | `openai` | `@ai-sdk/openai` | `OPENAI_API_KEY` |
247
+ | `google` | `@ai-sdk/google` | `GOOGLE_GENERATIVE_AI_API_KEY` |
164
248
 
165
- ```
166
- packages/ai-wingman/
167
- ├── bin/
168
- │ └── wingman.ts # CLI entry point (commander)
169
- ├── src/
170
- │ ├── types.ts # Config types for all patterns
171
- │ ├── registry/
172
- │ │ ├── providers.ts # Anthropic, OpenAI, Google
173
- │ │ ├── storage-adapters.ts
174
- │ │ ├── patterns.ts # Pattern registry + resolvers
175
- │ │ └── index.ts
176
- │ ├── generators/ # Pure (config) => string functions
177
- │ ├── patterns/ # One dir per pattern
178
- │ │ ├── chat/
179
- │ │ ├── structured-output/
180
- │ │ ├── tools/
181
- │ │ ├── stream-object/
182
- │ │ ├── rag/
183
- │ │ ├── interrupt/
184
- │ │ ├── agent/
185
- │ │ ├── multimodal/
186
- │ │ ├── audio/
187
- │ │ ├── eval/
188
- │ │ ├── image-gen/
189
- │ │ ├── generative-ui/
190
- │ │ └── document-processing/
191
- │ ├── commands/
192
- │ │ ├── add/ # Main orchestrator
193
- │ │ └── list/
194
- │ ├── planner/ # Builds ExecutionPlan before writing
195
- │ ├── steps/ # Shared interactive steps
196
- │ └── utils/
197
- └── tests/
198
- └── unit/generators/ # Snapshot tests per generator
199
- ```
249
+ ### All flags
200
250
 
201
- ### Adding a provider
251
+ | Flag | Applies to | What it does |
252
+ |------|-----------|-------------|
253
+ | `--provider <id>` | all | `anthropic` / `openai` / `google` |
254
+ | `--auth` | all | Add a NextAuth v5 session check to the route |
255
+ | `--no-page` | patterns with pages | Skip generating the page component |
256
+ | `--storage <id>` | `rag` | `memory` / `sqlite` / `pgvector` |
257
+ | `--storage memory` | `chat` | Add in-memory conversation storage |
258
+ | `--interrupt` | `chat` | Add a human approval gate to the chat route |
259
+ | `--stream` | `rag` | Stream the answer instead of waiting for the full response |
260
+ | `--schema-name <name>` | `structured-output`, `stream-object` | Name for the generated schema, type, and hook |
261
+ | `--no-hook` | `structured-output`, `stream-object` | Skip the generated React hook |
262
+ | `--tool-name <name>` | `tools` | Name for the generated tool stub |
263
+ | `--image-model <model>` | `image-gen` | `dall-e-3` (default) or `dall-e-2` |
264
+ | `--api-route <path>` | all | Custom output path for the API route |
265
+ | `--overwrite` | all | Overwrite existing files without prompting |
266
+ | `-y, --yes` | all | Accept all defaults |
202
267
 
203
- Add an entry to `src/registry/providers.ts`:
268
+ The CLI never silently overwrites a file — it prompts for each conflict unless `--overwrite` is set.
204
269
 
205
- ```ts
206
- {
207
- id: 'mistral',
208
- label: 'Mistral',
209
- package: '@ai-sdk/mistral',
210
- importName: 'mistral',
211
- envVar: 'MISTRAL_API_KEY',
212
- defaultModel: 'mistral-large-latest',
213
- modelFactory: 'mistral("mistral-large-latest")',
214
- }
215
- ```
270
+ ---
216
271
 
217
- No other changes needed — the prompt and all generators pick it up automatically.
272
+ ## Prerequisites
273
+
274
+ | Requirement | Notes |
275
+ |-------------|-------|
276
+ | Next.js + TypeScript | Required. The CLI exits if either is missing. |
277
+ | shadcn/ui | Required for page components. The CLI offers to set it up if it's not found. |
278
+
279
+ ---
280
+
281
+ ## Under the hood
282
+
283
+ - **Generators are pure functions** — `(config) => string`. No side effects, no network calls, no filesystem reads. Fast to test, easy to snapshot.
284
+ - **The planner runs before any files are written** — every `ai-wingman add` builds a complete `ExecutionPlan` first, shows it to you for confirmation, then executes. Nothing is written speculatively.
285
+ - **525 snapshot tests** across all 18 generators. Changing a generator output requires updating the snapshot deliberately — not by accident.
286
+ - **Providers and patterns are registry entries** — adding a new provider is one object in `providers.ts`. All generators pick it up automatically.
287
+
288
+ For project structure, local dev setup, and contribution guidelines see [CONTRIBUTING.md](./CONTRIBUTING.md).
289
+
290
+ ---
218
291
 
219
- ### Adding a pattern
292
+ ## Contributing
220
293
 
221
- 1. Create `src/patterns/<name>/index.ts` implementing the `Pattern` interface
222
- 2. Add `prompt-config.ts` and `execute.ts` alongside it
223
- 3. Add generators to `src/generators/` as needed
224
- 4. Register the pattern in `src/registry/patterns.ts`
225
- 5. Add snapshot tests in `tests/unit/generators/<name>.test.ts`
294
+ Contributions are welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get started.
226
295
 
227
296
  ---
228
297
 
@@ -0,0 +1,117 @@
1
+ type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
2
+
3
+ /** Config collected once before any pattern-specific prompts. */
4
+ interface SharedConfig {
5
+ provider: ProviderEntry;
6
+ pathAlias: string;
7
+ hasSrcDir: boolean;
8
+ packageManager: PackageManager;
9
+ targetDir: string;
10
+ prereqs: {
11
+ hasShadcn: boolean;
12
+ hasNext: boolean;
13
+ };
14
+ }
15
+ /** A single entry in the execution plan (display + execution metadata). */
16
+ type PlanEntry = {
17
+ kind: 'run';
18
+ command: string;
19
+ args: string[];
20
+ } | {
21
+ kind: 'create';
22
+ path: string;
23
+ overwrite?: boolean;
24
+ };
25
+ /** Unified plan produced by the planner across all requested patterns. */
26
+ interface ExecutionPlan {
27
+ /** Deduplicated package names to install before execution. */
28
+ packages: string[];
29
+ /** Ordered entries: CLI runs first, then file creates. */
30
+ entries: PlanEntry[];
31
+ /** Per-pattern groups used for display — same entries as above, grouped by pattern id. */
32
+ groups: Array<{
33
+ patternId: string;
34
+ entries: PlanEntry[];
35
+ }>;
36
+ }
37
+ /** Every pattern implements this interface. */
38
+ interface Pattern {
39
+ id: string;
40
+ description: string;
41
+ /** Non-universal CLI flags this pattern accepts (beyond provider, auth, overwrite, yes). */
42
+ cliFlags: (keyof AddChatOptions)[];
43
+ promptConfig(shared: SharedConfig, opts: unknown): Promise<unknown>;
44
+ getPackages(config: unknown): string[];
45
+ getPlanEntries(config: unknown): PlanEntry[];
46
+ getEnvVars(config: unknown): string[];
47
+ execute(config: unknown, shared: SharedConfig): Promise<void>;
48
+ }
49
+ interface ProviderEntry {
50
+ id: 'anthropic' | 'openai' | 'google';
51
+ label: string;
52
+ package: string;
53
+ importName: string;
54
+ envVar: string;
55
+ defaultModel: string;
56
+ modelFactory: string;
57
+ /** Method name on the provider for embedding models (e.g. 'embedding' for openai, 'textEmbeddingModel' for google). Absent if the provider has no native embedding support. */
58
+ embeddingMethod?: string;
59
+ /** Method name on the provider for speech generation (e.g. 'speech' for openai). Absent if unsupported. */
60
+ speechMethod?: string;
61
+ /** Method name on the provider for speech transcription (e.g. 'transcription' for openai). Absent if unsupported. */
62
+ transcriptionMethod?: string;
63
+ }
64
+ interface StorageEntry {
65
+ id: 'memory' | 'postgres';
66
+ label: string;
67
+ package?: string;
68
+ envVar?: string;
69
+ }
70
+ interface StackRegistry {
71
+ providers: ProviderEntry[];
72
+ storage: StorageEntry[];
73
+ }
74
+ /** Values parsed from CLI flags — undefined means "not supplied, prompt the user" */
75
+ interface AddChatOptions {
76
+ /** anthropic | openai | google */
77
+ provider?: string;
78
+ /** memory | postgres — presence implies storage component included (default: off) */
79
+ storage?: string;
80
+ /** true = --auth (default: off) */
81
+ auth?: boolean;
82
+ /** false = --no-page */
83
+ page?: boolean;
84
+ /** false = --no-chat-ui */
85
+ chatUi?: boolean;
86
+ /** override API route output path */
87
+ apiRoute?: string;
88
+ /** override storage output path */
89
+ storagePath?: string;
90
+ /** override page component output path */
91
+ pagePath?: string;
92
+ /** overwrite existing files without prompting */
93
+ overwrite?: boolean;
94
+ /** accept all defaults, skip optional prompts */
95
+ yes?: boolean;
96
+ /** schema/hook/type name (default: output) */
97
+ schemaName?: string;
98
+ /** override schema output path */
99
+ schemaPath?: string;
100
+ /** override hook output path */
101
+ hookPath?: string;
102
+ /** false = --no-hook */
103
+ hook?: boolean;
104
+ /** true = --interrupt */
105
+ interrupt?: boolean;
106
+ /** embedding model ID */
107
+ embeddingModel?: string;
108
+ /** image model: dall-e-3 | dall-e-2 (default: dall-e-3) */
109
+ imageModel?: string;
110
+ /** override API route output path (generative-ui) */
111
+ routePath?: string;
112
+ }
113
+
114
+ declare function resolvePatterns(ids: string[]): Pattern[];
115
+ declare function resolveAllPatterns(): Pattern[];
116
+
117
+ export { type ExecutionPlan, type PackageManager, type Pattern, type PlanEntry, type ProviderEntry, type SharedConfig, type StackRegistry, type StorageEntry, resolveAllPatterns, resolvePatterns };