dsh-cliworker-now 0.0.0-stage → 0.7.7

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 (344) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +364 -0
  3. package/README.md +368 -2
  4. package/cordis.patch.yml +3 -0
  5. package/lib/account-models.mjs +262 -0
  6. package/lib/client.js +22139 -0
  7. package/lib/client.js.map +1 -0
  8. package/lib/grok-catalog.mjs +145 -0
  9. package/lib/hermes-native-entry.py +96 -0
  10. package/lib/hermes-nous-refresh.py +331 -0
  11. package/lib/index.js +14544 -0
  12. package/lib/index.js.map +1 -0
  13. package/lib/native-launch.mjs +234 -0
  14. package/lib/native-spawn.mjs +32 -0
  15. package/lib/own-account-lease.mjs +105 -0
  16. package/lib/pi-installation.mjs +87 -0
  17. package/lib/pi-login.mjs +80 -0
  18. package/lib/pi-native-catalog.mjs +417 -0
  19. package/lib/pi-omp-bridge.mjs +602 -0
  20. package/lib/pi-omp-environment.mjs +15 -0
  21. package/lib/pi-omp-refresh.mjs +324 -0
  22. package/lib/private-launch.mjs +23 -0
  23. package/lib/terminal-bridge.mjs +18 -0
  24. package/lib/typert.host.d.ts +3 -0
  25. package/lib/typert.host.js +1430 -0
  26. package/lib/typert.remote-client.d.ts +72 -0
  27. package/lib/typert.remote-client.d.ts.map +1 -0
  28. package/lib/typert.remote-client.js +1256 -0
  29. package/lib/types/client/account-query-queue.d.ts +16 -0
  30. package/lib/types/client/account-query-queue.js +61 -0
  31. package/lib/types/client/account-query-queue.js.map +1 -0
  32. package/lib/types/client/account-terminal-css.d.ts +1 -0
  33. package/lib/types/client/account-terminal-css.js +3 -0
  34. package/lib/types/client/account-terminal-css.js.map +1 -0
  35. package/lib/types/client/account-terminal.d.ts +17 -0
  36. package/lib/types/client/account-terminal.js +525 -0
  37. package/lib/types/client/account-terminal.js.map +1 -0
  38. package/lib/types/client/assets/antigravity.png +0 -0
  39. package/lib/types/client/assets/claude-code.png +0 -0
  40. package/lib/types/client/assets/cliworker-now-logo.png +0 -0
  41. package/lib/types/client/assets/codex.png +0 -0
  42. package/lib/types/client/assets/grok.png +0 -0
  43. package/lib/types/client/assets/hermes.png +0 -0
  44. package/lib/types/client/assets/kimi-dark.png +0 -0
  45. package/lib/types/client/assets/kimi-light.png +0 -0
  46. package/lib/types/client/assets/mimo-code.png +0 -0
  47. package/lib/types/client/assets/omp.png +0 -0
  48. package/lib/types/client/assets/opencode.png +0 -0
  49. package/lib/types/client/assets/pi.png +0 -0
  50. package/lib/types/client/assets/zcode.png +0 -0
  51. package/lib/types/client/composer-keymap.d.ts +18 -0
  52. package/lib/types/client/composer-keymap.js +49 -0
  53. package/lib/types/client/composer-keymap.js.map +1 -0
  54. package/lib/types/client/conversation-timeline.d.ts +6 -0
  55. package/lib/types/client/conversation-timeline.js +65 -0
  56. package/lib/types/client/conversation-timeline.js.map +1 -0
  57. package/lib/types/client/copy-text.d.ts +5 -0
  58. package/lib/types/client/copy-text.js +45 -0
  59. package/lib/types/client/copy-text.js.map +1 -0
  60. package/lib/types/client/icons.d.ts +21 -0
  61. package/lib/types/client/icons.js +68 -0
  62. package/lib/types/client/icons.js.map +1 -0
  63. package/lib/types/client/index.d.ts +3 -0
  64. package/lib/types/client/index.js +124 -0
  65. package/lib/types/client/index.js.map +1 -0
  66. package/lib/types/client/management-styles.d.ts +1 -0
  67. package/lib/types/client/management-styles.js +17 -0
  68. package/lib/types/client/management-styles.js.map +1 -0
  69. package/lib/types/client/name-copy.d.ts +5 -0
  70. package/lib/types/client/name-copy.js +107 -0
  71. package/lib/types/client/name-copy.js.map +1 -0
  72. package/lib/types/client/native-job-overlay.d.ts +11 -0
  73. package/lib/types/client/native-job-overlay.js +129 -0
  74. package/lib/types/client/native-job-overlay.js.map +1 -0
  75. package/lib/types/client/operation-error.d.ts +2 -0
  76. package/lib/types/client/operation-error.js +12 -0
  77. package/lib/types/client/operation-error.js.map +1 -0
  78. package/lib/types/client/panel.d.ts +8 -0
  79. package/lib/types/client/panel.js +310 -0
  80. package/lib/types/client/panel.js.map +1 -0
  81. package/lib/types/client/rename-copy-styles.d.ts +1 -0
  82. package/lib/types/client/rename-copy-styles.js +21 -0
  83. package/lib/types/client/rename-copy-styles.js.map +1 -0
  84. package/lib/types/client/rename-worker.d.ts +9 -0
  85. package/lib/types/client/rename-worker.js +53 -0
  86. package/lib/types/client/rename-worker.js.map +1 -0
  87. package/lib/types/client/role-presets.d.ts +6 -0
  88. package/lib/types/client/role-presets.js +111 -0
  89. package/lib/types/client/role-presets.js.map +1 -0
  90. package/lib/types/client/settings-dialog.d.ts +13 -0
  91. package/lib/types/client/settings-dialog.js +442 -0
  92. package/lib/types/client/settings-dialog.js.map +1 -0
  93. package/lib/types/client/stat-popover.d.ts +10 -0
  94. package/lib/types/client/stat-popover.js +32 -0
  95. package/lib/types/client/stat-popover.js.map +1 -0
  96. package/lib/types/client/styles.d.ts +9 -0
  97. package/lib/types/client/styles.js +221 -0
  98. package/lib/types/client/styles.js.map +1 -0
  99. package/lib/types/client/telemetry.d.ts +11 -0
  100. package/lib/types/client/telemetry.js +24 -0
  101. package/lib/types/client/telemetry.js.map +1 -0
  102. package/lib/types/client/worker-card.d.ts +10 -0
  103. package/lib/types/client/worker-card.js +75 -0
  104. package/lib/types/client/worker-card.js.map +1 -0
  105. package/lib/types/client/worker-model-menu.d.ts +9 -0
  106. package/lib/types/client/worker-model-menu.js +136 -0
  107. package/lib/types/client/worker-model-menu.js.map +1 -0
  108. package/lib/types/client/workers.d.ts +21 -0
  109. package/lib/types/client/workers.js +59 -0
  110. package/lib/types/client/workers.js.map +1 -0
  111. package/lib/types/client/zcode-login-link-provider.d.ts +9 -0
  112. package/lib/types/client/zcode-login-link-provider.js +105 -0
  113. package/lib/types/client/zcode-login-link-provider.js.map +1 -0
  114. package/lib/types/client/zcode-login-link.d.ts +16 -0
  115. package/lib/types/client/zcode-login-link.js +194 -0
  116. package/lib/types/client/zcode-login-link.js.map +1 -0
  117. package/lib/types/host/account-identity.d.ts +16 -0
  118. package/lib/types/host/account-identity.js +126 -0
  119. package/lib/types/host/account-identity.js.map +1 -0
  120. package/lib/types/host/account-login.d.ts +10 -0
  121. package/lib/types/host/account-login.js +126 -0
  122. package/lib/types/host/account-login.js.map +1 -0
  123. package/lib/types/host/account-models.d.mts +21 -0
  124. package/lib/types/host/account-models.mjs +262 -0
  125. package/lib/types/host/accounts.d.ts +42 -0
  126. package/lib/types/host/accounts.js +945 -0
  127. package/lib/types/host/accounts.js.map +1 -0
  128. package/lib/types/host/adapters.d.ts +24 -0
  129. package/lib/types/host/adapters.js +380 -0
  130. package/lib/types/host/adapters.js.map +1 -0
  131. package/lib/types/host/agy-context.d.ts +8 -0
  132. package/lib/types/host/agy-context.js +122 -0
  133. package/lib/types/host/agy-context.js.map +1 -0
  134. package/lib/types/host/agy-models.d.ts +5 -0
  135. package/lib/types/host/agy-models.js +37 -0
  136. package/lib/types/host/agy-models.js.map +1 -0
  137. package/lib/types/host/agy-windows-account.d.ts +14 -0
  138. package/lib/types/host/agy-windows-account.js +104 -0
  139. package/lib/types/host/agy-windows-account.js.map +1 -0
  140. package/lib/types/host/authorized-catalog.d.ts +14 -0
  141. package/lib/types/host/authorized-catalog.js +35 -0
  142. package/lib/types/host/authorized-catalog.js.map +1 -0
  143. package/lib/types/host/bridge-protocol.d.ts +15 -0
  144. package/lib/types/host/bridge-protocol.js +80 -0
  145. package/lib/types/host/bridge-protocol.js.map +1 -0
  146. package/lib/types/host/claude-native-oauth.d.ts +17 -0
  147. package/lib/types/host/claude-native-oauth.js +272 -0
  148. package/lib/types/host/claude-native-oauth.js.map +1 -0
  149. package/lib/types/host/claude-own-route.d.ts +33 -0
  150. package/lib/types/host/claude-own-route.js +250 -0
  151. package/lib/types/host/claude-own-route.js.map +1 -0
  152. package/lib/types/host/cli-account-binding.d.ts +33 -0
  153. package/lib/types/host/cli-account-binding.js +540 -0
  154. package/lib/types/host/cli-account-binding.js.map +1 -0
  155. package/lib/types/host/cli-protocol.d.ts +27 -0
  156. package/lib/types/host/cli-protocol.js +212 -0
  157. package/lib/types/host/cli-protocol.js.map +1 -0
  158. package/lib/types/host/codex-account.d.ts +8 -0
  159. package/lib/types/host/codex-account.js +143 -0
  160. package/lib/types/host/codex-account.js.map +1 -0
  161. package/lib/types/host/codex-models.d.ts +6 -0
  162. package/lib/types/host/codex-models.js +169 -0
  163. package/lib/types/host/codex-models.js.map +1 -0
  164. package/lib/types/host/extended-adapters.d.ts +44 -0
  165. package/lib/types/host/extended-adapters.js +207 -0
  166. package/lib/types/host/extended-adapters.js.map +1 -0
  167. package/lib/types/host/first-party-account-context.d.ts +26 -0
  168. package/lib/types/host/first-party-account-context.js +55 -0
  169. package/lib/types/host/first-party-account-context.js.map +1 -0
  170. package/lib/types/host/first-party-models.d.ts +29 -0
  171. package/lib/types/host/first-party-models.js +459 -0
  172. package/lib/types/host/first-party-models.js.map +1 -0
  173. package/lib/types/host/grok-adapter.d.ts +44 -0
  174. package/lib/types/host/grok-adapter.js +293 -0
  175. package/lib/types/host/grok-adapter.js.map +1 -0
  176. package/lib/types/host/grok-models.d.ts +47 -0
  177. package/lib/types/host/grok-models.js +320 -0
  178. package/lib/types/host/grok-models.js.map +1 -0
  179. package/lib/types/host/harness-opencode-accounts.d.ts +17 -0
  180. package/lib/types/host/harness-opencode-accounts.js +80 -0
  181. package/lib/types/host/harness-opencode-accounts.js.map +1 -0
  182. package/lib/types/host/hermes-account-context.d.ts +8 -0
  183. package/lib/types/host/hermes-account-context.js +99 -0
  184. package/lib/types/host/hermes-account-context.js.map +1 -0
  185. package/lib/types/host/hermes-accounts.d.ts +19 -0
  186. package/lib/types/host/hermes-accounts.js +356 -0
  187. package/lib/types/host/hermes-accounts.js.map +1 -0
  188. package/lib/types/host/hermes-adapter.d.ts +93 -0
  189. package/lib/types/host/hermes-adapter.js +455 -0
  190. package/lib/types/host/hermes-adapter.js.map +1 -0
  191. package/lib/types/host/hermes-env.d.ts +4 -0
  192. package/lib/types/host/hermes-env.js +22 -0
  193. package/lib/types/host/hermes-env.js.map +1 -0
  194. package/lib/types/host/hermes-installation.d.ts +10 -0
  195. package/lib/types/host/hermes-installation.js +181 -0
  196. package/lib/types/host/hermes-installation.js.map +1 -0
  197. package/lib/types/host/hermes-models.d.ts +26 -0
  198. package/lib/types/host/hermes-models.js +328 -0
  199. package/lib/types/host/hermes-models.js.map +1 -0
  200. package/lib/types/host/hermes-native-entry.py +96 -0
  201. package/lib/types/host/hermes-nous-refresh.py +331 -0
  202. package/lib/types/host/hermes-nous.d.ts +53 -0
  203. package/lib/types/host/hermes-nous.js +343 -0
  204. package/lib/types/host/hermes-nous.js.map +1 -0
  205. package/lib/types/host/hermes-renewal.d.ts +27 -0
  206. package/lib/types/host/hermes-renewal.js +292 -0
  207. package/lib/types/host/hermes-renewal.js.map +1 -0
  208. package/lib/types/host/hermes-suppression.d.ts +7 -0
  209. package/lib/types/host/hermes-suppression.js +69 -0
  210. package/lib/types/host/hermes-suppression.js.map +1 -0
  211. package/lib/types/host/hermes-windows-installation.d.ts +5 -0
  212. package/lib/types/host/hermes-windows-installation.js +91 -0
  213. package/lib/types/host/hermes-windows-installation.js.map +1 -0
  214. package/lib/types/host/index.d.ts +140 -0
  215. package/lib/types/host/index.js +947 -0
  216. package/lib/types/host/index.js.map +1 -0
  217. package/lib/types/host/kimi-accounts.d.ts +17 -0
  218. package/lib/types/host/kimi-accounts.js +220 -0
  219. package/lib/types/host/kimi-accounts.js.map +1 -0
  220. package/lib/types/host/kimi-oauth-models.d.ts +14 -0
  221. package/lib/types/host/kimi-oauth-models.js +246 -0
  222. package/lib/types/host/kimi-oauth-models.js.map +1 -0
  223. package/lib/types/host/managed-agent.d.ts +4 -0
  224. package/lib/types/host/managed-agent.js +127 -0
  225. package/lib/types/host/managed-agent.js.map +1 -0
  226. package/lib/types/host/mimo-configuration.d.ts +22 -0
  227. package/lib/types/host/mimo-configuration.js +258 -0
  228. package/lib/types/host/mimo-configuration.js.map +1 -0
  229. package/lib/types/host/mimo-metadata-cache.d.ts +22 -0
  230. package/lib/types/host/mimo-metadata-cache.js +121 -0
  231. package/lib/types/host/mimo-metadata-cache.js.map +1 -0
  232. package/lib/types/host/native-capability-cache.d.ts +11 -0
  233. package/lib/types/host/native-capability-cache.js +94 -0
  234. package/lib/types/host/native-capability-cache.js.map +1 -0
  235. package/lib/types/host/native-launch.d.mts +2 -0
  236. package/lib/types/host/native-launch.mjs +234 -0
  237. package/lib/types/host/native-process.d.ts +5 -0
  238. package/lib/types/host/native-process.js +41 -0
  239. package/lib/types/host/native-process.js.map +1 -0
  240. package/lib/types/host/native-spawn.mjs +32 -0
  241. package/lib/types/host/opencode-adapter.d.ts +94 -0
  242. package/lib/types/host/opencode-adapter.js +507 -0
  243. package/lib/types/host/opencode-adapter.js.map +1 -0
  244. package/lib/types/host/opencode-native.d.ts +27 -0
  245. package/lib/types/host/opencode-native.js +403 -0
  246. package/lib/types/host/opencode-native.js.map +1 -0
  247. package/lib/types/host/own-account-lease.d.mts +5 -0
  248. package/lib/types/host/own-account-lease.mjs +105 -0
  249. package/lib/types/host/pi-installation.d.mts +7 -0
  250. package/lib/types/host/pi-installation.mjs +87 -0
  251. package/lib/types/host/pi-omp-accounts.d.ts +28 -0
  252. package/lib/types/host/pi-omp-accounts.js +175 -0
  253. package/lib/types/host/pi-omp-accounts.js.map +1 -0
  254. package/lib/types/host/pi-omp-adapter.d.ts +32 -0
  255. package/lib/types/host/pi-omp-adapter.js +190 -0
  256. package/lib/types/host/pi-omp-adapter.js.map +1 -0
  257. package/lib/types/host/pi-omp-environment.d.mts +1 -0
  258. package/lib/types/host/pi-omp-environment.mjs +15 -0
  259. package/lib/types/host/pi-omp-identity.d.ts +2 -0
  260. package/lib/types/host/pi-omp-identity.js +142 -0
  261. package/lib/types/host/pi-omp-identity.js.map +1 -0
  262. package/lib/types/host/pi-omp-logout.d.ts +3 -0
  263. package/lib/types/host/pi-omp-logout.js +152 -0
  264. package/lib/types/host/pi-omp-logout.js.map +1 -0
  265. package/lib/types/host/pi-omp-native.d.ts +71 -0
  266. package/lib/types/host/pi-omp-native.js +753 -0
  267. package/lib/types/host/pi-omp-native.js.map +1 -0
  268. package/lib/types/host/pi-omp-refresh.d.mts +7 -0
  269. package/lib/types/host/pi-omp-refresh.mjs +324 -0
  270. package/lib/types/host/private-launch.mjs +23 -0
  271. package/lib/types/host/process.d.ts +43 -0
  272. package/lib/types/host/process.js +134 -0
  273. package/lib/types/host/process.js.map +1 -0
  274. package/lib/types/host/protocol.d.ts +23 -0
  275. package/lib/types/host/protocol.js +112 -0
  276. package/lib/types/host/protocol.js.map +1 -0
  277. package/lib/types/host/roles.d.ts +34 -0
  278. package/lib/types/host/roles.js +80 -0
  279. package/lib/types/host/roles.js.map +1 -0
  280. package/lib/types/host/routing.d.ts +31 -0
  281. package/lib/types/host/routing.js +248 -0
  282. package/lib/types/host/routing.js.map +1 -0
  283. package/lib/types/host/runtime.d.ts +60 -0
  284. package/lib/types/host/runtime.js +598 -0
  285. package/lib/types/host/runtime.js.map +1 -0
  286. package/lib/types/host/storage.d.ts +48 -0
  287. package/lib/types/host/storage.js +449 -0
  288. package/lib/types/host/storage.js.map +1 -0
  289. package/lib/types/host/telemetry.d.ts +17 -0
  290. package/lib/types/host/telemetry.js +158 -0
  291. package/lib/types/host/telemetry.js.map +1 -0
  292. package/lib/types/host/windows-account-bootstrap.ps1 +44 -0
  293. package/lib/types/host/windows-account-launch.mjs +47 -0
  294. package/lib/types/host/windows-account-owner.ps1 +137 -0
  295. package/lib/types/host/windows-account-stdio.mjs +19 -0
  296. package/lib/types/host/windows-account-terminal.d.ts +17 -0
  297. package/lib/types/host/windows-account-terminal.js +208 -0
  298. package/lib/types/host/windows-account-terminal.js.map +1 -0
  299. package/lib/types/host/windows-agy-account.ps1 +81 -0
  300. package/lib/types/host/windows-cli-installation.d.ts +31 -0
  301. package/lib/types/host/windows-cli-installation.js +157 -0
  302. package/lib/types/host/windows-cli-installation.js.map +1 -0
  303. package/lib/types/host/windows-hidden-launch.mjs +49 -0
  304. package/lib/types/host/windows-hidden-process.d.ts +12 -0
  305. package/lib/types/host/windows-hidden-process.js +116 -0
  306. package/lib/types/host/windows-hidden-process.js.map +1 -0
  307. package/lib/types/host/zcode-account-models.d.ts +16 -0
  308. package/lib/types/host/zcode-account-models.js +114 -0
  309. package/lib/types/host/zcode-account-models.js.map +1 -0
  310. package/lib/types/host/zcode-adapter.d.ts +93 -0
  311. package/lib/types/host/zcode-adapter.js +808 -0
  312. package/lib/types/host/zcode-adapter.js.map +1 -0
  313. package/lib/types/host/zcode-grok-accounts.d.ts +30 -0
  314. package/lib/types/host/zcode-grok-accounts.js +408 -0
  315. package/lib/types/host/zcode-grok-accounts.js.map +1 -0
  316. package/lib/types/shared/accounts.d.ts +47 -0
  317. package/lib/types/shared/accounts.js +2 -0
  318. package/lib/types/shared/accounts.js.map +1 -0
  319. package/lib/types/shared/builtin-presets.d.ts +2 -0
  320. package/lib/types/shared/builtin-presets.js +231 -0
  321. package/lib/types/shared/builtin-presets.js.map +1 -0
  322. package/lib/types/shared/cli-settings.d.ts +5 -0
  323. package/lib/types/shared/cli-settings.js +2 -0
  324. package/lib/types/shared/cli-settings.js.map +1 -0
  325. package/lib/types/shared/model-presentation.d.ts +10 -0
  326. package/lib/types/shared/model-presentation.js +95 -0
  327. package/lib/types/shared/model-presentation.js.map +1 -0
  328. package/lib/types/shared/models.d.ts +7 -0
  329. package/lib/types/shared/models.js +35 -0
  330. package/lib/types/shared/models.js.map +1 -0
  331. package/lib/types/shared/telemetry.d.ts +18 -0
  332. package/lib/types/shared/telemetry.js +16 -0
  333. package/lib/types/shared/telemetry.js.map +1 -0
  334. package/lib/types/shared/types.d.ts +127 -0
  335. package/lib/types/shared/types.js +147 -0
  336. package/lib/types/shared/types.js.map +1 -0
  337. package/lib/windows-account-bootstrap.ps1 +44 -0
  338. package/lib/windows-account-launch.mjs +47 -0
  339. package/lib/windows-account-owner.ps1 +137 -0
  340. package/lib/windows-account-stdio.mjs +19 -0
  341. package/lib/windows-agy-account.ps1 +81 -0
  342. package/lib/windows-hidden-launch.mjs +49 -0
  343. package/lib/zcode-resume.mjs +423 -0
  344. package/package.json +109 -4
