@jingyi0605/codingns4dsh 0.2.0-rc.2 → 0.2.0-rc3

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 (355) hide show
  1. package/README.en.md +4 -4
  2. package/README.md +15 -6
  3. package/assets/provider-icons/antigravity.svg +39 -0
  4. package/assets/provider-icons/codebuddy.svg +37 -0
  5. package/assets/provider-icons/cursor-cli.svg +1 -0
  6. package/assets/provider-icons/kiro-cli.svg +11 -0
  7. package/assets/provider-icons/qoder-cn.svg +5 -0
  8. package/assets/provider-icons/qoder.svg +5 -0
  9. package/assets/provider-icons/workbuddy.svg +29 -0
  10. package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.d.ts.map +1 -1
  11. package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.js +78 -1
  12. package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.js.map +1 -1
  13. package/data/build/dist/client/bundle.js +3864 -507
  14. package/data/build/dist/client/bundle.js.map +1 -1
  15. package/data/build/dist/client/cli-catalog.d.ts +1 -1
  16. package/data/build/dist/client/cli-catalog.d.ts.map +1 -1
  17. package/data/build/dist/client/cli-catalog.js +11 -5
  18. package/data/build/dist/client/cli-catalog.js.map +1 -1
  19. package/data/build/dist/client/cli-slots.d.ts.map +1 -1
  20. package/data/build/dist/client/cli-slots.js +111 -13
  21. package/data/build/dist/client/cli-slots.js.map +1 -1
  22. package/data/build/dist/client/debug/ui.d.ts.map +1 -1
  23. package/data/build/dist/client/debug/ui.js +2 -1
  24. package/data/build/dist/client/debug/ui.js.map +1 -1
  25. package/data/build/dist/client/delegate-command.d.ts +1 -0
  26. package/data/build/dist/client/delegate-command.d.ts.map +1 -1
  27. package/data/build/dist/client/delegate-command.js +486 -27
  28. package/data/build/dist/client/delegate-command.js.map +1 -1
  29. package/data/build/dist/client/delegate-plan.d.ts +13 -4
  30. package/data/build/dist/client/delegate-plan.d.ts.map +1 -1
  31. package/data/build/dist/client/delegate-plan.js +10 -6
  32. package/data/build/dist/client/delegate-plan.js.map +1 -1
  33. package/data/build/dist/client/delegate-ui-dom.d.ts +46 -0
  34. package/data/build/dist/client/delegate-ui-dom.d.ts.map +1 -1
  35. package/data/build/dist/client/delegate-ui-dom.js +291 -7
  36. package/data/build/dist/client/delegate-ui-dom.js.map +1 -1
  37. package/data/build/dist/client/features/cli-adapters.d.ts.map +1 -1
  38. package/data/build/dist/client/features/cli-adapters.js +117 -8
  39. package/data/build/dist/client/features/cli-adapters.js.map +1 -1
  40. package/data/build/dist/client/features/mobile-access-panel.d.ts.map +1 -1
  41. package/data/build/dist/client/features/mobile-access-panel.js +8 -7
  42. package/data/build/dist/client/features/mobile-access-panel.js.map +1 -1
  43. package/data/build/dist/client/features/peer-host.d.ts +6 -4
  44. package/data/build/dist/client/features/peer-host.d.ts.map +1 -1
  45. package/data/build/dist/client/features/peer-host.js +346 -18
  46. package/data/build/dist/client/features/peer-host.js.map +1 -1
  47. package/data/build/dist/client/git-history-graph.d.ts +2 -2
  48. package/data/build/dist/client/git-history-graph.d.ts.map +1 -1
  49. package/data/build/dist/client/git-history-graph.js +2 -2
  50. package/data/build/dist/client/git-history-graph.js.map +1 -1
  51. package/data/build/dist/client/git-management.d.ts.map +1 -1
  52. package/data/build/dist/client/git-management.js +21 -1
  53. package/data/build/dist/client/git-management.js.map +1 -1
  54. package/data/build/dist/client/locale.d.ts.map +1 -1
  55. package/data/build/dist/client/locale.js +60 -6
  56. package/data/build/dist/client/locale.js.map +1 -1
  57. package/data/build/dist/client/locales/terminalAuth.d.ts.map +1 -1
  58. package/data/build/dist/client/locales/terminalAuth.js +4 -0
  59. package/data/build/dist/client/locales/terminalAuth.js.map +1 -1
  60. package/data/build/dist/client/locales/usage.d.ts.map +1 -1
  61. package/data/build/dist/client/locales/usage.js +20 -0
  62. package/data/build/dist/client/locales/usage.js.map +1 -1
  63. package/data/build/dist/client/mobile-session-interaction.d.ts.map +1 -1
  64. package/data/build/dist/client/mobile-session-interaction.js +24 -7
  65. package/data/build/dist/client/mobile-session-interaction.js.map +1 -1
  66. package/data/build/dist/client/mobile-sidebar-gestures.d.ts +55 -7
  67. package/data/build/dist/client/mobile-sidebar-gestures.d.ts.map +1 -1
  68. package/data/build/dist/client/mobile-sidebar-gestures.js +339 -40
  69. package/data/build/dist/client/mobile-sidebar-gestures.js.map +1 -1
  70. package/data/build/dist/client/model-catalog-cache.d.ts +5 -0
  71. package/data/build/dist/client/model-catalog-cache.d.ts.map +1 -0
  72. package/data/build/dist/client/model-catalog-cache.js +58 -0
  73. package/data/build/dist/client/model-catalog-cache.js.map +1 -0
  74. package/data/build/dist/client/peer-host-aggregate-refresh.d.ts +7 -0
  75. package/data/build/dist/client/peer-host-aggregate-refresh.d.ts.map +1 -1
  76. package/data/build/dist/client/peer-host-aggregate-refresh.js +13 -1
  77. package/data/build/dist/client/peer-host-aggregate-refresh.js.map +1 -1
  78. package/data/build/dist/client/peer-host-native-projection.d.ts +16 -1
  79. package/data/build/dist/client/peer-host-native-projection.d.ts.map +1 -1
  80. package/data/build/dist/client/peer-host-native-projection.js +49 -8
  81. package/data/build/dist/client/peer-host-native-projection.js.map +1 -1
  82. package/data/build/dist/client/peer-host-native-store-projection.d.ts +6 -2
  83. package/data/build/dist/client/peer-host-native-store-projection.d.ts.map +1 -1
  84. package/data/build/dist/client/peer-host-native-store-projection.js +308 -10
  85. package/data/build/dist/client/peer-host-native-store-projection.js.map +1 -1
  86. package/data/build/dist/client/provider-icon-assets.js +14 -0
  87. package/data/build/dist/client/provider-icon-assets.js.map +1 -1
  88. package/data/build/dist/client/provider-icons.d.ts.map +1 -1
  89. package/data/build/dist/client/provider-icons.js +15 -3
  90. package/data/build/dist/client/provider-icons.js.map +1 -1
  91. package/data/build/dist/client/remote-web-context.js +10 -6
  92. package/data/build/dist/client/remote-web-context.js.map +1 -1
  93. package/data/build/dist/client/service-tier.d.ts +54 -0
  94. package/data/build/dist/client/service-tier.d.ts.map +1 -0
  95. package/data/build/dist/client/service-tier.js +78 -0
  96. package/data/build/dist/client/service-tier.js.map +1 -0
  97. package/data/build/dist/client/settings-promo-styles.d.ts +28 -0
  98. package/data/build/dist/client/settings-promo-styles.d.ts.map +1 -0
  99. package/data/build/dist/client/settings-promo-styles.js +58 -0
  100. package/data/build/dist/client/settings-promo-styles.js.map +1 -0
  101. package/data/build/dist/client/settings-promo.d.ts +14 -0
  102. package/data/build/dist/client/settings-promo.d.ts.map +1 -0
  103. package/data/build/dist/client/settings-promo.js +68 -0
  104. package/data/build/dist/client/settings-promo.js.map +1 -0
  105. package/data/build/dist/client/settings-section.d.ts +2 -1
  106. package/data/build/dist/client/settings-section.d.ts.map +1 -1
  107. package/data/build/dist/client/settings-section.js +7 -4
  108. package/data/build/dist/client/settings-section.js.map +1 -1
  109. package/data/build/dist/client/subscription-slot.d.ts.map +1 -1
  110. package/data/build/dist/client/subscription-slot.js +181 -16
  111. package/data/build/dist/client/subscription-slot.js.map +1 -1
  112. package/data/build/dist/client/terminal/model.d.ts +82 -3
  113. package/data/build/dist/client/terminal/model.d.ts.map +1 -1
  114. package/data/build/dist/client/terminal/model.js +368 -29
  115. package/data/build/dist/client/terminal/model.js.map +1 -1
  116. package/data/build/dist/client/terminal/recovery.d.ts +16 -1
  117. package/data/build/dist/client/terminal/recovery.d.ts.map +1 -1
  118. package/data/build/dist/client/terminal/recovery.js +101 -39
  119. package/data/build/dist/client/terminal/recovery.js.map +1 -1
  120. package/data/build/dist/client/terminal/styles.d.ts +10 -0
  121. package/data/build/dist/client/terminal/styles.d.ts.map +1 -1
  122. package/data/build/dist/client/terminal/styles.js +27 -3
  123. package/data/build/dist/client/terminal/styles.js.map +1 -1
  124. package/data/build/dist/client/terminal/ui.d.ts +3 -2
  125. package/data/build/dist/client/terminal/ui.d.ts.map +1 -1
  126. package/data/build/dist/client/terminal/ui.js +215 -104
  127. package/data/build/dist/client/terminal/ui.js.map +1 -1
  128. package/data/build/dist/client/terminal/xterm-view.d.ts +5 -1
  129. package/data/build/dist/client/terminal/xterm-view.d.ts.map +1 -1
  130. package/data/build/dist/client/terminal/xterm-view.js +378 -20
  131. package/data/build/dist/client/terminal/xterm-view.js.map +1 -1
  132. package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts +58 -0
  133. package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts.map +1 -0
  134. package/data/build/dist/host/cli-adapters/acp-cli-driver.js +271 -0
  135. package/data/build/dist/host/cli-adapters/acp-cli-driver.js.map +1 -0
  136. package/data/build/dist/host/cli-adapters/antigravity-driver.d.ts +30 -0
  137. package/data/build/dist/host/cli-adapters/antigravity-driver.d.ts.map +1 -0
  138. package/data/build/dist/host/cli-adapters/antigravity-driver.js +210 -0
  139. package/data/build/dist/host/cli-adapters/antigravity-driver.js.map +1 -0
  140. package/data/build/dist/host/cli-adapters/claude-driver.js +1 -1
  141. package/data/build/dist/host/cli-adapters/claude-driver.js.map +1 -1
  142. package/data/build/dist/host/cli-adapters/codebuddy-driver.d.ts +139 -0
  143. package/data/build/dist/host/cli-adapters/codebuddy-driver.d.ts.map +1 -0
  144. package/data/build/dist/host/cli-adapters/codebuddy-driver.js +1721 -0
  145. package/data/build/dist/host/cli-adapters/codebuddy-driver.js.map +1 -0
  146. package/data/build/dist/host/cli-adapters/codebuddy-subscription.d.ts +53 -0
  147. package/data/build/dist/host/cli-adapters/codebuddy-subscription.d.ts.map +1 -0
  148. package/data/build/dist/host/cli-adapters/codebuddy-subscription.js +778 -0
  149. package/data/build/dist/host/cli-adapters/codebuddy-subscription.js.map +1 -0
  150. package/data/build/dist/host/cli-adapters/codex-driver.d.ts +12 -0
  151. package/data/build/dist/host/cli-adapters/codex-driver.d.ts.map +1 -1
  152. package/data/build/dist/host/cli-adapters/codex-driver.js +153 -6
  153. package/data/build/dist/host/cli-adapters/codex-driver.js.map +1 -1
  154. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts +43 -3
  155. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts.map +1 -1
  156. package/data/build/dist/host/cli-adapters/command-code-driver.js +637 -72
  157. package/data/build/dist/host/cli-adapters/command-code-driver.js.map +1 -1
  158. package/data/build/dist/host/cli-adapters/command-code-history.d.ts +147 -0
  159. package/data/build/dist/host/cli-adapters/command-code-history.d.ts.map +1 -0
  160. package/data/build/dist/host/cli-adapters/command-code-history.js +659 -0
  161. package/data/build/dist/host/cli-adapters/command-code-history.js.map +1 -0
  162. package/data/build/dist/host/cli-adapters/cursor-driver.d.ts +12 -0
  163. package/data/build/dist/host/cli-adapters/cursor-driver.d.ts.map +1 -0
  164. package/data/build/dist/host/cli-adapters/cursor-driver.js +20 -0
  165. package/data/build/dist/host/cli-adapters/cursor-driver.js.map +1 -0
  166. package/data/build/dist/host/cli-adapters/custom-upstream-classifier.d.ts +67 -0
  167. package/data/build/dist/host/cli-adapters/custom-upstream-classifier.d.ts.map +1 -0
  168. package/data/build/dist/host/cli-adapters/custom-upstream-classifier.js +169 -0
  169. package/data/build/dist/host/cli-adapters/custom-upstream-classifier.js.map +1 -0
  170. package/data/build/dist/host/cli-adapters/delegate-dispatch.d.ts +2 -1
  171. package/data/build/dist/host/cli-adapters/delegate-dispatch.d.ts.map +1 -1
  172. package/data/build/dist/host/cli-adapters/delegate-dispatch.js +14 -61
  173. package/data/build/dist/host/cli-adapters/delegate-dispatch.js.map +1 -1
  174. package/data/build/dist/host/cli-adapters/delegation-authorization.d.ts +19 -0
  175. package/data/build/dist/host/cli-adapters/delegation-authorization.d.ts.map +1 -0
  176. package/data/build/dist/host/cli-adapters/delegation-authorization.js +49 -0
  177. package/data/build/dist/host/cli-adapters/delegation-authorization.js.map +1 -0
  178. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.d.ts +34 -0
  179. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.d.ts.map +1 -0
  180. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.js +121 -0
  181. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.js.map +1 -0
  182. package/data/build/dist/host/cli-adapters/driver.d.ts +6 -0
  183. package/data/build/dist/host/cli-adapters/driver.d.ts.map +1 -1
  184. package/data/build/dist/host/cli-adapters/feature.d.ts.map +1 -1
  185. package/data/build/dist/host/cli-adapters/feature.js +269 -18
  186. package/data/build/dist/host/cli-adapters/feature.js.map +1 -1
  187. package/data/build/dist/host/cli-adapters/kiro-driver.d.ts +12 -0
  188. package/data/build/dist/host/cli-adapters/kiro-driver.d.ts.map +1 -0
  189. package/data/build/dist/host/cli-adapters/kiro-driver.js +18 -0
  190. package/data/build/dist/host/cli-adapters/kiro-driver.js.map +1 -0
  191. package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts.map +1 -1
  192. package/data/build/dist/host/cli-adapters/legacy-session-adapter.js +11 -0
  193. package/data/build/dist/host/cli-adapters/legacy-session-adapter.js.map +1 -1
  194. package/data/build/dist/host/cli-adapters/model-catalog.d.ts +5 -0
  195. package/data/build/dist/host/cli-adapters/model-catalog.d.ts.map +1 -1
  196. package/data/build/dist/host/cli-adapters/model-catalog.js +130 -0
  197. package/data/build/dist/host/cli-adapters/model-catalog.js.map +1 -1
  198. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.d.ts +33 -3
  199. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.d.ts.map +1 -1
  200. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js +115 -9
  201. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js.map +1 -1
  202. package/data/build/dist/host/cli-adapters/native-team-subagent.d.ts +14 -2
  203. package/data/build/dist/host/cli-adapters/native-team-subagent.d.ts.map +1 -1
  204. package/data/build/dist/host/cli-adapters/native-team-subagent.js +23 -4
  205. package/data/build/dist/host/cli-adapters/native-team-subagent.js.map +1 -1
  206. package/data/build/dist/host/cli-adapters/new-api-subscription.d.ts +75 -0
  207. package/data/build/dist/host/cli-adapters/new-api-subscription.d.ts.map +1 -0
  208. package/data/build/dist/host/cli-adapters/new-api-subscription.js +959 -0
  209. package/data/build/dist/host/cli-adapters/new-api-subscription.js.map +1 -0
  210. package/data/build/dist/host/cli-adapters/opencode-driver.d.ts.map +1 -1
  211. package/data/build/dist/host/cli-adapters/opencode-driver.js +9 -7
  212. package/data/build/dist/host/cli-adapters/opencode-driver.js.map +1 -1
  213. package/data/build/dist/host/cli-adapters/provider-subscription.d.ts +33 -3
  214. package/data/build/dist/host/cli-adapters/provider-subscription.d.ts.map +1 -1
  215. package/data/build/dist/host/cli-adapters/provider-subscription.js +158 -40
  216. package/data/build/dist/host/cli-adapters/provider-subscription.js.map +1 -1
  217. package/data/build/dist/host/cli-adapters/qoder-driver.d.ts +71 -0
  218. package/data/build/dist/host/cli-adapters/qoder-driver.d.ts.map +1 -0
  219. package/data/build/dist/host/cli-adapters/qoder-driver.js +553 -0
  220. package/data/build/dist/host/cli-adapters/qoder-driver.js.map +1 -0
  221. package/data/build/dist/host/cli-adapters/qoder-subscription.d.ts +31 -0
  222. package/data/build/dist/host/cli-adapters/qoder-subscription.d.ts.map +1 -0
  223. package/data/build/dist/host/cli-adapters/qoder-subscription.js +178 -0
  224. package/data/build/dist/host/cli-adapters/qoder-subscription.js.map +1 -0
  225. package/data/build/dist/host/cli-adapters/registry.d.ts +41 -2
  226. package/data/build/dist/host/cli-adapters/registry.d.ts.map +1 -1
  227. package/data/build/dist/host/cli-adapters/registry.js +187 -18
  228. package/data/build/dist/host/cli-adapters/registry.js.map +1 -1
  229. package/data/build/dist/host/cli-adapters/session-store.d.ts +4 -0
  230. package/data/build/dist/host/cli-adapters/session-store.d.ts.map +1 -1
  231. package/data/build/dist/host/cli-adapters/session-store.js +18 -2
  232. package/data/build/dist/host/cli-adapters/session-store.js.map +1 -1
  233. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +14 -1
  234. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts.map +1 -1
  235. package/data/build/dist/host/cli-adapters/standard-stream-driver.js +121 -23
  236. package/data/build/dist/host/cli-adapters/standard-stream-driver.js.map +1 -1
  237. package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts +10 -1
  238. package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts.map +1 -1
  239. package/data/build/dist/host/cli-adapters/stream-normalizer.js +23 -0
  240. package/data/build/dist/host/cli-adapters/stream-normalizer.js.map +1 -1
  241. package/data/build/dist/host/cli-adapters/subagent-tool.d.ts.map +1 -1
  242. package/data/build/dist/host/cli-adapters/subagent-tool.js +53 -7
  243. package/data/build/dist/host/cli-adapters/subagent-tool.js.map +1 -1
  244. package/data/build/dist/host/cli-bridge/bridge-server.d.ts +5 -0
  245. package/data/build/dist/host/cli-bridge/bridge-server.d.ts.map +1 -1
  246. package/data/build/dist/host/cli-bridge/bridge-server.js +7 -2
  247. package/data/build/dist/host/cli-bridge/bridge-server.js.map +1 -1
  248. package/data/build/dist/host/cli-bridge/command-code-mod.d.ts +5 -1
  249. package/data/build/dist/host/cli-bridge/command-code-mod.d.ts.map +1 -1
  250. package/data/build/dist/host/cli-bridge/command-code-mod.js +43 -12
  251. package/data/build/dist/host/cli-bridge/command-code-mod.js.map +1 -1
  252. package/data/build/dist/host/cli-bridge/dispatch.d.ts.map +1 -1
  253. package/data/build/dist/host/cli-bridge/dispatch.js +43 -5
  254. package/data/build/dist/host/cli-bridge/dispatch.js.map +1 -1
  255. package/data/build/dist/host/cli-bridge/mcp-stdio-entry.js +24 -5
  256. package/data/build/dist/host/cli-bridge/mcp-stdio-entry.js.map +1 -1
  257. package/data/build/dist/host/features/peer-host.d.ts +21 -1
  258. package/data/build/dist/host/features/peer-host.d.ts.map +1 -1
  259. package/data/build/dist/host/features/peer-host.js +174 -30
  260. package/data/build/dist/host/features/peer-host.js.map +1 -1
  261. package/data/build/dist/host/features/types.d.ts +2 -0
  262. package/data/build/dist/host/features/types.d.ts.map +1 -1
  263. package/data/build/dist/host/index.d.ts +11 -1
  264. package/data/build/dist/host/index.d.ts.map +1 -1
  265. package/data/build/dist/host/index.js +12 -2
  266. package/data/build/dist/host/index.js.map +1 -1
  267. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.js +6 -1
  268. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.js.map +1 -1
  269. package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.d.ts +2 -0
  270. package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.d.ts.map +1 -1
  271. package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.js +26 -7
  272. package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.js.map +1 -1
  273. package/data/build/dist/host/native-session-bridge.d.ts.map +1 -1
  274. package/data/build/dist/host/native-session-bridge.js +36 -7
  275. package/data/build/dist/host/native-session-bridge.js.map +1 -1
  276. package/data/build/dist/host/rpc.js +5 -2
  277. package/data/build/dist/host/rpc.js.map +1 -1
  278. package/data/build/dist/host/settings.d.ts.map +1 -1
  279. package/data/build/dist/host/settings.js +12 -5
  280. package/data/build/dist/host/settings.js.map +1 -1
  281. package/data/build/dist/host/terminal/backends/local-pty-backend.d.ts.map +1 -1
  282. package/data/build/dist/host/terminal/backends/local-pty-backend.js +14 -0
  283. package/data/build/dist/host/terminal/backends/local-pty-backend.js.map +1 -1
  284. package/data/build/dist/host/terminal/backends/tmux-backend.d.ts +40 -1
  285. package/data/build/dist/host/terminal/backends/tmux-backend.d.ts.map +1 -1
  286. package/data/build/dist/host/terminal/backends/tmux-backend.js +291 -18
  287. package/data/build/dist/host/terminal/backends/tmux-backend.js.map +1 -1
  288. package/data/build/dist/host/terminal/runtime-adapter.d.ts +32 -0
  289. package/data/build/dist/host/terminal/runtime-adapter.d.ts.map +1 -1
  290. package/data/build/dist/host/terminal/runtime-adapter.js +8 -0
  291. package/data/build/dist/host/terminal/runtime-adapter.js.map +1 -1
  292. package/data/build/dist/host/terminal/runtime-manager.d.ts +3 -0
  293. package/data/build/dist/host/terminal/runtime-manager.d.ts.map +1 -1
  294. package/data/build/dist/host/terminal/runtime-manager.js +92 -4
  295. package/data/build/dist/host/terminal/runtime-manager.js.map +1 -1
  296. package/data/build/dist/host/terminal/terminal-controller.d.ts.map +1 -1
  297. package/data/build/dist/host/terminal/terminal-controller.js +58 -6
  298. package/data/build/dist/host/terminal/terminal-controller.js.map +1 -1
  299. package/data/build/dist/host/terminal/terminal-process-service.d.ts.map +1 -1
  300. package/data/build/dist/host/terminal/terminal-process-service.js +12 -2
  301. package/data/build/dist/host/terminal/terminal-process-service.js.map +1 -1
  302. package/data/build/dist/host/terminal/terminal-service.d.ts +41 -4
  303. package/data/build/dist/host/terminal/terminal-service.d.ts.map +1 -1
  304. package/data/build/dist/host/terminal/terminal-service.js +551 -61
  305. package/data/build/dist/host/terminal/terminal-service.js.map +1 -1
  306. package/data/build/dist/index.d.ts +2 -2
  307. package/data/build/dist/index.d.ts.map +1 -1
  308. package/data/build/dist/index.js +2 -2
  309. package/data/build/dist/index.js.map +1 -1
  310. package/data/build/dist/shared/contracts/cli-adapter.d.ts +64 -2
  311. package/data/build/dist/shared/contracts/cli-adapter.d.ts.map +1 -1
  312. package/data/build/dist/shared/contracts/config.d.ts +54 -11
  313. package/data/build/dist/shared/contracts/config.d.ts.map +1 -1
  314. package/data/build/dist/shared/contracts/config.js +52 -8
  315. package/data/build/dist/shared/contracts/config.js.map +1 -1
  316. package/data/build/dist/shared/contracts/subscription.d.ts +5 -1
  317. package/data/build/dist/shared/contracts/subscription.d.ts.map +1 -1
  318. package/data/build/dist/shared/contracts/subscription.js.map +1 -1
  319. package/data/build/dist/shared/contracts/terminal.d.ts +8 -1
  320. package/data/build/dist/shared/contracts/terminal.d.ts.map +1 -1
  321. package/data/build/dist/shared/contracts/version.d.ts +1 -1
  322. package/data/build/dist/shared/contracts/version.d.ts.map +1 -1
  323. package/data/build/dist/shared/contracts/version.js +1 -1
  324. package/data/build/dist/shared/contracts/version.js.map +1 -1
  325. package/data/build/dist/shared/debug.d.ts +8 -0
  326. package/data/build/dist/shared/debug.d.ts.map +1 -1
  327. package/data/build/dist/shared/debug.js +43 -7
  328. package/data/build/dist/shared/debug.js.map +1 -1
  329. package/data/build/dist/shared/delegation-carrier.d.ts +24 -0
  330. package/data/build/dist/shared/delegation-carrier.d.ts.map +1 -0
  331. package/data/build/dist/shared/delegation-carrier.js +111 -0
  332. package/data/build/dist/shared/delegation-carrier.js.map +1 -0
  333. package/data/build/dist/shared/index.d.ts +2 -2
  334. package/data/build/dist/shared/index.d.ts.map +1 -1
  335. package/data/build/dist/shared/index.js +2 -2
  336. package/data/build/dist/shared/index.js.map +1 -1
  337. package/data/build/dist/shared/terminal-input.d.ts +8 -0
  338. package/data/build/dist/shared/terminal-input.d.ts.map +1 -0
  339. package/data/build/dist/shared/terminal-input.js +10 -0
  340. package/data/build/dist/shared/terminal-input.js.map +1 -0
  341. package/data/build/dist/transport/debug.d.ts +7 -0
  342. package/data/build/dist/transport/debug.d.ts.map +1 -1
  343. package/data/build/dist/transport/debug.js +33 -5
  344. package/data/build/dist/transport/debug.js.map +1 -1
  345. package/data/build/dist/transport/index.d.ts +1 -1
  346. package/data/build/dist/transport/index.d.ts.map +1 -1
  347. package/data/build/dist/transport/index.js +1 -1
  348. package/data/build/dist/transport/index.js.map +1 -1
  349. package/data/build/dist/typert.host.js +1 -1
  350. package/data/build/dist/typert.host.js.map +1 -1
  351. package/package.json +1 -1
  352. package/profile/README.md +2 -2
  353. package/profile/package.json +2 -2
  354. package/profile/version.json +1 -1
  355. package/version.json +1 -1
