botmux 2.101.0 → 2.102.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.
Files changed (133) hide show
  1. package/dist/adapters/backend/sandbox.d.ts +13 -1
  2. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  3. package/dist/adapters/backend/sandbox.js +33 -12
  4. package/dist/adapters/backend/sandbox.js.map +1 -1
  5. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  6. package/dist/adapters/backend/tmux-backend.js +4 -0
  7. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  8. package/dist/adapters/cli/coco.d.ts.map +1 -1
  9. package/dist/adapters/cli/coco.js +6 -1
  10. package/dist/adapters/cli/coco.js.map +1 -1
  11. package/dist/adapters/cli/codex-app.d.ts.map +1 -1
  12. package/dist/adapters/cli/codex-app.js +3 -1
  13. package/dist/adapters/cli/codex-app.js.map +1 -1
  14. package/dist/adapters/cli/codex.d.ts.map +1 -1
  15. package/dist/adapters/cli/codex.js +7 -1
  16. package/dist/adapters/cli/codex.js.map +1 -1
  17. package/dist/adapters/cli/hermes.d.ts.map +1 -1
  18. package/dist/adapters/cli/hermes.js +5 -4
  19. package/dist/adapters/cli/hermes.js.map +1 -1
  20. package/dist/adapters/cli/mtr.d.ts.map +1 -1
  21. package/dist/adapters/cli/mtr.js +4 -1
  22. package/dist/adapters/cli/mtr.js.map +1 -1
  23. package/dist/adapters/cli/opencode.d.ts.map +1 -1
  24. package/dist/adapters/cli/opencode.js +4 -1
  25. package/dist/adapters/cli/opencode.js.map +1 -1
  26. package/dist/adapters/cli/traex.d.ts.map +1 -1
  27. package/dist/adapters/cli/traex.js +4 -1
  28. package/dist/adapters/cli/traex.js.map +1 -1
  29. package/dist/adapters/cli/types.d.ts +4 -1
  30. package/dist/adapters/cli/types.d.ts.map +1 -1
  31. package/dist/bot-registry.d.ts +14 -0
  32. package/dist/bot-registry.d.ts.map +1 -1
  33. package/dist/bot-registry.js +9 -0
  34. package/dist/bot-registry.js.map +1 -1
  35. package/dist/core/command-handler.d.ts.map +1 -1
  36. package/dist/core/command-handler.js +22 -8
  37. package/dist/core/command-handler.js.map +1 -1
  38. package/dist/core/cost-calculator.d.ts.map +1 -1
  39. package/dist/core/cost-calculator.js +6 -0
  40. package/dist/core/cost-calculator.js.map +1 -1
  41. package/dist/core/dashboard-ipc-server.d.ts +9 -0
  42. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  43. package/dist/core/dashboard-ipc-server.js +96 -6
  44. package/dist/core/dashboard-ipc-server.js.map +1 -1
  45. package/dist/core/local-terminal-opener.d.ts +43 -0
  46. package/dist/core/local-terminal-opener.d.ts.map +1 -0
  47. package/dist/core/local-terminal-opener.js +221 -0
  48. package/dist/core/local-terminal-opener.js.map +1 -0
  49. package/dist/core/working-dir.d.ts +12 -1
  50. package/dist/core/working-dir.d.ts.map +1 -1
  51. package/dist/core/working-dir.js +20 -3
  52. package/dist/core/working-dir.js.map +1 -1
  53. package/dist/daemon.d.ts.map +1 -1
  54. package/dist/daemon.js +52 -8
  55. package/dist/daemon.js.map +1 -1
  56. package/dist/dashboard/bot-payload.d.ts +2 -0
  57. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  58. package/dist/dashboard/bot-payload.js +4 -0
  59. package/dist/dashboard/bot-payload.js.map +1 -1
  60. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  61. package/dist/dashboard/web/bot-defaults.js +135 -1
  62. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  63. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  64. package/dist/dashboard/web/i18n.js +30 -6
  65. package/dist/dashboard/web/i18n.js.map +1 -1
  66. package/dist/dashboard-web/app.js +2 -2
  67. package/dist/dashboard-web/chunks/bot-defaults-page-YAHNXFBC.js +370 -0
  68. package/dist/dashboard-web/chunks/{chunk-MR57RUVP.js → chunk-DWFMPIAQ.js} +5 -5
  69. package/dist/dashboard-web/chunks/{chunk-ECXPBQ3J.js → chunk-NC77G2OB.js} +1 -1
  70. package/dist/dashboard-web/chunks/{connectors-UGTF4Q4I.js → connectors-BW6WO7P5.js} +1 -1
  71. package/dist/dashboard-web/chunks/{groups-page-IKTCMQ4A.js → groups-page-UTXUVV2M.js} +1 -1
  72. package/dist/dashboard-web/chunks/{insights-page-7CCSHEKM.js → insights-page-IW3KNMG4.js} +1 -1
  73. package/dist/dashboard-web/chunks/{overview-page-JOJW65P5.js → overview-page-RO6R26AZ.js} +1 -1
  74. package/dist/dashboard-web/chunks/{roles-page-E2VN2DLV.js → roles-page-5DYKR2I5.js} +1 -1
  75. package/dist/dashboard-web/chunks/{schedules-6QIHJIHX.js → schedules-WUZP3UPF.js} +1 -1
  76. package/dist/dashboard-web/chunks/{sessions-page-QN2TARF2.js → sessions-page-GWZ4GKSG.js} +1 -1
  77. package/dist/dashboard-web/chunks/{settings-page-WWTXB577.js → settings-page-HJH6HQ7D.js} +1 -1
  78. package/dist/dashboard-web/chunks/{skills-page-2FAUPQ6H.js → skills-page-ATVGKR5I.js} +1 -1
  79. package/dist/dashboard-web/chunks/{team-federation-page-PTBQQSFS.js → team-federation-page-JVC73TTF.js} +1 -1
  80. package/dist/dashboard-web/chunks/{workflows-ZNBB5KFV.js → workflows-YCZTOJUS.js} +1 -1
  81. package/dist/dashboard-web/style.css +42 -0
  82. package/dist/dashboard.js +92 -15
  83. package/dist/dashboard.js.map +1 -1
  84. package/dist/i18n/en.d.ts.map +1 -1
  85. package/dist/i18n/en.js +13 -4
  86. package/dist/i18n/en.js.map +1 -1
  87. package/dist/i18n/zh.d.ts.map +1 -1
  88. package/dist/i18n/zh.js +13 -4
  89. package/dist/i18n/zh.js.map +1 -1
  90. package/dist/im/lark/card-builder.d.ts.map +1 -1
  91. package/dist/im/lark/card-builder.js +20 -0
  92. package/dist/im/lark/card-builder.js.map +1 -1
  93. package/dist/im/lark/card-handler.d.ts.map +1 -1
  94. package/dist/im/lark/card-handler.js +36 -12
  95. package/dist/im/lark/card-handler.js.map +1 -1
  96. package/dist/im/lark/client.d.ts.map +1 -1
  97. package/dist/im/lark/client.js +25 -5
  98. package/dist/im/lark/client.js.map +1 -1
  99. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  100. package/dist/im/lark/event-dispatcher.js +36 -3
  101. package/dist/im/lark/event-dispatcher.js.map +1 -1
  102. package/dist/services/bot-config-store.d.ts +4 -1
  103. package/dist/services/bot-config-store.d.ts.map +1 -1
  104. package/dist/services/bot-config-store.js +19 -1
  105. package/dist/services/bot-config-store.js.map +1 -1
  106. package/dist/services/bot-union-ids-store.d.ts +15 -0
  107. package/dist/services/bot-union-ids-store.d.ts.map +1 -1
  108. package/dist/services/bot-union-ids-store.js +25 -5
  109. package/dist/services/bot-union-ids-store.js.map +1 -1
  110. package/dist/services/open-platform-rename.d.ts +45 -0
  111. package/dist/services/open-platform-rename.d.ts.map +1 -0
  112. package/dist/services/open-platform-rename.js +182 -0
  113. package/dist/services/open-platform-rename.js.map +1 -0
  114. package/dist/services/platform-team-store.d.ts +5 -0
  115. package/dist/services/platform-team-store.d.ts.map +1 -1
  116. package/dist/services/platform-team-store.js +16 -0
  117. package/dist/services/platform-team-store.js.map +1 -1
  118. package/dist/services/sandbox-land.d.ts.map +1 -1
  119. package/dist/services/sandbox-land.js +16 -4
  120. package/dist/services/sandbox-land.js.map +1 -1
  121. package/dist/services/usage-ledger.d.ts.map +1 -1
  122. package/dist/services/usage-ledger.js +14 -2
  123. package/dist/services/usage-ledger.js.map +1 -1
  124. package/dist/setup/open-platform-automation.d.ts +8 -0
  125. package/dist/setup/open-platform-automation.d.ts.map +1 -1
  126. package/dist/setup/open-platform-automation.js +5 -3
  127. package/dist/setup/open-platform-automation.js.map +1 -1
  128. package/dist/worker.js +30 -8
  129. package/dist/worker.js.map +1 -1
  130. package/dist/workflows/events/payloads.d.ts +6 -6
  131. package/dist/workflows/events/schema.d.ts +12 -12
  132. package/package.json +1 -1
  133. package/dist/dashboard-web/chunks/bot-defaults-page-HOGLABBC.js +0 -358
