@amodalai/amodal 0.3.90 → 0.3.91

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/src/commands/audit.d.ts +1 -3
  3. package/dist/src/commands/audit.d.ts.map +1 -1
  4. package/dist/src/commands/audit.js +4 -53
  5. package/dist/src/commands/audit.js.map +1 -1
  6. package/dist/src/commands/build-manifest-types.js +1 -1
  7. package/dist/src/commands/build-tools.d.ts +3 -10
  8. package/dist/src/commands/build-tools.d.ts.map +1 -1
  9. package/dist/src/commands/build-tools.js +5 -118
  10. package/dist/src/commands/build-tools.js.map +1 -1
  11. package/dist/src/commands/build.js +1 -1
  12. package/dist/src/commands/build.js.map +1 -1
  13. package/dist/src/commands/deploy.d.ts +1 -1
  14. package/dist/src/commands/deploy.d.ts.map +1 -1
  15. package/dist/src/commands/deploy.js +3 -61
  16. package/dist/src/commands/deploy.js.map +1 -1
  17. package/dist/src/commands/deployments.d.ts.map +1 -1
  18. package/dist/src/commands/deployments.js +3 -36
  19. package/dist/src/commands/deployments.js.map +1 -1
  20. package/dist/src/commands/dev.d.ts.map +1 -1
  21. package/dist/src/commands/dev.js +7 -10
  22. package/dist/src/commands/dev.js.map +1 -1
  23. package/dist/src/commands/experiment.d.ts +1 -3
  24. package/dist/src/commands/experiment.d.ts.map +1 -1
  25. package/dist/src/commands/experiment.js +4 -102
  26. package/dist/src/commands/experiment.js.map +1 -1
  27. package/dist/src/commands/promote.d.ts.map +1 -1
  28. package/dist/src/commands/promote.js +3 -21
  29. package/dist/src/commands/promote.js.map +1 -1
  30. package/dist/src/commands/rollback.d.ts.map +1 -1
  31. package/dist/src/commands/rollback.js +3 -24
  32. package/dist/src/commands/rollback.js.map +1 -1
  33. package/dist/src/commands/secrets.d.ts.map +1 -1
  34. package/dist/src/commands/secrets.js +2 -102
  35. package/dist/src/commands/secrets.js.map +1 -1
  36. package/dist/src/commands/status.d.ts.map +1 -1
  37. package/dist/src/commands/status.js +3 -49
  38. package/dist/src/commands/status.js.map +1 -1
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +7 -8
  41. package/src/commands/audit.ts +4 -71
  42. package/src/commands/build-manifest-types.ts +1 -1
  43. package/src/commands/build-tools.ts +5 -142
  44. package/src/commands/build.ts +1 -1
  45. package/src/commands/deploy.test.ts +2 -13
  46. package/src/commands/deploy.ts +5 -67
  47. package/src/commands/deployments.ts +3 -39
  48. package/src/commands/dev.ts +7 -10
  49. package/src/commands/experiment.ts +4 -110
  50. package/src/commands/promote.ts +3 -21
  51. package/src/commands/rollback.ts +3 -24
  52. package/src/commands/secrets.test.ts +12 -134
  53. package/src/commands/secrets.ts +2 -116
  54. package/src/commands/status.ts +3 -51
  55. package/dist/src/shared/platform-client.d.ts +0 -110
  56. package/dist/src/shared/platform-client.d.ts.map +0 -1
  57. package/dist/src/shared/platform-client.js +0 -263
  58. package/dist/src/shared/platform-client.js.map +0 -1
  59. package/src/commands/audit.test.ts +0 -92
  60. package/src/commands/experiment.test.ts +0 -125
  61. package/src/shared/platform-client.test.ts +0 -70
  62. package/src/shared/platform-client.ts +0 -343
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amodalai/amodal",
3
- "version": "0.3.90",
3
+ "version": "0.3.91",
4
4
  "description": "Amodal CLI",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -18,7 +18,6 @@
18
18
  "amodal": "dist/src/main.js"
19
19
  },
