openmausbot 0.1.96 → 0.1.98

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 (185) hide show
  1. package/dist/assets/ActivityPanel-H6D3SD39.js +1 -0
  2. package/dist/assets/BotSettingsDialog-Dqz_AiBZ.js +7 -0
  3. package/dist/assets/CloudBackendPicker-iezpJFpF.js +1 -0
  4. package/dist/assets/ComputerPanel-DZPj-IWu.js +1 -0
  5. package/dist/assets/DesktopViewer-utONms1p.js +5 -0
  6. package/dist/assets/InspectorPanel-OVaBVrzC.js +5 -0
  7. package/dist/assets/KeyboardShortcutsModal-gk9mvHj_.js +1 -0
  8. package/dist/assets/LocalVmWorkspace-DLIvd2kC.js +1 -0
  9. package/dist/assets/MacLocalControl-bJv8yiPB.js +1 -0
  10. package/dist/assets/NewBotDialog-1qGOAdUM.js +2 -0
  11. package/dist/assets/RemoteAgentSettingsPanel-DqKr0HkO.js +1 -0
  12. package/dist/assets/RoutinesPage-BM2D4qGi.js +1 -0
  13. package/dist/assets/RoutinesSection-Dny9ra-c.js +1 -0
  14. package/dist/assets/SettingsModal-gC6XJJmt.js +11 -0
  15. package/dist/assets/TeamMapPage-B6fuu4r_.js +8 -0
  16. package/dist/assets/TriggersPanel-j0qTP2CO.js +1 -0
  17. package/dist/assets/VisibilitySection-DT0FqPvu.js +12 -0
  18. package/dist/assets/WebhooksPanel--YQyCjKO.js +3 -0
  19. package/dist/assets/{abnfDiagram-O67JEVCF-Dkbd2hcj.js → abnfDiagram-O67JEVCF-BsjcFX0-.js} +1 -1
  20. package/dist/assets/activity-BxOkayvD.js +1 -0
  21. package/dist/assets/{arc-Duj5Coy2.js → arc-CJNA94c6.js} +1 -1
  22. package/dist/assets/architectureDiagram-NJMV4G6O-dz2ud7lP.js +36 -0
  23. package/dist/assets/{blockDiagram-BEXU5L5S-CWDlTpXe.js → blockDiagram-BEXU5L5S-ChBEALoR.js} +1 -1
  24. package/dist/assets/brain-CFZ7PEXc.js +1 -0
  25. package/dist/assets/{c4Diagram-YGBWAQC7-B0t15PDc.js → c4Diagram-YGBWAQC7-KZNRKDQe.js} +1 -1
  26. package/dist/assets/channel-WhFyujhZ.js +1 -0
  27. package/dist/assets/{chunk-2Q5K7J3B-BJSCL-HV.js → chunk-2Q5K7J3B-BLLwmCET.js} +1 -1
  28. package/dist/assets/{chunk-3FUC2YCW-D3_ILccd.js → chunk-3FUC2YCW-CQxyreBZ.js} +2 -2
  29. package/dist/assets/{chunk-5VM5RSS4-D3dmwT_S.js → chunk-5VM5RSS4-D6sFMW0u.js} +1 -1
  30. package/dist/assets/{chunk-GTNCS2PH-Br73HFPD.js → chunk-GTNCS2PH-BaZ1YgLF.js} +1 -1
  31. package/dist/assets/{chunk-GWA4HPMP-uSsjxubC.js → chunk-GWA4HPMP-CcalphmC.js} +1 -1
  32. package/dist/assets/{chunk-JWPE2WC7-C40VWFyr.js → chunk-JWPE2WC7-CSk8R3ve.js} +1 -1
  33. package/dist/assets/{chunk-NETBCI7D-D6WNNYwU.js → chunk-NETBCI7D-CTmLjA57.js} +1 -1
  34. package/dist/assets/{chunk-WEXAMYUT-DOEhq64P.js → chunk-WEXAMYUT-CM9Z77Ne.js} +1 -1
  35. package/dist/assets/{chunk-XXDRQBXY-BqJEi6Pi.js → chunk-XXDRQBXY-B1fxpMS2.js} +1 -1
  36. package/dist/assets/{classDiagram-v2-NBCMYWYE-ByU_GnxT.js → classDiagram-v2-NBCMYWYE-DCCyoLpj.js} +1 -1
  37. package/dist/assets/computer-control-NLov352p.js +1 -0
  38. package/dist/assets/cose-bilkent-JH36ORCC-KyImBKvE.js +1 -0
  39. package/dist/assets/{cynefin-OW5HDTMX-CZWO7aYj.js → cynefin-OW5HDTMX-fsZc6MGa.js} +1 -1
  40. package/dist/assets/{cynefinDiagram-VND7K2PF-C70-w0la.js → cynefinDiagram-VND7K2PF-CGmHsShB.js} +1 -1
  41. package/dist/assets/{dagre-6A5THRUB-CnhjhExB.js → dagre-6A5THRUB-Dah1h-CH.js} +1 -1
  42. package/dist/assets/{diagram-22UHCM2B-bnjWCNb4.js → diagram-22UHCM2B-BIu71OyV.js} +1 -1
  43. package/dist/assets/{diagram-3UASUU5V-A4uTWoFV.js → diagram-3UASUU5V-gxhUB_Mu.js} +1 -1
  44. package/dist/assets/{diagram-ATOU4E4O-Zi6m3NUl.js → diagram-ATOU4E4O-CBhusUBn.js} +1 -1
  45. package/dist/assets/{diagram-CDSNMT55-DtCcmd5k.js → diagram-CDSNMT55-BdPrc86x.js} +1 -1
  46. package/dist/assets/{diagram-MLGK6HIB-DofuETS3.js → diagram-MLGK6HIB-Clp110R_.js} +1 -1
  47. package/dist/assets/{diagram-MPIPVDR6-Dw2T9PuU.js → diagram-MPIPVDR6-DJKfbugw.js} +1 -1
  48. package/dist/assets/{ebnfDiagram-ZINNZB2B-DbrwPiem.js → ebnfDiagram-ZINNZB2B-DnsltoBu.js} +1 -1
  49. package/dist/assets/{elk-276RUBZZ-BvCt1dCb.js → elk-276RUBZZ-jWdq6gqH.js} +1 -1
  50. package/dist/assets/{erDiagram-OPXOYQCR-Y-QKqPnU.js → erDiagram-OPXOYQCR-DArPVf8u.js} +1 -1
  51. package/dist/assets/{flowDiagram-KWPJA3E3-CDkL1B5w.js → flowDiagram-KWPJA3E3-D2HZ-2f7.js} +1 -1
  52. package/dist/assets/ganttDiagram-FUAMR5RP--o0KIxEo.js +292 -0
  53. package/dist/assets/{gitGraphDiagram-X574FWY7-nL9iFTCv.js → gitGraphDiagram-X574FWY7-CsoXr2D7.js} +1 -1
  54. package/dist/assets/image-plus-BbVjGHin.js +1 -0
  55. package/dist/assets/index-BrPW5HDO.css +1 -0
  56. package/dist/assets/index-C3NqfdVU.js +585 -0
  57. package/dist/assets/{index-DreDnjOu.js → index-CJTp9JEp.js} +1 -1
  58. package/dist/assets/{infoDiagram-VRGFBTTK-C7aHjzsf.js → infoDiagram-VRGFBTTK-g-6lNp7r.js} +1 -1
  59. package/dist/assets/{ishikawaDiagram-OU5B5YK6-KUZsNBTh.js → ishikawaDiagram-OU5B5YK6-B1d6qVTV.js} +1 -1
  60. package/dist/assets/{journeyDiagram-ZHPQQLJL-CGUuodFl.js → journeyDiagram-ZHPQQLJL-BTPuiU6T.js} +1 -1
  61. package/dist/assets/{kanban-definition-PNTS6WVX-Cy6r868Z.js → kanban-definition-PNTS6WVX-bDDuRJvP.js} +1 -1
  62. package/dist/assets/{linear-Bl669148.js → linear-BVVKbEMy.js} +1 -1
  63. package/dist/assets/{mermaid.core-86Xqz5Mr.js → mermaid.core-JJdoKyKB.js} +5 -5
  64. package/dist/assets/{mindmap-definition-NLK3R4M7-G4DzHLrd.js → mindmap-definition-NLK3R4M7-B4aE3T0q.js} +1 -1
  65. package/dist/assets/module-DCUsy2BQ.js +3 -0
  66. package/dist/assets/page-visible-BBo_Zm8g.js +1 -0
  67. package/dist/assets/{pegDiagram-GJSIUBJH-K4eruzY0.js → pegDiagram-GJSIUBJH-DFKQWpR7.js} +1 -1
  68. package/dist/assets/{pieDiagram-5QR66LMP-DYdR9PPq.js → pieDiagram-5QR66LMP-Iv7OKVJi.js} +1 -1
  69. package/dist/assets/{quadrantDiagram-O4NWA36T-BCAh0nEy.js → quadrantDiagram-O4NWA36T-U2YnfwBk.js} +1 -1
  70. package/dist/assets/{railroadDiagram-XR7U4H2S-p0dGRc4g.js → railroadDiagram-XR7U4H2S-CuPy6RqM.js} +1 -1
  71. package/dist/assets/remote-desktop-panel-BNEj7tUx.js +1 -0
  72. package/dist/assets/{requirementDiagram-PLB6GJNP-tLeBG0aL.js → requirementDiagram-PLB6GJNP-bMI5AK7T.js} +1 -1
  73. package/dist/assets/{sankeyDiagram-IPEJSGJF-QRuN16rV.js → sankeyDiagram-IPEJSGJF-BKcFE2WQ.js} +1 -1
  74. package/dist/assets/{sequenceDiagram-PO4LG4MO-ueT1nVoa.js → sequenceDiagram-PO4LG4MO-Bn9q88kl.js} +1 -1
  75. package/dist/assets/{sizeCapture-INFHLROL-wRS2zWg2.js → sizeCapture-INFHLROL-Cvmdq9HD.js} +1 -1
  76. package/dist/assets/{stateDiagram-v2-GCMORJYK-CYzA_hE1.js → stateDiagram-v2-GCMORJYK-JJQYw3eQ.js} +1 -1
  77. package/dist/assets/{swimlanes-2SLR337P-kDnv6LMc.js → swimlanes-2SLR337P-BkSCBEwp.js} +1 -1
  78. package/dist/assets/swimlanesDiagram-TC7HE7FX-CmTirbVT.js +8 -0
  79. package/dist/assets/table-file.worker-KkMx-SNx.js +10 -0
  80. package/dist/assets/{timeline-definition-EJHVYXUP-D1y2UbbH.js → timeline-definition-EJHVYXUP-DsaM4GHr.js} +1 -1
  81. package/dist/assets/{usecaseDiagram-POWQR4AR-IqB4v9HX.js → usecaseDiagram-POWQR4AR-3FOwLq7B.js} +1 -1
  82. package/dist/assets/user-DcZBnAuv.js +1 -0
  83. package/dist/assets/{vennDiagram-UO4OBE2U-BEi7KYVF.js → vennDiagram-UO4OBE2U-DyNjJsKt.js} +1 -1
  84. package/dist/assets/{wardleyDiagram-VNRHLVJA-Dkybo-Yf.js → wardleyDiagram-VNRHLVJA-Y4ZMcnBC.js} +1 -1
  85. package/dist/assets/{xychartDiagram-PMCCYNJV-BAPFJLpg.js → xychartDiagram-PMCCYNJV-BXZpg955.js} +1 -1
  86. package/dist/index.html +2 -2
  87. package/dist-server/cloud-home-start.js +20 -9
  88. package/dist-server/container-mcp.js +8 -0
  89. package/dist-server/desktop-entry.mjs +54 -0
  90. package/dist-server/drivers/agents-proxy.js +26 -9
  91. package/dist-server/index.js +3734 -2360
  92. package/dist-server/openmausbot.js +1664 -1553
  93. package/dist-server/pair-cli.js +1664 -1553
  94. package/dist-server/permission-proxy.js +2 -4
  95. package/dist-server/server/atomic.js +70 -2
  96. package/dist-server/server/auto-approve.js +1 -1
  97. package/dist-server/server/auto-vm-claims.js +13 -1
  98. package/dist-server/server/automatic-recovery.js +1 -2
  99. package/dist-server/server/boat.js +68 -84
  100. package/dist-server/server/bot-overview.js +1 -1
  101. package/dist-server/server/browser-engine.js +38 -1
  102. package/dist-server/server/browser-live.js +112 -25
  103. package/dist-server/server/browser-runtime.js +31 -1
  104. package/dist-server/server/checkpoints.js +275 -44
  105. package/dist-server/server/cli-setup.js +3 -3
  106. package/dist-server/server/cloud-computer-tools.js +11 -4
  107. package/dist-server/server/cloud-home-start.js +4 -4
  108. package/dist-server/server/cloud-home.js +3 -9
  109. package/dist-server/server/cloud-owner.js +1 -1
  110. package/dist-server/server/computer-engine-removal.js +70 -0
  111. package/dist-server/server/computer-selection.js +18 -0
  112. package/dist-server/server/config.js +29 -12
  113. package/dist-server/server/connector-card-text.js +15 -0
  114. package/dist-server/server/connector-scope-hint.js +83 -0
  115. package/dist-server/server/default-model-selection.js +23 -14
  116. package/dist-server/server/delegations.js +11 -5
  117. package/dist-server/server/delta-context.js +6 -1
  118. package/dist-server/server/drivers/acp/core.js +11 -1
  119. package/dist-server/server/drivers/acp/grok.js +47 -5
  120. package/dist-server/server/drivers/acp/opencode-go.js +16 -21
  121. package/dist-server/server/drivers/agents-call.js +1 -1
  122. package/dist-server/server/drivers/agents-catalog.js +27 -7
  123. package/dist-server/server/drivers/agents-proxy.js +1 -0
  124. package/dist-server/server/drivers/builtIn.js +0 -2
  125. package/dist-server/server/drivers/chat-mcp-tools.js +5 -3
  126. package/dist-server/server/drivers/claude-login-auth.js +1 -1
  127. package/dist-server/server/drivers/claude.js +84 -41
  128. package/dist-server/server/drivers/codex-device-auth.js +27 -319
  129. package/dist-server/server/drivers/codex.js +2 -2
  130. package/dist-server/server/drivers/device-auth.js +342 -0
  131. package/dist-server/server/drivers/openai-chat.js +110 -10
  132. package/dist-server/server/drivers/pi.js +184 -49
  133. package/dist-server/server/fleet-agent.js +18 -5
  134. package/dist-server/server/harness/http.js +5 -2
  135. package/dist-server/server/harness/registry.js +19 -0
  136. package/dist-server/server/harness-capabilities.js +7 -4
  137. package/dist-server/server/hosted-models.js +3 -1
  138. package/dist-server/server/index.js +823 -333
  139. package/dist-server/server/key-rejections.js +57 -0
  140. package/dist-server/server/live-call.js +11 -6
  141. package/dist-server/server/managed-policy.js +1 -1
  142. package/dist-server/server/message-file.js +7 -4
  143. package/dist-server/server/model-catalog/presets.js +8 -0
  144. package/dist-server/server/peer-roster.js +10 -2
  145. package/dist-server/server/permission-proxy.js +4 -0
  146. package/dist-server/server/provider-key-check.js +5 -1
  147. package/dist-server/server/request-auth.js +1 -1
  148. package/dist-server/server/room-turn-end.js +15 -0
  149. package/dist-server/server/room-turn-timeout.js +28 -0
  150. package/dist-server/server/routes/live.js +3 -3
  151. package/dist-server/server/routes/thread-models.js +36 -0
  152. package/dist-server/server/routine-requests.js +1 -1
  153. package/dist-server/server/routines.js +3 -3
  154. package/dist-server/server/screen-frame-gate.js +1 -3
  155. package/dist-server/server/skills.js +3 -2
  156. package/dist-server/server/store.js +273 -61
  157. package/dist-server/server/surface.js +29 -49
  158. package/dist-server/server/system-prompt.js +10 -10
  159. package/dist-server/server/team-backup.js +19 -4
  160. package/dist-server/server/thread-model.js +25 -0
  161. package/dist-server/server/turn-continuation.js +168 -0
  162. package/dist-server/server/webhook-ingress.js +8 -3
  163. package/dist-server/server/webhooks.js +40 -5
  164. package/dist-server/server/workspace.js +1 -1
  165. package/dist-server/shared/ask-question.js +0 -70
  166. package/dist-server/shared/cloud-computer.js +4 -6
  167. package/dist-server/shared/credential-request.js +1 -1
  168. package/dist-server/shared/device-sign-in.js +57 -0
  169. package/dist-server/shared/failed-turn.js +1 -4
  170. package/dist-server/shared/place-view.js +409 -0
  171. package/dist-server/shared/team-backup.js +2 -0
  172. package/dist-server/shared/thread-model.js +13 -0
  173. package/dist-server/shared/tool-scope-support.js +1 -2
  174. package/dist-server/vps-container-mcp.js +8 -0
  175. package/dist-server/workspace-backup.worker.js +41 -22
  176. package/package.json +1 -1
  177. package/dist/assets/DesktopViewer-DsnA23KM.js +0 -5
  178. package/dist/assets/architectureDiagram-NJMV4G6O-uYUsDawP.js +0 -36
  179. package/dist/assets/channel-BZxwC-Gw.js +0 -1
  180. package/dist/assets/cose-bilkent-JH36ORCC-D-Uglxqq.js +0 -1
  181. package/dist/assets/ganttDiagram-FUAMR5RP-CKV5D2F6.js +0 -292
  182. package/dist/assets/index-Du7o6Dsf.js +0 -610
  183. package/dist/assets/index-KxG4bWSr.css +0 -1
  184. package/dist/assets/swimlanesDiagram-TC7HE7FX-C7voMDle.js +0 -8
  185. package/dist-server/server/drivers/boatagent.js +0 -443
