@orchagent/cli 0.3.90 → 0.3.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,300 @@
1
+ "use strict";
2
+ /**
3
+ * Formatting and colorized output for `orch diff`.
4
+ *
5
+ * Git-style red/green coloring: removed lines are red, added lines are green,
6
+ * changed fields show old in red and new in green. Structured fields
7
+ * (arrays, dependencies, custom_tools, schemas, models) get item-level diffs.
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.formatValuePlain = formatValuePlain;
14
+ exports.formatPromptDiff = formatPromptDiff;
15
+ exports.formatSchemaDiff = formatSchemaDiff;
16
+ exports.formatStringArrayDiff = formatStringArrayDiff;
17
+ exports.formatDependencyDiff = formatDependencyDiff;
18
+ exports.formatCustomToolDiff = formatCustomToolDiff;
19
+ exports.formatModelsDiff = formatModelsDiff;
20
+ exports.printDiffs = printDiffs;
21
+ const chalk_1 = __importDefault(require("chalk"));
22
+ // ── Plain value formatting ────────────────────────────────────
23
+ /** Format a value as plain text (no ANSI colors). */
24
+ function formatValuePlain(val) {
25
+ if (val === undefined || val === null)
26
+ return '(none)';
27
+ if (typeof val === 'boolean')
28
+ return String(val);
29
+ if (typeof val === 'string') {
30
+ if (val.length > 120)
31
+ return val.slice(0, 117) + '...';
32
+ return val;
33
+ }
34
+ if (Array.isArray(val)) {
35
+ if (val.length === 0)
36
+ return '[]';
37
+ if (typeof val[0] === 'string')
38
+ return val.join(', ');
39
+ return JSON.stringify(val, null, 2);
40
+ }
41
+ if (typeof val === 'object')
42
+ return JSON.stringify(val, null, 2);
43
+ return String(val);
44
+ }
45
+ /** Apply a chalk color function to every line of a string. */
46
+ function colorLines(text, colorFn) {
47
+ return text.split('\n').map(colorFn).join('\n');
48
+ }
49
+ // ── Prompt diff ───────────────────────────────────────────────
50
+ function formatPromptDiff(oldPrompt, newPrompt) {
51
+ const oldLines = (oldPrompt || '').split('\n');
52
+ const newLines = (newPrompt || '').split('\n');
53
+ const lines = [];
54
+ const oldSet = new Set(oldLines);
55
+ const newSet = new Set(newLines);
56
+ for (const line of oldLines) {
57
+ if (!newSet.has(line)) {
58
+ lines.push(chalk_1.default.red(` - ${line}`));
59
+ }
60
+ }
61
+ for (const line of newLines) {
62
+ if (!oldSet.has(line)) {
63
+ lines.push(chalk_1.default.green(` + ${line}`));
64
+ }
65
+ }
66
+ if (lines.length === 0) {
67
+ lines.push(chalk_1.default.yellow(' (line order changed)'));
68
+ }
69
+ if (lines.length > 40) {
70
+ const shown = lines.slice(0, 40);
71
+ shown.push(chalk_1.default.dim(` ... and ${lines.length - 40} more lines`));
72
+ return shown.join('\n');
73
+ }
74
+ return lines.join('\n');
75
+ }
76
+ // ── Schema diff ───────────────────────────────────────────────
77
+ function formatSchemaDiff(_field, oldSchema, newSchema) {
78
+ const lines = [];
79
+ const oldProps = oldSchema?.properties || {};
80
+ const newProps = newSchema?.properties || {};
81
+ const oldRequired = new Set(oldSchema?.required || []);
82
+ const newRequired = new Set(newSchema?.required || []);
83
+ const allKeys = new Set([...Object.keys(oldProps), ...Object.keys(newProps)]);
84
+ for (const key of allKeys) {
85
+ const inOld = key in oldProps;
86
+ const inNew = key in newProps;
87
+ if (!inOld && inNew) {
88
+ const reqMark = newRequired.has(key) ? '' : '?';
89
+ lines.push(chalk_1.default.green(` + ${key}${reqMark}: ${newProps[key].type || 'any'}`));
90
+ }
91
+ else if (inOld && !inNew) {
92
+ const reqMark = oldRequired.has(key) ? '' : '?';
93
+ lines.push(chalk_1.default.red(` - ${key}${reqMark}: ${oldProps[key].type || 'any'}`));
94
+ }
95
+ else if (inOld && inNew) {
96
+ const oldType = oldProps[key].type || 'any';
97
+ const newType = newProps[key].type || 'any';
98
+ const wasReq = oldRequired.has(key);
99
+ const isReq = newRequired.has(key);
100
+ if (oldType !== newType || wasReq !== isReq) {
101
+ const oldMark = wasReq ? '' : '?';
102
+ const newMark = isReq ? '' : '?';
103
+ lines.push(chalk_1.default.red(` - ${key}${oldMark}: ${oldType}`));
104
+ lines.push(chalk_1.default.green(` + ${key}${newMark}: ${newType}`));
105
+ }
106
+ }
107
+ }
108
+ return lines.join('\n');
109
+ }
110
+ // ── String array diff ─────────────────────────────────────────
111
+ /** Item-level diff for simple string arrays (tags, providers, secrets, skills). */
112
+ function formatStringArrayDiff(oldArr, newArr) {
113
+ const oldSet = new Set(oldArr);
114
+ const newSet = new Set(newArr);
115
+ const lines = [];
116
+ for (const item of oldArr) {
117
+ if (!newSet.has(item)) {
118
+ lines.push(chalk_1.default.red(` - ${item}`));
119
+ }
120
+ }
121
+ for (const item of newArr) {
122
+ if (!oldSet.has(item)) {
123
+ lines.push(chalk_1.default.green(` + ${item}`));
124
+ }
125
+ }
126
+ // Show items present in both (unchanged) for context
127
+ for (const item of newArr) {
128
+ if (oldSet.has(item)) {
129
+ lines.push(chalk_1.default.dim(` ${item}`));
130
+ }
131
+ }
132
+ return lines.join('\n');
133
+ }
134
+ // ── Dependency diff ───────────────────────────────────────────
135
+ /** Item-level diff for ManifestDependency arrays. Shows version changes. */
136
+ function formatDependencyDiff(oldDeps, newDeps) {
137
+ const oldMap = new Map(oldDeps.map(d => [d.id, d.version]));
138
+ const newMap = new Map(newDeps.map(d => [d.id, d.version]));
139
+ const allIds = new Set([...oldMap.keys(), ...newMap.keys()]);
140
+ const lines = [];
141
+ for (const id of allIds) {
142
+ const oldV = oldMap.get(id);
143
+ const newV = newMap.get(id);
144
+ if (oldV && !newV) {
145
+ lines.push(chalk_1.default.red(` - ${id}@${oldV}`));
146
+ }
147
+ else if (!oldV && newV) {
148
+ lines.push(chalk_1.default.green(` + ${id}@${newV}`));
149
+ }
150
+ else if (oldV && newV && oldV !== newV) {
151
+ lines.push(` ${id}: ${chalk_1.default.red(oldV)} ${chalk_1.default.yellow('\u2192')} ${chalk_1.default.green(newV)}`);
152
+ }
153
+ else {
154
+ lines.push(chalk_1.default.dim(` ${id}@${oldV}`));
155
+ }
156
+ }
157
+ return lines.join('\n');
158
+ }
159
+ // ── Custom tool diff ──────────────────────────────────────────
160
+ /** Item-level diff for CustomTool arrays. */
161
+ function formatCustomToolDiff(oldTools, newTools) {
162
+ const oldMap = new Map(oldTools.map(t => [t.name, t]));
163
+ const newMap = new Map(newTools.map(t => [t.name, t]));
164
+ const allNames = new Set([...oldMap.keys(), ...newMap.keys()]);
165
+ const lines = [];
166
+ for (const name of allNames) {
167
+ const oldT = oldMap.get(name);
168
+ const newT = newMap.get(name);
169
+ if (oldT && !newT) {
170
+ lines.push(chalk_1.default.red(` - ${name}`));
171
+ }
172
+ else if (!oldT && newT) {
173
+ lines.push(chalk_1.default.green(` + ${name}`));
174
+ if (newT.description)
175
+ lines.push(chalk_1.default.green(` ${newT.description}`));
176
+ }
177
+ else if (oldT && newT && JSON.stringify(oldT) !== JSON.stringify(newT)) {
178
+ lines.push(` ~ ${chalk_1.default.bold(name)}`);
179
+ if (oldT.description !== newT.description) {
180
+ lines.push(` desc: ${chalk_1.default.red(oldT.description || '(none)')} ${chalk_1.default.yellow('\u2192')} ${chalk_1.default.green(newT.description || '(none)')}`);
181
+ }
182
+ if (oldT.command !== newT.command) {
183
+ lines.push(` cmd: ${chalk_1.default.red(oldT.command || '(none)')} ${chalk_1.default.yellow('\u2192')} ${chalk_1.default.green(newT.command || '(none)')}`);
184
+ }
185
+ }
186
+ else {
187
+ lines.push(chalk_1.default.dim(` ${name}`));
188
+ }
189
+ }
190
+ return lines.join('\n');
191
+ }
192
+ // ── Models (key-value object) diff ────────────────────────────
193
+ /** Key-level diff for Record<string, string> objects like default_models. */
194
+ function formatModelsDiff(oldObj, newObj) {
195
+ const old = oldObj || {};
196
+ const nw = newObj || {};
197
+ const allKeys = new Set([...Object.keys(old), ...Object.keys(nw)]);
198
+ const lines = [];
199
+ for (const key of allKeys) {
200
+ if (key in old && !(key in nw)) {
201
+ lines.push(chalk_1.default.red(` - ${key}: ${old[key]}`));
202
+ }
203
+ else if (!(key in old) && key in nw) {
204
+ lines.push(chalk_1.default.green(` + ${key}: ${nw[key]}`));
205
+ }
206
+ else if (old[key] !== nw[key]) {
207
+ lines.push(` ${key}: ${chalk_1.default.red(old[key])} ${chalk_1.default.yellow('\u2192')} ${chalk_1.default.green(nw[key])}`);
208
+ }
209
+ }
210
+ return lines.join('\n');
211
+ }
212
+ // ── Main printer ──────────────────────────────────────────────
213
+ /** Render a colorized diff to stdout. */
214
+ function printDiffs(refA, refB, diffs) {
215
+ process.stdout.write('\n');
216
+ process.stdout.write(chalk_1.default.bold(`${refA} ${chalk_1.default.yellow('\u2192')} ${refB}`) + '\n');
217
+ process.stdout.write(chalk_1.default.dim('\u2500'.repeat(50)) + '\n\n');
218
+ if (diffs.length === 0) {
219
+ process.stdout.write(chalk_1.default.green('No differences found.') + '\n');
220
+ return;
221
+ }
222
+ process.stdout.write(`${chalk_1.default.bold(String(diffs.length))} ${diffs.length === 1 ? 'change' : 'changes'}:\n\n`);
223
+ // Fields that get item-level diff when changed
224
+ const stringArrayFields = new Set([
225
+ 'supported_providers', 'tags', 'default_skills', 'required_secrets',
226
+ ]);
227
+ for (const diff of diffs) {
228
+ // ── Schema fields: property-level diff ──
229
+ if ((diff.field === 'input_schema' || diff.field === 'output_schema') &&
230
+ diff.kind === 'changed') {
231
+ process.stdout.write(chalk_1.default.cyan(`~ ${diff.field}:`) + '\n');
232
+ process.stdout.write(formatSchemaDiff(diff.field, diff.old, diff.new) + '\n\n');
233
+ continue;
234
+ }
235
+ // ── Prompt: line-level diff ──
236
+ if (diff.field === 'prompt' && diff.kind === 'changed') {
237
+ process.stdout.write(chalk_1.default.cyan(`~ prompt:`) + '\n');
238
+ process.stdout.write(formatPromptDiff(diff.old, diff.new) + '\n\n');
239
+ continue;
240
+ }
241
+ // ── String arrays: item-level diff ──
242
+ if (stringArrayFields.has(diff.field) && diff.kind === 'changed') {
243
+ process.stdout.write(chalk_1.default.cyan(`~ ${diff.field}:`) + '\n');
244
+ process.stdout.write(formatStringArrayDiff(diff.old, diff.new) + '\n\n');
245
+ continue;
246
+ }
247
+ // ── Dependencies: item-level diff ──
248
+ if (diff.field === 'dependencies' && diff.kind === 'changed') {
249
+ process.stdout.write(chalk_1.default.cyan(`~ dependencies:`) + '\n');
250
+ process.stdout.write(formatDependencyDiff(diff.old, diff.new) + '\n\n');
251
+ continue;
252
+ }
253
+ // ── Custom tools: item-level diff ──
254
+ if (diff.field === 'custom_tools' && diff.kind === 'changed') {
255
+ process.stdout.write(chalk_1.default.cyan(`~ custom_tools:`) + '\n');
256
+ process.stdout.write(formatCustomToolDiff(diff.old, diff.new) + '\n\n');
257
+ continue;
258
+ }
259
+ // ── Default models: key-level diff ──
260
+ if (diff.field === 'default_models' && diff.kind === 'changed') {
261
+ process.stdout.write(chalk_1.default.cyan(`~ default_models:`) + '\n');
262
+ process.stdout.write(formatModelsDiff(diff.old, diff.new) + '\n\n');
263
+ continue;
264
+ }
265
+ // ── Standard scalar fields ──
266
+ if (diff.kind === 'added') {
267
+ const formatted = formatValuePlain(diff.new);
268
+ if (formatted.includes('\n')) {
269
+ process.stdout.write(chalk_1.default.green(`+ ${diff.field}:`) + '\n');
270
+ process.stdout.write(colorLines(formatted, l => chalk_1.default.green(` ${l}`)) + '\n\n');
271
+ }
272
+ else {
273
+ process.stdout.write(chalk_1.default.green(`+ ${diff.field}: ${formatted}`) + '\n');
274
+ }
275
+ }
276
+ else if (diff.kind === 'removed') {
277
+ const formatted = formatValuePlain(diff.old);
278
+ if (formatted.includes('\n')) {
279
+ process.stdout.write(chalk_1.default.red(`- ${diff.field}:`) + '\n');
280
+ process.stdout.write(colorLines(formatted, l => chalk_1.default.red(` ${l}`)) + '\n\n');
281
+ }
282
+ else {
283
+ process.stdout.write(chalk_1.default.red(`- ${diff.field}: ${formatted}`) + '\n');
284
+ }
285
+ }
286
+ else {
287
+ // changed — old in red, new in green
288
+ const oldFmt = formatValuePlain(diff.old);
289
+ const newFmt = formatValuePlain(diff.new);
290
+ if (!oldFmt.includes('\n') && !newFmt.includes('\n')) {
291
+ process.stdout.write(`${chalk_1.default.cyan('~')} ${chalk_1.default.bold(diff.field)}: ${chalk_1.default.red(oldFmt)} ${chalk_1.default.yellow('\u2192')} ${chalk_1.default.green(newFmt)}\n`);
292
+ }
293
+ else {
294
+ process.stdout.write(chalk_1.default.cyan(`~ ${diff.field}:`) + '\n');
295
+ process.stdout.write(colorLines(oldFmt, l => chalk_1.default.red(` - ${l}`)) + '\n');
296
+ process.stdout.write(colorLines(newFmt, l => chalk_1.default.green(` + ${l}`)) + '\n\n');
297
+ }
298
+ }
299
+ }
300
+ }
@@ -1,15 +1,13 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.computeDiffs = computeDiffs;
7
4
  exports.registerDiffCommand = registerDiffCommand;
