@getpaseo/server 0.1.70 → 0.1.72

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 (197) hide show
  1. package/dist/server/client/daemon-client.d.ts +24 -4
  2. package/dist/server/client/daemon-client.d.ts.map +1 -1
  3. package/dist/server/client/daemon-client.js +41 -2
  4. package/dist/server/client/daemon-client.js.map +1 -1
  5. package/dist/server/server/agent/agent-manager.d.ts +17 -4
  6. package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
  7. package/dist/server/server/agent/agent-manager.js +177 -21
  8. package/dist/server/server/agent/agent-manager.js.map +1 -1
  9. package/dist/server/server/agent/agent-metadata-generator.d.ts +2 -0
  10. package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
  11. package/dist/server/server/agent/agent-metadata-generator.js +16 -7
  12. package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
  13. package/dist/server/server/agent/agent-projections.d.ts +6 -2
  14. package/dist/server/server/agent/agent-projections.d.ts.map +1 -1
  15. package/dist/server/server/agent/agent-projections.js +32 -0
  16. package/dist/server/server/agent/agent-projections.js.map +1 -1
  17. package/dist/server/server/agent/agent-prompt.d.ts +72 -0
  18. package/dist/server/server/agent/agent-prompt.d.ts.map +1 -0
  19. package/dist/server/server/agent/agent-prompt.js +169 -0
  20. package/dist/server/server/agent/agent-prompt.js.map +1 -0
  21. package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -1
  22. package/dist/server/server/agent/agent-response-loop.js +2 -1
  23. package/dist/server/server/agent/agent-response-loop.js.map +1 -1
  24. package/dist/server/server/agent/agent-sdk-types.d.ts +12 -0
  25. package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
  26. package/dist/server/server/agent/create-agent-mode.d.ts +2 -0
  27. package/dist/server/server/agent/create-agent-mode.d.ts.map +1 -1
  28. package/dist/server/server/agent/create-agent-mode.js +3 -0
  29. package/dist/server/server/agent/create-agent-mode.js.map +1 -1
  30. package/dist/server/server/agent/create-agent-title.d.ts +8 -0
  31. package/dist/server/server/agent/create-agent-title.d.ts.map +1 -0
  32. package/dist/server/server/agent/create-agent-title.js +29 -0
  33. package/dist/server/server/agent/create-agent-title.js.map +1 -0
  34. package/dist/server/server/agent/import-sessions.d.ts +52 -0
  35. package/dist/server/server/agent/import-sessions.d.ts.map +1 -0
  36. package/dist/server/server/agent/import-sessions.js +208 -0
  37. package/dist/server/server/agent/import-sessions.js.map +1 -0
  38. package/dist/server/server/agent/mcp-server.d.ts +1 -1
  39. package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
  40. package/dist/server/server/agent/mcp-server.js +29 -6
  41. package/dist/server/server/agent/mcp-server.js.map +1 -1
  42. package/dist/server/server/agent/mcp-shared.d.ts +1 -47
  43. package/dist/server/server/agent/mcp-shared.d.ts.map +1 -1
  44. package/dist/server/server/agent/mcp-shared.js +0 -145
  45. package/dist/server/server/agent/mcp-shared.js.map +1 -1
  46. package/dist/server/server/agent/provider-registry.d.ts +7 -0
  47. package/dist/server/server/agent/provider-registry.d.ts.map +1 -1
  48. package/dist/server/server/agent/provider-registry.js +7 -1
  49. package/dist/server/server/agent/provider-registry.js.map +1 -1
  50. package/dist/server/server/agent/providers/claude/agent.d.ts.map +1 -1
  51. package/dist/server/server/agent/providers/claude/agent.js +15 -0
  52. package/dist/server/server/agent/providers/claude/agent.js.map +1 -1
  53. package/dist/server/server/agent/providers/codex/app-server-transport.d.ts +25 -0
  54. package/dist/server/server/agent/providers/codex/app-server-transport.d.ts.map +1 -0
  55. package/dist/server/server/agent/providers/codex/app-server-transport.js +183 -0
  56. package/dist/server/server/agent/providers/codex/app-server-transport.js.map +1 -0
  57. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +9 -22
  58. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
  59. package/dist/server/server/agent/providers/codex-app-server-agent.js +39 -171
  60. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
  61. package/dist/server/server/agent/providers/opencode/runtime.d.ts +27 -0
  62. package/dist/server/server/agent/providers/opencode/runtime.d.ts.map +1 -0
  63. package/dist/server/server/agent/providers/opencode/runtime.js +5 -0
  64. package/dist/server/server/agent/providers/opencode/runtime.js.map +1 -0
  65. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +55 -0
  66. package/dist/server/server/agent/providers/opencode/server-manager.d.ts.map +1 -0
  67. package/dist/server/server/agent/providers/opencode/server-manager.js +255 -0
  68. package/dist/server/server/agent/providers/opencode/server-manager.js.map +1 -0
  69. package/dist/server/server/agent/providers/opencode/test-server-manager.d.ts +22 -0
  70. package/dist/server/server/agent/providers/opencode/test-server-manager.d.ts.map +1 -0
  71. package/dist/server/server/agent/providers/opencode/test-server-manager.js +28 -0
  72. package/dist/server/server/agent/providers/opencode/test-server-manager.js.map +1 -0
  73. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts +75 -0
  74. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts.map +1 -0
  75. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js +169 -0
  76. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js.map +1 -0
  77. package/dist/server/server/agent/providers/opencode-agent.d.ts +7 -36
  78. package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
  79. package/dist/server/server/agent/providers/opencode-agent.js +199 -261
  80. package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
  81. package/dist/server/server/agent/providers/pi-direct-agent.d.ts +8 -3
  82. package/dist/server/server/agent/providers/pi-direct-agent.d.ts.map +1 -1
  83. package/dist/server/server/agent/providers/pi-direct-agent.js +44 -34
  84. package/dist/server/server/agent/providers/pi-direct-agent.js.map +1 -1
  85. package/dist/server/server/chat/chat-mentions.d.ts +24 -8
  86. package/dist/server/server/chat/chat-mentions.d.ts.map +1 -1
  87. package/dist/server/server/chat/chat-mentions.js +77 -35
  88. package/dist/server/server/chat/chat-mentions.js.map +1 -1
  89. package/dist/server/server/chat/chat-service.d.ts +4 -0
  90. package/dist/server/server/chat/chat-service.d.ts.map +1 -1
  91. package/dist/server/server/chat/chat-service.js +9 -0
  92. package/dist/server/server/chat/chat-service.js.map +1 -1
  93. package/dist/server/server/checkout/status-projection.d.ts +19 -0
  94. package/dist/server/server/checkout/status-projection.d.ts.map +1 -0
  95. package/dist/server/server/checkout/status-projection.js +98 -0
  96. package/dist/server/server/checkout/status-projection.js.map +1 -0
  97. package/dist/server/server/daemon-keypair.d.ts.map +1 -1
  98. package/dist/server/server/daemon-keypair.js +4 -2
  99. package/dist/server/server/daemon-keypair.js.map +1 -1
  100. package/dist/server/server/exports.d.ts +1 -0
  101. package/dist/server/server/exports.d.ts.map +1 -1
  102. package/dist/server/server/exports.js +1 -0
  103. package/dist/server/server/exports.js.map +1 -1
  104. package/dist/server/server/paseo-home.js +2 -2
  105. package/dist/server/server/paseo-home.js.map +1 -1
  106. package/dist/server/server/paseo-worktree-service.d.ts +2 -1
  107. package/dist/server/server/paseo-worktree-service.d.ts.map +1 -1
  108. package/dist/server/server/paseo-worktree-service.js +30 -3
  109. package/dist/server/server/paseo-worktree-service.js.map +1 -1
  110. package/dist/server/server/persisted-config.d.ts.map +1 -1
  111. package/dist/server/server/persisted-config.js +5 -4
  112. package/dist/server/server/persisted-config.js.map +1 -1
  113. package/dist/server/server/private-files.d.ts +7 -0
  114. package/dist/server/server/private-files.d.ts.map +1 -0
  115. package/dist/server/server/private-files.js +42 -0
  116. package/dist/server/server/private-files.js.map +1 -0
  117. package/dist/server/server/push/token-store.d.ts.map +1 -1
  118. package/dist/server/server/push/token-store.js +4 -6
  119. package/dist/server/server/push/token-store.js.map +1 -1
  120. package/dist/server/server/schedule/service.d.ts +1 -1
  121. package/dist/server/server/schedule/service.d.ts.map +1 -1
  122. package/dist/server/server/schedule/service.js +14 -11
  123. package/dist/server/server/schedule/service.js.map +1 -1
  124. package/dist/server/server/server-id.d.ts.map +1 -1
  125. package/dist/server/server/server-id.js +8 -3
  126. package/dist/server/server/server-id.js.map +1 -1
  127. package/dist/server/server/session.d.ts +3 -17
  128. package/dist/server/server/session.d.ts.map +1 -1
  129. package/dist/server/server/session.js +174 -254
  130. package/dist/server/server/session.js.map +1 -1
  131. package/dist/server/server/workspace-directory.d.ts +0 -2
  132. package/dist/server/server/workspace-directory.d.ts.map +1 -1
  133. package/dist/server/server/workspace-directory.js +9 -26
  134. package/dist/server/server/workspace-directory.js.map +1 -1
  135. package/dist/server/server/workspace-git-service.d.ts +2 -1
  136. package/dist/server/server/workspace-git-service.d.ts.map +1 -1
  137. package/dist/server/server/workspace-git-service.js +1 -1
  138. package/dist/server/server/workspace-git-service.js.map +1 -1
  139. package/dist/server/server/worktree-branch-name-generator.d.ts +2 -0
  140. package/dist/server/server/worktree-branch-name-generator.d.ts.map +1 -1
  141. package/dist/server/server/worktree-branch-name-generator.js +18 -11
  142. package/dist/server/server/worktree-branch-name-generator.js.map +1 -1
  143. package/dist/server/services/github-service.d.ts +13 -0
  144. package/dist/server/services/github-service.d.ts.map +1 -1
  145. package/dist/server/services/github-service.js +12 -2
  146. package/dist/server/services/github-service.js.map +1 -1
  147. package/dist/server/shared/agent-labels.d.ts +2 -0
  148. package/dist/server/shared/agent-labels.d.ts.map +1 -0
  149. package/dist/server/shared/agent-labels.js +2 -0
  150. package/dist/server/shared/agent-labels.js.map +1 -0
  151. package/dist/server/shared/agent-state-bucket.d.ts +13 -0
  152. package/dist/server/shared/agent-state-bucket.d.ts.map +1 -0
  153. package/dist/server/shared/agent-state-bucket.js +41 -0
  154. package/dist/server/shared/agent-state-bucket.js.map +1 -0
  155. package/dist/server/shared/git-remote.d.ts +16 -0
  156. package/dist/server/shared/git-remote.d.ts.map +1 -0
  157. package/dist/server/shared/git-remote.js +72 -0
  158. package/dist/server/shared/git-remote.js.map +1 -0
  159. package/dist/server/shared/importable-providers.d.ts +7 -0
  160. package/dist/server/shared/importable-providers.d.ts.map +1 -0
  161. package/dist/server/shared/importable-providers.js +7 -0
  162. package/dist/server/shared/importable-providers.js.map +1 -0
  163. package/dist/server/shared/messages.d.ts +7148 -690
  164. package/dist/server/shared/messages.d.ts.map +1 -1
  165. package/dist/server/shared/messages.js +56 -4
  166. package/dist/server/shared/messages.js.map +1 -1
  167. package/dist/server/utils/build-metadata-prompt.d.ts +14 -0
  168. package/dist/server/utils/build-metadata-prompt.d.ts.map +1 -0
  169. package/dist/server/utils/build-metadata-prompt.js +28 -0
  170. package/dist/server/utils/build-metadata-prompt.js.map +1 -0
  171. package/dist/server/utils/checkout-git.d.ts +3 -1
  172. package/dist/server/utils/checkout-git.d.ts.map +1 -1
  173. package/dist/server/utils/checkout-git.js +3 -0
  174. package/dist/server/utils/checkout-git.js.map +1 -1
  175. package/dist/server/utils/github-remote.d.ts +3 -7
  176. package/dist/server/utils/github-remote.d.ts.map +1 -1
  177. package/dist/server/utils/github-remote.js +4 -70
  178. package/dist/server/utils/github-remote.js.map +1 -1
  179. package/dist/server/utils/paseo-config-schema.d.ts +625 -0
  180. package/dist/server/utils/paseo-config-schema.d.ts.map +1 -1
  181. package/dist/server/utils/paseo-config-schema.js +17 -0
  182. package/dist/server/utils/paseo-config-schema.js.map +1 -1
  183. package/dist/server/utils/wrap-user-instructions.d.ts +2 -0
  184. package/dist/server/utils/wrap-user-instructions.d.ts.map +1 -0
  185. package/dist/server/utils/wrap-user-instructions.js +13 -0
  186. package/dist/server/utils/wrap-user-instructions.js.map +1 -0
  187. package/dist/src/server/paseo-home.js +2 -2
  188. package/dist/src/server/paseo-home.js.map +1 -1
  189. package/dist/src/server/persisted-config.js +5 -4
  190. package/dist/src/server/persisted-config.js.map +1 -1
  191. package/dist/src/server/private-files.js +42 -0
  192. package/dist/src/server/private-files.js.map +1 -0
  193. package/dist/src/shared/messages.js +56 -4
  194. package/dist/src/shared/messages.js.map +1 -1
  195. package/dist/src/utils/paseo-config-schema.js +17 -0
  196. package/dist/src/utils/paseo-config-schema.js.map +1 -1
  197. package/package.json +4 -4
