vibe64 0.1.21 → 0.1.22

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 (143) hide show
  1. package/dist/assets/ProjectTypeGate-B3NHteXC.js +1 -0
  2. package/dist/assets/ProjectTypeGate-fJcYj6sR.css +1 -0
  3. package/dist/assets/{SetupReadinessGate-DkkorR2Y.js → SetupReadinessGate-2twHjoYZ.js} +1 -1
  4. package/dist/assets/{ShellLayout-BcKS2HG9.js → ShellLayout-BjAbXfzf.js} +1 -1
  5. package/dist/assets/{VTabs-BJ8MKoig.js → VTabs-BLGGdbms.js} +1 -1
  6. package/dist/assets/{error-CwT53qTu.js → error-DvUPciuh.js} +1 -1
  7. package/dist/assets/history-DfM4ewyV.js +1 -0
  8. package/dist/assets/home-sh4v0vz7.js +1 -0
  9. package/dist/assets/index-C4JbNnml.css +1 -0
  10. package/dist/assets/{index-BJxDQvyK.js → index-CdFWokfE.js} +1 -1
  11. package/dist/assets/index-D4oqjV9n.js +132 -0
  12. package/dist/assets/{index-CY-wDjNv.js → index-DqoYKexs.js} +15 -15
  13. package/dist/assets/{placement-7FCYadh2.js → placement-QfRaYTFY.js} +1 -1
  14. package/dist/assets/{setup-BzzdD38G.js → setup-B-WOti3H.js} +2 -2
  15. package/dist/assets/{streamEvents-Ba9kHw-1.js → streamEvents-CIqegoLa.js} +1 -1
  16. package/dist/assets/{studioGateApi-hkZdLr1Y.js → studioGateApi-CFtez6lH.js} +1 -1
  17. package/dist/assets/{target-scripts-8hczu84t.js → target-scripts-CI-nAISO.js} +1 -1
  18. package/dist/assets/useStudioTerminal-I8tuBymw.js +1 -0
  19. package/dist/assets/vibe64SessionPanelModel-DLdexNxC.js +1 -0
  20. package/dist/index.html +1 -1
  21. package/node_modules/@local/setup-doctor-core/src/server/doctorToolchain.js +4 -0
  22. package/node_modules/@local/studio-terminal-core/src/server/gitGithubTransport.js +33 -0
  23. package/node_modules/@local/studio-terminal-core/src/server/index.js +1 -0
  24. package/node_modules/@local/studio-terminal-core/src/server/terminalSessions.js +51 -1
  25. package/node_modules/@local/vibe64-adapters/src/server/adapter.js +4 -0
  26. package/node_modules/@local/vibe64-adapters/src/server/adapters/laravel/adapter.js +5 -0
  27. package/node_modules/@local/vibe64-adapters/src/server/adapters/laravel/databaseRuntime.js +50 -0
  28. package/node_modules/@local/vibe64-adapters/src/server/configStore.js +22 -1
  29. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/agent_conversation.txt +0 -2
  30. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/draft_issue.txt +18 -0
  31. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/make_plan.txt +14 -2
  32. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/prepare_for_merge.txt +2 -0
  33. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/resolve_pull_request.txt +1 -0
  34. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/run_deep_ui_check.txt +7 -3
  35. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/commitPush.js +4 -22
  36. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/factMetadata.js +21 -20
  37. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/issuePr.js +27 -4
  38. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/mergeSync.js +65 -8
  39. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/worktreeDependencies.js +12 -25
  40. package/node_modules/@local/vibe64-adapters/src/server/workflowSessionActions.js +77 -20
  41. package/node_modules/@local/vibe64-core/src/server/terminalWebSocketRoutes.js +14 -5
  42. package/node_modules/@local/vibe64-project/src/server/actions.js +21 -0
  43. package/node_modules/@local/vibe64-project/src/server/registerRoutes.js +6 -0
  44. package/node_modules/@local/vibe64-project/src/server/service.js +125 -8
  45. package/node_modules/@local/vibe64-runtime/src/server/coreProjectTools.js +135 -0
  46. package/node_modules/@local/vibe64-runtime/src/server/index.js +4 -0
  47. package/node_modules/@local/vibe64-runtime/src/server/projectToolRegistry.js +434 -0
  48. package/node_modules/@local/vibe64-runtime/src/server/runtime.js +40 -16
  49. package/node_modules/@local/vibe64-runtime/src/server/sessionWorktreeState.js +25 -0
  50. package/node_modules/@local/vibe64-runtime/src/server/terminalFailureFixRequest.js +112 -0
  51. package/node_modules/@local/vibe64-runtime/src/server/workflowArtifacts.js +2 -2
  52. package/node_modules/@local/vibe64-runtime/src/server/workflowDefinitionBuilders.js +1 -0
  53. package/node_modules/@local/vibe64-runtime/src/server/workflowDefinitionComposers.js +192 -0
  54. package/node_modules/@local/vibe64-runtime/src/server/workflowMachine.js +5 -0
  55. package/node_modules/@local/vibe64-runtime/src/server/workflowModules/coreCoding.js +1309 -419
  56. package/node_modules/@local/vibe64-runtime/src/server/workflowModules/coreLifecycle.js +540 -358
  57. package/node_modules/@local/vibe64-runtime/src/server/workflowModules/coreMaintenance.js +5 -26
  58. package/node_modules/@local/vibe64-runtime/src/server/workflowPresentation.js +153 -26
  59. package/node_modules/@local/vibe64-runtime/src/server/workflowStepMachineHelpers.js +63 -10
  60. package/node_modules/@local/vibe64-runtime/src/server/workflowStepMachines.js +63 -2
  61. package/node_modules/@local/vibe64-sessions/src/server/inputSchemas.js +5 -0
  62. package/node_modules/@local/vibe64-sessions/src/server/service.js +8 -9
  63. package/node_modules/@local/vibe64-terminals/src/server/actions.js +65 -0
  64. package/node_modules/@local/vibe64-terminals/src/server/codexTerminal.js +608 -23
  65. package/node_modules/@local/vibe64-terminals/src/server/commandTerminal.js +261 -4
  66. package/node_modules/@local/vibe64-terminals/src/server/fixCodexJobs.js +420 -0
  67. package/node_modules/@local/vibe64-terminals/src/server/inputSchemas.js +240 -0
  68. package/node_modules/@local/vibe64-terminals/src/server/launchTargetTerminal.js +2 -0
  69. package/node_modules/@local/vibe64-terminals/src/server/registerRoutes.js +226 -0
  70. package/node_modules/@local/vibe64-terminals/src/server/service.js +140 -1
  71. package/node_modules/@local/vibe64-terminals/src/server/targetToolchainTerminal.js +1 -1
  72. package/node_modules/@local/vibe64-terminals/src/server/terminalShared.js +34 -0
  73. package/node_modules/node-pty/build/Makefile +369 -0
  74. package/node_modules/node-pty/build/Release/pty.node +0 -0
  75. package/node_modules/node-pty/build/binding.Makefile +6 -0
  76. package/node_modules/node-pty/build/config.gypi +440 -0
  77. package/node_modules/node-pty/build/pty.target.mk +166 -0
  78. package/node_modules/node-pty/node-addon-api/node_addon_api.Makefile +6 -0
  79. package/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +104 -0
  80. package/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +108 -0
  81. package/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +104 -0
  82. package/node_modules/which/CHANGELOG.md +166 -0
  83. package/package.json +2 -2
  84. package/packages/setup-doctor-core/src/server/doctorToolchain.js +4 -0
  85. package/packages/studio-terminal-core/src/server/gitGithubTransport.js +33 -0
  86. package/packages/studio-terminal-core/src/server/index.js +1 -0
  87. package/packages/studio-terminal-core/src/server/terminalSessions.js +51 -1
  88. package/packages/vibe64-adapters/src/server/adapter.js +4 -0
  89. package/packages/vibe64-adapters/src/server/adapters/laravel/adapter.js +5 -0
  90. package/packages/vibe64-adapters/src/server/adapters/laravel/databaseRuntime.js +50 -0
  91. package/packages/vibe64-adapters/src/server/configStore.js +22 -1
  92. package/packages/vibe64-adapters/src/server/systemPrompts/agent_conversation.txt +0 -2
  93. package/packages/vibe64-adapters/src/server/systemPrompts/draft_issue.txt +18 -0
  94. package/packages/vibe64-adapters/src/server/systemPrompts/make_plan.txt +14 -2
  95. package/packages/vibe64-adapters/src/server/systemPrompts/prepare_for_merge.txt +2 -0
  96. package/packages/vibe64-adapters/src/server/systemPrompts/resolve_pull_request.txt +1 -0
  97. package/packages/vibe64-adapters/src/server/systemPrompts/run_deep_ui_check.txt +7 -3
  98. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/commitPush.js +4 -22
  99. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/factMetadata.js +21 -20
  100. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/issuePr.js +27 -4
  101. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/mergeSync.js +65 -8
  102. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/worktreeDependencies.js +12 -25
  103. package/packages/vibe64-adapters/src/server/workflowSessionActions.js +77 -20
  104. package/packages/vibe64-core/src/server/terminalWebSocketRoutes.js +14 -5
  105. package/packages/vibe64-project/src/server/actions.js +21 -0
  106. package/packages/vibe64-project/src/server/registerRoutes.js +6 -0
  107. package/packages/vibe64-project/src/server/service.js +125 -8
  108. package/packages/vibe64-runtime/src/server/coreProjectTools.js +135 -0
  109. package/packages/vibe64-runtime/src/server/index.js +4 -0
  110. package/packages/vibe64-runtime/src/server/projectToolRegistry.js +434 -0
  111. package/packages/vibe64-runtime/src/server/runtime.js +40 -16
  112. package/packages/vibe64-runtime/src/server/sessionWorktreeState.js +25 -0
  113. package/packages/vibe64-runtime/src/server/terminalFailureFixRequest.js +112 -0
  114. package/packages/vibe64-runtime/src/server/workflowArtifacts.js +2 -2
  115. package/packages/vibe64-runtime/src/server/workflowDefinitionBuilders.js +1 -0
  116. package/packages/vibe64-runtime/src/server/workflowDefinitionComposers.js +192 -0
  117. package/packages/vibe64-runtime/src/server/workflowMachine.js +5 -0
  118. package/packages/vibe64-runtime/src/server/workflowModules/coreCoding.js +1309 -419
  119. package/packages/vibe64-runtime/src/server/workflowModules/coreLifecycle.js +540 -358
  120. package/packages/vibe64-runtime/src/server/workflowModules/coreMaintenance.js +5 -26
  121. package/packages/vibe64-runtime/src/server/workflowPresentation.js +153 -26
  122. package/packages/vibe64-runtime/src/server/workflowStepMachineHelpers.js +63 -10
  123. package/packages/vibe64-runtime/src/server/workflowStepMachines.js +63 -2
  124. package/packages/vibe64-sessions/src/server/inputSchemas.js +5 -0
  125. package/packages/vibe64-sessions/src/server/service.js +8 -9
  126. package/packages/vibe64-terminals/src/server/actions.js +65 -0
  127. package/packages/vibe64-terminals/src/server/codexTerminal.js +608 -23
  128. package/packages/vibe64-terminals/src/server/commandTerminal.js +261 -4
  129. package/packages/vibe64-terminals/src/server/fixCodexJobs.js +420 -0
  130. package/packages/vibe64-terminals/src/server/inputSchemas.js +240 -0
  131. package/packages/vibe64-terminals/src/server/launchTargetTerminal.js +2 -0
  132. package/packages/vibe64-terminals/src/server/registerRoutes.js +226 -0
  133. package/packages/vibe64-terminals/src/server/service.js +140 -1
  134. package/packages/vibe64-terminals/src/server/targetToolchainTerminal.js +1 -1
  135. package/packages/vibe64-terminals/src/server/terminalShared.js +34 -0
  136. package/dist/assets/ProjectTypeGate-DStq4W4X.js +0 -1
  137. package/dist/assets/ProjectTypeGate-Dh2ycSoM.css +0 -1
  138. package/dist/assets/history-HQ_XliX2.js +0 -1
  139. package/dist/assets/home-B89EbUmA.js +0 -1
  140. package/dist/assets/index-16P0GeGq.js +0 -134
  141. package/dist/assets/index-eMhOXhf_.css +0 -1
  142. package/dist/assets/useStudioTerminal-D9TNb50w.js +0 -1
  143. package/dist/assets/vibe64SessionPanelModel-DvY_IbW3.js +0 -1