20
20
  "dependencies": {
21
- "@aws-sdk/client-s3": "^3.700.0",
22
21
  "ink": "^6.8.0",
23
22
  "ink-spinner": "^5.0.0",
24
23
  "ink-text-input": "^6.0.0",
@@ -27,12 +26,12 @@
27
26
  "react": "^19.2.4",
28
27
  "yargs": "^17.7.2",
29
28
  "zod": "^4.3.6",
30
- "@amodalai/types": "0.3.90",
31
- "@amodalai/core": "0.3.90",
32
- "@amodalai/db": "0.3.90",
33
- "@amodalai/runtime": "0.3.90",
34
- "@amodalai/studio": "0.3.90",
35
- "@amodalai/runtime-app": "0.3.90"
29
+ "@amodalai/types": "0.3.91",
30
+ "@amodalai/core": "0.3.91",
31
+ "@amodalai/db": "0.3.91",
32
+ "@amodalai/runtime": "0.3.91",
33
+ "@amodalai/studio": "0.3.91",
34
+ "@amodalai/runtime-app": "0.3.91"
36
35
  },
37
36
  "devDependencies": {
38
37
  "@types/node": "^20.11.24",
@@ -5,86 +5,19 @@
5
5
  */
6
6
 
7
7
  import type {CommandModule} from 'yargs';
8
- import {resolvePlatformConfig} from '../shared/platform-client.js';
9
8
 
10
9
  export interface AuditOptions {
11
10
  sessionId: string;
12
11
  format?: 'json' | 'table';
13
- platformUrl?: string;
14
- platformApiKey?: string;
15
12
  }
16
13
 
17
14
  /**
18
- * Retrieve audit trail for a session from the platform.
15
+ * Hosted audit trails are not available from the OSS CLI.
19
16
  */
20
17
  export async function runAudit(options: AuditOptions): Promise<void> {
21
- let platformUrl: string;
22
- let apiKey: string;
23
- try {
24
- const config = await resolvePlatformConfig({
25
- url: options.platformUrl,
26
- apiKey: options.platformApiKey,
27
- });
28
- platformUrl = config.url;
29
- apiKey = config.apiKey;
30
- } catch (err) {
31
- const msg = err instanceof Error ? err.message : String(err);
32
- process.stderr.write(`[audit] ${msg}\n`);
33
- process.exit(1);
34
- }
35
-
36
- try {
37
- const response = await fetch(`${platformUrl}/api/audit/sessions/${options.sessionId}`, {
38
- headers: {'Authorization': `Bearer ${apiKey}`},
39
- });
40
-
41
- if (!response.ok) {
42
- process.stderr.write(`[audit] HTTP ${response.status}: ${await response.text()}\n`);
43
- process.exit(1);
44
- }
45
-
46
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- platform response
47
- const data = await response.json() as {
48
- sessionId: string;
49
- events: Array<{
50
- id: string;
51
- eventType: string;
52
- data: Record<string, unknown>;
53
- tokenCount: number | null;
54
- durationMs: number | null;
55
- createdAt: string;
56
- }>;
57
- };
58
-
59
- if (options.format === 'json') {
60
- process.stdout.write(JSON.stringify(data, null, 2) + '\n');
61
- return;
62
- }
63
-
64
- // Table format
65
- const events = data.events;
66
- if (events.length === 0) {
67
- process.stdout.write('No audit events found for this session.\n');
68
- return;
69
- }
70
-
71
- const typeWidth = Math.max(10, ...events.map((e) => e.eventType.length));
72
- process.stdout.write(`\nSession: ${data.sessionId}\n`);
73
- process.stdout.write(`${'Type'.padEnd(typeWidth)} ${'Time'.padEnd(24)} Details\n`);
74
- process.stdout.write('-'.repeat(typeWidth + 50) + '\n');
75
-
76
- for (const event of events) {
77
- const time = event.createdAt.slice(0, 24);
78
- const details = event.durationMs ? `${event.durationMs}ms` : '';
79
- process.stdout.write(`${event.eventType.padEnd(typeWidth)} ${time.padEnd(24)} ${details}\n`);
80
- }
81
-
82
- process.stdout.write(`\nTotal: ${events.length} events\n`);
83
- } catch (err) {
84
- const msg = err instanceof Error ? err.message : String(err);
85
- process.stderr.write(`[audit] Error: ${msg}\n`);
86
- process.exit(1);
87
- }
18
+ void options;
19
+ process.stderr.write('[audit] Hosted audit retrieval is not included in the OSS CLI.\n');
20
+ process.exit(1);
88
21
  }
89
22
 
90
23
  export const auditCommand: CommandModule = {
@@ -10,7 +10,7 @@ import {z} from 'zod';
10
10
  * Schema for a single tool entry in the build manifest.
11
11
  */
12
12
  export const BuildManifestToolSchema = z.object({
13
- /** Daytona snapshot ID for fast workspace creation */
13
+ /** Sandbox snapshot ID for fast workspace creation */
14
14
  snapshotId: z.string().min(1),
15
15
  /** Content hash of the tool's source files */
16
16
  imageHash: z.string().min(1),
@@ -7,7 +7,6 @@
7
7
  import {createHash} from 'node:crypto';
8
8
  import {readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync} from 'node:fs';
9
9
  import {join, relative} from 'node:path';
10
- import {execSync} from 'node:child_process';
11
10
  import type {LoadedTool} from '@amodalai/core';
12
11
  import type {BuildManifest} from './build-manifest-types.js';
13
12
 
@@ -76,139 +75,13 @@ function loadExistingManifest(repoPath: string): BuildManifest | null {
76
75
  }
77
76
 
78
77
  /**
79
- * Read the platform config from amodal.json.
80
- */
81
- function getPlatformConfig(repoPath: string): {apiUrl: string; apiKey: string} | null {
82
- try {
83
- const configPath = join(repoPath, 'amodal.json');
84
- const raw = JSON.parse(readFileSync(configPath, 'utf-8'));
85
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
86
- const config = raw as Record<string, unknown>;
87
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
88
- const platform = config['platform'] as {projectId?: string; apiKey?: string} | undefined;
89
- if (!platform?.apiKey) return null;
90
-
91
- const apiUrl = (process.env['PLATFORM_API_URL'] ?? 'https://api.amodal.dev').replace(/\/$/, '');
92
- return {apiUrl, apiKey: platform.apiKey};
93
- } catch {
94
- return null;
95
- }
96
- }
97
-
98
- /**
99
- * Create a tar.gz archive of the tool directory.
100
- * Excludes node_modules, .git, __pycache__, etc.
101
- */
102
- export function createToolArchive(tool: LoadedTool): Buffer {
103
- // Use system tar — available on macOS and Linux
104
- const tarOutput = execSync(
105
- 'tar -czf - ' +
106
- '--exclude=node_modules --exclude=.git --exclude=__pycache__ ' +
107
- '--exclude=.venv --exclude=dist ' +
108
- '-C ' + JSON.stringify(tool.location) + ' .',
109
- {maxBuffer: 50 * 1024 * 1024}, // 50MB max
110
- );
111
- return Buffer.from(tarOutput);
112
- }
113
-
114
- const POLL_INTERVAL_MS = 3000;
115
- const POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes max
116
-
117
- /**
118
- * Upload a tool bundle to the platform API and wait for the build to complete.
119
- *
120
- * 1. POST /api/tools/build — starts the build (Vercel creates a Daytona
121
- * sandbox, uploads files, kicks off setup commands asynchronously)
122
- * 2. Poll GET /api/tools/build/:id — waits for setup to finish, then
123
- * the platform snapshots the sandbox and returns the snapshotId
124
- *
125
- * The ISV never needs Daytona credentials. The platform owns the infra.
126
- */
127
- async function buildToolOnPlatform(
128
- platformUrl: string,
129
- apiKey: string,
130
- tool: LoadedTool,
131
- imageHash: string,
132
- ): Promise<string> {
133
- const archive = createToolArchive(tool);
134
- const fileCount = listFilesRecursive(tool.location).length;
135
-
136
- process.stderr.write(`[build-tools] ${tool.name}: uploading ${fileCount} files (${(archive.length / 1024).toFixed(1)} KB)\n`);
137
-
138
- // 1. Start the build
139
- const startResponse = await fetch(`${platformUrl}/api/tools/build`, {
140
- method: 'POST',
141
- headers: {
142
- 'Authorization': `Bearer ${apiKey}`,
143
- 'Content-Type': 'application/gzip',
144
- 'X-Tool-Name': tool.name,
145
- 'X-Tool-Hash': imageHash,
146
- 'X-Sandbox-Language': tool.sandboxLanguage,
147
- 'X-Has-Setup-Script': String(tool.hasSetupScript),
148
- 'X-Has-Requirements-Txt': String(tool.hasRequirementsTxt),
149
- 'X-Has-Dockerfile': String(tool.hasDockerfile),
150
- 'X-Has-Package-Json': String(tool.hasPackageJson),
151
- },
152
- body: archive,
153
- });
154
-
155
- if (!startResponse.ok) {
156
- const text = await startResponse.text().catch(() => '');
157
- throw new Error(`Platform tool build failed to start (${startResponse.status}): ${text}`);
158
- }
159
-
160
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
161
- const buildResult = await startResponse.json() as {id: string; status: string; snapshotId?: string; error?: string};
162
-
163
- // If already complete (no setup needed), return immediately
164
- if (buildResult.status === 'complete' && buildResult.snapshotId) {
165
- return buildResult.snapshotId;
166
- }
167
- if (buildResult.status === 'failed') {
168
- throw new Error(`Tool build failed: ${buildResult.error ?? 'unknown error'}`);
169
- }
170
-
171
- // 2. Poll until complete
172
- const buildId = buildResult.id;
173
- const startTime = Date.now();
174
-
175
- while (Date.now() - startTime < POLL_TIMEOUT_MS) {
176
- await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
177
-
178
- const pollResponse = await fetch(`${platformUrl}/api/tools/build/${buildId}`, {
179
- headers: {'Authorization': `Bearer ${apiKey}`},
180
- });
181
-
182
- if (!pollResponse.ok) {
183
- throw new Error(`Failed to poll build status (${pollResponse.status})`);
184
- }
185
-
186
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
187
- const poll = await pollResponse.json() as {status: string; snapshotId?: string; error?: string};
188
-
189
- if (poll.status === 'complete' && poll.snapshotId) {
190
- return poll.snapshotId;
191
- }
192
- if (poll.status === 'failed') {
193
- throw new Error(`Tool build failed: ${poll.error ?? 'unknown error'}`);
194
- }
195
-
196
- process.stderr.write(`[build-tools] ${tool.name}: ${poll.status}...\n`);
197
- }
198
-
199
- throw new Error(`Tool build timed out after ${POLL_TIMEOUT_MS / 1000}s`);
200
- }
201
-
202
- /**
203
- * Build Daytona sandbox snapshots for custom tools.
78
+ * Build local custom-tool manifest entries.
204
79
  *
205
80
  * For each tool:
206
81
  * 1. Compute a content hash of all files in the tool directory
207
82
  * 2. If hash matches existing manifest entry, skip (cached)
208
- * 3. Otherwise, upload to the platform API which builds the image
209
- * and creates the Daytona snapshot using the platform's Daytona key
210
- *
211
- * The ISV never touches Daytona directly. The platform owns the infra.
83
+ * 3. Otherwise, generate a local placeholder snapshot id. Hosted control
84
+ * planes own sandbox image builds outside the OSS CLI.
212
85
  *
213
86
  * Writes .amodal/build-manifest.json locally for caching.
214
87
  * The manifest is also included in the deploy snapshot.
@@ -220,8 +93,6 @@ export async function buildToolTemplates(
220
93
  const existing = loadExistingManifest(repoPath);
221
94
  const existingTools = existing?.tools ?? {};
222
95
 
223
- const platform = getPlatformConfig(repoPath);
224
-
225
96
  const builtTools: Record<string, {snapshotId: string; imageHash: string; sandboxLanguage: string; hasDockerfile: boolean; hasSetupScript: boolean}> = {};
226
97
  let skipped = 0;
227
98
  let built = 0;
@@ -243,16 +114,8 @@ export async function buildToolTemplates(
243
114
  process.stderr.write(`[build-tools] ${tool.name}: building (${tool.sandboxLanguage})\n`);
244
115
  }
245
116
 
246
- let snapshotId: string;
247
- if (platform) {
248
- // Upload to platform API → platform builds on Daytona
249
- snapshotId = await buildToolOnPlatform(platform.apiUrl, platform.apiKey, tool, imageHash);
250
- } else {
251
- // No platform configured — generate a placeholder
252
- // (local dev mode — tools run in-process, snapshots not needed)
253
- snapshotId = `local-${imageHash.slice(0, 16)}`;
254
- process.stderr.write(`[build-tools] ${tool.name}: no platform configured, using local placeholder\n`);
255
- }
117
+ const snapshotId = `local-${imageHash.slice(0, 16)}`;
118
+ process.stderr.write(`[build-tools] ${tool.name}: using local placeholder\n`);
256
119
 
257
120
  builtTools[tool.name] = {snapshotId, imageHash, sandboxLanguage: tool.sandboxLanguage, hasDockerfile: tool.hasDockerfile, hasSetupScript: tool.hasSetupScript};
258
121
  built++;
@@ -164,7 +164,7 @@ export const buildCommand: CommandModule = {
164
164
  })
165
165
  .option('tools', {
166
166
  type: 'boolean',
167
- describe: 'Build Daytona sandbox snapshots for custom tools',
167
+ describe: 'Include local custom-tool build metadata',
168
168
  default: false,
169
169
  }),
170
170
  handler: async (argv) => {
@@ -20,13 +20,6 @@ vi.mock('./validate.js', () => ({
20
20
  runValidate: (...args: unknown[]) => mockRunValidate(...args),
21
21
  }));
22
22
 
23
- const mockPlatformCreate = vi.fn();
24
- vi.mock('../shared/platform-client.js', () => ({
25
- PlatformClient: {
26
- create: (...args: unknown[]) => mockPlatformCreate(...args),
27
- },
28
- }));
29
-
30
23
  // Import after mock
31
24
  const {runDeploy} = await import('./deploy.js');
32
25
 
@@ -49,9 +42,6 @@ describe('deploy command', () => {
49
42
 
50
43
  mockFindRepoRoot.mockReturnValue(testDir);
51
44
  mockRunValidate.mockResolvedValue(0); // Validation passes
52
- mockPlatformCreate.mockResolvedValue({
53
- uploadSnapshot: vi.fn().mockResolvedValue({id: 'deploy-test123', environment: 'production'}),
54
- });
55
45
  });
56
46
 
57
47
  afterEach(() => {
@@ -95,15 +85,14 @@ describe('deploy command', () => {
95
85
  stderrSpy.mockRestore();
96
86
  });
97
87
 
98
- it('returns 1 when platform not configured and not dry-run', async () => {
99
- mockPlatformCreate.mockRejectedValue(new Error('Platform URL not found. Run `amodal login`.'));
88
+ it('returns 1 for cloud deploy in OSS CLI', async () => {
100
89
  const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
101
90
 
102
91
  try {
103
92
  const code = await runDeploy({cwd: testDir});
104
93
  expect(code).toBe(1);
105
94
  const messages = stderrSpy.mock.calls.map((c) => String(c[0]));
106
- expect(messages.some((m) => m.includes('Platform'))).toBe(true);
95
+ expect(messages.some((m) => m.includes('not included in the OSS CLI'))).toBe(true);
107
96
  } finally {
108
97
  stderrSpy.mockRestore();
109
98
  }
@@ -6,10 +6,7 @@
6
6
 
7
7
  import type {CommandModule} from 'yargs';
8
8
  import {findRepoRoot} from '../shared/repo-discovery.js';
9
- import {PlatformClient} from '../shared/platform-client.js';
10
9
  import {runValidate} from './validate.js';
11
- import {createRepoTarball} from '../shared/tarball.js';
12
- import {readProjectLink} from './link.js';
13
10
 
14
11
  export interface DeployOptions {
15
12
  cwd?: string;
@@ -19,7 +16,7 @@ export interface DeployOptions {
19
16
  }
20
17
 
21
18
  /**
22
- * Deploy to the platform: validate → tarball → trigger build → poll.
19
+ * Validate a repo before cloud deployment.
23
20
  *
24
21
  * Returns 0 on success, 1 on error.
25
22
  */
@@ -48,69 +45,10 @@ export async function runDeploy(options: DeployOptions = {}): Promise<number> {
48
45
  return 0;
49
46
  }
50
47
 
51
- // Create platform client
52
- let client: PlatformClient;
53
- try {
54
- client = await PlatformClient.create();
55
- } catch (err) {
56
- const msg = err instanceof Error ? err.message : String(err);
57
- process.stderr.write(`[deploy] ${msg}\n`);
58
- return 1;
59
- }
60
-
61
- const projectLink = await readProjectLink();
62
- const appId = projectLink?.appId;
63
-
64
- if (!appId) {
65
- process.stderr.write('[deploy] No app linked. Run `amodal deploy link` first.\n');
66
- return 1;
67
- }
68
-
69
- // Create tarball
70
- process.stderr.write('[deploy] Creating tarball...\n');
71
- const tarballPath = await createRepoTarball(repoPath);
72
-
73
- try {
74
- // Trigger remote build
75
- process.stderr.write('[deploy] Triggering build...\n');
76
- const buildResult = await client.triggerRemoteBuild(appId, environment, tarballPath, options.message);
77
- const buildId = buildResult.buildId;
78
-
79
- process.stderr.write(`[deploy] Build ${buildId} accepted. Waiting for completion...\n`);
80
-
81
- // Poll for completion
82
- const maxWaitMs = 5 * 60 * 1000; // 5 minutes
83
- const pollIntervalMs = 3000;
84
- const startTime = Date.now();
85
-
86
- while (Date.now() - startTime < maxWaitMs) {
87
- await new Promise((r) => setTimeout(r, pollIntervalMs));
88
-
89
- const status = await client.getBuildStatus(buildId);
90
-
91
- if (status.status === 'complete') {
92
- process.stderr.write(`[deploy] Deployed ${status.deployId} to ${status.environment ?? environment}\n`);
93
- return 0;
94
- }
95
-
96
- if (status.status === 'error') {
97
- process.stderr.write(`[deploy] Build failed: ${status.error ?? 'unknown error'}\n`);
98
- return 1;
99
- }
100
-
101
- // Still building — continue polling
102
- }
103
-
104
- process.stderr.write(`[deploy] Build timed out after 5 minutes. Build ${buildId} may still be running.\n`);
105
- return 1;
106
- } catch (err) {
107
- const msg = err instanceof Error ? err.message : String(err);
108
- process.stderr.write(`[deploy] Deploy failed: ${msg}\n`);
109
- return 1;
110
- } finally {
111
- const {unlinkSync} = await import('node:fs');
112
- try { unlinkSync(tarballPath); } catch { /* best-effort */ }
113
- }
48
+ process.stderr.write(
49
+ '[deploy] Cloud deployment is not included in the OSS CLI. Use `amodal deploy build` to create a local snapshot, then deploy it with your hosted control-plane tooling.\n',
50
+ );
51
+ return 1;
114
52
  }
115
53
 
116
54
  export const deployCommand: CommandModule = {
@@ -5,7 +5,6 @@
5
5
  */
6
6
 
7
7
  import type {CommandModule} from 'yargs';
8
- import {PlatformClient} from '../shared/platform-client.js';
9
8
 
10
9
  export interface DeploymentsOptions {
11
10
  env?: string;
@@ -17,44 +16,9 @@ export interface DeploymentsOptions {
17
16
  * List deployment history.
18
17
  */
19
18
  export async function runDeployments(options: DeploymentsOptions = {}): Promise<number> {
20
- let client: PlatformClient;
21
- try {
22
- client = new PlatformClient();
23
- } catch (err) {
24
- const msg = err instanceof Error ? err.message : String(err);
25
- process.stderr.write(`[deployments] ${msg}\n`);
26
- return 1;
27
- }
28
-
29
- try {
30
- const deployments = await client.listDeployments({
31
- environment: options.env,
32
- limit: options.limit ?? 10,
33
- });
34
-
35
- if (options.json) {
36
- process.stdout.write(JSON.stringify(deployments, null, 2) + '\n');
37
- return 0;
38
- }
39
-
40
- if (deployments.length === 0) {
41
- process.stderr.write('[deployments] No deployments found.\n');
42
- return 0;
43
- }
44
-
45
- for (const d of deployments) {
46
- const active = d.isActive ? ' [ACTIVE]' : '';
47
- const msg = d.message ? ` — ${d.message}` : '';
48
- const sha = d.commitSha ? ` (${d.commitSha.slice(0, 7)})` : '';
49
- process.stdout.write(`${d.id} ${d.environment}${active} ${d.createdBy ?? d.source}${sha} ${d.createdAt}${msg}\n`);
50
- }
51
-
52
- return 0;
53
- } catch (err) {
54
- const msg = err instanceof Error ? err.message : String(err);
55
- process.stderr.write(`[deployments] Failed: ${msg}\n`);
56
- return 1;
57
- }
19
+ void options;
20
+ process.stderr.write('[deployments] Hosted deployment history is not included in the OSS CLI.\n');
21
+ return 1;
58
22
  }
59
23
 
60
24
  export const deploymentsCommand: CommandModule = {
@@ -203,13 +203,11 @@ export function formatLineForDev(line: string): string | null {
203
203
  return null;
204
204
  }
205
205
  case 'tool_log': {
206
- // Tools call ctx.log(...) for noteworthy progress (e.g.
207
- // install_template emits "Cloned whodatdev/template-X into
208
- // agent repo (N connection packages installed)"). When fired
206
+ // Tools call ctx.log(...) for noteworthy progress. When fired
209
207
  // during an intent run the callId starts with `intent_`, so
210
- // these lines pass the quiet filter but as raw JSON they
211
- // bury the useful message inside callId/session noise. Strip
212
- // to a clean nested bullet.
208
+ // these lines pass the quiet filter, but as raw JSON they bury
209
+ // the useful message inside callId/session noise. Strip to a
210
+ // clean nested bullet.
213
211
  const msg = str('message');
214
212
  if (!msg) return null;
215
213
  return ` · ${msg}`;
@@ -753,9 +751,8 @@ Or add it to your agent's .env file:
753
751
  // Two flows watched by the same poller:
754
752
  //
755
753
  // 1. AUTO-BOOT — runtime didn't start at CLI launch (no manifest
756
- // yet). Once amodal.json lands (commit_setup, the user-button
757
- // commit-setup endpoint, or init-repo's skip-onboarding
758
- // write), boot the runtime in place. Studio's runtime URL
754
+ // yet). Once amodal.json lands, boot the runtime in place.
755
+ // Studio's runtime URL
759
756
  // probe picks it up on the next tick.
760
757
  //
761
758
  // 2. AUTO-RESTART — runtime is already up but amodal.json has
@@ -766,7 +763,7 @@ Or add it to your agent's .env file:
766
763
  // bundle in memory and the new packages/config never load.
767
764
  //
768
765
  // 500ms debounce after detecting a change — lets the writer
769
- // (commit_setup's atomic rename, init-repo's full write) settle
766
+ // (commit_setup's atomic rename or a direct file write) settle
770
767
  // before loadRepo tries to read.
771
768
  // -------------------------------------------------------------------
772
769