@wong2kim/wmux 1.0.0 → 1.0.1

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 (110) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +209 -157
  3. package/dist/cli/cli/client.js +1 -1
  4. package/dist/cli/cli/commands/browser.js +19 -19
  5. package/dist/cli/cli/index.js +58 -58
  6. package/dist/cli/shared/constants.js +17 -4
  7. package/dist/mcp/shared/constants.js +17 -4
  8. package/package.json +96 -84
  9. package/assets/icon.ico +0 -0
  10. package/assets/icon.svg +0 -6
  11. package/forge.config.ts +0 -61
  12. package/index.html +0 -12
  13. package/postcss.config.js +0 -6
  14. package/src/cli/client.ts +0 -76
  15. package/src/cli/commands/browser.ts +0 -128
  16. package/src/cli/commands/input.ts +0 -72
  17. package/src/cli/commands/notify.ts +0 -29
  18. package/src/cli/commands/pane.ts +0 -90
  19. package/src/cli/commands/surface.ts +0 -102
  20. package/src/cli/commands/system.ts +0 -95
  21. package/src/cli/commands/workspace.ts +0 -116
  22. package/src/cli/index.ts +0 -145
  23. package/src/cli/utils.ts +0 -44
  24. package/src/main/index.ts +0 -86
  25. package/src/main/ipc/handlers/clipboard.handler.ts +0 -20
  26. package/src/main/ipc/handlers/metadata.handler.ts +0 -56
  27. package/src/main/ipc/handlers/pty.handler.ts +0 -69
  28. package/src/main/ipc/handlers/session.handler.ts +0 -17
  29. package/src/main/ipc/handlers/shell.handler.ts +0 -11
  30. package/src/main/ipc/registerHandlers.ts +0 -31
  31. package/src/main/mcp/McpRegistrar.ts +0 -156
  32. package/src/main/metadata/MetadataCollector.ts +0 -58
  33. package/src/main/notification/ToastManager.ts +0 -32
  34. package/src/main/pipe/PipeServer.ts +0 -190
  35. package/src/main/pipe/RpcRouter.ts +0 -46
  36. package/src/main/pipe/handlers/_bridge.ts +0 -40
  37. package/src/main/pipe/handlers/browser.rpc.ts +0 -132
  38. package/src/main/pipe/handlers/input.rpc.ts +0 -120
  39. package/src/main/pipe/handlers/meta.rpc.ts +0 -59
  40. package/src/main/pipe/handlers/notify.rpc.ts +0 -53
  41. package/src/main/pipe/handlers/pane.rpc.ts +0 -39
  42. package/src/main/pipe/handlers/surface.rpc.ts +0 -43
  43. package/src/main/pipe/handlers/system.rpc.ts +0 -36
  44. package/src/main/pipe/handlers/workspace.rpc.ts +0 -52
  45. package/src/main/pty/AgentDetector.ts +0 -247
  46. package/src/main/pty/OscParser.ts +0 -81
  47. package/src/main/pty/PTYBridge.ts +0 -88
  48. package/src/main/pty/PTYManager.ts +0 -104
  49. package/src/main/pty/ShellDetector.ts +0 -63
  50. package/src/main/session/SessionManager.ts +0 -53
  51. package/src/main/updater/AutoUpdater.ts +0 -132
  52. package/src/main/window/createWindow.ts +0 -71
  53. package/src/mcp/README.md +0 -56
  54. package/src/mcp/index.ts +0 -153
  55. package/src/mcp/wmux-client.ts +0 -127
  56. package/src/preload/index.ts +0 -111
  57. package/src/preload/preload.ts +0 -108
  58. package/src/renderer/App.tsx +0 -5
  59. package/src/renderer/components/Browser/BrowserPanel.tsx +0 -219
  60. package/src/renderer/components/Browser/BrowserToolbar.tsx +0 -253
  61. package/src/renderer/components/Company/ApprovalDialog.tsx +0 -3
  62. package/src/renderer/components/Company/CompanyView.tsx +0 -7
  63. package/src/renderer/components/Company/MessageFeedPanel.tsx +0 -3
  64. package/src/renderer/components/Layout/AppLayout.tsx +0 -234
  65. package/src/renderer/components/Notification/NotificationPanel.tsx +0 -129
  66. package/src/renderer/components/Palette/CommandPalette.tsx +0 -409
  67. package/src/renderer/components/Palette/PaletteItem.tsx +0 -55
  68. package/src/renderer/components/Pane/Pane.tsx +0 -122
  69. package/src/renderer/components/Pane/PaneContainer.tsx +0 -41
  70. package/src/renderer/components/Pane/SurfaceTabs.tsx +0 -46
  71. package/src/renderer/components/Settings/SettingsPanel.tsx +0 -886
  72. package/src/renderer/components/Sidebar/MiniSidebar.tsx +0 -67
  73. package/src/renderer/components/Sidebar/Sidebar.tsx +0 -84
  74. package/src/renderer/components/Sidebar/WorkspaceItem.tsx +0 -241
  75. package/src/renderer/components/StatusBar/StatusBar.tsx +0 -93
  76. package/src/renderer/components/Terminal/SearchBar.tsx +0 -126
  77. package/src/renderer/components/Terminal/Terminal.tsx +0 -102
  78. package/src/renderer/components/Terminal/ViCopyMode.tsx +0 -104
  79. package/src/renderer/hooks/useKeyboard.ts +0 -310
  80. package/src/renderer/hooks/useNotificationListener.ts +0 -80
  81. package/src/renderer/hooks/useNotificationSound.ts +0 -75
  82. package/src/renderer/hooks/useRpcBridge.ts +0 -451
  83. package/src/renderer/hooks/useT.ts +0 -11
  84. package/src/renderer/hooks/useTerminal.ts +0 -349
  85. package/src/renderer/hooks/useViCopyMode.ts +0 -320
  86. package/src/renderer/i18n/index.ts +0 -69
  87. package/src/renderer/i18n/locales/en.ts +0 -157
  88. package/src/renderer/i18n/locales/ja.ts +0 -155
  89. package/src/renderer/i18n/locales/ko.ts +0 -155
  90. package/src/renderer/i18n/locales/zh.ts +0 -155
  91. package/src/renderer/index.tsx +0 -6
  92. package/src/renderer/stores/index.ts +0 -19
  93. package/src/renderer/stores/slices/notificationSlice.ts +0 -56
  94. package/src/renderer/stores/slices/paneSlice.ts +0 -141
  95. package/src/renderer/stores/slices/surfaceSlice.ts +0 -122
  96. package/src/renderer/stores/slices/uiSlice.ts +0 -247
  97. package/src/renderer/stores/slices/workspaceSlice.ts +0 -120
  98. package/src/renderer/styles/globals.css +0 -150
  99. package/src/renderer/themes.ts +0 -99
  100. package/src/shared/constants.ts +0 -53
  101. package/src/shared/electron.d.ts +0 -11
  102. package/src/shared/rpc.ts +0 -71
  103. package/src/shared/types.ts +0 -176
  104. package/tailwind.config.js +0 -11
  105. package/tsconfig.cli.json +0 -24
  106. package/tsconfig.json +0 -21
  107. package/tsconfig.mcp.json +0 -25
  108. package/vite.main.config.ts +0 -14
  109. package/vite.preload.config.ts +0 -9
  110. package/vite.renderer.config.ts +0 -6
