@axhub/acp 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +4 -0
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/next-minimal-server.js.nft.json +1 -1
  6. package/.next/next-server.js.nft.json +1 -1
  7. package/.next/routes-manifest.json +28 -0
  8. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  9. package/.next/server/app/_global-error.html +1 -1
  10. package/.next/server/app/_global-error.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  16. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/server/app/_not-found.html +1 -1
  19. package/.next/server/app/_not-found.rsc +2 -2
  20. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  21. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  23. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  24. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  25. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  26. package/.next/server/app/api/acp/capabilities/route.js +5 -3
  27. package/.next/server/app/api/acp/capabilities/route.js.nft.json +1 -1
  28. package/.next/server/app/api/acp/commands/route.js +1 -1
  29. package/.next/server/app/api/acp/commands/route.js.nft.json +1 -1
  30. package/.next/server/app/api/acp/runtime/route.js.nft.json +1 -1
  31. package/.next/server/app/api/chat/cancel/route/app-paths-manifest.json +3 -0
  32. package/.next/server/app/api/chat/cancel/route/build-manifest.json +9 -0
  33. package/.next/server/app/api/chat/cancel/route/server-reference-manifest.json +4 -0
  34. package/.next/server/app/api/chat/cancel/route.js +11 -0
  35. package/.next/server/app/api/chat/cancel/route.js.nft.json +1 -0
  36. package/.next/server/app/api/chat/cancel/route_client-reference-manifest.js +3 -0
  37. package/.next/server/app/api/chat/resume/[streamId]/route/app-paths-manifest.json +3 -0
  38. package/.next/server/app/api/chat/resume/[streamId]/route/build-manifest.json +9 -0
  39. package/.next/server/app/api/chat/resume/[streamId]/route/server-reference-manifest.json +4 -0
  40. package/.next/server/app/api/chat/resume/[streamId]/route.js +11 -0
  41. package/.next/server/app/api/chat/resume/[streamId]/route.js.nft.json +1 -0
  42. package/.next/server/app/api/chat/resume/[streamId]/route_client-reference-manifest.js +3 -0
  43. package/.next/server/app/api/chat/route.js +5 -3
  44. package/.next/server/app/api/chat/route.js.nft.json +1 -1
  45. package/.next/server/app/api/conversations/[threadId]/messages/route.js +4 -2
  46. package/.next/server/app/api/conversations/[threadId]/messages/route.js.nft.json +1 -1
  47. package/.next/server/app/api/conversations/[threadId]/route.js +2 -2
  48. package/.next/server/app/api/conversations/[threadId]/route.js.nft.json +1 -1
  49. package/.next/server/app/api/conversations/[threadId]/runtime/route/app-paths-manifest.json +3 -0
  50. package/.next/server/app/api/conversations/[threadId]/runtime/route/build-manifest.json +9 -0
  51. package/.next/server/app/api/conversations/[threadId]/runtime/route/server-reference-manifest.json +4 -0
  52. package/.next/server/app/api/conversations/[threadId]/runtime/route.js +11 -0
  53. package/.next/server/app/api/conversations/[threadId]/runtime/route.js.nft.json +1 -0
  54. package/.next/server/app/api/conversations/[threadId]/runtime/route_client-reference-manifest.js +3 -0
  55. package/.next/server/app/api/conversations/route.js +2 -2
  56. package/.next/server/app/api/conversations/route.js.nft.json +1 -1
  57. package/.next/server/app/api/local-files/image/route.js.nft.json +1 -1
  58. package/.next/server/app/api/local-files/open/route.js.nft.json +1 -1
  59. package/.next/server/app/api/output-artifacts/thread/route/app-paths-manifest.json +3 -0
  60. package/.next/server/app/api/output-artifacts/thread/route/build-manifest.json +9 -0
  61. package/.next/server/app/api/output-artifacts/thread/route/server-reference-manifest.json +4 -0
  62. package/.next/server/app/api/output-artifacts/thread/route.js +8 -0
  63. package/.next/server/app/api/output-artifacts/thread/route.js.nft.json +1 -0
  64. package/.next/server/app/api/output-artifacts/thread/route_client-reference-manifest.js +3 -0
  65. package/.next/server/app/api/output-artifacts/workspace/route.js +1 -1
  66. package/.next/server/app/api/output-artifacts/workspace/route.js.nft.json +1 -1
  67. package/.next/server/app/api/tools/image-generation/files/[id]/route.js.nft.json +1 -1
  68. package/.next/server/app/api/tools/image-generation/records/route.js.nft.json +1 -1
  69. package/.next/server/app/api/tools/user-choice/route.js.nft.json +1 -1
  70. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  71. package/.next/server/app/page.js +2 -2
  72. package/.next/server/app/page.js.nft.json +1 -1
  73. package/.next/server/app/page_client-reference-manifest.js +1 -1
  74. package/.next/server/app/session/[provider]/[sessionId]/page.js +1 -1
  75. package/.next/server/app/session/[provider]/[sessionId]/page.js.nft.json +1 -1
  76. package/.next/server/app/session/[provider]/[sessionId]/page_client-reference-manifest.js +1 -1
  77. package/.next/server/app/thread/[threadId]/page.js +1 -1
  78. package/.next/server/app/thread/[threadId]/page.js.nft.json +1 -1
  79. package/.next/server/app/thread/[threadId]/page_client-reference-manifest.js +1 -1
  80. package/.next/server/app-paths-manifest.json +4 -0
  81. package/.next/server/chunks/0zjb_server_app_api_conversations_[threadId]_runtime_route_actions_08lhdqs.js +3 -0
  82. package/.next/server/chunks/[root-of-the-server]__04pn6ap._.js +3 -0
  83. package/.next/server/chunks/[root-of-the-server]__0aovkxs._.js +3 -0
  84. package/.next/server/chunks/[root-of-the-server]__0c.r6ru._.js +76 -0
  85. package/.next/server/chunks/[root-of-the-server]__0gmxr~m._.js +3 -0
  86. package/.next/server/chunks/[root-of-the-server]__0iokgmz._.js +1 -1
  87. package/.next/server/chunks/[root-of-the-server]__0j-lxr4._.js +1 -1
  88. package/.next/server/chunks/[root-of-the-server]__0lbwo2g._.js +3 -0
  89. package/.next/server/chunks/[root-of-the-server]__0ly6hop._.js +1 -1
  90. package/.next/server/chunks/[root-of-the-server]__0ml.1wa._.js +3 -0
  91. package/.next/server/chunks/[root-of-the-server]__0o2epta._.js +3 -0
  92. package/.next/server/chunks/[root-of-the-server]__0os92l7._.js +3 -0
  93. package/.next/server/chunks/[root-of-the-server]__0tmhg7j._.js +1 -1
  94. package/.next/server/chunks/[root-of-the-server]__0txmfnw._.js +2 -2
  95. package/.next/server/chunks/[root-of-the-server]__0wo0b8z._.js +1 -1
  96. package/.next/server/chunks/[root-of-the-server]__0xh8d4~._.js +3 -0
  97. package/.next/server/chunks/[root-of-the-server]__0zmyki-._.js +3 -0
  98. package/.next/server/chunks/[root-of-the-server]__0zn3~pq._.js +3 -0
  99. package/.next/server/chunks/[root-of-the-server]__13xepwb._.js +3 -0
  100. package/.next/server/chunks/_0_9_730._.js +107 -0
  101. package/.next/server/chunks/_0gx~6n6._.js +107 -0
  102. package/.next/server/chunks/_next-internal_server_app_api_chat_cancel_route_actions_0hdg4o_.js +3 -0
  103. package/.next/server/chunks/_next-internal_server_app_api_chat_resume_[streamId]_route_actions_12ynw6q.js +3 -0
  104. package/.next/server/chunks/_next-internal_server_app_api_output-artifacts_thread_route_actions_04~2mo7.js +3 -0
  105. package/.next/server/chunks/lib_conversations_store_ts_0gzcj38._.js +4 -4
  106. package/.next/server/chunks/node_modules_0nyqhq8._.js +3 -0
  107. package/.next/server/chunks/ssr/{[root-of-the-server]__0piffp7._.js → [root-of-the-server]__09wwymw._.js} +2 -2
  108. package/.next/server/chunks/ssr/{[root-of-the-server]__0488vn3._.js → [root-of-the-server]__0n6oe29._.js} +1 -1
  109. package/.next/server/chunks/ssr/{[root-of-the-server]__0icm-_h._.js → [root-of-the-server]__0niwg81._.js} +2 -2
  110. package/.next/server/chunks/ssr/_03.pm1z._.js +18 -16
  111. package/.next/server/chunks/ssr/_0txwi90._.js +1 -1
  112. package/.next/server/chunks/ssr/lib_conversations_store_ts_0-pd6d3._.js +2 -2
  113. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0ghu-f7.js +1 -1
  114. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_02suzhc.js +2 -2
  115. package/.next/server/functions-config-manifest.json +3 -0
  116. package/.next/server/instrumentation.js.nft.json +1 -1
  117. package/.next/server/middleware-build-manifest.js +3 -3
  118. package/.next/server/pages/404.html +1 -1
  119. package/.next/server/pages/500.html +1 -1
  120. package/.next/static/chunks/0btc2281yau9i.js +104 -0
  121. package/.next/static/chunks/0c~b2_-vk17t5.css +1 -0
  122. package/README.md +2 -2
  123. package/dist/components/assistant-ui/acp-command-menu.mjs +42 -9
  124. package/dist/components/assistant-ui/acp-elicitation-option-list.mjs +1 -1
  125. package/dist/components/assistant-ui/file.mjs +2 -2
  126. package/dist/components/assistant-ui/image-generation-settings-dialog.mjs +25 -6
  127. package/dist/components/assistant-ui/image.mjs +2 -2
  128. package/dist/components/assistant-ui/markdown-text.mjs +3 -3
  129. package/dist/components/assistant-ui/thread/composer.d.ts +1 -1
  130. package/dist/components/assistant-ui/thread/composer.mjs +37 -3
  131. package/dist/components/assistant-ui/thread/context-chips.mjs +3 -2
  132. package/dist/components/assistant-ui/thread/index.mjs +1 -1
  133. package/dist/components/assistant-ui/thread/message-list.mjs +1 -1
  134. package/dist/components/assistant-ui/thread/messages.mjs +2 -2
  135. package/dist/components/assistant-ui/thread-list.d.ts +8 -2
  136. package/dist/components/assistant-ui/thread-list.mjs +80 -7
  137. package/dist/components/assistant-ui/threadlist-sidebar.d.ts +4 -1
  138. package/dist/components/assistant-ui/threadlist-sidebar.mjs +2 -2
  139. package/dist/components/assistant-ui/tool-fallback.d.ts +1 -1
  140. package/dist/components/assistant-ui/tool-fallback.mjs +48 -11
  141. package/dist/components/tool-ui/option-list.d.ts +2 -1
  142. package/dist/components/tool-ui/option-list.mjs +4 -4
  143. package/dist/lib/acp2aisdk/client-context.d.ts +6 -0
  144. package/dist/lib/acp2aisdk/client-context.mjs +43 -7
  145. package/dist/lib/acp2aisdk/commands.mjs +5 -20
  146. package/dist/lib/acp2aisdk/context.d.ts +4 -0
  147. package/dist/lib/acp2aisdk/errors.d.ts +2 -0
  148. package/dist/lib/acp2aisdk/errors.mjs +37 -0
  149. package/dist/lib/acp2aisdk/index.d.ts +7 -0
  150. package/dist/lib/acp2aisdk/index.mjs +110 -34
  151. package/dist/lib/acp2aisdk/provider-compat.mjs +4 -2
  152. package/dist/lib/acp2aisdk/resumable-ui-stream.d.ts +11 -0
  153. package/dist/lib/acp2aisdk/resumable-ui-stream.mjs +323 -0
  154. package/dist/lib/acp2aisdk/runtime-message-filter.d.ts +6 -0
  155. package/dist/lib/acp2aisdk/runtime-message-filter.mjs +22 -0
  156. package/dist/lib/acp2aisdk/runtime-persistence.d.ts +21 -0
  157. package/dist/lib/acp2aisdk/runtime-persistence.mjs +135 -0
  158. package/dist/lib/acp2aisdk/session-store.mjs +7 -1
  159. package/dist/lib/acp2aisdk/skill-command-cache.mjs +1 -1
  160. package/dist/lib/api/client.d.ts +51 -4
  161. package/dist/lib/api/client.mjs +35 -4
  162. package/dist/lib/api/cors.mjs +7 -1
  163. package/dist/lib/api/http-response.d.ts +2 -0
  164. package/dist/lib/api/http-response.mjs +22 -0
  165. package/dist/lib/conversations/client-adapter.d.ts +1 -0
  166. package/dist/lib/conversations/client-adapter.mjs +158 -51
  167. package/dist/lib/conversations/provider-message-loader.d.ts +7 -0
  168. package/dist/lib/conversations/provider-message-loader.mjs +99 -0
  169. package/dist/lib/conversations/runtime-message-recovery.d.ts +9 -0
  170. package/dist/lib/conversations/runtime-message-recovery.mjs +95 -0
  171. package/dist/lib/conversations/store.d.ts +2 -2
  172. package/dist/lib/conversations/store.mjs +49 -149
  173. package/dist/lib/conversations/title-text.d.ts +3 -0
  174. package/dist/lib/conversations/title-text.mjs +81 -0
  175. package/dist/lib/conversations/types.d.ts +12 -1
  176. package/dist/lib/local-image-files.mjs +9 -1
  177. package/dist/lib/local-image-paths.mjs +31 -6
  178. package/dist/lib/output-artifacts/thread.d.ts +22 -0
  179. package/dist/lib/output-artifacts/thread.mjs +47 -0
  180. package/dist/lib/output-artifacts/workspace.mjs +6 -2
  181. package/dist/lib/provider-history/codex.mjs +5 -30
  182. package/dist/public-api/server.d.ts +1 -1
  183. package/dist/public-api/server.mjs +1 -1
  184. package/dist/tools/image-generation/client.mjs +6 -4
  185. package/dist/tools/image-generation/server.mjs +3 -1
  186. package/dist/tools/image-generation/shared.d.ts +1 -0
  187. package/dist/tools/image-generation/shared.mjs +4 -0
  188. package/dist/tools/image-generation/ui-detail.mjs +66 -2
  189. package/dist/tools/user-choice/ui.mjs +66 -30
  190. package/package.json +2 -1
  191. package/.next/server/chunks/[root-of-the-server]__04xq..~._.js +0 -3
  192. package/.next/server/chunks/[root-of-the-server]__07sxz4_._.js +0 -3
  193. package/.next/server/chunks/[root-of-the-server]__0dwg3fr._.js +0 -178
  194. package/.next/server/chunks/[root-of-the-server]__0eanzwb._.js +0 -3
  195. package/.next/server/chunks/[root-of-the-server]__0gqx~5k._.js +0 -3
  196. package/.next/server/chunks/[root-of-the-server]__0~mtsby._.js +0 -3
  197. package/.next/server/chunks/[root-of-the-server]__10-n4io._.js +0 -3
  198. package/.next/server/chunks/[root-of-the-server]__10g507v._.js +0 -3
  199. package/.next/static/chunks/0zftsky7gte_9.js +0 -102
  200. package/.next/static/chunks/1610ha42i.fl~.css +0 -1
  201. /package/.next/static/{mbk_N5Gs4ZJg3lciRL6ya → Kri5x_Y9TwyCw9FEY15ME}/_buildManifest.js +0 -0
  202. /package/.next/static/{mbk_N5Gs4ZJg3lciRL6ya → Kri5x_Y9TwyCw9FEY15ME}/_clientMiddlewareManifest.js +0 -0
  203. /package/.next/static/{mbk_N5Gs4ZJg3lciRL6ya → Kri5x_Y9TwyCw9FEY15ME}/_ssgManifest.js +0 -0
