@inkeep/create-agents 0.50.0 → 0.50.3
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/dist/__tests__/e2e/quickstart.test.js +159 -7
- package/dist/__tests__/e2e/utils.d.ts +2 -0
- package/dist/__tests__/e2e/utils.js +36 -0
- package/dist/__tests__/utils.test.js +54 -1
- package/dist/index.js +2 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +16 -3
- package/package.json +3 -2
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { execa } from 'execa';
|
|
3
|
+
import { chromium } from 'playwright';
|
|
3
4
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
4
|
-
import { cleanupDir, createTempDir, linkLocalPackages, runCommand, runCreateAgentsCLI, verifyDirectoryStructure, verifyFile, waitForServerReady, } from './utils';
|
|
5
|
+
import { cleanupDir, createTempDir, linkLocalPackages, runCommand, runCreateAgentsCLI, startDashboardServer, verifyDirectoryStructure, verifyFile, waitForServerReady, } from './utils';
|
|
5
6
|
// Use 127.0.0.1 instead of localhost to avoid IPv6/IPv4 resolution issues on CI (Ubuntu)
|
|
6
7
|
const manageApiUrl = 'http://127.0.0.1:3002';
|
|
8
|
+
// Dashboard must use localhost (not 127.0.0.1) so auth cookies share the same domain
|
|
9
|
+
// between the dashboard (localhost:3000) and the API (localhost:3002).
|
|
10
|
+
const dashboardApiUrl = 'http://localhost:3002';
|
|
7
11
|
// Use a test bypass secret for authentication in CI
|
|
8
12
|
// This bypasses the need for a real login/API key
|
|
9
13
|
const TEST_BYPASS_SECRET = 'e2e-test-bypass-secret-for-ci-testing-only';
|
|
@@ -29,16 +33,15 @@ describe('create-agents quickstart e2e', () => {
|
|
|
29
33
|
console.log(`Working directory: ${testDir}`);
|
|
30
34
|
const result = await runCreateAgentsCLI([
|
|
31
35
|
workspaceName,
|
|
32
|
-
'--
|
|
33
|
-
'
|
|
34
|
-
'--disable-git', // Skip git init for faster tests
|
|
36
|
+
'--skip-provider',
|
|
37
|
+
'--disable-git',
|
|
35
38
|
'--local-agents-prefix',
|
|
36
39
|
createAgentsPrefix,
|
|
37
40
|
'--local-templates-prefix',
|
|
38
41
|
projectTemplatesPrefix,
|
|
39
42
|
'--skip-inkeep-cli',
|
|
40
43
|
'--skip-inkeep-mcp',
|
|
41
|
-
'--skip-install',
|
|
44
|
+
'--skip-install',
|
|
42
45
|
], testDir);
|
|
43
46
|
// Verify the CLI completed successfully
|
|
44
47
|
expect(result.exitCode, `CLI failed with exit code ${result.exitCode}\nstdout: ${result.stdout}\nstderr: ${result.stderr}`).toBe(0);
|
|
@@ -62,11 +65,10 @@ describe('create-agents quickstart e2e', () => {
|
|
|
62
65
|
console.log('Verifying .env file...');
|
|
63
66
|
await verifyFile(path.join(projectDir, '.env'), [
|
|
64
67
|
/ENVIRONMENT=development/,
|
|
65
|
-
/OPENAI_API_KEY=test-openai-key/,
|
|
66
68
|
/INKEEP_AGENTS_MANAGE_DATABASE_URL=postgresql:\/\/appuser:password@localhost:5432\/inkeep_agents/,
|
|
67
69
|
/INKEEP_AGENTS_RUN_DATABASE_URL=postgresql:\/\/appuser:password@localhost:5433\/inkeep_agents/,
|
|
68
70
|
/INKEEP_AGENTS_API_URL="http:\/\/127\.0\.0\.1:3002"/,
|
|
69
|
-
/INKEEP_AGENTS_JWT_SIGNING_SECRET=\w+/,
|
|
71
|
+
/INKEEP_AGENTS_JWT_SIGNING_SECRET=\w+/,
|
|
70
72
|
]);
|
|
71
73
|
console.log('.env file verified');
|
|
72
74
|
// Verify inkeep.config.ts was created
|
|
@@ -92,6 +94,31 @@ describe('create-agents quickstart e2e', () => {
|
|
|
92
94
|
},
|
|
93
95
|
stream: true,
|
|
94
96
|
});
|
|
97
|
+
// Run auth init separately to create the "default" organization and admin user.
|
|
98
|
+
// setup-dev:cloud may exit early if its internal migrations fail (e.g. when CI
|
|
99
|
+
// already applied migrations from the monorepo root), skipping auth init entirely.
|
|
100
|
+
console.log('Running auth init to ensure default organization exists');
|
|
101
|
+
const authInitResult = await runCommand({
|
|
102
|
+
command: 'node',
|
|
103
|
+
args: ['node_modules/@inkeep/agents-core/dist/auth/init.js'],
|
|
104
|
+
cwd: projectDir,
|
|
105
|
+
timeout: 120000, // 2 min: SpiceDB schema write retries up to 30x at 1s each
|
|
106
|
+
env: {
|
|
107
|
+
INKEEP_AGENTS_MANAGE_UI_USERNAME: 'admin@example.com',
|
|
108
|
+
INKEEP_AGENTS_MANAGE_UI_PASSWORD: 'adminADMIN!@12',
|
|
109
|
+
BETTER_AUTH_SECRET: 'test-secret-key-for-ci',
|
|
110
|
+
SPICEDB_PRESHARED_KEY: 'dev-secret-key',
|
|
111
|
+
// Explicit DB URLs in case process.env doesn't carry them
|
|
112
|
+
INKEEP_AGENTS_RUN_DATABASE_URL: process.env.INKEEP_AGENTS_RUN_DATABASE_URL ||
|
|
113
|
+
'postgresql://appuser:password@localhost:5433/inkeep_agents',
|
|
114
|
+
INKEEP_AGENTS_MANAGE_DATABASE_URL: process.env.INKEEP_AGENTS_MANAGE_DATABASE_URL ||
|
|
115
|
+
'postgresql://appuser:password@localhost:5432/inkeep_agents',
|
|
116
|
+
},
|
|
117
|
+
stream: true,
|
|
118
|
+
});
|
|
119
|
+
if (authInitResult.exitCode !== 0) {
|
|
120
|
+
console.warn(`Auth init exited with code ${authInitResult.exitCode}\nstdout: ${authInitResult.stdout}\nstderr: ${authInitResult.stderr}`);
|
|
121
|
+
}
|
|
95
122
|
console.log('Project setup in database');
|
|
96
123
|
console.log('Starting dev servers');
|
|
97
124
|
// Start dev servers in background with output monitoring
|
|
@@ -132,6 +159,27 @@ describe('create-agents quickstart e2e', () => {
|
|
|
132
159
|
// Wait for servers to be ready with retries
|
|
133
160
|
await waitForServerReady(`${manageApiUrl}/health`, 120000); // Increased to 2 minutes for CI
|
|
134
161
|
console.log('Manage API is ready');
|
|
162
|
+
// Ensure admin user exists for dashboard login.
|
|
163
|
+
// Auth init may fail in CI (SpiceDB schema write, module resolution), so
|
|
164
|
+
// create the user directly via the API's Better Auth signup endpoint as a
|
|
165
|
+
// reliable fallback. Signup is idempotent — returns 200 if user exists.
|
|
166
|
+
console.log('Ensuring admin user exists via API signup');
|
|
167
|
+
try {
|
|
168
|
+
const signupRes = await fetch(`${manageApiUrl}/api/auth/sign-up/email`, {
|
|
169
|
+
method: 'POST',
|
|
170
|
+
headers: { 'Content-Type': 'application/json', Origin: manageApiUrl },
|
|
171
|
+
body: JSON.stringify({
|
|
172
|
+
email: 'admin@example.com',
|
|
173
|
+
password: 'adminADMIN!@12',
|
|
174
|
+
name: 'admin',
|
|
175
|
+
}),
|
|
176
|
+
});
|
|
177
|
+
const signupData = await signupRes.json().catch(() => null);
|
|
178
|
+
console.log(`Signup response: ${signupRes.status}`, signupData ? JSON.stringify(signupData).slice(0, 200) : '');
|
|
179
|
+
}
|
|
180
|
+
catch (signupError) {
|
|
181
|
+
console.warn('Signup request failed (non-fatal):', signupError);
|
|
182
|
+
}
|
|
135
183
|
console.log('Pushing project');
|
|
136
184
|
const pushResult = await runCommand({
|
|
137
185
|
command: 'pnpm',
|
|
@@ -158,6 +206,110 @@ describe('create-agents quickstart e2e', () => {
|
|
|
158
206
|
const data = await response.json();
|
|
159
207
|
expect(data.data.tenantId).toBe('default');
|
|
160
208
|
expect(data.data.id).toBe(projectId);
|
|
209
|
+
// Verify login works at the API level before starting dashboard
|
|
210
|
+
console.log('Testing login API directly');
|
|
211
|
+
try {
|
|
212
|
+
const loginTestRes = await fetch(`${manageApiUrl}/api/auth/sign-in/email`, {
|
|
213
|
+
method: 'POST',
|
|
214
|
+
headers: { 'Content-Type': 'application/json', Origin: manageApiUrl },
|
|
215
|
+
body: JSON.stringify({
|
|
216
|
+
email: 'admin@example.com',
|
|
217
|
+
password: 'adminADMIN!@12',
|
|
218
|
+
}),
|
|
219
|
+
});
|
|
220
|
+
const loginBody = await loginTestRes.text().catch(() => '');
|
|
221
|
+
console.log(`Login API test: ${loginTestRes.status} ${loginBody.slice(0, 300)}`);
|
|
222
|
+
if (!loginTestRes.ok) {
|
|
223
|
+
console.error('Login API test failed — dashboard login will likely fail');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (loginTestError) {
|
|
227
|
+
console.warn('Login API test failed (non-fatal):', loginTestError);
|
|
228
|
+
}
|
|
229
|
+
// --- Dashboard Lap ---
|
|
230
|
+
console.log('Starting dashboard lap');
|
|
231
|
+
const dashboardProcess = await startDashboardServer(projectDir, {
|
|
232
|
+
INKEEP_AGENTS_API_URL: dashboardApiUrl,
|
|
233
|
+
NEXT_PUBLIC_API_URL: dashboardApiUrl,
|
|
234
|
+
PUBLIC_INKEEP_AGENTS_API_URL: dashboardApiUrl,
|
|
235
|
+
BETTER_AUTH_SECRET: 'test-secret-key-for-ci',
|
|
236
|
+
INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET: TEST_BYPASS_SECRET,
|
|
237
|
+
});
|
|
238
|
+
console.log('Dashboard server started');
|
|
239
|
+
const browser = await chromium.launch({ headless: true });
|
|
240
|
+
try {
|
|
241
|
+
const page = await browser.newPage();
|
|
242
|
+
console.log('Navigating to login page');
|
|
243
|
+
await page.goto('http://localhost:3000/login', {
|
|
244
|
+
waitUntil: 'networkidle',
|
|
245
|
+
timeout: 15000,
|
|
246
|
+
});
|
|
247
|
+
console.log('Filling login form');
|
|
248
|
+
await page.fill('input[type="email"]', 'admin@example.com');
|
|
249
|
+
await page.fill('input[type="password"]', 'adminADMIN!@12');
|
|
250
|
+
await page.click('button[type="submit"]');
|
|
251
|
+
console.log('Waiting for redirect to projects page');
|
|
252
|
+
await page.waitForURL('**/default/projects**', {
|
|
253
|
+
timeout: 15000,
|
|
254
|
+
waitUntil: 'domcontentloaded',
|
|
255
|
+
});
|
|
256
|
+
console.log('Redirected to projects page');
|
|
257
|
+
console.log('Clicking activities-planner project');
|
|
258
|
+
// Use force:true because card uses a linkoverlay pattern that intercepts pointer events
|
|
259
|
+
await page.click(`a[href*="${projectId}"]`, { timeout: 15000, force: true });
|
|
260
|
+
await page.waitForURL(`**/default/projects/${projectId}/**`, {
|
|
261
|
+
timeout: 15000,
|
|
262
|
+
waitUntil: 'domcontentloaded',
|
|
263
|
+
});
|
|
264
|
+
console.log('Navigated to project page');
|
|
265
|
+
console.log('Clicking agent card');
|
|
266
|
+
// Use href locator to avoid matching project heading text
|
|
267
|
+
const agentId = 'activities-planner';
|
|
268
|
+
await page.click(`a[href*="/agents/${agentId}"]`, { timeout: 15000, force: true });
|
|
269
|
+
await page.waitForURL(`**/agents/${agentId}**`, {
|
|
270
|
+
timeout: 15000,
|
|
271
|
+
waitUntil: 'domcontentloaded',
|
|
272
|
+
});
|
|
273
|
+
console.log('Navigated to agent page');
|
|
274
|
+
console.log('Clicking Try it button');
|
|
275
|
+
await page.click('button:has-text("Try it")', { timeout: 15000, force: true });
|
|
276
|
+
console.log('Waiting for playground to open');
|
|
277
|
+
await page.waitForSelector('#playground-pane', { timeout: 15000 });
|
|
278
|
+
console.log('Playground panel is visible');
|
|
279
|
+
console.log('Verifying chat widget initialized');
|
|
280
|
+
await page.locator('#inkeep-widget-root').waitFor({ timeout: 15000 });
|
|
281
|
+
console.log('Chat widget is initialized');
|
|
282
|
+
console.log('Dashboard lap complete');
|
|
283
|
+
}
|
|
284
|
+
catch (dashboardError) {
|
|
285
|
+
console.error('Dashboard lap failed:', dashboardError);
|
|
286
|
+
try {
|
|
287
|
+
const activePage = browser.contexts()[0]?.pages()[0];
|
|
288
|
+
if (activePage) {
|
|
289
|
+
const screenshotPath = path.join(testDir, 'dashboard-failure.png');
|
|
290
|
+
await activePage.screenshot({ path: screenshotPath, fullPage: true });
|
|
291
|
+
console.log(`Screenshot saved to: ${screenshotPath}`);
|
|
292
|
+
console.log(`Current URL: ${activePage.url()}`);
|
|
293
|
+
console.log(`Page content: ${await activePage.content()}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
catch (screenshotError) {
|
|
297
|
+
console.error('Failed to capture screenshot:', screenshotError);
|
|
298
|
+
}
|
|
299
|
+
throw dashboardError;
|
|
300
|
+
}
|
|
301
|
+
finally {
|
|
302
|
+
await browser.close();
|
|
303
|
+
try {
|
|
304
|
+
dashboardProcess.kill('SIGTERM');
|
|
305
|
+
}
|
|
306
|
+
catch { }
|
|
307
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
308
|
+
try {
|
|
309
|
+
dashboardProcess.kill('SIGKILL');
|
|
310
|
+
}
|
|
311
|
+
catch { }
|
|
312
|
+
}
|
|
161
313
|
}
|
|
162
314
|
catch (error) {
|
|
163
315
|
console.error('Test failed with error:', error);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ChildProcess } from 'node:child_process';
|
|
1
2
|
/**
|
|
2
3
|
* Run the create-agents CLI with the given arguments
|
|
3
4
|
*/
|
|
@@ -46,3 +47,4 @@ export declare function linkLocalPackages(projectDir: string, monorepoRoot: stri
|
|
|
46
47
|
* Wait for a server to be ready by polling a health endpoint
|
|
47
48
|
*/
|
|
48
49
|
export declare function waitForServerReady(url: string, timeout: number): Promise<void>;
|
|
50
|
+
export declare function startDashboardServer(projectDir: string, env?: Record<string, string>): Promise<ChildProcess>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fork } from 'node:child_process';
|
|
1
2
|
import os from 'node:os';
|
|
2
3
|
import path, { dirname } from 'node:path';
|
|
3
4
|
import { fileURLToPath } from 'node:url';
|
|
@@ -155,6 +156,7 @@ export async function linkLocalPackages(projectDir, monorepoRoot) {
|
|
|
155
156
|
'@inkeep/agents-core': `link:${path.join(monorepoRoot, 'packages/agents-core')}`,
|
|
156
157
|
'@inkeep/agents-api': `link:${path.join(monorepoRoot, 'agents-api')}`,
|
|
157
158
|
'@inkeep/agents-cli': `link:${path.join(monorepoRoot, 'agents-cli')}`,
|
|
159
|
+
'@inkeep/agents-manage-ui': `link:${path.join(monorepoRoot, 'agents-manage-ui')}`,
|
|
158
160
|
};
|
|
159
161
|
// Replace package versions with local links
|
|
160
162
|
for (const [pkg, linkPath] of Object.entries(inkeepPackages)) {
|
|
@@ -218,3 +220,37 @@ export async function waitForServerReady(url, timeout) {
|
|
|
218
220
|
const errorDetails = lastError ? `: ${lastError.message}` : '';
|
|
219
221
|
throw new Error(`Server not ready at ${url} after ${elapsed}ms (${attempts} attempts)${errorDetails}`);
|
|
220
222
|
}
|
|
223
|
+
export async function startDashboardServer(projectDir, env = {}) {
|
|
224
|
+
const manageUiPkgJson = path.join(projectDir, 'node_modules/@inkeep/agents-manage-ui/package.json');
|
|
225
|
+
const manageUiRoot = path.dirname(manageUiPkgJson);
|
|
226
|
+
const standaloneDir = path.join(manageUiRoot, '.next/standalone/agents-manage-ui');
|
|
227
|
+
const serverEntry = path.join(standaloneDir, 'server.js');
|
|
228
|
+
if (!(await fs.pathExists(serverEntry))) {
|
|
229
|
+
throw new Error(`Dashboard standalone server not found at ${serverEntry}`);
|
|
230
|
+
}
|
|
231
|
+
const child = fork(serverEntry, [], {
|
|
232
|
+
cwd: standaloneDir,
|
|
233
|
+
env: {
|
|
234
|
+
...process.env,
|
|
235
|
+
NODE_ENV: 'production',
|
|
236
|
+
PORT: '3000',
|
|
237
|
+
HOSTNAME: '0.0.0.0',
|
|
238
|
+
...env,
|
|
239
|
+
},
|
|
240
|
+
stdio: 'pipe',
|
|
241
|
+
});
|
|
242
|
+
const outputHandler = (data) => {
|
|
243
|
+
const text = data.toString();
|
|
244
|
+
if (process.env.CI) {
|
|
245
|
+
if (text.includes('Error') || text.includes('EADDRINUSE') || text.includes('ready')) {
|
|
246
|
+
console.log('[Dashboard]:', text.trim());
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
if (child.stdout)
|
|
251
|
+
child.stdout.on('data', outputHandler);
|
|
252
|
+
if (child.stderr)
|
|
253
|
+
child.stderr.on('data', outputHandler);
|
|
254
|
+
await waitForServerReady('http://localhost:3000', 30000);
|
|
255
|
+
return child;
|
|
256
|
+
}
|
|
@@ -2,7 +2,7 @@ import * as p from '@clack/prompts';
|
|
|
2
2
|
import fs from 'fs-extra';
|
|
3
3
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
4
|
import { cloneTemplate, cloneTemplateLocal, getAvailableTemplates } from '../templates';
|
|
5
|
-
import { createAgents } from '../utils';
|
|
5
|
+
import { createAgents, defaultMockModelConfigurations } from '../utils';
|
|
6
6
|
// Create the mock execAsync function that will be used by promisify - hoisted so it's available in mocks
|
|
7
7
|
const { mockExecAsync } = vi.hoisted(() => ({
|
|
8
8
|
mockExecAsync: vi.fn().mockResolvedValue({ stdout: '', stderr: '' }),
|
|
@@ -278,6 +278,59 @@ describe('createAgents - Template and Project ID Logic', () => {
|
|
|
278
278
|
expect(fs.ensureDir).toHaveBeenCalledWith('src/projects/custom');
|
|
279
279
|
});
|
|
280
280
|
});
|
|
281
|
+
describe('Skip provider option', () => {
|
|
282
|
+
it('should use mock model configuration when skipProvider is true', async () => {
|
|
283
|
+
await createAgents({
|
|
284
|
+
dirName: 'test-dir',
|
|
285
|
+
skipProvider: true,
|
|
286
|
+
});
|
|
287
|
+
expect(cloneTemplate).toHaveBeenCalledWith(expect.stringContaining('activities-planner'), 'src/projects/activities-planner', expect.arrayContaining([
|
|
288
|
+
expect.objectContaining({
|
|
289
|
+
filePath: 'index.ts',
|
|
290
|
+
replacements: expect.objectContaining({
|
|
291
|
+
models: defaultMockModelConfigurations,
|
|
292
|
+
}),
|
|
293
|
+
}),
|
|
294
|
+
]));
|
|
295
|
+
const selectCalls = vi.mocked(p.select).mock.calls;
|
|
296
|
+
const providerSelectCalls = selectCalls.filter((call) => call[0] &&
|
|
297
|
+
typeof call[0] === 'object' &&
|
|
298
|
+
'message' in call[0] &&
|
|
299
|
+
call[0].message.includes('AI provider'));
|
|
300
|
+
expect(providerSelectCalls).toHaveLength(0);
|
|
301
|
+
expect(p.password).not.toHaveBeenCalled();
|
|
302
|
+
});
|
|
303
|
+
it('should use mock model configuration when skip is selected interactively', async () => {
|
|
304
|
+
vi.mocked(p.select).mockResolvedValueOnce('skip');
|
|
305
|
+
await createAgents({
|
|
306
|
+
dirName: 'test-dir',
|
|
307
|
+
});
|
|
308
|
+
expect(cloneTemplate).toHaveBeenCalledWith(expect.stringContaining('activities-planner'), 'src/projects/activities-planner', expect.arrayContaining([
|
|
309
|
+
expect.objectContaining({
|
|
310
|
+
filePath: 'index.ts',
|
|
311
|
+
replacements: expect.objectContaining({
|
|
312
|
+
models: defaultMockModelConfigurations,
|
|
313
|
+
}),
|
|
314
|
+
}),
|
|
315
|
+
]));
|
|
316
|
+
expect(p.password).not.toHaveBeenCalled();
|
|
317
|
+
});
|
|
318
|
+
it('should take precedence over API key flags when skipProvider is true', async () => {
|
|
319
|
+
await createAgents({
|
|
320
|
+
dirName: 'test-dir',
|
|
321
|
+
skipProvider: true,
|
|
322
|
+
openAiKey: 'test-key',
|
|
323
|
+
});
|
|
324
|
+
expect(cloneTemplate).toHaveBeenCalledWith(expect.stringContaining('activities-planner'), 'src/projects/activities-planner', expect.arrayContaining([
|
|
325
|
+
expect.objectContaining({
|
|
326
|
+
filePath: 'index.ts',
|
|
327
|
+
replacements: expect.objectContaining({
|
|
328
|
+
models: defaultMockModelConfigurations,
|
|
329
|
+
}),
|
|
330
|
+
}),
|
|
331
|
+
]));
|
|
332
|
+
});
|
|
333
|
+
});
|
|
281
334
|
describe('Security - Password input for API keys', () => {
|
|
282
335
|
it('should use password input instead of text input for API keys', async () => {
|
|
283
336
|
// Mock the select to return 'anthropic' to trigger the API key prompt
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ program
|
|
|
16
16
|
.option('--skip-inkeep-cli', 'Skip installing Inkeep CLI globally')
|
|
17
17
|
.option('--skip-inkeep-mcp', 'Skip installing Inkeep MCP server')
|
|
18
18
|
.option('--skip-install', 'Skip installing dependencies')
|
|
19
|
+
.option('--skip-provider', 'Skip AI provider setup (uses mock provider)')
|
|
19
20
|
.parse();
|
|
20
21
|
async function main() {
|
|
21
22
|
const options = program.opts();
|
|
@@ -33,6 +34,7 @@ async function main() {
|
|
|
33
34
|
skipInkeepCli: options.skipInkeepCli,
|
|
34
35
|
skipInkeepMcp: options.skipInkeepMcp,
|
|
35
36
|
skipInstall: options.skipInstall,
|
|
37
|
+
skipProvider: options.skipProvider,
|
|
36
38
|
});
|
|
37
39
|
}
|
|
38
40
|
catch (error) {
|
package/dist/utils.d.ts
CHANGED
|
@@ -31,6 +31,11 @@ export declare const defaultAnthropicModelConfigurations: {
|
|
|
31
31
|
model: "anthropic/claude-sonnet-4-5";
|
|
32
32
|
};
|
|
33
33
|
};
|
|
34
|
+
export declare const defaultMockModelConfigurations: {
|
|
35
|
+
base: {
|
|
36
|
+
model: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
34
39
|
export declare const createAgents: (args?: {
|
|
35
40
|
dirName?: string;
|
|
36
41
|
templateName?: string;
|
|
@@ -46,6 +51,7 @@ export declare const createAgents: (args?: {
|
|
|
46
51
|
skipInkeepCli?: boolean;
|
|
47
52
|
skipInkeepMcp?: boolean;
|
|
48
53
|
skipInstall?: boolean;
|
|
54
|
+
skipProvider?: boolean;
|
|
49
55
|
}) => Promise<void>;
|
|
50
56
|
export declare function createCommand(dirName?: string, options?: any): Promise<void>;
|
|
51
57
|
export declare function addInkeepMcp(): Promise<void>;
|
package/dist/utils.js
CHANGED
|
@@ -66,8 +66,11 @@ export const defaultAnthropicModelConfigurations = {
|
|
|
66
66
|
model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5,
|
|
67
67
|
},
|
|
68
68
|
};
|
|
69
|
+
export const defaultMockModelConfigurations = {
|
|
70
|
+
base: { model: 'mock/default' },
|
|
71
|
+
};
|
|
69
72
|
export const createAgents = async (args = {}) => {
|
|
70
|
-
let { dirName, openAiKey, anthropicKey, googleKey, azureKey, template, customProjectId, disableGit, localAgentsPrefix, localTemplatesPrefix, skipInkeepCli, skipInkeepMcp, skipInstall, } = args;
|
|
73
|
+
let { dirName, openAiKey, anthropicKey, googleKey, azureKey, template, customProjectId, disableGit, localAgentsPrefix, localTemplatesPrefix, skipInkeepCli, skipInkeepMcp, skipInstall, skipProvider, } = args;
|
|
71
74
|
const tenantId = 'default';
|
|
72
75
|
let projectId;
|
|
73
76
|
let templateName;
|
|
@@ -111,7 +114,7 @@ export const createAgents = async (args = {}) => {
|
|
|
111
114
|
throw new Error(validationError);
|
|
112
115
|
}
|
|
113
116
|
}
|
|
114
|
-
if (!anthropicKey && !openAiKey && !googleKey && !azureKey) {
|
|
117
|
+
if (!skipProvider && !anthropicKey && !openAiKey && !googleKey && !azureKey) {
|
|
115
118
|
const providerChoice = await p.select({
|
|
116
119
|
message: 'Which AI provider would you like to use?',
|
|
117
120
|
options: [
|
|
@@ -119,6 +122,7 @@ export const createAgents = async (args = {}) => {
|
|
|
119
122
|
{ value: 'openai', label: 'OpenAI' },
|
|
120
123
|
{ value: 'google', label: 'Google' },
|
|
121
124
|
{ value: 'azure', label: 'Azure' },
|
|
125
|
+
{ value: 'skip', label: 'Skip', hint: 'scaffolds with mock provider, no API key needed' },
|
|
122
126
|
],
|
|
123
127
|
});
|
|
124
128
|
if (p.isCancel(providerChoice)) {
|
|
@@ -189,9 +193,18 @@ export const createAgents = async (args = {}) => {
|
|
|
189
193
|
}
|
|
190
194
|
azureKey = azureKeyResponse;
|
|
191
195
|
}
|
|
196
|
+
else if (providerChoice === 'skip') {
|
|
197
|
+
skipProvider = true;
|
|
198
|
+
}
|
|
192
199
|
}
|
|
193
200
|
let defaultModelSettings = {};
|
|
194
|
-
if (
|
|
201
|
+
if (skipProvider) {
|
|
202
|
+
defaultModelSettings = defaultMockModelConfigurations;
|
|
203
|
+
if (openAiKey || anthropicKey || googleKey || azureKey) {
|
|
204
|
+
p.log.warn('--skip-provider is active. Provider key flags are ignored; mock/default model will be used.');
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else if (anthropicKey) {
|
|
195
208
|
defaultModelSettings = defaultAnthropicModelConfigurations;
|
|
196
209
|
}
|
|
197
210
|
else if (openAiKey) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkeep/create-agents",
|
|
3
|
-
"version": "0.50.
|
|
3
|
+
"version": "0.50.3",
|
|
4
4
|
"description": "Create an Inkeep Agent Framework project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,13 +33,14 @@
|
|
|
33
33
|
"degit": "^2.8.4",
|
|
34
34
|
"fs-extra": "^11.0.0",
|
|
35
35
|
"picocolors": "^1.0.0",
|
|
36
|
-
"@inkeep/agents-core": "0.50.
|
|
36
|
+
"@inkeep/agents-core": "0.50.3"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/degit": "^2.8.6",
|
|
40
40
|
"@types/fs-extra": "^11.0.0",
|
|
41
41
|
"@types/node": "^20.12.0",
|
|
42
42
|
"execa": "^9.6.0",
|
|
43
|
+
"playwright": "^1.58.2",
|
|
43
44
|
"tsx": "^4.7.0",
|
|
44
45
|
"typescript": "^5.4.0",
|
|
45
46
|
"vitest": "^3.2.4"
|