@jingyi0605/codingns 0.6.0 → 0.6.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 (170) hide show
  1. package/bin/codingns.mjs +15 -2
  2. package/dist/public/assets/{AdaptiveButlerPage-uFwDdN-F.js → AdaptiveButlerPage-Dw72U3hG.js} +3 -3
  3. package/dist/public/assets/{App-BZvapsi8.js → App-Dsf3ooXU.js} +3 -3
  4. package/dist/public/assets/{BootstrapPage-gHSoa4JN.js → BootstrapPage-CE0m1qSR.js} +1 -1
  5. package/dist/public/assets/ConversationPage-8wOY7SX-.js +4 -0
  6. package/dist/public/assets/{DesktopDetachPreviewPage-4eMRxiBW.js → DesktopDetachPreviewPage-Dxarr_Wf.js} +1 -1
  7. package/dist/public/assets/DesktopWindowPage-VytPwJ4c.js +2 -0
  8. package/dist/public/assets/FileContextPanel-DwFzLsOp.js +1 -0
  9. package/dist/public/assets/GitSidebar-CH6WqTrM.js +6 -0
  10. package/dist/public/assets/MobileCreateSessionSheet-DcxKM00P.js +1 -0
  11. package/dist/public/assets/{MobileTopHeaderFrame-Bwv8Ovm_.js → MobileTopHeaderFrame-C5rIKQT6.js} +1 -1
  12. package/dist/public/assets/MobileWorkspaceSwitcherHeader-CfUnHgv_.js +1 -0
  13. package/dist/public/assets/{RelayConnectEntryPage-D_4YL-YH.js → RelayConnectEntryPage-CgMvVZwa.js} +1 -1
  14. package/dist/public/assets/{ServerSettingsModal-CMSm3BZU.js → ServerSettingsModal-CFul__z1.js} +1 -1
  15. package/dist/public/assets/SessionIndexPage-B-tRhBXC.js +1 -0
  16. package/dist/public/assets/SettingsPage-C9LGxSQZ.js +1 -0
  17. package/dist/public/assets/TerminalManagerPanel-BbORd-ee.js +1 -0
  18. package/dist/public/assets/{TerminalPage-DaooFaJ4.js → TerminalPage-DWHv6mlu.js} +1 -1
  19. package/dist/public/assets/TerminalRuntimeFallbackModal-B29YxbQe.js +1 -0
  20. package/dist/public/assets/{ToolFilesPage-CGxBvYG0.js → ToolFilesPage-Dx9cv9hu.js} +1 -1
  21. package/dist/public/assets/ToolGitPage-D7H3vAia.js +1 -0
  22. package/dist/public/assets/ToolProcessesPage-PqQWxsy-.js +1 -0
  23. package/dist/public/assets/ToolsHomePage-CX05Pe_4.js +1 -0
  24. package/dist/public/assets/WorkbenchLandingPage-CchkAC75.js +1 -0
  25. package/dist/public/assets/WorkbenchLayout-pOZvEqp7.js +3 -0
  26. package/dist/public/assets/{WorkbenchModal-0tPIIhca.js → WorkbenchModal-ColqvV6a.js} +1 -1
  27. package/dist/public/assets/WorkbenchShellRoute-C0_h4lP6.js +1 -0
  28. package/dist/public/assets/WorkbenchShellRoute-RGZpA0_J.css +1 -0
  29. package/dist/public/assets/WorkspaceDebugDetailPage-Deqy2_pO.js +1 -0
  30. package/dist/public/assets/WorkspaceDetailPage-Cvf-ZdlB.js +1 -0
  31. package/dist/public/assets/WorkspaceHomePage-Dsyvqyk1.js +1 -0
  32. package/dist/public/assets/{client-runtime-manager-BZpL17fc.js → client-runtime-manager-DROQJ9v3.js} +1 -1
  33. package/dist/public/assets/{file-tree-icon-Db5LXC8h.js → file-tree-icon-Bp3Ntt7u.js} +1 -1
  34. package/dist/public/assets/index-B84Po2NA.css +1 -0
  35. package/dist/public/assets/index-C-0oeG_5.js +42 -0
  36. package/dist/public/assets/legna-code-6TqgZ4Ls.png +0 -0
  37. package/dist/public/assets/{login-direct-candidate-resolver-1mxe_Oh8.js → login-direct-candidate-resolver-DotM530R.js} +1 -1
  38. package/dist/public/assets/model-switch-api-Bh9nYslz.js +1 -0
  39. package/dist/public/assets/{preferences-service-DWnzl5a0.js → preferences-service-BG6GKG29.js} +1 -1
  40. package/dist/public/assets/{relay-entry-C5_Iay0I.js → relay-entry-pmr-c42O.js} +1 -1
  41. package/dist/public/assets/session-runtime-machine-YN84QBlr.js +21 -0
  42. package/dist/public/assets/{terminal-runtime-meta-cdtWVfCm.js → terminal-runtime-meta-8_uRZf7h.js} +1 -1
  43. package/dist/public/assets/useRegisteredDebugTemplates-DWX7LXQu.js +1 -0
  44. package/dist/public/index.html +2 -2
  45. package/dist/server/config/env.d.ts +2 -0
  46. package/dist/server/config/env.js +7 -0
  47. package/dist/server/config/env.js.map +1 -1
  48. package/dist/server/modules/model-switch/cc-switch-adapter.d.ts +7 -0
  49. package/dist/server/modules/model-switch/cc-switch-adapter.js +17 -0
  50. package/dist/server/modules/model-switch/cc-switch-adapter.js.map +1 -1
  51. package/dist/server/modules/parallel-sessions/parallel-session-controller.d.ts +4 -0
  52. package/dist/server/modules/parallel-sessions/parallel-session-controller.js +7 -0
  53. package/dist/server/modules/parallel-sessions/parallel-session-controller.js.map +1 -1
  54. package/dist/server/modules/parallel-sessions/parallel-session-group-service.d.ts +6 -1
  55. package/dist/server/modules/parallel-sessions/parallel-session-group-service.js +36 -2
  56. package/dist/server/modules/parallel-sessions/parallel-session-group-service.js.map +1 -1
  57. package/dist/server/modules/provider/opencode-model-options.d.ts +1 -0
  58. package/dist/server/modules/provider/opencode-model-options.js +54 -12
  59. package/dist/server/modules/provider/opencode-model-options.js.map +1 -1
  60. package/dist/server/modules/provider/provider-controller.d.ts +6 -1
  61. package/dist/server/modules/provider/provider-controller.js +24 -2
  62. package/dist/server/modules/provider/provider-controller.js.map +1 -1
  63. package/dist/server/modules/provider/provider-discovery-helper-client.d.ts +2 -0
  64. package/dist/server/modules/provider/provider-discovery-helper-client.js.map +1 -1
  65. package/dist/server/modules/provider/provider-discovery-helper-process.js +1 -1
  66. package/dist/server/modules/provider/provider-discovery-helper-process.js.map +1 -1
  67. package/dist/server/modules/provider/provider-discovery-runtime.js +5 -1
  68. package/dist/server/modules/provider/provider-discovery-runtime.js.map +1 -1
  69. package/dist/server/modules/sessions/claude-runtime-helper-client.d.ts +1 -0
  70. package/dist/server/modules/sessions/claude-runtime-helper-client.js +14 -0
  71. package/dist/server/modules/sessions/claude-runtime-helper-client.js.map +1 -1
  72. package/dist/server/modules/sessions/codex-app-server-helper-client.d.ts +1 -0
  73. package/dist/server/modules/sessions/codex-app-server-helper-client.js +10 -0
  74. package/dist/server/modules/sessions/codex-app-server-helper-client.js.map +1 -1
  75. package/dist/server/modules/sessions/provider-session-delete-cli.js +2 -0
  76. package/dist/server/modules/sessions/provider-session-delete-cli.js.map +1 -1
  77. package/dist/server/modules/sessions/session-controller.d.ts +7 -0
  78. package/dist/server/modules/sessions/session-controller.js +22 -0
  79. package/dist/server/modules/sessions/session-controller.js.map +1 -1
  80. package/dist/server/modules/sessions/session-history-service.d.ts +12 -2
  81. package/dist/server/modules/sessions/session-history-service.js +284 -16
  82. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  83. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +15 -2
  84. package/dist/server/modules/sessions/session-live-runtime-service.js +265 -50
  85. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  86. package/dist/server/modules/sessions/session-message-attachment-service.js +2 -2
  87. package/dist/server/modules/sessions/session-message-attachment-service.js.map +1 -1
  88. package/dist/server/modules/sessions/session-provider-config-service.d.ts +66 -0
  89. package/dist/server/modules/sessions/session-provider-config-service.js +821 -0
  90. package/dist/server/modules/sessions/session-provider-config-service.js.map +1 -0
  91. package/dist/server/modules/sessions/session-provider-error-mapper.d.ts +2 -0
  92. package/dist/server/modules/sessions/session-provider-error-mapper.js +42 -0
  93. package/dist/server/modules/sessions/session-provider-error-mapper.js.map +1 -1
  94. package/dist/server/server/create-server.js +11 -8
  95. package/dist/server/server/create-server.js.map +1 -1
  96. package/dist/server/storage/repositories/session-binding-repository.js +44 -5
  97. package/dist/server/storage/repositories/session-binding-repository.js.map +1 -1
  98. package/dist/server/storage/repositories/session-index-repository.js +6 -0
  99. package/dist/server/storage/repositories/session-index-repository.js.map +1 -1
  100. package/dist/server/storage/sqlite/client.js +19 -0
  101. package/dist/server/storage/sqlite/client.js.map +1 -1
  102. package/dist/server/storage/sqlite/schema.sql +5 -0
  103. package/dist/server/types/domain.d.ts +6 -0
  104. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.d.ts +5 -2
  105. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js +40 -8
  106. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js.map +1 -1
  107. package/node_modules/@codingns/session-sync-core/dist/index.d.ts +2 -0
  108. package/node_modules/@codingns/session-sync-core/dist/index.js +2 -0
  109. package/node_modules/@codingns/session-sync-core/dist/index.js.map +1 -1
  110. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +10 -1
  111. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +110 -35
  112. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
  113. package/node_modules/@codingns/session-sync-core/dist/providers/claude-session-store.d.ts +11 -0
  114. package/node_modules/@codingns/session-sync-core/dist/providers/claude-session-store.js +105 -0
  115. package/node_modules/@codingns/session-sync-core/dist/providers/claude-session-store.js.map +1 -0
  116. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +131 -39
  117. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -1
  118. package/node_modules/@codingns/session-sync-core/dist/providers/legna-code.d.ts +9 -0
  119. package/node_modules/@codingns/session-sync-core/dist/providers/legna-code.js +17 -0
  120. package/node_modules/@codingns/session-sync-core/dist/providers/legna-code.js.map +1 -0
  121. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.d.ts +8 -1
  122. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js +19 -6
  123. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js.map +1 -1
  124. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +1 -0
  125. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +13 -8
  126. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
  127. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.d.ts +5 -1
  128. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +103 -51
  129. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -1
  130. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +2 -1
  131. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +41 -21
  132. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  133. package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js +32 -8
  134. package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js.map +1 -1
  135. package/node_modules/@codingns/session-sync-core/dist/runtime/legna-runtime.d.ts +10 -0
  136. package/node_modules/@codingns/session-sync-core/dist/runtime/legna-runtime.js +16 -0
  137. package/node_modules/@codingns/session-sync-core/dist/runtime/legna-runtime.js.map +1 -0
  138. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js +167 -10
  139. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js.map +1 -1
  140. package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +2 -0
  141. package/node_modules/@codingns/session-sync-core/dist/types.d.ts +1 -1
  142. package/node_modules/@codingns/session-sync-core/dist/types.js +1 -1
  143. package/node_modules/@codingns/session-sync-core/dist/types.js.map +1 -1
  144. package/package.json +1 -1
  145. package/dist/public/assets/ConversationPage-z3sXtKZ7.js +0 -4
  146. package/dist/public/assets/DesktopWindowPage-CZcoGApB.js +0 -2
  147. package/dist/public/assets/FileContextPanel-C3qex8bb.js +0 -1
  148. package/dist/public/assets/GitSidebar-BK6H16XU.js +0 -6
  149. package/dist/public/assets/MobileCreateSessionSheet-BYfbvK8o.js +0 -1
  150. package/dist/public/assets/MobileSheet-Ckug8hTb.js +0 -1
  151. package/dist/public/assets/MobileWorkspaceSwitcherHeader-RqWrBdn2.js +0 -1
  152. package/dist/public/assets/SessionIndexPage-DuK10DL5.js +0 -1
  153. package/dist/public/assets/SettingsPage-fyD-xaHL.js +0 -1
  154. package/dist/public/assets/TerminalManagerPanel-CCLr1Ypk.js +0 -1
  155. package/dist/public/assets/TerminalRuntimeFallbackModal-aUzjEBwP.js +0 -1
  156. package/dist/public/assets/ToolGitPage-C264yjS9.js +0 -1
  157. package/dist/public/assets/ToolProcessesPage-BOP4A1cb.js +0 -1
  158. package/dist/public/assets/ToolsHomePage-CQxGiKQA.js +0 -1
  159. package/dist/public/assets/WorkbenchLandingPage-CvAY68ca.js +0 -1
  160. package/dist/public/assets/WorkbenchLayout-DGm8Tc5M.js +0 -3
  161. package/dist/public/assets/WorkbenchShellRoute-BF0nHWOk.css +0 -1
  162. package/dist/public/assets/WorkbenchShellRoute-DBBOsJo9.js +0 -1
  163. package/dist/public/assets/WorkspaceDebugDetailPage-CDerFYd2.js +0 -1
  164. package/dist/public/assets/WorkspaceDetailPage-BlJc1CHE.js +0 -1
  165. package/dist/public/assets/WorkspaceHomePage-BUsKJ3lv.js +0 -1
  166. package/dist/public/assets/default-session-permission-mode-DT4SGiwp.js +0 -1
  167. package/dist/public/assets/index-BZLcEHW3.js +0 -42
  168. package/dist/public/assets/index-BbspQPC2.css +0 -1
  169. package/dist/public/assets/session-runtime-machine-DdLeDqQr.js +0 -17
  170. package/dist/public/assets/useRegisteredDebugTemplates-oFAQNIqh.js +0 -1
