@orchagent/cli 0.3.24 → 0.3.26
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/call.js +56 -1
- package/dist/commands/run.js +23 -1
- package/dist/commands/test.js +52 -16
- package/dist/commands/workspace.js +1 -0
- package/package.json +1 -1
package/dist/commands/call.js
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -170,10 +203,32 @@ argument or --file option instead.
|
|
|
170
203
|
throw new errors_1.CliError('Missing API key. Run `orchagent login` first.');
|
|
171
204
|
}
|
|
172
205
|
const parsed = parseAgentRef(agentRef);
|
|
173
|
-
const
|
|
206
|
+
const configFile = await (0, config_1.loadConfig)();
|
|
207
|
+
const org = parsed.org ?? configFile.workspace ?? resolved.defaultOrg;
|
|
174
208
|
if (!org) {
|
|
175
209
|
throw new errors_1.CliError('Missing org. Use org/agent or set default org.');
|
|
176
210
|
}
|
|
211
|
+
// First-use confirmation when workspace is active (and user didn't specify explicit org)
|
|
212
|
+
if (configFile.workspace && !configFile.workspace_confirmed && !parsed.org) {
|
|
213
|
+
// Only prompt in interactive mode (TTY)
|
|
214
|
+
if (process.stdin.isTTY) {
|
|
215
|
+
const readline = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
216
|
+
const rl = readline.createInterface({
|
|
217
|
+
input: process.stdin,
|
|
218
|
+
output: process.stderr,
|
|
219
|
+
});
|
|
220
|
+
const answer = await new Promise((resolve) => {
|
|
221
|
+
rl.question(`Using workspace: ${configFile.workspace}. Continue? [Y/n]: `, resolve);
|
|
222
|
+
});
|
|
223
|
+
rl.close();
|
|
224
|
+
if (answer.toLowerCase() === 'n') {
|
|
225
|
+
throw new errors_1.CliError('Cancelled. Use explicit org/agent or `orch workspace use <slug>`.');
|
|
226
|
+
}
|
|
227
|
+
// Save confirmation so we don't prompt again until workspace changes
|
|
228
|
+
configFile.workspace_confirmed = true;
|
|
229
|
+
await (0, config_1.saveConfig)(configFile);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
177
232
|
const agentMeta = await (0, api_1.getAgentWithFallback)(resolved, org, parsed.agent, parsed.version);
|
|
178
233
|
const endpoint = options.endpoint?.trim() || agentMeta.default_endpoint || 'analyze';
|
|
179
234
|
const headers = {
|
package/dist/commands/run.js
CHANGED
|
@@ -816,10 +816,32 @@ Note: Use 'run' for local execution, 'call' for server-side execution.
|
|
|
816
816
|
}
|
|
817
817
|
const resolved = await (0, config_1.getResolvedConfig)();
|
|
818
818
|
const parsed = parseAgentRef(agentRef);
|
|
819
|
-
const
|
|
819
|
+
const configFile = await (0, config_1.loadConfig)();
|
|
820
|
+
const org = parsed.org ?? configFile.workspace ?? resolved.defaultOrg;
|
|
820
821
|
if (!org) {
|
|
821
822
|
throw new errors_1.CliError('Missing org. Use org/agent format.');
|
|
822
823
|
}
|
|
824
|
+
// First-use confirmation when workspace is active (and user didn't specify explicit org)
|
|
825
|
+
if (configFile.workspace && !configFile.workspace_confirmed && !parsed.org) {
|
|
826
|
+
// Only prompt in interactive mode (TTY)
|
|
827
|
+
if (process.stdin.isTTY) {
|
|
828
|
+
const readline = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
829
|
+
const rl = readline.createInterface({
|
|
830
|
+
input: process.stdin,
|
|
831
|
+
output: process.stderr,
|
|
832
|
+
});
|
|
833
|
+
const answer = await new Promise((resolve) => {
|
|
834
|
+
rl.question(`Using workspace: ${configFile.workspace}. Continue? [Y/n]: `, resolve);
|
|
835
|
+
});
|
|
836
|
+
rl.close();
|
|
837
|
+
if (answer.toLowerCase() === 'n') {
|
|
838
|
+
throw new errors_1.CliError('Cancelled. Use explicit org/agent or `orch workspace use <slug>`.');
|
|
839
|
+
}
|
|
840
|
+
// Save confirmation so we don't prompt again until workspace changes
|
|
841
|
+
configFile.workspace_confirmed = true;
|
|
842
|
+
await (0, config_1.saveConfig)(configFile);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
823
845
|
// Download agent definition with spinner
|
|
824
846
|
const agentData = await (0, spinner_1.withSpinner)(`Downloading ${org}/${parsed.agent}@${parsed.version}...`, async () => {
|
|
825
847
|
try {
|
package/dist/commands/test.js
CHANGED
|
@@ -14,6 +14,27 @@ const chokidar_1 = __importDefault(require("chokidar"));
|
|
|
14
14
|
const errors_1 = require("../lib/errors");
|
|
15
15
|
const config_1 = require("../lib/config");
|
|
16
16
|
const llm_1 = require("../lib/llm");
|
|
17
|
+
/**
|
|
18
|
+
* Validate a fixture and return helpful errors
|
|
19
|
+
*/
|
|
20
|
+
function validateFixture(data, fixturePath) {
|
|
21
|
+
const fileName = path_1.default.basename(fixturePath);
|
|
22
|
+
if (typeof data !== 'object' || data === null) {
|
|
23
|
+
throw new errors_1.CliError(`Invalid fixture ${fileName}: must be a JSON object`);
|
|
24
|
+
}
|
|
25
|
+
const obj = data;
|
|
26
|
+
if (!obj.input || typeof obj.input !== 'object') {
|
|
27
|
+
throw new errors_1.CliError(`Invalid fixture ${fileName}: missing required "input" field.\n` +
|
|
28
|
+
` Expected format: { "input": {...}, "expected_output": {...} }`);
|
|
29
|
+
}
|
|
30
|
+
if (!obj.expected_output && !obj.expected_contains) {
|
|
31
|
+
throw new errors_1.CliError(`Invalid fixture ${fileName}: must have "expected_output" or "expected_contains".\n` +
|
|
32
|
+
` Add one of:\n` +
|
|
33
|
+
` "expected_output": {"key": "exact value to match"}\n` +
|
|
34
|
+
` "expected_contains": ["substring to find"]`);
|
|
35
|
+
}
|
|
36
|
+
return data;
|
|
37
|
+
}
|
|
17
38
|
/**
|
|
18
39
|
* Parse SKILL.md frontmatter
|
|
19
40
|
*/
|
|
@@ -70,8 +91,10 @@ function runCommand(command, args, cwd, verbose) {
|
|
|
70
91
|
* Check if a command exists
|
|
71
92
|
*/
|
|
72
93
|
async function commandExists(command) {
|
|
94
|
+
const isWindows = process.platform === 'win32';
|
|
95
|
+
const checker = isWindows ? 'where' : 'which';
|
|
73
96
|
try {
|
|
74
|
-
const proc = (0, child_process_1.spawn)(
|
|
97
|
+
const proc = (0, child_process_1.spawn)(checker, [command], { shell: true, stdio: 'ignore' });
|
|
75
98
|
return new Promise((resolve) => {
|
|
76
99
|
proc.on('close', (code) => resolve(code === 0));
|
|
77
100
|
proc.on('error', () => resolve(false));
|
|
@@ -204,22 +227,28 @@ async function discoverTests(agentDir) {
|
|
|
204
227
|
*/
|
|
205
228
|
async function runPythonTests(agentDir, verbose) {
|
|
206
229
|
process.stderr.write(chalk_1.default.blue('\nRunning Python tests...\n\n'));
|
|
207
|
-
// Check if pytest is available
|
|
230
|
+
// Check if pytest is available directly
|
|
208
231
|
const hasPytest = await commandExists('pytest');
|
|
209
|
-
let command;
|
|
210
|
-
let args;
|
|
211
232
|
if (hasPytest) {
|
|
212
|
-
|
|
213
|
-
|
|
233
|
+
const args = verbose ? ['-v'] : [];
|
|
234
|
+
const { code } = await runCommand('pytest', args, agentDir, verbose);
|
|
235
|
+
return code;
|
|
214
236
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
237
|
+
// Try Python commands in order of preference
|
|
238
|
+
const pythonCommands = process.platform === 'win32'
|
|
239
|
+
? ['python', 'py', 'python3']
|
|
240
|
+
: ['python3', 'python'];
|
|
241
|
+
for (const pythonCmd of pythonCommands) {
|
|
242
|
+
if (await commandExists(pythonCmd)) {
|
|
243
|
+
const args = ['-m', 'pytest'];
|
|
244
|
+
if (verbose)
|
|
245
|
+
args.push('-v');
|
|
246
|
+
const { code } = await runCommand(pythonCmd, args, agentDir, verbose);
|
|
247
|
+
return code;
|
|
248
|
+
}
|
|
220
249
|
}
|
|
221
|
-
|
|
222
|
-
return
|
|
250
|
+
process.stderr.write(chalk_1.default.red('No Python interpreter found. Install Python and pytest.\n'));
|
|
251
|
+
return 1;
|
|
223
252
|
}
|
|
224
253
|
/**
|
|
225
254
|
* Run JavaScript/TypeScript tests
|
|
@@ -292,8 +321,8 @@ async function runFixtureTests(agentDir, fixtures, verbose, config) {
|
|
|
292
321
|
throw new errors_1.CliError('No LLM key found for fixture tests.\n' +
|
|
293
322
|
'Set an environment variable (e.g., OPENAI_API_KEY) or run `orchagent keys add <provider>`');
|
|
294
323
|
}
|
|
295
|
-
const { provider, key } = detected;
|
|
296
|
-
const model = (0, llm_1.getDefaultModel)(provider);
|
|
324
|
+
const { provider, key, model: serverModel } = detected;
|
|
325
|
+
const model = serverModel ?? (0, llm_1.getDefaultModel)(provider);
|
|
297
326
|
let passed = 0;
|
|
298
327
|
let failed = 0;
|
|
299
328
|
for (const fixturePath of fixtures) {
|
|
@@ -301,7 +330,14 @@ async function runFixtureTests(agentDir, fixtures, verbose, config) {
|
|
|
301
330
|
process.stderr.write(` ${fixtureName}: `);
|
|
302
331
|
try {
|
|
303
332
|
const raw = await promises_1.default.readFile(fixturePath, 'utf-8');
|
|
304
|
-
|
|
333
|
+
let parsed;
|
|
334
|
+
try {
|
|
335
|
+
parsed = JSON.parse(raw);
|
|
336
|
+
}
|
|
337
|
+
catch (e) {
|
|
338
|
+
throw new errors_1.CliError(`Invalid JSON in ${path_1.default.basename(fixturePath)}: ${e.message}`);
|
|
339
|
+
}
|
|
340
|
+
const fixture = validateFixture(parsed, fixturePath);
|
|
305
341
|
// Build and call LLM
|
|
306
342
|
const fullPrompt = (0, llm_1.buildPrompt)(prompt, fixture.input);
|
|
307
343
|
const result = await (0, llm_1.callLlm)(provider, key, model, fullPrompt, outputSchema);
|
|
@@ -85,6 +85,7 @@ async function useWorkspace(slug) {
|
|
|
85
85
|
// Save to config
|
|
86
86
|
const configFile = await (0, config_1.loadConfig)();
|
|
87
87
|
configFile.workspace = slug;
|
|
88
|
+
delete configFile.workspace_confirmed;
|
|
88
89
|
await (0, config_1.saveConfig)(configFile);
|
|
89
90
|
await (0, analytics_1.track)('cli_workspace_use', { slug });
|
|
90
91
|
process.stdout.write(chalk_1.default.green('\u2713') + ` Now using workspace: ${workspace.name} (${workspace.slug})\n`);
|