@getpaseo/server 0.1.95 → 0.1.97-beta.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 (134) hide show
  1. package/dist/server/{utils/executable.d.ts → executable-resolution/executable-resolution.d.ts} +2 -2
  2. package/dist/server/{utils/executable.js → executable-resolution/executable-resolution.js} +16 -14
  3. package/dist/server/executable-resolution/windows.d.ts +18 -0
  4. package/dist/server/executable-resolution/windows.js +62 -0
  5. package/dist/server/server/agent/agent-loading.js +4 -1
  6. package/dist/server/server/agent/agent-manager.d.ts +10 -2
  7. package/dist/server/server/agent/agent-manager.js +34 -46
  8. package/dist/server/server/agent/agent-projections.js +3 -0
  9. package/dist/server/server/agent/agent-prompt.js +19 -1
  10. package/dist/server/server/agent/agent-response-loop.js +2 -4
  11. package/dist/server/server/agent/agent-storage.d.ts +18 -19
  12. package/dist/server/server/agent/agent-storage.js +6 -23
  13. package/dist/server/server/agent/create-agent/create.d.ts +2 -12
  14. package/dist/server/server/agent/create-agent/create.js +28 -30
  15. package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +4 -2
  16. package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +31 -22
  17. package/dist/server/server/agent/import-sessions.d.ts +1 -10
  18. package/dist/server/server/agent/import-sessions.js +1 -53
  19. package/dist/server/server/agent/lifecycle-command.js +5 -4
  20. package/dist/server/server/agent/mcp-server.d.ts +8 -5
  21. package/dist/server/server/agent/mcp-server.js +41 -14
  22. package/dist/server/server/agent/mcp-shared.d.ts +6 -3
  23. package/dist/server/server/agent/mcp-shared.js +3 -0
  24. package/dist/server/server/agent/provider-launch-config.js +1 -1
  25. package/dist/server/server/agent/providers/acp-agent.d.ts +5 -0
  26. package/dist/server/server/agent/providers/acp-agent.js +31 -26
  27. package/dist/server/server/agent/providers/claude/agent.js +45 -6
  28. package/dist/server/server/agent/providers/codex-app-server-agent.js +1 -1
  29. package/dist/server/server/agent/providers/copilot-acp-agent.js +1 -0
  30. package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +0 -7
  31. package/dist/server/server/agent/providers/cursor-acp-agent.js +0 -78
  32. package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +2 -0
  33. package/dist/server/server/agent/providers/mock-load-test-agent.js +73 -1
  34. package/dist/server/server/agent/providers/opencode/server-manager.js +1 -1
  35. package/dist/server/server/agent/structured-generation-providers.js +45 -1
  36. package/dist/server/server/agent-attention-policy.d.ts +12 -3
  37. package/dist/server/server/agent-attention-policy.js +15 -3
  38. package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +7 -6
  39. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +21 -16
  40. package/dist/server/server/bootstrap.d.ts +3 -0
  41. package/dist/server/server/bootstrap.js +91 -12
  42. package/dist/server/server/config.js +1 -0
  43. package/dist/server/server/daemon-config-store.js +1 -0
  44. package/dist/server/server/exports.d.ts +1 -1
  45. package/dist/server/server/exports.js +1 -1
  46. package/dist/server/server/loop-service.d.ts +24 -24
  47. package/dist/server/server/migrations/backfill-workspace-id.migration.d.ts +9 -0
  48. package/dist/server/server/migrations/backfill-workspace-id.migration.js +60 -0
  49. package/dist/server/server/paseo-worktree-service.d.ts +9 -0
  50. package/dist/server/server/paseo-worktree-service.js +71 -12
  51. package/dist/server/server/path-utils.d.ts +1 -0
  52. package/dist/server/server/path-utils.js +6 -1
  53. package/dist/server/server/persisted-config.d.ts +7 -0
  54. package/dist/server/server/persisted-config.js +1 -0
  55. package/dist/server/server/persistence-hooks.d.ts +1 -0
  56. package/dist/server/server/persistence-hooks.js +13 -5
  57. package/dist/server/server/resolve-workspace-id-for-path.d.ts +3 -0
  58. package/dist/server/server/resolve-workspace-id-for-path.js +41 -0
  59. package/dist/server/server/script-proxy.d.ts +1 -1
  60. package/dist/server/server/script-proxy.js +1 -1
  61. package/dist/server/server/service-proxy.js +1 -1
  62. package/dist/server/server/session.d.ts +31 -6
  63. package/dist/server/server/session.js +640 -196
  64. package/dist/server/server/websocket-server.d.ts +5 -0
  65. package/dist/server/server/websocket-server.js +137 -3
  66. package/dist/server/server/workspace-archive-service.d.ts +60 -3
  67. package/dist/server/server/workspace-archive-service.js +217 -4
  68. package/dist/server/server/workspace-directory.d.ts +20 -2
  69. package/dist/server/server/workspace-directory.js +148 -70
  70. package/dist/server/server/workspace-git-service.js +21 -21
  71. package/dist/server/server/workspace-reconciliation-service.d.ts +1 -1
  72. package/dist/server/server/workspace-reconciliation-service.js +21 -22
  73. package/dist/server/server/workspace-registry-bootstrap.js +23 -10
  74. package/dist/server/server/workspace-registry-model.d.ts +3 -3
  75. package/dist/server/server/workspace-registry-model.js +9 -10
  76. package/dist/server/server/workspace-registry.d.ts +17 -4
  77. package/dist/server/server/workspace-registry.js +27 -0
  78. package/dist/server/server/worktree/commands.d.ts +7 -5
  79. package/dist/server/server/worktree/commands.js +38 -18
  80. package/dist/server/server/worktree-bootstrap.d.ts +1 -0
  81. package/dist/server/server/worktree-bootstrap.js +4 -1
  82. package/dist/server/server/worktree-branch-name-generator.d.ts +5 -1
  83. package/dist/server/server/worktree-branch-name-generator.js +8 -2
  84. package/dist/server/server/worktree-session.d.ts +4 -5
  85. package/dist/server/server/worktree-session.js +9 -3
  86. package/dist/server/services/github-service.js +1 -1
  87. package/dist/server/terminal/activity/terminal-activity-tracker.d.ts +20 -0
  88. package/dist/server/terminal/activity/terminal-activity-tracker.js +59 -0
  89. package/dist/server/terminal/agent-hooks/agent-hook-installer.d.ts +62 -0
  90. package/dist/server/terminal/agent-hooks/agent-hook-installer.js +117 -0
  91. package/dist/server/terminal/agent-hooks/claude/claude-settings.d.ts +7 -0
  92. package/dist/server/terminal/agent-hooks/claude/claude-settings.js +88 -0
  93. package/dist/server/terminal/agent-hooks/claude/claude.d.ts +4 -0
  94. package/dist/server/terminal/agent-hooks/claude/claude.js +47 -0
  95. package/dist/server/terminal/agent-hooks/codex/codex-settings.d.ts +7 -0
  96. package/dist/server/terminal/agent-hooks/codex/codex-settings.js +99 -0
  97. package/dist/server/terminal/agent-hooks/codex/codex.d.ts +4 -0
  98. package/dist/server/terminal/agent-hooks/codex/codex.js +30 -0
  99. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.d.ts +4 -0
  100. package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.js +46 -0
  101. package/dist/server/terminal/agent-hooks/opencode/opencode.d.ts +3 -0
  102. package/dist/server/terminal/agent-hooks/opencode/opencode.js +23 -0
  103. package/dist/server/terminal/agent-hooks/provider-registry.d.ts +24 -0
  104. package/dist/server/terminal/agent-hooks/provider-registry.js +36 -0
  105. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.d.ts +10 -0
  106. package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.js +26 -0
  107. package/dist/server/terminal/terminal-manager-factory.d.ts +4 -1
  108. package/dist/server/terminal/terminal-manager-factory.js +2 -2
  109. package/dist/server/terminal/terminal-manager.d.ts +33 -2
  110. package/dist/server/terminal/terminal-manager.js +144 -18
  111. package/dist/server/terminal/terminal-output-coalescer.d.ts +4 -0
  112. package/dist/server/terminal/terminal-output-coalescer.js +18 -0
  113. package/dist/server/terminal/terminal-restore.d.ts +1 -0
  114. package/dist/server/terminal/terminal-restore.js +6 -0
  115. package/dist/server/terminal/terminal-session-controller.d.ts +4 -2
  116. package/dist/server/terminal/terminal-session-controller.js +65 -24
  117. package/dist/server/terminal/terminal-worker-process.js +146 -63
  118. package/dist/server/terminal/terminal-worker-protocol.d.ts +19 -14
  119. package/dist/server/terminal/terminal.d.ts +42 -0
  120. package/dist/server/terminal/terminal.js +235 -16
  121. package/dist/server/terminal/worker-terminal-manager.d.ts +1 -0
  122. package/dist/server/terminal/worker-terminal-manager.js +220 -36
  123. package/dist/server/utils/build-metadata-prompt.d.ts +1 -1
  124. package/dist/server/utils/github-remote.js +1 -1
  125. package/dist/server/utils/tree-kill.d.ts +2 -2
  126. package/dist/src/{utils/executable.js → executable-resolution/executable-resolution.js} +16 -14
  127. package/dist/src/executable-resolution/windows.js +62 -0
  128. package/dist/src/server/agent/provider-launch-config.js +1 -1
  129. package/dist/src/server/persisted-config.js +1 -0
  130. package/package.json +10 -5
  131. package/dist/server/server/agent/agent-metadata-generator.d.ts +0 -36
  132. package/dist/server/server/agent/agent-metadata-generator.js +0 -112
  133. package/dist/server/server/paseo-worktree-archive-service.d.ts +0 -41
  134. package/dist/server/server/paseo-worktree-archive-service.js +0 -144
