@tokenbuddy/tokenbuddy 1.0.36 → 1.0.38

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 (146) hide show
  1. package/dist/src/buyer-store.d.ts +7 -2
  2. package/dist/src/buyer-store.js +46 -7
  3. package/dist/src/cli.d.ts +1 -0
  4. package/dist/src/cli.js +15 -7
  5. package/dist/src/daemon.d.ts +12 -0
  6. package/dist/src/daemon.js +791 -61
  7. package/dist/src/doctor-diagnostics.js +1 -6
  8. package/dist/src/provider-install.d.ts +2 -2
  9. package/dist/src/provider-install.js +248 -2
  10. package/dist/src/seller-catalog.d.ts +21 -0
  11. package/dist/src/seller-catalog.js +17 -0
  12. package/dist/src/seller-route-planner.d.ts +4 -1
  13. package/dist/src/seller-route-planner.js +3 -0
  14. package/dist/src/seller-routing-strategy.d.ts +3 -0
  15. package/dist/src/terminal-detect.d.ts +1 -1
  16. package/dist/src/terminal-detect.js +3 -2
  17. package/dist/src/workdir.d.ts +10 -0
  18. package/dist/src/workdir.js +26 -0
  19. package/package.json +15 -2
  20. package/static/ui/assets/index-Djfl9tw5.js +271 -0
  21. package/static/ui/assets/index-DkfztCkn.css +1 -0
  22. package/static/ui/index.html +2 -2
  23. package/dist/src/buyer-store.d.ts.map +0 -1
  24. package/dist/src/buyer-store.js.map +0 -1
  25. package/dist/src/clawtip-bootstrap.d.ts.map +0 -1
  26. package/dist/src/clawtip-bootstrap.js.map +0 -1
  27. package/dist/src/cli.d.ts.map +0 -1
  28. package/dist/src/cli.js.map +0 -1
  29. package/dist/src/credit-tracker.d.ts.map +0 -1
  30. package/dist/src/credit-tracker.js.map +0 -1
  31. package/dist/src/daemon.d.ts.map +0 -1
  32. package/dist/src/daemon.js.map +0 -1
  33. package/dist/src/doctor-clawtip-wallet.d.ts.map +0 -1
  34. package/dist/src/doctor-clawtip-wallet.js.map +0 -1
  35. package/dist/src/doctor-diagnostics.d.ts.map +0 -1
  36. package/dist/src/doctor-diagnostics.js.map +0 -1
  37. package/dist/src/index.d.ts.map +0 -1
  38. package/dist/src/index.js.map +0 -1
  39. package/dist/src/init-clawtip-activation.d.ts.map +0 -1
  40. package/dist/src/init-clawtip-activation.js.map +0 -1
  41. package/dist/src/init-payment-options.d.ts.map +0 -1
  42. package/dist/src/init-payment-options.js.map +0 -1
  43. package/dist/src/init-setup.d.ts.map +0 -1
  44. package/dist/src/init-setup.js.map +0 -1
  45. package/dist/src/model-index.d.ts.map +0 -1
  46. package/dist/src/model-index.js.map +0 -1
  47. package/dist/src/package-update.d.ts.map +0 -1
  48. package/dist/src/package-update.js.map +0 -1
  49. package/dist/src/prewarm-cache.d.ts.map +0 -1
  50. package/dist/src/prewarm-cache.js.map +0 -1
  51. package/dist/src/prewarm-scheduler.d.ts.map +0 -1
  52. package/dist/src/prewarm-scheduler.js.map +0 -1
  53. package/dist/src/provider-install.d.ts.map +0 -1
  54. package/dist/src/provider-install.js.map +0 -1
  55. package/dist/src/provider-routing-config.d.ts.map +0 -1
  56. package/dist/src/provider-routing-config.js.map +0 -1
  57. package/dist/src/registry-trust.d.ts.map +0 -1
  58. package/dist/src/registry-trust.js.map +0 -1
  59. package/dist/src/route-failover.d.ts.map +0 -1
  60. package/dist/src/route-failover.js.map +0 -1
  61. package/dist/src/seller-catalog.d.ts.map +0 -1
  62. package/dist/src/seller-catalog.js.map +0 -1
  63. package/dist/src/seller-concurrency-limiter.d.ts.map +0 -1
  64. package/dist/src/seller-concurrency-limiter.js.map +0 -1
  65. package/dist/src/seller-metadata-cache.d.ts.map +0 -1
  66. package/dist/src/seller-metadata-cache.js.map +0 -1
  67. package/dist/src/seller-pool.d.ts.map +0 -1
  68. package/dist/src/seller-pool.js.map +0 -1
  69. package/dist/src/seller-route-planner.d.ts.map +0 -1
  70. package/dist/src/seller-route-planner.js.map +0 -1
  71. package/dist/src/seller-routing-config.d.ts.map +0 -1
  72. package/dist/src/seller-routing-config.js.map +0 -1
  73. package/dist/src/seller-routing-strategy.d.ts.map +0 -1
  74. package/dist/src/seller-routing-strategy.js.map +0 -1
  75. package/dist/src/stream-failover.d.ts.map +0 -1
  76. package/dist/src/stream-failover.js.map +0 -1
  77. package/dist/src/tb-clawtip-proof.d.ts.map +0 -1
  78. package/dist/src/tb-clawtip-proof.js.map +0 -1
  79. package/dist/src/tb-proxyd.d.ts.map +0 -1
  80. package/dist/src/tb-proxyd.js.map +0 -1
  81. package/dist/src/terminal-detect.d.ts.map +0 -1
  82. package/dist/src/terminal-detect.js.map +0 -1
  83. package/dist/src/terminal-image.d.ts.map +0 -1
  84. package/dist/src/terminal-image.js.map +0 -1
  85. package/src/buyer-store.ts +0 -1090
  86. package/src/clawtip-bootstrap.ts +0 -65
  87. package/src/cli.ts +0 -2243
  88. package/src/credit-tracker.ts +0 -295
  89. package/src/daemon.ts +0 -5475
  90. package/src/doctor-clawtip-wallet.ts +0 -95
  91. package/src/doctor-diagnostics.ts +0 -1026
  92. package/src/index.ts +0 -16
  93. package/src/init-clawtip-activation.ts +0 -695
  94. package/src/init-payment-options.ts +0 -373
  95. package/src/init-setup.ts +0 -165
  96. package/src/model-index.ts +0 -278
  97. package/src/package-update.ts +0 -311
  98. package/src/prewarm-cache.ts +0 -485
  99. package/src/prewarm-scheduler.ts +0 -675
  100. package/src/provider-install.ts +0 -1006
  101. package/src/provider-routing-config.ts +0 -410
  102. package/src/registry-trust.ts +0 -51
  103. package/src/route-failover.ts +0 -304
  104. package/src/seller-catalog.ts +0 -505
  105. package/src/seller-concurrency-limiter.ts +0 -161
  106. package/src/seller-metadata-cache.ts +0 -91
  107. package/src/seller-pool.ts +0 -557
  108. package/src/seller-route-planner.ts +0 -513
  109. package/src/seller-routing-config.ts +0 -211
  110. package/src/seller-routing-strategy.ts +0 -362
  111. package/src/stream-failover.ts +0 -152
  112. package/src/tb-clawtip-proof.ts +0 -28
  113. package/src/tb-proxyd.ts +0 -101
  114. package/src/terminal-detect.ts +0 -333
  115. package/src/terminal-image.ts +0 -228
  116. package/static/ui/assets/index-0MVXD7bH.css +0 -1
  117. package/static/ui/assets/index-BVbeDEwq.js +0 -271
  118. package/static/ui/assets/index-BVbeDEwq.js.map +0 -1
  119. package/tests/cli-routing.test.ts +0 -363
  120. package/tests/control-plane-ui-endpoints.test.ts +0 -1630
  121. package/tests/credit-tracker.test.ts +0 -165
  122. package/tests/daemon-413-fallback.test.ts +0 -92
  123. package/tests/daemon-classify.test.ts +0 -452
  124. package/tests/daemon-roles.test.ts +0 -92
  125. package/tests/daemon-trusted-registry-cache.test.ts +0 -132
  126. package/tests/e2e.test.ts +0 -366
  127. package/tests/image-generation-e2e.test.ts +0 -230
  128. package/tests/model-index.test.ts +0 -198
  129. package/tests/package-update.test.ts +0 -147
  130. package/tests/prewarm-cache.test.ts +0 -296
  131. package/tests/prewarm-scheduler.test.ts +0 -367
  132. package/tests/provider-routing-config.test.ts +0 -150
  133. package/tests/registry-trust.test.ts +0 -28
  134. package/tests/route-failover.test.ts +0 -222
  135. package/tests/seller-catalog-413.test.ts +0 -120
  136. package/tests/seller-catalog-utilities.test.ts +0 -124
  137. package/tests/seller-concurrency-limiter.test.ts +0 -83
  138. package/tests/seller-metadata-cache.test.ts +0 -89
  139. package/tests/seller-pool.test.ts +0 -365
  140. package/tests/seller-route-planner.test.ts +0 -312
  141. package/tests/seller-routing-config.test.ts +0 -124
  142. package/tests/seller-routing-strategy.test.ts +0 -167
  143. package/tests/stream-failover.test.ts +0 -52
  144. package/tests/thousand-seller.test.ts +0 -151
  145. package/tests/tokenbuddy.test.ts +0 -4043
  146. package/tsconfig.json +0 -8
