larkcc 0.12.4 → 0.12.5

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/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.12.5] - 2026-05-09
11
+
12
+ ### Changed
13
+
14
+ - Sub-agent card: swap header title/subtitle (description as title, "Sub Agent" as subtitle), add header tags (elapsed time + tokens)
15
+ - Sub-agent card: display tool call sequence with arrow display; terminal state merges consecutive duplicates with counts
16
+ - Replace sub-agent footer column_set with header text_tag_list, removing duplicate info between header and footer
17
+ - Accumulate tool call history from progress events in TaskPanelController
18
+ - Logger timestamp color: `chalk.gray` → `chalk.blue`
19
+
20
+ ### Fixed
21
+
22
+ - Tool result truncation: remove 500-char early truncation in agent.ts (both CardKit and non-CardKit paths), let `buildToolResultPanel` handle it uniformly at 2000 chars
23
+ - Extract `STREAMING_TRUNCATE` (4000) and `TASK_SUMMARY_TRUNCATE` (3000) as shared constants, eliminating duplicated `TRUNCATE_LIMIT` in cardkit.ts and streaming.ts
24
+ - Remove unused `truncate()` helper and `THINKING_OVERFLOW_TRUNCATE` import in cardkit.ts
25
+
10
26
  ## [0.12.4] - 2026-05-09
11
27
 
12
28
  ### Changed
