@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
@@ -21,7 +21,7 @@ import { DictationStreamManager, } from "./dictation/dictation-stream-manager.js
21
21
  import { createVoiceTurnController, } from "./voice/voice-turn-controller.js";
22
22
  import { buildConfigOverrides, extractTimestamps, isStoredAgentProviderAvailable, toAgentPersistenceHandle, } from "./persistence-hooks.js";
23
23
  import { ensureAgentLoaded } from "./agent/agent-loading.js";
24
- import { sendPromptToAgent, unarchiveAgentState } from "./agent/mcp-shared.js";
24
+ import { formatSystemNotificationPrompt, sendPromptToAgent, unarchiveAgentState, } from "./agent/agent-prompt.js";
25
25
  import { experimental_createMCPClient } from "ai";
26
26
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
27
27
  import { buildWorkspaceScriptPayloads, readPaseoConfigForProjection, } from "./script-status-projection.js";
@@ -29,20 +29,23 @@ import { deriveProjectSlug } from "./workspace-git-metadata.js";
29
29
  import { spawnWorkspaceScript } from "./worktree-bootstrap.js";
30
30
  import { applyMutableProviderConfigToOverrides } from "./daemon-config-store.js";
31
31
  import { getErrorMessage, getErrorMessageOr } from "../shared/error-utils.js";
32
+ import { getAgentStatusPriority } from "../shared/agent-state-bucket.js";
32
33
  import { buildProviderRegistry } from "./agent/provider-registry.js";
33
34
  import { resolveSnapshotCwd } from "./agent/provider-snapshot-manager.js";
34
35
  import { scheduleAgentMetadataGeneration } from "./agent/agent-metadata-generator.js";
36
+ import { resolveCreateAgentTitles } from "./agent/create-agent-title.js";
35
37
  import { buildStoredAgentPayload, resolveEffectiveThinkingOptionId, resolveStoredAgentPayloadUpdatedAt, toAgentPayload, } from "./agent/agent-projections.js";
36
- import { MAX_EXPLICIT_AGENT_TITLE_CHARS } from "./agent/agent-title-limits.js";
37
38
  import { appendTimelineItemIfAgentKnown, emitLiveTimelineItemIfAgentKnown, } from "./agent/timeline-append.js";
38
39
  import { projectTimelineRows, selectTimelineWindowByProjectedLimit, } from "./agent/timeline-projection.js";
39
40
  import { DEFAULT_STRUCTURED_GENERATION_PROVIDERS, StructuredAgentFallbackError, StructuredAgentResponseError, generateStructuredAgentResponseWithFallback, } from "./agent/agent-response-loop.js";
41
+ import { ImportSessionsRequestError, importProviderSession, listImportableProviderSessions, normalizeImportAgentRequest, } from "./agent/import-sessions.js";
40
42
  import { checkoutLiteFromGitSnapshot, normalizeWorkspaceId as normalizePersistedWorkspaceId, deriveProjectGroupingName, classifyDirectoryForProjectMembership, deriveWorkspaceDisplayName, } from "./workspace-registry-model.js";
41
43
  import { createPersistedProjectRecord, createPersistedWorkspaceRecord, } from "./workspace-registry.js";
42
44
  import { buildVoiceModeSystemPrompt, stripVoiceModeSystemPrompt, wrapSpokenInput, } from "./voice-config.js";
43
45
  import { isVoicePermissionAllowed } from "./voice-permission-policy.js";
44
46
  import { listDirectoryEntries, readExplorerFile, readExplorerFileBytes, getDownloadableFileInfo, } from "./file-explorer/service.js";
45
47
  import { readPaseoConfigForEdit, writePaseoConfigForEdit, } from "../utils/paseo-config-file.js";
48
+ import { buildMetadataPrompt } from "../utils/build-metadata-prompt.js";
46
49
  import { archivePersistedWorkspaceRecord } from "./workspace-archive-service.js";
47
50
  import { WorkspaceReconciliationService } from "./workspace-reconciliation-service.js";
48
51
  import { checkoutResolvedBranch, commitChanges, mergeToBase, mergeFromBase, pullCurrentBranch, pushCurrentBranch, createPullRequest, } from "../utils/checkout-git.js";
