@getpaseo/server 0.1.101 → 0.1.102-beta.2

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 (132) hide show
  1. package/dist/scripts/supervisor.js +26 -8
  2. package/dist/server/server/agent/activity-curator.d.ts +17 -0
  3. package/dist/server/server/agent/activity-curator.js +101 -24
  4. package/dist/server/server/agent/agent-manager.js +5 -1
  5. package/dist/server/server/agent/agent-sdk-types.d.ts +7 -2
  6. package/dist/server/server/agent/provider-snapshot-manager.d.ts +8 -1
  7. package/dist/server/server/agent/provider-snapshot-manager.js +78 -33
  8. package/dist/server/server/agent/providers/acp-agent.d.ts +7 -0
  9. package/dist/server/server/agent/providers/acp-agent.js +8 -1
  10. package/dist/server/server/agent/providers/claude/agent.js +51 -14
  11. package/dist/server/server/agent/providers/claude/query.d.ts +3 -0
  12. package/dist/server/server/agent/providers/claude/query.js +4 -2
  13. package/dist/server/server/agent/providers/mock-load-test-agent.js +8 -0
  14. package/dist/server/server/agent/providers/opencode/paths.d.ts +2 -0
  15. package/dist/server/server/agent/providers/opencode/paths.js +7 -0
  16. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +2 -0
  17. package/dist/server/server/agent/providers/opencode/server-manager.js +34 -5
  18. package/dist/server/server/agent/providers/opencode-agent.d.ts +4 -0
  19. package/dist/server/server/agent/providers/opencode-agent.js +14 -2
  20. package/dist/server/server/agent/providers/pi/agent.d.ts +3 -0
  21. package/dist/server/server/agent/providers/pi/agent.js +9 -3
  22. package/dist/server/server/agent/providers/provider-image-output.js +11 -6
  23. package/dist/server/server/agent/tools/paseo-tools.d.ts +1 -1
  24. package/dist/server/server/agent/tools/paseo-tools.js +0 -2
  25. package/dist/server/server/bootstrap.d.ts +7 -1
  26. package/dist/server/server/bootstrap.js +18 -0
  27. package/dist/server/server/config.d.ts +2 -0
  28. package/dist/server/server/config.js +57 -1
  29. package/dist/server/server/daemon-worker.js +19 -7
  30. package/dist/server/server/lifecycle-reasons.d.ts +4 -0
  31. package/dist/server/server/lifecycle-reasons.js +6 -0
  32. package/dist/server/server/persisted-config.d.ts +7 -0
  33. package/dist/server/server/persisted-config.js +8 -0
  34. package/dist/server/server/process-diagnostics.d.ts +17 -0
  35. package/dist/server/server/process-diagnostics.js +22 -0
  36. package/dist/server/server/relay-transport.js +1 -0
  37. package/dist/server/server/resolve-worktree-creation-intent.js +3 -1
  38. package/dist/server/server/session/daemon/daemon-self-update-session-controller.d.ts +32 -0
  39. package/dist/server/server/session/daemon/daemon-self-update-session-controller.js +88 -0
  40. package/dist/server/server/session/daemon/daemon-self-updater.d.ts +32 -0
  41. package/dist/server/server/session/daemon/daemon-self-updater.js +56 -0
  42. package/dist/server/server/session/daemon/daemon-session.d.ts +12 -0
  43. package/dist/server/server/session/daemon/daemon-session.js +12 -0
  44. package/dist/server/server/session/daemon/diagnostics.js +10 -0
  45. package/dist/server/server/session/daemon/install-origin.d.ts +7 -0
  46. package/dist/server/server/session/daemon/install-origin.js +64 -0
  47. package/dist/server/server/session/daemon/npm-global-cli.d.ts +29 -0
  48. package/dist/server/server/session/daemon/npm-global-cli.js +98 -0
  49. package/dist/server/server/session/provider/provider-catalog-session.js +8 -4
  50. package/dist/server/server/session.d.ts +5 -3
  51. package/dist/server/server/session.js +74 -32
  52. package/dist/server/server/web-ui.d.ts +10 -0
  53. package/dist/server/server/web-ui.js +205 -0
  54. package/dist/server/server/websocket/runtime-metrics.d.ts +3 -0
  55. package/dist/server/server/websocket-server.d.ts +3 -0
  56. package/dist/server/server/websocket-server.js +190 -32
  57. package/dist/server/services/quota-fetcher/manifest.js +5 -0
  58. package/dist/server/services/quota-fetcher/providers/minimax.d.ts +29 -0
  59. package/dist/server/services/quota-fetcher/providers/minimax.js +227 -0
  60. package/dist/server/terminal/agent-hooks/agent-hook-installer.js +2 -2
  61. package/dist/server/utils/checkout-git.js +156 -3
  62. package/dist/server/utils/directory-suggestions.js +1 -4
  63. package/dist/server/utils/path.d.ts +2 -0
  64. package/dist/server/utils/path.js +13 -0
  65. package/dist/server/utils/worktree.d.ts +1 -0
  66. package/dist/server/utils/worktree.js +92 -11
  67. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +1 -0
  68. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
  69. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
  70. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js +1 -0
  71. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js.br +0 -0
  72. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js.gz +0 -0
  73. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js +1 -0
  74. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js.br +0 -0
  75. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js.gz +0 -0
  76. package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js +16157 -0
  77. package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js.br +0 -0
  78. package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js.gz +0 -0
  79. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js +1 -0
  80. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js.br +0 -0
  81. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js.gz +0 -0
  82. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js +3 -0
  83. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js.br +0 -0
  84. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js.gz +0 -0
  85. package/dist/server/web-ui/apple-touch-icon.png +0 -0
  86. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
  87. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
  88. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
  89. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
  90. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
  91. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
  92. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
  93. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
  94. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
  95. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
  96. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
  97. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
  98. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
  99. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
  100. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
  101. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
  102. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
  103. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
  104. package/dist/server/web-ui/assets/assets/images/editor-apps/antigravity.6e91a685c33435e0b466a56db86cf141.png +0 -0
  105. package/dist/server/web-ui/assets/assets/images/editor-apps/cursor.c31d6bce4fe9aadc3fe59962f4c4fcf3.png +0 -0
  106. package/dist/server/web-ui/assets/assets/images/editor-apps/file-explorer.3e15e8f72c825c85ce336bcb0cdef776.png +0 -0
  107. package/dist/server/web-ui/assets/assets/images/editor-apps/finder.7f68fc2c475621a672e1be09309d5567.png +0 -0
  108. package/dist/server/web-ui/assets/assets/images/editor-apps/vscode.832bdb4c685d930f1c864c793703600b.png +0 -0
  109. package/dist/server/web-ui/assets/assets/images/editor-apps/webstorm.aa5dc2cd8c20cc0a155c4c5c5ab3c5f5.png +0 -0
  110. package/dist/server/web-ui/assets/assets/images/editor-apps/zed.f3a670b7f9aa226da4fe53fb86f1abbd.png +0 -0
  111. package/dist/server/web-ui/assets/assets/images/favicon-dark-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  112. package/dist/server/web-ui/assets/assets/images/favicon-dark-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  113. package/dist/server/web-ui/assets/assets/images/favicon-dark.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  114. package/dist/server/web-ui/assets/assets/images/favicon-light-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  115. package/dist/server/web-ui/assets/assets/images/favicon-light-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  116. package/dist/server/web-ui/assets/assets/images/favicon-light.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  117. package/dist/server/web-ui/assets/assets/images/notification-icon.3bf81d33ddbf380606bdd248ba83e158.png +0 -0
  118. package/dist/server/web-ui/favicon.ico +0 -0
  119. package/dist/server/web-ui/index.html +90 -0
  120. package/dist/server/web-ui/index.html.br +0 -0
  121. package/dist/server/web-ui/index.html.gz +0 -0
  122. package/dist/server/web-ui/manifest.json +27 -0
  123. package/dist/server/web-ui/manifest.json.br +0 -0
  124. package/dist/server/web-ui/manifest.json.gz +0 -0
  125. package/dist/server/web-ui/metadata.json +1 -0
  126. package/dist/server/web-ui/metadata.json.br +1 -0
  127. package/dist/server/web-ui/metadata.json.gz +0 -0
  128. package/dist/server/web-ui/pwa-icon-192.png +0 -0
  129. package/dist/server/web-ui/pwa-icon-512.png +0 -0
  130. package/dist/server/web-ui/robots.txt +2 -0
  131. package/dist/src/server/persisted-config.js +8 -0
  132. package/package.json +7 -7
