nterminal 1.3.25 → 1.3.27

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 (36) hide show
  1. package/README.md +2 -1
  2. package/dist/client/assets/MarkdownPreview-CX0Zi6H6.js +1 -0
  3. package/dist/client/assets/{TranscriptMarkdownBody-BkgxZPQT.js → TranscriptMarkdownBody-BAtKa2bh.js} +1 -1
  4. package/dist/client/assets/{index-BauayuRF.js → index-B0Ef8nfS.js} +32 -32
  5. package/dist/client/assets/{index-CT36T3oC.js → index-BpnLI4BF.js} +1 -1
  6. package/dist/client/index.html +1 -1
  7. package/dist/server/agent/agentRoutes.js +6 -1
  8. package/dist/server/agent/agentRoutes.js.map +1 -1
  9. package/dist/server/index.js +14 -3
  10. package/dist/server/index.js.map +1 -1
  11. package/dist/server/routes/activityRoutes.js +3 -2
  12. package/dist/server/routes/activityRoutes.js.map +1 -1
  13. package/dist/server/routes/agentManagementRoutes.js +19 -1
  14. package/dist/server/routes/agentManagementRoutes.js.map +1 -1
  15. package/dist/server/routes/terminalRoutes.d.ts +4 -1
  16. package/dist/server/routes/terminalRoutes.js +15 -1
  17. package/dist/server/routes/terminalRoutes.js.map +1 -1
  18. package/dist/server/routes/terminalWebSocket.js +4 -0
  19. package/dist/server/routes/terminalWebSocket.js.map +1 -1
  20. package/dist/server/storage/terminalLayoutCleanup.d.ts +4 -0
  21. package/dist/server/storage/terminalLayoutCleanup.js +103 -0
  22. package/dist/server/storage/terminalLayoutCleanup.js.map +1 -0
  23. package/dist/server/terminal/TerminalManager.d.ts +23 -1
  24. package/dist/server/terminal/TerminalManager.js +338 -77
  25. package/dist/server/terminal/TerminalManager.js.map +1 -1
  26. package/dist/server/terminal/terminalSessionStore.d.ts +27 -0
  27. package/dist/server/terminal/terminalSessionStore.js +124 -0
  28. package/dist/server/terminal/terminalSessionStore.js.map +1 -0
  29. package/dist/shared/layoutState.d.ts +2 -0
  30. package/dist/shared/layoutState.js +3 -0
  31. package/dist/shared/layoutState.js.map +1 -1
  32. package/dist/shared/protocol.d.ts +2 -0
  33. package/dist/shared/protocol.js.map +1 -1
  34. package/docs/configuration.md +53 -0
  35. package/package.json +1 -1
  36. package/dist/client/assets/MarkdownPreview-D7uk3GJX.js +0 -1
