@inkeep/create-agents 0.2.1 → 0.2.2

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.
@@ -1,8 +1,8 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
1
+ import * as p from '@clack/prompts';
2
2
  import fs from 'fs-extra';
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
+ import { cloneTemplate, getAvailableTemplates } from '../templates';
3
5
  import { createAgents } from '../utils';
4
- import { getAvailableTemplates, cloneTemplate } from '../templates';
5
- import * as p from '@clack/prompts';
6
6
  // Mock all dependencies
7
7
  vi.mock('fs-extra');
8
8
  vi.mock('../templates');
@@ -48,7 +48,11 @@ describe('createAgents - Template and Project ID Logic', () => {
48
48
  vi.mocked(fs.mkdir).mockResolvedValue(undefined);
49
49
  vi.mocked(fs.remove).mockResolvedValue(undefined);
50
50
  // Mock templates
51
- vi.mocked(getAvailableTemplates).mockResolvedValue(['weather-graph', 'chatbot', 'data-analysis']);
51
+ vi.mocked(getAvailableTemplates).mockResolvedValue([
52
+ 'weather-graph',
53
+ 'chatbot',
54
+ 'data-analysis',
55
+ ]);
52
56
  vi.mocked(cloneTemplate).mockResolvedValue(undefined);
53
57
  // Mock util.promisify to return a mock exec function
54
58
  const mockExecAsync = vi.fn().mockResolvedValue({ stdout: '', stderr: '' });
@@ -72,7 +76,7 @@ describe('createAgents - Template and Project ID Logic', () => {
72
76
  await createAgents({
73
77
  dirName: 'test-dir',
74
78
  openAiKey: 'test-openai-key',
75
- anthropicKey: 'test-anthropic-key'
79
+ anthropicKey: 'test-anthropic-key',
76
80
  });
77
81
  // Should clone base template and weather-graph template
78
82
  expect(cloneTemplate).toHaveBeenCalledTimes(2);
@@ -85,10 +89,8 @@ describe('createAgents - Template and Project ID Logic', () => {
85
89
  await createAgents({
86
90
  dirName: 'test-dir',
87
91
  openAiKey: 'test-openai-key',
88
- anthropicKey: 'test-anthropic-key'
92
+ anthropicKey: 'test-anthropic-key',
89
93
  });
90
- // Check that .env file is created with correct project ID path
91
- expect(fs.writeFile).toHaveBeenCalledWith('src/weather-graph/.env', expect.any(String));
92
94
  // Check that inkeep.config.ts is created with correct project ID
93
95
  expect(fs.writeFile).toHaveBeenCalledWith('src/weather-graph/inkeep.config.ts', expect.stringContaining('projectId: "weather-graph"'));
94
96
  });
@@ -99,7 +101,7 @@ describe('createAgents - Template and Project ID Logic', () => {
99
101
  dirName: 'test-dir',
100
102
  template: 'chatbot',
101
103
  openAiKey: 'test-openai-key',
102
- anthropicKey: 'test-anthropic-key'
104
+ anthropicKey: 'test-anthropic-key',
103
105
  });
104
106
  // Should validate template exists
105
107
  expect(getAvailableTemplates).toHaveBeenCalled();
@@ -107,8 +109,6 @@ describe('createAgents - Template and Project ID Logic', () => {
107
109
  expect(cloneTemplate).toHaveBeenCalledTimes(2);
108
110
  expect(cloneTemplate).toHaveBeenCalledWith('https://github.com/inkeep/create-agents-template', expect.any(String));
109
111
  expect(cloneTemplate).toHaveBeenCalledWith('https://github.com/inkeep/agents-cookbook/templates/chatbot', 'src/chatbot');
110
- // Should create config files with template name as project ID
111
- expect(fs.writeFile).toHaveBeenCalledWith('src/chatbot/.env', expect.any(String));
112
112
  expect(fs.writeFile).toHaveBeenCalledWith('src/chatbot/inkeep.config.ts', expect.stringContaining('projectId: "chatbot"'));
113
113
  });
114
114
  it('should exit with error when template does not exist', async () => {
@@ -116,17 +116,21 @@ describe('createAgents - Template and Project ID Logic', () => {
116
116
  await expect(createAgents({
117
117
  dirName: 'test-dir',
118
118
  template: 'non-existent-template',
119
- openAiKey: 'test-openai-key'
119
+ openAiKey: 'test-openai-key',
120
120
  })).rejects.toThrow('process.exit called');
121
121
  expect(p.cancel).toHaveBeenCalledWith(expect.stringContaining('Template "non-existent-template" not found'));
122
122
  expect(processExitSpy).toHaveBeenCalledWith(0);
123
123
  });
124
124
  it('should show available templates when invalid template is provided', async () => {
125
- vi.mocked(getAvailableTemplates).mockResolvedValue(['weather-graph', 'chatbot', 'data-analysis']);
125
+ vi.mocked(getAvailableTemplates).mockResolvedValue([
126
+ 'weather-graph',
127
+ 'chatbot',
128
+ 'data-analysis',
129
+ ]);
126
130
  await expect(createAgents({
127
131
  dirName: 'test-dir',
128
132
  template: 'invalid',
129
- openAiKey: 'test-openai-key'
133
+ openAiKey: 'test-openai-key',
130
134
  })).rejects.toThrow('process.exit called');
131
135
  const cancelCall = vi.mocked(p.cancel).mock.calls[0][0];
132
136
  expect(cancelCall).toContain('weather-graph');
@@ -140,7 +144,7 @@ describe('createAgents - Template and Project ID Logic', () => {
140
144
  dirName: 'test-dir',
141
145
  customProjectId: 'my-custom-project',
142
146
  openAiKey: 'test-openai-key',
143
- anthropicKey: 'test-anthropic-key'
147
+ anthropicKey: 'test-anthropic-key',
144
148
  });
145
149
  // Should clone base template but NOT project template
146
150
  expect(cloneTemplate).toHaveBeenCalledTimes(1);
@@ -149,8 +153,6 @@ describe('createAgents - Template and Project ID Logic', () => {
149
153
  expect(getAvailableTemplates).not.toHaveBeenCalled();
150
154
  // Should create empty project directory
151
155
  expect(fs.ensureDir).toHaveBeenCalledWith('src/my-custom-project');
152
- // Should create config files with custom project ID
153
- expect(fs.writeFile).toHaveBeenCalledWith('src/my-custom-project/.env', expect.any(String));
154
156
  expect(fs.writeFile).toHaveBeenCalledWith('src/my-custom-project/inkeep.config.ts', expect.stringContaining('projectId: "my-custom-project"'));
155
157
  });
156
158
  it('should prioritize custom project ID over template if both are provided', async () => {
@@ -159,7 +161,7 @@ describe('createAgents - Template and Project ID Logic', () => {
159
161
  template: 'chatbot',
160
162
  customProjectId: 'my-custom-project',
161
163
  openAiKey: 'test-openai-key',
162
- anthropicKey: 'test-anthropic-key'
164
+ anthropicKey: 'test-anthropic-key',
163
165
  });
164
166
  // Should only clone base template, not project template
165
167
  expect(cloneTemplate).toHaveBeenCalledTimes(1);
@@ -172,12 +174,15 @@ describe('createAgents - Template and Project ID Logic', () => {
172
174
  });
173
175
  describe('Edge cases and validation', () => {
174
176
  it('should handle template names with hyphens correctly', async () => {
175
- vi.mocked(getAvailableTemplates).mockResolvedValue(['my-complex-template', 'another-template']);
177
+ vi.mocked(getAvailableTemplates).mockResolvedValue([
178
+ 'my-complex-template',
179
+ 'another-template',
180
+ ]);
176
181
  await createAgents({
177
182
  dirName: 'test-dir',
178
183
  template: 'my-complex-template',
179
184
  openAiKey: 'test-key',
180
- anthropicKey: 'test-key'
185
+ anthropicKey: 'test-key',
181
186
  });
182
187
  expect(cloneTemplate).toHaveBeenCalledTimes(2);
183
188
  expect(cloneTemplate).toHaveBeenCalledWith('https://github.com/inkeep/agents-cookbook/templates/my-complex-template', 'src/my-complex-template');
@@ -187,7 +192,7 @@ describe('createAgents - Template and Project ID Logic', () => {
187
192
  dirName: 'test-dir',
188
193
  customProjectId: 'my_project-123',
189
194
  openAiKey: 'test-key',
190
- anthropicKey: 'test-key'
195
+ anthropicKey: 'test-key',
191
196
  });
192
197
  expect(fs.ensureDir).toHaveBeenCalledWith('src/my_project-123');
193
198
  expect(fs.writeFile).toHaveBeenCalledWith('src/my_project-123/inkeep.config.ts', expect.stringContaining('projectId: "my_project-123"'));
@@ -197,7 +202,7 @@ describe('createAgents - Template and Project ID Logic', () => {
197
202
  await createAgents({
198
203
  dirName: 'dir1',
199
204
  openAiKey: 'key',
200
- anthropicKey: 'key'
205
+ anthropicKey: 'key',
201
206
  });
202
207
  expect(fs.ensureDir).toHaveBeenCalledWith('src');
203
208
  // Reset mocks
@@ -208,7 +213,7 @@ describe('createAgents - Template and Project ID Logic', () => {
208
213
  dirName: 'dir2',
209
214
  template: 'chatbot',
210
215
  openAiKey: 'key',
211
- anthropicKey: 'key'
216
+ anthropicKey: 'key',
212
217
  });
213
218
  expect(fs.ensureDir).toHaveBeenCalledWith('src');
214
219
  // Reset mocks
@@ -219,7 +224,7 @@ describe('createAgents - Template and Project ID Logic', () => {
219
224
  dirName: 'dir3',
220
225
  customProjectId: 'custom',
221
226
  openAiKey: 'key',
222
- anthropicKey: 'key'
227
+ anthropicKey: 'key',
223
228
  });
224
229
  expect(fs.ensureDir).toHaveBeenCalledWith('src');
225
230
  expect(fs.ensureDir).toHaveBeenCalledWith('src/custom');
package/dist/utils.js CHANGED
@@ -95,9 +95,9 @@ export const createAgents = async (args = {}) => {
95
95
  const providerChoice = await p.select({
96
96
  message: 'Which AI provider(s) would you like to use?',
97
97
  options: [
98
- { value: 'anthropic', label: 'Anthropic only' },
99
- { value: 'openai', label: 'OpenAI only' },
100
- { value: 'google', label: 'Google only' },
98
+ { value: 'anthropic', label: 'Anthropic' },
99
+ { value: 'openai', label: 'OpenAI' },
100
+ { value: 'google', label: 'Google' },
101
101
  ],
102
102
  });
103
103
  if (p.isCancel(providerChoice)) {
@@ -199,6 +199,7 @@ export const createAgents = async (args = {}) => {
199
199
  projectId,
200
200
  openAiKey,
201
201
  anthropicKey,
202
+ googleKey,
202
203
  manageApiPort: manageApiPort || '3002',
203
204
  runApiPort: runApiPort || '3003',
204
205
  modelSettings: defaultModelSettings,
@@ -223,9 +224,6 @@ export const createAgents = async (args = {}) => {
223
224
  // create or overwrite inkeep.config.ts
224
225
  s.message('Creating inkeep.config.ts...');
225
226
  await createInkeepConfig(config);
226
- // Create service files
227
- s.message('Creating service files...');
228
- await createServiceFiles(config);
229
227
  // Install dependencies
230
228
  s.message('Installing dependencies (this may take a while)...');
231
229
  await installDependencies();
@@ -272,51 +270,27 @@ async function createEnvironmentFiles(config) {
272
270
  ENVIRONMENT=development
273
271
 
274
272
  # Database
275
- DB_FILE_NAME=file:./local.db
273
+ DB_FILE_NAME=file:${process.cwd()}/local.db
276
274
 
277
275
  # AI Provider Keys
278
276
  ANTHROPIC_API_KEY=${config.anthropicKey || 'your-anthropic-key-here'}
279
277
  OPENAI_API_KEY=${config.openAiKey || 'your-openai-key-here'}
280
278
  GOOGLE_GENERATIVE_AI_API_KEY=${config.googleKey || 'your-google-key-here'}
281
- `;
282
- await fs.writeFile('.env', envContent);
283
- // Create .env.example
284
- const envExample = envContent.replace(/=.+$/gm, '=');
285
- await fs.writeFile('.env.example', envExample);
286
- // Create .env files for each API service
287
- const runApiEnvContent = `# Environment
288
- ENVIRONMENT=development
289
-
290
- # Database (relative path from API directory)
291
- DB_FILE_NAME=file:../../local.db
292
-
293
- # AI Provider Keys
294
- ANTHROPIC_API_KEY=${config.anthropicKey || 'your-anthropic-key-here'}
295
- OPENAI_API_KEY=${config.openAiKey || 'your-openai-key-here'}
296
- GOOGLE_GENERATIVE_AI_API_KEY=${config.googleKey || 'your-google-key-here'}
297
-
298
- AGENTS_RUN_API_URL=http://localhost:${config.runApiPort}
299
- `;
300
- const manageApiEnvContent = `# Environment
301
- ENVIRONMENT=development
302
279
 
303
- # Database (relative path from API directory)
304
- DB_FILE_NAME=file:../../local.db
280
+ # Inkeep API URLs
281
+ INKEEP_AGENTS_MANAGE_API_URL="http://localhost:3002"
282
+ INKEEP_AGENTS_RUN_API_URL="http://localhost:3003"
305
283
 
306
- AGENTS_MANAGE_API_URL=http://localhost:${config.manageApiPort}
307
- `;
308
- await fs.writeFile('apps/manage-api/.env', manageApiEnvContent);
309
- await fs.writeFile('apps/run-api/.env', runApiEnvContent);
310
- }
311
- async function createServiceFiles(config) {
312
- // Create .env file for the project directory (for inkeep CLI commands)
313
- const projectEnvContent = `# Environment
314
- ENVIRONMENT=development
284
+ # SigNoz
285
+ SIGNOZ_URL=your-signoz-url-here
286
+ SIGNOZ_API_KEY=your-signoz-api-key-here
315
287
 
316
- # Database (relative path from project directory)
317
- DB_FILE_NAME=file:../../local.db
288
+ # Nango
289
+ NANGO_HOST=your-nango-host-here
290
+ NANGO_CONNECT_BASE_URL=your-nango-connect-base-url-here
291
+ NANGO_SECRET_KEY=
318
292
  `;
319
- await fs.writeFile(`src/${config.projectId}/.env`, projectEnvContent);
293
+ await fs.writeFile('.env', envContent);
320
294
  }
321
295
  async function createInkeepConfig(config) {
322
296
  const inkeepConfig = `import { defineConfig } from '@inkeep/agents-cli/config';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/create-agents",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Create an Inkeep Agent Framework project",
5
5
  "type": "module",
6
6
  "bin": {