@@ -6,7 +6,7 @@ import type { SessionIndexRepository } from "../../storage/repositories/session-
6
6
  import type { SessionSendQueueRepository } from "../../storage/repositories/session-send-queue-repository.js";
7
7
  import type { SessionStateRepository } from "../../storage/repositories/session-state-repository.js";
8
8
  import type { SessionStatusSnapshotRepository } from "../../storage/repositories/session-status-snapshot-repository.js";
9
- import type { SessionActivityConfidence, SessionInterruptSource, SessionActivityResolutionSource, SessionListItem, SessionResolvedRunningState, SessionSendQueueItemRecord } from "../../types/domain.js";
9
+ import type { SessionActivityConfidence, SessionInterruptSource, SessionActivityResolutionSource, SessionListItem, SessionProviderConfigMode, SessionResolvedRunningState, SessionSendQueueItemRecord } from "../../types/domain.js";
10
10
  import { SessionActivityAuthorityService, type SessionActivityObservation } from "./session-activity-authority-service.js";
11
11
  import { SessionChangedFileService } from "./session-changed-file-service.js";
12
12
  import type { WorkspaceService } from "../workspace/workspace-service.js";
@@ -14,6 +14,7 @@ import type { SessionAttachmentInput } from "./session-message-attachment-servic
14
14
  import { SessionMessageAttachmentService } from "./session-message-attachment-service.js";