@@ -0,0 +1,103 @@
1
+ function pruneNode(node, ids) {
2
+ if (node.type === 'pane')
3
+ return ids.has(node.terminalId) ? node : null;
4
+ if (node.type === 'editor')
5
+ return node;
6
+ const first = pruneNode(node.first, ids);
7
+ const second = pruneNode(node.second, ids);
8
+ if (!first)
9
+ return second;
10
+ if (!second)
11
+ return first;
12
+ return first === node.first && second === node.second ? node : { ...node, first, second };
13
+ }
14
+ function terminalIds(node) {
15
+ if (node.type === 'pane')
16
+ return [node.terminalId];
17
+ if (node.type === 'editor')
18
+ return [];
19
+ return [...terminalIds(node.first), ...terminalIds(node.second)];
20
+ }
21
+ // Layout references cannot reconstruct a missing shell: old layouts contain
22
+ // IDs, not per-pane cwd/launch metadata. Keep workspace settings and favorites.
23
+ export function pruneMissingTerminalReferences(layout, ids) {
24
+ let changed = false;
25
+ const workspaces = layout.workspaces.map(workspace => {
26
+ const tabs = workspace.tabs.flatMap(tab => {
27
+ const root = pruneNode(tab.root, ids);
28
+ if (!root) {
29
+ changed = true;
30
+ return [];
31
+ }
32
+ const remaining = terminalIds(root);
33
+ const activeTerminalId = remaining.includes(tab.activeTerminalId) ? tab.activeTerminalId : remaining[0] ?? '';
34
+ if (root === tab.root && activeTerminalId === tab.activeTerminalId)
35
+ return [tab];
36
+ changed = true;
37
+ return [{ ...tab, root, activeTerminalId }];
38
+ });
39
+ const detachedTerminalIds = workspace.detachedTerminalIds.filter(id => ids.has(id));
40
+ const activeTabId = tabs.some(tab => tab.id === workspace.activeTabId) ? workspace.activeTabId : tabs[0]?.id ?? null;
41
+ if (detachedTerminalIds.length !== workspace.detachedTerminalIds.length || activeTabId !== workspace.activeTabId)
42
+ changed = true;
43
+ return { ...workspace, tabs, detachedTerminalIds, activeTabId };
44
+ });
45
+ return changed ? { ...layout, workspaces } : layout;
46
+ }
47
+ class InventorySuperseded extends Error {
48
+ }
49
+ // Capture before requesting the inventory. A layout edit or agent replacement
50
+ // while that request is in flight invalidates cleanup, not the user's changes.
51
+ export async function captureTerminalLayoutCleanup(store, agentId = null) {
52
+ const before = await store.read();
53
+ const slot = (state) => agentId === null ? state.terminalLayout : state.agentLayouts[agentId];
54
+ const saved = slot(before);
55
+ const agent = agentId === null ? null : before.agents.find(entry => entry.id === agentId);
56
+ const currentLayout = async (ids) => {
57
+ const state = await store.read();
58
+ if (agentId !== null && state.agents.find(entry => entry.id === agentId) !== agent)
59
+ return undefined;
60
+ const current = slot(state);
61
+ // Never pair newly created pane references with an older inventory: the
62
+ // browser would prune them while adopting the new revision, bypassing CAS.
63
+ if (!current || !current.layout.workspaces.every(workspace => workspace.detachedTerminalIds.every(id => ids.has(id)) &&
64
+ workspace.tabs.every(tab => terminalIds(tab.root).every(id => ids.has(id)))))
65
+ return undefined;
66
+ return current;
67
+ };
68
+ return async (response, status = 200) => {
69
+ if (!saved || (agentId !== null && !agent) || status !== 200 || !response || typeof response !== 'object')
70
+ return;
71
+ const inventory = response;
72
+ if (inventory.inventoryComplete !== true || !Array.isArray(inventory.terminals))
73
+ return;
74
+ const ids = new Set();
75
+ for (const terminal of inventory.terminals) {
76
+ if (!terminal || typeof terminal.id !== 'string' || !terminal.id ||
77
+ (terminal.status !== 'running' && terminal.status !== 'exited') || ids.has(terminal.id))
78
+ return;
79
+ ids.add(terminal.id);
80
+ }
81
+ const layout = pruneMissingTerminalReferences(saved.layout, ids);
82
+ if (layout === saved.layout)
83
+ return currentLayout(ids);
84
+ try {
85
+ await store.update(state => {
86
+ if (slot(state) !== saved || (agentId !== null && state.agents.find(entry => entry.id === agentId) !== agent)) {
87
+ throw new InventorySuperseded();
88
+ }
89
+ const next = { layout, revision: saved.revision + 1, updatedAt: new Date().toISOString() };
90
+ return agentId === null ? { ...state, terminalLayout: next }
91
+ : { ...state, agentLayouts: { ...state.agentLayouts, [agentId]: next } };
92
+ });
93
+ }
94
+ catch (error) {
95
+ if (!(error instanceof InventorySuperseded))
96
+ throw error;
97
+ }
98
+ // Pair inventory with the current main-owned layout. Parallel layout/list
99
+ // fetches must not leave the browser one revision behind its own cleanup.
100
+ return currentLayout(ids);
101
+ };
102
+ }
103
+ //# sourceMappingURL=terminalLayoutCleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminalLayoutCleanup.js","sourceRoot":"","sources":["../../../src/server/storage/terminalLayoutCleanup.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import { type PtyAdapter } from './PtyAdapter.js';
5
5
  import { type LifecycleEvent } from '../hooks/lifecycle.js';