@@ -50,10 +53,11 @@ import { getProjectIcon } from "../utils/project-icon.js";
50
53
  import { expandTilde } from "../utils/path.js";
51
54
  import { searchHomeDirectories, searchWorkspaceEntries } from "../utils/directory-suggestions.js";
52
55
  import { toCheckoutError } from "./checkout-git-utils.js";
56
+ import { buildCheckoutPrStatusPayloadFromSnapshot, buildCheckoutStatusPayloadFromSnapshot, } from "./checkout/status-projection.js";
53
57
  import { toResolver } from "./speech/provider-resolver.js";
54
58
  import { resolveClientMessageId } from "./client-message-id.js";
55
- import { ChatServiceError } from "./chat/chat-service.js";
56
- import { notifyChatMentions } from "./chat/chat-mentions.js";
59
+ import { ChatServiceError, parseMentionAgentIds, } from "./chat/chat-service.js";
60
+ import { notifyChatMentions, prepareChatMentionFanout } from "./chat/chat-mentions.js";
57
61
  import { execCommand } from "../utils/spawn.js";
58
62
  import { createGitHubService, } from "../services/github-service.js";
59
63
  import { summarizeFetchWorkspacesEntries, WorkspaceDirectory, } from "./workspace-directory.js";
@@ -61,7 +65,6 @@ import { attemptFirstAgentBranchAutoName, createPaseoWorktree, } from "./paseo-w
61
65
  import { generateBranchNameFromFirstAgentContext } from "./worktree-branch-name-generator.js";
62
66
  import { assertSafeGitRef as assertWorktreeSafeGitRef, buildAgentSessionConfig as buildWorktreeAgentSessionConfig, createPaseoWorktreeWorkflow as createWorktreeWorkflow, handleCreatePaseoWorktreeRequest as handleCreateWorktreeRequest, handlePaseoWorktreeArchiveRequest as handleWorktreeArchiveRequest, handlePaseoWorktreeListRequest as handleWorktreeListRequest, handleWorkspaceSetupStatusRequest as handleWorkspaceSetupStatusRequestMessage, } from "./worktree-session.js";
63
67
  import { toWorktreeWireError } from "./worktree-errors.js";
64
- const MAX_INITIAL_AGENT_TITLE_CHARS = Math.min(60, MAX_EXPLICIT_AGENT_TITLE_CHARS);
65
68
  const WORKSPACE_GIT_WATCH_REMOVED_STATE_KEY = "__removed__";
66
69
  async function resolveKnownProjectRootForConfig(input) {
67
70
  const requestedRoot = canonicalizeConfigRoot(input.repoRoot);
@@ -182,44 +185,6 @@ function beginAgentDeleteIfSupported(agentStorage, agentId) {
182
185
  agentStorage.beginDelete(agentId);
183
186
  }
184
187
  }
185
- function deriveInitialAgentTitle(prompt) {
186
- const firstContentLine = prompt
187
- .split(/\r?\n/)
188
- .map((line) => line.trim())
189
- .find((line) => line.length > 0);
190
- if (!firstContentLine) {
191
- return null;
192
- }
193
- const normalized = firstContentLine.replace(/\s+/g, " ").trim();
194
- if (!normalized) {
195
- return null;
196
- }
197
- const clamped = normalized.slice(0, MAX_INITIAL_AGENT_TITLE_CHARS).trim();
198
- return clamped.length > 0 ? clamped : null;
199
- }
200
- export function resolveCreateAgentTitles(options) {
201
- const explicitTitle = typeof options.configTitle === "string" && options.configTitle.trim().length > 0
202
- ? options.configTitle.trim()
203
- : null;
204
- const trimmedPrompt = options.initialPrompt?.trim();
205
- const provisionalTitle = explicitTitle ?? (trimmedPrompt ? deriveInitialAgentTitle(trimmedPrompt) : null);
206
- return {
207
- explicitTitle,
208
- provisionalTitle,
209
- };
210
- }
211
- function getFirstUserMessageText(timeline) {
212
- for (const item of timeline) {
213
- if (item.type !== "user_message") {
214
- continue;
215
- }
216
- const text = item.text.trim();
217
- if (text) {
218
- return text;
219
- }
220
- }
221
- return null;
222
- }
223
188
  const FETCH_AGENTS_SORT_KEYS = ["status_priority", "created_at", "updated_at", "title"];
