botmux 2.114.0 → 3.0.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 (136) hide show
  1. package/dist/adapters/backend/riff-backend.d.ts +15 -0
  2. package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
  3. package/dist/adapters/backend/riff-backend.js +9 -3
  4. package/dist/adapters/backend/riff-backend.js.map +1 -1
  5. package/dist/core/dashboard-ipc-server.js +2 -2
  6. package/dist/core/dashboard-ipc-server.js.map +1 -1
  7. package/dist/dashboard/compat.d.ts +19 -0
  8. package/dist/dashboard/compat.d.ts.map +1 -0
  9. package/dist/dashboard/compat.js +38 -0
  10. package/dist/dashboard/compat.js.map +1 -0
  11. package/dist/dashboard/stale-chunk-module.d.ts +3 -0
  12. package/dist/dashboard/stale-chunk-module.d.ts.map +1 -0
  13. package/dist/dashboard/stale-chunk-module.js +55 -0
  14. package/dist/dashboard/stale-chunk-module.js.map +1 -0
  15. package/dist/dashboard/web/app.d.ts.map +1 -1
  16. package/dist/dashboard/web/app.js +64 -2
  17. package/dist/dashboard/web/app.js.map +1 -1
  18. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
  19. package/dist/dashboard/web/bot-defaults-page.js +9 -7
  20. package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
  21. package/dist/dashboard/web/i18n.js +10 -10
  22. package/dist/dashboard/web/i18n.js.map +1 -1
  23. package/dist/dashboard/web/sessions-page.js +2 -2
  24. package/dist/dashboard/web/sessions-page.js.map +1 -1
  25. package/dist/dashboard/web/stale-chunk-reload.d.ts +16 -0
  26. package/dist/dashboard/web/stale-chunk-reload.d.ts.map +1 -0
  27. package/dist/dashboard/web/stale-chunk-reload.js +51 -0
  28. package/dist/dashboard/web/stale-chunk-reload.js.map +1 -0
  29. package/dist/dashboard-web/app.js +1 -1
  30. package/dist/dashboard-web/chunks/{bot-defaults-page-SRCBF7Z3.js → bot-defaults-page-MBORWWP7.js} +5 -5
  31. package/dist/dashboard-web/chunks/{chunk-3H6MVXXU.js → chunk-4QTBR7UF.js} +2 -2
  32. package/dist/dashboard-web/chunks/{chunk-77KD4TK2.js → chunk-7STGZ5BX.js} +1 -1
  33. package/dist/dashboard-web/chunks/{chunk-D2I5F4MY.js → chunk-EIO5AWDA.js} +1 -1
  34. package/dist/dashboard-web/chunks/{chunk-NGRUZCXP.js → chunk-G43RUPUN.js} +1 -1
  35. package/dist/dashboard-web/chunks/{connectors-page-RM3BJVMV.js → connectors-page-LKDT4WBG.js} +1 -1
  36. package/dist/dashboard-web/chunks/{groups-page-3D4YSYLA.js → groups-page-XKIWJ2TP.js} +1 -1
  37. package/dist/dashboard-web/chunks/{insights-page-CRFJKA54.js → insights-page-CBEZCYKV.js} +1 -1
  38. package/dist/dashboard-web/chunks/{monitor-room-HLK3XDT2.js → monitor-room-AQTHAWXA.js} +1 -1
  39. package/dist/dashboard-web/chunks/{monitoring-page-E3SNZFFN.js → monitoring-page-2R4NCNBQ.js} +1 -1
  40. package/dist/dashboard-web/chunks/{office-page-MKQ2TENK.js → office-page-5M6MQIIL.js} +1 -1
  41. package/dist/dashboard-web/chunks/{overview-page-ICFKKRLV.js → overview-page-N22HDZ2V.js} +1 -1
  42. package/dist/dashboard-web/chunks/{roles-page-2DFJ7YRU.js → roles-page-J6K2HWFX.js} +1 -1
  43. package/dist/dashboard-web/chunks/{schedules-page-S4WDIXH5.js → schedules-page-CGAQCB4J.js} +1 -1
  44. package/dist/dashboard-web/chunks/{sessions-page-4XWGUGB5.js → sessions-page-WJ2QYTIE.js} +2 -2
  45. package/dist/dashboard-web/chunks/{settings-page-OBTE4LYP.js → settings-page-GLRWV5KU.js} +1 -1
  46. package/dist/dashboard-web/chunks/{skills-page-CTRQJR47.js → skills-page-KQVW42QU.js} +1 -1
  47. package/dist/dashboard-web/chunks/{team-federation-page-GICLDKJP.js → team-federation-page-5PYUOV5M.js} +1 -1
  48. package/dist/dashboard-web/chunks/{v3-page-DI55IRL5.js → v3-page-DXPFILRZ.js} +1 -1
  49. package/dist/dashboard-web/chunks/{whiteboards-page-7KFWMILV.js → whiteboards-page-NUH6VZ4I.js} +1 -1
  50. package/dist/dashboard.js +26 -0
  51. package/dist/dashboard.js.map +1 -1
  52. package/dist/desktop/main/auto-start.d.ts +17 -0
  53. package/dist/desktop/main/auto-start.d.ts.map +1 -0
  54. package/dist/desktop/main/auto-start.js +37 -0
  55. package/dist/desktop/main/auto-start.js.map +1 -0
  56. package/dist/desktop/main/dashboard-compat.d.ts +25 -0
  57. package/dist/desktop/main/dashboard-compat.d.ts.map +1 -0
  58. package/dist/desktop/main/dashboard-compat.js +117 -0
  59. package/dist/desktop/main/dashboard-compat.js.map +1 -0
  60. package/dist/desktop/main/external-runtime.d.ts +29 -0
  61. package/dist/desktop/main/external-runtime.d.ts.map +1 -0
  62. package/dist/desktop/main/external-runtime.js +202 -0
  63. package/dist/desktop/main/external-runtime.js.map +1 -0
  64. package/dist/desktop/main/ipc.d.ts +20 -0
  65. package/dist/desktop/main/ipc.d.ts.map +1 -0
  66. package/dist/desktop/main/ipc.js +241 -0
  67. package/dist/desktop/main/ipc.js.map +1 -0
  68. package/dist/desktop/main/log-service.d.ts +4 -0
  69. package/dist/desktop/main/log-service.d.ts.map +1 -0
  70. package/dist/desktop/main/log-service.js +53 -0
  71. package/dist/desktop/main/log-service.js.map +1 -0
  72. package/dist/desktop/main/login-item.d.ts +10 -0
  73. package/dist/desktop/main/login-item.d.ts.map +1 -0
  74. package/dist/desktop/main/login-item.js +11 -0
  75. package/dist/desktop/main/login-item.js.map +1 -0
  76. package/dist/desktop/main/node-command.d.ts +22 -0
  77. package/dist/desktop/main/node-command.d.ts.map +1 -0
  78. package/dist/desktop/main/node-command.js +56 -0
  79. package/dist/desktop/main/node-command.js.map +1 -0
  80. package/dist/desktop/main/paths.d.ts +11 -0
  81. package/dist/desktop/main/paths.d.ts.map +1 -0
  82. package/dist/desktop/main/paths.js +13 -0
  83. package/dist/desktop/main/paths.js.map +1 -0
  84. package/dist/desktop/main/pm2-apps.d.ts +15 -0
  85. package/dist/desktop/main/pm2-apps.d.ts.map +1 -0
  86. package/dist/desktop/main/pm2-apps.js +97 -0
  87. package/dist/desktop/main/pm2-apps.js.map +1 -0
  88. package/dist/desktop/main/runtime-service.d.ts +49 -0
  89. package/dist/desktop/main/runtime-service.d.ts.map +1 -0
  90. package/dist/desktop/main/runtime-service.js +297 -0
  91. package/dist/desktop/main/runtime-service.js.map +1 -0
  92. package/dist/desktop/main/runtime-source.d.ts +17 -0
  93. package/dist/desktop/main/runtime-source.d.ts.map +1 -0
  94. package/dist/desktop/main/runtime-source.js +61 -0
  95. package/dist/desktop/main/runtime-source.js.map +1 -0
  96. package/dist/desktop/main/tray.d.ts +10 -0
  97. package/dist/desktop/main/tray.d.ts.map +1 -0
  98. package/dist/desktop/main/tray.js +27 -0
  99. package/dist/desktop/main/tray.js.map +1 -0
  100. package/dist/desktop/main/window.d.ts +16 -0
  101. package/dist/desktop/main/window.d.ts.map +1 -0
  102. package/dist/desktop/main/window.js +113 -0
  103. package/dist/desktop/main/window.js.map +1 -0
  104. package/dist/desktop/main.d.ts +2 -0
  105. package/dist/desktop/main.d.ts.map +1 -0
  106. package/dist/desktop/main.js +175 -0
  107. package/dist/desktop/main.js.map +1 -0
  108. package/dist/desktop/preload.d.ts +2 -0
  109. package/dist/desktop/preload.d.ts.map +1 -0
  110. package/dist/desktop/preload.js +24 -0
  111. package/dist/desktop/preload.js.map +1 -0
  112. package/dist/desktop/renderer/app.d.ts +35 -0
  113. package/dist/desktop/renderer/app.d.ts.map +1 -0
  114. package/dist/desktop/renderer/app.js +945 -0
  115. package/dist/desktop/renderer/app.js.map +1 -0
  116. package/dist/desktop/renderer/dashboard-url.d.ts +13 -0
  117. package/dist/desktop/renderer/dashboard-url.d.ts.map +1 -0
  118. package/dist/desktop/renderer/dashboard-url.js +98 -0
  119. package/dist/desktop/renderer/dashboard-url.js.map +1 -0
  120. package/dist/desktop/renderer/runtime-state.d.ts +8 -0
  121. package/dist/desktop/renderer/runtime-state.d.ts.map +1 -0
  122. package/dist/desktop/renderer/runtime-state.js +67 -0
  123. package/dist/desktop/renderer/runtime-state.js.map +1 -0
  124. package/dist/desktop/shared/types.d.ts +48 -0
  125. package/dist/desktop/shared/types.d.ts.map +1 -0
  126. package/dist/desktop/shared/types.js +2 -0
  127. package/dist/desktop/shared/types.js.map +1 -0
  128. package/dist/desktop/smoke.d.ts +28 -0
  129. package/dist/desktop/smoke.d.ts.map +1 -0
  130. package/dist/desktop/smoke.js +258 -0
  131. package/dist/desktop/smoke.js.map +1 -0
  132. package/dist/utils/version-info.d.ts +25 -0
  133. package/dist/utils/version-info.d.ts.map +1 -0
  134. package/dist/utils/version-info.js +48 -0
  135. package/dist/utils/version-info.js.map +1 -0
  136. package/package.json +9 -1
