@inkeep/create-agents 0.22.3 → 0.22.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.
@@ -37,6 +37,7 @@ describe('createAgents - Template and Project ID Logic', () => {
37
37
  vi.mocked(p.cancel).mockImplementation(() => { });
38
38
  vi.mocked(p.note).mockImplementation(() => { });
39
39
  vi.mocked(p.text).mockResolvedValue('test-dir');
40
+ vi.mocked(p.password).mockResolvedValue('test-api-key');
40
41
  vi.mocked(p.select).mockResolvedValue('dual');
41
42
  vi.mocked(p.confirm).mockResolvedValue(false);
42
43
  vi.mocked(p.spinner).mockReturnValue(mockSpinner);
@@ -270,10 +271,55 @@ describe('createAgents - Template and Project ID Logic', () => {
270
271
  expect(fs.ensureDir).toHaveBeenCalledWith('src/projects/custom');
271
272
  });
272
273
  });
274
+ describe('Security - Password input for API keys', () => {
275
+ it('should use password input instead of text input for API keys', async () => {
276
+ // Mock the select to return 'anthropic' to trigger the API key prompt
277
+ vi.mocked(p.select).mockResolvedValueOnce('anthropic');
278
+ vi.mocked(p.password).mockResolvedValueOnce('test-anthropic-key');
279
+ await createAgents({
280
+ dirName: 'test-dir',
281
+ });
282
+ // Verify that p.password was called for the API key
283
+ expect(p.password).toHaveBeenCalledWith(expect.objectContaining({
284
+ message: 'Enter your Anthropic API key:',
285
+ validate: expect.any(Function),
286
+ }));
287
+ // Verify that p.text was NOT called for API keys (only for directory name)
288
+ const textCalls = vi.mocked(p.text).mock.calls;
289
+ const apiKeyCalls = textCalls.filter((call) => call[0] &&
290
+ typeof call[0] === 'object' &&
291
+ 'message' in call[0] &&
292
+ (call[0].message.includes('API key') || call[0].message.includes('Anthropic') || call[0].message.includes('OpenAI') || call[0].message.includes('Google')));
293
+ expect(apiKeyCalls).toHaveLength(0);
294
+ });
295
+ it('should use password input for OpenAI keys', async () => {
296
+ vi.mocked(p.select).mockResolvedValueOnce('openai');
297
+ vi.mocked(p.password).mockResolvedValueOnce('test-openai-key');
298
+ await createAgents({
299
+ dirName: 'test-dir',
300
+ });
301
+ expect(p.password).toHaveBeenCalledWith(expect.objectContaining({
302
+ message: 'Enter your OpenAI API key:',
303
+ validate: expect.any(Function),
304
+ }));
305
+ });
306
+ it('should use password input for Google keys', async () => {
307
+ vi.mocked(p.select).mockResolvedValueOnce('google');
308
+ vi.mocked(p.password).mockResolvedValueOnce('test-google-key');
309
+ await createAgents({
310
+ dirName: 'test-dir',
311
+ });
312
+ expect(p.password).toHaveBeenCalledWith(expect.objectContaining({
313
+ message: 'Enter your Google API key:',
314
+ validate: expect.any(Function),
315
+ }));
316
+ });
317
+ });
273
318
  });
274
319
  // Helper to setup default mocks
