botmux 3.9.0 → 3.9.2
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/dist/.runtime-build-id +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +7 -0
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +20 -0
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/backend/types.d.ts +12 -0
- package/dist/adapters/backend/types.d.ts.map +1 -1
- package/dist/adapters/backend/types.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +40 -7
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/traex.d.ts.map +1 -1
- package/dist/adapters/cli/traex.js +87 -87
- package/dist/adapters/cli/traex.js.map +1 -1
- package/dist/cli/deferred-topic-send.d.ts +11 -0
- package/dist/cli/deferred-topic-send.d.ts.map +1 -1
- package/dist/cli/deferred-topic-send.js +21 -4
- package/dist/cli/deferred-topic-send.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +177 -38
- package/dist/cli.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +40 -1
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dispatch.d.ts +43 -5
- package/dist/core/dispatch.d.ts.map +1 -1
- package/dist/core/dispatch.js +104 -6
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/passthrough-commands.d.ts.map +1 -1
- package/dist/core/passthrough-commands.js +1 -1
- package/dist/core/passthrough-commands.js.map +1 -1
- package/dist/daemon.d.ts +11 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +32 -3
- package/dist/daemon.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +2 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +2 -0
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +9 -0
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/issue-card.d.ts +223 -0
- package/dist/im/lark/issue-card.d.ts.map +1 -0
- package/dist/im/lark/issue-card.js +542 -0
- package/dist/im/lark/issue-card.js.map +1 -0
- package/dist/im/lark/issue-command-deps.d.ts +41 -0
- package/dist/im/lark/issue-command-deps.d.ts.map +1 -0
- package/dist/im/lark/issue-command-deps.js +195 -0
- package/dist/im/lark/issue-command-deps.js.map +1 -0
- package/dist/im/lark/issue-command.d.ts +137 -0
- package/dist/im/lark/issue-command.d.ts.map +1 -0
- package/dist/im/lark/issue-command.js +335 -0
- package/dist/im/lark/issue-command.js.map +1 -0
- package/dist/platform/issue-client.d.ts +201 -0
- package/dist/platform/issue-client.d.ts.map +1 -0
- package/dist/platform/issue-client.js +142 -0
- package/dist/platform/issue-client.js.map +1 -0
- package/dist/platform/platform-http.d.ts +4 -0
- package/dist/platform/platform-http.d.ts.map +1 -1
- package/dist/platform/platform-http.js +38 -2
- package/dist/platform/platform-http.js.map +1 -1
- package/dist/services/codex-composer-state.d.ts +27 -0
- package/dist/services/codex-composer-state.d.ts.map +1 -0
- package/dist/services/codex-composer-state.js +53 -0
- package/dist/services/codex-composer-state.js.map +1 -0
- package/dist/services/codex-transcript.d.ts +33 -12
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js +82 -20
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/issue-board-store.d.ts +214 -0
- package/dist/services/issue-board-store.d.ts.map +1 -0
- package/dist/services/issue-board-store.js +472 -0
- package/dist/services/issue-board-store.js.map +1 -0
- package/dist/services/issue-claim-flow.d.ts +160 -0
- package/dist/services/issue-claim-flow.d.ts.map +1 -0
- package/dist/services/issue-claim-flow.js +222 -0
- package/dist/services/issue-claim-flow.js.map +1 -0
- package/dist/services/issue-outbox-pump.d.ts +25 -0
- package/dist/services/issue-outbox-pump.d.ts.map +1 -0
- package/dist/services/issue-outbox-pump.js +102 -0
- package/dist/services/issue-outbox-pump.js.map +1 -0
- package/dist/services/issue-release.d.ts +78 -0
- package/dist/services/issue-release.d.ts.map +1 -0
- package/dist/services/issue-release.js +89 -0
- package/dist/services/issue-release.js.map +1 -0
- package/dist/services/issue-report.d.ts +72 -0
- package/dist/services/issue-report.d.ts.map +1 -0
- package/dist/services/issue-report.js +84 -0
- package/dist/services/issue-report.js.map +1 -0
- package/dist/services/issue-status-view.d.ts +52 -0
- package/dist/services/issue-status-view.d.ts.map +1 -0
- package/dist/services/issue-status-view.js +42 -0
- package/dist/services/issue-status-view.js.map +1 -0
- package/dist/services/issue-status-writer.d.ts +98 -0
- package/dist/services/issue-status-writer.d.ts.map +1 -0
- package/dist/services/issue-status-writer.js +123 -0
- package/dist/services/issue-status-writer.js.map +1 -0
- package/dist/services/traex-paths.d.ts +14 -2
- package/dist/services/traex-paths.d.ts.map +1 -1
- package/dist/services/traex-paths.js +16 -2
- package/dist/services/traex-paths.js.map +1 -1
- package/dist/services/traex-transcript.d.ts +33 -0
- package/dist/services/traex-transcript.d.ts.map +1 -1
- package/dist/services/traex-transcript.js +135 -28
- package/dist/services/traex-transcript.js.map +1 -1
- package/dist/setup/lark-scopes.json +0 -2
- package/dist/worker.js +269 -7
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issue Board 卡片:`/issue` 的飞书原生入口。
|
|
3
|
+
*
|
|
4
|
+
* 三个视图,同一张卡片就地切换(不新发消息,避免刷屏):
|
|
5
|
+
* 看板 board → 点「领取」→ 确认 confirm(选仓库)→ 点「确认领取」→ 结果 result
|
|
6
|
+
*
|
|
7
|
+
* 领取由**你 @ 的那个 bot** 承接:`larkAppId` 就是承接方,不需要再选。想让别的 bot 干,
|
|
8
|
+
* 就去 @ 它发 `/issue`。少一次选择,语义也天然。
|
|
9
|
+
*
|
|
10
|
+
* 仓库不新造配置:候选来自 `scanMultipleProjects(configuredWorkingDirs(bot))` —— 现有仓库
|
|
11
|
+
* 选择卡片用的同一套扫描。注意**不能**直接用 `workingDirs` 原值:实测发现它常常配的是一个
|
|
12
|
+
* 工作区父目录(`~/claude-code-workspace`)而不是仓库列表,直接拿来当候选,选中的会是工作区
|
|
13
|
+
* 根目录,等于让 agent 在错误的位置动手。扫描一层才拿得到真正的仓库和 worktree。
|
|
14
|
+
*
|
|
15
|
+
* 平台只存展示用的 `targetRepoLabel`,这里按仓库名做一次匹配把它预选上,匹配不上就让人在
|
|
16
|
+
* 下拉里挑——不拦人,也不猜。
|
|
17
|
+
*
|
|
18
|
+
* Security(沿用 groups-card 的约定):
|
|
19
|
+
* - `action.value` 不经 Lark 校验,**绝不**从里面读身份字段;调用者身份只认 operator.*
|
|
20
|
+
* - 权限门在命令入口和每次回调都要跑一遍
|
|
21
|
+
*
|
|
22
|
+
* 只吃纯数据,不反向依赖 store / platform client,避免循环依赖。
|
|
23
|
+
*/
|
|
24
|
+
export const ISSUE_ACTION_REFRESH = 'issue_refresh';
|
|
25
|
+
export const ISSUE_ACTION_PAGE = 'issue_page';
|
|
26
|
+
export const ISSUE_ACTION_TEAM = 'issue_team';
|
|
27
|
+
export const ISSUE_ACTION_CLAIM_OPEN = 'issue_claim_open';
|
|
28
|
+
export const ISSUE_ACTION_CLAIM_DIR = 'issue_claim_dir';
|
|
29
|
+
export const ISSUE_ACTION_CLAIM_CONFIRM = 'issue_claim_confirm';
|
|
30
|
+
export const ISSUE_ACTION_CLAIM_CANCEL = 'issue_claim_cancel';
|
|
31
|
+
/** 一页放几条。看板是给人扫的,多了反而看不动;和 groups-card 保持一致。 */
|
|
32
|
+
const PAGE_SIZE = 5;
|
|
33
|
+
/** 「需要关注」最多铺几条。见 buildIssueBoardCard 里为什么必须封顶。 */
|
|
34
|
+
const ATTENTION_PREVIEW = 3;
|
|
35
|
+
/** Lark 的 select_static 选项数上限(与 groups-card 的 JUMP_PAGE_MAX_OPTIONS 同源)。
|
|
36
|
+
* 实测一个工作区能扫出 58 个仓库/worktree,不截断会直接超限。 */
|
|
37
|
+
const MAX_REPO_OPTIONS = 50;
|
|
38
|
+
/**
|
|
39
|
+
* 把平台的展示标签匹配到本机某个仓库,返回它的路径。
|
|
40
|
+
*
|
|
41
|
+
* 平台只有 `targetRepoLabel`("botmux"、"botmux 平台"…),是给人看的,没有路径。这里做的
|
|
42
|
+
* 是**预选**不是决定:匹配上就把下拉默认值设好省一次点击,匹配不上返回 undefined,让人自己
|
|
43
|
+
* 在下拉里挑。刻意不做模糊匹配——猜错仓库会让 agent 在错误的地方动手,代价远大于多点一下。
|
|
44
|
+
*
|
|
45
|
+
* 优先精确命中仓库名,再退一步允许去掉空格/下划线/连字符后相等("botmux 平台" 这种带空格
|
|
46
|
+
* 的标签能对上 `botmux-platform`)。前缀不算命中:`bot` 不该选中 `botmux`。
|
|
47
|
+
*/
|
|
48
|
+
export function matchRepo(label, repos) {
|
|
49
|
+
if (!label)
|
|
50
|
+
return undefined;
|
|
51
|
+
const want = label.trim().toLowerCase();
|
|
52
|
+
if (!want)
|
|
53
|
+
return undefined;
|
|
54
|
+
const exact = repos.find((r) => r.name.toLowerCase() === want);
|
|
55
|
+
if (exact)
|
|
56
|
+
return exact.path;
|
|
57
|
+
const norm = (s) => s.replace(/[\s_-]+/g, '');
|
|
58
|
+
return repos.find((r) => norm(r.name.toLowerCase()) === norm(want))?.path;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 按与标签的相关度给候选仓库排序并截断到 Lark 的选项上限。
|
|
62
|
+
*
|
|
63
|
+
* 与 {@link matchRepo} 分工明确:那个决定**选中谁**(严格,宁缺毋滥),这个只决定**先显示
|
|
64
|
+
* 谁**(宽松,含子串即可)。排序永远不会替人做选择,所以这里放宽是安全的——而不放宽的话,
|
|
65
|
+
* 标签没精确命中时人得在几十个仓库里自己翻,实测一个工作区能扫出 58 个。
|
|
66
|
+
*
|
|
67
|
+
* 截断是必要的:超过上限 Lark 会拒绝或静默丢弃。被截掉的部分由调用方在卡片上说明,
|
|
68
|
+
* 不能让人以为"没有就是不存在"。
|
|
69
|
+
*/
|
|
70
|
+
export function rankRepos(label, repos, limit = MAX_REPO_OPTIONS) {
|
|
71
|
+
const want = (label ?? '').trim().toLowerCase();
|
|
72
|
+
const norm = (s) => s.replace(/[\s_-]+/g, '');
|
|
73
|
+
const score = (r) => {
|
|
74
|
+
if (!want)
|
|
75
|
+
return 3;
|
|
76
|
+
const n = r.name.toLowerCase();
|
|
77
|
+
if (n === want)
|
|
78
|
+
return 0;
|
|
79
|
+
if (norm(n) === norm(want))
|
|
80
|
+
return 1;
|
|
81
|
+
if (norm(n).includes(norm(want)) || norm(want).includes(norm(n)))
|
|
82
|
+
return 2;
|
|
83
|
+
return 3;
|
|
84
|
+
};
|
|
85
|
+
const sorted = [...repos].sort((a, b) => {
|
|
86
|
+
const d = score(a) - score(b);
|
|
87
|
+
return d !== 0 ? d : a.name.localeCompare(b.name);
|
|
88
|
+
});
|
|
89
|
+
return { options: sorted.slice(0, limit), truncated: Math.max(0, sorted.length - limit) };
|
|
90
|
+
}
|
|
91
|
+
function h(content) {
|
|
92
|
+
return { tag: 'div', text: { tag: 'lark_md', content } };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* lark_md 文本位消毒。issue 的标题/正文/仓库标签都是**人在平台上自由填的**,直接拼进
|
|
96
|
+
* lark_md 会被标签与强调语法击穿:一个 `<font>` 或 `</font><at …>` 就能改掉整张卡的观感,
|
|
97
|
+
* 一个落单的反引号能让后面半张卡变成代码块。
|
|
98
|
+
*
|
|
99
|
+
* 转义顺序抄 [[brand-template]] 的 `safeText`(那是仓库里唯一做对的一份):**反斜杠必须最先**
|
|
100
|
+
* ——否则 `\*` 里的反斜杠自成偶数对,让紧跟的 `*` 重新变回有效强调。groups-card 等 5 处旧
|
|
101
|
+
* 拷贝都缺这一步,这里不跟着抄错。
|
|
102
|
+
*/
|
|
103
|
+
export function escapeLarkMd(s) {
|
|
104
|
+
return s
|
|
105
|
+
.replace(/[\r\n]+/g, ' ')
|
|
106
|
+
.replace(/\\/g, '\\\\')
|
|
107
|
+
.replace(/&/g, '&')
|
|
108
|
+
.replace(/</g, '<')
|
|
109
|
+
.replace(/>/g, '>')
|
|
110
|
+
.replace(/([*_~`])/g, '\\$1');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* 行内代码块的安全渲染。
|
|
114
|
+
*
|
|
115
|
+
* **不能**拿 `escapeLarkMd` 往代码块里塞:它给 `_` `*` 这些加反斜杠,而反斜杠在代码块里是
|
|
116
|
+
* **字面量**——`iss_f93d7d54…` 会显示成 `iss\_f93d7d54…`,人照着复制走的是错的任务 id。
|
|
117
|
+
* 代码块里唯一能击穿它的是反引号本身(换行同理,会把块撑破),去掉这两样就够。
|
|
118
|
+
*/
|
|
119
|
+
function code(s) {
|
|
120
|
+
return `\`${s.replace(/[`\r\n]+/g, '')}\``;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 按**显示宽度**截断(CJK 算两列),不是按字符数。
|
|
124
|
+
*
|
|
125
|
+
* 按 `length` 截会让中英文两种标题在卡片上宽窄差一倍:30 个汉字铺满两行,30 个字母才半行。
|
|
126
|
+
* 看板每行右边还挂着「领取」按钮,正文列本来就窄,超了就换行、按钮被挤到下一行,一排下来
|
|
127
|
+
* 参差不齐。
|
|
128
|
+
*/
|
|
129
|
+
export function truncateDisplay(s, maxWidth) {
|
|
130
|
+
const width = (ch) => (/[ᄀ-ᅟ⺀-가-힣豈-︰--⦆¢-₩]/.test(ch) ? 2 : 1);
|
|
131
|
+
let w = 0;
|
|
132
|
+
let out = '';
|
|
133
|
+
for (const ch of s) {
|
|
134
|
+
const cw = width(ch);
|
|
135
|
+
if (w + cw > maxWidth)
|
|
136
|
+
return `${out}…`;
|
|
137
|
+
w += cw;
|
|
138
|
+
out += ch;
|
|
139
|
+
}
|
|
140
|
+
return out;
|
|
141
|
+
}
|
|
142
|
+
/** 标题在看板行里的最大显示宽度。右边挂着「领取」按钮,正文列没有整行那么宽。 */
|
|
143
|
+
const BOARD_TITLE_WIDTH = 34;
|
|
144
|
+
/** 仓库标签的最大显示宽度。它是次要信息,不该跟标题抢地方。 */
|
|
145
|
+
const REPO_LABEL_WIDTH = 20;
|
|
146
|
+
/**
|
|
147
|
+
* 仓库标签的呈现:灰色小字,不是反引号包的行内代码。
|
|
148
|
+
*
|
|
149
|
+
* 行内代码在飞书里是带底色的等宽块,视觉重量比标题还大——一眼看过去先看到仓库名再看到任务,
|
|
150
|
+
* 主次颠倒。灰字是本仓卡片里次要元信息的既有写法(见 groups-card 的 chatId/appId 后缀)。
|
|
151
|
+
*/
|
|
152
|
+
function repoTag(label) {
|
|
153
|
+
return ` <font color="grey">${escapeLarkMd(truncateDisplay(label, REPO_LABEL_WIDTH))}</font>`;
|
|
154
|
+
}
|
|
155
|
+
function pageOf(rows, page) {
|
|
156
|
+
const pages = Math.max(1, Math.ceil(rows.length / PAGE_SIZE));
|
|
157
|
+
const p = Math.min(Math.max(0, page), pages - 1);
|
|
158
|
+
return { slice: rows.slice(p * PAGE_SIZE, p * PAGE_SIZE + PAGE_SIZE), page: p, pages };
|
|
159
|
+
}
|
|
160
|
+
/** 看板视图。只有「待领取」列出可操作的行,其余段给计数——卡片要能一眼扫完。 */
|
|
161
|
+
export function buildIssueBoardCard(data, _locale) {
|
|
162
|
+
const s = data.sections;
|
|
163
|
+
const { slice, page, pages } = pageOf(s.todo, data.page);
|
|
164
|
+
const elements = [];
|
|
165
|
+
elements.push(h(`**📋 ${data.teamName}**`));
|
|
166
|
+
if (data.teams.length > 1) {
|
|
167
|
+
elements.push({
|
|
168
|
+
tag: 'action',
|
|
169
|
+
actions: [
|
|
170
|
+
{
|
|
171
|
+
tag: 'select_static',
|
|
172
|
+
placeholder: { tag: 'plain_text', content: '切换团队' },
|
|
173
|
+
initial_option: data.teamId,
|
|
174
|
+
options: data.teams.map((t) => ({
|
|
175
|
+
text: { tag: 'plain_text', content: t.teamName },
|
|
176
|
+
value: t.teamId,
|
|
177
|
+
})),
|
|
178
|
+
value: { action: ISSUE_ACTION_TEAM, invoker_open_id: data.invokerOpenId },
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
elements.push({ tag: 'hr' });
|
|
184
|
+
if (s.needsAttention.length) {
|
|
185
|
+
elements.push(h(`🔴 **需要关注 (${s.needsAttention.length})**`));
|
|
186
|
+
// 必须封顶:这一段原来是无条件全量铺开的,团队里积压几十条 needs_attention 就会把整张
|
|
187
|
+
// 卡撑爆(飞书对卡片元素数与总长度都有上限,超了直接发不出去),而且把下面的待领取挤到
|
|
188
|
+
// 屏幕外。它只是提醒,不是操作区,列几条足够。
|
|
189
|
+
for (const r of s.needsAttention.slice(0, ATTENTION_PREVIEW)) {
|
|
190
|
+
elements.push(h(` ${escapeLarkMd(truncateDisplay(r.title, BOARD_TITLE_WIDTH))}`));
|
|
191
|
+
}
|
|
192
|
+
const restAttention = s.needsAttention.length - ATTENTION_PREVIEW;
|
|
193
|
+
if (restAttention > 0)
|
|
194
|
+
elements.push(h(` <font color="grey">…另有 ${restAttention} 条</font>`));
|
|
195
|
+
}
|
|
196
|
+
elements.push(h(`⚪️ **待领取 (${s.todo.length})**`));
|
|
197
|
+
if (!slice.length) {
|
|
198
|
+
elements.push(h(' _没有待领取的任务_'));
|
|
199
|
+
}
|
|
200
|
+
for (const r of slice) {
|
|
201
|
+
elements.push({
|
|
202
|
+
tag: 'div',
|
|
203
|
+
text: {
|
|
204
|
+
tag: 'lark_md',
|
|
205
|
+
content: ` ${escapeLarkMd(truncateDisplay(r.title, BOARD_TITLE_WIDTH))}${r.repoLabel ? repoTag(r.repoLabel) : ''}`,
|
|
206
|
+
},
|
|
207
|
+
extra: {
|
|
208
|
+
tag: 'button',
|
|
209
|
+
text: { tag: 'plain_text', content: '领取' },
|
|
210
|
+
type: 'primary',
|
|
211
|
+
value: {
|
|
212
|
+
action: ISSUE_ACTION_CLAIM_OPEN,
|
|
213
|
+
invoker_open_id: data.invokerOpenId,
|
|
214
|
+
teamId: data.teamId,
|
|
215
|
+
issueId: r.issueId,
|
|
216
|
+
// stateRev 随卡片往返:领取时作为 expectedStateRev,别人先改过就会 409,
|
|
217
|
+
// 好过拿一个卡片渲染那一刻的陈旧值去覆盖。
|
|
218
|
+
stateRev: String(r.stateRev),
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
elements.push(h(`🔵 **进行中 (${s.inProgress.length})** 🟡 **待验收 (${s.inReview.length})** ✅ **已完成 (${s.done.length})**`));
|
|
224
|
+
const actions = [];
|
|
225
|
+
if (pages > 1) {
|
|
226
|
+
actions.push({
|
|
227
|
+
tag: 'button',
|
|
228
|
+
text: { tag: 'plain_text', content: '‹ 上一页' },
|
|
229
|
+
disabled: page <= 0,
|
|
230
|
+
value: { action: ISSUE_ACTION_PAGE, invoker_open_id: data.invokerOpenId, teamId: data.teamId, page: String(page - 1) },
|
|
231
|
+
});
|
|
232
|
+
actions.push({
|
|
233
|
+
tag: 'button',
|
|
234
|
+
text: { tag: 'plain_text', content: `${page + 1}/${pages}` },
|
|
235
|
+
disabled: true,
|
|
236
|
+
value: { action: ISSUE_ACTION_PAGE, invoker_open_id: data.invokerOpenId, teamId: data.teamId, page: String(page) },
|
|
237
|
+
});
|
|
238
|
+
actions.push({
|
|
239
|
+
tag: 'button',
|
|
240
|
+
text: { tag: 'plain_text', content: '下一页 ›' },
|
|
241
|
+
disabled: page >= pages - 1,
|
|
242
|
+
value: { action: ISSUE_ACTION_PAGE, invoker_open_id: data.invokerOpenId, teamId: data.teamId, page: String(page + 1) },
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
actions.push({
|
|
246
|
+
tag: 'button',
|
|
247
|
+
text: { tag: 'plain_text', content: '🔄 刷新' },
|
|
248
|
+
value: { action: ISSUE_ACTION_REFRESH, invoker_open_id: data.invokerOpenId, teamId: data.teamId, page: String(page) },
|
|
249
|
+
});
|
|
250
|
+
elements.push({ tag: 'action', actions });
|
|
251
|
+
return JSON.stringify({ config: { wide_screen_mode: true }, elements });
|
|
252
|
+
}
|
|
253
|
+
/** 领取确认视图:选仓库 + 确认/取消。就地替换看板,不新发卡片。 */
|
|
254
|
+
export function buildClaimConfirmCard(data, _locale) {
|
|
255
|
+
const elements = [];
|
|
256
|
+
elements.push(h(`**领取「${escapeLarkMd(truncateDisplay(data.title, 60))}」**`));
|
|
257
|
+
const base = {
|
|
258
|
+
invoker_open_id: data.invokerOpenId,
|
|
259
|
+
teamId: data.teamId,
|
|
260
|
+
issueId: data.issueId,
|
|
261
|
+
stateRev: String(data.stateRev),
|
|
262
|
+
};
|
|
263
|
+
if (!data.repos.length) {
|
|
264
|
+
// 扫不到仓库就领,agent 起来也不知道该在哪动手——与其领了再报错,不如在这里说清楚。
|
|
265
|
+
elements.push(h('⚠️ 在这个 bot 的工作目录下没有扫到任何仓库,无法领取。'));
|
|
266
|
+
elements.push({
|
|
267
|
+
tag: 'action',
|
|
268
|
+
actions: [
|
|
269
|
+
{
|
|
270
|
+
tag: 'button',
|
|
271
|
+
text: { tag: 'plain_text', content: '返回' },
|
|
272
|
+
value: { action: ISSUE_ACTION_CLAIM_CANCEL, ...base },
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
});
|
|
276
|
+
return JSON.stringify({ config: { wide_screen_mode: true }, elements });
|
|
277
|
+
}
|
|
278
|
+
const { options, truncated } = rankRepos(data.repoLabel, data.repos);
|
|
279
|
+
// 选中项必须在选项里,否则 initial_option 落空、下拉显示为未选。
|
|
280
|
+
const selected = data.selectedDir && options.some((r) => r.path === data.selectedDir)
|
|
281
|
+
? data.selectedDir
|
|
282
|
+
: options[0].path;
|
|
283
|
+
elements.push(h(data.repoLabel
|
|
284
|
+
? `平台标注仓库${repoTag(data.repoLabel)}${data.selectedDir ? ' (已自动匹配)' : ' (未匹配到本地仓库,请手动选择)'}`
|
|
285
|
+
: '平台未标注仓库,请选择工作仓库'));
|
|
286
|
+
elements.push({
|
|
287
|
+
tag: 'action',
|
|
288
|
+
actions: [
|
|
289
|
+
{
|
|
290
|
+
tag: 'select_static',
|
|
291
|
+
placeholder: { tag: 'plain_text', content: '选择仓库' },
|
|
292
|
+
initial_option: selected,
|
|
293
|
+
// 下拉里显示仓库名 + 分支,比一串绝对路径好认——同名 worktree 靠分支区分。
|
|
294
|
+
options: options.map((r) => ({
|
|
295
|
+
text: { tag: 'plain_text', content: r.branch ? `${r.name} (${r.branch})` : r.name },
|
|
296
|
+
value: r.path,
|
|
297
|
+
})),
|
|
298
|
+
value: { action: ISSUE_ACTION_CLAIM_DIR, ...base },
|
|
299
|
+
},
|
|
300
|
+
],
|
|
301
|
+
});
|
|
302
|
+
elements.push(h(` \`${selected}\``));
|
|
303
|
+
if (truncated > 0) {
|
|
304
|
+
// 说清楚被截了,别让人以为"下拉里没有就是不存在"。
|
|
305
|
+
elements.push(h(`_候选较多,仅列出最相关的 ${options.length} 个(另有 ${truncated} 个未显示)_`));
|
|
306
|
+
}
|
|
307
|
+
elements.push({
|
|
308
|
+
tag: 'action',
|
|
309
|
+
actions: [
|
|
310
|
+
{
|
|
311
|
+
tag: 'button',
|
|
312
|
+
text: { tag: 'plain_text', content: '确认领取' },
|
|
313
|
+
type: 'primary',
|
|
314
|
+
value: { action: ISSUE_ACTION_CLAIM_CONFIRM, ...base, dir: selected },
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
tag: 'button',
|
|
318
|
+
text: { tag: 'plain_text', content: '取消' },
|
|
319
|
+
value: { action: ISSUE_ACTION_CLAIM_CANCEL, ...base },
|
|
320
|
+
},
|
|
321
|
+
],
|
|
322
|
+
});
|
|
323
|
+
return JSON.stringify({ config: { wide_screen_mode: true }, elements });
|
|
324
|
+
}
|
|
325
|
+
/** 结果视图。失败时**明说失败在哪一步**——不同阶段的补救方式完全不同(见 issue-claim-flow)。 */
|
|
326
|
+
export function buildClaimResultCard(data, _locale) {
|
|
327
|
+
const elements = [];
|
|
328
|
+
if (data.ok) {
|
|
329
|
+
elements.push(h(`✅ **已领取「${escapeLarkMd(truncateDisplay(data.title, 60))}」**`));
|
|
330
|
+
elements.push(h(`群:${escapeLarkMd(data.chatName)}`));
|
|
331
|
+
if (data.shareLink) {
|
|
332
|
+
elements.push({
|
|
333
|
+
tag: 'action',
|
|
334
|
+
actions: [
|
|
335
|
+
{
|
|
336
|
+
tag: 'button',
|
|
337
|
+
text: { tag: 'plain_text', content: '进入群' },
|
|
338
|
+
type: 'primary',
|
|
339
|
+
url: data.shareLink,
|
|
340
|
+
value: {},
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
return JSON.stringify({ config: { wide_screen_mode: true }, elements });
|
|
346
|
+
}
|
|
347
|
+
elements.push(h(`❌ **领取「${escapeLarkMd(truncateDisplay(data.title, 60))}」失败**`));
|
|
348
|
+
elements.push(h(`失败在:\`${escapeLarkMd(data.stage)}\` 原因:\`${escapeLarkMd(data.reason)}\``));
|
|
349
|
+
if (data.hint)
|
|
350
|
+
elements.push(h(data.hint));
|
|
351
|
+
return JSON.stringify({ config: { wide_screen_mode: true }, elements });
|
|
352
|
+
}
|
|
353
|
+
/** 正文摘要长度。够看清要干什么,又不至于把整个群第一屏占满。 */
|
|
354
|
+
const KICKOFF_BODY_MAX = 400;
|
|
355
|
+
/**
|
|
356
|
+
* 开工播报:领取建群后**发在任务群里**的第一条消息。
|
|
357
|
+
*
|
|
358
|
+
* 为什么必须有这么一张卡:kickoff prompt 是**内部投递**的(daemon 直接建会话,见
|
|
359
|
+
* [[issue-command-deps]] 的 ActivateSession),它不经过飞书,群里一个字都看不到。而新建的
|
|
360
|
+
* 群是普通群、默认 reply mode 不是 shared,`handleBotAdded` 的那条 seed 也不会发。两下一
|
|
361
|
+
* 叠,群从建好到 agent 吐出第一段输出之间**完全是空的**——人进群只看到一个空群,不知道
|
|
362
|
+
* agent 有没有开始干、在干什么、在哪个仓库干。实测反馈就是「找不到他已经开始工作了,
|
|
363
|
+
* 干完了才汇报一下」。
|
|
364
|
+
*
|
|
365
|
+
* 所以这张卡要把「agent 现在拿到的是什么」原样摊开:任务标题、正文、工作目录、平台任务
|
|
366
|
+
* 深链。它同时也是释放入口的说明书——不写在这里,人根本不知道 `/issue release` 存在。
|
|
367
|
+
*/
|
|
368
|
+
export function buildIssueKickoffCard(data, _locale) {
|
|
369
|
+
const elements = [];
|
|
370
|
+
elements.push(h(`🚀 **已开工:${escapeLarkMd(truncateDisplay(data.title, 60))}**`));
|
|
371
|
+
const body = data.body?.trim();
|
|
372
|
+
if (body) {
|
|
373
|
+
const excerpt = body.length > KICKOFF_BODY_MAX ? `${body.slice(0, KICKOFF_BODY_MAX)}…` : body;
|
|
374
|
+
// 正文是人在平台上自由填的,同样要消毒——一个落单的反引号能让后面半张卡变成代码块。
|
|
375
|
+
// 这里保留换行(正文本来就是多行),所以按行转义后再拼回去。
|
|
376
|
+
elements.push(h(excerpt.split('\n').map(escapeLarkMd).join('\n')));
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
elements.push(h('_这条任务没有填写详细描述_'));
|
|
380
|
+
}
|
|
381
|
+
elements.push({ tag: 'hr' });
|
|
382
|
+
elements.push(h(`📁 工作目录 ${code(data.workingDir)}`));
|
|
383
|
+
elements.push(h(`🔖 平台任务 ${code(data.issueId)}`));
|
|
384
|
+
if (data.issueUrl) {
|
|
385
|
+
elements.push({
|
|
386
|
+
tag: 'action',
|
|
387
|
+
actions: [
|
|
388
|
+
{
|
|
389
|
+
tag: 'button',
|
|
390
|
+
text: { tag: 'plain_text', content: '在平台上查看' },
|
|
391
|
+
url: data.issueUrl,
|
|
392
|
+
value: {},
|
|
393
|
+
},
|
|
394
|
+
],
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
elements.push({ tag: 'hr' });
|
|
398
|
+
// 这三个命令只在这里露出来。不写的话人根本不知道它们存在,遇事只能去平台上 force-detach。
|
|
399
|
+
elements.push(h('_做完会自动汇报。本群可用:`/issue status` 看现状 · `/issue done` 验收完成 ·'
|
|
400
|
+
+ ' `/issue release` 退回「待领取」(群都不会解散)。_'));
|
|
401
|
+
return JSON.stringify({ config: { wide_screen_mode: true }, elements });
|
|
402
|
+
}
|
|
403
|
+
/** 交付说明的展示上限。完整正文在会话里本来就有,这里只是给验收的人一个摘要。 */
|
|
404
|
+
const DELIVERY_REPORT_MAX = 1200;
|
|
405
|
+
/**
|
|
406
|
+
* 交付播报:`botmux report` 成功后发回任务群。
|
|
407
|
+
*
|
|
408
|
+
* 之所以必须发:平台的 `/status` 接口**只收状态、不收正文**(claimId/claimEpoch/sourceSeq/
|
|
409
|
+
* status/expectedStateRev,没有 note 字段)。交付说明在平台上无处可放,验收的人只会看到状态
|
|
410
|
+
* 变成「待验收」,完全不知道交付了什么。在补上平台侧的备注字段之前,群里是这段文字唯一
|
|
411
|
+
* 能落地的地方——否则它就只是 `botmux report` 的一行 stdout,谁也看不见。
|
|
412
|
+
*/
|
|
413
|
+
export function buildIssueDeliveryCard(data, _locale) {
|
|
414
|
+
const elements = [];
|
|
415
|
+
elements.push(h(data.alreadyInReview
|
|
416
|
+
? `📮 **已经是待验收状态**${data.title ? `:${escapeLarkMd(truncateDisplay(data.title, 60))}` : ''}`
|
|
417
|
+
: `✅ **已交付,等待验收**${data.title ? `:${escapeLarkMd(truncateDisplay(data.title, 60))}` : ''}`));
|
|
418
|
+
const body = data.report.trim();
|
|
419
|
+
if (body) {
|
|
420
|
+
const excerpt = body.length > DELIVERY_REPORT_MAX ? `${body.slice(0, DELIVERY_REPORT_MAX)}…` : body;
|
|
421
|
+
elements.push({ tag: 'hr' });
|
|
422
|
+
elements.push(h(excerpt.split('\n').map(escapeLarkMd).join('\n')));
|
|
423
|
+
}
|
|
424
|
+
elements.push({ tag: 'hr' });
|
|
425
|
+
elements.push(h(`🔖 平台任务 ${code(data.issueId)}`));
|
|
426
|
+
if (data.issueUrl) {
|
|
427
|
+
elements.push({
|
|
428
|
+
tag: 'action',
|
|
429
|
+
actions: [
|
|
430
|
+
{
|
|
431
|
+
tag: 'button',
|
|
432
|
+
text: { tag: 'plain_text', content: '去平台验收' },
|
|
433
|
+
type: 'primary',
|
|
434
|
+
url: data.issueUrl,
|
|
435
|
+
value: {},
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
return JSON.stringify({ config: { wide_screen_mode: true }, elements });
|
|
441
|
+
}
|
|
442
|
+
/** 平台状态 → 人话。卡上不该出现 `in_review` 这种只有读过代码的人才懂的词。 */
|
|
443
|
+
const STATUS_LABEL = {
|
|
444
|
+
open: '⚪️ 待领取',
|
|
445
|
+
claimed: '🟣 已领取(还没开工)',
|
|
446
|
+
in_progress: '🔵 进行中',
|
|
447
|
+
in_review: '🟡 待验收',
|
|
448
|
+
done: '✅ 已完成',
|
|
449
|
+
cancelling: '🟠 取消中',
|
|
450
|
+
needs_attention: '🔴 需要关注',
|
|
451
|
+
reopened: '🔁 已重开',
|
|
452
|
+
};
|
|
453
|
+
/** 需要关注的原因 → 人话。不翻译的话卡上只有一串下划线命名,等于没说。 */
|
|
454
|
+
const ATTENTION_LABEL = {
|
|
455
|
+
cancel_delivery_timeout: '取消指令迟迟没有回执',
|
|
456
|
+
claim_activate_timeout: '领取后 5 分钟内没有开工回写',
|
|
457
|
+
task_blocked: 'agent 报告被卡住',
|
|
458
|
+
run_timeout: '运行超时',
|
|
459
|
+
};
|
|
460
|
+
/** 本地绑定状态 → 人话。终态各有各的含义,别糊成一句「已结束」。 */
|
|
461
|
+
const BIND_STATE_LABEL = {
|
|
462
|
+
pending: '已领取,还没向平台绑定',
|
|
463
|
+
bound: '已绑定,本机正持有',
|
|
464
|
+
void: '绑定被平台拒绝,已作废',
|
|
465
|
+
released: '已释放,任务退回平台',
|
|
466
|
+
done: '已验收完成',
|
|
467
|
+
};
|
|
468
|
+
/**
|
|
469
|
+
* `/issue status`:本机与平台两边的现状对照。
|
|
470
|
+
*
|
|
471
|
+
* 卡片的重点不是"报个状态",而是把**两边不一致**摆出来——回写卡在发件箱、claim 已经被平台
|
|
472
|
+
* 收走、任务掉进需要关注,这三种情况在出问题时都是静默的,人只有主动查才看得见。所以:
|
|
473
|
+
* - claim 不归本机 → 顶格红字警告(这个群继续干下去的产出没人收)
|
|
474
|
+
* - 有待发回写 → 明说有几条、后台会重投,免得人以为状态更新丢了
|
|
475
|
+
* - 平台拉不到 → 说"拉不到",绝不说"任务不存在"(`findIssueById` 的 null 本就无法区分二者)
|
|
476
|
+
*/
|
|
477
|
+
export function buildIssueStatusCard(data, _locale) {
|
|
478
|
+
const elements = [];
|
|
479
|
+
const p = data.platform;
|
|
480
|
+
elements.push(h(`🔎 **任务现状**${p ? `:${escapeLarkMd(truncateDisplay(p.title, 60))}` : ''}`));
|
|
481
|
+
if (data.claimMine === false) {
|
|
482
|
+
elements.push(h('🔴 **平台上这条任务的领取已经不归本机**(被回收、租约过期或已被别人领走)。本群再干下去的产出,平台这边不会记在这条任务上。'));
|
|
483
|
+
}
|
|
484
|
+
elements.push({ tag: 'hr' });
|
|
485
|
+
if (p) {
|
|
486
|
+
const status = STATUS_LABEL[p.status] ?? escapeLarkMd(p.status);
|
|
487
|
+
const reason = p.attentionReason ? ATTENTION_LABEL[p.attentionReason] ?? escapeLarkMd(p.attentionReason) : undefined;
|
|
488
|
+
elements.push(h(`平台状态 ${status}${reason ? ` <font color="grey">(${reason})</font>` : ''}`));
|
|
489
|
+
if (p.claimAgent || p.claimLabel) {
|
|
490
|
+
const who = [p.claimAgent, p.claimLabel].filter(Boolean).map((x) => escapeLarkMd(truncateDisplay(String(x), 40)));
|
|
491
|
+
elements.push(h(`领取人 <font color="grey">${who.join(' · ')}</font>`));
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
// 拉不到 ≠ 不存在:findIssueById 的 null 同时covers 网络失败与已归档,不能替人下结论。
|
|
496
|
+
elements.push(h('平台状态 <font color="grey">拉不到(平台不可达,或这条任务已归档)</font>'));
|
|
497
|
+
}
|
|
498
|
+
elements.push(h(`本机绑定 ${escapeLarkMd(BIND_STATE_LABEL[data.bindState] ?? data.bindState)}`
|
|
499
|
+
+ (data.lastSyncedStatus ? ` <font color="grey">已同步到 ${STATUS_LABEL[data.lastSyncedStatus] ?? escapeLarkMd(data.lastSyncedStatus)}</font>` : '')));
|
|
500
|
+
if (data.pendingWrites > 0) {
|
|
501
|
+
elements.push(h(`⏳ 还有 **${data.pendingWrites}** 条状态回写没发出去,后台每 30 秒重投一次(不用手动重试)。`));
|
|
502
|
+
}
|
|
503
|
+
// 判死的行不在 pendingWrites 里。不单独报出来,界面上一声不吭就等于"已经同步好了",
|
|
504
|
+
// 而那次状态变更**永远不会**到平台——给了 fatal 就得给能看见它的地方。
|
|
505
|
+
if ((data.failedWrites ?? 0) > 0) {
|
|
506
|
+
elements.push(h(`❗ 有 **${data.failedWrites}** 条状态回写被平台拒绝、已放弃重投`
|
|
507
|
+
+ `${data.lastFailure ? `:${escapeLarkMd(truncateDisplay(data.lastFailure, 80))}` : ''}。`
|
|
508
|
+
+ '重试不会好转,去平台上看看这条任务还在不在、领取有没有被收回。'));
|
|
509
|
+
}
|
|
510
|
+
elements.push({ tag: 'hr' });
|
|
511
|
+
elements.push(h(`🔖 平台任务 ${code(data.issueId)}`));
|
|
512
|
+
if (data.issueUrl) {
|
|
513
|
+
elements.push({
|
|
514
|
+
tag: 'action',
|
|
515
|
+
actions: [
|
|
516
|
+
{
|
|
517
|
+
tag: 'button',
|
|
518
|
+
text: { tag: 'plain_text', content: '在平台上查看' },
|
|
519
|
+
url: data.issueUrl,
|
|
520
|
+
value: {},
|
|
521
|
+
},
|
|
522
|
+
],
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
return JSON.stringify({ config: { wide_screen_mode: true }, elements });
|
|
526
|
+
}
|
|
527
|
+
/** 失败阶段 → 给人的下一步提示。措辞对应 issue-claim-flow 里那张「失败留下什么」表。 */
|
|
528
|
+
export function claimFailureHint(stage) {
|
|
529
|
+
switch (stage) {
|
|
530
|
+
case 'claim':
|
|
531
|
+
return '本地没有留下任何痕迹,可以直接重试。';
|
|
532
|
+
case 'group':
|
|
533
|
+
return '平台上已经领取但群没建成。领取记录还在本机,启动对账会接手(补建群或释放领取)。';
|
|
534
|
+
case 'bind':
|
|
535
|
+
return '群已建好但平台拒绝了绑定(可能被回收或已被别人领走)。绑定已作废,群留着待人处理。';
|
|
536
|
+
case 'activate':
|
|
537
|
+
return '群和绑定都已就绪,只差把 bot 叫起来。可以直接在群里 @ 它,不必重新领取。';
|
|
538
|
+
default:
|
|
539
|
+
return undefined;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
//# sourceMappingURL=issue-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-card.js","sourceRoot":"","sources":["../../../src/im/lark/issue-card.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { IssueCommandDeps } from './issue-command.js';
|
|
2
|
+
/**
|
|
3
|
+
* kickoff 正文。写给 agent 看,所以要把它开工需要的一切都说全:干什么、在哪干、
|
|
4
|
+
* 做完怎么交付。
|
|
5
|
+
*
|
|
6
|
+
* 最后那句 `botmux report` 不是客套:它是**本机唯一**会把 issue 推到 in_review 的信号
|
|
7
|
+
* (见 [[issue-status-projector]] 的计划)。不写进 kickoff,agent 干完了平台也不知道。
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildKickoffPrompt(args: {
|
|
10
|
+
title: string;
|
|
11
|
+
body?: string;
|
|
12
|
+
workingDir: string;
|
|
13
|
+
issueId: string;
|
|
14
|
+
}): string;
|
|
15
|
+
/**
|
|
16
|
+
* 激活会话(把 held 群变成真的在跑的会话)。
|
|
17
|
+
*
|
|
18
|
+
* ⚠️ **不能用「让 worker bot 在群里 @ 自己」实现**——飞书不会把一个应用自己发的消息推回给
|
|
19
|
+
* 它自己(见 event-dispatcher 里那段注释:无 receive-all scope 的应用收不到自己发的消息),
|
|
20
|
+
* 所以那条 @ 永远不会变成一次 daemon 事件。`createGroupWithBots` 的 kickoff 能work,是因为它
|
|
21
|
+
* 由**另一个** bot 代发(它显式拒绝 `creator_cannot_kickoff_self`)。
|
|
22
|
+
*
|
|
23
|
+
* 而我们这里 creator 与 worker 是同一个 bot(「你 @ 谁谁就接手」),所以代发那条路也走不通。
|
|
24
|
+
*
|
|
25
|
+
* 正解是**根本不发消息**:botmux 自己就是 daemon,直接内部建会话即可——`autoStartOnGroupJoin`
|
|
26
|
+
* 走的就是这条路(daemon.ts `handleBotAdded`),全程没有任何 @。这也跟 held 模型天然契合:
|
|
27
|
+
* 群先建好、什么都不跑,等我们决定激活时再起会话。
|
|
28
|
+
*
|
|
29
|
+
* 该入口目前还没有从 daemon 暴露出来,所以这里由调用方注入。没注入时领取会**干净地停在
|
|
30
|
+
* activate 阶段**——按 issue-claim-flow 的约定,此时 binding 已 bound、群已就绪,补一次
|
|
31
|
+
* 激活即可,不必重领。宁可这样,也不要塞一个「看起来发出去了其实永远不触发」的实现。
|
|
32
|
+
*/
|
|
33
|
+
export type ActivateSession = (args: {
|
|
34
|
+
chatId: string;
|
|
35
|
+
larkAppId: string;
|
|
36
|
+
prompt: string;
|
|
37
|
+
workingDir: string;
|
|
38
|
+
}) => Promise<string>;
|
|
39
|
+
export declare function setIssueActivate(fn: ActivateSession): void;
|
|
40
|
+
export declare function buildIssueCommandDeps(activate?: ActivateSession | undefined): IssueCommandDeps;
|
|
41
|
+
//# sourceMappingURL=issue-command-deps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-command-deps.d.ts","sourceRoot":"","sources":["../../../src/im/lark/issue-command-deps.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,oBAAoB,CAAC;AAE3E;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAWT;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAUtB,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,CAE1D;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,eAAe,GAAG,SAA8B,GAAG,gBAAgB,CA0IlH"}
|