@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.
- package/dist/__tests__/utils.test.js +46 -0
- package/dist/utils.d.ts +6 -6
- package/dist/utils.js +26 -18
- package/package.json +2 -2
|
@@ -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
|
|
14
|
+
model: "openai/gpt-4.1";
|
|
15
15
|
};
|
|
16
16
|
structuredOutput: {
|
|
17
|
-
model: "openai/gpt-4.1-mini
|
|
17
|
+
model: "openai/gpt-4.1-mini";
|
|
18
18
|
};
|
|
19
19
|
summarizer: {
|
|
20
|
-
model: "openai/gpt-4.1-nano
|
|
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
|
|
25
|
+
model: "anthropic/claude-sonnet-4-5";
|
|
26
26
|
};
|
|
27
27
|
structuredOutput: {
|
|
28
|
-
model: "anthropic/claude-sonnet-4-5
|
|
28
|
+
model: "anthropic/claude-sonnet-4-5";
|
|
29
29
|
};
|
|
30
30
|
summarizer: {
|
|
31
|
-
model: "anthropic/claude-sonnet-4-5
|
|
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.
|
|
23
|
+
model: OPENAI_MODELS.GPT_4_1,
|
|
24
24
|
},
|
|
25
25
|
structuredOutput: {
|
|
26
|
-
model: OPENAI_MODELS.
|
|
26
|
+
model: OPENAI_MODELS.GPT_4_1_MINI,
|
|
27
27
|
},
|
|
28
28
|
summarizer: {
|
|
29
|
-
model: OPENAI_MODELS.
|
|
29
|
+
model: OPENAI_MODELS.GPT_4_1_NANO,
|
|
30
30
|
},
|
|
31
31
|
};
|
|
32
32
|
export const defaultAnthropicModelConfigurations = {
|
|
33
33
|
base: {
|
|
34
|
-
model: ANTHROPIC_MODELS.
|
|
34
|
+
model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5,
|
|
35
35
|
},
|
|
36
36
|
structuredOutput: {
|
|
37
|
-
model: ANTHROPIC_MODELS.
|
|
37
|
+
model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5,
|
|
38
38
|
},
|
|
39
39
|
summarizer: {
|
|
40
|
-
model: ANTHROPIC_MODELS.
|
|
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.
|
|
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.
|
|
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.
|
|
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:${
|
|
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.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
+
"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.
|
|
37
|
+
"@inkeep/agents-core": "0.22.5"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/degit": "^2.8.6",
|