@@ -1,90 +0,0 @@
1
- import { sendRequest } from '../client';
2
- import { printResult, printError, parseFlag } from '../utils';
3
- import type { RpcResponse } from '../../shared/rpc';
4
-
5
- interface PaneInfo {
6
- id: string;
7
- type: 'leaf' | 'branch';
8
- direction?: string;
9
- activeSurfaceId?: string;
10
- }
11
-
12
- function formatPaneList(result: unknown): void {
13
- const list = result as PaneInfo[];
14
- if (!Array.isArray(list) || list.length === 0) {
15
- console.log('No panes found.');
16
- return;
17
- }
18
- const maxId = Math.max(...list.map((p) => p.id.length));
19
- console.log('ID'.padEnd(maxId + 2) + 'TYPE'.padEnd(8) + 'DETAILS');
20
- console.log('-'.repeat(maxId + 30));
21
- for (const p of list) {
22
- let details = '';
23
- if (p.type === 'leaf' && p.activeSurfaceId) {
24
- details = `active surface: ${p.activeSurfaceId}`;
25
- } else if (p.type === 'branch' && p.direction) {
26
- details = `direction: ${p.direction}`;
27
- }
28
- console.log(p.id.padEnd(maxId + 2) + p.type.padEnd(8) + details);
29
- }
30
- }
31
-
32
- export async function handlePane(
33
- cmd: string,
34
- args: string[],
35
- jsonMode: boolean
36
- ): Promise<void> {
37
- let response: RpcResponse;
38
-
39
- switch (cmd) {
40
- case 'list-panes': {
41
- response = await sendRequest('pane.list', {});
42
- if (jsonMode) {
43
- printResult(response);
44
- } else {
45
- if (!response.ok) { printError(response); return; }
46
- formatPaneList(response.result);
47
- }
48
- break;
49
- }
50
-
51
- case 'focus-pane': {
52
- const id = args[0];
53
- if (!id) {
54
- console.error('Error: focus-pane requires <id>');
55
- process.exit(1);
56
- }
57
- response = await sendRequest('pane.focus', { id });
58
- if (jsonMode) {
59
- printResult(response);
60
- } else {
61
- if (!response.ok) { printError(response); return; }
62
- console.log(`Focused pane: ${id}`);
63
- }
64
- break;
65
- }
66
-
67
- case 'split': {
68
- const direction = parseFlag(args, '--direction') ?? 'right';
69
- if (direction !== 'right' && direction !== 'down') {
70
- console.error('Error: --direction must be "right" or "down"');
71
- process.exit(1);
72
- }
73
- // right → horizontal, down → vertical (server expects horizontal/vertical)
74
- const dirMap: Record<string, string> = { right: 'horizontal', down: 'vertical' };
75
- const mapped = dirMap[direction] || direction;
76
- response = await sendRequest('pane.split', { direction: mapped });
77
- if (jsonMode) {
78
- printResult(response);
79
- } else {
80
- if (!response.ok) { printError(response); return; }
81
- console.log(`Split pane ${direction}.`);
82
- }
83
- break;
84
- }
85
-
86
- default:
87
- console.error(`Unknown pane command: ${cmd}`);
88
- process.exit(1);
89
- }
90
- }
@@ -1,102 +0,0 @@
1
- import { sendRequest } from '../client';
2
- import { printResult, printError } from '../utils';
3
- import type { RpcResponse } from '../../shared/rpc';
4
-
5
- interface SurfaceInfo {
6
- id: string;
7
- title: string;
8
- shell: string;
9
- cwd: string;
10
- }
11
-
12
- function formatSurfaceList(result: unknown): void {
13
- const list = result as SurfaceInfo[];
14
- if (!Array.isArray(list) || list.length === 0) {
15
- console.log('No surfaces found.');
16
- return;
17
- }
18
- const maxId = Math.max(...list.map((s) => s.id.length));
19
- const maxTitle = Math.max(...list.map((s) => (s.title ?? '').length), 5);
20
- console.log(
21
- 'ID'.padEnd(maxId + 2) +
22
- 'TITLE'.padEnd(maxTitle + 2) +
23
- 'SHELL'
24
- );
25
- console.log('-'.repeat(maxId + maxTitle + 20));
26
- for (const s of list) {
27
- console.log(
28
- s.id.padEnd(maxId + 2) +
29
- (s.title ?? '').padEnd(maxTitle + 2) +
30
- (s.shell ?? '')
31
- );
32
- }
33
- }
34
-
35
- export async function handleSurface(
36
- cmd: string,
37
- args: string[],
38
- jsonMode: boolean
39
- ): Promise<void> {
40
- let response: RpcResponse;
41
-
42
- switch (cmd) {
43
- case 'list-surfaces': {
44
- response = await sendRequest('surface.list', {});
45
- if (jsonMode) {
46
- printResult(response);
47
- } else {
48
- if (!response.ok) { printError(response); return; }
49
- formatSurfaceList(response.result);
50
- }
51
- break;
52
- }
53
-
54
- case 'new-surface': {
55
- response = await sendRequest('surface.new', {});
56
- if (jsonMode) {
57
- printResult(response);
58
- } else {
59
- if (!response.ok) { printError(response); return; }
60
- const s = response.result as SurfaceInfo;
61
- console.log(`Created surface: ${s?.id ?? '(unknown)'}`);
62
- }
63
- break;
64
- }
65
-
66
- case 'focus-surface': {
67
- const id = args[0];
68
- if (!id) {
69
- console.error('Error: focus-surface requires <id>');
70
- process.exit(1);
71
- }
72
- response = await sendRequest('surface.focus', { id });
73
- if (jsonMode) {
74
- printResult(response);
75
- } else {
76
- if (!response.ok) { printError(response); return; }
77
- console.log(`Focused surface: ${id}`);
78
- }
79
- break;
80
- }
81
-
82
- case 'close-surface': {
83
- const id = args[0];
84
- if (!id) {
85
- console.error('Error: close-surface requires <id>');
86
- process.exit(1);
87
- }
88
- response = await sendRequest('surface.close', { id });
89
- if (jsonMode) {
90
- printResult(response);
91
- } else {
92
- if (!response.ok) { printError(response); return; }
93
- console.log(`Closed surface: ${id}`);
94
- }
95
- break;
96
- }
97
-
98
- default:
99
- console.error(`Unknown surface command: ${cmd}`);
100
- process.exit(1);
101
- }
102
- }
@@ -1,95 +0,0 @@
1
- import { sendRequest } from '../client';
2
- import { printResult, printError } from '../utils';
3
- import type { RpcResponse } from '../../shared/rpc';
4
-
5
- interface IdentifyResult {
6
- app: string;
7
- version: string;
8
- platform: string;
9
- }
10
-
11
- export async function handleSystem(
12
- cmd: string,
13
- args: string[],
14
- jsonMode: boolean
15
- ): Promise<void> {
16
- let response: RpcResponse;
17
-
18
- switch (cmd) {
19
- case 'identify': {
20
- response = await sendRequest('system.identify', {});
21
- if (jsonMode) {
22
- printResult(response);
23
- } else {
24
- if (!response.ok) { printError(response); return; }
25
- const info = response.result as IdentifyResult;
26
- console.log(`app: ${info?.app ?? 'wmux'}`);
27
- console.log(`version: ${info?.version ?? '1.0.0'}`);
28
- console.log(`platform: ${info?.platform ?? process.platform}`);
29
- }
30
- break;
31
- }
32
-
33
- case 'capabilities': {
34
- response = await sendRequest('system.capabilities', {});
35
- if (jsonMode) {
36
- printResult(response);
37
- } else {
38
- if (!response.ok) { printError(response); return; }
39
- // server may return { methods: string[] } or string[] directly
40
- const result = response.result as { methods?: string[] } | string[];
41
- const methods = Array.isArray(result) ? result : (result?.methods || []);
42
- if (methods.length > 0) {
43
- console.log('Supported RPC methods:');
44
- for (const m of methods) {
45
- console.log(` ${m}`);
46
- }
47
- } else {
48
- console.log(JSON.stringify(response.result, null, 2));
49
- }
50
- }
51
- break;
52
- }
53
-
54
- case 'set-status': {
55
- const text = args[0];
56
- if (text === undefined) {
57
- console.error('Error: set-status requires <text>');
58
- process.exit(1);
59
- }
60
- response = await sendRequest('meta.setStatus', { text });
61
- if (jsonMode) {
62
- printResult(response);
63
- } else {
64
- if (!response.ok) { printError(response); return; }
65
- console.log(`Status set: "${text}"`);
66
- }
67
- break;
68
- }
69
-
70
- case 'set-progress': {
71
- const raw = args[0];
72
- if (raw === undefined) {
73
- console.error('Error: set-progress requires <0-100>');
74
- process.exit(1);
75
- }
76
- const value = Number(raw);
77
- if (isNaN(value) || value < 0 || value > 100) {
78
- console.error('Error: progress value must be a number between 0 and 100');
79
- process.exit(1);
80
- }
81
- response = await sendRequest('meta.setProgress', { value });
82
- if (jsonMode) {
83
- printResult(response);
84
- } else {
85
- if (!response.ok) { printError(response); return; }
86
- console.log(`Progress set: ${value}%`);
87
- }
88
- break;
89
- }
90
-
91
- default:
92
- console.error(`Unknown system command: ${cmd}`);
93
- process.exit(1);
94
- }
95
- }
@@ -1,116 +0,0 @@
1
- import { sendRequest } from '../client';
2
- import { printResult, printError, parseFlag } from '../utils';
3
- import type { RpcResponse } from '../../shared/rpc';
4
-
5
- interface WorkspaceInfo {
6
- id: string;
7
- name: string;
8
- isActive?: boolean;
9
- }
10
-
11
- function formatWorkspaceList(result: unknown): void {
12
- const list = result as WorkspaceInfo[];
13
- if (!Array.isArray(list) || list.length === 0) {
14
- console.log('No workspaces found.');
15
- return;
16
- }
17
- const maxId = Math.max(...list.map((w) => w.id.length));
18
- console.log(
19
- 'ID'.padEnd(maxId + 2) + 'NAME' + ' ' + 'STATUS'
20
- );
21
- console.log('-'.repeat(maxId + 30));
22
- for (const ws of list) {
23
- const active = ws.isActive ? ' (active)' : '';
24
- console.log(ws.id.padEnd(maxId + 2) + ws.name + active);
25
- }
26
- }
27
-
28
- function formatWorkspaceCurrent(result: unknown): void {
29
- const ws = result as WorkspaceInfo | null;
30
- if (!ws) {
31
- console.log('No active workspace.');
32
- return;
33
- }
34
- console.log(`Current workspace: ${ws.name} (${ws.id})`);
35
- }
36
-
37
- export async function handleWorkspace(
38
- cmd: string,
39
- args: string[],
40
- jsonMode: boolean
41
- ): Promise<void> {
42
- let response: RpcResponse;
43
-
44
- switch (cmd) {
45
- case 'list-workspaces': {
46
- response = await sendRequest('workspace.list', {});
47
- if (jsonMode) {
48
- printResult(response);
49
- } else {
50
- if (!response.ok) { printError(response); return; }
51
- formatWorkspaceList(response.result);
52
- }
53
- break;
54
- }
55
-
56
- case 'new-workspace': {
57
- const name = parseFlag(args, '--name') ?? `workspace-${Date.now()}`;
58
- response = await sendRequest('workspace.new', { name });
59
- if (jsonMode) {
60
- printResult(response);
61
- } else {
62
- if (!response.ok) { printError(response); return; }
63
- const ws = response.result as WorkspaceInfo;
64
- console.log(`Created workspace: ${ws?.name ?? name} (${ws?.id ?? ''})`);
65
- }
66
- break;
67
- }
68
-
69
- case 'focus-workspace': {
70
- const id = args[0];
71
- if (!id) {
72
- console.error('Error: focus-workspace requires <id>');
73
- process.exit(1);
74
- }
75
- response = await sendRequest('workspace.focus', { id });
76
- if (jsonMode) {
77
- printResult(response);
78
- } else {
79
- if (!response.ok) { printError(response); return; }
80
- console.log(`Focused workspace: ${id}`);
81
- }
82
- break;
83
- }
84
-
85
- case 'close-workspace': {
86
- const id = args[0];
87
- if (!id) {
88
- console.error('Error: close-workspace requires <id>');
89
- process.exit(1);
90
- }
91
- response = await sendRequest('workspace.close', { id });
92
- if (jsonMode) {
93
- printResult(response);
94
- } else {
95
- if (!response.ok) { printError(response); return; }
96
- console.log(`Closed workspace: ${id}`);
97
- }
98
- break;
99
- }
100
-
101
- case 'current-workspace': {
102
- response = await sendRequest('workspace.current', {});
103
- if (jsonMode) {
104
- printResult(response);
105
- } else {
106
- if (!response.ok) { printError(response); return; }
107
- formatWorkspaceCurrent(response.result);
108
- }
109
- break;
110
- }
111
-
112
- default:
113
- console.error(`Unknown workspace command: ${cmd}`);
114
- process.exit(1);
115
- }
116
- }
package/src/cli/index.ts DELETED
@@ -1,145 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- process.on('SIGINT', () => {
4
- process.exit(130);
5
- });
6
-
7
- import { hasFlag } from './utils';
8
- import { handleWorkspace } from './commands/workspace';
9
- import { handleSurface } from './commands/surface';
10
- import { handlePane } from './commands/pane';
11
- import { handleInput } from './commands/input';
12
- import { handleNotify } from './commands/notify';
13
- import { handleSystem } from './commands/system';
14
- import { handleBrowser } from './commands/browser';
15
-
16
- const HELP_TEXT = `
17
- wmux CLI
18
-
19
- USAGE
20
- wmux <command> [options]
21
-
22
- WORKSPACE COMMANDS
23
- list-workspaces List all workspaces
24
- new-workspace [--name <name>] Create a new workspace
25
- focus-workspace <id> Focus a workspace by ID
26
- close-workspace <id> Close a workspace by ID
27
- current-workspace Show the active workspace
28
-
29
- SURFACE COMMANDS
30
- list-surfaces List all surfaces in the active workspace
31
- new-surface Open a new surface (terminal tab)
32
- focus-surface <id> Focus a surface by ID
33
- close-surface <id> Close a surface by ID
34
-
35
- PANE COMMANDS
36
- list-panes List all panes in the active workspace
37
- focus-pane <id> Focus a pane by ID
38
- split [--direction right|down] Split the active pane (default: right)
39
-
40
- INPUT COMMANDS
41
- send <text> Send text to the active terminal
42
- send-key <keystroke> Send a key (e.g. Enter, ctrl-c, Tab)
43
- read-screen Read the current terminal screen content
44
-
45
- NOTIFICATION COMMANDS
46
- notify --title <title> --body <body> Show a notification in wmux
47
-
48
- SYSTEM COMMANDS
49
- set-status <text> Set a status message on the active workspace
50
- set-progress <0-100> Set a progress value on the active workspace
51
- identify Show wmux app info
52
- capabilities List all supported RPC methods
53
-
54
- BROWSER COMMANDS
55
- browser snapshot Return the full page HTML of the active browser surface
56
- browser click <selector> Click an element by CSS selector
57
- browser fill <selector> <text> Fill an input field by CSS selector
58
- browser eval <code> Execute JavaScript in the browser context
59
- browser navigate <url> Navigate the browser surface to a URL
60
-
61
- GLOBAL FLAGS
62
- --json Output raw JSON (useful for scripting)
63
- --help Show this help text
64
-
65
- EXAMPLES
66
- wmux list-workspaces
67
- wmux new-workspace --name dev
68
- wmux send "echo hello"
69
- wmux notify --title "Done" --body "Build finished"
70
- wmux identify --json
71
- wmux browser snapshot
72
- wmux browser navigate "https://example.com"
73
- wmux browser click "#login-btn"
74
- `.trimStart();
75
-
76
- const WORKSPACE_CMDS = new Set([
77
- 'list-workspaces',
78
- 'new-workspace',
79
- 'focus-workspace',
80
- 'close-workspace',
81
- 'current-workspace',
82
- ]);
83
-
84
- const SURFACE_CMDS = new Set([
85
- 'list-surfaces',
86
- 'new-surface',
87
- 'focus-surface',
88
- 'close-surface',
89
- ]);
90
-
91
- const PANE_CMDS = new Set(['list-panes', 'focus-pane', 'split']);
92
-
93
- const INPUT_CMDS = new Set(['send', 'send-key', 'read-screen']);
94
-
95
- const SYSTEM_CMDS = new Set([
96
- 'identify',
97
- 'capabilities',
98
- 'set-status',
99
- 'set-progress',
100
- ]);
101
-
102
- async function main(): Promise<void> {
103
- // process.argv = ['node', 'index.js', ...userArgs]
104
- const argv = process.argv.slice(2);
105
-
106
- if (argv.length === 0 || hasFlag(argv, '--help') || hasFlag(argv, '-h')) {
107
- process.stdout.write(HELP_TEXT);
108
- process.exit(0);
109
- }
110
-
111
- const jsonMode = hasFlag(argv, '--json');
112
-
113
- // Strip global flags so commands see clean args
114
- const args = argv.filter((a) => a !== '--json' && a !== '--help' && a !== '-h');
115
-
116
- const cmd = args[0];
117
- const rest = args.slice(1);
118
-
119
- try {
120
- if (WORKSPACE_CMDS.has(cmd)) {
121
- await handleWorkspace(cmd, rest, jsonMode);
122
- } else if (SURFACE_CMDS.has(cmd)) {
123
- await handleSurface(cmd, rest, jsonMode);
124
- } else if (PANE_CMDS.has(cmd)) {
125
- await handlePane(cmd, rest, jsonMode);
126
- } else if (INPUT_CMDS.has(cmd)) {
127
- await handleInput(cmd, rest, jsonMode);
128
- } else if (cmd === 'notify') {
129
- await handleNotify(rest, jsonMode);
130
- } else if (SYSTEM_CMDS.has(cmd)) {
131
- await handleSystem(cmd, rest, jsonMode);
132
- } else if (cmd === 'browser') {
133
- await handleBrowser(rest, jsonMode);
134
- } else {
135
- console.error(`Unknown command: "${cmd}". Run 'wmux --help' for usage.`);
136
- process.exit(1);
137
- }
138
- } catch (err: unknown) {
139
- const message = err instanceof Error ? err.message : String(err);
140
- console.error(message);
141
- process.exit(1);
142
- }
143
- }
144
-
145
- main();
package/src/cli/utils.ts DELETED
@@ -1,44 +0,0 @@
1
- import type { RpcResponse } from '../shared/rpc';
2
-
3
- /**
4
- * Print the result field of a successful RPC response as JSON.
5
- * If the response contains an error, the error is printed to stderr and
6
- * the process exits with code 1.
7
- */
8
- export function printResult(response: RpcResponse): void {
9
- if (!response.ok) {
10
- printError(response);
11
- return;
12
- }
13
- console.log(JSON.stringify(response.result, null, 2));
14
- }
15
-
16
- /**
17
- * Print the error field of a failed RPC response to stderr and exit with 1.
18
- */
19
- export function printError(response: RpcResponse): void {
20
- const msg = !response.ok ? response.error : 'Unknown error from wmux';
21
- console.error(`Error: ${msg}`);
22
- process.exit(1);
23
- }
24
-
25
- /**
26
- * Parse a named flag value from an argv array.
27
- * e.g. parseFlag(['--name', 'dev'], '--name') => 'dev'
28
- * Returns undefined when the flag is not present.
29
- */
30
- export function parseFlag(args: string[], flag: string): string | undefined {
31
- const idx = args.indexOf(flag);
32
- if (idx === -1) return undefined;
33
- const value = args[idx + 1];
34
- if (value === undefined || value.startsWith('-')) return undefined;
35
- return value;
36
- }
37
-
38
- /**
39
- * Check whether a bare flag is present in argv.
40
- * e.g. hasFlag(['--json', 'identify'], '--json') => true
41
- */
42
- export function hasFlag(args: string[], flag: string): boolean {
43
- return args.includes(flag);
44
- }
package/src/main/index.ts DELETED
@@ -1,86 +0,0 @@
1
- process.on('unhandledRejection', (reason) => {
2
- console.error('[Main] Unhandled rejection:', reason);
3
- });
4
- process.on('uncaughtException', (err) => {
5
- console.error('[Main] Uncaught exception:', err);
6
- });
7
-
8
- import { app, BrowserWindow } from 'electron';
9
- import started from 'electron-squirrel-startup';
10
- import { createWindow } from './window/createWindow';
11
- import { PTYManager } from './pty/PTYManager';
12
- import { PTYBridge } from './pty/PTYBridge';
13
- import { registerAllHandlers } from './ipc/registerHandlers';
14
- import { RpcRouter } from './pipe/RpcRouter';
15
- import { PipeServer } from './pipe/PipeServer';
16
- import { registerWorkspaceRpc } from './pipe/handlers/workspace.rpc';
17
- import { registerSurfaceRpc } from './pipe/handlers/surface.rpc';
18
- import { registerPaneRpc } from './pipe/handlers/pane.rpc';
19
- import { registerInputRpc } from './pipe/handlers/input.rpc';
20
- import { registerNotifyRpc } from './pipe/handlers/notify.rpc';
21
- import { registerMetaRpc } from './pipe/handlers/meta.rpc';
22
- import { registerSystemRpc } from './pipe/handlers/system.rpc';
23
- import { registerBrowserRpc } from './pipe/handlers/browser.rpc';
24
- import { AutoUpdater } from './updater/AutoUpdater';
25
- import { McpRegistrar } from './mcp/McpRegistrar';
26
-
27
- if (started) {
28
- app.quit();
29
- }
30
-
31
- const ptyManager = new PTYManager();
32
- let mainWindow: BrowserWindow | null = null;
33
- const ptyBridge = new PTYBridge(ptyManager, () => mainWindow);
34
- const autoUpdater = new AutoUpdater(() => mainWindow);
35
-
36
- const rpcRouter = new RpcRouter();
37
- const pipeServer = new PipeServer(rpcRouter);
38
- const mcpRegistrar = new McpRegistrar();
39
-
40
- const cleanupHandlers = registerAllHandlers(ptyManager, ptyBridge, () => mainWindow);
41
- registerWorkspaceRpc(rpcRouter, () => mainWindow);
42
- registerSurfaceRpc(rpcRouter, () => mainWindow);
43
- registerPaneRpc(rpcRouter, () => mainWindow);
44
- registerInputRpc(rpcRouter, ptyManager, () => mainWindow);
45
- registerNotifyRpc(rpcRouter, () => mainWindow);
46
- registerMetaRpc(rpcRouter, () => mainWindow);
47
- registerSystemRpc(rpcRouter);
48
- registerBrowserRpc(rpcRouter, () => mainWindow);
49
-
50
- app.on('ready', () => {
51
- console.log('[Main] App ready, creating window...');
52
- mainWindow = createWindow();
53
- console.log('[Main] Window created:', !!mainWindow);
54
- mainWindow.on('closed', () => {
55
- mainWindow = null;
56
- });
57
- mainWindow.webContents.on('did-fail-load', (_e, code, desc) => {
58
- console.error('[Main] Page failed to load:', code, desc);
59
- });
60
- mainWindow.webContents.on('did-finish-load', () => {
61
- console.log('[Main] Page loaded successfully');
62
- });
63
- pipeServer.start();
64
- const authToken = pipeServer.getAuthToken();
65
- ptyManager.setAuthToken(authToken);
66
- mcpRegistrar.register(authToken);
67
- autoUpdater.start();
68
- });
69
-
70
- app.on('window-all-closed', () => {
71
- app.quit();
72
- });
73
-
74
- app.on('before-quit', () => {
75
- cleanupHandlers();
76
- ptyManager.disposeAll();
77
- pipeServer.stop();
78
- mcpRegistrar.unregister();
79
- autoUpdater.stop();
80
- });
81
-
82
- app.on('activate', () => {
83
- if (BrowserWindow.getAllWindows().length === 0) {
84
- mainWindow = createWindow();
85
- }
86
- });
@@ -1,20 +0,0 @@
1
- import { ipcMain, clipboard } from 'electron';
2
- import { IPC } from '../../../shared/constants';
3
-
4
- export function registerClipboardHandlers(): void {
5
- // Remove any previously registered handlers before re-registering.
6
- // ipcMain.handle() throws if the same channel is registered twice (e.g.
7
- // during dev HMR reloads), which silently kills clipboard IPC.
8
- ipcMain.removeHandler(IPC.CLIPBOARD_WRITE);
9
- ipcMain.removeHandler(IPC.CLIPBOARD_READ);
10
-
11
- ipcMain.handle(IPC.CLIPBOARD_WRITE, (_event, text: string) => {
12
- if (typeof text !== 'string') return;
13
- if (text.length > 1_000_000) return; // 1MB limit
14
- clipboard.writeText(text);
15
- });
16
-
17
- ipcMain.handle(IPC.CLIPBOARD_READ, () => {
18
- return clipboard.readText();
19
- });
20
- }