@jingyi0605/codingns 0.9.7 → 0.9.8

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 (155) hide show
  1. package/dist/public/assets/{AdaptiveButlerPage-DclGPzEx.js → AdaptiveButlerPage-D-gXre7Y.js} +2 -2
  2. package/dist/public/assets/{App-CcDXqFl1.css → App-7zrCMhE-.css} +1 -1
  3. package/dist/public/assets/App-Dl-mcdqy.js +30 -0
  4. package/dist/public/assets/{BootstrapPage-Bl21SsuW.js → BootstrapPage-B-yMdfpQ.js} +1 -1
  5. package/dist/public/assets/ConversationPage-DRQ5Sg_d.js +9 -0
  6. package/dist/public/assets/{DesktopDetachPreviewPage-uaOHVsjV.js → DesktopDetachPreviewPage-D1DMaGcy.js} +1 -1
  7. package/dist/public/assets/{DesktopModal-BxsogpLf.js → DesktopModal-BnfGW2gk.js} +1 -1
  8. package/dist/public/assets/DesktopWindowPage-2SWAi0xz.js +2 -0
  9. package/dist/public/assets/FileContextPanel-fbPuE9dO.js +1 -0
  10. package/dist/public/assets/GitSidebar-BkmesJJR.js +6 -0
  11. package/dist/public/assets/{MobileCreateSessionSheet-CqtmfVNo.js → MobileCreateSessionSheet-CEJcDBZJ.js} +1 -1
  12. package/dist/public/assets/{MobileSheet-C5IVmUsO.js → MobileSheet-rkn_CUOY.js} +1 -1
  13. package/dist/public/assets/{MobileTopHeaderFrame-EoBm3-X0.js → MobileTopHeaderFrame-CU0wsYSS.js} +1 -1
  14. package/dist/public/assets/MobileWorkspaceSwitcherHeader-idl8o1OB.js +1 -0
  15. package/dist/public/assets/{PluginAccessOverview-CrQiQxxZ.js → PluginAccessOverview-BBgM6tb0.js} +1 -1
  16. package/dist/public/assets/{PluginContainerPage-_2u-9thM.js → PluginContainerPage-D-ly3i3H.js} +1 -1
  17. package/dist/public/assets/{PluginDetailPage-F9cKjSCp.js → PluginDetailPage-CWAHYyyG.js} +1 -1
  18. package/dist/public/assets/{PluginsListPage-BOhcua_4.js → PluginsListPage-Cte3vBgR.js} +1 -1
  19. package/dist/public/assets/{RelayConnectEntryPage-Ck_uZLzj.js → RelayConnectEntryPage-sRJlstx9.js} +1 -1
  20. package/dist/public/assets/{ServerSettingsModal-ICd82a_x.js → ServerSettingsModal-BBft9KEC.js} +1 -1
  21. package/dist/public/assets/SessionIndexPage-CN7cEdl9.js +1 -0
  22. package/dist/public/assets/SettingsPage-BGT-YqG2.js +2 -0
  23. package/dist/public/assets/TerminalManagerPanel-6-ZJ8vGn.js +1 -0
  24. package/dist/public/assets/TerminalPage-CUXXQYU2.js +55 -0
  25. package/dist/public/assets/{TerminalRuntimeFallbackModal-DGPR_CMh.js → TerminalRuntimeFallbackModal-zc3qqMKJ.js} +1 -1
  26. package/dist/public/assets/ToolFilesPage-QzsZyr0F.js +1 -0
  27. package/dist/public/assets/ToolGitPage-CXg4ncuT.js +1 -0
  28. package/dist/public/assets/ToolProcessesPage-BPsOsg4w.js +1 -0
  29. package/dist/public/assets/ToolsHomePage-D1n4FU1s.js +1 -0
  30. package/dist/public/assets/WorkbenchLandingPage-BaU_dXls.js +1 -0
  31. package/dist/public/assets/WorkbenchLayout-DViAJhHz.js +1027 -0
  32. package/dist/public/assets/{WorkbenchModal-CsZeLArg.js → WorkbenchModal-DWsNm2B2.js} +1 -1
  33. package/dist/public/assets/WorkbenchShellRoute-BGfRqBUa.js +1 -0
  34. package/dist/public/assets/WorkbenchShellRoute-f2jWjHWu.css +1 -0
  35. package/dist/public/assets/WorkspaceDebugDetailPage-BX0zVSsI.js +1 -0
  36. package/dist/public/assets/WorkspaceDetailPage-Dx6JX4jx.js +1 -0
  37. package/dist/public/assets/WorkspaceHomePage-DQVJ042Z.js +1 -0
  38. package/dist/public/assets/{client-runtime-manager-BgGugw8T.js → client-runtime-manager-D9VbgJZ_.js} +1 -1
  39. package/dist/public/assets/host-alias-0TfFnYxR.js +1 -0
  40. package/dist/public/assets/index-DREvg1Yu.css +1 -0
  41. package/dist/public/assets/index-FOhyOpGY.js +50 -0
  42. package/dist/public/assets/{login-direct-candidate-resolver-ty2uOY5y.js → login-direct-candidate-resolver-17wEvjhh.js} +1 -1
  43. package/dist/public/assets/peer-host-config-sync-vYkmqzNz.js +1 -0
  44. package/dist/public/assets/{plugin-permission-copy-iK3faI3n.js → plugin-permission-copy-apDn8EWG.js} +1 -1
  45. package/dist/public/assets/{plugins-api-CmV7aDGA.js → plugins-api-CnZYRKoS.js} +1 -1
  46. package/dist/public/assets/{preferences-service-BoSmT_ny.js → preferences-service-PZlLLAWH.js} +1 -1
  47. package/dist/public/assets/relay-entry-DhHwflXl.js +1 -0
  48. package/dist/public/assets/terminal-runtime-meta-2zvacxvM.js +1 -0
  49. package/dist/public/assets/{useRegisteredDebugTemplates-B_vXUtSe.js → useRegisteredDebugTemplates-CJ-o4tFl.js} +1 -1
  50. package/dist/public/assets/workbench-navigation-aqJ1ay4M.js +1 -0
  51. package/dist/public/index.html +2 -2
  52. package/dist/server/middlewares/auth-guard.js +1 -0
  53. package/dist/server/middlewares/auth-guard.js.map +1 -1
  54. package/dist/server/modules/peer-host/host-api-proxy-service.d.ts +9 -0
  55. package/dist/server/modules/peer-host/host-api-proxy-service.js +174 -0
  56. package/dist/server/modules/peer-host/host-api-proxy-service.js.map +1 -0
  57. package/dist/server/modules/peer-host/host-handshake-controller.d.ts +7 -0
  58. package/dist/server/modules/peer-host/host-handshake-controller.js +10 -0
  59. package/dist/server/modules/peer-host/host-handshake-controller.js.map +1 -0
  60. package/dist/server/modules/peer-host/host-handshake.d.ts +15 -0
  61. package/dist/server/modules/peer-host/host-handshake.js +20 -0
  62. package/dist/server/modules/peer-host/host-handshake.js.map +1 -0
  63. package/dist/server/modules/peer-host/host-ws-proxy-service.d.ts +14 -0
  64. package/dist/server/modules/peer-host/host-ws-proxy-service.js +256 -0
  65. package/dist/server/modules/peer-host/host-ws-proxy-service.js.map +1 -0
  66. package/dist/server/modules/peer-host/peer-host-controller.d.ts +55 -0
  67. package/dist/server/modules/peer-host/peer-host-controller.js +62 -0
  68. package/dist/server/modules/peer-host/peer-host-controller.js.map +1 -0
  69. package/dist/server/modules/peer-host/peer-host-service.d.ts +77 -0
  70. package/dist/server/modules/peer-host/peer-host-service.js +529 -0
  71. package/dist/server/modules/peer-host/peer-host-service.js.map +1 -0
  72. package/dist/server/modules/sessions/codex-session-title-generator.js +18 -5
  73. package/dist/server/modules/sessions/codex-session-title-generator.js.map +1 -1
  74. package/dist/server/modules/sessions/session-history-service.d.ts +12 -1
  75. package/dist/server/modules/sessions/session-history-service.js +51 -38
  76. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  77. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +6 -0
  78. package/dist/server/modules/sessions/session-live-runtime-service.js +181 -80
  79. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  80. package/dist/server/modules/sessions/session-title-utils.d.ts +3 -0
  81. package/dist/server/modules/sessions/session-title-utils.js +25 -0
  82. package/dist/server/modules/sessions/session-title-utils.js.map +1 -0
  83. package/dist/server/modules/sessions/workspace-office-mcp-config.d.ts +2 -1
  84. package/dist/server/modules/sessions/workspace-office-mcp-config.js +44 -3
  85. package/dist/server/modules/sessions/workspace-office-mcp-config.js.map +1 -1
  86. package/dist/server/modules/tasks/task-manager.d.ts +2 -1
  87. package/dist/server/modules/tasks/task-manager.js +3 -0
  88. package/dist/server/modules/tasks/task-manager.js.map +1 -1
  89. package/dist/server/modules/tasks/task-scheduler.d.ts +2 -1
  90. package/dist/server/modules/tasks/task-scheduler.js +21 -0
  91. package/dist/server/modules/tasks/task-scheduler.js.map +1 -1
  92. package/dist/server/modules/tasks/task-types.d.ts +5 -0
  93. package/dist/server/modules/tasks/task-types.js.map +1 -1
  94. package/dist/server/modules/workbench/workbench-controller.js +3 -2
  95. package/dist/server/modules/workbench/workbench-controller.js.map +1 -1
  96. package/dist/server/modules/workspace/affairs-library-service.d.ts +1 -0
  97. package/dist/server/modules/workspace/affairs-library-service.js +80 -0
  98. package/dist/server/modules/workspace/affairs-library-service.js.map +1 -1
  99. package/dist/server/routes/peer-hosts.d.ts +3 -0
  100. package/dist/server/routes/peer-hosts.js +18 -0
  101. package/dist/server/routes/peer-hosts.js.map +1 -0
  102. package/dist/server/routes/public.d.ts +2 -1
  103. package/dist/server/routes/public.js +2 -1
  104. package/dist/server/routes/public.js.map +1 -1
  105. package/dist/server/server/create-server.d.ts +4 -0
  106. package/dist/server/server/create-server.js +30 -2
  107. package/dist/server/server/create-server.js.map +1 -1
  108. package/dist/server/shared/http/error-handler.js +12 -0
  109. package/dist/server/shared/http/error-handler.js.map +1 -1
  110. package/dist/server/storage/repositories/peer-host-repository.d.ts +44 -0
  111. package/dist/server/storage/repositories/peer-host-repository.js +271 -0
  112. package/dist/server/storage/repositories/peer-host-repository.js.map +1 -0
  113. package/dist/server/storage/sqlite/client.js +81 -0
  114. package/dist/server/storage/sqlite/client.js.map +1 -1
  115. package/dist/server/storage/sqlite/schema.sql +64 -0
  116. package/dist/server/types/domain.d.ts +43 -0
  117. package/dist/server/ws/workbench-ws-hub.js +5 -14
  118. package/dist/server/ws/workbench-ws-hub.js.map +1 -1
  119. package/dist/server/ws/ws-server.d.ts +2 -1
  120. package/dist/server/ws/ws-server.js +5 -1
  121. package/dist/server/ws/ws-server.js.map +1 -1
  122. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +29 -5
  123. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
  124. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +8 -1
  125. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js.map +1 -1
  126. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +3 -0
  127. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +144 -27
  128. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  129. package/package.json +1 -1
  130. package/dist/public/assets/App-BxX5mm9o.js +0 -30
  131. package/dist/public/assets/ConversationPage-CmiVCV0q.js +0 -9
  132. package/dist/public/assets/DesktopWindowPage-Bubfw1nC.js +0 -2
  133. package/dist/public/assets/FileContextPanel-DrYWcTkp.js +0 -1
  134. package/dist/public/assets/GitSidebar-CQsfJqun.js +0 -6
  135. package/dist/public/assets/MobileWorkspaceSwitcherHeader-BC8MMQs_.js +0 -1
  136. package/dist/public/assets/SessionIndexPage-Cox6P6dw.js +0 -1
  137. package/dist/public/assets/SettingsPage-BI5cM3j5.js +0 -2
  138. package/dist/public/assets/TerminalManagerPanel-DiVhBQhf.js +0 -1
  139. package/dist/public/assets/TerminalPage-DUMUO7Ng.js +0 -55
  140. package/dist/public/assets/ToolFilesPage-m88CAp-r.js +0 -1
  141. package/dist/public/assets/ToolGitPage-DCYpfTsb.js +0 -1
  142. package/dist/public/assets/ToolProcessesPage-Bk5ulsyq.js +0 -1
  143. package/dist/public/assets/ToolsHomePage-BrTwfjI7.js +0 -1
  144. package/dist/public/assets/WorkbenchLandingPage-q4AAmdMV.js +0 -1
  145. package/dist/public/assets/WorkbenchLayout-DD8b-m2G.js +0 -1027
  146. package/dist/public/assets/WorkbenchShellRoute-BaiW_vfb.js +0 -1
  147. package/dist/public/assets/WorkbenchShellRoute-CxKYZ6uF.css +0 -1
  148. package/dist/public/assets/WorkspaceDebugDetailPage-BcUUDEyw.js +0 -1
  149. package/dist/public/assets/WorkspaceDetailPage-zEZ1VARA.js +0 -1
  150. package/dist/public/assets/WorkspaceHomePage-CR0rqS4e.js +0 -1
  151. package/dist/public/assets/index-CFyk1rgJ.js +0 -50
  152. package/dist/public/assets/index-CrU73EIV.css +0 -1
  153. package/dist/public/assets/relay-entry-C8k5qsl5.js +0 -1
  154. package/dist/public/assets/terminal-runtime-meta-okQIDzfA.js +0 -1
  155. package/dist/public/assets/workbench-navigation-DoDaQR4z.js +0 -1