275
320
  function setupDefaultMocks() {
276
321
  vi.mocked(p.spinner).mockReturnValue(mockSpinner);
322
+ vi.mocked(p.password).mockResolvedValue('test-api-key');
277
323
  vi.mocked(fs.pathExists).mockResolvedValue(false);
278
324
  vi.mocked(fs.ensureDir).mockResolvedValue(undefined);
279
325
  vi.mocked(fs.writeFile).mockResolvedValue(undefined);
package/dist/utils.d.ts CHANGED
@@ -11,24 +11,24 @@ export declare const defaultGoogleModelConfigurations: {
11
11
  };
12
12
  export declare const defaultOpenaiModelConfigurations: {
13
13
  base: {
14
- model: "openai/gpt-4.1-2025-04-14";
14
+ model: "openai/gpt-4.1";
15
15
  };
16
16
  structuredOutput: {
17
- model: "openai/gpt-4.1-mini-2025-04-14";
17
+ model: "openai/gpt-4.1-mini";
18
18
  };
19
19
  summarizer: {
20
- model: "openai/gpt-4.1-nano-2025-04-14";
20
+ model: "openai/gpt-4.1-nano";
21
21
  };
22
22
  };
23
23
  export declare const defaultAnthropicModelConfigurations: {
24
24
  base: {
25
- model: "anthropic/claude-sonnet-4-5-20250929";
25
+ model: "anthropic/claude-sonnet-4-5";
26
26
  };
27
27
  structuredOutput: {
28
- model: "anthropic/claude-sonnet-4-5-20250929";
28
+ model: "anthropic/claude-sonnet-4-5";
29
29
  };
30
30
  summarizer: {
31
- model: "anthropic/claude-sonnet-4-5-20250929";
31
+ model: "anthropic/claude-sonnet-4-5";
32
32
  };
33
33
  };
34
34
  export declare const createAgents: (args?: {
package/dist/utils.js CHANGED
@@ -20,24 +20,24 @@ export const defaultGoogleModelConfigurations = {
20
20
  };
21
21
  export const defaultOpenaiModelConfigurations = {
22
22
  base: {
23
- model: OPENAI_MODELS.GPT_4_1_20250414,
23
+ model: OPENAI_MODELS.GPT_4_1,
24
24
  },
25
25
  structuredOutput: {
26
- model: OPENAI_MODELS.GPT_4_1_MINI_20250414,
26
+ model: OPENAI_MODELS.GPT_4_1_MINI,
27
27
  },
28
28
  summarizer: {
29
- model: OPENAI_MODELS.GPT_4_1_NANO_20250414,
29
+ model: OPENAI_MODELS.GPT_4_1_NANO,
30
30
  },
31
31
  };
32
32
  export const defaultAnthropicModelConfigurations = {
33
33
  base: {
34
- model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5_20250929,
34
+ model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5,
35
35
  },
36
36
  structuredOutput: {
37
- model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5_20250929,
37
+ model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5,
38
38
  },
39
39
  summarizer: {
40
- model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5_20250929,
40
+ model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5,
41
41
  },
42
42
  };
43
43
  export const createAgents = async (args = {}) => {
@@ -99,9 +99,8 @@ export const createAgents = async (args = {}) => {
99
99
  process.exit(0);
100
100
  }
101
101
  if (providerChoice === 'anthropic') {
102
- const anthropicKeyResponse = await p.text({
102
+ const anthropicKeyResponse = await p.password({
103
103
  message: 'Enter your Anthropic API key:',
104
- placeholder: 'sk-ant-...',
105
104
  validate: (value) => {
106
105
  if (!value || value.trim() === '') {
107
106
  return 'Anthropic API key is required';
@@ -116,9 +115,8 @@ export const createAgents = async (args = {}) => {
116
115
  anthropicKey = anthropicKeyResponse;
117
116
  }
118
117
  else if (providerChoice === 'openai') {
119
- const openAiKeyResponse = await p.text({
118
+ const openAiKeyResponse = await p.password({
120
119
  message: 'Enter your OpenAI API key:',
121
- placeholder: 'sk-...',
122
120
  validate: (value) => {
123
121
  if (!value || value.trim() === '') {
124
122
  return 'OpenAI API key is required';
@@ -133,9 +131,8 @@ export const createAgents = async (args = {}) => {
133
131
  openAiKey = openAiKeyResponse;
134
132
  }
135
133
  else if (providerChoice === 'google') {
136
- const googleKeyResponse = await p.text({
134
+ const googleKeyResponse = await p.password({
137
135
  message: 'Enter your Google API key:',
138
- placeholder: 'AIzaSy...',
139
136
  validate: (value) => {
140
137
  if (!value || value.trim() === '') {
141
138
  return 'Google API key is required';
@@ -258,11 +255,13 @@ async function createWorkspaceStructure() {
258
255
  await fs.ensureDir(`src`);
259
256
  }
260
257
  async function createEnvironmentFiles(config) {
258
+ // Convert to forward slashes for cross-platform SQLite URI compatibility
259
+ const dbPath = process.cwd().replace(/\\/g, '/');
261
260
  const envContent = `# Environment
262
261
  ENVIRONMENT=development
263
262
 
264
263
  # Database
265
- DB_FILE_NAME=file:${process.cwd()}/local.db
264
+ DB_FILE_NAME=file:${dbPath}/local.db
266
265
 
267
266
  # AI Provider Keys
268
267
  ANTHROPIC_API_KEY=${config.anthropicKey || 'your-anthropic-key-here'}
@@ -319,6 +318,8 @@ async function setupProjectInDatabase(config) {
319
318
  stdio: ['pipe', 'pipe', 'pipe'],
320
319
  detached: true,
321
320
  cwd: process.cwd(),
321
+ shell: true,
322
+ windowsHide: true,
322
323
  });
323
324
  await new Promise((resolve) => setTimeout(resolve, 5000));
324
325
  try {
@@ -329,12 +330,19 @@ async function setupProjectInDatabase(config) {
329
330
  finally {
330
331
  if (devProcess.pid) {
331
332
  try {
332
- process.kill(-devProcess.pid, 'SIGTERM');
333
- await new Promise((resolve) => setTimeout(resolve, 1000));
334
- try {
335
- process.kill(-devProcess.pid, 'SIGKILL');
333
+ if (process.platform === 'win32') {
334
+ // Windows: Use taskkill to kill process tree
335
+ await execAsync(`taskkill /pid ${devProcess.pid} /T /F`);
336
+ }
337
+ else {
338
+ // Unix: Use negative PID to kill process group
339
+ process.kill(-devProcess.pid, 'SIGTERM');
340
+ await new Promise((resolve) => setTimeout(resolve, 1000));
341
+ try {
342
+ process.kill(-devProcess.pid, 'SIGKILL');
343
+ }
344
+ catch { }
336
345
  }
337
- catch { }
338
346
  }
339
347
  catch (_error) {
340
348
  console.log('Note: Dev servers may still be running in background');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/create-agents",
3
- "version": "0.22.3",
3
+ "version": "0.22.5",
4
4
  "description": "Create an Inkeep Agent Framework project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -34,7 +34,7 @@
34
34
  "fs-extra": "^11.0.0",
35
35
  "picocolors": "^1.0.0",
36
36
  "drizzle-kit": "^0.31.5",
37
- "@inkeep/agents-core": "0.22.3"
37
+ "@inkeep/agents-core": "0.22.5"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/degit": "^2.8.6",