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
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
<% if (hasBasic) { %>import { rootAgent as basicAgent } from './agents/basic/agent.js';
|
|
3
|
+
<% } %><% if (hasMultiTool) { %>import { rootAgent as multiToolAgent } from './agents/multi-tool/agent.js';
|
|
4
|
+
<% } %><% if (hasTeam) { %>import { rootAgent as teamAgent } from './agents/team/root-agent.js';
|
|
5
|
+
<% } %><% if (hasStreaming) { %>import { rootAgent as streamingAgent } from './agents/streaming/agent.js';
|
|
6
|
+
<% } %><% if (hasWorkflow) { %>import { rootAgent as workflowAgent } from './agents/workflow/agent.js';
|
|
7
|
+
<% } %>
|
|
8
|
+
// Validate required environment variables based on model
|
|
9
|
+
const modelProvider = '<%= modelProvider %>';
|
|
10
|
+
const model = '<%= model %>';
|
|
11
|
+
|
|
12
|
+
if (modelProvider === 'gemini' && !process.env.GEMINI_API_KEY) {
|
|
13
|
+
console.error('❌ GEMINI_API_KEY is required for Gemini models.');
|
|
14
|
+
console.error('Get your API key from: https://aistudio.google.com/apikey');
|
|
15
|
+
console.error('Add it to your .env file: GEMINI_API_KEY=your_key_here');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (modelProvider === 'openai' && !process.env.OPENAI_API_KEY) {
|
|
20
|
+
console.error('❌ OPENAI_API_KEY is required for OpenAI models.');
|
|
21
|
+
console.error('Get your API key from: https://platform.openai.com/api-keys');
|
|
22
|
+
console.error('Add it to your .env file: OPENAI_API_KEY=your_key_here');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (modelProvider === 'anthropic' && !process.env.ANTHROPIC_API_KEY) {
|
|
27
|
+
console.error('❌ ANTHROPIC_API_KEY is required for Anthropic models.');
|
|
28
|
+
console.error('Get your API key from: https://console.anthropic.com/settings/keys');
|
|
29
|
+
console.error('Add it to your .env file: ANTHROPIC_API_KEY=your_key_here');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log('✅ Environment configured successfully');
|
|
34
|
+
console.log(`📦 Model Provider: ${modelProvider}`);
|
|
35
|
+
console.log(`🤖 Model: ${model}`);
|
|
36
|
+
console.log('');
|
|
37
|
+
console.log('Available agents:');
|
|
38
|
+
<% if (hasBasic) { %>console.log(' - basicAgent: Basic agent with time tool');
|
|
39
|
+
<% } %><% if (hasMultiTool) { %>console.log(' - multiToolAgent: Agent with multiple tools');
|
|
40
|
+
<% } %><% if (hasTeam) { %>console.log(' - teamAgent: Multi-agent team coordination');
|
|
41
|
+
<% } %><% if (hasStreaming) { %>console.log(' - streamingAgent: Streaming responses with Live API');
|
|
42
|
+
<% } %><% if (hasWorkflow) { %>console.log(' - workflowAgent: Workflow patterns (sequential/loop/parallel)');
|
|
43
|
+
<% } %>console.log('');
|
|
44
|
+
console.log('Run agents with ADK DevTools:');
|
|
45
|
+
console.log(' npm run adk:web - Web UI for all agents');
|
|
46
|
+
console.log(' npm run adk:run - CLI runner');
|
|
47
|
+
|
|
48
|
+
// Export agents for ADK DevTools
|
|
49
|
+
<% if (hasBasic) { %>export { basicAgent };
|
|
50
|
+
<% } %><% if (hasMultiTool) { %>export { multiToolAgent };
|
|
51
|
+
<% } %><% if (hasTeam) { %>export { teamAgent };
|
|
52
|
+
<% } %><% if (hasStreaming) { %>export { streamingAgent };
|
|
53
|
+
<% } %><% if (hasWorkflow) { %>export { workflowAgent };
|
|
54
|
+
<% } %>
|
|
55
|
+
// Default export for convenience
|
|
56
|
+
<% if (hasMultiTool) { %>export default multiToolAgent;
|
|
57
|
+
<% } else if (hasBasic) { %>export default basicAgent;
|
|
58
|
+
<% } else if (hasTeam) { %>export default teamAgent;
|
|
59
|
+
<% } else if (hasStreaming) { %>export default streamingAgent;
|
|
60
|
+
<% } else if (hasWorkflow) { %>export default workflowAgent;
|
|
61
|
+
<% } %>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<% if (hasBasic) { %>import { rootAgent as basicAgent } from '../src/agents/basic/agent.js';
|
|
2
|
+
|
|
3
|
+
describe('Basic Agent', () => {
|
|
4
|
+
it('should initialize with correct configuration', () => {
|
|
5
|
+
expect(basicAgent.name).toBe('hello_time_agent');
|
|
6
|
+
expect(basicAgent.tools).toHaveLength(1);
|
|
7
|
+
expect(basicAgent.tools[0].name).toBe('get_current_time');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('should have correct description', () => {
|
|
11
|
+
expect(basicAgent.description).toContain('time');
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
<% } %>
|
|
15
|
+
<% if (hasMultiTool) { %>import { rootAgent as multiToolAgent } from '../src/agents/multi-tool/agent.js';
|
|
16
|
+
|
|
17
|
+
describe('Multi-Tool Agent', () => {
|
|
18
|
+
it('should initialize with correct configuration', () => {
|
|
19
|
+
expect(multiToolAgent.name).toBe('multi_tool_agent');
|
|
20
|
+
expect(multiToolAgent.tools).toHaveLength(3);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should have time, weather, and calculate tools', () => {
|
|
24
|
+
const toolNames = multiToolAgent.tools.map((tool) => tool.name);
|
|
25
|
+
expect(toolNames).toContain('get_current_time');
|
|
26
|
+
expect(toolNames).toContain('get_weather');
|
|
27
|
+
expect(toolNames).toContain('calculate');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
<% } %>
|
|
31
|
+
<% if (hasTeam) { %>import { rootAgent as teamAgent } from '../src/agents/team/root-agent.js';
|
|
32
|
+
import { greetingAgent } from '../src/agents/team/greeting-agent.js';
|
|
33
|
+
import { farewellAgent } from '../src/agents/team/farewell-agent.js';
|
|
34
|
+
|
|
35
|
+
describe('Team Agents', () => {
|
|
36
|
+
it('root agent should coordinate sub-agents', () => {
|
|
37
|
+
expect(teamAgent.name).toBe('team_root_agent');
|
|
38
|
+
expect(teamAgent.agents).toHaveLength(2);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('greeting agent should have say_hello tool', () => {
|
|
42
|
+
expect(greetingAgent.name).toBe('greeting_agent');
|
|
43
|
+
expect(greetingAgent.tools).toHaveLength(1);
|
|
44
|
+
expect(greetingAgent.tools[0].name).toBe('say_hello');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('farewell agent should have say_goodbye tool', () => {
|
|
48
|
+
expect(farewellAgent.name).toBe('farewell_agent');
|
|
49
|
+
expect(farewellAgent.tools).toHaveLength(1);
|
|
50
|
+
expect(farewellAgent.tools[0].name).toBe('say_goodbye');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
<% } %>
|
|
54
|
+
<% if (hasStreaming) { %>import { rootAgent as streamingAgent } from '../src/agents/streaming/agent.js';
|
|
55
|
+
|
|
56
|
+
describe('Streaming Agent', () => {
|
|
57
|
+
it('should initialize with correct configuration', () => {
|
|
58
|
+
expect(streamingAgent.name).toBe('streaming_agent');
|
|
59
|
+
expect(streamingAgent.tools).toHaveLength(1);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should have process_data tool', () => {
|
|
63
|
+
expect(streamingAgent.tools[0].name).toBe('process_data');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
<% } %>
|
|
67
|
+
<% if (hasWorkflow) { %>import { rootAgent as workflowAgent } from '../src/agents/workflow/agent.js';
|
|
68
|
+
|
|
69
|
+
describe('Workflow Agent', () => {
|
|
70
|
+
it('should initialize with correct configuration', () => {
|
|
71
|
+
expect(workflowAgent.name).toBe('workflow_agent');
|
|
72
|
+
expect(workflowAgent.tools).toHaveLength(3);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should have workflow tools in correct order', () => {
|
|
76
|
+
const toolNames = workflowAgent.tools.map((tool) => tool.name);
|
|
77
|
+
expect(toolNames).toEqual(['validate_input', 'transform_data', 'save_result']);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
<% } %>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"verbatimModuleSyntax": false,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"outDir": "dist",
|
|
11
|
+
"rootDir": "src",
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"allowSyntheticDefaultImports": true
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*"],
|
|
19
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
20
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import { VitePluginNode } from 'vite-plugin-node';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
plugins: [
|
|
6
|
+
...VitePluginNode({
|
|
7
|
+
adapter: 'node',
|
|
8
|
+
appPath: './src/index.ts',
|
|
9
|
+
exportName: 'rootAgent',
|
|
10
|
+
tsCompiler: 'esbuild',
|
|
11
|
+
}),
|
|
12
|
+
],
|
|
13
|
+
build: {
|
|
14
|
+
outDir: 'dist',
|
|
15
|
+
lib: {
|
|
16
|
+
entry: './src/index.ts',
|
|
17
|
+
formats: ['es'],
|
|
18
|
+
fileName: 'index',
|
|
19
|
+
},
|
|
20
|
+
rollupOptions: {
|
|
21
|
+
external: [
|
|
22
|
+
'@google/adk',
|
|
23
|
+
'@google/adk-devtools',
|
|
24
|
+
'dotenv',
|
|
25
|
+
'zod',
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
target: 'node20',
|
|
29
|
+
minify: false,
|
|
30
|
+
},
|
|
31
|
+
resolve: {
|
|
32
|
+
alias: {
|
|
33
|
+
'@': './src',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
2
|
import { formatFiles, generateFiles, installPackagesTask, joinPathFragments, names } from '@nx/devkit';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
4
7
|
// Model options based on provider
|
|
5
8
|
// Note: Users can change to any model in their generated project
|
|
6
9
|
// This list is just for initial selection during project creation
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/generators/init/generator.ts"],"sourcesContent":["import {\n Tree,\n formatFiles,\n generateFiles,\n installPackagesTask,\n joinPathFragments,\n names,\n} from '@nx/devkit';\nimport * as path from 'path';\nimport { InitGeneratorSchema } from './schema.js';\n\n// Model options based on provider\n// Note: Users can change to any model in their generated project\n// This list is just for initial selection during project creation\nconst MODEL_OPTIONS = {\n gemini: [\n 'gemini-3.0-flash',\n 'gemini-3.0-pro',\n 'gemini-2.5-flash',\n 'gemini-2.5-pro',\n ],\n openai: ['gpt-5', 'gpt-5-mini', 'gpt-4o', 'gpt-4o-mini'],\n anthropic: [\n 'claude-4.5-sonnet',\n 'claude-4-sonnet',\n 'claude-4-opus',\n 'claude-3-5-sonnet',\n ],\n custom: [],\n};\n\nexport async function initGenerator(tree: Tree, options: InitGeneratorSchema) {\n const projectRoot = options.directory\n ? joinPathFragments(options.directory, options.name)\n : options.name;\n\n // Set default templates if none selected\n if (!options.templates || options.templates.length === 0) {\n options.templates = ['multi-tool'];\n }\n\n // Set default model provider\n if (!options.modelProvider) {\n options.modelProvider = 'gemini';\n }\n\n // Set default model based on provider\n if (!options.model) {\n const provider = options.modelProvider as keyof typeof MODEL_OPTIONS;\n options.model = MODEL_OPTIONS[provider]?.[0] || 'gemini-3.0-flash';\n }\n\n // Generate project files\n const substitutions = {\n ...names(options.name),\n projectName: options.name,\n description: options.description || 'My ADK Agent',\n modelProvider: options.modelProvider,\n model: options.model,\n templates: options.templates,\n hasBasic: options.templates.includes('basic'),\n hasMultiTool: options.templates.includes('multi-tool'),\n hasTeam: options.templates.includes('team'),\n hasStreaming: options.templates.includes('streaming'),\n hasWorkflow: options.templates.includes('workflow'),\n tmpl: '',\n };\n\n generateFiles(\n tree,\n path.join(__dirname, 'files'),\n projectRoot,\n substitutions,\n );\n\n // Format files\n await formatFiles(tree);\n\n // Print success message\n console.log(`\n✅ ADK Agent project created successfully!\n\n📁 Project: ${projectRoot}\n🤖 Model: ${options.model}\n📦 Templates: ${options.templates.join(', ')}\n\n🚀 Next steps:\n 1. cd ${projectRoot}\n 2. Copy .env.example to .env and add your API key\n 3. npm install${options.installDependencies ? ' (running now...)' : ''}\n 4. npm run dev\n\n📚 Documentation: https://google.github.io/adk-docs/\n`);\n\n // Return task for dependency installation if requested\n if (options.installDependencies) {\n return installPackagesTask(tree);\n }\n\n return () => {};\n}\n\nexport default initGenerator;\n"],"names":["formatFiles","generateFiles","installPackagesTask","joinPathFragments","names","path","MODEL_OPTIONS","gemini","openai","anthropic","custom","initGenerator","tree","options","projectRoot","directory","name","templates","length","modelProvider","model","provider","substitutions","projectName","description","hasBasic","includes","hasMultiTool","hasTeam","hasStreaming","hasWorkflow","tmpl","join","
|
|
1
|
+
{"version":3,"sources":["../../../src/generators/init/generator.ts"],"sourcesContent":["import {\n Tree,\n formatFiles,\n generateFiles,\n installPackagesTask,\n joinPathFragments,\n names,\n} from '@nx/devkit';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport { InitGeneratorSchema } from './schema.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Model options based on provider\n// Note: Users can change to any model in their generated project\n// This list is just for initial selection during project creation\nconst MODEL_OPTIONS = {\n gemini: [\n 'gemini-3.0-flash',\n 'gemini-3.0-pro',\n 'gemini-2.5-flash',\n 'gemini-2.5-pro',\n ],\n openai: ['gpt-5', 'gpt-5-mini', 'gpt-4o', 'gpt-4o-mini'],\n anthropic: [\n 'claude-4.5-sonnet',\n 'claude-4-sonnet',\n 'claude-4-opus',\n 'claude-3-5-sonnet',\n ],\n custom: [],\n};\n\nexport async function initGenerator(tree: Tree, options: InitGeneratorSchema) {\n const projectRoot = options.directory\n ? joinPathFragments(options.directory, options.name)\n : options.name;\n\n // Set default templates if none selected\n if (!options.templates || options.templates.length === 0) {\n options.templates = ['multi-tool'];\n }\n\n // Set default model provider\n if (!options.modelProvider) {\n options.modelProvider = 'gemini';\n }\n\n // Set default model based on provider\n if (!options.model) {\n const provider = options.modelProvider as keyof typeof MODEL_OPTIONS;\n options.model = MODEL_OPTIONS[provider]?.[0] || 'gemini-3.0-flash';\n }\n\n // Generate project files\n const substitutions = {\n ...names(options.name),\n projectName: options.name,\n description: options.description || 'My ADK Agent',\n modelProvider: options.modelProvider,\n model: options.model,\n templates: options.templates,\n hasBasic: options.templates.includes('basic'),\n hasMultiTool: options.templates.includes('multi-tool'),\n hasTeam: options.templates.includes('team'),\n hasStreaming: options.templates.includes('streaming'),\n hasWorkflow: options.templates.includes('workflow'),\n tmpl: '',\n };\n\n generateFiles(\n tree,\n path.join(__dirname, 'files'),\n projectRoot,\n substitutions,\n );\n\n // Format files\n await formatFiles(tree);\n\n // Print success message\n console.log(`\n✅ ADK Agent project created successfully!\n\n📁 Project: ${projectRoot}\n🤖 Model: ${options.model}\n📦 Templates: ${options.templates.join(', ')}\n\n🚀 Next steps:\n 1. cd ${projectRoot}\n 2. Copy .env.example to .env and add your API key\n 3. npm install${options.installDependencies ? ' (running now...)' : ''}\n 4. npm run dev\n\n📚 Documentation: https://google.github.io/adk-docs/\n`);\n\n // Return task for dependency installation if requested\n if (options.installDependencies) {\n return installPackagesTask(tree);\n }\n\n return () => {};\n}\n\nexport default initGenerator;\n"],"names":["formatFiles","generateFiles","installPackagesTask","joinPathFragments","names","path","fileURLToPath","__filename","url","__dirname","dirname","MODEL_OPTIONS","gemini","openai","anthropic","custom","initGenerator","tree","options","projectRoot","directory","name","templates","length","modelProvider","model","provider","substitutions","projectName","description","hasBasic","includes","hasMultiTool","hasTeam","hasStreaming","hasWorkflow","tmpl","join","console","log","installDependencies"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AAAA,SAEEA,WAAW,EACXC,aAAa,EACbC,mBAAmB,EACnBC,iBAAiB,EACjBC,KAAK,QACA,aAAa;AACpB,YAAYC,UAAU,OAAO;AAC7B,SAASC,aAAa,QAAQ,MAAM;AAGpC,MAAMC,aAAaD,cAAc,YAAYE,GAAG;AAChD,MAAMC,YAAYJ,KAAKK,OAAO,CAACH;AAE/B,kCAAkC;AAClC,iEAAiE;AACjE,kEAAkE;AAClE,MAAMI,gBAAgB;IACpBC,QAAQ;QACN;QACA;QACA;QACA;KACD;IACDC,QAAQ;QAAC;QAAS;QAAc;QAAU;KAAc;IACxDC,WAAW;QACT;QACA;QACA;QACA;KACD;IACDC,QAAQ,EAAE;AACZ;AAEA,OAAO,eAAeC,cAAcC,IAAU,EAAEC,OAA4B;IAC1E,MAAMC,cAAcD,QAAQE,SAAS,GACjCjB,kBAAkBe,QAAQE,SAAS,EAAEF,QAAQG,IAAI,IACjDH,QAAQG,IAAI;IAEhB,yCAAyC;IACzC,IAAI,CAACH,QAAQI,SAAS,IAAIJ,QAAQI,SAAS,CAACC,MAAM,KAAK,GAAG;QACxDL,QAAQI,SAAS,GAAG;YAAC;SAAa;IACpC;IAEA,6BAA6B;IAC7B,IAAI,CAACJ,QAAQM,aAAa,EAAE;QAC1BN,QAAQM,aAAa,GAAG;IAC1B;IAEA,sCAAsC;IACtC,IAAI,CAACN,QAAQO,KAAK,EAAE;YAEFd;QADhB,MAAMe,WAAWR,QAAQM,aAAa;QACtCN,QAAQO,KAAK,GAAGd,EAAAA,0BAAAA,aAAa,CAACe,SAAS,qBAAvBf,uBAAyB,CAAC,EAAE,KAAI;IAClD;IAEA,yBAAyB;IACzB,MAAMgB,gBAAgB,aACjBvB,MAAMc,QAAQG,IAAI;QACrBO,aAAaV,QAAQG,IAAI;QACzBQ,aAAaX,QAAQW,WAAW,IAAI;QACpCL,eAAeN,QAAQM,aAAa;QACpCC,OAAOP,QAAQO,KAAK;QACpBH,WAAWJ,QAAQI,SAAS;QAC5BQ,UAAUZ,QAAQI,SAAS,CAACS,QAAQ,CAAC;QACrCC,cAAcd,QAAQI,SAAS,CAACS,QAAQ,CAAC;QACzCE,SAASf,QAAQI,SAAS,CAACS,QAAQ,CAAC;QACpCG,cAAchB,QAAQI,SAAS,CAACS,QAAQ,CAAC;QACzCI,aAAajB,QAAQI,SAAS,CAACS,QAAQ,CAAC;QACxCK,MAAM;;IAGRnC,cACEgB,MACAZ,KAAKgC,IAAI,CAAC5B,WAAW,UACrBU,aACAQ;IAGF,eAAe;IACf,MAAM3B,YAAYiB;IAElB,wBAAwB;IACxBqB,QAAQC,GAAG,CAAC,CAAC;;;YAGH,EAAEpB,YAAY;UAChB,EAAED,QAAQO,KAAK,CAAC;cACZ,EAAEP,QAAQI,SAAS,CAACe,IAAI,CAAC,MAAM;;;QAGrC,EAAElB,YAAY;;gBAEN,EAAED,QAAQsB,mBAAmB,GAAG,sBAAsB,GAAG;;;;AAIzE,CAAC;IAEC,uDAAuD;IACvD,IAAItB,QAAQsB,mBAAmB,EAAE;QAC/B,OAAOtC,oBAAoBe;IAC7B;IAEA,OAAO,KAAO;AAChB;AAEA,eAAeD,cAAc"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"$id": "CreateAdkAgent",
|
|
4
|
+
"title": "Create ADK Agent",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The name of the agent project",
|
|
10
|
+
"$default": {
|
|
11
|
+
"$source": "argv",
|
|
12
|
+
"index": 0
|
|
13
|
+
},
|
|
14
|
+
"x-prompt": "What is the name of your agent project?"
|
|
15
|
+
},
|
|
16
|
+
"directory": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Directory where the project will be created",
|
|
19
|
+
"default": ""
|
|
20
|
+
},
|
|
21
|
+
"description": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "Project description",
|
|
24
|
+
"default": "My ADK Agent"
|
|
25
|
+
},
|
|
26
|
+
"templates": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"description": "Agent templates to include",
|
|
29
|
+
"items": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"enum": [
|
|
32
|
+
"basic",
|
|
33
|
+
"multi-tool",
|
|
34
|
+
"team",
|
|
35
|
+
"streaming",
|
|
36
|
+
"workflow"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
"default": [
|
|
40
|
+
"multi-tool"
|
|
41
|
+
],
|
|
42
|
+
"x-prompt": {
|
|
43
|
+
"message": "Select agent templates to include:",
|
|
44
|
+
"type": "list",
|
|
45
|
+
"multiselect": true,
|
|
46
|
+
"items": [
|
|
47
|
+
{
|
|
48
|
+
"value": "basic",
|
|
49
|
+
"label": "Basic Agent (getCurrentTime - from docs quickstart)"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"value": "multi-tool",
|
|
53
|
+
"label": "Multi-tool Agent (weather + time - from docs quickstart)"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"value": "team",
|
|
57
|
+
"label": "Agent Team (greeting + farewell + weather delegation)"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"value": "streaming",
|
|
61
|
+
"label": "Streaming Agent (Live API voice/text)"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"value": "workflow",
|
|
65
|
+
"label": "Workflow Agent (Sequential/Loop/Parallel)"
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"modelProvider": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"description": "LLM model provider",
|
|
73
|
+
"enum": [
|
|
74
|
+
"gemini",
|
|
75
|
+
"openai",
|
|
76
|
+
"anthropic",
|
|
77
|
+
"custom"
|
|
78
|
+
],
|
|
79
|
+
"default": "gemini",
|
|
80
|
+
"x-prompt": {
|
|
81
|
+
"message": "Select your preferred model provider:",
|
|
82
|
+
"type": "list",
|
|
83
|
+
"items": [
|
|
84
|
+
{
|
|
85
|
+
"value": "gemini",
|
|
86
|
+
"label": "Google Gemini (Google AI Studio or Vertex AI)"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"value": "openai",
|
|
90
|
+
"label": "OpenAI (GPT models via LiteLLM)"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"value": "anthropic",
|
|
94
|
+
"label": "Anthropic (Claude models via LiteLLM)"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"value": "custom",
|
|
98
|
+
"label": "Other/Custom (Manual configuration)"
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"model": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"description": "Specific model to use",
|
|
106
|
+
"default": "gemini-3.0-flash"
|
|
107
|
+
},
|
|
108
|
+
"installDependencies": {
|
|
109
|
+
"type": "boolean",
|
|
110
|
+
"description": "Install dependencies after generation",
|
|
111
|
+
"default": true,
|
|
112
|
+
"x-prompt": "Install dependencies now?"
|
|
113
|
+
},
|
|
114
|
+
"initGit": {
|
|
115
|
+
"type": "boolean",
|
|
116
|
+
"description": "Initialize git repository",
|
|
117
|
+
"default": true,
|
|
118
|
+
"x-prompt": "Initialize git repository?"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"required": [
|
|
122
|
+
"name"
|
|
123
|
+
]
|
|
124
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-adk-agent",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Nx generator for scaffolding ADK (Agent Development Kit) TypeScript projects with multiple templates, multi-model support, and modern tooling",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adk",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
],
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
|
-
"url": "https://github.com/
|
|
21
|
+
"url": "https://github.com/garatropic/adk-ts-new"
|
|
22
22
|
},
|
|
23
23
|
"author": "Maina Wycliffe",
|
|
24
24
|
"license": "MIT",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"dist",
|
|
49
49
|
"bin",
|
|
50
50
|
"generators.json",
|
|
51
|
+
"templates",
|
|
51
52
|
"src/generators/**/files/**",
|
|
52
53
|
"src/generators/**/schema.json",
|
|
53
54
|
"!**/*.tsbuildinfo"
|
|
@@ -65,13 +66,28 @@
|
|
|
65
66
|
"main": "packages/create-adk-agent/src/index.ts",
|
|
66
67
|
"tsConfig": "packages/create-adk-agent/tsconfig.lib.json",
|
|
67
68
|
"skipTypeCheck": true,
|
|
68
|
-
"stripLeadingPaths": true
|
|
69
|
+
"stripLeadingPaths": true,
|
|
70
|
+
"assets": [
|
|
71
|
+
{
|
|
72
|
+
"input": "packages/create-adk-agent/src/generators/init/files",
|
|
73
|
+
"glob": "**/*",
|
|
74
|
+
"output": "generators/init/files"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"input": "packages/create-adk-agent/src/generators/init",
|
|
78
|
+
"glob": "schema.json",
|
|
79
|
+
"output": "generators/init"
|
|
80
|
+
}
|
|
81
|
+
]
|
|
69
82
|
}
|
|
70
83
|
}
|
|
71
84
|
}
|
|
72
85
|
},
|
|
73
86
|
"dependencies": {
|
|
74
87
|
"@nx/devkit": "^22.3.3",
|
|
75
|
-
"@swc/helpers": "~0.5.11"
|
|
88
|
+
"@swc/helpers": "~0.5.11",
|
|
89
|
+
"kolorist": "^1.8.0",
|
|
90
|
+
"minimist": "^1.2.8",
|
|
91
|
+
"prompts": "^2.4.2"
|
|
76
92
|
}
|
|
77
93
|
}
|
|
@@ -60,16 +60,17 @@ npm install
|
|
|
60
60
|
|
|
61
61
|
### Run in Development Mode
|
|
62
62
|
|
|
63
|
-
Using **
|
|
63
|
+
Using **Vite** for fast TypeScript execution with hot reload:
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
66
|
npm run dev
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
This will:
|
|
70
|
-
- ✅ Start your agent immediately
|
|
70
|
+
- ✅ Start your agent immediately with Vite's fast HMR
|
|
71
71
|
- ✅ Watch for file changes and auto-reload
|
|
72
72
|
- ✅ Show compilation errors instantly
|
|
73
|
+
- ✅ Optimized build performance
|
|
73
74
|
|
|
74
75
|
### Run with ADK DevTools
|
|
75
76
|
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"dev": "
|
|
9
|
-
"dev:agent": "
|
|
10
|
-
"start": "
|
|
11
|
-
"build": "
|
|
8
|
+
"dev": "vite-node --watch src/index.ts",
|
|
9
|
+
"dev:agent": "vite-node --watch src/agents/multi-tool/agent.ts",
|
|
10
|
+
"start": "vite-node src/index.ts",
|
|
11
|
+
"build": "vite build",
|
|
12
12
|
"prod": "node dist/index.js",
|
|
13
13
|
"test": "jest",
|
|
14
14
|
"test:watch": "jest --watch",
|
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
"jest": "^29.7.0",
|
|
34
34
|
"prettier": "^3.2.0",
|
|
35
35
|
"ts-jest": "^29.1.0",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
36
|
+
"typescript": "^5.9.3",
|
|
37
|
+
"vite": "^6.0.0",
|
|
38
|
+
"vite-node": "^2.1.0",
|
|
39
|
+
"vite-plugin-node": "^3.1.0"
|
|
38
40
|
}
|
|
39
41
|
}
|
|
@@ -1,34 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FunctionTool, LlmAgent } from '@google/adk';<% if (modelProvider === 'openai' || modelProvider === 'anthropic') { %>
|
|
2
2
|
import { LiteLlm } from '@google/adk';<% } %>
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/* Mock tool implementation */
|
|
6
6
|
const getCurrentTime = new FunctionTool({
|
|
7
7
|
name: 'get_current_time',
|
|
8
|
-
description: 'Returns the current time in
|
|
8
|
+
description: 'Returns the current time in a specified city.',
|
|
9
9
|
parameters: z.object({
|
|
10
|
-
|
|
11
|
-
.string()
|
|
12
|
-
.optional()
|
|
13
|
-
.describe('The timezone to use (e.g., "America/New_York", "Europe/London")'),
|
|
10
|
+
city: z.string().describe('The name of the city for which to retrieve the current time.'),
|
|
14
11
|
}),
|
|
15
|
-
execute: ({
|
|
16
|
-
|
|
17
|
-
const timeString = now.toLocaleString('en-US', { timeZone: timezone });
|
|
18
|
-
return {
|
|
19
|
-
status: 'success',
|
|
20
|
-
report: `The current time in ${timezone} is ${timeString}`,
|
|
21
|
-
};
|
|
12
|
+
execute: ({ city }) => {
|
|
13
|
+
return { status: 'success', report: `The current time in ${city} is 10:30 AM` };
|
|
22
14
|
},
|
|
23
15
|
});
|
|
24
16
|
|
|
25
|
-
// Create the agent
|
|
26
17
|
export const rootAgent = new LlmAgent({
|
|
27
18
|
name: 'hello_time_agent',
|
|
28
19
|
<% if (modelProvider === 'gemini') { %>model: '<%= model %>',<% } else if (modelProvider === 'openai' || modelProvider === 'anthropic') { %>model: new LiteLlm({ model: '<%= model %>' }),<% } else { %>model: '<%= model %>',<% } %>
|
|
29
|
-
description: '
|
|
30
|
-
instruction: `You are a
|
|
31
|
-
|
|
32
|
-
If no timezone is specified, use UTC as the default.`,
|
|
20
|
+
description: 'Tells the current time in a specified city.',
|
|
21
|
+
instruction: `You are a helpful assistant that tells the current time in a city.
|
|
22
|
+
Use the 'getCurrentTime' tool for this purpose.`,
|
|
33
23
|
tools: [getCurrentTime],
|
|
34
24
|
});
|
|
@@ -1,83 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FunctionTool, LlmAgent } from '@google/adk';<% if (modelProvider === 'openai' || modelProvider === 'anthropic') { %>
|
|
2
2
|
import { LiteLlm } from '@google/adk';<% } %>
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/* Mock tool implementations */
|
|
6
6
|
const getCurrentTime = new FunctionTool({
|
|
7
7
|
name: 'get_current_time',
|
|
8
|
-
description: 'Returns the current time in
|
|
8
|
+
description: 'Returns the current time in a specified city.',
|
|
9
9
|
parameters: z.object({
|
|
10
|
-
|
|
11
|
-
.string()
|
|
12
|
-
.optional()
|
|
13
|
-
.describe('The timezone to use (e.g., "America/New_York", "Europe/London")'),
|
|
10
|
+
city: z.string().describe('The name of the city for which to retrieve the current time.'),
|
|
14
11
|
}),
|
|
15
|
-
execute: ({
|
|
16
|
-
|
|
17
|
-
const timeString = now.toLocaleString('en-US', { timeZone: timezone });
|
|
18
|
-
return {
|
|
19
|
-
status: 'success',
|
|
20
|
-
report: `The current time in ${timezone} is ${timeString}`,
|
|
21
|
-
};
|
|
12
|
+
execute: ({ city }) => {
|
|
13
|
+
return { status: 'success', report: `The current time in ${city} is 10:30 AM` };
|
|
22
14
|
},
|
|
23
15
|
});
|
|
24
16
|
|
|
25
|
-
// Tool to get weather (mock data for demo)
|
|
26
17
|
const getWeather = new FunctionTool({
|
|
27
18
|
name: 'get_weather',
|
|
28
|
-
description: 'Returns the current weather for a
|
|
19
|
+
description: 'Returns the current weather for a specified city.',
|
|
29
20
|
parameters: z.object({
|
|
30
|
-
|
|
21
|
+
city: z.string().describe('The name of the city for which to retrieve the weather.'),
|
|
31
22
|
}),
|
|
32
|
-
execute: ({
|
|
33
|
-
|
|
34
|
-
const conditions = ['sunny', 'cloudy', 'rainy', 'partly cloudy'];
|
|
35
|
-
const condition = conditions[Math.floor(Math.random() * conditions.length)];
|
|
36
|
-
const temp = Math.floor(Math.random() * 30) + 50; // 50-80°F
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
status: 'success',
|
|
40
|
-
report: `The weather in ${location} is ${condition} with a temperature of ${temp}°F`,
|
|
41
|
-
};
|
|
23
|
+
execute: ({ city }) => {
|
|
24
|
+
return { status: 'success', report: `The weather in ${city} is sunny and 72°F` };
|
|
42
25
|
},
|
|
43
26
|
});
|
|
44
27
|
|
|
45
|
-
// Tool for calculations
|
|
46
|
-
const calculate = new FunctionTool({
|
|
47
|
-
name: 'calculate',
|
|
48
|
-
description: 'Performs basic mathematical calculations.',
|
|
49
|
-
parameters: z.object({
|
|
50
|
-
expression: z
|
|
51
|
-
.string()
|
|
52
|
-
.describe('The mathematical expression to evaluate (e.g., "2 + 2", "10 * 5")'),
|
|
53
|
-
}),
|
|
54
|
-
execute: ({ expression }) => {
|
|
55
|
-
try {
|
|
56
|
-
// Simple eval for demo - in production, use a safe math parser
|
|
57
|
-
const result = eval(expression);
|
|
58
|
-
return {
|
|
59
|
-
status: 'success',
|
|
60
|
-
report: `${expression} = ${result}`,
|
|
61
|
-
};
|
|
62
|
-
} catch (error) {
|
|
63
|
-
return {
|
|
64
|
-
status: 'error',
|
|
65
|
-
report: `Error evaluating expression: ${error}`,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Create the agent with multiple tools
|
|
72
28
|
export const rootAgent = new LlmAgent({
|
|
73
29
|
name: 'multi_tool_agent',
|
|
74
30
|
<% if (modelProvider === 'gemini') { %>model: '<%= model %>',<% } else if (modelProvider === 'openai' || modelProvider === 'anthropic') { %>model: new LiteLlm({ model: '<%= model %>' }),<% } else { %>model: '<%= model %>',<% } %>
|
|
75
|
-
description: '
|
|
76
|
-
instruction: `You are a helpful assistant
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
Use the appropriate tool based on the user's request. Be friendly and helpful.`,
|
|
82
|
-
tools: [getCurrentTime, getWeather, calculate],
|
|
31
|
+
description: 'Provides current time and weather information for cities.',
|
|
32
|
+
instruction: `You are a helpful assistant that provides time and weather information.
|
|
33
|
+
Use the 'getCurrentTime' tool to get the time in a city.
|
|
34
|
+
Use the 'getWeather' tool to get weather information for a city.`,
|
|
35
|
+
tools: [getCurrentTime, getWeather],
|
|
83
36
|
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import { VitePluginNode } from 'vite-plugin-node';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
plugins: [
|
|
6
|
+
...VitePluginNode({
|
|
7
|
+
adapter: 'node',
|
|
8
|
+
appPath: './src/index.ts',
|
|
9
|
+
exportName: 'rootAgent',
|
|
10
|
+
tsCompiler: 'esbuild',
|
|
11
|
+
}),
|
|
12
|
+
],
|
|
13
|
+
build: {
|
|
14
|
+
outDir: 'dist',
|
|
15
|
+
lib: {
|
|
16
|
+
entry: './src/index.ts',
|
|
17
|
+
formats: ['es'],
|
|
18
|
+
fileName: 'index',
|
|
19
|
+
},
|
|
20
|
+
rollupOptions: {
|
|
21
|
+
external: [
|
|
22
|
+
'@google/adk',
|
|
23
|
+
'@google/adk-devtools',
|
|
24
|
+
'dotenv',
|
|
25
|
+
'zod',
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
target: 'node20',
|
|
29
|
+
minify: false,
|
|
30
|
+
},
|
|
31
|
+
resolve: {
|
|
32
|
+
alias: {
|
|
33
|
+
'@': './src',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|