@amaster.ai/runtime-cli 1.1.14-beta.0 → 1.1.14-beta.2
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/README.md +16 -1
- package/dist/cli.cjs +293 -5
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +293 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +293 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +293 -5
- package/dist/index.js.map +1 -1
- package/dist/skill/SKILL.md +11 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ CLI for Amaster SDK - Multi-app support for OpenClaw. Manage multiple Amaster ap
|
|
|
9
9
|
- **Structured Output**: `json`, `pretty`, `table`, `ndjson`, and `csv`
|
|
10
10
|
- **Entity Management**: CRUD, options lookup, and bulk operations on entities
|
|
11
11
|
- **BPM**: Manage Camunda processes, tasks, and instances
|
|
12
|
-
- **Workflow**:
|
|
12
|
+
- **Workflow**: Discover, inspect, and run workflows
|
|
13
13
|
- **S3 Storage**: Upload files, download objects, and inspect metadata
|
|
14
14
|
- **OpenClaw Integration**: Initialize app-specific skills and MCP servers
|
|
15
15
|
|
|
@@ -86,6 +86,10 @@ amaster logout --app myapp
|
|
|
86
86
|
### 4. Use SDK Features
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
|
+
# Discover runnable workflows and inspect required inputs
|
|
90
|
+
amaster workflow list --app myapp --format pretty
|
|
91
|
+
amaster workflow get <workflow-app-id> --app myapp --format pretty
|
|
92
|
+
|
|
89
93
|
# Run an anonymous workflow when the app exposes it publicly
|
|
90
94
|
amaster workflow run text-sentiment-analysis --app myapp \
|
|
91
95
|
--input '{"input_text":"I love this product. It is fast and easy to use."}'
|
|
@@ -639,6 +643,15 @@ amaster bpm modify-instance proc-123 --app myapp \
|
|
|
639
643
|
### Workflow
|
|
640
644
|
|
|
641
645
|
```bash
|
|
646
|
+
amaster workflow list [options] # List workflow apps and runnable names
|
|
647
|
+
--app <app-code> # App code (uses default if not specified)
|
|
648
|
+
--page <n> # Page number
|
|
649
|
+
--limit <n> # Page size
|
|
650
|
+
--mode <mode> # workflow | chat | completion | agent-chat
|
|
651
|
+
|
|
652
|
+
amaster workflow get <id> [options] # Get workflow details and input variables by workflow app ID
|
|
653
|
+
--app <app-code> # App code (uses default if not specified)
|
|
654
|
+
|
|
642
655
|
amaster workflow run <name> [options] # Run a workflow
|
|
643
656
|
--app <app-code> # App code (uses default if not specified)
|
|
644
657
|
-i, --input <json> # Workflow inputs object as JSON or @file
|
|
@@ -649,6 +662,8 @@ amaster workflow run <name> [options] # Run a workflow
|
|
|
649
662
|
--trace-id <traceId> # Workflow trace ID
|
|
650
663
|
```
|
|
651
664
|
|
|
665
|
+
Use `workflow list` to discover workflow app IDs and `runnable_name`. Use the `id` with `workflow get`, and use the `runnable_name` or the `name` returned by `workflow get` with `workflow run`.
|
|
666
|
+
|
|
652
667
|
### S3 Storage
|
|
653
668
|
|
|
654
669
|
```bash
|
package/dist/cli.cjs
CHANGED
|
@@ -2267,6 +2267,8 @@ async function getUserRoles(client, options) {
|
|
|
2267
2267
|
exitWithCommandError3(spinner, "Failed to fetch user roles", error);
|
|
2268
2268
|
}
|
|
2269
2269
|
}
|
|
2270
|
+
var WORKFLOW_LIST_PATH = "/api/proxy/builtin/platform/workflow/openapi/apps";
|
|
2271
|
+
var WORKFLOW_GET_PATH = (workflowId) => `/api/proxy/builtin/platform/workflow/openapi/apps/${encodeURIComponent(workflowId)}/dsl`;
|
|
2270
2272
|
function resolveInputSource4(input) {
|
|
2271
2273
|
if (!input.startsWith("@")) {
|
|
2272
2274
|
return input;
|
|
@@ -2292,6 +2294,151 @@ function parseJsonInput3(input, label) {
|
|
|
2292
2294
|
function isPlainObject4(value) {
|
|
2293
2295
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2294
2296
|
}
|
|
2297
|
+
function parseWorkflowTracing(value) {
|
|
2298
|
+
if (!value) {
|
|
2299
|
+
return null;
|
|
2300
|
+
}
|
|
2301
|
+
if (isPlainObject4(value)) {
|
|
2302
|
+
return value;
|
|
2303
|
+
}
|
|
2304
|
+
if (typeof value !== "string") {
|
|
2305
|
+
return null;
|
|
2306
|
+
}
|
|
2307
|
+
try {
|
|
2308
|
+
const parsed = JSON.parse(value);
|
|
2309
|
+
return isPlainObject4(parsed) ? parsed : null;
|
|
2310
|
+
} catch {
|
|
2311
|
+
return null;
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
function getRunnableName(summary) {
|
|
2315
|
+
const tracing = parseWorkflowTracing(summary.tracing);
|
|
2316
|
+
const baseName = tracing?.base_name;
|
|
2317
|
+
if (typeof baseName === "string" && baseName.trim()) {
|
|
2318
|
+
return baseName.trim();
|
|
2319
|
+
}
|
|
2320
|
+
return null;
|
|
2321
|
+
}
|
|
2322
|
+
function normalizeWorkflowSummary(summary) {
|
|
2323
|
+
return {
|
|
2324
|
+
...summary,
|
|
2325
|
+
id: typeof summary.id === "string" ? summary.id : "",
|
|
2326
|
+
name: typeof summary.name === "string" ? summary.name : "",
|
|
2327
|
+
runnable_name: getRunnableName(summary),
|
|
2328
|
+
description: typeof summary.description === "string" ? summary.description : null,
|
|
2329
|
+
mode: typeof summary.mode === "string" ? summary.mode : null
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2332
|
+
function extractWorkflowInputVariables(dsl) {
|
|
2333
|
+
if (!isPlainObject4(dsl)) {
|
|
2334
|
+
return [];
|
|
2335
|
+
}
|
|
2336
|
+
const candidateNodeSets = [];
|
|
2337
|
+
if (Array.isArray(dsl.nodes)) {
|
|
2338
|
+
candidateNodeSets.push(dsl.nodes);
|
|
2339
|
+
}
|
|
2340
|
+
if (isPlainObject4(dsl.graph) && Array.isArray(dsl.graph.nodes)) {
|
|
2341
|
+
candidateNodeSets.push(dsl.graph.nodes);
|
|
2342
|
+
}
|
|
2343
|
+
const variables = [];
|
|
2344
|
+
for (const nodeSet of candidateNodeSets) {
|
|
2345
|
+
for (const node of nodeSet) {
|
|
2346
|
+
if (!isPlainObject4(node) || !isPlainObject4(node.data)) {
|
|
2347
|
+
continue;
|
|
2348
|
+
}
|
|
2349
|
+
const nodeData = node.data;
|
|
2350
|
+
if (nodeData.type !== "start" || !Array.isArray(nodeData.variables)) {
|
|
2351
|
+
continue;
|
|
2352
|
+
}
|
|
2353
|
+
for (const variable of nodeData.variables) {
|
|
2354
|
+
if (!isPlainObject4(variable) || typeof variable.variable !== "string") {
|
|
2355
|
+
continue;
|
|
2356
|
+
}
|
|
2357
|
+
variables.push({
|
|
2358
|
+
...variable,
|
|
2359
|
+
variable: variable.variable,
|
|
2360
|
+
label: typeof variable.label === "string" ? variable.label : void 0,
|
|
2361
|
+
required: typeof variable.required === "boolean" ? variable.required : void 0,
|
|
2362
|
+
type: typeof variable.type === "string" ? variable.type : void 0
|
|
2363
|
+
});
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
return variables;
|
|
2368
|
+
}
|
|
2369
|
+
function normalizeWorkflowDefinition(definition) {
|
|
2370
|
+
return {
|
|
2371
|
+
...definition,
|
|
2372
|
+
workflow_id: typeof definition.workflow_id === "string" ? definition.workflow_id : "",
|
|
2373
|
+
app_id: typeof definition.app_id === "string" ? definition.app_id : "",
|
|
2374
|
+
version: typeof definition.version === "string" ? definition.version : void 0,
|
|
2375
|
+
name: typeof definition.name === "string" ? definition.name : "",
|
|
2376
|
+
dsl: isPlainObject4(definition.dsl) ? definition.dsl : void 0,
|
|
2377
|
+
context: typeof definition.context === "string" ? definition.context : void 0,
|
|
2378
|
+
input_variables: extractWorkflowInputVariables(definition.dsl)
|
|
2379
|
+
};
|
|
2380
|
+
}
|
|
2381
|
+
function invalidResponse(status, message) {
|
|
2382
|
+
return {
|
|
2383
|
+
data: null,
|
|
2384
|
+
error: {
|
|
2385
|
+
status,
|
|
2386
|
+
message
|
|
2387
|
+
},
|
|
2388
|
+
status
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2391
|
+
function createWorkflowService(client) {
|
|
2392
|
+
return {
|
|
2393
|
+
async list(params = {}) {
|
|
2394
|
+
const response = await client.http.request({
|
|
2395
|
+
url: WORKFLOW_LIST_PATH,
|
|
2396
|
+
method: "GET",
|
|
2397
|
+
params: {
|
|
2398
|
+
page: params.page ?? 1,
|
|
2399
|
+
limit: params.limit ?? 20,
|
|
2400
|
+
mode: params.mode ?? "workflow"
|
|
2401
|
+
}
|
|
2402
|
+
});
|
|
2403
|
+
if (!response.data || !Array.isArray(response.data.data)) {
|
|
2404
|
+
return invalidResponse(
|
|
2405
|
+
response.status,
|
|
2406
|
+
response.error?.message || "Invalid workflow list response structure"
|
|
2407
|
+
);
|
|
2408
|
+
}
|
|
2409
|
+
return {
|
|
2410
|
+
...response,
|
|
2411
|
+
data: {
|
|
2412
|
+
...response.data,
|
|
2413
|
+
page: typeof response.data.page === "number" ? response.data.page : params.page ?? 1,
|
|
2414
|
+
limit: typeof response.data.limit === "number" ? response.data.limit : params.limit ?? 20,
|
|
2415
|
+
total: typeof response.data.total === "number" ? response.data.total : response.data.data.length,
|
|
2416
|
+
has_more: typeof response.data.has_more === "boolean" ? response.data.has_more : false,
|
|
2417
|
+
data: response.data.data.map(normalizeWorkflowSummary)
|
|
2418
|
+
}
|
|
2419
|
+
};
|
|
2420
|
+
},
|
|
2421
|
+
async get(workflowId) {
|
|
2422
|
+
if (!workflowId) {
|
|
2423
|
+
return invalidResponse(400, "workflowId is required");
|
|
2424
|
+
}
|
|
2425
|
+
const response = await client.http.request({
|
|
2426
|
+
url: WORKFLOW_GET_PATH(workflowId),
|
|
2427
|
+
method: "GET"
|
|
2428
|
+
});
|
|
2429
|
+
if (!response.data || !isPlainObject4(response.data)) {
|
|
2430
|
+
return invalidResponse(
|
|
2431
|
+
response.status,
|
|
2432
|
+
response.error?.message || "Invalid workflow definition response structure"
|
|
2433
|
+
);
|
|
2434
|
+
}
|
|
2435
|
+
return {
|
|
2436
|
+
...response,
|
|
2437
|
+
data: normalizeWorkflowDefinition(response.data)
|
|
2438
|
+
};
|
|
2439
|
+
}
|
|
2440
|
+
};
|
|
2441
|
+
}
|
|
2295
2442
|
function loadOptionalJsonObjectInput3(input, label) {
|
|
2296
2443
|
if (!input) {
|
|
2297
2444
|
return {};
|
|
@@ -2366,6 +2513,128 @@ async function runWorkflow(client, options) {
|
|
|
2366
2513
|
exitWithCommandError4(spinner, "Failed to run workflow", error);
|
|
2367
2514
|
}
|
|
2368
2515
|
}
|
|
2516
|
+
async function listWorkflows(client, options = {}) {
|
|
2517
|
+
const spinner = createSpinner("Fetching workflows...", options.format);
|
|
2518
|
+
try {
|
|
2519
|
+
const workflowService = createWorkflowService(client);
|
|
2520
|
+
const result = await workflowService.list({
|
|
2521
|
+
page: options.page,
|
|
2522
|
+
limit: options.limit,
|
|
2523
|
+
mode: options.mode
|
|
2524
|
+
});
|
|
2525
|
+
if (result.error) {
|
|
2526
|
+
spinner.fail("Failed to fetch workflows");
|
|
2527
|
+
console.error(chalk4__default.default.red(result.error.message));
|
|
2528
|
+
process.exit(1);
|
|
2529
|
+
}
|
|
2530
|
+
const payload = result.data;
|
|
2531
|
+
const workflows = payload?.data || [];
|
|
2532
|
+
spinner.succeed(`Found ${workflows.length} workflow${workflows.length === 1 ? "" : "s"}`);
|
|
2533
|
+
renderOutput(payload, {
|
|
2534
|
+
format: options.format,
|
|
2535
|
+
tableRows: workflows.map((workflow) => ({
|
|
2536
|
+
id: workflow.id,
|
|
2537
|
+
runnableName: workflow.runnable_name,
|
|
2538
|
+
platformName: workflow.name,
|
|
2539
|
+
mode: workflow.mode,
|
|
2540
|
+
description: workflow.description
|
|
2541
|
+
})),
|
|
2542
|
+
csvRows: workflows.map((workflow) => ({
|
|
2543
|
+
id: workflow.id,
|
|
2544
|
+
runnableName: workflow.runnable_name,
|
|
2545
|
+
platformName: workflow.name,
|
|
2546
|
+
mode: workflow.mode,
|
|
2547
|
+
description: workflow.description
|
|
2548
|
+
})),
|
|
2549
|
+
ndjsonItems: workflows,
|
|
2550
|
+
pretty: () => {
|
|
2551
|
+
console.log(chalk4__default.default.blue("\nWorkflows\n"));
|
|
2552
|
+
if (workflows.length === 0) {
|
|
2553
|
+
console.log(chalk4__default.default.gray("No workflows found."));
|
|
2554
|
+
return;
|
|
2555
|
+
}
|
|
2556
|
+
for (const workflow of workflows) {
|
|
2557
|
+
console.log(`${chalk4__default.default.green("\u2022")} ${chalk4__default.default.bold(workflow.runnable_name || workflow.name)}`);
|
|
2558
|
+
console.log(` ${chalk4__default.default.gray("ID:")} ${workflow.id}`);
|
|
2559
|
+
console.log(` ${chalk4__default.default.gray("Platform Name:")} ${workflow.name}`);
|
|
2560
|
+
console.log(` ${chalk4__default.default.gray("Mode:")} ${workflow.mode || "workflow"}`);
|
|
2561
|
+
if (workflow.description) {
|
|
2562
|
+
console.log(` ${chalk4__default.default.gray("Description:")} ${workflow.description}`);
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
});
|
|
2567
|
+
} catch (error) {
|
|
2568
|
+
exitWithCommandError4(spinner, "Failed to fetch workflows", error);
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
async function getWorkflow(client, options) {
|
|
2572
|
+
const spinner = createSpinner(`Fetching workflow: ${options.id}...`, options.format);
|
|
2573
|
+
try {
|
|
2574
|
+
const workflowService = createWorkflowService(client);
|
|
2575
|
+
const result = await workflowService.get(options.id);
|
|
2576
|
+
if (result.error) {
|
|
2577
|
+
spinner.fail("Failed to fetch workflow");
|
|
2578
|
+
console.error(chalk4__default.default.red(result.error.message));
|
|
2579
|
+
process.exit(1);
|
|
2580
|
+
}
|
|
2581
|
+
const workflow = result.data;
|
|
2582
|
+
const inputVariables = workflow?.input_variables || [];
|
|
2583
|
+
spinner.succeed("Workflow loaded");
|
|
2584
|
+
renderOutput(workflow, {
|
|
2585
|
+
format: options.format,
|
|
2586
|
+
tableRows: workflow ? [
|
|
2587
|
+
{
|
|
2588
|
+
appId: workflow.app_id,
|
|
2589
|
+
workflowId: workflow.workflow_id,
|
|
2590
|
+
runnableName: workflow.name,
|
|
2591
|
+
version: workflow.version || null,
|
|
2592
|
+
inputVariables: inputVariables.map((item) => item.variable).join(", ")
|
|
2593
|
+
}
|
|
2594
|
+
] : [],
|
|
2595
|
+
csvRows: workflow ? [
|
|
2596
|
+
{
|
|
2597
|
+
appId: workflow.app_id,
|
|
2598
|
+
workflowId: workflow.workflow_id,
|
|
2599
|
+
runnableName: workflow.name,
|
|
2600
|
+
version: workflow.version || null,
|
|
2601
|
+
inputVariables: inputVariables.map((item) => item.variable).join(", ")
|
|
2602
|
+
}
|
|
2603
|
+
] : [],
|
|
2604
|
+
ndjsonItems: workflow ? [workflow] : [],
|
|
2605
|
+
pretty: () => {
|
|
2606
|
+
if (!workflow) {
|
|
2607
|
+
console.log(chalk4__default.default.gray("No workflow found."));
|
|
2608
|
+
return;
|
|
2609
|
+
}
|
|
2610
|
+
console.log(chalk4__default.default.blue(`
|
|
2611
|
+
Workflow: ${workflow.name}
|
|
2612
|
+
`));
|
|
2613
|
+
console.log(`${chalk4__default.default.gray("App ID:")} ${workflow.app_id}`);
|
|
2614
|
+
console.log(`${chalk4__default.default.gray("Workflow ID:")} ${workflow.workflow_id}`);
|
|
2615
|
+
if (workflow.version) {
|
|
2616
|
+
console.log(`${chalk4__default.default.gray("Version:")} ${workflow.version}`);
|
|
2617
|
+
}
|
|
2618
|
+
console.log(`
|
|
2619
|
+
${chalk4__default.default.gray("Input Variables:")}`);
|
|
2620
|
+
if (inputVariables.length === 0) {
|
|
2621
|
+
console.log(chalk4__default.default.gray(" none"));
|
|
2622
|
+
} else {
|
|
2623
|
+
for (const variable of inputVariables) {
|
|
2624
|
+
const label = variable.label ? ` ${chalk4__default.default.gray(`(${variable.label})`)}` : "";
|
|
2625
|
+
const type = variable.type ? ` ${chalk4__default.default.gray(`[${variable.type}]`)}` : "";
|
|
2626
|
+
const required = variable.required ? chalk4__default.default.yellow(" required") : chalk4__default.default.gray(" optional");
|
|
2627
|
+
console.log(` - ${chalk4__default.default.bold(variable.variable)}${label}${type}${required}`);
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
console.log(`
|
|
2631
|
+
${chalk4__default.default.gray("Run With:")} amaster workflow run ${workflow.name} --app <app-code> --input '{...}'`);
|
|
2632
|
+
}
|
|
2633
|
+
});
|
|
2634
|
+
} catch (error) {
|
|
2635
|
+
exitWithCommandError4(spinner, "Failed to fetch workflow", error);
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2369
2638
|
function exitWithCommandError5(spinner, failureMessage, error) {
|
|
2370
2639
|
spinner.fail(failureMessage);
|
|
2371
2640
|
const details = error instanceof Error ? error.message : String(error);
|
|
@@ -2774,11 +3043,12 @@ function createAmasterClient(appCode) {
|
|
|
2774
3043
|
}
|
|
2775
3044
|
const client$1 = client.createClient({
|
|
2776
3045
|
baseURL: appConfig.baseURL,
|
|
2777
|
-
|
|
2778
|
-
|
|
3046
|
+
headers: {
|
|
3047
|
+
"x-app-code": appCode,
|
|
3048
|
+
...token ? {
|
|
2779
3049
|
Authorization: `Bearer ${token}`
|
|
2780
|
-
}
|
|
2781
|
-
}
|
|
3050
|
+
} : {}
|
|
3051
|
+
},
|
|
2782
3052
|
onUnauthorized: () => {
|
|
2783
3053
|
if (token) {
|
|
2784
3054
|
console.error(chalk4__default.default.red("\n\u274C Session expired. Please login again."));
|
|
@@ -3331,7 +3601,25 @@ bpmCmd.command("start-form-deployed <key>").description("Get deployed start form
|
|
|
3331
3601
|
format: options.format
|
|
3332
3602
|
});
|
|
3333
3603
|
});
|
|
3334
|
-
var workflowCmd = program.command("workflow").description("
|
|
3604
|
+
var workflowCmd = program.command("workflow").description("Inspect and run workflows");
|
|
3605
|
+
workflowCmd.command("list").description("List runnable workflows").option("--app <app-code>", "App code (uses default if not specified)").option("--page <n>", "Page number").option("--limit <n>", "Page size").addOption(
|
|
3606
|
+
new commander.Option("--mode <mode>", "Workflow app mode").choices(["workflow", "chat", "completion", "agent-chat"])
|
|
3607
|
+
).addOption(createFormatOption()).action(async (options) => {
|
|
3608
|
+
const appCode = resolveAppCode(options.app);
|
|
3609
|
+
await listWorkflows(createAmasterClient(appCode), {
|
|
3610
|
+
page: options.page ? parseInt(options.page, 10) : void 0,
|
|
3611
|
+
limit: options.limit ? parseInt(options.limit, 10) : void 0,
|
|
3612
|
+
mode: options.mode,
|
|
3613
|
+
format: options.format
|
|
3614
|
+
});
|
|
3615
|
+
});
|
|
3616
|
+
workflowCmd.command("get <id>").alias("inspect").description("Get workflow details and input variables by workflow app ID").option("--app <app-code>", "App code (uses default if not specified)").addOption(createFormatOption()).action(async (id, options) => {
|
|
3617
|
+
const appCode = resolveAppCode(options.app);
|
|
3618
|
+
await getWorkflow(createAmasterClient(appCode), {
|
|
3619
|
+
id,
|
|
3620
|
+
format: options.format
|
|
3621
|
+
});
|
|
3622
|
+
});
|
|
3335
3623
|
workflowCmd.command("run <name>").alias("execute").description("Run a workflow").option("--app <app-code>", "App code (uses default if not specified)").option("-i, --input <json>", "Workflow inputs object as JSON or @file").option("-r, --request <json>", "Full WorkflowRunRequest as JSON or @file").addOption(
|
|
3336
3624
|
new commander.Option("--response-mode <mode>", "Workflow response mode").choices(["blocking", "streaming"])
|
|
3337
3625
|
).option("--user <user>", "Workflow user identifier").option("--files <json>", "Workflow files array as JSON or @file").option("--trace-id <traceId>", "Workflow trace ID").addOption(createFormatOption()).action(async (name, options) => {
|