@ai-setting/roy-agent-cli 1.5.110 → 1.5.112

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/index.js CHANGED
@@ -7426,7 +7426,7 @@ var require_dist = __commonJS((exports) => {
7426
7426
  var require_package = __commonJS((exports, module) => {
7427
7427
  module.exports = {
7428
7428
  name: "@ai-setting/roy-agent-cli",
7429
- version: "1.5.110",
7429
+ version: "1.5.112",
7430
7430
  type: "module",
7431
7431
  description: "CLI for roy-agent - Non-interactive command execution",
7432
7432
  main: "./dist/index.js",
@@ -9269,6 +9269,7 @@ Task #${taskId}`;
9269
9269
  message += `
9270
9270
  结果: ${truncatedResult}`;
9271
9271
  }
9272
+ message += this.appendSubSessionId(payload);
9272
9273
  return message;
9273
9274
  }
9274
9275
  formatTaskFailed(payload) {
@@ -9291,6 +9292,7 @@ Task #${taskId}`;
9291
9292
  message += `
9292
9293
  错误: ${truncatedError}`;
9293
9294
  }
9295
+ message += this.appendSubSessionId(payload);
9294
9296
  return message;
9295
9297
  }
9296
9298
  formatTaskTimeout(payload) {
@@ -9307,6 +9309,7 @@ bgprocess: ${bgProcessId}`;
9307
9309
  message += `
9308
9310
  Task #${taskId}`;
9309
9311
  }
9312
+ message += this.appendSubSessionId(payload);
9310
9313
  return message;
9311
9314
  }
9312
9315
  formatTaskStopped(payload) {
@@ -9323,8 +9326,16 @@ bgprocess: ${bgProcessId}`;
9323
9326
  message += `
9324
9327
  Task #${taskId}`;
9325
9328
  }
9329
+ message += this.appendSubSessionId(payload);
9326
9330
  return message;
9327
9331
  }
9332
+ appendSubSessionId(payload) {
9333
+ if (payload.subSessionId) {
9334
+ return `
9335
+ subSessionId: ${payload.subSessionId}`;
9336
+ }
9337
+ return "";
9338
+ }
9328
9339
  formatGeneric(event) {
9329
9340
  return `${this.prefix} 收到事件: ${event.type}`;
9330
9341
  }
@@ -9353,12 +9364,21 @@ Task #${taskId}`;
9353
9364
  return `${minutes}分${seconds}秒`;
9354
9365
  }
9355
9366
  formatWithEvent(event) {
9367
+ const triggerSessionId = extractTriggerSessionId(event);
9356
9368
  return {
9357
9369
  message: this.format(event),
9358
- envEvent: event
9370
+ envEvent: event,
9371
+ triggerSessionId
9359
9372
  };
9360
9373
  }
9361
9374
  }
9375
+ function extractTriggerSessionId(event) {
9376
+ const triggerSessionId = event?.metadata?.trigger_session_id;
9377
+ if (typeof triggerSessionId === "string" && triggerSessionId.length > 0) {
9378
+ return triggerSessionId;
9379
+ }
9380
+ return;
9381
+ }
9362
9382
 
9363
9383
  // src/commands/shared/event-handler.ts
9364
9384
  import { TracedAs as TracedAs3 } from "@ai-setting/roy-agent-core";
