@colinlu50/openclaw-lark-stream 260328.1.1 → 260328.1.2-final

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 CHANGED
@@ -3,6 +3,8 @@
3
3
  # OpenClaw 飞书插件 — 流式卡片版
4
4
 
5
5
  ![demo](./demo.gif)
6
+ ![footer](./demo_footer.png)
7
+ <sub>▲ 卡片底栏:完成状态、响应耗时、token 用量、context 使用率,均可独立开关</sub>
6
8
 
7
9
  基于官方 [openclaw-lark](https://github.com/larksuite/openclaw-lark) 插件,支持**实时流式输出**和 **Agent 执行过程可视化**。
8
10
 
@@ -108,7 +110,8 @@ openclaw gateway restart
108
110
  | elapsed | `8.3s` | `耗时 8.3s` |
109
111
  | context | `1% ctx` | `上下文 19k/200k (10%)` |
110
112
  | cache | `94% cache` | `缓存 18k/1k (94%)` |
111
- | tokens / model | 相同 | 相同 |
113
+ | tokens | `↑ 19k 145` | `输入 19k 输出 145` |
114
+ | model | 相同 | 相同 |
112
115
 
113
116
  默认效果:
114
117
 
@@ -128,7 +131,7 @@ openclaw gateway restart
128
131
  效果:
129
132
 
130
133
  ```
131
- 已完成 · 耗时 8.3s · 19k 145 · 缓存 18k/1k (94%) · 上下文 19k/200k (10%) · claude-3-7-sonnet
134
+ 已完成 · 耗时 8.3s · 输入 19k 输出 145 · 缓存 18k/1k (94%) · 上下文 19k/200k (10%) · claude-3-7-sonnet
132
135
  ```
133
136
 
134
137
  示例 — 关闭 token 展示,开启模型名称:
package/dist/index.js CHANGED
@@ -114809,8 +114809,13 @@ function formatFooterRuntimeSegments(params) {
114809
114809
  if (inTokens != null && outTokens != null) {
114810
114810
  const inLabel = compactNumber(inTokens);
114811
114811
  const outLabel = compactNumber(outTokens);
114812
- zhParts.push(`\u2191 ${inLabel} \u2193 ${outLabel}`);
114813
- enParts.push(`\u2191 ${inLabel} \u2193 ${outLabel}`);
114812
+ if (verbose) {
114813
+ zhParts.push(`\u8F93\u5165 ${inLabel} \u8F93\u51FA ${outLabel}`);
114814
+ enParts.push(`In ${inLabel} Out ${outLabel}`);
114815
+ } else {
114816
+ zhParts.push(`\u2191 ${inLabel} \u2193 ${outLabel}`);
114817
+ enParts.push(`\u2191 ${inLabel} \u2193 ${outLabel}`);
114818
+ }
114814
114819
  }
114815
114820
  }
114816
114821
  if (footer?.cache && metrics) {
@@ -115681,31 +115686,38 @@ var init_streaming_card_controller = __esm({
115681
115686
  return footer.tokens || footer.cache || footer.context || footer.model;
115682
115687
  }
115683
115688
  async getFooterSessionMetrics() {
115684
- try {
115685
- const storePath = path3.join(homedir(), ".openclaw", "agents", this.deps.agentId, "sessions", "sessions.json");
115686
- const raw = await readFile(storePath, "utf8");
115687
- const store2 = JSON.parse(raw);
115688
- const key = this.deps.sessionKey.trim().toLowerCase();
115689
- const prefixedKey = `agent:${this.deps.agentId}:${key}`;
115690
- const entry = store2[prefixedKey] ?? store2[key];
115691
- if (!entry || typeof entry !== "object") {
115692
- log17.debug("footer metrics: session entry not found", { prefixedKey, key });
115689
+ const storePath = path3.join(homedir(), ".openclaw", "agents", this.deps.agentId, "sessions", "sessions.json");
115690
+ const key = this.deps.sessionKey.trim().toLowerCase();
115691
+ const prefixedKey = `agent:${this.deps.agentId}:${key}`;
115692
+ const readMetrics = /* @__PURE__ */ __name(async () => {
115693
+ try {
115694
+ const raw = await readFile(storePath, "utf8");
115695
+ const store2 = JSON.parse(raw);
115696
+ const entry = store2[prefixedKey] ?? store2[key];
115697
+ if (!entry || typeof entry !== "object") {
115698
+ log17.debug("footer metrics: session entry not found", { prefixedKey, key });
115699
+ return void 0;
115700
+ }
115701
+ return {
115702
+ inputTokens: typeof entry.inputTokens === "number" ? entry.inputTokens : void 0,
115703
+ outputTokens: typeof entry.outputTokens === "number" ? entry.outputTokens : void 0,
115704
+ cacheRead: typeof entry.cacheRead === "number" ? entry.cacheRead : void 0,
115705
+ cacheWrite: typeof entry.cacheWrite === "number" ? entry.cacheWrite : void 0,
115706
+ totalTokens: typeof entry.totalTokens === "number" ? entry.totalTokens : void 0,
115707
+ totalTokensFresh: typeof entry.totalTokensFresh === "boolean" ? entry.totalTokensFresh : void 0,
115708
+ contextTokens: typeof entry.contextTokens === "number" ? entry.contextTokens : void 0,
115709
+ model: typeof entry.model === "string" ? entry.model : void 0
115710
+ };
115711
+ } catch (err) {
115712
+ log17.warn("footer metrics lookup failed", { error: String(err), sessionKey: this.deps.sessionKey });
115693
115713
  return void 0;
115694
115714
  }
115695
- return {
115696
- inputTokens: typeof entry.inputTokens === "number" ? entry.inputTokens : void 0,
115697
- outputTokens: typeof entry.outputTokens === "number" ? entry.outputTokens : void 0,
115698
- cacheRead: typeof entry.cacheRead === "number" ? entry.cacheRead : void 0,
115699
- cacheWrite: typeof entry.cacheWrite === "number" ? entry.cacheWrite : void 0,
115700
- totalTokens: typeof entry.totalTokens === "number" ? entry.totalTokens : void 0,
115701
- totalTokensFresh: typeof entry.totalTokensFresh === "boolean" ? entry.totalTokensFresh : void 0,
115702
- contextTokens: typeof entry.contextTokens === "number" ? entry.contextTokens : void 0,
115703
- model: typeof entry.model === "string" ? entry.model : void 0
115704
- };
115705
- } catch (err) {
115706
- log17.warn("footer metrics lookup failed", { error: String(err), sessionKey: this.deps.sessionKey });
115707
- return void 0;
115708
- }
115715
+ }, "readMetrics");
115716
+ const first = await readMetrics();
115717
+ if (first?.inputTokens != null) return first;
115718
+ log17.debug("footer metrics: inputTokens missing, retrying after delay", { prefixedKey });
115719
+ await new Promise((resolve4) => setTimeout(resolve4, 800));
115720
+ return readMetrics();
115709
115721
  }
115710
115722
  constructor(deps) {
115711
115723
  this.deps = deps;
@@ -117037,6 +117049,7 @@ async function dispatchPermissionNotification(dc, permissionError, replyToMessag
117037
117049
  } = createFeishuReplyDispatcher({
117038
117050
  cfg: dc.accountScopedCfg,
117039
117051
  agentId: dc.route.agentId,
117052
+ sessionKey: dc.threadSessionKey ?? dc.route.sessionKey,
117040
117053
  chatId: dc.ctx.chatId,
117041
117054
  replyToMessageId: replyToMessageId ?? dc.ctx.messageId,
117042
117055
  accountId: dc.account.accountId,
@@ -119852,6 +119865,7 @@ async function dispatchNormalMessage(dc, ctxPayload, chatHistories, historyKey,
119852
119865
  const { dispatcher, replyOptions, markDispatchIdle, markFullyComplete, abortCard } = createFeishuReplyDispatcher({
119853
119866
  cfg: dc.accountScopedCfg,
119854
119867
  agentId: dc.route.agentId,
119868
+ sessionKey: dc.threadSessionKey ?? dc.route.sessionKey,
119855
119869
  chatId: dc.ctx.chatId,
119856
119870
  replyToMessageId: replyToMessageId ?? dc.ctx.messageId,
119857
119871
  accountId: dc.account.accountId,