@orchagent/cli 0.3.72 → 0.3.74
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/init.js +59 -1
- package/dist/commands/publish.js +20 -15
- package/dist/commands/run.js +5 -3
- package/dist/commands/schedule.js +19 -2
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -361,6 +361,64 @@ Edit \`main.py\` to customize:
|
|
|
361
361
|
|
|
362
362
|
## Environment Variables
|
|
363
363
|
|
|
364
|
+
| Variable | Required | Description |
|
|
365
|
+
|----------|----------|-------------|
|
|
366
|
+
| \`DISCORD_BOT_TOKEN\` | Yes | Discord bot token (workspace secret) |
|
|
367
|
+
| \`ANTHROPIC_API_KEY\` | Auto | Injected by orchagent via \`supported_providers\` |
|
|
368
|
+
| \`DISCORD_CHANNEL_IDS\` | Yes | Comma-separated channel IDs (workspace secret) |
|
|
369
|
+
| \`MODEL\` | No | Claude model (default: claude-sonnet-4-5-20250929) |
|
|
370
|
+
| \`MAX_TOKENS\` | No | Max response tokens (default: 1024) |
|
|
371
|
+
`;
|
|
372
|
+
}
|
|
373
|
+
if (flavor === 'discord_js') {
|
|
374
|
+
return `# ${agentName}
|
|
375
|
+
|
|
376
|
+
An always-on Discord bot powered by Claude (JavaScript).
|
|
377
|
+
|
|
378
|
+
## Setup
|
|
379
|
+
|
|
380
|
+
### 1. Create a Discord bot
|
|
381
|
+
|
|
382
|
+
1. Go to the [Discord Developer Portal](https://discord.com/developers/applications)
|
|
383
|
+
2. Create a new application, then go to **Bot** and copy the bot token
|
|
384
|
+
3. Under **Privileged Gateway Intents**, enable **Message Content Intent**
|
|
385
|
+
4. Go to **OAuth2 > URL Generator**, select \`bot\` scope, then invite to your server
|
|
386
|
+
|
|
387
|
+
### 2. Get channel IDs
|
|
388
|
+
|
|
389
|
+
Enable Developer Mode in Discord (Settings > Advanced), then right-click a channel and copy its ID.
|
|
390
|
+
|
|
391
|
+
### 3. Local development
|
|
392
|
+
|
|
393
|
+
\`\`\`sh
|
|
394
|
+
cp .env.example .env
|
|
395
|
+
# Fill in DISCORD_BOT_TOKEN, ANTHROPIC_API_KEY, DISCORD_CHANNEL_IDS
|
|
396
|
+
|
|
397
|
+
npm install
|
|
398
|
+
node main.js
|
|
399
|
+
\`\`\`
|
|
400
|
+
|
|
401
|
+
### 4. Deploy
|
|
402
|
+
|
|
403
|
+
\`\`\`sh
|
|
404
|
+
orch publish
|
|
405
|
+
|
|
406
|
+
# Add secrets in your workspace (web dashboard > Settings > Secrets):
|
|
407
|
+
# DISCORD_BOT_TOKEN — your bot token
|
|
408
|
+
# DISCORD_CHANNEL_IDS — comma-separated channel IDs
|
|
409
|
+
|
|
410
|
+
orch service deploy
|
|
411
|
+
\`\`\`
|
|
412
|
+
|
|
413
|
+
## Customization
|
|
414
|
+
|
|
415
|
+
Edit \`main.js\` to customize:
|
|
416
|
+
|
|
417
|
+
- **SYSTEM_PROMPT** — controls how the bot responds
|
|
418
|
+
- **MODEL** / **MAX_TOKENS** — override via env vars
|
|
419
|
+
|
|
420
|
+
## Environment Variables
|
|
421
|
+
|
|
364
422
|
| Variable | Required | Description |
|
|
365
423
|
|----------|----------|-------------|
|
|
366
424
|
| \`DISCORD_BOT_TOKEN\` | Yes | Discord bot token (workspace secret) |
|
|
@@ -1018,7 +1076,7 @@ function registerInitCommand(program) {
|
|
|
1018
1076
|
await promises_1.default.writeFile(path_1.default.join(targetDir, 'main.js'), DISCORD_MAIN_JS);
|
|
1019
1077
|
await promises_1.default.writeFile(path_1.default.join(targetDir, 'package.json'), DISCORD_PACKAGE_JSON);
|
|
1020
1078
|
await promises_1.default.writeFile(path_1.default.join(targetDir, '.env.example'), DISCORD_JS_ENV_EXAMPLE);
|
|
1021
|
-
await promises_1.default.writeFile(path_1.default.join(targetDir, 'README.md'), readmeTemplate(agentName, '
|
|
1079
|
+
await promises_1.default.writeFile(path_1.default.join(targetDir, 'README.md'), readmeTemplate(agentName, 'discord_js'));
|
|
1022
1080
|
const prefix = name ? name + '/' : '';
|
|
1023
1081
|
process.stdout.write(`\nInitialized JS Discord bot "${agentName}" in ${targetDir}\n`);
|
|
1024
1082
|
process.stdout.write(`\nFiles created:\n`);
|
package/dist/commands/publish.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.extractTemplateVariables = extractTemplateVariables;
|
|
7
7
|
exports.deriveInputSchema = deriveInputSchema;
|
|
8
8
|
exports.scanUndeclaredEnvVars = scanUndeclaredEnvVars;
|
|
9
|
+
exports.detectSdkCompatible = detectSdkCompatible;
|
|
9
10
|
exports.checkDependencies = checkDependencies;
|
|
10
11
|
exports.registerPublishCommand = registerPublishCommand;
|
|
11
12
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
@@ -914,26 +915,30 @@ function registerPublishCommand(program) {
|
|
|
914
915
|
catch {
|
|
915
916
|
// Optional
|
|
916
917
|
}
|
|
917
|
-
// Include package.json + lockfile for JS agents (overrides DEFAULT_EXCLUDES)
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
process.stdout.write(` Including package.json for sandbox dependencies\n`);
|
|
923
|
-
// Include lockfile for deterministic installs (npm ci)
|
|
924
|
-
const lockPath = path_1.default.join(cwd, 'package-lock.json');
|
|
918
|
+
// Include package.json + lockfile for JS agents only (overrides DEFAULT_EXCLUDES)
|
|
919
|
+
// Guard on JS entrypoint to avoid bundling package.json for Python agents
|
|
920
|
+
// in mixed repos — the sandbox Python template lacks npm and would fail
|
|
921
|
+
if (bundleEntrypoint && bundleEntrypoint.endsWith('.js')) {
|
|
922
|
+
const pkgPath = path_1.default.join(cwd, 'package.json');
|
|
925
923
|
try {
|
|
926
|
-
await promises_1.default.access(
|
|
927
|
-
includePatterns.push('package
|
|
928
|
-
process.stdout.write(` Including package
|
|
924
|
+
await promises_1.default.access(pkgPath);
|
|
925
|
+
includePatterns.push('package.json');
|
|
926
|
+
process.stdout.write(` Including package.json for sandbox dependencies\n`);
|
|
927
|
+
// Include lockfile for deterministic installs (npm ci)
|
|
928
|
+
const lockPath = path_1.default.join(cwd, 'package-lock.json');
|
|
929
|
+
try {
|
|
930
|
+
await promises_1.default.access(lockPath);
|
|
931
|
+
includePatterns.push('package-lock.json');
|
|
932
|
+
process.stdout.write(` Including package-lock.json for deterministic installs\n`);
|
|
933
|
+
}
|
|
934
|
+
catch {
|
|
935
|
+
// No lockfile — npm install will be used instead of npm ci
|
|
936
|
+
}
|
|
929
937
|
}
|
|
930
938
|
catch {
|
|
931
|
-
// No
|
|
939
|
+
// No package.json
|
|
932
940
|
}
|
|
933
941
|
}
|
|
934
|
-
catch {
|
|
935
|
-
// No package.json — not a JS agent
|
|
936
|
-
}
|
|
937
942
|
}
|
|
938
943
|
const bundleResult = await (0, bundle_1.createCodeBundle)(cwd, bundlePath, {
|
|
939
944
|
entrypoint: bundleEntrypoint,
|
package/dist/commands/run.js
CHANGED
|
@@ -36,6 +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.localCommandForEntrypoint = localCommandForEntrypoint;
|
|
39
40
|
exports.isKeyedFileArg = isKeyedFileArg;
|
|
40
41
|
exports.readKeyedFiles = readKeyedFiles;
|
|
41
42
|
exports.mountDirectory = mountDirectory;
|
|
@@ -926,11 +927,12 @@ async function loadSkillPrompts(config, skillRefs, defaultOrg) {
|
|
|
926
927
|
}
|
|
927
928
|
return prompts;
|
|
928
929
|
}
|
|
929
|
-
function runCommand(command, args) {
|
|
930
|
+
function runCommand(command, args, options) {
|
|
930
931
|
return new Promise((resolve) => {
|
|
931
932
|
const proc = (0, child_process_1.spawn)(command, args, {
|
|
932
933
|
stdio: ['inherit', 'pipe', 'pipe'],
|
|
933
934
|
shell: true,
|
|
935
|
+
cwd: options?.cwd,
|
|
934
936
|
});
|
|
935
937
|
let stdout = '';
|
|
936
938
|
let stderr = '';
|
|
@@ -1068,7 +1070,7 @@ async function executeBundleAgent(config, org, agentName, version, agentData, ar
|
|
|
1068
1070
|
const npmArgs = useNpmCi
|
|
1069
1071
|
? ['ci', '--no-audit', '--no-fund']
|
|
1070
1072
|
: ['install', '--production', '--no-audit', '--no-fund'];
|
|
1071
|
-
const { code } = await runCommand('npm', npmArgs);
|
|
1073
|
+
const { code } = await runCommand('npm', npmArgs, { cwd: extractDir });
|
|
1072
1074
|
if (code !== 0) {
|
|
1073
1075
|
throw new errors_1.CliError('Failed to install npm dependencies');
|
|
1074
1076
|
}
|
|
@@ -1529,7 +1531,7 @@ async function executeLocalFromDir(dirPath, args, options) {
|
|
|
1529
1531
|
? ['ci', '--no-audit', '--no-fund']
|
|
1530
1532
|
: ['install', '--production', '--no-audit', '--no-fund'];
|
|
1531
1533
|
process.stderr.write('Installing npm dependencies...\n');
|
|
1532
|
-
const { code } = await runCommand('npm', npmArgs);
|
|
1534
|
+
const { code } = await runCommand('npm', npmArgs, { cwd: resolved });
|
|
1533
1535
|
if (code !== 0) {
|
|
1534
1536
|
process.stderr.write('Warning: Failed to install npm dependencies\n');
|
|
1535
1537
|
}
|
|
@@ -43,6 +43,21 @@ function statusColor(status) {
|
|
|
43
43
|
default: return status;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
async function resolveScheduleId(config, partialId, workspaceId) {
|
|
47
|
+
// If it looks like a full UUID already, return as-is
|
|
48
|
+
if (partialId.length >= 32)
|
|
49
|
+
return partialId;
|
|
50
|
+
// Fetch schedules and match by prefix
|
|
51
|
+
const response = await (0, api_1.request)(config, 'GET', `/workspaces/${workspaceId}/schedules?limit=200`);
|
|
52
|
+
const matches = response.schedules.filter((s) => s.id.startsWith(partialId));
|
|
53
|
+
if (matches.length === 0) {
|
|
54
|
+
throw new errors_1.CliError(`No schedule found matching '${partialId}'`);
|
|
55
|
+
}
|
|
56
|
+
if (matches.length > 1) {
|
|
57
|
+
throw new errors_1.CliError(`Ambiguous schedule ID '${partialId}' matches ${matches.length} schedules. Use a longer prefix.`);
|
|
58
|
+
}
|
|
59
|
+
return matches[0].id;
|
|
60
|
+
}
|
|
46
61
|
// ============================================
|
|
47
62
|
// COMMAND REGISTRATION
|
|
48
63
|
// ============================================
|
|
@@ -283,12 +298,13 @@ function registerScheduleCommand(program) {
|
|
|
283
298
|
.description('Manually trigger a schedule execution')
|
|
284
299
|
.option('--input <json>', 'Override input data as JSON')
|
|
285
300
|
.option('--workspace <slug>', 'Workspace slug (default: current workspace)')
|
|
286
|
-
.action(async (
|
|
301
|
+
.action(async (partialScheduleId, options) => {
|
|
287
302
|
const config = await (0, config_1.getResolvedConfig)();
|
|
288
303
|
if (!config.apiKey) {
|
|
289
304
|
throw new errors_1.CliError('Missing API key. Run `orch login` first.');
|
|
290
305
|
}
|
|
291
306
|
const workspaceId = await resolveWorkspaceId(config, options.workspace);
|
|
307
|
+
const scheduleId = await resolveScheduleId(config, partialScheduleId, workspaceId);
|
|
292
308
|
let body;
|
|
293
309
|
if (options.input) {
|
|
294
310
|
try {
|
|
@@ -323,12 +339,13 @@ function registerScheduleCommand(program) {
|
|
|
323
339
|
.description('Show detailed schedule information with recent runs and events')
|
|
324
340
|
.option('--workspace <slug>', 'Workspace slug (default: current workspace)')
|
|
325
341
|
.option('--json', 'Output as JSON')
|
|
326
|
-
.action(async (
|
|
342
|
+
.action(async (partialScheduleId, options) => {
|
|
327
343
|
const config = await (0, config_1.getResolvedConfig)();
|
|
328
344
|
if (!config.apiKey) {
|
|
329
345
|
throw new errors_1.CliError('Missing API key. Run `orch login` first.');
|
|
330
346
|
}
|
|
331
347
|
const workspaceId = await resolveWorkspaceId(config, options.workspace);
|
|
348
|
+
const scheduleId = await resolveScheduleId(config, partialScheduleId, workspaceId);
|
|
332
349
|
const [scheduleRes, runsRes, eventsRes] = await Promise.all([
|
|
333
350
|
(0, api_1.request)(config, 'GET', `/workspaces/${workspaceId}/schedules/${scheduleId}`),
|
|
334
351
|
(0, api_1.request)(config, 'GET', `/workspaces/${workspaceId}/schedules/${scheduleId}/runs?limit=5`),
|
package/package.json
CHANGED