@@ -0,0 +1,778 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';
5
+ import { createConnection } from 'node:net';
6
+ const INTERNAL_DOMAINS = new Set([
7
+ 'copilot.tencent.com', 'staging-copilot.tencent.com', 'www.codebuddy.cn', 'staging.codebuddy.cn',
8
+ 'www.workbuddy.cn', 'staging.workbuddy.cn',
9
+ ]);
10
+ const EXTERNAL_DOMAINS = new Set([
11
+ 'www.codebuddy.ai', 'codebuddy.ai', 'staging-codebuddy.tencent.com',
12
+ 'www.workbuddy.ai', 'workbuddy.ai', 'staging.workbuddy.ai',
13
+ ]);
14
+ const DEFAULT_ORIGINS = {
15
+ cn: ['https://copilot.tencent.com', 'https://www.codebuddy.cn'],
16
+ international: ['https://www.codebuddy.ai', 'https://staging-codebuddy.tencent.com'],
17
+ };
18
+ /** WorkBuddy 使用独立产品域名,不能回退到 CodeBuddy 计费域名。 */
19
+ const WORKBUDDY_ORIGINS = {
20
+ cn: ['https://www.workbuddy.cn'],
21
+ international: ['https://www.workbuddy.ai'],
22
+ };
23
+ const ACCOUNT_STATUS_VALID = 0;
24
+ const ACCOUNT_STATUS_USED_UP = 3;
25
+ /**
26
+ * 读取 CodeBuddy/WorkBuddy 官方计费摘要。
27
+ *
28
+ * ACP 的 `usage_update` 只描述当前会话 token 消耗,不能代替套餐余额。
29
+ * 这里直接调用官方只读 billing API,并且把接口不稳定视为“暂无用量”,不影响会话。
30
+ */
31
+ export class CodeBuddySubscriptionService {
32
+ request;
33
+ timeoutMs;
34
+ homeDirectory;
35
+ authFiles;
36
+ origins;
37
+ constructor(options = {}) {
38
+ this.request = options.fetch ?? fetch;
39
+ this.timeoutMs = options.timeoutMs ?? 8_000;
40
+ this.homeDirectory = options.homeDirectory?.trim() || process.env.HOME?.trim() || homedir();
41
+ this.authFiles = options.authFiles;
42
+ this.origins = options.origins ?? {};
43
+ }
44
+ async read(adapterId) {
45
+ if (adapterId === 'workbuddy' && this.authFiles === undefined) {
46
+ const viaIpc = await this.readWorkBuddyViaIpc();
47
+ if (viaIpc !== null)
48
+ return viaIpc;
49
+ }
50
+ return this.readWithRequest(adapterId, this.request);
51
+ }
52
+ async readWithRequest(adapterId, request, overrideAuth) {
53
+ const authFiles = this.authFiles ?? defaultAuthFiles(this.homeDirectory, adapterId);
54
+ const regions = overrideAuth === undefined
55
+ ? orderRegions(regionsForAdapter(adapterId), authFiles)
56
+ : regionsForAdapter(adapterId).filter((region) => matchesRegion(overrideAuth.domain, region));
57
+ if (regions.length === 0)
58
+ return null;
59
+ for (const region of regions) {
60
+ const auth = overrideAuth ?? readCodeBuddyAuth(authFiles, region);
61
+ if (auth === null)
62
+ continue;
63
+ const defaultOrigins = adapterId === 'workbuddy' ? WORKBUDDY_ORIGINS : DEFAULT_ORIGINS;
64
+ const origins = uniqueOrigins(this.origins[region] ?? defaultOrigins[region]);
65
+ for (const origin of origins) {
66
+ if (auth.enterpriseId !== null) {
67
+ const enterprise = normalizeEnterpriseUsage(await this.post(origin, '/billing/meter/get-enterprise-user-usage', auth, region, {}, adapterId, request));
68
+ if (enterprise !== null)
69
+ return buildUsage(origin, enterprise.summary, enterprise.resources, adapterId);
70
+ }
71
+ const summaryResponse = await this.post(origin, '/billing/meter/get-user-resource-summary', auth, region, {}, adapterId, request);
72
+ const summary = normalizeSummary(summaryResponse);
73
+ if (summary === null)
74
+ continue;
75
+ const packageCodes = summary.resources.map((resource) => resource.packageCode).filter(Boolean);
76
+ const [paid, free] = await Promise.all([
77
+ this.post(origin, '/billing/meter/get-user-resource-paid-packages', auth, region, {
78
+ PageNumber: 1,
79
+ PageSize: 200,
80
+ PackageCodes: packageCodes,
81
+ Status: [ACCOUNT_STATUS_VALID, ACCOUNT_STATUS_USED_UP],
82
+ NeedRenewInfo: true,
83
+ }, adapterId, request),
84
+ this.post(origin, '/billing/meter/get-user-resource-free-packages', auth, region, {
85
+ PageNumber: 1,
86
+ PageSize: 200,
87
+ PackageCodes: packageCodes,
88
+ Status: [ACCOUNT_STATUS_VALID, ACCOUNT_STATUS_USED_UP],
89
+ ...slicePeriodRange(),
90
+ }, adapterId, request),
91
+ ]);
92
+ const resources = mergeResources(summary.resources, normalizePackageAccounts(paid), normalizePackageAccounts(free));
93
+ return buildUsage(origin, summary, resources, adapterId);
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+ /** WorkBuddy 的认证文件是字段加密格式,必须让 daemon 通过 WBIPC 注入认证头。 */
99
+ async readWorkBuddyViaIpc() {
100
+ const authFiles = defaultAuthFiles(this.homeDirectory, 'workbuddy');
101
+ const auth = readWorkBuddyAuthMetadata(authFiles);
102
+ if (auth === null)
103
+ return null;
104
+ const ipc = await connectWorkBuddyRequestPipe(this.homeDirectory);
105
+ if (ipc === null)
106
+ return null;
107
+ try {
108
+ return await this.readWithRequest('workbuddy', ipc.fetch, auth);
109
+ }
110
+ finally {
111
+ ipc.close();
112
+ }
113
+ }
114
+ async post(origin, path, auth, region, body, adapterId, request) {
115
+ const controller = new AbortController();
116
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
117
+ const normalizedOrigin = normalizeOrigin(origin);
118
+ if (normalizedOrigin === '') {
119
+ clearTimeout(timer);
120
+ return null;
121
+ }
122
+ try {
123
+ const response = await request(`${normalizedOrigin}${path}`, {
124
+ method: 'POST',
125
+ headers: requestHeaders(normalizedOrigin, auth, region, adapterId),
126
+ body: JSON.stringify(body),
127
+ signal: controller.signal,
128
+ });
129
+ if (!response.ok)
130
+ return null;
131
+ return recordValue(await response.json());
132
+ }
133
+ catch {
134
+ return null;
135
+ }
136
+ finally {
137
+ clearTimeout(timer);
138
+ }
139
+ }
140
+ }
141
+ function regionsForAdapter(adapterId) {
142
+ // 兼容旧版持久化调用;统一适配器只向外暴露 codebuddy。
143
+ if (adapterId === 'codebuddy-cn')
144
+ adapterId = 'codebuddy';
145
+ // WorkBuddy 的国内版和国际版共用一个适配器,按认证文件 domain 选择计费区域。
146
+ if (adapterId === 'codebuddy' || adapterId === 'workbuddy')
147
+ return ['cn', 'international'];
148
+ return [];
149
+ }
150
+ function defaultAuthFiles(home, adapterId) {
151
+ if (adapterId === 'workbuddy')
152
+ return [workBuddyAuthFileForHome(home)];
153
+ return [
154
+ authFileForHome(home),
155
+ authFileForHome(join(home, '.codebuddy-cn-home')),
156
+ authFileForHome(join(home, '.codebuddy-international-home')),
157
+ authFileForHome(join(home, '.workbuddy')),
158
+ ];
159
+ }
160
+ function workBuddyAuthFileForHome(home) {
161
+ if (process.platform === 'win32')
162
+ return join(home, 'AppData/Local/CodeBuddyExtension/Data/Public/auth/workbuddy-desktop.info');
163
+ if (process.platform === 'darwin')
164
+ return join(home, 'Library/Application Support/CodeBuddyExtension/Data/Public/auth/workbuddy-desktop.info');
165
+ return join(home, '.local/share/CodeBuddyExtension/Data/Public/auth/workbuddy-desktop.info');
166
+ }
167
+ function readWorkBuddyAuthMetadata(files) {
168
+ for (const path of files) {
169
+ try {
170
+ const value = recordValue(JSON.parse(readFileSync(path, 'utf8')));
171
+ if (value === null)
172
+ continue;
173
+ const auth = recordValue(value.auth);
174
+ const account = recordValue(value.account);
175
+ const uid = textValue(account?.uid ?? value.uid);
176
+ const domain = (textValue(auth?.domain ?? account?.domain) ?? '').toLowerCase();
177
+ const encryptedToken = recordValue(auth?.accessToken ?? auth?.access_token);
178
+ if (uid === null || domain === '' || encryptedToken === null)
179
+ continue;
180
+ const enterpriseId = textValue(account?.enterpriseId ?? account?.enterprise_id ?? value.enterpriseId ?? value.enterprise_id);
181
+ // 令牌只作为类型占位;实际请求由 WorkBuddy daemon 通过 WBIPC 注入。
182
+ return { accessToken: '', uid, domain, enterpriseId };
183
+ }
184
+ catch {
185
+ // 认证文件缺失或损坏时继续检查其他候选文件。
186
+ }
187
+ }
188
+ return null;
189
+ }
190
+ function authFileForHome(home) {
191
+ if (process.platform === 'win32')
192
+ return join(home, 'AppData/Local/CodeBuddyExtension/Data/Public/auth/Tencent-Cloud.coding-copilot.info');
193
+ if (process.platform === 'darwin')
194
+ return join(home, 'Library/Application Support/CodeBuddyExtension/Data/Public/auth/Tencent-Cloud.coding-copilot.info');
195
+ return join(home, '.local/share/CodeBuddyExtension/Data/Public/auth/Tencent-Cloud.coding-copilot.info');
196
+ }
197
+ function orderRegions(regions, authFiles) {
198
+ if (regions.length < 2)
199
+ return regions;
200
+ const configured = `${process.env.CODEBUDDY_INTERNET_ENVIRONMENT ?? process.env.CODEBUDDY_COPILOT_INTERNET_ENVIRONMENT ?? ''}`.trim().toLowerCase();
201
+ const preferred = configured === 'internal' || configured === 'cn' || configured === 'china' || configured === 'ioa'
202
+ ? 'cn'
203
+ : configured === 'external' || configured === 'international' || configured === 'overseas'
204
+ ? 'international'
205
+ : regionFromAuthFile(authFiles[0]);
206
+ if (preferred === undefined || !regions.includes(preferred))
207
+ return regions;
208
+ return [preferred, ...regions.filter((region) => region !== preferred)];
209
+ }
210
+ function regionFromAuthFile(path) {
211
+ if (path === undefined)
212
+ return undefined;
213
+ try {
214
+ const value = recordValue(JSON.parse(readFileSync(path, 'utf8')));
215
+ const auth = recordValue(value?.auth);
216
+ const domain = (textValue(auth?.domain) ?? '').toLowerCase();
217
+ if (INTERNAL_DOMAINS.has(domain))
218
+ return 'cn';
219
+ if (EXTERNAL_DOMAINS.has(domain))
220
+ return 'international';
221
+ }
222
+ catch {
223
+ // 缺少或损坏的主认证文件时,继续按候选文件逐区查询。
224
+ }
225
+ return undefined;
226
+ }
227
+ function readCodeBuddyAuth(files, region) {
228
+ for (const path of files) {
229
+ try {
230
+ const value = recordValue(JSON.parse(readFileSync(path, 'utf8')));
231
+ if (value === null)
232
+ continue;
233
+ const auth = recordValue(value.auth);
234
+ const account = recordValue(value.account);
235
+ const accessToken = textValue(auth?.accessToken ?? auth?.access_token);
236
+ const uid = textValue(account?.uid ?? value.uid);
237
+ if (accessToken === null || uid === null)
238
+ continue;
239
+ const domain = (textValue(auth?.domain ?? account?.domain) ?? '').toLowerCase();
240
+ if (!matchesRegion(domain, region))
241
+ continue;
242
+ const enterpriseId = textValue(account?.enterpriseId ?? account?.enterprise_id ?? value.enterpriseId ?? value.enterprise_id);
243
+ return { accessToken, uid, domain, enterpriseId };
244
+ }
245
+ catch {
246
+ // 认证文件缺失或损坏时继续检查其他隔离根。
247
+ }
248
+ }
249
+ return null;
250
+ }
251
+ function matchesRegion(domain, region) {
252
+ if (domain === '')
253
+ return false;
254
+ const hostname = domain.replace(/^https?:\/\//u, '').split('/')[0]?.toLowerCase() ?? '';
255
+ return (region === 'cn' ? INTERNAL_DOMAINS : EXTERNAL_DOMAINS).has(hostname);
256
+ }
257
+ function requestHeaders(origin, auth, region, adapterId) {
258
+ return {
259
+ Authorization: `Bearer ${auth.accessToken}`,
260
+ 'X-User-Id': auth.uid,
261
+ 'X-Trace-ID': randomUUID(),
262
+ 'X-Request-ID': randomUUID(),
263
+ 'Accept-Language': region === 'cn' ? 'zh' : 'en',
264
+ Accept: 'application/json',
265
+ 'Content-Type': 'application/json',
266
+ Origin: origin,
267
+ Referer: `${origin}/`,
268
+ 'User-Agent': `CodingNS4DSH ${adapterId === 'workbuddy' ? 'WorkBuddy' : 'CodeBuddy'} subscription reader`,
269
+ ...(adapterId === 'workbuddy' ? {
270
+ 'X-Domain': auth.domain,
271
+ 'X-Product': 'WorkBuddy',
272
+ 'X-IDE-Type': 'WorkBuddy',
273
+ 'X-IDE-Name': 'WorkBuddy',
274
+ } : {}),
275
+ ...(auth.enterpriseId === null ? {} : { 'X-Enterprise-Id': auth.enterpriseId }),
276
+ };
277
+ }
278
+ function normalizeSummary(value) {
279
+ const data = unwrapData(value);
280
+ if (data === null)
281
+ return null;
282
+ const resources = arrayValue(data.Packages ?? data.packages).map(normalizeSummaryResource).filter((item) => item !== null);
283
+ const planCode = textValue(data.SubscriptionPackageCode ?? data.subscriptionPackageCode) ?? '';
284
+ const planName = textValue(data.SubscriptionPackageName ?? data.subscriptionPackageName ?? data.PackageName ?? data.packageName) ?? '';
285
+ const isPaid = booleanValue(data.IsPaidUser ?? data.isPaidUser);
286
+ if (resources.length === 0 && planCode === '' && planName === '')
287
+ return null;
288
+ return { planCode, planName, isPaid, resources };
289
+ }
290
+ /** 导出给 fixture/诊断使用的容错 summary 解析器,不暴露任何认证字段。 */
291
+ export function normalizeCodeBuddySummary(value) {
292
+ return normalizeSummary(recordValue(value));
293
+ }
294
+ function normalizeSummaryResource(value) {
295
+ const record = recordValue(value);
296
+ if (record === null)
297
+ return null;
298
+ const packageCode = textValue(record.PackageCode ?? record.packageCode ?? record.Code ?? record.code);
299
+ if (packageCode === null)
300
+ return null;
301
+ const total = numberValue(record.CycleTotalCapacity ?? record.cycleTotalCapacity ?? record.TotalCapacity ?? record.totalCapacity);
302
+ const remaining = numberValue(record.CycleRemainCapacity ?? record.cycleRemainCapacity ?? record.RemainCapacity ?? record.remainCapacity);
303
+ const used = numberValue(record.CycleUsedCapacity ?? record.cycleUsedCapacity ?? record.UsedCapacity ?? record.usedCapacity)
304
+ ?? (total !== null && remaining !== null ? Math.max(0, total - remaining) : null);
305
+ return {
306
+ packageCode,
307
+ packageName: textValue(record.PackageName ?? record.packageName) ?? packageCode,
308
+ total,
309
+ used,
310
+ remaining,
311
+ expiresAt: timestampValue(record.DeductionEndTime ?? record.ExpiredTime ?? record.CycleEndTime ?? record.expireAt),
312
+ refreshAt: timestampValue(record.CycleEndTime ?? record.refreshAt),
313
+ };
314
+ }
315
+ function normalizePackageAccounts(value) {
316
+ const data = unwrapData(value);
317
+ if (data === null)
318
+ return [];
319
+ const entries = arrayValue(data.Accounts ?? data.accounts ?? data.Resources ?? data.resources);
320
+ return entries.flatMap((entry) => {
321
+ const record = recordValue(entry);
322
+ if (record === null)
323
+ return [];
324
+ const resource = normalizeSummaryResource(record);
325
+ if (resource === null)
326
+ return [];
327
+ const capacityType = numberValue(record.CapacityType ?? record.capacityType);
328
+ const slices = arrayValue(record.SlicePeriodUsageDetails ?? record.slicePeriodUsageDetails);
329
+ if (capacityType !== 4 || slices.length === 0)
330
+ return [resource];
331
+ const slice = recordValue(slices[0]);
332
+ if (slice === null)
333
+ return [resource];
334
+ const total = numberValue(slice.CycleCapacitySizePrecise ?? slice.cycleCapacitySizePrecise) ?? resource.total;
335
+ const remaining = numberValue(slice.CycleCapacityRemainPrecise ?? slice.cycleCapacityRemainPrecise) ?? resource.remaining;
336
+ const used = numberValue(slice.CycleCapacityUsedPrecise ?? slice.cycleCapacityUsedPrecise) ?? (total !== null && remaining !== null ? Math.max(0, total - remaining) : resource.used);
337
+ return [{ ...resource, total, remaining, used, expiresAt: timestampValue(slice.CycleEndTime ?? slice.endTime) ?? resource.expiresAt, refreshAt: timestampValue(slice.CycleEndTime ?? slice.endTime) ?? resource.refreshAt }];
338
+ });
339
+ }
340
+ function mergeResources(...lists) {
341
+ const merged = new Map();
342
+ for (const list of lists) {
343
+ for (const resource of list) {
344
+ const current = merged.get(resource.packageCode);
345
+ merged.set(resource.packageCode, current === undefined ? resource : {
346
+ packageCode: resource.packageCode,
347
+ packageName: resource.packageName && resource.packageName !== resource.packageCode ? resource.packageName : current.packageName,
348
+ total: resource.total ?? current.total,
349
+ used: resource.used ?? current.used,
350
+ remaining: resource.remaining ?? current.remaining,
351
+ expiresAt: resource.expiresAt ?? current.expiresAt,
352
+ refreshAt: resource.refreshAt ?? current.refreshAt,
353
+ });
354
+ }
355
+ }
356
+ return [...merged.values()];
357
+ }
358
+ function buildUsage(origin, summary, resources, adapterId) {
359
+ const total = sumNumbers(resources.map((resource) => resource.total));
360
+ const remaining = sumNumbers(resources.map((resource) => resource.remaining));
361
+ const used = sumNumbers(resources.map((resource) => resource.used)) ?? (total !== null && remaining !== null ? Math.max(0, total - remaining) : null);
362
+ const details = [
363
+ ...(summary.isPaid === null ? [] : [{ label: '付费用户', value: summary.isPaid ? '是' : '否' }]),
364
+ ];
365
+ for (const resource of resources) {
366
+ const label = resource.packageName || resource.packageCode;
367
+ if (resource.total !== null)
368
+ details.push({ label: `${label} 总量`, value: resource.total });
369
+ if (resource.used !== null)
370
+ details.push({ label: `${label} 已用`, value: resource.used });
371
+ if (resource.remaining !== null)
372
+ details.push({ label: `${label} 剩余`, value: resource.remaining });
373
+ if (resource.expiresAt !== null)
374
+ details.push({ label: `${label} 周期结束`, value: new Date(resource.expiresAt).toISOString() });
375
+ }
376
+ const providerBalance = {
377
+ upstreamUrl: normalizeOrigin(origin),
378
+ currency: null,
379
+ unit: 'credits',
380
+ balance: remaining,
381
+ remaining,
382
+ used,
383
+ total,
384
+ requests: null,
385
+ inputTokens: null,
386
+ outputTokens: null,
387
+ planName: summary.planName || null,
388
+ details,
389
+ };
390
+ return {
391
+ authenticated: true,
392
+ planType: summary.planName || null,
393
+ primary: null,
394
+ secondary: null,
395
+ monthly: null,
396
+ rateLimitReachedType: null,
397
+ resetCredits: null,
398
+ capturedAt: new Date().toISOString(),
399
+ provider: {
400
+ id: adapterId,
401
+ displayName: adapterId === 'workbuddy' ? 'WorkBuddy' : 'CodeBuddy',
402
+ baseUrl: normalizeOrigin(origin),
403
+ capability: 'official-balance',
404
+ logoUrl: '',
405
+ },
406
+ providerBalance,
407
+ };
408
+ }
409
+ function normalizeEnterpriseUsage(value) {
410
+ const data = unwrapData(value);
411
+ if (data === null)
412
+ return null;
413
+ const total = numberValue(data.limitNum ?? data.limit_num ?? data.total);
414
+ const used = numberValue(data.credit ?? data.used ?? data.usedNum);
415
+ if (total === null && used === null)
416
+ return null;
417
+ const remaining = total !== null && used !== null ? Math.max(0, total - used) : null;
418
+ const resource = {
419
+ packageCode: 'enterprise',
420
+ packageName: '企业额度',
421
+ total,
422
+ used,
423
+ remaining,
424
+ expiresAt: timestampValue(data.cycleResetTime ?? data.cycle_reset_time),
425
+ refreshAt: timestampValue(data.cycleResetTime ?? data.cycle_reset_time),
426
+ };
427
+ return {
428
+ summary: { planCode: 'enterprise', planName: '企业版', isPaid: true, resources: [resource] },
429
+ resources: [resource],
430
+ };
431
+ }
432
+ function slicePeriodRange() {
433
+ const now = new Date();
434
+ const year = now.getFullYear();
435
+ const month = String(now.getMonth() + 1).padStart(2, '0');
436
+ const day = String(now.getDate()).padStart(2, '0');
437
+ return {
438
+ SlicePeriodStartTime: `${year}-${month}-${day} 00:00:00`,
439
+ SlicePeriodEndTime: `${year}-${month}-${day} 23:59:59`,
440
+ };
441
+ }
442
+ function unwrapData(value) {
443
+ let current = value;
444
+ for (let i = 0; i < 3 && current !== null; i += 1) {
445
+ const nested = recordValue(current.data ?? current.Data);
446
+ if (nested === null)
447
+ break;
448
+ current = nested;
449
+ }
450
+ return current;
451
+ }
452
+ function arrayValue(value) { return Array.isArray(value) ? value : []; }
453
+ function uniqueOrigins(values) {
454
+ return [...new Set(values.map(normalizeOrigin).filter((value) => value !== ''))];
455
+ }
456
+ function normalizeOrigin(value) {
457
+ try {
458
+ const url = new URL(value);
459
+ if (url.protocol !== 'http:' && url.protocol !== 'https:')
460
+ return '';
461
+ url.pathname = '';
462
+ url.search = '';
463
+ url.hash = '';
464
+ return url.toString().replace(/\/$/u, '');
465
+ }
466
+ catch {
467
+ return '';
468
+ }
469
+ }
470
+ function recordValue(value) { return typeof value === 'object' && value !== null && !Array.isArray(value) ? value : null; }
471
+ function textValue(value) { return typeof value === 'string' && value.trim() !== '' ? value.trim() : null; }
472
+ function numberValue(value) {
473
+ const number = typeof value === 'number' ? value : Number(value);
474
+ return Number.isFinite(number) ? number : null;
475
+ }
476
+ function booleanValue(value) { return typeof value === 'boolean' ? value : value === 1 || value === '1' ? true : value === 0 || value === '0' ? false : null; }
477
+ function timestampValue(value) {
478
+ if (value instanceof Date)
479
+ return value.getTime();
480
+ if (typeof value === 'number' || typeof value === 'string' && /^\d+(?:\.\d+)?$/u.test(value.trim())) {
481
+ const number = numberValue(value);
482
+ if (number === null || number <= 0)
483
+ return null;
484
+ return number < 100_000_000_000 ? Math.round(number * 1_000) : Math.round(number);
485
+ }
486
+ if (typeof value === 'string') {
487
+ const parsed = Date.parse(value);
488
+ return Number.isNaN(parsed) ? null : parsed;
489
+ }
490
+ return null;
491
+ }
492
+ function sumNumbers(values) {
493
+ const present = values.filter((value) => value !== null && Number.isFinite(value));
494
+ return present.length === 0 ? null : present.reduce((sum, value) => sum + value, 0);
495
+ }
496
+ const WORKBUDDY_IPC_PROTOCOL = 1;
497
+ const WORKBUDDY_IPC_MAX_FRAME_BYTES = 1024 * 1024;
498
+ const WORKBUDDY_IPC_HANDSHAKE_TIMEOUT_MS = 5_000;
499
+ const WORKBUDDY_IPC_CALL_TIMEOUT_MS = 12_000;
500
+ /**
501
+ * 连接 WorkBuddy daemon 的官方 WBIPC 请求通道。
502
+ *
503
+ * WorkBuddy 的认证文件只保存了桌面端可解密的字段,DSH 不能自行解密;
504
+ * 通过 wb.request/http.fetch 请求时由 daemon 注入当前登录态,避免串用 CodeBuddy token。
505
+ */
506
+ async function connectWorkBuddyRequestPipe(home) {
507
+ const discovery = readWorkBuddyIpcDiscovery(home);
508
+ if (discovery === null)
509
+ return null;
510
+ const socket = await connectWorkBuddyIpcSocket(discovery);
511
+ if (socket === null)
512
+ return null;
513
+ try {
514
+ const rpc = await handshakeWorkBuddyIpc(socket, discovery);
515
+ const pipe = await rpc.call('broker/GetPipe', { pipe: 'wb.request' });
516
+ const pipeRecord = recordValue(pipe);
517
+ const channel = textValue(pipeRecord?.channel);
518
+ if (channel === null)
519
+ throw new Error('WorkBuddy wb.request pipe unavailable');
520
+ return {
521
+ fetch: createWorkBuddyIpcFetch(rpc, channel),
522
+ close: rpc.close,
523
+ };
524
+ }
525
+ catch {
526
+ socket.destroy();
527
+ return null;
528
+ }
529
+ }
530
+ function readWorkBuddyIpcDiscovery(home) {
531
+ const configured = process.env.WORKBUDDY_CONFIG_DIR?.trim();
532
+ const configDirectory = configured || join(home, '.workbuddy');
533
+ try {
534
+ const value = recordValue(JSON.parse(readFileSync(join(configDirectory, 'wbipc/endpoint.json'), 'utf8')));
535
+ const endpoint = textValue(value?.endpoint);
536
+ const ticket = textValue(value?.ticket);
537
+ return endpoint === null || ticket === null ? null : { endpoint, ticket };
538
+ }
539
+ catch {
540
+ return null;
541
+ }
542
+ }
543
+ function connectWorkBuddyIpcSocket(discovery) {
544
+ return new Promise((resolve) => {
545
+ const endpoint = discovery.endpoint.startsWith('unix:') ? discovery.endpoint.slice('unix:'.length) : discovery.endpoint;
546
+ const socket = createConnection({ path: endpoint });
547
+ let settled = false;
548
+ const timer = setTimeout(() => finish(null), WORKBUDDY_IPC_HANDSHAKE_TIMEOUT_MS);
549
+ const finish = (result) => {
550
+ if (settled)
551
+ return;
552
+ settled = true;
553
+ clearTimeout(timer);
554
+ if (result === null)
555
+ socket.destroy();
556
+ resolve(result);
557
+ };
558
+ socket.once('connect', () => finish(socket));
559
+ socket.once('error', () => finish(null));
560
+ });
561
+ }
562
+ async function handshakeWorkBuddyIpc(socket, discovery) {
563
+ let buffer = Buffer.alloc(0);
564
+ let frameHandler = null;
565
+ const queuedFrames = [];
566
+ let failed = null;
567
+ const readFrame = () => new Promise((resolve, reject) => {
568
+ const queued = queuedFrames.shift();
569
+ if (queued !== undefined) {
570
+ resolve(queued);
571
+ return;
572
+ }
573
+ frameHandler = (frame) => {
574
+ frameHandler = null;
575
+ resolve(frame);
576
+ };
577
+ failed = reject;
578
+ });
579
+ const handleData = (chunk) => {
580
+ buffer = buffer.length === 0 ? chunk : Buffer.concat([buffer, chunk]);
581
+ for (;;) {
582
+ const newline = buffer.indexOf(0x0a);
583
+ if (newline < 0) {
584
+ if (buffer.length > WORKBUDDY_IPC_MAX_FRAME_BYTES) {
585
+ failed?.(new Error('WorkBuddy WBIPC frame exceeds limit'));
586
+ failed = null;
587
+ }
588
+ return;
589
+ }
590
+ if (newline > WORKBUDDY_IPC_MAX_FRAME_BYTES) {
591
+ failed?.(new Error('WorkBuddy WBIPC frame exceeds limit'));
592
+ failed = null;
593
+ return;
594
+ }
595
+ const line = buffer.subarray(0, newline);
596
+ buffer = buffer.subarray(newline + 1);
597
+ if (line.length === 0)
598
+ continue;
599
+ try {
600
+ const frame = recordValue(JSON.parse(line.toString('utf8')));
601
+ if (frame === null)
602
+ throw new Error('invalid WorkBuddy WBIPC frame');
603
+ if (frameHandler === null)
604
+ queuedFrames.push(frame);
605
+ else
606
+ frameHandler(frame);
607
+ }
608
+ catch (error) {
609
+ failed?.(error instanceof Error ? error : new Error(String(error)));
610
+ failed = null;
611
+ return;
612
+ }
613
+ }
614
+ };
615
+ socket.on('data', handleData);
616
+ const write = (frame) => {
617
+ const payload = `${JSON.stringify(frame)}\n`;
618
+ if (Buffer.byteLength(payload) > WORKBUDDY_IPC_MAX_FRAME_BYTES)
619
+ throw new Error('WorkBuddy WBIPC request exceeds limit');
620
+ socket.write(payload);
621
+ };
622
+ const rejectSocket = (error) => {
623
+ failed?.(error);
624
+ failed = null;
625
+ };
626
+ socket.once('error', () => rejectSocket(new Error('WorkBuddy WBIPC socket error')));
627
+ socket.once('close', () => rejectSocket(new Error('WorkBuddy WBIPC socket closed')));
628
+ const withTimeout = async (promise, message) => {
629
+ let timer;
630
+ try {
631
+ return await Promise.race([
632
+ promise,
633
+ new Promise((_, reject) => {
634
+ timer = setTimeout(() => reject(new Error(message)), WORKBUDDY_IPC_HANDSHAKE_TIMEOUT_MS);
635
+ }),
636
+ ]);
637
+ }
638
+ finally {
639
+ if (timer !== undefined)
640
+ clearTimeout(timer);
641
+ }
642
+ };
643
+ const clientNonce = randomBytes(16).toString('base64url');
644
+ const ticketId = createHash('sha256').update(discovery.ticket, 'utf8').digest('hex').slice(0, 16);
645
+ write({
646
+ type: 'session_hello',
647
+ protocol_min: WORKBUDDY_IPC_PROTOCOL,
648
+ protocol_max: WORKBUDDY_IPC_PROTOCOL,
649
+ client_nonce: clientNonce,
650
+ ticket_id: ticketId,
651
+ client: { kind: 'plugin', id: 'codingns-subscription' },
652
+ });
653
+ const challenge = await withTimeout(readFrame(), 'WorkBuddy WBIPC handshake timeout');
654
+ if (challenge.type === 'session_hello_error')
655
+ throw new Error(`WorkBuddy WBIPC handshake rejected: ${String(challenge.code ?? '?')}`);
656
+ if (challenge.type !== 'session_challenge')
657
+ throw new Error('unexpected WorkBuddy WBIPC handshake frame');
658
+ const serverNonce = textValue(challenge.server_nonce);
659
+ if (serverNonce === null)
660
+ throw new Error('WorkBuddy WBIPC server nonce missing');
661
+ const transcript = { protocol: WORKBUDDY_IPC_PROTOCOL, endpoint: discovery.endpoint, clientNonce, serverNonce };
662
+ const proof = (role) => createHmac('sha256', Buffer.from(discovery.ticket, 'utf8'))
663
+ .update(encodeWorkBuddyTranscript(role, transcript)).digest('base64url');
664
+ const serverProof = textValue(challenge.server_proof);
665
+ if (serverProof === null || !safeWorkBuddyEqual(proof('server'), serverProof))
666
+ throw new Error('WorkBuddy WBIPC endpoint proof failed');
667
+ write({ type: 'session_prove', client_proof: proof('client') });
668
+ const ack = await withTimeout(readFrame(), 'WorkBuddy WBIPC handshake acknowledgement timeout');
669
+ if (ack.type !== 'session_hello_ack')
670
+ throw new Error(`WorkBuddy WBIPC handshake rejected: ${String(ack.code ?? '?')}`);
671
+ const pending = new Map();
672
+ let nextId = 1;
673
+ const onRpcFrame = (frame) => {
674
+ const id = numberValue(frame.id);
675
+ if (id === null)
676
+ return;
677
+ const entry = pending.get(id);
678
+ if (entry === undefined)
679
+ return;
680
+ pending.delete(id);
681
+ clearTimeout(entry.timer);
682
+ const error = recordValue(frame.error);
683
+ if (error !== null) {
684
+ entry.reject(new Error(String(error.message ?? 'WorkBuddy WBIPC request failed')));
685
+ return;
686
+ }
687
+ entry.resolve(frame.result);
688
+ };
689
+ frameHandler = onRpcFrame;
690
+ while (queuedFrames.length > 0) {
691
+ const frame = queuedFrames.shift();
692
+ if (frame !== undefined)
693
+ onRpcFrame(frame);
694
+ }
695
+ const close = () => {
696
+ for (const entry of pending.values()) {
697
+ clearTimeout(entry.timer);
698
+ entry.reject(new Error('WorkBuddy WBIPC connection closed'));
699
+ }
700
+ pending.clear();
701
+ socket.destroy();
702
+ };
703
+ return {
704
+ call(method, params) {
705
+ const id = nextId++;
706
+ return new Promise((resolve, reject) => {
707
+ const timer = setTimeout(() => {
708
+ if (!pending.delete(id))
709
+ return;
710
+ reject(new Error(`WorkBuddy WBIPC call timeout: ${method}`));
711
+ }, WORKBUDDY_IPC_CALL_TIMEOUT_MS);
712
+ pending.set(id, { resolve, reject, timer });
713
+ try {
714
+ write({ jsonrpc: '2.0', id, method, params, mode: 'call' });
715
+ }
716
+ catch (error) {
717
+ clearTimeout(timer);
718
+ pending.delete(id);
719
+ reject(error);
720
+ }
721
+ });
722
+ },
723
+ close,
724
+ };
725
+ }
726
+ function encodeWorkBuddyTranscript(role, transcript) {
727
+ const parts = [role === 'server' ? 'wbipc-s' : 'wbipc-c', String(transcript.protocol), transcript.endpoint, transcript.clientNonce, transcript.serverNonce];
728
+ return Buffer.concat(parts.map((part) => {
729
+ const value = Buffer.from(part, 'utf8');
730
+ const length = Buffer.alloc(4);
731
+ length.writeUInt32BE(value.length, 0);
732
+ return Buffer.concat([length, value]);
733
+ }));
734
+ }
735
+ function safeWorkBuddyEqual(left, right) {
736
+ const a = Buffer.from(left, 'utf8');
737
+ const b = Buffer.from(right, 'utf8');
738
+ return a.length > 0 && a.length === b.length && timingSafeEqual(a, b);
739
+ }
740
+ function createWorkBuddyIpcFetch(rpc, channel) {
741
+ return async (input, init) => {
742
+ const url = typeof input === 'string' || input instanceof URL ? new URL(String(input)) : new URL(input.url);
743
+ const sourceHeaders = new Headers(init?.headers);
744
+ // WorkBuddy daemon 只允许这两个业务头,其余身份、Origin、追踪头由宿主裁决。
745
+ const headers = new Headers();
746
+ for (const name of ['accept', 'content-type']) {
747
+ const value = sourceHeaders.get(name);
748
+ if (value !== null)
749
+ headers.set(name, value);
750
+ }
751
+ const body = init?.body === undefined || init.body === null
752
+ ? undefined
753
+ : Buffer.from(await new Response(init.body).arrayBuffer()).toString('base64');
754
+ const result = recordValue(await rpc.call(`${channel}/http.fetch`, {
755
+ method: (init?.method ?? 'GET').toUpperCase(),
756
+ path: `${url.pathname}${url.search}`,
757
+ headers: Object.fromEntries(headers.entries()),
758
+ ...(body === undefined ? {} : { body_b64: body }),
759
+ }));
760
+ const status = numberValue(result?.status);
761
+ const responseHeaders = recordValue(result?.headers);
762
+ const normalizedHeaders = {};
763
+ if (responseHeaders !== null) {
764
+ for (const [key, value] of Object.entries(responseHeaders)) {
765
+ const text = textValue(value);
766
+ if (text !== null)
767
+ normalizedHeaders[key] = text;
768
+ }
769
+ }
770
+ const bodyValue = typeof result?.body_b64 === 'string' ? Buffer.from(result.body_b64, 'base64') : Buffer.alloc(0);
771
+ return new Response(bodyValue, {
772
+ status: status !== null && status >= 200 && status <= 599 ? status : 500,
773
+ headers: normalizedHeaders,
774
+ });
775
+ };
776
+ }
777
+ export { DEFAULT_ORIGINS as CODEBUDDY_BILLING_ORIGINS };
778
+ //# sourceMappingURL=codebuddy-subscription.js.map