@@ -0,0 +1,753 @@
1
+ import { constants } from 'node:fs';
2
+ import { lstat, open, mkdir, writeFile, rename, rm, mkdtemp, realpath, readlink } from 'node:fs/promises';
3
+ import { homedir, tmpdir } from 'node:os';
4
+ import { dirname, join, resolve, sep, parse, relative } from 'node:path';
5
+ import { randomUUID } from 'node:crypto';
6
+ import { DatabaseSync } from 'node:sqlite';
7
+ import { parse as parseYaml } from 'yaml';
8
+ import { authenticatedAccountLogins, providerLogin, usableNativeApiKey } from "./account-login.js";
9
+ import { acquireOwnAccountLease, releaseOwnAccountLease, OWN_ACCOUNT_BUSY } from './own-account-lease.mjs';
10
+ import { refreshFingerprint, refreshPrincipal, refreshJson, writeRefreshJson, assertPiOmpRefreshCache, assertPiOmpRefreshSources, } from './pi-omp-refresh.mjs';
11
+ const object = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
12
+ const defaultRoot = () => join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'cliworker-now');
13
+ const runtimeEnv = /^(?:PATH|HOME|SHELL|TMPDIR|NODE_OPTIONS|NODE_PATH|ELECTRON_RUN_AS_NODE|OMP_AUTH_BROKER_.*|OMP_PROFILE|PI_PROFILE|PI_CONFIG_DIR|PI_CODING_AGENT_DIR|LD_.*|DYLD_.*)$/;
14
+ const knownProviderEnvironment = {
15
+ openai: 'OPENAI_API_KEY',
16
+ anthropic: 'ANTHROPIC_API_KEY',
17
+ google: 'GEMINI_API_KEY',
18
+ xai: 'XAI_API_KEY',
19
+ groq: 'GROQ_API_KEY',
20
+ openrouter: 'OPENROUTER_API_KEY',
21
+ mistral: 'MISTRAL_API_KEY',
22
+ cerebras: 'CEREBRAS_API_KEY',
23
+ zai: 'ZAI_API_KEY',
24
+ 'zhipu-coding-plan': 'ZHIPU_API_KEY',
25
+ 'zai-coding-cn': 'ZAI_CODING_CN_API_KEY',
26
+ };
27
+ function configuredEnvironmentRefs(value, output = new Set()) {
28
+ if (typeof value === 'string' && /^[A-Z][A-Z0-9_]*$/.test(value))
29
+ output.add(value);
30
+ if (object(value) || Array.isArray(value))
31
+ for (const entry of Object.values(value))
32
+ configuredEnvironmentRefs(entry, output);
33
+ return output;
34
+ }
35
+ export const piOmpAccountDirectory = (cli, root = defaultRoot()) => join(root, 'accounts', cli, 'agent');
36
+ /** Preserve drive and UNC roots instead of treating them as ordinary path components. */
37
+ export function nativeAccountAncestors(path, paths = { resolve, parse, relative, join, sep }) {
38
+ const absolute = paths.resolve(path);
39
+ let current = paths.parse(absolute).root;
40
+ return paths
41
+ .relative(current, absolute)
42
+ .split(paths.sep)
43
+ .filter(Boolean)
44
+ .map((component) => (current = paths.join(current, component)));
45
+ }
46
+ export async function safePiOmpAncestors(path) {
47
+ for (const current of nativeAccountAncestors(path)) {
48
+ try {
49
+ const info = await lstat(current);
50
+ if (info.isSymbolicLink()) {
51
+ // macOS system aliases are immutable trust roots, unlike user links.
52
+ if (!((current === '/var' || current === '/tmp') &&
53
+ resolve(dirname(current), await readlink(current)) === `/private${current}`))
54
+ throw new Error('Unsafe native account ancestor symlink');
55
+ }
56
+ else if (!info.isDirectory())
57
+ throw new Error('Unsafe native account directory');
58
+ }
59
+ catch (error) {
60
+ if (error.code === 'ENOENT')
61
+ break;
62
+ throw error;
63
+ }
64
+ }
65
+ }
66
+ /** Bounded, no-follow reads. Never create, chmod, checkpoint, or migrate a source. */
67
+ async function readOptional(path, limit = 2 * 1024 * 1024) {
68
+ let file;
69
+ try {
70
+ const directory = dirname(path);
71
+ await safePiOmpAncestors(directory);
72
+ const parent = await lstat(directory);
73
+ if (!parent.isDirectory() || parent.isSymbolicLink())
74
+ throw new Error('Unsafe native account directory');
75
+ const entry = await lstat(path);
76
+ if (entry.isSymbolicLink() || !entry.isFile() || entry.nlink !== 1)
77
+ throw new Error('Unsafe native account file');
78
+ file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
79
+ const before = await file.stat();
80
+ if (!before.isFile() ||
81
+ before.nlink !== 1 ||
82
+ before.dev !== entry.dev ||
83
+ before.ino !== entry.ino ||
84
+ before.size > limit)
85
+ throw new Error('Unsafe native account file');
86
+ const buffer = Buffer.alloc(before.size + 1);
87
+ const { bytesRead } = await file.read(buffer, 0, buffer.length, 0);
88
+ const after = await file.stat();
89
+ const current = await lstat(path);
90
+ if (current.isSymbolicLink() ||
91
+ current.dev !== before.dev ||
92
+ current.ino !== before.ino ||
93
+ current.nlink !== 1 ||
94
+ bytesRead !== before.size ||
95
+ before.size !== after.size ||
96
+ before.mtimeMs !== after.mtimeMs ||
97
+ current.size !== after.size ||
98
+ current.mtimeMs !== after.mtimeMs)
99
+ throw new Error('Native account changed during read');
100
+ return buffer.subarray(0, bytesRead);
101
+ }
102
+ catch (error) {
103
+ if (error.code === 'ENOENT')
104
+ return undefined;
105
+ throw error;
106
+ }
107
+ finally {
108
+ await file?.close();
109
+ }
110
+ }
111
+ function parseObject(raw, yaml = false) {
112
+ if (!raw)
113
+ return {};
114
+ const result = yaml
115
+ ? parseYaml(raw.toString('utf8'), { maxAliasCount: 0 })
116
+ : JSON.parse(raw.toString('utf8'));
117
+ if (!object(result))
118
+ throw new Error('Invalid native account config');
119
+ return result;
120
+ }
121
+ function rejectCommands(value) {
122
+ if (typeof value === 'string' && value.trimStart().startsWith('!'))
123
+ throw new Error('Native credential command helpers are not enabled in plugin workers');
124
+ if (object(value) || Array.isArray(value))
125
+ for (const entry of Object.values(value))
126
+ rejectCommands(entry);
127
+ }
128
+ function credentialState(type, data, disabled) {
129
+ if (!object(data))
130
+ throw new Error('Invalid native credential data');
131
+ if (disabled)
132
+ return 'expired';
133
+ if (type === 'api' || type === 'api_key') {
134
+ const key = data.key ?? data.apiKey;
135
+ if (typeof key !== 'string' || !key.trim())
136
+ throw new Error('Invalid native API credential');
137
+ return 'configured';
138
+ }
139
+ if (type === 'oauth') {
140
+ if (typeof data.access !== 'string' || !data.access)
141
+ throw new Error('Invalid native OAuth credential');
142
+ if (typeof data.expires !== 'number' ||
143
+ !Number.isFinite(data.expires) ||
144
+ (data.refresh !== undefined && typeof data.refresh !== 'string'))
145
+ throw new Error('Invalid native OAuth expiry/refresh');
146
+ if (data.expires < Date.now() && !data.refresh)
147
+ return 'expired';
148
+ return 'configured';
149
+ }
150
+ throw new Error('Unsupported native credential type');
151
+ }
152
+ async function source(cli, path, scratch) {
153
+ const result = {
154
+ sourceId: resolve(path),
155
+ auth: {},
156
+ models: {},
157
+ modelCache: [],
158
+ modelsStore: {},
159
+ credentials: [],
160
+ kinds: new Set(),
161
+ expired: false,
162
+ env: {},
163
+ brokerConfigured: false,
164
+ };
165
+ const dotenv = await readOptional(join(path, '.env'), 64 * 1024);
166
+ if (dotenv)
167
+ for (const line of dotenv.toString('utf8').split(/\r?\n/)) {
168
+ if (!line.trim() || line.trimStart().startsWith('#'))
169
+ continue;
170
+ const match = /^(?:export\s+)?([A-Z][A-Z0-9_]*)\s*=\s*(.*)$/.exec(line.trim());
171
+ if (!match)
172
+ throw new Error('Invalid native environment config');
173
+ let value = match[2];
174
+ if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith("'") && value.endsWith("'")))
175
+ value = value.slice(1, -1);
176
+ if (cli === 'omp' && /^OMP_AUTH_BROKER_(?:URL|TOKEN)$/.test(match[1]) && value.trim())
177
+ result.brokerConfigured = true;
178
+ if (/`|\$\(|\x00/.test(value))
179
+ throw new Error('Native environment command interpolation is disabled');
180
+ // Preserve provider credential env only, never PATH/HOME/runtime overrides.
181
+ if (!runtimeEnv.test(match[1]))
182
+ result.env[match[1]] = value;
183
+ }
184
+ if (cli === 'pi') {
185
+ result.auth = parseObject(await readOptional(join(path, 'auth.json')));
186
+ result.models = parseObject(await readOptional(join(path, 'models.json')));
187
+ result.modelsStore = parseObject(await readOptional(join(path, 'models-store.json'), 16 * 1024 * 1024));
188
+ if (Object.values(result.modelsStore).some((entry) => !object(entry) || !Array.isArray(entry.models)))
189
+ throw new Error('Invalid Pi native model cache');
190
+ const settings = parseObject(await readOptional(join(path, 'settings.json')));
191
+ result.config =
192
+ settings.defaultThinkingLevel === undefined
193
+ ? {}
194
+ : { defaultThinkingLevel: settings.defaultThinkingLevel };
195
+ rejectCommands(result.auth);
196
+ rejectCommands(result.models);
197
+ for (const auth of Object.values(result.auth)) {
198
+ if (!object(auth) || typeof auth.type !== 'string')
199
+ throw new Error('Invalid Pi native credential');
200
+ const state = credentialState(auth.type, auth);
201
+ if (state === 'configured')
202
+ result.kinds.add(auth.type);
203
+ if (state === 'expired')
204
+ result.expired = true;
205
+ }
206
+ }
207
+ else {
208
+ result.models = parseObject(await readOptional(join(path, 'models.yml')), true);
209
+ const config = parseObject(await readOptional(join(path, 'config.yml')), true);
210
+ result.brokerConfigured ||= !!config.auth?.broker;
211
+ // Only model/auth-specific settings enter workers; extension/hooks/tools do not.
212
+ result.config = {
213
+ ...(object(config.auth)
214
+ ? { auth: Object.fromEntries(Object.entries(config.auth).filter(([key]) => key !== 'broker')) }
215
+ : {}),
216
+ ...(config.defaultThinkingLevel === undefined
217
+ ? {}
218
+ : { defaultThinkingLevel: config.defaultThinkingLevel }),
219
+ };
220
+ rejectCommands(result.models);
221
+ rejectCommands(result.config);
222
+ for (const provider of Object.values(result.models.providers ?? {})) {
223
+ if (!object(provider))
224
+ throw new Error('Invalid OMP native provider');
225
+ // Literal custom-provider keys are local configuration evidence. Environment
226
+ // names alone do not establish auth (Host's CN env is supplied separately).
227
+ if (typeof provider.apiKey === 'string' &&
228
+ !/^[A-Z][A-Z0-9_]*$/.test(provider.apiKey) &&
229
+ provider.apiKey.trim())
230
+ result.kinds.add('api');
231
+ }
232
+ for (const name of ['agent.db', 'models.db']) {
233
+ const bytes = await readOptional(join(path, name), 16 * 1024 * 1024);
234
+ if (!bytes)
235
+ continue;
236
+ const wal = await readOptional(join(path, `${name}-wal`), 32 * 1024 * 1024);
237
+ if (!scratch)
238
+ throw new Error('Missing private SQLite scratch directory');
239
+ const copy = join(scratch, `${randomUUID()}.db`);
240
+ await writeFile(copy, bytes, { flag: 'wx', mode: 0o600 });
241
+ if (wal)
242
+ await writeFile(`${copy}-wal`, wal, { flag: 'wx', mode: 0o600 });
243
+ let db;
244
+ try {
245
+ db = new DatabaseSync(copy);
246
+ if (db.prepare('PRAGMA quick_check').get()?.quick_check !== 'ok')
247
+ throw new Error('Invalid native account database');
248
+ const tables = new Set(db
249
+ .prepare("SELECT name FROM sqlite_master WHERE type='table'")
250
+ .all()
251
+ .map((x) => x.name));
252
+ if (name === 'agent.db' && tables.has('auth_credentials')) {
253
+ result.credentials = db
254
+ .prepare('SELECT rowid AS native_rowid,provider,credential_type,data,disabled_cause FROM auth_credentials')
255
+ .all();
256
+ for (const row of result.credentials) {
257
+ const data = JSON.parse(row.data);
258
+ rejectCommands(data);
259
+ const state = credentialState(row.credential_type, data, row.disabled_cause);
260
+ if (state === 'configured')
261
+ result.kinds.add(row.credential_type);
262
+ if (state === 'expired')
263
+ result.expired = true;
264
+ }
265
+ }
266
+ if (name === 'models.db' && tables.has('model_cache'))
267
+ result.modelCache = db
268
+ .prepare('SELECT provider_id,version,updated_at,authoritative,static_fingerprint,models FROM model_cache')
269
+ .all();
270
+ for (const row of result.modelCache) {
271
+ if (!Array.isArray(JSON.parse(row.models)))
272
+ throw new Error('Invalid OMP native model cache');
273
+ }
274
+ }
275
+ finally {
276
+ db?.close();
277
+ await Promise.all(['', '-wal', '-shm'].map((suffix) => rm(copy + suffix, { force: true })));
278
+ }
279
+ }
280
+ }
281
+ const refs = configuredEnvironmentRefs([result.models, result.config]);
282
+ for (const key of Object.keys(result.env))
283
+ if (!/_(?:API_KEY|TOKEN|SECRET)$/.test(key) && !refs.has(key))
284
+ delete result.env[key];
285
+ // Earlier versions wrote this exact Host-only route into the plugin store.
286
+ // Preserve native/user configuration, including an explicitly supplied own .env.
287
+ const legacy = result.models.providers?.['cliworker-zai-cn'];
288
+ if (object(legacy) &&
289
+ legacy.apiKey === 'ZAI_CODING_CN_API_KEY' &&
290
+ legacy.baseUrl === 'https://open.bigmodel.cn/api/coding/paas/v4' &&
291
+ !result.env.ZAI_CODING_CN_API_KEY)
292
+ delete result.models.providers['cliworker-zai-cn'];
293
+ return result;
294
+ }
295
+ async function withSources(cli, options, fn) {
296
+ options.signal?.throwIfAborted();
297
+ const root = options.accountRoot ?? defaultRoot();
298
+ await safePiOmpAncestors(root);
299
+ const scratch = await mkdtemp(join(await realpath(tmpdir()), 'cliworker-native-read-'));
300
+ try {
301
+ const global = join(options.nativeHome ?? homedir(), cli === 'pi' ? '.pi' : '.omp', 'agent');
302
+ const paths = [...new Set([global, piOmpAccountDirectory(cli, root)])];
303
+ const results = [];
304
+ for (const path of paths) {
305
+ options.signal?.throwIfAborted();
306
+ results.push(await source(cli, path, scratch));
307
+ }
308
+ options.signal?.throwIfAborted();
309
+ return await fn(results, scratch);
310
+ }
311
+ finally {
312
+ await rm(scratch, { recursive: true, force: true });
313
+ }
314
+ }
315
+ /** Current native roots only. Account actions must never remove a merged worker copy. */
316
+ export async function readPiOmpLogoutSources(cli, stateDirectory, signal, options = {}) {
317
+ return withSources(cli, { accountRoot: stateDirectory, ...options, signal }, async (sources) => {
318
+ const result = [];
319
+ for (const [index, source] of sources.entries()) {
320
+ const configured = Object.keys(source.auth).length ||
321
+ source.credentials.length ||
322
+ Object.values(source.models.providers ?? {}).some((provider) => object(provider) && provider.apiKey) ||
323
+ Object.values(knownProviderEnvironment).some((key) => usableNativeApiKey(source.env[key]));
324
+ if (!configured)
325
+ continue;
326
+ // OMP also autoloads its own config-root .env. Expose only a flag, never
327
+ // inject those broker fields into a private/native account menu.
328
+ const parentEnv = cli === 'omp' ? await readOptional(join(dirname(source.sourceId), '.env'), 64 * 1024) : undefined;
329
+ const brokerConfigured = source.brokerConfigured ||
330
+ !!parentEnv
331
+ ?.toString('utf8')
332
+ .split(/\r?\n/)
333
+ .some((line) => {
334
+ const match = /^(?:export\s+)?OMP_AUTH_BROKER_(?:URL|TOKEN)\s*=\s*(.*)$/.exec(line.trim());
335
+ return (match &&
336
+ match[1]
337
+ .trim()
338
+ .replace(/^(["'])(.*)\1$/, '$2')
339
+ .trim());
340
+ });
341
+ result.push({
342
+ id: (index === 0 ? 'native' : 'plugin'),
343
+ label: index === 0 ? 'CLI 全局账号' : '插件账号',
344
+ directory: source.sourceId,
345
+ env: source.env,
346
+ config: source.config ?? {},
347
+ stored: Object.keys(source.auth).length > 0 || source.credentials.length > 0,
348
+ brokerConfigured,
349
+ });
350
+ }
351
+ return result;
352
+ });
353
+ }
354
+ export async function listPiOmpAccountSources(cli, stateDirectory, signal, options = {}) {
355
+ return (await readPiOmpLogoutSources(cli, stateDirectory, signal, options)).map(({ id, label }) => ({
356
+ id,
357
+ label,
358
+ }));
359
+ }
360
+ function mergeSources(sources) {
361
+ const auth = Object.assign(Object.create(null), ...sources.map((s) => s.auth));
362
+ const providers = Object.assign(Object.create(null), ...sources.map((s) => s.models.providers ?? {}));
363
+ const env = Object.assign(Object.create(null), ...sources.map((s) => s.env));
364
+ const credentialProviders = new Map();
365
+ const cache = new Map();
366
+ for (const s of sources) {
367
+ for (const provider of new Set(s.credentials.map((row) => row.provider)))
368
+ credentialProviders.set(provider, s.credentials.filter((row) => row.provider === provider));
369
+ for (const row of s.modelCache)
370
+ cache.set(row.provider_id, row);
371
+ }
372
+ const kinds = new Set();
373
+ let expired = false;
374
+ for (const entry of Object.values(auth)) {
375
+ const state = credentialState(entry.type, entry);
376
+ if (state === 'configured')
377
+ kinds.add(entry.type);
378
+ if (state === 'expired')
379
+ expired = true;
380
+ }
381
+ for (const row of [...credentialProviders.values()].flat()) {
382
+ const state = credentialState(row.credential_type, JSON.parse(row.data), row.disabled_cause);
383
+ if (state === 'configured')
384
+ kinds.add(row.credential_type);
385
+ if (state === 'expired')
386
+ expired = true;
387
+ }
388
+ for (const provider of Object.values(providers)) {
389
+ if (typeof provider.apiKey === 'string' &&
390
+ provider.apiKey &&
391
+ (!/^[A-Z][A-Z0-9_]*$/.test(provider.apiKey) || env[provider.apiKey]))
392
+ kinds.add('api');
393
+ }
394
+ if (Object.values(knownProviderEnvironment).some((key) => env[key]))
395
+ kinds.add('api');
396
+ return { auth, providers, env, credentialProviders, cache, kinds, expired };
397
+ }
398
+ /** Internal binding material only. Never expose these values through public status. */
399
+ export async function readPiOmpAccountMaterial(cli, options = {}) {
400
+ return withSources(cli, options, async (sources) => {
401
+ const merged = mergeSources(sources);
402
+ return {
403
+ auth: merged.auth,
404
+ credentials: [...merged.credentialProviders.values()].flat(),
405
+ env: merged.env,
406
+ models: { providers: merged.providers },
407
+ configAuth: Object.assign({}, ...sources.map((s) => s.config ?? {})),
408
+ sourceIds: sources
409
+ .filter((s) => Object.keys(s.auth).length ||
410
+ s.credentials.length ||
411
+ Object.keys(s.env).length ||
412
+ Object.keys(s.config?.auth ?? {}).length ||
413
+ Object.values(s.models.providers ?? {}).some((p) => object(p) && p.apiKey))
414
+ .map((s) => s.sourceId),
415
+ };
416
+ });
417
+ }
418
+ async function sharedOAuthStore(cli, sources, options) {
419
+ if (!options.sharedOAuth)
420
+ return undefined;
421
+ const merged = mergeSources(sources);
422
+ const owners = new Map();
423
+ for (const source of sources)
424
+ for (const provider of cli === 'pi'
425
+ ? Object.keys(source.auth)
426
+ : new Set(source.credentials.map((row) => row.provider)))
427
+ owners.set(provider, source);
428
+ const credentials = cli === 'pi'
429
+ ? Object.entries(merged.auth).map(([provider, data]) => ({
430
+ provider,
431
+ data,
432
+ row: undefined,
433
+ cacheRowId: undefined,
434
+ }))
435
+ : [...merged.credentialProviders.values()].flat().map((row, index) => ({
436
+ provider: row.provider,
437
+ data: { ...JSON.parse(row.data), type: row.credential_type },
438
+ row,
439
+ cacheRowId: index + 1,
440
+ }));
441
+ const entries = [];
442
+ const fixed = [];
443
+ for (const { provider, data, row, cacheRowId } of credentials) {
444
+ if (data.type !== 'oauth' || row?.disabled_cause) {
445
+ fixed.push({
446
+ provider,
447
+ ...(row ? { cacheRowId } : {}),
448
+ hash: refreshFingerprint(row ? { ...data, disabled_cause: row.disabled_cause } : data),
449
+ });
450
+ continue;
451
+ }
452
+ const principal = refreshPrincipal(data);
453
+ if (!principal)
454
+ throw new Error('无法确认 OAuth 续期账号,请使用该 CLI 自身 API 配置');
455
+ const owner = owners.get(provider);
456
+ const path = join(await realpath(owner.sourceId), cli === 'pi' ? 'auth.json' : 'agent.db');
457
+ const info = await lstat(path);
458
+ if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1)
459
+ throw new Error('Unsafe OAuth source');
460
+ entries.push({
461
+ provider,
462
+ path,
463
+ hash: refreshFingerprint(data),
464
+ principal,
465
+ dev: info.dev,
466
+ ino: info.ino,
467
+ ...(row ? { rowId: row.native_rowid, cacheRowId } : {}),
468
+ });
469
+ }
470
+ if (!entries.length)
471
+ return undefined;
472
+ // One physical store and lease per CLI/source set, independent of worker/project.
473
+ const parent = join(options.accountRoot ?? defaultRoot(), 'account-runtime', cli, 'oauth');
474
+ await safePiOmpAncestors(parent);
475
+ await mkdir(parent, { recursive: true, mode: 0o700 });
476
+ // Provider order/additions must never create another lock for the same source.
477
+ const sourceKey = refreshFingerprint({
478
+ cli,
479
+ home: await realpath(options.nativeHome ?? homedir()),
480
+ accountRoot: await realpath(options.accountRoot ?? defaultRoot()),
481
+ });
482
+ const root = join(await realpath(parent), sourceKey);
483
+ await mkdir(root, { recursive: true, mode: 0o700 });
484
+ const info = await lstat(root);
485
+ if (!info.isDirectory() || info.isSymbolicLink() || (process.platform !== 'win32' && info.mode & 0o077))
486
+ throw new Error('Unsafe OAuth runtime');
487
+ const agent = join(root, 'agent');
488
+ const receipt = {
489
+ version: 1,
490
+ cli,
491
+ revision: refreshFingerprint({
492
+ entries,
493
+ auth: merged.auth,
494
+ credentials: [...merged.credentialProviders.values()],
495
+ env: merged.env,
496
+ providers: merged.providers,
497
+ config: sources.map((source) => source.config),
498
+ }),
499
+ entries,
500
+ fixed,
501
+ };
502
+ const nonce = randomUUID();
503
+ await acquireOwnAccountLease(root, nonce);
504
+ try {
505
+ options.signal?.throwIfAborted();
506
+ await mkdir(agent, { recursive: true, mode: 0o700 });
507
+ const agentInfo = await lstat(agent);
508
+ if (!agentInfo.isDirectory() ||
509
+ agentInfo.isSymbolicLink() ||
510
+ (process.platform !== 'win32' && agentInfo.mode & 0o077))
511
+ throw new Error('Unsafe OAuth runtime');
512
+ let previous;
513
+ try {
514
+ previous = await refreshJson(join(root, 'receipt.json'));
515
+ }
516
+ catch (error) {
517
+ if (error.code !== 'ENOENT')
518
+ throw error;
519
+ }
520
+ if (previous && refreshFingerprint(previous) === refreshFingerprint(receipt)) {
521
+ await assertPiOmpRefreshSources(root, receipt);
522
+ await assertPiOmpRefreshCache(root, receipt);
523
+ return { root, agent, receipt, nonce, reuse: true };
524
+ }
525
+ // A failed rebuild must not leave an old valid receipt over partially new data.
526
+ await rm(join(root, 'receipt.json'), { force: true });
527
+ return { root, agent, receipt, nonce, reuse: false };
528
+ }
529
+ catch (error) {
530
+ await releaseOwnAccountLease(root, nonce);
531
+ throw error;
532
+ }
533
+ }
534
+ /** Global native input then plugin account overrides by provider; empty plugin auth never hides global accounts. */
535
+ export async function snapshotPiOmpNative(cli, destination, options = {}) {
536
+ try {
537
+ return await withSources(cli, options, async (sources) => {
538
+ let unsupportedOAuth = false;
539
+ if (options.sharedOAuth) {
540
+ // Resolve the native override first. An unsupported current OAuth account
541
+ // must still shadow lower-priority credentials for the same provider.
542
+ const authOwners = new Map();
543
+ const credentialOwners = new Map();
544
+ for (const source of sources) {
545
+ for (const provider of Object.keys(source.auth))
546
+ authOwners.set(provider, source);
547
+ for (const row of source.credentials)
548
+ credentialOwners.set(row.provider, source);
549
+ }
550
+ sources = sources.map((source) => ({
551
+ ...source,
552
+ auth: Object.fromEntries(Object.entries(source.auth).filter(([provider, value]) => {
553
+ if (authOwners.get(provider) !== source)
554
+ return false;
555
+ const allowed = value.type !== 'oauth' || !!refreshPrincipal(value);
556
+ if (!allowed)
557
+ unsupportedOAuth = true;
558
+ return allowed;
559
+ })),
560
+ credentials: source.credentials.filter((row) => {
561
+ if (credentialOwners.get(row.provider) !== source)
562
+ return false;
563
+ const allowed = row.credential_type !== 'oauth' ||
564
+ !!row.disabled_cause ||
565
+ !!refreshPrincipal({ ...JSON.parse(row.data), type: 'oauth' });
566
+ if (!allowed)
567
+ unsupportedOAuth = true;
568
+ return allowed;
569
+ }),
570
+ }));
571
+ }
572
+ const { auth, providers, kinds, env, credentialProviders, cache, expired } = mergeSources(sources);
573
+ if (unsupportedOAuth && !kinds.size)
574
+ throw new Error('无法确认 OAuth 续期账号,请使用该 CLI 自身 API 配置');
575
+ const shared = await sharedOAuthStore(cli, sources, options);
576
+ const target = shared?.agent ?? destination;
577
+ try {
578
+ if (shared?.reuse)
579
+ return {
580
+ configured: kinds.size > 0,
581
+ expired,
582
+ providers: Object.keys(providers),
583
+ env,
584
+ directory: target,
585
+ leaseDirectory: shared.root,
586
+ receipt: shared.receipt,
587
+ };
588
+ const files = cli === 'pi'
589
+ ? {
590
+ 'auth.json': auth,
591
+ 'models.json': { providers },
592
+ 'settings.json': Object.assign(Object.create(null), ...sources.map((source) => source.config ?? {})),
593
+ 'native-env.json': env,
594
+ 'models-store.json': Object.assign(Object.create(null), ...sources.map((s) => s.modelsStore)),
595
+ }
596
+ : { 'models.yml': { providers }, 'native-env.json': env };
597
+ for (const [name, value] of Object.entries(files)) {
598
+ options.signal?.throwIfAborted();
599
+ const temporary = join(target, `.native-${randomUUID()}.tmp`);
600
+ await writeFile(temporary, JSON.stringify(value), { flag: 'wx', mode: 0o600 });
601
+ await rename(temporary, join(target, name));
602
+ }
603
+ if (cli === 'omp') {
604
+ const nativeAuth = Object.assign({}, ...sources.map((s) => s.config ?? {}));
605
+ const authConfig = join(target, 'native-auth.json');
606
+ const authTemp = `${authConfig}.${randomUUID()}.tmp`;
607
+ await writeFile(authTemp, JSON.stringify(nativeAuth), { flag: 'wx', mode: 0o600 });
608
+ await rename(authTemp, authConfig);
609
+ // Fresh DBs hold only native credential/catalog rows. No history, memory,
610
+ // user settings, jobs, leases or session paths are copied into a worker.
611
+ for (const [name, schema, rows, insert] of [
612
+ [
613
+ 'agent.db',
614
+ 'CREATE TABLE auth_credentials (id INTEGER PRIMARY KEY AUTOINCREMENT, provider TEXT NOT NULL, credential_type TEXT NOT NULL, data TEXT NOT NULL, disabled_cause TEXT, identity_key TEXT, created_at INTEGER NOT NULL DEFAULT 0, updated_at INTEGER NOT NULL DEFAULT 0)',
615
+ [...credentialProviders.values()].flat(),
616
+ 'INSERT INTO auth_credentials(provider,credential_type,data,disabled_cause) VALUES(?,?,?,?)',
617
+ ],
618
+ [
619
+ 'models.db',
620
+ "CREATE TABLE model_cache(provider_id TEXT PRIMARY KEY,version INTEGER NOT NULL,updated_at INTEGER NOT NULL,authoritative INTEGER NOT NULL DEFAULT 0,static_fingerprint TEXT NOT NULL DEFAULT '',models TEXT NOT NULL)",
621
+ [...cache.values()],
622
+ 'INSERT INTO model_cache VALUES(?,?,?,?,?,?)',
623
+ ],
624
+ ]) {
625
+ const temporary = join(target, `.native-${randomUUID()}.db`);
626
+ await writeFile(temporary, '', { flag: 'wx', mode: 0o600 });
627
+ const db = new DatabaseSync(temporary);
628
+ try {
629
+ db.exec(schema);
630
+ for (const row of rows)
631
+ db.prepare(insert).run(...(name === 'agent.db'
632
+ ? [row.provider, row.credential_type, row.data, row.disabled_cause]
633
+ : [
634
+ row.provider_id,
635
+ row.version,
636
+ row.updated_at,
637
+ row.authoritative,
638
+ row.static_fingerprint,
639
+ row.models,
640
+ ]));
641
+ }
642
+ finally {
643
+ db.close();
644
+ }
645
+ await rename(temporary, join(target, name));
646
+ // Old auxiliary files must not apply a previous DB's WAL to the replacement.
647
+ await Promise.all(['-wal', '-shm'].map((suffix) => rm(join(target, name + suffix), { force: true })));
648
+ }
649
+ }
650
+ if (shared) {
651
+ options.signal?.throwIfAborted();
652
+ await assertPiOmpRefreshSources(shared.root, shared.receipt);
653
+ await writeRefreshJson(join(shared.root, 'receipt.json'), shared.receipt);
654
+ }
655
+ return {
656
+ configured: kinds.size > 0,
657
+ expired,
658
+ providers: Object.keys(providers),
659
+ env,
660
+ directory: target,
661
+ ...(shared ? { leaseDirectory: shared.root, receipt: shared.receipt } : {}),
662
+ };
663
+ }
664
+ finally {
665
+ if (shared)
666
+ await releaseOwnAccountLease(shared.root, shared.nonce);
667
+ }
668
+ });
669
+ }
670
+ catch (error) {
671
+ options.signal?.throwIfAborted();
672
+ if (error instanceof Error &&
673
+ [
674
+ OWN_ACCOUNT_BUSY,
675
+ '无法确认 OAuth 续期账号,请使用该 CLI 自身 API 配置',
676
+ '账号配置已变化,请重新刷新模型',
677
+ ].includes(error.message))
678
+ throw error;
679
+ throw new Error('无法安全读取 Pi/OMP 原生账号或模型配置,请在账号终端检查');
680
+ }
681
+ }
682
+ export async function inspectPiOmpNativeAccount(cli, stateDirectory, signal, options = {}) {
683
+ signal.throwIfAborted();
684
+ try {
685
+ return await withSources(cli, { accountRoot: stateDirectory, ...options }, async (sources) => {
686
+ signal.throwIfAborted();
687
+ const { auth, providers, env, credentialProviders, expired } = mergeSources(sources);
688
+ const logins = [];
689
+ const ownValue = (value, referenceOnly = false) => typeof value === 'string' &&
690
+ (referenceOnly
691
+ ? /^[A-Z][A-Z0-9_]*$/.test(value)
692
+ : Object.values(knownProviderEnvironment).includes(value))
693
+ ? env[value]
694
+ : value;
695
+ const add = (provider, method) => {
696
+ const config = providers[provider];
697
+ logins.push(providerLogin(provider, method, {
698
+ baseUrl: ownValue(config?.baseUrl, true),
699
+ name: config?.name,
700
+ }));
701
+ };
702
+ let invalidOAuth = false;
703
+ const inspect = (provider, type, value, disabled) => {
704
+ if (credentialState(type, value, disabled) !== 'configured')
705
+ return;
706
+ if (type === 'api' || type === 'api_key') {
707
+ if (usableNativeApiKey(ownValue(value.key ?? value.apiKey)))
708
+ add(provider, 'api');
709
+ }
710
+ else if (usableNativeApiKey(value.access) &&
711
+ (value.expires >= Date.now() || usableNativeApiKey(value.refresh)))
712
+ add(provider, 'oauth');
713
+ else
714
+ invalidOAuth = true;
715
+ };
716
+ for (const [provider, value] of Object.entries(auth))
717
+ inspect(provider, value.type, value);
718
+ for (const [provider, rows] of credentialProviders)
719
+ for (const row of rows)
720
+ inspect(provider, row.credential_type, JSON.parse(row.data), row.disabled_cause);
721
+ for (const [provider, value] of Object.entries(providers)) {
722
+ if (usableNativeApiKey(ownValue(value.apiKey, true)))
723
+ add(provider, 'api');
724
+ }
725
+ for (const [provider, variable] of Object.entries(knownProviderEnvironment))
726
+ if (usableNativeApiKey(env[variable]))
727
+ add(provider, 'api');
728
+ if (logins.length)
729
+ return authenticatedAccountLogins(logins);
730
+ if (expired || invalidOAuth)
731
+ return { state: 'unauthenticated', verification: 'local', summary: '原生登录已失效,请重新登录' };
732
+ if (Object.keys(auth).length || credentialProviders.size || Object.keys(providers).length)
733
+ return { state: 'configured', verification: 'local', summary: '尚未配置有效凭据' };
734
+ return { state: 'unconfigured', verification: 'local', summary: '尚未配置原生账号' };
735
+ });
736
+ }
737
+ catch {
738
+ signal.throwIfAborted();
739
+ return { state: 'unavailable', summary: '账号或模型配置读取失败,请检查配置' };
740
+ }
741
+ }
742
+ export async function restorePiOmpEnvironment(directory) {
743
+ try {
744
+ const value = parseObject(await readOptional(join(directory, 'native-env.json'), 64 * 1024));
745
+ if (Object.entries(value).some(([key, item]) => !/^[A-Z][A-Z0-9_]*$/.test(key) || runtimeEnv.test(key) || typeof item !== 'string'))
746
+ throw new Error('Invalid native environment snapshot');
747
+ return value;
748
+ }
749
+ catch {
750
+ throw new Error('无法安全读取已有 Worker 的原生凭据环境');
751
+ }
752
+ }
753
+ //# sourceMappingURL=pi-omp-native.js.map