@aws/ml-container-creator 0.2.0 → 0.2.2
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/bin/cli.js +88 -86
- package/config/bootstrap-stack.json +211 -0
- package/config/parameter-schema.json +88 -0
- package/infra/ci-harness/bin/ci-harness.ts +26 -0
- package/infra/ci-harness/buildspec.yml +352 -0
- package/infra/ci-harness/cdk.json +27 -0
- package/infra/ci-harness/lambda/scanner/index.ts +199 -0
- package/infra/ci-harness/lib/ci-harness-stack.ts +609 -0
- package/infra/ci-harness/package-lock.json +3979 -0
- package/infra/ci-harness/package.json +32 -0
- package/infra/ci-harness/tsconfig.json +38 -0
- package/package.json +19 -10
- package/src/app.js +318 -318
- package/src/copy-tpl.js +19 -19
- package/src/lib/asset-manager.js +74 -74
- package/src/lib/aws-profile-parser.js +45 -45
- package/src/lib/bootstrap-command-handler.js +560 -547
- package/src/lib/bootstrap-config.js +45 -45
- package/src/lib/ci-register-helpers.js +19 -19
- package/src/lib/ci-report-helpers.js +37 -37
- package/src/lib/ci-stage-helpers.js +49 -49
- package/src/lib/comment-generator.js +4 -4
- package/src/lib/config-manager.js +105 -105
- package/src/lib/deployment-config-resolver.js +10 -10
- package/src/lib/deployment-registry.js +153 -153
- package/src/lib/engine-prefix-resolver.js +8 -8
- package/src/lib/key-value-parser.js +6 -6
- package/src/lib/manifest-cli.js +108 -108
- package/src/lib/prompt-runner.js +224 -224
- package/src/lib/prompts.js +121 -121
- package/src/lib/registry-command-handler.js +174 -174
- package/src/lib/registry-loader.js +52 -52
- package/src/lib/sensitive-redactor.js +9 -9
- package/src/lib/template-engine.js +1 -1
- package/src/lib/template-manager.js +62 -62
- package/src/prompt-adapter.js +18 -18
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
* search [--model, --architecture, --backend, --instance-type]
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import os from 'node:os'
|
|
22
|
-
import path from 'node:path'
|
|
23
|
-
import { readFileSync } from 'node:fs'
|
|
24
|
-
import { execSync } from 'node:child_process'
|
|
25
|
-
import { fileURLToPath } from 'node:url'
|
|
26
|
-
import DeploymentRegistry, { reconstructReplayFlags } from './deployment-registry.js'
|
|
21
|
+
import os from 'node:os';
|
|
22
|
+
import path from 'node:path';
|
|
23
|
+
import { readFileSync } from 'node:fs';
|
|
24
|
+
import { execSync } from 'node:child_process';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
import DeploymentRegistry, { reconstructReplayFlags } from './deployment-registry.js';
|
|
27
27
|
|
|
28
|
-
const PERSONAL_REGISTRY_PATH = path.join(os.homedir(), '.ml-container-creator', 'registry.json')
|
|
29
|
-
const PROJECT_REGISTRY_PATH = path.join(process.cwd(), '.ml-container-creator', 'registry.json')
|
|
28
|
+
const PERSONAL_REGISTRY_PATH = path.join(os.homedir(), '.ml-container-creator', 'registry.json');
|
|
29
|
+
const PROJECT_REGISTRY_PATH = path.join(process.cwd(), '.ml-container-creator', 'registry.json');
|
|
30
30
|
|
|
31
31
|
export default class RegistryCommandHandler {
|
|
32
32
|
constructor() {
|
|
@@ -40,41 +40,41 @@ export default class RegistryCommandHandler {
|
|
|
40
40
|
*/
|
|
41
41
|
async handle(args, options) {
|
|
42
42
|
if (args.length === 0) {
|
|
43
|
-
this._showRegistryHelp()
|
|
44
|
-
return
|
|
43
|
+
this._showRegistryHelp();
|
|
44
|
+
return;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const subcommand = args[0].toLowerCase()
|
|
47
|
+
const subcommand = args[0].toLowerCase();
|
|
48
48
|
|
|
49
49
|
switch (subcommand) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
50
|
+
case 'log':
|
|
51
|
+
await this._handleLog(options);
|
|
52
|
+
break;
|
|
53
|
+
case 'list':
|
|
54
|
+
this._handleList(options);
|
|
55
|
+
break;
|
|
56
|
+
case 'get':
|
|
57
|
+
this._handleGet(args[1]);
|
|
58
|
+
break;
|
|
59
|
+
case 'remove':
|
|
60
|
+
this._handleRemove(args[1]);
|
|
61
|
+
break;
|
|
62
|
+
case 'replay':
|
|
63
|
+
await this._handleReplay(args[1], options);
|
|
64
|
+
break;
|
|
65
|
+
case 'export':
|
|
66
|
+
this._handleExport(args[1], options);
|
|
67
|
+
break;
|
|
68
|
+
case 'import':
|
|
69
|
+
await this._handleImport(args[1], options);
|
|
70
|
+
break;
|
|
71
|
+
case 'search':
|
|
72
|
+
this._handleSearch(options);
|
|
73
|
+
break;
|
|
74
|
+
default:
|
|
75
|
+
console.log(`Unknown registry subcommand: ${subcommand}`);
|
|
76
|
+
this._showRegistryHelp();
|
|
77
|
+
break;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -87,12 +87,12 @@ export default class RegistryCommandHandler {
|
|
|
87
87
|
* @param {object} options - Parsed CLI options from do/register
|
|
88
88
|
*/
|
|
89
89
|
async _handleLog(options) {
|
|
90
|
-
const registryPath = options.project ? PROJECT_REGISTRY_PATH : PERSONAL_REGISTRY_PATH
|
|
91
|
-
const registry = new DeploymentRegistry(registryPath)
|
|
90
|
+
const registryPath = options.project ? PROJECT_REGISTRY_PATH : PERSONAL_REGISTRY_PATH;
|
|
91
|
+
const registry = new DeploymentRegistry(registryPath);
|
|
92
92
|
|
|
93
|
-
const deploymentConfig = options.deploymentConfig || options['deployment-config'] || ''
|
|
94
|
-
const architecture = options.architecture || ''
|
|
95
|
-
const backend = options.backend || ''
|
|
93
|
+
const deploymentConfig = options.deploymentConfig || options['deployment-config'] || '';
|
|
94
|
+
const architecture = options.architecture || '';
|
|
95
|
+
const backend = options.backend || '';
|
|
96
96
|
|
|
97
97
|
const entry = {
|
|
98
98
|
timestamp: new Date().toISOString(),
|
|
@@ -125,27 +125,27 @@ export default class RegistryCommandHandler {
|
|
|
125
125
|
source: 'local',
|
|
126
126
|
importedFrom: null
|
|
127
127
|
}
|
|
128
|
-
}
|
|
128
|
+
};
|
|
129
129
|
|
|
130
130
|
// Parse parameters from JSON string if provided
|
|
131
131
|
if (options.parameters) {
|
|
132
132
|
try {
|
|
133
133
|
entry.configuration.parameters = typeof options.parameters === 'string'
|
|
134
134
|
? JSON.parse(options.parameters)
|
|
135
|
-
: options.parameters
|
|
135
|
+
: options.parameters;
|
|
136
136
|
} catch (err) {
|
|
137
|
-
console.log(`Warning: Could not parse parameters JSON: ${err.message}`)
|
|
138
|
-
entry.configuration.parameters = {}
|
|
137
|
+
console.log(`Warning: Could not parse parameters JSON: ${err.message}`);
|
|
138
|
+
entry.configuration.parameters = {};
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
try {
|
|
143
|
-
const id = registry.add(entry)
|
|
144
|
-
console.log(
|
|
145
|
-
console.log(` Entry ID: ${id}`)
|
|
146
|
-
console.log(` View details: ml-container-creator registry get ${id}`)
|
|
143
|
+
const id = registry.add(entry);
|
|
144
|
+
console.log('✅ Deployment entry logged successfully.');
|
|
145
|
+
console.log(` Entry ID: ${id}`);
|
|
146
|
+
console.log(` View details: ml-container-creator registry get ${id}`);
|
|
147
147
|
} catch (err) {
|
|
148
|
-
console.log(`Error logging deployment entry: ${err.message}`)
|
|
148
|
+
console.log(`Error logging deployment entry: ${err.message}`);
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -158,34 +158,34 @@ export default class RegistryCommandHandler {
|
|
|
158
158
|
* @param {object} options - Parsed CLI options
|
|
159
159
|
*/
|
|
160
160
|
_handleList(options) {
|
|
161
|
-
const filters = this._extractFilters(options)
|
|
161
|
+
const filters = this._extractFilters(options);
|
|
162
162
|
|
|
163
|
-
const personalRegistry = new DeploymentRegistry(PERSONAL_REGISTRY_PATH)
|
|
164
|
-
const projectRegistry = new DeploymentRegistry(PROJECT_REGISTRY_PATH)
|
|
163
|
+
const personalRegistry = new DeploymentRegistry(PERSONAL_REGISTRY_PATH);
|
|
164
|
+
const projectRegistry = new DeploymentRegistry(PROJECT_REGISTRY_PATH);
|
|
165
165
|
|
|
166
|
-
const personalEntries = personalRegistry.list(filters).map(e => ({ ...e, _source: 'personal' }))
|
|
167
|
-
const projectEntries = projectRegistry.list(filters).map(e => ({ ...e, _source: 'project' }))
|
|
166
|
+
const personalEntries = personalRegistry.list(filters).map(e => ({ ...e, _source: 'personal' }));
|
|
167
|
+
const projectEntries = projectRegistry.list(filters).map(e => ({ ...e, _source: 'project' }));
|
|
168
168
|
|
|
169
|
-
const allEntries = [...personalEntries, ...projectEntries]
|
|
169
|
+
const allEntries = [...personalEntries, ...projectEntries];
|
|
170
170
|
|
|
171
171
|
if (allEntries.length === 0) {
|
|
172
|
-
console.log('No deployment entries found.')
|
|
173
|
-
console.log('Use "./do/register" after a successful deployment to add an entry.')
|
|
174
|
-
return
|
|
172
|
+
console.log('No deployment entries found.');
|
|
173
|
+
console.log('Use "./do/register" after a successful deployment to add an entry.');
|
|
174
|
+
return;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
console.log('\nDeployment Registry Entries:\n')
|
|
177
|
+
console.log('\nDeployment Registry Entries:\n');
|
|
178
178
|
for (const entry of allEntries) {
|
|
179
|
-
const id = entry.id || '(no id)'
|
|
180
|
-
const ts = entry.timestamp ? entry.timestamp.slice(0, 19) : '(no timestamp)'
|
|
181
|
-
const dc = entry.deployment?.deploymentConfig || '(none)'
|
|
182
|
-
const mn = entry.model?.modelName || '(none)'
|
|
183
|
-
const it = entry.infrastructure?.instanceType || '(none)'
|
|
184
|
-
const st = entry.status || '(none)'
|
|
185
|
-
const src = entry._source === 'project' ? ' [project]' : ''
|
|
186
|
-
console.log(` ${id} ${ts} ${dc} ${mn} ${it} ${st}${src}`)
|
|
179
|
+
const id = entry.id || '(no id)';
|
|
180
|
+
const ts = entry.timestamp ? entry.timestamp.slice(0, 19) : '(no timestamp)';
|
|
181
|
+
const dc = entry.deployment?.deploymentConfig || '(none)';
|
|
182
|
+
const mn = entry.model?.modelName || '(none)';
|
|
183
|
+
const it = entry.infrastructure?.instanceType || '(none)';
|
|
184
|
+
const st = entry.status || '(none)';
|
|
185
|
+
const src = entry._source === 'project' ? ' [project]' : '';
|
|
186
|
+
console.log(` ${id} ${ts} ${dc} ${mn} ${it} ${st}${src}`);
|
|
187
187
|
}
|
|
188
|
-
console.log('')
|
|
188
|
+
console.log('');
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
/**
|
|
@@ -197,20 +197,20 @@ export default class RegistryCommandHandler {
|
|
|
197
197
|
*/
|
|
198
198
|
_handleGet(id) {
|
|
199
199
|
if (!id) {
|
|
200
|
-
console.log('Usage: ml-container-creator registry get <id>')
|
|
201
|
-
return
|
|
200
|
+
console.log('Usage: ml-container-creator registry get <id>');
|
|
201
|
+
return;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
const entry = this._findEntry(id)
|
|
204
|
+
const entry = this._findEntry(id);
|
|
205
205
|
|
|
206
206
|
if (!entry) {
|
|
207
|
-
console.log(`Error: Entry "${id}" not found.`)
|
|
208
|
-
return
|
|
207
|
+
console.log(`Error: Entry "${id}" not found.`);
|
|
208
|
+
return;
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
console.log(`\nDeployment Entry: ${id}\n`)
|
|
212
|
-
console.log(JSON.stringify(entry, null, 2))
|
|
213
|
-
console.log('')
|
|
211
|
+
console.log(`\nDeployment Entry: ${id}\n`);
|
|
212
|
+
console.log(JSON.stringify(entry, null, 2));
|
|
213
|
+
console.log('');
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
/**
|
|
@@ -222,23 +222,23 @@ export default class RegistryCommandHandler {
|
|
|
222
222
|
*/
|
|
223
223
|
_handleRemove(id) {
|
|
224
224
|
if (!id) {
|
|
225
|
-
console.log('Usage: ml-container-creator registry remove <id>')
|
|
226
|
-
return
|
|
225
|
+
console.log('Usage: ml-container-creator registry remove <id>');
|
|
226
|
+
return;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
const personalRegistry = new DeploymentRegistry(PERSONAL_REGISTRY_PATH)
|
|
229
|
+
const personalRegistry = new DeploymentRegistry(PERSONAL_REGISTRY_PATH);
|
|
230
230
|
if (personalRegistry.remove(id)) {
|
|
231
|
-
console.log(`✅ Entry "${id}" removed from personal registry.`)
|
|
232
|
-
return
|
|
231
|
+
console.log(`✅ Entry "${id}" removed from personal registry.`);
|
|
232
|
+
return;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
const projectRegistry = new DeploymentRegistry(PROJECT_REGISTRY_PATH)
|
|
235
|
+
const projectRegistry = new DeploymentRegistry(PROJECT_REGISTRY_PATH);
|
|
236
236
|
if (projectRegistry.remove(id)) {
|
|
237
|
-
console.log(`✅ Entry "${id}" removed from project registry.`)
|
|
238
|
-
return
|
|
237
|
+
console.log(`✅ Entry "${id}" removed from project registry.`);
|
|
238
|
+
return;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
console.log(`Error: Entry "${id}" not found.`)
|
|
241
|
+
console.log(`Error: Entry "${id}" not found.`);
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
/**
|
|
@@ -252,19 +252,19 @@ export default class RegistryCommandHandler {
|
|
|
252
252
|
*/
|
|
253
253
|
async _handleReplay(id, options) {
|
|
254
254
|
if (!id) {
|
|
255
|
-
console.log('Usage: ml-container-creator registry replay <id> [--model-name <name>] [--instance-type <type>] ...')
|
|
256
|
-
return
|
|
255
|
+
console.log('Usage: ml-container-creator registry replay <id> [--model-name <name>] [--instance-type <type>] ...');
|
|
256
|
+
return;
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
const entry = this._findEntry(id)
|
|
259
|
+
const entry = this._findEntry(id);
|
|
260
260
|
|
|
261
261
|
if (!entry) {
|
|
262
|
-
console.log(`Error: Entry "${id}" not found.`)
|
|
263
|
-
return
|
|
262
|
+
console.log(`Error: Entry "${id}" not found.`);
|
|
263
|
+
return;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
// Build overrides from user-provided CLI options
|
|
267
|
-
const overrides = {}
|
|
267
|
+
const overrides = {};
|
|
268
268
|
const overrideMap = {
|
|
269
269
|
'deployment-config': '--deployment-config',
|
|
270
270
|
'deploymentConfig': '--deployment-config',
|
|
@@ -275,37 +275,37 @@ export default class RegistryCommandHandler {
|
|
|
275
275
|
'region': '--region',
|
|
276
276
|
'model-format': '--model-format',
|
|
277
277
|
'modelFormat': '--model-format'
|
|
278
|
-
}
|
|
278
|
+
};
|
|
279
279
|
|
|
280
280
|
for (const [optKey, flagKey] of Object.entries(overrideMap)) {
|
|
281
|
-
if (options[optKey]
|
|
282
|
-
overrides[flagKey] = options[optKey]
|
|
281
|
+
if (options[optKey] !== null && options[optKey] !== undefined) {
|
|
282
|
+
overrides[flagKey] = options[optKey];
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
const flags = reconstructReplayFlags(entry, overrides)
|
|
286
|
+
const flags = reconstructReplayFlags(entry, overrides);
|
|
287
287
|
|
|
288
|
-
console.log(`\nReplaying deployment entry: ${id}`)
|
|
289
|
-
console.log(` Deployment config: ${flags['--deployment-config'] || '(will prompt)'}`)
|
|
290
|
-
console.log(` Model name: ${flags['--model-name'] || '(will prompt)'}`)
|
|
291
|
-
console.log(` Instance type: ${flags['--instance-type'] || '(will prompt)'}`)
|
|
292
|
-
console.log(` Region: ${flags['--region'] || '(will prompt)'}`)
|
|
293
|
-
console.log('')
|
|
288
|
+
console.log(`\nReplaying deployment entry: ${id}`);
|
|
289
|
+
console.log(` Deployment config: ${flags['--deployment-config'] || '(will prompt)'}`);
|
|
290
|
+
console.log(` Model name: ${flags['--model-name'] || '(will prompt)'}`);
|
|
291
|
+
console.log(` Instance type: ${flags['--instance-type'] || '(will prompt)'}`);
|
|
292
|
+
console.log(` Region: ${flags['--region'] || '(will prompt)'}`);
|
|
293
|
+
console.log('');
|
|
294
294
|
|
|
295
|
-
const flagArgs = []
|
|
295
|
+
const flagArgs = [];
|
|
296
296
|
for (const [flag, value] of Object.entries(flags)) {
|
|
297
|
-
flagArgs.push(flag, value)
|
|
297
|
+
flagArgs.push(flag, value);
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
// Resolve the CLI script path relative to this module
|
|
301
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
302
|
-
const cliPath = path.resolve(path.dirname(__filename), '../../bin/cli.js')
|
|
301
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
302
|
+
const cliPath = path.resolve(path.dirname(__filename), '../../bin/cli.js');
|
|
303
303
|
|
|
304
304
|
try {
|
|
305
|
-
execSync(`ml-container-creator ${flagArgs.join(' ')}`, { stdio: 'inherit' })
|
|
305
|
+
execSync(`ml-container-creator ${flagArgs.join(' ')}`, { stdio: 'inherit' });
|
|
306
306
|
} catch {
|
|
307
307
|
// Fallback: invoke via node + script path if binary is not on PATH
|
|
308
|
-
execSync(`${process.execPath} ${cliPath} ${flagArgs.join(' ')}`, { stdio: 'inherit' })
|
|
308
|
+
execSync(`${process.execPath} ${cliPath} ${flagArgs.join(' ')}`, { stdio: 'inherit' });
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
|
|
@@ -318,22 +318,22 @@ export default class RegistryCommandHandler {
|
|
|
318
318
|
* @param {object} options - Parsed CLI options
|
|
319
319
|
*/
|
|
320
320
|
_handleExport(id, options) {
|
|
321
|
-
const registryPath = options.project ? PROJECT_REGISTRY_PATH : PERSONAL_REGISTRY_PATH
|
|
322
|
-
const registry = new DeploymentRegistry(registryPath)
|
|
321
|
+
const registryPath = options.project ? PROJECT_REGISTRY_PATH : PERSONAL_REGISTRY_PATH;
|
|
322
|
+
const registry = new DeploymentRegistry(registryPath);
|
|
323
323
|
|
|
324
|
-
const exportOptions = {}
|
|
324
|
+
const exportOptions = {};
|
|
325
325
|
if (options.status) {
|
|
326
|
-
exportOptions.status = options.status
|
|
326
|
+
exportOptions.status = options.status;
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
const result = registry.exportEntries(id || null, exportOptions)
|
|
329
|
+
const result = registry.exportEntries(id || null, exportOptions);
|
|
330
330
|
|
|
331
331
|
if (result.entries.length === 0) {
|
|
332
|
-
console.log('No entries to export.')
|
|
333
|
-
return
|
|
332
|
+
console.log('No entries to export.');
|
|
333
|
+
return;
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
-
console.log(JSON.stringify(result, null, 2))
|
|
336
|
+
console.log(JSON.stringify(result, null, 2));
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
/**
|
|
@@ -346,50 +346,50 @@ export default class RegistryCommandHandler {
|
|
|
346
346
|
*/
|
|
347
347
|
async _handleImport(filePath, options) {
|
|
348
348
|
if (!filePath) {
|
|
349
|
-
console.log('Usage: ml-container-creator registry import <file> [--merge|--replace]')
|
|
350
|
-
return
|
|
349
|
+
console.log('Usage: ml-container-creator registry import <file> [--merge|--replace]');
|
|
350
|
+
return;
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
let raw
|
|
353
|
+
let raw;
|
|
354
354
|
try {
|
|
355
|
-
raw = readFileSync(filePath, 'utf8')
|
|
355
|
+
raw = readFileSync(filePath, 'utf8');
|
|
356
356
|
} catch (err) {
|
|
357
|
-
console.log(`Error: File not found: ${filePath}`)
|
|
358
|
-
return
|
|
357
|
+
console.log(`Error: File not found: ${filePath}`);
|
|
358
|
+
return;
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
-
let json
|
|
361
|
+
let json;
|
|
362
362
|
try {
|
|
363
|
-
json = JSON.parse(raw)
|
|
363
|
+
json = JSON.parse(raw);
|
|
364
364
|
} catch (err) {
|
|
365
|
-
console.log(`Error: Invalid JSON in ${filePath}: ${err.message}`)
|
|
366
|
-
return
|
|
365
|
+
console.log(`Error: Invalid JSON in ${filePath}: ${err.message}`);
|
|
366
|
+
return;
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
if (!json.version || !Array.isArray(json.entries)) {
|
|
370
|
-
console.log('Error: Invalid export format — missing required "version" or "entries" fields.')
|
|
371
|
-
return
|
|
370
|
+
console.log('Error: Invalid export format — missing required "version" or "entries" fields.');
|
|
371
|
+
return;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
-
let strategy = 'skip'
|
|
374
|
+
let strategy = 'skip';
|
|
375
375
|
if (options.merge) {
|
|
376
|
-
strategy = 'merge'
|
|
376
|
+
strategy = 'merge';
|
|
377
377
|
} else if (options.replace) {
|
|
378
|
-
strategy = 'replace'
|
|
378
|
+
strategy = 'replace';
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
-
const registryPath = options.project ? PROJECT_REGISTRY_PATH : PERSONAL_REGISTRY_PATH
|
|
382
|
-
const registry = new DeploymentRegistry(registryPath)
|
|
381
|
+
const registryPath = options.project ? PROJECT_REGISTRY_PATH : PERSONAL_REGISTRY_PATH;
|
|
382
|
+
const registry = new DeploymentRegistry(registryPath);
|
|
383
383
|
|
|
384
384
|
try {
|
|
385
|
-
const result = registry.importEntries(json, strategy, path.basename(filePath))
|
|
386
|
-
console.log(
|
|
387
|
-
console.log(` Added: ${result.added}`)
|
|
388
|
-
console.log(` Skipped: ${result.skipped}`)
|
|
389
|
-
console.log(` Conflicts: ${result.conflicts}`)
|
|
390
|
-
console.log('')
|
|
385
|
+
const result = registry.importEntries(json, strategy, path.basename(filePath));
|
|
386
|
+
console.log('\nImport complete:');
|
|
387
|
+
console.log(` Added: ${result.added}`);
|
|
388
|
+
console.log(` Skipped: ${result.skipped}`);
|
|
389
|
+
console.log(` Conflicts: ${result.conflicts}`);
|
|
390
|
+
console.log('');
|
|
391
391
|
} catch (err) {
|
|
392
|
-
console.log(`Error importing entries: ${err.message}`)
|
|
392
|
+
console.log(`Error importing entries: ${err.message}`);
|
|
393
393
|
}
|
|
394
394
|
}
|
|
395
395
|
|
|
@@ -402,33 +402,33 @@ export default class RegistryCommandHandler {
|
|
|
402
402
|
* @param {object} options - Parsed CLI options
|
|
403
403
|
*/
|
|
404
404
|
_handleSearch(options) {
|
|
405
|
-
const query = this._extractFilters(options)
|
|
405
|
+
const query = this._extractFilters(options);
|
|
406
406
|
|
|
407
|
-
const personalRegistry = new DeploymentRegistry(PERSONAL_REGISTRY_PATH)
|
|
408
|
-
const projectRegistry = new DeploymentRegistry(PROJECT_REGISTRY_PATH)
|
|
407
|
+
const personalRegistry = new DeploymentRegistry(PERSONAL_REGISTRY_PATH);
|
|
408
|
+
const projectRegistry = new DeploymentRegistry(PROJECT_REGISTRY_PATH);
|
|
409
409
|
|
|
410
|
-
const personalResults = personalRegistry.search(query).map(e => ({ ...e, _source: 'personal' }))
|
|
411
|
-
const projectResults = projectRegistry.search(query).map(e => ({ ...e, _source: 'project' }))
|
|
410
|
+
const personalResults = personalRegistry.search(query).map(e => ({ ...e, _source: 'personal' }));
|
|
411
|
+
const projectResults = projectRegistry.search(query).map(e => ({ ...e, _source: 'project' }));
|
|
412
412
|
|
|
413
|
-
const allResults = [...personalResults, ...projectResults]
|
|
413
|
+
const allResults = [...personalResults, ...projectResults];
|
|
414
414
|
|
|
415
415
|
if (allResults.length === 0) {
|
|
416
|
-
console.log('No matching entries found.')
|
|
417
|
-
return
|
|
416
|
+
console.log('No matching entries found.');
|
|
417
|
+
return;
|
|
418
418
|
}
|
|
419
419
|
|
|
420
|
-
console.log(`\nSearch Results (${allResults.length} match${allResults.length === 1 ? '' : 'es'}):\n`)
|
|
420
|
+
console.log(`\nSearch Results (${allResults.length} match${allResults.length === 1 ? '' : 'es'}):\n`);
|
|
421
421
|
for (const entry of allResults) {
|
|
422
|
-
const id = entry.id || '(no id)'
|
|
423
|
-
const ts = entry.timestamp ? entry.timestamp.slice(0, 19) : '(no timestamp)'
|
|
424
|
-
const dc = entry.deployment?.deploymentConfig || '(none)'
|
|
425
|
-
const mn = entry.model?.modelName || '(none)'
|
|
426
|
-
const it = entry.infrastructure?.instanceType || '(none)'
|
|
427
|
-
const st = entry.status || '(none)'
|
|
428
|
-
const src = entry._source === 'project' ? ' [project]' : ''
|
|
429
|
-
console.log(` ${id} ${ts} ${dc} ${mn} ${it} ${st}${src}`)
|
|
422
|
+
const id = entry.id || '(no id)';
|
|
423
|
+
const ts = entry.timestamp ? entry.timestamp.slice(0, 19) : '(no timestamp)';
|
|
424
|
+
const dc = entry.deployment?.deploymentConfig || '(none)';
|
|
425
|
+
const mn = entry.model?.modelName || '(none)';
|
|
426
|
+
const it = entry.infrastructure?.instanceType || '(none)';
|
|
427
|
+
const st = entry.status || '(none)';
|
|
428
|
+
const src = entry._source === 'project' ? ' [project]' : '';
|
|
429
|
+
console.log(` ${id} ${ts} ${dc} ${mn} ${it} ${st}${src}`);
|
|
430
430
|
}
|
|
431
|
-
console.log('')
|
|
431
|
+
console.log('');
|
|
432
432
|
}
|
|
433
433
|
|
|
434
434
|
/**
|
|
@@ -481,7 +481,7 @@ EXAMPLES:
|
|
|
481
481
|
ml-container-creator registry export a1b2c3d4
|
|
482
482
|
ml-container-creator registry import team-deployments.json --merge
|
|
483
483
|
ml-container-creator registry search --model "meta-llama/*" --backend vllm
|
|
484
|
-
`)
|
|
484
|
+
`);
|
|
485
485
|
}
|
|
486
486
|
|
|
487
487
|
// ── Helper methods ──────────────────────────────────────────────
|
|
@@ -492,15 +492,15 @@ EXAMPLES:
|
|
|
492
492
|
* @returns {object} Filter key-value pairs
|
|
493
493
|
*/
|
|
494
494
|
_extractFilters(options) {
|
|
495
|
-
const filters = {}
|
|
496
|
-
if (options.backend) filters.backend = options.backend
|
|
497
|
-
if (options.architecture) filters.architecture = options.architecture
|
|
498
|
-
if (options.model) filters.model = options.model
|
|
495
|
+
const filters = {};
|
|
496
|
+
if (options.backend) filters.backend = options.backend;
|
|
497
|
+
if (options.architecture) filters.architecture = options.architecture;
|
|
498
|
+
if (options.model) filters.model = options.model;
|
|
499
499
|
if (options['instance-type'] || options.instanceType) {
|
|
500
|
-
filters['instance-type'] = options['instance-type'] || options.instanceType
|
|
500
|
+
filters['instance-type'] = options['instance-type'] || options.instanceType;
|
|
501
501
|
}
|
|
502
|
-
if (options.status) filters.status = options.status
|
|
503
|
-
return filters
|
|
502
|
+
if (options.status) filters.status = options.status;
|
|
503
|
+
return filters;
|
|
504
504
|
}
|
|
505
505
|
|
|
506
506
|
/**
|
|
@@ -509,11 +509,11 @@ EXAMPLES:
|
|
|
509
509
|
* @returns {object|null} The matching entry, or null
|
|
510
510
|
*/
|
|
511
511
|
_findEntry(id) {
|
|
512
|
-
const personalRegistry = new DeploymentRegistry(PERSONAL_REGISTRY_PATH)
|
|
513
|
-
const entry = personalRegistry.get(id)
|
|
514
|
-
if (entry) return entry
|
|
512
|
+
const personalRegistry = new DeploymentRegistry(PERSONAL_REGISTRY_PATH);
|
|
513
|
+
const entry = personalRegistry.get(id);
|
|
514
|
+
if (entry) return entry;
|
|
515
515
|
|
|
516
|
-
const projectRegistry = new DeploymentRegistry(PROJECT_REGISTRY_PATH)
|
|
517
|
-
return projectRegistry.get(id)
|
|
516
|
+
const projectRegistry = new DeploymentRegistry(PROJECT_REGISTRY_PATH);
|
|
517
|
+
return projectRegistry.get(id);
|
|
518
518
|
}
|
|
519
519
|
}
|