@amodalai/amodal 0.3.90 → 0.3.92

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 +25 -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
@@ -5,128 +5,22 @@
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 ExperimentOptions {
11
10
  action: 'create' | 'deploy' | 'watch' | 'list';
12
11
  name?: string;
13
12
  id?: string;
14
- platformUrl?: string;
15
- platformApiKey?: string;
16
13
  controlConfig?: string;
17
14
  variantConfig?: string;
18
15
  }
19
16
 
20
17
  /**
21
- * Manage model experiments via the platform API.
18
+ * Hosted experiment management is not available from the OSS CLI.
22
19
  */
23
20
  export async function runExperimentCommand(options: ExperimentOptions): Promise<void> {
24
- let platformUrl: string;
25
- let apiKey: string;
26
- try {
27
- const config = await resolvePlatformConfig({
28
- url: options.platformUrl,
29
- apiKey: options.platformApiKey,
30
- });
31
- platformUrl = config.url;
32
- apiKey = config.apiKey;
33
- } catch (err) {
34
- const msg = err instanceof Error ? err.message : String(err);
35
- process.stderr.write(`[experiment] ${msg}\n`);
36
- process.exit(1);
37
- }
38
-
39
- const headers = {
40
- 'Content-Type': 'application/json',
41
- 'Authorization': `Bearer ${apiKey}`,
42
- };
43
-
44
- switch (options.action) {
45
- case 'list': {
46
- const res = await fetch(`${platformUrl}/api/experiments`, {headers});
47
- if (!res.ok) {
48
- process.stderr.write(`[experiment] HTTP ${res.status}\n`);
49
- return;
50
- }
51
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- platform response
52
- const data = await res.json() as {experiments: Array<Record<string, unknown>>};
53
- if (data.experiments.length === 0) {
54
- process.stdout.write('No experiments found.\n');
55
- return;
56
- }
57
- for (const exp of data.experiments) {
58
- process.stdout.write(`${exp['id']} ${exp['name']} [${exp['status']}]\n`);
59
- }
60
- break;
61
- }
62
-
63
- case 'create': {
64
- if (!options.name) {
65
- process.stderr.write('[experiment] --name is required for create\n');
66
- return;
67
- }
68
- const controlConfig: Record<string, unknown> = options.controlConfig
69
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- CLI JSON input
70
- ? JSON.parse(options.controlConfig) as Record<string, unknown>
71
- : {};
72
- const variantConfig: Record<string, unknown> = options.variantConfig
73
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- CLI JSON input
74
- ? JSON.parse(options.variantConfig) as Record<string, unknown>
75
- : {};
76
-
77
- const res = await fetch(`${platformUrl}/api/experiments`, {
78
- method: 'POST',
79
- headers,
80
- body: JSON.stringify({name: options.name, controlConfig, variantConfig}),
81
- });
82
- if (!res.ok) {
83
- process.stderr.write(`[experiment] HTTP ${res.status}\n`);
84
- return;
85
- }
86
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- platform response
87
- const {id} = await res.json() as {id: string};
88
- process.stdout.write(`Created experiment: ${id}\n`);
89
- break;
90
- }
91
-
92
- case 'deploy': {
93
- if (!options.id) {
94
- process.stderr.write('[experiment] --id is required for deploy\n');
95
- return;
96
- }
97
- const res = await fetch(`${platformUrl}/api/experiments/${options.id}`, {
98
- method: 'PUT',
99
- headers,
100
- body: JSON.stringify({status: 'deployed'}),
101
- });
102
- if (!res.ok) {
103
- process.stderr.write(`[experiment] HTTP ${res.status}\n`);
104
- return;
105
- }
106
- process.stdout.write(`Deployed experiment: ${options.id}\n`);
107
- break;
108
- }
109
-
110
- case 'watch': {
111
- if (!options.id) {
112
- process.stderr.write('[experiment] --id is required for watch\n');
113
- return;
114
- }
115
- const res = await fetch(`${platformUrl}/api/experiments/${options.id}`, {headers});
116
- if (!res.ok) {
117
- process.stderr.write(`[experiment] HTTP ${res.status}\n`);
118
- return;
119
- }
120
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- platform response
121
- const exp = await res.json() as Record<string, unknown>;
122
- process.stdout.write(JSON.stringify(exp, null, 2) + '\n');
123
- break;
124
- }
125
-
126
- default:
127
- process.stderr.write(`[experiment] Unknown action: ${options.action}\n`);
128
- break;
129
- }
21
+ void options;
22
+ process.stderr.write('[experiment] Hosted experiment management is not included in the OSS CLI.\n');
23
+ process.exit(1);
130
24
  }