@@ -2,16 +2,55 @@ import { randomUUID } from "node:crypto";
2
2
  import { resolve } from "node:path";
3
3
  import { stat } from "node:fs/promises";
4
4
  import { AGENT_LIFECYCLE_STATUSES, } from "../../shared/agent-lifecycle.js";
5
+ import { PARENT_AGENT_ID_LABEL } from "../../shared/agent-labels.js";
5
6
  import { z } from "zod";
6
7
  import { InMemoryAgentTimelineStore, } from "./agent-timeline-store.js";
7
8
  import { AGENT_STREAM_COALESCE_DEFAULT_WINDOW_MS, AgentStreamCoalescer, } from "./agent-stream-coalescer.js";
8
9
  import { ForegroundRunState } from "./foreground-run-state.js";
9
10
  import { getAgentProviderDefinition } from "./provider-manifest.js";
11
+ import { IMPORTABLE_PROVIDERS } from "./provider-registry.js";
10
12
  const RELOAD_SESSION_CLOSE_TIMEOUT_MS = 3000;
11
13
  const INTERRUPT_SESSION_TIMEOUT_MS = 2000;
14
+ const STORED_AGENT_CAPABILITIES = {
15
+ supportsStreaming: false,
16
+ supportsSessionPersistence: true,
17
+ supportsDynamicModes: false,
18
+ supportsMcpServers: false,
19
+ supportsReasoningStream: false,
20
+ supportsToolInvocations: true,
21
+ };
12
22
  function formatProviderList(providers) {
13
23
  return providers.length > 0 ? providers.join(", ") : "none";
14
24
  }