@@ -0,0 +1,221 @@
1
+ import { spawn, spawnSync } from 'node:child_process';
2
+ import { homedir } from 'node:os';
3
+ import { delimiter } from 'node:path';
4
+ import { getBot } from '../bot-registry.js';
5
+ import { createCliAdapterSync } from '../adapters/cli/registry.js';
6
+ import { buildWrappedLaunch, decorateResumeForWrapper, parseWrapperCli } from '../setup/cli-selection.js';
7
+ function shellQuote(value) {
8
+ return `'${value.replace(/'/g, `'\\''`)}'`;
9
+ }
10
+ function onPath(bin) {
11
+ if (bin.includes('/'))
12
+ return spawnSync('test', ['-x', bin]).status === 0;
13
+ const paths = (process.env.PATH || '').split(delimiter).filter(Boolean);
14
+ if (paths.some(dir => spawnSync('test', ['-x', `${dir}/${bin}`]).status === 0))
15
+ return true;
16
+ const shell = process.env.SHELL || '/bin/zsh';
17
+ const result = spawnSync(shell, ['-lc', `command -v ${shellQuote(bin)}`], {
18
+ encoding: 'utf8',
19
+ timeout: 3000,
20
+ stdio: ['ignore', 'pipe', 'ignore'],
21
+ });
22
+ return result.status === 0 && (result.stdout ?? '').trim().length > 0;
23
+ }
24
+ function effectiveCliConfig(ds) {
25
+ let botCfg;
26
+ try {
27
+ botCfg = getBot(ds.larkAppId).config;
28
+ }
29
+ catch { /* tests / deregistered bot */ }
30
+ return {
31
+ cliId: (ds.session.cliId ?? ds.initConfig?.cliId ?? botCfg?.cliId ?? 'claude-code'),
32
+ cliPathOverride: ds.session.cliPathOverride ?? ds.initConfig?.cliPathOverride ?? botCfg?.cliPathOverride,
33
+ wrapperCli: ds.session.wrapperCli ?? ds.initConfig?.wrapperCli ?? botCfg?.wrapperCli,
34
+ model: ds.session.model ?? ds.initConfig?.model ?? botCfg?.model,
35
+ };
36
+ }
37
+ function isCodexFamily(cliId) {
38
+ return cliId === 'codex' || cliId === 'codex-app';
39
+ }
40
+ function defaultLocalExecutable(cliId, adapterResolvedBin, cliPathOverride) {
41
+ if (cliPathOverride?.trim())
42
+ return cliPathOverride.trim();
43
+ if (cliId === 'codex-app')
44
+ return 'codex';
45
+ if (cliId === 'mira')
46
+ return null;
47
+ if (cliId === 'mir')
48
+ return 'mircli';
49
+ return adapterResolvedBin;
50
+ }
51
+ function replaceFirstToken(command, executable) {
52
+ const rest = command.trim().replace(/^\S+/, '').trimStart();
53
+ return rest ? `${shellQuote(executable)} ${rest}` : shellQuote(executable);
54
+ }
55
+ function shellJoin(parts) {
56
+ return parts.map(shellQuote).join(' ');
57
+ }
58
+ function commandForWrapperLaunch(wrapperCli, args, model) {
59
+ const tokens = parseWrapperCli(wrapperCli);
60
+ const launch = buildWrappedLaunch(wrapperCli, args, (bin) => bin, { ttadkModel: model });
61
+ return {
62
+ command: shellJoin([launch.bin, ...launch.args]),
63
+ executable: tokens[0] ?? launch.bin,
64
+ };
65
+ }
66
+ function appleScriptString(value) {
67
+ return JSON.stringify(value);
68
+ }
69
+ export function localCliCommandForSession(ds) {
70
+ const cfg = effectiveCliConfig(ds);
71
+ const cwd = ds.workingDir || ds.session.workingDir || ds.adoptedFrom?.cwd || homedir();
72
+ const cd = `cd ${shellQuote(cwd)}`;
73
+ let adapter;
74
+ try {
75
+ adapter = createCliAdapterSync(cfg.cliId, cfg.cliPathOverride);
76
+ }
77
+ catch (err) {
78
+ return { ok: false, error: 'adapter_error', cliId: cfg.cliId, detail: err instanceof Error ? err.message : String(err) };
79
+ }
80
+ const rawResume = adapter.buildResumeCommand?.({
81
+ sessionId: ds.session.sessionId,
82
+ cliSessionId: ds.session.cliSessionId,
83
+ }) ?? null;
84
+ if (rawResume) {
85
+ const decorated = decorateResumeForWrapper(rawResume, cfg.wrapperCli, { ttadkModel: cfg.model });
86
+ if (cfg.wrapperCli?.trim()) {
87
+ const executable = parseWrapperCli(cfg.wrapperCli)[0];
88
+ if (!executable || !onPath(executable)) {
89
+ return { ok: false, error: 'cli_unavailable', cliId: cfg.cliId, executable };
90
+ }
91
+ return { ok: true, mode: 'resume', executable, command: `${cd} && exec ${decorated}` };
92
+ }
93
+ const executable = defaultLocalExecutable(cfg.cliId, adapter.resolvedBin, cfg.cliPathOverride);
94
+ if (!executable || !onPath(executable)) {
95
+ return { ok: false, error: 'cli_unavailable', cliId: cfg.cliId, executable: executable ?? cfg.cliId };
96
+ }
97
+ return { ok: true, mode: 'resume', executable, command: `${cd} && exec ${replaceFirstToken(rawResume, executable)}` };
98
+ }
99
+ if (cfg.wrapperCli?.trim()) {
100
+ const { command, executable } = commandForWrapperLaunch(cfg.wrapperCli, [], cfg.model);
101
+ if (!executable || !onPath(executable)) {
102
+ return { ok: false, error: 'cli_unavailable', cliId: cfg.cliId, executable };
103
+ }
104
+ return { ok: true, mode: 'launch', executable, command: `${cd} && exec ${command}` };
105
+ }
106
+ const executable = defaultLocalExecutable(cfg.cliId, adapter.resolvedBin, cfg.cliPathOverride);
107
+ if (!executable) {
108
+ return { ok: false, error: 'resume_unavailable', cliId: cfg.cliId };
109
+ }
110
+ if (!onPath(executable)) {
111
+ return { ok: false, error: 'cli_unavailable', cliId: cfg.cliId, executable };
112
+ }
113
+ return { ok: true, mode: 'launch', executable, command: `${cd} && exec ${shellQuote(executable)}` };
114
+ }
115
+ function spawnDetached(command, args) {
116
+ try {
117
+ const child = spawn(command, args, { detached: true, stdio: 'ignore' });
118
+ child.unref();
119
+ return { ok: true };
120
+ }
121
+ catch (err) {
122
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
123
+ }
124
+ }
125
+ function openOnMac(command) {
126
+ if (!onPath('osascript'))
127
+ return { ok: false, error: 'launcher_unavailable', detail: 'osascript not found', command };
128
+ const args = [
129
+ '-e', 'tell application "Terminal"',
130
+ '-e', 'activate',
131
+ '-e', `do script ${appleScriptString(command)}`,
132
+ '-e', 'end tell',
133
+ ];
134
+ const launched = spawnDetached('osascript', args);
135
+ if (!launched.ok)
136
+ return { ok: false, error: 'spawn_failed', detail: launched.error, command };
137
+ return { ok: true, backend: 'cli', command, launcher: 'Terminal.app' };
138
+ }
139
+ function openCodexApp() {
140
+ if (process.platform !== 'darwin') {
141
+ return { ok: false, error: 'unsupported_platform', detail: process.platform, command: 'open -a Codex' };
142
+ }
143
+ if (!onPath('open'))
144
+ return { ok: false, error: 'launcher_unavailable', detail: 'open not found', command: 'open -a Codex' };
145
+ const launched = spawnSync('open', ['-a', 'Codex'], { stdio: 'ignore', timeout: 3000 });
146
+ if (launched.status === 0) {
147
+ return { ok: true, backend: 'app', command: 'open -a Codex', launcher: 'Codex.app' };
148
+ }
149
+ return {
150
+ ok: false,
151
+ error: 'launcher_unavailable',
152
+ detail: launched.error?.message ?? 'Codex.app not found',
153
+ command: 'open -a Codex',
154
+ };
155
+ }
156
+ /** Per-emulator command forwarding: gnome-terminal wants `--`, xfce4-terminal
157
+ * `-x`, kitty / xdg-terminal-exec take the command as positional args, and the
158
+ * xterm lineage (konsole / alacritty / xterm and most others, including
159
+ * whatever BOTMUX_TERMINAL points at) wants `-e`. */
160
+ export function terminalLaunchArgs(terminalBase, shell, command) {
161
+ if (terminalBase === 'gnome-terminal')
162
+ return ['--', shell, '-lc', command];
163
+ if (terminalBase === 'xfce4-terminal')
164
+ return ['-x', shell, '-lc', command];
165
+ if (terminalBase === 'kitty' || terminalBase === 'xdg-terminal-exec')
166
+ return [shell, '-lc', command];
167
+ return ['-e', shell, '-lc', command];
168
+ }
169
+ function openOnLinux(command) {
170
+ const shell = process.env.SHELL || 'bash';
171
+ const preferred = process.env.BOTMUX_TERMINAL || process.env.TERMINAL;
172
+ const candidates = [
173
+ ...(preferred ? [preferred] : []),
174
+ 'xdg-terminal-exec',
175
+ 'gnome-terminal',
176
+ 'konsole',
177
+ 'xfce4-terminal',
178
+ 'kitty',
179
+ 'alacritty',
180
+ 'xterm',
181
+ ];
182
+ const terminal = candidates.find(onPath);
183
+ if (!terminal)
184
+ return { ok: false, error: 'launcher_unavailable', detail: 'no terminal launcher found', command };
185
+ const base = terminal.split('/').pop() || terminal;
186
+ const launched = spawnDetached(terminal, terminalLaunchArgs(base, shell, command));
187
+ if (!launched.ok)
188
+ return { ok: false, error: 'spawn_failed', detail: launched.error, command };
189
+ return { ok: true, backend: 'cli', command, launcher: terminal };
190
+ }
191
+ /** Whether the daemon host can plausibly pop a native terminal window at all.
192
+ * Gates the card button so headless/server deployments don't carry a button
193
+ * that can only ever fail: macOS always qualifies (osascript + Terminal.app
194
+ * ship with the OS); Linux only with a GUI session (DISPLAY/WAYLAND_DISPLAY)
195
+ * or an explicit BOTMUX_TERMINAL/TERMINAL override. */
196
+ export function localTerminalCapable() {
197
+ if (process.platform === 'darwin')
198
+ return true;
199
+ if (process.platform === 'linux') {
200
+ return Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY || process.env.BOTMUX_TERMINAL || process.env.TERMINAL);
201
+ }
202
+ return false;
203
+ }
204
+ export function openLocalTerminalForSession(ds) {
205
+ const cfg = effectiveCliConfig(ds);
206
+ const resolved = localCliCommandForSession(ds);
207
+ if (!resolved.ok && resolved.error === 'cli_unavailable' && isCodexFamily(cfg.cliId) && !cfg.wrapperCli?.trim()) {
208
+ const app = openCodexApp();
209
+ if (app.ok)
210
+ return app;
211
+ return { ...resolved, detail: app.detail ?? resolved.detail };
212
+ }
213
+ if (!resolved.ok)
214
+ return resolved;
215
+ if (process.platform === 'darwin')
216
+ return openOnMac(resolved.command);
217
+ if (process.platform === 'linux')
218
+ return openOnLinux(resolved.command);
219
+ return { ok: false, error: 'unsupported_platform', detail: process.platform, command: resolved.command };
220
+ }
221
+ //# sourceMappingURL=local-terminal-opener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-terminal-opener.js","sourceRoot":"","sources":["../../src/core/local-terminal-opener.ts"],"names":[],"mappings":"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"}
@@ -5,10 +5,21 @@ export declare function expandHome(p: string): string;
5
5
  * "owner explicitly chose a directory" — the daemon already runs CLI prompts
6
6
  * with full filesystem access, so an allowlist would be theater. We only do
7
7
  * the typo guards: exists and is a directory.
8
+ *
9
+ * Auto-create is opt-in (`opts.autoCreate`): only commands where the owner is
10
+ * explicitly typing a fresh path right now (`/cd`, `/oncall bind`) pass it —
11
+ * a missing path gets `mkdir -p` and `created: true` so the caller can tell
12
+ * the user. Every other call site (stored/derived paths at trigger time,
13
+ * dashboard writes, repo cards) keeps the exists-check as its typo guard —
14
+ * silently materializing an empty dir there would mask a stale or mistyped
15
+ * path instead of surfacing it.
8
16
  */
9
- export declare function validateWorkingDir(input: string, locale?: Locale): {
17
+ export declare function validateWorkingDir(input: string, locale?: Locale, opts?: {
18
+ autoCreate?: boolean;
19
+ }): {
10
20
  ok: true;
11
21
  resolvedPath: string;
22
+ created?: boolean;
12
23
  } | {
13
24
  ok: false;
14
25
  error: string;
@@ -1 +1 @@
1
- {"version":3,"file":"working-dir.d.ts","sourceRoot":"","sources":["../../src/core/working-dir.ts"],"names":[],"mappings":"AAOA,OAAO,EAAK,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAapI"}
1
+ {"version":3,"file":"working-dir.d.ts","sourceRoot":"","sources":["../../src/core/working-dir.ts"],"names":[],"mappings":"AAOA,OAAO,EAAK,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAqBtF"}
@@ -2,7 +2,7 @@
2
2
  * Working-directory path helpers, kept dependency-light so the CLI entrypoint
3
3
  * can import them without dragging in the daemon graph (worker-pool, PTY, …).
4
4
  */
5
- import { existsSync, statSync } from 'node:fs';
5
+ import { existsSync, statSync, mkdirSync } from 'node:fs';
6
6
  import { join, resolve } from 'node:path';
7
7
  import { homedir } from 'node:os';
8
8
  import { t } from '../i18n/index.js';
@@ -14,11 +14,28 @@ export function expandHome(p) {
14
14
  * "owner explicitly chose a directory" — the daemon already runs CLI prompts
15
15
  * with full filesystem access, so an allowlist would be theater. We only do
16
16
  * the typo guards: exists and is a directory.
17
+ *
18
+ * Auto-create is opt-in (`opts.autoCreate`): only commands where the owner is
19
+ * explicitly typing a fresh path right now (`/cd`, `/oncall bind`) pass it —
20
+ * a missing path gets `mkdir -p` and `created: true` so the caller can tell
21
+ * the user. Every other call site (stored/derived paths at trigger time,
22
+ * dashboard writes, repo cards) keeps the exists-check as its typo guard —
23
+ * silently materializing an empty dir there would mask a stale or mistyped
24
+ * path instead of surfacing it.
17
25
  */
18
- export function validateWorkingDir(input, locale) {
26
+ export function validateWorkingDir(input, locale, opts) {
19
27
  const resolvedPath = resolve(expandHome(input));
20
28
  if (!existsSync(resolvedPath)) {
21
- return { ok: false, error: t('cmd.cd.dir_not_exist', { path: resolvedPath }, locale) };
29
+ if (!opts?.autoCreate) {
30
+ return { ok: false, error: t('cmd.cd.dir_not_exist', { path: resolvedPath }, locale) };
31
+ }
32
+ try {
33
+ mkdirSync(resolvedPath, { recursive: true });
34
+ return { ok: true, resolvedPath, created: true };
35
+ }
36
+ catch (e) {
37
+ return { ok: false, error: t('cmd.cd.cannot_create', { path: resolvedPath, msg: e?.message ?? String(e) }, locale) };
38
+ }
22
39
  }
23
40
  let isDir = false;
24
41
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"working-dir.js","sourceRoot":"","sources":["../../src/core/working-dir.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,CAAC,EAAe,MAAM,kBAAkB,CAAC;AAElD,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,MAAe;IAC/D,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;IACzF,CAAC;IACD,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,CAAC;QAAC,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;IAAC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QACpE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;IACrH,CAAC;IACD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;IAC3F,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AACpC,CAAC"}
1
+ {"version":3,"file":"working-dir.js","sourceRoot":"","sources":["../../src/core/working-dir.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,CAAC,EAAe,MAAM,kBAAkB,CAAC;AAElD,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,MAAe,EACf,IAA+B;IAE/B,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC;YACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;QACzF,CAAC;QACD,IAAI,CAAC;YACH,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACnD,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;QACvH,CAAC;IACH,CAAC;IACD,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,CAAC;QAAC,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;IAAC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QACpE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;IACrH,CAAC;IACD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;IAC3F,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AACpC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAmBA,OAAO,EAA8G,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAkBhK,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAiGrD,OAAO,EAAE,oBAAoB,EAA6B,MAAM,uBAAuB,CAAC;AACxF,OAAO,KAAK,EAAE,sBAAsB,EAAiB,MAAM,wBAAwB,CAAC;AAqPpF,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmClK;AAED,iBAAe,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAe,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8D3I;AAMD,eAAO,MAAM,uBAAuB,qBAAe,CAAC;AACpD,eAAO,MAAM,yBAAyB,4BAAiB,CAAC;AAqCxD,wBAAsB,8BAA8B,CAClD,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC,CA+ClB;AAED,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAIpB;AAED,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAMpB;AAoKD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,sBAAsB,GAAG,oBAAoB,CA0C5G;AA65CD;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAe,uBAAuB,CAAC,GAAG,EAAE;IAC1C,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;;;;GAqBA;AAED,eAAO,MAAM,kCAAkC,gCAA0B,CAAC;AAihD1E,wBAAsB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAidlE"}
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAuI,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAoBzL,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAiGrD,OAAO,EAAE,oBAAoB,EAA6B,MAAM,uBAAuB,CAAC;AACxF,OAAO,KAAK,EAAE,sBAAsB,EAAiB,MAAM,wBAAwB,CAAC;AAqPpF,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmClK;AAED,iBAAe,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAe,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8D3I;AAMD,eAAO,MAAM,uBAAuB,qBAAe,CAAC;AACpD,eAAO,MAAM,yBAAyB,4BAAiB,CAAC;AAqCxD,wBAAsB,8BAA8B,CAClD,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC,CA+ClB;AAED,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAIpB;AAED,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAMpB;AAoKD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,sBAAsB,GAAG,oBAAoB,CA0C5G;AA65CD;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAe,uBAAuB,CAAC,GAAG,EAAE;IAC1C,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;;;;GAqBA;AAED,eAAO,MAAM,kCAAkC,gCAA0B,CAAC;AAihD1E,wBAAsB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmflE"}
package/dist/daemon.js CHANGED
@@ -16,7 +16,9 @@ import { sendRestartReportIfPending } from './core/restart-report.js';
16
16
  import { statSync } from 'node:fs';
17
17
  import { addReaction, getChatMode, listChatMemberOpenIds, replyMessage, resolveAllowedUsersWithMap, sendMessage, sendUserMessage, updateMessage } from './im/lark/client.js';
18
18
  import { resolveGroupJoinPrompt, waitForAllowedUserInChat } from './core/auto-start.js';
19
- import { loadBotConfigs, registerBot, getBot, getAllBots, findOncallChat, effectiveDefaultWorkingDir } from './bot-registry.js';
19
+ import { loadBotConfigs, registerBot, getBot, getAllBots, findOncallChat, effectiveDefaultWorkingDir, effectiveBotDisplayName } from './bot-registry.js';
20
+ import { setDisplayNameRefresher, findConfigField, applyConfigField } from './services/bot-config-store.js';
21
+ import { renameBotOnOpenPlatform } from './services/open-platform-rename.js';
20
22
  import * as sessionStore from './services/session-store.js';
21
23
  import * as chatFirstSeenStore from './services/chat-first-seen-store.js';
22
24
  import { ensureDefaultOncallBound } from './services/oncall-store.js';
@@ -42,7 +44,7 @@ import { RECEIVED_REACTION_EMOJI_TYPE } from './core/pending-response.js';
42
44
  import { t as tr, botLocale, localeForBot } from './i18n/index.js';
43
45
  import { createCliAdapterSync } from './adapters/cli/registry.js';
44
46
  import { initWorkerPool, setActiveSessionsRegistry, forkWorker, killWorker, reapOrphanWorkers, scheduleCardPatch, setCurrentCliVersion, CARD_POSTING_SENTINEL, parkStreamCard, closeSession as closeSessionHelper, ensureCliEnv, sweepGlobalBotmuxSkills, writableTerminalLinkFor, } from './core/worker-pool.js';
45
- import { ipcRoute, jsonRes, readJsonBody, setBotName, setLarkAppId, startIpcServer, setWorkflowRunner } from './core/dashboard-ipc-server.js';
47
+ import { ipcRoute, jsonRes, readJsonBody, setBotName, setLarkAppId, startIpcServer, setWorkflowRunner, setBotRenamer } from './core/dashboard-ipc-server.js';
46
48
  import { saveFrozenCards } from './services/frozen-card-store.js';
47
49
  import { DAEMON_COMMANDS, SESSIONLESS_DAEMON_COMMANDS, resolvePassthroughCommands, resolveAdapterDefaultPassthroughCommands, handleCommand, handleCardCommand, handleTermLinkCommand, parseSlashCommandInvocation, parseForceTopicInvocation } from './core/command-handler.js';
48
50
  import { SLASH_COMMAND_SHAPE } from './core/passthrough-commands.js';
@@ -3451,7 +3453,7 @@ export async function startDaemon(botIndex) {
3451
3453
  const ipcPort = config.dashboard.ipcBasePort + idx;
3452
3454
  const desc = {
3453
3455
  larkAppId: cfg.larkAppId,
3454
- botName: cfg.larkAppId,
3456
+ botName: cfg.displayName ?? cfg.larkAppId,
3455
3457
  cliId: cfg.cliId,
3456
3458
  botIndex: idx,
3457
3459
  ipcPort,
@@ -3464,6 +3466,45 @@ export async function startDaemon(botIndex) {
3464
3466
  // briefly sees an unusable on_/email (the resolution below rewrites this field).
3465
3467
  resolvedAllowedUsers: getBot(cfg.larkAppId).resolvedAllowedUsers.filter(u => u.startsWith('ou_')),
3466
3468
  };
3469
+ // 名称状态刷新:displayName 或飞书真名变化后,用有效展示名刷新 descriptor +
3470
+ // SessionRow.botName,无需重启 daemon。displayName 路径经 bot-config-store 的
3471
+ // 钩子触发;真·改名路径在下面的 renamer 里直接调用。
3472
+ const refreshBotNameState = () => {
3473
+ const effective = effectiveBotDisplayName(getBot(cfg.larkAppId));
3474
+ setBotName(effective);
3475
+ if (effective !== desc.botName) {
3476
+ desc.botName = effective;
3477
+ try {
3478
+ writeDaemonDescriptor(desc);
3479
+ }
3480
+ catch { /* best effort */ }
3481
+ }
3482
+ };
3483
+ setDisplayNameRefresher(refreshBotNameState);
3484
+ // 机器人真·改名(dashboard 档案头 ✎):开放平台自动化改飞书应用名并发布新版本
3485
+ // (群内显示名跟随已发布版本,见 services/open-platform-rename.ts)。成功后同步
3486
+ // 内存 botName / bots-info 名册 / descriptor,并清掉冗余的 displayName 别名——
3487
+ // 飞书名已经是新名,保持单一事实来源。
3488
+ setBotRenamer(async (newName) => {
3489
+ const r = await renameBotOnOpenPlatform(cfg.larkAppId, newName, cfg.brand);
3490
+ if (!r.ok)
3491
+ return r;
3492
+ const bot = getBot(cfg.larkAppId);
3493
+ bot.botName = newName;
3494
+ const spec = findConfigField('displayName');
3495
+ if (spec && bot.config.displayName) {
3496
+ // applyConfigField 的 displayName 钩子会顺带触发 refreshBotNameState。
3497
+ await applyConfigField(cfg.larkAppId, spec, null);
3498
+ }
3499
+ else {
3500
+ refreshBotNameState();
3501
+ }
3502
+ try {
3503
+ writeBotInfoFile(config.session.dataDir);
3504
+ }
3505
+ catch { /* best effort */ }
3506
+ return r;
3507
+ });
3467
3508
  // Initialise worker pool with daemon callbacks
3468
3509
  initWorkerPool({
3469
3510
  sessionReply,
@@ -3483,10 +3524,11 @@ export async function startDaemon(botIndex) {
3483
3524
  // Wire the workflow runner for /api/trigger (kind=workflow): reuse the same
3484
3525
  // heavy deps as the catalog run route.
3485
3526
  setWorkflowRunner((input) => triggerWorkflowRun(input, workflowTriggerDeps()));
3486
- // Seed dashboard IPC botName with the bot's config id; the friendly name from
3487
- // /bot/v3/info is wired into the registry descriptor (below) but the IPC server
3488
- // also needs its own copy for SessionRow.botName.
3489
- setBotName(cfg.larkAppId);
3527
+ // Seed dashboard IPC botName with the custom displayName (falling back to the
3528
+ // bot's config id); the friendly name from /bot/v3/info is wired into the
3529
+ // registry descriptor (below) but the IPC server also needs its own copy for
3530
+ // SessionRow.botName.
3531
+ setBotName(cfg.displayName ?? cfg.larkAppId);
3490
3532
  setLarkAppId(cfg.larkAppId);
3491
3533
  selfV3LarkAppId = cfg.larkAppId; // scope v3 humanGate cold-attach / start to this bot
3492
3534
  // Bind dashboard IPC HTTP server BEFORE publishing the registry descriptor.
@@ -3596,9 +3638,11 @@ export async function startDaemon(botIndex) {
3596
3638
  // Probe bot open_id and persist to bots-info.json. When the friendly
3597
3639
  // botName comes back from /bot/v3/info, refresh the dashboard descriptor
3598
3640
  // so the registry shows "Claude" / "Codex" instead of the raw app id.
3641
+ // A custom displayName (bots.json) beats the probed Lark name — the probe
3642
+ // must not overwrite a rename seeded at startup.
3599
3643
  probeBotOpenId(cfg.larkAppId).then(() => {
3600
3644
  writeBotInfoFile(config.session.dataDir);
3601
- const probedName = bot.botName;
3645
+ const probedName = cfg.displayName ?? bot.botName;
3602
3646
  const probedAvatar = bot.botAvatarUrl;
3603
3647
  let descChanged = false;
3604
3648
  if (probedName && probedName !== desc.botName) {