@orchagent/cli 0.3.41 → 0.3.43

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.
@@ -17,8 +17,8 @@ exports.agentsMdAdapter = {
17
17
  canConvert(agent) {
18
18
  const warnings = [];
19
19
  const errors = [];
20
- if (agent.type === 'code') {
21
- errors.push('Code agents cannot be converted to AGENTS.md');
20
+ if (agent.type === 'tool') {
21
+ errors.push('Tool agents cannot be converted to AGENTS.md');
22
22
  return { canConvert: false, warnings, errors };
23
23
  }
24
24
  if (!agent.prompt) {
@@ -27,9 +27,9 @@ exports.claudeCodeAdapter = {
27
27
  canConvert(agent) {
28
28
  const warnings = [];
29
29
  const errors = [];
30
- // Code agents cannot be converted
31
- if (agent.type === 'code') {
32
- errors.push('Code agents cannot be converted to Claude Code sub-agents (they require execution)');
30
+ // Tool agents cannot be converted
31
+ if (agent.type === 'tool') {
32
+ errors.push('Tool agents cannot be converted to Claude Code sub-agents (they require execution)');
33
33
  return { canConvert: false, warnings, errors };
34
34
  }
35
35
  // Check for prompt
@@ -18,8 +18,8 @@ exports.cursorAdapter = {
18
18
  canConvert(agent) {
19
19
  const warnings = [];
20
20
  const errors = [];
21
- if (agent.type === 'code') {
22
- errors.push('Code agents cannot be converted to Cursor rules');
21
+ if (agent.type === 'tool') {
22
+ errors.push('Tool agents cannot be converted to Cursor rules');
23
23
  return { canConvert: false, warnings, errors };
24
24
  }
25
25
  if (!agent.prompt) {
@@ -80,7 +80,7 @@ function registerAgentsCommand(program) {
80
80
  filteredAgents.forEach((agent) => {
81
81
  const name = agent.name;
82
82
  const version = agent.version;
83
- const type = agent.type || 'code';
83
+ const type = agent.type || 'tool';
84
84
  const stars = agent.stars_count ?? 0;
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);
@@ -194,7 +194,7 @@ Note: Use 'call' for server-side execution (requires login), 'run' for local exe
194
194
  File handling:
195
195
  For prompt agents, file content is read and sent as JSON mapped to the agent's
196
196
  input schema. Use --file-field to specify the field name (auto-detected by default).
197
- For code agents, files are uploaded as multipart form data.
197
+ For tools, files are uploaded as multipart form data.
198
198
 
199
199
  Important: Remote agents cannot access your local filesystem. If your --data payload
200
200
  contains keys like 'path', 'directory', 'file', etc., those values will be interpreted
@@ -438,7 +438,7 @@ Paid Agents:
438
438
  headers['Content-Type'] = 'application/json';
439
439
  }
440
440
  else if (filePaths.length > 0 || options.metadata) {
441
- // Code agent: handle multipart file uploads
441
+ // Tool: handle multipart file uploads
442
442
  // Inject llm_credentials into metadata if available
443
443
  let metadata = options.metadata;
444
444
  if (llmCredentials) {
@@ -201,7 +201,7 @@ async function clearDefault(config, options) {
201
201
  function registerEnvCommand(program) {
202
202
  const env = program
203
203
  .command('env')
204
- .description('Manage custom Docker environments for code agents');
204
+ .description('Manage custom Docker environments for tools');
205
205
  env
206
206
  .command('list')
207
207
  .description('List environments in workspace')
@@ -176,7 +176,7 @@ function registerInfoCommand(program) {
176
176
  process.stdout.write(chalk_1.default.gray('Note: Paid agents run on server only (use orch call)\n'));
177
177
  process.stdout.write(chalk_1.default.gray(' Owners can still download for development/testing\n'));
178
178
  }
179
- if (agentData.type === 'code') {
179
+ if (agentData.type === 'tool') {
180
180
  // Don't show internal routing URLs - they confuse users
181
181
  if (agentData.url && !agentData.url.includes('.internal')) {
182
182
  process.stdout.write(`Server: ${agentData.url}\n`);
@@ -46,10 +46,10 @@ const SCHEMA_TEMPLATE = `{
46
46
  }
47
47
  `;
48
48
  const CODE_TEMPLATE_PY = `"""
49
- orchagent code agent entrypoint.
49
+ orchagent tool entrypoint.
50
50
 
51
51
  Reads JSON input from stdin, processes it, and writes JSON output to stdout.
52
- This is the standard orchagent code agent protocol.
52
+ This is the standard orchagent tool protocol.
53
53
 
54
54
  Usage:
55
55
  echo '{"input": "hello"}' | python main.py
@@ -82,12 +82,12 @@ if __name__ == "__main__":
82
82
  main()
83
83
  `;
84
84
  function readmeTemplate(agentName, type) {
85
- const callExample = type === 'code'
85
+ const callExample = type === 'tool'
86
86
  ? `orchagent call ${agentName} input-file.txt`
87
- : `orchagent call ${agentName} --data '{"${type === 'agentic' ? 'task' : 'input'}": "Hello world"}'`;
88
- const runExample = type === 'code'
87
+ : `orchagent call ${agentName} --data '{"${type === 'agent' ? 'task' : 'input'}": "Hello world"}'`;
88
+ const runExample = type === 'tool'
89
89
  ? `orchagent run ${agentName} --input '{"file_path": "src/app.py"}'`
90
- : `orchagent run ${agentName} --input '{"${type === 'agentic' ? 'task' : 'input'}": "Hello world"}'`;
90
+ : `orchagent run ${agentName} --input '{"${type === 'agent' ? 'task' : 'input'}": "Hello world"}'`;
91
91
  return `# ${agentName}
92
92
 
93
93
  A brief description of what this agent does.
@@ -110,7 +110,7 @@ ${runExample}
110
110
 
111
111
  | Field | Type | Description |
112
112
  |-------|------|-------------|
113
- | \`input\` | string | The input to process |
113
+ | \`${type === 'agent' ? 'task' : 'input'}\` | string | ${type === 'agent' ? 'The task to perform' : 'The input to process'} |
114
114
 
115
115
  ## Output
116
116
 
@@ -119,13 +119,12 @@ ${runExample}
119
119
  | \`result\` | string | The agent's response |
120
120
  `;
121
121
  }
122
- const AGENTIC_MANIFEST_TEMPLATE = `{
122
+ const AGENT_MANIFEST_TEMPLATE = `{
123
123
  "name": "my-agent",
124
- "description": "An agentic AI agent with tool use",
125
- "type": "agentic",
124
+ "description": "An AI agent with tool use",
125
+ "type": "agent",
126
126
  "supported_providers": ["anthropic"],
127
127
  "max_turns": 25,
128
- "timeout_seconds": 300,
129
128
  "custom_tools": [
130
129
  {
131
130
  "name": "run_tests",
@@ -135,7 +134,7 @@ const AGENTIC_MANIFEST_TEMPLATE = `{
135
134
  ]
136
135
  }
137
136
  `;
138
- const AGENTIC_PROMPT_TEMPLATE = `You are a helpful AI agent with access to a sandboxed environment.
137
+ const AGENT_PROMPT_TEMPLATE = `You are a helpful AI agent with access to a sandboxed environment.
139
138
 
140
139
  Given the input, complete the task using the available tools:
141
140
  - Use bash to run commands
@@ -147,7 +146,7 @@ Input: The caller's input will be provided as JSON.
147
146
 
148
147
  Work step by step, verify your results, and submit the final output.
149
148
  `;
150
- const AGENTIC_SCHEMA_TEMPLATE = `{
149
+ const AGENT_SCHEMA_TEMPLATE = `{
151
150
  "input": {
152
151
  "type": "object",
153
152
  "properties": {
@@ -189,7 +188,7 @@ function registerInitCommand(program) {
189
188
  .command('init')
190
189
  .description('Initialize a new agent project')
191
190
  .argument('[name]', 'Agent name (default: current directory name)')
192
- .option('--type <type>', 'Type: prompt, code, agentic, or skill (default: prompt)', 'prompt')
191
+ .option('--type <type>', 'Type: prompt, tool, agent, or skill (default: prompt)', 'prompt')
193
192
  .action(async (name, options) => {
194
193
  const cwd = process.cwd();
195
194
  // When a name is provided, create a subdirectory for the project
@@ -243,20 +242,20 @@ function registerInitCommand(program) {
243
242
  }
244
243
  }
245
244
  // Create manifest and type-specific files
246
- if (options.type === 'agentic') {
247
- const manifest = JSON.parse(AGENTIC_MANIFEST_TEMPLATE);
245
+ if (options.type === 'agent') {
246
+ const manifest = JSON.parse(AGENT_MANIFEST_TEMPLATE);
248
247
  manifest.name = agentName;
249
248
  await promises_1.default.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
250
- await promises_1.default.writeFile(promptPath, AGENTIC_PROMPT_TEMPLATE);
251
- await promises_1.default.writeFile(schemaPath, AGENTIC_SCHEMA_TEMPLATE);
249
+ await promises_1.default.writeFile(promptPath, AGENT_PROMPT_TEMPLATE);
250
+ await promises_1.default.writeFile(schemaPath, AGENT_SCHEMA_TEMPLATE);
252
251
  }
253
252
  else {
254
253
  const manifest = JSON.parse(MANIFEST_TEMPLATE);
255
254
  manifest.name = agentName;
256
- manifest.type = ['code', 'skill'].includes(options.type) ? options.type : 'prompt';
255
+ manifest.type = ['tool', 'skill'].includes(options.type) ? options.type : 'prompt';
257
256
  await promises_1.default.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
258
- // Create prompt template (for prompt-based agents) or entrypoint (for code agents)
259
- if (options.type === 'code') {
257
+ // Create prompt template (for prompt-based agents) or entrypoint (for tool agents)
258
+ if (options.type === 'tool') {
260
259
  const entrypointPath = path_1.default.join(targetDir, 'main.py');
261
260
  await promises_1.default.writeFile(entrypointPath, CODE_TEMPLATE_PY);
262
261
  }
@@ -273,7 +272,7 @@ function registerInitCommand(program) {
273
272
  process.stdout.write(`\nFiles created:\n`);
274
273
  const prefix = name ? name + '/' : '';
275
274
  process.stdout.write(` ${prefix}orchagent.json - Agent configuration\n`);
276
- if (options.type === 'code') {
275
+ if (options.type === 'tool') {
277
276
  process.stdout.write(` ${prefix}main.py - Agent entrypoint (stdin/stdout JSON)\n`);
278
277
  }
279
278
  else {
@@ -282,7 +281,7 @@ function registerInitCommand(program) {
282
281
  process.stdout.write(` ${prefix}schema.json - Input/output schemas\n`);
283
282
  process.stdout.write(` ${prefix}README.md - Agent documentation\n`);
284
283
  process.stdout.write(`\nNext steps:\n`);
285
- if (options.type === 'agentic') {
284
+ if (options.type === 'agent') {
286
285
  const stepNum = name ? 2 : 1;
287
286
  if (name) {
288
287
  process.stdout.write(` 1. cd ${name}\n`);
@@ -292,7 +291,7 @@ function registerInitCommand(program) {
292
291
  process.stdout.write(` ${stepNum + 2}. Edit schema.json with your input/output schemas\n`);
293
292
  process.stdout.write(` ${stepNum + 3}. Run: orchagent publish\n`);
294
293
  }
295
- else if (options.type !== 'code') {
294
+ else if (options.type !== 'tool') {
296
295
  const stepNum = name ? 2 : 1;
297
296
  if (name) {
298
297
  process.stdout.write(` 1. cd ${name}\n`);
@@ -317,7 +317,7 @@ function registerPublishCommand(program) {
317
317
  `These must be nested under a "manifest" key. Example:\n\n` +
318
318
  ` {\n` +
319
319
  ` "name": "${manifest.name}",\n` +
320
- ` "type": "${manifest.type || 'code'}",\n` +
320
+ ` "type": "${manifest.type || 'tool'}",\n` +
321
321
  ` "manifest": {\n` +
322
322
  ` "manifest_version": 1,\n` +
323
323
  ` "dependencies": [...],\n` +
@@ -328,16 +328,16 @@ function registerPublishCommand(program) {
328
328
  ` }\n\n` +
329
329
  `See docs/manifest.md for details.`);
330
330
  }
331
- // Read prompt (for prompt-based, agentic, and skill agents)
331
+ // Read prompt (for prompt-based, agent, and skill agents)
332
332
  let prompt;
333
- if (manifest.type === 'prompt' || manifest.type === 'skill' || manifest.type === 'agentic') {
333
+ if (manifest.type === 'prompt' || manifest.type === 'skill' || manifest.type === 'agent') {
334
334
  const promptPath = path_1.default.join(cwd, 'prompt.md');
335
335
  try {
336
336
  prompt = await promises_1.default.readFile(promptPath, 'utf-8');
337
337
  }
338
338
  catch (err) {
339
339
  if (err.code === 'ENOENT') {
340
- const agentTypeName = manifest.type === 'skill' ? 'skill' : manifest.type === 'agentic' ? 'agentic agent' : 'prompt-based agent';
340
+ const agentTypeName = manifest.type === 'skill' ? 'skill' : manifest.type === 'agent' ? 'agent' : 'prompt-based agent';
341
341
  throw new errors_1.CliError(`No prompt.md found for ${agentTypeName}.\n\n` +
342
342
  'Create a prompt.md file in the current directory with your prompt template.\n' +
343
343
  'See: https://orchagent.io/docs/publishing');
@@ -345,15 +345,25 @@ function registerPublishCommand(program) {
345
345
  throw err;
346
346
  }
347
347
  }
348
- // For agentic agents, validate custom_tools and build manifest
349
- if (manifest.type === 'agentic') {
348
+ // For agent type, validate custom_tools and build manifest
349
+ if (manifest.type === 'agent') {
350
350
  // Validate custom_tools format
351
351
  if (manifest.custom_tools) {
352
+ const reservedNames = new Set(['bash', 'read_file', 'write_file', 'list_files', 'submit_result']);
353
+ const seenNames = new Set();
352
354
  for (const tool of manifest.custom_tools) {
353
355
  if (!tool.name || !tool.command) {
354
356
  throw new errors_1.CliError(`Invalid custom_tool: each tool must have 'name' and 'command' fields.\n` +
355
357
  `Found: ${JSON.stringify(tool)}`);
356
358
  }
359
+ if (reservedNames.has(tool.name)) {
360
+ throw new errors_1.CliError(`Custom tool '${tool.name}' conflicts with a built-in tool name.\n` +
361
+ `Reserved names: ${[...reservedNames].join(', ')}`);
362
+ }
363
+ if (seenNames.has(tool.name)) {
364
+ throw new errors_1.CliError(`Duplicate custom tool name: '${tool.name}'`);
365
+ }
366
+ seenNames.add(tool.name);
357
367
  }
358
368
  }
359
369
  // Validate max_turns
@@ -362,18 +372,18 @@ function registerPublishCommand(program) {
362
372
  throw new errors_1.CliError('max_turns must be a number between 1 and 50');
363
373
  }
364
374
  }
365
- // Store agentic config in manifest field
366
- const agenticManifest = {
375
+ // Store agent config in manifest field
376
+ const agentManifest = {
367
377
  ...(manifest.manifest || {}),
368
378
  };
369
379
  if (manifest.custom_tools) {
370
- agenticManifest.custom_tools = manifest.custom_tools;
380
+ agentManifest.custom_tools = manifest.custom_tools;
371
381
  }
372
382
  if (manifest.max_turns) {
373
- agenticManifest.max_turns = manifest.max_turns;
383
+ agentManifest.max_turns = manifest.max_turns;
374
384
  }
375
- manifest.manifest = agenticManifest;
376
- // Agentic agents default to anthropic provider
385
+ manifest.manifest = agentManifest;
386
+ // Agent type defaults to anthropic provider
377
387
  if (!manifest.supported_providers) {
378
388
  manifest.supported_providers = ['anthropic'];
379
389
  }
@@ -397,7 +407,7 @@ function registerPublishCommand(program) {
397
407
  }
398
408
  }
399
409
  // For prompt/skill agents, derive input schema from template variables if needed
400
- // (Agentic agents use schema.json directly — no template variable derivation)
410
+ // (Agent type uses schema.json directly — no template variable derivation)
401
411
  if (prompt && (manifest.type === 'prompt' || manifest.type === 'skill')) {
402
412
  const templateVars = extractTemplateVariables(prompt);
403
413
  if (templateVars.length > 0) {
@@ -424,13 +434,13 @@ function registerPublishCommand(program) {
424
434
  }
425
435
  }
426
436
  }
427
- // For code-based agents, either --url is required OR we bundle the code
428
- // For agentic agents, use internal placeholder (no user code, platform handles execution)
437
+ // For tool-based agents, either --url is required OR we bundle the code
438
+ // For agent type, use internal placeholder (no user code, platform handles execution)
429
439
  let agentUrl = options.url;
430
440
  let shouldUploadBundle = false;
431
- if (manifest.type === 'agentic') {
432
- // Agentic agents don't need a URL or code bundle
433
- agentUrl = agentUrl || 'https://agentic-agent.internal';
441
+ if (manifest.type === 'agent') {
442
+ // Agent type doesn't need a URL or code bundle
443
+ agentUrl = agentUrl || 'https://agent.internal';
434
444
  // But they can include a Dockerfile for custom environments
435
445
  if (options.docker) {
436
446
  const dockerfilePath = path_1.default.join(cwd, 'Dockerfile');
@@ -444,27 +454,27 @@ function registerPublishCommand(program) {
444
454
  }
445
455
  }
446
456
  }
447
- else if (manifest.type === 'code' && !options.url) {
457
+ else if (manifest.type === 'tool' && !options.url) {
448
458
  // Check if this looks like a Python or JS project that can be bundled
449
459
  const entrypoint = manifest.entrypoint || await (0, bundle_1.detectEntrypoint)(cwd);
450
460
  if (entrypoint) {
451
- // This is a hosted code agent - we'll bundle and upload
461
+ // This is a hosted tool - we'll bundle and upload
452
462
  shouldUploadBundle = true;
453
463
  // Set a placeholder URL that tells the gateway to use sandbox execution
454
- agentUrl = 'https://code-agent.internal';
455
- process.stdout.write(`Detected code project with entrypoint: ${entrypoint}\n`);
464
+ agentUrl = 'https://tool.internal';
465
+ process.stdout.write(`Detected tool project with entrypoint: ${entrypoint}\n`);
456
466
  }
457
467
  else {
458
- throw new errors_1.CliError('Code agent requires either --url <url> or an entry point file (main.py, app.py, index.js, etc.)');
468
+ throw new errors_1.CliError('Tool requires either --url <url> or an entry point file (main.py, app.py, index.js, etc.)');
459
469
  }
460
470
  }
461
471
  // Get org info
462
472
  const org = await (0, api_1.getOrg)(config);
463
473
  // Default to 'any' provider if not specified
464
474
  const supportedProviders = manifest.supported_providers || ['any'];
465
- // Detect SDK compatibility for code agents
475
+ // Detect SDK compatibility for tool agents
466
476
  let sdkCompatible = false;
467
- if (manifest.type === 'code') {
477
+ if (manifest.type === 'tool') {
468
478
  sdkCompatible = await detectSdkCompatible(cwd);
469
479
  if (sdkCompatible && !options.dryRun) {
470
480
  process.stdout.write(`SDK detected - agent will be marked as Local Ready\n`);
@@ -492,8 +502,8 @@ function registerPublishCommand(program) {
492
502
  process.stderr.write(` ✓ Input schema derived from template variables: ${vars.join(', ')}\n`);
493
503
  }
494
504
  }
495
- else if (manifest.type === 'agentic') {
496
- // Agentic agent validations
505
+ else if (manifest.type === 'agent') {
506
+ // Agent type validations
497
507
  const promptBytes = prompt ? Buffer.byteLength(prompt, 'utf-8') : 0;
498
508
  process.stderr.write(` ✓ prompt.md found (${promptBytes.toLocaleString()} bytes)\n`);
499
509
  if (schemaFromFile) {
@@ -504,8 +514,8 @@ function registerPublishCommand(program) {
504
514
  process.stderr.write(` ✓ Custom tools: ${customToolCount}\n`);
505
515
  process.stderr.write(` ✓ Max turns: ${manifest.max_turns || 25}\n`);
506
516
  }
507
- else if (manifest.type === 'code') {
508
- // Code agent validations
517
+ else if (manifest.type === 'tool') {
518
+ // Tool agent validations
509
519
  const entrypoint = manifest.entrypoint || await (0, bundle_1.detectEntrypoint)(cwd);
510
520
  process.stderr.write(` ✓ Entrypoint: ${entrypoint}\n`);
511
521
  if (sdkCompatible) {
@@ -513,7 +523,7 @@ function registerPublishCommand(program) {
513
523
  }
514
524
  }
515
525
  process.stderr.write(` ✓ Authentication valid (org: ${org.slug})\n`);
516
- // For code agents with bundles, show bundle preview
526
+ // For tools with bundles, show bundle preview
517
527
  if (shouldUploadBundle) {
518
528
  const bundlePreview = await (0, bundle_1.previewBundle)(cwd, {
519
529
  entrypoint: manifest.entrypoint,
@@ -567,7 +577,7 @@ function registerPublishCommand(program) {
567
577
  is_public: options.public ? true : false,
568
578
  supported_providers: supportedProviders,
569
579
  default_models: manifest.default_models,
570
- // Local run fields for code agents
580
+ // Local run fields for tool agents
571
581
  source_url: manifest.source_url,
572
582
  pip_package: manifest.pip_package,
573
583
  run_command: manifest.run_command,
@@ -585,7 +595,7 @@ function registerPublishCommand(program) {
585
595
  }
586
596
  const assignedVersion = result.agent?.version || 'v1';
587
597
  const agentId = result.agent?.id;
588
- // Upload code bundle if this is a hosted code agent or agentic agent with --docker
598
+ // Upload code bundle if this is a hosted tool agent or agent type with --docker
589
599
  if (shouldUploadBundle && agentId) {
590
600
  process.stdout.write(`\nBundling code...\n`);
591
601
  const tempDir = await promises_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'orchagent-bundle-'));
@@ -604,8 +614,8 @@ function registerPublishCommand(program) {
604
614
  throw new errors_1.CliError('--docker flag specified but no Dockerfile found in project directory');
605
615
  }
606
616
  }
607
- // For agentic agents, also include requirements.txt if present
608
- if (manifest.type === 'agentic') {
617
+ // For agent type, also include requirements.txt if present
618
+ if (manifest.type === 'agent') {
609
619
  const reqPath = path_1.default.join(cwd, 'requirements.txt');
610
620
  try {
611
621
  await promises_1.default.access(reqPath);
@@ -617,9 +627,10 @@ function registerPublishCommand(program) {
617
627
  }
618
628
  }
619
629
  const bundleResult = await (0, bundle_1.createCodeBundle)(cwd, bundlePath, {
620
- entrypoint: manifest.type === 'agentic' ? undefined : manifest.entrypoint,
630
+ entrypoint: manifest.type === 'agent' ? undefined : manifest.entrypoint,
621
631
  exclude: manifest.bundle?.exclude,
622
632
  include: includePatterns.length > 0 ? includePatterns : undefined,
633
+ skipEntrypointCheck: manifest.type === 'agent',
623
634
  });
624
635
  process.stdout.write(` Created bundle: ${bundleResult.fileCount} files, ${(bundleResult.sizeBytes / 1024).toFixed(1)}KB\n`);
625
636
  // Validate bundle size
@@ -269,9 +269,9 @@ async function downloadDependenciesRecursively(config, depStatuses, visited = ne
269
269
  if (status.agentData.has_bundle) {
270
270
  await saveBundleLocally(config, org, agent, status.dep.version, status.agentData.id);
271
271
  }
272
- // Install if it's a pip/source code agent
273
- if (status.agentData.type === 'code' && (status.agentData.source_url || status.agentData.pip_package)) {
274
- await installCodeAgent(status.agentData);
272
+ // Install if it's a pip/source tool agent
273
+ if (status.agentData.type === 'tool' && (status.agentData.source_url || status.agentData.pip_package)) {
274
+ await installTool(status.agentData);
275
275
  }
276
276
  }, { successText: `Downloaded ${depRef}` });
277
277
  // Download default skills
@@ -476,10 +476,10 @@ async function checkPackageInstalled(packageName) {
476
476
  return false;
477
477
  }
478
478
  }
479
- async function installCodeAgent(agentData) {
479
+ async function installTool(agentData) {
480
480
  const installSource = agentData.pip_package || agentData.source_url;
481
481
  if (!installSource) {
482
- throw new errors_1.CliError('This code agent does not support local execution.\n' +
482
+ throw new errors_1.CliError('This tool does not support local execution.\n' +
483
483
  'Use `orch call` to run it on the server instead.');
484
484
  }
485
485
  // Check if already installed (for pip packages)
@@ -503,13 +503,13 @@ async function installCodeAgent(agentData) {
503
503
  }
504
504
  }, { successText: 'Installation complete' });
505
505
  }
506
- async function executeCodeAgent(agentData, args) {
506
+ async function executeTool(agentData, args) {
507
507
  if (!agentData.run_command) {
508
- throw new errors_1.CliError('This code agent does not have a run command defined.\n' +
508
+ throw new errors_1.CliError('This tool does not have a run command defined.\n' +
509
509
  'Use `orch call` to run it on the server instead.');
510
510
  }
511
511
  // Install the agent if needed
512
- await installCodeAgent(agentData);
512
+ await installTool(agentData);
513
513
  // Parse the run command and append user args
514
514
  const [cmd, ...cmdArgs] = agentData.run_command.split(' ');
515
515
  const fullArgs = [...cmdArgs, ...args];
@@ -760,7 +760,7 @@ async function saveAgentLocally(org, agent, agentData) {
760
760
  if (agentData.type === 'prompt' && agentData.prompt) {
761
761
  await promises_1.default.writeFile(path_1.default.join(agentDir, 'prompt.md'), agentData.prompt);
762
762
  }
763
- // For code agents, save files if provided
763
+ // For tools, save files if provided
764
764
  if (agentData.files) {
765
765
  for (const file of agentData.files) {
766
766
  const filePath = path_1.default.join(agentDir, file.path);
@@ -887,7 +887,7 @@ Paid Agents:
887
887
  // Fall back to getting public agent info if download endpoint not available
888
888
  const agentMeta = await (0, api_1.getPublicAgent)(resolved, org, parsed.agent, parsed.version);
889
889
  return {
890
- type: agentMeta.type || 'code',
890
+ type: agentMeta.type || 'tool',
891
891
  name: agentMeta.name,
892
892
  version: agentMeta.version,
893
893
  description: agentMeta.description || undefined,
@@ -903,6 +903,13 @@ Paid Agents:
903
903
  ` Install for AI tools: orchagent skill install ${org}/${parsed.agent}\n` +
904
904
  ` Use with an agent: orchagent run <agent> --skills ${org}/${parsed.agent}`);
905
905
  }
906
+ // Agent type requires a sandbox with tool use — cannot run locally
907
+ if (agentData.type === 'agent') {
908
+ throw new errors_1.CliError('Agent type cannot be run locally.\n\n' +
909
+ 'Agent type requires a sandbox environment with tool use capabilities.\n\n' +
910
+ 'Use server execution instead:\n' +
911
+ ` orchagent call ${org}/${parsed.agent}@${parsed.version} --data '{"task": "..."}'`);
912
+ }
906
913
  // Check for dependencies (orchestrator agents)
907
914
  if (agentData.dependencies && agentData.dependencies.length > 0) {
908
915
  const depStatuses = await (0, spinner_1.withSpinner)('Checking dependencies...', async () => checkDependencies(resolved, agentData.dependencies), { successText: `Found ${agentData.dependencies.length} dependencies` });
@@ -946,31 +953,31 @@ Paid Agents:
946
953
  // Save locally
947
954
  const agentDir = await saveAgentLocally(org, parsed.agent, agentData);
948
955
  process.stderr.write(`\nAgent saved to: ${agentDir}\n`);
949
- if (agentData.type === 'code') {
956
+ if (agentData.type === 'tool') {
950
957
  // Check if this agent has a bundle available for local execution
951
958
  if (agentData.has_bundle) {
952
959
  if (options.downloadOnly) {
953
- process.stdout.write(`\nCode agent has bundle available for local execution.\n`);
960
+ process.stdout.write(`\nTool has bundle available for local execution.\n`);
954
961
  process.stdout.write(`Run with: orch run ${org}/${parsed.agent} [args...]\n`);
955
962
  return;
956
963
  }
957
- // Execute the bundle-based code agent locally
964
+ // Execute the bundle-based tool locally
958
965
  await executeBundleAgent(resolved, org, parsed.agent, parsed.version, agentData, args, options.input);
959
966
  return;
960
967
  }
961
968
  // Check for pip/source-based local execution (legacy)
962
969
  if (agentData.run_command && (agentData.source_url || agentData.pip_package)) {
963
970
  if (options.downloadOnly) {
964
- process.stdout.write(`\nCode agent ready for local execution.\n`);
971
+ process.stdout.write(`\nTool ready for local execution.\n`);
965
972
  process.stdout.write(`Run with: orch run ${org}/${parsed.agent} [args...]\n`);
966
973
  return;
967
974
  }
968
- // Execute the code agent locally
969
- await executeCodeAgent(agentData, args);
975
+ // Execute the tool locally
976
+ await executeTool(agentData, args);
970
977
  return;
971
978
  }
972
979
  // Fallback: agent doesn't support local execution
973
- process.stdout.write(`\nThis is a code-based agent that runs on the server.\n`);
980
+ process.stdout.write(`\nThis is a tool-based agent that runs on the server.\n`);
974
981
  process.stdout.write(`\nUse: orch call ${org}/${parsed.agent}@${parsed.version} --input '{...}'\n`);
975
982
  return;
976
983
  }
@@ -138,7 +138,7 @@ async function detectAgentType(agentDir) {
138
138
  return 'prompt';
139
139
  if (manifest.type === 'skill')
140
140
  return 'skill';
141
- if (manifest.type === 'code') {
141
+ if (manifest.type === 'tool') {
142
142
  // Detect language
143
143
  if (await fileExists(path_1.default.join(agentDir, 'requirements.txt')))
144
144
  return 'code-python';
@@ -146,7 +146,7 @@ async function detectAgentType(agentDir) {
146
146
  return 'code-python';
147
147
  if (await fileExists(path_1.default.join(agentDir, 'package.json')))
148
148
  return 'code-js';
149
- // Default to Python for code agents
149
+ // Default to Python for tool agents
150
150
  return 'code-python';
151
151
  }
152
152
  }
package/dist/lib/api.js CHANGED
@@ -299,12 +299,12 @@ async function searchMyAgents(config, query, options) {
299
299
  if (options?.type) {
300
300
  const typeFilter = options.type;
301
301
  if (typeFilter === 'agents') {
302
- agents = agents.filter(a => a.type === 'prompt' || a.type === 'code');
302
+ agents = agents.filter(a => a.type === 'prompt' || a.type === 'tool');
303
303
  }
304
304
  else if (typeFilter === 'skills' || typeFilter === 'skill') {
305
305
  agents = agents.filter(a => a.type === 'skill');
306
306
  }
307
- else if (typeFilter === 'code' || typeFilter === 'prompt') {
307
+ else if (typeFilter === 'tool' || typeFilter === 'prompt') {
308
308
  agents = agents.filter(a => a.type === typeFilter);
309
309
  }
310
310
  }
@@ -342,7 +342,7 @@ async function fetchLlmKeys(config) {
342
342
  return result.keys;
343
343
  }
344
344
  /**
345
- * Download a code bundle for local execution.
345
+ * Download a tool bundle for local execution.
346
346
  */
347
347
  async function downloadCodeBundle(config, org, agent, version) {
348
348
  const response = await safeFetch(`${config.apiUrl.replace(/\/$/, '')}/public/agents/${org}/${agent}/${version}/bundle`);
@@ -353,7 +353,7 @@ async function downloadCodeBundle(config, org, agent, version) {
353
353
  return Buffer.from(arrayBuffer);
354
354
  }
355
355
  /**
356
- * Upload a code bundle for a hosted code agent.
356
+ * Upload a code bundle for a hosted tool agent.
357
357
  */
358
358
  async function uploadCodeBundle(config, agentId, bundlePath, entrypoint) {
359
359
  if (!config.apiKey) {
@@ -421,7 +421,7 @@ async function getAgentWithFallback(config, org, agentName, version) {
421
421
  return myAgent;
422
422
  }
423
423
  /**
424
- * Download a code bundle for a private agent using authenticated endpoint.
424
+ * Download a tool bundle for a private agent using authenticated endpoint.
425
425
  */
426
426
  async function downloadCodeBundleAuthenticated(config, agentId) {
427
427
  if (!config.apiKey) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * Code bundling utilities for hosted code agents.
3
+ * Code bundling utilities for hosted tools.
4
4
  *
5
5
  * Creates zip bundles from project directories for upload to orchagent.
6
6
  */
@@ -119,14 +119,16 @@ async function createCodeBundle(sourceDir, outputPath, options = {}) {
119
119
  if (!stat.isDirectory()) {
120
120
  throw new Error(`Source path is not a directory: ${sourceDir}`);
121
121
  }
122
- // Verify entrypoint exists if specified
123
- const entrypoint = options.entrypoint || 'main.py';
124
- const entrypointPath = path_1.default.join(sourceDir, entrypoint);
125
- try {
126
- await promises_1.default.access(entrypointPath);
127
- }
128
- catch {
129
- throw new Error(`Entrypoint file not found: ${entrypoint}`);
122
+ // Verify entrypoint exists if specified (skip for agent type that has no code)
123
+ if (!options.skipEntrypointCheck) {
124
+ const entrypoint = options.entrypoint || 'main.py';
125
+ const entrypointPath = path_1.default.join(sourceDir, entrypoint);
126
+ try {
127
+ await promises_1.default.access(entrypointPath);
128
+ }
129
+ catch {
130
+ throw new Error(`Entrypoint file not found: ${entrypoint}`);
131
+ }
130
132
  }
131
133
  // Create output directory if needed
132
134
  const outputDir = path_1.default.dirname(outputPath);
@@ -24,7 +24,7 @@ function printAgentsTable(agents, options) {
24
24
  const table = new cli_table3_1.default({ head });
25
25
  agents.forEach((agent) => {
26
26
  const fullName = `${agent.org_slug}/${agent.name}`;
27
- const type = agent.type || 'code';
27
+ const type = agent.type || 'tool';
28
28
  const providers = formatProviders(agent.supported_providers);
29
29
  const stars = agent.stars_count ?? 0;
30
30
  const price = (0, pricing_1.formatPrice)(agent);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchagent/cli",
3
- "version": "0.3.41",
3
+ "version": "0.3.43",
4
4
  "description": "Command-line interface for the orchagent AI agent marketplace",
5
5
  "license": "MIT",
6
6
  "author": "orchagent <hello@orchagent.io>",