@orchagent/cli 0.3.100 → 0.3.101
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/agent-keys.js +5 -9
- package/dist/commands/diff.js +4 -2
- package/dist/commands/docs.js +6 -1
- package/dist/commands/fork.js +2 -1
- package/dist/commands/init.js +7 -4
- package/dist/commands/install.js +18 -30
- package/dist/commands/logs.js +3 -1
- package/dist/commands/publish.js +28 -2
- package/dist/commands/pull.js +8 -26
- package/dist/commands/replay.js +40 -7
- package/dist/commands/run.js +35 -62
- package/dist/commands/schedule.js +39 -5
- package/dist/commands/security.js +9 -25
- package/dist/commands/transfer.js +15 -5
- package/dist/commands/tree.js +15 -3
- package/dist/lib/bundle.js +7 -1
- package/dist/lib/resolve-agent.js +62 -0
- package/package.json +1 -1
|
@@ -9,18 +9,14 @@ const config_1 = require("../lib/config");
|
|
|
9
9
|
const api_1 = require("../lib/api");
|
|
10
10
|
const errors_1 = require("../lib/errors");
|
|
11
11
|
const key_store_1 = require("../lib/key-store");
|
|
12
|
+
const resolve_agent_1 = require("../lib/resolve-agent");
|
|
12
13
|
/**
|
|
13
14
|
* Resolve an agent reference ("org/agent" or just "agent") to an agent ID.
|
|
14
|
-
* Uses the
|
|
15
|
+
* Uses the shared resolveAgentContext() for parsing and org/workspace resolution,
|
|
16
|
+
* then finds the latest version via the authenticated list-agents endpoint.
|
|
15
17
|
*/
|
|
16
18
|
async function resolveAgentId(config, ref) {
|
|
17
|
-
const
|
|
18
|
-
const agentName = parts.length >= 2 ? parts[1] : parts[0];
|
|
19
|
-
const orgSlug = parts.length >= 2 ? parts[0] : undefined;
|
|
20
|
-
// Resolve workspace context from org slug or config
|
|
21
|
-
const configFile = await (0, config_1.loadConfig)();
|
|
22
|
-
const resolvedOrg = orgSlug ?? configFile.workspace ?? config.defaultOrg;
|
|
23
|
-
const workspaceId = resolvedOrg ? await (0, api_1.resolveWorkspaceIdForOrg)(config, resolvedOrg) : undefined;
|
|
19
|
+
const { org, agent: agentName, workspaceId } = await (0, resolve_agent_1.resolveAgentContext)(ref, config);
|
|
24
20
|
const agents = await (0, api_1.listMyAgents)(config, workspaceId);
|
|
25
21
|
const matching = agents.filter(a => a.name === agentName);
|
|
26
22
|
if (matching.length === 0) {
|
|
@@ -28,7 +24,7 @@ async function resolveAgentId(config, ref) {
|
|
|
28
24
|
}
|
|
29
25
|
// Use the latest version
|
|
30
26
|
const latest = matching.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0];
|
|
31
|
-
return { agent: latest, agentId: latest.id, orgSlug: latest.org_slug ??
|
|
27
|
+
return { agent: latest, agentId: latest.id, orgSlug: latest.org_slug ?? org, workspaceId };
|
|
32
28
|
}
|
|
33
29
|
function registerAgentKeysCommand(program) {
|
|
34
30
|
const agentKeys = program
|
package/dist/commands/diff.js
CHANGED
|
@@ -246,8 +246,10 @@ function parseSecondRef(value, firstOrg, firstName) {
|
|
|
246
246
|
const parsed = (0, agent_ref_1.parseAgentRef)(value);
|
|
247
247
|
return { org: parsed.org ?? firstOrg, agent: parsed.agent, version: parsed.version };
|
|
248
248
|
}
|
|
249
|
-
// Otherwise treat as a version shorthand for the same agent
|
|
250
|
-
|
|
249
|
+
// Otherwise treat as a version shorthand for the same agent.
|
|
250
|
+
// Strip leading '@' — users naturally type `@v2` since the full form is `org/agent@v2`.
|
|
251
|
+
const version = value.startsWith('@') ? value.slice(1) : value;
|
|
252
|
+
return { org: firstOrg, agent: firstName, version };
|
|
251
253
|
}
|
|
252
254
|
// ── Command ────────────────────────────────────────────────────
|
|
253
255
|
function registerDiffCommand(program) {
|
package/dist/commands/docs.js
CHANGED
|
@@ -10,16 +10,21 @@ const DOCS_ROUTES = {
|
|
|
10
10
|
'': '/',
|
|
11
11
|
'cli': '/using-agents/cli-commands',
|
|
12
12
|
'agents': '/building-agents/agent-types',
|
|
13
|
+
'orchestration': '/building-agents/orchestration',
|
|
13
14
|
'skills': '/building-agents/orchestration',
|
|
14
15
|
'sdk': '/building-agents/sdk',
|
|
15
16
|
'api': '/api-reference/overview',
|
|
16
17
|
'quickstart': '/quickstart',
|
|
18
|
+
'scheduling': '/using-agents/scheduling',
|
|
19
|
+
'services': '/using-agents/services',
|
|
20
|
+
'security': '/concepts/security',
|
|
21
|
+
'billing': '/concepts/billing',
|
|
17
22
|
};
|
|
18
23
|
function registerDocsCommand(program) {
|
|
19
24
|
program
|
|
20
25
|
.command('docs')
|
|
21
26
|
.description('Open documentation in browser')
|
|
22
|
-
.argument('[topic]', 'Topic: cli, agents, skills, sdk, api, quickstart')
|
|
27
|
+
.argument('[topic]', 'Topic: cli, agents, orchestration, skills, sdk, api, quickstart, scheduling, services, security, billing')
|
|
23
28
|
.action(async (topic) => {
|
|
24
29
|
if (topic && !(topic in DOCS_ROUTES)) {
|
|
25
30
|
const validTopics = Object.keys(DOCS_ROUTES).filter(k => k).join(', ');
|
package/dist/commands/fork.js
CHANGED
|
@@ -81,8 +81,9 @@ Examples:
|
|
|
81
81
|
throw new errors_1.CliError('Missing org. Use org/agent format or set default org.');
|
|
82
82
|
}
|
|
83
83
|
const { agent, version } = parsed;
|
|
84
|
+
const workspaceId = await (0, api_1.resolveWorkspaceIdForOrg)(config, org);
|
|
84
85
|
write('Resolving source agent...\n');
|
|
85
|
-
const source = await (0, api_1.getAgentWithFallback)(config, org, agent, version);
|
|
86
|
+
const source = await (0, api_1.getAgentWithFallback)(config, org, agent, version, workspaceId);
|
|
86
87
|
if (!source.id) {
|
|
87
88
|
throw new errors_1.CliError(`Could not resolve source agent ID for '${org}/${agent}@${version}'.`);
|
|
88
89
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -1494,7 +1494,10 @@ function resolveInitFlavor(typeOption) {
|
|
|
1494
1494
|
if (normalized === 'prompt') {
|
|
1495
1495
|
return { type: 'prompt', flavor: 'direct_llm' };
|
|
1496
1496
|
}
|
|
1497
|
-
if (normalized === 'agent'
|
|
1497
|
+
if (normalized === 'agent') {
|
|
1498
|
+
return { type: 'agent', flavor: 'managed_loop' };
|
|
1499
|
+
}
|
|
1500
|
+
if (normalized === 'agentic') {
|
|
1498
1501
|
return { type: 'agent', flavor: 'code_runtime' };
|
|
1499
1502
|
}
|
|
1500
1503
|
if (normalized === 'tool' || normalized === 'code') {
|
|
@@ -1511,7 +1514,7 @@ function registerInitCommand(program) {
|
|
|
1511
1514
|
.option('--orchestrator', 'Create an orchestrator agent with dependency scaffolding and SDK boilerplate')
|
|
1512
1515
|
.option('--run-mode <mode>', 'Run mode for agents: on_demand or always_on', 'on_demand')
|
|
1513
1516
|
.option('--language <lang>', 'Language: python or javascript (default: python)', 'python')
|
|
1514
|
-
.option('--loop', 'Use platform-managed LLM loop
|
|
1517
|
+
.option('--loop', 'Use platform-managed LLM loop execution (explicit for --type agentic; default for --type agent)')
|
|
1515
1518
|
.option('--template <name>', 'Start from a template (use --list-templates to see options)')
|
|
1516
1519
|
.option('--list-templates', 'Show available templates with descriptions')
|
|
1517
1520
|
.action(async (name, options) => {
|
|
@@ -1617,7 +1620,7 @@ function registerInitCommand(program) {
|
|
|
1617
1620
|
const isJavaScript = ['javascript', 'js', 'typescript', 'ts'].includes(language);
|
|
1618
1621
|
// Block unsupported JS flavors
|
|
1619
1622
|
if (isJavaScript && initMode.flavor === 'managed_loop') {
|
|
1620
|
-
throw new errors_1.CliError('JavaScript is not supported for
|
|
1623
|
+
throw new errors_1.CliError('JavaScript is not supported for managed-loop agents. Use --type agentic for a code-runtime agent scaffold.');
|
|
1621
1624
|
}
|
|
1622
1625
|
// JS orchestrators are now supported via the orchagent-sdk npm package
|
|
1623
1626
|
// Block --language for types that don't create runtime files
|
|
@@ -2037,7 +2040,7 @@ function registerInitCommand(program) {
|
|
|
2037
2040
|
}
|
|
2038
2041
|
}
|
|
2039
2042
|
if (initMode.flavor !== 'code_runtime' && initMode.flavor !== 'orchestrator' && initMode.flavor !== 'discord' && runMode === 'always_on') {
|
|
2040
|
-
throw new errors_1.CliError("run_mode=always_on requires runtime.command in orchagent.json (e.g. \"runtime\": { \"command\": \"python main.py\" }). Use --type tool for code-runtime agents.");
|
|
2043
|
+
throw new errors_1.CliError("run_mode=always_on requires runtime.command in orchagent.json (e.g. \"runtime\": { \"command\": \"python main.py\" }). Use --type tool or --type agentic for code-runtime agents.");
|
|
2041
2044
|
}
|
|
2042
2045
|
// Create manifest and type-specific files
|
|
2043
2046
|
const manifest = JSON.parse(MANIFEST_TEMPLATE);
|
package/dist/commands/install.js
CHANGED
|
@@ -10,24 +10,12 @@ const os_1 = __importDefault(require("os"));
|
|
|
10
10
|
const config_1 = require("../lib/config");
|
|
11
11
|
const api_1 = require("../lib/api");
|
|
12
12
|
const errors_1 = require("../lib/errors");
|
|
13
|
+
const resolve_agent_1 = require("../lib/resolve-agent");
|
|
13
14
|
const analytics_1 = require("../lib/analytics");
|
|
14
15
|
const adapters_1 = require("../adapters");
|
|
15
16
|
const skill_resolve_1 = require("../lib/skill-resolve");
|
|
16
17
|
const installed_1 = require("../lib/installed");
|
|
17
18
|
const agents_md_utils_1 = require("../lib/agents-md-utils");
|
|
18
|
-
const DEFAULT_VERSION = 'latest';
|
|
19
|
-
function parseAgentRef(value) {
|
|
20
|
-
const [ref, versionPart] = value.split('@');
|
|
21
|
-
const version = versionPart?.trim() || DEFAULT_VERSION;
|
|
22
|
-
const segments = ref.split('/');
|
|
23
|
-
if (segments.length === 1) {
|
|
24
|
-
return { name: segments[0], version };
|
|
25
|
-
}
|
|
26
|
-
if (segments.length === 2) {
|
|
27
|
-
return { org: segments[0], name: segments[1], version };
|
|
28
|
-
}
|
|
29
|
-
throw new errors_1.CliError('Invalid agent reference. Use org/agent or agent format.');
|
|
30
|
-
}
|
|
31
19
|
async function downloadAgentWithFallback(config, org, name, version, workspaceId) {
|
|
32
20
|
// Fetch public metadata first to check if paid
|
|
33
21
|
let publicMeta;
|
|
@@ -135,19 +123,21 @@ function registerInstallCommand(program) {
|
|
|
135
123
|
errors: [],
|
|
136
124
|
};
|
|
137
125
|
const resolved = await (0, config_1.getResolvedConfig)();
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
126
|
+
let agentCtx;
|
|
127
|
+
try {
|
|
128
|
+
agentCtx = await (0, resolve_agent_1.resolveAgentContext)(agentArg, resolved);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
if (jsonMode && err instanceof errors_1.CliError) {
|
|
132
|
+
result.errors.push(err.message);
|
|
144
133
|
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
145
134
|
process.exit(errors_1.ExitCodes.INVALID_INPUT);
|
|
146
135
|
}
|
|
147
|
-
throw
|
|
136
|
+
throw err;
|
|
148
137
|
}
|
|
149
|
-
|
|
150
|
-
result.
|
|
138
|
+
const { org, agent: agentName, version, workspaceId } = agentCtx;
|
|
139
|
+
result.agent = `${org}/${agentName}`;
|
|
140
|
+
result.version = version;
|
|
151
141
|
// Determine target formats
|
|
152
142
|
let targetFormats = [];
|
|
153
143
|
if (options.format) {
|
|
@@ -186,13 +176,11 @@ function registerInstallCommand(program) {
|
|
|
186
176
|
throw new errors_1.CliError(errMsg);
|
|
187
177
|
}
|
|
188
178
|
result.scope = scope;
|
|
189
|
-
// Resolve workspace context for the target org
|
|
190
|
-
const workspaceId = await (0, api_1.resolveWorkspaceIdForOrg)(resolved, org);
|
|
191
179
|
// Download agent
|
|
192
|
-
log(`Fetching ${org}/${
|
|
180
|
+
log(`Fetching ${org}/${agentName}@${version}...\n`);
|
|
193
181
|
let agent;
|
|
194
182
|
try {
|
|
195
|
-
agent = await downloadAgentWithFallback(resolved, org,
|
|
183
|
+
agent = await downloadAgentWithFallback(resolved, org, agentName, version, workspaceId);
|
|
196
184
|
}
|
|
197
185
|
catch (err) {
|
|
198
186
|
if (jsonMode) {
|
|
@@ -273,15 +261,15 @@ function registerInstallCommand(program) {
|
|
|
273
261
|
catch {
|
|
274
262
|
// File doesn't exist, will create new
|
|
275
263
|
}
|
|
276
|
-
const agentRef = `${org}/${
|
|
264
|
+
const agentRef = `${org}/${agentName}`;
|
|
277
265
|
file.content = (0, agents_md_utils_1.mergeAgentsMdContent)(existingContent, file.content, agentRef);
|
|
278
266
|
}
|
|
279
267
|
await promises_1.default.writeFile(fullPath, file.content);
|
|
280
268
|
filesWritten++;
|
|
281
269
|
// Track installation
|
|
282
270
|
const installedAgent = {
|
|
283
|
-
agent: `${org}/${
|
|
284
|
-
version:
|
|
271
|
+
agent: `${org}/${agentName}`,
|
|
272
|
+
version: version,
|
|
285
273
|
format: formatId,
|
|
286
274
|
scope: effectiveScope,
|
|
287
275
|
path: fullPath,
|
|
@@ -297,7 +285,7 @@ function registerInstallCommand(program) {
|
|
|
297
285
|
if (!options.dryRun) {
|
|
298
286
|
if (filesWritten > 0) {
|
|
299
287
|
await (0, analytics_1.track)('cli_agent_install', {
|
|
300
|
-
agent: `${org}/${
|
|
288
|
+
agent: `${org}/${agentName}`,
|
|
301
289
|
formats: targetFormats,
|
|
302
290
|
scope,
|
|
303
291
|
});
|
package/dist/commands/logs.js
CHANGED
|
@@ -182,7 +182,7 @@ async function listRuns(config, workspaceId, agentName, options) {
|
|
|
182
182
|
if (result.total > result.runs.length) {
|
|
183
183
|
process.stdout.write(chalk_1.default.gray(`\nShowing ${result.runs.length} of ${result.total} runs. Use --limit to see more.\n`));
|
|
184
184
|
}
|
|
185
|
-
process.stdout.write(chalk_1.default.gray('\nView detailed logs for a run: orch logs <run-id>\n'));
|
|
185
|
+
process.stdout.write(chalk_1.default.gray('\nView detailed logs for a run: orch logs <run-id> · Replay a run: orch replay <run-id>\n'));
|
|
186
186
|
}
|
|
187
187
|
// ============================================
|
|
188
188
|
// SHOW RUN LOGS
|
|
@@ -229,5 +229,7 @@ async function showRunLogs(config, workspaceId, runId, json) {
|
|
|
229
229
|
process.stdout.write(chalk_1.default.gray('\nNo sandbox output available for this run. ' +
|
|
230
230
|
'Execution logs are captured for agents with a code runtime (tool/agent types with runtime.command).\n'));
|
|
231
231
|
}
|
|
232
|
+
// Footer hints
|
|
233
|
+
process.stdout.write(chalk_1.default.gray(`\nReplay: orch replay ${runId.slice(0, 8)} · Trace: orch trace ${runId.slice(0, 8)}\n`));
|
|
232
234
|
process.stdout.write('\n');
|
|
233
235
|
}
|
package/dist/commands/publish.js
CHANGED
|
@@ -510,6 +510,8 @@ async function batchPublish(rootDir, options) {
|
|
|
510
510
|
forwardArgs.push('--no-local-download');
|
|
511
511
|
if (options.requiredSecrets === false)
|
|
512
512
|
forwardArgs.push('--no-required-secrets');
|
|
513
|
+
if (options.verbose)
|
|
514
|
+
forwardArgs.push('--verbose');
|
|
513
515
|
const results = [];
|
|
514
516
|
for (let i = 0; i < sorted.length; i++) {
|
|
515
517
|
const agent = sorted[i];
|
|
@@ -586,6 +588,7 @@ function registerPublishCommand(program) {
|
|
|
586
588
|
.option('--no-local-download', 'Prevent users from downloading and running locally (default: allowed)')
|
|
587
589
|
.option('--no-required-secrets', '(deprecated) No longer needed — required_secrets defaults to []')
|
|
588
590
|
.option('--all', 'Publish all agents in subdirectories (dependency order)')
|
|
591
|
+
.option('--verbose', 'Show detailed bundle contents (file list)')
|
|
589
592
|
.action(async (options) => {
|
|
590
593
|
const cwd = process.cwd();
|
|
591
594
|
// --all: batch publish all agents in subdirectories
|
|
@@ -696,6 +699,11 @@ function registerPublishCommand(program) {
|
|
|
696
699
|
process.stdout.write(`\n${chalk_1.default.green('✔')} Published ${org.slug}/${skillData.frontmatter.name}@${skillVersion} successfully!\n\n`);
|
|
697
700
|
if (hasMultipleFiles) {
|
|
698
701
|
process.stdout.write(`Files: ${skillFiles.length} files included\n`);
|
|
702
|
+
if (options.verbose) {
|
|
703
|
+
for (const f of skillFiles) {
|
|
704
|
+
process.stdout.write(` ${f.path}\n`);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
699
707
|
}
|
|
700
708
|
process.stdout.write(`Visibility: private\n`);
|
|
701
709
|
process.stdout.write(`\nView analytics and usage: https://orchagent.io/dashboard\n`);
|
|
@@ -1061,6 +1069,12 @@ function registerPublishCommand(program) {
|
|
|
1061
1069
|
process.stderr.write(` Files: ${bundlePreview.fileCount} files\n`);
|
|
1062
1070
|
process.stderr.write(` Size: ${(bundlePreview.totalSizeBytes / 1024).toFixed(1)} KB\n`);
|
|
1063
1071
|
process.stderr.write(` Entrypoint: ${bundlePreview.entrypoint}\n`);
|
|
1072
|
+
if (options.verbose && bundlePreview.files?.length) {
|
|
1073
|
+
process.stderr.write(` Bundled files:\n`);
|
|
1074
|
+
for (const f of bundlePreview.files) {
|
|
1075
|
+
process.stderr.write(` ${f}\n`);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1064
1078
|
}
|
|
1065
1079
|
process.stderr.write('\nAgent Preview:\n');
|
|
1066
1080
|
process.stderr.write(` Name: ${manifest.name}\n`);
|
|
@@ -1324,6 +1338,12 @@ function registerPublishCommand(program) {
|
|
|
1324
1338
|
skipEntrypointCheck: false,
|
|
1325
1339
|
});
|
|
1326
1340
|
process.stdout.write(` Created bundle: ${bundleResult.fileCount} files, ${(bundleResult.sizeBytes / 1024).toFixed(1)}KB\n`);
|
|
1341
|
+
if (options.verbose && bundleResult.files?.length) {
|
|
1342
|
+
process.stdout.write(` Bundled files:\n`);
|
|
1343
|
+
for (const f of bundleResult.files) {
|
|
1344
|
+
process.stdout.write(` ${f}\n`);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1327
1347
|
// Validate bundle size
|
|
1328
1348
|
const validation = await (0, bundle_1.validateBundle)(bundlePath);
|
|
1329
1349
|
if (!validation.valid) {
|
|
@@ -1404,14 +1424,20 @@ function registerPublishCommand(program) {
|
|
|
1404
1424
|
// Show security review result if available
|
|
1405
1425
|
const secReview = result.security_review;
|
|
1406
1426
|
if (secReview?.verdict) {
|
|
1407
|
-
if (secReview.verdict === '
|
|
1427
|
+
if (secReview.verdict === 'approved') {
|
|
1408
1428
|
process.stdout.write(`Security: ${chalk_1.default.green('passed')}\n`);
|
|
1409
1429
|
}
|
|
1410
1430
|
else if (secReview.verdict === 'flagged') {
|
|
1411
1431
|
process.stdout.write(`Security: ${chalk_1.default.yellow('flagged')} — ${secReview.summary || 'review recommended'}\n`);
|
|
1412
1432
|
}
|
|
1433
|
+
else if (secReview.verdict === 'error') {
|
|
1434
|
+
process.stdout.write(`Security: ${chalk_1.default.gray('review unavailable')} — publish succeeded, review will be retried\n`);
|
|
1435
|
+
}
|
|
1436
|
+
else if (secReview.verdict === 'skipped') {
|
|
1437
|
+
process.stdout.write(`Security: ${chalk_1.default.gray('review skipped')} — ${secReview.summary || 'content not eligible for review'}\n`);
|
|
1438
|
+
}
|
|
1413
1439
|
else {
|
|
1414
|
-
process.stdout.write(`Security: ${secReview.verdict}\n`);
|
|
1440
|
+
process.stdout.write(`Security: ${chalk_1.default.gray(secReview.verdict)} — ${secReview.summary || ''}\n`);
|
|
1415
1441
|
}
|
|
1416
1442
|
}
|
|
1417
1443
|
if (result.service_key) {
|
package/dist/commands/pull.js
CHANGED
|
@@ -12,21 +12,10 @@ const child_process_1 = require("child_process");
|
|
|
12
12
|
const config_1 = require("../lib/config");
|
|
13
13
|
const api_1 = require("../lib/api");
|
|
14
14
|
const errors_1 = require("../lib/errors");
|
|
15
|
+
const resolve_agent_1 = require("../lib/resolve-agent");
|
|
15
16
|
const analytics_1 = require("../lib/analytics");
|
|
16
17
|
const output_1 = require("../lib/output");
|
|
17
18
|
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
18
|
-
function parsePullRef(value) {
|
|
19
|
-
const [ref, versionPart] = value.split('@');
|
|
20
|
-
const version = versionPart?.trim() || 'latest';
|
|
21
|
-
const segments = ref.split('/');
|
|
22
|
-
if (segments.length === 1) {
|
|
23
|
-
return { agent: segments[0], version };
|
|
24
|
-
}
|
|
25
|
-
if (segments.length === 2) {
|
|
26
|
-
return { org: segments[0], agent: segments[1], version };
|
|
27
|
-
}
|
|
28
|
-
throw new errors_1.CliError('Invalid agent reference. Use org/agent[@version] or agent[@version] format.');
|
|
29
|
-
}
|
|
30
19
|
function canonicalType(typeValue) {
|
|
31
20
|
const normalized = (typeValue || 'agent').toLowerCase();
|
|
32
21
|
if (['prompt', 'tool', 'agent', 'skill'].includes(normalized))
|
|
@@ -359,19 +348,12 @@ Examples:
|
|
|
359
348
|
process.stdout.write(message);
|
|
360
349
|
};
|
|
361
350
|
const config = await (0, config_1.getResolvedConfig)();
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (!org) {
|
|
367
|
-
throw new errors_1.CliError('Missing org. Use org/agent[@version] format, or set a default org with:\n' +
|
|
368
|
-
' orch config set default-org <org>');
|
|
369
|
-
}
|
|
370
|
-
// Resolve workspace context for the target org
|
|
371
|
-
const workspaceId = await (0, api_1.resolveWorkspaceIdForOrg)(config, org);
|
|
372
|
-
write(`Resolving ${org}/${parsed.agent}@${parsed.version}...\n`);
|
|
351
|
+
const { org, agent: agentName, version, workspaceId } = await (0, resolve_agent_1.resolveAgentContext)(agentRef, config, {
|
|
352
|
+
missingOrgMessage: 'Missing org. Use org/agent[@version] format, or set a default org with:\n orch config set default-org <org>',
|
|
353
|
+
});
|
|
354
|
+
write(`Resolving ${org}/${agentName}@${version}...\n`);
|
|
373
355
|
// Resolve agent data
|
|
374
|
-
const data = await resolveAgent(config, org,
|
|
356
|
+
const data = await resolveAgent(config, org, agentName, version, workspaceId);
|
|
375
357
|
// Reject skills
|
|
376
358
|
if (canonicalType(data.type) === 'skill') {
|
|
377
359
|
throw new errors_1.CliError("This is a skill. Use 'orch skill install <ref>' instead.");
|
|
@@ -455,7 +437,7 @@ Examples:
|
|
|
455
437
|
// Track analytics
|
|
456
438
|
await (0, analytics_1.track)('cli_pull', {
|
|
457
439
|
org,
|
|
458
|
-
agent:
|
|
440
|
+
agent: agentName,
|
|
459
441
|
version: data.version,
|
|
460
442
|
engine,
|
|
461
443
|
source: data.source,
|
|
@@ -465,7 +447,7 @@ Examples:
|
|
|
465
447
|
if (options.json) {
|
|
466
448
|
const result = {
|
|
467
449
|
success: true,
|
|
468
|
-
requested_ref: `${org}/${
|
|
450
|
+
requested_ref: `${org}/${agentName}@${version}`,
|
|
469
451
|
resolved_ref: resolvedRef,
|
|
470
452
|
output_dir: outputDir,
|
|
471
453
|
engine,
|
package/dist/commands/replay.js
CHANGED
|
@@ -91,6 +91,21 @@ function registerReplayCommand(program) {
|
|
|
91
91
|
.option('--override-policy <id>', 'Override provider policy ID for this replay')
|
|
92
92
|
.option('--no-wait', 'Queue the replay and return immediately without waiting for results')
|
|
93
93
|
.option('--json', 'Output as JSON')
|
|
94
|
+
.addHelpText('after', `
|
|
95
|
+
How snapshots work:
|
|
96
|
+
Every cloud run automatically captures a snapshot of its input, config,
|
|
97
|
+
secrets, and agent version before execution. This snapshot enables
|
|
98
|
+
deterministic replay — even if the agent has been updated since.
|
|
99
|
+
|
|
100
|
+
Local runs (--local) do not create snapshots and cannot be replayed.
|
|
101
|
+
Runs created before snapshot support was added also cannot be replayed.
|
|
102
|
+
|
|
103
|
+
Examples:
|
|
104
|
+
orch replay a1b2c3d4 Replay and wait for results
|
|
105
|
+
orch replay a1b2c3d4 --no-wait Queue and return immediately
|
|
106
|
+
orch replay a1b2c3d4 --reason "debug" Replay with audit reason
|
|
107
|
+
orch replay a1b2c3d4 --json Output as JSON
|
|
108
|
+
`)
|
|
94
109
|
.action(async (runId, options) => {
|
|
95
110
|
const config = await (0, config_1.getResolvedConfig)();
|
|
96
111
|
if (!config.apiKey) {
|
|
@@ -109,15 +124,33 @@ function registerReplayCommand(program) {
|
|
|
109
124
|
throw new errors_1.CliError(`Invalid run ID '${runId}'. Provide a full UUID or a short hex prefix (7+ characters).`);
|
|
110
125
|
}
|
|
111
126
|
// Submit replay request
|
|
112
|
-
const
|
|
127
|
+
const reqBody = {};
|
|
113
128
|
if (options.reason)
|
|
114
|
-
|
|
129
|
+
reqBody.reason = options.reason;
|
|
115
130
|
if (options.overridePolicy)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
131
|
+
reqBody.override_provider_policy_id = options.overridePolicy;
|
|
132
|
+
let replay;
|
|
133
|
+
try {
|
|
134
|
+
replay = await (0, api_1.request)(config, 'POST', `/workspaces/${workspaceId}/runs/${resolvedRunId}/replay`, {
|
|
135
|
+
body: JSON.stringify(reqBody),
|
|
136
|
+
headers: { 'Content-Type': 'application/json' },
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
if (err instanceof api_1.ApiError && err.status === 404) {
|
|
141
|
+
const isSnapshotMissing = err.message.toLowerCase().includes('snapshot');
|
|
142
|
+
if (isSnapshotMissing) {
|
|
143
|
+
throw new errors_1.CliError(`No snapshot available for run ${resolvedRunId.slice(0, 8)}.\n\n` +
|
|
144
|
+
`Snapshots are captured automatically for cloud runs. This run may have been:\n` +
|
|
145
|
+
` - A local run (--local), which does not create snapshots\n` +
|
|
146
|
+
` - Created before snapshot support was added\n\n` +
|
|
147
|
+
`Run \`orch logs ${resolvedRunId.slice(0, 8)}\` to inspect the original run.`);
|
|
148
|
+
}
|
|
149
|
+
throw new errors_1.CliError(`Run ${resolvedRunId.slice(0, 8)} not found. ` +
|
|
150
|
+
`Check the run ID and workspace, or run \`orch logs\` to list recent runs.`);
|
|
151
|
+
}
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
121
154
|
if (options.json && options.wait === false) {
|
|
122
155
|
(0, output_1.printJson)(replay);
|
|
123
156
|
return;
|
package/dist/commands/run.js
CHANGED
|
@@ -54,6 +54,7 @@ const child_process_1 = require("child_process");
|
|
|
54
54
|
const chalk_1 = __importDefault(require("chalk"));
|
|
55
55
|
const dotenv_1 = require("../lib/dotenv");
|
|
56
56
|
const config_1 = require("../lib/config");
|
|
57
|
+
const resolve_agent_1 = require("../lib/resolve-agent");
|
|
57
58
|
const api_1 = require("../lib/api");
|
|
58
59
|
const errors_1 = require("../lib/errors");
|
|
59
60
|
const output_1 = require("../lib/output");
|
|
@@ -84,18 +85,6 @@ function localCommandForEntrypoint(entrypoint) {
|
|
|
84
85
|
}
|
|
85
86
|
return 'python3';
|
|
86
87
|
}
|
|
87
|
-
function parseAgentRef(value) {
|
|
88
|
-
const [ref, versionPart] = value.split('@');
|
|
89
|
-
const version = versionPart?.trim() || DEFAULT_VERSION;
|
|
90
|
-
const segments = ref.split('/');
|
|
91
|
-
if (segments.length === 1) {
|
|
92
|
-
return { agent: segments[0], version };
|
|
93
|
-
}
|
|
94
|
-
if (segments.length === 2) {
|
|
95
|
-
return { org: segments[0], agent: segments[1], version };
|
|
96
|
-
}
|
|
97
|
-
throw new errors_1.CliError('Invalid agent reference. Use org/agent or agent format.');
|
|
98
|
-
}
|
|
99
88
|
function canonicalAgentType(typeValue) {
|
|
100
89
|
const normalized = (typeValue || 'agent').toLowerCase();
|
|
101
90
|
// Handle legacy type names: agentic → agent, code → tool
|
|
@@ -1869,15 +1858,8 @@ async function executeCloud(agentRef, file, options) {
|
|
|
1869
1858
|
if (!resolved.apiKey) {
|
|
1870
1859
|
throw new errors_1.CliError('Missing API key. Run `orchagent login` first.');
|
|
1871
1860
|
}
|
|
1872
|
-
const
|
|
1873
|
-
const
|
|
1874
|
-
const org = parsed.org ?? configFile.workspace ?? resolved.defaultOrg;
|
|
1875
|
-
if (!org) {
|
|
1876
|
-
throw new errors_1.CliError('Missing org. Use org/agent or set default org.');
|
|
1877
|
-
}
|
|
1878
|
-
// Resolve workspace context for the target org
|
|
1879
|
-
const workspaceId = await (0, api_1.resolveWorkspaceIdForOrg)(resolved, org);
|
|
1880
|
-
const agentMeta = await (0, api_1.getAgentWithFallback)(resolved, org, parsed.agent, parsed.version, workspaceId);
|
|
1861
|
+
const { org, agent: agentName, version, workspaceId } = await (0, resolve_agent_1.resolveAgentContext)(agentRef, resolved);
|
|
1862
|
+
const agentMeta = await (0, api_1.getAgentWithFallback)(resolved, org, agentName, version, workspaceId);
|
|
1881
1863
|
const cloudType = canonicalAgentType(agentMeta.type);
|
|
1882
1864
|
const cloudEngine = resolveExecutionEngine({
|
|
1883
1865
|
type: agentMeta.type,
|
|
@@ -1891,10 +1873,8 @@ async function executeCloud(agentRef, file, options) {
|
|
|
1891
1873
|
const agentRequiredSecrets = agentMeta.required_secrets;
|
|
1892
1874
|
if (agentRequiredSecrets?.length) {
|
|
1893
1875
|
try {
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
if (wsId) {
|
|
1897
|
-
const secretsResult = await (0, api_1.request)(resolved, 'GET', `/workspaces/${wsId}/secrets`);
|
|
1876
|
+
if (workspaceId) {
|
|
1877
|
+
const secretsResult = await (0, api_1.request)(resolved, 'GET', `/workspaces/${workspaceId}/secrets`);
|
|
1898
1878
|
const existingNames = new Set(secretsResult.secrets.map((s) => s.name));
|
|
1899
1879
|
const missing = agentRequiredSecrets.filter((s) => !existingNames.has(s));
|
|
1900
1880
|
if (missing.length > 0) {
|
|
@@ -1918,7 +1898,7 @@ async function executeCloud(agentRef, file, options) {
|
|
|
1918
1898
|
// --estimate-only: show cost estimate and exit without running
|
|
1919
1899
|
if (options.estimate || options.estimateOnly) {
|
|
1920
1900
|
try {
|
|
1921
|
-
const est = await (0, api_1.getAgentCostEstimate)(resolved, org,
|
|
1901
|
+
const est = await (0, api_1.getAgentCostEstimate)(resolved, org, agentName, version);
|
|
1922
1902
|
const e = est.estimate;
|
|
1923
1903
|
if (e.sample_size === 0) {
|
|
1924
1904
|
process.stderr.write(chalk_1.default.yellow('\nNo run history available for cost estimation.\n'));
|
|
@@ -2245,7 +2225,7 @@ async function executeCloud(agentRef, file, options) {
|
|
|
2245
2225
|
}
|
|
2246
2226
|
} // end of non-injection path
|
|
2247
2227
|
const verboseQs = options.verbose ? '?verbose=true' : '';
|
|
2248
|
-
const url = `${resolved.apiUrl.replace(/\/$/, '')}/${org}/${
|
|
2228
|
+
const url = `${resolved.apiUrl.replace(/\/$/, '')}/${org}/${agentName}/${version}/${endpoint}${verboseQs}`;
|
|
2249
2229
|
// Enable SSE streaming for sandbox-backed engines (unless --json or --no-stream or --output)
|
|
2250
2230
|
const isManagedLoopAgent = cloudType === 'agent' && cloudEngine === 'managed_loop';
|
|
2251
2231
|
const isCodeRuntimeAgent = cloudEngine === 'code_runtime';
|
|
@@ -2257,13 +2237,13 @@ async function executeCloud(agentRef, file, options) {
|
|
|
2257
2237
|
}
|
|
2258
2238
|
// Print verbose debug info before request
|
|
2259
2239
|
if (options.verbose && !options.json) {
|
|
2260
|
-
process.stderr.write(chalk_1.default.gray(`\n[verbose] ${org}/${
|
|
2240
|
+
process.stderr.write(chalk_1.default.gray(`\n[verbose] ${org}/${agentName}@${version}\n` +
|
|
2261
2241
|
`[verbose] type=${cloudType} engine=${cloudEngine} endpoint=${endpoint}\n` +
|
|
2262
2242
|
`[verbose] stream=${wantStream ? 'yes' : 'no'} url=${url}\n`));
|
|
2263
2243
|
}
|
|
2264
2244
|
const { spinner, dispose: disposeSpinner } = options.json
|
|
2265
2245
|
? { spinner: null, dispose: () => { } }
|
|
2266
|
-
: (0, spinner_1.createElapsedSpinner)(`Running ${org}/${
|
|
2246
|
+
: (0, spinner_1.createElapsedSpinner)(`Running ${org}/${agentName}@${version}...`);
|
|
2267
2247
|
spinner?.start();
|
|
2268
2248
|
// Streamed sandbox runs can take longer; use 10 min timeout (or --wait-timeout).
|
|
2269
2249
|
const waitTimeoutSec = options.waitTimeout ? parseInt(options.waitTimeout, 10) : undefined;
|
|
@@ -2432,11 +2412,11 @@ async function executeCloud(agentRef, file, options) {
|
|
|
2432
2412
|
let finalPayload = null;
|
|
2433
2413
|
let hadError = false;
|
|
2434
2414
|
if (options.verbose) {
|
|
2435
|
-
process.stderr.write(chalk_1.default.gray(`\nStreaming ${org}/${
|
|
2415
|
+
process.stderr.write(chalk_1.default.gray(`\nStreaming ${org}/${agentName}@${version} (verbose):\n`));
|
|
2436
2416
|
process.stderr.write(chalk_1.default.gray(` type=${cloudType} engine=${cloudEngine} endpoint=${endpoint}\n`));
|
|
2437
2417
|
}
|
|
2438
2418
|
else {
|
|
2439
|
-
process.stderr.write(chalk_1.default.gray(`\nStreaming ${org}/${
|
|
2419
|
+
process.stderr.write(chalk_1.default.gray(`\nStreaming ${org}/${agentName}@${version}:\n`));
|
|
2440
2420
|
}
|
|
2441
2421
|
let progressErrorShown = false;
|
|
2442
2422
|
let streamTimedOut = false;
|
|
@@ -2497,7 +2477,7 @@ async function executeCloud(agentRef, file, options) {
|
|
|
2497
2477
|
? ''
|
|
2498
2478
|
: chalk_1.default.gray('Tip: Use --wait-timeout <seconds> to wait longer.\n')));
|
|
2499
2479
|
await (0, analytics_1.track)('cli_run', {
|
|
2500
|
-
agent: `${org}/${
|
|
2480
|
+
agent: `${org}/${agentName}@${version}`,
|
|
2501
2481
|
input_type: hasInjection ? 'file_injection' : unkeyedFileArgs.length > 0 ? 'file' : options.data ? 'json' : 'empty',
|
|
2502
2482
|
mode: 'cloud',
|
|
2503
2483
|
streamed: true,
|
|
@@ -2508,7 +2488,7 @@ async function executeCloud(agentRef, file, options) {
|
|
|
2508
2488
|
throw err;
|
|
2509
2489
|
}
|
|
2510
2490
|
await (0, analytics_1.track)('cli_run', {
|
|
2511
|
-
agent: `${org}/${
|
|
2491
|
+
agent: `${org}/${agentName}@${version}`,
|
|
2512
2492
|
input_type: hasInjection ? 'file_injection' : unkeyedFileArgs.length > 0 ? 'file' : options.data ? 'json' : 'empty',
|
|
2513
2493
|
mode: 'cloud',
|
|
2514
2494
|
streamed: true,
|
|
@@ -2549,14 +2529,14 @@ async function executeCloud(agentRef, file, options) {
|
|
|
2549
2529
|
}
|
|
2550
2530
|
const runId = response.headers?.get?.('x-run-id');
|
|
2551
2531
|
if (runId) {
|
|
2552
|
-
process.stderr.write(chalk_1.default.gray(`
|
|
2532
|
+
process.stderr.write(chalk_1.default.gray(`Snapshot saved · Logs: orch logs ${runId} · Replay: orch replay ${runId}\n`));
|
|
2553
2533
|
}
|
|
2554
2534
|
}
|
|
2555
2535
|
}
|
|
2556
2536
|
}
|
|
2557
2537
|
return;
|
|
2558
2538
|
}
|
|
2559
|
-
spinner?.succeed(`Ran ${org}/${
|
|
2539
|
+
spinner?.succeed(`Ran ${org}/${agentName}@${version}`);
|
|
2560
2540
|
const inputType = hasInjection
|
|
2561
2541
|
? 'file_injection'
|
|
2562
2542
|
: unkeyedFileArgs.length > 0
|
|
@@ -2569,7 +2549,7 @@ async function executeCloud(agentRef, file, options) {
|
|
|
2569
2549
|
? 'metadata'
|
|
2570
2550
|
: 'empty';
|
|
2571
2551
|
await (0, analytics_1.track)('cli_run', {
|
|
2572
|
-
agent: `${org}/${
|
|
2552
|
+
agent: `${org}/${agentName}@${version}`,
|
|
2573
2553
|
input_type: inputType,
|
|
2574
2554
|
mode: 'cloud',
|
|
2575
2555
|
});
|
|
@@ -2638,7 +2618,7 @@ async function executeCloud(agentRef, file, options) {
|
|
|
2638
2618
|
}
|
|
2639
2619
|
const runId = response.headers?.get?.('x-run-id');
|
|
2640
2620
|
if (runId) {
|
|
2641
|
-
process.stderr.write(chalk_1.default.gray(`
|
|
2621
|
+
process.stderr.write(chalk_1.default.gray(`Snapshot saved · Logs: orch logs ${runId} · Replay: orch replay ${runId}\n`));
|
|
2642
2622
|
}
|
|
2643
2623
|
}
|
|
2644
2624
|
}
|
|
@@ -2670,21 +2650,14 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2670
2650
|
}
|
|
2671
2651
|
}
|
|
2672
2652
|
const resolved = await (0, config_1.getResolvedConfig)();
|
|
2673
|
-
const
|
|
2674
|
-
const configFile = await (0, config_1.loadConfig)();
|
|
2675
|
-
const org = parsed.org ?? configFile.workspace ?? resolved.defaultOrg;
|
|
2676
|
-
if (!org) {
|
|
2677
|
-
throw new errors_1.CliError('Missing org. Use org/agent format.');
|
|
2678
|
-
}
|
|
2679
|
-
// Resolve workspace context for the target org
|
|
2680
|
-
const workspaceId = await (0, api_1.resolveWorkspaceIdForOrg)(resolved, org);
|
|
2653
|
+
const { org, agent: localAgentName, version: localVersion, workspaceId } = await (0, resolve_agent_1.resolveAgentContext)(agentRef, resolved);
|
|
2681
2654
|
// Download agent definition with spinner
|
|
2682
|
-
const agentData = await (0, spinner_1.withSpinner)(`Downloading ${org}/${
|
|
2655
|
+
const agentData = await (0, spinner_1.withSpinner)(`Downloading ${org}/${localAgentName}@${localVersion}...`, async () => {
|
|
2683
2656
|
try {
|
|
2684
|
-
return await downloadAgent(resolved, org,
|
|
2657
|
+
return await downloadAgent(resolved, org, localAgentName, localVersion, workspaceId);
|
|
2685
2658
|
}
|
|
2686
2659
|
catch (err) {
|
|
2687
|
-
const agentMeta = await (0, api_1.getPublicAgent)(resolved, org,
|
|
2660
|
+
const agentMeta = await (0, api_1.getPublicAgent)(resolved, org, localAgentName, localVersion);
|
|
2688
2661
|
return {
|
|
2689
2662
|
type: agentMeta.type || 'agent',
|
|
2690
2663
|
run_mode: agentMeta.run_mode ?? null,
|
|
@@ -2696,7 +2669,7 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2696
2669
|
supported_providers: agentMeta.supported_providers || ['any'],
|
|
2697
2670
|
};
|
|
2698
2671
|
}
|
|
2699
|
-
}, { successText: `Downloaded ${org}/${
|
|
2672
|
+
}, { successText: `Downloaded ${org}/${localAgentName}@${localVersion}` });
|
|
2700
2673
|
const localType = canonicalAgentType(agentData.type);
|
|
2701
2674
|
const localEngine = resolveExecutionEngine(agentData);
|
|
2702
2675
|
// Skills cannot be run directly
|
|
@@ -2704,8 +2677,8 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2704
2677
|
throw new errors_1.CliError('Skills cannot be run directly.\n\n' +
|
|
2705
2678
|
'Skills are instructions meant to be injected into AI agent contexts.\n\n' +
|
|
2706
2679
|
'Options:\n' +
|
|
2707
|
-
` Install for AI tools: orchagent skill install ${org}/${
|
|
2708
|
-
` Use with an agent: orchagent run <agent> --skills ${org}/${
|
|
2680
|
+
` Install for AI tools: orchagent skill install ${org}/${localAgentName}\n` +
|
|
2681
|
+
` Use with an agent: orchagent run <agent> --skills ${org}/${localAgentName}`);
|
|
2709
2682
|
}
|
|
2710
2683
|
// Managed-loop agents execute locally with the agent runner.
|
|
2711
2684
|
if (localEngine === 'managed_loop') {
|
|
@@ -2713,11 +2686,11 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2713
2686
|
throw new errors_1.CliError('Agent prompt not available for local execution.\n\n' +
|
|
2714
2687
|
'This agent may have local download disabled.\n' +
|
|
2715
2688
|
'Remove the --local flag to run in the cloud:\n' +
|
|
2716
|
-
` orch run ${org}/${
|
|
2689
|
+
` orch run ${org}/${localAgentName}@${localVersion} --data '{"task": "..."}'`);
|
|
2717
2690
|
}
|
|
2718
2691
|
if (!options.input) {
|
|
2719
2692
|
process.stderr.write(`\nAgent downloaded. Run with:\n`);
|
|
2720
|
-
process.stderr.write(` orch run ${org}/${
|
|
2693
|
+
process.stderr.write(` orch run ${org}/${localAgentName}@${localVersion} --local --data '{\"task\": \"...\"}'\n`);
|
|
2721
2694
|
return;
|
|
2722
2695
|
}
|
|
2723
2696
|
// Resolve @file.json / @- stdin syntax before parsing
|
|
@@ -2731,7 +2704,7 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2731
2704
|
}
|
|
2732
2705
|
warnInputSchemaErrors(agentInputData, agentData.input_schema);
|
|
2733
2706
|
// Write prompt to temp dir and run
|
|
2734
|
-
const tempAgentDir = path_1.default.join(os_1.default.tmpdir(), `orchagent-agent-${
|
|
2707
|
+
const tempAgentDir = path_1.default.join(os_1.default.tmpdir(), `orchagent-agent-${localAgentName}-${Date.now()}`);
|
|
2735
2708
|
await promises_1.default.mkdir(tempAgentDir, { recursive: true });
|
|
2736
2709
|
try {
|
|
2737
2710
|
await promises_1.default.writeFile(path_1.default.join(tempAgentDir, 'prompt.md'), agentData.prompt);
|
|
@@ -2761,7 +2734,7 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2761
2734
|
}
|
|
2762
2735
|
if (choice === 'server') {
|
|
2763
2736
|
process.stderr.write(`\nRun without --local for server execution:\n`);
|
|
2764
|
-
process.stderr.write(` orch run ${org}/${
|
|
2737
|
+
process.stderr.write(` orch run ${org}/${localAgentName}@${localVersion} --data '{...}'\n\n`);
|
|
2765
2738
|
process.exit(0);
|
|
2766
2739
|
}
|
|
2767
2740
|
await downloadDependenciesRecursively(resolved, depStatuses, new Set(), workspaceId);
|
|
@@ -2784,13 +2757,13 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2784
2757
|
}
|
|
2785
2758
|
}
|
|
2786
2759
|
// Save locally
|
|
2787
|
-
const agentDir = await saveAgentLocally(org,
|
|
2760
|
+
const agentDir = await saveAgentLocally(org, localAgentName, agentData);
|
|
2788
2761
|
process.stderr.write(`\nAgent saved to: ${agentDir}\n`);
|
|
2789
2762
|
if (localEngine === 'code_runtime') {
|
|
2790
2763
|
if (agentData.has_bundle) {
|
|
2791
2764
|
if (options.downloadOnly) {
|
|
2792
2765
|
process.stdout.write(`\nCode runtime bundle is available for local execution.\n`);
|
|
2793
|
-
process.stdout.write(`Run with: orch run ${org}/${
|
|
2766
|
+
process.stdout.write(`Run with: orch run ${org}/${localAgentName} --local [args...]\n`);
|
|
2794
2767
|
return;
|
|
2795
2768
|
}
|
|
2796
2769
|
// Pre-build injected payload for bundle agent if keyed files/mounts present
|
|
@@ -2806,13 +2779,13 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2806
2779
|
});
|
|
2807
2780
|
bundleInput = injected.body;
|
|
2808
2781
|
}
|
|
2809
|
-
await executeBundleAgent(resolved, org,
|
|
2782
|
+
await executeBundleAgent(resolved, org, localAgentName, localVersion, agentData, args, bundleInput, workspaceId);
|
|
2810
2783
|
return;
|
|
2811
2784
|
}
|
|
2812
2785
|
if (agentData.run_command && (agentData.source_url || agentData.pip_package)) {
|
|
2813
2786
|
if (options.downloadOnly) {
|
|
2814
2787
|
process.stdout.write(`\nTool ready for local execution.\n`);
|
|
2815
|
-
process.stdout.write(`Run with: orch run ${org}/${
|
|
2788
|
+
process.stdout.write(`Run with: orch run ${org}/${localAgentName} --local [args...]\n`);
|
|
2816
2789
|
return;
|
|
2817
2790
|
}
|
|
2818
2791
|
await executeTool(agentData, args);
|
|
@@ -2820,12 +2793,12 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2820
2793
|
}
|
|
2821
2794
|
// Fallback: code runtime agent doesn't support local execution.
|
|
2822
2795
|
process.stdout.write(`\nThis code runtime agent is configured for server execution.\n`);
|
|
2823
|
-
process.stdout.write(`\nRun without --local: orch run ${org}/${
|
|
2796
|
+
process.stdout.write(`\nRun without --local: orch run ${org}/${localAgentName}@${localVersion} --data '{...}'\n`);
|
|
2824
2797
|
return;
|
|
2825
2798
|
}
|
|
2826
2799
|
if (options.downloadOnly) {
|
|
2827
2800
|
process.stdout.write(`\nAgent downloaded. Run with:\n`);
|
|
2828
|
-
process.stdout.write(` orch run ${org}/${
|
|
2801
|
+
process.stdout.write(` orch run ${org}/${localAgentName}@${localVersion} --local --input '{...}'\n`);
|
|
2829
2802
|
return;
|
|
2830
2803
|
}
|
|
2831
2804
|
// Check for keyed file/mount injection
|
|
@@ -2835,7 +2808,7 @@ async function executeLocal(agentRef, args, options) {
|
|
|
2835
2808
|
// Direct LLM agents execute locally via prompt composition.
|
|
2836
2809
|
if (!options.input && !execLocalHasInjection) {
|
|
2837
2810
|
process.stdout.write(`\nAgent ready.\n`);
|
|
2838
|
-
process.stdout.write(`Run with: orch run ${org}/${
|
|
2811
|
+
process.stdout.write(`Run with: orch run ${org}/${localAgentName}@${localVersion} --local --input '{...}'\n`);
|
|
2839
2812
|
return;
|
|
2840
2813
|
}
|
|
2841
2814
|
let inputData;
|
|
@@ -162,6 +162,7 @@ function registerScheduleCommand(program) {
|
|
|
162
162
|
.option('--alert-webhook <url>', 'Webhook URL to POST on failure (HTTPS required)')
|
|
163
163
|
.option('--alert-on-failure-count <n>', 'Number of consecutive failures before alerting (default: 3)', parseInt)
|
|
164
164
|
.option('--workspace <slug>', 'Workspace slug (default: current workspace)')
|
|
165
|
+
.option('--json', 'Output as JSON')
|
|
165
166
|
.action(async (agentArg, options) => {
|
|
166
167
|
const config = await (0, config_1.getResolvedConfig)();
|
|
167
168
|
if (!config.apiKey) {
|
|
@@ -217,6 +218,10 @@ function registerScheduleCommand(program) {
|
|
|
217
218
|
body: JSON.stringify(body),
|
|
218
219
|
headers: { 'Content-Type': 'application/json' },
|
|
219
220
|
});
|
|
221
|
+
if (options.json) {
|
|
222
|
+
(0, output_1.printJson)(result);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
220
225
|
const s = result.schedule;
|
|
221
226
|
process.stdout.write(chalk_1.default.green('\u2713') + ` Schedule created\n\n`);
|
|
222
227
|
process.stdout.write(` ID: ${s.id}\n`);
|
|
@@ -264,6 +269,7 @@ function registerScheduleCommand(program) {
|
|
|
264
269
|
.option('--alert-on-failure-count <n>', 'Number of consecutive failures before alerting', parseInt)
|
|
265
270
|
.option('--clear-alert-webhook', 'Remove the alert webhook URL')
|
|
266
271
|
.option('--workspace <slug>', 'Workspace slug (default: current workspace)')
|
|
272
|
+
.option('--json', 'Output as JSON')
|
|
267
273
|
.action(async (partialScheduleId, options) => {
|
|
268
274
|
const config = await (0, config_1.getResolvedConfig)();
|
|
269
275
|
if (!config.apiKey) {
|
|
@@ -322,6 +328,10 @@ function registerScheduleCommand(program) {
|
|
|
322
328
|
body: JSON.stringify(updates),
|
|
323
329
|
headers: { 'Content-Type': 'application/json' },
|
|
324
330
|
});
|
|
331
|
+
if (options.json) {
|
|
332
|
+
(0, output_1.printJson)(result);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
325
335
|
const s = result.schedule;
|
|
326
336
|
process.stdout.write(chalk_1.default.green('\u2713') + ` Schedule updated\n\n`);
|
|
327
337
|
process.stdout.write(` ID: ${s.id}\n`);
|
|
@@ -349,6 +359,7 @@ function registerScheduleCommand(program) {
|
|
|
349
359
|
.description('Delete a schedule')
|
|
350
360
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
351
361
|
.option('--workspace <slug>', 'Workspace slug (default: current workspace)')
|
|
362
|
+
.option('--json', 'Output as JSON (implies --yes)')
|
|
352
363
|
.action(async (partialScheduleId, options) => {
|
|
353
364
|
const config = await (0, config_1.getResolvedConfig)();
|
|
354
365
|
if (!config.apiKey) {
|
|
@@ -356,7 +367,7 @@ function registerScheduleCommand(program) {
|
|
|
356
367
|
}
|
|
357
368
|
const workspaceId = await resolveWorkspaceId(config, options.workspace);
|
|
358
369
|
const scheduleId = await resolveScheduleId(config, partialScheduleId, workspaceId);
|
|
359
|
-
if (!options.yes) {
|
|
370
|
+
if (!options.yes && !options.json) {
|
|
360
371
|
const rl = promises_1.default.createInterface({
|
|
361
372
|
input: process.stdin,
|
|
362
373
|
output: process.stdout,
|
|
@@ -368,7 +379,11 @@ function registerScheduleCommand(program) {
|
|
|
368
379
|
return;
|
|
369
380
|
}
|
|
370
381
|
}
|
|
371
|
-
await (0, api_1.request)(config, 'DELETE', `/workspaces/${workspaceId}/schedules/${scheduleId}`);
|
|
382
|
+
const result = await (0, api_1.request)(config, 'DELETE', `/workspaces/${workspaceId}/schedules/${scheduleId}`);
|
|
383
|
+
if (options.json) {
|
|
384
|
+
(0, output_1.printJson)({ ...result, id: scheduleId });
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
372
387
|
process.stdout.write(chalk_1.default.green('\u2713') + ` Schedule ${scheduleId} deleted\n`);
|
|
373
388
|
});
|
|
374
389
|
// orch schedule trigger <schedule-id>
|
|
@@ -378,6 +393,7 @@ function registerScheduleCommand(program) {
|
|
|
378
393
|
.option('--data <json>', 'Override input data as JSON')
|
|
379
394
|
.addOption(new commander_1.Option('--input <json>').hideHelp())
|
|
380
395
|
.option('--workspace <slug>', 'Workspace slug (default: current workspace)')
|
|
396
|
+
.option('--json', 'Output as JSON')
|
|
381
397
|
.action(async (partialScheduleId, options) => {
|
|
382
398
|
const config = await (0, config_1.getResolvedConfig)();
|
|
383
399
|
if (!config.apiKey) {
|
|
@@ -396,11 +412,17 @@ function registerScheduleCommand(program) {
|
|
|
396
412
|
throw new errors_1.CliError('Invalid JSON in --data');
|
|
397
413
|
}
|
|
398
414
|
}
|
|
399
|
-
|
|
415
|
+
if (!options.json) {
|
|
416
|
+
process.stdout.write('Triggering schedule...\n');
|
|
417
|
+
}
|
|
400
418
|
const result = await (0, api_1.request)(config, 'POST', `/workspaces/${workspaceId}/schedules/${scheduleId}/trigger`, body ? {
|
|
401
419
|
body,
|
|
402
420
|
headers: { 'Content-Type': 'application/json' },
|
|
403
421
|
} : {});
|
|
422
|
+
if (options.json) {
|
|
423
|
+
(0, output_1.printJson)(result);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
404
426
|
// Status-aware header message
|
|
405
427
|
const isAsync = result.status === 'queued' || result.status === 'deduplicated';
|
|
406
428
|
if (isAsync) {
|
|
@@ -565,6 +587,7 @@ function registerScheduleCommand(program) {
|
|
|
565
587
|
.command('test-alert <schedule-id>')
|
|
566
588
|
.description('Send a test alert to the schedule\'s configured webhook URL')
|
|
567
589
|
.option('--workspace <slug>', 'Workspace slug (default: current workspace)')
|
|
590
|
+
.option('--json', 'Output as JSON')
|
|
568
591
|
.action(async (partialScheduleId, options) => {
|
|
569
592
|
const config = await (0, config_1.getResolvedConfig)();
|
|
570
593
|
if (!config.apiKey) {
|
|
@@ -572,8 +595,14 @@ function registerScheduleCommand(program) {
|
|
|
572
595
|
}
|
|
573
596
|
const workspaceId = await resolveWorkspaceId(config, options.workspace);
|
|
574
597
|
const scheduleId = await resolveScheduleId(config, partialScheduleId, workspaceId);
|
|
575
|
-
|
|
598
|
+
if (!options.json) {
|
|
599
|
+
process.stdout.write('Sending test alert...\n');
|
|
600
|
+
}
|
|
576
601
|
const result = await (0, api_1.request)(config, 'POST', `/workspaces/${workspaceId}/schedules/${scheduleId}/test-alert`);
|
|
602
|
+
if (options.json) {
|
|
603
|
+
(0, output_1.printJson)({ ...result, schedule_id: scheduleId });
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
577
606
|
if (result.success) {
|
|
578
607
|
process.stdout.write(chalk_1.default.green('\u2713') + ' Test alert delivered successfully\n');
|
|
579
608
|
}
|
|
@@ -587,6 +616,7 @@ function registerScheduleCommand(program) {
|
|
|
587
616
|
.description('Regenerate the webhook secret (invalidates old URL)')
|
|
588
617
|
.option('--workspace <slug>', 'Workspace slug (default: current workspace)')
|
|
589
618
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
619
|
+
.option('--json', 'Output as JSON (implies --yes)')
|
|
590
620
|
.action(async (partialScheduleId, options) => {
|
|
591
621
|
const config = await (0, config_1.getResolvedConfig)();
|
|
592
622
|
if (!config.apiKey) {
|
|
@@ -594,7 +624,7 @@ function registerScheduleCommand(program) {
|
|
|
594
624
|
}
|
|
595
625
|
const workspaceId = await resolveWorkspaceId(config, options.workspace);
|
|
596
626
|
const scheduleId = await resolveScheduleId(config, partialScheduleId, workspaceId);
|
|
597
|
-
if (!options.yes) {
|
|
627
|
+
if (!options.yes && !options.json) {
|
|
598
628
|
const rl = promises_1.default.createInterface({
|
|
599
629
|
input: process.stdin,
|
|
600
630
|
output: process.stdout,
|
|
@@ -609,6 +639,10 @@ function registerScheduleCommand(program) {
|
|
|
609
639
|
}
|
|
610
640
|
}
|
|
611
641
|
const result = await (0, api_1.request)(config, 'POST', `/workspaces/${workspaceId}/schedules/${scheduleId}/regenerate-webhook`);
|
|
642
|
+
if (options.json) {
|
|
643
|
+
(0, output_1.printJson)({ ...result, schedule_id: scheduleId });
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
612
646
|
process.stdout.write(chalk_1.default.green('\u2713') + ' Webhook secret regenerated\n\n');
|
|
613
647
|
process.stdout.write(` ${chalk_1.default.bold('New Webhook URL')} (save this — retrieve later with ${chalk_1.default.cyan('orch schedule info --reveal')}):\n`);
|
|
614
648
|
process.stdout.write(` ${result.webhook_url}\n\n`);
|
|
@@ -11,26 +11,11 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
11
11
|
const config_1 = require("../lib/config");
|
|
12
12
|
const api_1 = require("../lib/api");
|
|
13
13
|
const errors_1 = require("../lib/errors");
|
|
14
|
+
const resolve_agent_1 = require("../lib/resolve-agent");
|
|
14
15
|
const output_1 = require("../lib/output");
|
|
15
16
|
const spinner_1 = require("../lib/spinner");
|
|
16
17
|
const llm_1 = require("../lib/llm");
|
|
17
18
|
const analytics_1 = require("../lib/analytics");
|
|
18
|
-
const DEFAULT_VERSION = 'latest';
|
|
19
|
-
function parseAgentRef(value) {
|
|
20
|
-
const [ref, versionPart] = value.split('@');
|
|
21
|
-
const version = versionPart?.trim() || DEFAULT_VERSION;
|
|
22
|
-
const segments = ref.split('/');
|
|
23
|
-
if (segments.length === 1) {
|
|
24
|
-
return { agent: segments[0], version };
|
|
25
|
-
}
|
|
26
|
-
if (segments.length === 2) {
|
|
27
|
-
return { org: segments[0], agent: segments[1], version };
|
|
28
|
-
}
|
|
29
|
-
if (segments.length === 3) {
|
|
30
|
-
return { org: segments[0], agent: segments[1], version: segments[2] };
|
|
31
|
-
}
|
|
32
|
-
throw new errors_1.CliError('Invalid agent reference. Use org/agent/version or org/agent@version format.');
|
|
33
|
-
}
|
|
34
19
|
// Severity color mapping
|
|
35
20
|
function severityColor(severity) {
|
|
36
21
|
switch (severity.toLowerCase()) {
|
|
@@ -189,15 +174,8 @@ Examples:
|
|
|
189
174
|
if (!resolved.apiKey) {
|
|
190
175
|
throw new errors_1.CliError('Missing API key. Run `orchagent login` first.');
|
|
191
176
|
}
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
const org = parsed.org ?? configFile.workspace ?? resolved.defaultOrg;
|
|
195
|
-
if (!org) {
|
|
196
|
-
throw new errors_1.CliError('Missing org. Use org/agent or set default org.');
|
|
197
|
-
}
|
|
198
|
-
const agentId = `${org}/${parsed.agent}/${parsed.version}`;
|
|
199
|
-
// Resolve workspace context for the target org
|
|
200
|
-
const workspaceId = await (0, api_1.resolveWorkspaceIdForOrg)(resolved, org);
|
|
177
|
+
const { org, agent: agentName, version, workspaceId } = await (0, resolve_agent_1.resolveAgentContext)(agentRef, resolved);
|
|
178
|
+
const agentId = `${org}/${agentName}/${version}`;
|
|
201
179
|
// Detect LLM key for the scan
|
|
202
180
|
let llmKey;
|
|
203
181
|
let llmProvider;
|
|
@@ -235,6 +213,12 @@ Examples:
|
|
|
235
213
|
if (options.maxAttacks) {
|
|
236
214
|
requestBody.max_attacks = options.maxAttacks;
|
|
237
215
|
}
|
|
216
|
+
// Send provider preference so gateway can narrow vault key search
|
|
217
|
+
// (even when no local key is found, the gateway resolves from vault)
|
|
218
|
+
const effectiveProvider = llmProvider || options.provider;
|
|
219
|
+
if (effectiveProvider) {
|
|
220
|
+
requestBody.llm_provider = effectiveProvider;
|
|
221
|
+
}
|
|
238
222
|
const url = `${resolved.apiUrl.replace(/\/$/, '')}/security/test`;
|
|
239
223
|
// Make the API call with a spinner
|
|
240
224
|
const spinner = (0, spinner_1.createSpinner)(`Scanning ${agentId} for vulnerabilities...`);
|
|
@@ -8,6 +8,7 @@ const promises_1 = __importDefault(require("readline/promises"));
|
|
|
8
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
9
|
const config_1 = require("../lib/config");
|
|
10
10
|
const api_1 = require("../lib/api");
|
|
11
|
+
const agent_ref_1 = require("../lib/agent-ref");
|
|
11
12
|
const errors_1 = require("../lib/errors");
|
|
12
13
|
const analytics_1 = require("../lib/analytics");
|
|
13
14
|
const output_1 = require("../lib/output");
|
|
@@ -34,7 +35,7 @@ async function promptText(message) {
|
|
|
34
35
|
}
|
|
35
36
|
function registerTransferCommand(program) {
|
|
36
37
|
program
|
|
37
|
-
.command('transfer <agent
|
|
38
|
+
.command('transfer <agent>')
|
|
38
39
|
.description('Transfer an agent to another workspace')
|
|
39
40
|
.requiredOption('--to <workspace-slug>', 'Target workspace slug')
|
|
40
41
|
.option('-w, --workspace <workspace-slug>', 'Source workspace slug (defaults to active workspace)')
|
|
@@ -43,12 +44,13 @@ function registerTransferCommand(program) {
|
|
|
43
44
|
.option('--json', 'Output result as JSON')
|
|
44
45
|
.addHelpText('after', `
|
|
45
46
|
Examples:
|
|
46
|
-
orch transfer my-agent --to team-workspace # Transfer
|
|
47
|
+
orch transfer my-agent --to team-workspace # Transfer by name
|
|
48
|
+
orch transfer my-org/my-agent --to team-workspace # Transfer using org/agent format
|
|
47
49
|
orch transfer my-agent --to team-workspace --workspace my-team
|
|
48
50
|
orch transfer my-agent --to team-workspace --dry-run # Preview transfer
|
|
49
51
|
orch transfer my-agent --to team-workspace --yes # Skip confirmation
|
|
50
52
|
`)
|
|
51
|
-
.action(async (
|
|
53
|
+
.action(async (agentArg, options) => {
|
|
52
54
|
const write = (message) => {
|
|
53
55
|
if (!options.json)
|
|
54
56
|
process.stdout.write(message);
|
|
@@ -58,6 +60,14 @@ Examples:
|
|
|
58
60
|
if (!config.apiKey) {
|
|
59
61
|
throw new errors_1.CliError('Not logged in. Run `orchagent login` first.');
|
|
60
62
|
}
|
|
63
|
+
// Parse org/agent[@version] or bare agent name
|
|
64
|
+
const parsed = (0, agent_ref_1.parseAgentRef)(agentArg);
|
|
65
|
+
const agentName = parsed.agent;
|
|
66
|
+
// If org was provided via org/agent format, use it as source workspace
|
|
67
|
+
// --workspace flag takes precedence if both are given
|
|
68
|
+
if (parsed.org && options.workspace && parsed.org !== options.workspace) {
|
|
69
|
+
throw new errors_1.CliError(`Conflicting source workspace: '${parsed.org}' (from agent ref) vs '${options.workspace}' (from --workspace flag).`);
|
|
70
|
+
}
|
|
61
71
|
write('Finding agent and workspaces...\n');
|
|
62
72
|
// Fetch workspace list first (needed to resolve source/target IDs).
|
|
63
73
|
const workspacesResponse = await (0, api_1.request)(config, 'GET', '/workspaces');
|
|
@@ -66,8 +76,8 @@ Examples:
|
|
|
66
76
|
if (!targetWorkspace) {
|
|
67
77
|
throw new errors_1.CliError(`Workspace '${options.to}' not found. Run \`orchagent workspace list\` to see available workspaces.`);
|
|
68
78
|
}
|
|
69
|
-
// Resolve source workspace
|
|
70
|
-
const sourceWorkspaceSlug = options.workspace ?? configFile.workspace;
|
|
79
|
+
// Resolve source workspace: --workspace flag > org from ref > config workspace
|
|
80
|
+
const sourceWorkspaceSlug = options.workspace ?? parsed.org ?? configFile.workspace;
|
|
71
81
|
const sourceWorkspace = sourceWorkspaceSlug
|
|
72
82
|
? workspacesResponse.workspaces.find((w) => w.slug === sourceWorkspaceSlug)
|
|
73
83
|
: null;
|
package/dist/commands/tree.js
CHANGED
|
@@ -27,9 +27,21 @@ function registerTreeCommand(program) {
|
|
|
27
27
|
throw new errors_1.CliError('Missing org. Use org/agent format or set default org.');
|
|
28
28
|
}
|
|
29
29
|
const { agent, version } = parsed;
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
// Public-first fallback: try public tree endpoint (works for any public
|
|
31
|
+
// agent regardless of caller context), then fall back to authenticated
|
|
32
|
+
// endpoint with workspace header for private agents. Matches the pattern
|
|
33
|
+
// used by info/fork/estimate commands. (T12-04)
|
|
34
|
+
let tree;
|
|
35
|
+
try {
|
|
36
|
+
tree = await (0, api_1.publicRequest)(config, `/public/agents/${org}/${agent}/${version}/tree`);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
if (!(err instanceof api_1.ApiError) || err.status !== 404)
|
|
40
|
+
throw err;
|
|
41
|
+
// Public endpoint returned 404 — try authenticated endpoint for private agents
|
|
42
|
+
const workspaceId = await (0, api_1.resolveWorkspaceIdForOrg)(config, org);
|
|
43
|
+
tree = await (0, api_1.request)(config, 'GET', `/agents/${org}/${agent}/${version}/tree`, workspaceId ? { headers: { 'X-Workspace-Id': workspaceId } } : undefined);
|
|
44
|
+
}
|
|
33
45
|
if (options.json) {
|
|
34
46
|
console.log(JSON.stringify(tree, null, 2));
|
|
35
47
|
return;
|
package/dist/lib/bundle.js
CHANGED
|
@@ -137,18 +137,23 @@ async function createCodeBundle(sourceDir, outputPath, options = {}) {
|
|
|
137
137
|
const output = (0, fs_1.createWriteStream)(outputPath);
|
|
138
138
|
const archive = (0, archiver_1.default)('zip', { zlib: { level: 9 } });
|
|
139
139
|
let fileCount = 0;
|
|
140
|
+
const files = [];
|
|
140
141
|
output.on('close', () => {
|
|
141
142
|
resolve({
|
|
142
143
|
path: outputPath,
|
|
143
144
|
sizeBytes: archive.pointer(),
|
|
144
145
|
fileCount,
|
|
146
|
+
files,
|
|
145
147
|
});
|
|
146
148
|
});
|
|
147
149
|
archive.on('error', (err) => {
|
|
148
150
|
reject(err);
|
|
149
151
|
});
|
|
150
|
-
archive.on('entry', () => {
|
|
152
|
+
archive.on('entry', (entry) => {
|
|
151
153
|
fileCount++;
|
|
154
|
+
if (entry.name) {
|
|
155
|
+
files.push(entry.name);
|
|
156
|
+
}
|
|
152
157
|
});
|
|
153
158
|
archive.pipe(output);
|
|
154
159
|
// Add directory contents with exclusions
|
|
@@ -235,6 +240,7 @@ async function previewBundle(sourceDir, options = {}) {
|
|
|
235
240
|
totalSizeBytes,
|
|
236
241
|
entrypoint,
|
|
237
242
|
excludePatterns,
|
|
243
|
+
files,
|
|
238
244
|
};
|
|
239
245
|
}
|
|
240
246
|
/**
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveOrg = resolveOrg;
|
|
4
|
+
exports.resolveAgentContext = resolveAgentContext;
|
|
5
|
+
const agent_ref_1 = require("./agent-ref");
|
|
6
|
+
const config_1 = require("./config");
|
|
7
|
+
const api_1 = require("./api");
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the org from a parsed AgentRef using the standard fallback chain:
|
|
11
|
+
* 1. Explicit org from ref (org/agent@version)
|
|
12
|
+
* 2. Workspace from config file
|
|
13
|
+
* 3. defaultOrg from resolved config
|
|
14
|
+
*
|
|
15
|
+
* Throws CliError if no org can be determined.
|
|
16
|
+
*/
|
|
17
|
+
async function resolveOrg(parsed, config, options) {
|
|
18
|
+
if (parsed.org)
|
|
19
|
+
return parsed.org;
|
|
20
|
+
const configFile = await (0, config_1.loadConfig)();
|
|
21
|
+
const org = configFile.workspace ?? config.defaultOrg;
|
|
22
|
+
if (!org) {
|
|
23
|
+
throw new errors_1.CliError(options?.missingOrgMessage ??
|
|
24
|
+
'Missing org. Use org/agent format or set default org.');
|
|
25
|
+
}
|
|
26
|
+
return org;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Central agent-reference resolution pipeline used by all commands.
|
|
30
|
+
*
|
|
31
|
+
* Takes a raw agent reference string (e.g., "org/agent@v2", "agent", "agent@latest")
|
|
32
|
+
* and resolves it to a full context with org, agent name, version, and workspace ID.
|
|
33
|
+
*
|
|
34
|
+
* Resolution steps:
|
|
35
|
+
* 1. Parse the ref string into { org?, agent, version }
|
|
36
|
+
* 2. Resolve org via fallback chain: ref → config workspace → defaultOrg
|
|
37
|
+
* 3. Resolve workspace ID for team workspace context (optional)
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* const ctx = await resolveAgentContext('acme/my-agent@v2', config)
|
|
41
|
+
* // ctx = { org: 'acme', agent: 'my-agent', version: 'v2', workspaceId: 'ws-123' }
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* const ctx = await resolveAgentContext('my-agent', config)
|
|
45
|
+
* // ctx = { org: 'default-org', agent: 'my-agent', version: 'latest', workspaceId: undefined }
|
|
46
|
+
*/
|
|
47
|
+
async function resolveAgentContext(agentRefString, config, options) {
|
|
48
|
+
const parsed = (0, agent_ref_1.parseAgentRef)(agentRefString);
|
|
49
|
+
const org = await resolveOrg(parsed, config, {
|
|
50
|
+
missingOrgMessage: options?.missingOrgMessage,
|
|
51
|
+
});
|
|
52
|
+
let workspaceId;
|
|
53
|
+
if (!options?.skipWorkspaceResolution) {
|
|
54
|
+
workspaceId = await (0, api_1.resolveWorkspaceIdForOrg)(config, org);
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
org,
|
|
58
|
+
agent: parsed.agent,
|
|
59
|
+
version: parsed.version,
|
|
60
|
+
workspaceId,
|
|
61
|
+
};
|
|
62
|
+
}
|
package/package.json
CHANGED