@downcity/city 1.1.39 → 1.1.47

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 (353) hide show
  1. package/README.md +4 -9
  2. package/bin/cli/Index.js +2 -0
  3. package/bin/cli/Index.js.map +1 -1
  4. package/bin/cli/agent/AgentChat.d.ts +2 -1
  5. package/bin/cli/agent/AgentChat.d.ts.map +1 -1
  6. package/bin/cli/agent/AgentChat.js +93 -214
  7. package/bin/cli/agent/AgentChat.js.map +1 -1
  8. package/bin/cli/agent/AgentChatTypes.d.ts +8 -12
  9. package/bin/cli/agent/AgentChatTypes.d.ts.map +1 -1
  10. package/bin/cli/agent/AgentHistory.js +2 -2
  11. package/bin/cli/agent/AgentHistory.js.map +1 -1
  12. package/bin/cli/agent/AgentManager.d.ts.map +1 -1
  13. package/bin/cli/agent/AgentManager.js +26 -27
  14. package/bin/cli/agent/AgentManager.js.map +1 -1
  15. package/bin/cli/agent/AgentManagerTypes.d.ts +2 -2
  16. package/bin/cli/agent/AgentManagerTypes.d.ts.map +1 -1
  17. package/bin/cli/agent/AgentReset.js +4 -4
  18. package/bin/cli/agent/AgentReset.js.map +1 -1
  19. package/bin/cli/agent/AgentSelection.js +6 -6
  20. package/bin/cli/agent/AgentSelection.js.map +1 -1
  21. package/bin/cli/agent/AgentSelectionTypes.d.ts +1 -1
  22. package/bin/cli/agent/AgentSelectionTypes.d.ts.map +1 -1
  23. package/bin/cli/agent/Init.js +10 -10
  24. package/bin/cli/agent/Init.js.map +1 -1
  25. package/bin/cli/agent/Restart.js +2 -2
  26. package/bin/cli/agent/Restart.js.map +1 -1
  27. package/bin/cli/agent/Run.d.ts +1 -1
  28. package/bin/cli/agent/Run.d.ts.map +1 -1
  29. package/bin/cli/agent/Run.js +37 -17
  30. package/bin/cli/agent/Run.js.map +1 -1
  31. package/bin/cli/agent/Start.js +2 -2
  32. package/bin/cli/agent/Start.js.map +1 -1
  33. package/bin/cli/agent/Stop.js +2 -2
  34. package/bin/cli/agent/Stop.js.map +1 -1
  35. package/bin/cli/control-plane/ControlPlaneProcess.js +5 -5
  36. package/bin/cli/control-plane/ControlPlaneProcess.js.map +1 -1
  37. package/bin/cli/model/ModelCreateCommand.js +1 -1
  38. package/bin/cli/model/ModelCreateCommand.js.map +1 -1
  39. package/bin/cli/model/ModelManageCommand.d.ts.map +1 -1
  40. package/bin/cli/model/ModelManageCommand.js +5 -3
  41. package/bin/cli/model/ModelManageCommand.js.map +1 -1
  42. package/bin/cli/model/ModelManager.js +3 -3
  43. package/bin/cli/model/ModelManager.js.map +1 -1
  44. package/bin/cli/model/ModelSupport.d.ts +0 -1
  45. package/bin/cli/model/ModelSupport.d.ts.map +1 -1
  46. package/bin/cli/model/ModelSupport.js +2 -11
  47. package/bin/cli/model/ModelSupport.js.map +1 -1
  48. package/bin/cli/shared/CliReporterTypes.d.ts +1 -1
  49. package/bin/cli/shared/Config.js +2 -2
  50. package/bin/cli/shared/Config.js.map +1 -1
  51. package/bin/cli/shared/Env.d.ts +1 -1
  52. package/bin/cli/shared/Env.d.ts.map +1 -1
  53. package/bin/cli/shared/Env.js +18 -149
  54. package/bin/cli/shared/Env.js.map +1 -1
  55. package/bin/cli/shared/IndexAgentCommand.d.ts.map +1 -1
  56. package/bin/cli/shared/IndexAgentCommand.js +3 -3
  57. package/bin/cli/shared/IndexAgentCommand.js.map +1 -1
  58. package/bin/cli/shared/IndexSupport.d.ts +3 -3
  59. package/bin/cli/shared/IndexSupport.d.ts.map +1 -1
  60. package/bin/cli/shared/IndexSupport.js +14 -8
  61. package/bin/cli/shared/IndexSupport.js.map +1 -1
  62. package/bin/cli/shared/ManagedPluginActionCommands.d.ts.map +1 -1
  63. package/bin/cli/shared/ManagedPluginActionCommands.js +5 -4
  64. package/bin/cli/shared/ManagedPluginActionCommands.js.map +1 -1
  65. package/bin/cli/shared/ManagedPluginRemote.d.ts.map +1 -1
  66. package/bin/cli/shared/ManagedPluginRemote.js +4 -4
  67. package/bin/cli/shared/ManagedPluginRemote.js.map +1 -1
  68. package/bin/cli/shared/PluginTargetSupport.d.ts +2 -2
  69. package/bin/cli/shared/PluginTargetSupport.d.ts.map +1 -1
  70. package/bin/cli/shared/PluginTargetSupport.js +19 -19
  71. package/bin/cli/shared/PluginTargetSupport.js.map +1 -1
  72. package/bin/cli/shared/Plugins.js +10 -10
  73. package/bin/cli/shared/Plugins.js.map +1 -1
  74. package/bin/cli/shared/PublicHostEnv.d.ts +1 -1
  75. package/bin/cli/shared/PublicHostEnv.js +2 -2
  76. package/bin/cli/shared/PublicHostEnv.js.map +1 -1
  77. package/bin/cli/shared/Terminal.d.ts +13 -0
  78. package/bin/cli/shared/Terminal.d.ts.map +1 -0
  79. package/bin/cli/shared/Terminal.js +22 -0
  80. package/bin/cli/shared/Terminal.js.map +1 -0
  81. package/bin/config/DowncitySchema.d.ts.map +1 -1
  82. package/bin/config/DowncitySchema.js +3 -111
  83. package/bin/config/DowncitySchema.js.map +1 -1
  84. package/bin/config/Paths.d.ts +0 -56
  85. package/bin/config/Paths.d.ts.map +1 -1
  86. package/bin/config/Paths.js +9 -51
  87. package/bin/config/Paths.js.map +1 -1
  88. package/bin/control/ControlGateway.js +1 -1
  89. package/bin/control/ControlGateway.js.map +1 -1
  90. package/bin/control/EnvApiRoutes.d.ts +1 -1
  91. package/bin/control/EnvApiRoutes.d.ts.map +1 -1
  92. package/bin/control/EnvApiRoutes.js +7 -79
  93. package/bin/control/EnvApiRoutes.js.map +1 -1
  94. package/bin/control/PlatformApiRoutes.d.ts +2 -2
  95. package/bin/control/PlatformApiRoutes.d.ts.map +1 -1
  96. package/bin/control/PlatformApiRoutes.js +2 -2
  97. package/bin/control/PlatformApiRoutes.js.map +1 -1
  98. package/bin/control/gateway/AgentActions.d.ts +2 -2
  99. package/bin/control/gateway/AgentActions.d.ts.map +1 -1
  100. package/bin/control/gateway/AgentActions.js +7 -7
  101. package/bin/control/gateway/AgentActions.js.map +1 -1
  102. package/bin/control/gateway/AgentCatalog.d.ts +3 -6
  103. package/bin/control/gateway/AgentCatalog.d.ts.map +1 -1
  104. package/bin/control/gateway/AgentCatalog.js +16 -18
  105. package/bin/control/gateway/AgentCatalog.js.map +1 -1
  106. package/bin/control/instant/InstantSessionRunner.d.ts.map +1 -1
  107. package/bin/control/instant/InstantSessionRunner.js +3 -1
  108. package/bin/control/instant/InstantSessionRunner.js.map +1 -1
  109. package/bin/env/ProcessEnv.d.ts +24 -0
  110. package/bin/env/ProcessEnv.d.ts.map +1 -0
  111. package/bin/env/ProcessEnv.js +41 -0
  112. package/bin/env/ProcessEnv.js.map +1 -0
  113. package/bin/http/auth/AuthEnv.d.ts +1 -1
  114. package/bin/http/auth/AuthEnv.js +1 -1
  115. package/bin/model/runtime/CreateRuntimeModel.d.ts +8 -0
  116. package/bin/model/runtime/CreateRuntimeModel.d.ts.map +1 -1
  117. package/bin/model/runtime/CreateRuntimeModel.js +43 -37
  118. package/bin/model/runtime/CreateRuntimeModel.js.map +1 -1
  119. package/bin/model/service/ModelPoolService.d.ts +1 -1
  120. package/bin/model/service/ModelPoolService.d.ts.map +1 -1
  121. package/bin/model/service/ModelPoolService.js +8 -6
  122. package/bin/model/service/ModelPoolService.js.map +1 -1
  123. package/bin/platform/store/StoreEnvRepository.d.ts +5 -49
  124. package/bin/platform/store/StoreEnvRepository.d.ts.map +1 -1
  125. package/bin/platform/store/StoreEnvRepository.js +31 -178
  126. package/bin/platform/store/StoreEnvRepository.js.map +1 -1
  127. package/bin/platform/store/StoreSchema.js +3 -44
  128. package/bin/platform/store/StoreSchema.js.map +1 -1
  129. package/bin/platform/store/index.d.ts +9 -45
  130. package/bin/platform/store/index.d.ts.map +1 -1
  131. package/bin/platform/store/index.js +12 -62
  132. package/bin/platform/store/index.js.map +1 -1
  133. package/bin/platform/store/schema.d.ts +2 -2
  134. package/bin/platform/store/schema.js +2 -2
  135. package/bin/process/daemon/Api.d.ts +1 -1
  136. package/bin/process/daemon/CliArgs.d.ts +1 -0
  137. package/bin/process/daemon/CliArgs.d.ts.map +1 -1
  138. package/bin/process/daemon/CliArgs.js +20 -1
  139. package/bin/process/daemon/CliArgs.js.map +1 -1
  140. package/bin/process/daemon/Client.d.ts +18 -2
  141. package/bin/process/daemon/Client.d.ts.map +1 -1
  142. package/bin/process/daemon/Client.js +70 -20
  143. package/bin/process/daemon/Client.js.map +1 -1
  144. package/bin/process/daemon/Manager.d.ts.map +1 -1
  145. package/bin/process/daemon/Manager.js +2 -1
  146. package/bin/process/daemon/Manager.js.map +1 -1
  147. package/bin/terminal/admin/auth-error.d.ts +34 -0
  148. package/bin/terminal/admin/auth-error.d.ts.map +1 -0
  149. package/bin/terminal/admin/auth-error.js +51 -0
  150. package/bin/terminal/admin/auth-error.js.map +1 -0
  151. package/bin/terminal/admin/commands/accounts.d.ts +6 -0
  152. package/bin/terminal/admin/commands/accounts.d.ts.map +1 -0
  153. package/bin/terminal/admin/commands/accounts.js +44 -0
  154. package/bin/terminal/admin/commands/accounts.js.map +1 -0
  155. package/bin/terminal/admin/commands/balance.d.ts +6 -0
  156. package/bin/terminal/admin/commands/balance.d.ts.map +1 -0
  157. package/bin/terminal/admin/commands/balance.js +153 -0
  158. package/bin/terminal/admin/commands/balance.js.map +1 -0
  159. package/bin/terminal/admin/commands/config.d.ts +10 -0
  160. package/bin/terminal/admin/commands/config.d.ts.map +1 -0
  161. package/bin/terminal/admin/commands/config.js +11 -0
  162. package/bin/terminal/admin/commands/config.js.map +1 -0
  163. package/bin/terminal/admin/commands/custom.d.ts +6 -0
  164. package/bin/terminal/admin/commands/custom.d.ts.map +1 -0
  165. package/bin/terminal/admin/commands/custom.js +47 -0
  166. package/bin/terminal/admin/commands/custom.js.map +1 -0
  167. package/bin/terminal/admin/commands/instruction.d.ts +9 -0
  168. package/bin/terminal/admin/commands/instruction.d.ts.map +1 -0
  169. package/bin/terminal/admin/commands/instruction.js +10 -0
  170. package/bin/terminal/admin/commands/instruction.js.map +1 -0
  171. package/bin/terminal/admin/commands/models.d.ts +14 -0
  172. package/bin/terminal/admin/commands/models.d.ts.map +1 -0
  173. package/bin/terminal/admin/commands/models.js +61 -0
  174. package/bin/terminal/admin/commands/models.js.map +1 -0
  175. package/bin/terminal/admin/commands/payment.d.ts +6 -0
  176. package/bin/terminal/admin/commands/payment.d.ts.map +1 -0
  177. package/bin/terminal/admin/commands/payment.js +59 -0
  178. package/bin/terminal/admin/commands/payment.js.map +1 -0
  179. package/bin/terminal/admin/commands/products.d.ts +6 -0
  180. package/bin/terminal/admin/commands/products.d.ts.map +1 -0
  181. package/bin/terminal/admin/commands/products.js +80 -0
  182. package/bin/terminal/admin/commands/products.js.map +1 -0
  183. package/bin/terminal/admin/commands/service-env.d.ts +11 -0
  184. package/bin/terminal/admin/commands/service-env.d.ts.map +1 -0
  185. package/bin/terminal/admin/commands/service-env.js +248 -0
  186. package/bin/terminal/admin/commands/service-env.js.map +1 -0
  187. package/bin/terminal/admin/commands/usage.d.ts +6 -0
  188. package/bin/terminal/admin/commands/usage.d.ts.map +1 -0
  189. package/bin/terminal/admin/commands/usage.js +44 -0
  190. package/bin/terminal/admin/commands/usage.js.map +1 -0
  191. package/bin/terminal/admin/loop.d.ts +6 -0
  192. package/bin/terminal/admin/loop.d.ts.map +1 -0
  193. package/bin/terminal/admin/loop.js +70 -0
  194. package/bin/terminal/admin/loop.js.map +1 -0
  195. package/bin/terminal/agent/pi-agent.d.ts +15 -0
  196. package/bin/terminal/agent/pi-agent.d.ts.map +1 -0
  197. package/bin/terminal/agent/pi-agent.js +136 -0
  198. package/bin/terminal/agent/pi-agent.js.map +1 -0
  199. package/bin/terminal/app.d.ts +13 -0
  200. package/bin/terminal/app.d.ts.map +1 -0
  201. package/bin/terminal/app.js +123 -0
  202. package/bin/terminal/app.js.map +1 -0
  203. package/bin/terminal/auth/admin.d.ts +8 -0
  204. package/bin/terminal/auth/admin.d.ts.map +1 -0
  205. package/bin/terminal/auth/admin.js +18 -0
  206. package/bin/terminal/auth/admin.js.map +1 -0
  207. package/bin/terminal/auth/mode-select.d.ts +11 -0
  208. package/bin/terminal/auth/mode-select.d.ts.map +1 -0
  209. package/bin/terminal/auth/mode-select.js +33 -0
  210. package/bin/terminal/auth/mode-select.js.map +1 -0
  211. package/bin/terminal/auth/server-switch.d.ts +22 -0
  212. package/bin/terminal/auth/server-switch.d.ts.map +1 -0
  213. package/bin/terminal/auth/server-switch.js +241 -0
  214. package/bin/terminal/auth/server-switch.js.map +1 -0
  215. package/bin/terminal/auth/user.d.ts +19 -0
  216. package/bin/terminal/auth/user.d.ts.map +1 -0
  217. package/bin/terminal/auth/user.js +261 -0
  218. package/bin/terminal/auth/user.js.map +1 -0
  219. package/bin/terminal/core/browser.d.ts +12 -0
  220. package/bin/terminal/core/browser.d.ts.map +1 -0
  221. package/bin/terminal/core/browser.js +29 -0
  222. package/bin/terminal/core/browser.js.map +1 -0
  223. package/bin/terminal/core/env.d.ts +15 -0
  224. package/bin/terminal/core/env.d.ts.map +1 -0
  225. package/bin/terminal/core/env.js +67 -0
  226. package/bin/terminal/core/env.js.map +1 -0
  227. package/bin/terminal/core/session.d.ts +97 -0
  228. package/bin/terminal/core/session.d.ts.map +1 -0
  229. package/bin/terminal/core/session.js +342 -0
  230. package/bin/terminal/core/session.js.map +1 -0
  231. package/bin/terminal/core/stripe.d.ts +26 -0
  232. package/bin/terminal/core/stripe.d.ts.map +1 -0
  233. package/bin/terminal/core/stripe.js +22 -0
  234. package/bin/terminal/core/stripe.js.map +1 -0
  235. package/bin/terminal/core/ui.d.ts +29 -0
  236. package/bin/terminal/core/ui.d.ts.map +1 -0
  237. package/bin/terminal/core/ui.js +60 -0
  238. package/bin/terminal/core/ui.js.map +1 -0
  239. package/bin/terminal/core/update.d.ts +20 -0
  240. package/bin/terminal/core/update.d.ts.map +1 -0
  241. package/bin/terminal/core/update.js +193 -0
  242. package/bin/terminal/core/update.js.map +1 -0
  243. package/bin/terminal/user/balance.d.ts +31 -0
  244. package/bin/terminal/user/balance.d.ts.map +1 -0
  245. package/bin/terminal/user/balance.js +131 -0
  246. package/bin/terminal/user/balance.js.map +1 -0
  247. package/bin/terminal/user/chat.d.ts +12 -0
  248. package/bin/terminal/user/chat.d.ts.map +1 -0
  249. package/bin/terminal/user/chat.js +70 -0
  250. package/bin/terminal/user/chat.js.map +1 -0
  251. package/bin/terminal/user/loop.d.ts +13 -0
  252. package/bin/terminal/user/loop.d.ts.map +1 -0
  253. package/bin/terminal/user/loop.js +93 -0
  254. package/bin/terminal/user/loop.js.map +1 -0
  255. package/bin/terminal/user/models.d.ts +10 -0
  256. package/bin/terminal/user/models.d.ts.map +1 -0
  257. package/bin/terminal/user/models.js +39 -0
  258. package/bin/terminal/user/models.js.map +1 -0
  259. package/bin/utils/storage.d.ts +0 -1
  260. package/bin/utils/storage.d.ts.map +1 -1
  261. package/bin/utils/storage.js +0 -6
  262. package/bin/utils/storage.js.map +1 -1
  263. package/package.json +7 -3
  264. package/public/app.js +3 -3
  265. package/src/cli/Index.ts +2 -0
  266. package/src/cli/agent/AgentChat.ts +113 -289
  267. package/src/cli/agent/AgentChatTypes.ts +8 -12
  268. package/src/cli/agent/AgentHistory.ts +2 -2
  269. package/src/cli/agent/AgentManager.ts +27 -28
  270. package/src/cli/agent/AgentManagerTypes.ts +2 -2
  271. package/src/cli/agent/AgentReset.ts +4 -4
  272. package/src/cli/agent/AgentSelection.ts +6 -6
  273. package/src/cli/agent/AgentSelectionTypes.ts +1 -1
  274. package/src/cli/agent/Init.ts +13 -13
  275. package/src/cli/agent/Restart.ts +2 -2
  276. package/src/cli/agent/Run.ts +38 -17
  277. package/src/cli/agent/Start.ts +2 -2
  278. package/src/cli/agent/Stop.ts +2 -2
  279. package/src/cli/control-plane/ControlPlaneProcess.ts +5 -5
  280. package/src/cli/model/ModelCreateCommand.ts +1 -1
  281. package/src/cli/model/ModelManageCommand.ts +5 -3
  282. package/src/cli/model/ModelManager.ts +3 -3
  283. package/src/cli/model/ModelSupport.ts +2 -10
  284. package/src/cli/shared/CliReporterTypes.ts +1 -1
  285. package/src/cli/shared/Config.ts +2 -2
  286. package/src/cli/shared/Env.ts +22 -230
  287. package/src/cli/shared/IndexAgentCommand.ts +3 -4
  288. package/src/cli/shared/IndexSupport.ts +16 -10
  289. package/src/cli/shared/ManagedPluginActionCommands.ts +4 -4
  290. package/src/cli/shared/ManagedPluginRemote.ts +4 -4
  291. package/src/cli/shared/PluginTargetSupport.ts +19 -19
  292. package/src/cli/shared/Plugins.ts +10 -10
  293. package/src/cli/shared/PublicHostEnv.ts +2 -2
  294. package/src/cli/shared/Terminal.ts +24 -0
  295. package/src/config/DowncitySchema.ts +3 -113
  296. package/src/config/Paths.ts +9 -90
  297. package/src/control/ControlGateway.ts +3 -3
  298. package/src/control/EnvApiRoutes.ts +7 -91
  299. package/src/control/PlatformApiRoutes.ts +6 -6
  300. package/src/control/gateway/AgentActions.ts +10 -10
  301. package/src/control/gateway/AgentCatalog.ts +17 -21
  302. package/src/control/instant/InstantSessionRunner.ts +3 -1
  303. package/src/env/ProcessEnv.ts +43 -0
  304. package/src/http/auth/AuthEnv.ts +1 -1
  305. package/src/model/runtime/CreateRuntimeModel.ts +54 -37
  306. package/src/model/service/ModelPoolService.ts +13 -11
  307. package/src/platform/store/StoreEnvRepository.ts +31 -234
  308. package/src/platform/store/StoreSchema.ts +3 -49
  309. package/src/platform/store/index.ts +11 -80
  310. package/src/platform/store/schema.ts +2 -2
  311. package/src/process/daemon/Api.ts +1 -1
  312. package/src/process/daemon/CliArgs.ts +24 -1
  313. package/src/process/daemon/Client.ts +90 -22
  314. package/src/process/daemon/Manager.ts +2 -1
  315. package/src/terminal/admin/auth-error.ts +62 -0
  316. package/src/terminal/admin/commands/accounts.ts +44 -0
  317. package/src/terminal/admin/commands/balance.ts +160 -0
  318. package/src/terminal/admin/commands/config.ts +13 -0
  319. package/src/terminal/admin/commands/custom.ts +46 -0
  320. package/src/terminal/admin/commands/instruction.ts +12 -0
  321. package/src/terminal/admin/commands/models.ts +64 -0
  322. package/src/terminal/admin/commands/payment.ts +94 -0
  323. package/src/terminal/admin/commands/products.ts +72 -0
  324. package/src/terminal/admin/commands/service-env.ts +256 -0
  325. package/src/terminal/admin/commands/usage.ts +44 -0
  326. package/src/terminal/admin/loop.ts +69 -0
  327. package/src/terminal/agent/pi-agent.ts +180 -0
  328. package/src/terminal/app.ts +120 -0
  329. package/src/terminal/auth/admin.ts +21 -0
  330. package/src/terminal/auth/mode-select.ts +38 -0
  331. package/src/terminal/auth/server-switch.ts +275 -0
  332. package/src/terminal/auth/user.ts +351 -0
  333. package/src/terminal/core/browser.ts +31 -0
  334. package/src/terminal/core/env.ts +71 -0
  335. package/src/terminal/core/session.ts +450 -0
  336. package/src/terminal/core/stripe.ts +37 -0
  337. package/src/terminal/core/ui.ts +84 -0
  338. package/src/terminal/core/update.ts +230 -0
  339. package/src/terminal/user/balance.ts +215 -0
  340. package/src/terminal/user/chat.ts +80 -0
  341. package/src/terminal/user/loop.ts +112 -0
  342. package/src/terminal/user/models.ts +43 -0
  343. package/src/utils/storage.ts +0 -7
  344. package/bin/process/rpc/Client.d.ts +0 -13
  345. package/bin/process/rpc/Client.d.ts.map +0 -1
  346. package/bin/process/rpc/Client.js +0 -98
  347. package/bin/process/rpc/Client.js.map +0 -1
  348. package/bin/process/rpc/Paths.d.ts +0 -14
  349. package/bin/process/rpc/Paths.d.ts.map +0 -1
  350. package/bin/process/rpc/Paths.js +0 -36
  351. package/bin/process/rpc/Paths.js.map +0 -1
  352. package/src/process/rpc/Client.ts +0 -113
  353. package/src/process/rpc/Paths.ts +0 -43
