@orchagent/cli 0.3.48 → 0.3.51
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/agent-keys.js +84 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/publish.js +48 -11
- package/dist/commands/run.js +744 -122
- package/dist/lib/api.js +12 -0
- package/dist/lib/errors.js +1 -0
- package/dist/lib/sse.js +41 -0
- package/package.json +3 -2
- package/src/resources/agent_runner.py +768 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerAgentKeysCommand = registerAgentKeysCommand;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const config_1 = require("../lib/config");
|
|
9
|
+
const api_1 = require("../lib/api");
|
|
10
|
+
const errors_1 = require("../lib/errors");
|
|
11
|
+
/**
|
|
12
|
+
* Resolve an agent reference ("org/agent" or just "agent") to an agent ID.
|
|
13
|
+
* Uses the authenticated list-agents endpoint and finds the latest version.
|
|
14
|
+
*/
|
|
15
|
+
async function resolveAgentId(config, ref) {
|
|
16
|
+
const parts = ref.split('/');
|
|
17
|
+
const agentName = parts.length >= 2 ? parts[1] : parts[0];
|
|
18
|
+
const agents = await (0, api_1.listMyAgents)(config);
|
|
19
|
+
const matching = agents.filter(a => a.name === agentName);
|
|
20
|
+
if (matching.length === 0) {
|
|
21
|
+
throw new errors_1.CliError(`Agent '${ref}' not found. Run 'orchagent agents' to list your agents.`);
|
|
22
|
+
}
|
|
23
|
+
// Use the latest version
|
|
24
|
+
const latest = matching.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0];
|
|
25
|
+
return { agent: latest, agentId: latest.id };
|
|
26
|
+
}
|
|
27
|
+
function registerAgentKeysCommand(program) {
|
|
28
|
+
const agentKeys = program
|
|
29
|
+
.command('agent-keys')
|
|
30
|
+
.description('Manage agent service keys');
|
|
31
|
+
agentKeys
|
|
32
|
+
.command('list <agent>')
|
|
33
|
+
.description('List service keys for an agent (org/name or name)')
|
|
34
|
+
.action(async (ref) => {
|
|
35
|
+
const config = await (0, config_1.getResolvedConfig)();
|
|
36
|
+
if (!config.apiKey) {
|
|
37
|
+
throw new errors_1.CliError('Missing API key. Run `orchagent login` first.');
|
|
38
|
+
}
|
|
39
|
+
const { agent, agentId } = await resolveAgentId(config, ref);
|
|
40
|
+
const result = await (0, api_1.listAgentKeys)(config, agentId);
|
|
41
|
+
if (result.keys.length === 0) {
|
|
42
|
+
process.stdout.write(`No service keys for ${agent.name}.\n`);
|
|
43
|
+
process.stdout.write(`\nCreate one with: orchagent agent-keys create ${ref}\n`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
process.stdout.write(`Service keys for ${agent.name}:\n\n`);
|
|
47
|
+
process.stdout.write(` ${'ID'.padEnd(38)} ${'PREFIX'.padEnd(14)} ${'CREATED'.padEnd(22)} LAST USED\n`);
|
|
48
|
+
process.stdout.write(` ${'─'.repeat(38)} ${'─'.repeat(14)} ${'─'.repeat(22)} ${'─'.repeat(22)}\n`);
|
|
49
|
+
for (const key of result.keys) {
|
|
50
|
+
const created = new Date(key.created_at).toLocaleDateString();
|
|
51
|
+
const lastUsed = key.last_used_at
|
|
52
|
+
? new Date(key.last_used_at).toLocaleDateString()
|
|
53
|
+
: chalk_1.default.gray('never');
|
|
54
|
+
process.stdout.write(` ${key.id.padEnd(38)} ${key.prefix.padEnd(14)} ${created.padEnd(22)} ${lastUsed}\n`);
|
|
55
|
+
}
|
|
56
|
+
process.stdout.write('\n');
|
|
57
|
+
});
|
|
58
|
+
agentKeys
|
|
59
|
+
.command('create <agent>')
|
|
60
|
+
.description('Create a new service key for an agent')
|
|
61
|
+
.action(async (ref) => {
|
|
62
|
+
const config = await (0, config_1.getResolvedConfig)();
|
|
63
|
+
if (!config.apiKey) {
|
|
64
|
+
throw new errors_1.CliError('Missing API key. Run `orchagent login` first.');
|
|
65
|
+
}
|
|
66
|
+
const { agent } = await resolveAgentId(config, ref);
|
|
67
|
+
const result = await (0, api_1.createAgentKey)(config, agent.id);
|
|
68
|
+
process.stdout.write(`\nNew service key for ${agent.name}:\n\n`);
|
|
69
|
+
process.stdout.write(` ${result.key}\n\n`);
|
|
70
|
+
process.stderr.write(chalk_1.default.yellow('Save this key now — it cannot be retrieved again.\n'));
|
|
71
|
+
});
|
|
72
|
+
agentKeys
|
|
73
|
+
.command('delete <agent> <key-id>')
|
|
74
|
+
.description('Delete a service key')
|
|
75
|
+
.action(async (ref, keyId) => {
|
|
76
|
+
const config = await (0, config_1.getResolvedConfig)();
|
|
77
|
+
if (!config.apiKey) {
|
|
78
|
+
throw new errors_1.CliError('Missing API key. Run `orchagent login` first.');
|
|
79
|
+
}
|
|
80
|
+
const { agent, agentId } = await resolveAgentId(config, ref);
|
|
81
|
+
await (0, api_1.deleteAgentKey)(config, agentId, keyId);
|
|
82
|
+
process.stdout.write(`Deleted key ${keyId} from ${agent.name}.\n`);
|
|
83
|
+
});
|
|
84
|
+
}
|
package/dist/commands/index.js
CHANGED
|
@@ -27,6 +27,7 @@ const list_1 = require("./list");
|
|
|
27
27
|
const test_1 = require("./test");
|
|
28
28
|
const security_1 = require("./security");
|
|
29
29
|
const billing_1 = require("./billing");
|
|
30
|
+
const agent_keys_1 = require("./agent-keys");
|
|
30
31
|
function registerCommands(program) {
|
|
31
32
|
(0, login_1.registerLoginCommand)(program);
|
|
32
33
|
(0, whoami_1.registerWhoamiCommand)(program);
|
|
@@ -54,4 +55,5 @@ function registerCommands(program) {
|
|
|
54
55
|
(0, test_1.registerTestCommand)(program);
|
|
55
56
|
(0, security_1.registerSecurityCommand)(program);
|
|
56
57
|
(0, billing_1.registerBillingCommand)(program);
|
|
58
|
+
(0, agent_keys_1.registerAgentKeysCommand)(program);
|
|
57
59
|
}
|
package/dist/commands/publish.js
CHANGED
|
@@ -14,6 +14,7 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
14
14
|
const config_1 = require("../lib/config");
|
|
15
15
|
const api_1 = require("../lib/api");
|
|
16
16
|
const errors_1 = require("../lib/errors");
|
|
17
|
+
const api_2 = require("../lib/api");
|
|
17
18
|
const analytics_1 = require("../lib/analytics");
|
|
18
19
|
const bundle_1 = require("../lib/bundle");
|
|
19
20
|
/**
|
|
@@ -165,8 +166,6 @@ function registerPublishCommand(program) {
|
|
|
165
166
|
.command('publish')
|
|
166
167
|
.description('Publish agent or skill from local files')
|
|
167
168
|
.option('--url <url>', 'Agent URL (for code-based agents)')
|
|
168
|
-
.option('--public', 'Make agent public')
|
|
169
|
-
.option('--private', 'Make agent private (deprecated: now the default)')
|
|
170
169
|
.option('--profile <name>', 'Use API key from named profile')
|
|
171
170
|
.option('--dry-run', 'Show what would be published without making changes')
|
|
172
171
|
.option('--skills <skills>', 'Default skills (comma-separated, e.g., org/skill@v1,org/other@v1)')
|
|
@@ -174,9 +173,6 @@ function registerPublishCommand(program) {
|
|
|
174
173
|
.option('--docker', 'Include Dockerfile for custom environment (builds E2B template)')
|
|
175
174
|
.option('--local-download', 'Allow users to download and run locally (default: server-only)')
|
|
176
175
|
.action(async (options) => {
|
|
177
|
-
if (options.private) {
|
|
178
|
-
process.stderr.write('Warning: --private is deprecated (private is now the default). You can safely remove it.\n');
|
|
179
|
-
}
|
|
180
176
|
const skillsFromFlag = options.skills
|
|
181
177
|
? options.skills.split(',').map(s => s.trim()).filter(Boolean)
|
|
182
178
|
: undefined;
|
|
@@ -211,7 +207,7 @@ function registerPublishCommand(program) {
|
|
|
211
207
|
process.stderr.write(` Name: ${skillData.frontmatter.name}\n`);
|
|
212
208
|
process.stderr.write(` Type: skill\n`);
|
|
213
209
|
process.stderr.write(` Version: ${versionInfo}\n`);
|
|
214
|
-
process.stderr.write(` Visibility:
|
|
210
|
+
process.stderr.write(` Visibility: private\n`);
|
|
215
211
|
process.stderr.write(` Providers: any\n`);
|
|
216
212
|
if (hasMultipleFiles) {
|
|
217
213
|
process.stderr.write(` Files: ${skillFiles.length} files\n`);
|
|
@@ -233,7 +229,7 @@ function registerPublishCommand(program) {
|
|
|
233
229
|
type: 'skill',
|
|
234
230
|
description: skillData.frontmatter.description,
|
|
235
231
|
prompt: skillData.body,
|
|
236
|
-
is_public:
|
|
232
|
+
is_public: false,
|
|
237
233
|
supported_providers: ['any'],
|
|
238
234
|
default_skills: skillsFromFlag,
|
|
239
235
|
skills_locked: options.skillsLocked || undefined,
|
|
@@ -248,7 +244,7 @@ function registerPublishCommand(program) {
|
|
|
248
244
|
if (hasMultipleFiles) {
|
|
249
245
|
process.stdout.write(`Files: ${skillFiles.length} files included\n`);
|
|
250
246
|
}
|
|
251
|
-
process.stdout.write(`
|
|
247
|
+
process.stdout.write(`Visibility: private\n`);
|
|
252
248
|
process.stdout.write(`\nView analytics and usage: https://orchagent.io/dashboard\n`);
|
|
253
249
|
}
|
|
254
250
|
catch (err) {
|
|
@@ -513,7 +509,7 @@ function registerPublishCommand(program) {
|
|
|
513
509
|
process.stderr.write(` Name: ${manifest.name}\n`);
|
|
514
510
|
process.stderr.write(` Type: ${manifest.type}${shouldUploadBundle ? ' (hosted)' : ''}\n`);
|
|
515
511
|
process.stderr.write(` Version: ${versionInfo}\n`);
|
|
516
|
-
process.stderr.write(` Visibility:
|
|
512
|
+
process.stderr.write(` Visibility: private\n`);
|
|
517
513
|
process.stderr.write(` Providers: ${supportedProviders.join(', ')}\n`);
|
|
518
514
|
const effectiveSkills = skillsFromFlag || manifest.default_skills;
|
|
519
515
|
const effectiveLocked = manifest.skills_locked || options.skillsLocked;
|
|
@@ -548,7 +544,7 @@ function registerPublishCommand(program) {
|
|
|
548
544
|
input_schema: inputSchema,
|
|
549
545
|
output_schema: outputSchema,
|
|
550
546
|
tags: manifest.tags,
|
|
551
|
-
is_public:
|
|
547
|
+
is_public: false,
|
|
552
548
|
supported_providers: supportedProviders,
|
|
553
549
|
default_models: manifest.default_models,
|
|
554
550
|
// Local run fields for tool agents
|
|
@@ -565,6 +561,34 @@ function registerPublishCommand(program) {
|
|
|
565
561
|
});
|
|
566
562
|
}
|
|
567
563
|
catch (err) {
|
|
564
|
+
// Improve SECURITY_BLOCKED error display
|
|
565
|
+
if (err instanceof api_2.ApiError && err.status === 422) {
|
|
566
|
+
const payload = err.payload;
|
|
567
|
+
const errorCode = payload?.error?.code;
|
|
568
|
+
if (errorCode === 'SECURITY_BLOCKED') {
|
|
569
|
+
const analysis = payload?.security_analysis;
|
|
570
|
+
const blockReason = payload?.error?.message || 'Security pattern detected';
|
|
571
|
+
process.stderr.write(chalk_1.default.red(`\nPublish blocked: ${blockReason}\n\n`));
|
|
572
|
+
// Show matched patterns with file:line
|
|
573
|
+
const matches = (analysis?.matches || []);
|
|
574
|
+
if (matches.length > 0) {
|
|
575
|
+
process.stderr.write(chalk_1.default.yellow('Patterns detected:\n'));
|
|
576
|
+
for (const match of matches.slice(0, 5)) {
|
|
577
|
+
const severity = String(match.severity || '').toUpperCase();
|
|
578
|
+
const file = match.file_path || 'unknown';
|
|
579
|
+
const line = match.line_number || '?';
|
|
580
|
+
const desc = match.description || match.pattern_id || '';
|
|
581
|
+
process.stderr.write(` ${chalk_1.default.red(severity)} ${file}:${line} — ${desc}\n`);
|
|
582
|
+
}
|
|
583
|
+
process.stderr.write('\n');
|
|
584
|
+
}
|
|
585
|
+
process.stderr.write('Skills are scanned for patterns that could instruct AI agents to\n' +
|
|
586
|
+
'perform harmful actions (shell injection, data exfiltration, etc.).\n\n' +
|
|
587
|
+
'Code-execution references (eval, subprocess, importlib) are allowed\n' +
|
|
588
|
+
'since the E2B sandbox is the security boundary for code execution.\n');
|
|
589
|
+
throw new errors_1.CliError('Publish blocked by security scan', errors_1.ExitCodes.PERMISSION_DENIED);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
568
592
|
throw err;
|
|
569
593
|
}
|
|
570
594
|
const assignedVersion = result.agent?.version || 'v1';
|
|
@@ -640,7 +664,20 @@ function registerPublishCommand(program) {
|
|
|
640
664
|
process.stdout.write(`\nPublished agent: ${org.slug}/${manifest.name}@${assignedVersion}\n`);
|
|
641
665
|
process.stdout.write(`Type: ${manifest.type}${shouldUploadBundle ? ' (hosted)' : ''}\n`);
|
|
642
666
|
process.stdout.write(`Providers: ${supportedProviders.join(', ')}\n`);
|
|
643
|
-
process.stdout.write(`
|
|
667
|
+
process.stdout.write(`Visibility: private\n`);
|
|
668
|
+
// Show security review result if available
|
|
669
|
+
const secReview = result.security_review;
|
|
670
|
+
if (secReview?.verdict) {
|
|
671
|
+
if (secReview.verdict === 'passed') {
|
|
672
|
+
process.stdout.write(`Security: ${chalk_1.default.green('passed')}\n`);
|
|
673
|
+
}
|
|
674
|
+
else if (secReview.verdict === 'flagged') {
|
|
675
|
+
process.stdout.write(`Security: ${chalk_1.default.yellow('flagged')} — ${secReview.summary || 'review recommended'}\n`);
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
process.stdout.write(`Security: ${secReview.verdict}\n`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
644
681
|
if (result.service_key) {
|
|
645
682
|
process.stdout.write(`\nService key (save this - shown only once):\n`);
|
|
646
683
|
process.stdout.write(` ${result.service_key}\n`);
|