@@ -43,6 +43,8 @@ import {
43
43
  codexTerminalNamespace,
44
44
  directoryExists,
45
45
  dockerCommand,
46
+ fixCodexTerminalNamespace,
47
+ globalCodexTerminalNamespace,
46
48
  stableHash,
47
49
  terminalTargetRoot,
48
50
  terminalWorktreePath
@@ -68,6 +70,11 @@ import {
68
70
  import {
69
71
  targetToolchainTerminalArgs
70
72
  } from "./targetToolchainTerminal.js";
73
+ import {
74
+ defaultFixCodexJobStore,
75
+ fixCodexReportInstructions,
76
+ prepareFixCodexReportHelper
77
+ } from "./fixCodexJobs.js";
71
78
 
72
79
  const CODEX_THREAD_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
73
80
  const CODEX_THREAD_ID_TOKEN_PATTERN = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/giu;
@@ -99,6 +106,7 @@ const CODEX_BOOTSTRAP_TASK_ID = "codex_bootstrap";
99
106
  const START_CODEX_TERMINAL_CONTROL_ACTION = "start_codex_terminal";
100
107
  const MAX_OPEN_CODEX_TERMINALS = 3;
101
108
  const STUDIO_DAEMON_ID = crypto.randomUUID();
109
+ const GLOBAL_CODEX_TERMINAL_SCOPE = "global";
102
110
  const CODEX_TURN_STATE = Object.freeze({
103
111
  IDLE: "idle",
104
112
  TRANSMITTING: "transmitting"
@@ -112,6 +120,13 @@ function errorMessage(value, fallback = "Codex could not be prepared.") {
112
120
  return normalizeText(value?.error || value?.message || value) || fallback;
113
121
  }
114
122
 
123
+ function retryableTerminalFailure(result = {}) {
124
+ return {
125
+ ...result,
126
+ retryable: false
127
+ };
128
+ }
129
+
115
130
  function delay(ms) {
116
131
  return new Promise((resolve) => {
117
132
  setTimeout(resolve, ms);
@@ -149,9 +164,37 @@ async function terminalTargetRootForSession(projectService, sessionId) {
149
164
  try {
150
165
  const runtime = await projectService.createRuntime();
151
166
  const session = await runtime.getSession(sessionId);
152
- return terminalTargetRoot(session, projectService);
167
+ return terminalTargetRoot(session, projectService) ||
168
+ await globalCodexTargetRoot(projectService, runtime);
169
+ } catch {
170
+ return globalCodexTargetRoot(projectService);
171
+ }
172
+ }
173
+
174
+ async function globalCodexTargetRoot(projectService = {}, runtime = null) {
175
+ const serviceRoot = terminalTargetRoot({}, projectService);
176
+ if (serviceRoot) {
177
+ return serviceRoot;
178
+ }
179
+
180
+ const runtimeRoot = terminalTargetRoot({
181
+ targetRoot: runtime?.targetRoot
182
+ });
183
+ if (runtimeRoot) {
184
+ return runtimeRoot;
185
+ }
186
+
187
+ if (typeof projectService.readProjectType !== "function") {
188
+ return "";
189
+ }
190
+
191
+ try {
192
+ const projectType = await projectService.readProjectType();
193
+ return terminalTargetRoot({
194
+ targetRoot: projectType?.projectType?.targetRoot || projectType?.targetRoot
195
+ });
153
196
  } catch {
154
- return terminalTargetRoot({}, projectService);
197
+ return "";
155
198
  }
156
199
  }
157
200
 
@@ -235,6 +278,34 @@ function codexTerminalSnapshot(sessionId = "", terminalSessionId = "") {
235
278
  });
236
279
  }
237
280
 
281
+ function globalCodexTerminalSnapshot(terminalSessionId = "") {
282
+ return readTerminalSession(terminalSessionId, {
283
+ namespace: globalCodexTerminalNamespace()
284
+ });
285
+ }
286
+
287
+ function codexTerminalStatus(terminal = null) {
288
+ if (!terminal) {
289
+ return null;
290
+ }
291
+ return {
292
+ activityLabel: terminal.metadata?.codexTurnLabel || "",
293
+ activityStartedAt: terminal.metadata?.codexTurnStartedAt || "",
294
+ activityFinishedAt: terminal.metadata?.codexTurnFinishedAt || "",
295
+ activityReason: terminal.metadata?.codexTurnReason || "",
296
+ commandPreview: terminal.commandPreview || "",
297
+ id: terminal.id || "",
298
+ inputVersion: terminal.inputVersion || 0,
299
+ lastInputAt: terminal.lastInputAt || "",
300
+ lastInputBytes: terminal.lastInputBytes || 0,
301
+ lastOutputAt: terminal.lastOutputAt || "",
302
+ lastOutputBytes: terminal.lastOutputBytes || 0,
303
+ outputVersion: terminal.outputVersion || 0,
304
+ status: terminal.status || "",
305
+ transmitting: terminal.metadata?.codexTurnState === CODEX_TURN_STATE.TRANSMITTING
306
+ };
307
+ }
308
+
238
309
  function activeCodexTerminal(session = {}) {
239
310
  const sessionId = normalizeText(session.sessionId);
240
311
  if (!sessionId) {
@@ -248,17 +319,17 @@ function activeCodexTerminal(session = {}) {
248
319
  .filter((terminal) => !workdir || terminal.metadata?.workdir === workdir)
249
320
  .sort((left, right) => String(right.createdAt || "").localeCompare(String(left.createdAt || "")));
250
321
  const terminal = terminals[0] || null;
251
- if (!terminal) {
252
- return null;
253
- }
254
- return {
255
- activityLabel: terminal.metadata?.codexTurnLabel || "",
256
- activityReason: terminal.metadata?.codexTurnReason || "",
257
- commandPreview: terminal.commandPreview || "",
258
- id: terminal.id || "",
259
- status: terminal.status || "",
260
- transmitting: terminal.metadata?.codexTurnState === CODEX_TURN_STATE.TRANSMITTING
261
- };
322
+ return codexTerminalStatus(terminal);
323
+ }
324
+
325
+ function activeGlobalCodexTerminal(targetRoot = "") {
326
+ const terminals = listTerminalSessions({
327
+ namespace: globalCodexTerminalNamespace()
328
+ })
329
+ .filter((terminal) => terminal.status !== "exited")
330
+ .filter((terminal) => !targetRoot || terminal.metadata?.targetRoot === targetRoot)
331
+ .sort((left, right) => String(right.createdAt || "").localeCompare(String(left.createdAt || "")));
332
+ return codexTerminalStatus(terminals[0] || null);
262
333
  }
263
334
 
264
335
  function writeCodexTerminalInput(sessionId = "", terminalSessionId = "", data = "") {
@@ -286,7 +357,7 @@ function codexTurnLabel(reason = "") {
286
357
  case "codex-prompt-injection-started":
287
358
  return "Sending prompt to Codex...";
288
359
  default:
289
- return "Terminal is transmitting...";
360
+ return "Codex is thinking...";
290
361
  }
291
362
  }
292
363
 
@@ -429,8 +500,13 @@ function codexTerminalArgs({
429
500
  });
430
501
  }
431
502
 
432
- function codexContainerName({ sessionId, terminalId }) {
433
- return `${STUDIO_CODEX_CONTAINER_PREFIX}-${stableHash(sessionId)}-${stableHash(terminalId)}`;
503
+ function codexContainerName({
504
+ scope = "",
505
+ sessionId = "",
506
+ terminalId = ""
507
+ } = {}) {
508
+ const containerScope = normalizeText(scope || sessionId || GLOBAL_CODEX_TERMINAL_SCOPE);
509
+ return `${STUDIO_CODEX_CONTAINER_PREFIX}-${stableHash(containerScope)}-${stableHash(terminalId)}`;
434
510
  }
435
511
 
436
512
  function maskedCodexTerminalDockerArgs(args = []) {
@@ -438,6 +514,7 @@ function maskedCodexTerminalDockerArgs(args = []) {
438
514
  }
439
515
 
440
516
  function createCodexTerminalController({
517
+ fixJobStore = defaultFixCodexJobStore,
441
518
  projectService,
442
519
  publishPromptInjected = async () => null,
443
520
  publishSessionChanged = async () => null
@@ -449,25 +526,25 @@ function createCodexTerminalController({
449
526
  const session = await runtime.getSession(sessionId);
450
527
  const targetRoot = terminalTargetRoot(session, projectService);
451
528
  if (!targetRoot) {
452
- return {
529
+ return retryableTerminalFailure({
453
530
  ok: false,
454
531
  error: "Vibe64 Codex target root is not available."
455
- };
532
+ });
456
533
  }
457
534
  const workdir = terminalWorktreePath(session);
458
535
  if (!workdir || !containerWorkspacePath(targetRoot, workdir)) {
459
- return {
536
+ return retryableTerminalFailure({
460
537
  ok: false,
461
538
  error: workdir
462
539
  ? "Vibe64 Codex workdir is outside the target root."
463
540
  : "Create the session worktree before starting Codex."
464
- };
541
+ });
465
542
  }
466
543
  if (!await directoryExists(workdir)) {
467
- return {
544
+ return retryableTerminalFailure({
468
545
  ok: false,
469
546
  error: `Session worktree directory does not exist: ${workdir}`
470
- };
547
+ });
471
548
  }
472
549
  const imageResult = await resolveTerminalToolchainImage({
473
550
  runtime,
@@ -556,6 +633,102 @@ function createCodexTerminalController({
556
633
  return withCodexState(terminalResponse, session);
557
634
  }
558
635
 
636
+ async function startGlobalCodexTerminalSession() {
637
+ const runtime = await projectService.createRuntime();
638
+ const targetRoot = await globalCodexTargetRoot(projectService, runtime);
639
+ if (!targetRoot) {
640
+ return retryableTerminalFailure({
641
+ ok: false,
642
+ error: "Global Codex target root is not available."
643
+ });
644
+ }
645
+ if (!await directoryExists(targetRoot)) {
646
+ return retryableTerminalFailure({
647
+ ok: false,
648
+ error: `Main repo directory does not exist: ${targetRoot}`
649
+ });
650
+ }
651
+
652
+ const session = {
653
+ targetRoot
654
+ };
655
+ const imageResult = await resolveTerminalToolchainImage({
656
+ runtime,
657
+ session,
658
+ target: "codex",
659
+ targetRoot
660
+ });
661
+ if (imageResult.ok === false) {
662
+ return imageResult;
663
+ }
664
+
665
+ await prepareCodexAttachmentRoot();
666
+ await ensureTargetRuntimeNetwork(targetRoot);
667
+ await ensureAdapterRuntimeContainers({
668
+ runtime,
669
+ session,
670
+ target: "codex",
671
+ targetRoot
672
+ });
673
+ const terminalEnv = await projectTerminalEnvironment({
674
+ projectService,
675
+ runtime,
676
+ session,
677
+ target: "codex",
678
+ targetRoot
679
+ });
680
+ const terminalEnvHash = terminalEnvironmentFingerprint(terminalEnv);
681
+ const namespace = globalCodexTerminalNamespace();
682
+ const terminalResponse = startTerminalSession({
683
+ args: ({ id }) => codexTerminalArgs({
684
+ codexThreadId: "",
685
+ containerName: codexContainerName({
686
+ scope: GLOBAL_CODEX_TERMINAL_SCOPE,
687
+ terminalId: id
688
+ }),
689
+ env: terminalEnv,
690
+ image: imageResult.image,
691
+ sessionId: "",
692
+ targetRoot,
693
+ terminalId: id,
694
+ worktree: targetRoot
695
+ }),
696
+ command: "docker",
697
+ commandPreview: ({ args }) => dockerCommand(maskedCodexTerminalDockerArgs(args)),
698
+ cwd: targetRoot,
699
+ maxRunning: MAX_OPEN_CODEX_TERMINALS,
700
+ metadata: {
701
+ envHash: terminalEnvHash,
702
+ image: imageResult.image,
703
+ imageLabel: imageResult.label,
704
+ scope: GLOBAL_CODEX_TERMINAL_SCOPE,
705
+ targetRoot,
706
+ workdir: targetRoot
707
+ },
708
+ namespace,
709
+ onClose: async ({ id }) => {
710
+ await removeDockerContainer(codexContainerName({
711
+ scope: GLOBAL_CODEX_TERMINAL_SCOPE,
712
+ terminalId: id
713
+ }));
714
+ await cleanupCodexAttachments(targetRoot, GLOBAL_CODEX_TERMINAL_SCOPE);
715
+ },
716
+ reuseRunning: (terminalSession) => {
717
+ return terminalSession.metadata?.scope === GLOBAL_CODEX_TERMINAL_SCOPE &&
718
+ terminalSession.metadata?.targetRoot === targetRoot &&
719
+ terminalSession.metadata?.envHash === terminalEnvHash &&
720
+ terminalSession.metadata?.image === imageResult.image &&
721
+ terminalSession.metadata?.workdir === targetRoot;
722
+ }
723
+ });
724
+ const codexTerminal = activeGlobalCodexTerminal(targetRoot);
725
+ return {
726
+ ...terminalResponse,
727
+ codexTerminal,
728
+ globalCodexTerminal: codexTerminal
729
+ };
730
+ }
731
+
559
732
  async function waitForCodexReady(sessionId, terminalSessionId) {
560
733
  const startedAt = Date.now();
561
734
  let lastOutput = "";
@@ -656,6 +829,16 @@ function createCodexTerminalController({
656
829
  );
657
830
  }
658
831
 
832
+ async function writePromptIntoGlobalCodexTerminal(terminalSessionId, prompt) {
833
+ return writeTerminalSession(
834
+ terminalSessionId,
835
+ `${PROMPT_INJECTION_PREFIX}${prompt}${PROMPT_INJECTION_SUFFIX}`,
836
+ {
837
+ namespace: globalCodexTerminalNamespace()
838
+ }
839
+ );
840
+ }
841
+
659
842
  async function markCodexTerminalTransmitting(sessionId, terminalSessionId, signature, reason) {
660
843
  const result = updateCodexTerminalMetadata(
661
844
  sessionId,
@@ -683,10 +866,290 @@ function createCodexTerminalController({
683
866
  return result;
684
867
  }
685
868
 
869
+ async function waitForGlobalCodexReady(terminalSessionId) {
870
+ const startedAt = Date.now();
871
+ let lastOutput = "";
872
+ let lastChangedAt = Date.now();
873
+ while (Date.now() - startedAt <= CODEX_BOOT_TIMEOUT_MS) {
874
+ const snapshot = globalCodexTerminalSnapshot(terminalSessionId);
875
+ if (snapshot.ok === false || snapshot.status === "exited") {
876
+ return {
877
+ ok: false,
878
+ error: snapshot.error || "Global Codex terminal is not running."
879
+ };
880
+ }
881
+ const output = String(snapshot.output || "");
882
+ if (codexTrustPromptLooksActive(output)) {
883
+ return {
884
+ ok: false,
885
+ error: "Answer the Codex trust prompt before sending this project tool prompt."
886
+ };
887
+ }
888
+ if (output !== lastOutput) {
889
+ lastOutput = output;
890
+ lastChangedAt = Date.now();
891
+ }
892
+ if (
893
+ output &&
894
+ Date.now() - startedAt >= CODEX_BOOT_MIN_AGE_MS &&
895
+ Date.now() - lastChangedAt >= CODEX_BOOT_QUIET_MS
896
+ ) {
897
+ return {
898
+ ok: true,
899
+ output
900
+ };
901
+ }
902
+ await delay(250);
903
+ }
904
+ return {
905
+ ok: true,
906
+ output: lastOutput
907
+ };
908
+ }
909
+
910
+ async function injectPromptIntoGlobalCodex(handoff = {}) {
911
+ const terminalInput = codexPromptHandoffTerminalInput(handoff);
912
+ if (!terminalInput) {
913
+ return {
914
+ ok: false,
915
+ error: "Codex prompt handoff is empty."
916
+ };
917
+ }
918
+
919
+ const terminalResponse = await startGlobalCodexTerminalSession();
920
+ if (terminalResponse.ok === false) {
921
+ return terminalResponse;
922
+ }
923
+ const terminalSessionId = terminalResponse.id || terminalResponse.terminalSessionId || "";
924
+ if (!terminalSessionId) {
925
+ return {
926
+ ok: false,
927
+ error: "Global Codex terminal did not start."
928
+ };
929
+ }
930
+
931
+ const ready = await waitForGlobalCodexReady(terminalSessionId);
932
+ if (ready.ok === false) {
933
+ return ready;
934
+ }
935
+
936
+ const snapshot = globalCodexTerminalSnapshot(terminalSessionId);
937
+ const outputStart = String(snapshot.output || "").length;
938
+ const injected = await writePromptIntoGlobalCodexTerminal(
939
+ terminalSessionId,
940
+ terminalInput
941
+ );
942
+ if (injected.ok === false) {
943
+ return injected;
944
+ }
945
+
946
+ const targetRoot = await globalCodexTargetRoot(projectService);
947
+ const codexTerminal = activeGlobalCodexTerminal(targetRoot);
948
+ return {
949
+ ...injected,
950
+ codexPromptInjected: true,
951
+ codexPromptHandoffOutputStart: outputStart,
952
+ codexTerminal,
953
+ globalCodexTerminal: codexTerminal,
954
+ terminalSessionId
955
+ };
956
+ }
957
+
958
+ async function waitForCodexReadyInNamespace(namespace = "", terminalSessionId = "") {
959
+ const startedAt = Date.now();
960
+ let lastOutput = "";
961
+ let lastChangedAt = Date.now();
962
+ while (Date.now() - startedAt <= CODEX_BOOT_TIMEOUT_MS) {
963
+ const snapshot = readTerminalSession(terminalSessionId, {
964
+ namespace
965
+ });
966
+ if (snapshot.ok === false || snapshot.status === "exited") {
967
+ return {
968
+ ok: false,
969
+ error: snapshot.error || "Fix Codex terminal is not running."
970
+ };
971
+ }
972
+ const output = String(snapshot.output || "");
973
+ if (codexTrustPromptLooksActive(output)) {
974
+ return {
975
+ ok: false,
976
+ error: "Answer the Codex trust prompt before sending this fix prompt."
977
+ };
978
+ }
979
+ if (output !== lastOutput) {
980
+ lastOutput = output;
981
+ lastChangedAt = Date.now();
982
+ }
983
+ if (
984
+ output &&
985
+ Date.now() - startedAt >= CODEX_BOOT_MIN_AGE_MS &&
986
+ Date.now() - lastChangedAt >= CODEX_BOOT_QUIET_MS
987
+ ) {
988
+ return {
989
+ ok: true,
990
+ output
991
+ };
992
+ }
993
+ await delay(250);
994
+ }
995
+ return {
996
+ ok: true,
997
+ output: lastOutput
998
+ };
999
+ }
1000
+
1001
+ async function startFixCodexJob(input = {}) {
1002
+ const runtime = await projectService.createRuntime();
1003
+ const targetRoot = terminalTargetRoot({
1004
+ targetRoot: input.targetRoot || projectService.targetRoot || runtime?.targetRoot
1005
+ });
1006
+ if (!targetRoot) {
1007
+ return retryableTerminalFailure({
1008
+ ok: false,
1009
+ error: "Fix Codex target root is not available."
1010
+ });
1011
+ }
1012
+ if (!await directoryExists(targetRoot)) {
1013
+ return retryableTerminalFailure({
1014
+ ok: false,
1015
+ error: `Main repo directory does not exist: ${targetRoot}`
1016
+ });
1017
+ }
1018
+ const workdir = path.resolve(normalizeText(input.workdir) || targetRoot);
1019
+ if (!containerWorkspacePath(targetRoot, workdir)) {
1020
+ return retryableTerminalFailure({
1021
+ ok: false,
1022
+ error: "Fix Codex workdir is outside the target root."
1023
+ });
1024
+ }
1025
+ if (!await directoryExists(workdir)) {
1026
+ return retryableTerminalFailure({
1027
+ ok: false,
1028
+ error: `Fix Codex workdir does not exist: ${workdir}`
1029
+ });
1030
+ }
1031
+ const jobSeed = fixJobStore.createJob({
1032
+ prompt: input.prompt,
1033
+ scope: input.scope || "project",
1034
+ subject: input.subject,
1035
+ targetRoot
1036
+ });
1037
+ const fullPrompt = [
1038
+ input.prompt,
1039
+ "",
1040
+ fixCodexReportInstructions(jobSeed)
1041
+ ].join("\n").trim();
1042
+ const jobId = jobSeed.job.id;
1043
+ const namespace = fixCodexTerminalNamespace(jobId);
1044
+ const session = {
1045
+ metadata: {
1046
+ worktree_path: workdir
1047
+ },
1048
+ targetRoot
1049
+ };
1050
+ const imageResult = await resolveTerminalToolchainImage({
1051
+ runtime,
1052
+ session,
1053
+ target: "fix-codex",
1054
+ targetRoot
1055
+ });
1056
+ if (imageResult.ok === false) {
1057
+ return imageResult;
1058
+ }
1059
+
1060
+ await prepareCodexAttachmentRoot();
1061
+ const reportHelper = await prepareFixCodexReportHelper({
1062
+ fixJobStore,
1063
+ jobId,
1064
+ targetRoot,
1065
+ token: jobSeed.token
1066
+ });
1067
+ await ensureTargetRuntimeNetwork(targetRoot);
1068
+ await ensureAdapterRuntimeContainers({
1069
+ runtime,
1070
+ session,
1071
+ target: "fix-codex",
1072
+ targetRoot
1073
+ });
1074
+ const terminalEnv = await projectTerminalEnvironment({
1075
+ projectService,
1076
+ runtime,
1077
+ session,
1078
+ target: "fix-codex",
1079
+ targetRoot
1080
+ });
1081
+ const terminalEnvHash = terminalEnvironmentFingerprint(terminalEnv);
1082
+ const terminalResponse = startTerminalSession({
1083
+ args: ({ id }) => codexTerminalArgs({
1084
+ codexThreadId: "",
1085
+ containerName: codexContainerName({
1086
+ scope: `fix:${jobId}`,
1087
+ terminalId: id
1088
+ }),
1089
+ env: {
1090
+ ...terminalEnv,
1091
+ ...reportHelper.env
1092
+ },
1093
+ helperMount: reportHelper.mount,
1094
+ image: imageResult.image,
1095
+ sessionId: "",
1096
+ targetRoot,
1097
+ terminalId: id,
1098
+ worktree: workdir
1099
+ }),
1100
+ command: "docker",
1101
+ commandPreview: ({ args }) => dockerCommand(maskedCodexTerminalDockerArgs(args)),
1102
+ cwd: targetRoot,
1103
+ maxRunning: 1,
1104
+ metadata: {
1105
+ envHash: terminalEnvHash,
1106
+ fixJobId: jobId,
1107
+ image: imageResult.image,
1108
+ imageLabel: imageResult.label,
1109
+ scope: "fix-codex",
1110
+ targetRoot,
1111
+ workdir
1112
+ },
1113
+ namespace,
1114
+ onClose: async ({ id }) => {
1115
+ await removeDockerContainer(codexContainerName({
1116
+ scope: `fix:${jobId}`,
1117
+ terminalId: id
1118
+ }));
1119
+ await cleanupCodexAttachments(targetRoot, `fix:${jobId}`);
1120
+ },
1121
+ reuseRunning: false
1122
+ });
1123
+ if (terminalResponse.ok === false) {
1124
+ return terminalResponse;
1125
+ }
1126
+
1127
+ const job = fixJobStore.attachTerminal(jobId, terminalResponse.id);
1128
+ void (async () => {
1129
+ const ready = await waitForCodexReadyInNamespace(namespace, terminalResponse.id);
1130
+ if (ready.ok === false) {
1131
+ return;
1132
+ }
1133
+ await writeTerminalSession(
1134
+ terminalResponse.id,
1135
+ `${PROMPT_INJECTION_PREFIX}${wrapPromptWithStudioContext(fullPrompt)}${PROMPT_INJECTION_SUFFIX}`,
1136
+ {
1137
+ namespace
1138
+ }
1139
+ );
1140
+ })();
1141
+
1142
+ return {
1143
+ ...terminalResponse,
1144
+ fixJob: job
1145
+ };
1146
+ }
1147
+
686
1148
  async function writeCodexBootstrapTaskEvent(runtime, sessionId, {
687
1149
  error = "",
688
1150
  kind = "",
689
1151
  message = "",
1152
+ retryable = true,
690
1153
  status = "running",
691
1154
  terminalSessionId = ""
692
1155
  } = {}) {
@@ -702,7 +1165,7 @@ function createCodexTerminalController({
702
1165
  kind: "codex_bootstrap",
703
1166
  label: "Codex bootstrap",
704
1167
  message: normalizeText(message),
705
- retry: status === "failed"
1168
+ retry: status === "failed" && retryable !== false
706
1169
  ? {
707
1170
  control: {
708
1171
  action: START_CODEX_TERMINAL_CONTROL_ACTION
@@ -749,6 +1212,7 @@ function createCodexTerminalController({
749
1212
  error: errorMessage(result),
750
1213
  kind: "failed",
751
1214
  message: "Codex bootstrap failed.",
1215
+ retryable: result?.retryable !== false,
752
1216
  status: "failed",
753
1217
  terminalSessionId
754
1218
  });
@@ -1016,6 +1480,18 @@ function createCodexTerminalController({
1016
1480
  }
1017
1481
 
1018
1482
  return Object.freeze({
1483
+ closeGlobalTerminal(terminalSessionId) {
1484
+ return closeTerminalSession(terminalSessionId, {
1485
+ namespace: globalCodexTerminalNamespace()
1486
+ });
1487
+ },
1488
+
1489
+ closeFixTerminal(jobId, terminalSessionId) {
1490
+ return closeTerminalSession(terminalSessionId, {
1491
+ namespace: fixCodexTerminalNamespace(jobId)
1492
+ });
1493
+ },
1494
+
1019
1495
  async closeAllForSession(sessionId) {
1020
1496
  await closeTerminalSessionsForNamespace(codexTerminalNamespace(sessionId));
1021
1497
  const targetRoot = await terminalTargetRootForSession(projectService, sessionId);
@@ -1030,6 +1506,29 @@ function createCodexTerminalController({
1030
1506
  });
1031
1507
  },
1032
1508
 
1509
+ readGlobalTerminal(terminalSessionId) {
1510
+ return vibe64Result(async () => {
1511
+ const targetRoot = await globalCodexTargetRoot(projectService);
1512
+ const snapshot = readTerminalSession(terminalSessionId, {
1513
+ namespace: globalCodexTerminalNamespace()
1514
+ });
1515
+ const codexTerminal = activeGlobalCodexTerminal(targetRoot);
1516
+ return {
1517
+ ...snapshot,
1518
+ codexTerminal,
1519
+ globalCodexTerminal: codexTerminal
1520
+ };
1521
+ });
1522
+ },
1523
+
1524
+ readFixTerminal(jobId, terminalSessionId) {
1525
+ return vibe64Result(async () => {
1526
+ return readTerminalSession(terminalSessionId, {
1527
+ namespace: fixCodexTerminalNamespace(jobId)
1528
+ });
1529
+ });
1530
+ },
1531
+
1033
1532
  readTerminal(sessionId, terminalSessionId) {
1034
1533
  return vibe64Result(async () => {
1035
1534
  const runtime = await projectService.createRuntime();
@@ -1046,6 +1545,27 @@ function createCodexTerminalController({
1046
1545
  });
1047
1546
  },
1048
1547
 
1548
+ async injectGlobalCodexPrompt(handoff = {}) {
1549
+ return vibe64Result(async () => {
1550
+ return injectPromptIntoGlobalCodex(handoff);
1551
+ });
1552
+ },
1553
+
1554
+ async startFixJob(input = {}) {
1555
+ return vibe64Result(async () => {
1556
+ return startFixCodexJob(input);
1557
+ });
1558
+ },
1559
+
1560
+ async reportFixJob(jobId, input = {}) {
1561
+ return vibe64Result(async () => {
1562
+ return {
1563
+ fixJob: fixJobStore.reportJob(jobId, input),
1564
+ ok: true
1565
+ };
1566
+ });
1567
+ },
1568
+
1049
1569
  async ensureThread(sessionId) {
1050
1570
  return vibe64Result(async () => {
1051
1571
  return ensureCodexThreadReady(sessionId);
@@ -1070,6 +1590,47 @@ function createCodexTerminalController({
1070
1590
  });
1071
1591
  },
1072
1592
 
1593
+ async startGlobalTerminal() {
1594
+ return vibe64Result(async () => {
1595
+ return startGlobalCodexTerminalSession();
1596
+ });
1597
+ },
1598
+
1599
+ async globalTerminalState() {
1600
+ return vibe64Result(async () => {
1601
+ const targetRoot = await globalCodexTargetRoot(projectService);
1602
+ const codexTerminal = activeGlobalCodexTerminal(targetRoot);
1603
+ return {
1604
+ codexTerminal,
1605
+ globalCodexTerminal: codexTerminal,
1606
+ ok: true
1607
+ };
1608
+ });
1609
+ },
1610
+
1611
+ subscribeGlobalTerminal(terminalSessionId, subscriber) {
1612
+ return vibe64Result(async () => {
1613
+ const targetRoot = await globalCodexTargetRoot(projectService);
1614
+ const subscribed = subscribeTerminalSession(terminalSessionId, subscriber, {
1615
+ namespace: globalCodexTerminalNamespace()
1616
+ });
1617
+ const codexTerminal = activeGlobalCodexTerminal(targetRoot);
1618
+ return {
1619
+ ...subscribed,
1620
+ codexTerminal,
1621
+ globalCodexTerminal: codexTerminal
1622
+ };
1623
+ });
1624
+ },
1625
+
1626
+ subscribeFixTerminal(jobId, terminalSessionId, subscriber) {
1627
+ return vibe64Result(async () => {
1628
+ return subscribeTerminalSession(terminalSessionId, subscriber, {
1629
+ namespace: fixCodexTerminalNamespace(jobId)
1630
+ });
1631
+ });
1632
+ },
1633
+
1073
1634
  subscribeTerminal(sessionId, terminalSessionId, subscriber) {
1074
1635
  return vibe64Result(async () => {
1075
1636
  const runtime = await projectService.createRuntime();
@@ -1105,10 +1666,34 @@ function createCodexTerminalController({
1105
1666
  });
1106
1667
  },
1107
1668
 
1669
+ writeGlobalTerminal(terminalSessionId, data) {
1670
+ return writeTerminalSession(terminalSessionId, data, {
1671
+ namespace: globalCodexTerminalNamespace()
1672
+ });
1673
+ },
1674
+
1675
+ writeFixTerminal(jobId, terminalSessionId, data) {
1676
+ return writeTerminalSession(terminalSessionId, data, {
1677
+ namespace: fixCodexTerminalNamespace(jobId)
1678
+ });
1679
+ },
1680
+
1108
1681
  resizeTerminal(sessionId, terminalSessionId, size) {
1109
1682
  return resizeTerminalSession(terminalSessionId, size, {
1110
1683
  namespace: codexTerminalNamespace(sessionId)
1111
1684
  });
1685
+ },
1686
+
1687
+ resizeGlobalTerminal(terminalSessionId, size) {
1688
+ return resizeTerminalSession(terminalSessionId, size, {
1689
+ namespace: globalCodexTerminalNamespace()
1690
+ });
1691
+ },
1692
+
1693
+ resizeFixTerminal(jobId, terminalSessionId, size) {
1694
+ return resizeTerminalSession(terminalSessionId, size, {
1695
+ namespace: fixCodexTerminalNamespace(jobId)
1696
+ });
1112
1697
  }
1113
1698
  });
1114
1699
  }