@jesonliu/lark-claudecode-bridge 1.0.2 → 1.0.4
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/assets/web/css/main.css +13 -0
- package/assets/web/js/core.js +3 -1
- package/assets/web/js/pages/larkcli-device.js +188 -0
- package/assets/web/js/pages/overview.js +244 -5
- package/assets/web/js/ui.js +66 -2
- package/config.example.yaml +3 -0
- package/dist/bin/lcb.js +10 -0
- package/dist/bin/lcb.js.map +1 -1
- package/dist/executor/notify-server.d.ts +0 -2
- package/dist/executor/notify-server.js +3 -10
- package/dist/executor/notify-server.js.map +1 -1
- package/dist/executor/plugin-manager.d.ts +16 -0
- package/dist/executor/plugin-manager.js +40 -1
- package/dist/executor/plugin-manager.js.map +1 -1
- package/dist/gateway/card-builder.d.ts +6 -5
- package/dist/gateway/card-builder.js +10 -9
- package/dist/gateway/card-builder.js.map +1 -1
- package/dist/gateway/diff-card.d.ts +7 -7
- package/dist/gateway/diff-card.js +14 -8
- package/dist/gateway/diff-card.js.map +1 -1
- package/dist/gateway/feishu-gateway.d.ts +7 -1
- package/dist/gateway/feishu-gateway.js +8 -3
- package/dist/gateway/feishu-gateway.js.map +1 -1
- package/dist/index.js +100 -30
- package/dist/index.js.map +1 -1
- package/dist/lark-cli-manager.d.ts +336 -0
- package/dist/lark-cli-manager.js +985 -0
- package/dist/lark-cli-manager.js.map +1 -0
- package/dist/notify-sop.d.ts +1 -1
- package/dist/notify-sop.js +3 -3
- package/dist/notify-sop.js.map +1 -1
- package/dist/session/commands.d.ts +3 -0
- package/dist/session/commands.js +3 -3
- package/dist/session/commands.js.map +1 -1
- package/dist/session/plugin-command.js +18 -2
- package/dist/session/plugin-command.js.map +1 -1
- package/dist/session/session-store.d.ts +9 -2
- package/dist/session/session-store.js +9 -3
- package/dist/session/session-store.js.map +1 -1
- package/dist/util/file-tracker.d.ts +13 -6
- package/dist/util/file-tracker.js +28 -10
- package/dist/util/file-tracker.js.map +1 -1
- package/dist/util/npm.d.ts +13 -0
- package/dist/util/npm.js +44 -0
- package/dist/util/npm.js.map +1 -0
- package/dist/util/terminal-window.d.ts +111 -0
- package/dist/util/terminal-window.js +425 -0
- package/dist/util/terminal-window.js.map +1 -0
- package/dist/util/workspace-diff.d.ts +4 -7
- package/dist/util/workspace-diff.js +30 -35
- package/dist/util/workspace-diff.js.map +1 -1
- package/dist/web/server.js +94 -4
- package/dist/web/server.js.map +1 -1
- package/dist/web/update.d.ts +1 -5
- package/dist/web/update.js +2 -20
- package/dist/web/update.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { type LaunchTerminalResult, type TerminalTask } from './util/terminal-window.js';
|
|
2
|
+
/** 飞书官方 CLI 的 npm 包名(命令名 lark-cli;注意 @larksuiteoapi 作用域是 lark-mcp,勿混淆) */
|
|
3
|
+
export declare const LARK_CLI_PACKAGE = "@larksuite/cli";
|
|
4
|
+
/** 飞书 CLI 官方 SKILL 的来源 URL(`npx skills add` 的 well-known discovery 入口) */
|
|
5
|
+
export declare const LARK_CLI_SKILL_SOURCE = "https://open.feishu.cn";
|
|
6
|
+
/**
|
|
7
|
+
* 触发 lark-cli「Agent 上下文」分支的环境变量(来源:`lark-cli config bind --help` 自述
|
|
8
|
+
* --source 由 OPENCLAW_HOME / HERMES_HOME / LARK_CHANNEL 自动探测)。实测本机设了
|
|
9
|
+
* HERMES_HOME 时 auth status 报 "hermes not bound"、config init 被拒——与 bridge 无关的
|
|
10
|
+
* 上下文不能劫持标准安装流程,入口与探测处统一剔除。
|
|
11
|
+
*/
|
|
12
|
+
export declare const AGENT_CONTEXT_ENV_KEYS: readonly ['HERMES_HOME', 'OPENCLAW_HOME', 'LARK_CHANNEL'];
|
|
13
|
+
/** 返回剔除 Agent 上下文变量后的 env 副本(不改传入对象;纯函数可测) */
|
|
14
|
+
export declare function stripAgentContextEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
15
|
+
export interface LarkCliDetect {
|
|
16
|
+
installed: boolean;
|
|
17
|
+
/** 解析不到时缺省(已安装但版本未知,不算未装) */
|
|
18
|
+
version?: string;
|
|
19
|
+
}
|
|
20
|
+
/** 纯函数(可测):从 `lark-cli --version` 输出解析语义化版本(如 1.2.3 / 1.2.3-beta.1) */
|
|
21
|
+
export declare function parseLarkCliVersion(out: string): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* 纯函数(可测):从 `npm ls -g @larksuite/cli --json` 输出解析已装版本。
|
|
24
|
+
* JSON.parse 的结果可能是 null(字面量 "null" 也合法),必须挡住非对象再取属性
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseNpmLsVersion(out: string): string | undefined;
|
|
27
|
+
/** 纯函数(可测):包内 CLI 入口绝对路径(不依赖 PATH 的检测/调用锚点);实测 execFile 正反斜杠均可执行,用平台原生形式即可 */
|
|
28
|
+
export declare function larkCliEntryPath(prefix: string): string;
|
|
29
|
+
type ExecRunner = (file: string, args: string[], opts: {
|
|
30
|
+
timeout: number;
|
|
31
|
+
windowsHide: boolean;
|
|
32
|
+
encoding: 'utf8';
|
|
33
|
+
env?: NodeJS.ProcessEnv;
|
|
34
|
+
}) => Promise<string>;
|
|
35
|
+
/** npm 全局安装前缀(`npm prefix -g`);供不依赖 PATH 的检测/调用锚定包位置 */
|
|
36
|
+
export declare function npmGlobalPrefix(timeoutMs?: number): Promise<string>;
|
|
37
|
+
/** 弃掉前缀缓存(安装成功后调用;测试用同一入口重置) */
|
|
38
|
+
export declare function resetNpmGlobalPrefixCache(): void;
|
|
39
|
+
/**
|
|
40
|
+
* 检测 lark-cli 是否已安装 + 版本。**多路兜底,任一命中即已安装**(顺序固定,全部不依赖调用方的 PATH):
|
|
41
|
+
* ① `lark-cli` 直接调用(快路径:PATH 正常时一次到位,含非默认安装位置)
|
|
42
|
+
* ② npm 全局前缀下的包内入口 `scripts/run.js`(主力兜底:绕开 PATH,锁定本机真实安装)
|
|
43
|
+
* ③ `npm ls -g @larksuite/cli --json`(最后兜底:包在但入口跑不起来时仍能给出已装 + 版本)
|
|
44
|
+
* 历史教训:旧实现只有 ①,PATH 查不到就误报「未安装」,前端据此给出安装按钮,
|
|
45
|
+
* 用户点了反而撞上 npm 重装的文件锁(EBUSY)——已安装的 CLI 被误判成裸机。
|
|
46
|
+
*/
|
|
47
|
+
export declare function detectLarkCli(timeoutMs?: number, runner?: ExecRunner, getPrefix?: () => Promise<string>): Promise<LarkCliDetect>;
|
|
48
|
+
/** 纯函数(可测):win32 上 npm 就地重装全局包被文件锁挡住的瞬时错误——退避重试可自愈 */
|
|
49
|
+
export declare function isTransientNpmLockError(message: string): boolean;
|
|
50
|
+
/** install 的重试参数(测试注入 attempts=1 + 零退避即可关掉重试) */
|
|
51
|
+
export interface InstallRetryOpts {
|
|
52
|
+
attempts?: number;
|
|
53
|
+
delaysMs?: number[];
|
|
54
|
+
/** 覆盖 npm 执行(测试注入用);缺省真实 runNpm */
|
|
55
|
+
runNpmFn?: (args: string[], timeoutMs: number) => Promise<string>;
|
|
56
|
+
sleep?: (ms: number) => Promise<void>;
|
|
57
|
+
log?: (msg: string) => void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* npm install -g @larksuite/cli(安装与升级同一命令);返回 npm 输出。
|
|
61
|
+
*
|
|
62
|
+
* win32 下「就地升级」要先 rename 旧目录再解包,杀毒实时扫描 / 并发 npm / 刚跑过的
|
|
63
|
+
* lark-cli 进程都可能瞬时锁住该目录 → EBUSY。实测该场景下 rename 未留下任何残留、
|
|
64
|
+
* 旧版本毫发无伤,只是这一次没换成——故对**锁类错误**退避重试(共 3 次,1.5s / 3s);
|
|
65
|
+
* 网络/404 等确定性失败立即抛出,不浪费用户时间。
|
|
66
|
+
*/
|
|
67
|
+
export declare function installLarkCli(timeoutMs?: number, opts?: InstallRetryOpts): Promise<string>;
|
|
68
|
+
/** npm view 查询最新版本(页面「有新版本」提示用) */
|
|
69
|
+
export declare function checkLarkCliLatest(timeoutMs?: number): Promise<string>;
|
|
70
|
+
/** 纯函数(可测):skill 目录名是否为飞书系 SKILL(feishu / lark 子串均命中) */
|
|
71
|
+
export declare function isFeishuSkillDirName(name: string): boolean;
|
|
72
|
+
export interface LarkCliSkillDetect {
|
|
73
|
+
installed: boolean;
|
|
74
|
+
/** 命中的 skill 目录名(首个) */
|
|
75
|
+
name?: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 检测飞书官方 SKILL 是否已装(默认 ~/.claude/skills,与安装动作同源)。
|
|
79
|
+
* 判据:目录名命中 feishu/lark **且** 内含 SKILL.md(防同名散目录误报)。
|
|
80
|
+
* managed 会话的可见性由 bridgeUserSkills() 启动桥接保证,这里不查托管目录。
|
|
81
|
+
*/
|
|
82
|
+
export declare function detectLarkCliSkill(skillsDir?: string, fs?: {
|
|
83
|
+
exists(p: string): boolean;
|
|
84
|
+
readdir(d: string): string[];
|
|
85
|
+
}): Promise<LarkCliSkillDetect>;
|
|
86
|
+
export interface InstallSkillOpts {
|
|
87
|
+
/** 覆盖 npx 执行(测试注入);缺省真实 runNpx */
|
|
88
|
+
runNpxFn?: (args: string[], timeoutMs: number) => Promise<string>;
|
|
89
|
+
/** 装好后复扫的目标目录(测试注入用) */
|
|
90
|
+
skillsDir?: string;
|
|
91
|
+
log?: (msg: string) => void;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* 安装飞书官方 SKILL(`npx skills add`,落盘 ~/.claude/skills):
|
|
95
|
+
* - `--copy` 必须——skills CLI 默认 symlink,Windows 上需开发者模式/管理员权限,必挂;
|
|
96
|
+
* - 装完复扫确认落盘,扫不到视为失败(npx 静默空转的场景不能谎报成功);
|
|
97
|
+
* - **不做任何拷贝**:managed 会话由既有 bridgeUserSkills() 在 lcb start 时 junction 桥接,
|
|
98
|
+
* 装完需重启桥接器生效。
|
|
99
|
+
*/
|
|
100
|
+
export declare function installLarkCliSkill(timeoutMs?: number, opts?: InstallSkillOpts): Promise<string>;
|
|
101
|
+
/**
|
|
102
|
+
* 纯函数(可测):授权状态是否为「应用未配置」——决定概览页给「配置应用」还是「去终端授权」。
|
|
103
|
+
* detail 的两个来源(error.subtype / reason)实测均含 not_configured 字样。
|
|
104
|
+
*/
|
|
105
|
+
export declare function needsLarkCliConfig(auth: LarkCliAuthStatus): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* 核心编排(依赖注入可测):已装 → 直接返回;未装 → install → 复检;
|
|
108
|
+
* install 抛错 → warn 后返回未装态,**绝不抛出**(桥接器启动不能被外部工具安装失败拖垮)
|
|
109
|
+
*/
|
|
110
|
+
export declare function ensureLarkCliFlow(deps: {
|
|
111
|
+
detect(): Promise<LarkCliDetect>;
|
|
112
|
+
install(log?: (msg: string) => void): Promise<string>;
|
|
113
|
+
log?: (msg: string) => void;
|
|
114
|
+
}): Promise<LarkCliDetect>;
|
|
115
|
+
/** 生产入口:console 反馈([lark-cli] 前缀),后台异步调用(lcb start 里 void + catch) */
|
|
116
|
+
export declare function ensureLarkCli(): Promise<LarkCliDetect>;
|
|
117
|
+
export type LarkCliAuthState = 'authorized' | 'unauthorized' | 'unknown';
|
|
118
|
+
export interface LarkCliAuthStatus {
|
|
119
|
+
state: LarkCliAuthState;
|
|
120
|
+
/** 未授权的原因(error.subtype / message / reason),供 UI 悬浮提示 */
|
|
121
|
+
detail?: string;
|
|
122
|
+
/** 已授权时的可读身份(账号名 / 邮箱) */
|
|
123
|
+
identity?: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 纯函数(可测):取文本里第一个**大括号平衡**的 JSON 对象。
|
|
127
|
+
* lark-cli 的输出前后可能夹日志,且未授权时整个 JSON 走 stderr——两个流都要能扫。
|
|
128
|
+
*/
|
|
129
|
+
export declare function firstJsonObject(text: string): unknown;
|
|
130
|
+
/**
|
|
131
|
+
* 纯函数(可测):从 auth status 的原始输出判定登录态。
|
|
132
|
+
*
|
|
133
|
+
* 两个**实测**陷阱(都不可靠地凭直觉推导):
|
|
134
|
+
* ① 未授权时 JSON 写在 **stderr**、退出码 **3**、stdout 空 —— 判据绝不能看退出码;
|
|
135
|
+
* ② `auth list` 未登录时返回 `{ok:true, reason:"not_configured", users:[]}` ——
|
|
136
|
+
* `ok:true` 不等于已授权,必须找正向证据(users 非空)。
|
|
137
|
+
*
|
|
138
|
+
* 反向误判同样有害:解析不出来时退 **unknown** 而非 unauthorized ——
|
|
139
|
+
* 把「不知道」说成「未授权」会让用户白跑一趟终端。
|
|
140
|
+
*/
|
|
141
|
+
export declare function parseLarkCliAuth(raw: {
|
|
142
|
+
stdout: string;
|
|
143
|
+
stderr: string;
|
|
144
|
+
code: number | null;
|
|
145
|
+
}): LarkCliAuthStatus;
|
|
146
|
+
export type AuthRunner = (file: string, args: string[], opts: {
|
|
147
|
+
timeout: number;
|
|
148
|
+
windowsHide: boolean;
|
|
149
|
+
encoding: 'utf8';
|
|
150
|
+
env?: NodeJS.ProcessEnv;
|
|
151
|
+
cwd?: string;
|
|
152
|
+
}) => Promise<{
|
|
153
|
+
stdout: string;
|
|
154
|
+
stderr: string;
|
|
155
|
+
code: number | null;
|
|
156
|
+
}>;
|
|
157
|
+
/** 双流捕获。字符串 code(ENOENT/EACCES)才算「没跑起来」→ reject;数字退出码一律 resolve 交给解析 */
|
|
158
|
+
export declare const defaultAuthRunner: AuthRunner;
|
|
159
|
+
/**
|
|
160
|
+
* 探测授权状态(纯本地,约百毫秒级——页面轮询靠它,因此**不加 `--verify`**:那需要联网)。
|
|
161
|
+
* 命令跑不起来时退到 node + 包内入口,与 detectLarkCli 第 ② 路同源。
|
|
162
|
+
*/
|
|
163
|
+
export declare function checkLarkCliAuth(timeoutMs?: number, runner?: AuthRunner): Promise<LarkCliAuthStatus>;
|
|
164
|
+
/**
|
|
165
|
+
* 纯函数(可测):剥掉 ANSI SGR 序列与 BOM。
|
|
166
|
+
* `--json` 理论上不带色,但 lark-cli changelog #169「Correct URL formatting in login --no-wait
|
|
167
|
+
* output」说明这个位置历史上出过 URL 格式事故;ANSI 混进 JSON 字符串会直接毁掉 JSON.parse。
|
|
168
|
+
*/
|
|
169
|
+
export declare function stripAnsiAndBom(text: string): string;
|
|
170
|
+
export interface LarkCliDeviceStart {
|
|
171
|
+
/** ★ 只进内存,绝不出 HTTP */
|
|
172
|
+
deviceCode: string;
|
|
173
|
+
verificationUrl: string;
|
|
174
|
+
/** 人可读短码(手输兜底);实测无独立字段,从 URL 的 query 里取 */
|
|
175
|
+
userCode?: string;
|
|
176
|
+
expiresInSec: number;
|
|
177
|
+
intervalSec: number;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 纯函数(可测):解析 `auth login --no-wait --json` 的输出。
|
|
181
|
+
*
|
|
182
|
+
* **实测形状(v1.0.96)——平铺,没有 ok/data 信封**,与 lark-cli README 的「JSON Output Contract」
|
|
183
|
+
* 不一致(该契约显然不覆盖本命令):
|
|
184
|
+
* {"device_code":"…","expires_in":600,"hint":"…",
|
|
185
|
+
* "verification_url":"https://accounts.feishu.cn/oauth/v1/device/verify?flow_id=…&user_code=WAFK-BYM3"}
|
|
186
|
+
* 注意实测**没有** interval、也**没有**独立的 user_code 字段(只在 URL 的 query 里)。
|
|
187
|
+
* 解析器仍对文件级信封与 verification_uri 命名做兼容,不赌单一形状。
|
|
188
|
+
*
|
|
189
|
+
* deviceCode 或 URL 任一缺失即失败——半成品会让前端显示一个扫了没反应的二维码,
|
|
190
|
+
* 比直接报错难排查十倍。
|
|
191
|
+
*/
|
|
192
|
+
export declare function parseLarkCliDeviceStart(raw: {
|
|
193
|
+
stdout: string;
|
|
194
|
+
stderr: string;
|
|
195
|
+
code: number | null;
|
|
196
|
+
}): {
|
|
197
|
+
ok: true;
|
|
198
|
+
value: LarkCliDeviceStart;
|
|
199
|
+
} | {
|
|
200
|
+
ok: false;
|
|
201
|
+
error: string;
|
|
202
|
+
};
|
|
203
|
+
export interface LarkCliDeviceOutcome {
|
|
204
|
+
phase: 'done' | 'failed' | 'expired';
|
|
205
|
+
identity?: string;
|
|
206
|
+
error?: string;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* 纯函数(可测):收尾进程结束后判定本次设备流的结果。
|
|
210
|
+
*
|
|
211
|
+
* **这是整个设备流最容易出错的地方**:已授权用户点「重新授权」再扫一次码时,
|
|
212
|
+
* checkAuth() 前后都是 authorized——**状态探测无法区分「本来就好」与「本次扫码完成」**。
|
|
213
|
+
* 唯一可靠的正向信号是收尾进程的退出码。
|
|
214
|
+
*
|
|
215
|
+
* 正向兜底可以有(未授权 → 已授权的跃迁必然意味着本次扫码成功),
|
|
216
|
+
* 但**反向兜底绝不能有**:wasAuthorized=true 且 exit≠0 时必须 failed,
|
|
217
|
+
* 否则会把「本来就已授权」误报成「本次扫码成功」——已授权用户一打开弹窗就会看到
|
|
218
|
+
* "✅ 授权完成",而他其实什么都没扫。
|
|
219
|
+
*/
|
|
220
|
+
export declare function decideDeviceFinishOutcome(a: {
|
|
221
|
+
exitCode: number | null;
|
|
222
|
+
stdout: string;
|
|
223
|
+
stderr: string;
|
|
224
|
+
wasAuthorized: boolean;
|
|
225
|
+
authAfter?: LarkCliAuthStatus;
|
|
226
|
+
}): LarkCliDeviceOutcome;
|
|
227
|
+
export type LarkCliDeviceState = 'pending' | 'done' | 'failed' | 'expired' | 'none';
|
|
228
|
+
export interface LarkCliDeviceSessionInfo {
|
|
229
|
+
ok: boolean;
|
|
230
|
+
state?: LarkCliDeviceState;
|
|
231
|
+
verificationUrl?: string;
|
|
232
|
+
/** 仅 start 返回(status 每 2s 轮询,不重复传几 KB 图) */
|
|
233
|
+
qrDataUrl?: string;
|
|
234
|
+
userCode?: string;
|
|
235
|
+
/** 每次现算的剩余秒数 */
|
|
236
|
+
expiresInSec?: number;
|
|
237
|
+
intervalSec?: number;
|
|
238
|
+
reused?: boolean;
|
|
239
|
+
identity?: string;
|
|
240
|
+
error?: string;
|
|
241
|
+
/** 未装 / 未配置——让前端把用户导到对应入口而不是干瞪眼 */
|
|
242
|
+
hint?: 'install' | 'config';
|
|
243
|
+
}
|
|
244
|
+
/** 二维码临时目录(与 terminal-window.ts 的 tmp 用法同源) */
|
|
245
|
+
export declare function larkCliQrDir(tmpDir?: string): string;
|
|
246
|
+
/** 内存态查询(零副作用、亚毫秒)——撑住前端 2s 轮询 */
|
|
247
|
+
export declare function getLarkCliDeviceStatus(now?: number): LarkCliDeviceSessionInfo;
|
|
248
|
+
/**
|
|
249
|
+
* 放弃当前会话(改用终端 / 新一轮发起前)。
|
|
250
|
+
* **不 kill 子进程**:Windows 上 execFile('cmd', …) 的进程树是 cmd → node → lark-cli.exe,
|
|
251
|
+
* kill 直接子进程往往留下孤儿。靠 gen 失配丢弃结果 + execFile 的 timeout 自灭即可——
|
|
252
|
+
* 孤儿最多空转到 device code 过期后自行退出。
|
|
253
|
+
*/
|
|
254
|
+
export declare function abandonLarkCliDeviceSession(): void;
|
|
255
|
+
/** 重置编排 + 设备流状态(测试用) */
|
|
256
|
+
export declare function resetLarkCliDeviceState(): void;
|
|
257
|
+
/**
|
|
258
|
+
* 纯函数(可测):cmd.exe 下的参数转义。
|
|
259
|
+
*
|
|
260
|
+
* **这不是洁癖,是实测踩出来的**:verification_url 必然含 `&`(`?flow_id=…&user_code=…`),
|
|
261
|
+
* 而 `cmd /c lark-cli … <url>` 会把 `&` 当成**命令分隔符**,命令被截断成两条,
|
|
262
|
+
* 二维码文件压根不生成(只留一个莫名其妙的 ENOENT)。
|
|
263
|
+
* 注意:Node 只在参数含空格/制表符时才加引号,飞书 URL 不含空格,所以 `&` 是裸奔到 cmd 的。
|
|
264
|
+
*/
|
|
265
|
+
export declare function cmdEscapeArg(s: string): string;
|
|
266
|
+
/**
|
|
267
|
+
* 生成二维码 data URL。失败返回 undefined——**二维码只是展示层**,生成不出来就降级为
|
|
268
|
+
* 只显示可复制链接,设备流照常进行。
|
|
269
|
+
* cwd 设为专用 tmp 子目录:lark-cli 的写路径允许根是 cwd / /tmp / ~/files(实测 cwd 生效),
|
|
270
|
+
* 故 -o 用相对名即可落进允许根。
|
|
271
|
+
*/
|
|
272
|
+
export declare function defaultMakeQr(url: string, runner?: AuthRunner, log?: (m: string) => void, tmpDir?: string): Promise<string | undefined>;
|
|
273
|
+
export interface LarkCliDeviceDeps {
|
|
274
|
+
runner: AuthRunner;
|
|
275
|
+
finishRunner: AuthRunner;
|
|
276
|
+
detect(): Promise<LarkCliDetect>;
|
|
277
|
+
checkAuth(): Promise<LarkCliAuthStatus>;
|
|
278
|
+
makeQr(url: string): Promise<string | undefined>;
|
|
279
|
+
now(): number;
|
|
280
|
+
log(msg: string): void;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* 发起设备流授权(页面二维码的主入口)。
|
|
284
|
+
*
|
|
285
|
+
* 四道闸挡住「每点一次就多一个 flow」:
|
|
286
|
+
* ① 幂等复用:未过期的 pending 会话直接返回同一个 URL(挡住刷新页面 / 关弹窗再开)
|
|
287
|
+
* ② in-flight 合并:并发调用 await 同一个 promise(挡住双击)
|
|
288
|
+
* ③ regenerate:用户显式要求时才新建
|
|
289
|
+
* ④ gen 代号:新建时 +1,在飞的老收尾进程靠它丢弃过期结果
|
|
290
|
+
*/
|
|
291
|
+
export declare function startLarkCliDeviceAuth(opts?: {
|
|
292
|
+
regenerate?: boolean;
|
|
293
|
+
deps?: Partial<LarkCliDeviceDeps>;
|
|
294
|
+
}): Promise<LarkCliDeviceSessionInfo>;
|
|
295
|
+
export type LarkCliOp = 'install' | 'update' | 'auth' | 'config' | 'skill';
|
|
296
|
+
export interface LarkCliActionResult {
|
|
297
|
+
ok: boolean;
|
|
298
|
+
/** 已有操作在进行 / 刚拉起过终端 */
|
|
299
|
+
busy?: boolean;
|
|
300
|
+
mode: 'terminal' | 'silent' | 'none';
|
|
301
|
+
terminal?: string;
|
|
302
|
+
scriptPath?: string;
|
|
303
|
+
output?: string;
|
|
304
|
+
/** 为何没用终端(降级说明,前端展示用) */
|
|
305
|
+
reason?: string;
|
|
306
|
+
error?: string;
|
|
307
|
+
}
|
|
308
|
+
/** 重置编排状态(测试用)。进程内单例:并发 npm 必撞 Windows 文件锁,这里必须互斥 */
|
|
309
|
+
export declare function resetLarkCliActionState(): void;
|
|
310
|
+
export interface LarkCliActionDeps {
|
|
311
|
+
detect(): Promise<LarkCliDetect>;
|
|
312
|
+
install(): Promise<string>;
|
|
313
|
+
/** SKILL 静默安装(op:'skill');缺省真实 installLarkCliSkill */
|
|
314
|
+
installSkill(): Promise<string>;
|
|
315
|
+
/** 授权/配置态探测:config op 用它拒绝重复向导;install op 用它决定脚本是否插 config init 段 */
|
|
316
|
+
checkAuth(): Promise<LarkCliAuthStatus>;
|
|
317
|
+
launch(task: TerminalTask, opts?: {
|
|
318
|
+
needConfig?: boolean;
|
|
319
|
+
}): Promise<LaunchTerminalResult>;
|
|
320
|
+
now(): number;
|
|
321
|
+
log(msg: string): void;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* 安装/更新/授权/配置/SKILL 五条动作的统一编排。
|
|
325
|
+
*
|
|
326
|
+
* - install / update:优先拉起终端(用户能看见 npm 输出并顺势完成配置与授权);
|
|
327
|
+
* 拉不起终端(SSH / 无桌面)则降级静默安装,`reason` 带回降级原因。
|
|
328
|
+
* - auth / config:**不降级** —— 交互式向导没有静默等价物,拉不起终端就如实报错。
|
|
329
|
+
* config 额外要求当前确属「未配置」态(needsLarkCliConfig),已配置时拒绝重复向导。
|
|
330
|
+
* - skill:静默安装(npx skills add,无交互),不拉终端;失败仅返回错误不抛出。
|
|
331
|
+
*
|
|
332
|
+
* 互斥覆盖「探测 + 拉起」的亚秒窗口;终端存活期由 10s 冷却兜(否则用户 3 分钟后
|
|
333
|
+
* 想再授权会被自己锁死)。
|
|
334
|
+
*/
|
|
335
|
+
export declare function runLarkCliActionFlow(op: LarkCliOp, deps?: Partial<LarkCliActionDeps>): Promise<LarkCliActionResult>;
|
|
336
|
+
export {};
|