create-adk-agent 0.0.1 โ 0.0.5
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 +77 -25
- package/bin/create-adk-agent.js +364 -0
- 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 +34 -0
- package/dist/generators/init/files/src/agents/multi-tool/agent.ts.template +83 -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 +25 -5
- 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/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 +155 -0
- package/templates/basic/_gitignore +8 -0
- package/templates/basic/jest.config.ts +8 -0
- package/templates/basic/package.json +41 -0
- package/templates/basic/src/index.ts +60 -0
- package/templates/basic/tests/agents.test.ts +19 -0
- package/templates/basic/tsconfig.json +21 -0
package/README.md
CHANGED
|
@@ -1,31 +1,57 @@
|
|
|
1
|
-
#
|
|
1
|
+
# create-adk-agent
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **The fastest way to start building with Google's Agent Development Kit (ADK)**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Scaffold production-ready ADK TypeScript projects in seconds with best practices, multiple templates, and zero configuration.
|
|
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.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
## ๐ Quick Start
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
|
-
npx
|
|
12
|
+
npx create-adk-agent my-agent
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
Or use it non-interactively:
|
|
14
16
|
|
|
15
17
|
```bash
|
|
16
|
-
|
|
18
|
+
npx create-adk-agent my-agent --template=basic --modelProvider=gemini --model=gemini-2.0-flash
|
|
17
19
|
```
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
That's it! You'll get a fully configured ADK project with:
|
|
22
|
+
|
|
23
|
+
- โ
TypeScript configured for ADK (ES2022, NodeNext)
|
|
24
|
+
- โ
Environment setup with API key validation
|
|
25
|
+
- โ
Working agent examples from official docs
|
|
26
|
+
- โ
Hot reload development with tsx
|
|
27
|
+
- โ
Testing setup with Jest
|
|
28
|
+
- โ
All the tooling (ESLint, Prettier, etc.)
|
|
29
|
+
|
|
30
|
+
## ๐ก Why Use This?
|
|
31
|
+
|
|
32
|
+
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.
|
|
33
|
+
|
|
34
|
+
**Perfect for:**
|
|
20
35
|
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
- ๐งช **Testing Ready** - Pre-configured Jest testing setup
|
|
26
|
-
- ๐ฆ **Modern Stack** - TypeScript, ESLint, Prettier, Zod validation
|
|
36
|
+
- ๐ Learning ADK quickly with working examples
|
|
37
|
+
- ๐ Starting new ADK projects without boilerplate hassle
|
|
38
|
+
- ๐ฆ Getting ADK best practices out of the box
|
|
39
|
+
- ๐ Experimenting with different agent patterns
|
|
27
40
|
|
|
28
|
-
##
|
|
41
|
+
## โจ What You Get
|
|
42
|
+
|
|
43
|
+
## โจ What You Get
|
|
44
|
+
|
|
45
|
+
- ๐ค **5 Agent Templates** - Pre-built examples from [official ADK docs](https://google.github.io/adk-docs/) (basic, multi-tool, team, streaming, workflow)
|
|
46
|
+
- ๐ **Multi-Model Ready** - Pre-configured for Gemini, OpenAI, and Anthropic
|
|
47
|
+
- โก **Hot Reload** - Instant TypeScript execution with tsx (no build step needed)
|
|
48
|
+
- ๐ **Security Built-in** - Proper `.env` handling with validation and git-ignore
|
|
49
|
+
- ๐งช **Testing Included** - Jest configured and ready to go
|
|
50
|
+
- ๐ฆ **Best Practices** - TypeScript, ESLint, Prettier, Zod validation
|
|
51
|
+
|
|
52
|
+
## ๐ Agent Templates
|
|
53
|
+
|
|
54
|
+
All templates are based on [official ADK documentation examples](https://google.github.io/adk-docs/):
|
|
29
55
|
|
|
30
56
|
### Basic Agent
|
|
31
57
|
|
|
@@ -49,28 +75,31 @@ Sequential workflow patterns with validation, transformation, and saving steps.
|
|
|
49
75
|
|
|
50
76
|
## ๐ฏ Usage
|
|
51
77
|
|
|
52
|
-
### Interactive
|
|
78
|
+
### Simple (Interactive)
|
|
79
|
+
|
|
80
|
+
Just run the command and answer a few questions:
|
|
53
81
|
|
|
54
82
|
```bash
|
|
55
|
-
npx
|
|
83
|
+
npx create-adk-agent my-agent
|
|
56
84
|
```
|
|
57
85
|
|
|
58
|
-
You'll
|
|
86
|
+
You'll choose:
|
|
59
87
|
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
- Whether to install dependencies
|
|
88
|
+
- Which agent templates to include
|
|
89
|
+
- Your preferred model provider (Gemini, OpenAI, or Anthropic)
|
|
90
|
+
- Whether to install dependencies now
|
|
63
91
|
- Whether to initialize git
|
|
64
92
|
|
|
65
|
-
### Non-Interactive
|
|
93
|
+
### Advanced (Non-Interactive)
|
|
94
|
+
|
|
95
|
+
Skip prompts by providing options:
|
|
66
96
|
|
|
67
97
|
```bash
|
|
68
|
-
npx
|
|
98
|
+
npx create-adk-agent my-agent \
|
|
69
99
|
--templates=basic,multi-tool \
|
|
70
100
|
--modelProvider=gemini \
|
|
71
101
|
--model=gemini-3.0-flash \
|
|
72
102
|
--description="My custom agent" \
|
|
73
|
-
--directory=apps \
|
|
74
103
|
--installDependencies \
|
|
75
104
|
--no-interactive
|
|
76
105
|
```
|
|
@@ -114,7 +143,30 @@ npx @adk-ts-new/create-adk-agent my-agent \
|
|
|
114
143
|
|
|
115
144
|
**Note:** You can change to any model after project generation. The list above is for initial setup convenience.
|
|
116
145
|
|
|
117
|
-
##
|
|
146
|
+
## ๐ฌ Getting Started Workflow
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# 1. Create your project (takes ~10 seconds)
|
|
150
|
+
npx create-adk-agent my-agent
|
|
151
|
+
|
|
152
|
+
# 2. Navigate to project
|
|
153
|
+
cd my-agent
|
|
154
|
+
|
|
155
|
+
# 3. Add your API key
|
|
156
|
+
cp .env.example .env
|
|
157
|
+
# Edit .env and add your API key (get it from links in the file)
|
|
158
|
+
|
|
159
|
+
# 4. Start coding! (hot reload enabled)
|
|
160
|
+
npm run dev
|
|
161
|
+
|
|
162
|
+
# 5. Or use ADK DevTools
|
|
163
|
+
npm run adk:web # Beautiful web UI
|
|
164
|
+
npm run adk:run # CLI runner
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**That's it!** You're now building with ADK. No complex setup, no configuration headaches.
|
|
168
|
+
|
|
169
|
+
## ๐ Learn More About ADK
|
|
118
170
|
|
|
119
171
|
```
|
|
120
172
|
my-agent/
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
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`);
|
|
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
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"parser": "@typescript-eslint/parser",
|
|
3
|
+
"extends": [
|
|
4
|
+
"eslint:recommended",
|
|
5
|
+
"plugin:@typescript-eslint/recommended"
|
|
6
|
+
],
|
|
7
|
+
"plugins": ["@typescript-eslint"],
|
|
8
|
+
"env": {
|
|
9
|
+
"node": true,
|
|
10
|
+
"es2022": true
|
|
11
|
+
},
|
|
12
|
+
"parserOptions": {
|
|
13
|
+
"ecmaVersion": 2022,
|
|
14
|
+
"sourceType": "module"
|
|
15
|
+
},
|
|
16
|
+
"rules": {
|
|
17
|
+
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
|
|
18
|
+
"@typescript-eslint/no-explicit-any": "warn"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Environment files - NEVER commit these!
|
|
2
|
+
.env
|
|
3
|
+
.env.local
|
|
4
|
+
.env*.local
|
|
5
|
+
|
|
6
|
+
# Dependencies
|
|
7
|
+
node_modules/
|
|
8
|
+
|
|
9
|
+
# Build output
|
|
10
|
+
dist/
|
|
11
|
+
|
|
12
|
+
# IDE
|
|
13
|
+
.vscode/
|
|
14
|
+
.idea/
|
|
15
|
+
|
|
16
|
+
# OS
|
|
17
|
+
.DS_Store
|
|
18
|
+
Thumbs.db
|
|
19
|
+
|
|
20
|
+
# Test coverage
|
|
21
|
+
coverage/
|
|
22
|
+
|
|
23
|
+
# Logs
|
|
24
|
+
*.log
|
|
25
|
+
npm-debug.log*
|
|
26
|
+
yarn-debug.log*
|
|
27
|
+
yarn-error.log*
|