@@ -1,35 +1,12 @@
1
- import { randomUUID } from "node:crypto";
2
- import { realpathSync } from "node:fs";
3
- import { homedir } from "node:os";
4
- import { basename, dirname, isAbsolute, join, resolve } from "node:path";
1
+ // Codex's half of the in-app device-code sign-in (device-auth.ts): `codex
2
+ // login --device-auth` for a ChatGPT account, with `codex login status` to
3
+ // keep a working login and to confirm the new one, and `codex logout` for
4
+ // Settings' sign-out.
5
5
  import { stripVTControlCharacters } from "node:util";
6
- import { killCliTree, spawnCli } from "../procs.js";
7
- const DEVICE_URL = "https://auth.openai.com/codex/device";
8
- const MAX_OUTPUT = 16_384;
9
- // Two configured instances can use the same on-disk login. Only the auth
10
- // operation is exclusive: normal turns are not blocked by this lock.
11
- const authenticatingHomes = new Set();
12
- /** The real path of a credential home, so two spellings of one home share
13
- * one sign-in lock. A missing tail keeps its name under its real parent. */
14
- export function canonicalPath(path) {
15
- try {
16
- return realpathSync(path);
17
- }
18
- catch {
19
- const parent = dirname(path);
20
- return parent === path ? path : join(canonicalPath(parent), basename(path));
21
- }
22
- }
6
+ import { deviceSignInPrompt } from "../../shared/device-sign-in.js";
7
+ import { DeviceAuthController } from "./device-auth.js";
23
8
  export function codexDevicePrompt(output) {
24
- const clean = stripVTControlCharacters(output);
25
- // Chunks may stop halfway through a code. Never publish the incomplete
26
- // final line before its newline arrives.
27
- const lines = clean.split(/\r?\n/).slice(0, -1).map((line) => line.trim());
28
- // Do not turn arbitrary output into a link, or pass through query tokens.
29
- if (!lines.some((line) => /^https:\/\/auth\.openai\.com\/codex\/device\/?$/.test(line)))
30
- return null;
31
- const userCode = lines.find((line) => /^[A-Z0-9]{4,8}-[A-Z0-9]{4,8}$/.test(line));
32
- return userCode ? { authorizationUrl: DEVICE_URL, userCode } : null;
9
+ return deviceSignInPrompt("codex", stripVTControlCharacters(output));
33
10
  }
