Skip to content

Commit 5710794

Browse files
authored
feat: make terminals persistent and serializable (#156)
1 parent aec2e07 commit 5710794

File tree

8 files changed

+646
-73
lines changed

8 files changed

+646
-73
lines changed

apps/array/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"typecheck": "tsc -p tsconfig.node.json --noEmit && tsc -p tsconfig.web.json --noEmit",
2222
"generate-client": "tsx scripts/update-openapi-client.ts",
2323
"knip": "knip",
24-
"test": "vitest run"
24+
"test": "vitest run",
25+
"postinstall": "cd ../.. && npx @electron/rebuild -f -m node_modules/node-pty || true"
2526
},
2627
"keywords": [
2728
"posthog",
@@ -39,6 +40,7 @@
3940
"@electron-forge/plugin-vite": "^7.10.2",
4041
"@electron-forge/publisher-github": "^7.10.2",
4142
"@electron-forge/shared-types": "^7.10.2",
43+
"@electron/rebuild": "^4.0.1",
4244
"@testing-library/jest-dom": "^6.9.1",
4345
"@testing-library/react": "^16.3.0",
4446
"@testing-library/user-event": "^14.6.1",
@@ -87,6 +89,7 @@
8789
"@tiptap/starter-kit": "^3.11.0",
8890
"@tiptap/suggestion": "^3.11.0",
8991
"@xterm/addon-fit": "^0.10.0",
92+
"@xterm/addon-serialize": "^0.13.0",
9093
"@xterm/addon-web-links": "^0.11.0",
9194
"@xterm/xterm": "^5.5.0",
9295
"ai": "^5.0.75",

apps/array/src/main/preload.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ contextBridge.exposeInMainWorld("electronAPI", {
240240
ipcRenderer.invoke("shell:write", sessionId, data),
241241
shellResize: (sessionId: string, cols: number, rows: number): Promise<void> =>
242242
ipcRenderer.invoke("shell:resize", sessionId, cols, rows),
243+
shellCheck: (sessionId: string): Promise<boolean> =>
244+
ipcRenderer.invoke("shell:check", sessionId),
243245
shellDestroy: (sessionId: string): Promise<void> =>
244246
ipcRenderer.invoke("shell:destroy", sessionId),
245247
onShellData: (

apps/array/src/main/services/shell.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@ export function registerShellIpc(): void {
3030
cwd?: string,
3131
): Promise<void> => {
3232
try {
33-
// Clean up existing session if any
3433
const existing = sessions.get(sessionId);
3534
if (existing) {
36-
existing.pty.kill();
37-
sessions.delete(sessionId);
35+
return;
3836
}
3937

4038
const shell = getDefaultShell();
@@ -67,6 +65,11 @@ export function registerShellIpc(): void {
6765
env.LC_MONETARY = locale;
6866
}
6967

68+
env.TERM_PROGRAM = "Array";
69+
env.TERM_PROGRAM_VERSION = "0.4.0";
70+
env.COLORTERM = "truecolor";
71+
env.FORCE_COLOR = "3"; // truecolor
72+
7073
// Spawn as login shell to properly load PATH and environment
7174
const shellArgs = ["-l"];
7275

@@ -139,6 +142,14 @@ export function registerShellIpc(): void {
139142
},
140143
);
141144

145+
// Check if shell session exists
146+
ipcMain.handle(
147+
"shell:check",
148+
async (_event: IpcMainInvokeEvent, sessionId: string): Promise<boolean> => {
149+
return sessions.has(sessionId);
150+
},
151+
);
152+
142153
// Destroy shell session
143154
ipcMain.handle(
144155
"shell:destroy",

apps/array/src/renderer/features/task-detail/components/TaskShellPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function TaskShellPanel({ taskId, task }: TaskShellPanelProps) {
1313

1414
return (
1515
<Box height="100%">
16-
<ShellTerminal cwd={taskData.repoPath || undefined} />
16+
<ShellTerminal cwd={taskData.repoPath || undefined} stateKey={taskId} />
1717
</Box>
1818
);
1919
}

0 commit comments

Comments
 (0)