@@ -0,0 +1,49 @@
1
+ import { type DashboardResult } from '../../cli/dashboard-endpoint.js';
2
+ import type { DesktopPaths, DesktopRuntimeState, RuntimeSource } from '../shared/types.js';
3
+ import { type BotmuxCommand } from './node-command.js';
4
+ import { type Pm2AppSummary } from './runtime-source.js';
5
+ export interface RunResult {
6
+ code: number;
7
+ stdout: string;
8
+ stderr: string;
9
+ signal?: NodeJS.Signals | null;
10
+ }
11
+ type RunCommand = (cmd: BotmuxCommand) => Promise<RunResult>;
12
+ type DashboardEndpointCaller = (path: '/__cli/current') => Promise<DashboardResult>;
13
+ export interface ExternalRuntimeCandidate {
14
+ kind: 'external';
15
+ root: string;
16
+ cliPath: string;
17
+ binPath: string;
18
+ pathEnv?: string;
19
+ version: string;
20
+ runtimeSource?: Exclude<RuntimeSource, 'none'>;
21
+ }
22
+ export type RuntimeLaunchTarget = ExternalRuntimeCandidate;
23
+ export interface RuntimeServiceDeps {
24
+ paths: DesktopPaths;
25
+ appVersion: string;
26
+ execPath: string;
27
+ env: NodeJS.ProcessEnv;
28
+ fs: {
29
+ existsSync(path: string): boolean;
30
+ readFileSync(path: string, encoding: BufferEncoding): string;
31
+ };
32
+ run?: RunCommand;
33
+ dashboardEndpoint?: DashboardEndpointCaller;
34
+ commandTimeoutMs?: number;
35
+ externalRuntime?: ExternalRuntimeCandidate | null;
36
+ discoverExternalRuntime?: () => ExternalRuntimeCandidate | null;
37
+ pm2Apps?: (runtime: ExternalRuntimeCandidate) => Promise<Pm2AppSummary[]>;
38
+ }
39
+ export declare function createRuntimeService(deps: RuntimeServiceDeps): {
40
+ getState(): Promise<DesktopRuntimeState>;
41
+ start(): Promise<RunResult>;
42
+ stop(): Promise<RunResult>;
43
+ restart(): Promise<RunResult>;
44
+ takeover(): Promise<RunResult>;
45
+ dashboard(): Promise<RunResult>;
46
+ currentDashboard(): Promise<RunResult>;
47
+ };
48
+ export {};
49
+ //# sourceMappingURL=runtime-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-service.d.ts","sourceRoot":"","sources":["../../../src/desktop/main/runtime-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAA8B,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAsD,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE7G,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;CAChC;AAED,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;AAC7D,KAAK,uBAAuB,GAAG,CAAC,IAAI,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAGpF,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;CAChD;AAED,MAAM,MAAM,mBAAmB,GAAG,wBAAwB,CAAC;AA6D3D,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,YAAY,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,EAAE,EAAE;QACF,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAClC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,CAAC;KAC9D,CAAC;IACF,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAClD,uBAAuB,CAAC,EAAE,MAAM,wBAAwB,GAAG,IAAI,CAAC;IAChE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CAC3E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB;gBAuL7C,OAAO,CAAC,mBAAmB,CAAC;aAUzB,OAAO,CAAC,SAAS,CAAC;YAGnB,OAAO,CAAC,SAAS,CAAC;eAGf,OAAO,CAAC,SAAS,CAAC;gBAGjB,OAAO,CAAC,SAAS,CAAC;iBAajB,OAAO,CAAC,SAAS,CAAC;wBAKX,OAAO,CAAC,SAAS,CAAC;EAkB/C"}
@@ -0,0 +1,297 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { join } from 'node:path';
3
+ import { callDashboard } from '../../cli/dashboard-endpoint.js';
4
+ import { buildExternalBotmuxCommand } from './node-command.js';
5
+ import { classifyRuntimeSource, countActiveBotmuxDaemonApps } from './runtime-source.js';
6
+ const defaultCommandTimeoutMs = 30_000;
7
+ function defaultRun(cmd, timeoutMs = defaultCommandTimeoutMs) {
8
+ return new Promise(resolve => {
9
+ const child = spawn(cmd.command, cmd.args, { env: cmd.env, stdio: ['ignore', 'pipe', 'pipe'] });
10
+ let stdout = '';
11
+ let stderr = '';
12
+ let settled = false;
13
+ const timer = setTimeout(() => {
14
+ if (settled)
15
+ return;
16
+ settled = true;
17
+ // Timeout is surfaced as an ordinary failed action so renderer controls
18
+ // can recover and show the last error without waiting for child close.
19
+ child.kill();
20
+ resolve({
21
+ code: 1,
22
+ stdout,
23
+ stderr: `Command timed out after ${timeoutMs}ms`,
24
+ signal: null,
25
+ });
26
+ }, timeoutMs);
27
+ const finish = (result) => {
28
+ if (settled)
29
+ return;
30
+ settled = true;
31
+ clearTimeout(timer);
32
+ resolve(result);
33
+ };
34
+ child.stdout.on('data', chunk => {
35
+ stdout += String(chunk);
36
+ });
37
+ child.stderr.on('data', chunk => {
38
+ stderr += String(chunk);
39
+ });
40
+ child.on('error', error => {
41
+ finish({ code: 1, stdout, stderr: stderr || error.message, signal: null });
42
+ });
43
+ child.on('close', (code, signal) => {
44
+ // Signal-only exits still represent a failed desktop action to the UI.
45
+ finish({
46
+ code: code ?? 1,
47
+ stdout,
48
+ stderr: signal && !stderr ? `Process terminated by signal ${signal}` : stderr,
49
+ signal,
50
+ });
51
+ });
52
+ });
53
+ }
54
+ function dashboardEndpointResultToRunResult(result) {
55
+ if (result.ok) {
56
+ const stdout = result.localUrl
57
+ ? `${result.url}\n本地直连(平台异常时可用): ${result.localUrl}`
58
+ : result.url;
59
+ return { code: 0, stdout, stderr: '', signal: null };
60
+ }
61
+ const detail = result.detail ? `: ${result.detail}` : '';
62
+ return { code: 1, stdout: '', stderr: `${result.reason}${detail}`, signal: null };
63
+ }
64
+ export function createRuntimeService(deps) {
65
+ const run = deps.run ?? ((cmd) => defaultRun(cmd, deps.commandTimeoutMs));
66
+ const botsPath = join(deps.paths.botmuxHome, 'bots.json');
67
+ const installCliMessage = 'Install the global botmux CLI with `npm install -g botmux`, then reopen Botmux Desktop.';
68
+ function command(runtime, args) {
69
+ return buildExternalBotmuxCommand({
70
+ binPath: runtime.binPath,
71
+ botmuxHome: deps.paths.botmuxHome,
72
+ args,
73
+ baseEnv: deps.env,
74
+ pathEnv: runtime.pathEnv,
75
+ });
76
+ }
77
+ function currentExternalRuntime() {
78
+ return deps.discoverExternalRuntime ? deps.discoverExternalRuntime() : deps.externalRuntime ?? null;
79
+ }
80
+ function activeRuntime() {
81
+ return currentExternalRuntime();
82
+ }
83
+ function rejectedCliRequired() {
84
+ return {
85
+ code: 1,
86
+ stdout: '',
87
+ stderr: installCliMessage,
88
+ signal: null,
89
+ };
90
+ }
91
+ async function runCliAction(args) {
92
+ const runtime = activeRuntime();
93
+ if (!runtime)
94
+ return rejectedCliRequired();
95
+ const state = await service.getState();
96
+ if (!state.runtimeManaged && (state.status === 'running' || state.status === 'degraded')) {
97
+ return {
98
+ code: 1,
99
+ stdout: '',
100
+ stderr: state.message ?? 'Current botmux runtime is not controlled by the selected CLI',
101
+ signal: null,
102
+ };
103
+ }
104
+ return run(command(runtime, args));
105
+ }
106
+ function externalSource(runtime) {
107
+ return runtime.runtimeSource ?? 'global-cli';
108
+ }
109
+ function readBotConfig() {
110
+ if (!deps.fs.existsSync(botsPath))
111
+ return { status: 'not_configured', count: 0 };
112
+ try {
113
+ const parsed = JSON.parse(deps.fs.readFileSync(botsPath, 'utf-8'));
114
+ if (!Array.isArray(parsed))
115
+ return { status: 'invalid', message: 'bots.json must contain a JSON array' };
116
+ if (parsed.length === 0)
117
+ return { status: 'not_configured', count: 0 };
118
+ for (let i = 0; i < parsed.length; i += 1) {
119
+ const bot = parsed[i];
120
+ if (!bot || typeof bot !== 'object')
121
+ return { status: 'invalid', message: `bots.json entry ${i} must be an object` };
122
+ if (typeof bot.larkAppId !== 'string' || bot.larkAppId.length === 0) {
123
+ return { status: 'invalid', message: `bots.json entry ${i} is missing larkAppId` };
124
+ }
125
+ if (typeof bot.larkAppSecret !== 'string' || bot.larkAppSecret.length === 0) {
126
+ return { status: 'invalid', message: `bots.json entry ${i} is missing larkAppSecret` };
127
+ }
128
+ }
129
+ return { status: 'configured', count: parsed.length };
130
+ }
131
+ catch (err) {
132
+ return { status: 'invalid', message: err instanceof Error ? err.message : String(err) };
133
+ }
134
+ }
135
+ let stateInFlight = null;
136
+ async function computeState() {
137
+ const config = readBotConfig();
138
+ const active = currentExternalRuntime();
139
+ const selectedSource = active ? externalSource(active) : 'none';
140
+ if (config.status === 'invalid') {
141
+ // A malformed bots.json is actionable user state, not an empty setup.
142
+ return {
143
+ status: 'degraded',
144
+ appVersion: deps.appVersion,
145
+ runtimeVersion: active?.version ?? null,
146
+ runtimeSource: selectedSource,
147
+ runtimeManaged: false,
148
+ runtimePath: active?.cliPath ?? null,
149
+ botCount: 0,
150
+ onlineDaemonCount: 0,
151
+ attentionCount: 1,
152
+ dashboardUrl: null,
153
+ message: active ? config.message : `${config.message}. ${installCliMessage}`,
154
+ };
155
+ }
156
+ if (config.status === 'not_configured') {
157
+ return {
158
+ status: 'not_configured',
159
+ appVersion: deps.appVersion,
160
+ runtimeVersion: active?.version ?? null,
161
+ runtimeSource: selectedSource,
162
+ runtimeManaged: Boolean(active),
163
+ runtimePath: active?.cliPath ?? null,
164
+ botCount: 0,
165
+ onlineDaemonCount: 0,
166
+ attentionCount: 0,
167
+ dashboardUrl: null,
168
+ message: active ? undefined : installCliMessage,
169
+ };
170
+ }
171
+ if (!active) {
172
+ return {
173
+ status: 'degraded',
174
+ appVersion: deps.appVersion,
175
+ runtimeVersion: null,
176
+ runtimeSource: 'none',
177
+ runtimeManaged: false,
178
+ runtimePath: null,
179
+ botCount: config.count,
180
+ onlineDaemonCount: 0,
181
+ attentionCount: 1,
182
+ dashboardUrl: null,
183
+ message: installCliMessage,
184
+ };
185
+ }
186
+ if (deps.pm2Apps) {
187
+ try {
188
+ const pm2Apps = await deps.pm2Apps(active);
189
+ const source = classifyRuntimeSource({ pm2Apps });
190
+ const onlineDaemonCount = countActiveBotmuxDaemonApps(pm2Apps);
191
+ if (source.running) {
192
+ return {
193
+ status: 'running',
194
+ appVersion: deps.appVersion,
195
+ runtimeVersion: active.version,
196
+ runtimeSource: selectedSource,
197
+ runtimeManaged: true,
198
+ runtimePath: source.sourcePath ?? active.cliPath,
199
+ botCount: config.count,
200
+ onlineDaemonCount,
201
+ attentionCount: 0,
202
+ dashboardUrl: null,
203
+ };
204
+ }
205
+ }
206
+ catch (err) {
207
+ // PM2 discovery failure should be visible in the rail instead of
208
+ // silently pretending the runtime is stopped.
209
+ return {
210
+ status: 'degraded',
211
+ appVersion: deps.appVersion,
212
+ runtimeVersion: active.version,
213
+ runtimeSource: selectedSource,
214
+ runtimeManaged: false,
215
+ runtimePath: active.cliPath,
216
+ botCount: config.count,
217
+ onlineDaemonCount: 0,
218
+ attentionCount: 1,
219
+ dashboardUrl: null,
220
+ message: err instanceof Error ? err.message : String(err),
221
+ };
222
+ }
223
+ }
224
+ return {
225
+ status: 'stopped',
226
+ appVersion: deps.appVersion,
227
+ runtimeVersion: active.version,
228
+ runtimeSource: selectedSource,
229
+ runtimeManaged: true,
230
+ runtimePath: active.cliPath,
231
+ botCount: config.count,
232
+ onlineDaemonCount: 0,
233
+ attentionCount: 0,
234
+ dashboardUrl: null,
235
+ };
236
+ }
237
+ const service = {
238
+ getState() {
239
+ if (stateInFlight)
240
+ return stateInFlight;
241
+ // Desktop has both polling and renderer-initiated refreshes. Coalesce
242
+ // overlapping state reads so slow PM2 probes do not amplify into several
243
+ // concurrent `pm2 jlist` calls and false degraded states.
244
+ stateInFlight = computeState().finally(() => {
245
+ stateInFlight = null;
246
+ });
247
+ return stateInFlight;
248
+ },
249
+ async start() {
250
+ return runCliAction(['start']);
251
+ },
252
+ async stop() {
253
+ return runCliAction(['stop']);
254
+ },
255
+ async restart() {
256
+ return runCliAction(['restart']);
257
+ },
258
+ async takeover() {
259
+ const state = await this.getState();
260
+ // Compatibility shim for the old IPC name: "takeover" now means adopt
261
+ // the selected global CLI runtime. It never stops or replaces a runtime.
262
+ return {
263
+ code: state.runtimeManaged ? 0 : 1,
264
+ stdout: '',
265
+ stderr: state.runtimeManaged
266
+ ? ''
267
+ : 'Current botmux runtime is not controlled by the selected CLI',
268
+ signal: null,
269
+ };
270
+ },
271
+ async dashboard() {
272
+ const runtime = activeRuntime();
273
+ if (!runtime)
274
+ return rejectedCliRequired();
275
+ return run(command(runtime, ['dashboard']));
276
+ },
277
+ async currentDashboard() {
278
+ const runtime = activeRuntime();
279
+ if (!runtime)
280
+ return rejectedCliRequired();
281
+ // Desktop embeds the existing authenticated dashboard session by default.
282
+ // Falling back to rotation is decided by the IPC locator only when the
283
+ // dashboard explicitly reports that no active token exists yet.
284
+ const result = deps.dashboardEndpoint
285
+ ? await deps.dashboardEndpoint('/__cli/current')
286
+ : await callDashboard({
287
+ configDir: deps.paths.botmuxHome,
288
+ defaultPort: 7891,
289
+ envPort: deps.env.BOTMUX_DASHBOARD_PORT,
290
+ path: '/__cli/current',
291
+ });
292
+ return dashboardEndpointResultToRunResult(result);
293
+ },
294
+ };
295
+ return service;
296
+ }
297
+ //# sourceMappingURL=runtime-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-service.js","sourceRoot":"","sources":["../../../src/desktop/main/runtime-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface Pm2AppSummary {
2
+ name: string;
3
+ script?: string;
4
+ status?: string;
5
+ }
6
+ export interface RuntimeSourceInput {
7
+ pm2Apps: Pm2AppSummary[];
8
+ normalizePath?: (path: string) => string;
9
+ }
10
+ export interface RuntimeSource {
11
+ running: boolean;
12
+ sourcePath: string | null;
13
+ }
14
+ export declare function classifyRuntimeSource(input: RuntimeSourceInput): RuntimeSource;
15
+ export declare function countActiveBotmuxDaemonApps(pm2Apps: Pm2AppSummary[]): number;
16
+ export declare function parsePm2Apps(stdout: string): Pm2AppSummary[];
17
+ //# sourceMappingURL=runtime-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-source.d.ts","sourceRoot":"","sources":["../../../src/desktop/main/runtime-source.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAa9E;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,CAE5E;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAmB5D"}
@@ -0,0 +1,61 @@
1
+ import { resolve } from 'node:path';
2
+ export function classifyRuntimeSource(input) {
3
+ // CLI-first Desktop only needs to know whether a botmux PM2 process exists;
4
+ // ownership comes from the selected global CLI, not from a bundled path.
5
+ const botmuxApps = activeBotmuxApps(input.pm2Apps);
6
+ if (botmuxApps.length === 0)
7
+ return { running: false, sourcePath: null };
8
+ const sourcePaths = botmuxApps
9
+ .map(app => app.script ? normalizeRuntimePath(app.script, input.normalizePath) : null)
10
+ .filter((path) => path !== null);
11
+ return {
12
+ running: true,
13
+ sourcePath: sourcePaths[0] ?? null,
14
+ };
15
+ }
16
+ export function countActiveBotmuxDaemonApps(pm2Apps) {
17
+ return pm2Apps.filter(isBotmuxDaemonApp).filter(isActivePm2App).length;
18
+ }
19
+ export function parsePm2Apps(stdout) {
20
+ try {
21
+ const parsed = JSON.parse(stdout);
22
+ if (!Array.isArray(parsed))
23
+ return [];
24
+ return parsed.flatMap(app => {
25
+ if (!app || typeof app !== 'object')
26
+ return [];
27
+ const record = app;
28
+ if (typeof record.name !== 'string')
29
+ return [];
30
+ const script = typeof record.script === 'string'
31
+ ? record.script
32
+ : typeof record.pm2_env?.pm_exec_path === 'string'
33
+ ? record.pm2_env.pm_exec_path
34
+ : undefined;
35
+ const status = typeof record.pm2_env?.status === 'string' ? record.pm2_env.status : undefined;
36
+ return [{ name: record.name, script, status }];
37
+ });
38
+ }
39
+ catch {
40
+ return [];
41
+ }
42
+ }
43
+ function activeBotmuxApps(pm2Apps) {
44
+ return pm2Apps.filter(isBotmuxApp).filter(isActivePm2App);
45
+ }
46
+ function isBotmuxApp(app) {
47
+ return app.name === 'botmux-dashboard' || app.name === 'botmux' || app.name.startsWith('botmux-');
48
+ }
49
+ function isBotmuxDaemonApp(app) {
50
+ return app.name !== 'botmux-dashboard' && (app.name === 'botmux' || app.name.startsWith('botmux-'));
51
+ }
52
+ function isActivePm2App(app) {
53
+ // PM2 keeps stopped processes in jlist, so only live-ish statuses should hold
54
+ // the desktop UI in the running state. Missing status preserves old callers.
55
+ return !app.status || app.status === 'online' || app.status === 'launching';
56
+ }
57
+ function normalizeRuntimePath(path, normalizePath) {
58
+ const resolved = resolve(path);
59
+ return normalizePath ? normalizePath(resolved) : resolved;
60
+ }
61
+ //# sourceMappingURL=runtime-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-source.js","sourceRoot":"","sources":["../../../src/desktop/main/runtime-source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { Tray, type BrowserWindow } from 'electron';
2
+ export declare function createDesktopTray(args: {
3
+ window: BrowserWindow;
4
+ onStart: () => void;
5
+ onStop: () => void;
6
+ onRestart: () => void;
7
+ onOpenLogs: () => void;
8
+ onOpenHome: () => void;
9
+ }): Tray;
10
+ //# sourceMappingURL=tray.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tray.d.ts","sourceRoot":"","sources":["../../../src/desktop/main/tray.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,IAAI,EAAe,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAEvE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB,GAAG,IAAI,CA0BP"}
@@ -0,0 +1,27 @@
1
+ import { Menu, Tray, nativeImage } from 'electron';
2
+ export function createDesktopTray(args) {
3
+ // Keep the menu-bar lifecycle functional even before a branded tray icon
4
+ // asset exists.
5
+ const tray = new Tray(nativeImage.createEmpty());
6
+ const showWindow = () => {
7
+ args.window.show();
8
+ args.window.focus();
9
+ };
10
+ const menu = Menu.buildFromTemplate([
11
+ { label: 'Show Console', click: showWindow },
12
+ { type: 'separator' },
13
+ { label: 'Start Botmux', click: args.onStart },
14
+ { label: 'Stop Botmux', click: args.onStop },
15
+ { label: 'Restart Botmux', click: args.onRestart },
16
+ { type: 'separator' },
17
+ { label: 'Open Logs', click: args.onOpenLogs },
18
+ { label: 'Open Botmux Home', click: args.onOpenHome },
19
+ { type: 'separator' },
20
+ { label: 'Quit App', role: 'quit' },
21
+ ]);
22
+ tray.setToolTip('Botmux');
23
+ tray.setContextMenu(menu);
24
+ tray.on('click', showWindow);
25
+ return tray;
26
+ }
27
+ //# sourceMappingURL=tray.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tray.js","sourceRoot":"","sources":["../../../src/desktop/main/tray.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAsB,MAAM,UAAU,CAAC;AAEvE,MAAM,UAAU,iBAAiB,CAAC,IAOjC;IACC,yEAAyE;IACzE,gBAAgB;IAChB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACnB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC;QAClC,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,EAAE;QAC5C,EAAE,IAAI,EAAE,WAAW,EAAE;QACrB,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE;QAC9C,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE;QAC5C,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE;QAClD,EAAE,IAAI,EAAE,WAAW,EAAE;QACrB,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE;QAC9C,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE;QACrD,EAAE,IAAI,EAAE,WAAW,EAAE;QACrB,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE;KACpC,CAAC,CAAC;IAEH,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC1B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE7B,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { BrowserWindow } from 'electron';
2
+ export declare const desktopShellSidebarWidth = 250;
3
+ export declare const desktopDashboardPreferredContentWidth = 1320;
4
+ export declare const desktopDashboardMinContentWidth = 980;
5
+ export declare const desktopWindowPreferredWidth: number;
6
+ export declare const desktopWindowMinWidth: number;
7
+ export declare function desktopWindowInitialWidth(workAreaWidth?: number): number;
8
+ export declare function createMainWindow(preloadPath: string, rendererDir: string): BrowserWindow;
9
+ export declare function shouldOpenUrlExternally(url: string): boolean;
10
+ export declare function shouldOpenGuestNavigationExternally(url: string, currentUrl: string): boolean;
11
+ export declare function shouldBlockTopLevelNavigation(input: {
12
+ url: string;
13
+ isMainFrame: boolean;
14
+ rendererUrl: URL;
15
+ }): boolean;
16
+ //# sourceMappingURL=window.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/desktop/main/window.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAmC,MAAM,UAAU,CAAC;AAI1E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,qCAAqC,OAAO,CAAC;AAC1D,eAAO,MAAM,+BAA+B,MAAM,CAAC;AACnD,eAAO,MAAM,2BAA2B,QAAmE,CAAC;AAC5G,eAAO,MAAM,qBAAqB,QAA6D,CAAC;AAGhG,wBAAgB,yBAAyB,CACvC,aAAa,SAAgD,GAC5D,MAAM,CAOR;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,CAqDxF;AAWD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAW5F;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,GAAG,CAAC;CAClB,GAAG,OAAO,CAIV"}
@@ -0,0 +1,113 @@
1
+ import { BrowserWindow, screen, shell } from 'electron';
2
+ import { join } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ export const desktopShellSidebarWidth = 250;
5
+ export const desktopDashboardPreferredContentWidth = 1320;
6
+ export const desktopDashboardMinContentWidth = 980;
7
+ export const desktopWindowPreferredWidth = desktopDashboardPreferredContentWidth + desktopShellSidebarWidth;
8
+ export const desktopWindowMinWidth = desktopDashboardMinContentWidth + desktopShellSidebarWidth;
9
+ const desktopWindowScreenMargin = 48;
10
+ export function desktopWindowInitialWidth(workAreaWidth = screen.getPrimaryDisplay().workAreaSize.width) {
11
+ // The desktop shell adds a native rail around the browser dashboard; reserve
12
+ // that rail so the embedded pages do not start in their narrow layout.
13
+ return Math.max(desktopWindowMinWidth, Math.min(desktopWindowPreferredWidth, workAreaWidth - desktopWindowScreenMargin));
14
+ }
15
+ export function createMainWindow(preloadPath, rendererDir) {
16
+ const rendererPath = join(rendererDir, 'index.html');
17
+ const rendererUrl = pathToFileURL(rendererPath);
18
+ const win = new BrowserWindow({
19
+ width: desktopWindowInitialWidth(),
20
+ height: 860,
21
+ minWidth: desktopWindowMinWidth,
22
+ minHeight: 680,
23
+ title: 'Botmux',
24
+ webPreferences: {
25
+ // Renderer code is browser-only; privileged APIs stay behind preload IPC.
26
+ preload: preloadPath,
27
+ nodeIntegration: false,
28
+ contextIsolation: true,
29
+ sandbox: false,
30
+ webviewTag: true,
31
+ },
32
+ });
33
+ win.webContents.on('will-attach-webview', (event, webPreferences) => {
34
+ // The dashboard runs in a guest WebContents; keep it isolated from Electron
35
+ // and Node even though the shell itself owns privileged IPC through preload.
36
+ webPreferences.nodeIntegration = false;
37
+ webPreferences.contextIsolation = true;
38
+ webPreferences.sandbox = true;
39
+ delete webPreferences.preload;
40
+ });
41
+ configureExternalOpenHandler(win.webContents);
42
+ win.webContents.on('did-attach-webview', (_event, webContents) => {
43
+ // target=_blank links live inside the dashboard guest, not the shell page;
44
+ // hook the guest too so terminal/changelog/group links leave Electron safely.
45
+ configureExternalOpenHandler(webContents);
46
+ webContents.on('will-navigate', (event, url) => {
47
+ if (!shouldOpenGuestNavigationExternally(url, webContents.getURL()))
48
+ return;
49
+ event.preventDefault();
50
+ void shell.openExternal(url);
51
+ });
52
+ });
53
+ win.webContents.on('will-frame-navigate', event => {
54
+ if (shouldBlockTopLevelNavigation({
55
+ url: event.url,
56
+ isMainFrame: event.isMainFrame,
57
+ rendererUrl,
58
+ })) {
59
+ event.preventDefault();
60
+ }
61
+ });
62
+ void win.loadFile(rendererPath).catch(error => {
63
+ console.error('[desktop] failed to load renderer', error);
64
+ });
65
+ return win;
66
+ }
67
+ function configureExternalOpenHandler(contents) {
68
+ contents.setWindowOpenHandler(({ url }) => {
69
+ // Let dashboard links open in the user's browser, never in a privileged
70
+ // Electron child window.
71
+ if (shouldOpenUrlExternally(url))
72
+ void shell.openExternal(url);
73
+ return { action: 'deny' };
74
+ });
75
+ }
76
+ export function shouldOpenUrlExternally(url) {
77
+ try {
78
+ const parsed = new URL(url);
79
+ return parsed.protocol === 'http:' || parsed.protocol === 'https:';
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ export function shouldOpenGuestNavigationExternally(url, currentUrl) {
86
+ try {
87
+ const parsed = new URL(url);
88
+ const current = new URL(currentUrl);
89
+ // Let the dashboard's initial load and same-origin hash/path changes stay in
90
+ // the webview; terminal panes and Feishu/browser links use another origin.
91
+ if (current.protocol !== 'http:' && current.protocol !== 'https:')
92
+ return false;
93
+ return shouldOpenUrlExternally(url) && parsed.origin !== current.origin;
94
+ }
95
+ catch {
96
+ return false;
97
+ }
98
+ }
99
+ export function shouldBlockTopLevelNavigation(input) {
100
+ // Dashboard guest views are allowed to reach the local HTTP dashboard; the
101
+ // guard only keeps the privileged desktop shell itself on the bundled file.
102
+ return input.isMainFrame && !isRendererUrl(input.url, input.rendererUrl);
103
+ }
104
+ function isRendererUrl(url, rendererUrl) {
105
+ try {
106
+ const parsed = new URL(url);
107
+ return parsed.protocol === 'file:' && parsed.pathname === rendererUrl.pathname;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ //# sourceMappingURL=window.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.js","sourceRoot":"","sources":["../../../src/desktop/main/window.ts"],"names":[],"mappings":"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"}