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,234 @@
1
+ // Inspect fixed launcher data; never ask a shell to interpret CLI arguments.
2
+ import { openSync, readSync, fstatSync, closeSync, realpathSync, statSync, existsSync } from 'node:fs'
3
+ import { basename, dirname, extname, isAbsolute, relative, resolve, sep, delimiter, join } from 'node:path'
4
+ import { homedir, userInfo } from 'node:os'
5
+
6
+ const invalid = () => Object.assign(
7
+ new Error('CLI 启动入口无法确认,请配置原生程序或固定 Node/Bun 入口'),
8
+ { code: 'CLI_LAUNCHER_UNSUPPORTED' },
9
+ )
10
+ const batch = (value) => /\.(?:cmd|bat)$/i.test(value)
11
+ function text(path, limit = 128 * 1024) {
12
+ const descriptor = openSync(path, 'r')
13
+ try {
14
+ const info = fstatSync(descriptor)
15
+ if (!info.isFile() || info.size > limit) throw invalid()
16
+ const bytes = Buffer.alloc(info.size + 1)
17
+ const read = readSync(descriptor, bytes, 0, bytes.length, 0)
18
+ const after = fstatSync(descriptor)
19
+ if (read !== info.size || info.size !== after.size || info.mtimeMs !== after.mtimeMs) throw invalid()
20
+ return bytes
21
+ .subarray(0, read)
22
+ .toString('utf8')
23
+ .replace(/^\uFEFF/, '')
24
+ } finally {
25
+ closeSync(descriptor)
26
+ }
27
+ }
28
+ function file(path) {
29
+ const canonical = realpathSync(path)
30
+ if (!statSync(canonical).isFile()) throw invalid()
31
+ return canonical
32
+ }
33
+ function scriptRuntime(path) {
34
+ const descriptor = openSync(path, 'r')
35
+ try {
36
+ const bytes = Buffer.alloc(256)
37
+ const length = readSync(descriptor, bytes, 0, bytes.length, 0)
38
+ const header = bytes.subarray(0, length).toString('utf8').split('\n')[0].trim()
39
+ if (header.startsWith('#!')) {
40
+ const match = /^#!\s*(?:\/usr\/bin\/env\s+(?:-S\s+)?)?(?:[^\s]*\/)?(node|bun)\s*$/.exec(header)
41
+ if (!match) throw invalid()
42
+ return match[1]
43
+ }
44
+ // A fixed npm bin entry can declare its runtime in the package manifest.
45
+ for (let directory = dirname(path), depth = 0; depth < 5; depth++, directory = dirname(directory)) {
46
+ const manifestPath = join(directory, 'package.json')
47
+ if (!existsSync(manifestPath)) continue
48
+ const manifest = JSON.parse(text(manifestPath))
49
+ const bins = typeof manifest.bin === 'string' ? [manifest.bin] : Object.values(manifest.bin ?? {})
50
+ if (bins.some((entry) => typeof entry === 'string' && resolve(directory, entry) === path)) {
51
+ if (manifest.engines?.bun && !manifest.engines?.node) return 'bun'
52
+ return 'node'
53
+ }
54
+ break
55
+ }
56
+ return /\.[cm]?js$/i.test(path) ? 'node' : undefined
57
+ } finally {
58
+ closeSync(descriptor)
59
+ }
60
+ }
61
+ function runtimeProgram(runtime, platform, launcherDirectory) {
62
+ if (runtime === 'node') return process.execPath
63
+ if (runtime !== 'bun') throw invalid()
64
+ const name = platform === 'win32' ? 'bun.exe' : 'bun'
65
+ const candidates = [
66
+ ...(launcherDirectory ? [join(launcherDirectory, name)] : []),
67
+ ...(process.env.PATH ?? '')
68
+ .split(delimiter)
69
+ .map((directory) => directory.replace(/^"|"$/g, ''))
70
+ .filter(isAbsolute)
71
+ .map((directory) => join(directory, name)),
72
+ ...(process.env.BUN_INSTALL ? [join(process.env.BUN_INSTALL, 'bin', name)] : []),
73
+ ...[homedir(), userInfo().homedir].map((home) => join(home, '.bun', 'bin', name)),
74
+ ]
75
+ const candidate = candidates.find((path) => existsSync(path) && statSync(path).isFile())
76
+ if (!candidate) throw new Error('未找到 Bun,请安装该 CLI 所需的 Bun 运行时')
77
+ return file(candidate)
78
+ }
79
+ /** npm's native bin shim is data, not a batch program to execute. */
80
+ function nativePackageBin(shim, suffix) {
81
+ const parts = suffix.replace(/\\/g, '/').split('/')
82
+ if (parts[0] !== 'node_modules' || parts.some((part) => !part || part === '.' || part === '..'))
83
+ throw invalid()
84
+ const scoped = parts[1]?.startsWith('@')
85
+ const name = parts.slice(1, scoped ? 3 : 2).join('/')
86
+ if (!/^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/.test(name)) throw invalid()
87
+ const root = fileDirectory(resolve(dirname(shim), ...parts.slice(0, scoped ? 3 : 2)))
88
+ const entry = file(resolve(dirname(shim), ...parts))
89
+ const inside = relative(root, entry)
90
+ if (!inside || inside === '..' || inside.startsWith('..' + sep) || isAbsolute(inside)) throw invalid()
91
+ const manifest = JSON.parse(text(join(root, 'package.json')))
92
+ const command = basename(shim, extname(shim))
93
+ const declared = typeof manifest.bin === 'string'
94
+ ? name.split('/').at(-1) === command ? manifest.bin : undefined
95
+ : manifest.bin?.[command]
96
+ if (manifest.name !== name || typeof declared !== 'string' || isAbsolute(declared) ||
97
+ declared.replace(/\\/g, '/').split('/').includes('..') || file(resolve(root, declared)) !== entry)
98
+ throw invalid()
99
+ const descriptor = openSync(entry, 'r')
100
+ try {
101
+ const header = Buffer.alloc(64), signature = Buffer.alloc(4)
102
+ const size = fstatSync(descriptor).size
103
+ if (readSync(descriptor, header, 0, 64, 0) !== 64 || header.toString('ascii', 0, 2) !== 'MZ')
104
+ throw invalid()
105
+ const offset = header.readUInt32LE(0x3c)
106
+ if (offset < 64 || offset + 4 > size || readSync(descriptor, signature, 0, 4, offset) !== 4 ||
107
+ signature.toString('hex') !== '50450000') throw invalid()
108
+ } finally {
109
+ closeSync(descriptor)
110
+ }
111
+ return entry
112
+ }
113
+ function fileDirectory(path) {
114
+ const canonical = realpathSync(path)
115
+ if (!statSync(canonical).isDirectory()) throw invalid()
116
+ return canonical
117
+ }
118
+ function inspectBatch(executable, platform) {
119
+ const source = text(file(executable)).trim().replace(/\r\n/g, '\n')
120
+ // Nous' official fallback contains just a fixed interpreter and its encoded
121
+ // launcher. Preserve its own bootstrap; do not guess a virtualenv interpreter.
122
+ const hermes =
123
+ /^@echo off\n"([^"\n%]+)" -I -c "(import base64; exec\(base64\.b64decode\('([A-Za-z0-9+/]+={0,2})'\)\))" %\*$/i.exec(
124
+ source,
125
+ )
126
+ if (hermes) {
127
+ const decoded = Buffer.from(hermes[3], 'base64')
128
+ if (
129
+ !isAbsolute(hermes[1]) ||
130
+ decoded.toString('base64') !== hermes[3] ||
131
+ !decoded.toString('utf8').startsWith('import os, re, sys\n') ||
132
+ !decoded.toString('utf8').includes('import hermes_bootstrap') ||
133
+ !decoded.toString('utf8').includes('from hermes_cli.main import main')
134
+ )
135
+ throw invalid()
136
+ return { kind: 'python', argv: [file(hermes[1]), '-I', '-c', hermes[2]] }
137
+ }
138
+ const entries = new Set()
139
+ const runtimes = new Set()
140
+ for (const original of source.split('\n')) {
141
+ let line = original.trim()
142
+ if (!line || /^@?(?:echo off|rem\b.*)$/i.test(line)) continue
143
+ // npm cmd-shim's standard final control prefix is launcher boilerplate;
144
+ // it is discarded, and nothing from it is executed by this module.
145
+ line = line.replace(/^endLocal & goto #_undefined_# 2>NUL \|\| title [^&\n]+ & /i, '')
146
+ const native = /^@?"%(?:~dp0[\\/]?|dp0%[\\/])([^"\n%]+\.exe)"\s+%\*$/i.exec(line)
147
+ if (native) {
148
+ entries.add(nativePackageBin(executable, native[1]))
149
+ runtimes.add('native')
150
+ continue
151
+ }
152
+ const command =
153
+ /^@?(?:(node|bun)|"%_prog%"|"%(?:~dp0[\\/]?|dp0%[\\/])(node|bun)\.exe")\s+"%(?:~dp0[\\/]?|dp0%[\\/])([^"\n%]+)"\s+%\*$/i.exec(
154
+ line,
155
+ )
156
+ if (command) {
157
+ const path = file(resolve(dirname(executable), command[3].replace(/[\\/]/g, sep)))
158
+ if (!scriptRuntime(path)) throw invalid()
159
+ entries.add(path)
160
+ if (command[1] || command[2]) runtimes.add((command[1] || command[2]).toLowerCase())
161
+ continue
162
+ }
163
+ const program = /^@?set "?_prog=(?:%(?:~dp0[\\/]?|dp0%[\\/]))?(node|bun)(?:\.exe)?"?$/i.exec(line)
164
+ if (program) {
165
+ runtimes.add(program[1].toLowerCase())
166
+ continue
167
+ }
168
+ if (
169
+ /^@?(?:goto start|:find_dp0|:start|set dp0=%~dp0|exit \/b|setlocal|endlocal|call :find_dp0)$/i.test(
170
+ line,
171
+ ) ||
172
+ /^@?if (?:not )?exist "%(?:~dp0[\\/]?|dp0%[\\/])(?:node|bun)\.exe" \($/i.test(line) ||
173
+ /^\)(?: else \()?$/i.test(line) ||
174
+ /^@?set pathext=%pathext:;\.js;=;%$/i.test(line) ||
175
+ /^@?if (?:not )?defined node_path \($/i.test(line) ||
176
+ /^@?set "node_path=[^"\n&|<>]+"$/i.test(line)
177
+ )
178
+ continue
179
+ throw invalid()
180
+ }
181
+ if (entries.size !== 1 || runtimes.size !== 1) throw invalid()
182
+ const entry = [...entries][0],
183
+ runtime = [...runtimes][0]
184
+ if (runtime === 'native') return { kind: 'native', argv: [entry] }
185
+ if (scriptRuntime(entry) !== runtime) throw invalid()
186
+ return { kind: runtime, argv: [runtimeProgram(runtime, platform, dirname(executable)), entry] }
187
+ }
188
+
189
+ /** Canonical npm entry for installation identity checks; Python launchers keep their identity. */
190
+ export function resolveNativeEntry(executable, platform = process.platform) {
191
+ if (platform !== 'win32') return executable
192
+ if (isAbsolute(executable) && !extname(executable) && !existsSync(executable)) {
193
+ const extensions = (process.env.PATHEXT || '.EXE;.COM;.CMD;.BAT')
194
+ .split(';')
195
+ .map((extension) => extension.toLowerCase())
196
+ .filter((extension) => /^\.(?:exe|com|cmd|bat)$/.test(extension))
197
+ const candidate = [...new Set(extensions)]
198
+ .map((extension) => executable + extension)
199
+ .find((path) => existsSync(path) && statSync(path).isFile())
200
+ if (candidate) executable = candidate
201
+ }
202
+ if (!batch(executable)) return executable
203
+ let inspected
204
+ try {
205
+ inspected = inspectBatch(executable, platform)
206
+ } catch {
207
+ // A present but invalid shim is not an absent CLI. Never forward raw paths or script text.
208
+ throw invalid()
209
+ }
210
+ // Keep Bun's fixed shim identity: it may pin a bundled bun.exe beside the
211
+ // shim which cannot be recovered from only the package's JS path.
212
+ return inspected.kind === 'node' ? inspected.argv[1] : inspected.kind === 'native' ? inspected.argv[0] : executable
213
+ }
214
+
215
+ /** Windows CreateProcess accepts real programs, not npm command files. */
216
+ export function nativeLaunchArgv(argv, platform = process.platform) {
217
+ if (
218
+ !Array.isArray(argv) ||
219
+ !argv.length ||
220
+ argv.some((value) => typeof value !== 'string' || value.includes('\0'))
221
+ )
222
+ throw invalid()
223
+ if (platform !== 'win32') {
224
+ if (!/\.[cm]?js$/i.test(argv[0])) return [...argv]
225
+ const entry = file(argv[0])
226
+ return [runtimeProgram(scriptRuntime(entry), platform), entry, ...argv.slice(1)]
227
+ }
228
+ const executable = resolveNativeEntry(argv[0], platform),
229
+ arguments_ = argv.slice(1)
230
+ if (batch(executable)) return [...inspectBatch(executable, platform).argv, ...arguments_]
231
+ if (/\.[cm]?js$/i.test(executable) || (extname(executable) === '' && scriptRuntime(executable)))
232
+ return [runtimeProgram(scriptRuntime(executable), platform), file(executable), ...arguments_]
233
+ return [executable, ...arguments_]
234
+ }
@@ -0,0 +1,32 @@
1
+ import { spawn } from 'node:child_process'
2
+
3
+ /** Native CLI descendants keep their pipes/ConPTY and the enclosing Host Job.
4
+ * Window presentation is per child: hiding a wrapper does not hide its children.
5
+ * Node ignores windowsHide on POSIX, so both platforms use this one boundary.
6
+ */
7
+ export function spawnNativeProcess(executable, argv, options) {
8
+ return spawn(executable, argv, { ...options, windowsHide: true })
9
+ }
10
+
11
+ /** Relay ordinary background pipes as bytes with Node's stream backpressure.
12
+ * Numeric/inherited descriptors make libuv omit CREATE_NO_WINDOW on Windows.
13
+ * This must never be used for a ConPTY: its console handles stay inherited. */
14
+ export function forwardNativeStdio(child) {
15
+ const stopInput = () => {
16
+ process.stdin.unpipe(child.stdin)
17
+ process.stdin.destroy()
18
+ }
19
+ const fail = () => { child.kill('SIGTERM'); process.exitCode = 1 }
20
+ child.stdin.on('error', error => { stopInput(); if (error.code !== 'EPIPE') fail() })
21
+ child.stdin.once('close', stopInput)
22
+ child.once('exit', stopInput)
23
+ child.once('error', stopInput)
24
+ process.stdin.on('error', fail)
25
+ process.stdout.on('error', fail)
26
+ process.stderr.on('error', fail)
27
+ child.stdout.on('error', fail)
28
+ child.stderr.on('error', fail)
29
+ process.stdin.pipe(child.stdin)
30
+ child.stdout.pipe(process.stdout, { end: false })
31
+ child.stderr.pipe(process.stderr, { end: false })
32
+ }
@@ -0,0 +1,105 @@
1
+ import { constants } from 'node:fs'
2
+ import { lstat, mkdir, open, realpath, rename, rm, writeFile } from 'node:fs/promises'
3
+ import { join, resolve } from 'node:path'
4
+
5
+ export const OWN_ACCOUNT_BUSY = '账号正被使用,请稍后刷新'
6
+ const nonceValid = (value) => typeof value === 'string' && /^[a-f0-9-]{36}$/.test(value)
7
+ async function privateRoot(root) {
8
+ const info = await lstat(root)
9
+ if (
10
+ !info.isDirectory() ||
11
+ info.isSymbolicLink() ||
12
+ (process.platform !== 'win32' && (info.mode & 0o077)) ||
13
+ (await realpath(root)) !== resolve(root)
14
+ )
15
+ throw new Error('账号运行目录无法安全使用')
16
+ }
17
+ /** A lease is not stolen after PID death: its descendants may still be alive.
18
+ * Only Host cleanup after confirmed process-range exit may release it. */
19
+ export async function assertOwnAccountLeaseIdle(root) {
20
+ await privateRoot(root)
21
+ try {
22
+ await lstat(join(root, '.lease'))
23
+ } catch (error) {
24
+ if (error?.code === 'ENOENT') return
25
+ throw error
26
+ }
27
+ throw new Error(OWN_ACCOUNT_BUSY)
28
+ }
29
+ export async function acquireOwnAccountLease(root, nonce) {
30
+ if (!nonceValid(nonce)) throw new Error('Invalid account lease')
31
+ await privateRoot(root)
32
+ const lock = join(root, '.lease')
33
+ const pending = join(root, `.lease-${nonce}.pending`)
34
+ await assertOwnAccountLeaseIdle(root)
35
+ await mkdir(pending, { mode: 0o700 })
36
+ try {
37
+ await writeFile(join(pending, 'owner.json'), JSON.stringify({ nonce, pid: process.pid }), {
38
+ flag: 'wx',
39
+ mode: 0o600,
40
+ })
41
+ // Publish a complete, nonempty owner directory in one filesystem operation.
42
+ // A killed initializer leaves only its nonce-specific pending directory.
43
+ await rename(pending, lock)
44
+ } catch (error) {
45
+ await rm(pending, { recursive: true, force: true })
46
+ if (error?.code === 'EEXIST' || error?.code === 'ENOTEMPTY') throw new Error(OWN_ACCOUNT_BUSY)
47
+ throw error
48
+ }
49
+ }
50
+ export async function ownsOwnAccountLease(root, nonce) {
51
+ if (!nonceValid(nonce)) throw new Error('Invalid account lease')
52
+ await privateRoot(root)
53
+ let handle
54
+ try {
55
+ const lock = await lstat(join(root, '.lease'))
56
+ if (!lock.isDirectory() || lock.isSymbolicLink() || (process.platform !== 'win32' && (lock.mode & 0o077)))
57
+ throw new Error('账号使用状态无法确认')
58
+ handle = await open(
59
+ join(root, '.lease/owner.json'),
60
+ constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,
61
+ )
62
+ const info = await handle.stat()
63
+ if (!info.isFile() || info.nlink !== 1 || (process.platform !== 'win32' && (info.mode & 0o077)) || info.size > 1024)
64
+ throw new Error('账号使用状态无法确认')
65
+ return JSON.parse(await handle.readFile('utf8')).nonce === nonce
66
+ } catch (error) {
67
+ if (error?.code === 'ENOENT') return false
68
+ throw error
69
+ } finally {
70
+ await handle?.close()
71
+ }
72
+ }
73
+ export async function releaseOwnAccountLease(root, nonce) {
74
+ if (!nonceValid(nonce)) throw new Error('Invalid account lease')
75
+ await privateRoot(root)
76
+ // Safe only at this API's contract boundary: Host confirmed this nonce's whole
77
+ // process range exited, including an initializer killed before publication.
78
+ await rm(join(root, `.lease-${nonce}.pending`), { recursive: true, force: true })
79
+ const lock = join(root, '.lease')
80
+ let handle
81
+ try {
82
+ const directory = await lstat(lock)
83
+ if (!directory.isDirectory() || directory.isSymbolicLink() || (process.platform !== 'win32' && (directory.mode & 0o077)))
84
+ throw new Error('账号使用状态无法安全清理')
85
+ handle = await open(
86
+ join(lock, 'owner.json'),
87
+ constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,
88
+ )
89
+ const info = await handle.stat()
90
+ if (!info.isFile() || info.nlink !== 1 || (process.platform !== 'win32' && (info.mode & 0o077)) || info.size > 1024)
91
+ throw new Error('账号使用状态无法安全清理')
92
+ const owner = JSON.parse(await handle.readFile('utf8'))
93
+ if (owner.nonce !== nonce) return
94
+ const current = await lstat(lock)
95
+ if (current.dev !== directory.dev || current.ino !== directory.ino || current.isSymbolicLink())
96
+ throw new Error('账号使用状态在清理前改变')
97
+ await handle.close()
98
+ handle = undefined
99
+ await rm(lock, { recursive: true })
100
+ } catch (error) {
101
+ if (error?.code !== 'ENOENT') throw error
102
+ } finally {
103
+ await handle?.close()
104
+ }
105
+ }
@@ -0,0 +1,87 @@
1
+ // One verified Pi package for the Host, account UI, native catalog and RPC entry.
2
+ // Resolve installation metadata only; never execute an arbitrary shell launcher.
3
+ import { readFileSync, realpathSync, statSync } from 'node:fs'
4
+ import { createHash } from 'node:crypto'
5
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'
6
+ import { resolveNativeEntry } from './native-launch.mjs'
7
+
8
+ const versions = new Set(['1.0.2', '1.0.4', '1.1.0'])
9
+ const failure = () =>
10
+ Object.assign(
11
+ new Error('Pi 安装身份或原生接口不匹配;需要 Pi Coding Agent 1.0.2、1.0.4 或 1.1.0,不能使用 OMP 入口'),
12
+ { code: 'CLI_IDENTITY_MISMATCH' },
13
+ )
14
+ function metadata(path) {
15
+ const info = statSync(path)
16
+ if (!info.isFile() || info.size > 128 * 1024) throw failure()
17
+ return readFileSync(path, 'utf8')
18
+ }
19
+ // Exact official Windows managed launcher inspected from Pi 1.1.0. It is read as
20
+ // installation metadata, never evaluated. Unknown bootstrap code fails closed.
21
+ const managedWindowsLauncherSHA256 = '3d8b27bb3f5c07543303b0ee774ce215e4d6ae2b0ae43311c4acf51f517ffd13'
22
+ function windowsManagedEntry(launcher) {
23
+ const source = metadata(launcher).trim().replace(/\r\n/g, '\n')
24
+ if (createHash('sha256').update(source).digest('hex') !== managedWindowsLauncherSHA256) throw failure()
25
+ const install = join(dirname(dirname(launcher)), 'install')
26
+ const version = metadata(join(install, 'current-version')).trim()
27
+ if (!versions.has(version)) throw failure()
28
+ const directory = resolve(install, 'releases', version, 'node_modules/@earendil-works/pi-coding-agent')
29
+ // A version pointer/package symlink must not select code outside this release.
30
+ if (realpathSync(directory) !== directory) throw failure()
31
+ const manifest = JSON.parse(metadata(join(directory, 'package.json')))
32
+ const bin = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.pi
33
+ if (manifest.name !== '@earendil-works/pi-coding-agent' || manifest.version !== version ||
34
+ !['dist/cli.js', 'dist/bundle/cli.js'].includes(bin)) throw failure()
35
+ const entry = realpathSync(resolve(directory, bin))
36
+ const inside = relative(directory, entry)
37
+ if (!inside || inside === '..' || inside.startsWith('..' + sep) || isAbsolute(inside)) throw failure()
38
+ return entry
39
+ }
40
+
41
+ export function inspectPiInstallation(entry) {
42
+ try {
43
+ let executable = realpathSync(entry)
44
+ if (
45
+ ['pi', 'pi.cmd', 'pi.bat'].includes(basename(executable).toLowerCase()) &&
46
+ basename(dirname(executable)) === 'bin'
47
+ ) {
48
+ const launcher = metadata(executable)
49
+ if (launcher.includes('PI_MANAGED_INSTALL_ROOT=') && launcher.includes('install/current-version')) {
50
+ const install = join(dirname(dirname(executable)), 'install')
51
+ const version = metadata(join(install, 'current-version')).trim()
52
+ if (!versions.has(version)) throw failure()
53
+ executable = realpathSync(
54
+ join(install, 'releases', version, 'node_modules/@earendil-works/pi-coding-agent/dist/cli.js'),
55
+ )
56
+ }
57
+ }
58
+ executable = realpathSync(resolveNativeEntry(executable))
59
+ if (basename(executable).toLowerCase() === 'pi-launcher.js' && basename(dirname(executable)) === 'bin')
60
+ executable = windowsManagedEntry(executable)
61
+ let directory = dirname(executable)
62
+ for (let depth = 0; depth < 5; depth++, directory = dirname(directory)) {
63
+ let manifest
64
+ try {
65
+ manifest = JSON.parse(metadata(join(directory, 'package.json')))
66
+ } catch {
67
+ continue
68
+ }
69
+ if (manifest.name !== '@earendil-works/pi-coding-agent' || !versions.has(manifest.version))
70
+ throw failure()
71
+ const dist = join(directory, 'dist')
72
+ if (![join(dist, 'cli.js'), join(dist, 'bundle/cli.js')].includes(executable)) throw failure()
73
+ for (const relative of ['cli.js', 'index.js', 'core/model-runtime.js', 'core/auth-storage.js']) {
74
+ if (!statSync(join(dist, relative)).isFile()) throw failure()
75
+ }
76
+ return {
77
+ root: directory,
78
+ dist,
79
+ version: manifest.version,
80
+ executable: realpathSync(join(dist, 'cli.js')),
81
+ }
82
+ }
83
+ } catch {
84
+ throw failure()
85
+ }
86
+ throw failure()
87
+ }
@@ -0,0 +1,80 @@
1
+ // Pi 1.0.2 / 1.0.4 native UI compatibility entry. No initial prompt, injected keystrokes,
2
+ // model request, or subscription validation: open its own provider login menu.
3
+ import { join } from 'node:path'
4
+ import { pathToFileURL } from 'node:url'
5
+ import { inspectPiInstallation } from './pi-installation.mjs'
6
+
7
+ process.umask(0o077)
8
+ try {
9
+ const executable = process.argv[2]
10
+ const action = process.argv[3] ?? 'login'
11
+ if (!['login', 'logout'].includes(action)) throw new Error('Invalid account action')
12
+ if (!executable) throw new Error('Missing Pi entry')
13
+ const { dist } = inspectPiInstallation(executable)
14
+ const {
15
+ createAgentSessionServices,
16
+ createAgentSessionFromServices,
17
+ createAgentSessionRuntime,
18
+ SessionManager,
19
+ InteractiveMode,
20
+ ModelRuntime,
21
+ } = await import(pathToFileURL(join(dist, 'index.js')).href)
22
+ if (
23
+ [
24
+ createAgentSessionServices,
25
+ createAgentSessionFromServices,
26
+ createAgentSessionRuntime,
27
+ SessionManager?.inMemory,
28
+ InteractiveMode,
29
+ ].some((entry) => typeof entry !== 'function') ||
30
+ ['init', action === 'logout' ? 'showOAuthSelector' : 'handleLoginCommand', 'run'].some(
31
+ (method) => typeof InteractiveMode.prototype[method] !== 'function',
32
+ )
33
+ )
34
+ throw new Error('Unsupported Pi login SDK capabilities')
35
+ const cwd = process.cwd(),
36
+ agentDir = process.env.PI_CODING_AGENT_DIR
37
+ const runtime = await createAgentSessionRuntime(
38
+ async ({ cwd, agentDir, sessionManager }) => {
39
+ const services = await createAgentSessionServices({
40
+ cwd,
41
+ agentDir,
42
+ ...(action === 'logout'
43
+ ? {
44
+ modelRuntime: await ModelRuntime.create({
45
+ authPath: process.argv[4],
46
+ modelsPath: null,
47
+ modelsStorePath: join(agentDir, 'models-store.json'),
48
+ refreshOnCreate: false,
49
+ allowModelNetwork: false,
50
+ }),
51
+ }
52
+ : {}),
53
+ resourceLoaderOptions: {
54
+ noExtensions: true,
55
+ noSkills: true,
56
+ noPromptTemplates: true,
57
+ noThemes: true,
58
+ noContextFiles: true,
59
+ },
60
+ })
61
+ const created = await createAgentSessionFromServices({
62
+ services,
63
+ sessionManager,
64
+ noTools: 'all',
65
+ tools: [],
66
+ })
67
+ return { ...created, services, diagnostics: services.diagnostics }
68
+ },
69
+ { cwd, agentDir, sessionManager: SessionManager.inMemory(cwd) },
70
+ )
71
+ const ui = new InteractiveMode(runtime)
72
+ await ui.init()
73
+ if (action === 'logout') await ui.showOAuthSelector('logout')
74
+ else await ui.handleLoginCommand()
75
+ await ui.run()
76
+ } catch {
77
+ // Native errors can contain authentication data. Keep this boundary generic.
78
+ process.stderr.write('无法打开 Pi 原生账号界面,请检查 Pi Coding Agent 安装与受支持的原生接口。\n')
79
+ process.exitCode = 1
80
+ }