@@ -1,10 +1,13 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import fs from "node:fs/promises";
2
3
  import path from "node:path";
3
4
  import { normalizeAcpProvider } from "../acp2aisdk/provider-registry.mjs";
4
5
  import { DEFAULT_PERMISSION_MODE, normalizeWorkspacePath, } from "../acp2aisdk/session-store.mjs";
5
- import { convertTranscriptToMessageRepository, findProviderSession, loadProviderTranscript, scanProviderSessions, } from "../provider-history/index.mjs";
6
+ import { findProviderSession, scanProviderSessions, } from "../provider-history/index.mjs";
6
7
  import { mergePersistedBuiltinToolSettings, normalizePersistedBuiltinToolSettings, } from "../../tools/registry.mjs";
7
8
  import { deleteRuntimeMessages, getRuntimeMessageRepository, isRuntimeMessageConversationExpired, pruneExpiredRuntimeMessages, upsertRuntimeMessage, } from "./message-repository.mjs";
9
+ import { loadProviderMessageRepository } from "./provider-message-loader.mjs";
10
+ import { getUserFacingMessageText } from "./title-text.mjs";
8
11
  const STORE_VERSION = 1;
9
12
  const DEFAULT_CONVERSATION_LIST_LIMIT = 50;
10
13
  const MAX_CONVERSATION_LIST_LIMIT = 200;