8
- const chalk_1 = __importDefault(require("chalk"));
9
5
  const config_1 = require("../lib/config");
10
6
  const api_1 = require("../lib/api");
11
7
  const agent_ref_1 = require("../lib/agent-ref");
8
+ const errors_1 = require("../lib/errors");
12
9
  const spinner_1 = require("../lib/spinner");
10
+ const diff_format_1 = require("./diff-format");
13
11
  // ── Helpers ────────────────────────────────────────────────────
14
12
  function extractDependencies(manifest) {
15
13
  if (!manifest)
@@ -236,130 +234,6 @@ function computeDiffs(a, b) {
236
234
  }
237
235
  return diffs;
238
236
  }
239
- // ── Formatting ─────────────────────────────────────────────────
240
- function formatValue(val) {
241
- if (val === undefined || val === null)
242
- return chalk_1.default.gray('(none)');
243
- if (typeof val === 'boolean')
244
- return val ? chalk_1.default.green('true') : chalk_1.default.red('false');
245
- if (typeof val === 'string') {
246
- if (val.length > 120)
247
- return val.slice(0, 117) + '...';
248
- return val;
249
- }
250
- if (Array.isArray(val)) {
251
- if (val.length === 0)
252
- return chalk_1.default.gray('[]');
253
- // Array of strings
254
- if (typeof val[0] === 'string')
255
- return val.join(', ');
256
- // Array of objects — compact JSON
257
- return JSON.stringify(val, null, 2);
258
- }
259
- if (typeof val === 'object')
260
- return JSON.stringify(val, null, 2);
261
- return String(val);
262
- }
263
- function formatPromptDiff(oldPrompt, newPrompt) {
264
- const oldLines = (oldPrompt || '').split('\n');
265
- const newLines = (newPrompt || '').split('\n');
266
- const lines = [];
267
- // Simple line-by-line diff (not LCS — good enough for prompt comparison)
268
- const maxLines = Math.max(oldLines.length, newLines.length);
269
- const oldSet = new Set(oldLines);
270
- const newSet = new Set(newLines);
271
- for (const line of oldLines) {
272
- if (!newSet.has(line)) {
273
- lines.push(chalk_1.default.red(` - ${line}`));
274
- }
275
- }
276
- for (const line of newLines) {
277
- if (!oldSet.has(line)) {
278
- lines.push(chalk_1.default.green(` + ${line}`));
279
- }
280
- }
281
- if (lines.length === 0) {
282
- // Lines are the same but order changed
283
- lines.push(chalk_1.default.yellow(' (line order changed)'));
284
- }
285
- // Truncate if very large
286
- if (lines.length > 40) {
287
- const shown = lines.slice(0, 40);
288
- shown.push(chalk_1.default.gray(` ... and ${lines.length - 40} more lines`));
289
- return shown.join('\n');
290
- }
291
- return lines.join('\n');
292
- }
293
- function formatSchemaDiff(field, oldSchema, newSchema) {
294
- const lines = [];
295
- const oldProps = oldSchema?.properties || {};
296
- const newProps = newSchema?.properties || {};
297
- const oldRequired = new Set(oldSchema?.required || []);
298
- const newRequired = new Set(newSchema?.required || []);
299
- const allKeys = new Set([...Object.keys(oldProps), ...Object.keys(newProps)]);
300
- for (const key of allKeys) {
301
- const inOld = key in oldProps;
302
- const inNew = key in newProps;
303
- if (!inOld && inNew) {
304
- const reqMark = newRequired.has(key) ? '' : '?';
305
- lines.push(chalk_1.default.green(` + ${key}${reqMark}: ${newProps[key].type || 'any'}`));
306
- }
307
- else if (inOld && !inNew) {
308
- const reqMark = oldRequired.has(key) ? '' : '?';
309
- lines.push(chalk_1.default.red(` - ${key}${reqMark}: ${oldProps[key].type || 'any'}`));
310
- }
311
- else if (inOld && inNew) {
312
- const oldType = oldProps[key].type || 'any';
313
- const newType = newProps[key].type || 'any';
314
- const wasReq = oldRequired.has(key);
315
- const isReq = newRequired.has(key);
316
- if (oldType !== newType || wasReq !== isReq) {
317
- const oldMark = wasReq ? '' : '?';
318
- const newMark = isReq ? '' : '?';
319
- lines.push(chalk_1.default.red(` - ${key}${oldMark}: ${oldType}`));
320
- lines.push(chalk_1.default.green(` + ${key}${newMark}: ${newType}`));
321
- }
322
- }
323
- }
324
- return lines.join('\n');
325
- }
326
- function printDiffs(refA, refB, diffs) {
327
- process.stdout.write('\n');
328
- process.stdout.write(chalk_1.default.bold(`${refA} ${chalk_1.default.yellow('→')} ${refB}`) + '\n');
329
- process.stdout.write('='.repeat(50) + '\n\n');
330
- if (diffs.length === 0) {
331
- process.stdout.write(chalk_1.default.green('No differences found.') + '\n');
332
- return;
333
- }
334
- process.stdout.write(`${chalk_1.default.bold(String(diffs.length))} ${diffs.length === 1 ? 'change' : 'changes'}:\n\n`);
335
- for (const diff of diffs) {
336
- // Schema fields get special formatting
337
- if ((diff.field === 'input_schema' || diff.field === 'output_schema') && diff.kind === 'changed') {
338
- process.stdout.write(chalk_1.default.cyan(`~ ${diff.field}:`) + '\n');
339
- process.stdout.write(formatSchemaDiff(diff.field, diff.old, diff.new) + '\n\n');
340
- continue;
341
- }
342
- // Prompt gets special formatting
343
- if (diff.field === 'prompt' && diff.kind === 'changed') {
344
- process.stdout.write(chalk_1.default.cyan(`~ prompt:`) + '\n');
345
- process.stdout.write(formatPromptDiff(diff.old, diff.new) + '\n\n');
346
- continue;
347
- }
348
- // Standard fields
349
- const prefix = diff.kind === 'added' ? chalk_1.default.green('+')
350
- : diff.kind === 'removed' ? chalk_1.default.red('-')
351
- : chalk_1.default.cyan('~');
352
- if (diff.kind === 'added') {
353
- process.stdout.write(`${prefix} ${chalk_1.default.bold(diff.field)}: ${formatValue(diff.new)}\n`);
354
- }
355
- else if (diff.kind === 'removed') {
356
- process.stdout.write(`${prefix} ${chalk_1.default.bold(diff.field)}: ${formatValue(diff.old)}\n`);
357
- }
358
- else {
359
- process.stdout.write(`${prefix} ${chalk_1.default.bold(diff.field)}: ${formatValue(diff.old)} ${chalk_1.default.yellow('→')} ${formatValue(diff.new)}\n`);
360
- }
361
- }
362
- }
363
237
  // ── Ref parsing ────────────────────────────────────────────────
