@wu529778790/open-im 1.9.1-beta.0 → 1.9.1
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 +3 -18
- package/README.zh-CN.md +3 -18
- package/dist/config.d.ts +0 -2
- package/dist/config.js +1 -1
- package/dist/constants.d.ts +0 -2
- package/dist/constants.js +0 -2
- package/dist/feishu/card-builder.d.ts +0 -2
- package/dist/feishu/card-builder.js +1 -1
- package/dist/workbuddy/event-handler.js +3 -1
- package/package.json +1 -1
- package/dist/claude/stream-parser.d.ts +0 -17
- package/dist/claude/stream-parser.js +0 -50
- package/dist/claude/types.d.ts +0 -54
- package/dist/claude/types.js +0 -21
- package/dist/workbuddy/index.d.ts +0 -8
- package/dist/workbuddy/index.js +0 -8
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Multi-platform IM bridge for AI CLI tools. Connect Telegram, Feishu, WeCom, Ding
|
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- Multi-platform support: Telegram, Feishu, WeCom, DingTalk, QQ, WeChat (
|
|
9
|
+
- Multi-platform support: Telegram, Feishu, WeCom, DingTalk, QQ, and WeChat (WorkBuddy), with multiple platforms enabled at the same time
|
|
10
10
|
- Multiple AI tools: Claude, Codex, and CodeBuddy
|
|
11
11
|
- Per-platform AI routing: each IM platform can use a different AI tool, with `aiCommand` as the global default and `platforms.<name>.aiCommand` as the override
|
|
12
12
|
- Streaming replies: relay AI output and tool execution progress in real time (DingTalk streaming is not fully supported yet)
|
|
@@ -56,7 +56,7 @@ Open the config page at [`http://127.0.0.1:39282`](http://127.0.0.1:39282) (or t
|
|
|
56
56
|
- **AI Tooling** – **General**: default AI tool (Claude / Codex / CodeBuddy), work directory, hook port, log level. **Per-tool tabs**: Claude (CLI path, timeout, proxy, config path, ANTHROPIC\_\* fields), Codex (CLI path, timeout, proxy), CodeBuddy (CLI path, timeout).
|
|
57
57
|
- **Service control** – Validate config, Save, Start bridge, Stop bridge.
|
|
58
58
|
|
|
59
|
-
WeChat
|
|
59
|
+
WorkBuddy (WeChat) is not in the web UI; configure it in `~/.open-im/config.json` or via `open-im init`.
|
|
60
60
|
|
|
61
61
|
- `open-im start` serves both the config page and the bridge on your local machine.
|
|
62
62
|
- `open-im dev` opens the page automatically only when setup is incomplete.
|
|
@@ -234,13 +234,6 @@ The following is valid JSON and can be saved directly as `~/.open-im/config.json
|
|
|
234
234
|
"clientSecret": "YOUR_DINGTALK_CLIENT_SECRET",
|
|
235
235
|
"cardTemplateId": "YOUR_DINGTALK_AI_CARD_TEMPLATE_ID"
|
|
236
236
|
},
|
|
237
|
-
"wechat": {
|
|
238
|
-
"enabled": false,
|
|
239
|
-
"aiCommand": "claude",
|
|
240
|
-
"allowedUserIds": [],
|
|
241
|
-
"appId": "YOUR_WECHAT_APP_ID",
|
|
242
|
-
"appSecret": "YOUR_WECHAT_APP_SECRET"
|
|
243
|
-
},
|
|
244
237
|
"workbuddy": {
|
|
245
238
|
"enabled": false,
|
|
246
239
|
"aiCommand": "claude",
|
|
@@ -288,13 +281,6 @@ The following is valid JSON and can be saved directly as `~/.open-im/config.json
|
|
|
288
281
|
| `WEWORK_SECRET` | WeCom secret |
|
|
289
282
|
| `WEWORK_WS_URL` | WeCom WebSocket URL |
|
|
290
283
|
| `WEWORK_ALLOWED_USER_IDS` | WeCom allowlist |
|
|
291
|
-
| `WECHAT_APP_ID` | WeChat standard mode app ID |
|
|
292
|
-
| `WECHAT_APP_SECRET` | WeChat standard mode app secret |
|
|
293
|
-
| `WECHAT_TOKEN` | WeChat AGP mode token |
|
|
294
|
-
| `WECHAT_GUID` | WeChat AGP mode GUID |
|
|
295
|
-
| `WECHAT_USER_ID` | WeChat AGP mode user ID |
|
|
296
|
-
| `WECHAT_WS_URL` | WeChat WebSocket URL |
|
|
297
|
-
| `WECHAT_ALLOWED_USER_IDS` | WeChat allowlist |
|
|
298
284
|
| `WORKBUDDY_ACCESS_TOKEN` | WorkBuddy OAuth access token (auto-generated by `open-im init`) |
|
|
299
285
|
| `WORKBUDDY_REFRESH_TOKEN` | WorkBuddy OAuth refresh token (auto-generated by `open-im init`) |
|
|
300
286
|
| `WORKBUDDY_USER_ID` | WorkBuddy user ID |
|
|
@@ -310,8 +296,7 @@ The following is valid JSON and can be saved directly as `~/.open-im/config.json
|
|
|
310
296
|
- QQ: create a bot in the [QQ Open Platform](https://bot.q.qq.com/) and get the `App ID` and `App Secret`
|
|
311
297
|
- DingTalk: create an internal enterprise app in DingTalk Open Platform, enable bot Stream Mode, and get the `Client ID` and `Client Secret`
|
|
312
298
|
- WeCom: get the bot ID and secret from the [WeCom admin console](https://work.weixin.qq.com/)
|
|
313
|
-
- WeChat:
|
|
314
|
-
- WorkBuddy: connects via CodeBuddy (copilot.tencent.com) Centrifuge WebSocket; run `open-im init` and select "WorkBuddy 微信客服 (WeChat KF)" to complete OAuth login and WeChat KF binding
|
|
299
|
+
- WeChat (WorkBuddy): connects via CodeBuddy (copilot.tencent.com) Centrifuge WebSocket; run `open-im init` and select "WorkBuddy 微信客服 (WeChat KF)" to complete OAuth login and WeChat KF binding
|
|
315
300
|
|
|
316
301
|
Notes on DingTalk: the current implementation uses a hybrid model of "Stream Mode for receiving messages + OpenAPI for sending messages".
|
|
317
302
|
|
package/README.zh-CN.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## 功能特性
|
|
8
8
|
|
|
9
|
-
- 多平台:支持 Telegram、飞书、企业微信、钉钉、QQ
|
|
9
|
+
- 多平台:支持 Telegram、飞书、企业微信、钉钉、QQ、微信(WorkBuddy),可同时启用
|
|
10
10
|
- 多 AI 工具:支持 Claude、Codex、CodeBuddy
|
|
11
11
|
- 按平台分配 AI:根级 `aiCommand` 作为默认值,`platforms.<name>.aiCommand` 可为不同 IM 单独指定 AI 工具
|
|
12
12
|
- 流式输出:实时回传 AI 回复与工具执行进度(目前钉钉暂未实现流式传输)
|
|
@@ -62,7 +62,7 @@ open-im start
|
|
|
62
62
|
- **AI 工具配置** – **公共**:默认 AI 工具(Claude / Codex / CodeBuddy)、工作目录、Hook 端口、日志级别。**分工具**:Claude(CLI 路径、超时、代理、配置路径、ANTHROPIC\_\* 等)、Codex(CLI 路径、超时、代理)、CodeBuddy(CLI 路径、超时)
|
|
63
63
|
- **服务控制** – 校验配置、保存、启动桥接、停止桥接
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
WorkBuddy(微信)暂不在网页中配置,如需使用请在 `~/.open-im/config.json` 中手动配置或通过 `open-im init` 引导。
|
|
66
66
|
|
|
67
67
|
- `open-im start` 会同时启动桥接服务并提供该配置页(本机场景)。
|
|
68
68
|
- `open-im dev` 仅在未完成配置时自动打开页面。
|
|
@@ -240,13 +240,6 @@ codebuddy login
|
|
|
240
240
|
"clientSecret": "YOUR_DINGTALK_CLIENT_SECRET",
|
|
241
241
|
"cardTemplateId": "YOUR_DINGTALK_AI_CARD_TEMPLATE_ID"
|
|
242
242
|
},
|
|
243
|
-
"wechat": {
|
|
244
|
-
"enabled": false,
|
|
245
|
-
"aiCommand": "claude",
|
|
246
|
-
"allowedUserIds": [],
|
|
247
|
-
"appId": "YOUR_WECHAT_APP_ID",
|
|
248
|
-
"appSecret": "YOUR_WECHAT_APP_SECRET"
|
|
249
|
-
},
|
|
250
243
|
"workbuddy": {
|
|
251
244
|
"enabled": false,
|
|
252
245
|
"aiCommand": "claude",
|
|
@@ -294,13 +287,6 @@ codebuddy login
|
|
|
294
287
|
| `WEWORK_SECRET` | 企业微信 Secret |
|
|
295
288
|
| `WEWORK_WS_URL` | 企业微信 WebSocket 地址 |
|
|
296
289
|
| `WEWORK_ALLOWED_USER_IDS` | 企业微信白名单 |
|
|
297
|
-
| `WECHAT_APP_ID` | 微信标准模式 App ID |
|
|
298
|
-
| `WECHAT_APP_SECRET` | 微信标准模式 App Secret |
|
|
299
|
-
| `WECHAT_TOKEN` | 微信 AGP 模式 Token |
|
|
300
|
-
| `WECHAT_GUID` | 微信 AGP 模式 GUID |
|
|
301
|
-
| `WECHAT_USER_ID` | 微信 AGP 模式 User ID |
|
|
302
|
-
| `WECHAT_WS_URL` | 微信 WebSocket 地址 |
|
|
303
|
-
| `WECHAT_ALLOWED_USER_IDS` | 微信白名单 |
|
|
304
290
|
| `WORKBUDDY_ACCESS_TOKEN` | WorkBuddy OAuth 访问令牌(由 `open-im init` 自动生成) |
|
|
305
291
|
| `WORKBUDDY_REFRESH_TOKEN` | WorkBuddy OAuth 刷新令牌(由 `open-im init` 自动生成) |
|
|
306
292
|
| `WORKBUDDY_USER_ID` | WorkBuddy 用户 ID |
|
|
@@ -316,8 +302,7 @@ codebuddy login
|
|
|
316
302
|
- QQ:从 [QQ 开放平台](https://bot.q.qq.com/) 创建机器人,获取 `App ID` 和 `App Secret`
|
|
317
303
|
- 钉钉:从钉钉开放平台创建企业内部应用,启用机器人 Stream Mode,获取 `Client ID` 和 `Client Secret`
|
|
318
304
|
- 企业微信:从 [企业微信管理后台](https://work.weixin.qq.com/) 获取 Bot ID 和 Secret
|
|
319
|
-
-
|
|
320
|
-
- WorkBuddy:通过 CodeBuddy(copilot.tencent.com)Centrifuge WebSocket 接入微信客服;运行 `open-im init` 并选择 "WorkBuddy 微信客服 (WeChat KF)" 完成 OAuth 登录和微信客服绑定
|
|
305
|
+
- 微信(WorkBuddy):通过 CodeBuddy(copilot.tencent.com)Centrifuge WebSocket 接入微信客服;运行 `open-im init` 并选择 "WorkBuddy 微信客服 (WeChat KF)" 完成 OAuth 登录和微信客服绑定
|
|
321
306
|
|
|
322
307
|
说明:钉钉当前采用“Stream Mode 收消息 + OpenAPI 发送消息”的混合模式。
|
|
323
308
|
|
package/dist/config.d.ts
CHANGED
|
@@ -188,8 +188,6 @@ export declare function getClaudeConfigHome(): string;
|
|
|
188
188
|
export declare function loadClaudeSettingsEnv(): Record<string, string>;
|
|
189
189
|
/** 保存环境变量到 Claude Code 配置文件(~/.claude/settings.json) */
|
|
190
190
|
export declare function saveClaudeSettingsEnv(env: Record<string, string>): void;
|
|
191
|
-
/** 检查是否已配置 Claude API 凭证 */
|
|
192
|
-
export declare function hasClaudeCredentials(): boolean;
|
|
193
191
|
/** 检测是否需要交互式配置(无 token 且无环境变量) */
|
|
194
192
|
export declare function needsSetup(): boolean;
|
|
195
193
|
export declare function loadConfig(): Config;
|
package/dist/config.js
CHANGED
|
@@ -163,7 +163,7 @@ export function saveClaudeSettingsEnv(env) {
|
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
/** 检查是否已配置 Claude API 凭证 */
|
|
166
|
-
|
|
166
|
+
function hasClaudeCredentials() {
|
|
167
167
|
return !!(process.env.ANTHROPIC_API_KEY ||
|
|
168
168
|
process.env.ANTHROPIC_AUTH_TOKEN ||
|
|
169
169
|
process.env.CLAUDE_CODE_OAUTH_TOKEN ||
|
package/dist/constants.d.ts
CHANGED
|
@@ -9,8 +9,6 @@ export declare const TERMINAL_ONLY_COMMANDS: Set<string>;
|
|
|
9
9
|
export declare const CARDKIT_THROTTLE_MS = 80;
|
|
10
10
|
/** Telegram 编辑消息节流:200ms(open-im 默认值) */
|
|
11
11
|
export declare const TELEGRAM_THROTTLE_MS = 200;
|
|
12
|
-
/** WeChat 流式更新节流:1000ms(AGP 协议建议值) */
|
|
13
|
-
export declare const WECHAT_THROTTLE_MS = 1000;
|
|
14
12
|
/** WorkBuddy 流式更新节流:1000ms(Centrifuge 协议建议值) */
|
|
15
13
|
export declare const WORKBUDDY_THROTTLE_MS = 1000;
|
|
16
14
|
export declare const WEWORK_THROTTLE_MS = 500;
|
package/dist/constants.js
CHANGED
|
@@ -30,8 +30,6 @@ export const TERMINAL_ONLY_COMMANDS = new Set([
|
|
|
30
30
|
export const CARDKIT_THROTTLE_MS = 80;
|
|
31
31
|
/** Telegram 编辑消息节流:200ms(open-im 默认值) */
|
|
32
32
|
export const TELEGRAM_THROTTLE_MS = 200;
|
|
33
|
-
/** WeChat 流式更新节流:1000ms(AGP 协议建议值) */
|
|
34
|
-
export const WECHAT_THROTTLE_MS = 1000;
|
|
35
33
|
/** WorkBuddy 流式更新节流:1000ms(Centrifuge 协议建议值) */
|
|
36
34
|
export const WORKBUDDY_THROTTLE_MS = 1000;
|
|
37
35
|
export const WEWORK_THROTTLE_MS = 500;
|
|
@@ -12,8 +12,6 @@ interface CardOptions {
|
|
|
12
12
|
toolName?: string;
|
|
13
13
|
}
|
|
14
14
|
export declare function truncateForStreaming(text: string): string;
|
|
15
|
-
/** CardKit 2.0 格式,含 element_id 供 cardElement.content 流式更新 */
|
|
16
|
-
export declare function buildCardV2Object(options: CardOptions, cardId?: string): Record<string, unknown>;
|
|
17
15
|
export declare function buildCardV2(options: CardOptions, cardId?: string): string;
|
|
18
16
|
export declare function splitLongContent(text: string, maxLen?: number): string[];
|
|
19
17
|
export {};
|
|
@@ -27,7 +27,7 @@ export function truncateForStreaming(text) {
|
|
|
27
27
|
return truncateText(text, MAX_STREAMING_CONTENT_LENGTH);
|
|
28
28
|
}
|
|
29
29
|
/** CardKit 2.0 格式,含 element_id 供 cardElement.content 流式更新 */
|
|
30
|
-
|
|
30
|
+
function buildCardV2Object(options, cardId) {
|
|
31
31
|
const { content, status, note, thinking, toolName: rawToolName } = options;
|
|
32
32
|
const toolName = getAIToolDisplayName(rawToolName ?? 'claude');
|
|
33
33
|
const elements = [];
|
|
@@ -20,13 +20,14 @@ export function setupWorkBuddyHandlers(config, sessionManager) {
|
|
|
20
20
|
const runningTasks = new Map();
|
|
21
21
|
const taskKeyByChatId = new Map();
|
|
22
22
|
const stopTaskCleanup = startTaskCleanup(runningTasks);
|
|
23
|
+
let currentMsgId = '';
|
|
23
24
|
const commandHandler = new CommandHandler({
|
|
24
25
|
config,
|
|
25
26
|
sessionManager,
|
|
26
27
|
requestQueue,
|
|
27
28
|
sender: {
|
|
28
29
|
sendTextReply: async (chatId, text) => {
|
|
29
|
-
|
|
30
|
+
await sendTextReply(null, chatId, text, currentMsgId);
|
|
30
31
|
},
|
|
31
32
|
},
|
|
32
33
|
getRunningTasksSize: () => runningTasks.size,
|
|
@@ -71,6 +72,7 @@ export function setupWorkBuddyHandlers(config, sessionManager) {
|
|
|
71
72
|
});
|
|
72
73
|
}
|
|
73
74
|
async function handleEvent(chatId, msgId, content) {
|
|
75
|
+
currentMsgId = msgId;
|
|
74
76
|
log.info(`[handleEvent] chatId=${chatId}, msgId=${msgId}, content="${content.substring(0, 100)}"`);
|
|
75
77
|
// Use chatId as userId for WorkBuddy (WeChat KF doesn't have separate userId)
|
|
76
78
|
const userId = chatId;
|
package/package.json
CHANGED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { StreamEvent } from './types.js';
|
|
2
|
-
export declare function parseStreamLine(line: string): StreamEvent | null;
|
|
3
|
-
export declare function extractTextDelta(event: StreamEvent): {
|
|
4
|
-
text: string;
|
|
5
|
-
} | null;
|
|
6
|
-
export declare function extractThinkingDelta(event: StreamEvent): {
|
|
7
|
-
text: string;
|
|
8
|
-
} | null;
|
|
9
|
-
export declare function extractResult(event: StreamEvent): {
|
|
10
|
-
success: boolean;
|
|
11
|
-
result: string;
|
|
12
|
-
accumulated: string;
|
|
13
|
-
cost: number;
|
|
14
|
-
durationMs: number;
|
|
15
|
-
numTurns: number;
|
|
16
|
-
toolStats: Record<string, number>;
|
|
17
|
-
} | null;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
export function parseStreamLine(line) {
|
|
2
|
-
const trimmed = line.trim();
|
|
3
|
-
if (!trimmed)
|
|
4
|
-
return null;
|
|
5
|
-
try {
|
|
6
|
-
const parsed = JSON.parse(trimmed);
|
|
7
|
-
if (typeof parsed === 'object' && parsed !== null && 'type' in parsed) {
|
|
8
|
-
return parsed;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
catch {
|
|
12
|
-
/* ignore */
|
|
13
|
-
}
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
export function extractTextDelta(event) {
|
|
17
|
-
const e = event;
|
|
18
|
-
if (e.type === 'stream_event' &&
|
|
19
|
-
e.event?.type === 'content_block_delta' &&
|
|
20
|
-
e.event.delta?.type === 'text_delta' &&
|
|
21
|
-
e.event.delta.text) {
|
|
22
|
-
return { text: e.event.delta.text };
|
|
23
|
-
}
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
export function extractThinkingDelta(event) {
|
|
27
|
-
const e = event;
|
|
28
|
-
if (e.type === 'stream_event' &&
|
|
29
|
-
e.event?.type === 'content_block_delta' &&
|
|
30
|
-
e.event.delta?.type === 'thinking_delta' &&
|
|
31
|
-
e.event.delta.thinking) {
|
|
32
|
-
return { text: e.event.delta.thinking };
|
|
33
|
-
}
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
export function extractResult(event) {
|
|
37
|
-
if (event.type === 'result' && 'subtype' in event) {
|
|
38
|
-
const e = event;
|
|
39
|
-
return {
|
|
40
|
-
success: e.subtype === 'success',
|
|
41
|
-
result: e.result,
|
|
42
|
-
accumulated: '',
|
|
43
|
-
cost: e.total_cost_usd ?? 0,
|
|
44
|
-
durationMs: e.duration_ms ?? 0,
|
|
45
|
-
numTurns: e.num_turns ?? 0,
|
|
46
|
-
toolStats: {},
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return null;
|
|
50
|
-
}
|
package/dist/claude/types.d.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export interface StreamInit {
|
|
2
|
-
type: 'system';
|
|
3
|
-
subtype: 'init';
|
|
4
|
-
session_id: string;
|
|
5
|
-
model: string;
|
|
6
|
-
}
|
|
7
|
-
export interface StreamContentBlockDelta {
|
|
8
|
-
type: 'stream_event';
|
|
9
|
-
event: {
|
|
10
|
-
type: 'content_block_delta';
|
|
11
|
-
index: number;
|
|
12
|
-
delta: {
|
|
13
|
-
type: string;
|
|
14
|
-
text?: string;
|
|
15
|
-
thinking?: string;
|
|
16
|
-
partial_json?: string;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
export interface StreamContentBlockStop {
|
|
21
|
-
type: 'stream_event';
|
|
22
|
-
event: {
|
|
23
|
-
type: 'content_block_stop';
|
|
24
|
-
index: number;
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
export interface StreamContentBlockStart {
|
|
28
|
-
type: 'stream_event';
|
|
29
|
-
event: {
|
|
30
|
-
type: 'content_block_start';
|
|
31
|
-
index: number;
|
|
32
|
-
content_block: {
|
|
33
|
-
type: string;
|
|
34
|
-
name?: string;
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
export interface StreamResult {
|
|
39
|
-
type: 'result';
|
|
40
|
-
subtype: 'success' | 'error';
|
|
41
|
-
result: string;
|
|
42
|
-
total_cost_usd: number;
|
|
43
|
-
duration_ms: number;
|
|
44
|
-
num_turns: number;
|
|
45
|
-
}
|
|
46
|
-
export type StreamEvent = StreamInit | StreamContentBlockDelta | StreamContentBlockStart | StreamContentBlockStop | StreamResult | {
|
|
47
|
-
type: string;
|
|
48
|
-
[key: string]: unknown;
|
|
49
|
-
};
|
|
50
|
-
export declare function isStreamInit(e: StreamEvent): e is StreamInit;
|
|
51
|
-
export declare function isContentBlockDelta(e: StreamEvent): e is StreamContentBlockDelta;
|
|
52
|
-
export declare function isContentBlockStart(e: StreamEvent): e is StreamContentBlockStart;
|
|
53
|
-
export declare function isContentBlockStop(e: StreamEvent): e is StreamContentBlockStop;
|
|
54
|
-
export declare function isStreamResult(e: StreamEvent): e is StreamResult;
|
package/dist/claude/types.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export function isStreamInit(e) {
|
|
2
|
-
return e.type === 'system' && 'subtype' in e && e.subtype === 'init';
|
|
3
|
-
}
|
|
4
|
-
export function isContentBlockDelta(e) {
|
|
5
|
-
return (e.type === 'stream_event' &&
|
|
6
|
-
typeof e.event === 'object' &&
|
|
7
|
-
e.event.type === 'content_block_delta');
|
|
8
|
-
}
|
|
9
|
-
export function isContentBlockStart(e) {
|
|
10
|
-
return (e.type === 'stream_event' &&
|
|
11
|
-
typeof e.event === 'object' &&
|
|
12
|
-
e.event.type === 'content_block_start');
|
|
13
|
-
}
|
|
14
|
-
export function isContentBlockStop(e) {
|
|
15
|
-
return (e.type === 'stream_event' &&
|
|
16
|
-
typeof e.event === 'object' &&
|
|
17
|
-
e.event.type === 'content_block_stop');
|
|
18
|
-
}
|
|
19
|
-
export function isStreamResult(e) {
|
|
20
|
-
return e.type === 'result' && 'subtype' in e;
|
|
21
|
-
}
|
package/dist/workbuddy/index.js
DELETED