@@ -9482,6 +9502,25 @@ class EventHandler {
9482
9502
  return null;
9483
9503
  if (this.activeEventSessionId)
9484
9504
  return this.activeEventSessionId;
9505
+ const triggerSessionId = this.queue.map((item) => item.triggerSessionId).find((id) => !!id);
9506
+ if (triggerSessionId) {
9507
+ try {
9508
+ const existing = await this.sessionComponent.get(triggerSessionId);
9509
+ if (existing) {
9510
+ if (this.isStopped) {
9511
+ return null;
9512
+ }
9513
+ this.activeEventSessionId = existing.id;
9514
+ return existing.id;
9515
+ }
9516
+ console.warn(`[EventHandler] Parent session ${triggerSessionId} not found, creating new session`);
9517
+ } catch (error) {
9518
+ console.error(`[EventHandler] Failed to lookup parent session ${triggerSessionId}:`, error);
9519
+ }
9520
+ }
9521
+ return this.createNewEventSession();
9522
+ }
9523
+ async createNewEventSession() {
9485
9524
  try {
9486
9525
  const session = await this.sessionComponent.create({
9487
9526
  title: `Event Session - ${new Date().toLocaleString()}`
@@ -10781,11 +10820,169 @@ var InteractiveCommand = createInteractiveCommand();
10781
10820
 
10782
10821
  // src/commands/sessions/list.ts
10783
10822
  import chalk6 from "chalk";
10823
+
10824
+ // src/commands/sessions/session-graph.ts
10825
+ function buildSessionTree(sessions) {
10826
+ const byId = new Map;
10827
+ const childrenByParent = new Map;
10828
+ for (const s of sessions) {
10829
+ byId.set(s.id, s);
10830
+ const pid = s.parentSessionId;
10831
+ if (pid !== null && pid !== undefined && pid !== "") {
10832
+ const bucket = childrenByParent.get(pid);
10833
+ if (bucket)
10834
+ bucket.push(s);
10835
+ else
10836
+ childrenByParent.set(pid, [s]);
10837
+ }
10838
+ }
10839
+ const cycleMembers = new Set;
10840
+ const consumed = new Set;
10841
+ function build(session, ancestorStack) {
10842
+ const node = { session, children: [] };
10843
+ const candidates = childrenByParent.get(session.id) ?? [];
10844
+ for (const candidate of candidates) {
10845
+ if (ancestorStack.has(candidate.id)) {
10846
+ cycleMembers.add(candidate.id);
10847
+ cycleMembers.add(session.id);
10848
+ continue;
10849
+ }
10850
+ if (consumed.has(candidate.id)) {
10851
+ continue;
10852
+ }
10853
+ consumed.add(candidate.id);
10854
+ const nextStack = new Set(ancestorStack);
10855
+ nextStack.add(session.id);
10856
+ const child = build(candidate, nextStack);
10857
+ node.children.push(child);
10858
+ }
10859
+ return node;
10860
+ }
10861
+ const roots = [];
10862
+ const orphans = [];
10863
+ for (const s of sessions) {
10864
+ const parentId = s.parentSessionId;
10865
+ const hasParentId = parentId !== null && parentId !== undefined && parentId !== "";
10866
+ if (!hasParentId) {
10867
+ if (consumed.has(s.id))
10868
+ continue;
10869
+ consumed.add(s.id);
10870
+ const node = build(s, new Set([s.id]));
10871
+ roots.push(node);
10872
+ } else if (!byId.has(parentId)) {
10873
+ orphans.push(s);
10874
+ }
10875
+ }
10876
+ if (consumed.size + orphans.length < sessions.length) {
10877
+ for (const s of sessions) {
10878
+ if (consumed.has(s.id))
10879
+ continue;
10880
+ if (orphans.includes(s))
10881
+ continue;
10882
+ const visited = new Set;
10883
+ let cur = s;
10884
+ while (cur) {
10885
+ if (visited.has(cur.id)) {
10886
+ for (const v of visited)
10887
+ cycleMembers.add(v);
10888
+ cycleMembers.add(s.id);
10889
+ break;
10890
+ }
10891
+ visited.add(cur.id);
10892
+ const pid = cur.parentSessionId;
10893
+ if (pid === null || pid === undefined || pid === "")
10894
+ break;
10895
+ cur = byId.get(pid);
10896
+ }
10897
+ consumed.add(s.id);
10898
+ const node = build(s, new Set([s.id]));
10899
+ roots.push(node);
10900
+ }
10901
+ }
10902
+ return { roots, orphans, cycles: cycleMembers };
10903
+ }
10904
+ var TREE_BRANCH = "├── ";
10905
+ var TREE_LAST = "└── ";
10906
+ var TREE_VERTICAL = "│ ";
10907
+ var TREE_EMPTY = " ";
10908
+ function renderSessionTree(tree, options = {}) {
10909
+ if (tree.roots.length === 0 && tree.orphans.length === 0) {
10910
+ return "No sessions.";
10911
+ }
10912
+ const lines = ["Session Tree"];
10913
+ for (let i = 0;i < tree.roots.length; i++) {
10914
+ const isLast = i === tree.roots.length - 1 && tree.orphans.length === 0;
10915
+ renderNode(tree.roots[i], "", isLast, lines, tree.cycles, options);
10916
+ }
10917
+ if (tree.orphans.length > 0) {
10918
+ for (let i = 0;i < tree.orphans.length; i++) {
10919
+ const s = tree.orphans[i];
10920
+ const isLast = i === tree.orphans.length - 1;
10921
+ const branch = isLast ? TREE_LAST : TREE_BRANCH;
10922
+ lines.push(`${branch}${formatNodeLabel(s, true, false, options)}`);
10923
+ }
10924
+ }
10925
+ return lines.join(`
10926
+ `);
10927
+ }
10928
+ function renderNode(node, prefix, isLast, lines, cycles, options) {
10929
+ const branch = isLast ? TREE_LAST : TREE_BRANCH;
10930
+ const isCycle = cycles.has(node.session.id);
10931
+ lines.push(`${prefix}${branch}${formatNodeLabel(node.session, false, isCycle, options)}`);
10932
+ const childPrefix = prefix + (isLast ? TREE_EMPTY : TREE_VERTICAL);
10933
+ for (let i = 0;i < node.children.length; i++) {
10934
+ const isChildLast = i === node.children.length - 1;
10935
+ renderNode(node.children[i], childPrefix, isChildLast, lines, cycles, options);
10936
+ }
10937
+ }
10938
+ function formatNodeLabel(session, isOrphan, isCycle = false, options = {}) {
10939
+ const idStr = options.useShortId ? shortSessionId(session.id) : session.id;
10940
+ const sourceLabel = inferSourceLabel(session);
10941
+ const status = inferStatus(session);
10942
+ const created = new Date(session.createdAt).toISOString().slice(0, 16).replace("T", " ");
10943
+ const parts = [idStr, sourceLabel];
10944
+ if (status)
10945
+ parts.push(`(${status})`);
10946
+ parts.push(created);
10947
+ let label = parts.join(" ");
10948
+ if (isOrphan)
10949
+ label = `[orphan] ${label}`;
10950
+ if (isCycle)
10951
+ label = `[cycle] ${label}`;
10952
+ return label;
10953
+ }
10954
+ function shortSessionId(id) {
10955
+ const underscoreIdx = id.indexOf("_");
10956
+ const stripped = underscoreIdx > 0 && underscoreIdx < id.length - 8 ? id.slice(underscoreIdx + 1) : id;
10957
+ return stripped.length > 8 ? stripped.slice(0, 8) : stripped;
10958
+ }
10959
+ function inferSourceLabel(session) {
10960
+ const meta = session.metadata;
10961
+ const type = meta?.type;
10962
+ if (type === "workflow") {
10963
+ const name = meta?.workflowName;
10964
+ return name ? `workflow/${name}` : "workflow";
10965
+ }
10966
+ if (type === "agent")
10967
+ return "agent";
10968
+ if (type === "subagent" || type === "sub-agent")
10969
+ return "[subagent]";
10970
+ return "chat";
10971
+ }
10972
+ function inferStatus(session) {
10973
+ const meta = session.metadata;
10974
+ const status = meta?.status;
10975
+ if (typeof status === "string" && status.length > 0)
10976
+ return status;
10977
+ return null;
10978
+ }
10979
+
10980
+ // src/commands/sessions/list.ts
10784
10981
  var ListCommand = {
10785
10982
  command: "list [options]",
10786
10983
  aliases: ["ls"],
10787
10984
  describe: "列出所有会话",
10788
- builder: (yargs) => yargs.option("limit", { alias: "n", type: "number", default: 20 }).option("offset", { type: "number", default: 0 }).option("sort", { type: "string", default: "updatedAt" }).option("order", { type: "string", default: "desc" }).option("json", { alias: "j", type: "boolean", default: false }).option("quiet", { alias: "q", type: "boolean", hidden: true }).option("id", { alias: "i", type: "boolean", default: false, description: "显示 Session ID" }).option("type", { alias: "t", type: "string", description: "按 session 类型过滤 (如 workflow)" }).option("status", { alias: "s", type: "string", description: "按状态过滤 (如 running, paused)" }),
10985
+ builder: (yargs) => yargs.option("limit", { alias: "n", type: "number", default: 20 }).option("offset", { type: "number", default: 0 }).option("sort", { type: "string", default: "updatedAt" }).option("order", { type: "string", default: "desc" }).option("json", { alias: "j", type: "boolean", default: false }).option("quiet", { alias: "q", type: "boolean", hidden: true }).option("id", { alias: "i", type: "boolean", default: false, description: "显示 Session ID" }).option("type", { alias: "t", type: "string", description: "按 session 类型过滤 (如 workflow)" }).option("status", { alias: "s", type: "string", description: "按状态过滤 (如 running, paused)" }).option("graph", { alias: "g", type: "boolean", default: false, description: "以层次化树形结构展示 session 父子关系" }).option("short-id", { type: "boolean", default: false, description: "[graph] 用 8 字符截断 id 显示(默认显示完整 sessionId)" }),
10789
10986
  async handler(args) {
10790
10987
  const isQuiet = args.quiet === true;
10791
10988
  if (isQuiet) {
@@ -10826,6 +11023,11 @@ var ListCommand = {
10826
11023
  const sessions = await sessionComponent.list(listOptions);
10827
11024
  const totalCount = await sessionComponent.getCount();
10828
11025
  const activeSessionId = sessionComponent.getActiveSessionId();
11026
+ if (args.graph) {
11027
+ const tree = buildSessionTree(sessions);
11028
+ output.log(renderSessionTree(tree, { useShortId: args.shortId === true }));
11029
+ return;
11030
+ }
10829
11031
  if (args.json) {
10830
11032
  output.json({
10831
11033
  total: sessions.length,
@@ -10840,6 +11042,8 @@ var ListCommand = {
10840
11042
  type: workflowMeta?.type || "chat",
10841
11043
  status: workflowMeta?.status,
10842
11044
  workflowName: workflowMeta?.workflowName,
11045
+ parentSessionId: s.parentSessionId ?? null,
11046
+ parentID: s.parentID ?? null,
10843
11047
  hasCheckpoint: !!s.metadata?.checkpoints?.checkpoints?.length,
10844
11048
  lastCheckpointAt: s.metadata?.checkpoints?.latestCheckpointId,
10845
11049
  createdAt: new Date(s.createdAt).toISOString(),
@@ -10857,6 +11061,7 @@ var ListCommand = {
10857
11061
  chalk6.bold("#"),
10858
11062
  chalk6.bold("Title"),
10859
11063
  chalk6.bold("ID"),
11064
+ chalk6.bold("Parent"),
10860
11065
  hasTypeFilter || hasStatusFilter ? chalk6.bold("Status") : null,
10861
11066
  chalk6.bold("Msgs"),
10862
11067
  chalk6.bold("CP")
@@ -10866,8 +11071,9 @@ var ListCommand = {
10866
11071
  const hasCp = (s.metadata?.checkpoints?.checkpoints?.length ?? 0) > 0;
10867
11072
  const title = s.title.length > 20 ? s.title.slice(0, 17) + "..." : s.title;
10868
11073
  const idStr = s.id;
11074
+ const useShortId = args.shortId === true;
11075
+ const parentStr = s.parentSessionId ? chalk6.gray(useShortId ? shortSessionId(s.parentSessionId) : s.parentSessionId) : chalk6.gray("-");
10869
11076
  const workflowMeta = s.metadata?.type === "workflow" ? s.metadata : null;
10870
- const typeStr = workflowMeta?.type || "";
10871
11077
  const statusStr = workflowMeta?.status || "";
10872
11078
  let statusDisplay = "";
10873
11079
  if (hasTypeFilter || hasStatusFilter) {
@@ -10878,7 +11084,8 @@ var ListCommand = {
10878
11084
  const cells = [
10879
11085
  marker + " " + (args.offset + i + 1),
10880
11086
  title,
10881
- chalk6.gray(idStr)
11087
+ chalk6.gray(idStr),
11088
+ parentStr
10882
11089
  ];
10883
11090
  if (hasTypeFilter || hasStatusFilter) {
10884
11091
  cells.push(statusDisplay || chalk6.gray("-"));
@@ -11315,6 +11522,152 @@ var DeleteCommand = {
11315
11522
 
11316
11523
  // src/commands/sessions/messages.ts
11317
11524
  import chalk11 from "chalk";
11525
+
11526
+ // src/commands/sessions/format-message-content.ts
11527
+ var TEXT_MAX_CHARS = 300;
11528
+ var TOOL_ARGS_MAX_CHARS = 200;
11529
+ var TOOL_RESULT_MAX_CHARS = 200;
11530
+ var LEGACY_CONTENT_MAX_CHARS = 200;
11531
+ var REASONING_MAX_LINES = 5;
11532
+ var CHECKPOINT_MAX_LINES = 10;
11533
+ var INPUT_VALUE_MAX_CHARS = 50;
11534
+ var WORKFLOW_RESULT_MAX_CHARS = 200;
11535
+ var WORKFLOW_RESULT_MAX_LINES = 5;
11536
+ var WORKFLOW_END_MAX_CHARS = 300;
11537
+ var WORKFLOW_END_MAX_LINES = 6;
11538
+ var ELLIPSIS = "...";
11539
+ function truncateChars(s, max) {
11540
+ if (s.length > max) {
11541
+ return s.slice(0, max - ELLIPSIS.length) + ELLIPSIS;
11542
+ }
11543
+ return s;
11544
+ }
11545
+ function formatCheckpointContent(content, opts = {}) {
11546
+ const detail = opts.detail ?? false;
11547
+ const lines = content.split(`
11548
+ `);
11549
+ if (detail) {
11550
+ return lines.join(`
11551
+ `);
11552
+ }
11553
+ return lines.slice(0, CHECKPOINT_MAX_LINES).join(`
11554
+ `) + (lines.length > CHECKPOINT_MAX_LINES ? `
11555
+ ` + ELLIPSIS : "");
11556
+ }
11557
+ function formatMessageContent(m, opts = {}) {
11558
+ const detail = opts.detail ?? false;
11559
+ const lines = [];
11560
+ if (m.parts && m.parts.length > 0) {
11561
+ for (const part of m.parts) {
11562
+ if (part.type === "text") {
11563
+ const raw = part.content || "";
11564
+ const text = detail ? raw : truncateChars(raw, TEXT_MAX_CHARS);
11565
+ lines.push(...text.split(`
11566
+ `).map((l) => l || " "));
11567
+ } else if (part.type === "tool-call") {
11568
+ lines.push(`[Tool Call] ${part.toolName}`);
11569
+ const argsStr = typeof part.arguments === "string" ? part.arguments : JSON.stringify(part.arguments ?? null, null, 2);
11570
+ if (argsStr) {
11571
+ const final = detail ? argsStr : truncateChars(argsStr, TOOL_ARGS_MAX_CHARS);
11572
+ lines.push(...final.split(`
11573
+ `));
11574
+ }
11575
+ } else if (part.type === "tool-result") {
11576
+ lines.push(`[Tool Result] ${part.toolName}`);
11577
+ const raw = part.output || "No output";
11578
+ const output = detail ? raw : truncateChars(raw, TOOL_RESULT_MAX_CHARS);
11579
+ lines.push(...output.split(`
11580
+ `));
11581
+ } else if (part.type === "reasoning") {
11582
+ lines.push(`[Reasoning]`);
11583
+ const content = part.content || "";
11584
+ if (detail) {
11585
+ lines.push(...content.split(`
11586
+ `));
11587
+ } else {
11588
+ lines.push(...content.split(`
11589
+ `).slice(0, REASONING_MAX_LINES));
11590
+ }
11591
+ } else if (part.type === "checkpoint") {
11592
+ lines.push(`[Checkpoint]`);
11593
+ } else if (part.type === "workflow-node-call") {
11594
+ lines.push(`[Node Call] ${part.nodeType}: ${part.nodeId}`);
11595
+ if (part.input && Object.keys(part.input).length > 0) {
11596
+ const entries = Object.entries(part.input).slice(0, 3);
11597
+ const inputSummary = entries.map(([k, v]) => {
11598
+ const vStr = JSON.stringify(v);
11599
+ const final = detail ? vStr : vStr.slice(0, INPUT_VALUE_MAX_CHARS);
11600
+ return `${k}: ${final}`;
11601
+ }).join(", ");
11602
+ lines.push(...inputSummary.split(`
11603
+ `).map((l) => ` ${l}`));
11604
+ }
11605
+ if (part.agentSessionId) {
11606
+ lines.push(` agentSessionId: ${part.agentSessionId}`);
11607
+ }
11608
+ } else if (part.type === "workflow-node-interrupt") {
11609
+ lines.push(`[Node Interrupt] ${part.nodeType}: ${part.nodeId}`);
11610
+ lines.push(` Query: ${part.query}`);
11611
+ if (part.options && part.options.length > 0) {
11612
+ lines.push(` Options: ${part.options.join(", ")}`);
11613
+ }
11614
+ if (part.agentSessionId) {
11615
+ lines.push(` agentSessionId: ${part.agentSessionId}`);
11616
+ }
11617
+ } else if (part.type === "workflow-node-result") {
11618
+ const status = part.error ? "❌" : "✅";
11619
+ lines.push(`${status} [Node Result] ${part.nodeType}: ${part.nodeId}`);
11620
+ if (part.output) {
11621
+ let outputStr = typeof part.output === "string" ? part.output : JSON.stringify(part.output);
11622
+ if (!detail) {
11623
+ outputStr = outputStr.slice(0, WORKFLOW_RESULT_MAX_CHARS);
11624
+ }
11625
+ const outputLines = outputStr.split(`
11626
+ `);
11627
+ const slicedLines = detail ? outputLines : outputLines.slice(0, WORKFLOW_RESULT_MAX_LINES);
11628
+ lines.push(...slicedLines.map((l) => ` ${l}`));
11629
+ }
11630
+ if (part.error) {
11631
+ lines.push(` Error: ${part.error}`);
11632
+ }
11633
+ if (part.durationMs !== undefined) {
11634
+ lines.push(` Duration: ${part.durationMs}ms`);
11635
+ }
11636
+ } else if (part.type === "workflow-node-resume") {
11637
+ lines.push(`[Node Resume] Response: ${part.response}`);
11638
+ } else if (part.type === "workflow-node-start") {
11639
+ lines.push(`[Node Start] ${part.nodeId}`);
11640
+ } else if (part.type === "workflow-node-end") {
11641
+ const status = part.error ? "❌" : "✅";
11642
+ lines.push(`${status} [Node End] ${part.nodeId}`);
11643
+ if (part.output) {
11644
+ let outputStr = typeof part.output === "string" ? part.output : JSON.stringify(part.output, null, 2);
11645
+ if (!detail) {
11646
+ outputStr = outputStr.slice(0, WORKFLOW_END_MAX_CHARS);
11647
+ }
11648
+ const outputLines = outputStr.split(`
11649
+ `);
11650
+ const slicedLines = detail ? outputLines : outputLines.slice(0, WORKFLOW_END_MAX_LINES);
11651
+ lines.push(...slicedLines.map((l) => ` ${l}`));
11652
+ }
11653
+ if (part.error) {
11654
+ lines.push(` Error: ${part.error}`);
11655
+ }
11656
+ if (part.durationMs !== undefined) {
11657
+ lines.push(` Duration: ${part.durationMs}ms`);
11658
+ }
11659
+ }
11660
+ }
11661
+ } else if (m.content) {
11662
+ const content = detail ? m.content : truncateChars(m.content, LEGACY_CONTENT_MAX_CHARS);
11663
+ lines.push(...content.split(`
11664
+ `).map((l) => l || " "));
11665
+ }
11666
+ return lines.length > 0 ? lines : ["(empty)"];
11667
+ }
11668
+
11669
+ // src/commands/sessions/messages.ts
11670
+ var MAX_CONTENT_LINES = 20;
11318
11671
  var MessagesCommand = {
11319
11672
  command: "messages <session-id>",
11320
11673
  aliases: ["msgs"],
@@ -11323,7 +11676,11 @@ var MessagesCommand = {
11323
11676
  describe: "会话 ID",
11324
11677
  type: "string",
11325
11678
  demandOption: true
11326
- }).option("limit", { alias: "n", type: "number", demandOption: true, describe: "返回消息数量" }).option("offset", { alias: "o", type: "number", demandOption: true, describe: "起始偏移量" }).option("reverse", { alias: "r", type: "boolean", default: false }).option("json", { alias: "j", type: "boolean", default: false }),
11679
+ }).option("limit", { alias: "n", type: "number", demandOption: true, describe: "返回消息数量" }).option("offset", { alias: "o", type: "number", demandOption: true, describe: "起始偏移量" }).option("reverse", { alias: "r", type: "boolean", default: false }).option("json", { alias: "j", type: "boolean", default: false }).option("detail", {
11680
+ type: "boolean",
11681
+ default: false,
11682
+ describe: "显示完整消息内容(不截断)"
11683
+ }),
11327
11684
  async handler(args) {
11328
11685
  const a = args;
11329
11686
  const output = new OutputService2;
@@ -11374,111 +11731,13 @@ var MessagesCommand = {
11374
11731
  }))
11375
11732
  });
11376
11733
  } else {
11377
- const checkpointStyle = (content) => {
11378
- const lines = content.split(`
11379
- `);
11380
- return lines.slice(0, 10).join(`
11381
- `) + (lines.length > 10 ? `
11382
- ...` : "");
11383
- };
11734
+ const detail = a.detail === true;
11384
11735
  const roleColors = {
11385
11736
  user: chalk11.blue,
11386
11737
  assistant: chalk11.green,
11387
11738
  system: chalk11.gray,
11388
11739
  tool: chalk11.yellow
11389
11740
  };
11390
- const formatMessageContent = (m) => {
11391
- const lines = [];
11392
- if (m.parts && m.parts.length > 0) {
11393
- for (const part of m.parts) {
11394
- if (part.type === "text") {
11395
- const text = part.content?.length > 300 ? part.content.slice(0, 297) + "..." : part.content || "";
11396
- lines.push(...text.split(`
11397
- `).map((l) => l || " "));
11398
- } else if (part.type === "tool-call") {
11399
- lines.push(chalk11.cyan(`[Tool Call] ${part.toolName}`));
11400
- const argsStr = typeof part.arguments === "string" ? part.arguments : JSON.stringify(part.arguments ?? null, null, 2);
11401
- if (argsStr && argsStr.length > 200) {
11402
- lines.push(...argsStr.slice(0, 197).split(`
11403
- `).map((l) => chalk11.gray(l)));
11404
- lines.push(chalk11.gray("..."));
11405
- } else if (argsStr) {
11406
- lines.push(...argsStr.split(`
11407
- `).map((l) => chalk11.gray(l)));
11408
- }
11409
- } else if (part.type === "tool-result") {
11410
- lines.push(chalk11.yellow(`[Tool Result] ${part.toolName}`));
11411
- const output2 = part.output?.length > 200 ? part.output.slice(0, 197) + "..." : part.output || "No output";
11412
- lines.push(...output2.split(`
11413
- `).map((l) => chalk11.gray(l)));
11414
- } else if (part.type === "reasoning") {
11415
- lines.push(chalk11.magenta(`[Reasoning]`));
11416
- lines.push(...(part.content || "").split(`
11417
- `).slice(0, 5).map((l) => chalk11.gray(l)));
11418
- } else if (part.type === "checkpoint") {
11419
- lines.push(chalk11.cyan(`[Checkpoint]`));
11420
- } else if (part.type === "workflow-node-call") {
11421
- lines.push(chalk11.blue(`[Node Call] ${part.nodeType}: ${part.nodeId}`));
11422
- if (part.input && Object.keys(part.input).length > 0) {
11423
- const inputSummary = Object.entries(part.input).slice(0, 3).map(([k, v]) => `${k}: ${JSON.stringify(v).slice(0, 50)}`).join(", ");
11424
- lines.push(...inputSummary.split(`
11425
- `).map((l) => chalk11.gray(` ${l}`)));
11426
- }
11427
- if (part.agentSessionId) {
11428
- lines.push(chalk11.gray(` agentSessionId: ${part.agentSessionId}`));
11429
- }
11430
- } else if (part.type === "workflow-node-interrupt") {
11431
- lines.push(chalk11.yellow(`[Node Interrupt] ${part.nodeType}: ${part.nodeId}`));
11432
- lines.push(chalk11.bold(` Query: ${part.query}`));
11433
- if (part.options && part.options.length > 0) {
11434
- lines.push(chalk11.gray(` Options: ${part.options.join(", ")}`));
11435
- }
11436
- if (part.agentSessionId) {
11437
- lines.push(chalk11.gray(` agentSessionId: ${part.agentSessionId}`));
11438
- }
11439
- } else if (part.type === "workflow-node-result") {
11440
- const status = part.error ? "❌" : "✅";
11441
- lines.push(chalk11.green(`${status} [Node Result] ${part.nodeType}: ${part.nodeId}`));
11442
- if (part.output) {
11443
- const outputStr = typeof part.output === "string" ? part.output : JSON.stringify(part.output).slice(0, 200);
11444
- lines.push(...outputStr.split(`
11445
- `).slice(0, 5).map((l) => chalk11.gray(` ${l}`)));
11446
- }
11447
- if (part.error) {
11448
- lines.push(chalk11.red(` Error: ${part.error}`));
11449
- }
11450
- if (part.durationMs !== undefined) {
11451
- lines.push(chalk11.gray(` Duration: ${part.durationMs}ms`));
11452
- }
11453
- } else if (part.type === "workflow-node-resume") {
11454
- lines.push(chalk11.green(`[Node Resume] Response: ${part.response}`));
11455
- } else if (part.type === "workflow-node-start") {
11456
- lines.push(chalk11.blue(`[Node Start] ${part.nodeId}`));
11457
- } else if (part.type === "workflow-node-end") {
11458
- const status = part.error ? "❌" : "✅";
11459
- lines.push(chalk11.green(`${status} [Node End] ${part.nodeId}`));
11460
- if (part.output) {
11461
- const outputStr = typeof part.output === "string" ? part.output.slice(0, 300) : JSON.stringify(part.output, null, 2).slice(0, 300);
11462
- lines.push(...outputStr.split(`
11463
- `).slice(0, 6).map((l) => chalk11.gray(` ${l}`)));
11464
- if (outputStr.length >= 300)
11465
- lines.push(chalk11.gray(" ..."));
11466
- }
11467
- if (part.error) {
11468
- lines.push(chalk11.red(` Error: ${part.error}`));
11469
- }
11470
- if (part.durationMs !== undefined) {
11471
- lines.push(chalk11.gray(` Duration: ${part.durationMs}ms`));
11472
- }
11473
- }
11474
- }
11475
- } else if (m.content) {
11476
- const content = m.content.length > 200 ? m.content.slice(0, 197) + "..." : m.content;
11477
- lines.push(...content.split(`
11478
- `).map((l) => l || " "));
11479
- }
11480
- return lines.length > 0 ? lines : ["(empty)"];
11481
- };
11482
11741
  output.log(chalk11.bold(`┌─ Messages (${a.sessionId}) ────────────────────────┐`));
11483
11742
  messages.forEach((m, i) => {
11484
11743
  const roleColor = roleColors[m.role] || chalk11.white;
@@ -11489,18 +11748,21 @@ var MessagesCommand = {
11489
11748
  if (m.metadata?.isCheckpoint) {
11490
11749
  output.log(chalk11.cyan("├─ #" + (a.offset + i + 1) + " checkpoint") + " " + chalk11.gray(time));
11491
11750
  output.log("│");
11492
- output.log("│ " + checkpointStyle(m.content).split(`
11751
+ const checkpointContent = formatCheckpointContent(m.content, { detail });
11752
+ output.log("│ " + checkpointContent.split(`
11493
11753
  `).join(`
11494
11754
  │ `));
11495
11755
  output.log("│");
11496
11756
  } else {
11497
11757
  output.log(chalk11.cyan("├─ #" + (a.offset + i + 1) + " ") + roleColor(m.role.padEnd(10)) + " " + chalk11.gray(time));
11498
- const contentLines = formatMessageContent(m);
11499
- for (const line of contentLines.slice(0, 20)) {
11758
+ const rawLines = formatMessageContent(m, { detail });
11759
+ const contentLines = colorizeContentLines(rawLines, m);
11760
+ const finalLines = detail ? contentLines : contentLines.slice(0, MAX_CONTENT_LINES);
11761
+ for (const line of finalLines) {
11500
11762
  output.log("│ " + line);
11501
11763
  }
11502
- if (contentLines.length > 20) {
11503
- output.log("│ " + chalk11.gray("... (truncated)"));
11764
+ if (!detail && contentLines.length > MAX_CONTENT_LINES) {
11765
+ output.log("│ " + chalk11.gray(`... (truncated, total ${contentLines.length} lines)`));
11504
11766
  }
11505
11767
  output.log("│");
11506
11768
  }
@@ -11518,6 +11780,43 @@ var MessagesCommand = {
11518
11780
  }
11519
11781
  }
11520
11782
  };
11783
+ function colorizeContentLines(lines, _m) {
11784
+ return lines.map((line) => {
11785
+ if (line.startsWith("[Tool Call]"))
11786
+ return chalk11.cyan(line);
11787
+ if (line.startsWith("[Tool Result]"))
11788
+ return chalk11.yellow(line);
11789
+ if (line === "[Reasoning]")
11790
+ return chalk11.magenta(line);
11791
+ if (line === "[Checkpoint]")
11792
+ return chalk11.cyan(line);
11793
+ if (line.startsWith("[Node Call]"))
11794
+ return chalk11.blue(line);
11795
+ if (line.startsWith("[Node Interrupt]"))
11796
+ return chalk11.yellow(line);
11797
+ if (line.startsWith("[Node Resume]"))
11798
+ return chalk11.green(line);
11799
+ if (line.startsWith("[Node Start]"))
11800
+ return chalk11.blue(line);
11801
+ if (line.startsWith("✅") || line.startsWith("❌")) {
11802
+ if (line.includes("[Node Result]"))
11803
+ return chalk11.green(line);
11804
+ if (line.includes("[Node End]"))
11805
+ return chalk11.green(line);
11806
+ return line;
11807
+ }
11808
+ if (line.startsWith(" ")) {
11809
+ if (line.startsWith(" Error:"))
11810
+ return chalk11.red(line);
11811
+ if (line.startsWith(" Query:"))
11812
+ return chalk11.bold(line);
11813
+ if (line.startsWith(" Options:") || line.startsWith(" agentSessionId:") || line.startsWith(" Duration:"))
11814
+ return chalk11.gray(line);
11815
+ return chalk11.gray(line);
11816
+ }
11817
+ return line;
11818
+ });
11819
+ }
11521
11820
 
11522
11821
  // src/commands/sessions/compact.ts
11523
11822
  import chalk12 from "chalk";
@@ -19189,6 +19488,7 @@ import fs5 from "fs";
19189
19488
  import path8 from "path";
19190
19489
  import { createRunWorkflowTool } from "@ai-setting/roy-agent-core/env/workflow/tools";
19191
19490
  import { getTracerProvider as getTracerProvider4, propagation, wrapFunction } from "@ai-setting/roy-agent-core";
19491
+ import { isValidSessionId } from "@ai-setting/roy-agent-core/env/session/session-id";
19192
19492
  var runWorkflow = wrapFunction(async function runWorkflowImpl(args) {
19193
19493
  const output = new OutputService2;
19194
19494
  const envService = new EnvironmentService(output);
@@ -19260,6 +19560,14 @@ var runWorkflow = wrapFunction(async function runWorkflowImpl(args) {
19260
19560
  parallelLimit: args.parallelLimit,
19261
19561
  timeout: args.timeout
19262
19562
  };
19563
+ const rawEnvParentId = process.env["ROY_PARENT_SESSION_ID"];
19564
+ if (typeof rawEnvParentId === "string" && rawEnvParentId.length > 0) {
19565
+ if (isValidSessionId(rawEnvParentId)) {
19566
+ runOptions.parentSessionId = rawEnvParentId;
19567
+ } else {
19568
+ output.warn(`Ignoring malformed ROY_PARENT_SESSION_ID env value (must match /^[A-Za-z0-9_-]{8,128}$/)`);
19569
+ }
19570
+ }
19263
19571
  if (args.session) {
19264
19572
  const sessionId = args.session;
19265
19573
  output.log(chalk69.blue(`\uD83D\uDD04 Resuming workflow from session: ${sessionId}`));