15
15
  import { type SessionPermissionEnvelope, type SessionPermissionReplyInput, type SessionPermissionRequestView } from "./session-permission-request-service.js";
16
16
  import type { SessionHistoryEnvelope, SessionHistoryMessageWithOrigin, SessionHistoryService } from "./session-history-service.js";
17
+ import { SessionProviderConfigService } from "./session-provider-config-service.js";
17
18
  interface RuntimeSendOptions {
18
19
  model?: string | null;
19
20
  reasoningLevel?: string | null;
@@ -31,6 +32,8 @@ interface StartLiveSessionInput {
31
32
  sessionKind?: "default" | "annotation";
32
33
  annotationSourceMessageId?: string | null;
33
34
  annotationSourceText?: string | null;
35
+ providerConfigMode?: SessionProviderConfigMode;
36
+ providerPresetId?: string | null;
34
37
  runtimeOptions?: RuntimeSendOptions;
35
38
  }
36
39
  interface SendLiveMessageInput {
@@ -38,6 +41,8 @@ interface SendLiveMessageInput {
38
41
  userId: string;
39
42
  content: string;
40
43
  clientRequestId: string | null;
44
+ providerConfigMode?: SessionProviderConfigMode;
45
+ providerPresetId?: string | null;
41
46
  runtimeOptions?: RuntimeSendOptions;
42
47
  }
43
48
  interface LiveMessageAcceptedResult {
@@ -181,6 +186,7 @@ export declare class SessionLiveRuntimeService {
181
186
  private readonly sessionIndexRepository;
182
187
  private readonly sessionStateRepository;
183
188
  private readonly sessionStatusSnapshotRepository;
189
+ private readonly sessionProviderConfigService;
184
190
  private readonly config;
185
191
  private readonly providerRuntimeService;
186
192
  private readonly sessionActivityAuthorityService;
@@ -196,7 +202,7 @@ export declare class SessionLiveRuntimeService {
196
202
  private readonly queueDispatchSessions;
197
203
  private readonly queueRetryTimers;
198
204
  private readonly pendingSendDebugTracesBySessionId;
199
- constructor(sessionHistoryService: SessionHistoryService, sessionMessageAttachmentService: SessionMessageAttachmentService, workspaceService: WorkspaceService, sessionChangedFileService: SessionChangedFileService, sessionBindingRepository: SessionBindingRepository, authUserRepository: AuthUserRepository, sessionSendQueueRepository: SessionSendQueueRepository, sessionIndexRepository: SessionIndexRepository, sessionStateRepository: SessionStateRepository, sessionStatusSnapshotRepository: SessionStatusSnapshotRepository, config: HostConfig, sessionActivityAuthorityService?: SessionActivityAuthorityService);
205
+ 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);
200
206
  startLiveSession(input: StartLiveSessionInput): Promise<LiveMessageAcceptedResult>;
201
207
  sendLiveMessage(input: SendLiveMessageInput): Promise<LiveMessageAcceptedResult>;
202
208
  listQueuedMessages(sessionId: string, userId: string): Promise<SessionQueueItemView[]>;
@@ -244,6 +250,13 @@ export declare class SessionLiveRuntimeService {
244
250
  private resolveStartedSession;
245
251
  private upsertRuntimeBackedSessionRecords;
246
252
  private ensurePendingSessionBinding;
253
+ private resolveEffectiveSessionProviderBinding;
254
+ private getSessionBindingOrThrow;
255
+ private resolveRequestedSessionProviderBinding;
256
+ private persistResolvedSessionProviderBinding;
257
+ private assertProviderBindingStableDuringActiveRun;
258
+ private hasSessionProviderBindingChanged;
259
+ private resolveCodexRuntimeRequestRawStoreRef;
247
260
  private buildBindingSnapshot;
248
261
  private persistRuntimeEvent;
249
262
  private emitTerminalStateEvent;
@@ -1,7 +1,7 @@
1
- import { existsSync, readdirSync } from "node:fs";
1
+ import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { performance } from "node:perf_hooks";
4
- import { ClaudeRuntimeAdapter, CodexRuntimeAdapter, GeminiRuntimeAdapter, KimiRuntimeAdapter, OpenCodeRuntimeAdapter, ProviderRuntimeService } from "@codingns/session-sync-core";
4
+ import { ClaudeRuntimeAdapter, CodexRuntimeAdapter, GeminiRuntimeAdapter, KimiRuntimeAdapter, LegnaRuntimeAdapter, OpenCodeRuntimeAdapter, ProviderRuntimeService } from "@codingns/session-sync-core";
5
5
  import { AppError, isAppError } from "../../shared/errors/app-error.js";
6
6
  import { createId } from "../../shared/utils/id.js";
7
7
  import { isPerfDebugEnabled, logPerformance } from "../../shared/utils/perf-log.js";
@@ -9,9 +9,10 @@ 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 { SessionPermissionRequestService } from "./session-permission-request-service.js";
12
- import { mapSessionProviderError } from "./session-provider-error-mapper.js";
12
+ import { appendSessionProviderErrorContext, mapSessionProviderError } from "./session-provider-error-mapper.js";
13
13
  import { ClaudeRuntimeHelperAdapter } from "./claude-runtime-helper-client.js";
14
14
  import { CodexAppServerHelperClient } from "./codex-app-server-helper-client.js";
15
+ const OPENCODE_ORDER_DEBUG_ENABLED = /^(1|true|yes)$/i.test(process.env.CODINGNS_OPENCODE_ORDER_DEBUG?.trim() ?? "");
15
16
  const RUNTIME_START_BINDING_WAIT_TIMEOUT_MS = 10_000;
16
17
  const START_BINDING_POLL_INTERVAL_MS = 50;
17
18
  const EXTERNAL_RUNTIME_INTERRUPT_SUPPRESSION_MS = 30_000;
@@ -27,6 +28,7 @@ export class SessionLiveRuntimeService {
27
28
  sessionIndexRepository;
28
29
  sessionStateRepository;
29
30
  sessionStatusSnapshotRepository;
31
+ sessionProviderConfigService;
30
32
  config;
31
33
  providerRuntimeService;
32
34
  sessionActivityAuthorityService;
@@ -42,7 +44,7 @@ export class SessionLiveRuntimeService {
42
44
  queueDispatchSessions = new Set();
43
45
  queueRetryTimers = new Map();
44
46
  pendingSendDebugTracesBySessionId = new Map();
45
- constructor(sessionHistoryService, sessionMessageAttachmentService, workspaceService, sessionChangedFileService, sessionBindingRepository, authUserRepository, sessionSendQueueRepository, sessionIndexRepository, sessionStateRepository, sessionStatusSnapshotRepository, config, sessionActivityAuthorityService = new SessionActivityAuthorityService()) {
47
+ constructor(sessionHistoryService, sessionMessageAttachmentService, workspaceService, sessionChangedFileService, sessionBindingRepository, authUserRepository, sessionSendQueueRepository, sessionIndexRepository, sessionStateRepository, sessionStatusSnapshotRepository, sessionProviderConfigService, config, sessionActivityAuthorityService = new SessionActivityAuthorityService()) {
46
48
  this.sessionHistoryService = sessionHistoryService;
47
49
  this.sessionMessageAttachmentService = sessionMessageAttachmentService;
48
50
  this.workspaceService = workspaceService;
@@ -53,6 +55,7 @@ export class SessionLiveRuntimeService {
53
55
  this.sessionIndexRepository = sessionIndexRepository;
54
56
  this.sessionStateRepository = sessionStateRepository;
55
57
  this.sessionStatusSnapshotRepository = sessionStatusSnapshotRepository;
58
+ this.sessionProviderConfigService = sessionProviderConfigService;
56
59
  this.config = config;
57
60
  this.sessionActivityAuthorityService = sessionActivityAuthorityService;
58
61
  this.sessionPermissionRequestService = new SessionPermissionRequestService(sessionHistoryService, sessionBindingRepository, authUserRepository, workspaceService, config, async (envelope) => {
@@ -79,7 +82,19 @@ export class SessionLiveRuntimeService {
79
82
  });
80
83
  try {
81
84
  const capabilities = this.sessionHistoryService.getProviderCapabilitiesSnapshot(input.provider);
82
- this.ensurePendingSessionBinding(sessionId, workspace.id, input.provider);
85
+ const providerBinding = this.sessionProviderConfigService.prepareSessionBinding({
86
+ sessionId,
87
+ provider: input.provider,
88
+ providerConfigMode: input.providerConfigMode,
89
+ providerPresetId: input.providerPresetId ?? null
90
+ });
91
+ const providerLaunchContext = this.sessionProviderConfigService.resolveLaunchContext({
92
+ provider: input.provider,
93
+ providerConfigMode: providerBinding.providerConfigMode,
94
+ providerPresetId: providerBinding.providerPresetId,
95
+ runtimeHomeDir: providerBinding.runtimeHomeDir
96
+ });
97
+ this.ensurePendingSessionBinding(sessionId, workspace.id, input.provider, providerBinding);
83
98
  const persistedAttachments = this.persistMessageAttachments(sessionId, input.clientRequestId, input.runtimeOptions?.attachments ?? []);
84
99
  const providerPrompt = this.sessionMessageAttachmentService.buildProviderPrompt(input.provider, input.content, persistedAttachments.runtimeAttachments);
85
100
  const providerInstructionFilePath = resolveRuntimeInstructionFilePath(input.provider, workspace.path, input.runtimeOptions?.providerInstructionFilePath ?? null);
@@ -93,6 +108,8 @@ export class SessionLiveRuntimeService {
93
108
  provider: input.provider,
94
109
  providerSessionId: null,
95
110
  rawStoreRef: null,
111
+ runtimeHomeDir: providerLaunchContext.runtimeHomeDir,
112
+ runtimeEnv: providerLaunchContext.runtimeEnv,
96
113
  sequenceBase: 1,
97
114
  options: {
98
115
  content: input.content,
@@ -104,7 +121,12 @@ export class SessionLiveRuntimeService {
104
121
  providerInstructionFilePath,
105
122
  attachments: persistedAttachments.runtimeAttachments
106
123
  }
107
- }, "start");
124
+ }, "start", {
125
+ provider: input.provider,
126
+ providerConfigMode: providerBinding.providerConfigMode,
127
+ providerPresetId: providerBinding.providerPresetId,
128
+ runtimeHomeDir: providerBinding.runtimeHomeDir
129
+ });
108
130
  this.logSendDebugStep(debugTrace, "launch_runtime", launchRuntimeStartedAtMs, {
109
131
  userId: input.userId
110
132
  });
@@ -203,6 +225,7 @@ export class SessionLiveRuntimeService {
203
225
  }
204
226
  async enqueueLiveMessage(input) {
205
227
  const session = await this.resolveQueueDispatchSession(input.sessionId, input.userId);
228
+ this.resolveEffectiveSessionProviderBinding(session, input);
206
229
  this.persistMessageAttachments(input.sessionId, input.clientRequestId, input.runtimeOptions?.attachments ?? []);
207
230
  const timestamp = nowIso();
208
231
  const queueItem = {
@@ -649,6 +672,16 @@ export class SessionLiveRuntimeService {
649
672
  if (!envelope) {
650
673
  return;
651
674
  }
675
+ logOpenCodeOrderEnvelopeDebug("runtime.envelope.forward", {
676
+ sessionId,
677
+ runtimeSessionId,
678
+ provider: event.provider ?? null,
679
+ eventType: event.type ?? null,
680
+ envelopeType: envelope.type,
681
+ message: "message" in envelope && envelope.message
682
+ ? summarizeOpenCodeOrderMessage(envelope.message)
683
+ : null
684
+ });
652
685
  await onEnvelope(envelope);
653
686
  });
654
687
  const externalSubscription = this.subscribeExternalRuntime(runtimeSessionId, async (envelope) => {
@@ -1027,14 +1060,14 @@ export class SessionLiveRuntimeService {
1027
1060
  void this.dispatchNextQueuedMessage(input.sessionId);
1028
1061
  }
1029
1062
  }
1030
- async startRuntimeRun(request, userId, mode) {
1063
+ async startRuntimeRun(request, userId, mode, providerBinding) {
1031
1064
  this.runtimeMessageSeenSessions.delete(request.sessionId);
1032
1065
  this.runtimeHistoryFallbackSentSessions.delete(request.sessionId);
1033
1066
  this.clearExternalRuntimeInterruptSuppression(request.sessionId);
1034
1067
  if (request.provider === "claude-code") {
1035
1068
  this.clearExternalRuntimeSnapshot(request.sessionId);
1036
1069
  }
1037
- const handle = await this.launchRuntimeRun(request, mode);
1070
+ const handle = await this.launchRuntimeRun(request, mode, providerBinding);
1038
1071
  const snapshot = handle.getSnapshot();
1039
1072
  const currentState = this.sessionStateRepository.findBySessionAndUser(request.sessionId, userId);
1040
1073
  this.attachRuntimePersistence(handle, request.sessionId, request.workspaceId, userId);
@@ -1066,9 +1099,43 @@ export class SessionLiveRuntimeService {
1066
1099
  const capabilities = await this.sessionHistoryService.getSessionCapabilities(input.sessionId);
1067
1100
  const workspace = this.workspaceService.getWorkspaceOrThrow(session.workspaceId);
1068
1101
  const runtimeMode = shouldStartNativeSessionOnFirstMessage(session);
1102
+ const existingBinding = this.getSessionBindingOrThrow(session.sessionId);
1103
+ const resolvedProviderBinding = this.resolveRequestedSessionProviderBinding(session, input, existingBinding);
1104
+ const runtimeSessionId = this.resolveRuntimeSessionId(input.sessionId);
1105
+ const activeRun = this.getLiveRuntimeSnapshot(runtimeSessionId);
1106
+ const externalRuntimeSnapshot = this.getFreshExternalRuntimeSnapshot(runtimeSessionId);
1107
+ const hasActiveRun = Boolean(activeRun && isActiveRuntimeState(activeRun.runningState));
1108
+ if (hasActiveRun && activeRun?.provider === "claude-code") {
1109
+ this.clearExternalRuntimeSnapshot(runtimeSessionId);
1110
+ }
1111
+ if (hasActiveRun
1112
+ || (!activeRun &&
1113
+ session.provider === "claude-code" &&
1114
+ externalRuntimeSnapshot &&
1115
+ isActiveRuntimeState(externalRuntimeSnapshot.runningState))) {
1116
+ this.assertProviderBindingStableDuringActiveRun(existingBinding, resolvedProviderBinding);
1117
+ }
1118
+ if (!activeRun &&
1119
+ session.provider === "claude-code" &&
1120
+ externalRuntimeSnapshot &&
1121
+ isActiveRuntimeState(externalRuntimeSnapshot.runningState)) {
1122
+ throw new AppError({
1123
+ statusCode: 409,
1124
+ errorCode: "SESSION_EXTERNAL_RUN_ACTIVE",
1125
+ detail: "当前 Claude 外部会话仍在运行,不能直接追加;请加入队列或等待当前轮结束",
1126
+ field: "sessionId"
1127
+ });
1128
+ }
1129
+ const providerBinding = hasActiveRun
1130
+ ? existingBinding
1131
+ : this.persistResolvedSessionProviderBinding(existingBinding, resolvedProviderBinding);
1132
+ const providerLaunchContext = this.sessionProviderConfigService.resolveLaunchContext(providerBinding);
1069
1133
  const syntheticForkRawStoreRef = runtimeMode === "start" && shouldResumeCodexSyntheticForkSession(session)
1070
1134
  ? session.rawStoreRef
1071
1135
  : null;
1136
+ const runtimeRawStoreRef = runtimeMode === "start"
1137
+ ? syntheticForkRawStoreRef
1138
+ : await this.resolveCodexRuntimeRequestRawStoreRef(session, providerBinding);
1072
1139
  const nextUserSequence = runtimeMode === "start"
1073
1140
  ? 1
1074
1141
  : await this.resolveNextUserSequence(input.sessionId, session.messageCount);
@@ -1083,7 +1150,9 @@ export class SessionLiveRuntimeService {
1083
1150
  workspacePath: workspace.path,
1084
1151
  provider: session.provider,
1085
1152
  providerSessionId: runtimeMode === "start" ? null : session.providerSessionId,
1086
- rawStoreRef: runtimeMode === "start" ? syntheticForkRawStoreRef : session.rawStoreRef,
1153
+ rawStoreRef: runtimeRawStoreRef,
1154
+ runtimeHomeDir: providerLaunchContext.runtimeHomeDir,
1155
+ runtimeEnv: providerLaunchContext.runtimeEnv,
1087
1156
  sequenceBase: nextUserSequence,
1088
1157
  options: {
1089
1158
  content: input.content,
@@ -1096,26 +1165,7 @@ export class SessionLiveRuntimeService {
1096
1165
  attachments: resolvedAttachments.runtimeAttachments
1097
1166
  }
1098
1167
  };
1099
- const runtimeSessionId = this.resolveRuntimeSessionId(input.sessionId);
1100
- const activeRun = this.getLiveRuntimeSnapshot(runtimeSessionId);
1101
- const externalRuntimeSnapshot = this.getFreshExternalRuntimeSnapshot(runtimeSessionId);
1102
- if (activeRun &&
1103
- activeRun.provider === "claude-code" &&
1104
- isActiveRuntimeState(activeRun.runningState)) {
1105
- this.clearExternalRuntimeSnapshot(runtimeSessionId);
1106
- }
1107
- if (!activeRun &&
1108
- session.provider === "claude-code" &&
1109
- externalRuntimeSnapshot &&
1110
- isActiveRuntimeState(externalRuntimeSnapshot.runningState)) {
1111
- throw new AppError({
1112
- statusCode: 409,
1113
- errorCode: "SESSION_EXTERNAL_RUN_ACTIVE",
1114
- detail: "当前 Claude 外部会话仍在运行,不能直接追加;请加入队列或等待当前轮结束",
1115
- field: "sessionId"
1116
- });
1117
- }
1118
- if (activeRun && isActiveRuntimeState(activeRun.runningState)) {
1168
+ if (hasActiveRun) {
1119
1169
  const submitStartedAtMs = performance.now();
1120
1170
  try {
1121
1171
  await this.providerRuntimeService.submitToActiveRun(runtimeSessionId, runtimeRequest.options);
@@ -1125,13 +1175,23 @@ export class SessionLiveRuntimeService {
1125
1175
  });
1126
1176
  }
1127
1177
  catch (error) {
1128
- const mapped = mapSessionProviderError(error);
1178
+ const mapped = appendSessionProviderErrorContext(mapSessionProviderError(error), this.sessionProviderConfigService.describeBinding({
1179
+ provider: session.provider,
1180
+ providerConfigMode: providerBinding.providerConfigMode,
1181
+ providerPresetId: providerBinding.providerPresetId,
1182
+ runtimeHomeDir: providerBinding.runtimeHomeDir
1183
+ }));
1129
1184
  // 运行时句柄还没来得及收尾时,steer 可能会撞上 provider 已终态。
1130
1185
  // 这里直接失败只会把一条正常消息变成偶发 409,属于纯粹的坏味道。
1131
1186
  if (mapped.errorCode === "SESSION_NOT_RUNNING") {
1132
1187
  await this.providerRuntimeService.abandonRun(runtimeSessionId);
1133
1188
  const restartRuntimeStartedAtMs = performance.now();
1134
- await this.startRuntimeRun(runtimeRequest, input.userId, runtimeMode);
1189
+ await this.startRuntimeRun(runtimeRequest, input.userId, runtimeMode, {
1190
+ provider: session.provider,
1191
+ providerConfigMode: providerBinding.providerConfigMode,
1192
+ providerPresetId: providerBinding.providerPresetId,
1193
+ runtimeHomeDir: providerBinding.runtimeHomeDir
1194
+ });
1135
1195
  this.logSendDebugStep(debugTrace, "restart_runtime_after_stale_active_run", restartRuntimeStartedAtMs, {
1136
1196
  runtimeMode
1137
1197
  });
@@ -1143,7 +1203,12 @@ export class SessionLiveRuntimeService {
1143
1203
  }
1144
1204
  else {
1145
1205
  const startRuntimeStartedAtMs = performance.now();
1146
- await this.startRuntimeRun(runtimeRequest, input.userId, runtimeMode);
1206
+ await this.startRuntimeRun(runtimeRequest, input.userId, runtimeMode, {
1207
+ provider: session.provider,
1208
+ providerConfigMode: providerBinding.providerConfigMode,
1209
+ providerPresetId: providerBinding.providerPresetId,
1210
+ runtimeHomeDir: providerBinding.runtimeHomeDir
1211
+ });
1147
1212
  this.logSendDebugStep(debugTrace, "start_runtime_run", startRuntimeStartedAtMs, {
1148
1213
  runtimeMode
1149
1214
  });
@@ -1305,14 +1370,18 @@ export class SessionLiveRuntimeService {
1305
1370
  .then((refreshedSession) => refreshedSession ?? session)
1306
1371
  .catch(() => session);
1307
1372
  }
1308
- async launchRuntimeRun(request, mode) {
1373
+ async launchRuntimeRun(request, mode, providerBinding) {
1309
1374
  try {
1310
1375
  return await (mode === "start"
1311
1376
  ? this.providerRuntimeService.startSession(request)
1312
1377
  : this.providerRuntimeService.continueSession(request));
1313
1378
  }
1314
1379
  catch (error) {
1315
- throw mapSessionProviderError(error);
1380
+ const mapped = mapSessionProviderError(error);
1381
+ if (!providerBinding) {
1382
+ throw mapped;
1383
+ }
1384
+ throw appendSessionProviderErrorContext(mapped, this.sessionProviderConfigService.describeBinding(providerBinding));
1316
1385
  }
1317
1386
  }
1318
1387
  attachRuntimePersistence(handle, sessionId, workspaceId, userId) {
@@ -1390,8 +1459,109 @@ export class SessionLiveRuntimeService {
1390
1459
  });
1391
1460
  this.sessionActivityAuthorityService.observe(createRuntimeActivityObservation(input.sessionId, input.snapshot));
1392
1461
  }
1393
- ensurePendingSessionBinding(sessionId, workspaceId, provider) {
1394
- this.sessionHistoryService.persistSessionBinding(sessionId, workspaceId, this.buildBindingSnapshot(sessionId, provider, null, null));
1462
+ ensurePendingSessionBinding(sessionId, workspaceId, provider, providerBinding) {
1463
+ const snapshot = this.buildBindingSnapshot(sessionId, provider, null, null);
1464
+ const timestamp = nowIso();
1465
+ const existingBinding = this.sessionBindingRepository.findBySessionId(sessionId);
1466
+ this.sessionBindingRepository.upsert({
1467
+ sessionId,
1468
+ workspaceId,
1469
+ provider: snapshot.provider,
1470
+ providerSessionId: snapshot.providerSessionId,
1471
+ rawStoreRef: snapshot.rawStoreRef,
1472
+ providerConfigMode: providerBinding?.providerConfigMode ?? existingBinding?.providerConfigMode ?? "global-default",
1473
+ providerPresetId: providerBinding?.providerPresetId ?? existingBinding?.providerPresetId ?? null,
1474
+ runtimeHomeDir: providerBinding?.runtimeHomeDir ?? existingBinding?.runtimeHomeDir ?? null,
1475
+ createdAt: existingBinding?.createdAt ?? timestamp,
1476
+ updatedAt: timestamp
1477
+ });
1478
+ }
1479
+ resolveEffectiveSessionProviderBinding(session, input) {
1480
+ const existingBinding = this.getSessionBindingOrThrow(session.sessionId);
1481
+ const providerBinding = this.resolveRequestedSessionProviderBinding(session, input, existingBinding);
1482
+ return this.persistResolvedSessionProviderBinding(existingBinding, providerBinding);
1483
+ }
1484
+ getSessionBindingOrThrow(sessionId) {
1485
+ const existingBinding = this.sessionBindingRepository.findBySessionId(sessionId);
1486
+ if (!existingBinding) {
1487
+ throw new AppError({
1488
+ statusCode: 404,
1489
+ errorCode: "SESSION_NOT_FOUND",
1490
+ detail: "session 不存在"
1491
+ });
1492
+ }
1493
+ return existingBinding;
1494
+ }
1495
+ resolveRequestedSessionProviderBinding(session, input, existingBinding) {
1496
+ return this.sessionProviderConfigService.resolveSessionBinding({
1497
+ sessionId: session.sessionId,
1498
+ provider: session.provider,
1499
+ existingBinding,
1500
+ providerConfigMode: input.providerConfigMode,
1501
+ providerPresetId: input.providerPresetId ?? null
1502
+ });
1503
+ }
1504
+ persistResolvedSessionProviderBinding(existingBinding, providerBinding) {
1505
+ if (!this.hasSessionProviderBindingChanged(existingBinding, providerBinding)) {
1506
+ return existingBinding;
1507
+ }
1508
+ const nextBinding = {
1509
+ ...existingBinding,
1510
+ providerConfigMode: providerBinding.providerConfigMode,
1511
+ providerPresetId: providerBinding.providerPresetId,
1512
+ runtimeHomeDir: providerBinding.runtimeHomeDir,
1513
+ updatedAt: nowIso()
1514
+ };
1515
+ this.sessionBindingRepository.upsert(nextBinding);
1516
+ return nextBinding;
1517
+ }
1518
+ assertProviderBindingStableDuringActiveRun(existingBinding, requestedBinding) {
1519
+ if (!this.hasSessionProviderBindingChanged(existingBinding, requestedBinding)) {
1520
+ return;
1521
+ }
1522
+ throw new AppError({
1523
+ statusCode: 409,
1524
+ errorCode: "SESSION_PROVIDER_CONFIG_CHANGE_REQUIRES_NEW_RUN",
1525
+ detail: "当前会话仍在执行,不能中途切换模型配置文件;请等本轮结束后再发起新一轮",
1526
+ field: "sessionId"
1527
+ });
1528
+ }
1529
+ hasSessionProviderBindingChanged(currentBinding, nextBinding) {
1530
+ return (currentBinding.providerConfigMode !== nextBinding.providerConfigMode
1531
+ || normalizeOptionalBindingValue(currentBinding.providerPresetId)
1532
+ !== normalizeOptionalBindingValue(nextBinding.providerPresetId)
1533
+ || normalizeOptionalBindingValue(currentBinding.runtimeHomeDir)
1534
+ !== normalizeOptionalBindingValue(nextBinding.runtimeHomeDir));
1535
+ }
1536
+ async resolveCodexRuntimeRequestRawStoreRef(session, providerBinding) {
1537
+ if (session.provider !== "codex") {
1538
+ return session.rawStoreRef;
1539
+ }
1540
+ const currentRawStoreRef = session.rawStoreRef?.trim() || null;
1541
+ if (currentRawStoreRef && existsSync(currentRawStoreRef)) {
1542
+ return currentRawStoreRef;
1543
+ }
1544
+ const messages = await Promise.resolve(this.sessionHistoryService.readAllTextHistoryMessages(session.sessionId)).catch(() => []);
1545
+ if (!Array.isArray(messages) || messages.length === 0) {
1546
+ return currentRawStoreRef;
1547
+ }
1548
+ const baseDir = providerBinding.runtimeHomeDir?.trim()
1549
+ || path.resolve(path.dirname(this.config.databasePath), "runtime", "codex-resume-history");
1550
+ const syntheticDir = path.join(baseDir, ".codingns-synthetic-resume");
1551
+ const syntheticFilePath = path.join(syntheticDir, `${session.sessionId}.jsonl`);
1552
+ const serialized = messages
1553
+ .map((message) => JSON.stringify({
1554
+ timestamp: message.timestamp,
1555
+ type: "event_msg",
1556
+ payload: {
1557
+ type: message.role === "assistant" ? "agent_message" : "user_message",
1558
+ message: message.content
1559
+ }
1560
+ }))
1561
+ .join("\n");
1562
+ mkdirSync(syntheticDir, { recursive: true });
1563
+ writeFileSync(syntheticFilePath, `${serialized}\n`, "utf8");
1564
+ return syntheticFilePath;
1395
1565
  }
1396
1566
  buildBindingSnapshot(sessionId, provider, providerSessionId, rawStoreRef) {
1397
1567
  const pendingValue = `pending://${provider}/${sessionId}`;
@@ -1762,7 +1932,7 @@ export class SessionLiveRuntimeService {
1762
1932
  }
1763
1933
  }
1764
1934
  async resolveNextUserSequence(sessionId, messageCount) {
1765
- let maxSequence = Math.max(messageCount, 0);
1935
+ let maxSequence = 0;
1766
1936
  const envelope = await Promise.resolve(this.sessionHistoryService.readRecentHistoryEnvelope(sessionId, 10)).catch(() => {
1767
1937
  return null;
1768
1938
  });
@@ -1771,6 +1941,9 @@ export class SessionLiveRuntimeService {
1771
1941
  maxSequence = message.sequence;
1772
1942
  }
1773
1943
  }
1944
+ if (maxSequence <= 0) {
1945
+ maxSequence = Math.max(messageCount, 0);
1946
+ }
1774
1947
  return Math.max(maxSequence + 1, 1);
1775
1948
  }
1776
1949
  async waitForResolvedStartBinding(sessionId, workspaceId, provider, handle) {
@@ -2294,21 +2467,33 @@ function createProviderRuntimeAdapters(config, options = {}) {
2294
2467
  if ("dispose" in claudeAdapter && typeof claudeAdapter.dispose === "function") {
2295
2468
  disposables.push(claudeAdapter);
2296
2469
  }
2297
- const codexTransportHelper = process.env.VITEST
2298
- ? null
2299
- : new CodexAppServerHelperClient(config.codexCliPath, {
2300
- homeDir: config.codexHomeDir
2301
- });
2302
- if (codexTransportHelper) {
2303
- disposables.push(codexTransportHelper);
2304
- }
2305
2470
  return {
2306
2471
  adapters: [
2307
2472
  claudeAdapter,
2473
+ new LegnaRuntimeAdapter({
2474
+ homeDir: config.legnaCodeHomeDir,
2475
+ commandPath: config.legnaCodeCliPath,
2476
+ legacyClaudeHomeDir: config.claudeCodeHomeDir
2477
+ }),
2308
2478
  new CodexRuntimeAdapter({
2309
2479
  homeDir: config.codexHomeDir,
2310
2480
  commandPath: config.codexCliPath,
2311
- transportFactory: codexTransportHelper?.createTransport.bind(codexTransportHelper),
2481
+ transportFactory: process.env.VITEST
2482
+ ? undefined
2483
+ : (request) => {
2484
+ const client = new CodexAppServerHelperClient(config.codexCliPath, {
2485
+ homeDir: request.runtimeHomeDir?.trim() || config.codexHomeDir,
2486
+ runtimeEnv: request.runtimeEnv ?? null
2487
+ });
2488
+ const transport = client.createTransport();
2489
+ return {
2490
+ ...transport,
2491
+ close() {
2492
+ transport.close();
2493
+ client.dispose();
2494
+ }
2495
+ };
2496
+ },
2312
2497
  handleServerRequest: options.handleCodexServerRequest
2313
2498
  }),
2314
2499
  new GeminiRuntimeAdapter({
@@ -2333,12 +2518,16 @@ function resolveRuntimeInstructionFilePath(provider, workspacePath, explicitFile
2333
2518
  const resolvedExplicit = path.resolve(normalizedExplicit);
2334
2519
  return existsSync(resolvedExplicit) ? resolvedExplicit : null;
2335
2520
  }
2336
- if (provider !== "claude-code") {
2521
+ const defaultInstructionPath = provider === "claude-code"
2522
+ ? path.join(workspacePath, "CLAUDE.md")
2523
+ : provider === "legna-code"
2524
+ ? path.join(workspacePath, "LEGNA.md")
2525
+ : null;
2526
+ if (!defaultInstructionPath) {
2337
2527
  return null;
2338
2528
  }
2339
- const defaultClaudeInstructionPath = path.join(workspacePath, "CLAUDE.md");
2340
- return existsSync(defaultClaudeInstructionPath)
2341
- ? path.resolve(defaultClaudeInstructionPath)
2529
+ return existsSync(defaultInstructionPath)
2530
+ ? path.resolve(defaultInstructionPath)
2342
2531
  : null;
2343
2532
  }
2344
2533
  function buildClaudeHookBridgeConfig(config) {
@@ -2398,4 +2587,30 @@ function workspaceSlug(workspacePath) {
2398
2587
  .replaceAll("\\", "-")
2399
2588
  .replaceAll("/", "-");
2400
2589
  }
2590
+ function normalizeOptionalBindingValue(value) {
2591
+ const normalized = value?.trim();
2592
+ return normalized && normalized.length > 0 ? normalized : null;
2593
+ }
2594
+ function logOpenCodeOrderEnvelopeDebug(scope, detail) {
2595
+ if (!OPENCODE_ORDER_DEBUG_ENABLED) {
2596
+ return;
2597
+ }
2598
+ console.info(`[opencode-order-envelope] ${scope}`, {
2599
+ timestamp: new Date().toISOString(),
2600
+ ...detail
2601
+ });
2602
+ }
2603
+ function summarizeOpenCodeOrderMessage(message) {
2604
+ const content = typeof message.content === "string" ? message.content : "";
2605
+ const normalized = content.replace(/\s+/g, " ").trim();
2606
+ return {
2607
+ messageId: message.messageId ?? null,
2608
+ role: message.role ?? null,
2609
+ kind: message.kind ?? null,
2610
+ sequence: message.sequence ?? null,
2611
+ timestamp: message.timestamp ?? null,
2612
+ rawRef: message.rawRef ?? null,
2613
+ contentPreview: normalized.length > 80 ? `${normalized.slice(0, 80)}...` : normalized
2614
+ };
2615
+ }
2401
2616
  //# sourceMappingURL=session-live-runtime-service.js.map