25
+ function buildStoredAgentConfig(record) {
26
+ const config = {
27
+ provider: record.provider,
28
+ cwd: record.cwd,
29
+ };
30
+ if (!record.config) {
31
+ return config;
32
+ }
33
+ if (record.config.title != null)
34
+ config.title = record.config.title;
35
+ if (record.config.modeId != null)
36
+ config.modeId = record.config.modeId;
37
+ if (record.config.model != null)
38
+ config.model = record.config.model;
39
+ if (record.config.thinkingOptionId != null) {
40
+ config.thinkingOptionId = record.config.thinkingOptionId;
41
+ }
42
+ if (record.config.featureValues != null) {
43
+ config.featureValues = record.config.featureValues;
44
+ }
45
+ if (record.config.extra != null)
46
+ config.extra = record.config.extra;
47
+ if (record.config.systemPrompt != null) {
48
+ config.systemPrompt = record.config.systemPrompt;
49
+ }
50
+ if (record.config.mcpServers != null)
51
+ config.mcpServers = record.config.mcpServers;
52
+ return config;
53
+ }
15
54
  export { AGENT_LIFECYCLE_STATUSES };
16
55
  function resolveInitialAttention(input) {
17
56
  if (input == null || !input.requiresAttention) {
@@ -99,6 +138,7 @@ export class AgentManager {
99
138
  constructor(options) {
100
139
  this.clients = new Map();
101
140
  this.providerEnabled = new Map();
141
+ this.providerDerivedFromId = new Map();
102
142
  this.agents = new Map();
103
143
  this.timelineStore = new InMemoryAgentTimelineStore();
104
144
  this.agentsAwaitingInitialSnapshotPersist = new Set();
@@ -137,6 +177,7 @@ export class AgentManager {
137
177
  for (const [provider, definition] of Object.entries(input.providerDefinitions)) {
138
178
  if (definition) {
139
179
  this.providerEnabled.set(provider, definition.enabled);
180
+ this.providerDerivedFromId.set(provider, definition.derivedFromProviderId ?? null);
140
181
  }
141
182
  }
142
183
  for (const [provider, client] of Object.entries(input.clients)) {
@@ -239,18 +280,15 @@ export class AgentManager {
239
280
  .filter((agent) => !agent.internal)
240
281
  .map((agent) => Object.assign({}, agent));
241
282
  }
242
- async listPersistedAgents(options) {
243
- if (options?.provider) {
244
- const client = this.requireClient(options.provider);
245
- if (!client.listPersistedAgents) {
246
- return [];
247
- }
248
- return client.listPersistedAgents({ limit: options.limit });
249
- }
250
- const providerEntries = Array.from(this.clients.entries()).filter(([, client]) => !!client.listPersistedAgents);
283
+ async listImportablePersistedAgents(options) {
284
+ const providerEntries = Array.from(this.clients.entries()).filter(([provider, client]) => !!client.listPersistedAgents &&
285
+ this.isProviderImportable(provider, options?.providerFilter));
251
286
  const descriptorLists = await Promise.all(providerEntries.map(async ([provider, client]) => {
252
287
  try {
253
- return await client.listPersistedAgents({ limit: options?.limit });
288
+ return await client.listPersistedAgents({
289
+ limit: options?.limit,
290
+ cwd: options?.cwd,
291
+ });
254
292
  }
255
293
  catch (error) {
256
294
  this.logger.warn({ err: error, provider }, "Failed to list persisted agents for provider");
@@ -263,6 +301,21 @@ export class AgentManager {
263
301
  .sort((a, b) => b.lastActivityAt.getTime() - a.lastActivityAt.getTime())
264
302
  .slice(0, limit);
265
303
  }
304
+ isProviderImportable(provider, providerFilter) {
305
+ if (!IMPORTABLE_PROVIDERS.includes(provider)) {
306
+ return false;
307
+ }
308
+ if (this.providerEnabled.get(provider) === false) {
309
+ return false;
310
+ }
311
+ if (this.providerDerivedFromId.get(provider) != null) {
312
+ return false;
313
+ }
314
+ if (providerFilter && !providerFilter.has(provider)) {
315
+ return false;
316
+ }
317
+ return true;
318
+ }
266
319
  async findPersistedAgent(provider, sessionId) {
267
320
  const client = this.requireClient(provider);
268
321
  if (!client.listPersistedAgents) {
@@ -427,14 +480,19 @@ export class AgentManager {
427
480
  const session = await client.resumeSession(handle, hasResumeOverrides ? resumeOverrides : undefined, launchContext);
428
481
  return this.registerSession(session, normalizedConfig, resolvedAgentId, options);
429
482
  }
430
- // Hot-reload an active agent session with config overrides while preserving
431
- // in-memory timeline state.
432
- async reloadAgentSession(agentId, overrides) {
483
+ // Hot-reload an active agent session with config overrides. By default the
484
+ // in-memory timeline is preserved (used for voice-mode toggles and similar
485
+ // config swaps). When `rehydrateFromDisk` is set, the timeline is wiped so a
486
+ // new epoch is minted and provider history is re-streamed — this is what the
487
+ // user-facing "Reload agent" action wants when the on-disk session was
488
+ // mutated outside Paseo.
489
+ async reloadAgentSession(agentId, overrides, options) {
433
490
  let existing = this.requireSessionAgent(agentId);
434
491
  if (this.hasInFlightRun(agentId)) {
435
492
  await this.cancelAgentRun(agentId);
436
493
  existing = this.requireSessionAgent(agentId);
437
494
  }
495
+ const rehydrateFromDisk = options?.rehydrateFromDisk ?? false;
438
496
  const preservedHistoryPrimed = existing.historyPrimed;
439
497
  const preservedLastUsage = existing.lastUsage;
440
498
  const preservedLastError = existing.lastError;
@@ -461,13 +519,20 @@ export class AgentManager {
461
519
  }
462
520
  this.foregroundRuns.clearAgent(agentId, existing);
463
521
  await this.closeReloadedSession(existing.session, agentId);
522
+ if (rehydrateFromDisk) {
523
+ // Wipe both durable and in-memory timeline so registerSession mints a
524
+ // new epoch and hydrateTimelineFromProvider re-streams the freshly read
525
+ // provider history into an empty timeline.
526
+ await this.deleteCommittedTimeline(agentId);
527
+ this.timelineStore.delete(agentId);
528
+ }
464
529
  // Preserve existing labels and timeline during reload.
465
530
  return this.registerSession(session, normalizedConfig, agentId, {
466
531
  labels: existing.labels,
467
532
  createdAt: existing.createdAt,
468
533
  updatedAt: existing.updatedAt,
469
534
  lastUserMessageAt: existing.lastUserMessageAt,
470
- historyPrimed: preservedHistoryPrimed,
535
+ historyPrimed: rehydrateFromDisk ? false : preservedHistoryPrimed,
471
536
  lastUsage: preservedLastUsage,
472
537
  lastError: preservedLastError,
473
538
  attention: preservedAttention,
@@ -546,22 +611,99 @@ export class AgentManager {
546
611
  if (!stored) {
547
612
  throw new Error(`Agent ${agentId} not found in storage after snapshot`);
548
613
  }
614
+ const { archivedAt } = await this.markRecordArchived(stored);
615
+ await this.closeAgent(agentId);
616
+ await this.cascadeArchiveChildren(agentId);
617
+ return { archivedAt };
618
+ }
619
+ // Children created via the MCP `create_agent` tool carry the parent-agent-id
620
+ // label pointing back at the caller. Archiving the parent cascades to those
621
+ // children so subagent fleets don't outlive their orchestrator. Handoff agents
622
+ // launched the same way are caught by this cascade — see docs/agent-lifecycle.md
623
+ // for the accepted limitation.
624
+ async cascadeArchiveChildren(parentAgentId) {
625
+ const registry = this.registry;
626
+ if (!registry) {
627
+ return;
628
+ }
629
+ const records = await registry.list();
630
+ for (const record of records) {
631
+ if (record.archivedAt) {
632
+ continue;
633
+ }
634
+ if (record.labels?.[PARENT_AGENT_ID_LABEL] !== parentAgentId) {
635
+ continue;
636
+ }
637
+ if (this.agents.has(record.id)) {
638
+ await this.archiveAgent(record.id);
639
+ }
640
+ else {
641
+ await this.markRecordArchived(record);
642
+ await this.cascadeArchiveChildren(record.id);
643
+ }
644
+ }
645
+ }
646
+ async markRecordArchived(record) {
647
+ const registry = this.requireRegistry();
549
648
  const archivedAt = new Date().toISOString();
550
- const normalizedStatus = stored.lastStatus === "running" || stored.lastStatus === "initializing"
649
+ const normalizedStatus = record.lastStatus === "running" || record.lastStatus === "initializing"
551
650
  ? "idle"
552
- : stored.lastStatus;
553
- await this.registry.upsert({
554
- ...stored,
651
+ : record.lastStatus;
652
+ const archivedRecord = {
653
+ ...record,
555
654
  archivedAt,
556
655
  updatedAt: archivedAt,
557
656
  lastStatus: normalizedStatus,
558
657
  requiresAttention: false,
559
658
  attentionReason: null,
560
659
  attentionTimestamp: null,
660
+ };
661
+ await registry.upsert(archivedRecord);
662
+ await this.archiveNativeSessionBestEffort(record.provider, record.persistence);
663
+ if (this.agents.has(record.id)) {
664
+ this.notifyAgentState(record.id);
665
+ }
666
+ else if (!archivedRecord.internal) {
667
+ this.dispatchArchivedStoredAgent(archivedRecord);
668
+ }
669
+ return archivedRecord;
670
+ }
671
+ dispatchArchivedStoredAgent(record) {
672
+ const updatedAt = new Date(record.updatedAt);
673
+ this.dispatch({
674
+ type: "agent_state",
675
+ agent: {
676
+ id: record.id,
677
+ provider: record.provider,
678
+ cwd: record.cwd,
679
+ session: null,
680
+ capabilities: STORED_AGENT_CAPABILITIES,
681
+ config: buildStoredAgentConfig(record),
682
+ runtimeInfo: undefined,
683
+ lifecycle: "closed",
684
+ createdAt: new Date(record.createdAt),
685
+ updatedAt,
686
+ availableModes: [],
687
+ features: record.features,
688
+ currentModeId: record.lastModeId ?? null,
689
+ pendingPermissions: new Map(),
690
+ bufferedPermissionResolutions: new Map(),
691
+ inFlightPermissionResponses: new Set(),
692
+ pendingReplacement: false,
693
+ activeForegroundTurnId: null,
694
+ foregroundTurnWaiters: new Set(),
695
+ finalizedForegroundTurnIds: new Set(),
696
+ unsubscribeSession: null,
697
+ persistence: record.persistence ?? null,
698
+ historyPrimed: true,
699
+ lastUserMessageAt: record.lastUserMessageAt ? new Date(record.lastUserMessageAt) : null,
700
+ lastUsage: undefined,
701
+ lastError: record.lastError ?? undefined,
702
+ attention: { requiresAttention: false },
703
+ internal: record.internal,
704
+ labels: record.labels,
705
+ },
561
706
  });
562
- this.notifyAgentState(agentId);
563
- await this.closeAgent(agentId);
564
- return { archivedAt };
565
707
  }
566
708
  async setAgentMode(agentId, modeId) {
567
709
  const agent = this.requireSessionAgent(agentId);
@@ -678,6 +820,7 @@ export class AgentManager {
678
820
  attentionTimestamp: null,
679
821
  };
680
822
  await registry.upsert(nextRecord);
823
+ await this.archiveNativeSessionBestEffort(record.provider, record.persistence);
681
824
  return nextRecord;
682
825
  }
683
826
  async unarchiveSnapshot(agentId) {
@@ -2247,6 +2390,19 @@ export class AgentManager {
2247
2390
  }
2248
2391
  return client;
2249
2392
  }
2393
+ async archiveNativeSessionBestEffort(provider, persistence) {
2394
+ if (!persistence)
2395
+ return;
2396
+ const client = this.clients.get(provider);
2397
+ if (!client?.archiveNativeSession)
2398
+ return;
2399
+ try {
2400
+ await client.archiveNativeSession(persistence);
2401
+ }
2402
+ catch (error) {
2403
+ this.logger.warn({ error, provider, sessionId: persistence.sessionId }, "Failed to archive native session (best-effort)");
2404
+ }
2405
+ }
2250
2406
  requireAgent(id) {
2251
2407
  const normalizedId = validateAgentId(id, "requireAgent");
2252
2408
  const agent = this.agents.get(normalizedId);