@amodalai/amodal 0.3.33 → 0.3.34

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amodalai/amodal",
3
- "version": "0.3.33",
3
+ "version": "0.3.34",
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.33",
30
- "@amodalai/core": "0.3.33",
31
- "@amodalai/db": "0.3.33",
32
- "@amodalai/runtime": "0.3.33",
33
- "@amodalai/studio": "0.3.33",
34
- "@amodalai/runtime-app": "0.3.33"
29
+ "@amodalai/types": "0.3.34",
30
+ "@amodalai/core": "0.3.34",
31
+ "@amodalai/db": "0.3.34",
32
+ "@amodalai/runtime": "0.3.34",
33
+ "@amodalai/studio": "0.3.34",
34
+ "@amodalai/runtime-app": "0.3.34"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "^20.11.24",
@@ -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);
@@ -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(`[init] Created project "${name}" (${provider})\n`);
66
- process.stderr.write('[init] Next steps:\n');
67
- process.stderr.write(' 1. Add a connection: amodal connect <name>\n');
68
- process.stderr.write(' 2. Validate config: amodal validate\n');
69
- process.stderr.write(' 3. Start dev server: amodal dev\n');
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`);
@@ -150,4 +155,29 @@ describe.skipIf(!!skipReason)('subprocess smoke tests', () => {
150
155
  expect(text.length).toBeGreaterThan(0);
151
156
  expect(text).toContain('data:');
152
157
  }, 45_000);
158
+
159
+ it('studio proxies admin chat to admin agent', async () => {
160
+ const res = await fetch(`http://localhost:${STUDIO_PORT}/api/studio/admin-chat/stream`, {
161
+ method: 'POST',
162
+ headers: {'Content-Type': 'application/json'},
163
+ body: JSON.stringify({message: 'Say ok'}),
164
+ signal: AbortSignal.timeout(30_000),
165
+ });
166
+ expect(res.status).toBe(200);
167
+ const text = await res.text();
168
+ expect(text).toContain('data:');
169
+ }, 45_000);
170
+
171
+ it('admin agent reads a file from the repo using file tools', async () => {
172
+ const res = await fetch(`http://localhost:${ADMIN_PORT}/chat`, {
173
+ method: 'POST',
174
+ headers: {'Content-Type': 'application/json'},
175
+ body: JSON.stringify({message: 'Read the file knowledge/test-doc.md using the read_repo_file tool and tell me its contents.'}),
176
+ signal: AbortSignal.timeout(30_000),
177
+ });
178
+ expect(res.status).toBe(200);
179
+ const text = await res.text();
180
+ expect(text).toContain('tool_call_start');
181
+ expect(text).toContain('SENTINEL_FILE_TOOLS_9923');
182
+ }, 45_000);
153
183
  });