@@ -0,0 +1,450 @@
1
+ /**
2
+ * Session 与 server 配置持久化模块。
3
+ *
4
+ * 关键说明(中文)
5
+ * - server 是一等资源,必须显式配置后 CLI 才进入身份菜单
6
+ * - 不再注入默认 server;没有 server 时必须先添加
7
+ * - user session 仍然按 base_url 隔离保存
8
+ * - admin_secret_key 直接属于 server 配置,不再作为独立 session 维护
9
+ */
10
+
11
+ import fs from "node:fs";
12
+ import os from "node:os";
13
+ import path from "node:path";
14
+ import crypto from "node:crypto";
15
+ import { normalizeBaseUrl } from "./env.js";
16
+
17
+ const DIR = path.join(os.homedir(), ".downcity");
18
+ const CONFIG_FILE = path.join(DIR, "config.json");
19
+ const LEGACY_CONFIG_FILE = path.join(DIR, "product-client-config.json");
20
+ const LEGACY_USER_FILE = path.join(DIR, "product-client-user.json");
21
+ const LEGACY_ADMIN_FILE = path.join(DIR, "product-client-admin.json");
22
+
23
+ // ============================================================
24
+ // 类型
25
+ // ============================================================
26
+
27
+ export interface AdminSession {
28
+ /** 当前 server 的 server URL */
29
+ base_url: string;
30
+ /** 当前 server 的 admin secret key */
31
+ admin_token: string;
32
+ }
33
+
34
+ export interface UserSession {
35
+ /** 当前登录目标的 server server URL */
36
+ base_url: string;
37
+ /** 用户邮箱 */
38
+ email: string;
39
+ /** 用户 ID */
40
+ user_id: string;
41
+ /** 当前 product ID */
42
+ product_id: string;
43
+ /** user token */
44
+ user_token: string;
45
+ }
46
+
47
+ export interface ServerProfile {
48
+ /** 展示名称 */
49
+ name: string;
50
+ /** InfraRuntime 服务地址 */
51
+ base_url: string;
52
+ /** 该 server 对应的 admin secret key */
53
+ admin_secret_key: string;
54
+ }
55
+
56
+ export interface ClientConfig {
57
+ /** 当前激活的 server URL */
58
+ active_server_url?: string;
59
+ /** 已保存的 server 列表 */
60
+ servers: ServerProfile[];
61
+ /** 当前选择的模型 ID */
62
+ model: string;
63
+ /** 上次使用的身份 */
64
+ last_identity?: "admin" | "user";
65
+ }
66
+
67
+ // ============================================================
68
+ // Config 读写
69
+ // ============================================================
70
+
71
+ /**
72
+ * 从磁盘读取 config,并把旧结构迁移到新的 server 模型。
73
+ */
74
+ export function readConfig(): ClientConfig {
75
+ const raw = readJSON<Record<string, unknown>>(CONFIG_FILE)
76
+ ?? readJSON<Record<string, unknown>>(LEGACY_CONFIG_FILE)
77
+ ?? {};
78
+ const servers = readServersFromConfig(raw);
79
+ const active_server_url = readActiveServerURL(raw, servers);
80
+
81
+ return {
82
+ active_server_url,
83
+ servers,
84
+ model: typeof raw.model === "string" ? raw.model : "",
85
+ last_identity: raw.last_identity === "admin" || raw.last_identity === "user"
86
+ ? raw.last_identity
87
+ : undefined,
88
+ };
89
+ }
90
+
91
+ /**
92
+ * 写入 config 到磁盘。
93
+ */
94
+ export function writeConfig(config: ClientConfig): void {
95
+ const normalizedServers = normalizeServers(config.servers);
96
+ const active = normalizedServers.find((server) => server.base_url === config.active_server_url)
97
+ ? config.active_server_url
98
+ : normalizedServers[0]?.base_url;
99
+
100
+ writeJSON(CONFIG_FILE, {
101
+ active_server_url: active,
102
+ servers: normalizedServers,
103
+ model: config.model ?? "",
104
+ last_identity: config.last_identity,
105
+ });
106
+ }
107
+
108
+ // ============================================================
109
+ // Server 管理
110
+ // ============================================================
111
+
112
+ /**
113
+ * 读取当前激活的 server。
114
+ */
115
+ export function readActiveServer(): ServerProfile | undefined {
116
+ const config = readConfig();
117
+ return config.servers.find((server) => server.base_url === config.active_server_url);
118
+ }
119
+
120
+ /**
121
+ * 设置当前激活的 server。
122
+ */
123
+ export function setActiveServer(baseUrl: string): void {
124
+ const config = readConfig();
125
+ const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
126
+ if (!config.servers.find((server) => server.base_url === normalizedBaseUrl)) {
127
+ throw new Error(`Unknown server: ${normalizedBaseUrl}`);
128
+ }
129
+ writeConfig({
130
+ ...config,
131
+ active_server_url: normalizedBaseUrl,
132
+ });
133
+ }
134
+
135
+ /**
136
+ * 添加 server,并设为当前激活 server。
137
+ */
138
+ export function addServer(input: {
139
+ base_url: string;
140
+ admin_secret_key: string;
141
+ name?: string;
142
+ }): ServerProfile {
143
+ const config = readConfig();
144
+ const normalized = normalizeServer(input);
145
+ const existingIndex = config.servers.findIndex((server) => server.base_url === normalized.base_url);
146
+
147
+ if (existingIndex >= 0) {
148
+ config.servers[existingIndex] = normalized;
149
+ } else {
150
+ config.servers.push(normalized);
151
+ }
152
+
153
+ writeConfig({
154
+ ...config,
155
+ servers: config.servers,
156
+ active_server_url: normalized.base_url,
157
+ });
158
+
159
+ return normalized;
160
+ }
161
+
162
+ /**
163
+ * 更新已存在的 server。
164
+ *
165
+ * 关键说明(中文)
166
+ * - 如果 base_url 变化,会清除旧 URL 下的 user session
167
+ * - active server 会自动切换到新 URL
168
+ */
169
+ export function updateServer(
170
+ currentBaseUrl: string,
171
+ input: {
172
+ base_url: string;
173
+ admin_secret_key: string;
174
+ name?: string;
175
+ },
176
+ ): ServerProfile {
177
+ const config = readConfig();
178
+ const normalizedCurrent = normalizeBaseUrl(currentBaseUrl);
179
+ const index = config.servers.findIndex((server) => server.base_url === normalizedCurrent);
180
+ if (index < 0) {
181
+ throw new Error(`Unknown server: ${normalizedCurrent}`);
182
+ }
183
+
184
+ const normalizedNext = normalizeServer(input);
185
+ const duplicateIndex = config.servers.findIndex((server) => server.base_url === normalizedNext.base_url);
186
+ if (duplicateIndex >= 0 && duplicateIndex !== index) {
187
+ throw new Error(`Server already exists: ${normalizedNext.base_url}`);
188
+ }
189
+
190
+ config.servers[index] = normalizedNext;
191
+ const activeServerUrl = config.active_server_url === normalizedCurrent
192
+ ? normalizedNext.base_url
193
+ : config.active_server_url;
194
+
195
+ writeConfig({
196
+ ...config,
197
+ servers: config.servers,
198
+ active_server_url: activeServerUrl,
199
+ });
200
+
201
+ if (normalizedCurrent !== normalizedNext.base_url) {
202
+ clearServerSessions(normalizedCurrent);
203
+ }
204
+
205
+ return normalizedNext;
206
+ }
207
+
208
+ /**
209
+ * 删除 server,同时清除该 URL 下的所有 session。
210
+ */
211
+ export function removeServer(baseUrl: string): void {
212
+ const config = readConfig();
213
+ const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
214
+ const nextServers = config.servers.filter((server) => server.base_url !== normalizedBaseUrl);
215
+ const nextActive = config.active_server_url === normalizedBaseUrl
216
+ ? nextServers[0]?.base_url
217
+ : config.active_server_url;
218
+
219
+ writeConfig({
220
+ ...config,
221
+ servers: nextServers,
222
+ active_server_url: nextActive,
223
+ });
224
+ clearServerSessions(normalizedBaseUrl);
225
+ }
226
+
227
+ /**
228
+ * 根据 URL 读取 server。
229
+ */
230
+ export function readServer(baseUrl: string): ServerProfile | undefined {
231
+ const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
232
+ return readConfig().servers.find((server) => server.base_url === normalizedBaseUrl);
233
+ }
234
+
235
+ // ============================================================
236
+ // User Session(按 URL 隔离)
237
+ // ============================================================
238
+
239
+ function sessionDir(url: string): string {
240
+ return path.join(DIR, "servers", urlHash(url));
241
+ }
242
+
243
+ function userFile(url: string): string {
244
+ return path.join(sessionDir(url), "user.json");
245
+ }
246
+
247
+ export function readUserSession(url: string): UserSession | undefined {
248
+ return readJSON<UserSession>(userFile(url)) ?? readLegacyUserSession(url);
249
+ }
250
+
251
+ export function writeUserSession(session: UserSession): void {
252
+ writeJSON(userFile(session.base_url), session);
253
+ }
254
+
255
+ export function clearUserSession(url: string): void {
256
+ try {
257
+ fs.unlinkSync(userFile(url));
258
+ } catch {
259
+ // ignore
260
+ }
261
+
262
+ const legacy = readLegacyUserSession(url);
263
+ if (legacy) {
264
+ try {
265
+ fs.unlinkSync(LEGACY_USER_FILE);
266
+ } catch {
267
+ // ignore
268
+ }
269
+ }
270
+ }
271
+
272
+ /**
273
+ * 清除某个 server URL 下的所有 session。
274
+ */
275
+ export function clearServerSessions(url: string): void {
276
+ clearUserSession(url);
277
+ clearLegacyAdminSession(url);
278
+ }
279
+
280
+ // ============================================================
281
+ // 内部工具
282
+ // ============================================================
283
+
284
+ function readServersFromConfig(raw: Record<string, unknown>): ServerProfile[] {
285
+ const input = Array.isArray(raw.servers) ? raw.servers : [];
286
+ const servers: ServerProfile[] = [];
287
+
288
+ for (const item of input) {
289
+ if (!item || typeof item !== "object") continue;
290
+ const record = item as Record<string, unknown>;
291
+ const rawBaseUrl = typeof record.base_url === "string"
292
+ ? record.base_url
293
+ : typeof record.url === "string"
294
+ ? record.url
295
+ : "";
296
+
297
+ if (!rawBaseUrl.trim()) continue;
298
+
299
+ const normalizedBaseUrl = normalizeBaseUrl(rawBaseUrl);
300
+ const adminSecretKey = typeof record.admin_secret_key === "string"
301
+ ? record.admin_secret_key.trim()
302
+ : readLegacyAdminToken(normalizedBaseUrl);
303
+ const name = typeof record.name === "string" && record.name.trim()
304
+ ? record.name.trim()
305
+ : deriveServerName(normalizedBaseUrl);
306
+
307
+ const existing = servers.find((server) => server.base_url === normalizedBaseUrl);
308
+ if (existing) {
309
+ existing.name = name;
310
+ existing.admin_secret_key = adminSecretKey;
311
+ continue;
312
+ }
313
+
314
+ servers.push({
315
+ name,
316
+ base_url: normalizedBaseUrl,
317
+ admin_secret_key: adminSecretKey,
318
+ });
319
+ }
320
+
321
+ if (servers.length === 0 && typeof raw.base_url === "string" && raw.base_url.trim()) {
322
+ const normalizedBaseUrl = normalizeBaseUrl(raw.base_url);
323
+ servers.push({
324
+ name: deriveServerName(normalizedBaseUrl),
325
+ base_url: normalizedBaseUrl,
326
+ admin_secret_key: readLegacyAdminToken(normalizedBaseUrl),
327
+ });
328
+ }
329
+
330
+ return servers;
331
+ }
332
+
333
+ function readActiveServerURL(raw: Record<string, unknown>, servers: ServerProfile[]): string | undefined {
334
+ const rawActive = typeof raw.active_server_url === "string"
335
+ ? raw.active_server_url
336
+ : typeof raw.base_url === "string"
337
+ ? raw.base_url
338
+ : "";
339
+
340
+ if (rawActive.trim()) {
341
+ const normalized = normalizeBaseUrl(rawActive);
342
+ if (servers.find((server) => server.base_url === normalized)) {
343
+ return normalized;
344
+ }
345
+ }
346
+
347
+ return servers[0]?.base_url;
348
+ }
349
+
350
+ function normalizeServers(servers: ServerProfile[]): ServerProfile[] {
351
+ const normalized: ServerProfile[] = [];
352
+
353
+ for (const server of servers) {
354
+ const item = normalizeServer(server);
355
+ if (normalized.find((candidate) => candidate.base_url === item.base_url)) {
356
+ continue;
357
+ }
358
+ normalized.push(item);
359
+ }
360
+
361
+ return normalized;
362
+ }
363
+
364
+ function normalizeServer(input: {
365
+ base_url: string;
366
+ admin_secret_key: string;
367
+ name?: string;
368
+ }): ServerProfile {
369
+ const normalizedBaseUrl = normalizeBaseUrl(input.base_url);
370
+ const normalizedAdminSecretKey = String(input.admin_secret_key ?? "").trim();
371
+ if (!normalizedAdminSecretKey) {
372
+ throw new Error("admin_secret_key cannot be empty");
373
+ }
374
+
375
+ const normalizedName = String(input.name ?? "").trim() || deriveServerName(normalizedBaseUrl);
376
+
377
+ return {
378
+ name: normalizedName,
379
+ base_url: normalizedBaseUrl,
380
+ admin_secret_key: normalizedAdminSecretKey,
381
+ };
382
+ }
383
+
384
+ function deriveServerName(baseUrl: string): string {
385
+ try {
386
+ const url = new URL(baseUrl);
387
+ return url.hostname || baseUrl;
388
+ } catch {
389
+ return baseUrl;
390
+ }
391
+ }
392
+
393
+ function readLegacyAdminToken(url: string): string {
394
+ const payload = readJSON<{ admin_token?: string }>(legacyAdminFile(url)) ?? readLegacyGlobalAdminSession(url);
395
+ return String(payload?.admin_token ?? "").trim();
396
+ }
397
+
398
+ function clearLegacyAdminSession(url: string): void {
399
+ try {
400
+ fs.unlinkSync(legacyAdminFile(url));
401
+ } catch {
402
+ // ignore
403
+ }
404
+
405
+ const legacy = readLegacyGlobalAdminSession(url);
406
+ if (legacy) {
407
+ try {
408
+ fs.unlinkSync(LEGACY_ADMIN_FILE);
409
+ } catch {
410
+ // ignore
411
+ }
412
+ }
413
+ }
414
+
415
+ function legacyAdminFile(url: string): string {
416
+ return path.join(sessionDir(url), "admin.json");
417
+ }
418
+
419
+ function readLegacyUserSession(url: string): UserSession | undefined {
420
+ const payload = readJSON<UserSession>(LEGACY_USER_FILE);
421
+ if (!payload?.base_url) {
422
+ return undefined;
423
+ }
424
+ return normalizeBaseUrl(payload.base_url) === normalizeBaseUrl(url) ? payload : undefined;
425
+ }
426
+
427
+ function readLegacyGlobalAdminSession(url: string): { admin_token?: string } | undefined {
428
+ const payload = readJSON<{ base_url?: string; admin_token?: string }>(LEGACY_ADMIN_FILE);
429
+ if (!payload?.base_url) {
430
+ return undefined;
431
+ }
432
+ return normalizeBaseUrl(payload.base_url) === normalizeBaseUrl(url) ? payload : undefined;
433
+ }
434
+
435
+ function urlHash(url: string): string {
436
+ return crypto.createHash("sha256").update(url).digest("hex").slice(0, 16);
437
+ }
438
+
439
+ function readJSON<T>(filepath: string): T | undefined {
440
+ try {
441
+ return JSON.parse(fs.readFileSync(filepath, "utf8")) as T;
442
+ } catch {
443
+ return undefined;
444
+ }
445
+ }
446
+
447
+ function writeJSON(filepath: string, data: unknown): void {
448
+ fs.mkdirSync(path.dirname(filepath), { recursive: true });
449
+ fs.writeFileSync(filepath, JSON.stringify(data, null, 2));
450
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Stripe 终端辅助模块。
3
+ *
4
+ * 关键说明(中文)
5
+ * - manager 侧不直接管理 Stripe 资源
6
+ * - 这里只负责基于当前 Infra server 推导可复制的固定回调地址
7
+ * - 这样用户在 Stripe Dashboard 里不需要手动拼 webhook URL
8
+ */
9
+
10
+ import { normalizeBaseUrl } from "./env.js";
11
+
12
+ /**
13
+ * Stripe 常用 endpoint 集合。
14
+ */
15
+ export interface StripeEndpointSet {
16
+ /** 当前 InfraRuntime 对外地址 */
17
+ base_url: string;
18
+ /** Stripe webhook endpoint */
19
+ webhook_url: string;
20
+ /** 默认支付成功页 */
21
+ success_url: string;
22
+ /** 默认支付取消页 */
23
+ cancel_url: string;
24
+ }
25
+
26
+ /**
27
+ * 基于当前 InfraRuntime 地址构建 Stripe 相关 URL。
28
+ */
29
+ export function buildStripeEndpoints(baseUrl: string): StripeEndpointSet {
30
+ const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
31
+ return {
32
+ base_url: normalizedBaseUrl,
33
+ webhook_url: `${normalizedBaseUrl}/v1/payment.stripe/webhook`,
34
+ success_url: `${normalizedBaseUrl}/v1/payment.stripe/redirect/success`,
35
+ cancel_url: `${normalizedBaseUrl}/v1/payment.stripe/redirect/cancel`,
36
+ };
37
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * UI 工具模块。
3
+ *
4
+ * 提供 CLI 交互所需的输入/输出封装。
5
+ * 模型选择接受通用的 { id, name, hint } 数组,不依赖 server model 类型。
6
+ */
7
+
8
+ import { password, select, text, isCancel, intro, log } from "@clack/prompts";
9
+
10
+ export { intro, log, isCancel };
11
+
12
+ // ============================================================
13
+ // 显示函数
14
+ // ============================================================
15
+
16
+ export function show(text: string): void { log.info(text); }
17
+ export function showError(text: string): void { log.error(text); }
18
+ export function showSuccess(text: string): void { log.success(text); }
19
+
20
+ // ============================================================
21
+ // 交互 prompts
22
+ // ============================================================
23
+
24
+ /** 主命令菜单 */
25
+ export async function askUserCommand(): Promise<string | undefined> {
26
+ const s = await select({ message: "Command", options: [
27
+ { label: "Chat (agent)", value: "chat", hint: "Continuous conversation with pi-agent" },
28
+ { label: "Models", value: "models", hint: "List and select model" },
29
+ { label: "Balance", value: "balance", hint: "View current balance" },
30
+ { label: "History", value: "history", hint: "View balance ledger" },
31
+ { label: "Topups", value: "topups", hint: "View recharge orders" },
32
+ { label: "Recharge (Stripe)", value: "recharge", hint: "Create Checkout and pay in browser" },
33
+ { label: "Create topup", value: "topup_create", hint: "Create a pending topup order only" },
34
+ { label: "Redeem code", value: "redeem_code", hint: "Redeem a one-time credit code" },
35
+ { label: "My profile", value: "me" },
36
+ { label: "List services", value: "services" },
37
+ { label: "Call service", value: "service" },
38
+ { label: "Switch to Admin", value: "switch" },
39
+ { label: "Logout", value: "logout" },
40
+ { label: "Quit", value: "quit" },
41
+ ]});
42
+ if (!s || isCancel(s)) return undefined;
43
+ return s as string;
44
+ }
45
+
46
+ /** 文本输入 */
47
+ export async function askText(label: string): Promise<string | undefined> {
48
+ const v = await text({ message: label });
49
+ return (!v || isCancel(v)) ? undefined : v as string;
50
+ }
51
+
52
+ /** 密码输入 */
53
+ export async function askSecret(label: string): Promise<string | undefined> {
54
+ const v = await password({ message: label });
55
+ return (!v || isCancel(v)) ? undefined : v as string;
56
+ }
57
+
58
+ // ============================================================
59
+ // 模型选择(通用,不依赖 server 类型)
60
+ // ============================================================
61
+
62
+ /** 模型选项 */
63
+ export interface ModelOption {
64
+ /** 模型 ID */
65
+ id: string;
66
+ /** 模型展示名 */
67
+ name: string;
68
+ /** 提示信息 */
69
+ hint: string;
70
+ }
71
+
72
+ /** 列出并选择模型,返回模型 id 或 undefined */
73
+ export async function askModel(
74
+ models: ModelOption[],
75
+ currentModel: string,
76
+ ): Promise<string | undefined> {
77
+ const options = models.map((m) => ({
78
+ label: m.id === currentModel ? `★ ${m.name}` : ` ${m.name}`,
79
+ value: m.id,
80
+ hint: m.hint,
81
+ }));
82
+ const s = await select({ message: "Select model (★ current)", options });
83
+ return (!s || isCancel(s)) ? undefined : String(s);
84
+ }