@@ -11,7 +11,11 @@ function parseLifecycleMessage(msg) {
11
11
  }
12
12
  const type = msg.type;
13
13
  if (type === "paseo:shutdown") {
14
- return { type: "paseo:shutdown" };
14
+ const reason = msg.reason;
15
+ return {
16
+ type: "paseo:shutdown",
17
+ ...(typeof reason === "string" && reason.trim().length > 0 ? { reason } : {}),
18
+ };
15
19
  }
16
20
  if (type === "paseo:ready") {
17
21
  const listen = msg.listen;
@@ -169,12 +173,14 @@ export function runSupervisor(options) {
169
173
  return;
170
174
  }
171
175
  if (lifecycleMessage.type === "paseo:shutdown") {
172
- writeLifecycleLog("Worker requested shutdown");
173
- requestShutdown("Shutdown requested by worker");
176
+ const reason = lifecycleMessage.reason ?? "worker_requested_shutdown";
177
+ writeLifecycleLog("Worker requested shutdown", { reason });
178
+ requestShutdown(reason);
174
179
  return;
175
180
  }
176
- writeLifecycleLog("Worker requested restart", lifecycleMessage.reason ? { reason: lifecycleMessage.reason } : {});
177
- requestRestart("Restart requested by worker");
181
+ const reason = lifecycleMessage.reason ?? "worker_requested_restart";
182
+ writeLifecycleLog("Worker requested restart", { reason });
183
+ requestRestart(reason);
178
184
  });