package/dist/index.js CHANGED
@@ -6868,7 +6868,7 @@ var init_logger = __esm({
6868
6868
  "src/logger.ts"() {
6869
6869
  "use strict";
6870
6870
  init_source();
6871
- ts = () => source_default.gray((/* @__PURE__ */ new Date()).toLocaleTimeString());
6871
+ ts = () => source_default.blue((/* @__PURE__ */ new Date()).toLocaleTimeString());
6872
6872
  logger = {
6873
6873
  info: (msg) => console.log(`${ts()} ${source_default.cyan("\u2139")} ${msg}`),
6874
6874
  success: (msg) => console.log(`${ts()} ${source_default.green("\u2705")} ${msg}`),
@@ -135962,13 +135962,15 @@ function buildToolPanels(results) {
135962
135962
  if (results.length === 0) return [];
135963
135963
  return results.map((r2) => buildToolResultPanel(r2));
135964
135964
  }
135965
- var THINKING_OVERFLOW_TRUNCATE, TOOL_RESULT_TRUNCATE, EXT_LANG_MAP;
135965
+ var THINKING_OVERFLOW_TRUNCATE, TOOL_RESULT_TRUNCATE, STREAMING_TRUNCATE, TASK_SUMMARY_TRUNCATE, EXT_LANG_MAP;
135966
135966
  var init_duration = __esm({
135967
135967
  "src/format/duration.ts"() {
135968
135968
  "use strict";
135969
135969
  init_card_optimize();
135970
135970
  THINKING_OVERFLOW_TRUNCATE = 3e3;
135971
135971
  TOOL_RESULT_TRUNCATE = 2e3;
135972
+ STREAMING_TRUNCATE = 4e3;
135973
+ TASK_SUMMARY_TRUNCATE = 3e3;
135972
135974
  EXT_LANG_MAP = {
135973
135975
  ts: "typescript",
135974
135976
  tsx: "typescript",
@@ -137823,56 +137825,57 @@ var init_download = __esm({
137823
137825
  function fmtDur(sec) {
137824
137826
  return sec < 60 ? `${sec.toFixed(0)}s` : `${Math.floor(sec / 60)}m ${Math.round(sec % 60)}s`;
137825
137827
  }
137828
+ function formatToolSequence(toolsUsed, isTerminal) {
137829
+ if (toolsUsed.length === 0) return "";
137830
+ if (!isTerminal) {
137831
+ return toolsUsed.map((t) => TOOL_DISPLAY[t] ?? `\u{1F527} ${t}`).join(" \u2192 ");
137832
+ }
137833
+ const merged = [];
137834
+ let current = toolsUsed[0];
137835
+ let count = 1;
137836
+ for (let i2 = 1; i2 < toolsUsed.length; i2++) {
137837
+ if (toolsUsed[i2] === current) {
137838
+ count++;
137839
+ } else {
137840
+ const label = TOOL_DISPLAY[current] ?? `\u{1F527} ${current}`;
137841
+ merged.push(count > 1 ? `${label} \xD7${count}` : label);
137842
+ current = toolsUsed[i2];
137843
+ count = 1;
137844
+ }
137845
+ }
137846
+ const lastLabel = TOOL_DISPLAY[current] ?? `\u{1F527} ${current}`;
137847
+ merged.push(count > 1 ? `${lastLabel} \xD7${count}` : lastLabel);
137848
+ return merged.join(" \u2192 ");
137849
+ }
137826
137850
  function buildTaskPanelCard(options) {
137827
- const { description, status, summary, lastToolName, elapsedSeconds, tokens, headerIconImgKey } = options;
137851
+ const { description, status, summary, lastToolName, toolsUsed, elapsedSeconds, tokens, headerIconImgKey } = options;
137828
137852
  const st = STATUS_TEMPLATE[status];
137853
+ const isTerminal = status !== "running";
137829
137854
  const elements = [];
137830
137855
  const statusParts = [`**${st.icon} ${st.label}**`];
137831
- if (lastToolName && status === "running") statusParts.push(`Tool: \`${lastToolName}\``);
137856
+ if (lastToolName && status === "running") statusParts.push(`\`${lastToolName}\``);
137832
137857
  elements.push({ tag: "markdown", content: statusParts.join(" \xB7 ") });
137833
- const hasContent = summary && summary !== "Done" && summary !== "Aborted";
137834
- if (hasContent) {
137835
- elements.push({ tag: "markdown", content: summary.length > 3e3 ? summary.slice(0, 3e3) + "..." : summary });
137858
+ if (toolsUsed && toolsUsed.length > 0) {
137859
+ elements.push({ tag: "markdown", content: formatToolSequence(toolsUsed, isTerminal), text_size: "notation" });
137860
+ }
137861
+ if (summary && summary !== "Done" && summary !== "Aborted") {
137862
+ elements.push({ tag: "markdown", content: summary.length > TASK_SUMMARY_TRUNCATE ? summary.slice(0, TASK_SUMMARY_TRUNCATE) + "..." : summary });
137836
137863
  } else if (status === "running") {
137837
137864
  elements.push({ tag: "markdown", content: "Processing..." });
137838
137865
  }
137839
- const footerColumns = [];
137840
- if (elapsedSeconds != null) {
137841
- footerColumns.push({
137842
- tag: "column",
137843
- width: "weighted",
137844
- weight: 1,
137845
- vertical_align: "center",
137846
- elements: [{ tag: "markdown", content: `<font color='grey'>\u23F1 ${fmtDur(elapsedSeconds)}</font>`, text_size: "notation" }]
137847
- });
137848
- }
137849
- if (status !== "running" && tokens != null) {
137850
- footerColumns.push({
137851
- tag: "column",
137852
- width: "weighted",
137853
- weight: 1,
137854
- vertical_align: "center",
137855
- elements: [{ tag: "markdown", content: `<font color='grey'>\u{1FA99} ${tokens.toLocaleString()} tokens</font>`, text_size: "notation" }]
137856
- });
137857
- }
137858
- if (footerColumns.length > 0) {
137859
- elements.push({
137860
- tag: "column_set",
137861
- flex_mode: "none",
137862
- background_style: "default",
137863
- columns: footerColumns
137864
- });
137865
- }
137866
- const icon = headerIconImgKey ? { tag: "custom_icon", img_key: headerIconImgKey } : { tag: "standard_icon", token: "larkcommunity_colorful" };
137866
+ const tags = [];
137867
+ if (elapsedSeconds != null) tags.push({ text: fmtDur(elapsedSeconds), color: "turquoise" });
137868
+ if (isTerminal && tokens != null) tags.push({ text: `${tokens.toLocaleString()} tokens`, color: "blue" });
137867
137869
  return {
137868
137870
  schema: "2.0",
137869
137871
  config: { wide_screen_mode: true },
137870
- header: {
137871
- title: { tag: "plain_text", content: "\u{1F916} Sub Agent" },
137872
- subtitle: { tag: "plain_text", content: description },
137872
+ header: buildHeader({
137873
+ title: description,
137874
+ subtitle: "\u{1F916} Sub Agent",
137873
137875
  template: st.color,
137874
- icon
137875
- },
137876
+ iconImgKey: headerIconImgKey,
137877
+ tags
137878
+ }),
137876
137879
  body: { elements }
137877
137880
  };
137878
137881
  }
@@ -137891,16 +137894,27 @@ async function updateTaskCard(client, msgId, options) {
137891
137894
  data: { content: JSON.stringify(card) }
137892
137895
  });
137893
137896
  }
137894
- var STATUS_TEMPLATE;
137897
+ var STATUS_TEMPLATE, TOOL_DISPLAY;
137895
137898
  var init_task_panel = __esm({
137896
137899
  "src/feishu/task-panel.ts"() {
137897
137900
  "use strict";
137901
+ init_card();
137902
+ init_duration();
137898
137903
  STATUS_TEMPLATE = {
137899
137904
  running: { color: "turquoise", icon: "\u{1F504}", label: "Running" },
137900
137905
  completed: { color: "green", icon: "\u2705", label: "Completed" },
137901
137906
  failed: { color: "red", icon: "\u274C", label: "Failed" },
137902
137907
  stopped: { color: "grey", icon: "\u23F9", label: "Stopped" }
137903
137908
  };
137909
+ TOOL_DISPLAY = {
137910
+ Read: "\u{1F4C2} Read",
137911
+ Write: "\u{1F4DD} Write",
137912
+ Edit: "\u270F\uFE0F Edit",
137913
+ Bash: "\u26A1 Bash",
137914
+ Glob: "\u{1F4C2} Glob",
137915
+ Grep: "\u{1F50D} Grep",
137916
+ LS: "\u{1F4C1} LS"
137917
+ };
137904
137918
  }
137905
137919
  });
137906
137920
 
@@ -137980,7 +137994,7 @@ var VERSION3;
137980
137994
  var init_version = __esm({
137981
137995
  "src/version.ts"() {
137982
137996
  "use strict";
137983
- VERSION3 = "0.12.4";
137997
+ VERSION3 = "0.12.5";
137984
137998
  }
137985
137999
  });
137986
138000
 
@@ -154740,12 +154754,13 @@ var init_streaming = __esm({
154740
154754
  "src/streaming.ts"() {
154741
154755
  "use strict";
154742
154756
  init_card_optimize();
154757
+ init_duration();
154743
154758
  init_thinking();
154744
154759
  init_feishu();
154745
154760
  LONG_GAP_MS = 2e3;
154746
154761
  GAP_CHECK_INTERVAL = 500;
154747
154762
  HEARTBEAT_MS = 15e3;
154748
- TRUNCATE_LIMIT = 4e3;
154763
+ TRUNCATE_LIMIT = STREAMING_TRUNCATE;
154749
154764
  FlushController = class {
154750
154765
  minIntervalMs;
154751
154766
  onFlush;
@@ -155026,7 +155041,7 @@ var init_cardkit = __esm({
155026
155041
  init_feishu();
155027
155042
  init_streaming();
155028
155043
  init_format();
155029
- TRUNCATE_LIMIT2 = 4e3;
155044
+ TRUNCATE_LIMIT2 = STREAMING_TRUNCATE;
155030
155045
  CardKitApiError = class extends Error {
155031
155046
  code;
155032
155047
  constructor(code, msg, context) {
@@ -155529,7 +155544,8 @@ var init_task_panel2 = __esm({
155529
155544
  msgId,
155530
155545
  description: event.description,
155531
155546
  status: "running",
155532
- startTime: Date.now()
155547
+ startTime: Date.now(),
155548
+ toolsUsed: []
155533
155549
  });
155534
155550
  logger.dim(`[task-panel] started: ${event.description.slice(0, 40)}`);
155535
155551
  } catch (err) {
@@ -155541,7 +155557,12 @@ var init_task_panel2 = __esm({
155541
155557
  const task = this.tasks.get(event.task_id);
155542
155558
  if (!task || task.status !== "running") return;
155543
155559
  if (event.summary) task.summary = event.summary;
155544
- if (event.last_tool_name) task.lastToolName = event.last_tool_name;
155560
+ if (event.last_tool_name) {
155561
+ task.lastToolName = event.last_tool_name;
155562
+ if (task.toolsUsed[task.toolsUsed.length - 1] !== event.last_tool_name) {
155563
+ task.toolsUsed.push(event.last_tool_name);
155564
+ }
155565
+ }
155545
155566
  if (event.usage) {
155546
155567
  task.tokens = event.usage.total_tokens;
155547
155568
  }
@@ -155551,6 +155572,7 @@ var init_task_panel2 = __esm({
155551
155572
  status: "running",
155552
155573
  summary: task.summary,
155553
155574
  lastToolName: task.lastToolName,
155575
+ toolsUsed: task.toolsUsed,
155554
155576
  elapsedSeconds: (Date.now() - task.startTime) / 1e3,
155555
155577
  tokens: task.tokens,
155556
155578
  headerIconImgKey: this.headerIconImgKey
@@ -155572,6 +155594,7 @@ var init_task_panel2 = __esm({
155572
155594
  description: task.description,
155573
155595
  status: event.status,
155574
155596
  summary: event.summary,
155597
+ toolsUsed: task.toolsUsed,
155575
155598
  elapsedSeconds,
155576
155599
  tokens: task.tokens,
155577
155600
  headerIconImgKey: this.headerIconImgKey
@@ -155591,6 +155614,7 @@ var init_task_panel2 = __esm({
155591
155614
  description: task.description,
155592
155615
  status: "stopped",
155593
155616
  summary: task.summary ?? "Aborted",
155617
+ toolsUsed: task.toolsUsed,
155594
155618
  elapsedSeconds: (Date.now() - task.startTime) / 1e3,
155595
155619
  tokens: task.tokens
155596
155620
  });
@@ -155609,6 +155633,7 @@ var init_task_panel2 = __esm({
155609
155633
  description: task.description,
155610
155634
  status: "completed",
155611
155635
  summary: task.summary ?? "Done",
155636
+ toolsUsed: task.toolsUsed,
155612
155637
  elapsedSeconds: (Date.now() - task.startTime) / 1e3,
155613
155638
  tokens: task.tokens
155614
155639
  });
@@ -155649,9 +155674,6 @@ function formatInput(name, input) {
155649
155674
  if (name === "Glob") return String(input.pattern ?? "");
155650
155675
  return JSON.stringify(input).slice(0, 100);
155651
155676
  }
155652
- function truncate(str2, len) {
155653
- return str2.length > len ? str2.slice(0, len) + "..." : str2;
155654
- }
155655
155677
  function buildReplyContext(config2, profile2, cwd2, chatId, rootMsgId) {
155656
155678
  return {
155657
155679
  profile: profile2 ?? "default",
@@ -155809,13 +155831,13 @@ async function runAgent(prompt2, cwd2, config2, client, chatId, rootMsgId, image
155809
155831
  await cardkitCtrl?.clearStatus();
155810
155832
  const raw = typeof block.content === "string" ? block.content : JSON.stringify(block.content ?? "");
155811
155833
  const toolEntry = cardkitToolResults.find((t) => t.id === block.tool_use_id);
155812
- if (toolEntry) toolEntry.resultPreview = truncate(raw, 500);
155834
+ if (toolEntry) toolEntry.resultPreview = raw;
155813
155835
  break;
155814
155836
  }
155815
155837
  const toolInfo = toolMsgMap.get(block.tool_use_id);
155816
155838
  if (toolInfo) {
155817
155839
  const raw = typeof block.content === "string" ? block.content : JSON.stringify(block.content ?? "");
155818
- await updateToolCard(client, toolInfo.msgId, toolInfo.label, toolInfo.detail, truncate(raw, 500));
155840
+ await updateToolCard(client, toolInfo.msgId, toolInfo.label, toolInfo.detail, raw.length > TOOL_RESULT_TRUNCATE ? truncateSafely(raw, TOOL_RESULT_TRUNCATE) : raw);
155819
155841
  }
155820
155842
  }
155821
155843
  }
@@ -155945,6 +155967,7 @@ var init_agent = __esm({
155945
155967
  init_guide();
155946
155968
  init_thinking();
155947
155969
  init_duration();
155970
+ init_card_optimize();
155948
155971
  init_image_resolver();
155949
155972
  init_streaming();
155950
155973
  init_cardkit();