34
11
  function loginFailure(output) {
35
12
  if (/(unexpected argument|unrecognized (argument|option)|unknown option).*device-auth/i.test(output)) {
@@ -43,293 +20,24 @@ function loginFailure(output) {
43
20
  }
44
21
  return "ChatGPT sign-in did not finish. Check the server's connection and that device-code login is enabled in ChatGPT, then try again.";
45
22
  }
46
- /** A fixed Codex login command, not a remotely accessible terminal. CLI
47
- * output stays in bounded private memory; only a device URL/code is exposed. */
48
- export class CodexDeviceAuthController {
49
- flow = null;
50
- command = null;
51
- disposed = false;
52
- options;
53
- constructor(options) { this.options = options; }
54
- async start() {
55
- if (this.disposed)
56
- throw new Error("This provider was removed. Refresh Settings before signing in.");
57
- if (this.flow?.status.phase === "waiting") {
58
- if (this.flow.ready)
59
- return { ...this.flow.status, phase: "waiting" };
60
- throw new Error("A ChatGPT sign-in is already starting. Please wait for the code.");
61
- }
62
- await this.flow?.stopping;
63
- if (this.disposed)
64
- throw new Error("This provider was removed. Refresh Settings before signing in.");
65
- const env = this.options.environment();
66
- const home = env.HOME || env.USERPROFILE || homedir();
67
- if (!isAbsolute(home) || (env.CODEX_HOME && !isAbsolute(env.CODEX_HOME))) {
68
- throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing in.");
69
- }
70
- const homeKey = canonicalPath(resolve(env.CODEX_HOME || join(home, ".codex")));
71
- if (authenticatingHomes.has(homeKey)) {
72
- throw new Error("A ChatGPT sign-in is already running for this server account. Finish or cancel it before starting another.");
73
- }
74
- authenticatingHomes.add(homeKey);
75
- return new Promise((resolveStart, reject) => {
76
- const flow = {
77
- status: {
78
- phase: "waiting", flowId: randomUUID(), authorizationUrl: null,
79
- expiresAt: new Date(Date.now() + (this.options.lifetimeMs ?? 15 * 60_000)).toISOString(),
80
- },
81
- child: null, ready: false, resolve: resolveStart, reject, homeKey,
82
- startupTimer: setTimeout(() => this.finish(flow, "failed", "Codex did not provide a sign-in code in time. Check the server connection and update Codex, then try again."), this.options.startupTimeoutMs ?? 30_000),
83
- expiryTimer: setTimeout(() => this.finish(flow, "expired", "The ChatGPT sign-in code expired. Start sign-in again."), this.options.lifetimeMs ?? 15 * 60_000),
84
- };
85
- flow.startupTimer.unref();
86
- flow.expiryTimer.unref();
87
- this.flow = flow;
88
- // Never overwrite a working login just because Connect was clicked twice.
89
- this.run(flow, ["login", "status"], env, home, (code, output) => {
90
- if (code === 0 && /^logged in.*chatgpt\b/im.test(output)) {
91
- this.finish(flow, "succeeded");
92
- }
93
- else if (code === 0 && /^logged in\b/im.test(output)) {
94
- this.finish(flow, "failed", "Codex already has a different sign-in method on this server. Ask the server administrator to review it before changing accounts.");
95
- }
96
- else if (code !== 0 && /^not logged in\b/im.test(output)) {
97
- this.run(flow, ["login", "--device-auth"], env, home, (loginCode, loginOutput) => {
98
- if (loginCode !== 0 || !flow.ready) {
99
- this.finish(flow, "failed", loginFailure(loginOutput));
100
- return;
101
- }
102
- // A successful command is not enough: verify credentials using the
103
- // same executable and environment that will run this client's bots.
104
- flow.startupTimer = setTimeout(() => this.finish(flow, "failed", "Codex finished sign-in but could not confirm the account. Refresh Settings and try again."), this.options.startupTimeoutMs ?? 30_000);
105
- flow.startupTimer.unref();
106
- this.run(flow, ["login", "status"], env, home, (statusCode, statusOutput) => {
107
- this.finish(flow, statusCode === 0 && /^logged in.*chatgpt\b/im.test(statusOutput) ? "succeeded" : "failed", "Codex finished sign-in but did not confirm a ChatGPT account. Refresh Settings and try again.");
108
- });
109
- }, true);
110
- }
111
- else
112
- this.finish(flow, "failed", "Codex could not confirm the existing sign-in on this server. Update Codex and check its login status before trying again.");
113
- });
114
- });
115
- }
116
- async get(flowId) {
117
- if (!flowId || this.flow?.status.flowId !== flowId)
118
- throw new Error("This sign-in is no longer available. Start sign-in again.");
119
- return { ...this.flow.status };
120
- }
121
- async cancel() {
122
- if (this.flow?.status.phase === "waiting")
123
- this.finish(this.flow, "cancelled", "ChatGPT sign-in cancelled.");
124
- await this.flow?.stopping;
125
- if (this.flow?.terminationFailed)
126
- throw new Error(this.flow.status.message);
127
- if (this.command && !await this.stopChild(this.command)) {
128
- throw new Error("Codex could not be stopped on this server. Ask the server administrator to stop the account command before trying again.");
129
- }
130
- }
131
- async dispose() {
132
- this.disposed = true;
133
- await this.cancel();
134
- this.flow = null;
135
- }
136
- /** Remove the ChatGPT sign-in Codex stores for this server account so a
137
- * different account can connect. A sign-in in progress is never pulled
138
- * away underneath the browser completing it. */
139
- async signOut() {
140
- if (this.disposed)
141
- throw new Error("This provider was removed. Refresh Settings before signing out.");
142
- if (this.flow?.status.phase === "waiting")
143
- throw new Error("Finish or cancel the ChatGPT sign-in in progress before signing out.");
144
- await this.flow?.stopping;
145
- if (this.disposed)
146
- throw new Error("This provider was removed. Refresh Settings before signing out.");
147
- const env = this.options.environment();
148
- const home = env.HOME || env.USERPROFILE || homedir();
149
- if (!isAbsolute(home) || (env.CODEX_HOME && !isAbsolute(env.CODEX_HOME))) {
150
- throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing out.");
151
- }
152
- const homeKey = canonicalPath(resolve(env.CODEX_HOME || join(home, ".codex")));
153
- if (authenticatingHomes.has(homeKey)) {
154
- throw new Error("A ChatGPT sign-in is running for this server account. Finish or cancel it before signing out.");
155
- }
156
- authenticatingHomes.add(homeKey);
157
- try {
158
- const before = await this.exec(["login", "status"], env, home);
159
- if (before.code === 1 && /^not logged in\b/im.test(before.output))
160
- return;
161
- if (before.code !== 0 || !/^logged in.*chatgpt\b/im.test(before.output)) {
162
- throw new Error("Codex did not confirm a ChatGPT sign-in. Other authentication methods will not be removed; ask the server administrator to check the account.");
163
- }
164
- const logout = await this.exec(["logout"], env, home);
165
- if (logout.code !== 0)
166
- throw new Error("Codex could not remove the sign-in on this server. Check the server's Codex installation and try again.");
167
- // The command's own report is not enough: confirm with the same status
168
- // check that decides whether bots may run on this account.
169
- const status = await this.exec(["login", "status"], env, home);
170
- if (status.code !== 1 || !/^not logged in\b/im.test(status.output)) {
171
- throw new Error("Codex still reports a sign-in on this server. Update Codex and check its login status before trying again.");
172
- }
173
- }
174
- finally {
175
- // If the OS cannot stop a command, it may still change credentials.
176
- // Keep the home reserved until that exact child actually exits.
177
- const child = this.command;
178
- if (child && child.exitCode === null && child.signalCode === null) {
179
- child.once("close", () => authenticatingHomes.delete(homeKey));
180
- }
181
- else
182
- authenticatingHomes.delete(homeKey);
183
- }
184
- }
185
- /** One bounded, non-interactive Codex command. Its output stays here;
186
- * callers see an exit code and a status-line match, never the text. */
187
- exec(args, env, cwd) {
188
- return new Promise((resolveExec, rejectExec) => {
189
- if (this.disposed) {
190
- rejectExec(new Error("This provider was removed. Refresh Settings before signing out."));
191
- return;
192
- }
193
- let child;
194
- try {
195
- child = spawnCli(this.options.cli, args, { env: { ...env, NO_COLOR: "1" }, cwd, stdio: ["pipe", "pipe", "pipe"] });
196
- }
197
- catch {
198
- rejectExec(new Error("Codex could not start on this server. Install or update the configured Codex CLI, then try again."));
199
- return;
200
- }
201
- this.command = child;
202
- child.stdin.end();
203
- let output = "";
204
- const receive = (chunk) => {
205
- if (output.length < MAX_OUTPUT)
206
- output += chunk.toString("utf8").slice(0, MAX_OUTPUT - output.length);
207
- };
208
- child.stdout.on("data", receive);
209
- child.stderr.on("data", receive);
210
- // A hung CLI must not hold the credential-home lock forever.
211
- const timer = setTimeout(() => {
212
- void this.stopChild(child).catch(() => false).then((stopped) => {
213
- if (!stopped)
214
- rejectExec(new Error("Codex could not be stopped on this server. Ask the server administrator to stop the account command before trying again."));
215
- });
216
- }, this.options.startupTimeoutMs ?? 30_000);
217
- timer.unref();
218
- child.once("error", (error) => {
219
- clearTimeout(timer);
220
- rejectExec(new Error(error.code === "ENOENT"
221
- ? "Codex is not installed on this server. Run npm install -g @openai/codex@latest on the server, then try again."
222
- : "Codex could not start on this server. Check the configured CLI path and its executable permissions."));
223
- });
224
- child.once("close", (code) => {
225
- clearTimeout(timer);
226
- if (this.command === child)
227
- this.command = null;
228
- resolveExec({ code, output: stripVTControlCharacters(output) });
229
- });
230
- });
231
- }
232
- run(flow, args, env, cwd, done, parsePrompt = false) {
233
- if (flow.status.phase !== "waiting")
234
- return;
235
- let child;
236
- try {
237
- child = spawnCli(this.options.cli, args, { env: { ...env, NO_COLOR: "1" }, cwd, stdio: ["pipe", "pipe", "pipe"] });
238
- }
239
- catch {
240
- this.finish(flow, "failed", "Codex could not start on this server. Install or update the configured Codex CLI, then try again.");
241
- return;
242
- }
243
- flow.child = child;
244
- child.stdin.end();
245
- let output = "";
246
- const receive = (chunk) => {
247
- if (flow.status.phase !== "waiting")
248
- return;
249
- if (output.length + chunk.length > MAX_OUTPUT) {
250
- this.finish(flow, "failed", "Codex returned an unexpected sign-in response. Update the server's Codex CLI and try again.");
251
- return;
252
- }
253
- output += chunk.toString("utf8");
254
- const prompt = parsePrompt && !flow.ready ? codexDevicePrompt(output) : null;
255
- if (prompt) {
256
- flow.status = { ...flow.status, ...prompt };
257
- flow.ready = true;
258
- clearTimeout(flow.startupTimer);
259
- flow.resolve({ ...flow.status, phase: "waiting" });
260
- }
261
- };
262
- child.stdout.on("data", receive);
263
- child.stderr.on("data", receive);
264
- child.once("error", (error) => {
265
- const message = error.code === "ENOENT"
266
- ? "Codex is not installed on this server. Run npm install -g @openai/codex@latest on the server, then try again."
267
- : "Codex could not start on this server. Check the configured CLI path and its executable permissions.";
268
- this.finish(flow, "failed", message);
269
- });
270
- child.once("close", (code) => {
271
- if (flow.child === child)
272
- flow.child = null;
273
- if (flow.status.phase === "waiting")
274
- done(code, stripVTControlCharacters(output));
275
- output = "";
276
- });
277
- }
278
- finish(flow, phase, message) {
279
- if (flow.status.phase !== "waiting")
280
- return;
281
- clearTimeout(flow.startupTimer);
282
- clearTimeout(flow.expiryTimer);
283
- flow.status = {
284
- phase, flowId: flow.status.flowId, authorizationUrl: null, expiresAt: null,
285
- ...(phase !== "succeeded" && message ? { message } : {}),
286
- };
287
- if (!flow.ready) {
288
- if (phase === "succeeded")
289
- flow.resolve({ ...flow.status, phase });
290
- else
291
- flow.reject(new Error(message ?? "ChatGPT sign-in did not finish."));
292
- }
293
- flow.stopping = this.stopChild(flow.child).catch(() => false).then((stopped) => {
294
- const release = () => authenticatingHomes.delete(flow.homeKey);
295
- if (stopped) {
296
- release();
297
- return;
298
- }
299
- flow.terminationFailed = true;
300
- flow.status = { ...flow.status, phase: "failed", message: "Codex could not be stopped on this server. Ask the server administrator to stop the login process before trying again." };
301
- // Retain the credential-home lock until the OS actually reports exit.
302
- const child = flow.child;
303
- if (!child || child.exitCode !== null || child.signalCode !== null)
304
- release();
305
- else
306
- child.once("close", release);
307
- });
308
- if (phase === "succeeded")
309
- void this.options.onAuthenticated?.().catch(() => { });
310
- }
311
- async stopChild(child) {
312
- if (!child || await killCliTree(child, this.options.terminateTimeoutMs ?? 1500))
313
- return true;
314
- // A broken CLI may ignore SIGTERM. Do not leave a stale device flow able
315
- // to write credentials after the user cancelled it.
316
- if (process.platform !== "win32" && child.pid) {
317
- try {
318
- process.kill(-child.pid, "SIGKILL");
319
- }
320
- catch {
321
- child.kill("SIGKILL");
322
- }
323
- }
324
- else
325
- child.kill("SIGKILL");
326
- await new Promise((resolveStop) => {
327
- if (child.exitCode !== null || child.signalCode !== null)
328
- return resolveStop();
329
- const timer = setTimeout(resolveStop, 1500);
330
- timer.unref();
331
- child.once("close", () => { clearTimeout(timer); resolveStop(); });
332
- });
333
- return child.exitCode !== null || child.signalCode !== null;
334
- }
23
+ export const CODEX_DEVICE_SIGN_IN = {
24
+ provider: "codex",
25
+ product: "Codex",
26
+ account: "ChatGPT",
27
+ homeEnv: "CODEX_HOME",
28
+ homeDir: ".codex",
29
+ loginArgs: ["login", "--device-auth"],
30
+ install: "Run npm install -g @openai/codex@latest on the server, then try again.",
31
+ failure: loginFailure,
32
+ status: {
33
+ args: ["login", "status"],
34
+ read: (code, output) => code === 0 && /^logged in.*chatgpt\b/im.test(output) ? "signed-in"
35
+ : code === 0 && /^logged in\b/im.test(output) ? "other"
36
+ : code !== 0 && /^not logged in\b/im.test(output) ? "signed-out"
37
+ : "unknown",
38
+ },
39
+ logoutArgs: ["logout"],
40
+ };
41
+ export class CodexDeviceAuthController extends DeviceAuthController {
42
+ constructor(options) { super(CODEX_DEVICE_SIGN_IN, options); }
335
43
  }
@@ -1711,8 +1711,8 @@ export const CodexDriver = {
1711
1711
  // back. The app-server offers no way to clear a level either:
1712
1712
  // "" is rejected outright and thread/start takes no effort at
1713
1713
  // all. So a thread keeps the last level it was sent until it is
1714
- // sent another, and choosing Default lands on the bot's next new
1715
- // thread rather than the current one.
1714
+ // sent another; back on Default, the harness gives a thread that
1715
+ // holds a level a new thread instead of resuming it (server/index.ts).
1716
1716
  ...(turn.effort ? { effort: turn.effort } : {}),
1717
1717
  });
1718
1718
  };