elanous 0.2.42 → 0.2.43

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 (685) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{7a98bc80.fa935989e829f9c2.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{73d2eb0e.4966ad55293c801a.js → 0ad6802e.ae7afb63fdcb4491.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/114.2b90424d1a3ce84c.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1151-5c2bb8f002ca2dd6.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1200.6a37c202f9f17e9a.js +226 -0
  9. package/apps/pwa/out/_next/static/chunks/1261-a616d5728e02e624.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1313-19f737e0222c4444.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1357.3bbef3976c37f94a.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1362-20adddfaf662b0fa.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/{3507.97e1977bc4d5fb0a.js → 1406.a1dc2ab6f8449374.js} +2 -2
  14. package/apps/pwa/out/_next/static/chunks/1737-9491fc6ab29b9ec6.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1803-4f91a8e7dcaf042c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1961.a81b12872c3e93a9.js +23 -0
  17. package/apps/pwa/out/_next/static/chunks/{53c73f84.373b6160adfa89a4.js → 1970cf59.2d4d8ce5d6c81853.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{9211-330b6736a63d4cb3.js → 2073-ba274e00e4f9efb4.js} +1 -1
  20. package/apps/pwa/out/_next/static/chunks/{7411.9b4b8b747dc7b802.js → 2144.25b292396712196d.js} +2 -2
  21. package/apps/pwa/out/_next/static/chunks/2268-53861f339e0b65a2.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2312.0c8b61e22d3136d7.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6632.0eac1c554f8f2ef3.js → 2573.387a707f6f9d720c.js} +2 -2
  24. package/apps/pwa/out/_next/static/chunks/273.f156eee28f11af77.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2873.d2140e5a82546401.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/{1262.e804feb8fd1acb8c.js → 3072.01338851ca21a6f7.js} +2 -2
  27. package/apps/pwa/out/_next/static/chunks/3091.a5a4143dea33d197.js +90 -0
  28. package/apps/pwa/out/_next/static/chunks/{2456.b6de0e1c05f28843.js → 3095.dc44586a5f83b86d.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/{3207.a756c95e9ec8c3c8.js → 3113.d7472bbc27d580c7.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/3228-9650b6447b6fa288.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/3402.44b565b314f2263c.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/3557ac4a.c8931684475018ad.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{8505.fd803c6c33b54cc3.js → 360.ae9f9f4c33c395e8.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
  35. package/apps/pwa/out/_next/static/chunks/{b450776b.3db34d8d965f82d3.js → 363bfab3.9623b9f89363541f.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/3694.e0099884345f0198.js +64 -0
  37. package/apps/pwa/out/_next/static/chunks/3744.54f87db52acfd1ab.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3903.3ef4656c67572764.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3935.16701e33f8982dc9.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3955.6922286237f2ac2b.js +24 -0
  41. package/apps/pwa/out/_next/static/chunks/3969.272ee7f9fd6c62e5.js +34 -0
  42. package/apps/pwa/out/_next/static/chunks/{8138.6c10b2a356d52fca.js → 4199.ce86b281fd0a60b7.js} +1 -1
  43. package/apps/pwa/out/_next/static/chunks/4311-6dd3144002cc0c2d.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4426-2b230fad00c88930.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{2690.0521c738b7749931.js → 4445.7990c76b3751a918.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4447-14c5161fa59166c7.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4856-b0b8075bba8c53f4.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4870-de370d65e73c0bb5.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4885-2c989165c4b29fad.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/{1945.7b54990d578c119b.js → 4894.fec2ca9e99caefa2.js} +1 -1
  51. package/apps/pwa/out/_next/static/chunks/5093.8f04b7f8cb899a95.js +94 -0
  52. package/apps/pwa/out/_next/static/chunks/5122-2bb177cebf89e19a.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/5154.5f56dc3902e3d275.js +36 -0
  54. package/apps/pwa/out/_next/static/chunks/529.64ff7257180b2ac9.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5394.5dabeb0c62293a28.js +93 -0
  56. package/apps/pwa/out/_next/static/chunks/5461.08bf2404ff38ec85.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5474-22e08a85583209b2.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{9427.96aa912ddb5801e0.js → 5564.9e72532188f57586.js} +16 -16
  59. package/apps/pwa/out/_next/static/chunks/5567-265df39ed8fe9dcb.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5570-a94ae19811cb2046.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5574-b47c9ef2dceff1fd.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/{4043.6b91203436c9c86b.js → 5628.6ddb2d5ffba4ff4c.js} +4 -4
  63. package/apps/pwa/out/_next/static/chunks/{1319.b9b815ae0f181e06.js → 5730.43d7ccc09988e646.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/{3482.a9ae9d2ad6a5bd97.js → 5789.2da35c258292e1e5.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5824.da9527b15a3221e5.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/{1487.2f67b79444062da6.js → 5930.8b4df3b46c32b05a.js} +1 -1
  68. package/apps/pwa/out/_next/static/chunks/5963-c4d8469c52a0828b.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/6001.ec4049ceb3c43418.js +27 -0
  70. package/apps/pwa/out/_next/static/chunks/6120-471f03db1e299c0c.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6175-41479e643aca1878.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6291.a2de4f9787637075.js +104 -0
  73. package/apps/pwa/out/_next/static/chunks/6400-6699907c3537436a.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/6428.1f4327d6ae5fdf9a.js +287 -0
  75. package/apps/pwa/out/_next/static/chunks/644.02cb026fa44bcd0a.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6466-6c87d60d3dd174fb.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{3347.f846266b5e5f3ede.js → 6540.c7bef57ad8f90a87.js} +3 -3
  78. package/apps/pwa/out/_next/static/chunks/6773.d4264665ab31bec0.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6822.3c789f1a8443e774.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/{8262.ddc03e06b733f184.js → 6944.309f4e3ea54d1537.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/7261-8ff69d3b2ee671fd.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7266.084c6bbc70035140.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7271.5c0100e7320aa856.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7429-bf5731358c8f2f68.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7464.01f7a0ae1215fbe7.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7479.0fcad5f37eb64f0c.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/{4770.769c9cd9c7034eba.js → 7483.427a2fe2049e388d.js} +2 -2
  88. package/apps/pwa/out/_next/static/chunks/{1147-5196d19c222051b3.js → 7502-be74718178e13e56.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7530.0889722b19572065.js +24 -0
  90. package/apps/pwa/out/_next/static/chunks/7645.5b2ee3ad45c55ea3.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7788.7d1c79f1a8e18946.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7900.096f455c7c1efc53.js +77 -0
  93. package/apps/pwa/out/_next/static/chunks/7910-6f139bcafd238b9f.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7966.f71c8958d1637548.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{8673-bab689a55f7e13b9.js → 8062-7cd0bcc7f01455ba.js} +3 -3
  96. package/apps/pwa/out/_next/static/chunks/8073.f6cf2f2c71aafbd0.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8201.190b94088980f430.js +74 -0
  98. package/apps/pwa/out/_next/static/chunks/8205.282ca4bb62d54a0a.js +62 -0
  99. package/apps/pwa/out/_next/static/chunks/8313-dfa1021bb58a46d6.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/837-81336ebaca8198a8.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8447.7963352ef5f71b76.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8574-868e8129525ef6d9.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8588.d1c6a2903727ce87.js +149 -0
  104. package/apps/pwa/out/_next/static/chunks/8637.90f92d5c8db4732c.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/868.6e953be05bcf6dca.js +41 -0
  106. package/apps/pwa/out/_next/static/chunks/8706-e1fe0309343a2273.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8749-06384cdfc4520add.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{9656-374232558fd528d0.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{5440-4236de26c5ea5856.js → 8967-7dfebf710c9dec9d.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/{1063.2fb8a9dc55c731f2.js → 8986.8e2e4efbfa655c59.js} +1 -1
  111. package/apps/pwa/out/_next/static/chunks/8997-3c564dbb3b58b055.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/{4320.583cbab64db6be02.js → 923.2034d10ae91e9c20.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{1574.878c18ecc97b1bd4.js → 943.39ae5e82f4f1893f.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/9469.0500480de55fb205.js +32 -0
  116. package/apps/pwa/out/_next/static/chunks/9770.5f75bc6088b16109.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9810-2543267050e58b82.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9870.8419702475254745.js +8 -0
  119. package/apps/pwa/out/_next/static/chunks/9941-376d1b74d51b01a4.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9958.385434ab04241758.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/aa57532f.510551854ff239b1.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-deea1450b17cb8dc.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-70985b904f8650ef.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a2e15e33e56a4353.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-fc72ce2db12d6ca9.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-be03e41f9436ebd9.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-35a35999382da3f2.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-3ff5b1e6ca88b848.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-a65101300a0ee5c1.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-3aca5b6d67dba511.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-45b8ab0a71e61314.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-53046e282d4cda8e.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-17809e60e8354c17.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-fd2442d347bf5898.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-e9d720d6fc082e21.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-6b8b4267bab0a677.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-deea1450b17cb8dc.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-8bcf6233ac7c17af.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-7cc25591cfc2126f.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-053e871f35c9beba.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-eff819f0c2d5e084.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-4d7e9d8db5274a87.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-2b2d8f5aa5f69ad4.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-0b8f92c5062e68b1.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1bd9d0fdac2ced3d.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/{page-0f291d3c8fd55a3a.js → page-9ee28f7df07428ea.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-44b7a1ff468c6648.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-cbc6523711dc1b65.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-fdad47899c2695be.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-79a8b5fee4c20871.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-03e8ac9606aeaffb.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-4cd55c55ec287e2f.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-db17b4305404161e.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-30041d848350fd02.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c540da022dbf86b0.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9399efc538da057f.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ca2d09128c585ca4.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-0e2635aecd343038.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ef7f4399b6b7726e.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-deea1450b17cb8dc.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-caf530535b875468.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-eaa20c1543a5fd8e.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c541eb1b75120f61.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-ab5e213eda9479f4.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-0a815f34367b6db6.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-e858ba0ed9393b68.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-1638ee9dd6e0582f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-4cf5a399109391f2.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b4396321238798ec.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-cb72bfd21006781a.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6135d0242afbc434.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a1dccf907eddb856.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/c7945435-b44d4dbe90ba0dcb.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{3d0154af.5331fec737ffe8c3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/{e8543907.5b040a5f22a0b0e5.js → d96660fb.cbc21a2a88539dbb.js} +7 -7
  176. package/apps/pwa/out/_next/static/chunks/{50061469.0326382241ef3b2d.js → ea514caa.05a24f78d9dffe5f.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/fb7d20d5-6892502b6ee39ca6.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-e8a911e19b1be41f.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-7022f418fabba021.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-e5f15df755756a1e.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-4525f91e36940c9b.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-140f0e519c085b0f.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-8f22ef63dcb865b1.js +1 -0
  184. package/apps/pwa/out/_next/static/css/d1f8bb401740a549.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/catalog/external-commands.yaml +5 -3
  279. package/catalog/meta/catalogVersion.yaml +2 -1
  280. package/catalog/signing/catalog-signing-public.pem +3 -0
  281. package/graphs/intake/intake-daily.yaml +16 -0
  282. package/graphs/intake/news-sources.yaml +1 -0
  283. package/graphs/intake/recipes.yaml +7 -0
  284. package/graphs/overlays/examples/research-runtime-empty-terminal.yaml +28 -0
  285. package/graphs/profiles/local.yaml +5 -0
  286. package/graphs/profiles/pod.yaml +4 -0
  287. package/package.json +6 -2
  288. package/plugins/demo-absorption-briefing/plugin.json +18 -0
  289. package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
  290. package/plugins/demo-browser-hand/plugin.json +13 -0
  291. package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
  292. package/plugins/demo-linear-secretary/plugin.json +15 -0
  293. package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
  294. package/plugins/demo-plugin-wizard/plugin.json +11 -0
  295. package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
  296. package/plugins/demo-research/plugin.json +16 -0
  297. package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
  298. package/plugins/demo-video-briefing/plugin.json +15 -0
  299. package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
  300. package/scripts/build-signed-catalog.ts +48 -0
  301. package/scripts/ci-typecheck-main-delta.sh +88 -0
  302. package/scripts/codex-fallback-live-probe.ts +1 -1
  303. package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
  304. package/scripts/demo/demo1104-stage.config.ts +21 -0
  305. package/scripts/demo/demo1104-stage.ts +316 -0
  306. package/scripts/goal-method-audit.ts +17 -1
  307. package/scripts/graph-units/land-enqueue.ts +90 -0
  308. package/scripts/hooks/codex-notify.sh +32 -0
  309. package/scripts/install.sh +10 -38
  310. package/scripts/landing-heal/land-plan.ts +57 -0
  311. package/scripts/release-loop/auto-approve-node.ts +1 -1
  312. package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
  313. package/scripts/release-loop/gate-method.ts +139 -0
  314. package/scripts/release-loop/gate-node.ts +180 -20
  315. package/scripts/release-loop/gate-traffic-mode.ts +151 -3
  316. package/scripts/release-loop/node-verdict.ts +38 -25
  317. package/scripts/release-loop/preflight.ts +362 -8
  318. package/scripts/release-loop/unattended-release.ts +20 -9
  319. package/scripts/rhythm/daily.ts +36 -4
  320. package/scripts/rhythm/linear-progress-sync.ts +298 -0
  321. package/scripts/video-pipeline.ts +9 -1
  322. package/scripts/warm-pool-provider-config.ts +29 -6
  323. package/src/acp/agent-manager.ts +1 -0
  324. package/src/acp/codex-app-server-agent.ts +33 -0
  325. package/src/acp/codex-app-server-client.ts +153 -16
  326. package/src/acp/core-turn-bridge.ts +17 -12
  327. package/src/acp/event-router.ts +20 -1
  328. package/src/acp/server.ts +6 -0
  329. package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
  330. package/src/agent-mission/claude-headless.ts +4 -1
  331. package/src/agent-mission/codex-exec.ts +105 -0
  332. package/src/agent-mission/driver.ts +192 -11
  333. package/src/agent-mission/grok-auth-status.ts +47 -0
  334. package/src/agent-mission/hand-hooks.ts +101 -0
  335. package/src/agent-mission/mission-cli.ts +56 -21
  336. package/src/agent-mission/mission-hand-reply.ts +118 -0
  337. package/src/agent-mission/mission-line.ts +180 -0
  338. package/src/agent-mission/mission-out.ts +256 -18
  339. package/src/agent-mission/tool-install.ts +122 -11
  340. package/src/agents/general-purpose.md +1 -1
  341. package/src/auto-research/research-turn.ts +95 -10
  342. package/src/autopilot/pr-manager.ts +31 -3
  343. package/src/boot/daemon-tools/self-implement.ts +3 -1
  344. package/src/boot/daemon-tools/web-search.ts +1 -2
  345. package/src/briefing/brief-items.ts +55 -11
  346. package/src/cli/agent-cli.ts +2 -1
  347. package/src/cli/catalog-cli.ts +31 -0
  348. package/src/cli/connector-cli.ts +16 -0
  349. package/src/cli/doctor-fix.ts +2 -2
  350. package/src/cli/intake-source-cli.ts +44 -8
  351. package/src/cli/msg-cli.ts +32 -3
  352. package/src/cli/pr-cli.ts +21 -1
  353. package/src/cli/pr-land-heavy-remote.ts +44 -6
  354. package/src/cli/pr-land-overlap-evidence.ts +13 -1
  355. package/src/cli/pr-land-pod-shadow-job.ts +143 -5
  356. package/src/cli/pr-land-pod-shadow.ts +9 -2
  357. package/src/cli/release-checklist-read-cli.ts +44 -16
  358. package/src/cli/release-cli.ts +23 -3
  359. package/src/cli/research-cli.ts +9 -0
  360. package/src/cli/setup-cli.ts +166 -6
  361. package/src/cli/setup-keys.ts +187 -0
  362. package/src/cli/task-plugin-wizard-host.ts +114 -0
  363. package/src/cli/tasks-cli.ts +54 -9
  364. package/src/cli/tui-test-cli.ts +186 -0
  365. package/src/config.ts +4 -2
  366. package/src/connectors/linear-daily-progress.ts +228 -0
  367. package/src/connectors/linear-projector.ts +34 -12
  368. package/src/connectors/linear.ts +151 -7
  369. package/src/core-turn/deep-turn-bloom.ts +67 -0
  370. package/src/core-turn/research-policy.ts +37 -0
  371. package/src/core-turn/run-core-turn.ts +320 -30
  372. package/src/core-turn/types.ts +2 -0
  373. package/src/dashboard/chat/acp-chat.ts +10 -0
  374. package/src/dashboard/classic-sidetab-mission-job.ts +103 -0
  375. package/src/dashboard/classic-sidetab-mission-pair.ts +81 -0
  376. package/src/dashboard/classic-sidetab-mission-trio.ts +219 -0
  377. package/src/dashboard/classic-sidetab-mission.ts +167 -5
  378. package/src/dashboard/index.ts +378 -13
  379. package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
  380. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +8 -0
  381. package/src/dashboard/mission-cli-consumer.ts +20 -8
  382. package/src/dashboard/plugin-wizard-runtime.ts +50 -0
  383. package/src/dashboard/plugin-wizard-tool.ts +55 -0
  384. package/src/dashboard/sidetab-runtime.ts +1 -1
  385. package/src/dashboard/terminal-popup-runtime.ts +6 -3
  386. package/src/decisions/linear-progress-summary.ts +78 -0
  387. package/src/decisions/linear-progress-sync.ts +152 -0
  388. package/src/domains/outbound-alert.ts +49 -11
  389. package/src/domains/telegram-kind-route.ts +16 -9
  390. package/src/graph-runner/arg-allowance.ts +13 -0
  391. package/src/graph-runner/graph-run-api.ts +3 -1
  392. package/src/graph-runner/runner.ts +85 -17
  393. package/src/graph-wizard/mission-compose.ts +407 -12
  394. package/src/harness/dispatch-backpressure.ts +54 -1
  395. package/src/harness/dispatch-shadow-compare.ts +74 -0
  396. package/src/harness/harness-cli-command.ts +11 -1
  397. package/src/harness/skill-exec.ts +21 -9
  398. package/src/harness/skill-select.ts +1 -1
  399. package/src/hooks/error-report-cloud.ts +101 -0
  400. package/src/hooks/receiver.ts +29 -2
  401. package/src/index.ts +127 -10
  402. package/src/intake-plane/actions.ts +354 -0
  403. package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
  404. package/src/intake-plane/intake-sources.ts +78 -8
  405. package/src/intake-plane/items.ts +14 -4
  406. package/src/intake-plane/linear-mission-sync.ts +80 -0
  407. package/src/intake-plane/linear-secretary-runtime.ts +178 -0
  408. package/src/intake-plane/linear-wish.ts +227 -1
  409. package/src/life/life-cli.ts +168 -0
  410. package/src/life/life-kinds.ts +160 -0
  411. package/src/live-supply/budget-consumer.ts +78 -0
  412. package/src/live-supply/read.ts +3 -0
  413. package/src/live-supply/snapshot.ts +45 -0
  414. package/src/llm/provider-credentials.ts +8 -2
  415. package/src/llm.ts +2 -1
  416. package/src/maturity/feature-maturity.ts +3 -3
  417. package/src/msg/msg-sse-server.ts +3 -3
  418. package/src/msg/msg-store.ts +177 -19
  419. package/src/native-tool-catalog.ts +36 -2
  420. package/src/nexus/api/http-server.ts +37 -1
  421. package/src/nexus/api/mcp-public-allowlist.ts +2 -0
  422. package/src/nexus/index.ts +7 -2
  423. package/src/nexus/outbound/format.ts +9 -0
  424. package/src/nexus/outbound/router.ts +98 -13
  425. package/src/nexus/setup-status.ts +9 -0
  426. package/src/nexus/state/state.ts +3 -0
  427. package/src/oauth/codex-account-store.ts +20 -7
  428. package/src/oauth/codex-owner-mirror.ts +44 -0
  429. package/src/oauth/codex.ts +17 -2
  430. package/src/oauth/fallback-chain.ts +47 -17
  431. package/src/onboarding/first-run-doctor.ts +8 -1
  432. package/src/onboarding/first-run.ts +85 -26
  433. package/src/onboarding/key-setup.ts +103 -0
  434. package/src/onboarding/menu-answer.ts +13 -0
  435. package/src/onboarding/secret-prompt.ts +37 -0
  436. package/src/plugins/install/plugin-install.ts +59 -0
  437. package/src/pr-tool/census.ts +130 -0
  438. package/src/pty-shell/pty-control-ipc.ts +4 -1
  439. package/src/registry/catalog-server.ts +232 -0
  440. package/src/registry/loader.ts +45 -1
  441. package/src/registry/types.ts +1 -2
  442. package/src/research/axis-fanout.ts +43 -28
  443. package/src/self-dev/ask-launch-flow.ts +72 -1
  444. package/src/self-dev/dev-cli.ts +4 -1
  445. package/src/self-dev/dev-pipeline.ts +5 -0
  446. package/src/self-dev/draft-residue.ts +64 -5
  447. package/src/self-dev/graph-front-nodes.ts +2 -1
  448. package/src/self-dev/graph-journey-route.ts +76 -21
  449. package/src/self-dev/launch-preflight.ts +58 -0
  450. package/src/self-dev/orchestrate.ts +1 -1
  451. package/src/self-dev/shard-aggregate.ts +4 -0
  452. package/src/self-dev/shard-run.ts +36 -15
  453. package/src/self-implement/abandoned-classification.ts +12 -3
  454. package/src/self-implement/budget-gate.ts +7 -0
  455. package/src/self-implement/child-llm-preference.ts +10 -1
  456. package/src/self-implement/doctor-visit.ts +30 -8
  457. package/src/self-implement/elanous-tui-spawn.ts +3 -0
  458. package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
  459. package/src/self-implement/gate-artifacts.ts +2 -1
  460. package/src/self-implement/goal-author-cli.ts +4 -2
  461. package/src/self-implement/goal-author.ts +358 -4
  462. package/src/self-implement/graph-overlay-yaml.ts +30 -4
  463. package/src/self-implement/graph-overlay.ts +3 -1
  464. package/src/self-implement/graph-profile-yaml.ts +107 -0
  465. package/src/self-implement/graph-yaml.ts +26 -3
  466. package/src/self-implement/off-diff-evidence.ts +249 -5
  467. package/src/self-implement/orchestrator.ts +240 -15
  468. package/src/self-implement/run-chart.ts +6 -3
  469. package/src/self-implement/run-ledger.ts +51 -1
  470. package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
  471. package/src/self-implement/tdd-evidence-tags.ts +9 -0
  472. package/src/self-implement/train-gate-receipt.ts +166 -0
  473. package/src/self-implement/train-gate-remote.ts +62 -18
  474. package/src/session/chat.ts +4 -2
  475. package/src/session/session-fanout.ts +2 -0
  476. package/src/session/streaming/acp-stream-sink.ts +2 -1
  477. package/src/session/streaming/chunk-producer.ts +6 -0
  478. package/src/session/streaming/stream-compositor.ts +3 -2
  479. package/src/session-runtime/index.ts +37 -1
  480. package/src/session-runtime/retry-policy.ts +1 -1
  481. package/src/setup/llm-env-detect.ts +3 -0
  482. package/src/setup/service-key-catalog.ts +46 -0
  483. package/src/setup/service-keys.ts +241 -0
  484. package/src/sidetab-core/visible-agent-mission.ts +98 -22
  485. package/src/skills/tools/agent.ts +23 -4
  486. package/src/skills/tools/omni-search.ts +123 -25
  487. package/src/task-agent/parent-host.ts +10 -0
  488. package/src/task-agent/repair-outcomes.ts +65 -0
  489. package/src/task-agent/task-hand.ts +20 -7
  490. package/src/task-orchestrator/dispatcher.ts +14 -1
  491. package/src/task-orchestrator/linear-capture-events.ts +55 -0
  492. package/src/task-orchestrator/store.ts +16 -5
  493. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +4 -0
  494. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +92 -1
  495. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
  496. package/src/task-orchestrator/surfaces/pod-source-receive.ts +23 -11
  497. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
  498. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +35 -9
  499. package/src/task-orchestrator/surfaces/self-implement-pod.ts +172 -6
  500. package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
  501. package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
  502. package/src/task-orchestrator/types.ts +14 -0
  503. package/src/telegram.ts +14 -16
  504. package/src/terminal/coding-agent.ts +14 -5
  505. package/src/terminal/session-registry.ts +1 -1
  506. package/src/tool-hints/gate.ts +1 -0
  507. package/src/tool-runtime/agent-runtime.ts +1 -0
  508. package/src/tool-runtime/browser-hand-runtime.ts +381 -0
  509. package/src/tool-runtime/browser-runtime.ts +2 -1
  510. package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
  511. package/src/tool-runtime/elanous-linear-secretary-runtime.ts +57 -0
  512. package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
  513. package/src/tool-runtime/index.ts +6 -0
  514. package/src/tool-runtime/types.ts +3 -0
  515. package/src/tui/entry.ts +24 -1
  516. package/src/tui/sidetab/attach.ts +140 -11
  517. package/src/tui/sidetab/herdr-portal.ts +225 -0
  518. package/src/user-config.ts +34 -9
  519. package/src/user-intent/types.ts +4 -3
  520. package/src/ux-sim/browser-hand.ts +165 -0
  521. package/src/ux-sim/draft-inventory-builder.ts +198 -0
  522. package/src/ux-sim/fake-browser-page.ts +81 -0
  523. package/src/ux-sim/fake-linear-device.ts +31 -0
  524. package/src/ux-sim/graph-engine-sim.ts +47 -0
  525. package/src/ux-sim/linear-secretary.ts +216 -0
  526. package/src/ux-sim/mock-scenario-catalog.json +75 -23
  527. package/src/ux-sim/mock-scenario-catalog.ts +120 -2
  528. package/src/ux-sim/onboarding-first-run-device.ts +31 -21
  529. package/src/ux-sim/scenario.ts +70 -26
  530. package/src/ux-sim/service-key-setup.ts +50 -0
  531. package/src/ux-sim/term-slash-device.ts +74 -0
  532. package/src/ux-sim/turn-throw-sim.ts +31 -0
  533. package/src/version/packed-revision.json +1 -1
  534. package/src/web-search/exa.ts +77 -0
  535. package/src/web-search/index.ts +30 -9
  536. package/src/web-search/provider.ts +4 -1
  537. package/src/web-search/x-intent.ts +5 -0
  538. package/apps/pwa/out/_next/static/chunks/0244e5b5.6fc7670f8223d82d.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +0 -36
  540. package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/1455-530ca16c7e71baff.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +0 -32
  543. package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +0 -286
  548. package/apps/pwa/out/_next/static/chunks/2160.a097e7b138ae1c55.js +0 -23
  549. package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +0 -34
  552. package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/2974.595d1e29d040cb6a.js +0 -64
  557. package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +0 -93
  558. package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +0 -41
  559. package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +0 -24
  561. package/apps/pwa/out/_next/static/chunks/3741.9cf76acaa2ee5298.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +0 -77
  567. package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/4276.336d76d858fcdf1b.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +0 -74
  572. package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +0 -149
  573. package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +0 -27
  575. package/apps/pwa/out/_next/static/chunks/5431-72a1dbde59400691.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/5885.0a3e52c8faccec98.js +0 -287
  583. package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/6131.348b7d6bdcd267ce.js +0 -226
  586. package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +0 -90
  587. package/apps/pwa/out/_next/static/chunks/6377.bc7df239edbff244.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +0 -104
  594. package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +0 -94
  595. package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +0 -24
  602. package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +0 -8
  610. package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/8546-6f03f8ea34dd61d9.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/9249.976f1e69a9d80754.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/9415.69e4a21c60c7d2db.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/9633.ce5bddc56784da72.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +0 -62
  626. package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/9a852a62-6192a6ea9346ced3.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0e3d7b9421b79dac.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/term/page-bf067887b3307423.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +0 -1
  684. package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
  685. /package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
@@ -29,13 +29,14 @@ import { codexPolicyAllowsCredits, codexPolicyAllowsFallback, resolveCodexQuotaP
29
29
  import { emitDecision } from '../live/detail-switch.js';
30
30
  import { debug } from '../debug/log.js';
31
31
  import {
32
- decideFallback, normalizeFallbackChain, grokQuotaFromUsageSnapshot,
32
+ decideFallback, fallbackChainForProvider, normalizeFallbackChain, grokQuotaFromUsageSnapshot,
33
33
  type FallbackDecision, type FallbackInput, type FallbackStep, type RotationOutcome,
34
34
  } from './fallback-chain.js';
35
35
  import { collectClaudePtyMaturitySample, judgeClaudePtyMaturity, type ClaudePtyMaturity } from './claude-pty-maturity.js';
36
36
  import type { UsageOutcomesDeps } from '../budget/usage-outcomes.js';
37
37
  import { resolveGrokCredential } from '../grok/credential.js';
38
38
  import { getOpenRouterApiKey } from '../config.js';
39
+ import { zaiCodingPlanAvailable } from '../llm/zai-coding-plan.js';
39
40
  import { lookupOpenRouterModelSpec } from '../model-tier/llm-tier-map.js';
40
41
  import { sendOutbound } from '../domains/outbound-alert.js';
41
42
 
@@ -55,7 +56,7 @@ export function _setCodexAccountOutboundSenderForTesting(sender: CodexAccountOut
55
56
  /** ⛔⭐ 정적 import 로 읽는다 — 종전 `require()` 는 ESM 에서 «정의되지 않을 수 있고», 그러면
56
57
  * fail-soft 가 삼켜 ***config false 가 영영 무시된다***(리뷰 should-fix: 노브가 no-op 이 된다).
57
58
  * ⚠️ 순환 없음을 확인했다 — user-config 는 oauth 를 안 끌어온다. */
58
- type RotationConfig = { llm?: { codexCreditReserve?: unknown; codexAccountRotation?: boolean; codexAccountAlerts?: boolean; codexAccountRotationThresholdPercent?: unknown; codexAccountRotationThresholdPercentByAccount?: Readonly<Record<string, unknown>>; codexCreditsAllowed?: boolean; codexResetAutoConsumePerDay?: number; codexQuotaPolicy?: unknown; fallbackChain?: unknown; openrouter?: { fallbackModel?: unknown } } };
59
+ type RotationConfig = { llm?: { provider?: string; model?: string; codexCreditReserve?: unknown; codexAccountRotation?: boolean; codexAccountAlerts?: boolean; codexAccountRotationThresholdPercent?: unknown; codexAccountRotationThresholdPercentByAccount?: Readonly<Record<string, unknown>>; codexCreditsAllowed?: boolean; codexResetAutoConsumePerDay?: number; codexQuotaPolicy?: unknown; fallbackChain?: unknown; openrouter?: { fallbackModel?: unknown } } };
59
60
 
60
61
  function readUserConfig(): RotationConfig {
61
62
  return getUserConfig();
@@ -312,7 +313,8 @@ function rotationCreditsGrant(candidates: readonly RotationCandidate[]): Rotatio
312
313
  if (codexPolicyAllowsCredits(policy)) return { allowed: true, via: 'policy' };
313
314
  if (!codexPolicyAllowsFallback(policy)) return { allowed: false, via: 'none' };
314
315
  try {
315
- const { chain } = normalizeFallbackChain(configReader().llm?.fallbackChain);
316
+ const llm = configReader().llm;
317
+ const { chain } = normalizeFallbackChain(llm?.fallbackChain, llm?.provider);
316
318
  if (!chain.includes('codex-credits')) return { allowed: false, via: 'none' };
317
319
  const creditAccountCount = codexCreditAccountNames(candidates, codexCreditReserveFromConfig()).length;
318
320
  const fallbackModel = configReader().llm?.openrouter?.fallbackModel;
@@ -1121,6 +1123,8 @@ export function resolveRunFallback(
1121
1123
  readonly grokQuota?: 'usable' | 'exhausted' | 'unknown';
1122
1124
  /** OpenRouter 키 «존재» seam(테스트 격리) — 안 주면 `getOpenRouterApiKey()` 로 잰다. 키 값은 기록하지 않는다. */
1123
1125
  readonly openrouterAvailable?: boolean;
1126
+ /** Z.ai 키 «존재» seam(테스트 격리) — 안 주면 키 존재만 잰다. */
1127
+ readonly zaiAvailable?: boolean;
1124
1128
  /** codex 크레딧 잔액 «확인» seam — 안 주면 회전 후보의 크레딧 신호(잔액 > 0 · 보유 ≠ false)로 잰다. */
1125
1129
  readonly codexCreditsAvailable?: boolean;
1126
1130
  /** ⛔ 런 원장 «읽기» seam — 체인에 `claude-pty` 가 있을 때만 쓴다. 안 주면 실제 런 원장을 읽는다. */
@@ -1150,11 +1154,18 @@ export function resolveRunFallback(
1150
1154
  rotation = { reason: 'no-candidate' };
1151
1155
  }
1152
1156
 
1153
- const normalized = normalizeFallbackChain(configReader().llm?.fallbackChain);
1157
+ const llm = configReader().llm;
1158
+ const normalized = normalizeFallbackChain(llm?.fallbackChain, llm?.provider);
1154
1159
  const { dropped, usedDefault } = normalized;
1155
1160
  // 대표 정책 `within-quota` — codex 밖으로 폴백하지 않는다(회전만). 전부 차면 멈춘다.
1156
1161
  const quotaPolicy = codexQuotaPolicyFromConfig();
1157
- const chain = codexPolicyAllowsFallback(quotaPolicy)
1162
+ // A non-Codex primary has no Codex quota to enforce. Only its implicit
1163
+ // provider default bypasses the Codex fallback policy; an explicit chain
1164
+ // continues to obey the existing within-quota contract.
1165
+ const nonCodexProviderDefault = usedDefault
1166
+ && (llm?.provider === 'glm' || llm?.provider === 'zai' || llm?.provider === 'openrouter')
1167
+ && fallbackChainForProvider(llm?.provider) !== undefined;
1168
+ const chain = codexPolicyAllowsFallback(quotaPolicy) || nonCodexProviderDefault
1158
1169
  ? normalized.chain
1159
1170
  : normalized.chain.filter((step) => step === 'codex-rotate');
1160
1171
  // ⛔ grok 가용성은 «호출자가 확정»해서 줄 수 있다(테스트 격리). 안 주면 여기서 잰다.
@@ -1164,7 +1175,8 @@ export function resolveRunFallback(
1164
1175
  // ⛔ 「지금 쓸 수 있나」는 «자격과 다른 축»이다. 안 주면 'unknown' — 그리고 unknown 은 «통과»다.
1165
1176
  // ⇒ 「모르고 갔다」와 「알고 갔다」가 관측에서 갈린다(아래 grokQuota).
1166
1177
  const grokQuota = deps.grokQuota ?? readCachedGrokQuota();
1167
- const fallbackModel = configReader().llm?.openrouter?.fallbackModel;
1178
+ const fallbackModel = llm?.openrouter?.fallbackModel
1179
+ ?? (llm?.provider === 'openrouter' ? llm.model : undefined);
1168
1180
  // SUBSCRIPTION-EXHAUST-REROUTE — 크레딧 예비분에 닿은 «넘김»은 OpenRouter 가 먼저다(대표 OP 10-11: grok 이 아니다).
1169
1181
  // 운영 체인 `['codex-rotate','grok']` 에는 openrouter 칸이 없다 ⇒ 이 경로에만 codex 바로 뒤에 openrouter 를 끼운다
1170
1182
  // (나머지 칸은 그 뒤 · 키가 없으면 종전 체인으로). 모델은 `llm.openrouter.fallbackModel`, 없으면 «중» 기본 glm-5.3.
@@ -1179,6 +1191,7 @@ export function resolveRunFallback(
1179
1191
  : reserveReroute ? CREDIT_RESERVE_OPENROUTER_MODEL : undefined;
1180
1192
  const openrouterAvailable = effectiveChain.includes('openrouter')
1181
1193
  && (deps.openrouterAvailable ?? Boolean(getOpenRouterApiKey()?.trim()));
1194
+ const zaiAvailable = effectiveChain.includes('zai') && (deps.zaiAvailable ?? zaiCodingPlanAvailable());
1182
1195
  // CODEX-CREDITS-STEP — 체인에 그 칸이 있을 때만 잰다(없으면 판정이 안 읽는다). 잔액을 «모르면» 없다고 본다(돈 · fail-closed).
1183
1196
  // ⛔ 사람이 계정을 «명시»했으면 그 계정의 잔액만 본다 — 다른 계정 잔액으로 칸을 열고 명시 계정으로 쏘면 fail-closed 가 깨진다.
1184
1197
  const explicitAccount = snapshot.reason === 'explicit';
@@ -1191,7 +1204,7 @@ export function resolveRunFallback(
1191
1204
  // ⛔ 없으면 `undefined` 이고 판정은 종전 그대로다(수집 0회 · 판정식 무변경).
1192
1205
  const claudePtyMaturity = claudePtyMaturityForChain(effectiveChain, deps.claudePtyLedger);
1193
1206
  const fallbackBase = {
1194
- rotation, chain: effectiveChain, grokAvailable, grokQuota, openrouterFallbackModel, openrouterAvailable, codexCreditsAvailable,
1207
+ rotation, chain: effectiveChain, grokAvailable, grokQuota, openrouterFallbackModel, openrouterAvailable, zaiAvailable, codexCreditsAvailable,
1195
1208
  ...(claudePtyMaturity ? { claudePtyMaturity } : {}),
1196
1209
  };
1197
1210
  const fallbackInput: FallbackInput = deps.currentCredentialRateLimited === true && deps.currentStep
@@ -0,0 +1,44 @@
1
+ import { hostname } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { elanousStateRoot } from '../autopilot/state-paths.js';
4
+ import { getUserConfig } from '../user-config.js';
5
+ import { loadTokens, type ProviderAuthState } from './store.js';
6
+
7
+ export const CODEX_OWNER_MIRROR_RELATIVE_PATH = join('remote-parent-credentials', 'cli-mirror', 'auth.json');
8
+ export const CODEX_OWNER_MIRROR_REQUIRED = 'Codex 주인 미러가 없거나 만료됐다 — 주인 호스트에서 `eln codex mirror push <host>` 를 실행해야 한다';
9
+
10
+ export function codexOwnerMirrorAuthPath(): string {
11
+ return join(elanousStateRoot(), CODEX_OWNER_MIRROR_RELATIVE_PATH);
12
+ }
13
+
14
+ function normalizedHost(value: string): string {
15
+ return value.trim().replace(/\.local$/i, '').toLowerCase();
16
+ }
17
+
18
+ /** The HQ-configured machine identity is the stable short name used by the lease. */
19
+ export function isCodexTokenOwnerHost(config = getUserConfig(), machine = hostname()): boolean {
20
+ const owner = normalizedHost(config.llm.codexTokenOwnerHost || 'mbp');
21
+ const local = normalizedHost(config.hq?.hostName || machine);
22
+ return local === owner;
23
+ }
24
+
25
+ /** Read only a fresh, access-only HQ snapshot. This helper never performs OAuth refresh. */
26
+ export function readCodexOwnerAccessMirror(
27
+ storeKey: string,
28
+ opts: { path?: string; now?: number } = {},
29
+ ): ProviderAuthState {
30
+ const path = opts.path ?? codexOwnerMirrorAuthPath();
31
+ const now = opts.now ?? Date.now();
32
+ let state: ProviderAuthState | null = null;
33
+ try { state = loadTokens(storeKey, path); } catch { /* fail closed below */ }
34
+ const tokenFields = state?.tokens as (ProviderAuthState['tokens'] & { refresh_token?: unknown }) | undefined;
35
+ const expiresAt = state?.tokens.expiresAt;
36
+ if (!state || state.authMode !== 'chatgpt' || !state.tokens.accessToken
37
+ || tokenFields?.refreshToken !== '' || tokenFields?.refresh_token !== ''
38
+ || typeof expiresAt !== 'number'
39
+ || !Number.isFinite(expiresAt) || expiresAt <= now + 120_000) {
40
+ throw new Error(CODEX_OWNER_MIRROR_REQUIRED);
41
+ }
42
+ return state;
43
+ }
44
+
@@ -29,7 +29,8 @@ import { join } from 'node:path';
29
29
  import { DEFAULT_CODEX_ACCOUNT, codexStoreKey, isValidAccountName, resolveCodexAccount, effectiveCodexHome, type CodexAccountResolution } from './codex-account.js';
30
30
  import { importCodexAccountFromHome, resolveCodexAccountForRun } from './codex-account-store.js';
31
31
  import { decodeJWTPayload } from './jwt.js';
32
- import { authStorePath } from './store.js';
32
+ import { authStorePath, isUnderTestRunner } from './store.js';
33
+ import { codexOwnerMirrorAuthPath, isCodexTokenOwnerHost, readCodexOwnerAccessMirror } from './codex-owner-mirror.js';
33
34
  import { platform, release, arch } from 'node:os';
34
35
  import {
35
36
  saveTokens, loadTokens, expiresAtFromSeconds,
@@ -428,8 +429,22 @@ function remainingSeconds(state: ProviderAuthState | null): number | null {
428
429
  }
429
430
 
430
431
  export async function loadFreshCodexAuthState(
431
- opts: { fetchImpl?: typeof fetch; mirrorCodex?: boolean } = {},
432
+ opts: { fetchImpl?: typeof fetch; mirrorCodex?: boolean; ownerMirrorPath?: string } = {},
432
433
  ): Promise<ProviderAuthState | null> {
434
+ let tokenOwnerHost = process.env.ELANOUS_REMOTE_CODEX_ACCESS_ONLY !== '1' && isUnderTestRunner();
435
+ if (!tokenOwnerHost && process.env.ELANOUS_REMOTE_CODEX_ACCESS_ONLY !== '1' && isCodexTokenOwnerHost()) {
436
+ const { hqFenceDecision } = await import('../hq/hq.js');
437
+ tokenOwnerHost = hqFenceDecision('ledger-cli').run;
438
+ }
439
+ if (!tokenOwnerHost) {
440
+ // A non-owner host reads only the HQ-pushed access snapshot. It never
441
+ // reconciles ~/.codex or reaches the refresh endpoint with local credentials.
442
+ const mirrorPath = opts.ownerMirrorPath ?? codexOwnerMirrorAuthPath();
443
+ const account = resolveCodexAccountForRun(process.env, { storePath: mirrorPath });
444
+ const state = readCodexOwnerAccessMirror(account.storeKey, { path: mirrorPath });
445
+ observeCodexAuth('fresh', { storeKey: account.storeKey, remainingSeconds: remainingSeconds(state), refreshed: false, source: 'owner-cli-mirror' });
446
+ return state;
447
+ }
433
448
  // ⭐ 어느 «계정»의 토큰인가 — 기본 계정이면 종전과 동일한 키(`openai-codex`)다.
434
449
  // ⛔ 이름 계정이면 그 계정의 스토어 키와 «그 계정의 홈» 미러를 쓴다(A 가 B 를 덮지 않게).
435
450
  // ⭐⭐ 그리고 «리밋에 걸렸으면 다른 계정으로 넘긴다»(S4 · 대표 결정).
@@ -44,6 +44,22 @@ export type FallbackStep = (typeof FALLBACK_STEPS)[number];
44
44
  * «머문다». 즉 기본에 두는 비용은 0 이고 얻는 것은 「죽지 않음」이다. */
45
45
  export const DEFAULT_FALLBACK_CHAIN: readonly FallbackStep[] = ['codex-rotate', 'grok'];
46
46
 
47
+ /** Build a one-provider default when the user has explicitly selected a provider.
48
+ *
49
+ * Keep this mapping here so chat retry, account rotation, child defaults and launch
50
+ * budgeting do not each invent their own provider priority. `auto` keeps the
51
+ * historical default chain; explicit provider selection must never add Codex/Grok.
52
+ */
53
+ export function fallbackChainForProvider(provider: unknown): readonly FallbackStep[] | undefined {
54
+ if (typeof provider !== 'string') return undefined;
55
+ switch (provider.trim().toLowerCase()) {
56
+ case 'glm':
57
+ case 'zai': return ['zai'];
58
+ case 'openrouter': return ['openrouter'];
59
+ default: return undefined;
60
+ }
61
+ }
62
+
47
63
  export function isFallbackStep(value: unknown): value is FallbackStep {
48
64
  return typeof value === 'string' && (FALLBACK_STEPS as readonly string[]).includes(value);
49
65
  }
@@ -54,9 +70,11 @@ export function isFallbackStep(value: unknown): value is FallbackStep {
54
70
  * ⛔ 비었거나 전부 무효면 기본 체인으로 — 「설정이 있다」와 「설정이 유효하다」는 다르다. */
55
71
  export function normalizeFallbackChain(
56
72
  value: unknown,
73
+ configuredProvider?: unknown,
57
74
  ): { chain: readonly FallbackStep[]; dropped: readonly string[]; usedDefault: boolean } {
75
+ const configuredDefault = fallbackChainForProvider(configuredProvider);
58
76
  if (!Array.isArray(value)) {
59
- return { chain: DEFAULT_FALLBACK_CHAIN, dropped: [], usedDefault: true };
77
+ return { chain: configuredDefault ?? DEFAULT_FALLBACK_CHAIN, dropped: [], usedDefault: true };
60
78
  }
61
79
  const chain: FallbackStep[] = [];
62
80
  const dropped: string[] = [];
@@ -68,7 +86,7 @@ export function normalizeFallbackChain(
68
86
  }
69
87
  }
70
88
  if (chain.length === 0) {
71
- return { chain: DEFAULT_FALLBACK_CHAIN, dropped, usedDefault: true };
89
+ return { chain: configuredDefault ?? DEFAULT_FALLBACK_CHAIN, dropped, usedDefault: true };
72
90
  }
73
91
  return { chain, dropped, usedDefault: false };
74
92
  }
@@ -83,7 +101,7 @@ export type FallbackDecision =
83
101
  /** codex 계정을 갈아탄다(종전 동작). */
84
102
  | { readonly action: 'codex-rotate'; readonly to: RotationCandidate }
85
103
  /** 백엔드를 통째로 바꾼다. */
86
- | { readonly action: 'switch-backend'; readonly backend: 'grok' | 'claude' }
104
+ | { readonly action: 'switch-backend'; readonly backend: 'grok' | 'claude' | 'zai' }
87
105
  /** 명시한 유료 OpenRouter 모델로 전환한다. 호출부가 모델을 바꾸지 못하면 실행하지 않는다. */
88
106
  | { readonly action: 'switch-backend'; readonly backend: 'openrouter'; readonly model: string }
89
107
  /** codex 로 «돌아와» 선불 크레딧으로 계속한다 — 체인의 `codex-credits` 칸(마지막 수단 · 유료).
@@ -116,6 +134,7 @@ export type StayReason =
116
134
  | 'grok-exhausted'
117
135
  /** 유료 OpenRouter 모델 또는 키가 없다. */
118
136
  | 'openrouter-unavailable'
137
+ | 'zai-unavailable'
119
138
  /** claude PTY 의 최근 표본이 성숙 관문을 통과하지 못했거나 읽히지 않는다. */
120
139
  | 'claude-pty-immature'
121
140
  /** 체인에 `codex-credits` 가 있는데 크레딧 잔액이 «확인된» codex 계정이 없다(모름 포함 — 돈이라 fail-closed). */
@@ -137,6 +156,8 @@ export type FallbackInput = {
137
156
  readonly openrouterFallbackModel?: string;
138
157
  /** OpenRouter 키 존재 여부(키 값 자체는 판정·관측에 넣지 않는다). */
139
158
  readonly openrouterAvailable?: boolean;
159
+ /** Direct Z.ai coding-plan credential is available (key presence only). */
160
+ readonly zaiAvailable?: boolean;
140
161
  /**
141
162
  * grok 이 «지금 쓸 수 있나» — ⛔ 자격(`grokAvailable`)과 «다른 축»이다.
142
163
  * 'usable' 쓸 수 있다(잔량 있음 · 무제한 · 임계 미만)
@@ -183,13 +204,13 @@ export function decideFallback(input: FallbackInput): FallbackDecision {
183
204
  const {
184
205
  rotation, chain, currentStep, currentCredentialRateLimited = false,
185
206
  grokAvailable, grokQuota = 'unknown', claudePtyMaturity, stayOnResetCreditAvailable = false,
186
- openrouterFallbackModel, openrouterAvailable = false, codexCreditsAvailable = false,
207
+ openrouterFallbackModel, openrouterAvailable = false, zaiAvailable = false, codexCreditsAvailable = false,
187
208
  } = input;
188
- const openrouter = { model: openrouterFallbackModel, available: openrouterAvailable, codexCreditsAvailable };
209
+ const providerExtras = { openrouterModel: openrouterFallbackModel, openrouterAvailable, zaiAvailable, codexCreditsAvailable };
189
210
 
190
211
  if (currentCredentialRateLimited) {
191
212
  if (currentStep === undefined) return { action: 'stay', why: 'chain-exhausted' };
192
- return stepAfter(chain, currentStep, grokAvailable, grokQuota, claudePtyMaturity, openrouter, 'chain-exhausted');
213
+ return stepAfter(chain, currentStep, grokAvailable, grokQuota, claudePtyMaturity, providerExtras, 'chain-exhausted');
193
214
  }
194
215
  if (rotation.reason === 'explicit') return { action: 'stay', why: 'explicit' };
195
216
  if (rotation.reason === 'not-reached' || (rotation.reason === 'credit-pace' && !('to' in rotation))) {
@@ -203,13 +224,13 @@ export function decideFallback(input: FallbackInput): FallbackDecision {
203
224
  // 회전이 답을 냈는데 체인이 codex-rotate 를 «빼» 놨다면 그 뜻을 존중하고
204
225
  // 다음 칸으로 간다(회전을 원치 않는 구성).
205
226
  if (chain.includes('codex-rotate')) return { action: 'codex-rotate', to: rotation.to };
206
- return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity, openrouter, 'chain-exhausted');
227
+ return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity, providerExtras, 'chain-exhausted');
207
228
  }
208
229
 
209
230
  // no-candidate | disabled | reset-credit-available(기본) — codex 축이 끝났다. 다음 칸을 본다.
210
231
  // ⛔ 다음 칸이 «없을 때»의 이름만 고른다. 진행(stepAfterCodex)은 그대로다.
211
232
  const fallbackWhy = stayReasonWhenCodexAxisEnds(rotation.reason === 'credit-pace' ? 'no-candidate' : rotation.reason);
212
- return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity, openrouter, fallbackWhy);
233
+ return stepAfterCodex(chain, grokAvailable, grokQuota, claudePtyMaturity, providerExtras, fallbackWhy);
213
234
  }
214
235
 
215
236
  /** codex 축이 끝났는데 체인 다음 칸도 없을 때 머무는 이유.
@@ -223,18 +244,23 @@ export function stayReasonWhenCodexAxisEnds(
223
244
  return 'chain-exhausted';
224
245
  }
225
246
 
226
- /** 칸 판정에 필요한 «나머지» 재료 — OpenRouter 모델·키, codex 크레딧 잔액 확인. */
227
- type StepExtras = { readonly model?: string; readonly available: boolean; readonly codexCreditsAvailable?: boolean };
247
+ /** Per-provider evidence consumed by backend steps. */
248
+ type StepExtras = {
249
+ readonly openrouterModel?: string;
250
+ readonly openrouterAvailable?: boolean;
251
+ readonly zaiAvailable?: boolean;
252
+ readonly codexCreditsAvailable?: boolean;
253
+ };
228
254
 
229
255
  function stepAfterCodex(
230
256
  chain: readonly FallbackStep[],
231
257
  grokAvailable: boolean,
232
258
  grokQuota: 'usable' | 'exhausted' | 'unknown',
233
259
  claudePtyMaturity: ClaudePtyMaturity | undefined,
234
- openrouter: StepExtras,
260
+ providerExtras: StepExtras,
235
261
  whyIfNone: StayReason,
236
262
  ): FallbackDecision {
237
- return stepAfter(chain, 'codex-rotate', grokAvailable, grokQuota, claudePtyMaturity, openrouter, whyIfNone);
263
+ return stepAfter(chain, 'codex-rotate', grokAvailable, grokQuota, claudePtyMaturity, providerExtras, whyIfNone);
238
264
  }
239
265
 
240
266
  function stepAfter(
@@ -243,7 +269,7 @@ function stepAfter(
243
269
  grokAvailable: boolean,
244
270
  grokQuota: 'usable' | 'exhausted' | 'unknown',
245
271
  claudePtyMaturity: ClaudePtyMaturity | undefined,
246
- openrouter: StepExtras,
272
+ providerExtras: StepExtras,
247
273
  whyIfNone: StayReason,
248
274
  ): FallbackDecision {
249
275
  const idx = currentStep === undefined ? -1 : chain.indexOf(currentStep);
@@ -255,12 +281,16 @@ function stepAfter(
255
281
  for (const step of rest) {
256
282
  if (step === 'codex-credits') {
257
283
  // ⛔ 크레딧은 돈이다 — 잔액이 «확인된» 계정이 없으면 건너뛴다(「모른다」는 통과가 «아니다»).
258
- if (openrouter.codexCreditsAvailable !== true) { skip(step, 'codex-credits-unavailable'); continue; }
284
+ if (providerExtras.codexCreditsAvailable !== true) { skip(step, 'codex-credits-unavailable'); continue; }
259
285
  return { action: 'codex-credits', skipped };
260
286
  }
287
+ if (step === 'zai') {
288
+ if (!providerExtras.zaiAvailable) { skip(step, 'zai-unavailable'); continue; }
289
+ return { action: 'switch-backend', backend: 'zai' };
290
+ }
261
291
  if (step === 'openrouter') {
262
- const model = openrouter.model?.trim();
263
- if (!openrouter.available || !model || !/^openrouter\/[^/\s]+\/[^\s]+$/.test(model)) {
292
+ const model = providerExtras.openrouterModel?.trim();
293
+ if (!providerExtras.openrouterAvailable || !model || !/^openrouter\/[^/\s]+\/[^\s]+$/.test(model)) {
264
294
  skip(step, 'openrouter-unavailable');
265
295
  continue;
266
296
  }
@@ -290,7 +320,7 @@ export function describeFallback(decision: FallbackDecision): string {
290
320
  case 'switch-backend':
291
321
  return decision.backend === 'openrouter'
292
322
  ? `백엔드 전환 → openrouter (${decision.model} · API 과금)`
293
- : `백엔드 전환 → ${decision.backend} (구독)`;
323
+ : decision.backend === 'zai' ? '백엔드 전환 → Z.ai GLM' : `백엔드 전환 → ${decision.backend} (구독)`;
294
324
  case 'codex-credits':
295
325
  return `codex 크레딧으로 계속 (마지막 칸 · 선불 크레딧 과금${decision.skipped.length ? ` · 건너뜀 ${decision.skipped.map((s) => `${s.step}:${s.why}`).join(', ')}` : ''})`;
296
326
  case 'stay':
@@ -7,6 +7,13 @@ const AUTOMATIC = new Set<DoctorFixItem['id']>(['private-files', 'key-cache-perm
7
7
  const DEFERRED = new Set<DoctorFixItem['id']>(['install-path', 'bun-tmpdir']);
8
8
  const LATER_LINE = '나중에: elanous doctor --fix (셸 시작 파일 수정)';
9
9
 
10
+ export function safeDoctorReason(reason: string | undefined): string {
11
+ if (!reason) return '원인 불명';
12
+ return /(?:api[_-]?key|secret|token)\s*(?:=|:)?\s*\S+/i.test(reason)
13
+ ? '민감 정보가 포함된 오류'
14
+ : reason;
15
+ }
16
+
10
17
  export interface FirstRunDoctorResult {
11
18
  fixed: string[];
12
19
  skipped: string[];
@@ -20,7 +27,7 @@ export function runFirstRunDoctor(deps: DoctorFixDeps): FirstRunDoctorResult {
20
27
  const result: FirstRunDoctorResult = { fixed: [], skipped: [], failed: [], later: [], lines: [] };
21
28
  const record = (id: string, outcome: 'fixed' | 'skipped' | 'failed', reason?: string) => {
22
29
  result[outcome].push(id);
23
- if (outcome === 'failed') result.lines.push(`doctor: ${id} 수리 실패 — ${reason || '원인 불명'}`);
30
+ if (outcome === 'failed') result.lines.push(`doctor: ${id} 수리 실패 — ${safeDoctorReason(reason)}`);
24
31
  try { debug.log('doctor.first-run', outcome, { id }); } catch { /* 관측 실패가 첫 실행을 막지 않는다. */ }
25
32
  };
26
33
 
@@ -4,6 +4,12 @@ import { debug } from '../debug/log.js';
4
4
  import { detectLocale, type Locale } from '../expression/locale.js';
5
5
  import { unattendedNextStepLine } from './entry-hints.js';
6
6
  import { resolveProviderCredential } from '../llm/provider-credentials.js';
7
+ import { zaiCodingPlanAvailable } from '../llm/zai-coding-plan.js';
8
+ import { collectServiceKeys, printKeySetupReport } from './key-setup.js';
9
+ import { getSecretAsync, setSecretAsync } from '../nexus/config/secrets/index.js';
10
+ import { probeProvider } from '../llm/provider-probe.js';
11
+ import { createSecretPrompt } from './secret-prompt.js';
12
+ import { parseMenuAnswer as parseNumericMenuAnswer } from './menu-answer.js';
7
13
  import {
8
14
  getUserConfig, saveUserConfig, userConfigPath,
9
15
  type LLMProviderName, type UserConfig,
@@ -11,44 +17,45 @@ import {
11
17
 
12
18
  export interface FirstRunDeps {
13
19
  config?: UserConfig;
20
+ env?: NodeJS.ProcessEnv;
14
21
  path?: string;
15
22
  detectProviders?: () => Promise<DetectedProvider[]>;
16
23
  isTTY?: boolean;
17
24
  /** Locale for user-facing wording; defaults to the shared ambient decision (detectLocale). */
18
25
  locale?: Locale;
19
26
  chooseProvider?: (detected: readonly LLMProviderName[]) => Promise<LLMProviderName | null>;
27
+ promptSecret?: (message: string) => Promise<string | undefined>;
28
+ getSecretAsync?: typeof getSecretAsync;
29
+ setSecretAsync?: typeof setSecretAsync;
30
+ probeKey?: typeof probeProvider;
31
+ setupWhenNoProvider?: (config: UserConfig) => Promise<FirstRunProviderSetupResult>;
20
32
  print?: (message: string) => void;
21
33
  saveConfig?: (config: UserConfig, path: string) => void;
22
34
  }
23
35
 
24
- const CHOICE_BASE: readonly LLMProviderName[] = ['openai-codex', 'grok', 'anthropic'];
25
- const CHOICE_LABEL: Partial<Record<LLMProviderName, string>> = { 'openai-codex': 'Codex', grok: 'Grok', anthropic: 'Claude' };
26
- const SUBSCRIPTION_PRIORITY = ['openai-codex', 'grok', 'anthropic', 'gemini', 'openai', 'openrouter'] as const;
36
+ export type FirstRunProviderSetupResult = LLMProviderName | null | { kind: 'needs-llm' };
27
37
 
28
- /** Menu order: detected subscriptions first (in priority order), then the remaining base choices. */
38
+ const CHOICE_BASE: readonly LLMProviderName[] = ['openai-codex', 'grok', 'anthropic', 'openrouter', 'glm'];
39
+ const CHOICE_LABEL: Partial<Record<LLMProviderName, string>> = { 'openai-codex': 'Codex', grok: 'Grok', anthropic: 'Claude', openrouter: 'OpenRouter', glm: 'GLM' };
40
+ const SUBSCRIPTION_PRIORITY = ['openai-codex', 'grok', 'anthropic', 'gemini', 'openai', 'glm', 'openrouter'] as const;
41
+
42
+ /** Menu order: detected usable providers first, then the remaining supported choices. */
29
43
  export function orderProviderChoices(detected: readonly LLMProviderName[] = []): LLMProviderName[] {
30
44
  return [...detected, ...CHOICE_BASE.filter((name) => !detected.includes(name))];
31
45
  }
32
46
 
33
- export type MenuAnswer =
34
- | { kind: 'chosen'; provider: LLMProviderName }
35
- | { kind: 'cancel' }
36
- | { kind: 'miss' };
47
+ export type MenuAnswer = import('./menu-answer.js').MenuAnswer<LLMProviderName>;
37
48
 
38
49
  // FIRST10-FIX: 첫 화면의 오타 한 번이 first-run 전체를 취소하던 마찰 — 빈 입력(취소 의사)과 달리
39
50
  // 선택지를 가리키지 못하는 입력(범위 밖·전각·비정수)은 취소가 아니라 다시 묻는다.
40
51
  // 메뉴 답으로 인정하는 건 반각 십진 자릿수 문자열뿐이다 — Number() 는 '1e0'·'0x1'·'+1' 같은
41
52
  // 수식 표기를 정수로 강제 변환해 선택지로 샌다(0.2.35 재측정).
42
53
  export function parseMenuAnswer(answer: string, choices: readonly LLMProviderName[]): MenuAnswer {
43
- const trimmed = answer.trim();
44
- if (trimmed === '') return { kind: 'cancel' };
45
- if (!/^[0-9]+$/.test(trimmed)) return { kind: 'miss' };
46
- const provider = choices[Number(trimmed) - 1];
47
- return provider !== undefined ? { kind: 'chosen', provider } : { kind: 'miss' };
54
+ return parseNumericMenuAnswer(answer, choices);
48
55
  }
49
56
 
50
57
  /**
51
- * The fixed choice line of the first-run menu (`1 Codex, 2 Grok, 3 Claude`).
58
+ * The choice line of the first-run menu.
52
59
  * Single source of the wording: the prompt below renders it, and the ux-sim
53
60
  * first-run device asserts against it, so a wording change cannot drift apart.
54
61
  */
@@ -56,6 +63,8 @@ export function formatProviderMenu(choices: readonly LLMProviderName[]): string
56
63
  return choices.map((name, i) => `${i + 1} ${CHOICE_LABEL[name] ?? name}`).join(', ');
57
64
  }
58
65
 
66
+ export const FIRST_RUN_PROVIDER_MENU_PROMPT = 'Choose LLM';
67
+
59
68
  export async function promptProviderMenu(
60
69
  ask: (prompt: string) => Promise<string>,
61
70
  detected: readonly LLMProviderName[] = [],
@@ -63,7 +72,7 @@ export async function promptProviderMenu(
63
72
  const choices = orderProviderChoices(detected);
64
73
  const menu = formatProviderMenu(choices);
65
74
  for (;;) {
66
- const parsed = parseMenuAnswer(await ask(`Choose LLM (${menu}; Enter to cancel): `), choices);
75
+ const parsed = parseMenuAnswer(await ask(`${FIRST_RUN_PROVIDER_MENU_PROMPT} (${menu}; Enter to cancel): `), choices);
67
76
  if (parsed.kind === 'chosen') return parsed.provider;
68
77
  if (parsed.kind === 'cancel') return null;
69
78
  }
@@ -84,6 +93,8 @@ const FIRST_RUN_TEXT = {
84
93
  detectedPrefix: '감지: ',
85
94
  subscription: ' 구독',
86
95
  needsLlm: 'eln setup llm 으로 고르세요',
96
+ keyStoredNotReady: '키를 저장하고 검증했지만 첫 실행에서 사용할 provider 연결은 아직 완료되지 않았습니다.',
97
+ keySetupFailed: '키 설정을 완료하지 못했습니다. 비밀 값을 표시하지 않고 중단했습니다.',
87
98
  claudeNoPath: 'claude-code 구독은 구독으로 쓸 수 있는 경로가 없어 자동 선택하지 않음',
88
99
  multipleDetected: '둘 이상 감지되어 고르세요',
89
100
  },
@@ -91,6 +102,8 @@ const FIRST_RUN_TEXT = {
91
102
  detectedPrefix: 'detected: ',
92
103
  subscription: ' subscription',
93
104
  needsLlm: 'pick a provider via eln setup llm',
105
+ keyStoredNotReady: 'The key was saved and verified, but first-run provider setup is not complete yet.',
106
+ keySetupFailed: 'Key setup could not be completed. It stopped without displaying secret values.',
94
107
  claudeNoPath: 'claude-code subscription has no usable path in elanous; not auto-selecting',
95
108
  multipleDetected: 'more than one detected; pick one',
96
109
  },
@@ -105,7 +118,19 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
105
118
  const text = FIRST_RUN_TEXT[(deps.locale ?? detectLocale()) === 'en' ? 'en' : 'ko'];
106
119
  const detectionLabel = (provider: string) =>
107
120
  `${provider === 'openai-codex' ? 'codex' : provider}${text.subscription}`;
121
+ // An incomplete onboarding marker does not mean the user's LLM is unconfigured.
122
+ // Keep an already usable provider, key and model rather than replacing it with a detected subscription.
123
+ const existing = cfg.llm.provider !== 'auto'
124
+ ? resolveProviderCredential({ provider: cfg.llm.provider, rotation: cfg.llm.rotation,
125
+ baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey, env: deps.env })
126
+ : undefined;
127
+ const configured = existing && existing.source !== 'none'
128
+ ? cfg.llm.provider
129
+ // Z.ai's coding-plan credential is stored in its dedicated cache/env, not llm.apiKey.
130
+ : cfg.llm.provider === 'glm' && zaiCodingPlanAvailable() ? 'glm' : undefined;
108
131
  let detected: DetectedProvider[] = [];
132
+ // This read-only scan is unconditional, even with an incomplete existing config;
133
+ // provider availability must not depend on the setup marker/config being absent.
109
134
  try { detected = await (deps.detectProviders ?? detectProviders)(); }
110
135
  catch { /* Detection is advisory; a TTY can still choose. */ }
111
136
  const subscriptions = detected.filter((d) => d.available && (d.auth === 'oauth' || d.auth === 'agent-cli'));
@@ -113,14 +138,6 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
113
138
  const observe = (event: 'detected' | 'chosen' | 'ready' | 'needs-llm', inputs: number) =>
114
139
  debug.log('onboarding.first-run', event, { providers, inputs });
115
140
  observe('detected', 0);
116
- // An incomplete onboarding marker does not mean the user's LLM is unconfigured.
117
- // Keep an already usable provider, key and model rather than replacing them with a detected subscription.
118
- const existing = cfg.llm.provider !== 'auto'
119
- ? resolveProviderCredential({ provider: cfg.llm.provider, rotation: cfg.llm.rotation,
120
- baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey })
121
- : undefined;
122
- const configured = existing && existing.source !== 'none'
123
- ? cfg.llm.provider : undefined;
124
141
  // claude-code is detected but has no subscription path in elanous: mapping it to the 'anthropic'
125
142
  // API-key provider would save a provider whose first call fails for a subscription-only user.
126
143
  const usable = SUBSCRIPTION_PRIORITY.filter((name) => providers.includes(name));
@@ -134,6 +151,7 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
134
151
  let provider: LLMProviderName | null | undefined = configured ?? (usable.length === 1 ? usable[0] : undefined);
135
152
  if (!configured && provider) print(detectionLine(provider));
136
153
  let inputs = 0;
154
+ let providerSetUpInPlace = false;
137
155
  if (!provider) {
138
156
  if (providers.length > 0) {
139
157
  print(detectionLine(usable.length === 0
@@ -144,23 +162,64 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
144
162
  // FIRST-CHAT-NONTTY — bare `elanous` with no TTY gets the same one-line next step as the other entrances.
145
163
  return needsLlm(0, [unattendedNextStepLine()]);
146
164
  }
165
+ if (deps.setupWhenNoProvider && usable.length === 0) {
166
+ inputs = 1;
167
+ const setupResult = await deps.setupWhenNoProvider(cfg);
168
+ if (typeof setupResult === 'object' && setupResult !== null && setupResult.kind === 'needs-llm') {
169
+ return needsLlm(inputs);
170
+ }
171
+ provider = typeof setupResult === 'string' ? setupResult : null;
172
+ if (!provider) {
173
+ print('LLM 없이 첫 화면을 엽니다. LLM 기능은 사용할 수 없습니다. 다시 설정: `elanous setup keys` 또는 `elanous login openai-codex`.');
174
+ (deps.saveConfig ?? saveUserConfig)({ ...cfg, onboarding: { ...cfg.onboarding, ready: true } }, path);
175
+ observe('ready', inputs);
176
+ return { outcome: 'ready', inputs };
177
+ }
178
+ providerSetUpInPlace = true;
179
+ observe('chosen', inputs);
180
+ } else {
147
181
  inputs = 1;
148
182
  provider = await (deps.chooseProvider ?? chooseProvider)(usable);
149
183
  if (!provider) return { outcome: 'cancelled', inputs };
150
184
  observe('chosen', inputs);
185
+ }
151
186
  }
152
187
  const credential = inputs === 1 || provider !== cfg.llm.provider
153
188
  ? resolveProviderCredential({
154
189
  provider, rotation: cfg.llm.rotation,
155
190
  baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey,
191
+ env: deps.env,
156
192
  })
157
193
  : undefined;
158
- if (inputs === 1 && credential?.source === 'none') return needsLlm(inputs);
194
+ if (inputs === 1 && credential?.source === 'none'
195
+ && !(providerSetUpInPlace && provider === 'openai-codex')) {
196
+ if ((deps.isTTY ?? process.stdin.isTTY) !== true) return needsLlm(inputs);
197
+ try {
198
+ const results = await collectServiceKeys({
199
+ config: cfg,
200
+ promptSecret: deps.promptSecret ?? createSecretPrompt(),
201
+ print,
202
+ getSecret: deps.getSecretAsync,
203
+ setSecret: deps.setSecretAsync,
204
+ probe: deps.probeKey,
205
+ providers: [provider],
206
+ });
207
+ printKeySetupReport(results, print);
208
+ if (results.length === 0 || results.some((result) => result.status !== 'success')) return needsLlm(inputs);
209
+ return needsLlm(inputs, [text.keyStoredNotReady]);
210
+ } catch {
211
+ return needsLlm(inputs, [text.keySetupFailed]);
212
+ }
213
+ }
159
214
  (deps.saveConfig ?? saveUserConfig)({
160
215
  ...cfg,
161
216
  llm: { ...cfg.llm, provider,
162
- ...(provider !== cfg.llm.provider ? { apiKey: credential?.apiKey, baseUrl: credential?.baseUrl, model: undefined } : {}),
163
- ...(credential?.apiKey ? { apiKey: credential.apiKey } : {}),
217
+ ...(provider !== cfg.llm.provider ? {
218
+ apiKey: credential?.source === 'rotation' ? credential.apiKey : undefined,
219
+ baseUrl: credential?.baseUrl,
220
+ model: undefined,
221
+ } : {}),
222
+ ...(credential?.source === 'rotation' && credential.apiKey ? { apiKey: credential.apiKey } : {}),
164
223
  ...(credential?.baseUrl ? { baseUrl: credential.baseUrl } : {}) },
165
224
  onboarding: { ...cfg.onboarding, ready: true },
166
225
  }, path);