pi-remote-feishu 0.1.0
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/ARCHITECTURE.md +837 -0
- package/ARCHITECTURE.zh-CN.md +704 -0
- package/README.md +118 -0
- package/dist/attachments/mime.d.ts +11 -0
- package/dist/attachments/mime.js +27 -0
- package/dist/attachments/mime.js.map +1 -0
- package/dist/attachments/processor.d.ts +29 -0
- package/dist/attachments/processor.js +48 -0
- package/dist/attachments/processor.js.map +1 -0
- package/dist/attachments/temp-files.d.ts +16 -0
- package/dist/attachments/temp-files.js +32 -0
- package/dist/attachments/temp-files.js.map +1 -0
- package/dist/bin/pi-remote-feishu.d.ts +2 -0
- package/dist/bin/pi-remote-feishu.js +359 -0
- package/dist/bin/pi-remote-feishu.js.map +1 -0
- package/dist/bridge/card-actions.d.ts +13 -0
- package/dist/bridge/card-actions.js +156 -0
- package/dist/bridge/card-actions.js.map +1 -0
- package/dist/bridge/conversation-router.d.ts +21 -0
- package/dist/bridge/conversation-router.js +65 -0
- package/dist/bridge/conversation-router.js.map +1 -0
- package/dist/bridge/message-handler.d.ts +22 -0
- package/dist/bridge/message-handler.js +218 -0
- package/dist/bridge/message-handler.js.map +1 -0
- package/dist/bridge/message-normalizer.d.ts +17 -0
- package/dist/bridge/message-normalizer.js +81 -0
- package/dist/bridge/message-normalizer.js.map +1 -0
- package/dist/bridge/prompt-queue.d.ts +20 -0
- package/dist/bridge/prompt-queue.js +39 -0
- package/dist/bridge/prompt-queue.js.map +1 -0
- package/dist/bridge/runtime-host.d.ts +45 -0
- package/dist/bridge/runtime-host.js +133 -0
- package/dist/bridge/runtime-host.js.map +1 -0
- package/dist/bridge/session-host-manager.d.ts +59 -0
- package/dist/bridge/session-host-manager.js +143 -0
- package/dist/bridge/session-host-manager.js.map +1 -0
- package/dist/bridge/stream-renderer.d.ts +50 -0
- package/dist/bridge/stream-renderer.js +108 -0
- package/dist/bridge/stream-renderer.js.map +1 -0
- package/dist/bridge/ui-context.d.ts +19 -0
- package/dist/bridge/ui-context.js +150 -0
- package/dist/bridge/ui-context.js.map +1 -0
- package/dist/cards/common.d.ts +33 -0
- package/dist/cards/common.js +84 -0
- package/dist/cards/common.js.map +1 -0
- package/dist/cards/help.d.ts +11 -0
- package/dist/cards/help.js +31 -0
- package/dist/cards/help.js.map +1 -0
- package/dist/cards/models.d.ts +24 -0
- package/dist/cards/models.js +46 -0
- package/dist/cards/models.js.map +1 -0
- package/dist/cards/permission.d.ts +9 -0
- package/dist/cards/permission.js +17 -0
- package/dist/cards/permission.js.map +1 -0
- package/dist/cards/sessions.d.ts +11 -0
- package/dist/cards/sessions.js +54 -0
- package/dist/cards/sessions.js.map +1 -0
- package/dist/cards/status.d.ts +15 -0
- package/dist/cards/status.js +20 -0
- package/dist/cards/status.js.map +1 -0
- package/dist/cards/stop.d.ts +16 -0
- package/dist/cards/stop.js +24 -0
- package/dist/cards/stop.js.map +1 -0
- package/dist/config/load-config.d.ts +19 -0
- package/dist/config/load-config.js +51 -0
- package/dist/config/load-config.js.map +1 -0
- package/dist/config/schema.d.ts +52 -0
- package/dist/config/schema.js +260 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/extensions/index.d.ts +7 -0
- package/dist/extensions/index.js +71 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/lark-cli-guard.d.ts +12 -0
- package/dist/extensions/lark-cli-guard.js +75 -0
- package/dist/extensions/lark-cli-guard.js.map +1 -0
- package/dist/feishu/channel.d.ts +28 -0
- package/dist/feishu/channel.js +191 -0
- package/dist/feishu/channel.js.map +1 -0
- package/dist/feishu/context.d.ts +5 -0
- package/dist/feishu/context.js +19 -0
- package/dist/feishu/context.js.map +1 -0
- package/dist/feishu/webhook.d.ts +5 -0
- package/dist/feishu/webhook.js +8 -0
- package/dist/feishu/webhook.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/store/json-store.d.ts +25 -0
- package/dist/store/json-store.js +105 -0
- package/dist/store/json-store.js.map +1 -0
- package/dist/store/store.d.ts +7 -0
- package/dist/store/store.js +15 -0
- package/dist/store/store.js.map +1 -0
- package/dist/tools/send-file-to-chat.d.ts +26 -0
- package/dist/tools/send-file-to-chat.js +85 -0
- package/dist/tools/send-file-to-chat.js.map +1 -0
- package/dist/types.d.ts +300 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -0
- package/skills/lark-doc-cli/SKILL.md +56 -0
- package/skills/lark-im-readonly/SKILL.md +49 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/cards/sessions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE1E,eAAe;AACf,SAAS,aAAa,CAAC,QAAoC;IACzD,OAAO,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC;AAED,2BAA2B;AAC3B,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAIjC;IACC,MAAM,QAAQ,GAAiB;QAC7B,SAAS,CAAC,CAAC,UAAU,EAAE,KAAK,OAAO,CAAC,iBAAiB,IAAI,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnG,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,iBAAiB,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;KAC/G,CAAC;IAEF,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;QACpF,QAAQ,CAAC,IAAI,CACX,SAAS,CACP;YACE,KAAK,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,WAAW,IAAI;YACzD,KAAK,OAAO,CAAC,UAAU,IAAI;YAC3B,QAAQ,OAAO,CAAC,SAAS,EAAE;YAC3B,MAAM,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE;SACzC,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CACF,CAAC;QACF,QAAQ,CAAC,IAAI,CACX,OAAO,CAAC;YACN,8BAA8B;YAC9B,MAAM,CAAC,IAAI,EAAE;gBACX,GAAG,EAAE,SAAS;gBACd,MAAM,EAAE,QAAQ;gBAChB,UAAU,EAAE,OAAO,CAAC,iBAAiB;gBACrC,gBAAgB,EAAE,OAAO,CAAC,UAAU;aACrC,CAAC;YACF,sBAAsB;YACtB,MAAM,CACJ,IAAI,EACJ;gBACE,GAAG,EAAE,SAAS;gBACd,MAAM,EAAE,QAAQ;gBAChB,UAAU,EAAE,OAAO,CAAC,iBAAiB;gBACrC,gBAAgB,EAAE,OAAO,CAAC,UAAU;aACrC,EACD,QAAQ,CACT;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC;QACrD,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JsonObject } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* 运行状态卡片(/status 命令触发):
|
|
4
|
+
* 展示连接状态、聊天类型、会话模式、队列深度、是否运行中、当前模型等信息。
|
|
5
|
+
* 头部颜色随连接状态变化(已连接=绿,未连接=红)。
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildStatusCard(options: {
|
|
8
|
+
sessionKey: string;
|
|
9
|
+
connected: boolean;
|
|
10
|
+
queueDepth: number;
|
|
11
|
+
active: boolean;
|
|
12
|
+
model?: string;
|
|
13
|
+
chatType: "private" | "group";
|
|
14
|
+
sessionMode: string;
|
|
15
|
+
}): JsonObject;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { card, noteBlock, textBlock } from "./common.js";
|
|
2
|
+
/**
|
|
3
|
+
* 运行状态卡片(/status 命令触发):
|
|
4
|
+
* 展示连接状态、聊天类型、会话模式、队列深度、是否运行中、当前模型等信息。
|
|
5
|
+
* 头部颜色随连接状态变化(已连接=绿,未连接=红)。
|
|
6
|
+
*/
|
|
7
|
+
export function buildStatusCard(options) {
|
|
8
|
+
return card("Pi 飞书状态", options.connected ? "green" : "red", [
|
|
9
|
+
textBlock([
|
|
10
|
+
`**连接状态**:${options.connected ? "已连接" : "未连接"}`,
|
|
11
|
+
`**聊天类型**:${options.chatType === "group" ? "群聊" : "私聊"}`,
|
|
12
|
+
`**会话模式**:${options.sessionMode}`,
|
|
13
|
+
`**队列深度**:${options.queueDepth}`,
|
|
14
|
+
`**运行中**:${options.active ? "是" : "否"}`,
|
|
15
|
+
`**模型**:${options.model ?? "未选择"}`,
|
|
16
|
+
].join("\n")),
|
|
17
|
+
noteBlock(`Session:${options.sessionKey}`),
|
|
18
|
+
]);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/cards/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAQ/B;IACC,OAAO,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE;QAC1D,SAAS,CACP;YACE,YAAY,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE;YAC/C,YAAY,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;YACxD,YAAY,OAAO,CAAC,WAAW,EAAE;YACjC,YAAY,OAAO,CAAC,UAAU,EAAE;YAChC,WAAW,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE;YACvC,UAAU,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE;SACnC,CAAC,IAAI,CAAC,IAAI,CAAC,CACb;QACD,SAAS,CAAC,WAAW,OAAO,CAAC,UAAU,EAAE,CAAC;KAC3C,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { JsonObject } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* "正在处理"卡片:每次普通消息入队生成时,先发送这张卡片。
|
|
4
|
+
* 黄色头部 + "停止生成"按钮(danger),点击后由 card-actions 的 cmd: "stop" 分支中止生成。
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildStopCard(options: {
|
|
7
|
+
sessionKey: string;
|
|
8
|
+
chatType: "private" | "group";
|
|
9
|
+
senderName?: string;
|
|
10
|
+
sessionMode: string;
|
|
11
|
+
}): JsonObject;
|
|
12
|
+
/**
|
|
13
|
+
* 生成结束卡片:生成完成后把"正在处理"卡片原地更新为这张。
|
|
14
|
+
* title 一般为"Pi 已完成"或"Pi 失败",message 是结果说明。
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildStopDoneCard(title: string, message: string): JsonObject;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { actions, button, card, noteBlock, textBlock } from "./common.js";
|
|
2
|
+
/**
|
|
3
|
+
* "正在处理"卡片:每次普通消息入队生成时,先发送这张卡片。
|
|
4
|
+
* 黄色头部 + "停止生成"按钮(danger),点击后由 card-actions 的 cmd: "stop" 分支中止生成。
|
|
5
|
+
*/
|
|
6
|
+
export function buildStopCard(options) {
|
|
7
|
+
return card("Pi 正在处理", "yellow", [
|
|
8
|
+
textBlock([
|
|
9
|
+
// 群聊中告知正在回复谁
|
|
10
|
+
options.chatType === "group" && options.senderName ? `正在回复:**${options.senderName}**` : "正在生成回复。",
|
|
11
|
+
`会话:\`${options.sessionKey}\``,
|
|
12
|
+
`模式:${options.sessionMode}`,
|
|
13
|
+
].join("\n")),
|
|
14
|
+
actions([button("停止生成", { cmd: "stop", sessionKey: options.sessionKey }, "danger")]),
|
|
15
|
+
]);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 生成结束卡片:生成完成后把"正在处理"卡片原地更新为这张。
|
|
19
|
+
* title 一般为"Pi 已完成"或"Pi 失败",message 是结果说明。
|
|
20
|
+
*/
|
|
21
|
+
export function buildStopDoneCard(title, message) {
|
|
22
|
+
return card(title, "grey", [textBlock(message), noteBlock("这张状态卡会保留在当前聊天中。")]);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=stop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/cards/stop.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE1E;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAK7B;IACC,OAAO,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE;QAC/B,SAAS,CACP;YACE,aAAa;YACb,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,SAAS;YACjG,QAAQ,OAAO,CAAC,UAAU,IAAI;YAC9B,MAAM,OAAO,CAAC,WAAW,EAAE;SAC5B,CAAC,IAAI,CAAC,IAAI,CAAC,CACb;QACD,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;KACrF,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,OAAe;IAC9D,OAAO,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type PartialFeishuConfig } from "./schema.js";
|
|
2
|
+
import type { FeishuConfig } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* 配置加载入口。
|
|
5
|
+
* 配置来源及优先级(低 -> 高):
|
|
6
|
+
* 环境变量 FEISHU_APP_ID / FEISHU_APP_SECRET / ... < 配置文件 < CLI 参数
|
|
7
|
+
*/
|
|
8
|
+
/** loadConfig 的选项:可直接传部分配置字段覆盖,外加 configPath / cwd */
|
|
9
|
+
export interface LoadConfigOptions extends PartialFeishuConfig {
|
|
10
|
+
configPath?: string;
|
|
11
|
+
cwd?: string;
|
|
12
|
+
}
|
|
13
|
+
/** 对外暴露"配置文件在哪儿",供 doctor 命令展示 */
|
|
14
|
+
export declare function resolveConfigFilePath(cwd: string, explicitPath?: string): string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* 加载并归一化完整配置。
|
|
17
|
+
* 合并顺序:envConfig(最低)-> fileConfig -> cliConfig(最高)。
|
|
18
|
+
*/
|
|
19
|
+
export declare function loadConfig(options?: LoadConfigOptions): FeishuConfig;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { defaultUserConfigPath, mergeConfig, normalizeConfig, parsePartialConfig } from "./schema.js";
|
|
4
|
+
/** 读取并解析一个配置文件(JSON) */
|
|
5
|
+
function readConfigFile(path) {
|
|
6
|
+
const raw = readFileSync(path, "utf-8");
|
|
7
|
+
return parsePartialConfig(JSON.parse(raw));
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 定位配置文件:
|
|
11
|
+
* - 显式指定 configPath 时用显式路径
|
|
12
|
+
* - 否则优先找项目级 .pi/feishu.json,其次用户级 ~/.pi/agent/feishu.json
|
|
13
|
+
* - 都没有则返回 undefined(只用环境变量 + CLI 参数)
|
|
14
|
+
*/
|
|
15
|
+
function findConfigFile(cwd, explicitPath) {
|
|
16
|
+
if (explicitPath)
|
|
17
|
+
return resolve(explicitPath);
|
|
18
|
+
const projectPath = join(cwd, ".pi", "feishu.json");
|
|
19
|
+
if (existsSync(projectPath))
|
|
20
|
+
return projectPath;
|
|
21
|
+
const userPath = defaultUserConfigPath();
|
|
22
|
+
if (existsSync(userPath))
|
|
23
|
+
return userPath;
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
/** 对外暴露"配置文件在哪儿",供 doctor 命令展示 */
|
|
27
|
+
export function resolveConfigFilePath(cwd, explicitPath) {
|
|
28
|
+
return findConfigFile(resolve(cwd), explicitPath);
|
|
29
|
+
}
|
|
30
|
+
/** 从环境变量读取配置(FEISHU_APP_ID 等) */
|
|
31
|
+
function envConfig() {
|
|
32
|
+
return parsePartialConfig({
|
|
33
|
+
appId: process.env.FEISHU_APP_ID,
|
|
34
|
+
appSecret: process.env.FEISHU_APP_SECRET,
|
|
35
|
+
botName: process.env.FEISHU_BOT_NAME,
|
|
36
|
+
encryptKey: process.env.FEISHU_ENCRYPT_KEY,
|
|
37
|
+
verificationToken: process.env.FEISHU_VERIFICATION_TOKEN,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 加载并归一化完整配置。
|
|
42
|
+
* 合并顺序:envConfig(最低)-> fileConfig -> cliConfig(最高)。
|
|
43
|
+
*/
|
|
44
|
+
export function loadConfig(options = {}) {
|
|
45
|
+
const cwd = resolve(options.cwd ?? process.cwd());
|
|
46
|
+
const configPath = findConfigFile(cwd, options.configPath);
|
|
47
|
+
const fileConfig = configPath ? readConfigFile(configPath) : {};
|
|
48
|
+
const cliConfig = parsePartialConfig(options);
|
|
49
|
+
return normalizeConfig(mergeConfig(envConfig(), fileConfig, cliConfig), cwd);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=load-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../src/config/load-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAA4B,MAAM,aAAa,CAAC;AAehI,wBAAwB;AACxB,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,OAAO,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,GAAW,EAAE,YAAqB;IACxD,IAAI,YAAY;QAAE,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IACpD,IAAI,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,WAAW,CAAC;IAChD,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IACzC,IAAI,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC1C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,qBAAqB,CAAC,GAAW,EAAE,YAAqB;IACtE,OAAO,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;AACpD,CAAC;AAED,iCAAiC;AACjC,SAAS,SAAS;IAChB,OAAO,kBAAkB,CAAC;QACxB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;QAChC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;QACxC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;QACpC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC1C,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB;KACzD,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,UAA6B,EAAE;IACxD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAE9C,OAAO,eAAe,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { FeishuConfig, FeishuDebugConfig, FeishuFilesConfig, FeishuPolicyConfig, FeishuRenderingConfig, FeishuSessionsConfig, FeishuWebhookConfig } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================
|
|
4
|
+
* 配置系统
|
|
5
|
+
* ------------------------------------------------------------
|
|
6
|
+
* 负责把 环境变量 / 配置文件 / CLI 参数 三层配置合并、校验、
|
|
7
|
+
* 补默认值,最终生成完整的 FeishuConfig。
|
|
8
|
+
*
|
|
9
|
+
* 三个函数:
|
|
10
|
+
* - parsePartialConfig:把任意 JSON 安全解析成部分配置(忽略非法字段)
|
|
11
|
+
* - mergeConfig:浅合并多个部分配置(子对象也逐层合并)
|
|
12
|
+
* - normalizeConfig:补默认值并生成完整配置,缺 appId/appSecret 会抛错
|
|
13
|
+
* ============================================================
|
|
14
|
+
*/
|
|
15
|
+
/** 文件回传大小上限的默认值:20MB */
|
|
16
|
+
export declare const DEFAULT_MAX_UPLOAD_BYTES: number;
|
|
17
|
+
/** 会话空闲回收默认值:30 分钟 */
|
|
18
|
+
export declare const DEFAULT_IDLE_TTL_MS: number;
|
|
19
|
+
/** 部分配置:所有字段可选,代表"用户只写了其中一部分" */
|
|
20
|
+
export interface PartialFeishuConfig {
|
|
21
|
+
appId?: string;
|
|
22
|
+
appSecret?: string;
|
|
23
|
+
encryptKey?: string;
|
|
24
|
+
verificationToken?: string;
|
|
25
|
+
botName?: string;
|
|
26
|
+
transport?: "websocket" | "webhook";
|
|
27
|
+
webhook?: Partial<FeishuWebhookConfig>;
|
|
28
|
+
policy?: Partial<FeishuPolicyConfig>;
|
|
29
|
+
sessions?: Partial<FeishuSessionsConfig>;
|
|
30
|
+
rendering?: Partial<FeishuRenderingConfig>;
|
|
31
|
+
files?: Partial<FeishuFilesConfig>;
|
|
32
|
+
debug?: Partial<FeishuDebugConfig>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 把任意 JSON 值安全解析成部分配置。
|
|
36
|
+
* 非法字段会被忽略,不会抛错(配置来源可能是用户手写的文件)。
|
|
37
|
+
*/
|
|
38
|
+
export declare function parsePartialConfig(value: unknown): PartialFeishuConfig;
|
|
39
|
+
/**
|
|
40
|
+
* 合并多份部分配置:后面的覆盖前面的(子对象逐层浅合并)。
|
|
41
|
+
* 用于按优先级合并 环境变量 < 配置文件 < CLI 参数。
|
|
42
|
+
*/
|
|
43
|
+
export declare function mergeConfig(...configs: PartialFeishuConfig[]): PartialFeishuConfig;
|
|
44
|
+
/**
|
|
45
|
+
* 补默认值并生成完整配置。
|
|
46
|
+
* - appId / appSecret 为必填,缺失直接抛错
|
|
47
|
+
* - 各子配置使用默认值(如 requireMention 默认 true、groupScope 默认 shared-chat)
|
|
48
|
+
* - 目录类字段统一 resolve 成绝对路径
|
|
49
|
+
*/
|
|
50
|
+
export declare function normalizeConfig(partial: PartialFeishuConfig, cwd: string): FeishuConfig;
|
|
51
|
+
/** 用户级默认配置文件路径:~/.pi/agent/feishu.json */
|
|
52
|
+
export declare function defaultUserConfigPath(): string;
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { homedir, tmpdir } from "node:os";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* ============================================================
|
|
5
|
+
* 配置系统
|
|
6
|
+
* ------------------------------------------------------------
|
|
7
|
+
* 负责把 环境变量 / 配置文件 / CLI 参数 三层配置合并、校验、
|
|
8
|
+
* 补默认值,最终生成完整的 FeishuConfig。
|
|
9
|
+
*
|
|
10
|
+
* 三个函数:
|
|
11
|
+
* - parsePartialConfig:把任意 JSON 安全解析成部分配置(忽略非法字段)
|
|
12
|
+
* - mergeConfig:浅合并多个部分配置(子对象也逐层合并)
|
|
13
|
+
* - normalizeConfig:补默认值并生成完整配置,缺 appId/appSecret 会抛错
|
|
14
|
+
* ============================================================
|
|
15
|
+
*/
|
|
16
|
+
/** 文件回传大小上限的默认值:20MB */
|
|
17
|
+
export const DEFAULT_MAX_UPLOAD_BYTES = 20 * 1024 * 1024;
|
|
18
|
+
/** 会话空闲回收默认值:30 分钟 */
|
|
19
|
+
export const DEFAULT_IDLE_TTL_MS = 30 * 60 * 1000;
|
|
20
|
+
/* ---------- 安全读取辅助:类型不对/空串一律返回 undefined ---------- */
|
|
21
|
+
function readString(value) {
|
|
22
|
+
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
23
|
+
}
|
|
24
|
+
function readBoolean(value) {
|
|
25
|
+
return typeof value === "boolean" ? value : undefined;
|
|
26
|
+
}
|
|
27
|
+
function readNumber(value) {
|
|
28
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
29
|
+
}
|
|
30
|
+
function readStringArray(value) {
|
|
31
|
+
if (!Array.isArray(value))
|
|
32
|
+
return undefined;
|
|
33
|
+
const strings = value.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
|
|
34
|
+
return strings.length === value.length ? strings : undefined;
|
|
35
|
+
}
|
|
36
|
+
function withString(target, key, value) {
|
|
37
|
+
if (value !== undefined) {
|
|
38
|
+
target[key] = value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function isObject(value) {
|
|
42
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
43
|
+
}
|
|
44
|
+
function readGroupScope(value) {
|
|
45
|
+
return value === "shared-chat" || value === "per-user" ? value : undefined;
|
|
46
|
+
}
|
|
47
|
+
function readStoreKind(value) {
|
|
48
|
+
return value === "json" || value === "sqlite" ? value : undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 把任意 JSON 值安全解析成部分配置。
|
|
52
|
+
* 非法字段会被忽略,不会抛错(配置来源可能是用户手写的文件)。
|
|
53
|
+
*/
|
|
54
|
+
export function parsePartialConfig(value) {
|
|
55
|
+
if (!isObject(value))
|
|
56
|
+
return {};
|
|
57
|
+
// ---- policy ----
|
|
58
|
+
const policyValue = value.policy;
|
|
59
|
+
let policy;
|
|
60
|
+
if (isObject(policyValue)) {
|
|
61
|
+
policy = {};
|
|
62
|
+
const requireMention = readBoolean(policyValue.requireMention);
|
|
63
|
+
const dmEnabled = readBoolean(policyValue.dmEnabled);
|
|
64
|
+
const groupEnabled = readBoolean(policyValue.groupEnabled);
|
|
65
|
+
const allowUsers = readStringArray(policyValue.allowUsers);
|
|
66
|
+
const allowChats = readStringArray(policyValue.allowChats);
|
|
67
|
+
if (requireMention !== undefined)
|
|
68
|
+
policy.requireMention = requireMention;
|
|
69
|
+
if (dmEnabled !== undefined)
|
|
70
|
+
policy.dmEnabled = dmEnabled;
|
|
71
|
+
if (groupEnabled !== undefined)
|
|
72
|
+
policy.groupEnabled = groupEnabled;
|
|
73
|
+
if (allowUsers)
|
|
74
|
+
policy.allowUsers = allowUsers;
|
|
75
|
+
if (allowChats)
|
|
76
|
+
policy.allowChats = allowChats;
|
|
77
|
+
}
|
|
78
|
+
// ---- sessions ----
|
|
79
|
+
const sessionsValue = value.sessions;
|
|
80
|
+
let sessions;
|
|
81
|
+
if (isObject(sessionsValue)) {
|
|
82
|
+
sessions = {};
|
|
83
|
+
const groupScope = readGroupScope(sessionsValue.groupScope);
|
|
84
|
+
const defaultCwd = readString(sessionsValue.defaultCwd);
|
|
85
|
+
const store = readStoreKind(sessionsValue.store);
|
|
86
|
+
const idleTtlMs = readNumber(sessionsValue.idleTtlMs);
|
|
87
|
+
if (sessionsValue.privateScope === "per-user")
|
|
88
|
+
sessions.privateScope = "per-user";
|
|
89
|
+
if (groupScope)
|
|
90
|
+
sessions.groupScope = groupScope;
|
|
91
|
+
if (defaultCwd)
|
|
92
|
+
sessions.defaultCwd = defaultCwd;
|
|
93
|
+
if (store)
|
|
94
|
+
sessions.store = store;
|
|
95
|
+
if (idleTtlMs !== undefined)
|
|
96
|
+
sessions.idleTtlMs = idleTtlMs;
|
|
97
|
+
}
|
|
98
|
+
// ---- rendering ----
|
|
99
|
+
const renderingValue = value.rendering;
|
|
100
|
+
let rendering;
|
|
101
|
+
if (isObject(renderingValue)) {
|
|
102
|
+
rendering = {};
|
|
103
|
+
const showToolEvents = readBoolean(renderingValue.showToolEvents);
|
|
104
|
+
if (renderingValue.mode === "stream-card" || renderingValue.mode === "markdown" || renderingValue.mode === "text") {
|
|
105
|
+
rendering.mode = renderingValue.mode;
|
|
106
|
+
}
|
|
107
|
+
if (renderingValue.showThinking === "hide" ||
|
|
108
|
+
renderingValue.showThinking === "quote" ||
|
|
109
|
+
renderingValue.showThinking === "plain") {
|
|
110
|
+
rendering.showThinking = renderingValue.showThinking;
|
|
111
|
+
}
|
|
112
|
+
if (showToolEvents !== undefined)
|
|
113
|
+
rendering.showToolEvents = showToolEvents;
|
|
114
|
+
}
|
|
115
|
+
// ---- files ----
|
|
116
|
+
const filesValue = value.files;
|
|
117
|
+
let files;
|
|
118
|
+
if (isObject(filesValue)) {
|
|
119
|
+
files = {};
|
|
120
|
+
const allowedOutputDirs = readStringArray(filesValue.allowedOutputDirs);
|
|
121
|
+
const maxUploadBytes = readNumber(filesValue.maxUploadBytes);
|
|
122
|
+
const tempDir = readString(filesValue.tempDir);
|
|
123
|
+
if (allowedOutputDirs)
|
|
124
|
+
files.allowedOutputDirs = allowedOutputDirs;
|
|
125
|
+
if (maxUploadBytes !== undefined)
|
|
126
|
+
files.maxUploadBytes = maxUploadBytes;
|
|
127
|
+
if (tempDir)
|
|
128
|
+
files.tempDir = tempDir;
|
|
129
|
+
}
|
|
130
|
+
// ---- webhook ----
|
|
131
|
+
const webhookValue = value.webhook;
|
|
132
|
+
let webhook;
|
|
133
|
+
if (isObject(webhookValue)) {
|
|
134
|
+
webhook = {};
|
|
135
|
+
const host = readString(webhookValue.host);
|
|
136
|
+
const port = readNumber(webhookValue.port);
|
|
137
|
+
const path = readString(webhookValue.path);
|
|
138
|
+
if (host)
|
|
139
|
+
webhook.host = host;
|
|
140
|
+
if (port !== undefined)
|
|
141
|
+
webhook.port = port;
|
|
142
|
+
if (path)
|
|
143
|
+
webhook.path = path;
|
|
144
|
+
}
|
|
145
|
+
// ---- debug ----
|
|
146
|
+
const debugValue = value.debug;
|
|
147
|
+
let debug;
|
|
148
|
+
if (isObject(debugValue)) {
|
|
149
|
+
debug = {};
|
|
150
|
+
const logIncomingEvents = readBoolean(debugValue.logIncomingEvents);
|
|
151
|
+
if (logIncomingEvents !== undefined)
|
|
152
|
+
debug.logIncomingEvents = logIncomingEvents;
|
|
153
|
+
}
|
|
154
|
+
// ---- 顶层字段 ----
|
|
155
|
+
const result = {};
|
|
156
|
+
withString(result, "appId", readString(value.appId));
|
|
157
|
+
withString(result, "appSecret", readString(value.appSecret));
|
|
158
|
+
withString(result, "encryptKey", readString(value.encryptKey));
|
|
159
|
+
withString(result, "verificationToken", readString(value.verificationToken));
|
|
160
|
+
withString(result, "botName", readString(value.botName));
|
|
161
|
+
if (value.transport === "webhook" || value.transport === "websocket") {
|
|
162
|
+
result.transport = value.transport;
|
|
163
|
+
}
|
|
164
|
+
if (webhook)
|
|
165
|
+
result.webhook = webhook;
|
|
166
|
+
if (policy)
|
|
167
|
+
result.policy = policy;
|
|
168
|
+
if (sessions)
|
|
169
|
+
result.sessions = sessions;
|
|
170
|
+
if (rendering)
|
|
171
|
+
result.rendering = rendering;
|
|
172
|
+
if (files)
|
|
173
|
+
result.files = files;
|
|
174
|
+
if (debug)
|
|
175
|
+
result.debug = debug;
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* 合并多份部分配置:后面的覆盖前面的(子对象逐层浅合并)。
|
|
180
|
+
* 用于按优先级合并 环境变量 < 配置文件 < CLI 参数。
|
|
181
|
+
*/
|
|
182
|
+
export function mergeConfig(...configs) {
|
|
183
|
+
const merged = {};
|
|
184
|
+
for (const config of configs) {
|
|
185
|
+
Object.assign(merged, {
|
|
186
|
+
...config,
|
|
187
|
+
policy: { ...merged.policy, ...config.policy },
|
|
188
|
+
sessions: { ...merged.sessions, ...config.sessions },
|
|
189
|
+
rendering: { ...merged.rendering, ...config.rendering },
|
|
190
|
+
files: { ...merged.files, ...config.files },
|
|
191
|
+
webhook: { ...merged.webhook, ...config.webhook },
|
|
192
|
+
debug: { ...merged.debug, ...config.debug },
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return merged;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* 补默认值并生成完整配置。
|
|
199
|
+
* - appId / appSecret 为必填,缺失直接抛错
|
|
200
|
+
* - 各子配置使用默认值(如 requireMention 默认 true、groupScope 默认 shared-chat)
|
|
201
|
+
* - 目录类字段统一 resolve 成绝对路径
|
|
202
|
+
*/
|
|
203
|
+
export function normalizeConfig(partial, cwd) {
|
|
204
|
+
if (!partial.appId) {
|
|
205
|
+
throw new Error("Missing Feishu appId");
|
|
206
|
+
}
|
|
207
|
+
if (!partial.appSecret) {
|
|
208
|
+
throw new Error("Missing Feishu appSecret");
|
|
209
|
+
}
|
|
210
|
+
const policy = {
|
|
211
|
+
requireMention: partial.policy?.requireMention ?? true,
|
|
212
|
+
dmEnabled: partial.policy?.dmEnabled ?? true,
|
|
213
|
+
groupEnabled: partial.policy?.groupEnabled ?? true,
|
|
214
|
+
...(partial.policy?.allowUsers ? { allowUsers: partial.policy.allowUsers } : {}),
|
|
215
|
+
...(partial.policy?.allowChats ? { allowChats: partial.policy.allowChats } : {}),
|
|
216
|
+
};
|
|
217
|
+
const sessions = {
|
|
218
|
+
privateScope: "per-user",
|
|
219
|
+
groupScope: partial.sessions?.groupScope ?? "shared-chat",
|
|
220
|
+
defaultCwd: resolve(partial.sessions?.defaultCwd ?? cwd),
|
|
221
|
+
store: partial.sessions?.store ?? "json",
|
|
222
|
+
idleTtlMs: partial.sessions?.idleTtlMs ?? DEFAULT_IDLE_TTL_MS,
|
|
223
|
+
};
|
|
224
|
+
const rendering = {
|
|
225
|
+
mode: partial.rendering?.mode ?? "stream-card",
|
|
226
|
+
showThinking: partial.rendering?.showThinking ?? "quote",
|
|
227
|
+
showToolEvents: partial.rendering?.showToolEvents ?? true,
|
|
228
|
+
};
|
|
229
|
+
const files = {
|
|
230
|
+
allowedOutputDirs: partial.files?.allowedOutputDirs?.map((dir) => resolve(dir)) ?? [resolve(sessions.defaultCwd ?? cwd)],
|
|
231
|
+
maxUploadBytes: partial.files?.maxUploadBytes ?? DEFAULT_MAX_UPLOAD_BYTES,
|
|
232
|
+
tempDir: resolve(partial.files?.tempDir ?? join(tmpdir(), "pi-remote-feishu")),
|
|
233
|
+
};
|
|
234
|
+
const debug = {
|
|
235
|
+
logIncomingEvents: partial.debug?.logIncomingEvents ?? false,
|
|
236
|
+
};
|
|
237
|
+
return {
|
|
238
|
+
appId: partial.appId,
|
|
239
|
+
appSecret: partial.appSecret,
|
|
240
|
+
...(partial.encryptKey ? { encryptKey: partial.encryptKey } : {}),
|
|
241
|
+
...(partial.verificationToken ? { verificationToken: partial.verificationToken } : {}),
|
|
242
|
+
...(partial.botName ? { botName: partial.botName } : {}),
|
|
243
|
+
transport: partial.transport ?? "websocket",
|
|
244
|
+
webhook: {
|
|
245
|
+
host: partial.webhook?.host ?? "127.0.0.1",
|
|
246
|
+
port: partial.webhook?.port ?? 8787,
|
|
247
|
+
path: partial.webhook?.path ?? "/feishu/events",
|
|
248
|
+
},
|
|
249
|
+
policy,
|
|
250
|
+
sessions,
|
|
251
|
+
rendering,
|
|
252
|
+
files,
|
|
253
|
+
debug,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/** 用户级默认配置文件路径:~/.pi/agent/feishu.json */
|
|
257
|
+
export function defaultUserConfigPath() {
|
|
258
|
+
return join(homedir(), ".pi", "agent", "feishu.json");
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAa1C;;;;;;;;;;;;GAYG;AAEH,wBAAwB;AACxB,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AACzD,sBAAsB;AACtB,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAkBlD,wDAAwD;AAExD,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAClF,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACjF,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/G,OAAO,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/D,CAAC;AAED,SAAS,UAAU,CAAC,MAA2B,EAAE,GAA2E,EAAE,KAAyB;IACrJ,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACtB,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,KAAK,KAAK,aAAa,IAAI,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7E,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEhC,mBAAmB;IACnB,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC;IACjC,IAAI,MAA+C,CAAC;IACpD,IAAI,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1B,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,cAAc,GAAG,WAAW,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,WAAW,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,eAAe,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,eAAe,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC3D,IAAI,cAAc,KAAK,SAAS;YAAE,MAAM,CAAC,cAAc,GAAG,cAAc,CAAC;QACzE,IAAI,SAAS,KAAK,SAAS;YAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;QAC1D,IAAI,YAAY,KAAK,SAAS;YAAE,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;QACnE,IAAI,UAAU;YAAE,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAC/C,IAAI,UAAU;YAAE,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;IACjD,CAAC;IAED,qBAAqB;IACrB,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC;IACrC,IAAI,QAAmD,CAAC;IACxD,IAAI,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC5B,QAAQ,GAAG,EAAE,CAAC;QACd,MAAM,UAAU,GAAG,cAAc,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,aAAa,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACtD,IAAI,aAAa,CAAC,YAAY,KAAK,UAAU;YAAE,QAAQ,CAAC,YAAY,GAAG,UAAU,CAAC;QAClF,IAAI,UAAU;YAAE,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;QACjD,IAAI,UAAU;YAAE,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;QACjD,IAAI,KAAK;YAAE,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;QAClC,IAAI,SAAS,KAAK,SAAS;YAAE,QAAQ,CAAC,SAAS,GAAG,SAAS,CAAC;IAC9D,CAAC;IAED,sBAAsB;IACtB,MAAM,cAAc,GAAG,KAAK,CAAC,SAAS,CAAC;IACvC,IAAI,SAAqD,CAAC;IAC1D,IAAI,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QAC7B,SAAS,GAAG,EAAE,CAAC;QACf,MAAM,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAClE,IAAI,cAAc,CAAC,IAAI,KAAK,aAAa,IAAI,cAAc,CAAC,IAAI,KAAK,UAAU,IAAI,cAAc,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAClH,SAAS,CAAC,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC;QACvC,CAAC;QACD,IACE,cAAc,CAAC,YAAY,KAAK,MAAM;YACtC,cAAc,CAAC,YAAY,KAAK,OAAO;YACvC,cAAc,CAAC,YAAY,KAAK,OAAO,EACvC,CAAC;YACD,SAAS,CAAC,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC;QACvD,CAAC;QACD,IAAI,cAAc,KAAK,SAAS;YAAE,SAAS,CAAC,cAAc,GAAG,cAAc,CAAC;IAC9E,CAAC;IAED,kBAAkB;IAClB,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;IAC/B,IAAI,KAA6C,CAAC;IAClD,IAAI,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACzB,KAAK,GAAG,EAAE,CAAC;QACX,MAAM,iBAAiB,GAAG,eAAe,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QACxE,MAAM,cAAc,GAAG,UAAU,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,iBAAiB;YAAE,KAAK,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QACnE,IAAI,cAAc,KAAK,SAAS;YAAE,KAAK,CAAC,cAAc,GAAG,cAAc,CAAC;QACxE,IAAI,OAAO;YAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IACvC,CAAC;IAED,oBAAoB;IACpB,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;IACnC,IAAI,OAAiD,CAAC;IACtD,IAAI,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3B,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,IAAI;YAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;QAC9B,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;QAC5C,IAAI,IAAI;YAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAChC,CAAC;IAED,kBAAkB;IAClB,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;IAC/B,IAAI,KAA6C,CAAC;IAClD,IAAI,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACzB,KAAK,GAAG,EAAE,CAAC;QACX,MAAM,iBAAiB,GAAG,WAAW,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QACpE,IAAI,iBAAiB,KAAK,SAAS;YAAE,KAAK,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;IACnF,CAAC;IAED,iBAAiB;IACjB,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACrD,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7D,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/D,UAAU,CAAC,MAAM,EAAE,mBAAmB,EAAE,UAAU,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC7E,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IACzD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;QACrE,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IACrC,CAAC;IACD,IAAI,OAAO;QAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IACtC,IAAI,MAAM;QAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;IACnC,IAAI,QAAQ;QAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACzC,IAAI,SAAS;QAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;IAC5C,IAAI,KAAK;QAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;IAChC,IAAI,KAAK;QAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;IAChC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAG,OAA8B;IAC3D,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;YACpB,GAAG,MAAM;YACT,MAAM,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE;YAC9C,QAAQ,EAAE,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE;YACpD,SAAS,EAAE,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE;YACvD,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE;YAC3C,OAAO,EAAE,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE;YACjD,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE;SAC5C,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAA4B,EAAE,GAAW;IACvE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,MAAM,GAAuB;QACjC,cAAc,EAAE,OAAO,CAAC,MAAM,EAAE,cAAc,IAAI,IAAI;QACtD,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI;QAC5C,YAAY,EAAE,OAAO,CAAC,MAAM,EAAE,YAAY,IAAI,IAAI;QAClD,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjF,CAAC;IAEF,MAAM,QAAQ,GAAyB;QACrC,YAAY,EAAE,UAAU;QACxB,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,IAAI,aAAa;QACzD,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,IAAI,GAAG,CAAC;QACxD,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,IAAI,MAAM;QACxC,SAAS,EAAE,OAAO,CAAC,QAAQ,EAAE,SAAS,IAAI,mBAAmB;KAC9D,CAAC;IAEF,MAAM,SAAS,GAA0B;QACvC,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,IAAI,aAAa;QAC9C,YAAY,EAAE,OAAO,CAAC,SAAS,EAAE,YAAY,IAAI,OAAO;QACxD,cAAc,EAAE,OAAO,CAAC,SAAS,EAAE,cAAc,IAAI,IAAI;KAC1D,CAAC;IAEF,MAAM,KAAK,GAAsB;QAC/B,iBAAiB,EACf,OAAO,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC;QACvG,cAAc,EAAE,OAAO,CAAC,KAAK,EAAE,cAAc,IAAI,wBAAwB;QACzE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC;KAC/E,CAAC;IAEF,MAAM,KAAK,GAAsB;QAC/B,iBAAiB,EAAE,OAAO,CAAC,KAAK,EAAE,iBAAiB,IAAI,KAAK;KAC7D,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,WAAW;QAC3C,OAAO,EAAE;YACP,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,IAAI,WAAW;YAC1C,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI;YACnC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,IAAI,gBAAgB;SAChD;QACD,MAAM;QACN,QAAQ;QACR,SAAS;QACT,KAAK;QACL,KAAK;KACN,CAAC;AACJ,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,qBAAqB;IACnC,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { loadConfig } from "../config/load-config.js";
|
|
4
|
+
import { createSendFileToChatTool } from "../tools/send-file-to-chat.js";
|
|
5
|
+
import { FEISHU_CLI_PROMPT_GUARD, FEISHU_NO_CLI_PROMPT_GUARD, isBlockedLarkImCommand, isLarkCliInstalled, } from "./lark-cli-guard.js";
|
|
6
|
+
/**
|
|
7
|
+
* ============================================================
|
|
8
|
+
* Pi 扩展入口(package.json 的 pi.extensions 指向本文件)
|
|
9
|
+
* ------------------------------------------------------------
|
|
10
|
+
* 以 Pi 扩展方式加载时(在 TUI 里启用 pi-remote-feishu),注册:
|
|
11
|
+
* - /feishu 状态命令
|
|
12
|
+
* - 可选的 lark-cli 技能(检测到 lark-cli 时)
|
|
13
|
+
* - 系统提示词护栏(防止模型乱用 lark-cli im 命令)
|
|
14
|
+
* - bash 工具调用拦截(屏蔽 IM 写/收命令)
|
|
15
|
+
* - send_file_to_chat 工具
|
|
16
|
+
* ============================================================
|
|
17
|
+
*/
|
|
18
|
+
const extensionDir = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const packageRoot = resolve(extensionDir, "..", "..");
|
|
20
|
+
/** skills 目录(lark-doc-cli / lark-im-readonly 两个技能) */
|
|
21
|
+
const skillsDir = resolve(packageRoot, "skills");
|
|
22
|
+
/**
|
|
23
|
+
* 扩展主函数。
|
|
24
|
+
* 注意:本文件是"TUI 侧"的扩展集成;serve 模式的运行时工具注入在
|
|
25
|
+
* runtime-host.ts 的扩展工厂里(两者独立)。
|
|
26
|
+
*/
|
|
27
|
+
export default function feishuExtension(pi) {
|
|
28
|
+
const larkCliInstalled = isLarkCliInstalled();
|
|
29
|
+
// 注册 /feishu 状态命令,方便用户查看扩展加载状态
|
|
30
|
+
pi.registerCommand("feishu", {
|
|
31
|
+
description: "Show Feishu extension status",
|
|
32
|
+
handler: async (_args, ctx) => {
|
|
33
|
+
ctx.ui.notify(larkCliInstalled
|
|
34
|
+
? "Feishu extension is loaded. Lark CLI skills enabled: lark-doc-cli, lark-im-readonly. IM send/reply/receive commands are guarded."
|
|
35
|
+
: "Feishu extension is loaded. lark-cli was not detected, so Lark CLI skills are disabled. Current-chat transport tools remain available.", "info");
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
// 检测到 lark-cli 时,把 skills 目录注册为 Pi 可发现的技能
|
|
39
|
+
if (larkCliInstalled) {
|
|
40
|
+
pi.on("resources_discover", () => ({
|
|
41
|
+
skillPaths: [skillsDir],
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
// 在会话启动前注入系统提示词护栏(有/无 lark-cli 两套)
|
|
45
|
+
pi.on("before_agent_start", (event) => ({
|
|
46
|
+
systemPrompt: `${event.systemPrompt}\n\n${larkCliInstalled ? FEISHU_CLI_PROMPT_GUARD : FEISHU_NO_CLI_PROMPT_GUARD}`,
|
|
47
|
+
}));
|
|
48
|
+
// 拦截 bash 工具调用:屏蔽 lark-cli im 的发送/回复/接收等命令
|
|
49
|
+
pi.on("tool_call", (event) => {
|
|
50
|
+
if (event.toolName !== "bash")
|
|
51
|
+
return undefined;
|
|
52
|
+
const command = typeof event.input.command === "string" ? event.input.command : "";
|
|
53
|
+
if (!isBlockedLarkImCommand(command))
|
|
54
|
+
return undefined;
|
|
55
|
+
return {
|
|
56
|
+
block: true,
|
|
57
|
+
reason: "Blocked by pi-remote-feishu: lark-cli IM send/reply/receive commands are disabled. Use the Feishu transport or send_file_to_chat for current-chat replies.",
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
// 注册 send_file_to_chat 工具;配置缺失时给出警告提示
|
|
61
|
+
try {
|
|
62
|
+
const config = loadConfig();
|
|
63
|
+
pi.registerTool(createSendFileToChatTool(config));
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
pi.on("agent_start", (_event, ctx) => {
|
|
67
|
+
ctx.ui.notify("Feishu config not found; send_file_to_chat is not registered.", "warning");
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;GAWG;AAEH,MAAM,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7D,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACtD,sDAAsD;AACtD,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AAEjD;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAgB;IACtD,MAAM,gBAAgB,GAAG,kBAAkB,EAAE,CAAC;IAE9C,+BAA+B;IAC/B,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE;QAC3B,WAAW,EAAE,8BAA8B;QAC3C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,CACX,gBAAgB;gBACd,CAAC,CAAC,kIAAkI;gBACpI,CAAC,CAAC,wIAAwI,EAC5I,MAAM,CACP,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;IAEH,0CAA0C;IAC1C,IAAI,gBAAgB,EAAE,CAAC;QACrB,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC;YACjC,UAAU,EAAE,CAAC,SAAS,CAAC;SACxB,CAAC,CAAC,CAAC;IACN,CAAC;IAED,mCAAmC;IACnC,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtC,YAAY,EAAE,GAAG,KAAK,CAAC,YAAY,OAAO,gBAAgB,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,0BAA0B,EAAE;KACpH,CAAC,CAAC,CAAC;IAEJ,2CAA2C;IAC3C,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;QAC3B,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM;YAAE,OAAO,SAAS,CAAC;QAChD,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC;YAAE,OAAO,SAAS,CAAC;QACvD,OAAO;YACL,KAAK,EAAE,IAAI;YACX,MAAM,EACJ,4JAA4J;SAC/J,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,sCAAsC;IACtC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,EAAE,CAAC,YAAY,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;YACnC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,+DAA+D,EAAE,SAAS,CAAC,CAAC;QAC5F,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** 检测本机是否安装了 lark-cli(运行 `lark-cli --version`) */
|
|
2
|
+
export declare function isLarkCliInstalled(): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* 判断一条 bash 命令是否需要被拦截:
|
|
5
|
+
* 仅当它调用 lark-cli im 且包含被禁动作时才拦截。
|
|
6
|
+
* 动作匹配使用 +action 或 action 两种写法均可(正则做了转义)。
|
|
7
|
+
*/
|
|
8
|
+
export declare function isBlockedLarkImCommand(command: string): boolean;
|
|
9
|
+
/** 系统提示词护栏:检测到 lark-cli 时注入(允许文档/只读 IM,禁止 IM 写/收) */
|
|
10
|
+
export declare const FEISHU_CLI_PROMPT_GUARD = "\n## Feishu CLI Boundary\n\nThis session may expose Lark CLI skills for Feishu documents and read-only IM inspection.\n\n- Use lark-doc-cli for Feishu document tasks such as fetching, creating, updating, and inserting media into docs.\n- Use lark-im-readonly only for read-only IM tasks such as looking up chats, listing members, searching existing messages, or downloading message resources.\n- Do not use lark-cli IM commands to send, reply, forward, delete, update, receive, or listen for messages.\n- In a Feishu-triggered run, the pi-remote-feishu transport is the only normal reply channel back to the current chat.\n- To return generated local files to the current Feishu chat, use send_file_to_chat instead of manually sending IM messages with lark-cli.\n";
|
|
11
|
+
/** 系统提示词护栏:未检测到 lark-cli 时注入 */
|
|
12
|
+
export declare const FEISHU_NO_CLI_PROMPT_GUARD = "\n## Feishu CLI Boundary\n\nThe lark-cli executable was not detected when pi-remote-feishu loaded.\n\n- Do not attempt to use lark-cli commands unless the user installs and authenticates lark-cli, then reloads Pi.\n- Use pi-remote-feishu transport features for the current Feishu chat.\n- To return generated local files to the current Feishu chat, use send_file_to_chat.\n- If the user asks to read or edit a Feishu document and no SDK document tool is available yet, ask for the document link or token and explain that SDK document tooling is not implemented in this extension version.\n";
|