@orchagent/cli 0.3.54 → 0.3.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/index.js +4 -0
- package/dist/commands/init.js +73 -52
- package/dist/commands/publish.js +133 -74
- package/dist/commands/run.js +87 -31
- package/dist/commands/schedule.js +128 -1
- package/dist/commands/service.js +401 -0
- package/dist/commands/transfer.js +219 -0
- package/dist/lib/api.js +18 -1
- package/package.json +1 -1
package/dist/commands/index.js
CHANGED
|
@@ -29,6 +29,8 @@ const security_1 = require("./security");
|
|
|
29
29
|
const billing_1 = require("./billing");
|
|
30
30
|
const agent_keys_1 = require("./agent-keys");
|
|
31
31
|
const schedule_1 = require("./schedule");
|
|
32
|
+
const service_1 = require("./service");
|
|
33
|
+
const transfer_1 = require("./transfer");
|
|
32
34
|
function registerCommands(program) {
|
|
33
35
|
(0, login_1.registerLoginCommand)(program);
|
|
34
36
|
(0, whoami_1.registerWhoamiCommand)(program);
|
|
@@ -58,4 +60,6 @@ function registerCommands(program) {
|
|
|
58
60
|
(0, billing_1.registerBillingCommand)(program);
|
|
59
61
|
(0, agent_keys_1.registerAgentKeysCommand)(program);
|
|
60
62
|
(0, schedule_1.registerScheduleCommand)(program);
|
|
63
|
+
(0, service_1.registerServiceCommand)(program);
|
|
64
|
+
(0, transfer_1.registerTransferCommand)(program);
|
|
61
65
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -10,7 +10,8 @@ const errors_1 = require("../lib/errors");
|
|
|
10
10
|
const MANIFEST_TEMPLATE = `{
|
|
11
11
|
"name": "my-agent",
|
|
12
12
|
"description": "A simple AI agent",
|
|
13
|
-
"type": "
|
|
13
|
+
"type": "agent",
|
|
14
|
+
"run_mode": "on_demand",
|
|
14
15
|
"tags": []
|
|
15
16
|
}
|
|
16
17
|
`;
|
|
@@ -81,13 +82,15 @@ def main():
|
|
|
81
82
|
if __name__ == "__main__":
|
|
82
83
|
main()
|
|
83
84
|
`;
|
|
84
|
-
function readmeTemplate(agentName,
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
function readmeTemplate(agentName, flavor) {
|
|
86
|
+
const inputField = flavor === 'managed_loop' ? 'task' : 'input';
|
|
87
|
+
const inputDescription = flavor === 'managed_loop' ? 'The task to perform' : 'The input to process';
|
|
88
|
+
const cloudExample = flavor === 'code_runtime'
|
|
89
|
+
? `orchagent run ${agentName} --data '{"input": "Hello world"}'`
|
|
90
|
+
: `orchagent run ${agentName} --data '{"${inputField}": "Hello world"}'`;
|
|
91
|
+
const localExample = flavor === 'code_runtime'
|
|
92
|
+
? `orchagent run ${agentName} --local --data '{"input": "Hello world"}'`
|
|
93
|
+
: `orchagent run ${agentName} --local --data '{"${inputField}": "Hello world"}'`;
|
|
91
94
|
return `# ${agentName}
|
|
92
95
|
|
|
93
96
|
A brief description of what this agent does.
|
|
@@ -110,7 +113,7 @@ ${localExample}
|
|
|
110
113
|
|
|
111
114
|
| Field | Type | Description |
|
|
112
115
|
|-------|------|-------------|
|
|
113
|
-
| \`${
|
|
116
|
+
| \`${inputField}\` | string | ${inputDescription} |
|
|
114
117
|
|
|
115
118
|
## Output
|
|
116
119
|
|
|
@@ -119,14 +122,6 @@ ${localExample}
|
|
|
119
122
|
| \`result\` | string | The agent's response |
|
|
120
123
|
`;
|
|
121
124
|
}
|
|
122
|
-
const AGENT_MANIFEST_TEMPLATE = `{
|
|
123
|
-
"name": "my-agent",
|
|
124
|
-
"description": "An AI agent with tool use",
|
|
125
|
-
"type": "agent",
|
|
126
|
-
"supported_providers": ["anthropic"],
|
|
127
|
-
"max_turns": 25
|
|
128
|
-
}
|
|
129
|
-
`;
|
|
130
125
|
const AGENT_PROMPT_TEMPLATE = `You are a helpful AI agent.
|
|
131
126
|
|
|
132
127
|
Given the input, complete the task step by step.
|
|
@@ -169,14 +164,39 @@ license: MIT
|
|
|
169
164
|
|
|
170
165
|
Instructions and guidance for AI agents...
|
|
171
166
|
`;
|
|
167
|
+
function resolveInitFlavor(typeOption) {
|
|
168
|
+
const normalized = (typeOption || 'agent').trim().toLowerCase();
|
|
169
|
+
if (normalized === 'skill') {
|
|
170
|
+
return { type: 'skill' };
|
|
171
|
+
}
|
|
172
|
+
if (normalized === 'agent') {
|
|
173
|
+
return { type: 'agent', flavor: 'direct_llm' };
|
|
174
|
+
}
|
|
175
|
+
if (normalized === 'prompt') {
|
|
176
|
+
return { type: 'agent', flavor: 'direct_llm' };
|
|
177
|
+
}
|
|
178
|
+
if (normalized === 'agentic') {
|
|
179
|
+
return { type: 'agent', flavor: 'managed_loop' };
|
|
180
|
+
}
|
|
181
|
+
if (normalized === 'tool' || normalized === 'code') {
|
|
182
|
+
return { type: 'agent', flavor: 'code_runtime' };
|
|
183
|
+
}
|
|
184
|
+
throw new errors_1.CliError(`Unknown --type '${typeOption}'. Use 'agent' or 'skill' (legacy: prompt, tool, agentic, code).`);
|
|
185
|
+
}
|
|
172
186
|
function registerInitCommand(program) {
|
|
173
187
|
program
|
|
174
188
|
.command('init')
|
|
175
189
|
.description('Initialize a new agent project')
|
|
176
190
|
.argument('[name]', 'Agent name (default: current directory name)')
|
|
177
|
-
.option('--type <type>', 'Type:
|
|
191
|
+
.option('--type <type>', 'Type: agent or skill (legacy: prompt, tool, agentic, code)', 'agent')
|
|
192
|
+
.option('--run-mode <mode>', 'Run mode for agents: on_demand or always_on', 'on_demand')
|
|
178
193
|
.action(async (name, options) => {
|
|
179
194
|
const cwd = process.cwd();
|
|
195
|
+
const runMode = (options.runMode || 'on_demand').trim().toLowerCase();
|
|
196
|
+
if (!['on_demand', 'always_on'].includes(runMode)) {
|
|
197
|
+
throw new errors_1.CliError("Invalid --run-mode. Use 'on_demand' or 'always_on'.");
|
|
198
|
+
}
|
|
199
|
+
const initMode = resolveInitFlavor(options.type);
|
|
180
200
|
// When a name is provided, create a subdirectory for the project
|
|
181
201
|
const targetDir = name ? path_1.default.join(cwd, name) : cwd;
|
|
182
202
|
const agentName = name || path_1.default.basename(cwd);
|
|
@@ -185,7 +205,7 @@ function registerInitCommand(program) {
|
|
|
185
205
|
await promises_1.default.mkdir(targetDir, { recursive: true });
|
|
186
206
|
}
|
|
187
207
|
// Handle skill type separately
|
|
188
|
-
if (
|
|
208
|
+
if (initMode.type === 'skill') {
|
|
189
209
|
const skillPath = path_1.default.join(targetDir, 'SKILL.md');
|
|
190
210
|
// Check if already initialized
|
|
191
211
|
try {
|
|
@@ -227,38 +247,45 @@ function registerInitCommand(program) {
|
|
|
227
247
|
throw err;
|
|
228
248
|
}
|
|
229
249
|
}
|
|
250
|
+
if (initMode.flavor === 'direct_llm' && runMode === 'always_on') {
|
|
251
|
+
throw new errors_1.CliError("run_mode=always_on requires a non-direct runtime. Use legacy '--type tool' or add runtime.command in orchagent.json.");
|
|
252
|
+
}
|
|
230
253
|
// Create manifest and type-specific files
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
254
|
+
const manifest = JSON.parse(MANIFEST_TEMPLATE);
|
|
255
|
+
manifest.name = agentName;
|
|
256
|
+
manifest.type = 'agent';
|
|
257
|
+
manifest.run_mode = runMode;
|
|
258
|
+
if (initMode.flavor === 'managed_loop') {
|
|
259
|
+
manifest.description = 'An AI agent with tool use';
|
|
260
|
+
manifest.supported_providers = ['anthropic'];
|
|
261
|
+
manifest.loop = { max_turns: 25 };
|
|
262
|
+
}
|
|
263
|
+
else if (initMode.flavor === 'code_runtime') {
|
|
264
|
+
manifest.description = 'A code-runtime agent';
|
|
265
|
+
manifest.runtime = { command: 'python main.py' };
|
|
266
|
+
}
|
|
267
|
+
await promises_1.default.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
268
|
+
if (initMode.flavor === 'code_runtime') {
|
|
269
|
+
const entrypointPath = path_1.default.join(targetDir, 'main.py');
|
|
270
|
+
await promises_1.default.writeFile(entrypointPath, CODE_TEMPLATE_PY);
|
|
271
|
+
await promises_1.default.writeFile(schemaPath, SCHEMA_TEMPLATE);
|
|
272
|
+
}
|
|
273
|
+
else if (initMode.flavor === 'managed_loop') {
|
|
235
274
|
await promises_1.default.writeFile(promptPath, AGENT_PROMPT_TEMPLATE);
|
|
236
275
|
await promises_1.default.writeFile(schemaPath, AGENT_SCHEMA_TEMPLATE);
|
|
237
276
|
}
|
|
238
277
|
else {
|
|
239
|
-
|
|
240
|
-
manifest.name = agentName;
|
|
241
|
-
manifest.type = ['tool', 'skill'].includes(options.type) ? options.type : 'prompt';
|
|
242
|
-
await promises_1.default.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
243
|
-
// Create prompt template (for prompt-based agents) or entrypoint (for tool agents)
|
|
244
|
-
if (options.type === 'tool') {
|
|
245
|
-
const entrypointPath = path_1.default.join(targetDir, 'main.py');
|
|
246
|
-
await promises_1.default.writeFile(entrypointPath, CODE_TEMPLATE_PY);
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
await promises_1.default.writeFile(promptPath, PROMPT_TEMPLATE);
|
|
250
|
-
}
|
|
251
|
-
// Create schema template
|
|
278
|
+
await promises_1.default.writeFile(promptPath, PROMPT_TEMPLATE);
|
|
252
279
|
await promises_1.default.writeFile(schemaPath, SCHEMA_TEMPLATE);
|
|
253
280
|
}
|
|
254
281
|
// Create README
|
|
255
282
|
const readmePath = path_1.default.join(targetDir, 'README.md');
|
|
256
|
-
await promises_1.default.writeFile(readmePath, readmeTemplate(agentName,
|
|
283
|
+
await promises_1.default.writeFile(readmePath, readmeTemplate(agentName, initMode.flavor || 'direct_llm'));
|
|
257
284
|
process.stdout.write(`Initialized agent "${agentName}" in ${targetDir}\n`);
|
|
258
285
|
process.stdout.write(`\nFiles created:\n`);
|
|
259
286
|
const prefix = name ? name + '/' : '';
|
|
260
287
|
process.stdout.write(` ${prefix}orchagent.json - Agent configuration\n`);
|
|
261
|
-
if (
|
|
288
|
+
if (initMode.flavor === 'code_runtime') {
|
|
262
289
|
process.stdout.write(` ${prefix}main.py - Agent entrypoint (stdin/stdout JSON)\n`);
|
|
263
290
|
}
|
|
264
291
|
else {
|
|
@@ -266,32 +293,26 @@ function registerInitCommand(program) {
|
|
|
266
293
|
}
|
|
267
294
|
process.stdout.write(` ${prefix}schema.json - Input/output schemas\n`);
|
|
268
295
|
process.stdout.write(` ${prefix}README.md - Agent documentation\n`);
|
|
296
|
+
process.stdout.write(` Run mode: ${runMode}\n`);
|
|
297
|
+
process.stdout.write(` Execution: ${initMode.flavor}\n`);
|
|
269
298
|
process.stdout.write(`\nNext steps:\n`);
|
|
270
|
-
if (
|
|
271
|
-
const stepNum = name ? 2 : 1;
|
|
272
|
-
if (name) {
|
|
273
|
-
process.stdout.write(` 1. cd ${name}\n`);
|
|
274
|
-
}
|
|
275
|
-
process.stdout.write(` ${stepNum}. Edit prompt.md with your agent instructions\n`);
|
|
276
|
-
process.stdout.write(` ${stepNum + 1}. Edit schema.json with your input/output schemas\n`);
|
|
277
|
-
process.stdout.write(` ${stepNum + 2}. Run: orchagent publish\n`);
|
|
278
|
-
}
|
|
279
|
-
else if (options.type !== 'tool') {
|
|
299
|
+
if (initMode.flavor === 'code_runtime') {
|
|
280
300
|
const stepNum = name ? 2 : 1;
|
|
281
301
|
if (name) {
|
|
282
302
|
process.stdout.write(` 1. cd ${name}\n`);
|
|
283
303
|
}
|
|
284
|
-
process.stdout.write(` ${stepNum}. Edit
|
|
304
|
+
process.stdout.write(` ${stepNum}. Edit main.py with your agent logic\n`);
|
|
285
305
|
process.stdout.write(` ${stepNum + 1}. Edit schema.json with your input/output schemas\n`);
|
|
286
|
-
process.stdout.write(` ${stepNum + 2}.
|
|
306
|
+
process.stdout.write(` ${stepNum + 2}. Test: echo '{"input": "test"}' | python main.py\n`);
|
|
307
|
+
process.stdout.write(` ${stepNum + 3}. Run: orchagent publish\n`);
|
|
287
308
|
}
|
|
288
309
|
else {
|
|
289
310
|
const stepNum = name ? 2 : 1;
|
|
290
311
|
if (name) {
|
|
291
312
|
process.stdout.write(` 1. cd ${name}\n`);
|
|
292
313
|
}
|
|
293
|
-
process.stdout.write(` ${stepNum}. Edit
|
|
294
|
-
process.stdout.write(` ${stepNum + 1}.
|
|
314
|
+
process.stdout.write(` ${stepNum}. Edit prompt.md with your agent instructions\n`);
|
|
315
|
+
process.stdout.write(` ${stepNum + 1}. Edit schema.json with your input/output schemas\n`);
|
|
295
316
|
process.stdout.write(` ${stepNum + 2}. Run: orchagent publish\n`);
|
|
296
317
|
}
|
|
297
318
|
});
|
package/dist/commands/publish.js
CHANGED
|
@@ -161,6 +161,48 @@ async function collectSkillFiles(skillDir, maxFiles = 20, maxTotalSize = 500_000
|
|
|
161
161
|
await walkDir(skillDir);
|
|
162
162
|
return files;
|
|
163
163
|
}
|
|
164
|
+
function canonicalizeManifestType(typeValue) {
|
|
165
|
+
const rawType = (typeValue || 'agent').trim().toLowerCase();
|
|
166
|
+
if (rawType === 'skill') {
|
|
167
|
+
return { canonicalType: 'skill', rawType };
|
|
168
|
+
}
|
|
169
|
+
if (['agent', 'prompt', 'tool', 'agentic', 'code'].includes(rawType)) {
|
|
170
|
+
return { canonicalType: 'agent', rawType };
|
|
171
|
+
}
|
|
172
|
+
throw new errors_1.CliError(`Invalid type '${typeValue}'. Use 'agent' or 'skill' (legacy values accepted: prompt, tool, agentic, code).`);
|
|
173
|
+
}
|
|
174
|
+
function normalizeRunMode(runMode) {
|
|
175
|
+
const normalized = (runMode || 'on_demand').trim().toLowerCase();
|
|
176
|
+
if (normalized === 'on_demand' || normalized === 'always_on') {
|
|
177
|
+
return normalized;
|
|
178
|
+
}
|
|
179
|
+
throw new errors_1.CliError("run_mode must be 'on_demand' or 'always_on'");
|
|
180
|
+
}
|
|
181
|
+
function inferExecutionEngineFromManifest(manifest, rawType) {
|
|
182
|
+
const runtimeCommand = manifest.runtime?.command?.trim();
|
|
183
|
+
const hasLoop = Boolean(manifest.loop && Object.keys(manifest.loop).length > 0);
|
|
184
|
+
if (runtimeCommand && hasLoop) {
|
|
185
|
+
throw new errors_1.CliError('runtime.command and loop cannot both be set');
|
|
186
|
+
}
|
|
187
|
+
if (runtimeCommand)
|
|
188
|
+
return 'code_runtime';
|
|
189
|
+
if (hasLoop)
|
|
190
|
+
return 'managed_loop';
|
|
191
|
+
if (rawType === 'tool' || rawType === 'code')
|
|
192
|
+
return 'code_runtime';
|
|
193
|
+
if (rawType === 'agentic')
|
|
194
|
+
return 'managed_loop';
|
|
195
|
+
if (rawType === 'agent' && (manifest.custom_tools?.length || manifest.max_turns)) {
|
|
196
|
+
return 'managed_loop';
|
|
197
|
+
}
|
|
198
|
+
return 'direct_llm';
|
|
199
|
+
}
|
|
200
|
+
function commandForEntrypoint(entrypoint) {
|
|
201
|
+
if (entrypoint.endsWith('.js') || entrypoint.endsWith('.mjs') || entrypoint.endsWith('.cjs') || entrypoint.endsWith('.ts')) {
|
|
202
|
+
return `node ${entrypoint}`;
|
|
203
|
+
}
|
|
204
|
+
return `python ${entrypoint}`;
|
|
205
|
+
}
|
|
164
206
|
function registerPublishCommand(program) {
|
|
165
207
|
program
|
|
166
208
|
.command('publish')
|
|
@@ -269,6 +311,16 @@ function registerPublishCommand(program) {
|
|
|
269
311
|
if (!manifest.name) {
|
|
270
312
|
throw new errors_1.CliError('orchagent.json must have name');
|
|
271
313
|
}
|
|
314
|
+
const { canonicalType, rawType } = canonicalizeManifestType(manifest.type);
|
|
315
|
+
const runMode = normalizeRunMode(manifest.run_mode);
|
|
316
|
+
const executionEngine = inferExecutionEngineFromManifest(manifest, rawType);
|
|
317
|
+
const callable = Boolean(manifest.callable);
|
|
318
|
+
if (canonicalType === 'skill') {
|
|
319
|
+
throw new errors_1.CliError("Use SKILL.md for publishing skills. Remove orchagent.json and run 'orchagent publish' from a skill directory.");
|
|
320
|
+
}
|
|
321
|
+
if (runMode === 'always_on' && executionEngine === 'direct_llm') {
|
|
322
|
+
throw new errors_1.CliError('run_mode=always_on requires runtime.command or loop configuration');
|
|
323
|
+
}
|
|
272
324
|
// Warn about deprecated prompt field
|
|
273
325
|
if (manifest.prompt) {
|
|
274
326
|
process.stderr.write(chalk_1.default.yellow('Warning: "prompt" field in orchagent.json is ignored. Use prompt.md file instead.\n'));
|
|
@@ -310,7 +362,7 @@ function registerPublishCommand(program) {
|
|
|
310
362
|
`These must be nested under a "manifest" key. Example:\n\n` +
|
|
311
363
|
` {\n` +
|
|
312
364
|
` "name": "${manifest.name}",\n` +
|
|
313
|
-
` "type": "${manifest.type || '
|
|
365
|
+
` "type": "${manifest.type || 'agent'}",\n` +
|
|
314
366
|
` "manifest": {\n` +
|
|
315
367
|
` "manifest_version": 1,\n` +
|
|
316
368
|
` "dependencies": [...],\n` +
|
|
@@ -321,26 +373,25 @@ function registerPublishCommand(program) {
|
|
|
321
373
|
` }\n\n` +
|
|
322
374
|
`See docs/manifest.md for details.`);
|
|
323
375
|
}
|
|
324
|
-
// Read prompt
|
|
376
|
+
// Read prompt for LLM-driven engines (direct_llm + managed_loop).
|
|
325
377
|
let prompt;
|
|
326
|
-
if (
|
|
378
|
+
if (executionEngine === 'direct_llm' || executionEngine === 'managed_loop') {
|
|
327
379
|
const promptPath = path_1.default.join(cwd, 'prompt.md');
|
|
328
380
|
try {
|
|
329
381
|
prompt = await promises_1.default.readFile(promptPath, 'utf-8');
|
|
330
382
|
}
|
|
331
383
|
catch (err) {
|
|
332
384
|
if (err.code === 'ENOENT') {
|
|
333
|
-
|
|
334
|
-
throw new errors_1.CliError(`No prompt.md found for ${agentTypeName}.\n\n` +
|
|
385
|
+
throw new errors_1.CliError('No prompt.md found for this agent.\n\n' +
|
|
335
386
|
'Create a prompt.md file in the current directory with your prompt template.\n' +
|
|
336
387
|
'See: https://orchagent.io/docs/publishing');
|
|
337
388
|
}
|
|
338
389
|
throw err;
|
|
339
390
|
}
|
|
340
391
|
}
|
|
341
|
-
//
|
|
342
|
-
|
|
343
|
-
|
|
392
|
+
// Validate managed-loop specific fields + normalize loop payload
|
|
393
|
+
let loopConfig;
|
|
394
|
+
if (executionEngine === 'managed_loop') {
|
|
344
395
|
if (manifest.custom_tools) {
|
|
345
396
|
const reservedNames = new Set(['bash', 'read_file', 'write_file', 'list_files', 'submit_result']);
|
|
346
397
|
const seenNames = new Set();
|
|
@@ -359,24 +410,24 @@ function registerPublishCommand(program) {
|
|
|
359
410
|
seenNames.add(tool.name);
|
|
360
411
|
}
|
|
361
412
|
}
|
|
362
|
-
// Validate max_turns
|
|
363
413
|
if (manifest.max_turns !== undefined) {
|
|
364
414
|
if (typeof manifest.max_turns !== 'number' || manifest.max_turns < 1 || manifest.max_turns > 50) {
|
|
365
415
|
throw new errors_1.CliError('max_turns must be a number between 1 and 50');
|
|
366
416
|
}
|
|
367
417
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
418
|
+
const providedLoop = manifest.loop && typeof manifest.loop === 'object'
|
|
419
|
+
? { ...manifest.loop }
|
|
420
|
+
: {};
|
|
421
|
+
if (!('max_turns' in providedLoop) && manifest.max_turns !== undefined) {
|
|
422
|
+
providedLoop.max_turns = manifest.max_turns;
|
|
423
|
+
}
|
|
424
|
+
if (!('custom_tools' in providedLoop) && manifest.custom_tools?.length) {
|
|
425
|
+
providedLoop.custom_tools = manifest.custom_tools;
|
|
374
426
|
}
|
|
375
|
-
if (
|
|
376
|
-
|
|
427
|
+
if (Object.keys(providedLoop).length === 0) {
|
|
428
|
+
providedLoop.max_turns = 25;
|
|
377
429
|
}
|
|
378
|
-
|
|
379
|
-
// Agent type defaults to anthropic provider
|
|
430
|
+
loopConfig = providedLoop;
|
|
380
431
|
if (!manifest.supported_providers) {
|
|
381
432
|
manifest.supported_providers = ['anthropic'];
|
|
382
433
|
}
|
|
@@ -398,9 +449,8 @@ function registerPublishCommand(program) {
|
|
|
398
449
|
throw new errors_1.CliError(`Failed to read schema.json: ${err}`);
|
|
399
450
|
}
|
|
400
451
|
}
|
|
401
|
-
// For
|
|
402
|
-
|
|
403
|
-
if (prompt && (manifest.type === 'prompt' || manifest.type === 'skill')) {
|
|
452
|
+
// For direct LLM and managed loop agents, derive input schema from template variables if needed.
|
|
453
|
+
if (prompt && (executionEngine === 'direct_llm' || executionEngine === 'managed_loop')) {
|
|
404
454
|
const templateVars = extractTemplateVariables(prompt);
|
|
405
455
|
if (templateVars.length > 0) {
|
|
406
456
|
if (!schemaFromFile) {
|
|
@@ -426,47 +476,44 @@ function registerPublishCommand(program) {
|
|
|
426
476
|
}
|
|
427
477
|
}
|
|
428
478
|
}
|
|
429
|
-
// For tool-based agents, either --url is required OR we bundle the code
|
|
430
|
-
// For agent type, use internal placeholder (no user code, platform handles execution)
|
|
431
479
|
let agentUrl = options.url;
|
|
432
480
|
let shouldUploadBundle = false;
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
process.stdout.write(`Including Dockerfile for custom environment\n`);
|
|
481
|
+
let runtimeConfig;
|
|
482
|
+
let bundleEntrypoint = manifest.entrypoint;
|
|
483
|
+
if (executionEngine === 'code_runtime') {
|
|
484
|
+
if (!bundleEntrypoint) {
|
|
485
|
+
bundleEntrypoint = await (0, bundle_1.detectEntrypoint)(cwd) || undefined;
|
|
486
|
+
}
|
|
487
|
+
if (!options.url) {
|
|
488
|
+
if (!bundleEntrypoint) {
|
|
489
|
+
throw new errors_1.CliError('Tool requires either --url <url> or an entry point file (main.py, app.py, index.js, etc.)');
|
|
443
490
|
}
|
|
444
|
-
catch {
|
|
445
|
-
throw new errors_1.CliError('--docker flag specified but no Dockerfile found in project directory');
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
else if (manifest.type === 'tool' && !options.url) {
|
|
450
|
-
// Check if this looks like a Python or JS project that can be bundled
|
|
451
|
-
const entrypoint = manifest.entrypoint || await (0, bundle_1.detectEntrypoint)(cwd);
|
|
452
|
-
if (entrypoint) {
|
|
453
|
-
// This is a hosted tool - we'll bundle and upload
|
|
454
491
|
shouldUploadBundle = true;
|
|
455
|
-
// Set a placeholder URL that tells the gateway to use sandbox execution
|
|
456
492
|
agentUrl = 'https://tool.internal';
|
|
457
|
-
process.stdout.write(`Detected
|
|
493
|
+
process.stdout.write(`Detected code runtime entrypoint: ${bundleEntrypoint}\n`);
|
|
458
494
|
}
|
|
459
|
-
|
|
460
|
-
|
|
495
|
+
let runtimeCommand = manifest.runtime?.command?.trim() || '';
|
|
496
|
+
if (!runtimeCommand && manifest.run_command?.trim()) {
|
|
497
|
+
runtimeCommand = manifest.run_command.trim();
|
|
498
|
+
}
|
|
499
|
+
if (!runtimeCommand) {
|
|
500
|
+
runtimeCommand = commandForEntrypoint(bundleEntrypoint || 'main.py');
|
|
461
501
|
}
|
|
502
|
+
runtimeConfig = { ...(manifest.runtime || {}), command: runtimeCommand };
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
agentUrl = agentUrl || 'https://prompt-agent.internal';
|
|
506
|
+
}
|
|
507
|
+
if (options.docker && executionEngine !== 'code_runtime') {
|
|
508
|
+
throw new errors_1.CliError('--docker is only supported for code runtime agents');
|
|
462
509
|
}
|
|
463
510
|
// Get org info
|
|
464
511
|
const org = await (0, api_1.getOrg)(config);
|
|
465
512
|
// Default to 'any' provider if not specified
|
|
466
513
|
const supportedProviders = manifest.supported_providers || ['any'];
|
|
467
|
-
// Detect SDK compatibility for
|
|
514
|
+
// Detect SDK compatibility for code runtime agents
|
|
468
515
|
let sdkCompatible = false;
|
|
469
|
-
if (
|
|
516
|
+
if (executionEngine === 'code_runtime') {
|
|
470
517
|
sdkCompatible = await detectSdkCompatible(cwd);
|
|
471
518
|
if (sdkCompatible && !options.dryRun) {
|
|
472
519
|
process.stdout.write(`SDK detected - agent will be marked as Local Ready\n`);
|
|
@@ -481,8 +528,7 @@ function registerPublishCommand(program) {
|
|
|
481
528
|
process.stderr.write('\nDRY RUN - No changes will be made\n\n');
|
|
482
529
|
process.stderr.write('Validating...\n');
|
|
483
530
|
process.stderr.write(` ✓ orchagent.json found and valid\n`);
|
|
484
|
-
if (
|
|
485
|
-
// Prompt agent validations
|
|
531
|
+
if (executionEngine === 'direct_llm') {
|
|
486
532
|
const promptBytes = prompt ? Buffer.byteLength(prompt, 'utf-8') : 0;
|
|
487
533
|
process.stderr.write(` ✓ prompt.md found (${promptBytes.toLocaleString()} bytes)\n`);
|
|
488
534
|
if (schemaFromFile) {
|
|
@@ -494,31 +540,29 @@ function registerPublishCommand(program) {
|
|
|
494
540
|
process.stderr.write(` ✓ Input schema derived from template variables: ${vars.join(', ')}\n`);
|
|
495
541
|
}
|
|
496
542
|
}
|
|
497
|
-
else if (
|
|
498
|
-
// Agent type validations
|
|
543
|
+
else if (executionEngine === 'managed_loop') {
|
|
499
544
|
const promptBytes = prompt ? Buffer.byteLength(prompt, 'utf-8') : 0;
|
|
500
545
|
process.stderr.write(` ✓ prompt.md found (${promptBytes.toLocaleString()} bytes)\n`);
|
|
501
546
|
if (schemaFromFile) {
|
|
502
547
|
const schemaTypes = [inputSchema ? 'input' : null, outputSchema ? 'output' : null].filter(Boolean).join(' + ');
|
|
503
548
|
process.stderr.write(` ✓ schema.json found (${schemaTypes} schemas)\n`);
|
|
504
549
|
}
|
|
505
|
-
const customToolCount = manifest.custom_tools?.length || 0;
|
|
550
|
+
const customToolCount = manifest.custom_tools?.length || Number(Array.isArray(loopConfig?.custom_tools) ? loopConfig.custom_tools.length : 0);
|
|
506
551
|
process.stderr.write(` ✓ Custom tools: ${customToolCount}\n`);
|
|
507
|
-
process.stderr.write(` ✓ Max turns: ${manifest.max_turns || 25}\n`);
|
|
552
|
+
process.stderr.write(` ✓ Max turns: ${loopConfig?.max_turns || manifest.max_turns || 25}\n`);
|
|
508
553
|
}
|
|
509
|
-
else if (
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
process.stderr.write(` ✓ Entrypoint: ${entrypoint}\n`);
|
|
554
|
+
else if (executionEngine === 'code_runtime') {
|
|
555
|
+
process.stderr.write(` ✓ runtime.command: ${String(runtimeConfig?.command || '')}\n`);
|
|
556
|
+
process.stderr.write(` ✓ Entrypoint: ${bundleEntrypoint || '(remote url only)'}\n`);
|
|
513
557
|
if (sdkCompatible) {
|
|
514
558
|
process.stderr.write(` ✓ SDK detected (orchagent-sdk in requirements.txt)\n`);
|
|
515
559
|
}
|
|
516
560
|
}
|
|
517
561
|
process.stderr.write(` ✓ Authentication valid (org: ${org.slug})\n`);
|
|
518
|
-
// For
|
|
562
|
+
// For hosted code-runtime agents, show bundle preview
|
|
519
563
|
if (shouldUploadBundle) {
|
|
520
564
|
const bundlePreview = await (0, bundle_1.previewBundle)(cwd, {
|
|
521
|
-
entrypoint:
|
|
565
|
+
entrypoint: bundleEntrypoint,
|
|
522
566
|
exclude: manifest.bundle?.exclude,
|
|
523
567
|
include: manifest.bundle?.include,
|
|
524
568
|
});
|
|
@@ -529,7 +573,10 @@ function registerPublishCommand(program) {
|
|
|
529
573
|
}
|
|
530
574
|
process.stderr.write('\nAgent Preview:\n');
|
|
531
575
|
process.stderr.write(` Name: ${manifest.name}\n`);
|
|
532
|
-
process.stderr.write(` Type: ${
|
|
576
|
+
process.stderr.write(` Type: ${canonicalType}\n`);
|
|
577
|
+
process.stderr.write(` Run mode: ${runMode}\n`);
|
|
578
|
+
process.stderr.write(` Engine: ${executionEngine}${shouldUploadBundle ? ' (hosted)' : ''}\n`);
|
|
579
|
+
process.stderr.write(` Callable: ${callable ? 'enabled' : 'disabled'}\n`);
|
|
533
580
|
process.stderr.write(` Version: ${versionInfo}\n`);
|
|
534
581
|
process.stderr.write(` Visibility: private\n`);
|
|
535
582
|
process.stderr.write(` Providers: ${supportedProviders.join(', ')}\n`);
|
|
@@ -544,7 +591,7 @@ function registerPublishCommand(program) {
|
|
|
544
591
|
process.stderr.write(`\nWould publish: ${preview.org_slug}/${manifest.name}@${preview.next_version}\n`);
|
|
545
592
|
if (shouldUploadBundle) {
|
|
546
593
|
const bundlePreview = await (0, bundle_1.previewBundle)(cwd, {
|
|
547
|
-
entrypoint:
|
|
594
|
+
entrypoint: bundleEntrypoint,
|
|
548
595
|
exclude: manifest.bundle?.exclude,
|
|
549
596
|
include: manifest.bundle?.include,
|
|
550
597
|
});
|
|
@@ -559,7 +606,11 @@ function registerPublishCommand(program) {
|
|
|
559
606
|
try {
|
|
560
607
|
result = await (0, api_1.createAgent)(config, {
|
|
561
608
|
name: manifest.name,
|
|
562
|
-
type:
|
|
609
|
+
type: canonicalType,
|
|
610
|
+
run_mode: runMode,
|
|
611
|
+
runtime: runtimeConfig,
|
|
612
|
+
loop: loopConfig,
|
|
613
|
+
callable,
|
|
563
614
|
description: manifest.description,
|
|
564
615
|
prompt,
|
|
565
616
|
url: agentUrl,
|
|
@@ -569,7 +620,7 @@ function registerPublishCommand(program) {
|
|
|
569
620
|
is_public: false,
|
|
570
621
|
supported_providers: supportedProviders,
|
|
571
622
|
default_models: manifest.default_models,
|
|
572
|
-
// Local run fields for
|
|
623
|
+
// Local run fields for code runtime agents
|
|
573
624
|
source_url: manifest.source_url,
|
|
574
625
|
pip_package: manifest.pip_package,
|
|
575
626
|
run_command: manifest.run_command,
|
|
@@ -615,7 +666,7 @@ function registerPublishCommand(program) {
|
|
|
615
666
|
}
|
|
616
667
|
const assignedVersion = result.agent?.version || 'v1';
|
|
617
668
|
const agentId = result.agent?.id;
|
|
618
|
-
// Upload code bundle
|
|
669
|
+
// Upload code bundle for hosted code runtime agents
|
|
619
670
|
if (shouldUploadBundle && agentId) {
|
|
620
671
|
process.stdout.write(`\nBundling code...\n`);
|
|
621
672
|
const tempDir = await promises_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'orchagent-bundle-'));
|
|
@@ -634,8 +685,7 @@ function registerPublishCommand(program) {
|
|
|
634
685
|
throw new errors_1.CliError('--docker flag specified but no Dockerfile found in project directory');
|
|
635
686
|
}
|
|
636
687
|
}
|
|
637
|
-
|
|
638
|
-
if (manifest.type === 'agent') {
|
|
688
|
+
if (executionEngine === 'code_runtime') {
|
|
639
689
|
const reqPath = path_1.default.join(cwd, 'requirements.txt');
|
|
640
690
|
try {
|
|
641
691
|
await promises_1.default.access(reqPath);
|
|
@@ -647,10 +697,10 @@ function registerPublishCommand(program) {
|
|
|
647
697
|
}
|
|
648
698
|
}
|
|
649
699
|
const bundleResult = await (0, bundle_1.createCodeBundle)(cwd, bundlePath, {
|
|
650
|
-
entrypoint:
|
|
700
|
+
entrypoint: bundleEntrypoint,
|
|
651
701
|
exclude: manifest.bundle?.exclude,
|
|
652
702
|
include: includePatterns.length > 0 ? includePatterns : undefined,
|
|
653
|
-
skipEntrypointCheck:
|
|
703
|
+
skipEntrypointCheck: false,
|
|
654
704
|
});
|
|
655
705
|
process.stdout.write(` Created bundle: ${bundleResult.fileCount} files, ${(bundleResult.sizeBytes / 1024).toFixed(1)}KB\n`);
|
|
656
706
|
// Validate bundle size
|
|
@@ -660,7 +710,7 @@ function registerPublishCommand(program) {
|
|
|
660
710
|
}
|
|
661
711
|
// Upload the bundle with entrypoint
|
|
662
712
|
process.stdout.write(` Uploading bundle...\n`);
|
|
663
|
-
const uploadResult = await (0, api_1.uploadCodeBundle)(config, agentId, bundlePath,
|
|
713
|
+
const uploadResult = await (0, api_1.uploadCodeBundle)(config, agentId, bundlePath, bundleEntrypoint);
|
|
664
714
|
process.stdout.write(` Uploaded: ${uploadResult.code_hash.substring(0, 12)}...\n`);
|
|
665
715
|
// Show environment info if applicable
|
|
666
716
|
if (uploadResult.environment_id) {
|
|
@@ -682,9 +732,18 @@ function registerPublishCommand(program) {
|
|
|
682
732
|
await promises_1.default.rm(tempDir, { recursive: true, force: true });
|
|
683
733
|
}
|
|
684
734
|
}
|
|
685
|
-
await (0, analytics_1.track)('cli_publish', {
|
|
735
|
+
await (0, analytics_1.track)('cli_publish', {
|
|
736
|
+
agent_type: canonicalType,
|
|
737
|
+
execution_engine: executionEngine,
|
|
738
|
+
run_mode: runMode,
|
|
739
|
+
callable,
|
|
740
|
+
hosted: shouldUploadBundle,
|
|
741
|
+
});
|
|
686
742
|
process.stdout.write(`\nPublished agent: ${org.slug}/${manifest.name}@${assignedVersion}\n`);
|
|
687
|
-
process.stdout.write(`Type: ${
|
|
743
|
+
process.stdout.write(`Type: ${canonicalType}\n`);
|
|
744
|
+
process.stdout.write(`Run mode: ${runMode}\n`);
|
|
745
|
+
process.stdout.write(`Execution engine: ${executionEngine}${shouldUploadBundle ? ' (hosted)' : ''}\n`);
|
|
746
|
+
process.stdout.write(`Callable: ${callable ? 'enabled' : 'disabled'}\n`);
|
|
688
747
|
process.stdout.write(`Providers: ${supportedProviders.join(', ')}\n`);
|
|
689
748
|
process.stdout.write(`Visibility: private\n`);
|
|
690
749
|
// Show security review result if available
|