create-adk-agent 0.0.2 โ 0.0.9
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.
- package/README.md +30 -202
- package/bin/create-adk-agent.js +361 -35
- package/dist/generators/init/files/.env.example.template +16 -0
- package/dist/generators/init/files/.eslintrc.json.template +20 -0
- package/dist/generators/init/files/.gitignore.template +27 -0
- package/dist/generators/init/files/.prettierrc.template +7 -0
- package/dist/generators/init/files/README.md.template +243 -0
- package/dist/generators/init/files/jest.config.ts.template +7 -0
- package/dist/generators/init/files/package.json.template +41 -0
- package/dist/generators/init/files/src/agents/basic/agent.ts.template +24 -0
- package/dist/generators/init/files/src/agents/multi-tool/agent.ts.template +36 -0
- package/dist/generators/init/files/src/agents/streaming/agent.ts.template +36 -0
- package/dist/generators/init/files/src/agents/team/farewell-agent.ts.template +43 -0
- package/dist/generators/init/files/src/agents/team/greeting-agent.ts.template +43 -0
- package/dist/generators/init/files/src/agents/team/root-agent.ts.template +18 -0
- package/dist/generators/init/files/src/agents/workflow/agent.ts.template +69 -0
- package/dist/generators/init/files/src/index.ts.template +61 -0
- package/dist/generators/init/files/tests/agents.test.ts.template +80 -0
- package/dist/generators/init/files/tsconfig.json.template +20 -0
- package/dist/generators/init/files/vite.config.ts.template +36 -0
- package/dist/generators/init/generator.js +3 -0
- package/dist/generators/init/generator.js.map +1 -1
- package/dist/generators/init/schema.json +124 -0
- package/package.json +20 -4
- package/src/generators/init/files/README.md.template +3 -2
- package/src/generators/init/files/package.json.template +8 -6
- package/src/generators/init/files/src/agents/basic/agent.ts.template +9 -19
- package/src/generators/init/files/src/agents/multi-tool/agent.ts.template +15 -62
- package/src/generators/init/files/vite.config.ts.template +36 -0
- package/templates/basic/.env.example +16 -0
- package/templates/basic/.eslintrc.json +13 -0
- package/templates/basic/.prettierrc +5 -0
- package/templates/basic/README.md +49 -0
- package/templates/basic/_gitignore +8 -0
- package/templates/basic/jest.config.ts +8 -0
- package/templates/basic/package.json +43 -0
- package/templates/basic/src/index.ts +59 -0
- package/templates/basic/tests/agents.test.ts +19 -0
- package/templates/basic/tsconfig.json +21 -0
- package/templates/multi-tool/src/index.ts +60 -0
package/README.md
CHANGED
|
@@ -1,241 +1,69 @@
|
|
|
1
1
|
# create-adk-agent
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Scaffold production-ready [Google ADK](https://google.github.io/adk-docs/) TypeScript projects in seconds
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
**What is ADK?** The [Agent Development Kit](https://google.github.io/adk-docs/) is Google's framework for building AI agents. This tool makes it easy to get started.
|
|
8
|
-
|
|
9
|
-
## ๐ Quick Start
|
|
5
|
+
## Quick Start
|
|
10
6
|
|
|
11
7
|
```bash
|
|
12
8
|
npx create-adk-agent my-agent
|
|
13
9
|
```
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
- โ
TypeScript configured for ADK
|
|
17
|
-
- โ
Environment setup with API key validation
|
|
18
|
-
- โ
Working agent examples from official docs
|
|
19
|
-
- โ
Hot reload development with tsx
|
|
20
|
-
- โ
Testing setup with Jest
|
|
21
|
-
- โ
All the tooling (ESLint, Prettier, etc.)
|
|
22
|
-
|
|
23
|
-
## ๐ก Why Use This?
|
|
24
|
-
|
|
25
|
-
Instead of manually setting up TypeScript, configuring ESM, managing API keys, and copying examples from docs, `create-adk-agent` does it all for you in one command.
|
|
26
|
-
|
|
27
|
-
**Perfect for:**
|
|
28
|
-
- ๐ Learning ADK quickly with working examples
|
|
29
|
-
- ๐ Starting new ADK projects without boilerplate hassle
|
|
30
|
-
- ๐ฆ Getting ADK best practices out of the box
|
|
31
|
-
- ๐ Experimenting with different agent patterns
|
|
32
|
-
|
|
33
|
-
## โจ What You Get
|
|
34
|
-
|
|
35
|
-
## โจ What You Get
|
|
36
|
-
|
|
37
|
-
- ๐ค **5 Agent Templates** - Pre-built examples from [official ADK docs](https://google.github.io/adk-docs/) (basic, multi-tool, team, streaming, workflow)
|
|
38
|
-
- ๐ **Multi-Model Ready** - Pre-configured for Gemini, OpenAI, and Anthropic
|
|
39
|
-
- โก **Hot Reload** - Instant TypeScript execution with tsx (no build step needed)
|
|
40
|
-
- ๐ **Security Built-in** - Proper `.env` handling with validation and git-ignore
|
|
41
|
-
- ๐งช **Testing Included** - Jest configured and ready to go
|
|
42
|
-
- ๐ฆ **Best Practices** - TypeScript, ESLint, Prettier, Zod validation
|
|
43
|
-
|
|
44
|
-
## ๐ Agent Templates
|
|
45
|
-
|
|
46
|
-
All templates are based on [official ADK documentation examples](https://google.github.io/adk-docs/):
|
|
47
|
-
|
|
48
|
-
### Basic Agent
|
|
49
|
-
|
|
50
|
-
Simple agent with time tool - perfect for learning ADK basics.
|
|
51
|
-
|
|
52
|
-
### Multi-Tool Agent (Default)
|
|
53
|
-
|
|
54
|
-
Agent with multiple tools (time, weather, calculator) demonstrating tool composition.
|
|
55
|
-
|
|
56
|
-
### Team Agent
|
|
11
|
+
Creates a TypeScript project pre-configured for building AI agents with Google's Agent Development Kit.
|
|
57
12
|
|
|
58
|
-
|
|
13
|
+
## What You Get
|
|
59
14
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Sequential workflow patterns with validation, transformation, and saving steps.
|
|
67
|
-
|
|
68
|
-
## ๐ฏ Usage
|
|
15
|
+
- โ
Working agent examples from [ADK docs](https://google.github.io/adk-docs/get-started/typescript/)
|
|
16
|
+
- โ
TypeScript configured (ES2022, NodeNext, ESM)
|
|
17
|
+
- โ
Hot reload with tsx (instant execution)
|
|
18
|
+
- โ
Multi-model support (Gemini, OpenAI, Anthropic)
|
|
19
|
+
- โ
Environment setup with API key validation
|
|
20
|
+
- โ
Testing with Jest, linting with ESLint
|
|
69
21
|
|
|
70
|
-
|
|
22
|
+
## Usage
|
|
71
23
|
|
|
72
|
-
|
|
24
|
+
**Interactive:**
|
|
73
25
|
|
|
74
26
|
```bash
|
|
75
27
|
npx create-adk-agent my-agent
|
|
76
28
|
```
|
|
77
29
|
|
|
78
|
-
|
|
79
|
-
- Which agent templates to include
|
|
80
|
-
- Your preferred model provider (Gemini, OpenAI, or Anthropic)
|
|
81
|
-
- Whether to install dependencies now
|
|
82
|
-
- Whether to initialize git
|
|
83
|
-
|
|
84
|
-
### Advanced (Non-Interactive)
|
|
85
|
-
|
|
86
|
-
Skip prompts by providing options:
|
|
30
|
+
**Non-interactive:**
|
|
87
31
|
|
|
88
32
|
```bash
|
|
89
33
|
npx create-adk-agent my-agent \
|
|
90
|
-
--
|
|
34
|
+
--template=basic \
|
|
91
35
|
--modelProvider=gemini \
|
|
92
|
-
--model=gemini-
|
|
93
|
-
--description="My custom agent" \
|
|
94
|
-
--installDependencies \
|
|
95
|
-
--no-interactive
|
|
36
|
+
--model=gemini-2.5-flash
|
|
96
37
|
```
|
|
97
38
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
| Option | Type | Description | Default |
|
|
101
|
-
| ----------------------- | --------------------------------- | -------------------------- | ---------------------- |
|
|
102
|
-
| `name` | string | Project name (required) | - |
|
|
103
|
-
| `--templates` | string[] | Agent templates to include | `['multi-tool']` |
|
|
104
|
-
| `--modelProvider` | gemini\|openai\|anthropic\|custom | LLM provider | `gemini` |
|
|
105
|
-
| `--model` | string | Specific model to use | Provider's first model |
|
|
106
|
-
| `--description` | string | Project description | `My ADK Agent` |
|
|
107
|
-
| `--directory` | string | Target directory | Same as name |
|
|
108
|
-
| `--installDependencies` | boolean | Run npm install | Prompt |
|
|
109
|
-
| `--initGit` | boolean | Initialize git repo | Prompt |
|
|
110
|
-
| `--no-interactive` | boolean | Skip prompts | `false` |
|
|
111
|
-
|
|
112
|
-
## ๐ค Supported Models
|
|
113
|
-
|
|
114
|
-
### Google Gemini (Direct)
|
|
115
|
-
|
|
116
|
-
- gemini-3.0-flash
|
|
117
|
-
- gemini-3.0-pro
|
|
118
|
-
- gemini-2.5-flash
|
|
119
|
-
- gemini-2.5-pro
|
|
120
|
-
|
|
121
|
-
### OpenAI (via LiteLLM)
|
|
122
|
-
|
|
123
|
-
- gpt-5
|
|
124
|
-
- gpt-5-mini
|
|
125
|
-
- gpt-4o
|
|
126
|
-
- gpt-4o-mini
|
|
127
|
-
|
|
128
|
-
### Anthropic (via LiteLLM)
|
|
129
|
-
|
|
130
|
-
- claude-4.5-sonnet
|
|
131
|
-
- claude-4-sonnet
|
|
132
|
-
- claude-4-opus
|
|
133
|
-
- claude-3-5-sonnet
|
|
134
|
-
|
|
135
|
-
**Note:** You can change to any model after project generation. The list above is for initial setup convenience.
|
|
136
|
-
|
|
137
|
-
## ๐ฌ Getting Started Workflow
|
|
39
|
+
## After Generation
|
|
138
40
|
|
|
139
41
|
```bash
|
|
140
|
-
# 1. Create your project (takes ~10 seconds)
|
|
141
|
-
npx create-adk-agent my-agent
|
|
142
|
-
|
|
143
|
-
# 2. Navigate to project
|
|
144
42
|
cd my-agent
|
|
145
43
|
|
|
146
|
-
#
|
|
44
|
+
# Add your API key
|
|
147
45
|
cp .env.example .env
|
|
148
|
-
# Edit .env
|
|
46
|
+
# Edit .env with your API key
|
|
149
47
|
|
|
150
|
-
#
|
|
48
|
+
# Start development
|
|
151
49
|
npm run dev
|
|
152
50
|
|
|
153
|
-
#
|
|
154
|
-
npm run adk:web #
|
|
51
|
+
# Use ADK DevTools
|
|
52
|
+
npm run adk:web # Interactive web UI
|
|
155
53
|
npm run adk:run # CLI runner
|
|
156
54
|
```
|
|
157
55
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
## ๐ Learn More About ADK
|
|
161
|
-
|
|
162
|
-
```
|
|
163
|
-
my-agent/
|
|
164
|
-
โโโ src/
|
|
165
|
-
โ โโโ agents/
|
|
166
|
-
โ โ โโโ basic/ # Basic agent (if selected)
|
|
167
|
-
โ โ โโโ multi-tool/ # Multi-tool agent (if selected)
|
|
168
|
-
โ โ โโโ team/ # Team agents (if selected)
|
|
169
|
-
โ โ โโโ streaming/ # Streaming agent (if selected)
|
|
170
|
-
โ โ โโโ workflow/ # Workflow agent (if selected)
|
|
171
|
-
โ โโโ index.ts # Entry point with env validation
|
|
172
|
-
โโโ tests/
|
|
173
|
-
โ โโโ agents.test.ts # Jest tests
|
|
174
|
-
โโโ .env.example # Environment template (commit this)
|
|
175
|
-
โโโ .env # Your API keys (DO NOT COMMIT)
|
|
176
|
-
โโโ .gitignore # Includes .env patterns
|
|
177
|
-
โโโ package.json # With tsx, ADK, and dev tools
|
|
178
|
-
โโโ tsconfig.json # Configured for ESM + NodeNext
|
|
179
|
-
โโโ README.md # Project-specific documentation
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## ๐ Security
|
|
56
|
+
## Templates
|
|
183
57
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
- `.env` in `.gitignore` by default
|
|
187
|
-
- API key validation on startup
|
|
188
|
-
- Clear warnings about committing secrets
|
|
189
|
-
- `.env.example` template for sharing
|
|
190
|
-
|
|
191
|
-
## ๐ ๏ธ Development Workflow
|
|
192
|
-
|
|
193
|
-
After generating your project:
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
cd my-agent
|
|
197
|
-
|
|
198
|
-
# 1. Set up your API key
|
|
199
|
-
cp .env.example .env
|
|
200
|
-
# Edit .env and add your API key
|
|
58
|
+
- **basic** - Single agent with one tool ([docs example](https://google.github.io/adk-docs/get-started/typescript/#define-the-agent-code))
|
|
59
|
+
- **multi-tool** - Agent with multiple tools (default)
|
|
201
60
|
|
|
202
|
-
|
|
203
|
-
npm install
|
|
61
|
+
## Learn More
|
|
204
62
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
# 4. Run tests
|
|
209
|
-
npm test
|
|
210
|
-
|
|
211
|
-
# 5. Use ADK DevTools
|
|
212
|
-
npm run adk:web # Web UI
|
|
213
|
-
npm run adk:run # CLI runner
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## ๐ Documentation
|
|
217
|
-
|
|
218
|
-
- [ADK Documentation](https://google.github.io/adk-docs/)
|
|
219
|
-
- [TypeScript Quick Start](https://google.github.io/adk-docs/get-started/typescript/)
|
|
220
|
-
- [Agent Tutorial](https://google.github.io/adk-docs/tutorial/agent/)
|
|
221
|
-
|
|
222
|
-
## ๐ค Contributing
|
|
223
|
-
|
|
224
|
-
Contributions welcome! This is an Nx workspace project.
|
|
225
|
-
|
|
226
|
-
### Development
|
|
227
|
-
|
|
228
|
-
```bash
|
|
229
|
-
# Build the generator
|
|
230
|
-
nx build create-adk-agent
|
|
231
|
-
|
|
232
|
-
# Test locally
|
|
233
|
-
nx g @adk-ts-new/create-adk-agent:init test-project
|
|
234
|
-
|
|
235
|
-
# Run tests
|
|
236
|
-
nx test create-adk-agent
|
|
237
|
-
```
|
|
63
|
+
- **[ADK Documentation](https://google.github.io/adk-docs/)** - Official ADK guide
|
|
64
|
+
- **[TypeScript Quickstart](https://google.github.io/adk-docs/get-started/typescript/)** - Getting started
|
|
65
|
+
- **[Building Agents](https://google.github.io/adk-docs/tutorials/)** - Agent tutorials
|
|
238
66
|
|
|
239
|
-
##
|
|
67
|
+
## License
|
|
240
68
|
|
|
241
|
-
MIT
|
|
69
|
+
MIT
|
package/bin/create-adk-agent.js
CHANGED
|
@@ -1,38 +1,364 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
3
|
+
// @ts-check
|
|
4
|
+
import { blue, cyan, green, red, reset, yellow } from 'kolorist';
|
|
5
|
+
import minimist from 'minimist';
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import prompts from 'prompts';
|
|
10
|
+
|
|
11
|
+
const argv = minimist(process.argv.slice(2), { string: ['_'] });
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
|
|
14
|
+
// Template configurations
|
|
15
|
+
const TEMPLATES = [
|
|
16
|
+
{
|
|
17
|
+
name: 'basic',
|
|
18
|
+
display: 'Basic Agent',
|
|
19
|
+
description: 'Single agent with one tool (time example)',
|
|
20
|
+
color: green,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'multi-tool',
|
|
24
|
+
display: 'Multi-Tool Agent',
|
|
25
|
+
description: 'Agent with multiple tools (recommended)',
|
|
26
|
+
color: blue,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'streaming',
|
|
30
|
+
display: 'Streaming Agent',
|
|
31
|
+
description: 'Agent with Live API streaming support',
|
|
32
|
+
color: cyan,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'team',
|
|
36
|
+
display: 'Multi-Agent Team',
|
|
37
|
+
description: 'Multiple agents working together',
|
|
38
|
+
color: yellow,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'workflow',
|
|
42
|
+
display: 'Workflow Agent',
|
|
43
|
+
description: 'Sequential and parallel execution patterns',
|
|
44
|
+
color: yellow,
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
// Model provider configurations
|
|
49
|
+
const MODEL_PROVIDERS = {
|
|
50
|
+
gemini: {
|
|
51
|
+
name: 'Google Gemini',
|
|
52
|
+
models: [
|
|
53
|
+
'gemini-2.0-flash',
|
|
54
|
+
'gemini-2.0-flash-thinking-exp-01-21',
|
|
55
|
+
'gemini-1.5-pro',
|
|
56
|
+
],
|
|
57
|
+
apiKeyVar: 'GEMINI_API_KEY',
|
|
58
|
+
importStatement: "import { LlmAgent, FunctionTool } from '@google/adk';",
|
|
59
|
+
modelConfig: (model) => `'${model}'`,
|
|
60
|
+
},
|
|
61
|
+
openai: {
|
|
62
|
+
name: 'OpenAI',
|
|
63
|
+
models: ['openai/gpt-4o', 'openai/gpt-4o-mini', 'openai/gpt-4-turbo'],
|
|
64
|
+
apiKeyVar: 'OPENAI_API_KEY',
|
|
65
|
+
importStatement:
|
|
66
|
+
"import { LlmAgent, FunctionTool, LiteLlm } from '@google/adk';",
|
|
67
|
+
modelConfig: (model) => `new LiteLlm({ model: '${model}' })`,
|
|
68
|
+
},
|
|
69
|
+
anthropic: {
|
|
70
|
+
name: 'Anthropic (Claude)',
|
|
71
|
+
models: [
|
|
72
|
+
'anthropic/claude-3-5-sonnet',
|
|
73
|
+
'anthropic/claude-3-opus',
|
|
74
|
+
'anthropic/claude-3-haiku',
|
|
75
|
+
],
|
|
76
|
+
apiKeyVar: 'ANTHROPIC_API_KEY',
|
|
77
|
+
importStatement:
|
|
78
|
+
"import { LlmAgent, FunctionTool, LiteLlm } from '@google/adk';",
|
|
79
|
+
modelConfig: (model) => `new LiteLlm({ model: '${model}' })`,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const renameFiles = {
|
|
84
|
+
_gitignore: '.gitignore',
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
function formatTargetDir(targetDir) {
|
|
88
|
+
return targetDir?.trim().replace(/\/+$/g, '');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function isValidPackageName(projectName) {
|
|
92
|
+
return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(
|
|
93
|
+
projectName,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function toValidPackageName(projectName) {
|
|
98
|
+
return projectName
|
|
99
|
+
.trim()
|
|
100
|
+
.toLowerCase()
|
|
101
|
+
.replace(/\s+/g, '-')
|
|
102
|
+
.replace(/^[._]/, '')
|
|
103
|
+
.replace(/[^a-z0-9-~]+/g, '-');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function copy(src, dest) {
|
|
107
|
+
const stat = fs.statSync(src);
|
|
108
|
+
if (stat.isDirectory()) {
|
|
109
|
+
copyDir(src, dest);
|
|
110
|
+
} else {
|
|
111
|
+
fs.copyFileSync(src, dest);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function copyDir(srcDir, destDir) {
|
|
116
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
117
|
+
for (const file of fs.readdirSync(srcDir)) {
|
|
118
|
+
const srcFile = path.resolve(srcDir, file);
|
|
119
|
+
const destFile = path.resolve(destDir, file);
|
|
120
|
+
copy(srcFile, destFile);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function isEmpty(pathToCheck) {
|
|
125
|
+
const files = fs.readdirSync(pathToCheck);
|
|
126
|
+
return files.length === 0 || (files.length === 1 && files[0] === '.git');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function emptyDir(dir) {
|
|
130
|
+
if (!fs.existsSync(dir)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
for (const file of fs.readdirSync(dir)) {
|
|
134
|
+
fs.rmSync(path.resolve(dir, file), { recursive: true, force: true });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function replacePlaceholders(root, files, config) {
|
|
139
|
+
for (const file of Array.isArray(files) ? files : [files]) {
|
|
140
|
+
const filePath = path.join(root, file);
|
|
141
|
+
if (!fs.existsSync(filePath)) continue;
|
|
142
|
+
|
|
143
|
+
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
144
|
+
const newFileContent = Object.keys(config).reduce(
|
|
145
|
+
(content, placeholder) =>
|
|
146
|
+
content.replace(new RegExp(placeholder, 'g'), config[placeholder]),
|
|
147
|
+
fileContent,
|
|
148
|
+
);
|
|
149
|
+
fs.writeFileSync(filePath, newFileContent);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function init() {
|
|
154
|
+
let targetDir = formatTargetDir(argv._[0]);
|
|
155
|
+
let template = argv.template || argv.t;
|
|
156
|
+
let modelProvider = argv.modelProvider || argv.mp;
|
|
157
|
+
let model = argv.model || argv.m;
|
|
158
|
+
let description = argv.description || argv.d;
|
|
159
|
+
|
|
160
|
+
const defaultTargetDir = 'my-adk-agent';
|
|
161
|
+
const getProjectName = () =>
|
|
162
|
+
targetDir === '.' ? path.basename(path.resolve()) : targetDir;
|
|
163
|
+
|
|
164
|
+
let result = {};
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
result = await prompts(
|
|
168
|
+
[
|
|
169
|
+
{
|
|
170
|
+
type: targetDir ? null : 'text',
|
|
171
|
+
name: 'projectName',
|
|
172
|
+
message: reset('Project name:'),
|
|
173
|
+
initial: defaultTargetDir,
|
|
174
|
+
onState: (state) => {
|
|
175
|
+
targetDir = formatTargetDir(state.value) || defaultTargetDir;
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: () =>
|
|
180
|
+
!fs.existsSync(targetDir) || isEmpty(targetDir) ? null : 'confirm',
|
|
181
|
+
name: 'overwrite',
|
|
182
|
+
message: () =>
|
|
183
|
+
(targetDir === '.'
|
|
184
|
+
? 'Current directory'
|
|
185
|
+
: `Target directory "${targetDir}"`) +
|
|
186
|
+
` is not empty. Remove existing files and continue?`,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
type: (_, { overwrite } = {}) => {
|
|
190
|
+
if (overwrite === false) {
|
|
191
|
+
throw new Error(red('โ') + ' Operation cancelled');
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
},
|
|
195
|
+
name: 'overwriteChecker',
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
type: () => (isValidPackageName(getProjectName()) ? null : 'text'),
|
|
199
|
+
name: 'packageName',
|
|
200
|
+
message: reset('Package name:'),
|
|
201
|
+
initial: () => toValidPackageName(getProjectName()),
|
|
202
|
+
validate: (dir) =>
|
|
203
|
+
isValidPackageName(dir) || 'Invalid package.json name',
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
type: description ? null : 'text',
|
|
207
|
+
name: 'description',
|
|
208
|
+
message: reset('Project description:'),
|
|
209
|
+
initial: 'My ADK Agent',
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
type: template ? null : 'select',
|
|
213
|
+
name: 'template',
|
|
214
|
+
message: reset('Select a template:'),
|
|
215
|
+
choices: TEMPLATES.map((t) => ({
|
|
216
|
+
title: `${t.color(t.display)} - ${t.description}`,
|
|
217
|
+
value: t.name,
|
|
218
|
+
})),
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
type: modelProvider ? null : 'select',
|
|
222
|
+
name: 'modelProvider',
|
|
223
|
+
message: reset('Select LLM provider:'),
|
|
224
|
+
choices: Object.entries(MODEL_PROVIDERS).map(([key, value]) => ({
|
|
225
|
+
title: value.name,
|
|
226
|
+
value: key,
|
|
227
|
+
})),
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
type: (prev, values) => {
|
|
231
|
+
const provider = modelProvider || values.modelProvider;
|
|
232
|
+
return model || !provider ? null : 'select';
|
|
233
|
+
},
|
|
234
|
+
name: 'model',
|
|
235
|
+
message: reset('Select model:'),
|
|
236
|
+
choices: (prev, values) => {
|
|
237
|
+
const provider = modelProvider || values.modelProvider;
|
|
238
|
+
return MODEL_PROVIDERS[provider].models.map((m) => ({
|
|
239
|
+
title: m,
|
|
240
|
+
value: m,
|
|
241
|
+
}));
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
{
|
|
246
|
+
onCancel: () => {
|
|
247
|
+
throw new Error(red('โ') + ' Operation cancelled');
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
);
|
|
251
|
+
} catch (cancelled) {
|
|
252
|
+
console.log(cancelled.message);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Extract values from prompts
|
|
257
|
+
const {
|
|
258
|
+
overwrite,
|
|
259
|
+
packageName,
|
|
260
|
+
description: promptDescription,
|
|
261
|
+
template: promptTemplate,
|
|
262
|
+
modelProvider: promptModelProvider,
|
|
263
|
+
model: promptModel,
|
|
264
|
+
} = result;
|
|
265
|
+
|
|
266
|
+
// Use CLI args or prompt values
|
|
267
|
+
template = template || promptTemplate || 'basic';
|
|
268
|
+
modelProvider = modelProvider || promptModelProvider || 'gemini';
|
|
269
|
+
model = model || promptModel || MODEL_PROVIDERS[modelProvider].models[0];
|
|
270
|
+
description = description || promptDescription || 'My ADK Agent';
|
|
271
|
+
|
|
272
|
+
const root = path.join(cwd, targetDir);
|
|
273
|
+
|
|
274
|
+
if (overwrite) {
|
|
275
|
+
emptyDir(root);
|
|
276
|
+
} else if (!fs.existsSync(root)) {
|
|
277
|
+
fs.mkdirSync(root, { recursive: true });
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
console.log(`\n${green('โ')} Scaffolding project in ${root}...\n`);
|
|
281
|
+
|
|
282
|
+
const templateDir = path.resolve(
|
|
283
|
+
fileURLToPath(import.meta.url),
|
|
284
|
+
'..',
|
|
285
|
+
'..',
|
|
286
|
+
'templates',
|
|
287
|
+
template,
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
if (!fs.existsSync(templateDir)) {
|
|
291
|
+
console.error(red(`โ Error: Template "${template}" not found!`));
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const write = (file, content) => {
|
|
296
|
+
const targetPath = renameFiles[file]
|
|
297
|
+
? path.join(root, renameFiles[file])
|
|
298
|
+
: path.join(root, file);
|
|
299
|
+
|
|
300
|
+
if (content) {
|
|
301
|
+
fs.writeFileSync(targetPath, content);
|
|
302
|
+
} else {
|
|
303
|
+
copy(path.join(templateDir, file), targetPath);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// Copy all template files
|
|
308
|
+
const files = fs.readdirSync(templateDir);
|
|
309
|
+
for (const file of files.filter((f) => f !== 'package.json')) {
|
|
310
|
+
write(file);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Handle package.json separately
|
|
314
|
+
const pkg = JSON.parse(
|
|
315
|
+
fs.readFileSync(path.join(templateDir, 'package.json'), 'utf-8'),
|
|
316
|
+
);
|
|
317
|
+
pkg.name = packageName || getProjectName();
|
|
318
|
+
pkg.description = description;
|
|
319
|
+
|
|
320
|
+
write('package.json', JSON.stringify(pkg, null, 2));
|
|
321
|
+
|
|
322
|
+
// Replace placeholders
|
|
323
|
+
const providerConfig = MODEL_PROVIDERS[modelProvider];
|
|
324
|
+
const modelConfig = providerConfig.modelConfig(model);
|
|
325
|
+
|
|
326
|
+
replacePlaceholders(root, 'README.md', {
|
|
327
|
+
__PROJECT_NAME__: pkg.name,
|
|
328
|
+
__DESCRIPTION__: description,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
replacePlaceholders(root, 'src/index.ts', {
|
|
332
|
+
__MODEL_CONFIG__: modelConfig,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Update imports if needed (for LiteLLM)
|
|
336
|
+
if (modelProvider !== 'gemini') {
|
|
337
|
+
replacePlaceholders(root, 'src/index.ts', {
|
|
338
|
+
"import { LlmAgent, FunctionTool } from '@google/adk';":
|
|
339
|
+
providerConfig.importStatement,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
console.log(`${green('โ')} Project created successfully!\n`);
|
|
344
|
+
console.log(`${cyan('Next steps:')}\n`);
|
|
345
|
+
|
|
346
|
+
if (root !== cwd) {
|
|
347
|
+
console.log(` cd ${path.relative(cwd, root)}`);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
console.log(` npm install`);
|
|
351
|
+
console.log(` cp .env.example .env`);
|
|
352
|
+
console.log(` ${yellow('# Edit .env and add your API key')}`);
|
|
353
|
+
console.log(` npm run dev\n`);
|
|
354
|
+
|
|
355
|
+
console.log(`${cyan('Configuration:')}`);
|
|
356
|
+
console.log(` Template: ${green(template)}`);
|
|
357
|
+
console.log(` Provider: ${green(providerConfig.name)}`);
|
|
358
|
+
console.log(` Model: ${green(model)}`);
|
|
359
|
+
console.log(` API Key: ${yellow(providerConfig.apiKeyVar)}\n`);
|
|
38
360
|
}
|
|
361
|
+
|
|
362
|
+
init().catch((e) => {
|
|
363
|
+
console.error(e);
|
|
364
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Google Gemini API Key
|
|
2
|
+
# Get your key from: https://aistudio.google.com/apikey
|
|
3
|
+
GEMINI_API_KEY=your_google_api_key_here
|
|
4
|
+
|
|
5
|
+
# OR use Vertex AI (for Google Cloud)
|
|
6
|
+
# GOOGLE_GENAI_USE_VERTEXAI=true
|
|
7
|
+
# GOOGLE_CLOUD_PROJECT=your-project-id
|
|
8
|
+
# GOOGLE_CLOUD_LOCATION=us-central1
|
|
9
|
+
|
|
10
|
+
# OpenAI API Key (if using OpenAI models)
|
|
11
|
+
# Get your key from: https://platform.openai.com/api-keys
|
|
12
|
+
# OPENAI_API_KEY=your_openai_api_key_here
|
|
13
|
+
|
|
14
|
+
# Anthropic API Key (if using Claude models)
|
|
15
|
+
# Get your key from: https://console.anthropic.com/settings/keys
|
|
16
|
+
# ANTHROPIC_API_KEY=your_anthropic_api_key_here
|