@@ -141,7 +144,7 @@ async function readStore(workspacePath) {
141
144
  }
142
145
  async function writeStore(data, workspacePath) {
143
146
  const storePath = getStorePath(workspacePath);
144
- const tempStorePath = `${storePath}.${process.pid}.${Date.now()}.tmp`;
147
+ const tempStorePath = `${storePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;
145
148
  await fs.mkdir(/* turbopackIgnore: true */ path.dirname(storePath), {
146
149
  recursive: true,
147
150
  });
@@ -169,7 +172,9 @@ function isRecord(value) {
169
172
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
170
173
  }
171
174
  function normalizeConversationTitle(value, maxLength) {
172
- let title = typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
175
+ let title = typeof value === "string"
176
+ ? getUserFacingMessageText(value).replace(/\s+/g, " ").trim()
177
+ : "";
173
178
  if (maxLength)
174
179
  title = title.slice(0, maxLength).trim();
175
180
  return title && title !== PLACEHOLDER_TITLE ? title : undefined;
@@ -203,7 +208,7 @@ function titleFromStoredMessage(message) {
203
208
  if (!isRecord(content) || content.role !== "user")
204
209
  return undefined;
205
210
  const body = Array.isArray(content.parts) ? content.parts : content.content;
206
- return normalizeConversationTitle(extractStoredText(body), GENERATED_TITLE_MAX_LENGTH);
211
+ return normalizeConversationTitle(getUserFacingMessageText(extractStoredText(body)), GENERATED_TITLE_MAX_LENGTH);
207
212
  }
208
213
  function titleFromRuntimeMessages(data, threadId) {
209
214
  var _a, _b, _c;
@@ -215,33 +220,6 @@ function titleFromRuntimeMessages(data, threadId) {
215
220
  }
216
221
  return undefined;
217
222
  }
218
- function backfillMissingConversationTitles(data) {
219
- var _a;
220
- for (const conversation of data.conversations) {
221
- const title = normalizeConversationTitle(conversation.title);
222
- if (title) {
223
- conversation.title = title;
224
- continue;
225
- }
226
- conversation.title =
227
- (_a = titleFromRuntimeMessages(data, conversation.threadId)) !== null && _a !== void 0 ? _a : null;
228
- }
229
- }
230
- function shouldScanProviderSessionsForTitleBackfill(data, workspacePath) {
231
- const activeSessionThreadIds = new Set(data.sessions
232
- .filter((session) => session.provider === "codex" &&
233
- session.workspacePath === workspacePath &&
234
- !!session.acpSessionId &&
235
- !session.closedAt)
236
- .map((session) => session.threadId));
237
- return data.conversations.some((thread) => isActiveConversation(thread) &&
238
- thread.provider === "codex" &&
239
- thread.workspacePath === workspacePath &&
240
- !normalizeConversationTitle(thread.title) &&
241
- !!(thread.providerSessionId ||
242
- thread.sourcePath ||
243
- activeSessionThreadIds.has(thread.threadId)));
244
- }
245
223
  function normalizeBuiltinToolSettings(value) {
246
224
  return normalizePersistedBuiltinToolSettings(value);
247
225
  }
@@ -291,32 +269,17 @@ function updateConversationRecord(record, request) {
291
269
  ? request.lastActiveAt
292
270
  : record.lastActiveAt, updatedAt: nowIso(), status: record.status === "deleted" ? "active" : record.status, deletedAt: record.status === "deleted" ? null : record.deletedAt });
293
271
  }
294
- function filterMessagesByFormat(repo, format) {
295
- return format
296
- ? repo.messages.filter((message) => message.format === format)
297
- : repo.messages;
298
- }
299
- function errorMessage(error) {
300
- return error instanceof Error ? error.message : String(error);
301
- }
302
272
  export async function listConversations(workspacePath, options = {}) {
303
273
  const normalizedWorkspacePath = normalizeWorkspacePath(workspacePath);
304
274
  const shouldRefreshProvider = options.refreshProvider === true;
305
- const snapshot = shouldRefreshProvider
306
- ? null
307
- : await readStore(normalizedWorkspacePath);
308
- const shouldScanProvider = shouldRefreshProvider ||
309
- (snapshot
310
- ? shouldScanProviderSessionsForTitleBackfill(snapshot, normalizedWorkspacePath)
311
- : false);
312
- const providerSessions = shouldScanProvider
313
- ? await scanProviderSessionsCached(normalizedWorkspacePath, options.refreshProvider)
314
- : [];
275
+ if (!shouldRefreshProvider) {
276
+ const data = await readStore(normalizedWorkspacePath);
277
+ return paginateConversations(data.conversations, options);
278
+ }
279
+ const providerSessions = await scanProviderSessionsCached(normalizedWorkspacePath, options.refreshProvider);
315
280
  return updateStore(normalizedWorkspacePath, (data) => {
316
- var _a, _b, _c, _d, _e, _f;
281
+ var _a, _b, _c, _d, _e;
317
282
  const now = nowIso();
318
- const importProviderSessions = shouldRefreshProvider;
319
- backfillMissingConversationTitles(data);
320
283
  for (const session of providerSessions) {
321
284
  const existingSession = data.sessions.find((record) => {
322
285
  var _a;
@@ -334,8 +297,6 @@ export async function listConversations(workspacePath, options = {}) {
334
297
  thread.providerSessionId === session.sessionId));
335
298
  }
336
299
  const existing = existingIndex >= 0 ? data.conversations[existingIndex] : null;
337
- if (!existing && !importProviderSessions)
338
- continue;
339
300
  const existingTitle = normalizeConversationTitle(existing === null || existing === void 0 ? void 0 : existing.title);
340
301
  const providerTitle = normalizeConversationTitle(session.title);
341
302
  const record = Object.assign(Object.assign({}, (existing !== null && existing !== void 0 ? existing : {
@@ -349,9 +310,7 @@ export async function listConversations(workspacePath, options = {}) {
349
310
  thoughtLevel: null,
350
311
  permissionMode: DEFAULT_PERMISSION_MODE,
351
312
  status: "active",
352
- })), { updatedAt: (_c = (_b = session.lastActiveAt) !== null && _b !== void 0 ? _b : session.createdAt) !== null && _c !== void 0 ? _c : now, workspacePath: normalizeWorkspacePath((_d = session.workspacePath) !== null && _d !== void 0 ? _d : normalizedWorkspacePath), provider: session.provider, title: (_f = (_e = existingTitle !== null && existingTitle !== void 0 ? existingTitle : providerTitle) !== null && _e !== void 0 ? _e : (existing
353
- ? titleFromRuntimeMessages(data, existing.threadId)
354
- : null)) !== null && _f !== void 0 ? _f : null, providerSessionId: session.sessionId, sourcePath: session.sourcePath, sourceKind: session.sourceKind, lastSeenMtime: session.lastSeenMtime, lastActiveAt: session.lastActiveAt });
313
+ })), { updatedAt: (_c = (_b = session.lastActiveAt) !== null && _b !== void 0 ? _b : session.createdAt) !== null && _c !== void 0 ? _c : now, workspacePath: normalizeWorkspacePath((_d = session.workspacePath) !== null && _d !== void 0 ? _d : normalizedWorkspacePath), provider: session.provider, title: (_e = existingTitle !== null && existingTitle !== void 0 ? existingTitle : providerTitle) !== null && _e !== void 0 ? _e : null, providerSessionId: session.sessionId, sourcePath: session.sourcePath, sourceKind: session.sourceKind, lastSeenMtime: session.lastSeenMtime, lastActiveAt: session.lastActiveAt });
355
314
  if (existingIndex >= 0) {
356
315
  data.conversations[existingIndex] = record;
357
316
  }
@@ -463,101 +422,27 @@ async function deleteExpiredRuntimeMessagesForThread(workspacePath, threadId) {
463
422
  }
464
423
  });
465
424
  }
466
- async function loadProviderMessageRepository({ threadId, format, workspacePath, conversation, }) {
467
- var _a, _b;
468
- let providerSession = null;
469
- let providerSessionError = null;
470
- const providerSessionId = (_a = conversation === null || conversation === void 0 ? void 0 : conversation.providerSessionId) !== null && _a !== void 0 ? _a : (threadId.includes(":") ? threadId.slice(threadId.indexOf(":") + 1) : null);
471
- const provider = (_b = conversation === null || conversation === void 0 ? void 0 : conversation.provider) !== null && _b !== void 0 ? _b : threadId.split(":")[0];
472
- if (!(conversation === null || conversation === void 0 ? void 0 : conversation.sourcePath) && providerSessionId) {
473
- try {
474
- providerSession = await findProviderSession(provider, providerSessionId, workspacePath);
475
- }
476
- catch (error) {
477
- providerSessionError = errorMessage(error);
478
- }
479
- }
480
- if (conversation === null || conversation === void 0 ? void 0 : conversation.sourcePath) {
481
- try {
482
- const transcript = await loadProviderTranscript({
483
- provider: conversation.provider,
484
- sessionId: conversation.providerSessionId,
485
- sourcePath: conversation.sourcePath,
486
- });
487
- const repo = convertTranscriptToMessageRepository(transcript, format !== null && format !== void 0 ? format : "ai-sdk/v6");
488
- const messages = filterMessagesByFormat(repo, format);
489
- if (messages.length === 0) {
490
- return {
491
- messages: [],
492
- diagnostic: {
493
- source: "provider-history",
494
- error: "Provider transcript had no messages",
495
- },
496
- };
497
- }
498
- return {
499
- headId: repo.headId,
500
- messages,
501
- diagnostic: { source: "provider-history" },
502
- };
503
- }
504
- catch (error) {
505
- return {
506
- messages: [],
507
- diagnostic: {
508
- source: "provider-history",
509
- error: errorMessage(error),
510
- },
511
- };
512
- }
513
- }
514
- if (providerSession === null || providerSession === void 0 ? void 0 : providerSession.sourcePath) {
515
- try {
516
- const transcript = await loadProviderTranscript({
517
- provider: providerSession.provider,
518
- sessionId: providerSession.sessionId,
519
- sourcePath: providerSession.sourcePath,
520
- });
521
- const repo = convertTranscriptToMessageRepository(transcript, format !== null && format !== void 0 ? format : "ai-sdk/v6");
522
- const messages = filterMessagesByFormat(repo, format);
523
- if (messages.length === 0) {
524
- return {
525
- messages: [],
526
- diagnostic: {
527
- source: "provider-history",
528
- error: "Provider transcript had no messages",
529
- },
530
- };
531
- }
532
- return {
533
- headId: repo.headId,
534
- messages,
535
- diagnostic: { source: "provider-history" },
536
- };
537
- }
538
- catch (error) {
539
- return {
540
- messages: [],
541
- diagnostic: {
542
- source: "provider-history",
543
- error: errorMessage(error),
544
- },
545
- };
546
- }
547
- }
548
- return {
549
- messages: [],
550
- diagnostic: {
551
- source: "provider-history",
552
- error: providerSessionError !== null && providerSessionError !== void 0 ? providerSessionError : "Provider transcript not found",
553
- },
554
- };
425
+ async function syncMissingConversationTitleFromMessages({ workspacePath, threadId, messages, }) {
426
+ const title = messages
427
+ .map((message) => titleFromStoredMessage(message))
428
+ .find((candidate) => Boolean(candidate));
429
+ if (!title)
430
+ return;
431
+ await updateStore(workspacePath, (data) => {
432
+ const record = findActiveConversation(data, threadId);
433
+ if (!record || normalizeConversationTitle(record.title))
434
+ return;
435
+ record.title = title;
436
+ });
555
437
  }
556
- export async function loadConversationMessages(threadId, format, workspacePath) {
438
+ export async function loadConversationMessages(threadId, format, workspacePath, source = "auto") {
557
439
  var _a;
558
440
  const data = await readStore(workspacePath);
559
441
  const conversation = data.conversations.find((thread) => thread.threadId === threadId && thread.status !== "deleted");
560
- if (conversation) {
442
+ if (source === "runtime") {
443
+ return getRuntimeMessageRepository(data, threadId, format);
444
+ }
445
+ if (conversation && source !== "provider") {
561
446
  if (isRuntimeMessageConversationExpired(conversation)) {
562
447
  if ((_a = data.messages) === null || _a === void 0 ? void 0 : _a[threadId]) {
563
448
  await deleteExpiredRuntimeMessagesForThread(workspacePath, threadId);
@@ -566,8 +451,16 @@ export async function loadConversationMessages(threadId, format, workspacePath)
566
451
  }
567
452
  else {
568
453
  const runtimeRepo = readRuntimeMessagesIfAvailable(data, threadId, format);
569
- if (runtimeRepo)
454
+ if (runtimeRepo) {
455
+ if (!normalizeConversationTitle(conversation.title)) {
456
+ await syncMissingConversationTitleFromMessages({
457
+ workspacePath,
458
+ threadId,
459
+ messages: runtimeRepo.messages,
460
+ });
461
+ }
570
462
  return runtimeRepo;
463
+ }
571
464
  }
572
465
  }
573
466
  const providerRepo = await loadProviderMessageRepository({
@@ -576,6 +469,13 @@ export async function loadConversationMessages(threadId, format, workspacePath)
576
469
  workspacePath,
577
470
  conversation: conversation !== null && conversation !== void 0 ? conversation : null,
578
471
  });
472
+ if (conversation && !normalizeConversationTitle(conversation.title)) {
473
+ await syncMissingConversationTitleFromMessages({
474
+ workspacePath,
475
+ threadId,
476
+ messages: providerRepo.messages,
477
+ });
478
+ }
579
479
  return providerRepo;
580
480
  }
581
481
  export async function saveConversationMessage(threadId, request, workspacePath) {
@@ -0,0 +1,3 @@
1
+ export declare function isDisplayOnlyTagBlock(text: string): boolean;
2
+ export declare function isDisplayOnlyTagStart(text: string): boolean;
3
+ export declare function getUserFacingMessageText(text: string): string;
@@ -0,0 +1,81 @@
1
+ const DISPLAY_ONLY_TAG_ROOTS = new Set([
2
+ "app-context",
3
+ "collaboration_mode",
4
+ "developer",
5
+ "dynamic_context",
6
+ "environment_context",
7
+ "permissions instructions",
8
+ "plugins_instructions",
9
+ "skills_instructions",
10
+ "system",
11
+ ]);
12
+ function normalizeTagRoot(value) {
13
+ return value.trim().toLowerCase();
14
+ }
15
+ function isDisplayOnlyTagRoot(root) {
16
+ const normalizedRoot = normalizeTagRoot(root);
17
+ if (DISPLAY_ONLY_TAG_ROOTS.has(normalizedRoot))
18
+ return true;
19
+ return (normalizedRoot.includes("_") ||
20
+ normalizedRoot.includes("-") ||
21
+ normalizedRoot.includes(" "));
22
+ }
23
+ function getOpeningTagRoot(text) {
24
+ var _a, _b;
25
+ const match = text.trim().match(/^<([A-Za-z][\w:-]*)(?:\s[^>]*)?>/u);
26
+ return (_b = (_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : null;
27
+ }
28
+ function escapeRegExp(value) {
29
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
30
+ }
31
+ function getWrappedTagRoot(text) {
32
+ var _a, _b;
33
+ const trimmed = text.trim();
34
+ const match = trimmed.match(/^<([A-Za-z][\w:-]*)(?:\s[^>]*)?>[\s\S]*<\/\1>$/u);
35
+ return (_b = (_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : null;
36
+ }
37
+ function extractTaggedText(text, tagName) {
38
+ var _a, _b, _c;
39
+ const pattern = new RegExp(`<${tagName}(?:\\s[^>]*)?>([\\s\\S]*?)<\\/${tagName}>`, "iu");
40
+ return (_c = (_b = (_a = pattern.exec(text)) === null || _a === void 0 ? void 0 : _a[1]) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : "";
41
+ }
42
+ function stripLeadingDisplayOnlyTagBlocks(text) {
43
+ var _a;
44
+ let remaining = text.trim();
45
+ for (let index = 0; index < 10; index += 1) {
46
+ const openingMatch = remaining.match(/^<([A-Za-z][\w:-]*)(?:\s[^>]*)?>/u);
47
+ const root = (_a = openingMatch === null || openingMatch === void 0 ? void 0 : openingMatch[1]) === null || _a === void 0 ? void 0 : _a.trim();
48
+ if (!openingMatch || !root || !isDisplayOnlyTagRoot(root)) {
49
+ return remaining;
50
+ }
51
+ const closingPattern = new RegExp(`</${escapeRegExp(root)}>`, "iu");
52
+ const contentStart = openingMatch[0].length;
53
+ const closingMatch = closingPattern.exec(remaining.slice(contentStart));
54
+ if (!closingMatch)
55
+ return "";
56
+ remaining = remaining
57
+ .slice(contentStart + closingMatch.index + closingMatch[0].length)
58
+ .trim();
59
+ }
60
+ return remaining;
61
+ }
62
+ export function isDisplayOnlyTagBlock(text) {
63
+ const root = getWrappedTagRoot(text);
64
+ return root ? isDisplayOnlyTagRoot(root) : false;
65
+ }
66
+ export function isDisplayOnlyTagStart(text) {
67
+ const root = getOpeningTagRoot(text);
68
+ return root ? isDisplayOnlyTagRoot(root) : false;
69
+ }
70
+ export function getUserFacingMessageText(text) {
71
+ const trimmed = text.trim();
72
+ if (!trimmed)
73
+ return "";
74
+ const userMessageText = extractTaggedText(trimmed, "user_message");
75
+ if (userMessageText)
76
+ return userMessageText;
77
+ const stripped = stripLeadingDisplayOnlyTagBlocks(trimmed);
78
+ return isDisplayOnlyTagBlock(stripped) || isDisplayOnlyTagStart(stripped)
79
+ ? ""
80
+ : stripped;
81
+ }
@@ -1,4 +1,4 @@
1
- import type { AcpBuiltinToolSettings, AcpPermissionMode, AcpProviderKey } from "../acp2aisdk";
1
+ import type { AcpBuiltinToolSettings, AcpPermissionMode, AcpProviderKey, AcpRunState } from "../acp2aisdk";
2
2
  export type ConversationStatus = "active" | "archived" | "deleted";
3
3
  export type ConversationSourceKind = "codex-jsonl";
4
4
  export type ConversationBuiltinToolSettings = AcpBuiltinToolSettings;
@@ -52,6 +52,17 @@ export type ConversationMessageRepository<TContent = Record<string, unknown>> =
52
52
  error?: string;
53
53
  };
54
54
  };
55
+ export type ConversationMessageSource = "auto" | "provider" | "runtime";
56
+ export type ConversationRuntimeResponse = {
57
+ threadId: string;
58
+ provider: AcpProviderKey;
59
+ workspacePath: string;
60
+ metadata: {
61
+ runState: AcpRunState;
62
+ } | null;
63
+ acpSessionId: string | null;
64
+ lastUsedAt: number | null;
65
+ };
55
66
  export type ConversationStoreData = {
56
67
  version: 1;
57
68
  conversations: ConversationRecord[];
@@ -11,6 +11,14 @@ export const LOCAL_IMAGE_FILE_EXTENSIONS = new Set([
11
11
  ".webp",
12
12
  ]);
13
13
  const LOCAL_FILE_EXTENSION_RE = /^\.[A-Za-z0-9][A-Za-z0-9_-]{0,15}$/;
14
+ function decodePathComponent(value) {
15
+ try {
16
+ return decodeURIComponent(value);
17
+ }
18
+ catch (_a) {
19
+ return value;
20
+ }
21
+ }
14
22
  export function normalizeLocalFilePath(value) {
15
23
  const raw = value.trim();
16
24
  if (!raw)
@@ -35,7 +43,7 @@ export function normalizeLocalFilePath(value) {
35
43
  return null;
36
44
  }
37
45
  }
38
- const withoutQuery = raw.split(/[?#]/, 1)[0];
46
+ const withoutQuery = decodePathComponent(raw.split(/[?#]/, 1)[0]);
39
47
  const windowsPath = withoutQuery.replace(/^\/([A-Za-z]:[\\/])/, "$1");
40
48
  if (path.win32.isAbsolute(windowsPath)) {
41
49
  return windowsPath;
@@ -11,11 +11,36 @@ function trimPathValue(value) {
11
11
  }
12
12
  return trimmed;
13
13
  }
14
+ function decodePathComponent(value) {
15
+ try {
16
+ return decodeURIComponent(value);
17
+ }
18
+ catch (_a) {
19
+ return value;
20
+ }
21
+ }
22
+ function normalizeLocalPathValue(value) {
23
+ const raw = trimPathValue(value);
24
+ if (/^https?:\/\//i.test(raw)) {
25
+ try {
26
+ const url = new URL(raw);
27
+ if (LOCAL_HOSTS.has(url.hostname)) {
28
+ return decodePathComponent(url.pathname);
29
+ }
30
+ }
31
+ catch (_a) {
32
+ return raw;
33
+ }
34
+ }
35
+ if (raw.startsWith("file://"))
36
+ return raw;
37
+ return decodePathComponent(raw);
38
+ }
14
39
  function hasImageExtension(value) {
15
- return IMAGE_EXTENSION_RE.test(value.split(/\s+/, 1)[0]);
40
+ return IMAGE_EXTENSION_RE.test(value);
16
41
  }
17
42
  function hasFileExtension(value) {
18
- return FILE_EXTENSION_RE.test(value.split(/\s+/, 1)[0]);
43
+ return FILE_EXTENSION_RE.test(value);
19
44
  }
20
45
  function isLocalHostUrl(value) {
21
46
  try {
@@ -32,7 +57,7 @@ function isLocalAbsolutePath(value) {
32
57
  UNC_LOCAL_PATH_RE.test(value));
33
58
  }
34
59
  export function isLocalFilePath(value) {
35
- const raw = trimPathValue(value);
60
+ const raw = normalizeLocalPathValue(value);
36
61
  if (!hasFileExtension(raw))
37
62
  return false;
38
63
  if (raw.startsWith("file://"))
@@ -51,7 +76,7 @@ export function isLocalFilePath(value) {
51
76
  return isLocalAbsolutePath(raw);
52
77
  }
53
78
  export function isLocalImagePath(value) {
54
- const raw = trimPathValue(value);
79
+ const raw = normalizeLocalPathValue(value);
55
80
  if (!hasImageExtension(raw))
56
81
  return false;
57
82
  if (raw.startsWith("file://"))
@@ -82,10 +107,10 @@ export function isRenderableImageUrl(value) {
82
107
  return false;
83
108
  }
84
109
  export function getLocalImagePreviewUrl(value) {
85
- return `/api/local-files/image?path=${encodeURIComponent(trimPathValue(value))}`;
110
+ return `/api/local-files/image?path=${encodeURIComponent(normalizeLocalPathValue(value))}`;
86
111
  }
87
112
  export function getLocalFileName(value) {
88
- const raw = trimPathValue(value);
113
+ const raw = normalizeLocalPathValue(value);
89
114
  let pathValue = raw;
90
115
  if (raw.startsWith("file://") || isLocalHostUrl(raw)) {
91
116
  try {
@@ -0,0 +1,22 @@
1
+ import { type AcpOutputArtifact } from "../../components/assistant-ui/addons/output-artifacts";
2
+ import type { ConversationMessageSource, StoredMessageEntry } from "../conversations/types";
3
+ import type { ImageGenerationRecord } from "../../tools/image-generation/shared";
4
+ export type ThreadOutputArtifactCollection = {
5
+ messages: StoredMessageEntry<Record<string, unknown>>[];
6
+ artifacts: AcpOutputArtifact[];
7
+ imageGenerationRecords: ImageGenerationRecord[];
8
+ workspaceArtifacts: AcpOutputArtifact[];
9
+ diagnostic?: {
10
+ source?: string;
11
+ error?: string;
12
+ };
13
+ };
14
+ type CollectThreadOutputArtifactsOptions = {
15
+ threadId: string;
16
+ workspacePath?: string | null;
17
+ format?: string | null;
18
+ source?: ConversationMessageSource;
19
+ sinceMs?: number | null;
20
+ };
21
+ export declare function collectThreadOutputArtifacts({ threadId, workspacePath, format, source, sinceMs, }: CollectThreadOutputArtifactsOptions): Promise<ThreadOutputArtifactCollection>;
22
+ export {};
@@ -0,0 +1,47 @@
1
+ import { normalizeAcpOutputArtifacts, } from "../../components/assistant-ui/addons/output-artifacts.mjs";
2
+ import { loadConversationMessages } from "../conversations/store.mjs";
3
+ import { listImageGenerationRecords } from "../../tools/image-generation/service.mjs";
4
+ import { scanWorkspaceOutputArtifacts } from "./workspace.mjs";
5
+ function getArtifactMergeKey(artifact) {
6
+ return `${artifact.kind}:${artifact.path || artifact.title}`;
7
+ }
8
+ function mergeAcpOutputArtifacts(...collections) {
9
+ const byKey = new Map();
10
+ for (const artifact of collections.flat()) {
11
+ const key = getArtifactMergeKey(artifact);
12
+ const previous = byKey.get(key);
13
+ if (!previous ||
14
+ (!previous.newText && artifact.newText) ||
15
+ artifact.updatedAt >= previous.updatedAt) {
16
+ byKey.set(key, artifact);
17
+ }
18
+ }
19
+ return [...byKey.values()];
20
+ }
21
+ function normalizeSinceMs(value) {
22
+ return Number.isFinite(value) ? Math.max(0, Number(value)) : 0;
23
+ }
24
+ export async function collectThreadOutputArtifacts({ threadId, workspacePath, format = "ai-sdk/v6", source = "auto", sinceMs, }) {
25
+ const repo = await loadConversationMessages(threadId, format, workspacePath, source);
26
+ const messages = repo.messages;
27
+ const messageArtifacts = normalizeAcpOutputArtifacts(messages.map((message) => message.content));
28
+ const [imageGenerationRecords, workspaceArtifacts] = await Promise.all([
29
+ listImageGenerationRecords({
30
+ workspacePath,
31
+ threadId,
32
+ limit: 100,
33
+ }).catch(() => []),
34
+ scanWorkspaceOutputArtifacts({
35
+ workspacePath,
36
+ threadId,
37
+ sinceMs: normalizeSinceMs(sinceMs),
38
+ }).catch(() => []),
39
+ ]);
40
+ return {
41
+ messages,
42
+ artifacts: mergeAcpOutputArtifacts(messageArtifacts, workspaceArtifacts),
43
+ imageGenerationRecords,
44
+ workspaceArtifacts,
45
+ diagnostic: repo.diagnostic,
46
+ };
47
+ }
@@ -54,7 +54,9 @@ function normalizeRelativePath(value) {
54
54
  }
55
55
  function isWithinWorkspace(root, filePath) {
56
56
  const relativePath = path.relative(root, filePath);
57
- return Boolean(relativePath && !relativePath.startsWith("..") && !path.isAbsolute(relativePath));
57
+ return Boolean(relativePath &&
58
+ !relativePath.startsWith("..") &&
59
+ !path.isAbsolute(relativePath));
58
60
  }
59
61
  function isExcludedRelativePath(relativePath) {
60
62
  const parts = normalizeRelativePath(relativePath).split("/");
@@ -121,7 +123,9 @@ async function collectCandidateFiles(root) {
121
123
  const visit = async (directory) => {
122
124
  if (files.length >= MAX_SCAN_FILES)
123
125
  return;
124
- const entries = await fs.readdir(directory, { withFileTypes: true }).catch(() => []);
126
+ const entries = await fs
127
+ .readdir(directory, { withFileTypes: true })
128
+ .catch(() => []);
125
129
  for (const entry of entries) {
126
130
  if (files.length >= MAX_SCAN_FILES)
127
131
  return;
@@ -1,19 +1,10 @@
1
1
  import fs from "node:fs/promises";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
+ import { getUserFacingMessageText, isDisplayOnlyTagBlock, } from "../conversations/title-text.mjs";
4
5
  const PROVIDER = "codex";
5
6
  const SOURCE_KIND = "codex-jsonl";
6
7
  const UUID_RE = /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/;
7
- const DISPLAY_ONLY_TAG_ROOTS = new Set([
8
- "app-context",
9
- "collaboration_mode",
10
- "developer",
11
- "environment_context",
12
- "permissions instructions",
13
- "plugins_instructions",
14
- "skills_instructions",
15
- "system",
16
- ]);
17
8
  const FINAL_ASSISTANT_PHASE = "final_answer";
18
9
  function getCodexSessionsRoot() {
19
10
  if (process.env.ACP_UI_CODEX_SESSIONS_ROOT) {
@@ -77,20 +68,6 @@ function truncate(text, maxLength) {
77
68
  return trimmed;
78
69
  return `${trimmed.slice(0, maxLength).trim()}...`;
79
70
  }
80
- function getWrappedTagRoot(text) {
81
- var _a, _b;
82
- const trimmed = text.trim();
83
- const match = trimmed.match(/^<([^>\n]+)>[\s\S]*<\/\1>$/);
84
- return (_b = (_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : null;
85
- }
86
- function isDisplayOnlyTagBlock(text) {
87
- const root = getWrappedTagRoot(text);
88
- if (!root)
89
- return false;
90
- if (DISPLAY_ONLY_TAG_ROOTS.has(root))
91
- return true;
92
- return root.includes("_") || root.includes("-") || root.includes(" ");
93
- }
94
71
  async function collectJsonlFiles(root) {
95
72
  const files = [];
96
73
  async function visit(dir) {
@@ -154,10 +131,8 @@ async function parseSessionMeta(filePath, lines) {
154
131
  isRecord(value.payload) &&
155
132
  value.payload.type === "message" &&
156
133
  value.payload.role === "user") {
157
- const text = extractText(value.payload.content).trim();
158
- if (text &&
159
- !text.startsWith("# AGENTS.md") &&
160
- !isDisplayOnlyTagBlock(text)) {
134
+ const text = getUserFacingMessageText(extractText(value.payload.content)).trim();
135
+ if (text && !text.startsWith("# AGENTS.md")) {
161
136
  firstUserMessage = text;
162
137
  }
163
138
  }
@@ -171,7 +146,7 @@ async function parseSessionMeta(filePath, lines) {
171
146
  value.type === "response_item" &&
172
147
  isRecord(value.payload) &&
173
148
  value.payload.type === "message") {
174
- const text = extractText(value.payload.content).trim();
149
+ const text = getUserFacingMessageText(extractText(value.payload.content)).trim();
175
150
  if (text && !isDisplayOnlyTagBlock(text))
176
151
  summary = text;
177
152
  }
@@ -210,7 +185,7 @@ function parseTranscriptMessage(value, index) {
210
185
  payload.phase !== FINAL_ASSISTANT_PHASE) {
211
186
  return null;
212
187
  }
213
- const text = extractText(payload.content).trim();
188
+ const text = getUserFacingMessageText(extractText(payload.content)).trim();
214
189
  if (!text || isDisplayOnlyTagBlock(text))
215
190
  return null;
216
191
  return {
@@ -1,4 +1,4 @@
1
- export { cleanupAcpSession, getAcpSessionMetadata, listAcpSessionMetadata, streamAcpChat, } from "../lib/acp2aisdk";
1
+ export { cancelAcpSession, cleanupAcpSession, getAcpSessionMetadata, listAcpSessionMetadata, streamAcpChat, } from "../lib/acp2aisdk";
2
2
  export { buildAcpCapabilitySnapshot } from "../lib/acp2aisdk/capabilities";
3
3
  export { ACP_PROVIDER_ALIASES, ACP_PROVIDER_DEFAULT_MODE_IDS, ACP_PROVIDER_KEYS, ACP_PROVIDER_REGISTRY, getAcpProviderDefaultModeId, isAcpProviderKey, normalizeAcpProvider, readProviderOverridesFromEnv, resolveAcpProviderConfig, } from "../lib/acp2aisdk/provider-registry";
4
4
  export { createAcpSessionKey, createInitialMetadata, DEFAULT_PERMISSION_MODE, DEFAULT_THREAD_ID, getDefaultWorkspacePath, getGlobalAcpSessionStore, normalizeThreadId, normalizeWorkspacePath, SESSION_IDLE_TTL_MS, } from "../lib/acp2aisdk/session-store";