@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.
- package/dist/public/assets/{AdaptiveButlerPage-DclGPzEx.js → AdaptiveButlerPage-D-gXre7Y.js} +2 -2
- package/dist/public/assets/{App-CcDXqFl1.css → App-7zrCMhE-.css} +1 -1
- package/dist/public/assets/App-Dl-mcdqy.js +30 -0
- package/dist/public/assets/{BootstrapPage-Bl21SsuW.js → BootstrapPage-B-yMdfpQ.js} +1 -1
- package/dist/public/assets/ConversationPage-DRQ5Sg_d.js +9 -0
- package/dist/public/assets/{DesktopDetachPreviewPage-uaOHVsjV.js → DesktopDetachPreviewPage-D1DMaGcy.js} +1 -1
- package/dist/public/assets/{DesktopModal-BxsogpLf.js → DesktopModal-BnfGW2gk.js} +1 -1
- package/dist/public/assets/DesktopWindowPage-2SWAi0xz.js +2 -0
- package/dist/public/assets/FileContextPanel-fbPuE9dO.js +1 -0
- package/dist/public/assets/GitSidebar-BkmesJJR.js +6 -0
- package/dist/public/assets/{MobileCreateSessionSheet-CqtmfVNo.js → MobileCreateSessionSheet-CEJcDBZJ.js} +1 -1
- package/dist/public/assets/{MobileSheet-C5IVmUsO.js → MobileSheet-rkn_CUOY.js} +1 -1
- package/dist/public/assets/{MobileTopHeaderFrame-EoBm3-X0.js → MobileTopHeaderFrame-CU0wsYSS.js} +1 -1
- package/dist/public/assets/MobileWorkspaceSwitcherHeader-idl8o1OB.js +1 -0
- package/dist/public/assets/{PluginAccessOverview-CrQiQxxZ.js → PluginAccessOverview-BBgM6tb0.js} +1 -1
- package/dist/public/assets/{PluginContainerPage-_2u-9thM.js → PluginContainerPage-D-ly3i3H.js} +1 -1
- package/dist/public/assets/{PluginDetailPage-F9cKjSCp.js → PluginDetailPage-CWAHYyyG.js} +1 -1
- package/dist/public/assets/{PluginsListPage-BOhcua_4.js → PluginsListPage-Cte3vBgR.js} +1 -1
- package/dist/public/assets/{RelayConnectEntryPage-Ck_uZLzj.js → RelayConnectEntryPage-sRJlstx9.js} +1 -1
- package/dist/public/assets/{ServerSettingsModal-ICd82a_x.js → ServerSettingsModal-BBft9KEC.js} +1 -1
- package/dist/public/assets/SessionIndexPage-CN7cEdl9.js +1 -0
- package/dist/public/assets/SettingsPage-BGT-YqG2.js +2 -0
- package/dist/public/assets/TerminalManagerPanel-6-ZJ8vGn.js +1 -0
- package/dist/public/assets/TerminalPage-CUXXQYU2.js +55 -0
- package/dist/public/assets/{TerminalRuntimeFallbackModal-DGPR_CMh.js → TerminalRuntimeFallbackModal-zc3qqMKJ.js} +1 -1
- package/dist/public/assets/ToolFilesPage-QzsZyr0F.js +1 -0
- package/dist/public/assets/ToolGitPage-CXg4ncuT.js +1 -0
- package/dist/public/assets/ToolProcessesPage-BPsOsg4w.js +1 -0
- package/dist/public/assets/ToolsHomePage-D1n4FU1s.js +1 -0
- package/dist/public/assets/WorkbenchLandingPage-BaU_dXls.js +1 -0
- package/dist/public/assets/WorkbenchLayout-DViAJhHz.js +1027 -0
- package/dist/public/assets/{WorkbenchModal-CsZeLArg.js → WorkbenchModal-DWsNm2B2.js} +1 -1
- package/dist/public/assets/WorkbenchShellRoute-BGfRqBUa.js +1 -0
- package/dist/public/assets/WorkbenchShellRoute-f2jWjHWu.css +1 -0
- package/dist/public/assets/WorkspaceDebugDetailPage-BX0zVSsI.js +1 -0
- package/dist/public/assets/WorkspaceDetailPage-Dx6JX4jx.js +1 -0
- package/dist/public/assets/WorkspaceHomePage-DQVJ042Z.js +1 -0
- package/dist/public/assets/{client-runtime-manager-BgGugw8T.js → client-runtime-manager-D9VbgJZ_.js} +1 -1
- package/dist/public/assets/host-alias-0TfFnYxR.js +1 -0
- package/dist/public/assets/index-DREvg1Yu.css +1 -0
- package/dist/public/assets/index-FOhyOpGY.js +50 -0
- package/dist/public/assets/{login-direct-candidate-resolver-ty2uOY5y.js → login-direct-candidate-resolver-17wEvjhh.js} +1 -1
- package/dist/public/assets/peer-host-config-sync-vYkmqzNz.js +1 -0
- package/dist/public/assets/{plugin-permission-copy-iK3faI3n.js → plugin-permission-copy-apDn8EWG.js} +1 -1
- package/dist/public/assets/{plugins-api-CmV7aDGA.js → plugins-api-CnZYRKoS.js} +1 -1
- package/dist/public/assets/{preferences-service-BoSmT_ny.js → preferences-service-PZlLLAWH.js} +1 -1
- package/dist/public/assets/relay-entry-DhHwflXl.js +1 -0
- package/dist/public/assets/terminal-runtime-meta-2zvacxvM.js +1 -0
- package/dist/public/assets/{useRegisteredDebugTemplates-B_vXUtSe.js → useRegisteredDebugTemplates-CJ-o4tFl.js} +1 -1
- package/dist/public/assets/workbench-navigation-aqJ1ay4M.js +1 -0
- package/dist/public/index.html +2 -2
- package/dist/server/middlewares/auth-guard.js +1 -0
- package/dist/server/middlewares/auth-guard.js.map +1 -1
- package/dist/server/modules/peer-host/host-api-proxy-service.d.ts +9 -0
- package/dist/server/modules/peer-host/host-api-proxy-service.js +174 -0
- package/dist/server/modules/peer-host/host-api-proxy-service.js.map +1 -0
- package/dist/server/modules/peer-host/host-handshake-controller.d.ts +7 -0
- package/dist/server/modules/peer-host/host-handshake-controller.js +10 -0
- package/dist/server/modules/peer-host/host-handshake-controller.js.map +1 -0
- package/dist/server/modules/peer-host/host-handshake.d.ts +15 -0
- package/dist/server/modules/peer-host/host-handshake.js +20 -0
- package/dist/server/modules/peer-host/host-handshake.js.map +1 -0
- package/dist/server/modules/peer-host/host-ws-proxy-service.d.ts +14 -0
- package/dist/server/modules/peer-host/host-ws-proxy-service.js +256 -0
- package/dist/server/modules/peer-host/host-ws-proxy-service.js.map +1 -0
- package/dist/server/modules/peer-host/peer-host-controller.d.ts +55 -0
- package/dist/server/modules/peer-host/peer-host-controller.js +62 -0
- package/dist/server/modules/peer-host/peer-host-controller.js.map +1 -0
- package/dist/server/modules/peer-host/peer-host-service.d.ts +77 -0
- package/dist/server/modules/peer-host/peer-host-service.js +529 -0
- package/dist/server/modules/peer-host/peer-host-service.js.map +1 -0
- package/dist/server/modules/sessions/codex-session-title-generator.js +18 -5
- package/dist/server/modules/sessions/codex-session-title-generator.js.map +1 -1
- package/dist/server/modules/sessions/session-history-service.d.ts +12 -1
- package/dist/server/modules/sessions/session-history-service.js +51 -38
- package/dist/server/modules/sessions/session-history-service.js.map +1 -1
- package/dist/server/modules/sessions/session-live-runtime-service.d.ts +6 -0
- package/dist/server/modules/sessions/session-live-runtime-service.js +181 -80
- package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
- package/dist/server/modules/sessions/session-title-utils.d.ts +3 -0
- package/dist/server/modules/sessions/session-title-utils.js +25 -0
- package/dist/server/modules/sessions/session-title-utils.js.map +1 -0
- package/dist/server/modules/sessions/workspace-office-mcp-config.d.ts +2 -1
- package/dist/server/modules/sessions/workspace-office-mcp-config.js +44 -3
- package/dist/server/modules/sessions/workspace-office-mcp-config.js.map +1 -1
- package/dist/server/modules/tasks/task-manager.d.ts +2 -1
- package/dist/server/modules/tasks/task-manager.js +3 -0
- package/dist/server/modules/tasks/task-manager.js.map +1 -1
- package/dist/server/modules/tasks/task-scheduler.d.ts +2 -1
- package/dist/server/modules/tasks/task-scheduler.js +21 -0
- package/dist/server/modules/tasks/task-scheduler.js.map +1 -1
- package/dist/server/modules/tasks/task-types.d.ts +5 -0
- package/dist/server/modules/tasks/task-types.js.map +1 -1
- package/dist/server/modules/workbench/workbench-controller.js +3 -2
- package/dist/server/modules/workbench/workbench-controller.js.map +1 -1
- package/dist/server/modules/workspace/affairs-library-service.d.ts +1 -0
- package/dist/server/modules/workspace/affairs-library-service.js +80 -0
- package/dist/server/modules/workspace/affairs-library-service.js.map +1 -1
- package/dist/server/routes/peer-hosts.d.ts +3 -0
- package/dist/server/routes/peer-hosts.js +18 -0
- package/dist/server/routes/peer-hosts.js.map +1 -0
- package/dist/server/routes/public.d.ts +2 -1
- package/dist/server/routes/public.js +2 -1
- package/dist/server/routes/public.js.map +1 -1
- package/dist/server/server/create-server.d.ts +4 -0
- package/dist/server/server/create-server.js +30 -2
- package/dist/server/server/create-server.js.map +1 -1
- package/dist/server/shared/http/error-handler.js +12 -0
- package/dist/server/shared/http/error-handler.js.map +1 -1
- package/dist/server/storage/repositories/peer-host-repository.d.ts +44 -0
- package/dist/server/storage/repositories/peer-host-repository.js +271 -0
- package/dist/server/storage/repositories/peer-host-repository.js.map +1 -0
- package/dist/server/storage/sqlite/client.js +81 -0
- package/dist/server/storage/sqlite/client.js.map +1 -1
- package/dist/server/storage/sqlite/schema.sql +64 -0
- package/dist/server/types/domain.d.ts +43 -0
- package/dist/server/ws/workbench-ws-hub.js +5 -14
- package/dist/server/ws/workbench-ws-hub.js.map +1 -1
- package/dist/server/ws/ws-server.d.ts +2 -1
- package/dist/server/ws/ws-server.js +5 -1
- package/dist/server/ws/ws-server.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +29 -5
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +8 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +3 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +144 -27
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
- package/package.json +1 -1
- package/dist/public/assets/App-BxX5mm9o.js +0 -30
- package/dist/public/assets/ConversationPage-CmiVCV0q.js +0 -9
- package/dist/public/assets/DesktopWindowPage-Bubfw1nC.js +0 -2
- package/dist/public/assets/FileContextPanel-DrYWcTkp.js +0 -1
- package/dist/public/assets/GitSidebar-CQsfJqun.js +0 -6
- package/dist/public/assets/MobileWorkspaceSwitcherHeader-BC8MMQs_.js +0 -1
- package/dist/public/assets/SessionIndexPage-Cox6P6dw.js +0 -1
- package/dist/public/assets/SettingsPage-BI5cM3j5.js +0 -2
- package/dist/public/assets/TerminalManagerPanel-DiVhBQhf.js +0 -1
- package/dist/public/assets/TerminalPage-DUMUO7Ng.js +0 -55
- package/dist/public/assets/ToolFilesPage-m88CAp-r.js +0 -1
- package/dist/public/assets/ToolGitPage-DCYpfTsb.js +0 -1
- package/dist/public/assets/ToolProcessesPage-Bk5ulsyq.js +0 -1
- package/dist/public/assets/ToolsHomePage-BrTwfjI7.js +0 -1
- package/dist/public/assets/WorkbenchLandingPage-q4AAmdMV.js +0 -1
- package/dist/public/assets/WorkbenchLayout-DD8b-m2G.js +0 -1027
- package/dist/public/assets/WorkbenchShellRoute-BaiW_vfb.js +0 -1
- package/dist/public/assets/WorkbenchShellRoute-CxKYZ6uF.css +0 -1
- package/dist/public/assets/WorkspaceDebugDetailPage-BcUUDEyw.js +0 -1
- package/dist/public/assets/WorkspaceDetailPage-zEZ1VARA.js +0 -1
- package/dist/public/assets/WorkspaceHomePage-CR0rqS4e.js +0 -1
- package/dist/public/assets/index-CFyk1rgJ.js +0 -50
- package/dist/public/assets/index-CrU73EIV.css +0 -1
- package/dist/public/assets/relay-entry-C8k5qsl5.js +0 -1
- package/dist/public/assets/terminal-runtime-meta-okQIDzfA.js +0 -1
- package/dist/public/assets/workbench-navigation-DoDaQR4z.js +0 -1
|
@@ -208,6 +208,7 @@ export declare class SessionLiveRuntimeService {
|
|
|
208
208
|
private readonly queueDispatchSessions;
|
|
209
209
|
private readonly queueRetryTimers;
|
|
210
210
|
private readonly pendingSendDebugTracesBySessionId;
|
|
211
|
+
private readonly runtimePersistenceQueues;
|
|
211
212
|
constructor(sessionHistoryService: SessionHistoryService, sessionMessageAttachmentService: SessionMessageAttachmentService, workspaceService: WorkspaceService, sessionChangedFileService: SessionChangedFileService, sessionBindingRepository: SessionBindingRepository, authUserRepository: AuthUserRepository, sessionSendQueueRepository: SessionSendQueueRepository, sessionIndexRepository: SessionIndexRepository, sessionStateRepository: SessionStateRepository, sessionStatusSnapshotRepository: SessionStatusSnapshotRepository, sessionProviderConfigService: SessionProviderConfigService, config: HostConfig, sessionActivityAuthorityService?: SessionActivityAuthorityService, openCliSessionPromptService?: OpenCliSessionPromptService | null, workspaceSessionRuntimeContextService?: Pick<WorkspaceSessionRuntimeContextService, "prepareWorkspaceInstructionBundle"> | null);
|
|
212
213
|
startLiveSession(input: StartLiveSessionInput): Promise<LiveMessageAcceptedResult>;
|
|
213
214
|
sendLiveMessage(input: SendLiveMessageInput): Promise<LiveMessageAcceptedResult>;
|
|
@@ -253,6 +254,7 @@ export declare class SessionLiveRuntimeService {
|
|
|
253
254
|
private resolveQueueDispatchSession;
|
|
254
255
|
private launchRuntimeRun;
|
|
255
256
|
private attachRuntimePersistence;
|
|
257
|
+
private enqueueRuntimeEventPersistence;
|
|
256
258
|
private createRuntimeBackedSession;
|
|
257
259
|
private prepareWorkspaceRuntimeContext;
|
|
258
260
|
private resolveEffectiveRuntimeHomeDir;
|
|
@@ -268,6 +270,9 @@ export declare class SessionLiveRuntimeService {
|
|
|
268
270
|
private resolveCodexRuntimeRequestRawStoreRef;
|
|
269
271
|
private buildBindingSnapshot;
|
|
270
272
|
private persistRuntimeEvent;
|
|
273
|
+
private runRuntimeSqliteRead;
|
|
274
|
+
private runRuntimeSqliteWrite;
|
|
275
|
+
private runRuntimeSqliteOperation;
|
|
271
276
|
private emitTerminalStateEvent;
|
|
272
277
|
private reconcileTerminalRuntimeSnapshot;
|
|
273
278
|
private forceInterruptInactiveSession;
|
|
@@ -282,6 +287,7 @@ export declare class SessionLiveRuntimeService {
|
|
|
282
287
|
private findAcceptedUserMessage;
|
|
283
288
|
private resolveNextUserSequence;
|
|
284
289
|
private waitForResolvedStartBinding;
|
|
290
|
+
private requestCodexTitleGenerationAfterStartBinding;
|
|
285
291
|
private persistMessageAttachments;
|
|
286
292
|
private refreshSyntheticSessionTitle;
|
|
287
293
|
private mapRuntimeEventToEnvelope;
|
|
@@ -9,12 +9,14 @@ import { logPermissionDebug } from "../../shared/utils/permission-debug-log.js";
|
|
|
9
9
|
import { nowIso } from "../../shared/utils/time.js";
|
|
10
10
|
import { SessionActivityAuthorityService } from "./session-activity-authority-service.js";
|
|
11
11
|
import { createProviderCapabilityBlockedError } from "../provider/provider-disabled.js";
|
|
12
|
+
import { buildSessionTitleFromContent } from "./session-title-utils.js";
|
|
12
13
|
import { SessionPermissionRequestService } from "./session-permission-request-service.js";
|
|
13
14
|
import { appendSessionProviderErrorContext, mapSessionProviderError } from "./session-provider-error-mapper.js";
|
|
14
15
|
import { buildClaudeCompatibleHookBridgeUrl, buildClaudeCompatibleRawStoreRef, buildClaudeCompatibleSessionTitle, findClaudeCompatibleSessionFile, isClaudeCompatibleProvider } from "./claude-compatible-provider-registry.js";
|
|
15
16
|
import { ClaudeRuntimeHelperAdapter } from "./claude-runtime-helper-client.js";
|
|
16
17
|
import { CodexAppServerHelperClient } from "./codex-app-server-helper-client.js";
|
|
17
18
|
const OPENCODE_ORDER_DEBUG_ENABLED = /^(1|true|yes)$/i.test(process.env.CODINGNS_OPENCODE_ORDER_DEBUG?.trim() ?? "");
|
|
19
|
+
const RUNTIME_EVENT_SQLITE_BUSY_RETRY_DELAYS_MS = [100, 250, 500, 1_000, 1_500, 2_000];
|
|
18
20
|
const RUNTIME_START_BINDING_WAIT_TIMEOUT_MS = 10_000;
|
|
19
21
|
const START_BINDING_POLL_INTERVAL_MS = 50;
|
|
20
22
|
const EXTERNAL_RUNTIME_INTERRUPT_SUPPRESSION_MS = 30_000;
|
|
@@ -48,6 +50,7 @@ export class SessionLiveRuntimeService {
|
|
|
48
50
|
queueDispatchSessions = new Set();
|
|
49
51
|
queueRetryTimers = new Map();
|
|
50
52
|
pendingSendDebugTracesBySessionId = new Map();
|
|
53
|
+
runtimePersistenceQueues = new Map();
|
|
51
54
|
constructor(sessionHistoryService, sessionMessageAttachmentService, workspaceService, sessionChangedFileService, sessionBindingRepository, authUserRepository, sessionSendQueueRepository, sessionIndexRepository, sessionStateRepository, sessionStatusSnapshotRepository, sessionProviderConfigService, config, sessionActivityAuthorityService = new SessionActivityAuthorityService(), openCliSessionPromptService = null, workspaceSessionRuntimeContextService = null) {
|
|
52
55
|
this.sessionHistoryService = sessionHistoryService;
|
|
53
56
|
this.sessionMessageAttachmentService = sessionMessageAttachmentService;
|
|
@@ -178,13 +181,20 @@ export class SessionLiveRuntimeService {
|
|
|
178
181
|
// 先把基础记录建出来,再回放 runtime 缓存事件,避免超快启动时出现
|
|
179
182
|
// “事件先到、索引还没落库”的竞态窗口。
|
|
180
183
|
this.attachRuntimePersistence(handle, sessionId, workspace.id, input.userId);
|
|
181
|
-
const startBindingTask = this.waitForResolvedStartBinding(sessionId, workspace.id, input.provider, handle)
|
|
184
|
+
const startBindingTask = this.waitForResolvedStartBinding(sessionId, workspace.id, input.provider, handle);
|
|
185
|
+
if (input.provider === "codex") {
|
|
186
|
+
void this.requestCodexTitleGenerationAfterStartBinding(sessionId, input.content, startBindingTask)
|
|
187
|
+
.catch(() => {
|
|
188
|
+
return;
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
const safeStartBindingTask = startBindingTask.catch(() => {
|
|
182
192
|
return;
|
|
183
193
|
});
|
|
184
194
|
if (shouldAwaitStartBindingBeforeAcceptedUserLookup(input.provider)) {
|
|
185
195
|
const bindingWaitStartedAtMs = performance.now();
|
|
186
196
|
await Promise.race([
|
|
187
|
-
|
|
197
|
+
safeStartBindingTask,
|
|
188
198
|
waitForAcceptedUserLookupWindow()
|
|
189
199
|
]);
|
|
190
200
|
this.logSendDebugStep(debugTrace, "binding_wait", bindingWaitStartedAtMs, {
|
|
@@ -201,7 +211,7 @@ export class SessionLiveRuntimeService {
|
|
|
201
211
|
matched: Boolean(acceptedMessage)
|
|
202
212
|
});
|
|
203
213
|
if (!shouldAwaitStartBindingBeforeAcceptedUserLookup(input.provider)) {
|
|
204
|
-
void
|
|
214
|
+
void safeStartBindingTask;
|
|
205
215
|
}
|
|
206
216
|
const acceptedAt = acceptedMessage?.timestamp ?? requestStartedAt;
|
|
207
217
|
const boundAttachments = this.sessionMessageAttachmentService.bindClientRequestToMessage(sessionId, input.clientRequestId, acceptedMessage?.messageId ?? null);
|
|
@@ -1466,9 +1476,24 @@ export class SessionLiveRuntimeService {
|
|
|
1466
1476
|
}
|
|
1467
1477
|
attachRuntimePersistence(handle, sessionId, workspaceId, userId) {
|
|
1468
1478
|
handle.attach(async (event) => {
|
|
1469
|
-
await this.
|
|
1479
|
+
await this.enqueueRuntimeEventPersistence(sessionId, workspaceId, userId, event);
|
|
1470
1480
|
});
|
|
1471
1481
|
}
|
|
1482
|
+
enqueueRuntimeEventPersistence(sessionId, workspaceId, userId, event) {
|
|
1483
|
+
const previous = this.runtimePersistenceQueues.get(sessionId) ?? Promise.resolve();
|
|
1484
|
+
const task = previous
|
|
1485
|
+
.catch(() => {
|
|
1486
|
+
return;
|
|
1487
|
+
})
|
|
1488
|
+
.then(() => this.persistRuntimeEvent(sessionId, workspaceId, userId, event));
|
|
1489
|
+
const queuedTask = task.finally(() => {
|
|
1490
|
+
if (this.runtimePersistenceQueues.get(sessionId) === queuedTask) {
|
|
1491
|
+
this.runtimePersistenceQueues.delete(sessionId);
|
|
1492
|
+
}
|
|
1493
|
+
});
|
|
1494
|
+
this.runtimePersistenceQueues.set(sessionId, queuedTask);
|
|
1495
|
+
return task;
|
|
1496
|
+
}
|
|
1472
1497
|
createRuntimeBackedSession(input) {
|
|
1473
1498
|
this.upsertRuntimeBackedSessionRecords(input);
|
|
1474
1499
|
}
|
|
@@ -1547,7 +1572,7 @@ export class SessionLiveRuntimeService {
|
|
|
1547
1572
|
sessionVisibility: currentIndex?.sessionVisibility ?? input.sessionVisibility,
|
|
1548
1573
|
isSubagent: currentIndex?.isSubagent ?? false,
|
|
1549
1574
|
subagentLabel: currentIndex?.subagentLabel ?? null,
|
|
1550
|
-
title: currentIndex?.title?.trim() ||
|
|
1575
|
+
title: currentIndex?.title?.trim() || buildSessionTitleFromContent(input.initialContent, "继续对话"),
|
|
1551
1576
|
messageCount: currentIndex?.messageCount ?? 0,
|
|
1552
1577
|
isArchived: currentIndex?.isArchived ?? false,
|
|
1553
1578
|
lastMessageAt: currentIndex?.lastMessageAt ?? input.snapshot.lastEventAt,
|
|
@@ -1692,103 +1717,121 @@ export class SessionLiveRuntimeService {
|
|
|
1692
1717
|
}
|
|
1693
1718
|
async persistRuntimeEvent(sessionId, workspaceId, userId, event) {
|
|
1694
1719
|
this.observePendingSendDebugTraceEvent(sessionId, event);
|
|
1695
|
-
this.
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1720
|
+
await this.runRuntimeSqliteWrite(sessionId, "persistSessionBinding", () => {
|
|
1721
|
+
this.sessionHistoryService.persistSessionBinding(sessionId, workspaceId, {
|
|
1722
|
+
provider: event.provider,
|
|
1723
|
+
providerSessionId: event.providerSessionId,
|
|
1724
|
+
rawStoreRef: event.rawStoreRef,
|
|
1725
|
+
userId
|
|
1726
|
+
});
|
|
1700
1727
|
});
|
|
1701
|
-
const currentState = this.sessionStateRepository.findBySessionAndUser(sessionId, userId);
|
|
1728
|
+
const currentState = await this.runRuntimeSqliteRead(sessionId, "findSessionState", () => this.sessionStateRepository.findBySessionAndUser(sessionId, userId));
|
|
1702
1729
|
const currentRunningState = currentState?.runningState ?? null;
|
|
1703
|
-
const
|
|
1730
|
+
const shouldPreserveTerminalStatusEvent = isTerminalSessionRunningState(currentRunningState);
|
|
1704
1731
|
if (event.type === "message") {
|
|
1705
1732
|
this.runtimeMessageSeenSessions.add(sessionId);
|
|
1706
1733
|
this.runtimeHistoryFallbackSentSessions.delete(sessionId);
|
|
1707
1734
|
const workspace = this.workspaceService.getWorkspaceOrThrow(workspaceId);
|
|
1708
|
-
await this.
|
|
1709
|
-
return;
|
|
1710
|
-
});
|
|
1711
|
-
const existing = this.sessionIndexRepository.findIndexRecordBySessionId(sessionId);
|
|
1735
|
+
const existing = await this.runRuntimeSqliteRead(sessionId, "findSessionIndex", () => this.sessionIndexRepository.findIndexRecordBySessionId(sessionId));
|
|
1712
1736
|
if (existing) {
|
|
1713
|
-
this.
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1737
|
+
await this.runRuntimeSqliteWrite(sessionId, "upsertSessionIndex", () => {
|
|
1738
|
+
this.sessionIndexRepository.upsert({
|
|
1739
|
+
...existing,
|
|
1740
|
+
messageCount: existing.messageCount + 1,
|
|
1741
|
+
lastMessageAt: event.message.timestamp,
|
|
1742
|
+
updatedAt: event.message.timestamp
|
|
1743
|
+
});
|
|
1718
1744
|
});
|
|
1719
1745
|
}
|
|
1720
|
-
this.
|
|
1721
|
-
|
|
1722
|
-
sessionId,
|
|
1723
|
-
userId,
|
|
1724
|
-
runningState: shouldPreserveTerminalState ? currentRunningState : "running",
|
|
1725
|
-
activitySource: "runtime",
|
|
1726
|
-
favorite: currentState?.favorite ?? false,
|
|
1727
|
-
lastEventAt: event.message.timestamp,
|
|
1728
|
-
completedAt: shouldPreserveTerminalState ? currentState?.completedAt ?? null : null,
|
|
1729
|
-
lastSeenAt: currentState?.lastSeenAt ?? null,
|
|
1730
|
-
updatedAt: nowIso()
|
|
1746
|
+
await this.runRuntimeSqliteWrite(sessionId, "recordChangedFiles", () => {
|
|
1747
|
+
this.sessionChangedFileService.recordMessages(sessionId, workspaceId, workspace.path, [event.message]);
|
|
1731
1748
|
});
|
|
1732
|
-
this.
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1749
|
+
await this.runRuntimeSqliteWrite(sessionId, "upsertSessionState", () => {
|
|
1750
|
+
this.sessionStateRepository.upsert({
|
|
1751
|
+
sessionId,
|
|
1752
|
+
userId,
|
|
1753
|
+
runningState: "running",
|
|
1754
|
+
activitySource: "runtime",
|
|
1755
|
+
favorite: currentState?.favorite ?? false,
|
|
1756
|
+
lastEventAt: event.message.timestamp,
|
|
1757
|
+
completedAt: null,
|
|
1758
|
+
lastSeenAt: currentState?.lastSeenAt ?? null,
|
|
1759
|
+
updatedAt: nowIso()
|
|
1760
|
+
});
|
|
1761
|
+
});
|
|
1762
|
+
const currentSnapshot = await this.runRuntimeSqliteRead(sessionId, "findStatusSnapshot", () => this.sessionStatusSnapshotRepository.findBySessionId(sessionId));
|
|
1763
|
+
await this.runRuntimeSqliteWrite(sessionId, "upsertStatusSnapshot", () => {
|
|
1764
|
+
this.upsertSnapshot(sessionId, {
|
|
1765
|
+
syncStatus: "idle",
|
|
1766
|
+
syncCursor: currentSnapshot?.syncCursor ?? null,
|
|
1767
|
+
lastSyncAt: event.message.timestamp,
|
|
1768
|
+
lastErrorCode: null,
|
|
1769
|
+
lastErrorDetail: null,
|
|
1770
|
+
resumedAt: currentSnapshot?.resumedAt ?? null
|
|
1771
|
+
});
|
|
1739
1772
|
});
|
|
1740
1773
|
return;
|
|
1741
1774
|
}
|
|
1742
|
-
if (
|
|
1743
|
-
this.
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1775
|
+
if (shouldPreserveTerminalStatusEvent) {
|
|
1776
|
+
await this.runRuntimeSqliteWrite(sessionId, "upsertTerminalPreservedState", () => {
|
|
1777
|
+
this.sessionStateRepository.upsert({
|
|
1778
|
+
sessionId,
|
|
1779
|
+
userId,
|
|
1780
|
+
runningState: currentRunningState,
|
|
1781
|
+
activitySource: "runtime",
|
|
1782
|
+
favorite: currentState?.favorite ?? false,
|
|
1783
|
+
lastEventAt: event.timestamp,
|
|
1784
|
+
completedAt: currentState?.completedAt ?? null,
|
|
1785
|
+
lastSeenAt: currentState?.lastSeenAt ?? null,
|
|
1786
|
+
updatedAt: nowIso()
|
|
1787
|
+
});
|
|
1753
1788
|
});
|
|
1754
|
-
this.
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1789
|
+
const currentSnapshot = await this.runRuntimeSqliteRead(sessionId, "findStatusSnapshot", () => this.sessionStatusSnapshotRepository.findBySessionId(sessionId));
|
|
1790
|
+
await this.runRuntimeSqliteWrite(sessionId, "upsertTerminalPreservedSnapshot", () => {
|
|
1791
|
+
this.upsertSnapshot(sessionId, {
|
|
1792
|
+
syncStatus: "idle",
|
|
1793
|
+
syncCursor: currentSnapshot?.syncCursor ?? null,
|
|
1794
|
+
lastSyncAt: event.timestamp,
|
|
1795
|
+
lastErrorCode: null,
|
|
1796
|
+
lastErrorDetail: null,
|
|
1797
|
+
resumedAt: currentSnapshot?.resumedAt ?? null
|
|
1798
|
+
});
|
|
1761
1799
|
});
|
|
1762
1800
|
await this.maybeEmitRuntimeHistoryFallback(sessionId, event);
|
|
1763
1801
|
return;
|
|
1764
1802
|
}
|
|
1765
1803
|
const completedAt = event.status === "completed" || event.status === "interrupted" || event.status === "failed"
|
|
1766
1804
|
? event.timestamp
|
|
1767
|
-
: this.sessionStateRepository.findBySessionAndUser(sessionId, userId)?.completedAt ?? null;
|
|
1805
|
+
: (await this.runRuntimeSqliteRead(sessionId, "findCompletedState", () => this.sessionStateRepository.findBySessionAndUser(sessionId, userId)))?.completedAt ?? null;
|
|
1768
1806
|
if (completedAt) {
|
|
1769
1807
|
await this.sessionHistoryService.syncSessionTitle(sessionId).catch(() => {
|
|
1770
1808
|
return;
|
|
1771
1809
|
});
|
|
1772
1810
|
}
|
|
1773
|
-
this.
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1811
|
+
await this.runRuntimeSqliteWrite(sessionId, "upsertRuntimeState", () => {
|
|
1812
|
+
this.sessionStateRepository.upsert({
|
|
1813
|
+
sessionId,
|
|
1814
|
+
userId,
|
|
1815
|
+
runningState: toStoredRunningState(event.status),
|
|
1816
|
+
activitySource: "runtime",
|
|
1817
|
+
favorite: currentState?.favorite ?? false,
|
|
1818
|
+
lastEventAt: event.timestamp,
|
|
1819
|
+
completedAt,
|
|
1820
|
+
lastSeenAt: currentState?.lastSeenAt ?? null,
|
|
1821
|
+
updatedAt: nowIso()
|
|
1822
|
+
});
|
|
1783
1823
|
});
|
|
1784
1824
|
this.sessionActivityAuthorityService.observe(createRuntimeEventObservation(sessionId, event, this.providerRuntimeService.getSnapshot(sessionId)?.startedAt ?? null));
|
|
1785
|
-
this.
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1825
|
+
const currentSnapshot = await this.runRuntimeSqliteRead(sessionId, "findStatusSnapshot", () => this.sessionStatusSnapshotRepository.findBySessionId(sessionId));
|
|
1826
|
+
await this.runRuntimeSqliteWrite(sessionId, "upsertRuntimeSnapshot", () => {
|
|
1827
|
+
this.upsertSnapshot(sessionId, {
|
|
1828
|
+
syncStatus: event.type === "error" ? "error" : "idle",
|
|
1829
|
+
syncCursor: currentSnapshot?.syncCursor ?? null,
|
|
1830
|
+
lastSyncAt: event.timestamp,
|
|
1831
|
+
lastErrorCode: event.type === "error" ? event.errorCode : null,
|
|
1832
|
+
lastErrorDetail: event.type === "error" ? (event.detail ?? "runtime failed") : null,
|
|
1833
|
+
resumedAt: currentSnapshot?.resumedAt ?? null
|
|
1834
|
+
});
|
|
1792
1835
|
});
|
|
1793
1836
|
await this.maybeEmitRuntimeHistoryFallback(sessionId, event);
|
|
1794
1837
|
if (isTerminalRuntimeEventStatus(event.status)) {
|
|
@@ -1804,6 +1847,36 @@ export class SessionLiveRuntimeService {
|
|
|
1804
1847
|
void this.dispatchNextQueuedMessage(sessionId);
|
|
1805
1848
|
}
|
|
1806
1849
|
}
|
|
1850
|
+
async runRuntimeSqliteRead(sessionId, scope, operation) {
|
|
1851
|
+
return await this.runRuntimeSqliteOperation(sessionId, scope, operation);
|
|
1852
|
+
}
|
|
1853
|
+
async runRuntimeSqliteWrite(sessionId, scope, operation) {
|
|
1854
|
+
await this.runRuntimeSqliteOperation(sessionId, scope, operation);
|
|
1855
|
+
}
|
|
1856
|
+
async runRuntimeSqliteOperation(sessionId, scope, operation) {
|
|
1857
|
+
let attempt = 0;
|
|
1858
|
+
while (true) {
|
|
1859
|
+
try {
|
|
1860
|
+
return operation();
|
|
1861
|
+
}
|
|
1862
|
+
catch (error) {
|
|
1863
|
+
if (!isSqliteBusyError(error) || attempt >= RUNTIME_EVENT_SQLITE_BUSY_RETRY_DELAYS_MS.length) {
|
|
1864
|
+
throw error;
|
|
1865
|
+
}
|
|
1866
|
+
const delayMs = RUNTIME_EVENT_SQLITE_BUSY_RETRY_DELAYS_MS[attempt];
|
|
1867
|
+
attempt += 1;
|
|
1868
|
+
logPerformance("session.runtime_event.sqlite_busy_retry", delayMs, {
|
|
1869
|
+
sessionId,
|
|
1870
|
+
scope,
|
|
1871
|
+
attempt
|
|
1872
|
+
}, {
|
|
1873
|
+
thresholdMs: 0,
|
|
1874
|
+
force: true
|
|
1875
|
+
});
|
|
1876
|
+
await delay(delayMs);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1807
1880
|
async emitTerminalStateEvent(event) {
|
|
1808
1881
|
for (const listener of this.terminalStateListeners) {
|
|
1809
1882
|
await listener(event);
|
|
@@ -2085,6 +2158,25 @@ export class SessionLiveRuntimeService {
|
|
|
2085
2158
|
await waitForRuntimeBindingPoll();
|
|
2086
2159
|
}
|
|
2087
2160
|
}
|
|
2161
|
+
async requestCodexTitleGenerationAfterStartBinding(sessionId, firstUserMessage, startBindingTask) {
|
|
2162
|
+
const normalizedFirstUserMessage = firstUserMessage.trim();
|
|
2163
|
+
if (!normalizedFirstUserMessage) {
|
|
2164
|
+
return;
|
|
2165
|
+
}
|
|
2166
|
+
try {
|
|
2167
|
+
await startBindingTask;
|
|
2168
|
+
}
|
|
2169
|
+
catch {
|
|
2170
|
+
return;
|
|
2171
|
+
}
|
|
2172
|
+
const binding = this.sessionBindingRepository.findBySessionId(sessionId);
|
|
2173
|
+
if (!binding
|
|
2174
|
+
|| binding.provider !== "codex"
|
|
2175
|
+
|| !hasResolvedRuntimeBinding(binding.providerSessionId, binding.rawStoreRef)) {
|
|
2176
|
+
return;
|
|
2177
|
+
}
|
|
2178
|
+
this.sessionHistoryService.requestCodexTitleGenerationForNewSession(sessionId, normalizedFirstUserMessage);
|
|
2179
|
+
}
|
|
2088
2180
|
persistMessageAttachments(sessionId, clientRequestId, attachments) {
|
|
2089
2181
|
if (!clientRequestId || attachments.length === 0) {
|
|
2090
2182
|
return {
|
|
@@ -2422,10 +2514,6 @@ function mapClaudeHookToRuntimeUpdate(hookEventName, payload, timestamp) {
|
|
|
2422
2514
|
}
|
|
2423
2515
|
return null;
|
|
2424
2516
|
}
|
|
2425
|
-
function buildSessionTitle(content) {
|
|
2426
|
-
const title = content.trim().replace(/\s+/g, " ");
|
|
2427
|
-
return title.slice(0, 48) || "继续对话";
|
|
2428
|
-
}
|
|
2429
2517
|
function resolveRuntimeSessionTitle(provider, existingTitle, content, parentTitle, forkMethod, forkSourceType) {
|
|
2430
2518
|
const normalizedExistingTitle = existingTitle.trim();
|
|
2431
2519
|
const normalizedParentTitle = parentTitle?.trim() ?? "";
|
|
@@ -2435,7 +2523,7 @@ function resolveRuntimeSessionTitle(provider, existingTitle, content, parentTitl
|
|
|
2435
2523
|
(!isForkSession || normalizedExistingTitle !== normalizedParentTitle)) {
|
|
2436
2524
|
return null;
|
|
2437
2525
|
}
|
|
2438
|
-
return
|
|
2526
|
+
return buildSessionTitleFromContent(content, "继续对话");
|
|
2439
2527
|
}
|
|
2440
2528
|
function isSyntheticRuntimeSessionTitle(provider, title) {
|
|
2441
2529
|
if (provider !== "codex") {
|
|
@@ -2737,6 +2825,19 @@ function normalizeOptionalBindingValue(value) {
|
|
|
2737
2825
|
const normalized = value?.trim();
|
|
2738
2826
|
return normalized && normalized.length > 0 ? normalized : null;
|
|
2739
2827
|
}
|
|
2828
|
+
function isSqliteBusyError(error) {
|
|
2829
|
+
if (!error || typeof error !== "object") {
|
|
2830
|
+
return false;
|
|
2831
|
+
}
|
|
2832
|
+
const sqliteCode = "code" in error ? error.code : null;
|
|
2833
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2834
|
+
return sqliteCode === "SQLITE_BUSY" || message.includes("database is locked");
|
|
2835
|
+
}
|
|
2836
|
+
async function delay(ms) {
|
|
2837
|
+
await new Promise((resolve) => {
|
|
2838
|
+
setTimeout(resolve, ms);
|
|
2839
|
+
});
|
|
2840
|
+
}
|
|
2740
2841
|
function logOpenCodeOrderEnvelopeDebug(scope, detail) {
|
|
2741
2842
|
if (!OPENCODE_ORDER_DEBUG_ENABLED) {
|
|
2742
2843
|
return;
|