179
185
  child.on("close", (code, signal) => {
180
186
  clearInterval(heartbeat);
@@ -199,6 +205,18 @@ export function runSupervisor(options) {
199
205
  exitSupervisor(typeof code === "number" ? code : 1);
200
206
  });
201
207
  };
208
+ const signalWorker = (signal, reason) => {
209
+ if (!child) {
210
+ return;
211
+ }
212
+ writeLifecycleLog("Supervisor sending signal to worker", {
213
+ reason,
214
+ signal,
215
+ supervisorPid: process.pid,
216
+ workerPid: child.pid ?? null,
217
+ });
218
+ child.kill(signal);
219
+ };
202
220
  const requestRestart = (reason) => {
203
221
  if (!child || restarting || shuttingDown) {
204
222
  return;
@@ -206,7 +224,7 @@ export function runSupervisor(options) {
206
224
  restarting = true;
207
225
  writeLifecycleLog("Restart requested", { reason });
208
226
  log(`${reason}. Stopping worker for restart...`);
209
- child.kill("SIGTERM");
227
+ signalWorker("SIGTERM", reason);
210
228
  };
211
229
  const requestShutdown = (reason) => {
212
230
  if (shuttingDown) {
@@ -220,10 +238,10 @@ export function runSupervisor(options) {
220
238
  exitSupervisor(0);
221
239
  return;
222
240
  }
223
- child.kill("SIGTERM");
241
+ signalWorker("SIGTERM", reason);
224
242
  };
225
243
  const forwardSignal = (signal) => {
226
- requestShutdown(`Received ${signal}`);
244
+ requestShutdown(`supervisor_received_${signal}`);
227
245
  };
228
246
  process.on("SIGINT", () => forwardSignal("SIGINT"));
229
247
  process.on("SIGTERM", () => forwardSignal("SIGTERM"));
@@ -1,11 +1,28 @@
1
1
  import type { AgentTimelineItem } from "./agent-sdk-types.js";
2
+ import type { AgentAttachment } from "@getpaseo/protocol/messages";
3
+ import type { AgentTimelineRow } from "./agent-timeline-store-types.js";
2
4
  interface ActivityCuratorOptions {
3
5
  maxItems?: number;
4
6
  labelAssistantMessages?: boolean;
7
+ includeKinds?: readonly AgentTimelineItem["type"][];
8
+ includeExternalToolInput?: boolean;
5
9
  }
10
+ type TextAgentAttachment = Extract<AgentAttachment, {
11
+ type: "text";
12
+ }>;
6
13
  /**
7
14
  * Convert normalized agent timeline items into a concise text summary.
8
15
  */
9
16
  export declare function curateAgentActivity(timeline: AgentTimelineItem[], options?: ActivityCuratorOptions): string;
17
+ export declare function buildAgentForkContextAttachment(input: {
18
+ rows: readonly AgentTimelineRow[];
19
+ boundaryMessageId?: string | null;
20
+ agentTitle?: string | null;
21
+ cwd?: string | null;
22
+ }): {
23
+ attachment: TextAgentAttachment;
24
+ itemCount: number;
25
+ boundaryMessageId: string | null;
26
+ };
10
27
  export {};
11
28
  //# sourceMappingURL=activity-curator.d.ts.map
@@ -71,16 +71,42 @@ function projectForCuration(items) {
71
71
  }));
72
72
  return projectTimelineRows({ rows, mode: "projected" }).map((entry) => entry.item);
73
73
  }