224
189
  export function resolveWaitForFinishError(options) {
225
190
  if (options.status !== "error") {
@@ -253,31 +218,6 @@ class VoiceFeatureUnavailableError extends Error {
253
218
  this.missingModelIds = [...context.missingModelIds];
254
219
  }
255
220
  }
256
- function buildImportPersistenceHandle(input) {
257
- const cwd = input.cwd ?? process.cwd();
258
- return {
259
- provider: input.provider,
260
- sessionId: input.sessionId,
261
- nativeHandle: input.sessionId,
262
- metadata: {
263
- provider: input.provider,
264
- cwd,
265
- },
266
- };
267
- }
268
- function applyImportCwdOverride(handle, cwd) {
269
- if (!cwd) {
270
- return handle;
271
- }
272
- return {
273
- ...handle,
274
- metadata: {
275
- ...handle.metadata,
276
- provider: handle.provider,
277
- cwd,
278
- },
279
- };
280
- }
281
221
  function convertPCMToWavBuffer(pcmBuffer, sampleRate, channels, bitsPerSample) {
282
222
  const headerSize = 44;
283
223
  const wavBuffer = Buffer.alloc(headerSize + pcmBuffer.length);
@@ -367,7 +307,12 @@ export class Session {
367
307
  getSortValue: (agent, key) => {
368
308
  switch (key) {
369
309
  case "status_priority":
370
- return this.getStatusPriority(agent);
310
+ return getAgentStatusPriority({
311
+ status: agent.status,
312
+ pendingPermissionCount: agent.pendingPermissions?.length ?? 0,
313
+ requiresAttention: agent.requiresAttention,
314
+ attentionReason: agent.attentionReason ?? null,
315
+ });
371
316
  case "created_at":
372
317
  return Date.parse(agent.createdAt);
373
318
  case "updated_at":
@@ -1112,6 +1057,8 @@ export class Session {
1112
1057
  return this.handleFetchAgents(msg);
1113
1058
  case "fetch_agent_history_request":
1114
1059
  return this.handleFetchAgentHistory(msg);
1060
+ case "fetch_recent_provider_sessions_request":
1061
+ return this.handleFetchRecentProviderSessions(msg);
1115
1062
  case "fetch_agent_request":
1116
1063
  return this.handleFetchAgent(msg.agentId, msg.requestId);
1117
1064
  case "delete_agent_request":
@@ -1262,6 +1209,7 @@ export class Session {
1262
1209
  },
1263
1210
  });
1264
1211
  }
1212
+ // eslint-disable-next-line complexity
1265
1213
  dispatchCheckoutMessage(msg) {
1266
1214
  switch (msg.type) {
1267
1215
  case "checkout_status_request":
@@ -1297,6 +1245,8 @@ export class Session {
1297
1245
  return this.handleCheckoutPushRequest(msg);
1298
1246
  case "checkout_pr_create_request":
1299
1247
  return this.handleCheckoutPrCreateRequest(msg);
1248
+ case "checkout_pr_merge_request":
1249
+ return this.handleCheckoutPrMergeRequest(msg);
1300
1250
  case "checkout_pr_status_request":
1301
1251
  return this.handleCheckoutPrStatusRequest(msg);
1302
1252
  case "pull_request_timeline_request":
@@ -2114,6 +2064,7 @@ export class Session {
2114
2064
  agentManager: this.agentManager,
2115
2065
  agentId: snapshot.id,
2116
2066
  cwd: snapshot.cwd,
2067
+ workspaceGitService: this.workspaceGitService,
2117
2068
  initialPrompt: trimmedPrompt,
2118
2069
  explicitTitle: params.explicitTitle,
2119
2070
  paseoHome: this.paseoHome,
@@ -2175,26 +2126,30 @@ export class Session {
2175
2126
  }
2176
2127
  }
2177
2128
  async handleImportAgentRequest(msg) {
2178
- const { provider, sessionId, cwd, labels, requestId } = msg;
2179
- this.sessionLogger.info({ sessionId, provider }, `Importing agent ${sessionId} (${provider})`);
2129
+ const normalized = normalizeImportAgentRequest(msg);
2130
+ if ("error" in normalized) {
2131
+ this.emit({
2132
+ type: "status",
2133
+ payload: {
2134
+ status: "agent_create_failed",
2135
+ requestId: msg.requestId,
2136
+ error: normalized.error,
2137
+ },
2138
+ });
2139
+ return;
2140
+ }
2141
+ const { provider, providerHandleId, requestId } = normalized;
2142
+ this.sessionLogger.info({ providerHandleId, provider }, `Importing agent ${providerHandleId} (${provider})`);
2180
2143
  try {
2181
- const descriptor = await this.agentManager.findPersistedAgent(provider, sessionId);
2182
- if (!descriptor && provider === "opencode" && !cwd) {
2183
- throw new Error("OpenCode sessions require --cwd when the session cannot be found in persisted agents");
2184
- }
2185
- const handle = descriptor
2186
- ? applyImportCwdOverride(descriptor.persistence, cwd)
2187
- : buildImportPersistenceHandle({ provider, sessionId, cwd });
2188
- const overrides = cwd ? { cwd } : undefined;
2189
- await this.unarchiveAgentByHandle(handle);
2190
- const snapshot = await this.agentManager.resumeAgentFromPersistence(handle, overrides, undefined, {
2191
- labels,
2144
+ const { snapshot, timelineSize } = await importProviderSession({
2145
+ request: normalized,
2146
+ agentManager: this.agentManager,
2147
+ agentStorage: this.agentStorage,
2148
+ workspaceGitService: this.workspaceGitService,
2149
+ paseoHome: this.paseoHome,
2150
+ logger: this.sessionLogger,
2192
2151
  });
2193
- await unarchiveAgentState(this.agentStorage, this.agentManager, snapshot.id);
2194
- await this.agentManager.hydrateTimelineFromProvider(snapshot.id);
2195
- await this.applyImportedAgentTitle(snapshot);
2196
2152
  await this.forwardAgentUpdate(snapshot);
2197
- const timelineSize = this.agentManager.getTimeline(snapshot.id).length;
2198
2153
  const agentPayload = await this.buildAgentPayload(snapshot);
2199
2154
  this.emit({
2200
2155
  type: "status",
@@ -2229,28 +2184,6 @@ export class Session {
2229
2184
  });
2230
2185
  }
2231
2186
  }
2232
- async applyImportedAgentTitle(snapshot) {
2233
- const initialPrompt = getFirstUserMessageText(this.agentManager.getTimeline(snapshot.id));
2234
- if (!initialPrompt) {
2235
- return;
2236
- }
2237
- const { explicitTitle, provisionalTitle } = resolveCreateAgentTitles({
2238
- configTitle: snapshot.config.title,
2239
- initialPrompt,
2240
- });
2241
- if (!explicitTitle && provisionalTitle) {
2242
- await this.agentManager.setTitle(snapshot.id, provisionalTitle);
2243
- }
2244
- scheduleAgentMetadataGeneration({
2245
- agentManager: this.agentManager,
2246
- agentId: snapshot.id,
2247
- cwd: snapshot.cwd,
2248
- initialPrompt,
2249
- explicitTitle,
2250
- paseoHome: this.paseoHome,
2251
- logger: this.sessionLogger,
2252
- });
2253
- }
2254
2187
  async handleRefreshAgentRequest(msg) {
2255
2188
  const { agentId, requestId } = msg;
2256
2189
  this.sessionLogger.info({ agentId }, `Refreshing agent ${agentId} from persistence`);
@@ -2260,7 +2193,9 @@ export class Session {
2260
2193
  const existing = this.agentManager.getAgent(agentId);
2261
2194
  if (existing) {
2262
2195
  await this.interruptAgentIfRunning(agentId);
2263
- snapshot = await this.agentManager.reloadAgentSession(agentId);
2196
+ snapshot = await this.agentManager.reloadAgentSession(agentId, undefined, {
2197
+ rehydrateFromDisk: true,
2198
+ });
2264
2199
  }
2265
2200
  else {
2266
2201
  const record = await this.agentStorage.get(agentId);
@@ -2369,6 +2304,7 @@ export class Session {
2369
2304
  return generateBranchNameFromFirstAgentContext({
2370
2305
  agentManager: this.agentManager,
2371
2306
  cwd,
2307
+ workspaceGitService: this.workspaceGitService,
2372
2308
  firstAgentContext,
2373
2309
  logger: this.sessionLogger,
2374
2310
  });
@@ -2756,14 +2692,19 @@ export class Session {
2756
2692
  const patch = diff.diff.length > maxPatchChars
2757
2693
  ? `${diff.diff.slice(0, maxPatchChars)}\n\n... (diff truncated to ${maxPatchChars} chars)\n`
2758
2694
  : diff.diff;
2759
- const prompt = [
2760
- "Write a concise git commit message for the changes below.",
2761
- "Return JSON only with a single field 'message'.",
2762
- "",
2763
- fileList,
2764
- "",
2765
- patch.length > 0 ? patch : "(No diff available)",
2766
- ].join("\n");
2695
+ const prompt = await buildMetadataPrompt({
2696
+ cwd,
2697
+ workspaceGitService: this.workspaceGitService,
2698
+ configKey: "commitMessage",
2699
+ before: "Write a concise git commit message for the changes below.",
2700
+ after: [
2701
+ "Return JSON only with a single field 'message'.",
2702
+ "",
2703
+ fileList,
2704
+ "",
2705
+ patch.length > 0 ? patch : "(No diff available)",
2706
+ ].join("\n"),
2707
+ });
2767
2708
  try {
2768
2709
  const result = await generateStructuredAgentResponseWithFallback({
2769
2710
  manager: this.agentManager,
@@ -2813,14 +2754,19 @@ export class Session {
2813
2754
  const patch = diff.diff.length > maxPatchChars
2814
2755
  ? `${diff.diff.slice(0, maxPatchChars)}\n\n... (diff truncated to ${maxPatchChars} chars)\n`
2815
2756
  : diff.diff;
2816
- const prompt = [
2817
- "Write a pull request title and body for the changes below.",
2818
- "Return JSON only with fields 'title' and 'body'.",
2819
- "",
2820
- fileList,
2821
- "",
2822
- patch.length > 0 ? patch : "(No diff available)",
2823
- ].join("\n");
2757
+ const prompt = await buildMetadataPrompt({
2758
+ cwd,
2759
+ workspaceGitService: this.workspaceGitService,
2760
+ configKey: "pullRequest",
2761
+ before: "Write a pull request title and body for the changes below.",
2762
+ after: [
2763
+ "Return JSON only with fields 'title' and 'body'.",
2764
+ "",
2765
+ fileList,
2766
+ "",
2767
+ patch.length > 0 ? patch : "(No diff available)",
2768
+ ].join("\n"),
2769
+ });
2824
2770
  try {
2825
2771
  return await generateStructuredAgentResponseWithFallback({
2826
2772
  manager: this.agentManager,
@@ -3193,7 +3139,7 @@ export class Session {
3193
3139
  const snapshot = await this.workspaceGitService.getSnapshot(resolvedCwd);
3194
3140
  this.emit({
3195
3141
  type: "checkout_status_response",
3196
- payload: this.buildCheckoutStatusPayloadFromSnapshot({
3142
+ payload: buildCheckoutStatusPayloadFromSnapshot({
3197
3143
  cwd,
3198
3144
  requestId,
3199
3145
  snapshot,
@@ -3503,94 +3449,18 @@ export class Session {
3503
3449
  this.checkoutDiffSubscriptions.get(msg.subscriptionId)?.();
3504
3450
  this.checkoutDiffSubscriptions.delete(msg.subscriptionId);
3505
3451
  }
3506
- buildCheckoutStatusPayloadFromSnapshot({ cwd, requestId, snapshot, }) {
3507
- if (!snapshot.git.isGit) {
3508
- return {
3509
- cwd,
3510
- isGit: false,
3511
- repoRoot: null,
3512
- currentBranch: null,
3513
- isDirty: null,
3514
- baseRef: null,
3515
- aheadBehind: null,
3516
- aheadOfOrigin: null,
3517
- behindOfOrigin: null,
3518
- hasRemote: false,
3519
- remoteUrl: null,
3520
- isPaseoOwnedWorktree: false,
3521
- error: null,
3522
- requestId,
3523
- };
3524
- }
3525
- if (snapshot.git.repoRoot === null || snapshot.git.isDirty === null) {
3526
- throw new Error("Workspace git snapshot is missing required checkout status fields");
3527
- }
3528
- if (snapshot.git.isPaseoOwnedWorktree) {
3529
- if (snapshot.git.mainRepoRoot === null || snapshot.git.baseRef === null) {
3530
- throw new Error("Workspace git snapshot is missing required worktree status fields");
3531
- }
3532
- return {
3533
- cwd,
3534
- isGit: true,
3535
- repoRoot: snapshot.git.repoRoot,
3536
- mainRepoRoot: snapshot.git.mainRepoRoot,
3537
- currentBranch: snapshot.git.currentBranch ?? null,
3538
- isDirty: snapshot.git.isDirty,
3539
- baseRef: snapshot.git.baseRef,
3540
- aheadBehind: snapshot.git.aheadBehind ?? null,
3541
- aheadOfOrigin: snapshot.git.aheadOfOrigin ?? null,
3542
- behindOfOrigin: snapshot.git.behindOfOrigin ?? null,
3543
- hasRemote: snapshot.git.hasRemote,
3544
- remoteUrl: snapshot.git.remoteUrl,
3545
- isPaseoOwnedWorktree: true,
3546
- error: null,
3547
- requestId,
3548
- };
3549
- }
3550
- return {
3551
- cwd,
3552
- isGit: true,
3553
- repoRoot: snapshot.git.repoRoot,
3554
- mainRepoRoot: snapshot.git.mainRepoRoot,
3555
- currentBranch: snapshot.git.currentBranch ?? null,
3556
- isDirty: snapshot.git.isDirty,
3557
- baseRef: snapshot.git.baseRef ?? null,
3558
- aheadBehind: snapshot.git.aheadBehind ?? null,
3559
- aheadOfOrigin: snapshot.git.aheadOfOrigin ?? null,
3560
- behindOfOrigin: snapshot.git.behindOfOrigin ?? null,
3561
- hasRemote: snapshot.git.hasRemote,
3562
- remoteUrl: snapshot.git.remoteUrl,
3563
- isPaseoOwnedWorktree: false,
3564
- error: null,
3565
- requestId,
3566
- };
3567
- }
3568
- buildCheckoutPrStatusPayloadFromSnapshot({ cwd, requestId, snapshot, }) {
3569
- return {
3570
- cwd,
3571
- status: normalizeCheckoutPrStatusPayload(snapshot.github.pullRequest),
3572
- githubFeaturesEnabled: snapshot.github.featuresEnabled,
3573
- error: snapshot.github.error
3574
- ? {
3575
- code: "UNKNOWN",
3576
- message: snapshot.github.error.message,
3577
- }
3578
- : null,
3579
- requestId,
3580
- };
3581
- }
3582
3452
  emitCheckoutStatusUpdate(cwd, snapshot) {
3583
3453
  try {
3584
3454
  const requestId = `subscription:${cwd}`;
3585
3455
  this.emit({
3586
3456
  type: "checkout_status_update",
3587
3457
  payload: {
3588
- ...this.buildCheckoutStatusPayloadFromSnapshot({
3458
+ ...buildCheckoutStatusPayloadFromSnapshot({
3589
3459
  cwd,
3590
3460
  requestId,
3591
3461
  snapshot,
3592
3462
  }),
3593
- prStatus: this.buildCheckoutPrStatusPayloadFromSnapshot({
3463
+ prStatus: buildCheckoutPrStatusPayloadFromSnapshot({
3594
3464
  cwd,
3595
3465
  requestId,
3596
3466
  snapshot,
@@ -3918,26 +3788,55 @@ export class Session {
3918
3788
  });
3919
3789
  }
3920
3790
  }
3921
- async handleCheckoutPrStatusRequest(msg) {
3791
+ async handleCheckoutPrMergeRequest(msg) {
3922
3792
  const { cwd, requestId } = msg;
3923
3793
  try {
3924
3794
  const snapshot = await this.workspaceGitService.getSnapshot(cwd);
3795
+ const prNumber = snapshot.github.pullRequest?.number;
3796
+ if (typeof prNumber !== "number") {
3797
+ throw new Error("Unable to determine GitHub pull request number for merge");
3798
+ }
3799
+ await this.github.mergePullRequest({
3800
+ cwd,
3801
+ prNumber,
3802
+ mergeMethod: msg.mergeMethod,
3803
+ });
3804
+ await this.notifyGitMutation(cwd, "merge-pr", { invalidateGithub: true });
3925
3805
  this.emit({
3926
- type: "checkout_pr_status_response",
3806
+ type: "checkout_pr_merge_response",
3927
3807
  payload: {
3928
3808
  cwd,
3929
- status: normalizeCheckoutPrStatusPayload(snapshot.github.pullRequest),
3930
- githubFeaturesEnabled: snapshot.github.featuresEnabled,
3931
- error: snapshot.github.error
3932
- ? {
3933
- code: "UNKNOWN",
3934
- message: snapshot.github.error.message,
3935
- }
3936
- : null,
3809
+ success: true,
3810
+ error: null,
3937
3811
  requestId,
3938
3812
  },
3939
3813
  });
3940
3814
  }
3815
+ catch (error) {
3816
+ this.emit({
3817
+ type: "checkout_pr_merge_response",
3818
+ payload: {
3819
+ cwd,
3820
+ success: false,
3821
+ error: toCheckoutError(error),
3822
+ requestId,
3823
+ },
3824
+ });
3825
+ }
3826
+ }
3827
+ async handleCheckoutPrStatusRequest(msg) {
3828
+ const { cwd, requestId } = msg;
3829
+ try {
3830
+ const snapshot = await this.workspaceGitService.getSnapshot(cwd);
3831
+ this.emit({
3832
+ type: "checkout_pr_status_response",
3833
+ payload: buildCheckoutPrStatusPayloadFromSnapshot({
3834
+ cwd,
3835
+ requestId,
3836
+ snapshot,
3837
+ }),
3838
+ });
3839
+ }
3941
3840
  catch (error) {
3942
3841
  this.emit({
3943
3842
  type: "checkout_pr_status_response",
@@ -4333,23 +4232,6 @@ export class Session {
4333
4232
  const payload = this.buildStoredAgentPayload(record);
4334
4233
  return this.isProviderVisibleToClient(payload.provider) ? payload : null;
4335
4234
  }
4336
- getStatusPriority(agent) {
4337
- const attentionReason = agent.attentionReason ?? null;
4338
- const hasPendingPermission = (agent.pendingPermissions?.length ?? 0) > 0;
4339
- if (hasPendingPermission || attentionReason === "permission") {
4340
- return 0;
4341
- }
4342
- if (agent.status === "error" || attentionReason === "error") {
4343
- return 1;
4344
- }
4345
- if (agent.status === "running") {
4346
- return 2;
4347
- }
4348
- if (agent.status === "initializing") {
4349
- return 3;
4350
- }
4351
- return 4;
4352
- }
4353
4235
  async buildActiveProjectPlacementsByWorkspaceCwd() {
4354
4236
  const [persistedWorkspaces, persistedProjects] = await Promise.all([
4355
4237
  this.workspaceRegistry.list(),
@@ -5002,6 +4884,42 @@ export class Session {
5002
4884
  });
5003
4885
  }
5004
4886
  }
4887
+ async handleFetchRecentProviderSessions(request) {
4888
+ try {
4889
+ const result = await listImportableProviderSessions({
4890
+ request,
4891
+ agentManager: this.agentManager,
4892
+ agentStorage: this.agentStorage,
4893
+ providerRegistry: this.getProviderRegistry(),
4894
+ });
4895
+ this.emit({
4896
+ type: "fetch_recent_provider_sessions_response",
4897
+ payload: {
4898
+ requestId: request.requestId,
4899
+ entries: result.entries,
4900
+ ...(result.filteredAlreadyImportedCount > 0
4901
+ ? { filteredAlreadyImportedCount: result.filteredAlreadyImportedCount }
4902
+ : {}),
4903
+ },
4904
+ });
4905
+ }
4906
+ catch (error) {
4907
+ const code = error instanceof ImportSessionsRequestError
4908
+ ? error.code
4909
+ : "fetch_recent_provider_sessions_failed";
4910
+ const message = error instanceof Error ? error.message : "Failed to fetch recent provider sessions";
4911
+ this.sessionLogger.error({ err: error }, "Failed to handle fetch_recent_provider_sessions_request");
4912
+ this.emit({
4913
+ type: "rpc_error",
4914
+ payload: {
4915
+ requestId: request.requestId,
4916
+ requestType: request.type,
4917
+ error: message,
4918
+ code,
4919
+ },
4920
+ });
4921
+ }
4922
+ }
5005
4923
  async handleFetchWorkspacesRequest(request) {
5006
4924
  const requestedSubscriptionId = request.subscribe?.subscriptionId?.trim();
5007
4925
  const subscriptionId = resolveSubscriptionId(request.subscribe, requestedSubscriptionId);
@@ -6351,6 +6269,19 @@ export class Session {
6351
6269
  async handleChatPostRequest(request) {
6352
6270
  try {
6353
6271
  const authorAgentId = request.authorAgentId?.trim() || this.clientId;
6272
+ const mentionAgentIds = parseMentionAgentIds(request.body);
6273
+ const storedAgents = await this.agentStorage.list();
6274
+ const liveAgents = this.agentManager.listAgents();
6275
+ const fanout = await prepareChatMentionFanout({
6276
+ authorAgentId,
6277
+ mentionAgentIds,
6278
+ storedAgents,
6279
+ liveAgents,
6280
+ listRoomPosterAgentIds: () => this.chatService.listRoomPosterAgentIds({ room: request.room }),
6281
+ });
6282
+ if (!fanout.ok) {
6283
+ throw new ChatServiceError("chat_mention_fanout_limit_exceeded", fanout.error);
6284
+ }
6354
6285
  const message = await this.chatService.dispatchMessage({
6355
6286
  room: request.room,
6356
6287
  authorAgentId,
@@ -6371,11 +6302,20 @@ export class Session {
6371
6302
  body: request.body,
6372
6303
  mentionAgentIds: message.mentionAgentIds,
6373
6304
  logger: this.sessionLogger,
6374
- listStoredAgents: () => this.agentStorage.list(),
6375
- listLiveAgents: () => this.agentManager.listAgents(),
6305
+ storedAgents,
6306
+ liveAgents,
6307
+ prepared: fanout.prepared,
6376
6308
  resolveAgentIdentifier: (identifier) => this.resolveAgentIdentifier(identifier),
6377
6309
  sendAgentMessage: async (agentId, text) => {
6378
- await this.handleSendAgentMessage(agentId, text);
6310
+ await sendPromptToAgent({
6311
+ agentManager: this.agentManager,
6312
+ agentStorage: this.agentStorage,
6313
+ agentId,
6314
+ prompt: formatSystemNotificationPrompt(text),
6315
+ unarchive: false,
6316
+ recordUserMessage: false,
6317
+ logger: this.sessionLogger,
6318
+ });
6379
6319
  },
6380
6320
  });
6381
6321
  }
@@ -6723,26 +6663,6 @@ export class Session {
6723
6663
  // Stash handlers
6724
6664
  // ---------------------------------------------------------------------------
6725
6665
  Session.PASEO_STASH_PREFIX = "paseo-auto-stash:";
6726
- export function normalizeCheckoutPrStatusPayload(status) {
6727
- if (!status) {
6728
- return null;
6729
- }
6730
- return {
6731
- number: status.number,
6732
- url: status.url,
6733
- title: status.title,
6734
- state: status.state,
6735
- repoOwner: status.repoOwner,
6736
- repoName: status.repoName,
6737
- baseRefName: status.baseRefName,
6738
- headRefName: status.headRefName,
6739
- isMerged: status.isMerged,
6740
- isDraft: status.isDraft ?? false,
6741
- checks: status.checks ?? [],
6742
- checksStatus: status.checksStatus,
6743
- reviewDecision: status.reviewDecision,
6744
- };
6745
- }
6746
6666
  function isValidPullRequestTimelineIdentity(options) {
6747
6667
  if (!Number.isInteger(options.prNumber) || options.prNumber <= 0) {
6748
6668
  return false;