@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/dist/cli.js CHANGED
@@ -2258,6 +2258,8 @@ async function getUserRoles(client, options) {
2258
2258
  exitWithCommandError3(spinner, "Failed to fetch user roles", error);
2259
2259
  }
2260
2260
  }
2261
+ var WORKFLOW_LIST_PATH = "/api/proxy/builtin/platform/workflow/openapi/apps";
2262
+ var WORKFLOW_GET_PATH = (workflowId) => `/api/proxy/builtin/platform/workflow/openapi/apps/${encodeURIComponent(workflowId)}/dsl`;
2261
2263
  function resolveInputSource4(input) {
2262
2264
  if (!input.startsWith("@")) {
2263
2265
  return input;
@@ -2283,6 +2285,151 @@ function parseJsonInput3(input, label) {
2283
2285
  function isPlainObject4(value) {
2284
2286
  return typeof value === "object" && value !== null && !Array.isArray(value);
2285
2287
  }
2288
+ function parseWorkflowTracing(value) {
2289
+ if (!value) {
2290
+ return null;
2291
+ }
2292
+ if (isPlainObject4(value)) {
2293
+ return value;
2294
+ }
2295
+ if (typeof value !== "string") {
2296
+ return null;
2297
+ }
2298
+ try {
2299
+ const parsed = JSON.parse(value);
2300
+ return isPlainObject4(parsed) ? parsed : null;
2301
+ } catch {
2302
+ return null;
2303
+ }
2304
+ }
2305
+ function getRunnableName(summary) {
2306
+ const tracing = parseWorkflowTracing(summary.tracing);
2307
+ const baseName = tracing?.base_name;
2308
+ if (typeof baseName === "string" && baseName.trim()) {
2309
+ return baseName.trim();
2310
+ }
2311
+ return null;
2312
+ }
2313
+ function normalizeWorkflowSummary(summary) {
2314
+ return {
2315
+ ...summary,
2316
+ id: typeof summary.id === "string" ? summary.id : "",
2317
+ name: typeof summary.name === "string" ? summary.name : "",
2318
+ runnable_name: getRunnableName(summary),
2319
+ description: typeof summary.description === "string" ? summary.description : null,
2320
+ mode: typeof summary.mode === "string" ? summary.mode : null
2321
+ };
2322
+ }
2323
+ function extractWorkflowInputVariables(dsl) {
2324
+ if (!isPlainObject4(dsl)) {
2325
+ return [];
2326
+ }
2327
+ const candidateNodeSets = [];
2328
+ if (Array.isArray(dsl.nodes)) {
2329
+ candidateNodeSets.push(dsl.nodes);
2330
+ }
2331
+ if (isPlainObject4(dsl.graph) && Array.isArray(dsl.graph.nodes)) {
2332
+ candidateNodeSets.push(dsl.graph.nodes);
2333
+ }
2334
+ const variables = [];
2335
+ for (const nodeSet of candidateNodeSets) {
2336
+ for (const node of nodeSet) {
2337
+ if (!isPlainObject4(node) || !isPlainObject4(node.data)) {
2338
+ continue;
2339
+ }
2340
+ const nodeData = node.data;
2341
+ if (nodeData.type !== "start" || !Array.isArray(nodeData.variables)) {
2342
+ continue;
2343
+ }
2344
+ for (const variable of nodeData.variables) {
2345
+ if (!isPlainObject4(variable) || typeof variable.variable !== "string") {
2346
+ continue;
2347
+ }
2348
+ variables.push({
2349
+ ...variable,
2350
+ variable: variable.variable,
2351
+ label: typeof variable.label === "string" ? variable.label : void 0,
2352
+ required: typeof variable.required === "boolean" ? variable.required : void 0,
2353
+ type: typeof variable.type === "string" ? variable.type : void 0
2354
+ });
2355
+ }
2356
+ }
2357
+ }
2358
+ return variables;
2359
+ }
2360
+ function normalizeWorkflowDefinition(definition) {
2361
+ return {
2362
+ ...definition,
2363
+ workflow_id: typeof definition.workflow_id === "string" ? definition.workflow_id : "",
2364
+ app_id: typeof definition.app_id === "string" ? definition.app_id : "",
2365
+ version: typeof definition.version === "string" ? definition.version : void 0,
2366
+ name: typeof definition.name === "string" ? definition.name : "",
2367
+ dsl: isPlainObject4(definition.dsl) ? definition.dsl : void 0,
2368
+ context: typeof definition.context === "string" ? definition.context : void 0,
2369
+ input_variables: extractWorkflowInputVariables(definition.dsl)
2370
+ };
2371
+ }
2372
+ function invalidResponse(status, message) {
2373
+ return {
2374
+ data: null,
2375
+ error: {
2376
+ status,
2377
+ message
2378
+ },
2379
+ status
2380
+ };
2381
+ }
2382
+ function createWorkflowService(client) {
2383
+ return {
2384
+ async list(params = {}) {
2385
+ const response = await client.http.request({
2386
+ url: WORKFLOW_LIST_PATH,
2387
+ method: "GET",
2388
+ params: {
2389
+ page: params.page ?? 1,
2390
+ limit: params.limit ?? 20,
2391
+ mode: params.mode ?? "workflow"
2392
+ }
2393
+ });
2394
+ if (!response.data || !Array.isArray(response.data.data)) {
2395
+ return invalidResponse(
2396
+ response.status,
2397
+ response.error?.message || "Invalid workflow list response structure"
2398
+ );
2399
+ }
2400
+ return {
2401
+ ...response,
2402
+ data: {
2403
+ ...response.data,
2404
+ page: typeof response.data.page === "number" ? response.data.page : params.page ?? 1,
2405
+ limit: typeof response.data.limit === "number" ? response.data.limit : params.limit ?? 20,
2406
+ total: typeof response.data.total === "number" ? response.data.total : response.data.data.length,
2407
+ has_more: typeof response.data.has_more === "boolean" ? response.data.has_more : false,
2408
+ data: response.data.data.map(normalizeWorkflowSummary)
2409
+ }
2410
+ };
2411
+ },
2412
+ async get(workflowId) {
2413
+ if (!workflowId) {
2414
+ return invalidResponse(400, "workflowId is required");
2415
+ }
2416
+ const response = await client.http.request({
2417
+ url: WORKFLOW_GET_PATH(workflowId),
2418
+ method: "GET"
2419
+ });
2420
+ if (!response.data || !isPlainObject4(response.data)) {
2421
+ return invalidResponse(
2422
+ response.status,
2423
+ response.error?.message || "Invalid workflow definition response structure"
2424
+ );
2425
+ }
2426
+ return {
2427
+ ...response,
2428
+ data: normalizeWorkflowDefinition(response.data)
2429
+ };
2430
+ }
2431
+ };
2432
+ }
2286
2433
  function loadOptionalJsonObjectInput3(input, label) {
2287
2434
  if (!input) {
2288
2435
  return {};
@@ -2357,6 +2504,128 @@ async function runWorkflow(client, options) {
2357
2504
  exitWithCommandError4(spinner, "Failed to run workflow", error);
2358
2505
  }
2359
2506
  }
2507
+ async function listWorkflows(client, options = {}) {
2508
+ const spinner = createSpinner("Fetching workflows...", options.format);
2509
+ try {
2510
+ const workflowService = createWorkflowService(client);
2511
+ const result = await workflowService.list({
2512
+ page: options.page,
2513
+ limit: options.limit,
2514
+ mode: options.mode
2515
+ });
2516
+ if (result.error) {
2517
+ spinner.fail("Failed to fetch workflows");
2518
+ console.error(chalk4.red(result.error.message));
2519
+ process.exit(1);
2520
+ }
2521
+ const payload = result.data;
2522
+ const workflows = payload?.data || [];
2523
+ spinner.succeed(`Found ${workflows.length} workflow${workflows.length === 1 ? "" : "s"}`);
2524
+ renderOutput(payload, {
2525
+ format: options.format,
2526
+ tableRows: workflows.map((workflow) => ({
2527
+ id: workflow.id,
2528
+ runnableName: workflow.runnable_name,
2529
+ platformName: workflow.name,
2530
+ mode: workflow.mode,
2531
+ description: workflow.description
2532
+ })),
2533
+ csvRows: workflows.map((workflow) => ({
2534
+ id: workflow.id,
2535
+ runnableName: workflow.runnable_name,
2536
+ platformName: workflow.name,
2537
+ mode: workflow.mode,
2538
+ description: workflow.description
2539
+ })),
2540
+ ndjsonItems: workflows,
2541
+ pretty: () => {
2542
+ console.log(chalk4.blue("\nWorkflows\n"));
2543
+ if (workflows.length === 0) {
2544
+ console.log(chalk4.gray("No workflows found."));
2545
+ return;
2546
+ }
2547
+ for (const workflow of workflows) {
2548
+ console.log(`${chalk4.green("\u2022")} ${chalk4.bold(workflow.runnable_name || workflow.name)}`);
2549
+ console.log(` ${chalk4.gray("ID:")} ${workflow.id}`);
2550
+ console.log(` ${chalk4.gray("Platform Name:")} ${workflow.name}`);
2551
+ console.log(` ${chalk4.gray("Mode:")} ${workflow.mode || "workflow"}`);
2552
+ if (workflow.description) {
2553
+ console.log(` ${chalk4.gray("Description:")} ${workflow.description}`);
2554
+ }
2555
+ }
2556
+ }
2557
+ });
2558
+ } catch (error) {
2559
+ exitWithCommandError4(spinner, "Failed to fetch workflows", error);
2560
+ }
2561
+ }
2562
+ async function getWorkflow(client, options) {
2563
+ const spinner = createSpinner(`Fetching workflow: ${options.id}...`, options.format);
2564
+ try {
2565
+ const workflowService = createWorkflowService(client);
2566
+ const result = await workflowService.get(options.id);
2567
+ if (result.error) {
2568
+ spinner.fail("Failed to fetch workflow");
2569
+ console.error(chalk4.red(result.error.message));
2570
+ process.exit(1);
2571
+ }
2572
+ const workflow = result.data;
2573
+ const inputVariables = workflow?.input_variables || [];
2574
+ spinner.succeed("Workflow loaded");
2575
+ renderOutput(workflow, {
2576
+ format: options.format,
2577
+ tableRows: workflow ? [
2578
+ {
2579
+ appId: workflow.app_id,
2580
+ workflowId: workflow.workflow_id,
2581
+ runnableName: workflow.name,
2582
+ version: workflow.version || null,
2583
+ inputVariables: inputVariables.map((item) => item.variable).join(", ")
2584
+ }
2585
+ ] : [],
2586
+ csvRows: 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
+ ndjsonItems: workflow ? [workflow] : [],
2596
+ pretty: () => {
2597
+ if (!workflow) {
2598
+ console.log(chalk4.gray("No workflow found."));
2599
+ return;
2600
+ }
2601
+ console.log(chalk4.blue(`
2602
+ Workflow: ${workflow.name}
2603
+ `));
2604
+ console.log(`${chalk4.gray("App ID:")} ${workflow.app_id}`);
2605
+ console.log(`${chalk4.gray("Workflow ID:")} ${workflow.workflow_id}`);
2606
+ if (workflow.version) {
2607
+ console.log(`${chalk4.gray("Version:")} ${workflow.version}`);
2608
+ }
2609
+ console.log(`
2610
+ ${chalk4.gray("Input Variables:")}`);
2611
+ if (inputVariables.length === 0) {
2612
+ console.log(chalk4.gray(" none"));
2613
+ } else {
2614
+ for (const variable of inputVariables) {
2615
+ const label = variable.label ? ` ${chalk4.gray(`(${variable.label})`)}` : "";
2616
+ const type = variable.type ? ` ${chalk4.gray(`[${variable.type}]`)}` : "";
2617
+ const required = variable.required ? chalk4.yellow(" required") : chalk4.gray(" optional");
2618
+ console.log(` - ${chalk4.bold(variable.variable)}${label}${type}${required}`);
2619
+ }
2620
+ }
2621
+ console.log(`
2622
+ ${chalk4.gray("Run With:")} amaster workflow run ${workflow.name} --app <app-code> --input '{...}'`);
2623
+ }
2624
+ });
2625
+ } catch (error) {
2626
+ exitWithCommandError4(spinner, "Failed to fetch workflow", error);
2627
+ }
2628
+ }
2360
2629
  function exitWithCommandError5(spinner, failureMessage, error) {
2361
2630
  spinner.fail(failureMessage);
2362
2631
  const details = error instanceof Error ? error.message : String(error);
@@ -2765,11 +3034,12 @@ function createAmasterClient(appCode) {
2765
3034
  }
2766
3035
  const client = createClient({
2767
3036
  baseURL: appConfig.baseURL,
2768
- ...token ? {
2769
- headers: {
3037
+ headers: {
3038
+ "x-app-code": appCode,
3039
+ ...token ? {
2770
3040
  Authorization: `Bearer ${token}`
2771
- }
2772
- } : {},
3041
+ } : {}
3042
+ },
2773
3043
  onUnauthorized: () => {
2774
3044
  if (token) {
2775
3045
  console.error(chalk4.red("\n\u274C Session expired. Please login again."));
@@ -3322,7 +3592,25 @@ bpmCmd.command("start-form-deployed <key>").description("Get deployed start form
3322
3592
  format: options.format
3323
3593
  });
3324
3594
  });
3325
- var workflowCmd = program.command("workflow").description("Run workflows");
3595
+ var workflowCmd = program.command("workflow").description("Inspect and run workflows");
3596
+ 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(
3597
+ new Option("--mode <mode>", "Workflow app mode").choices(["workflow", "chat", "completion", "agent-chat"])
3598
+ ).addOption(createFormatOption()).action(async (options) => {
3599
+ const appCode = resolveAppCode(options.app);
3600
+ await listWorkflows(createAmasterClient(appCode), {
3601
+ page: options.page ? parseInt(options.page, 10) : void 0,
3602
+ limit: options.limit ? parseInt(options.limit, 10) : void 0,
3603
+ mode: options.mode,
3604
+ format: options.format
3605
+ });
3606
+ });
3607
+ 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) => {
3608
+ const appCode = resolveAppCode(options.app);
3609
+ await getWorkflow(createAmasterClient(appCode), {
3610
+ id,
3611
+ format: options.format
3612
+ });
3613
+ });
3326
3614
  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(
3327
3615
  new Option("--response-mode <mode>", "Workflow response mode").choices(["blocking", "streaming"])
3328
3616
  ).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) => {