74
- function curateAgentActivityEntries(timeline, options) {
75
- if (timeline.length === 0) {
74
+ function shouldIncludeItem(item, options) {
75
+ if (!options?.includeKinds) {
76
+ return true;
77
+ }
78
+ return options.includeKinds.includes(item.type);
79
+ }
80
+ function formatToolCallEntry(item, options) {
81
+ const inputJson = formatToolInputJson(inputFromUnknownDetail(item.detail));
82
+ const display = buildToolCallDisplayModel({
83
+ name: item.name,
84
+ status: item.status,
85
+ error: item.error,
86
+ detail: item.detail,
87
+ metadata: item.metadata,
88
+ });
89
+ const displayName = display.displayName;
90
+ const summary = formatToolSummary(display.summary);
91
+ if ((options?.includeExternalToolInput ?? true) &&
92
+ isLikelyExternalToolName(item.name) &&
93
+ inputJson) {
94
+ return activityEntry(`[${displayName}] ${inputJson}`);
95
+ }
96
+ return activityEntry(summary ? `[${displayName}] ${summary}` : `[${displayName}]`);
97
+ }
98
+ function curateProjectedActivityEntries(items, options) {
99
+ if (items.length === 0) {
76
100
  return [];
77
101
  }
78
- const collapsed = projectForCuration(timeline);
79
102
  const maxItems = options?.maxItems ?? DEFAULT_MAX_ITEMS;
80
- const recentItems = maxItems > 0 && collapsed.length > maxItems ? collapsed.slice(-maxItems) : collapsed;
103
+ const recentItems = maxItems > 0 && items.length > maxItems ? items.slice(-maxItems) : items;
81
104
  const entries = [];
82
105
  const buffers = { message: "", thought: "" };
83
106
  for (const item of recentItems) {
107
+ if (!shouldIncludeItem(item, options)) {
108
+ continue;
109
+ }
84
110
  switch (item.type) {
85
111
  case "user_message":
86
112
  flushBuffers(entries, buffers, options);
@@ -94,26 +120,7 @@ function curateAgentActivityEntries(timeline, options) {
94
120
  break;
95
121
  case "tool_call": {
96
122
  flushBuffers(entries, buffers, options);
97
- const inputJson = formatToolInputJson(inputFromUnknownDetail(item.detail));
98
- const display = buildToolCallDisplayModel({
99
- name: item.name,
100
- status: item.status,
101
- error: item.error,
102
- detail: item.detail,
103
- metadata: item.metadata,
104
- });
105
- const displayName = display.displayName;
106
- const summary = formatToolSummary(display.summary);
107
- if (isLikelyExternalToolName(item.name) && inputJson) {
108
- entries.push(activityEntry(`[${displayName}] ${inputJson}`));
109
- break;
110
- }
111
- if (summary) {
112
- entries.push(activityEntry(`[${displayName}] ${summary}`));
113
- }
114
- else {
115
- entries.push(activityEntry(`[${displayName}]`));
116
- }
123
+ entries.push(formatToolCallEntry(item, options));
117
124
  break;
118
125
  }
119
126
  case "todo":
@@ -138,6 +145,10 @@ function curateAgentActivityEntries(timeline, options) {
138
145
  flushBuffers(entries, buffers, options);
139
146
  return entries;
140
147
  }
148
+ function curateAgentActivityEntries(timeline, options) {
149
+ const collapsed = projectForCuration(timeline);
150
+ return curateProjectedActivityEntries(collapsed, options);
151
+ }
141
152
  /**
142
153
  * Convert normalized agent timeline items into a concise text summary.
143
154
  */
@@ -147,4 +158,70 @@ export function curateAgentActivity(timeline, options) {
147
158
  ? entries.map((entry) => entry.text).join("\n")
148
159
  : "No activity to display.";
149
160
  }
161
+ function selectForkContextRows(input) {
162
+ const boundaryMessageId = input.boundaryMessageId?.trim() || null;
163
+ if (!boundaryMessageId) {
164
+ const projected = projectTimelineRows({ rows: input.rows, mode: "projected" });
165
+ return {
166
+ items: projected.map((entry) => entry.item),
167
+ boundaryMessageId: null,
168
+ };
169
+ }
170
+ const boundaryIndex = input.rows.findLastIndex((row) => row.item.type === "assistant_message" && row.item.messageId === boundaryMessageId);
171
+ if (boundaryIndex < 0) {
172
+ throw new Error("Selected assistant message is no longer available.");
173
+ }
174
+ const selectedRows = input.rows.slice(0, boundaryIndex + 1);
175
+ const projected = projectTimelineRows({ rows: selectedRows, mode: "projected" });
176
+ return {
177
+ items: projected.map((entry) => entry.item),
178
+ boundaryMessageId,
179
+ };
180
+ }
181
+ function trimContextMetadata(value) {
182
+ const trimmed = value?.trim();
183
+ return trimmed ? trimmed : null;
184
+ }
185
+ function buildForkContextText(input) {
186
+ const header = ["Chat history from a previous Paseo agent."];
187
+ const agentTitle = trimContextMetadata(input.agentTitle);
188
+ const cwd = trimContextMetadata(input.cwd);
189
+ if (agentTitle) {
190
+ header.push(`Source agent: ${agentTitle}`);
191
+ }
192
+ if (cwd) {
193
+ header.push(`Source directory: ${cwd}`);
194
+ }
195
+ return `${header.join("\n")}\n\n${input.body}`;
196
+ }
197
+ export function buildAgentForkContextAttachment(input) {
198
+ const selected = selectForkContextRows({
199
+ rows: input.rows,
200
+ boundaryMessageId: input.boundaryMessageId,
201
+ });
202
+ const entries = curateProjectedActivityEntries(selected.items, {
203
+ maxItems: 0,
204
+ labelAssistantMessages: true,
205
+ includeKinds: ["user_message", "assistant_message", "tool_call"],
206
+ includeExternalToolInput: false,
207
+ });
208
+ const body = entries.length > 0
209
+ ? entries.map((entry) => entry.text).join("\n")
210
+ : "No chat history to display.";
211
+ return {
212
+ attachment: {
213
+ type: "text",
214
+ mimeType: "text/plain",
215
+ contextKind: "chat_history",
216
+ title: "Chat history",
217
+ text: buildForkContextText({
218
+ body,
219
+ agentTitle: input.agentTitle,
220
+ cwd: input.cwd,
221
+ }),
222
+ },
223
+ itemCount: selected.items.length,
224
+ boundaryMessageId: selected.boundaryMessageId,
225
+ };
226
+ }
150
227
  //# sourceMappingURL=activity-curator.js.map
@@ -2623,7 +2623,11 @@ export class AgentManager {
2623
2623
  return undefined;
2624
2624
  }
2625
2625
  try {
2626
- const catalog = await client.fetchCatalog({ cwd: config.cwd, force: false });
2626
+ const catalog = await client.fetchCatalog({
2627
+ scope: "workspace",
2628
+ cwd: config.cwd,
2629
+ force: false,
2630
+ });
2627
2631
  return (catalog.models.find((model) => model.isDefault) ?? catalog.models[0])?.id;
2628
2632
  }
2629
2633
  catch {
@@ -585,11 +585,16 @@ export interface AgentSession {
585
585
  }): Promise<void>;
586
586
  } | null;
587
587
  }
588
- export interface FetchCatalogOptions {
588
+ export type FetchCatalogOptions = {
589
+ scope: "global";
590
+ force: boolean;
591
+ timeoutMs?: number;
592
+ } | {
593
+ scope: "workspace";
589
594
  cwd: string;
590
595
  force: boolean;
591
596
  timeoutMs?: number;
592
- }
597
+ };
593
598
  export interface ProviderCatalog {
594
599
  models: AgentModelDefinition[];
595
600
  modes: AgentMode[];
@@ -5,6 +5,7 @@ import type { WorkspaceGitService } from "../workspace-git-service.js";
5
5
  import type { ManagedProcessRegistry } from "../managed-processes/managed-processes.js";
6
6
  import type { AgentProviderRuntimeSettingsMap, ProviderOverride } from "./provider-launch-config.js";
7
7
  import type { MutableDaemonConfig } from "../daemon-config-store.js";
8
+ export declare const GLOBAL_PROVIDER_SNAPSHOT_KEY = "paseo:global";
8
9
  type ProviderSnapshotChangeListener = (entries: ProviderSnapshotEntry[], cwd: string) => void;
9
10
  export interface ProviderSnapshotManagerOptions {
10
11
  logger: Logger;
@@ -21,6 +22,10 @@ interface ProviderSnapshotRefreshOptions {
21
22
  cwd: string;
22
23
  providers?: AgentProvider[];
23
24
  }
25
+ interface ProviderSnapshotWarmUpOptions {
26
+ cwd?: string | null;
27
+ providers?: AgentProvider[];
28
+ }
24
29
  interface ProviderSnapshotReadOptions {
25
30
  cwd?: string | null;
26
31
  providers?: AgentProvider[];
@@ -80,7 +85,7 @@ export declare class ProviderSnapshotManager {
80
85
  getSnapshot(cwd?: string): ProviderSnapshotEntry[];
81
86
  refreshSnapshotForCwd(options: ProviderSnapshotRefreshOptions): Promise<void>;
82
87
  refreshSettingsSnapshot(options?: Omit<ProviderSnapshotRefreshOptions, "cwd">): Promise<void>;
83
- warmUpSnapshotForCwd(options: ProviderSnapshotRefreshOptions): Promise<void>;
88
+ warmUpSnapshotForCwd(options: ProviderSnapshotWarmUpOptions): Promise<void>;
84
89
  refresh(options: ProviderSnapshotRefreshOptions): Promise<void>;
85
90
  listRegisteredProviderIds(): AgentProvider[];
86
91
  hasProvider(provider: AgentProvider): boolean;
@@ -101,6 +106,7 @@ export declare class ProviderSnapshotManager {
101
106
  destroy(): void;
102
107
  private buildRegistry;
103
108
  private resolveParent;
109
+ private getSnapshotForTarget;
104
110
  private getReadyProvider;
105
111
  private requireProvider;
106
112
  private refreshDiagnosticSnapshotEntry;
@@ -124,5 +130,6 @@ export declare class ProviderSnapshotManager {
124
130
  private resolveRefreshProviders;
125
131
  }
126
132
  export declare function resolveSnapshotCwd(cwd?: string | null): string;
133
+ export declare function isGlobalProviderSnapshotKey(cwd: string): boolean;
127
134
  export {};
128
135
  //# sourceMappingURL=provider-snapshot-manager.d.ts.map
@@ -9,6 +9,7 @@ import { formatProviderDiagnostic, formatProviderDiagnosticError, } from "./prov
9
9
  const DEFAULT_REFRESH_TIMEOUT_MS = 60000;
10
10
  const DEFAULT_DIAGNOSTIC_TIMEOUT_MS = 120000;
11
11
  const REFRESH_TIMEOUT_ENV_VAR = "PASEO_PROVIDER_REFRESH_TIMEOUT_MS";
12
+ export const GLOBAL_PROVIDER_SNAPSHOT_KEY = "paseo:global";
12
13
  // Provider refresh probes can be slow on cold starts (e.g. Copilot's first
13
14
  // `copilot --acp` invocation, OpenCode workspace probes with many MCP servers).
14
15
  // Allow operators to bump the ceiling via env var without rebuilding.
@@ -52,31 +53,30 @@ export class ProviderSnapshotManager {
52
53
  this.providerClients = { ...this.extraClients };
53
54
  }
54
55
  getSnapshot(cwd) {
55
- const resolvedCwd = resolveSnapshotCwd(cwd);
56
- const providersToWarm = this.resolveProvidersToWarm(resolvedCwd);
57
- if (providersToWarm.length > 0) {
58
- void this.warmUp(resolvedCwd, providersToWarm);
59
- }
60
- return entriesToArray(this.getOrCreateSnapshot(resolvedCwd));
56
+ const target = resolveProviderSnapshotTarget(cwd);
57
+ return this.getSnapshotForTarget(target);
61
58
  }
62
59
  async refreshSnapshotForCwd(options) {
63
60
  const snapshotCwd = resolveSnapshotCwd(options.cwd);
61
+ const target = createWorkspaceSnapshotTarget(snapshotCwd);
64
62
  const providers = this.resolveRefreshProviders(options.providers);
65
63
  this.resetSnapshotToLoading(snapshotCwd, providers, { preserveExisting: false });
66
64
  this.emitChange(snapshotCwd);
67
- await this.refreshProviders(snapshotCwd, providers ?? this.getProviderIds());
65
+ await this.refreshProviders(target, providers ?? this.getProviderIds());
68
66
  }
69
67
  async refreshSettingsSnapshot(options = {}) {
70
- const homeCwd = resolveSnapshotCwd();
68
+ const target = createGlobalSnapshotTarget();
69
+ const homeCwd = target.snapshotCwd;
71
70
  const providers = this.resolveRefreshProviders(options.providers);
72
71
  const providersToRefresh = providers ?? this.getProviderIds();
73
72
  this.clearCachedProviders(providers);
74
73
  this.resetSnapshotToLoading(homeCwd, providers, { preserveExisting: false });
75
74
  this.emitChange(homeCwd);
76
- await this.refreshProviders(homeCwd, providersToRefresh);
75
+ await this.refreshProviders(target, providersToRefresh);
77
76
  }
78
77
  async warmUpSnapshotForCwd(options) {
79
- const snapshotCwd = resolveSnapshotCwd(options.cwd);
78
+ const target = resolveProviderSnapshotTarget(options.cwd);
79
+ const snapshotCwd = target.snapshotCwd;
80
80
  const providers = this.resolveRefreshProviders(options.providers);
81
81
  if (options.providers && providers?.length === 0) {
82
82
  return;
@@ -85,7 +85,7 @@ export class ProviderSnapshotManager {
85
85
  if (providersToWarm.length === 0) {
86
86
  return;
87
87
  }
88
- await this.warmUp(snapshotCwd, providersToWarm);
88
+ await this.warmUp(target, providersToWarm);
89
89
  }
90
90
  async refresh(options) {
91
91
  await this.refreshSnapshotForCwd(options);
@@ -128,12 +128,12 @@ export class ProviderSnapshotManager {
128
128
  return client;
129
129
  }
130
130
  async listProviders(input = {}) {
131
- const cwd = resolveSnapshotCwd(input.cwd);
131
+ const target = resolveProviderSnapshotTarget(input.cwd);
132
132
  if (input.wait) {
133
- await this.warmUpSnapshotForCwd({ cwd, providers: input.providers });
133
+ await this.warmUpSnapshotForCwd({ cwd: input.cwd, providers: input.providers });
134
134
  }
135
135
  const providerFilter = input.providers ? new Set(input.providers) : null;
136
- const entries = this.getSnapshot(cwd);
136
+ const entries = this.getSnapshotForTarget(target);
137
137
  return providerFilter ? entries.filter((entry) => providerFilter.has(entry.provider)) : entries;
138
138
  }
139
139
  async getProvider(input) {
@@ -276,6 +276,13 @@ export class ProviderSnapshotManager {
276
276
  }),
277
277
  };
278
278
  }
279
+ getSnapshotForTarget(target) {
280
+ const providersToWarm = this.resolveProvidersToWarm(target.snapshotCwd);
281
+ if (providersToWarm.length > 0) {
282
+ void this.warmUp(target, providersToWarm);
283
+ }
284
+ return entriesToArray(this.getOrCreateSnapshot(target.snapshotCwd));
285
+ }
279
286
  async getReadyProvider(input) {
280
287
  const entry = await this.getProvider(input);
281
288
  if (!entry.enabled) {
@@ -298,9 +305,11 @@ export class ProviderSnapshotManager {
298
305
  }
299
306
  async refreshDiagnosticSnapshotEntry(provider, definition) {
300
307
  try {
301
- const cwd = resolveSnapshotCwd();
302
- await this.refreshSnapshotForCwd({ cwd, providers: [provider] });
303
- return await this.getProvider({ cwd, provider, wait: false });
308
+ const target = createGlobalSnapshotTarget();
309
+ this.resetSnapshotToLoading(target.snapshotCwd, [provider], { preserveExisting: false });
310
+ this.emitChange(target.snapshotCwd);
311
+ await this.refreshProviders(target, [provider]);
312
+ return await this.getProvider({ provider, wait: false });
304
313
  }
305
314
  catch (error) {
306
315
  return {
@@ -371,16 +380,22 @@ export class ProviderSnapshotManager {
371
380
  }
372
381
  return entries;
373
382
  }
374
- async warmUp(cwd, providers) {
383
+ async warmUp(target, providers) {
375
384
  const providersToRefresh = providers ?? this.getProviderIds();
376
385
  await this.loadProviders({
377
- cwd,
386
+ snapshotCwd: target.snapshotCwd,
387
+ catalogScope: target.catalogScope,
378
388
  providers: providersToRefresh,
379
389
  force: false,
380
390
  });
381
391
  }
382
- async refreshProviders(cwd, providers) {
383
- await this.loadProviders({ cwd, providers, force: true });
392
+ async refreshProviders(target, providers) {
393
+ await this.loadProviders({
394
+ snapshotCwd: target.snapshotCwd,
395
+ catalogScope: target.catalogScope,
396
+ providers,
397
+ force: true,
398
+ });
384
399
  }
385
400
  resolveProvidersToWarm(cwd, providers) {
386
401
  const providersToInspect = providers ?? this.getProviderIds();
@@ -440,40 +455,41 @@ export class ProviderSnapshotManager {
440
455
  if (!definition) {
441
456
  return Promise.resolve();
442
457
  }
443
- const existingLoad = this.getProviderLoad(options.cwd, options.provider);
458
+ const existingLoad = this.getProviderLoad(options.snapshotCwd, options.provider);
444
459
  if (existingLoad && !options.force) {
445
460
  return existingLoad.promise;
446
461
  }
447
- const existingEntry = this.snapshots.get(options.cwd)?.get(options.provider);
462
+ const existingEntry = this.snapshots.get(options.snapshotCwd)?.get(options.provider);
448
463
  if (existingEntry && existingEntry.status !== "loading" && !options.force) {
449
464
  return Promise.resolve();
450
465
  }
451
466
  const load = {
452
467
  promise: Promise.resolve(),
453
468
  };
454
- this.setProviderLoad(options.cwd, options.provider, load);
469
+ this.setProviderLoad(options.snapshotCwd, options.provider, load);
455
470
  load.promise = Promise.resolve()
456
471
  .then(() => this.refreshProvider({
457
- cwd: options.cwd,
472
+ snapshotCwd: options.snapshotCwd,
473
+ catalogScope: options.catalogScope,
458
474
  provider: options.provider,
459
475
  definition,
460
476
  load,
461
477
  force: options.force,
462
478
  }))
463
479
  .finally(() => {
464
- const providerLoads = this.providerLoads.get(options.cwd);
480
+ const providerLoads = this.providerLoads.get(options.snapshotCwd);
465
481
  if (providerLoads?.get(options.provider) === load) {
466
482
  providerLoads.delete(options.provider);
467
483
  }
468
484
  if (providerLoads?.size === 0) {
469
- this.providerLoads.delete(options.cwd);
485
+ this.providerLoads.delete(options.snapshotCwd);
470
486
  }
471
487
  });
472
488
  return load.promise;
473
489
  }
474
490
  async refreshProvider(options) {
475
- const { cwd, provider, definition, load, force } = options;
476
- const snapshot = this.getOrCreateSnapshot(options.cwd);
491
+ const { snapshotCwd, catalogScope, provider, definition, load, force } = options;
492
+ const snapshot = this.getOrCreateSnapshot(snapshotCwd);
477
493
  const base = {
478
494
  provider,
479
495
  label: definition.label,
@@ -481,11 +497,11 @@ export class ProviderSnapshotManager {
481
497
  defaultModeId: definition.defaultModeId,
482
498
  };
483
499
  const setEntry = (entry) => {
484
- if (!this.isCurrentProviderLoad(cwd, provider, load)) {
500
+ if (!this.isCurrentProviderLoad(snapshotCwd, provider, load)) {
485
501
  return false;
486
502
  }
487
503
  snapshot.set(provider, entry);
488
- this.emitChange(cwd);
504
+ this.emitChange(snapshotCwd);
489
505
  return true;
490
506
  };
491
507
  try {
@@ -499,7 +515,8 @@ export class ProviderSnapshotManager {
499
515
  setEntry({ ...base, status: "unavailable", enabled: true });
500
516
  return;
501
517
  }
502
- const catalog = await withTimeout(definition.fetchCatalog({ cwd, force, timeoutMs: this.refreshTimeoutMs }, client), this.refreshTimeoutMs, `Timed out refreshing ${definition.label} after ${this.refreshTimeoutMs}ms`);
518
+ const catalogOptions = createFetchCatalogOptions(catalogScope, force);
519
+ const catalog = await withTimeout(definition.fetchCatalog({ ...catalogOptions, timeoutMs: this.refreshTimeoutMs }, client), this.refreshTimeoutMs, `Timed out refreshing ${definition.label} after ${this.refreshTimeoutMs}ms`);
503
520
  setEntry({
504
521
  ...base,
505
522
  status: "ready",
@@ -517,7 +534,7 @@ export class ProviderSnapshotManager {
517
534
  error: toErrorMessage(error),
518
535
  });
519
536
  if (emitted) {
520
- this.logger.warn({ err: error, provider, cwd }, "Failed to refresh provider snapshot");
537
+ this.logger.warn({ err: error, provider, cwd: snapshotCwd }, "Failed to refresh provider snapshot");
521
538
  }
522
539
  }
523
540
  }
@@ -609,6 +626,34 @@ export function resolveSnapshotCwd(cwd) {
609
626
  }
610
627
  return resolved;
611
628
  }
629
+ function resolveProviderSnapshotTarget(cwd) {
630
+ const trimmed = cwd?.trim();
631
+ if (!trimmed) {
632
+ return createGlobalSnapshotTarget();
633
+ }
634
+ return createWorkspaceSnapshotTarget(resolveSnapshotCwd(trimmed));
635
+ }
636
+ function createGlobalSnapshotTarget() {
637
+ return {
638
+ snapshotCwd: GLOBAL_PROVIDER_SNAPSHOT_KEY,
639
+ catalogScope: { scope: "global" },
640
+ };
641
+ }
642
+ function createWorkspaceSnapshotTarget(cwd) {
643
+ const snapshotCwd = resolveSnapshotCwd(cwd);
644
+ return {
645
+ snapshotCwd,
646
+ catalogScope: { scope: "workspace", cwd: snapshotCwd },
647
+ };
648
+ }
649
+ function createFetchCatalogOptions(scope, force) {
650
+ return scope.scope === "global"
651
+ ? { scope: "global", force }
652
+ : { scope: "workspace", cwd: scope.cwd, force };
653
+ }
654
+ export function isGlobalProviderSnapshotKey(cwd) {
655
+ return cwd === GLOBAL_PROVIDER_SNAPSHOT_KEY;
656
+ }
612
657
  function entriesToArray(entries) {
613
658
  return Array.from(entries.values(), cloneEntry);
614
659
  }
@@ -261,6 +261,13 @@ export declare class ACPAgentSession implements AgentSession, ACPClient {
261
261
  constructor(config: AgentSessionConfig, options: ACPAgentSessionOptions);
262
262
  get id(): string | null;
263
263
  initializeNewSession(): Promise<void>;
264
+ /**
265
+ * IMPORTANT: Some ACP providers (e.g., Devin CLI) require all three params
266
+ * (sessionId, cwd, mcpServers) to be present in session/load or
267
+ * unstable_resumeSession — even when mcpServers is an empty array — and
268
+ * return "Invalid params" if any are omitted. Never drop cwd or mcpServers
269
+ * from these calls regardless of capabilities.
270
+ */
264
271
  initializeResumedSession(): Promise<void>;
265
272
  run(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<AgentRunResult>;
266
273
  startTurn(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<{
@@ -386,7 +386,7 @@ export class ACPAgentClient {
386
386
  return session;
387
387
  }
388
388
  async fetchCatalog(options) {
389
- const { cwd } = options;
389
+ const cwd = options.scope === "global" ? homedir() : options.cwd;
390
390
  const timeoutMs = options.timeoutMs ?? ACP_CATALOG_TIMEOUT_MS;
391
391
  let probe = null;
392
392
  try {
@@ -802,6 +802,13 @@ export class ACPAgentSession {
802
802
  this.applySessionState(response);
803
803
  await this.applyConfiguredOverrides();
804
804
  }
805
+ /**
806
+ * IMPORTANT: Some ACP providers (e.g., Devin CLI) require all three params
807
+ * (sessionId, cwd, mcpServers) to be present in session/load or
808
+ * unstable_resumeSession — even when mcpServers is an empty array — and
809
+ * return "Invalid params" if any are omitted. Never drop cwd or mcpServers
810
+ * from these calls regardless of capabilities.
811
+ */
805
812
  async initializeResumedSession() {
806
813
  const handle = this.initialHandle;
807
814
  if (!handle) {