131
25
 
132
26
  export const experimentCommand: 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 PromoteOptions {
11
10
  fromEnv: string;
@@ -16,26 +15,9 @@ export interface PromoteOptions {
16
15
  * Promote a deployment from one environment to another.
17
16
  */
18
17
  export async function runPromote(options: PromoteOptions): Promise<number> {
19
- let client: PlatformClient;
20
- try {
21
- client = new PlatformClient();
22
- } catch (err) {
23
- const msg = err instanceof Error ? err.message : String(err);
24
- process.stderr.write(`[promote] ${msg}\n`);
25
- return 1;
26
- }
27
-
28
- const toEnv = options.toEnv ?? 'production';
29
-
30
- try {
31
- const result = await client.promote(options.fromEnv, toEnv);
32
- process.stderr.write(`[promote] Promoted from ${options.fromEnv} to ${toEnv}: ${result.id}\n`);
33
- return 0;
34
- } catch (err) {
35
- const msg = err instanceof Error ? err.message : String(err);
36
- process.stderr.write(`[promote] Failed: ${msg}\n`);
37
- return 1;
38
- }
18
+ void options;
19
+ process.stderr.write('[promote] Hosted deployment promotion is not included in the OSS CLI.\n');
20
+ return 1;
39
21
  }
40
22
 
41
23
  export const promoteCommand: 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 RollbackOptions {
11
10
  deployId?: string;
@@ -17,29 +16,9 @@ export interface RollbackOptions {
17
16
  * Rollback to a previous deployment.
18
17
  */
19
18
  export async function runRollback(options: RollbackOptions = {}): 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(`[rollback] ${msg}\n`);
26
- return 1;
27
- }
28
-
29
- const environment = options.env ?? 'production';
30
-
31
- try {
32
- const result = await client.rollback({
33
- deployId: options.deployId,
34
- environment,
35
- });
36
- process.stderr.write(`[rollback] Rolled back to ${result.id} in ${result.environment}\n`);
37
- return 0;
38
- } catch (err) {
39
- const msg = err instanceof Error ? err.message : String(err);
40
- process.stderr.write(`[rollback] Failed: ${msg}\n`);
41
- return 1;
42
- }
19
+ void options;
20
+ process.stderr.write('[rollback] Hosted deployment rollback is not included in the OSS CLI.\n');
21
+ return 1;
43
22
  }
44
23
 
45
24
  export const rollbackCommand: CommandModule = {
@@ -4,22 +4,15 @@
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
6
 
7
- import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
7
+ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
8
8
 
9
9
  describe('runSecrets', () => {
10
10
  let stderrOutput: string;
11
11
  let stdoutOutput: string;
12
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
- let fetchSpy: any;
14
- const originalEnv = process.env;
12
+ let fetchSpy: ReturnType<typeof vi.spyOn>;
15
13
 
16
14
  beforeEach(() => {
17
15
  vi.clearAllMocks();
18
- process.env = {
19
- ...originalEnv,
20
- PLATFORM_API_URL: 'https://api.example.com',
21
- PLATFORM_API_KEY: 'test-key',
22
- };
23
16
  stderrOutput = '';
24
17
  stdoutOutput = '';
25
18
  vi.spyOn(process.stderr, 'write').mockImplementation((chunk) => {
@@ -34,135 +27,20 @@ describe('runSecrets', () => {
34
27
  });
35
28
 
36
29
  afterEach(() => {
37
- process.env = originalEnv;
38
- fetchSpy.mockRestore();
30
+ vi.restoreAllMocks();
39
31
  });
40
32
 
41
- it('should set a secret', async () => {
42
- fetchSpy.mockResolvedValue(new Response('{}', {status: 200}));
43
-
44
- const {runSecrets} = await import('./secrets.js');
45
- const result = await runSecrets({subcommand: 'set', key: 'DB_URL', value: 'postgres://...'});
46
- expect(result).toBe(0);
47
- expect(stderrOutput).toContain('set successfully');
48
- });
49
-
50
- it('should return 1 when key missing for set', async () => {
51
- const {runSecrets} = await import('./secrets.js');
52
- const result = await runSecrets({subcommand: 'set'});
53
- expect(result).toBe(1);
54
- expect(stderrOutput).toContain('Missing key');
55
- });
56
-
57
- it('should return 1 when value missing for set', async () => {
58
- const {runSecrets} = await import('./secrets.js');
59
- const result = await runSecrets({subcommand: 'set', key: 'DB_URL'});
60
- expect(result).toBe(1);
61
- expect(stderrOutput).toContain('Missing value');
62
- });
63
-
64
- it('should list secrets', async () => {
65
- fetchSpy.mockResolvedValue(new Response(JSON.stringify([
66
- {key: 'DB_URL'},
67
- {key: 'API_KEY'},
68
- ]), {status: 200}));
69
-
70
- const {runSecrets} = await import('./secrets.js');
71
- const result = await runSecrets({subcommand: 'list'});
72
- expect(result).toBe(0);
73
- expect(stdoutOutput).toContain('DB_URL');
74
- expect(stdoutOutput).toContain('API_KEY');
75
- });
76
-
77
- it('should list secrets as JSON', async () => {
78
- fetchSpy.mockResolvedValue(new Response(JSON.stringify([{key: 'DB_URL'}]), {status: 200}));
79
-
80
- const {runSecrets} = await import('./secrets.js');
81
- const result = await runSecrets({subcommand: 'list', json: true});
82
- expect(result).toBe(0);
83
- const parsed = JSON.parse(stdoutOutput);
84
- expect(parsed).toHaveLength(1);
85
- });
86
-
87
- it('should handle empty secrets list', async () => {
88
- fetchSpy.mockResolvedValue(new Response('[]', {status: 200}));
89
-
33
+ it.each([
34
+ {subcommand: 'set' as const, key: 'DB_URL', value: 'postgres://example'},
35
+ {subcommand: 'list' as const},
36
+ {subcommand: 'delete' as const, key: 'DB_URL'},
37
+ ])('fails closed for hosted secret management in OSS: $subcommand', async (options) => {
90
38
  const {runSecrets} = await import('./secrets.js');
91
- const result = await runSecrets({subcommand: 'list'});
92
- expect(result).toBe(0);
93
- expect(stderrOutput).toContain('No secrets configured');
94
- });
95
-
96
- it('should delete a secret', async () => {
97
- fetchSpy.mockResolvedValue(new Response('{}', {status: 200}));
39
+ const result = await runSecrets(options);
98
40
 
99
- const {runSecrets} = await import('./secrets.js');
100
- const result = await runSecrets({subcommand: 'delete', key: 'DB_URL'});
101
- expect(result).toBe(0);
102
- expect(stderrOutput).toContain('deleted');
103
- });
104
-
105
- it('should return 1 when key missing for delete', async () => {
106
- const {runSecrets} = await import('./secrets.js');
107
- const result = await runSecrets({subcommand: 'delete'});
108
41
  expect(result).toBe(1);
109
- expect(stderrOutput).toContain('Missing key');
110
- });
111
-
112
- it('should return 1 when platform not configured', async () => {
113
- delete process.env['PLATFORM_API_URL'];
114
- delete process.env['PLATFORM_API_KEY'];
115
-
116
- const {runSecrets} = await import('./secrets.js');
117
- const result = await runSecrets({subcommand: 'list'});
118
- expect(result).toBe(1);
119
- });
120
-
121
- it('should handle auth failure', async () => {
122
- fetchSpy.mockResolvedValue(new Response('Unauthorized', {status: 401}));
123
-
124
- const {runSecrets} = await import('./secrets.js');
125
- const result = await runSecrets({subcommand: 'list'});
126
- expect(result).toBe(1);
127
- expect(stderrOutput).toContain('401');
128
- });
129
-
130
- it('should handle network error', async () => {
131
- fetchSpy.mockRejectedValue(new Error('ECONNREFUSED'));
132
-
133
- const {runSecrets} = await import('./secrets.js');
134
- const result = await runSecrets({subcommand: 'set', key: 'K', value: 'V'});
135
- expect(result).toBe(1);
136
- expect(stderrOutput).toContain('ECONNREFUSED');
137
- });
138
-
139
- it('should handle set server error', async () => {
140
- fetchSpy.mockResolvedValue(new Response('Internal Error', {status: 500}));
141
-
142
- const {runSecrets} = await import('./secrets.js');
143
- const result = await runSecrets({subcommand: 'set', key: 'K', value: 'V'});
144
- expect(result).toBe(1);
145
- expect(stderrOutput).toContain('500');
146
- });
147
-
148
- it('should show count for listed secrets', async () => {
149
- fetchSpy.mockResolvedValue(new Response(JSON.stringify([
150
- {key: 'A'},
151
- {key: 'B'},
152
- {key: 'C'},
153
- ]), {status: 200}));
154
-
155
- const {runSecrets} = await import('./secrets.js');
156
- await runSecrets({subcommand: 'list'});
157
- expect(stderrOutput).toContain('3 secrets');
158
- });
159
-
160
- it('should use singular for single secret', async () => {
161
- fetchSpy.mockResolvedValue(new Response(JSON.stringify([{key: 'ONLY'}]), {status: 200}));
162
-
163
- const {runSecrets} = await import('./secrets.js');
164
- await runSecrets({subcommand: 'list'});
165
- expect(stderrOutput).toContain('1 secret configured');
166
- expect(stderrOutput).not.toContain('1 secrets');
42
+ expect(stderrOutput).toContain('Hosted secret management is not included in the OSS CLI');
43
+ expect(stdoutOutput).toBe('');
44
+ expect(fetchSpy).not.toHaveBeenCalled();
167
45
  });
168
46
  });
@@ -5,7 +5,6 @@
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 SecretsOptions {
11
10
  cwd?: string;
@@ -20,121 +19,8 @@ export interface SecretsOptions {
20
19
  * Returns 0 on success, 1 on error.
21
20
  */
22
21
  export async function runSecrets(options: SecretsOptions): Promise<number> {
23
- let config: {url: string; apiKey: string};
24
- try {
25
- config = await resolvePlatformConfig();
26
- } catch (err) {
27
- const msg = err instanceof Error ? err.message : String(err);
28
- process.stderr.write(`[secrets] ${msg}\n`);
29
- return 1;
30
- }
31
-
32
- const headers: Record<string, string> = {
33
- 'Authorization': `Bearer ${config.apiKey}`,
34
- 'Content-Type': 'application/json',
35
- };
36
-
37
- switch (options.subcommand) {
38
- case 'set': {
39
- if (!options.key) {
40
- process.stderr.write('[secrets] Missing key. Usage: amodal secrets set <key> <value>\n');
41
- return 1;
42
- }
43
- if (options.value === undefined) {
44
- process.stderr.write('[secrets] Missing value. Usage: amodal secrets set <key> <value>\n');
45
- return 1;
46
- }
47
-
48
- try {
49
- const response = await fetch(`${config.url}/api/secrets`, {
50
- method: 'PUT',
51
- headers,
52
- body: JSON.stringify({key: options.key, value: options.value}),
53
- });
54
-
55
- if (!response.ok) {
56
- process.stderr.write(`[secrets] Failed to set secret: ${response.status} ${response.statusText}\n`);
57
- return 1;
58
- }
59
-
60
- process.stderr.write(`[secrets] Secret "${options.key}" set successfully.\n`);
61
- return 0;
62
- } catch (err) {
63
- const msg = err instanceof Error ? err.message : String(err);
64
- process.stderr.write(`[secrets] Failed to set secret: ${msg}\n`);
65
- return 1;
66
- }
67
- }
68
-
69
- case 'list': {
70
- try {
71
- const response = await fetch(`${config.url}/api/secrets`, {
72
- method: 'GET',
73
- headers,
74
- });
75
-
76
- if (!response.ok) {
77
- process.stderr.write(`[secrets] Failed to list secrets: ${response.status} ${response.statusText}\n`);
78
- return 1;
79
- }
80
-
81
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
82
- const secrets = (await response.json()) as Array<{key: string}>;
83
-
84
- if (secrets.length === 0) {
85
- process.stderr.write('[secrets] No secrets configured.\n');
86
- return 0;
87
- }
88
-
89
- if (options.json) {
90
- process.stdout.write(JSON.stringify(secrets, null, 2) + '\n');
91
- return 0;
92
- }
93
-
94
- process.stdout.write('KEY\n');
95
- for (const secret of secrets) {
96
- process.stdout.write(`${secret.key}\n`);
97
- }
98
-
99
- process.stderr.write(`[secrets] ${secrets.length} secret${secrets.length === 1 ? '' : 's'} configured.\n`);
100
- return 0;
101
- } catch (err) {
102
- const msg = err instanceof Error ? err.message : String(err);
103
- process.stderr.write(`[secrets] Failed to list secrets: ${msg}\n`);
104
- return 1;
105
- }
106
- }
107
-
108
- case 'delete': {
109
- if (!options.key) {
110
- process.stderr.write('[secrets] Missing key. Usage: amodal secrets delete <key>\n');
111
- return 1;
112
- }
113
-
114
- try {
115
- const response = await fetch(`${config.url}/api/secrets/${encodeURIComponent(options.key)}`, {
116
- method: 'DELETE',
117
- headers,
118
- });
119
-
120
- if (!response.ok) {
121
- process.stderr.write(`[secrets] Failed to delete secret: ${response.status} ${response.statusText}\n`);
122
- return 1;
123
- }
124
-
125
- process.stderr.write(`[secrets] Secret "${options.key}" deleted.\n`);
126
- return 0;
127
- } catch (err) {
128
- const msg = err instanceof Error ? err.message : String(err);
129
- process.stderr.write(`[secrets] Failed to delete secret: ${msg}\n`);
130
- return 1;
131
- }
132
- }
133
-
134
- default:
135
- break;
136
- }
137
-
22
+ void options;
23
+ process.stderr.write('[secrets] Hosted secret management is not included in the OSS CLI.\n');
138
24
  return 1;
139
25
  }
140
26
 
@@ -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 StatusOptions {
11
10
  env?: string;
@@ -16,56 +15,9 @@ export interface StatusOptions {
16
15
  * Show current deployment status per environment.
17
16
  */
18
17
  export async function runStatus(options: StatusOptions = {}): Promise<number> {
19
- let client: PlatformClient;
20
- try {
21
- client = await PlatformClient.create();
22
- } catch (err) {
23
- const msg = err instanceof Error ? err.message : String(err);
24
- process.stderr.write(`[status] ${msg}\n`);
25
- return 1;
26
- }
27
-
28
- const environments = options.env ? [options.env] : ['production', 'staging'];
29
-
30
- try {
31
- const results: Array<{environment: string; id?: string; createdAt?: string; createdBy?: string; commitSha?: string}> = [];
32
-
33
- for (const env of environments) {
34
- const deployments = await client.listDeployments({environment: env, limit: 1});
35
- const active = deployments.find((d) => d.isActive);
36
- if (active) {
37
- results.push({
38
- environment: env,
39
- id: active.id,
40
- createdAt: active.createdAt,
41
- createdBy: active.createdBy ?? undefined,
42
- commitSha: active.commitSha ?? undefined,
43
- });
44
- } else {
45
- results.push({environment: env});
46
- }
47
- }
48
-
49
- if (options.json) {
50
- process.stdout.write(JSON.stringify(results, null, 2) + '\n');
51
- return 0;
52
- }
53
-
54
- for (const r of results) {
55
- if (r.id) {
56
- const sha = r.commitSha ? ` (${r.commitSha.slice(0, 7)})` : '';
57
- process.stdout.write(`${r.environment}: ${r.id}${sha} — ${r.createdBy ?? 'unknown'} at ${r.createdAt}\n`);
58
- } else {
59
- process.stdout.write(`${r.environment}: no active deployment\n`);
60
- }
61
- }
62
-
63
- return 0;
64
- } catch (err) {
65
- const msg = err instanceof Error ? err.message : String(err);
66
- process.stderr.write(`[status] Failed: ${msg}\n`);
67
- return 1;
68
- }
18
+ void options;
19
+ process.stderr.write('[status] Hosted deployment status is not included in the OSS CLI.\n');
20
+ return 1;
69
21
  }
70
22
 
71
23
  export const statusCommand: CommandModule = {
@@ -1,110 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Amodal Labs, Inc.
4
- * SPDX-License-Identifier: MIT
5
- */
6
- /**
7
- * Metadata returned for a deployment by the platform API.
8
- */
9
- export interface DeploymentMeta {
10
- id: string;
11
- environment: string;
12
- isActive: boolean;
13
- createdAt: string;
14
- createdBy: string;
15
- source: string;
16
- commitSha?: string;
17
- branch?: string;
18
- message?: string;
19
- }
20
- /**
21
- * Resolve platform URL and API key from multiple sources:
22
- * 1. Explicit options (flags)
23
- * 2. .amodal/project.json (platformUrl from `amodal link`)
24
- * 3. ~/.amodalrc (auth token from `amodal login`)
25
- * 4. Env vars (fallback)
26
- */
27
- export declare function resolvePlatformConfig(options?: {
28
- url?: string;
29
- apiKey?: string;
30
- }): Promise<{
31
- url: string;
32
- apiKey: string;
33
- }>;
34
- /**
35
- * Platform API client for snapshot deployments.
36
- *
37
- * Resolves credentials from: explicit options → project link → rc file → env vars.
38
- * Use `PlatformClient.create()` for async auto-discovery, or `new PlatformClient()` for sync usage.
39
- */
40
- export declare class PlatformClient {
41
- private readonly baseUrl;
42
- private readonly apiKey;
43
- constructor(options?: {
44
- url?: string;
45
- apiKey?: string;
46
- });
47
- /**
48
- * Create a PlatformClient with auto-discovery of credentials.
49
- * Resolves from: explicit options → project link → rc file → env vars.
50
- */
51
- static create(options?: {
52
- url?: string;
53
- apiKey?: string;
54
- }): Promise<PlatformClient>;
55
- private headers;
56
- private request;
57
- /**
58
- * Try to refresh the token using the stored refresh token.
59
- * Updates both the in-memory key and the rc file on success.
60
- */
61
- private tryRefreshToken;
62
- /**
63
- * Trigger a runtime-app build on the build server.
64
- * Sends the repo tarball to the build server which builds the SPA and uploads to R2.
65
- */
66
- triggerBuild(buildServerUrl: string, appId: string, deployId: string, repoTarball: import('node:fs').ReadStream): Promise<void>;
67
- /**
68
- * Trigger a remote build:
69
- * 1. Get scoped R2 temp credentials from the platform API
70
- * 2. Upload the tarball directly to R2 with those creds
71
- * 3. Tell the platform API to trigger a Fly Machine build
72
- *
73
- * Returns a buildId for polling.
74
- */
75
- triggerRemoteBuild(appId: string, environment: string, tarballPath: string, message?: string): Promise<{
76
- buildId: string;
77
- }>;
78
- /**
79
- * Poll build status.
80
- */
81
- getBuildStatus(buildId: string): Promise<{
82
- status: 'building' | 'complete' | 'error';
83
- deployId?: string;
84
- environment?: string;
85
- error?: string;
86
- }>;
87
- /**
88
- * List deployments for the authenticated app.
89
- */
90
- listDeployments(options?: {
91
- environment?: string;
92
- limit?: number;
93
- }): Promise<DeploymentMeta[]>;
94
- /**
95
- * Rollback to a previous deployment.
96
- */
97
- rollback(options?: {
98
- deployId?: string;
99
- environment?: string;
100
- }): Promise<DeploymentMeta>;
101
- /**
102
- * Promote a deployment from one environment to another.
103
- */
104
- promote(fromEnv: string, toEnv?: string): Promise<DeploymentMeta>;
105
- /**
106
- * Get status of a specific deployment.
107
- */
108
- getStatus(deployId: string): Promise<DeploymentMeta>;
109
- }
110
- //# sourceMappingURL=platform-client.d.ts.map