@@ -75,6 +75,12 @@ interface SessionHistoryAdapterOverrides {
75
75
  providerSessionDeleteCli?: ProviderSessionDeleteCli;
76
76
  }
77
77
  type LiveActivityObservationResolver = (sessionId: string) => SessionActivityObservation | null;
78
+ type SessionTitleChangedObserver = (input: {
79
+ sessionId: string;
80
+ userId: string;
81
+ workspaceId: string;
82
+ title: string;
83
+ }) => Promise<void> | void;
78
84
  type SessionDeletedObserver = (input: {
79
85
  sessionId: string;
80
86
  userId: string;
@@ -116,6 +122,7 @@ export declare class SessionHistoryService {
116
122
  private readonly codexDirtyBindingRepairStates;
117
123
  private readonly streamingDeltaSuppressionDebugState;
118
124
  private readonly liveActivityObservationResolvers;
125
+ private readonly sessionTitleChangedObservers;
119
126
  private readonly sessionDeletedObservers;
120
127
  private readonly workspaceSessionRelations;
121
128
  private workspaceStateRefreshTaskSequence;
@@ -127,6 +134,9 @@ export declare class SessionHistoryService {
127
134
  registerSessionDeletedObserver(observer: SessionDeletedObserver): {
128
135
  close(): void;
129
136
  };
137
+ registerSessionTitleChangedObserver(observer: SessionTitleChangedObserver): {
138
+ close(): void;
139
+ };
130
140
  private registerBackgroundTasks;
131
141
  discoverWorkspaceSessions(workspaceId: string, userId: string, options?: {
132
142
  maxAgeMs?: number;
@@ -218,9 +228,10 @@ export declare class SessionHistoryService {
218
228
  private shouldSuppressStreamingSessionDelta;
219
229
  private publishHistoryEnvelope;
220
230
  private syncSessionTitleFromProvider;
221
- private requestCodexTitleGenerationIfNeeded;
231
+ requestCodexTitleGenerationForNewSession(sessionId: string, firstUserMessage: string): void;
222
232
  private shouldRequestCodexTitleGeneration;
223
233
  private runCodexSessionTitleGeneration;
234
+ private notifySessionTitleChanged;
224
235
  private readFirstUserMessageTitleForSync;
225
236
  private resolvePersistedParentSessionId;
226
237
  private ensureSessionChangedFilesIndexed;
@@ -9,6 +9,7 @@ import { isTerminalDebugEnabled, logTerminalDebug, terminalDebugNowMs } from "..
9
9
  import { nowIso } from "../../shared/utils/time.js";
10
10
  import { inspectSessionActivity } from "./session-activity-inspector.js";
11
11
  import { SessionActivityAuthorityService } from "./session-activity-authority-service.js";
12
+ import { buildSessionTitleFromContent, normalizeRuntimePromptTitle } from "./session-title-utils.js";
12
13
  import { mapSessionProviderError } from "./session-provider-error-mapper.js";
13
14
  import { SessionForkRepository } from "../../storage/repositories/session-fork-repository.js";
14
15
  import { buildParallelGroupColorToken, resolveParallelDisplayParentSessionId } from "../parallel-sessions/parallel-session-group-service.js";
@@ -91,6 +92,7 @@ export class SessionHistoryService {
91
92
  codexDirtyBindingRepairStates = new Map();
92
93
  streamingDeltaSuppressionDebugState = new Map();
93
94
  liveActivityObservationResolvers = new Set();
95
+ sessionTitleChangedObservers = new Set();
94
96
  sessionDeletedObservers = new Set();
95
97
  workspaceSessionRelations = new Map();
96
98
  workspaceStateRefreshTaskSequence = 0;
@@ -204,6 +206,14 @@ export class SessionHistoryService {
204
206
  }
205
207
  };
206
208
  }
209
+ registerSessionTitleChangedObserver(observer) {
210
+ this.sessionTitleChangedObservers.add(observer);
211
+ return {
212
+ close: () => {
213
+ this.sessionTitleChangedObservers.delete(observer);
214
+ }
215
+ };
216
+ }
207
217
  registerBackgroundTasks() {
208
218
  if (!this.taskManager.has(HOST_TASK_TYPES.workspaceDiscovery)) {
209
219
  this.taskManager.register({
@@ -238,8 +248,9 @@ export class SessionHistoryService {
238
248
  this.taskManager.register({
239
249
  taskType: HOST_TASK_TYPES.sessionCodexTitleGenerate,
240
250
  executionLane: "external_process",
251
+ concurrency: 1,
241
252
  timeoutMs: 45_000,
242
- run: async ({ sessionId }, context) => this.runCodexSessionTitleGeneration(sessionId, context.signal)
253
+ run: async ({ sessionId, firstUserMessage }, context) => this.runCodexSessionTitleGeneration(sessionId, firstUserMessage, context.signal)
243
254
  });
244
255
  }
245
256
  }
@@ -461,7 +472,6 @@ export class SessionHistoryService {
461
472
  async syncSessionTitle(sessionId, signal) {
462
473
  const binding = this.getBindingOrThrow(sessionId);
463
474
  await this.syncSessionTitleFromProvider(sessionId, binding, signal);
464
- this.requestCodexTitleGenerationIfNeeded(sessionId, "session_history.sync_session_title");
465
475
  }
466
476
  async syncWorkspaceSessionTitles(workspaceId, userId, concurrency = 1, signal) {
467
477
  const sessions = this.sessionIndexRepository.listByWorkspace(workspaceId, userId);
@@ -1167,7 +1177,6 @@ export class SessionHistoryService {
1167
1177
  return null;
1168
1178
  }
1169
1179
  await this.syncSessionTitleFromProvider(sessionId, binding);
1170
- this.requestCodexTitleGenerationIfNeeded(sessionId, "session_history.read_recent_history");
1171
1180
  const snapshot = this.sessionStatusSnapshotRepository.findBySessionId(sessionId);
1172
1181
  this.upsertSnapshot(sessionId, {
1173
1182
  syncStatus: "idle",
@@ -1641,9 +1650,6 @@ export class SessionHistoryService {
1641
1650
  }
1642
1651
  this.workspaceSessionRelations.set(workspaceId, relationMap);
1643
1652
  this.observeDiscoveredProviderActivity(sessions, discoveredSessionIds, userId, timestamp);
1644
- for (const persisted of persistedSessions) {
1645
- this.requestCodexTitleGenerationIfNeeded(persisted.sessionId, "session_history.discover_workspace_sessions.codex_title");
1646
- }
1647
1653
  const listItemsStartedAt = Date.now();
1648
1654
  const items = this.sessionIndexRepository.listByWorkspace(workspaceId, userId);
1649
1655
  listItemsDurationMs = Date.now() - listItemsStartedAt;
@@ -2221,7 +2227,6 @@ export class SessionHistoryService {
2221
2227
  return;
2222
2228
  }
2223
2229
  await this.syncSessionTitleFromProvider(sessionId, binding);
2224
- this.requestCodexTitleGenerationIfNeeded(sessionId, "session_history.publish_history_envelope");
2225
2230
  const snapshot = this.sessionStatusSnapshotRepository.findBySessionId(sessionId);
2226
2231
  this.upsertSnapshot(sessionId, {
2227
2232
  syncStatus: "idle",
@@ -2274,15 +2279,20 @@ export class SessionHistoryService {
2274
2279
  updatedAt: nowIso()
2275
2280
  });
2276
2281
  }
2277
- requestCodexTitleGenerationIfNeeded(sessionId, source) {
2278
- if (!this.shouldRequestCodexTitleGeneration(sessionId)) {
2282
+ requestCodexTitleGenerationForNewSession(sessionId, firstUserMessage) {
2283
+ const normalizedFirstUserMessage = firstUserMessage.trim();
2284
+ if (!normalizedFirstUserMessage) {
2285
+ return;
2286
+ }
2287
+ if (!this.shouldRequestCodexTitleGeneration(sessionId, normalizedFirstUserMessage)) {
2279
2288
  return;
2280
2289
  }
2281
2290
  const handle = this.taskManager.enqueue(HOST_TASK_TYPES.sessionCodexTitleGenerate, {
2282
2291
  key: sessionId,
2283
- source,
2292
+ source: "session_history.new_codex_session_title",
2284
2293
  input: {
2285
- sessionId
2294
+ sessionId,
2295
+ firstUserMessage: normalizedFirstUserMessage
2286
2296
  }
2287
2297
  });
2288
2298
  if (handle.deduped) {
@@ -2298,7 +2308,7 @@ export class SessionHistoryService {
2298
2308
  });
2299
2309
  });
2300
2310
  }
2301
- shouldRequestCodexTitleGeneration(sessionId) {
2311
+ shouldRequestCodexTitleGeneration(sessionId, firstUserMessage) {
2302
2312
  const binding = this.sessionBindingRepository.findBySessionId(sessionId);
2303
2313
  const index = this.sessionIndexRepository.findIndexRecordBySessionId(sessionId);
2304
2314
  if (!binding || !index || binding.provider !== "codex") {
@@ -2307,12 +2317,9 @@ export class SessionHistoryService {
2307
2317
  if (isPendingBindingValue(binding.providerSessionId) || isPendingBindingValue(binding.rawStoreRef)) {
2308
2318
  return false;
2309
2319
  }
2310
- if (index.messageCount <= 0) {
2311
- return false;
2312
- }
2313
- return true;
2320
+ return shouldGenerateCodexSessionTitle(index.title, firstUserMessage);
2314
2321
  }
2315
- async runCodexSessionTitleGeneration(sessionId, signal) {
2322
+ async runCodexSessionTitleGeneration(sessionId, firstUserMessage, signal) {
2316
2323
  const binding = this.sessionBindingRepository.findBySessionId(sessionId);
2317
2324
  const index = this.sessionIndexRepository.findIndexRecordBySessionId(sessionId);
2318
2325
  if (!binding || !index || binding.provider !== "codex") {
@@ -2321,20 +2328,17 @@ export class SessionHistoryService {
2321
2328
  if (isPendingBindingValue(binding.providerSessionId) || isPendingBindingValue(binding.rawStoreRef)) {
2322
2329
  return { title: null };
2323
2330
  }
2324
- const page = await this.sessionSyncService.readHistory(binding.provider, binding.providerSessionId, binding.rawStoreRef, null, 16, "forward").catch(() => null);
2325
- if (!page) {
2326
- return { title: null };
2327
- }
2328
- const firstUserMessage = page.messages.find((message) => message.role === "user")?.content ?? null;
2329
2331
  if (!shouldGenerateCodexSessionTitle(index.title, firstUserMessage)) {
2330
2332
  return { title: null };
2331
2333
  }
2332
2334
  const title = await this.codexSessionTitleGenerator.generate({
2333
2335
  currentTitle: index.title,
2334
- messages: page.messages.map((message) => ({
2335
- role: message.role,
2336
- content: message.content
2337
- })),
2336
+ messages: [
2337
+ {
2338
+ role: "user",
2339
+ content: firstUserMessage
2340
+ }
2341
+ ],
2338
2342
  signal
2339
2343
  });
2340
2344
  if (!title || !shouldApplyGeneratedCodexSessionTitle(title, firstUserMessage)) {
@@ -2348,9 +2352,29 @@ export class SessionHistoryService {
2348
2352
  title,
2349
2353
  updatedAt: nowIso()
2350
2354
  });
2355
+ await this.notifySessionTitleChanged({
2356
+ sessionId,
2357
+ userId: binding.userId,
2358
+ workspaceId: binding.workspaceId,
2359
+ title
2360
+ });
2351
2361
  }
2352
2362
  return { title };
2353
2363
  }
2364
+ async notifySessionTitleChanged(input) {
2365
+ const userId = input.userId ?? this.workspaceRepository.findById(input.workspaceId)?.ownerUserId;
2366
+ if (!userId) {
2367
+ return;
2368
+ }
2369
+ await Promise.allSettled(Array.from(this.sessionTitleChangedObservers).map(async (observer) => {
2370
+ await observer({
2371
+ sessionId: input.sessionId,
2372
+ userId,
2373
+ workspaceId: input.workspaceId,
2374
+ title: input.title
2375
+ });
2376
+ }));
2377
+ }
2354
2378
  async readFirstUserMessageTitleForSync(binding) {
2355
2379
  const pageSize = 20;
2356
2380
  const maxPages = 3;
@@ -4265,7 +4289,7 @@ function shouldMatchSessionBindingByRawStoreRef(provider) {
4265
4289
  function resolveSessionListTitle(provider, existingTitle, fallbackContent, parentTitle = null) {
4266
4290
  const normalizedExistingTitle = existingTitle?.trim() ?? "";
4267
4291
  const normalizedParentTitle = parentTitle?.trim() ?? "";
4268
- const fallbackTitle = buildUserMessageTitle(fallbackContent, normalizedExistingTitle || "继续对话");
4292
+ const fallbackTitle = buildSessionTitleFromContent(fallbackContent, normalizedExistingTitle || "继续对话");
4269
4293
  if (normalizedExistingTitle.length > 0 &&
4270
4294
  !isSyntheticCodexSessionTitle(normalizedExistingTitle) &&
4271
4295
  (normalizedParentTitle.length === 0 ||
@@ -4280,17 +4304,6 @@ function resolveSessionListTitle(provider, existingTitle, fallbackContent, paren
4280
4304
  }
4281
4305
  return normalizedExistingTitle || fallbackTitle;
4282
4306
  }
4283
- function buildUserMessageTitle(content, fallbackTitle) {
4284
- const title = content.trim().replace(/\s+/g, " ");
4285
- return title.slice(0, 48) || fallbackTitle;
4286
- }
4287
- function normalizeRuntimePromptTitle(content) {
4288
- const normalized = (typeof content === "string" ? content : "").trim().replace(/\s+/g, " ");
4289
- if (normalized.length === 0) {
4290
- return null;
4291
- }
4292
- return normalized.slice(0, 48);
4293
- }
4294
4307
  function buildRecoveredSessionTitle(provider, providerSessionId) {
4295
4308
  if (isPendingBindingValue(providerSessionId)) {
4296
4309
  return "新会话";