364
238
  /**
365
239
  * Parse second ref which can be:
@@ -369,7 +243,8 @@ function printDiffs(refA, refB, diffs) {
369
243
  function parseSecondRef(value, firstOrg, firstName) {
370
244
  // If it contains '/', treat as full ref
371
245
  if (value.includes('/')) {
372
- return (0, agent_ref_1.parseAgentRef)(value);
246
+ const parsed = (0, agent_ref_1.parseAgentRef)(value);
247
+ return { org: parsed.org ?? firstOrg, agent: parsed.agent, version: parsed.version };
373
248
  }
374
249
  // Otherwise treat as a version shorthand for the same agent
375
250
  return { org: firstOrg, agent: firstName, version: value };
@@ -382,7 +257,13 @@ function registerDiffCommand(program) {
382
257
  .option('--json', 'Output as JSON')
383
258
  .action(async (ref1Arg, ref2Arg, options) => {
384
259
  const config = await (0, config_1.getResolvedConfig)();
385
- const ref1 = (0, agent_ref_1.parseAgentRef)(ref1Arg);
260
+ const ref1Raw = (0, agent_ref_1.parseAgentRef)(ref1Arg);
261
+ const configFile = await (0, config_1.loadConfig)();
262
+ const ref1Org = ref1Raw.org ?? configFile.workspace ?? config.defaultOrg;
263
+ if (!ref1Org) {
264
+ throw new errors_1.CliError('Missing org. Use org/agent format or set default org.');
265
+ }
266
+ const ref1 = { org: ref1Org, agent: ref1Raw.agent, version: ref1Raw.version };
386
267
  let ref2;
387
268
  if (ref2Arg) {
388
269
  ref2 = parseSecondRef(ref2Arg, ref1.org, ref1.agent);
@@ -413,6 +294,6 @@ function registerDiffCommand(program) {
413
294
  }, null, 2) + '\n');
414
295
  return;
415
296
  }
416
- printDiffs(refALabel, refBLabel, diffs);
297
+ (0, diff_format_1.printDiffs)(refALabel, refBLabel, diffs);
417
298
  });
418
299
  }
@@ -35,11 +35,14 @@ function registerEstimateCommand(program) {
35
35
  .option('--json', 'Output as JSON')
36
36
  .action(async (agentArg, options) => {
37
37
  const config = await (0, config_1.getResolvedConfig)();
38
- const { org, agent, version } = (0, agent_ref_1.parseAgentRef)(agentArg);
38
+ const parsed = (0, agent_ref_1.parseAgentRef)(agentArg);
39
+ const configFile = await (0, config_1.loadConfig)();
40
+ const org = parsed.org ?? configFile.workspace ?? config.defaultOrg;
39
41
  if (!org) {
40
- process.stderr.write(chalk_1.default.red('Error: org/agent format required (e.g. myorg/my-agent)\n'));
42
+ process.stderr.write(chalk_1.default.red('Error: Missing org. Use org/agent format or set default org.\n'));
41
43
  process.exit(1);
42
44
  }
45
+ const { agent, version } = parsed;
43
46
  let data;
44
47
  try {
45
48
  data = await (0, api_1.getAgentCostEstimate)(config, org, agent, version);
@@ -56,7 +56,13 @@ Examples:
56
56
  if (!config.apiKey) {
57
57
  throw new errors_1.CliError('Not logged in. Run `orchagent login` first.');
58
58
  }
59
- const { org, agent, version } = (0, agent_ref_1.parseAgentRef)(agentRef);
59
+ const parsed = (0, agent_ref_1.parseAgentRef)(agentRef);
60
+ const configFile = await (0, config_1.loadConfig)();
61
+ const org = parsed.org ?? configFile.workspace ?? config.defaultOrg;
62
+ if (!org) {
63
+ throw new errors_1.CliError('Missing org. Use org/agent format or set default org.');
64
+ }
65
+ const { agent, version } = parsed;
60
66
  write('Resolving source agent...\n');
61
67
  const source = await (0, api_1.getAgentWithFallback)(config, org, agent, version);
62
68
  if (!source.id) {
@@ -14,7 +14,8 @@ const output_1 = require("../lib/output");
14
14
  const package_json_1 = __importDefault(require("../../package.json"));
15
15
  /**
16
16
  * Generate a minimal sample input from an agent's input schema.
17
- * Produces just enough to satisfy required fields.
17
+ * Produces just enough to satisfy required fields, using schema hints
18
+ * (format, examples, field name conventions) to create realistic values.
18
19
  */