6
6
  import { readHookOwner, validateHookTranscript, type HookProcessIdentity } from '../hooks/hookBinding.js';
7
7
  import { verifyHookPaneOwner } from '../hooks/hookProcess.js';
8
+ import type { TerminalSessionStore } from './terminalSessionStore.js';
8
9
  export interface CreateTerminalOptions {
9
10
  parentTerminalId?: TerminalId;
10
11
  cwd?: string;
@@ -23,6 +24,7 @@ export interface TerminalAttachment {
23
24
  dispose(): void;
24
25
  }
25
26
  export interface TerminalManagerOptions {
27
+ sessionStore?: TerminalSessionStore;
26
28
  resolveCwd?: (pid: number) => Promise<string | null>;
27
29
  now?: () => Date;
28
30
  onCompletion?: (event: TerminalManagerCompletionEvent) => void | Promise<void>;
@@ -65,7 +67,7 @@ export interface TerminalManagerCompletionEvent {
65
67
  completionId?: string;
66
68
  }
67
69
  export interface TerminalManagerDiagnostic {
68
- event: 'terminal.status_poll_failed' | 'terminal.process_snapshot_failed' | 'terminal.restore_failed' | 'terminal.transcript_poll_failed' | 'terminal.transcript_poll_slow' | 'terminal.reattach_failed' | 'terminal.destroy_failed' | 'terminal.close_failed';
70
+ event: 'terminal.status_poll_failed' | 'terminal.process_snapshot_failed' | 'terminal.restore_failed' | 'terminal.recovery_save_failed' | 'terminal.transcript_poll_failed' | 'terminal.transcript_poll_slow' | 'terminal.reattach_failed' | 'terminal.destroy_failed' | 'terminal.close_failed';
69
71
  terminalId?: TerminalId;
70
72
  queueDepth?: number;
71
73
  elapsedMs?: number;
@@ -115,6 +117,7 @@ export declare class TerminalManager {
115
117
  private readonly completionStates;
116
118
  private statusPollTimer;
117
119
  private restoreRetryTimer;
120
+ private restoreRetryDelayMs;
118
121
  private restoreInflight;
119
122
  private statusPollInflight;
120
123
  private activeTranscriptWorkers;
@@ -124,6 +127,14 @@ export declare class TerminalManager {
124
127
  private terminalMutationGeneration;
125
128
  private shutdownRequested;
126
129
  private disposed;
130
+ private readonly sessionStore;
131
+ private recoveryReady;
132
+ private recoveryTimer;
133
+ private recoveryWriteTimer;
134
+ private recoveryCheckpoint;
135
+ private readonly pendingSessionRestores;
136
+ private readonly creatingSessionIds;
137
+ private readonly pendingDeletionCancellations;
127
138
  constructor(config: AppConfig, ptyAdapter: PtyAdapter, options?: TerminalManagerOptions);
128
139
  private startStatusPoller;
129
140
  private runStatusPoll;
@@ -136,8 +147,16 @@ export declare class TerminalManager {
136
147
  dispose(): void;
137
148
  createTerminal(options?: CreateTerminalOptions): Promise<TerminalSummary>;
138
149
  private createTerminalUntracked;
150
+ private createRecord;
139
151
  restoreSessions(): Promise<void>;
140
152
  private restoreSessionsUntracked;
153
+ hasCompleteInventory(): boolean;
154
+ isRecoveryPending(): boolean;
155
+ private retrySessionRestore;
156
+ private assertRecoveryReady;
157
+ private saveRecoveryMetadata;
158
+ private scheduleRecoverySave;
159
+ checkpointRecovery(): Promise<void>;
141
160
  private scheduleRestoreRetry;
142
161
  private clearRestoreRetryTimer;
143
162
  private wireUpPty;
@@ -207,6 +226,9 @@ export declare class TerminalManager {
207
226
  private sealPendingScroll;
208
227
  private markClosing;
209
228
  private recoverOrFinalizeFailedClose;
229
+ private cancelFailedClose;
230
+ private retryDeletionCancellation;
231
+ private forgetRecoverySession;
210
232
  closeAll(): Promise<void>;
211
233
  destroyAllTerminals(): Promise<DestroyAllTerminalsResult>;
212
234
  private awaitPendingInitializations;