@colinlu50/openclaw-lark-stream 2026.3.26 → 2026.3.27

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.en.md ADDED
@@ -0,0 +1,56 @@
1
+ English | [中文](./README.md)
2
+
3
+ # OpenClaw Lark/Feishu Plugin — Stream Card Fork
4
+
5
+ Fork of the official [openclaw-larksuite](https://github.com/larksuite/openclaw-larksuite) plugin with **streaming block output** and **tool call indicators**.
6
+
7
+ ## What's Changed
8
+
9
+ The official plugin delivers LLM block results all at once after completion. This fork enables:
10
+
11
+ - **Real-time block streaming** — each block's content is progressively appended to the streaming card as it's generated
12
+ - **Tool call indicators** — when the agent calls a tool, the card shows the current tool at the top in real-time, with a collapsible summary panel on completion
13
+
14
+ ## Installation
15
+
16
+ Requires [OpenClaw](https://openclaw.ai) (>= 2026.2.26) and Node.js (>= v22).
17
+
18
+ ```bash
19
+ openclaw plugins install @colinlu50/openclaw-lark-stream
20
+ ```
21
+
22
+ Then restart the gateway:
23
+
24
+ ```bash
25
+ openclaw gateway restart
26
+ ```
27
+
28
+ > If you had the official plugin installed, uninstall it first:
29
+ > ```bash
30
+ > openclaw plugins uninstall openclaw-lark --force
31
+ > ```
32
+
33
+ ### From source (for development)
34
+
35
+ ```bash
36
+ cd ~/.openclaw/extensions
37
+ git clone git@github.com:ColinLu50/openclaw-lark-stream.git openclaw-lark-stream
38
+ cd openclaw-lark-stream && npm install && npm run build
39
+ openclaw gateway restart
40
+ ```
41
+
42
+ ## Configuration
43
+
44
+ The card footer shows elapsed time and completion status by default. To disable:
45
+
46
+ ```bash
47
+ openclaw config set channels.feishu.footer.elapsed false # hide elapsed time
48
+ openclaw config set channels.feishu.footer.status false # hide completion status
49
+ ```
50
+
51
+ - **elapsed** — displays total response time (e.g. `Elapsed 3.2s`) in the card footer
52
+ - **status** — displays completion state (`Completed` / `Error` / `Stopped`) in the card footer
53
+
54
+ ## License
55
+
56
+ MIT — same as the upstream project.
package/README.md CHANGED
@@ -1,76 +1,4 @@
1
- [English](#english) | [中文](#中文)
2
-
3
- ---
4
-
5
- <a id="english"></a>
6
-
7
- # OpenClaw Lark/Feishu Plugin — Stream Card Fork
8
-
9
- Fork of the official [openclaw-larksuite](https://github.com/larksuite/openclaw-larksuite) plugin with **streaming block output** and **tool call indicators**.
10
-
11
- ## What's Changed
12
-
13
- The official plugin delivers LLM block results all at once after completion. This fork enables:
14
-
15
- - **Real-time block streaming** — each block's content is progressively appended to the streaming card as it's generated
16
- - **Tool call indicators** — when the agent calls a tool, the card shows tool call status in real-time
17
-
18
- ### Modified Files
19
-
20
- - `src/card/reply-dispatcher.ts` — enable block streaming in streaming card mode; wire `onToolStart` callback
21
- - `src/card/streaming-card-controller.ts` — append each delivered block to the card in real-time; add `onToolStart()` to display tool call status
22
- - `src/card/builder.ts` — collapsible panel for tool call summary in completed cards
23
-
24
- ## Installation
25
-
26
- Requires [OpenClaw](https://openclaw.ai) (>= 2026.2.26) and Node.js (>= v22).
27
-
28
- ### Option A: npm install (recommended)
29
-
30
- 1. Install the official plugin first to complete the guided setup (App ID, secret, OAuth, etc.):
31
- ```bash
32
- npx -y @larksuite/openclaw-lark install
33
- ```
34
-
35
- 2. Replace with the stream fork:
36
- ```bash
37
- openclaw plugins install @colinlu50/openclaw-lark-stream
38
- ```
39
-
40
- If you already have the official plugin installed, skip step 1.
41
-
42
- ### Option B: From source (for development)
43
-
44
- ```bash
45
- cd ~/.openclaw/extensions
46
- rm -rf openclaw-lark
47
- git clone git@github.com:ColinLu50/openclaw-lark-stream.git openclaw-lark
48
- cd openclaw-lark && npm install
49
- ```
50
-
51
- Restart OpenClaw.
52
-
53
- ## Configuration
54
-
55
- Enable optional card footer metadata:
56
-
57
- ```bash
58
- openclaw config set channels.feishu.footer.elapsed true # show elapsed time
59
- openclaw config set channels.feishu.footer.status true # show completion status
60
- ```
61
-
62
- - **elapsed** — displays total response time (e.g. `Elapsed 3.2s`) in the card footer
63
- - **status** — displays completion state (`Completed` / `Error` / `Stopped`) in the card footer
64
-
65
- Both default to `false` (hidden).
66
-
67
- ## License
68
-
69
- MIT — same as the upstream project.
70
-
71
- ---
72
-
73
- <a id="中文"></a>
1
+ [English](./README.en.md) | 中文
74
2
 
75
3
  # OpenClaw 飞书插件 — 流式卡片 Fork
76
4
 
@@ -80,57 +8,48 @@ MIT — same as the upstream project.
80
8
 
81
9
  官方插件在 LLM 生成完一个 block 后才一次性推送结果。本 Fork 实现了:
82
10
 
83
- - **实时流式追加** — 每个 block 的内容在生成过程中逐步追加到流式卡片,让用户获得即时的视觉反馈
84
- - **工具调用状态** — agent 调用工具时,卡片实时显示工具调用状态
85
-
86
- ### 改动文件
87
-
88
- - `src/card/reply-dispatcher.ts` — 在流式卡片模式下启用 block 流式输出;接入 `onToolStart` 回调
89
- - `src/card/streaming-card-controller.ts` — 将每个已交付的 block 实时追加到卡片;添加 `onToolStart()` 显示工具调用状态
90
- - `src/card/builder.ts` — 完成卡片中工具调用摘要的折叠面板
11
+ - **实时流式追加** — 每个 block 的内容在生成过程中逐步追加到流式卡片
12
+ - **工具调用状态** — agent 调用工具时,卡片顶部实时显示当前工具,完成后自动折叠为摘要面板
91
13
 
92
14
  ## 安装
93
15
 
94
16
  需要 [OpenClaw](https://openclaw.ai)(>= 2026.2.26)和 Node.js(>= v22)。
95
17
 
96
- ### 方式 A:npm 安装(推荐)
18
+ ```bash
19
+ openclaw plugins install @colinlu50/openclaw-lark-stream
20
+ ```
97
21
 
98
- 1. 先安装官方插件完成引导配置(App ID、密钥、OAuth 等):
99
- ```bash
100
- npx -y @larksuite/openclaw-lark install
101
- ```
22
+ 安装完成后重启网关:
102
23
 
103
- 2. 用流式 Fork 替换:
104
- ```bash
105
- openclaw plugins install @colinlu50/openclaw-lark-stream
106
- ```
24
+ ```bash
25
+ openclaw gateway restart
26
+ ```
107
27
 
108
- 如果已安装过官方插件,跳过第 1 步。
28
+ > 如果之前安装过官方插件,先卸载:
29
+ > ```bash
30
+ > openclaw plugins uninstall openclaw-lark --force
31
+ > ```
109
32
 
110
- ### 方式 B:从源码安装(用于开发)
33
+ ### 从源码安装(开发用)
111
34
 
112
35
  ```bash
113
36
  cd ~/.openclaw/extensions
114
- rm -rf openclaw-lark
115
- git clone git@github.com:ColinLu50/openclaw-lark-stream.git openclaw-lark
116
- cd openclaw-lark && npm install
37
+ git clone git@github.com:ColinLu50/openclaw-lark-stream.git openclaw-lark-stream
38
+ cd openclaw-lark-stream && npm install && npm run build
39
+ openclaw gateway restart
117
40
  ```
118
41
 
119
- 重启 OpenClaw。
120
-
121
42
  ## 配置
122
43
 
123
- 开启可选的卡片底栏元信息:
44
+ 卡片底栏默认显示耗时和完成状态,如需关闭:
124
45
 
125
46
  ```bash
126
- openclaw config set channels.feishu.footer.elapsed true # 开启耗时
127
- openclaw config set channels.feishu.footer.status true # 开启状态展示
47
+ openclaw config set channels.feishu.footer.elapsed false # 隐藏耗时
48
+ openclaw config set channels.feishu.footer.status false # 隐藏完成状态
128
49
  ```
129
50
 
130
- - **elapsed** — 在卡片底栏显示总响应耗时(如 `耗时 3.2s`)
131
- - **status** — 在卡片底栏显示完成状态(`已完成` / `出错` / `已停止`)
132
-
133
- 两者默认为 `false`(不显示)。
51
+ - **elapsed** — 卡片底栏显示总响应耗时(如 `耗时 3.2s`)
52
+ - **status** — 卡片底栏显示完成状态(`已完成` / `出错` / `已停止`)
134
53
 
135
54
  ## 许可证
136
55
 
@@ -1,15 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { execFileSync } from "node:child_process";
4
- import { existsSync, rmSync } from "node:fs";
4
+ import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
5
5
  import { dirname, join } from "node:path";
6
6
 
7
7
  const SELF_PACKAGE = "@colinlu50/openclaw-lark-stream";
8
- const PLUGIN_DIR = join(
9
- process.env.OPENCLAW_STATE_DIR || join(process.env.HOME || process.env.USERPROFILE || "", ".openclaw"),
10
- "extensions",
11
- "openclaw-lark-stream",
12
- );
8
+ const STATE_DIR = process.env.OPENCLAW_STATE_DIR || join(process.env.HOME || process.env.USERPROFILE || "", ".openclaw");
9
+ const EXTENSIONS_DIR = join(STATE_DIR, "extensions");
10
+ const CONFIG_FILE = join(STATE_DIR, "openclaw.json");
11
+ // Tools installs official plugin as "openclaw-lark"; our manifest uses "openclaw-lark-stream"
12
+ const OFFICIAL_DIR = join(EXTENSIONS_DIR, "openclaw-lark");
13
+ const SELF_DIR = join(EXTENSIONS_DIR, "openclaw-lark-stream");
13
14
 
14
15
  const args = process.argv.slice(2);
15
16
  const subcommand = args[0];
@@ -28,12 +29,19 @@ if (subcommand === "install" || subcommand === "update") {
28
29
  // Tools may fail on gateway restart etc. — that's OK, config is preserved.
29
30
  }
30
31
 
31
- // Step 2: Replace official plugin code with ours
32
+ // Step 2: Clean up old plugin dirs + config references, then install ours
32
33
  try {
33
- if (existsSync(PLUGIN_DIR)) {
34
- console.log(`\nSwapping official plugin with ${SELF_PACKAGE}...`);
35
- rmSync(PLUGIN_DIR, { recursive: true, force: true });
34
+ for (const dir of [OFFICIAL_DIR, SELF_DIR]) {
35
+ if (existsSync(dir)) {
36
+ console.log(`\nRemoving ${dir}...`);
37
+ rmSync(dir, { recursive: true, force: true });
38
+ }
36
39
  }
40
+ // Remove stale "openclaw-lark" references from config so openclaw doesn't
41
+ // fail validation when the directory is gone.
42
+ cleanConfigReferences("openclaw-lark");
43
+
44
+ console.log(`\nInstalling ${SELF_PACKAGE}...`);
37
45
  execFileSync("openclaw", ["plugins", "install", SELF_PACKAGE], {
38
46
  stdio: "inherit",
39
47
  });
@@ -54,6 +62,39 @@ try {
54
62
  process.exit(error.status ?? 1);
55
63
  }
56
64
 
65
+ /**
66
+ * Remove stale plugin references from openclaw.json so that
67
+ * `openclaw plugins install` doesn't fail config validation.
68
+ */
69
+ function cleanConfigReferences(pluginId) {
70
+ if (!existsSync(CONFIG_FILE)) return;
71
+ try {
72
+ const cfg = JSON.parse(readFileSync(CONFIG_FILE, "utf8"));
73
+ let changed = false;
74
+ if (cfg.plugins?.entries?.[pluginId]) {
75
+ delete cfg.plugins.entries[pluginId];
76
+ changed = true;
77
+ }
78
+ if (cfg.plugins?.installs?.[pluginId]) {
79
+ delete cfg.plugins.installs[pluginId];
80
+ changed = true;
81
+ }
82
+ if (Array.isArray(cfg.plugins?.allow)) {
83
+ const idx = cfg.plugins.allow.indexOf(pluginId);
84
+ if (idx !== -1) {
85
+ cfg.plugins.allow.splice(idx, 1);
86
+ changed = true;
87
+ }
88
+ }
89
+ if (changed) {
90
+ writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2) + "\n", "utf8");
91
+ console.log(`Cleaned "${pluginId}" references from ${CONFIG_FILE}`);
92
+ }
93
+ } catch {
94
+ // Config parse failure — let openclaw handle it
95
+ }
96
+ }
97
+
57
98
  function runTools(fwdArgs) {
58
99
  let version = "latest";
59
100
  const vIdx = fwdArgs.indexOf("--tools-version");
package/dist/index.js CHANGED
@@ -114064,8 +114064,8 @@ var init_footer_config = __esm({
114064
114064
  "src/core/footer-config.ts"() {
114065
114065
  "use strict";
114066
114066
  DEFAULT_FOOTER_CONFIG = {
114067
- status: false,
114068
- elapsed: false
114067
+ status: true,
114068
+ elapsed: true
114069
114069
  };
114070
114070
  __name(resolveFooterConfig, "resolveFooterConfig");
114071
114071
  }