botmux 2.81.0 → 2.82.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/dist/core/closed-session-card.d.ts +16 -0
- package/dist/core/closed-session-card.d.ts.map +1 -0
- package/dist/core/closed-session-card.js +39 -0
- package/dist/core/closed-session-card.js.map +1 -0
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +40 -30
- package/dist/core/command-handler.js.map +1 -1
- package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/web/bot-onboarding.js +61 -2
- package/dist/dashboard/web/bot-onboarding.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +4 -0
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard-web/app.js +161 -160
- package/dist/dashboard.js +14 -2
- package/dist/dashboard.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +33 -28
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/setup/cli-selection.d.ts +33 -4
- package/dist/setup/cli-selection.d.ts.map +1 -1
- package/dist/setup/cli-selection.js +101 -4
- package/dist/setup/cli-selection.js.map +1 -1
- package/dist/worker.js +16 -3
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type DaemonSession } from './types.js';
|
|
2
|
+
import type { Locale } from '../i18n/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Build the same "session closed" card `/close` emits for a session that is
|
|
5
|
+
* about to be displaced (e.g. a mid-session `/repo` switch reuses the SAME
|
|
6
|
+
* anchor for a fresh session). Without this trace the old context vanishes —
|
|
7
|
+
* relay/adopt/resume all hit `anchor_occupied` once the new session holds the
|
|
8
|
+
* anchor — so the card keeps it visible and carries the terminal
|
|
9
|
+
* `claude --resume` command as the real recovery path.
|
|
10
|
+
*
|
|
11
|
+
* MUST be called BEFORE killWorker/closeSession: it reads the live session's
|
|
12
|
+
* identity (sessionId, cliSessionId, title, workingDir, anchor) straight off
|
|
13
|
+
* `ds`. Returns the card JSON; the caller decides how to deliver it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildClosedSessionCard(ds: DaemonSession, locale: Locale): string;
|
|
16
|
+
//# sourceMappingURL=closed-session-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"closed-session-card.d.ts","sourceRoot":"","sources":["../../src/core/closed-session-card.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAyBhF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { getBot } from '../bot-registry.js';
|
|
2
|
+
import { createCliAdapterSync } from '../adapters/cli/registry.js';
|
|
3
|
+
import { decorateResumeForWrapper } from '../setup/cli-selection.js';
|
|
4
|
+
import { buildSessionClosedCard } from '../im/lark/card-builder.js';
|
|
5
|
+
import { sessionAnchorId } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Build the same "session closed" card `/close` emits for a session that is
|
|
8
|
+
* about to be displaced (e.g. a mid-session `/repo` switch reuses the SAME
|
|
9
|
+
* anchor for a fresh session). Without this trace the old context vanishes —
|
|
10
|
+
* relay/adopt/resume all hit `anchor_occupied` once the new session holds the
|
|
11
|
+
* anchor — so the card keeps it visible and carries the terminal
|
|
12
|
+
* `claude --resume` command as the real recovery path.
|
|
13
|
+
*
|
|
14
|
+
* MUST be called BEFORE killWorker/closeSession: it reads the live session's
|
|
15
|
+
* identity (sessionId, cliSessionId, title, workingDir, anchor) straight off
|
|
16
|
+
* `ds`. Returns the card JSON; the caller decides how to deliver it.
|
|
17
|
+
*/
|
|
18
|
+
export function buildClosedSessionCard(ds, locale) {
|
|
19
|
+
const botCfg = getBot(ds.larkAppId).config;
|
|
20
|
+
const closedSessionId = ds.session.sessionId;
|
|
21
|
+
const closedCliId = ds.session.cliId ?? botCfg.cliId;
|
|
22
|
+
const cliResumeCommand = (() => {
|
|
23
|
+
try {
|
|
24
|
+
const adapter = createCliAdapterSync(closedCliId, botCfg.cliPathOverride);
|
|
25
|
+
const raw = adapter.buildResumeCommand?.({
|
|
26
|
+
sessionId: closedSessionId,
|
|
27
|
+
cliSessionId: ds.session.cliSessionId,
|
|
28
|
+
}) ?? null;
|
|
29
|
+
// ttadk 网关:resume 命令必须带 `-m <model> --skip-check`(模型取 bot.model),
|
|
30
|
+
// 否则用户复制粘贴这条命令会卡在 ttadk 的交互式选模型菜单(CoCo 不带 -m)。
|
|
31
|
+
return raw ? decorateResumeForWrapper(raw, botCfg.wrapperCli, { ttadkModel: botCfg.model }) : null;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
})();
|
|
37
|
+
return buildSessionClosedCard(closedSessionId, sessionAnchorId(ds), ds.session.title, closedCliId, ds.session.workingDir, cliResumeCommand, locale);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=closed-session-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"closed-session-card.js","sourceRoot":"","sources":["../../src/core/closed-session-card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAsB,MAAM,YAAY,CAAC;AAGjE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,EAAiB,EAAE,MAAc;IACtE,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IAC3C,MAAM,eAAe,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IAC7C,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;IACrD,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;YAC1E,MAAM,GAAG,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;gBACvC,SAAS,EAAE,eAAe;gBAC1B,YAAY,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY;aACtC,CAAC,IAAI,IAAI,CAAC;YACX,kEAAkE;YAClE,+CAA+C;YAC/C,OAAO,GAAG,CAAC,CAAC,CAAC,wBAAwB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrG,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;IAC1B,CAAC,CAAC,EAAE,CAAC;IACL,OAAO,sBAAsB,CAC3B,eAAe,EACf,eAAe,CAAC,EAAE,CAAC,EACnB,EAAE,CAAC,OAAO,CAAC,KAAK,EAChB,WAAW,EACX,EAAE,CAAC,OAAO,CAAC,UAAU,EACrB,gBAAgB,EAChB,MAAM,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../src/core/command-handler.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAQxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAoF,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACjJ,OAAO,EAA8D,KAAK,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACtI,OAAO,EAAuB,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../src/core/command-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ import * as scheduleStore from '../services/schedule-store.js';
|
|
|
13
13
|
import * as scheduler from './scheduler.js';
|
|
14
14
|
import { scanMultipleProjects, describeProjectDir } from '../services/project-scanner.js';
|
|
15
15
|
import { createRepoWorktree } from '../services/git-worktree.js';
|
|
16
|
-
import { buildRepoSelectCard, buildAdoptSelectCard, buildCodexAppThreadSelectCard,
|
|
16
|
+
import { buildRepoSelectCard, buildAdoptSelectCard, buildCodexAppThreadSelectCard, buildSlashListCard, getCliDisplayName, buildConfigCard, buildLandCard } from '../im/lark/card-builder.js';
|
|
17
17
|
import { computeSandboxDiff } from '../services/sandbox-land.js';
|
|
18
18
|
import { createCliAdapterSync } from '../adapters/cli/registry.js';
|
|
19
19
|
import { deleteMessage, sendMessage, sendUserMessage, listChatBotMembers, resolveUserUnionId, getChatModeStrict, uploadFile } from '../im/lark/client.js';
|
|
@@ -34,7 +34,8 @@ import { putDocSubscription, removeDocSubscription, listDocSubscriptionsForSessi
|
|
|
34
34
|
import { bindOncall, unbindOncall, getOncallStatus } from '../services/oncall-store.js';
|
|
35
35
|
import { CONFIG_FIELDS, findConfigField, settableFieldKeys, parseBooleanValue, applyConfigField, setBotAllowedUsers, getConfigSnapshot, getConfigCardData, } from '../services/bot-config-store.js';
|
|
36
36
|
import { resolveCliId, findInvalidAllowedUserEntries } from '../setup/bot-config-editor.js';
|
|
37
|
-
import {
|
|
37
|
+
import { buildClosedSessionCard } from './closed-session-card.js';
|
|
38
|
+
import { ttadkConfigModelChoices } from '../setup/cli-selection.js';
|
|
38
39
|
import { publishAttentionPatch, announcePendingRepoSession } from './session-activity.js';
|
|
39
40
|
import { setCardMode } from '../services/card-mode-store.js';
|
|
40
41
|
import { canOperate } from '../im/lark/event-dispatcher.js';
|
|
@@ -618,11 +619,17 @@ async function handleConfigCommand(message, rootId, larkAppId, deps) {
|
|
|
618
619
|
const cardLoc = cardLocaleArg(sub);
|
|
619
620
|
if (!sub || cardLoc) {
|
|
620
621
|
const renderLoc = cardLoc ?? loc;
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
622
|
+
// ttadk 网关 bot:模型候选用 ttadk 网关模型(glm-5.1…),不是底层适配器的
|
|
623
|
+
// opus/gpt-5(那会被 worker 注入成 `ttadk -m opus` 用错模型启动失败);CoCo 无候选。
|
|
624
|
+
// 非 ttadk(返回 null)才回落底层适配器自己的 modelChoices。
|
|
625
|
+
const ttadkChoices = ttadkConfigModelChoices(bot.config.wrapperCli);
|
|
626
|
+
let modelChoices = ttadkChoices ?? [];
|
|
627
|
+
if (ttadkChoices === null) {
|
|
628
|
+
try {
|
|
629
|
+
modelChoices = createCliAdapterSync(bot.config.cliId, bot.config.cliPathOverride).modelChoices ?? [];
|
|
630
|
+
}
|
|
631
|
+
catch { /* 无候选 → 不渲染 model 下拉 */ }
|
|
624
632
|
}
|
|
625
|
-
catch { /* 无候选 → 不渲染 model 下拉 */ }
|
|
626
633
|
const data = getConfigCardData(larkAppId, modelChoices);
|
|
627
634
|
if (!data) {
|
|
628
635
|
await reply(buildConfigHelp(renderLoc));
|
|
@@ -875,29 +882,12 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
|
|
|
875
882
|
switch (cmd) {
|
|
876
883
|
case '/close': {
|
|
877
884
|
if (ds) {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
const
|
|
881
|
-
const closedCliId = ds.session.cliId ?? botCfg.cliId;
|
|
882
|
-
const closedAnchor = sessionAnchorId(ds);
|
|
883
|
-
const closedWorkingDir = ds.session.workingDir;
|
|
884
|
-
const cliResumeCommand = (() => {
|
|
885
|
-
try {
|
|
886
|
-
const adapter = createCliAdapterSync(closedCliId, botCfg.cliPathOverride);
|
|
887
|
-
const raw = adapter.buildResumeCommand?.({
|
|
888
|
-
sessionId: closedSessionId,
|
|
889
|
-
cliSessionId: ds.session.cliSessionId,
|
|
890
|
-
}) ?? null;
|
|
891
|
-
return raw ? decorateResumeForWrapper(raw, botCfg.wrapperCli) : null;
|
|
892
|
-
}
|
|
893
|
-
catch {
|
|
894
|
-
return null;
|
|
895
|
-
}
|
|
896
|
-
})();
|
|
885
|
+
// Capture the closed-session card BEFORE killWorker/closeSession —
|
|
886
|
+
// it reads the live session's identity off `ds`.
|
|
887
|
+
const card = buildClosedSessionCard(ds, loc);
|
|
897
888
|
killWorker(ds);
|
|
898
|
-
sessionStore.closeSession(
|
|
889
|
+
sessionStore.closeSession(ds.session.sessionId);
|
|
899
890
|
activeSessions.delete(sessionKey(rootId, larkAppId));
|
|
900
|
-
const card = buildSessionClosedCard(closedSessionId, closedAnchor, closedTitle, closedCliId, closedWorkingDir, cliResumeCommand, loc);
|
|
901
891
|
// 「会话已关闭」卡片优先「仅自己可见」:普通群里走 ephemeral 只发给执行
|
|
902
892
|
// /close 的本人;话题群不支持 ephemeral(18053) 时回退为正常的群内可见回复
|
|
903
893
|
// ——与流式卡片上「关闭会话」按钮的送达方式保持一致。
|
|
@@ -1094,19 +1084,39 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
|
|
|
1094
1084
|
// close + recreate the session (mid-session switch). Used by both the
|
|
1095
1085
|
// numeric `/repo <N>` form and the `/repo <path|name>` form.
|
|
1096
1086
|
const commitRepoSelection = async (selectedPath, displayName, how) => {
|
|
1097
|
-
ds.workingDir = selectedPath;
|
|
1098
|
-
ds.session.workingDir = selectedPath;
|
|
1099
|
-
sessionStore.updateSession(ds.session);
|
|
1100
1087
|
if (ds.pendingRepo) {
|
|
1088
|
+
// First spawn: pin the new cwd onto the CURRENT session, then fork.
|
|
1089
|
+
ds.workingDir = selectedPath;
|
|
1090
|
+
ds.session.workingDir = selectedPath;
|
|
1091
|
+
sessionStore.updateSession(ds.session);
|
|
1101
1092
|
await forkPendingCli(t('cmd.repo.selected_in_pending', { name: displayName }, loc));
|
|
1102
1093
|
}
|
|
1103
1094
|
else {
|
|
1095
|
+
// Safety net: a mid-session `/repo` switch closes the running
|
|
1096
|
+
// session and spawns a fresh one on the SAME anchor. Without a
|
|
1097
|
+
// trace, the old context silently vanishes (relay/adopt/resume all
|
|
1098
|
+
// hit `anchor_occupied` once the new session holds the anchor).
|
|
1099
|
+
// So, before displacing it, post the same "session closed" card
|
|
1100
|
+
// `/close` emits — it keeps the old session visible and carries the
|
|
1101
|
+
// terminal `claude --resume` command. (Its in-card resume button
|
|
1102
|
+
// still hits anchor_occupied while the new session occupies this
|
|
1103
|
+
// anchor — expected; `/close` the new one first, or use the
|
|
1104
|
+
// command.) Mirrors the `/close` case above.
|
|
1105
|
+
//
|
|
1106
|
+
// The new cwd is NOT written onto the old session here — it would
|
|
1107
|
+
// pollute the displaced session's stored workingDir (and the closed
|
|
1108
|
+
// card), so `claude --resume` later would reopen the old context in
|
|
1109
|
+
// the new repo's cwd. The new repo is pinned onto the fresh session
|
|
1110
|
+
// below instead.
|
|
1111
|
+
const closedCard = buildClosedSessionCard(ds, loc);
|
|
1104
1112
|
killWorker(ds);
|
|
1105
1113
|
sessionStore.closeSession(ds.session.sessionId);
|
|
1114
|
+
await deliverEphemeralOrReply(ds, message.senderId, closedCard, 'interactive', () => sessionReply(rootId, closedCard, 'interactive'));
|
|
1106
1115
|
const session = sessionStore.createSession(ds.chatId, rootId, displayName, ds.chatType);
|
|
1107
1116
|
ds.session = session;
|
|
1108
1117
|
ds.lastUserPrompt = undefined;
|
|
1109
1118
|
ds.lastCliInput = undefined;
|
|
1119
|
+
ds.workingDir = selectedPath;
|
|
1110
1120
|
ds.session.workingDir = selectedPath;
|
|
1111
1121
|
ds.session.larkAppId = ds.larkAppId;
|
|
1112
1122
|
sessionStore.updateSession(ds.session);
|