@orchagent/cli 0.3.7 → 0.3.8
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/dist/commands/env.js +245 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/publish.js +15 -0
- package/dist/lib/api.js +42 -0
- package/package.json +1 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.registerEnvCommand = registerEnvCommand;
|
|
40
|
+
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
41
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
42
|
+
const fs = __importStar(require("fs/promises"));
|
|
43
|
+
const config_1 = require("../lib/config");
|
|
44
|
+
const api_1 = require("../lib/api");
|
|
45
|
+
const errors_1 = require("../lib/errors");
|
|
46
|
+
const analytics_1 = require("../lib/analytics");
|
|
47
|
+
async function resolveWorkspaceId(config, slug) {
|
|
48
|
+
const configFile = await (0, config_1.loadConfig)();
|
|
49
|
+
const targetSlug = slug ?? configFile.workspace;
|
|
50
|
+
if (!targetSlug) {
|
|
51
|
+
// Use user's personal org
|
|
52
|
+
const org = await (0, api_1.getOrg)(config);
|
|
53
|
+
return org.id;
|
|
54
|
+
}
|
|
55
|
+
const response = await (0, api_1.request)(config, 'GET', '/workspaces');
|
|
56
|
+
const workspace = response.workspaces.find((w) => w.slug === targetSlug);
|
|
57
|
+
if (!workspace) {
|
|
58
|
+
throw new errors_1.CliError(`Workspace '${targetSlug}' not found`);
|
|
59
|
+
}
|
|
60
|
+
return workspace.id;
|
|
61
|
+
}
|
|
62
|
+
function statusColor(status) {
|
|
63
|
+
switch (status) {
|
|
64
|
+
case 'ready':
|
|
65
|
+
return chalk_1.default.green(status);
|
|
66
|
+
case 'building':
|
|
67
|
+
return chalk_1.default.yellow(status);
|
|
68
|
+
case 'failed':
|
|
69
|
+
return chalk_1.default.red(status);
|
|
70
|
+
case 'pending':
|
|
71
|
+
return chalk_1.default.gray(status);
|
|
72
|
+
default:
|
|
73
|
+
return chalk_1.default.gray(status ?? 'unknown');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function listEnvs(config, options) {
|
|
77
|
+
const workspaceId = await resolveWorkspaceId(config, options.workspace);
|
|
78
|
+
const result = await (0, api_1.listEnvironments)(config, workspaceId);
|
|
79
|
+
if (result.environments.length === 0) {
|
|
80
|
+
console.log(chalk_1.default.gray('No environments found.'));
|
|
81
|
+
console.log(chalk_1.default.gray('Use `orch env create` to create one, or include a Dockerfile in your agent bundle.'));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const table = new cli_table3_1.default({
|
|
85
|
+
head: [
|
|
86
|
+
chalk_1.default.cyan('Name'),
|
|
87
|
+
chalk_1.default.cyan('Status'),
|
|
88
|
+
chalk_1.default.cyan('Agents'),
|
|
89
|
+
chalk_1.default.cyan('Type'),
|
|
90
|
+
chalk_1.default.cyan('ID'),
|
|
91
|
+
],
|
|
92
|
+
style: { head: [], border: [] },
|
|
93
|
+
});
|
|
94
|
+
for (const env of result.environments) {
|
|
95
|
+
const isDefault = env.environment.id === result.default_environment_id;
|
|
96
|
+
const name = isDefault
|
|
97
|
+
? `${env.environment.name} ${chalk_1.default.yellow('(default)')}`
|
|
98
|
+
: env.environment.name;
|
|
99
|
+
table.push([
|
|
100
|
+
name,
|
|
101
|
+
statusColor(env.build?.status),
|
|
102
|
+
env.agent_count.toString(),
|
|
103
|
+
env.environment.is_predefined ? chalk_1.default.blue('predefined') : chalk_1.default.gray('custom'),
|
|
104
|
+
env.environment.id.slice(0, 8),
|
|
105
|
+
]);
|
|
106
|
+
}
|
|
107
|
+
console.log();
|
|
108
|
+
console.log(chalk_1.default.bold('Environments:'));
|
|
109
|
+
console.log(table.toString());
|
|
110
|
+
console.log();
|
|
111
|
+
if (result.default_environment_id) {
|
|
112
|
+
const defaultEnv = result.environments.find((e) => e.environment.id === result.default_environment_id);
|
|
113
|
+
if (defaultEnv) {
|
|
114
|
+
console.log(chalk_1.default.gray(`Workspace default: ${chalk_1.default.white(defaultEnv.environment.name)}`));
|
|
115
|
+
console.log(chalk_1.default.gray('All new agents will use this environment unless they include their own Dockerfile.'));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async function getEnvStatus(config, environmentId) {
|
|
120
|
+
const result = await (0, api_1.getEnvironment)(config, environmentId);
|
|
121
|
+
console.log();
|
|
122
|
+
console.log(chalk_1.default.bold(`Environment: ${result.environment.name}`));
|
|
123
|
+
console.log();
|
|
124
|
+
console.log(` ID: ${result.environment.id}`);
|
|
125
|
+
console.log(` Status: ${statusColor(result.build?.status)}`);
|
|
126
|
+
console.log(` Agents: ${result.agent_count}`);
|
|
127
|
+
console.log(` Type: ${result.environment.is_predefined ? 'predefined' : 'custom'}`);
|
|
128
|
+
console.log(` Created: ${new Date(result.environment.created_at).toLocaleString()}`);
|
|
129
|
+
if (result.build?.status === 'failed') {
|
|
130
|
+
console.log();
|
|
131
|
+
console.log(chalk_1.default.red('Build Error:'));
|
|
132
|
+
console.log(chalk_1.default.red(` ${result.build.error_message || 'Unknown error'}`));
|
|
133
|
+
}
|
|
134
|
+
if (result.build?.build_logs) {
|
|
135
|
+
console.log();
|
|
136
|
+
console.log(chalk_1.default.gray('Build Logs:'));
|
|
137
|
+
console.log(chalk_1.default.gray(result.build.build_logs));
|
|
138
|
+
}
|
|
139
|
+
console.log();
|
|
140
|
+
console.log(chalk_1.default.gray('Dockerfile:'));
|
|
141
|
+
console.log(chalk_1.default.gray('---'));
|
|
142
|
+
console.log(result.environment.dockerfile_content);
|
|
143
|
+
console.log(chalk_1.default.gray('---'));
|
|
144
|
+
}
|
|
145
|
+
async function createEnv(config, options) {
|
|
146
|
+
let dockerfileContent;
|
|
147
|
+
try {
|
|
148
|
+
dockerfileContent = await fs.readFile(options.file, 'utf-8');
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
throw new errors_1.CliError(`Failed to read Dockerfile: ${options.file}`);
|
|
152
|
+
}
|
|
153
|
+
console.log(chalk_1.default.gray(`Creating environment '${options.name}'...`));
|
|
154
|
+
const result = await (0, api_1.createEnvironment)(config, options.name, dockerfileContent);
|
|
155
|
+
if (result.reused) {
|
|
156
|
+
console.log(chalk_1.default.cyan('Existing environment with same Dockerfile found, reusing.'));
|
|
157
|
+
console.log(`Environment ID: ${result.environment.id}`);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
console.log(chalk_1.default.green('Environment created, build started.'));
|
|
161
|
+
console.log(`Environment ID: ${result.environment.id}`);
|
|
162
|
+
console.log();
|
|
163
|
+
console.log(chalk_1.default.gray(`Check build status: orch env status ${result.environment.id}`));
|
|
164
|
+
}
|
|
165
|
+
await (0, analytics_1.track)('env_create', {
|
|
166
|
+
environment_id: result.environment.id,
|
|
167
|
+
reused: result.reused,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async function deleteEnv(config, environmentId) {
|
|
171
|
+
console.log(chalk_1.default.gray(`Deleting environment ${environmentId}...`));
|
|
172
|
+
await (0, api_1.deleteEnvironment)(config, environmentId);
|
|
173
|
+
console.log(chalk_1.default.green('Environment deleted.'));
|
|
174
|
+
await (0, analytics_1.track)('env_delete', { environment_id: environmentId });
|
|
175
|
+
}
|
|
176
|
+
async function setDefault(config, environmentId, options) {
|
|
177
|
+
const workspaceId = await resolveWorkspaceId(config, options.workspace);
|
|
178
|
+
console.log(chalk_1.default.gray(`Setting default environment for workspace...`));
|
|
179
|
+
await (0, api_1.setWorkspaceDefaultEnvironment)(config, workspaceId, environmentId);
|
|
180
|
+
console.log(chalk_1.default.green('Default environment set for workspace.'));
|
|
181
|
+
console.log(chalk_1.default.gray('All new agents will use this environment unless they include their own Dockerfile.'));
|
|
182
|
+
await (0, analytics_1.track)('env_set_default', {
|
|
183
|
+
environment_id: environmentId,
|
|
184
|
+
workspace_id: workspaceId,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
async function clearDefault(config, options) {
|
|
188
|
+
const workspaceId = await resolveWorkspaceId(config, options.workspace);
|
|
189
|
+
console.log(chalk_1.default.gray(`Clearing default environment for workspace...`));
|
|
190
|
+
await (0, api_1.setWorkspaceDefaultEnvironment)(config, workspaceId, null);
|
|
191
|
+
console.log(chalk_1.default.green('Default environment cleared. Agents will use base image.'));
|
|
192
|
+
await (0, analytics_1.track)('env_clear_default', { workspace_id: workspaceId });
|
|
193
|
+
}
|
|
194
|
+
function registerEnvCommand(program) {
|
|
195
|
+
const env = program
|
|
196
|
+
.command('env')
|
|
197
|
+
.description('Manage custom Docker environments for code agents');
|
|
198
|
+
env
|
|
199
|
+
.command('list')
|
|
200
|
+
.description('List environments in workspace')
|
|
201
|
+
.option('-w, --workspace <slug>', 'Workspace slug')
|
|
202
|
+
.action(async (options) => {
|
|
203
|
+
const config = await (0, config_1.getResolvedConfig)();
|
|
204
|
+
await listEnvs(config, options);
|
|
205
|
+
});
|
|
206
|
+
env
|
|
207
|
+
.command('status <environment-id>')
|
|
208
|
+
.description('Check environment build status')
|
|
209
|
+
.action(async (environmentId) => {
|
|
210
|
+
const config = await (0, config_1.getResolvedConfig)();
|
|
211
|
+
await getEnvStatus(config, environmentId);
|
|
212
|
+
});
|
|
213
|
+
env
|
|
214
|
+
.command('create')
|
|
215
|
+
.description('Create environment from Dockerfile')
|
|
216
|
+
.requiredOption('-f, --file <path>', 'Path to Dockerfile')
|
|
217
|
+
.requiredOption('-n, --name <name>', 'Environment name')
|
|
218
|
+
.action(async (options) => {
|
|
219
|
+
const config = await (0, config_1.getResolvedConfig)();
|
|
220
|
+
await createEnv(config, options);
|
|
221
|
+
});
|
|
222
|
+
env
|
|
223
|
+
.command('delete <environment-id>')
|
|
224
|
+
.description('Delete an environment')
|
|
225
|
+
.action(async (environmentId) => {
|
|
226
|
+
const config = await (0, config_1.getResolvedConfig)();
|
|
227
|
+
await deleteEnv(config, environmentId);
|
|
228
|
+
});
|
|
229
|
+
env
|
|
230
|
+
.command('set-default <environment-id>')
|
|
231
|
+
.description('Set workspace default environment (all agents use this)')
|
|
232
|
+
.option('-w, --workspace <slug>', 'Workspace slug (defaults to current)')
|
|
233
|
+
.action(async (environmentId, options) => {
|
|
234
|
+
const config = await (0, config_1.getResolvedConfig)();
|
|
235
|
+
await setDefault(config, environmentId, options);
|
|
236
|
+
});
|
|
237
|
+
env
|
|
238
|
+
.command('clear-default')
|
|
239
|
+
.description('Clear workspace default environment (agents use base image)')
|
|
240
|
+
.option('-w, --workspace <slug>', 'Workspace slug (defaults to current)')
|
|
241
|
+
.action(async (options) => {
|
|
242
|
+
const config = await (0, config_1.getResolvedConfig)();
|
|
243
|
+
await clearDefault(config, options);
|
|
244
|
+
});
|
|
245
|
+
}
|
package/dist/commands/index.js
CHANGED
|
@@ -25,6 +25,7 @@ const config_1 = require("./config");
|
|
|
25
25
|
const install_1 = require("./install");
|
|
26
26
|
const formats_1 = require("./formats");
|
|
27
27
|
const update_1 = require("./update");
|
|
28
|
+
const env_1 = require("./env");
|
|
28
29
|
function registerCommands(program) {
|
|
29
30
|
(0, login_1.registerLoginCommand)(program);
|
|
30
31
|
(0, whoami_1.registerWhoamiCommand)(program);
|
|
@@ -50,4 +51,5 @@ function registerCommands(program) {
|
|
|
50
51
|
(0, install_1.registerInstallCommand)(program);
|
|
51
52
|
(0, formats_1.registerFormatsCommand)(program);
|
|
52
53
|
(0, update_1.registerUpdateCommand)(program);
|
|
54
|
+
(0, env_1.registerEnvCommand)(program);
|
|
53
55
|
}
|
package/dist/commands/publish.js
CHANGED
|
@@ -8,6 +8,7 @@ const promises_1 = __importDefault(require("fs/promises"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const os_1 = __importDefault(require("os"));
|
|
10
10
|
const yaml_1 = __importDefault(require("yaml"));
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
12
|
const config_1 = require("../lib/config");
|
|
12
13
|
const api_1 = require("../lib/api");
|
|
13
14
|
const errors_1 = require("../lib/errors");
|
|
@@ -463,6 +464,20 @@ function registerPublishCommand(program) {
|
|
|
463
464
|
process.stdout.write(` Uploading bundle...\n`);
|
|
464
465
|
const uploadResult = await (0, api_1.uploadCodeBundle)(config, agentId, bundlePath, manifest.entrypoint);
|
|
465
466
|
process.stdout.write(` Uploaded: ${uploadResult.code_hash.substring(0, 12)}...\n`);
|
|
467
|
+
// Show environment info if applicable
|
|
468
|
+
if (uploadResult.environment_id) {
|
|
469
|
+
if (uploadResult.environment_source === 'dockerfile_new') {
|
|
470
|
+
process.stdout.write(` ${chalk_1.default.cyan('Custom environment detected (Dockerfile)')}\n`);
|
|
471
|
+
process.stdout.write(` ${chalk_1.default.yellow('Environment building...')} Agent will be ready when build completes.\n`);
|
|
472
|
+
process.stdout.write(` ${chalk_1.default.gray(`Check status: orch env status ${uploadResult.environment_id}`)}\n`);
|
|
473
|
+
}
|
|
474
|
+
else if (uploadResult.environment_source === 'dockerfile_reused') {
|
|
475
|
+
process.stdout.write(` ${chalk_1.default.green('Custom environment (reusing existing build)')}\n`);
|
|
476
|
+
}
|
|
477
|
+
else if (uploadResult.environment_source === 'workspace_default') {
|
|
478
|
+
process.stdout.write(` ${chalk_1.default.cyan('Using workspace default environment')}\n`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
466
481
|
}
|
|
467
482
|
finally {
|
|
468
483
|
// Clean up temp files
|
package/dist/lib/api.js
CHANGED
|
@@ -59,6 +59,11 @@ exports.deleteAgent = deleteAgent;
|
|
|
59
59
|
exports.previewAgentVersion = previewAgentVersion;
|
|
60
60
|
exports.reportInstall = reportInstall;
|
|
61
61
|
exports.fetchUserProfile = fetchUserProfile;
|
|
62
|
+
exports.listEnvironments = listEnvironments;
|
|
63
|
+
exports.getEnvironment = getEnvironment;
|
|
64
|
+
exports.createEnvironment = createEnvironment;
|
|
65
|
+
exports.deleteEnvironment = deleteEnvironment;
|
|
66
|
+
exports.setWorkspaceDefaultEnvironment = setWorkspaceDefaultEnvironment;
|
|
62
67
|
const errors_1 = require("./errors");
|
|
63
68
|
const DEFAULT_TIMEOUT_MS = 15000;
|
|
64
69
|
const CALL_TIMEOUT_MS = 120000; // 2 minutes for agent calls (can take time)
|
|
@@ -399,3 +404,40 @@ async function fetchUserProfile(config) {
|
|
|
399
404
|
const result = await request(config, 'GET', '/users/me');
|
|
400
405
|
return result.user;
|
|
401
406
|
}
|
|
407
|
+
/**
|
|
408
|
+
* List environments in a workspace (plus predefined).
|
|
409
|
+
*/
|
|
410
|
+
async function listEnvironments(config, workspaceId) {
|
|
411
|
+
const params = workspaceId ? `?workspace_id=${encodeURIComponent(workspaceId)}` : '';
|
|
412
|
+
return request(config, 'GET', `/environments${params}`);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Get environment details including build status.
|
|
416
|
+
*/
|
|
417
|
+
async function getEnvironment(config, environmentId) {
|
|
418
|
+
return request(config, 'GET', `/environments/${environmentId}`);
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Create a new environment from Dockerfile.
|
|
422
|
+
*/
|
|
423
|
+
async function createEnvironment(config, name, dockerfileContent) {
|
|
424
|
+
return request(config, 'POST', '/environments', {
|
|
425
|
+
body: JSON.stringify({ name, dockerfile_content: dockerfileContent }),
|
|
426
|
+
headers: { 'Content-Type': 'application/json' },
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Delete an environment (must have no agents using it).
|
|
431
|
+
*/
|
|
432
|
+
async function deleteEnvironment(config, environmentId) {
|
|
433
|
+
return request(config, 'DELETE', `/environments/${environmentId}`);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Set workspace default environment.
|
|
437
|
+
*/
|
|
438
|
+
async function setWorkspaceDefaultEnvironment(config, workspaceId, environmentId) {
|
|
439
|
+
return request(config, 'POST', `/environments/workspaces/${workspaceId}/default-environment`, {
|
|
440
|
+
body: JSON.stringify({ environment_id: environmentId }),
|
|
441
|
+
headers: { 'Content-Type': 'application/json' },
|
|
442
|
+
});
|
|
443
|
+
}
|