@orchagent/cli 0.3.102 → 0.3.104

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.
@@ -193,6 +193,10 @@ function registerDagCommand(program) {
193
193
  throw new errors_1.CliError('Missing API key. Run `orch login` first.');
194
194
  }
195
195
  const workspaceId = await resolveWorkspaceId(config, options.workspace);
196
+ // Accept req_xxx format (gateway request_id shown in run output)
197
+ if (/^req_[0-9a-f]+$/i.test(runId)) {
198
+ runId = runId.slice(4);
199
+ }
196
200
  // Resolve short run IDs
197
201
  let resolvedRunId = runId;
198
202
  if (isUuid(runId)) {
@@ -9,6 +9,7 @@ const config_1 = require("../lib/config");
9
9
  const api_1 = require("../lib/api");
10
10
  const agent_ref_1 = require("../lib/agent-ref");
11
11
  const errors_1 = require("../lib/errors");
12
+ const json_input_1 = require("../lib/json-input");
12
13
  const spinner_1 = require("../lib/spinner");
13
14
  const output_1 = require("../lib/output");
14
15
  const package_json_1 = __importDefault(require("../../package.json"));
@@ -194,13 +195,7 @@ function registerHealthCommand(program) {
194
195
  const inputSchema = agentMeta.input_schema;
195
196
  let body;
196
197
  if (options.data) {
197
- try {
198
- JSON.parse(options.data);
199
- body = options.data;
200
- }
201
- catch {
202
- throw new errors_1.CliError('Invalid JSON in --data option.');
203
- }
198
+ body = await (0, json_input_1.resolveJsonBody)(options.data);
204
199
  }
205
200
  else {
206
201
  const sample = generateSampleInput(inputSchema);
@@ -2242,6 +2242,10 @@ function registerInitCommand(program) {
2242
2242
  process.stdout.write(` ${stepNum + 1}. Edit schema.json with your input/output schemas\n`);
2243
2243
  process.stdout.write(` ${stepNum + 2}. Run: orchagent publish\n`);
2244
2244
  }
2245
+ if (initMode.flavor === 'managed_loop') {
2246
+ process.stdout.write(`\n Note: supported_providers: ["any"] means anthropic, openai, or gemini\n`);
2247
+ process.stdout.write(` Your vault key determines which is used (set with: orch secrets set)\n`);
2248
+ }
2245
2249
  process.stdout.write(AGENT_BUILDER_HINT);
2246
2250
  });
2247
2251
  }
@@ -548,11 +548,21 @@ async function batchPublish(rootDir, options) {
548
548
  catch {
549
549
  // Non-critical — just won't show org prefix
550
550
  }
551
- const plan = (0, batch_publish_1.formatPublishPlan)(sorted, orgSlug);
552
- process.stderr.write(plan);
551
+ // Dry-run: show ordering preview and exit (no subprocesses)
553
552
  if (options.dryRun) {
554
- process.stderr.write(chalk_1.default.cyan('DRY RUN running orch publish --dry-run in each directory:\n\n'));
553
+ const summary = (0, batch_publish_1.formatDryRunSummary)(sorted, orgSlug);
554
+ process.stderr.write(summary);
555
+ await (0, analytics_1.track)('cli_publish_all', {
556
+ total: sorted.length,
557
+ succeeded: 0,
558
+ failed: 0,
559
+ skipped: sorted.length,
560
+ dry_run: true,
561
+ });
562
+ return;
555
563
  }
564
+ const plan = (0, batch_publish_1.formatPublishPlan)(sorted, orgSlug);
565
+ process.stderr.write(plan);
556
566
  // Build the CLI args to forward (exclude --all)
557
567
  const forwardArgs = [];
558
568
  if (options.profile)
@@ -50,7 +50,7 @@ function commandForEntrypoint(entrypoint) {
50
50
  || entrypoint.endsWith('.ts')) {
51
51
  return `node ${entrypoint}`;
52
52
  }
53
- return `python ${entrypoint}`;
53
+ return `python3 ${entrypoint}`;
54
54
  }
55
55
  // ─── Agent Resolution ───────────────────────────────────────────────────────
