create-adk-agent 0.0.2 → 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 +10 -1
- 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 +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 +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/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
|
@@ -12,8 +12,15 @@ Scaffold production-ready ADK TypeScript projects in seconds with best practices
|
|
|
12
12
|
npx create-adk-agent my-agent
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
Or use it non-interactively:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx create-adk-agent my-agent --template=basic --modelProvider=gemini --model=gemini-2.0-flash
|
|
19
|
+
```
|
|
20
|
+
|
|
15
21
|
That's it! You'll get a fully configured ADK project with:
|
|
16
|
-
|
|
22
|
+
|
|
23
|
+
- ✅ TypeScript configured for ADK (ES2022, NodeNext)
|
|
17
24
|
- ✅ Environment setup with API key validation
|
|
18
25
|
- ✅ Working agent examples from official docs
|
|
19
26
|
- ✅ Hot reload development with tsx
|
|
@@ -25,6 +32,7 @@ That's it! You'll get a fully configured ADK project with:
|
|
|
25
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.
|
|
26
33
|
|
|
27
34
|
**Perfect for:**
|
|
35
|
+
|
|
28
36
|
- 🎓 Learning ADK quickly with working examples
|
|
29
37
|
- 🚀 Starting new ADK projects without boilerplate hassle
|
|
30
38
|
- 📦 Getting ADK best practices out of the box
|
|
@@ -76,6 +84,7 @@ npx create-adk-agent my-agent
|
|
|
76
84
|
```
|
|
77
85
|
|
|
78
86
|
You'll choose:
|
|
87
|
+
|
|
79
88
|
- Which agent templates to include
|
|
80
89
|
- Your preferred model provider (Gemini, OpenAI, or Anthropic)
|
|
81
90
|
- Whether to install dependencies now
|
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
|
|
@@ -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*
|