@amodalai/amodal 0.3.33 → 0.3.35
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/CHANGELOG.md +31 -0
- package/dist/src/commands/dev.d.ts.map +1 -1
- package/dist/src/commands/dev.js +3 -0
- package/dist/src/commands/dev.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +17 -5
- package/dist/src/commands/init.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/commands/dev.ts +4 -0
- package/src/commands/init.ts +17 -5
- package/src/e2e-subprocess.test.ts +39 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amodalai/amodal",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.35",
|
|
4
4
|
"description": "Amodal CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"react": "^19.2.4",
|
|
27
27
|
"yargs": "^17.7.2",
|
|
28
28
|
"zod": "^4.3.6",
|
|
29
|
-
"@amodalai/types": "0.3.
|
|
30
|
-
"@amodalai/core": "0.3.
|
|
31
|
-
"@amodalai/db": "0.3.
|
|
32
|
-
"@amodalai/runtime": "0.3.
|
|
33
|
-
"@amodalai/studio": "0.3.
|
|
34
|
-
"@amodalai/runtime-app": "0.3.
|
|
29
|
+
"@amodalai/types": "0.3.35",
|
|
30
|
+
"@amodalai/core": "0.3.35",
|
|
31
|
+
"@amodalai/db": "0.3.35",
|
|
32
|
+
"@amodalai/runtime": "0.3.35",
|
|
33
|
+
"@amodalai/studio": "0.3.35",
|
|
34
|
+
"@amodalai/runtime-app": "0.3.35"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "^20.11.24",
|
package/src/commands/dev.ts
CHANGED
|
@@ -178,6 +178,7 @@ function spawnStudio(opts: {
|
|
|
178
178
|
runtimePort: number;
|
|
179
179
|
repoPath: string;
|
|
180
180
|
agentId?: string;
|
|
181
|
+
adminAgentUrl?: string;
|
|
181
182
|
}): StudioSpawnResult | null {
|
|
182
183
|
const studioDir = resolveStudioDir();
|
|
183
184
|
if (!studioDir) {
|
|
@@ -195,6 +196,7 @@ function spawnStudio(opts: {
|
|
|
195
196
|
PORT: String(opts.port),
|
|
196
197
|
HOSTNAME: '0.0.0.0',
|
|
197
198
|
...(opts.agentId ? {AGENT_ID: opts.agentId} : {}),
|
|
199
|
+
...(opts.adminAgentUrl ? {ADMIN_AGENT_URL: opts.adminAgentUrl} : {}),
|
|
198
200
|
};
|
|
199
201
|
|
|
200
202
|
// Pre-built server (npm install): dist-server/studio-server.js
|
|
@@ -304,6 +306,7 @@ async function spawnAdminAgent(opts: {
|
|
|
304
306
|
...process.env,
|
|
305
307
|
AMODAL_NO_ADMIN: '1',
|
|
306
308
|
AMODAL_NO_STUDIO: '1',
|
|
309
|
+
REPO_PATH: opts.repoPath,
|
|
307
310
|
};
|
|
308
311
|
if (opts.studioUrl) {
|
|
309
312
|
env['STUDIO_URL'] = opts.studioUrl;
|
|
@@ -460,6 +463,7 @@ Or add it to your agent's .env file:
|
|
|
460
463
|
runtimePort,
|
|
461
464
|
repoPath,
|
|
462
465
|
agentId,
|
|
466
|
+
adminAgentUrl: options.noAdmin ? undefined : `http://localhost:${String(adminPort)}`,
|
|
463
467
|
});
|
|
464
468
|
if (studioResult) {
|
|
465
469
|
managedProcesses.push(studioResult.process);
|
package/src/commands/init.ts
CHANGED
|
@@ -62,11 +62,23 @@ export async function runInit(options: InitOptions = {}): Promise<void> {
|
|
|
62
62
|
writeFileSync(envPath, generateEnvTemplate(provider));
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
process.stderr.write(
|
|
66
|
-
process.stderr.write(
|
|
67
|
-
process.stderr.write('
|
|
68
|
-
process.stderr.write('
|
|
69
|
-
process.stderr.write('
|
|
65
|
+
process.stderr.write('\n');
|
|
66
|
+
process.stderr.write(` Amodal project initialized in ${cwd}\n`);
|
|
67
|
+
process.stderr.write('\n');
|
|
68
|
+
process.stderr.write(' Created:\n');
|
|
69
|
+
process.stderr.write(' amodal.json Agent config\n');
|
|
70
|
+
process.stderr.write(' .env API keys and database URL\n');
|
|
71
|
+
process.stderr.write(' connections/ API connections\n');
|
|
72
|
+
process.stderr.write(' skills/ Reasoning frameworks\n');
|
|
73
|
+
process.stderr.write(' knowledge/ Domain knowledge\n');
|
|
74
|
+
process.stderr.write(' automations/ Scheduled tasks\n');
|
|
75
|
+
process.stderr.write(' evals/ Test assertions\n');
|
|
76
|
+
process.stderr.write('\n');
|
|
77
|
+
process.stderr.write(' Next steps:\n');
|
|
78
|
+
process.stderr.write(' 1. Add your API key to .env\n');
|
|
79
|
+
process.stderr.write(' 2. Set DATABASE_URL in .env (Postgres)\n');
|
|
80
|
+
process.stderr.write(' 3. Run: amodal dev\n');
|
|
81
|
+
process.stderr.write('\n');
|
|
70
82
|
}
|
|
71
83
|
|
|
72
84
|
/**
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
import {describe, it, expect, beforeAll, afterAll} from 'vitest';
|
|
20
20
|
import {spawn, type ChildProcess} from 'node:child_process';
|
|
21
21
|
import {resolve} from 'node:path';
|
|
22
|
-
import {mkdtempSync, writeFileSync, rmSync,readFileSync, existsSync} from 'node:fs';
|
|
22
|
+
import {mkdtempSync, mkdirSync, writeFileSync, rmSync, readFileSync, existsSync} from 'node:fs';
|
|
23
23
|
import {tmpdir} from 'node:os';
|
|
24
24
|
import {fileURLToPath} from 'node:url';
|
|
25
25
|
|
|
@@ -82,6 +82,11 @@ describe.skipIf(!!skipReason)('subprocess smoke tests', () => {
|
|
|
82
82
|
JSON.stringify({name: 'subprocess-smoke', version: '1.0.0'}),
|
|
83
83
|
);
|
|
84
84
|
|
|
85
|
+
// Create a test knowledge file for file tools tests
|
|
86
|
+
const knowledgeDir = resolve(agentDir, 'knowledge');
|
|
87
|
+
mkdirSync(knowledgeDir, {recursive: true});
|
|
88
|
+
writeFileSync(resolve(knowledgeDir, 'test-doc.md'), '# Test\n\nSENTINEL_FILE_TOOLS_9923\n');
|
|
89
|
+
|
|
85
90
|
const cliEntry = resolve(__dir, '../dist/src/main.js');
|
|
86
91
|
if (!existsSync(cliEntry)) {
|
|
87
92
|
throw new Error(`CLI not built — run pnpm --filter @amodalai/amodal run build first`);
|
|
@@ -128,6 +133,14 @@ describe.skipIf(!!skipReason)('subprocess smoke tests', () => {
|
|
|
128
133
|
expect(body['status']).toBe('ok');
|
|
129
134
|
});
|
|
130
135
|
|
|
136
|
+
it('auth/token returns 404 in local dev (no auth system)', async () => {
|
|
137
|
+
const res = await fetch(`http://localhost:${RUNTIME_PORT}/auth/token`, {
|
|
138
|
+
method: 'POST',
|
|
139
|
+
signal: AbortSignal.timeout(5000),
|
|
140
|
+
});
|
|
141
|
+
expect(res.status).toBe(404);
|
|
142
|
+
});
|
|
143
|
+
|
|
131
144
|
it('studio responds to health check', async () => {
|
|
132
145
|
const ok = await waitForHealth(STUDIO_PORT, 15_000);
|
|
133
146
|
expect(ok).toBe(true);
|
|
@@ -150,4 +163,29 @@ describe.skipIf(!!skipReason)('subprocess smoke tests', () => {
|
|
|
150
163
|
expect(text.length).toBeGreaterThan(0);
|
|
151
164
|
expect(text).toContain('data:');
|
|
152
165
|
}, 45_000);
|
|
166
|
+
|
|
167
|
+
it('studio proxies admin chat to admin agent', async () => {
|
|
168
|
+
const res = await fetch(`http://localhost:${STUDIO_PORT}/api/studio/admin-chat/stream`, {
|
|
169
|
+
method: 'POST',
|
|
170
|
+
headers: {'Content-Type': 'application/json'},
|
|
171
|
+
body: JSON.stringify({message: 'Say ok'}),
|
|
172
|
+
signal: AbortSignal.timeout(30_000),
|
|
173
|
+
});
|
|
174
|
+
expect(res.status).toBe(200);
|
|
175
|
+
const text = await res.text();
|
|
176
|
+
expect(text).toContain('data:');
|
|
177
|
+
}, 45_000);
|
|
178
|
+
|
|
179
|
+
it('admin agent reads a file from the repo using file tools', async () => {
|
|
180
|
+
const res = await fetch(`http://localhost:${ADMIN_PORT}/chat`, {
|
|
181
|
+
method: 'POST',
|
|
182
|
+
headers: {'Content-Type': 'application/json'},
|
|
183
|
+
body: JSON.stringify({message: 'Read the file knowledge/test-doc.md using the read_repo_file tool and tell me its contents.'}),
|
|
184
|
+
signal: AbortSignal.timeout(30_000),
|
|
185
|
+
});
|
|
186
|
+
expect(res.status).toBe(200);
|
|
187
|
+
const text = await res.text();
|
|
188
|
+
expect(text).toContain('tool_call_start');
|
|
189
|
+
expect(text).toContain('SENTINEL_FILE_TOOLS_9923');
|
|
190
|
+
}, 45_000);
|
|
153
191
|
});
|