56
56
  async function resolveAgent(config, org, agent, version, workspaceId) {
@@ -128,13 +128,21 @@ async function resolveAgent(config, org, agent, version, workspaceId) {
128
128
  async function tryOwnerFallback(config, org, agent, version, workspaceId) {
129
129
  try {
130
130
  let match = findOwnerMatch(await (0, api_1.listMyAgents)(config, workspaceId), agent, version, org);
131
+ let effectiveWorkspaceId = workspaceId;
131
132
  // Retry without workspace restriction to find agents in personal org
132
133
  if (!match && workspaceId) {
133
134
  match = findOwnerMatch(await (0, api_1.listMyAgents)(config, undefined), agent, version, org);
135
+ effectiveWorkspaceId = undefined;
134
136
  }
135
137
  if (!match)
136
138
  return null;
137
- const agentData = await (0, api_1.request)(config, 'GET', `/agents/${match.id}`);
139
+ // Pass workspace context so GET /agents/{id} uses the correct org scope.
140
+ // Without this header, the gateway scopes to the caller's personal org,
141
+ // which 404s when the agent lives in a team workspace.
142
+ const headers = {};
143
+ if (effectiveWorkspaceId)
144
+ headers['X-Workspace-Id'] = effectiveWorkspaceId;
145
+ const agentData = await (0, api_1.request)(config, 'GET', `/agents/${match.id}`, { headers });
138
146
  return mapAgentToPullData(agentData);
139
147
  }
140
148
  catch {
@@ -164,7 +172,13 @@ async function resolveFromMyAgents(config, agent, version, org, workspaceId) {
164
172
  return null;
165
173
  target = found;
166
174
  }
167
- const agentData = await (0, api_1.request)(config, 'GET', `/agents/${target.id}`);
175
+ // Pass workspace context so GET /agents/{id} uses the correct org scope.
176
+ // Without this header, the gateway scopes to the caller's personal org,
177
+ // which 404s when the agent lives in a team workspace.
178
+ const headers = {};
179
+ if (workspaceId)
180
+ headers['X-Workspace-Id'] = workspaceId;
181
+ const agentData = await (0, api_1.request)(config, 'GET', `/agents/${target.id}`, { headers });
168
182
  return mapAgentToPullData(agentData);
169
183
  }
170
184
  function mapAgentToPullData(agent) {
@@ -57,6 +57,7 @@ const config_1 = require("../lib/config");
57
57
  const resolve_agent_1 = require("../lib/resolve-agent");
58
58
  const api_1 = require("../lib/api");
59
59
  const errors_1 = require("../lib/errors");
60
+ const json_input_1 = require("../lib/json-input");
60
61
  const output_1 = require("../lib/output");
61
62
  const spinner_1 = require("../lib/spinner");
62
63
  const llm_1 = require("../lib/llm");
@@ -360,32 +361,6 @@ async function buildMultipartBody(filePaths, metadata) {
360
361
  sourceLabel: filePaths.length === 1 ? filePaths[0] : `${filePaths.length} files`,
361
362
  };
362
363
  }
363
- async function resolveJsonBody(input) {
364
- let raw = input;
365
- if (input.startsWith('@')) {
366
- const source = input.slice(1);
367
- if (!source) {
368
- throw new errors_1.CliError('Invalid JSON input. Use a JSON string or @file.');
369
- }
370
- if (source === '-') {
371
- const stdinData = await readStdin();
372
- if (!stdinData) {
373
- throw new errors_1.CliError('No stdin provided for JSON input.');
374
- }
375
- raw = stdinData.toString('utf8');
376
- }
377
- else {
378
- await validateFilePath(source);
379
- raw = await promises_1.default.readFile(source, 'utf8');
380
- }
381
- }
382
- try {
383
- return JSON.stringify(JSON.parse(raw));
384
- }
385
- catch {
386
- throw (0, errors_1.jsonInputError)('data');
387
- }
388
- }
389
364
  // ─── Keyed file & mount helpers ──────────────────────────────────────────────
390
365
  const KEYED_FILE_KEY_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
391
366
  function isKeyedFileArg(arg) {
@@ -494,7 +469,7 @@ async function buildInjectedPayload(options) {
494
469
  let merged = {};
495
470
  // 1. Start with --data
496
471
  if (options.dataOption) {
497
- const resolved = await resolveJsonBody(options.dataOption);
472
+ const resolved = await (0, json_input_1.resolveJsonBody)(options.dataOption);
498
473
  merged = JSON.parse(resolved);
499
474
  }
500
475
  let totalBytes = 0;
@@ -1912,7 +1887,7 @@ async function executeCloud(agentRef, file, options) {
1912
1887
  // --estimate-only: show cost estimate and exit without running
1913
1888
  if (options.estimate || options.estimateOnly) {
1914
1889
  try {
1915
- const est = await (0, api_1.getAgentCostEstimate)(resolved, org, agentName, version);
1890
+ const est = await (0, api_1.getAgentCostEstimate)(resolved, org, agentName, version, workspaceId);
1916
1891
  const e = est.estimate;
1917
1892
  if (e.sample_size === 0) {
1918
1893
  process.stderr.write(chalk_1.default.yellow('\nNo run history available for cost estimation.\n'));
@@ -1952,12 +1927,19 @@ async function executeCloud(agentRef, file, options) {
1952
1927
  return;
1953
1928
  }
1954
1929
  }
1955
- catch {
1956
- // Non-fatal: if estimate fails, proceed with the run (or exit if --estimate-only)
1930
+ catch (err) {
1931
+ // Provide specific error messages based on failure type
1932
+ const detail = err instanceof api_1.ApiError && err.status === 404
1933
+ ? 'Agent not found.'
1934
+ : err instanceof api_1.ApiError && err.status === 429
1935
+ ? 'Rate limited — try again shortly.'
1936
+ : err instanceof api_1.ApiError
1937
+ ? `API error (${err.status}).`
1938
+ : 'Network error — check your connection.';
1957
1939
  if (options.estimateOnly) {
1958
- throw new errors_1.CliError('Could not fetch cost estimate.');
1940
+ throw new errors_1.CliError(`Could not fetch cost estimate: ${detail}`);
1959
1941
  }
1960
- process.stderr.write(chalk_1.default.gray('Could not fetch cost estimate. Proceeding...\n\n'));
1942
+ process.stderr.write(chalk_1.default.gray(`Could not fetch cost estimate: ${detail} Proceeding with run...\n\n`));
1961
1943
  }
1962
1944
  }
1963
1945
  const endpoint = options.endpoint?.trim() || agentMeta.default_endpoint || 'analyze';
@@ -2069,7 +2051,7 @@ async function executeCloud(agentRef, file, options) {
2069
2051
  }
2070
2052
  if (options.data && filePaths.length > 0) {
2071
2053
  // Merge file content into --data
2072
- const resolvedBody = await resolveJsonBody(options.data);
2054
+ const resolvedBody = await (0, json_input_1.resolveJsonBody)(options.data);
2073
2055
  const bodyObj = JSON.parse(resolvedBody);
2074
2056
  if (cloudEngine !== 'code_runtime') {
2075
2057
  const fieldName = resolveFileField(options.fileField, agentMeta.input_schema);
@@ -2117,7 +2099,7 @@ async function executeCloud(agentRef, file, options) {
2117
2099
  }
2118
2100
  }
2119
2101
  else if (options.data) {
2120
- const resolvedBody = await resolveJsonBody(options.data);
2102
+ const resolvedBody = await (0, json_input_1.resolveJsonBody)(options.data);
2121
2103
  warnIfLocalPathReference(resolvedBody);
2122
2104
  const parsedBody = JSON.parse(resolvedBody);
2123
2105
  warnInputSchemaErrors(parsedBody, agentMeta.input_schema);
@@ -2573,7 +2555,22 @@ async function executeCloud(agentRef, file, options) {
2573
2555
  process.stdout.write(`${payload}\n`);
2574
2556
  return;
2575
2557
  }
2576
- (0, output_1.printJson)(payload);
2558
+ // In verbose mode, strip stdout/stderr from the JSON payload since they'll
2559
+ // be displayed in dedicated colored sections below (avoids duplication)
2560
+ if (options.verbose && typeof payload === 'object' && payload !== null && 'metadata' in payload) {
2561
+ const payloadObj = payload;
2562
+ const meta = payloadObj.metadata;
2563
+ if (meta && (meta.stdout || meta.stderr)) {
2564
+ const { stdout: _s, stderr: _e, ...cleanMeta } = meta;
2565
+ (0, output_1.printJson)({ ...payloadObj, metadata: cleanMeta });
2566
+ }
2567
+ else {
2568
+ (0, output_1.printJson)(payload);
2569
+ }
2570
+ }
2571
+ else {
2572
+ (0, output_1.printJson)(payload);
2573
+ }
2577
2574
  // Display timing metadata on stderr (non-json mode only)
2578
2575
  if (typeof payload === 'object' && payload !== null && 'metadata' in payload) {
2579
2576
  const meta = payload.metadata;
@@ -2585,7 +2582,14 @@ async function executeCloud(agentRef, file, options) {
2585
2582
  if (stderr) {
2586
2583
  process.stderr.write(chalk_1.default.bold.yellow('\n--- stderr ---') + '\n' + stderr + '\n');
2587
2584
  }
2588
- if (stdout) {
2585
+ // For code_runtime agents, stdout IS the data — skip if it would
2586
+ // duplicate what's already visible in the JSON data field
2587
+ const dataStr = typeof payload.data === 'string'
2588
+ ? payload.data
2589
+ : JSON.stringify(payload.data);
2590
+ const stdoutDuplicatesData = isCodeRuntimeAgent && stdout && dataStr &&
2591
+ stdout.trim() === dataStr.trim();
2592
+ if (stdout && !stdoutDuplicatesData) {
2589
2593
  process.stderr.write(chalk_1.default.bold.cyan('\n--- stdout ---') + '\n' + stdout + '\n');
2590
2594
  }
2591
2595
  if (!stderr && !stdout) {
@@ -2685,7 +2689,7 @@ async function executeLocal(agentRef, args, options) {
2685
2689
  return;
2686
2690
  }
2687
2691
  // Resolve @file.json / @- stdin syntax before parsing
2688
- const resolvedInput = await resolveJsonBody(options.input);
2692
+ const resolvedInput = await (0, json_input_1.resolveJsonBody)(options.input);
2689
2693
  let agentInputData;
2690
2694
  try {
2691
2695
  agentInputData = JSON.parse(resolvedInput);
@@ -2871,7 +2875,7 @@ function registerRunCommand(program) {
2871
2875
  // Local-only options
2872
2876
  .option('--download-only', 'Just download the agent, do not execute (local only)')
2873
2877
  .option('--with-deps', 'Automatically download all dependencies (local only)')
2874
- .option('--here', 'Scan current directory (local only)')
2878
+ .option('--here', 'Send current directory as path input, for tool agents with a path field (local only)')
2875
2879
  .option('--path <dir>', 'Shorthand for --data \'{"path": "<dir>"}\' (local only)')
2876
2880
  .addHelpText('after', `
2877
2881
  Examples:
@@ -11,6 +11,7 @@ const promises_1 = __importDefault(require("readline/promises"));
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 json_input_1 = require("../lib/json-input");
14
15
  const output_1 = require("../lib/output");
15
16
  const agent_ref_1 = require("../lib/agent-ref");
16
17
  const api_2 = require("../lib/api");
@@ -187,12 +188,8 @@ function registerScheduleCommand(program) {
187
188
  const rawInput = options.data ?? options.input;
188
189
  let inputData;
189
190
  if (rawInput) {
190
- try {
191
- inputData = JSON.parse(rawInput);
192
- }
193
- catch {
194
- throw new errors_1.CliError('Invalid JSON in --data. Use single quotes: --data \'{"key": "value"}\'');
195
- }
191
+ const resolved = await (0, json_input_1.resolveJsonBody)(rawInput);
192
+ inputData = JSON.parse(resolved);
196
193
  }
197
194
  const scheduleType = options.webhook ? 'webhook' : 'cron';
198
195
  const body = {
@@ -105,6 +105,10 @@ function registerTraceCommand(program) {
105
105
  throw new errors_1.CliError('Missing API key. Run `orch login` first.');
106
106
  }
107
107
  const workspaceId = await resolveWorkspaceId(config, options.workspace);
108
+ // Accept req_xxx format (gateway request_id shown in run output)
109
+ if (/^req_[0-9a-f]+$/i.test(runId)) {
110
+ runId = runId.slice(4);
111
+ }
108
112
  // Resolve short run IDs
109
113
  let resolvedRunId = runId;
110
114
  if (isUuid(runId)) {
package/dist/lib/api.js CHANGED
@@ -286,10 +286,11 @@ async function getPublicAgent(config, org, agent, version) {
286
286
  }
287
287
  async function getAgentCostEstimate(config, org, agent, version, workspaceId) {
288
288
  const path = `/public/agents/${org}/${agent}/${version}/cost-estimate`;
289
- if (workspaceId && config.apiKey) {
290
- return request(config, 'GET', path, {
291
- headers: { 'X-Workspace-Id': workspaceId },
292
- });
289
+ if (config.apiKey) {
290
+ const headers = {};
291
+ if (workspaceId)
292
+ headers['X-Workspace-Id'] = workspaceId;
293
+ return request(config, 'GET', path, { headers });
293
294
  }
294
295
  return publicRequest(config, path);
295
296
  }
@@ -380,15 +381,18 @@ async function getAgentWithFallback(config, org, agentName, version, workspaceId
380
381
  if (!config.apiKey) {
381
382
  throw new ApiError(`Agent '${org}/${agentName}@${version}' not found`, 404);
382
383
  }
383
- const userOrg = await getOrg(config, workspaceId);
384
- if (userOrg.slug !== org) {
385
- throw new ApiError(`Agent '${org}/${agentName}@${version}' not found`, 404);
386
- }
384
+ // Try authenticated lookup in the resolved workspace context
387
385
  const myAgent = await getMyAgent(config, agentName, version, workspaceId);
388
- if (!myAgent) {
389
- throw new ApiError(`Agent '${org}/${agentName}@${version}' not found`, 404);
386
+ if (myAgent)
387
+ return myAgent;
388
+ // Fallback: if workspace was specified, also check personal org —
389
+ // handles cross-workspace lookups (e.g., team context looking up personal agent)
390
+ if (workspaceId) {
391
+ const personalAgent = await getMyAgent(config, agentName, version);
392
+ if (personalAgent)
393
+ return personalAgent;
390
394
  }
391
- return myAgent;
395
+ throw new ApiError(`Agent '${org}/${agentName}@${version}' not found`, 404);
392
396
  }
393
397
  /**
394
398
  * Resolve a workspace ID from an org slug.
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.discoverAgents = discoverAgents;
7
7
  exports.topoSort = topoSort;
8
8
  exports.formatPublishPlan = formatPublishPlan;
9
+ exports.formatDryRunSummary = formatDryRunSummary;
9
10
  const promises_1 = __importDefault(require("fs/promises"));
10
11
  const path_1 = __importDefault(require("path"));
11
12
  const chalk_1 = __importDefault(require("chalk"));
@@ -221,3 +222,75 @@ function formatPublishPlan(sorted, orgSlug) {
221
222
  lines.push('');
222
223
  return lines.join('\n');
223
224
  }
225
+ /**
226
+ * Format an enhanced dry-run summary for --all --dry-run.
227
+ * Shows publish ordering, local/external dependencies, and graph health.
228
+ */
229
+ function formatDryRunSummary(sorted, orgSlug) {
230
+ const lines = [];
231
+ const localNames = new Set(sorted.map(a => a.name));
232
+ // Collect external deps (referenced but not in the project)
233
+ const externalDeps = new Map(); // ref → [agent names that reference it]
234
+ for (const agent of sorted) {
235
+ for (const ref of agent.dependencyRefs) {
236
+ const depName = ref.includes('/') ? ref.split('/')[1] : ref;
237
+ if (!localNames.has(depName)) {
238
+ const consumers = externalDeps.get(ref) || [];
239
+ consumers.push(agent.name);
240
+ externalDeps.set(ref, consumers);
241
+ }
242
+ }
243
+ }
244
+ // Publish order table
245
+ lines.push('');
246
+ lines.push(chalk_1.default.bold(` Publish order (${sorted.length} agent${sorted.length === 1 ? '' : 's'}):`));
247
+ lines.push('');
248
+ for (let i = 0; i < sorted.length; i++) {
249
+ const agent = sorted[i];
250
+ const type = agent.isSkill ? 'skill' : 'agent';
251
+ const prefix = orgSlug ? `${orgSlug}/` : '';
252
+ // Separate local and external deps for clarity
253
+ const localDeps = [];
254
+ const extDeps = [];
255
+ for (const ref of agent.dependencyRefs) {
256
+ const depName = ref.includes('/') ? ref.split('/')[1] : ref;
257
+ if (localNames.has(depName)) {
258
+ localDeps.push(depName);
259
+ }
260
+ else {
261
+ extDeps.push(ref);
262
+ }
263
+ }
264
+ let depInfo = '';
265
+ if (localDeps.length > 0 || extDeps.length > 0) {
266
+ const parts = [];
267
+ if (localDeps.length > 0)
268
+ parts.push(localDeps.join(', '));
269
+ if (extDeps.length > 0)
270
+ parts.push(extDeps.map(d => `${d} ${chalk_1.default.yellow('(external)')}`).join(', '));
271
+ depInfo = ` ${chalk_1.default.gray('→')} ${parts.join(', ')}`;
272
+ }
273
+ lines.push(` ${chalk_1.default.bold(`${i + 1}.`)} ${prefix}${agent.name} ${chalk_1.default.gray(`[${type}]`)}${depInfo}`);
274
+ lines.push(` ${chalk_1.default.gray(agent.dirName + '/')}`);
275
+ }
276
+ // External dependencies section
277
+ if (externalDeps.size > 0) {
278
+ lines.push('');
279
+ lines.push(chalk_1.default.yellow(` External dependencies (must already be published):`));
280
+ for (const [ref, consumers] of externalDeps) {
281
+ lines.push(` ${ref} ${chalk_1.default.gray(`← ${consumers.join(', ')}`)}`);
282
+ }
283
+ }
284
+ // Summary
285
+ lines.push('');
286
+ const skillCount = sorted.filter(a => a.isSkill).length;
287
+ const agentCount = sorted.length - skillCount;
288
+ const parts = [];
289
+ if (agentCount > 0)
290
+ parts.push(`${agentCount} agent${agentCount === 1 ? '' : 's'}`);
291
+ if (skillCount > 0)
292
+ parts.push(`${skillCount} skill${skillCount === 1 ? '' : 's'}`);
293
+ lines.push(chalk_1.default.green(` ✓ ${parts.join(', ')} ready to publish (no circular dependencies)`));
294
+ lines.push('');
295
+ return lines.join('\n');
296
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveJsonBody = resolveJsonBody;
7
+ const promises_1 = __importDefault(require("fs/promises"));
8
+ const errors_1 = require("./errors");
9
+ async function readStdin() {
10
+ if (process.stdin.isTTY)
11
+ return null;
12
+ const chunks = [];
13
+ for await (const chunk of process.stdin) {
14
+ chunks.push(Buffer.from(chunk));
15
+ }
16
+ if (!chunks.length)
17
+ return null;
18
+ return Buffer.concat(chunks);
19
+ }
20
+ async function validateFilePath(filePath) {
21
+ const stat = await promises_1.default.stat(filePath);
22
+ if (stat.isDirectory()) {
23
+ throw new errors_1.CliError(`Expected a file but got a directory: ${filePath}\n\n` +
24
+ `Provide a JSON file path, e.g. --data @input.json`);
25
+ }
26
+ }
27
+ /**
28
+ * Resolve a --data value to a validated JSON string.
29
+ *
30
+ * Supports three input forms:
31
+ * - Plain JSON string: '{"key":"value"}'
32
+ * - File reference: @input.json
33
+ * - Stdin pipe: @-
34
+ */
35
+ async function resolveJsonBody(input) {
36
+ let raw = input;
37
+ if (input.startsWith('@')) {
38
+ const source = input.slice(1);
39
+ if (!source) {
40
+ throw new errors_1.CliError('Invalid JSON input. Use a JSON string or @file.');
41
+ }
42
+ if (source === '-') {
43
+ const stdinData = await readStdin();
44
+ if (!stdinData) {
45
+ throw new errors_1.CliError('No stdin provided for JSON input.');
46
+ }
47
+ raw = stdinData.toString('utf8');
48
+ }
49
+ else {
50
+ await validateFilePath(source);
51
+ raw = await promises_1.default.readFile(source, 'utf8');
52
+ }
53
+ }
54
+ try {
55
+ return JSON.stringify(JSON.parse(raw));
56
+ }
57
+ catch {
58
+ throw (0, errors_1.jsonInputError)('data');
59
+ }
60
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchagent/cli",
3
- "version": "0.3.102",
3
+ "version": "0.3.104",
4
4
  "description": "Command-line interface for orchagent — deploy and run AI agents for your team",
5
5
  "license": "MIT",
6
6
  "author": "orchagent <hello@orchagent.io>",