19
20
  function generateSampleInput(schema) {
20
21
  if (!schema?.properties)
@@ -24,28 +25,110 @@ function generateSampleInput(schema) {
24
25
  for (const [key, prop] of Object.entries(schema.properties)) {
25
26
  if (!required.has(key))
26
27
  continue;
27
- result[key] = sampleValue(prop);
28
+ result[key] = sampleValue(prop, key);
28
29
  }
29
30
  // If no required fields, fill one optional field so the request isn't empty
30
31
  if (Object.keys(result).length === 0) {
31
32
  const firstKey = Object.keys(schema.properties)[0];
32
33
  if (firstKey) {
33
- result[firstKey] = sampleValue(schema.properties[firstKey]);
34
+ result[firstKey] = sampleValue(schema.properties[firstKey], firstKey);
34
35
  }
35
36
  }
36
37
  return Object.keys(result).length > 0 ? result : undefined;
37
38
  }
38
- function sampleValue(prop) {
39
+ /** Well-known JSON Schema string formats → realistic sample values. */
40
+ const FORMAT_SAMPLES = {
41
+ uri: 'https://example.com',
42
+ url: 'https://example.com',
43
+ iri: 'https://example.com',
44
+ 'uri-reference': '/test',
45
+ 'iri-reference': '/test',
46
+ email: 'test@example.com',
47
+ 'idn-email': 'test@example.com',
48
+ date: '2026-01-01',
49
+ 'date-time': '2026-01-01T00:00:00Z',
50
+ time: '12:00:00',
51
+ uuid: '00000000-0000-0000-0000-000000000000',
52
+ hostname: 'example.com',
53
+ 'idn-hostname': 'example.com',
54
+ ipv4: '192.0.2.1',
55
+ ipv6: '::1',
56
+ 'json-pointer': '/test',
57
+ 'relative-json-pointer': '0/test',
58
+ regex: '.*',
59
+ };
60
+ /**
61
+ * Field name segments that suggest a specific value type.
62
+ * Checked after format (format takes priority).
63
+ */
64
+ const NAME_HINT_SAMPLES = [
65
+ { segments: new Set(['url', 'uri', 'href', 'link', 'endpoint', 'webhook']), value: 'https://example.com' },
66
+ { segments: new Set(['email']), value: 'test@example.com' },
67
+ { segments: new Set(['path', 'file', 'filename', 'filepath']), value: '/tmp/test' },
68
+ { segments: new Set(['date', 'timestamp']), value: '2026-01-01' },
69
+ { segments: new Set(['phone', 'tel', 'telephone']), value: '+12025551234' },
70
+ { segments: new Set(['ip', 'ipaddr', 'ipaddress']), value: '192.0.2.1' },
71
+ { segments: new Set(['host', 'hostname', 'domain']), value: 'example.com' },
72
+ { segments: new Set(['uuid', 'guid']), value: '00000000-0000-0000-0000-000000000000' },
73
+ ];
74
+ function sampleString(prop, fieldName) {
75
+ // 1. Schema format (highest priority after default/enum)
76
+ if (prop.format && FORMAT_SAMPLES[prop.format]) {
77
+ return FORMAT_SAMPLES[prop.format];
78
+ }
79
+ // 2. Field name heuristics — split on _ and - to get semantic segments
80
+ if (fieldName) {
81
+ const segments = new Set(fieldName.toLowerCase().split(/[_-]/));
82
+ for (const hint of NAME_HINT_SAMPLES) {
83
+ for (const seg of segments) {
84
+ if (hint.segments.has(seg))
85
+ return hint.value;
86
+ }
87
+ }
88
+ }
89
+ // 3. Respect minLength
90
+ const base = 'test';
91
+ if (prop.minLength && prop.minLength > base.length) {
92
+ return base + 'x'.repeat(prop.minLength - base.length);
93
+ }
94
+ return base;
95
+ }
96
+ function sampleNumber(prop) {
97
+ const min = prop.exclusiveMinimum !== undefined
98
+ ? prop.exclusiveMinimum + 1
99
+ : prop.minimum;
100
+ const max = prop.exclusiveMaximum !== undefined
101
+ ? prop.exclusiveMaximum - 1
102
+ : prop.maximum;
103
+ if (min !== undefined && max !== undefined) {
104
+ return prop.type === 'integer' ? Math.ceil((min + max) / 2) : (min + max) / 2;
105
+ }
106
+ if (min !== undefined)
107
+ return min;
108
+ if (max !== undefined)
109
+ return max;
110
+ return 1;
111
+ }
112
+ function sampleArray(prop) {
113
+ const count = prop.minItems || 0;
114
+ if (count === 0)
115
+ return [];
116
+ const itemProp = prop.items || { type: 'string' };
117
+ return Array.from({ length: count }, () => sampleValue(itemProp));
118
+ }
119
+ function sampleValue(prop, fieldName) {
39
120
  if (prop.default !== undefined)
40
121
  return prop.default;
122
+ if (prop.examples?.length)
123
+ return prop.examples[0];
41
124
  if (prop.enum?.length)
42
125
  return prop.enum[0];
43
126
  switch (prop.type) {
44
- case 'string': return 'test';
127
+ case 'string': return sampleString(prop, fieldName);
45
128
  case 'number':
46
- case 'integer': return 1;
129
+ case 'integer': return sampleNumber(prop);
47
130
  case 'boolean': return true;
48
- case 'array': return [];
131
+ case 'array': return sampleArray(prop);
49
132
  case 'object': return {};
50
133
  default: return 'test';
51
134
  }
@@ -5,6 +5,7 @@ const login_1 = require("./login");
5
5
  const logout_1 = require("./logout");
6
6
  const agents_1 = require("./agents");
7
7
  const init_1 = require("./init");
8
+ const scaffold_1 = require("./scaffold");
8
9
  const publish_1 = require("./publish");
9
10
  const whoami_1 = require("./whoami");
10
11
  const run_1 = require("./run");
@@ -42,11 +43,14 @@ const replay_1 = require("./replay");
42
43
  const trace_1 = require("./trace");
43
44
  const metrics_1 = require("./metrics");
44
45
  const dag_1 = require("./dag");
46
+ const completion_1 = require("./completion");
47
+ const validate_1 = require("./validate");
45
48
  function registerCommands(program) {
46
49
  (0, login_1.registerLoginCommand)(program);
47
50
  (0, logout_1.registerLogoutCommand)(program);
48
51
  (0, whoami_1.registerWhoamiCommand)(program);
49
52
  (0, init_1.registerInitCommand)(program);
53
+ (0, scaffold_1.registerScaffoldCommand)(program);
50
54
  (0, publish_1.registerPublishCommand)(program);
51
55
  (0, run_1.registerRunCommand)(program);
52
56
  (0, info_1.registerInfoCommand)(program);
@@ -84,4 +88,6 @@ function registerCommands(program) {
84
88
  (0, trace_1.registerTraceCommand)(program);
85
89
  (0, metrics_1.registerMetricsCommand)(program);
86
90
  (0, dag_1.registerDagCommand)(program);
91
+ (0, completion_1.registerCompletionCommand)(program);
92
+ (0, validate_1.registerValidateCommand)(program);
87
93
  }