@@ -1,8 +1,22 @@
1
1
  import { createTerminalManager } from "./terminal-manager.js";
2
2
  import { captureTerminalLines } from "./terminal-capture.js";
3
+ import { TerminalOutputCoalescer } from "./terminal-output-coalescer.js";
3
4
  const manager = createTerminalManager();
4
5
  const unsubscribeByTerminalId = new Map();
6
+ const outputCoalescerByTerminalId = new Map();
5
7
  let ipcClosing = false;
8
+ let inFlightTerminalCreateRequest = null;
9
+ // The conpty failure signal is process-scoped, not request-scoped. Serializing
10
+ // creates keeps an async spawn failure attributable to exactly one request.
11
+ let createTerminalQueue = Promise.resolve();
12
+ // node-pty completes its Windows conpty spawn asynchronously on a separate
13
+ // conout worker thread. When that spawn fails (bad cwd, missing command, etc.)
14
+ // it throws an exception there that cannot be caught at the call site and would
15
+ // otherwise crash this worker process and sever every existing terminal.
16
+ process.on("uncaughtException", (error) => {
17
+ console.error("Terminal worker uncaught exception (kept alive):", error);
18
+ reportInFlightTerminalCreateFailure(error);
19
+ });
6
20
  function sendToParent(message) {
7
21
  if (ipcClosing || !process.connected || !process.send) {
8
22
  return;
@@ -18,14 +32,37 @@ function sendToParent(message) {
18
32
  ipcClosing = true;
19
33
  }
20
34
  }
35
+ function buildTerminalStateResult(session, options) {
36
+ if (!session) {
37
+ return null;
38
+ }
39
+ return { ...session.getStateSnapshot(options), replayPreamble: session.getReplayPreamble() };
40
+ }
21
41
  function toTerminalInfo(session) {
22
42
  return {
23
43
  id: session.id,
24
44
  name: session.name,
25
45
  cwd: session.cwd,
46
+ workspaceId: session.workspaceId,
26
47
  ...(session.getTitle() ? { title: session.getTitle() } : {}),
48
+ activity: session.getActivity(),
27
49
  };
28
50
  }
51
+ function terminalWorkerErrorMessage(error) {
52
+ return error instanceof Error ? error.message : "Terminal worker request failed";
53
+ }
54
+ function reportInFlightTerminalCreateFailure(error) {
55
+ if (!inFlightTerminalCreateRequest || inFlightTerminalCreateRequest.errorReported) {
56
+ return;
57
+ }
58
+ inFlightTerminalCreateRequest.errorReported = true;
59
+ sendToParent({
60
+ type: "response",
61
+ requestId: inFlightTerminalCreateRequest.requestId,
62
+ ok: false,
63
+ error: terminalWorkerErrorMessage(error),
64
+ });
65
+ }
29
66
  function clearTerminalSubscriptions(terminalId) {
30
67
  const subscriptions = unsubscribeByTerminalId.get(terminalId);
31
68
  if (subscriptions) {
@@ -39,10 +76,41 @@ function clearTerminalSubscriptions(terminalId) {
39
76
  }
40
77
  }
41
78
  unsubscribeByTerminalId.delete(terminalId);
79
+ const coalescer = outputCoalescerByTerminalId.get(terminalId);
80
+ if (coalescer) {
81
+ coalescer.dispose();
82
+ outputCoalescerByTerminalId.delete(terminalId);
83
+ }
42
84
  }
43
85
  function watchTerminal(session) {
44
86
  clearTerminalSubscriptions(session.id);
87
+ // Coalesce pty output chunks into a single IPC message per ~5ms window so a
88
+ // burst of small chunks no longer costs one process.send each. The batch
89
+ // carries the LAST chunk's revision (the highest) so downstream snapshot
90
+ // replay dedup stays correct.
91
+ let pendingOutputRevision;
92
+ const outputCoalescer = new TerminalOutputCoalescer({
93
+ timers: { setTimeout, clearTimeout },
94
+ onFlush: ({ payload }) => {
95
+ const revision = pendingOutputRevision;
96
+ pendingOutputRevision = undefined;
97
+ sendToParent({
98
+ type: "terminalMessage",
99
+ terminalId: session.id,
100
+ message: { type: "output", data: payload.toString("utf8"), revision },
101
+ });
102
+ },
103
+ });
104
+ outputCoalescerByTerminalId.set(session.id, outputCoalescer);
45
105
  const unsubscribeMessage = session.subscribe((message) => {
106
+ if (message.type === "output") {
107
+ pendingOutputRevision = message.revision;
108
+ outputCoalescer.handle(message.data);
109
+ return;
110
+ }
111
+ // Non-output messages (snapshot/snapshotReady/titleChange) must not jump
112
+ // ahead of buffered output: flush the coalescer first, then forward.
113
+ outputCoalescer.flush();
46
114
  sendToParent({
47
115
  type: "terminalMessage",
48
116
  terminalId: session.id,
@@ -50,6 +118,7 @@ function watchTerminal(session) {
50
118
  });
51
119
  });
52
120
  const unsubscribeExit = session.onExit((info) => {
121
+ outputCoalescer.flush();
53
122
  clearTerminalSubscriptions(session.id);
54
123
  sendToParent({
55
124
  type: "terminalExit",
@@ -58,6 +127,7 @@ function watchTerminal(session) {
58
127
  });
59
128
  });
60
129
  const unsubscribeTitle = session.onTitleChange((title) => {
130
+ outputCoalescer.flush();
61
131
  sendToParent({
62
132
  type: "terminalTitleChange",
63
133
  terminalId: session.id,
@@ -65,56 +135,80 @@ function watchTerminal(session) {
65
135
  });
66
136
  });
67
137
  const unsubscribeCommandFinished = session.onCommandFinished((info) => {
138
+ outputCoalescer.flush();
68
139
  sendToParent({
69
140
  type: "terminalCommandFinished",
70
141
  terminalId: session.id,
71
142
  info,
72
143
  });
73
144
  });
145
+ const unsubscribeActivity = session.onActivityChange((transition) => {
146
+ sendToParent({
147
+ type: "terminalActivityChange",
148
+ terminalId: session.id,
149
+ activity: transition.activity,
150
+ previous: transition.previous,
151
+ });
152
+ });
74
153
  unsubscribeByTerminalId.set(session.id, [
75
154
  unsubscribeMessage,
76
155
  unsubscribeExit,
77
156
  unsubscribeTitle,
78
157
  unsubscribeCommandFinished,
158
+ unsubscribeActivity,
79
159
  ]);
80
160
  }
81
- manager.subscribeTerminalsChanged((event) => {
82
- sendToParent({
83
- type: "terminalsChanged",
84
- cwd: event.cwd,
85
- terminals: event.terminals,
86
- });
87
- });
88
- async function handleRequest(message) {
89
- switch (message.type) {
90
- case "getTerminals": {
91
- const terminals = await manager.getTerminals(message.cwd);
92
- sendToParent({
93
- type: "response",
94
- requestId: message.requestId,
95
- ok: true,
96
- result: terminals.map(toTerminalInfo),
97
- });
161
+ function enqueueCreateTerminalRequest(message) {
162
+ const nextRequest = createTerminalQueue.then(() => handleCreateTerminalRequest(message));
163
+ createTerminalQueue = nextRequest.catch(() => { });
164
+ return nextRequest;
165
+ }
166
+ async function handleCreateTerminalRequest(message) {
167
+ const request = {
168
+ requestId: message.requestId,
169
+ errorReported: false,
170
+ };
171
+ inFlightTerminalCreateRequest = request;
172
+ try {
173
+ const { workspaceId } = message.options;
174
+ if (!workspaceId) {
175
+ throw new Error("workspaceId is required");
176
+ }
177
+ const session = await manager.createTerminal({ ...message.options, workspaceId });
178
+ if (request.errorReported) {
179
+ session.kill();
98
180
  return;
99
181
  }
100
- case "createTerminal": {
101
- const session = await manager.createTerminal(message.options);
102
- watchTerminal(session);
103
- const initialSnapshot = session.getStateSnapshot();
104
- sendToParent({
105
- type: "terminalCreated",
182
+ watchTerminal(session);
183
+ const initialSnapshot = session.getStateSnapshot();
184
+ sendToParent({
185
+ type: "terminalCreated",
186
+ terminal: toTerminalInfo(session),
187
+ state: initialSnapshot.state,
188
+ });
189
+ sendToParent({
190
+ type: "response",
191
+ requestId: message.requestId,
192
+ ok: true,
193
+ result: {
106
194
  terminal: toTerminalInfo(session),
107
195
  state: initialSnapshot.state,
108
- });
109
- sendToParent({
110
- type: "response",
111
- requestId: message.requestId,
112
- ok: true,
113
- result: {
114
- terminal: toTerminalInfo(session),
115
- state: initialSnapshot.state,
116
- },
117
- });
196
+ },
197
+ });
198
+ }
199
+ catch (error) {
200
+ reportInFlightTerminalCreateFailure(error);
201
+ }
202
+ finally {
203
+ if (inFlightTerminalCreateRequest === request) {
204
+ inFlightTerminalCreateRequest = null;
205
+ }
206
+ }
207
+ }
208
+ async function handleRequest(message) {
209
+ switch (message.type) {
210
+ case "createTerminal": {
211
+ await enqueueCreateTerminalRequest(message);
118
212
  return;
119
213
  }
120
214
  case "registerCwdEnv": {
@@ -122,52 +216,41 @@ async function handleRequest(message) {
122
216
  sendToParent({ type: "response", requestId: message.requestId, ok: true });
123
217
  return;
124
218
  }
219
+ case "setActivity": {
220
+ await manager.setTerminalActivity(message.terminalId, message.state);
221
+ sendToParent({ type: "response", requestId: message.requestId, ok: true });
222
+ return;
223
+ }
224
+ case "clearAttention": {
225
+ await manager.clearTerminalAttention(message.terminalId);
226
+ sendToParent({ type: "response", requestId: message.requestId, ok: true });
227
+ return;
228
+ }
125
229
  case "killTerminal": {
126
- const session = manager.getTerminal(message.terminalId);
127
- const cwd = session?.cwd;
128
230
  manager.killTerminal(message.terminalId);
231
+ // Removal is owned by session.onExit -> terminalExit; the parent mirror
232
+ // clears contribution and emits terminalsChanged from that single path.
129
233
  clearTerminalSubscriptions(message.terminalId);
130
- if (cwd) {
131
- sendToParent({
132
- type: "terminalRemoved",
133
- terminalId: message.terminalId,
134
- cwd,
135
- });
136
- }
137
234
  sendToParent({ type: "response", requestId: message.requestId, ok: true });
138
235
  return;
139
236
  }
140
237
  case "killTerminalAndWait": {
141
- const session = manager.getTerminal(message.terminalId);
142
- const cwd = session?.cwd;
143
238
  await manager.killTerminalAndWait(message.terminalId, message.options);
144
239
  clearTerminalSubscriptions(message.terminalId);
145
- if (cwd) {
146
- sendToParent({
147
- type: "terminalRemoved",
148
- terminalId: message.terminalId,
149
- cwd,
150
- });
151
- }
152
240
  sendToParent({ type: "response", requestId: message.requestId, ok: true });
153
241
  return;
154
242
  }
155
243
  case "getTerminalState": {
156
- const session = manager.getTerminal(message.terminalId);
157
- sendToParent({
158
- type: "response",
159
- requestId: message.requestId,
160
- ok: true,
161
- result: session?.getStateSnapshot(message.options) ?? null,
162
- });
163
- return;
164
- }
165
- case "listDirectories": {
244
+ // Flush buffered output before snapshotting: the headless state already includes it,
245
+ // so if the coalescer emitted it afterward (in a batch carrying a revision past the
246
+ // snapshot's) the controller's revision dedup wouldn't drop it and the client would
247
+ // see the bytes twice. Flushing first sends them with a revision <= the snapshot's.
248
+ outputCoalescerByTerminalId.get(message.terminalId)?.flush();
166
249
  sendToParent({
167
250
  type: "response",
168
251
  requestId: message.requestId,
169
252
  ok: true,
170
- result: manager.listDirectories(),
253
+ result: buildTerminalStateResult(manager.getTerminal(message.terminalId), message.options),
171
254
  });
172
255
  return;
173
256
  }
@@ -210,7 +293,7 @@ process.on("message", (message) => {
210
293
  type: "response",
211
294
  requestId: message.requestId,
212
295
  ok: false,
213
- error: error instanceof Error ? error.message : "Terminal worker request failed",
296
+ error: terminalWorkerErrorMessage(error),
214
297
  });
215
298
  });
216
299
  });
@@ -1,30 +1,32 @@
1
1
  import type { TerminalExitInfo, ServerMessage, ClientMessage, TerminalStateSnapshot, TerminalStateSnapshotOptions } from "./terminal.js";
2
2
  import type { TerminalState } from "@getpaseo/protocol/messages";
3
+ import type { TerminalActivity, TerminalActivityState } from "@getpaseo/protocol/terminal-activity";
3
4
  import type { CaptureTerminalLinesResult } from "./terminal-capture.js";
4
5
  export interface WorkerTerminalInfo {
5
6
  id: string;
6
7
  name: string;
7
8
  cwd: string;
9
+ workspaceId?: string;
8
10
  title?: string;
11
+ activity: TerminalActivity | null;
9
12
  }
10
13
  export interface WorkerCreateTerminalOptions {
11
14
  id?: string;
12
15
  cwd: string;
16
+ workspaceId?: string;
13
17
  name?: string;
14
18
  title?: string;
15
19
  env?: Record<string, string>;
16
20
  command?: string;
17
21
  args?: string[];
22
+ activityToken?: string;
23
+ activityUrl?: string | null;
18
24
  }
19
25
  export interface WorkerKillAndWaitOptions {
20
26
  gracefulTimeoutMs?: number;
21
27
  forceTimeoutMs?: number;
22
28
  }
23
29
  export type TerminalWorkerRequest = {
24
- type: "getTerminals";
25
- requestId: string;
26
- cwd: string;
27
- } | {
28
30
  type: "createTerminal";
29
31
  requestId: string;
30
32
  options: WorkerCreateTerminalOptions;
@@ -33,6 +35,15 @@ export type TerminalWorkerRequest = {
33
35
  requestId: string;
34
36
  cwd: string;
35
37
  env: Record<string, string>;
38
+ } | {
39
+ type: "setActivity";
40
+ requestId: string;
41
+ terminalId: string;
42
+ state: TerminalActivityState;
43
+ } | {
44
+ type: "clearAttention";
45
+ requestId: string;
46
+ terminalId: string;
36
47
  } | {
37
48
  type: "killTerminal";
38
49
  requestId: string;
@@ -54,9 +65,6 @@ export type TerminalWorkerRequest = {
54
65
  start?: number;
55
66
  end?: number;
56
67
  stripAnsi?: boolean;
57
- } | {
58
- type: "listDirectories";
59
- requestId: string;
60
68
  } | {
61
69
  type: "killAll";
62
70
  requestId: string;
@@ -81,10 +89,6 @@ export type TerminalWorkerEvent = {
81
89
  type: "terminalCreated";
82
90
  terminal: WorkerTerminalInfo;
83
91
  state: TerminalState;
84
- } | {
85
- type: "terminalRemoved";
86
- terminalId: string;
87
- cwd: string;
88
92
  } | {
89
93
  type: "terminalMessage";
90
94
  terminalId: string;
@@ -104,9 +108,10 @@ export type TerminalWorkerEvent = {
104
108
  exitCode: number | null;
105
109
  };
106
110
  } | {
107
- type: "terminalsChanged";
108
- cwd: string;
109
- terminals: WorkerTerminalInfo[];
111
+ type: "terminalActivityChange";
112
+ terminalId: string;
113
+ activity: TerminalActivity | null;
114
+ previous: TerminalActivity | null;
110
115
  };
111
116
  export type TerminalWorkerToParentMessage = TerminalWorkerResponse | TerminalWorkerEvent;
112
117
  export type TerminalWorkerCaptureResult = CaptureTerminalLinesResult;
@@ -1,4 +1,5 @@
1
1
  import type { TerminalState } from "@getpaseo/protocol/messages";
2
+ import type { TerminalActivity, TerminalActivityState } from "@getpaseo/protocol/terminal-activity";
2
3
  export interface TerminalExitInfo {
3
4
  exitCode: number | null;
4
5
  signal: number | null;
@@ -10,6 +11,7 @@ export interface TerminalCommandFinishedInfo {
10
11
  export interface TerminalStateSnapshot {
11
12
  state: TerminalState;
12
13
  revision: number;
14
+ replayPreamble?: string;
13
15
  }
14
16
  export interface TerminalStateSnapshotOptions {
15
17
  scrollbackLines?: number;
@@ -43,19 +45,26 @@ export type ServerMessage = {
43
45
  } | {
44
46
  type: "snapshotReady";
45
47
  revision?: number;
48
+ replayPreamble?: string;
46
49
  } | {
47
50
  type: "titleChange";
48
51
  title?: string;
49
52
  };
53
+ export interface TerminalActivityTransition {
54
+ activity: TerminalActivity | null;
55
+ previous: TerminalActivity | null;
56
+ }
50
57
  export interface TerminalSession {
51
58
  id: string;
52
59
  name: string;
53
60
  cwd: string;
61
+ workspaceId: string;
54
62
  send(msg: ClientMessage): void;
55
63
  subscribe(listener: (msg: ServerMessage) => void, options?: TerminalSubscribeOptions): () => void;
56
64
  onExit(listener: (info: TerminalExitInfo) => void): () => void;
57
65
  onCommandFinished(listener: (info: TerminalCommandFinishedInfo) => void): () => void;
58
66
  onTitleChange(listener: (title?: string) => void): () => void;
67
+ onActivityChange(listener: (transition: TerminalActivityTransition) => void): () => void;
59
68
  getSize(): {
60
69
  rows: number;
61
70
  cols: number;
@@ -64,6 +73,9 @@ export interface TerminalSession {
64
73
  getStateSnapshot(options?: TerminalStateSnapshotOptions): TerminalStateSnapshot;
65
74
  getReplayPreamble(): string;
66
75
  getTitle(): string | undefined;
76
+ getActivity(): TerminalActivity | null;
77
+ setActivity(state: TerminalActivityState): void;
78
+ clearActivityAttention(): boolean;
67
79
  setTitle(title: string): void;
68
80
  getExitInfo(): TerminalExitInfo | null;
69
81
  kill(): void;
@@ -75,8 +87,10 @@ export interface TerminalSession {
75
87
  export interface CreateTerminalOptions {
76
88
  id?: string;
77
89
  cwd: string;
90
+ workspaceId: string;
78
91
  shell?: string;
79
92
  env?: Record<string, string>;
93
+ activityEnv?: Record<string, string>;
80
94
  rows?: number;
81
95
  cols?: number;
82
96
  name?: string;
@@ -88,6 +102,8 @@ interface BuildTerminalEnvironmentInput {
88
102
  shell: string;
89
103
  env: Record<string, string>;
90
104
  zshShellIntegrationDir?: string;
105
+ paseoCliBinDir?: string | null;
106
+ paseoHookCliPath?: string | null;
91
107
  }
92
108
  interface EnsureNodePtySpawnHelperExecutableOptions {
93
109
  packageRoot?: string;
@@ -100,7 +116,33 @@ export declare function resolveDefaultTerminalShell(options?: {
100
116
  platform?: NodeJS.Platform;
101
117
  env?: NodeJS.ProcessEnv;
102
118
  }): string;
119
+ export interface ResolvedTerminalCommand {
120
+ command: string;
121
+ args: string[];
122
+ }
123
+ export interface ResolveTerminalSpawnCommandOptions {
124
+ platform?: NodeJS.Platform;
125
+ env?: Record<string, string | undefined>;
126
+ resolveExecutable?: (name: string) => Promise<string | null>;
127
+ }
128
+ /**
129
+ * Resolve a terminal profile command (e.g. `claude`) into something node-pty's
130
+ * conpty backend can actually launch on Windows.
131
+ *
132
+ * On Windows, conpty's underlying `CreateProcess` does not apply `PATHEXT`, so a
133
+ * bare `claude` (installed by npm as `claude.cmd`) fails with `error code: 2`
134
+ * (`ERROR_FILE_NOT_FOUND`). Worse, conpty completes the spawn asynchronously on
135
+ * its own conout worker thread, so that failure surfaces as an uncaught
136
+ * exception that takes down the whole terminal worker process. Resolving the
137
+ * real path up front — and routing `.cmd`/`.bat` shims through `cmd.exe /c`
138
+ * (node-pty has no `shell` option) — keeps the profile launchable.
139
+ *
140
+ * Non-Windows and the default-shell path (no explicit command) are unchanged.
141
+ */
142
+ export declare function resolveTerminalSpawnCommand(command: string, args: string[], options?: ResolveTerminalSpawnCommandOptions): Promise<ResolvedTerminalCommand>;
103
143
  export declare function resolveZshShellIntegrationDir(): string;
144
+ export declare function resolvePaseoCliBinDir(): string | null;
145
+ export declare function resolvePaseoCliExecutablePath(): string | null;
104
146
  export declare function buildTerminalEnvironment(input: BuildTerminalEnvironmentInput): Record<string, string>;
105
147
  export declare function normalizeProcessTitle(processTitle: string): string | undefined;
106
148
  export declare function humanizeProcessTitle(processTitle: string): string | undefined;