@orchagent/cli 0.3.35 → 0.3.37

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.
@@ -85,8 +85,8 @@ function registerAgentsCommand(program) {
85
85
  const price = (0, pricing_1.formatPrice)(agent);
86
86
  const coloredPrice = (0, pricing_1.isPaidAgent)(agent) ? chalk_1.default.yellow(price) : chalk_1.default.green(price);
87
87
  const desc = agent.description
88
- ? agent.description.length > 30
89
- ? agent.description.slice(0, 27) + '...'
88
+ ? agent.description.length > 60
89
+ ? agent.description.slice(0, 57) + '...'
90
90
  : agent.description
91
91
  : '-';
92
92
  table.push([name, version, type, stars.toString(), coloredPrice, desc]);
@@ -295,14 +295,17 @@ Paid Agents:
295
295
  const supportedProviders = agentMeta.supported_providers || ['any'];
296
296
  let llmKey;
297
297
  let llmProvider;
298
+ // Resolve effective provider: CLI flag > config default
299
+ const configDefaultProvider = await (0, config_1.getDefaultProvider)();
300
+ const effectiveProvider = options.provider ?? configDefaultProvider;
298
301
  if (options.key) {
299
302
  // Explicit key provided - require provider
300
- if (!options.provider) {
303
+ if (!effectiveProvider) {
301
304
  throw new errors_1.CliError('When using --key, you must also specify --provider (openai, anthropic, or gemini)');
302
305
  }
303
- (0, llm_1.validateProvider)(options.provider);
306
+ (0, llm_1.validateProvider)(effectiveProvider);
304
307
  // Warn on potential model/provider mismatch
305
- if (options.model && options.provider) {
308
+ if (options.model && effectiveProvider) {
306
309
  const modelLower = options.model.toLowerCase();
307
310
  const providerPatterns = {
308
311
  openai: /^(gpt-|o1-|o3-|davinci|text-)/,
@@ -310,21 +313,21 @@ Paid Agents:
310
313
  gemini: /^gemini-/,
311
314
  ollama: /^(llama|mistral|deepseek|phi|qwen)/,
312
315
  };
313
- const expectedPattern = providerPatterns[options.provider];
316
+ const expectedPattern = providerPatterns[effectiveProvider];
314
317
  if (expectedPattern && !expectedPattern.test(modelLower)) {
315
- process.stderr.write(`Warning: Model '${options.model}' may not be a ${options.provider} model.\n\n`);
318
+ process.stderr.write(`Warning: Model '${options.model}' may not be a ${effectiveProvider} model.\n\n`);
316
319
  }
317
320
  }
318
321
  llmKey = options.key;
319
- llmProvider = options.provider;
322
+ llmProvider = effectiveProvider;
320
323
  }
321
324
  else {
322
325
  // Try to detect from environment or server
323
- // If --provider specified, prioritize that provider
326
+ // If provider specified (flag or config default), prioritize that provider
324
327
  let providersToCheck = supportedProviders;
325
- if (options.provider) {
326
- (0, llm_1.validateProvider)(options.provider);
327
- providersToCheck = [options.provider];
328
+ if (effectiveProvider) {
329
+ (0, llm_1.validateProvider)(effectiveProvider);
330
+ providersToCheck = [effectiveProvider];
328
331
  // Warn on potential model/provider mismatch
329
332
  if (options.model) {
330
333
  const modelLower = options.model.toLowerCase();
@@ -334,9 +337,9 @@ Paid Agents:
334
337
  gemini: /^gemini-/,
335
338
  ollama: /^(llama|mistral|deepseek|phi|qwen)/,
336
339
  };
337
- const expectedPattern = providerPatterns[options.provider];
340
+ const expectedPattern = providerPatterns[effectiveProvider];
338
341
  if (expectedPattern && !expectedPattern.test(modelLower)) {
339
- process.stderr.write(`Warning: Model '${options.model}' may not be a ${options.provider} model.\n\n`);
342
+ process.stderr.write(`Warning: Model '${options.model}' may not be a ${effectiveProvider} model.\n\n`);
340
343
  }
341
344
  }
342
345
  }
@@ -358,7 +361,7 @@ Paid Agents:
358
361
  }
359
362
  else if (agentMeta.type === 'prompt') {
360
363
  // Warn if no key found for prompt-based agent
361
- const searchedProviders = options.provider ? [options.provider] : supportedProviders;
364
+ const searchedProviders = effectiveProvider ? [effectiveProvider] : supportedProviders;
362
365
  const providerList = searchedProviders.join(', ');
363
366
  process.stderr.write(`Warning: No LLM key found for provider(s): ${providerList}\n` +
364
367
  `Set an env var (e.g., OPENAI_API_KEY), run 'orchagent keys add <provider>', use --key, or configure in web dashboard\n\n`);
@@ -10,7 +10,7 @@ function getAllValidFormatIds() {
10
10
  const skillFormatIds = [...config_1.VALID_FORMAT_IDS];
11
11
  return [...new Set([...adapterIds, ...skillFormatIds])];
12
12
  }
13
- const SUPPORTED_KEYS = ['default-format', 'default-scope'];
13
+ const SUPPORTED_KEYS = ['default-format', 'default-scope', 'default-provider'];
14
14
  function isValidKey(key) {
15
15
  return SUPPORTED_KEYS.includes(key);
16
16
  }
@@ -36,6 +36,14 @@ async function setConfigValue(key, value) {
36
36
  await (0, config_1.setDefaultScope)(value);
37
37
  process.stdout.write(`Set default-scope to: ${value}\n`);
38
38
  }
39
+ if (key === 'default-provider') {
40
+ const validProviders = [...config_1.VALID_PROVIDERS];
41
+ if (!validProviders.includes(value)) {
42
+ throw new errors_1.CliError(`Invalid provider: ${value}. Valid providers: ${validProviders.join(', ')}`);
43
+ }
44
+ await (0, config_1.setDefaultProvider)(value);
45
+ process.stdout.write(`Set default-provider to: ${value}\n`);
46
+ }
39
47
  }
40
48
  async function getConfigValue(key) {
41
49
  if (!isValidKey(key)) {
@@ -60,6 +68,22 @@ async function getConfigValue(key) {
60
68
  process.stdout.write(`${scope}\n`);
61
69
  }
62
70
  }
71
+ if (key === 'default-provider') {
72
+ const provider = await (0, config_1.getDefaultProvider)();
73
+ if (!provider) {
74
+ process.stdout.write('(not set)\n');
75
+ }
76
+ else {
77
+ process.stdout.write(`${provider}\n`);
78
+ }
79
+ }
80
+ }
81
+ async function unsetConfigValue(key) {
82
+ if (!isValidKey(key)) {
83
+ throw new errors_1.CliError(`Unknown config key: ${key}. Supported keys: ${SUPPORTED_KEYS.join(', ')}`);
84
+ }
85
+ await (0, config_1.unsetConfigKey)(key);
86
+ process.stdout.write(`Unset ${key}\n`);
63
87
  }
64
88
  async function listConfigValues() {
65
89
  const config = await (0, config_1.loadConfig)();
@@ -80,6 +104,14 @@ async function listConfigValues() {
80
104
  else {
81
105
  process.stdout.write(' default-scope: (not set)\n');
82
106
  }
107
+ // default-provider
108
+ const provider = config.default_provider;
109
+ if (provider) {
110
+ process.stdout.write(` default-provider: ${provider}\n`);
111
+ }
112
+ else {
113
+ process.stdout.write(' default-provider: (not set)\n');
114
+ }
83
115
  process.stdout.write('\n');
84
116
  }
85
117
  function registerConfigCommand(program) {
@@ -98,6 +130,12 @@ function registerConfigCommand(program) {
98
130
  .action(async (key) => {
99
131
  await getConfigValue(key);
100
132
  });
133
+ config
134
+ .command('unset <key>')
135
+ .description('Remove a configuration value (restore to default)')
136
+ .action(async (key) => {
137
+ await unsetConfigValue(key);
138
+ });
101
139
  config
102
140
  .command('list')
103
141
  .description('List all configuration values')
@@ -35,7 +35,7 @@ function registerForkCommand(program) {
35
35
  process.stdout.write(`Forked ${org}/${name}/${version} to your account\n`);
36
36
  process.stdout.write(`\nYour forked agent: ${myOrg.slug}/${name}/v1\n`);
37
37
  process.stdout.write(`\nNext steps:\n`);
38
- process.stdout.write(` 1. Run: orchagent init ${name}\n`);
38
+ process.stdout.write(` 1. Run: orchagent install ${myOrg.slug}/${name}\n`);
39
39
  process.stdout.write(` 2. Edit the prompt and schemas locally\n`);
40
40
  process.stdout.write(` 3. Run: orchagent publish\n`);
41
41
  });
@@ -125,6 +125,7 @@ function registerInstallCommand(program) {
125
125
  .description('Install agent as sub-agent (Claude Code, Cursor, etc.)')
126
126
  .option('--format <formats>', 'Comma-separated format IDs (e.g., claude-code,cursor)')
127
127
  .option('--scope <scope>', 'Install scope: user (home dir) or project (current dir)')
128
+ .option('--global', 'Install to home directory (alias for --scope user)')
128
129
  .option('--dry-run', 'Show what would be installed without making changes')
129
130
  .option('--json', 'Output result as JSON (for automation/tooling)')
130
131
  .addHelpText('after', `
@@ -188,8 +189,8 @@ Note: Paid agents cannot be installed locally - they run on server only.
188
189
  }
189
190
  }
190
191
  result.formats = targetFormats;
191
- // Resolve scope: CLI flag > config default > fallback to 'user'
192
- let scope = (options.scope ?? await (0, config_1.getDefaultScope)() ?? 'user');
192
+ // Resolve scope: --global > --scope > config default > fallback to 'user'
193
+ let scope = (options.global ? 'user' : (options.scope ?? await (0, config_1.getDefaultScope)() ?? 'user'));
193
194
  if (scope !== 'user' && scope !== 'project') {
194
195
  const errMsg = 'Scope must be "user" or "project"';
195
196
  if (jsonMode) {
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractCount = extractCount;
6
7
  exports.registerSecurityCommand = registerSecurityCommand;
7
8
  const promises_1 = __importDefault(require("fs/promises"));
8
9
  const chalk_1 = __importDefault(require("chalk"));
@@ -61,6 +62,14 @@ function riskLevelColor(level) {
61
62
  return level;
62
63
  }
63
64
  }
65
+ /** Extract count from summary value (handles both flat numbers and {total, leaked} objects). */
66
+ function extractCount(value) {
67
+ if (typeof value === 'number')
68
+ return value;
69
+ if (value && typeof value === 'object' && 'leaked' in value)
70
+ return value.leaked;
71
+ return 0;
72
+ }
64
73
  function formatSummaryOutput(result) {
65
74
  process.stdout.write('\n');
66
75
  process.stdout.write(chalk_1.default.bold('Security Scan Results\n'));
@@ -78,8 +87,8 @@ function formatSummaryOutput(result) {
78
87
  process.stdout.write(chalk_1.default.bold('By Severity:\n'));
79
88
  const severityOrder = ['critical', 'high', 'medium', 'low'];
80
89
  for (const sev of severityOrder) {
81
- const count = result.summary.by_severity[sev];
82
- if (count && count > 0) {
90
+ const count = extractCount(result.summary.by_severity[sev]);
91
+ if (count > 0) {
83
92
  process.stdout.write(` ${severityColor(sev)}: ${count}\n`);
84
93
  }
85
94
  }
@@ -88,7 +97,8 @@ function formatSummaryOutput(result) {
88
97
  // Breakdown by category
89
98
  if (Object.keys(result.summary.by_category).length > 0) {
90
99
  process.stdout.write(chalk_1.default.bold('By Category:\n'));
91
- for (const [cat, count] of Object.entries(result.summary.by_category)) {
100
+ for (const [cat, rawCount] of Object.entries(result.summary.by_category)) {
101
+ const count = extractCount(rawCount);
92
102
  if (count > 0) {
93
103
  process.stdout.write(` ${cat}: ${count}\n`);
94
104
  }
@@ -293,7 +303,8 @@ function generateMarkdownReport(result) {
293
303
  if (Object.keys(result.summary.by_severity).length > 0) {
294
304
  lines.push('### By Severity');
295
305
  lines.push('');
296
- for (const [sev, count] of Object.entries(result.summary.by_severity)) {
306
+ for (const [sev, rawCount] of Object.entries(result.summary.by_severity)) {
307
+ const count = extractCount(rawCount);
297
308
  if (count > 0) {
298
309
  lines.push(`- ${sev.toUpperCase()}: ${count}`);
299
310
  }
@@ -303,7 +314,8 @@ function generateMarkdownReport(result) {
303
314
  if (Object.keys(result.summary.by_category).length > 0) {
304
315
  lines.push('### By Category');
305
316
  lines.push('');
306
- for (const [cat, count] of Object.entries(result.summary.by_category)) {
317
+ for (const [cat, rawCount] of Object.entries(result.summary.by_category)) {
318
+ const count = extractCount(rawCount);
307
319
  if (count > 0) {
308
320
  lines.push(`- ${cat}: ${count}`);
309
321
  }
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.FORMAT_SKILL_DIRS = exports.VALID_FORMAT_IDS = void 0;
39
+ exports.VALID_PROVIDERS = exports.FORMAT_SKILL_DIRS = exports.VALID_FORMAT_IDS = void 0;
40
40
  exports.loadConfig = loadConfig;
41
41
  exports.saveConfig = saveConfig;
42
42
  exports.getResolvedConfig = getResolvedConfig;
@@ -45,6 +45,9 @@ exports.getDefaultFormats = getDefaultFormats;
45
45
  exports.setDefaultFormats = setDefaultFormats;
46
46
  exports.getDefaultScope = getDefaultScope;
47
47
  exports.setDefaultScope = setDefaultScope;
48
+ exports.getDefaultProvider = getDefaultProvider;
49
+ exports.setDefaultProvider = setDefaultProvider;
50
+ exports.unsetConfigKey = unsetConfigKey;
48
51
  const promises_1 = __importDefault(require("fs/promises"));
49
52
  const path_1 = __importDefault(require("path"));
50
53
  const os_1 = __importDefault(require("os"));
@@ -140,3 +143,31 @@ async function setDefaultScope(scope) {
140
143
  config.default_scope = scope;
141
144
  await saveConfig(config);
142
145
  }
146
+ exports.VALID_PROVIDERS = ['openai', 'anthropic', 'gemini'];
147
+ async function getDefaultProvider() {
148
+ const config = await loadConfig();
149
+ return config.default_provider;
150
+ }
151
+ async function setDefaultProvider(provider) {
152
+ const config = await loadConfig();
153
+ config.default_provider = provider;
154
+ await saveConfig(config);
155
+ }
156
+ /**
157
+ * Remove a config key, restoring it to "not set" state.
158
+ * Maps CLI key names (kebab-case) to ConfigFile properties.
159
+ */
160
+ const CONFIG_KEY_MAP = {
161
+ 'default-format': 'default_formats',
162
+ 'default-scope': 'default_scope',
163
+ 'default-provider': 'default_provider',
164
+ };
165
+ async function unsetConfigKey(cliKey) {
166
+ const configProp = CONFIG_KEY_MAP[cliKey];
167
+ if (!configProp) {
168
+ throw new Error(`Unknown config key: ${cliKey}`);
169
+ }
170
+ const config = await loadConfig();
171
+ delete config[configProp];
172
+ await saveConfig(config);
173
+ }
@@ -30,8 +30,8 @@ function printAgentsTable(agents, options) {
30
30
  const price = (0, pricing_1.formatPrice)(agent);
31
31
  const priceColored = (0, pricing_1.isPaidAgent)(agent) ? chalk_1.default.yellow(price) : chalk_1.default.green(price);
32
32
  const desc = agent.description
33
- ? agent.description.length > 30
34
- ? agent.description.slice(0, 27) + '...'
33
+ ? agent.description.length > 60
34
+ ? agent.description.slice(0, 57) + '...'
35
35
  : agent.description
36
36
  : '-';
37
37
  const visibility = agent.is_public === false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchagent/cli",
3
- "version": "0.3.35",
3
+ "version": "0.3.37",
4
4
  "description": "Command-line interface for the orchagent AI agent marketplace",
5
5
  "license": "MIT",
6
6
  "author": "orchagent <hello@orchagent.io>",
@@ -40,8 +40,7 @@
40
40
  "test:coverage": "vitest run --coverage",
41
41
  "test:e2e": "vitest run --config vitest.e2e.config.ts",
42
42
  "test:all": "vitest run && vitest run --config vitest.e2e.config.ts",
43
- "prepublishOnly": "npm run build",
44
- "postpublish": "cd ../cli-wrapper && npm version $npm_package_version --no-git-tag-version --allow-same-version && npm publish && echo '\n✓ Wrapper published at orchagent@'$npm_package_version"
43
+ "prepublishOnly": "npm run build"
45
44
  },
46
45
  "dependencies": {
47
46
  "@sentry/node": "^9.3.0",