@@ -1,373 +0,0 @@
1
- import * as p from "@clack/prompts";
2
- import * as fs from "fs";
3
- import * as os from "os";
4
- import * as path from "path";
5
- import type { PaymentConfig } from "./buyer-store.js";
6
- import type { ProviderCandidate } from "./provider-install.js";
7
-
8
- /** 当前 init 流程已支持的支付方式。当前仅 JD ClawTip 扫码支付。 */
9
- export type InitPaymentMethod = "clawtip";
10
-
11
- /**
12
- * `INIT_PAYMENT_OPTIONS` 里的单条目,喂给 `@clack/prompts` 的 select 组件。
13
- */
14
- export interface InitPaymentOption {
15
- /** 选项值,对应 `InitPaymentMethod` */
16
- value: InitPaymentMethod;
17
- /** 展示给用户的标签 */
18
- label: string;
19
- /** 选段下方的小字提示,可选 */
20
- hint?: string;
21
- }
22
-
23
- /**
24
- * `INIT_COMING_SOON_PAYMENT_OPTIONS` 里的单条目:未上线的支付方式占位。
25
- * 仅用于"更多支付方式"提示框展示,不可被选中。
26
- */
27
- export interface ComingSoonPaymentOption {
28
- /** 选项 ID(仅作展示和未来上线时引用) */
29
- id: string;
30
- /** 人类可读名称 */
31
- label: string;
32
- }
33
-
34
- /**
35
- * buyer-store 里 ClawTip 支付的已有绑定(持久化的关键字段)。
36
- * `resourceUrl` / `orderNo` 至少存在一个才视为"可复用绑定"。
37
- */
38
- export interface ExistingClawtipBinding {
39
- /** 原始 config 对象(透传回 buyer-store 时用) */
40
- config: Record<string, unknown>;
41
- /** 资源 URL(可选) */
42
- resourceUrl?: string;
43
- /** 订单号(可选) */
44
- orderNo?: string;
45
- }
46
-
47
- /**
48
- * `buildInitTerminalSelectionState()` 的输出单条,喂给 `@clack/prompts` 的多选组件。
49
- */
50
- export interface InitTerminalOption {
51
- /** 选项值(通常是 `provider.id` 或 `"other"`) */
52
- value: string;
53
- /** 展示给用户的标签 */
54
- label: string;
55
- /** 选段下方的小字提示,可选 */
56
- hint?: string;
57
- }
58
-
59
- /**
60
- * `buildInitTerminalSelectionState()` 的输出:已配置 / 待配置 两个分组。
61
- * `options` 末尾会追加 `OTHER_TERMINAL_OPTION`,给"我自己接"留口。
62
- */
63
- export interface InitTerminalSelectionState {
64
- /** 已配置完成的 provider(`status === "configured"`) */
65
- installed: InitTerminalOption[];
66
- /** 待配置的 provider,末尾追加 `OTHER_TERMINAL_OPTION` */
67
- options: InitTerminalOption[];
68
- }
69
-
70
- /**
71
- * `inspectOpenClawWalletConfig()` 的输出:本地 OpenClaw 钱包目录的探查结果。
72
- * `alternatePaths` 是 `~/.openclaw/configs/` 里除 `config.json` 之外的文件,
73
- * 用于在 missing 状态下提示用户"目录里其实有别的东西"。
74
- */
75
- export interface OpenClawWalletConfigState {
76
- /** `~/.openclaw/configs/config.json` 的预期路径 */
77
- expectedPath: string;
78
- /** `~/.openclaw/configs/` 目录是否存在 */
79
- configsDirExists: boolean;
80
- /** `expectedPath` 是否真实存在 */
81
- exists: boolean;
82
- /** 同目录里其它文件路径(按文件名字典序) */
83
- alternatePaths: string[];
84
- }
85
-
86
- /**
87
- * ClawTip 钱包就绪状态四象限:
88
- * - `ready`:saved binding + 本地 wallet config 同时存在
89
- * - `metadata_missing_wallet`:只 saved binding,wallet 缺
90
- * - `wallet_missing_metadata`:只 wallet config,metadata 缺
91
- * - `missing`:都缺
92
- */
93
- export type ClawtipWalletStatus =
94
- | "ready"
95
- | "metadata_missing_wallet"
96
- | "wallet_missing_metadata"
97
- | "missing";
98
-
99
- /**
100
- * `inspectClawtipWalletReadiness()` 的输出:状态枚举 + 物证 + 给用户看的说明。
101
- */
102
- export interface ClawtipWalletReadiness {
103
- /** 综合状态 */
104
- status: ClawtipWalletStatus;
105
- /** 本地 OpenClaw wallet config 探查结果 */
106
- walletConfig: OpenClawWalletConfigState;
107
- /** buyer-store 里的 saved binding(如果有) */
108
- savedBinding?: ExistingClawtipBinding;
109
- /** 既 saved 又本地存在的可复用 binding(如果有) */
110
- reusableBinding?: ExistingClawtipBinding;
111
- /** 面向 init 面板 / doctor 的人类可读说明 */
112
- message: string;
113
- }
114
-
115
- /** init 流程里"我自己接"的兜底选项 */
116
- export const OTHER_TERMINAL_OPTION: InitTerminalOption = {
117
- value: "other",
118
- label: "Other",
119
- hint: "I will configure my own terminal using the TokenBuddy proxy endpoints."
120
- };
121
-
122
- /** init 流程已支持的可选支付方式(喂给 `@clack/prompts` 的 select 组件) */
123
- export const INIT_PAYMENT_OPTIONS: InitPaymentOption[] = [
124
- {
125
- value: "clawtip",
126
- label: "JD ClawTip Pay (Scan QR Code to activate)",
127
- hint: "1 Fen activation fee"
128
- }
129
- ];
130
-
131
- /** init 流程"更多支付方式"占位列表(仅展示用,不可选) */
132
- export const INIT_COMING_SOON_PAYMENT_OPTIONS = [
133
- {
134
- id: "wechat-pay",
135
- label: "WeChat Pay"
136
- },
137
- {
138
- id: "alipay-agent-payment",
139
- label: "Alipay Agent Payment"
140
- },
141
- {
142
- id: "coinbase-smart-wallet",
143
- label: "Coinbase Smart Wallet"
144
- }
145
- ] satisfies ReadonlyArray<ComingSoonPaymentOption>;
146
-
147
- /**
148
- * 在 init 流程的支付选择面板下追加"更多支付方式(接入中)"提示。
149
- *
150
- * @param note 注入的 note 函数(默认 `@clack/prompts.note`,测试可替换)
151
- */
152
- export function noteInitComingSoonPayments(
153
- note: (message?: string, title?: string) => void = p.note
154
- ): void {
155
- note(
156
- INIT_COMING_SOON_PAYMENT_OPTIONS.map((entry) => `- ${entry.label}(接入中)`).join("\n"),
157
- "更多支付方式"
158
- );
159
- }
160
-
161
- /**
162
- * 把 provider-install 阶段的探测结果转成 `InitTerminalSelectionState`:
163
- * 已配置完成的归 `installed`;已检测到但未配置的归 `options`,末尾追加 `OTHER_TERMINAL_OPTION`。
164
- *
165
- * @param providers provider-install 的探测结果
166
- * @returns init 流程的多选状态
167
- */
168
- export function buildInitTerminalSelectionState(providers: ProviderCandidate[]): InitTerminalSelectionState {
169
- const installed = providers
170
- .filter((provider) => provider.detected && provider.status === "configured")
171
- .map((provider) => ({
172
- value: provider.id,
173
- label: `${provider.name}(已安装)`,
174
- hint: provider.reason
175
- }));
176
-
177
- const options = providers
178
- .filter((provider) => provider.detected && provider.status !== "configured")
179
- .map((provider) => ({
180
- value: provider.id,
181
- label: provider.name,
182
- hint: provider.reason
183
- }));
184
-
185
- return {
186
- installed,
187
- options: [...options, OTHER_TERMINAL_OPTION]
188
- };
189
- }
190
-
191
- /**
192
- * 校验 init 多选面板的返回值:必须至少选一个 terminal 或选择 `Other`。
193
- *
194
- * @param selected `@clack/prompts` 多选返回值
195
- * @returns 错误消息字符串;合法时返回 `undefined`
196
- */
197
- export function validateInitTerminalSelection(selected: string[] | undefined): string | undefined {
198
- if (!selected || selected.length === 0) {
199
- return "Select at least one terminal or choose Other.";
200
- }
201
- return undefined;
202
- }
203
-
204
- /**
205
- * 把"已配置完成的 terminal"列表渲染成 init 面板顶部的摘要文案。
206
- *
207
- * @param installed 已配置完成的 terminal 列表
208
- * @returns 多行 markdown 摘要;空列表时返回 `undefined`
209
- */
210
- export function buildInstalledTerminalMessage(installed: InitTerminalOption[]): string | undefined {
211
- if (installed.length === 0) {
212
- return undefined;
213
- }
214
- return installed
215
- .map((entry) => `- ${entry.label}${entry.hint ? `\n ${entry.hint}` : ""}`)
216
- .join("\n");
217
- }
218
-
219
- function defaultHomeDir(): string {
220
- return process.env.HOME || os.homedir();
221
- }
222
-
223
- /**
224
- * 探查 `~/.openclaw/configs/` 目录及其默认 wallet 配置:
225
- * - 是否存在 configs 目录
226
- * - `config.json` 是否存在
227
- * - 同目录里其它文件列表(用于 missing 状态下的提示)
228
- *
229
- * @param home 用户 home 目录(默认读 `process.env.HOME` 或 `os.homedir()`)
230
- * @returns 探查结果
231
- */
232
- export function inspectOpenClawWalletConfig(home: string = defaultHomeDir()): OpenClawWalletConfigState {
233
- const configsDir = path.join(home, ".openclaw", "configs");
234
- const expectedPath = path.join(configsDir, "config.json");
235
- const configsDirExists = fs.existsSync(configsDir);
236
- const alternatePaths: string[] = [];
237
-
238
- if (configsDirExists) {
239
- try {
240
- const entries = fs.readdirSync(configsDir)
241
- .filter((entry) => entry !== "config.json" && !entry.startsWith("."))
242
- .sort();
243
- for (const entry of entries) {
244
- alternatePaths.push(path.join(configsDir, entry));
245
- }
246
- } catch {
247
- // Ignore directory read failures and treat as no alternates.
248
- }
249
- }
250
-
251
- return {
252
- expectedPath,
253
- configsDirExists,
254
- exists: fs.existsSync(expectedPath),
255
- alternatePaths
256
- };
257
- }
258
-
259
- function stringField(value: unknown): string | undefined {
260
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
261
- }
262
-
263
- /**
264
- * 从 `PaymentConfig` 里识别 ClawTip 已保存的关键字段(`resourceUrl` / `orderNo`)。
265
- * 两者都没有时返回 `undefined`。
266
- *
267
- * @param payment buyer-store 读到的 payment 配置
268
- * @returns 识别出的 binding;无关键字段时返回 `undefined`
269
- */
270
- export function detectExistingClawtipBinding(payment: PaymentConfig | undefined): ExistingClawtipBinding | undefined {
271
- if (!payment || payment.method !== "clawtip" || !payment.config || typeof payment.config !== "object") {
272
- return undefined;
273
- }
274
- const config = payment.config as Record<string, unknown>;
275
- const resourceUrl = stringField(config.resourceUrl);
276
- const orderNo = stringField(config.orderNo);
277
- if (!resourceUrl && !orderNo) {
278
- return undefined;
279
- }
280
- return {
281
- config,
282
- resourceUrl,
283
- orderNo,
284
- };
285
- }
286
-
287
- /**
288
- * 判断已保存的 ClawTip binding 能否被本地 OpenClaw wallet config 复用:
289
- * wallet config 必须存在并且 saved binding 至少有一个关键字段。
290
- *
291
- * @param payment buyer-store 读到的 payment 配置
292
- * @param walletConfig `inspectOpenClawWalletConfig()` 的结果
293
- * @returns 可复用 binding;不可复用时返回 `undefined`
294
- */
295
- export function detectReusableClawtipBinding(
296
- payment: PaymentConfig | undefined,
297
- walletConfig: OpenClawWalletConfigState
298
- ): ExistingClawtipBinding | undefined {
299
- if (!walletConfig.exists) {
300
- return undefined;
301
- }
302
- return detectExistingClawtipBinding(payment);
303
- }
304
-
305
- /**
306
- * 综合判断 ClawTip 钱包的就绪状态:把 saved binding、wallet config 和 reuse 关系
307
- * 合并成 `ClawtipWalletReadiness`,供 init 面板、doctor 和激活流程共同消费。
308
- *
309
- * @param payment buyer-store 读到的 payment 配置
310
- * @param walletConfig 本地 wallet 探查结果(默认 `inspectOpenClawWalletConfig()`)
311
- * @returns 就绪状态 + 物证 + 人类可读说明
312
- */
313
- export function inspectClawtipWalletReadiness(
314
- payment: PaymentConfig | undefined,
315
- walletConfig: OpenClawWalletConfigState = inspectOpenClawWalletConfig(),
316
- ): ClawtipWalletReadiness {
317
- const savedBinding = detectExistingClawtipBinding(payment);
318
- const reusableBinding = detectReusableClawtipBinding(payment, walletConfig);
319
-
320
- if (reusableBinding) {
321
- return {
322
- status: "ready",
323
- walletConfig,
324
- savedBinding,
325
- reusableBinding,
326
- message: "ClawTip payment metadata and local OpenClaw wallet config are both present.",
327
- };
328
- }
329
-
330
- if (savedBinding) {
331
- return {
332
- status: "metadata_missing_wallet",
333
- walletConfig,
334
- savedBinding,
335
- message: "Saved ClawTip payment metadata exists, but the local OpenClaw wallet config is missing.",
336
- };
337
- }
338
-
339
- if (walletConfig.exists) {
340
- return {
341
- status: "wallet_missing_metadata",
342
- walletConfig,
343
- message: "Local OpenClaw wallet config exists, but TokenBuddy ClawTip payment metadata is not saved.",
344
- };
345
- }
346
-
347
- return {
348
- status: "missing",
349
- walletConfig,
350
- message: "ClawTip payment metadata and local OpenClaw wallet config are not configured.",
351
- };
352
- }
353
-
354
- /**
355
- * 把 init 流程的若干条摘要拼成"成功"提示:
356
- * - 顶部一行 emoji + 成功消息
357
- * - 中间每条摘要 `- ` 开头
358
- * - 末尾附 `tb doctor` 提示
359
- *
360
- * @param summaryLines 摘要行(会先 trim,空行会被跳过)
361
- * @returns 多行 markdown 摘要
362
- */
363
- export function buildInitSuccessMessage(summaryLines: string[] = []): string {
364
- const lines = ["✅ TokenBuddy setup completed successfully."];
365
- for (const line of summaryLines) {
366
- const trimmed = line.trim();
367
- if (trimmed) {
368
- lines.push(`- ${trimmed}`);
369
- }
370
- }
371
- lines.push("Run `tb doctor` to audit status anytime.");
372
- return lines.join("\n");
373
- }
package/src/init-setup.ts DELETED
@@ -1,165 +0,0 @@
1
- export const INIT_SETUP_CONFIG_KEY = "init-setup";
2
-
3
- export const INIT_SETUP_VERSION = 1;
4
-
5
- export const INIT_SETUP_STEPS = [
6
- "gateway_intro",
7
- "model_access",
8
- "supplier_routing",
9
- "auto_purchase",
10
- "connect_tools",
11
- "verify_gateway",
12
- "install_app",
13
- ] as const;
14
-
15
- export const DEFAULT_INIT_RECOMMENDED_MODELS = [
16
- "deepseek-v4-flash",
17
- "kimi-2.6",
18
- "gpt-5.5",
19
- "gpt-5.4",
20
- "claude-opus-4.7",
21
- "claude-opus-4.8",
22
- "claude-sonnet-4.6",
23
- "gemma-4-26b-a4b-it",
24
- "qwen3-235b-a22b",
25
- "google/gemini-3.5-flash",
26
- "google/gemini-3.1-pro-preview",
27
- "qwen/qwen3.7-max",
28
- "qwen/qwen3.7-plus",
29
- ] as const;
30
-
31
- export type InitSetupStep = typeof INIT_SETUP_STEPS[number];
32
- export type InitSetupStatus = "not_started" | "in_progress" | "completed";
33
-
34
- export interface InitSetupMarker {
35
- status: InitSetupStatus;
36
- version: typeof INIT_SETUP_VERSION;
37
- completedSteps: InitSetupStep[];
38
- startedAt?: string;
39
- updatedAt?: string;
40
- completedAt?: string;
41
- }
42
-
43
- const INIT_SETUP_STEP_SET = new Set<string>(INIT_SETUP_STEPS);
44
-
45
- export function normalizeInitSetupMarker(value: unknown): InitSetupMarker {
46
- if (!value || typeof value !== "object") {
47
- return defaultInitSetupMarker();
48
- }
49
- const raw = value as {
50
- status?: unknown;
51
- completedSteps?: unknown;
52
- startedAt?: unknown;
53
- updatedAt?: unknown;
54
- completedAt?: unknown;
55
- };
56
- const status = normalizeInitSetupStatus(raw.status);
57
- return {
58
- status,
59
- version: INIT_SETUP_VERSION,
60
- completedSteps: normalizeInitSetupSteps(raw.completedSteps),
61
- startedAt: typeof raw.startedAt === "string" ? raw.startedAt : undefined,
62
- updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : undefined,
63
- completedAt: typeof raw.completedAt === "string" ? raw.completedAt : undefined,
64
- };
65
- }
66
-
67
- export function buildInProgressInitSetupMarker(
68
- previous: InitSetupMarker = defaultInitSetupMarker(),
69
- now: Date = new Date(),
70
- ): InitSetupMarker {
71
- const updatedAt = now.toISOString();
72
- return {
73
- ...previous,
74
- status: previous.status === "completed" ? "completed" : "in_progress",
75
- version: INIT_SETUP_VERSION,
76
- startedAt: previous.startedAt || updatedAt,
77
- updatedAt,
78
- };
79
- }
80
-
81
- export function buildCompletedInitSetupMarker(
82
- completedSteps: readonly string[] = INIT_SETUP_STEPS,
83
- now: Date = new Date(),
84
- ): InitSetupMarker {
85
- const normalizedSteps = normalizeInitSetupSteps(completedSteps);
86
- const updatedAt = now.toISOString();
87
- return {
88
- status: "completed",
89
- version: INIT_SETUP_VERSION,
90
- completedSteps: normalizedSteps.length > 0 ? normalizedSteps : [...INIT_SETUP_STEPS],
91
- startedAt: updatedAt,
92
- updatedAt,
93
- completedAt: updatedAt,
94
- };
95
- }
96
-
97
- export function assertInitSetupSteps(value: unknown): InitSetupStep[] {
98
- if (value === undefined) {
99
- return [...INIT_SETUP_STEPS];
100
- }
101
- if (!Array.isArray(value)) {
102
- throw new Error("completedSteps must be an array");
103
- }
104
- const steps: InitSetupStep[] = [];
105
- for (const entry of value) {
106
- if (typeof entry !== "string" || !INIT_SETUP_STEP_SET.has(entry)) {
107
- throw new Error(`unknown init setup step: ${String(entry)}`);
108
- }
109
- if (!steps.includes(entry as InitSetupStep)) {
110
- steps.push(entry as InitSetupStep);
111
- }
112
- }
113
- return steps;
114
- }
115
-
116
- export function isFreshInitMachine(marker: InitSetupMarker): boolean {
117
- return marker.status !== "completed";
118
- }
119
-
120
- export function normalizeInitRecommendedModels(value: readonly string[] | string | undefined): string[] {
121
- const entries = typeof value === "string"
122
- ? value.split(",")
123
- : value ?? [];
124
- return Array.from(new Set(entries.map((entry) => entry.trim()).filter(Boolean)));
125
- }
126
-
127
- export function resolveInitRecommendedModels(input?: {
128
- configuredModels?: readonly string[];
129
- env?: Record<string, string | undefined>;
130
- }): string[] {
131
- const configured = normalizeInitRecommendedModels(input?.configuredModels);
132
- if (configured.length > 0) {
133
- return configured;
134
- }
135
- const envModels = normalizeInitRecommendedModels(input?.env?.TB_PROXYD_INIT_RECOMMENDED_MODELS);
136
- if (envModels.length > 0) {
137
- return envModels;
138
- }
139
- return [...DEFAULT_INIT_RECOMMENDED_MODELS];
140
- }
141
-
142
- function defaultInitSetupMarker(): InitSetupMarker {
143
- return {
144
- status: "not_started",
145
- version: INIT_SETUP_VERSION,
146
- completedSteps: [],
147
- };
148
- }
149
-
150
- function normalizeInitSetupStatus(value: unknown): InitSetupStatus {
151
- return value === "in_progress" || value === "completed" ? value : "not_started";
152
- }
153
-
154
- function normalizeInitSetupSteps(value: unknown): InitSetupStep[] {
155
- if (!Array.isArray(value)) {
156
- return [];
157
- }
158
- const steps: InitSetupStep[] = [];
159
- for (const entry of value) {
160
- if (typeof entry === "string" && INIT_SETUP_STEP_SET.has(entry) && !steps.includes(entry as InitSetupStep)) {
161
- steps.push(entry as InitSetupStep);
162
- }
163
- }
164
- return steps;
165
- }