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