@eddyskywalker/dsh-chatgpt-subscription 0.32.0 → 0.34.0

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 (116) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +100 -111
  3. package/lib/client.js +4731 -1239
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +11514 -3162
  6. package/lib/types/client/common/format.d.ts +10 -0
  7. package/lib/types/client/common/format.d.ts.map +1 -1
  8. package/lib/types/client/hub/brand-icons.d.ts +18 -2
  9. package/lib/types/client/hub/brand-icons.d.ts.map +1 -1
  10. package/lib/types/client/hub/hub-styles.d.ts.map +1 -1
  11. package/lib/types/client/hub/providers.d.ts.map +1 -1
  12. package/lib/types/client/index.d.ts +4 -0
  13. package/lib/types/client/index.d.ts.map +1 -1
  14. package/lib/types/client/minimax-code/VideoFormDialog.d.ts +46 -50
  15. package/lib/types/client/minimax-code/VideoFormDialog.d.ts.map +1 -1
  16. package/lib/types/client/minimax-code/locales.d.ts +80 -20
  17. package/lib/types/client/minimax-code/locales.d.ts.map +1 -1
  18. package/lib/types/client/minimax-code/styles.d.ts.map +1 -1
  19. package/lib/types/client/minimax-code/video-command-host.d.ts +17 -11
  20. package/lib/types/client/minimax-code/video-command-host.d.ts.map +1 -1
  21. package/lib/types/client/minimax-code/video-command-icon.d.ts +38 -0
  22. package/lib/types/client/minimax-code/video-command-icon.d.ts.map +1 -0
  23. package/lib/types/client/minimax-code/video-command.d.ts +53 -59
  24. package/lib/types/client/minimax-code/video-command.d.ts.map +1 -1
  25. package/lib/types/client/minimax-code/video-media-dropzone.d.ts +57 -0
  26. package/lib/types/client/minimax-code/video-media-dropzone.d.ts.map +1 -0
  27. package/lib/types/client/minimax-code/video-media-input.d.ts +173 -0
  28. package/lib/types/client/minimax-code/video-media-input.d.ts.map +1 -0
  29. package/lib/types/client/minimax-code/video-presets.d.ts +67 -0
  30. package/lib/types/client/minimax-code/video-presets.d.ts.map +1 -0
  31. package/lib/types/client/minimax-code/video-workspace.d.ts +41 -0
  32. package/lib/types/client/minimax-code/video-workspace.d.ts.map +1 -0
  33. package/lib/types/client/opendesign/OpenDesignComposerQuota.d.ts +20 -0
  34. package/lib/types/client/opendesign/OpenDesignComposerQuota.d.ts.map +1 -0
  35. package/lib/types/client/opendesign/OpenDesignSection.d.ts +18 -0
  36. package/lib/types/client/opendesign/OpenDesignSection.d.ts.map +1 -0
  37. package/lib/types/client/opendesign/api.d.ts +45 -0
  38. package/lib/types/client/opendesign/api.d.ts.map +1 -0
  39. package/lib/types/client/opendesign/locales.d.ts +689 -0
  40. package/lib/types/client/opendesign/locales.d.ts.map +1 -0
  41. package/lib/types/client/opendesign/styles.d.ts +11 -0
  42. package/lib/types/client/opendesign/styles.d.ts.map +1 -0
  43. package/lib/types/client/qoder/QoderComposerQuota.d.ts +41 -0
  44. package/lib/types/client/qoder/QoderComposerQuota.d.ts.map +1 -0
  45. package/lib/types/client/qoder/QoderSection.d.ts +36 -0
  46. package/lib/types/client/qoder/QoderSection.d.ts.map +1 -0
  47. package/lib/types/client/qoder/api.d.ts +4 -0
  48. package/lib/types/client/qoder/api.d.ts.map +1 -0
  49. package/lib/types/client/qoder/locales.d.ts +316 -0
  50. package/lib/types/client/qoder/locales.d.ts.map +1 -0
  51. package/lib/types/client/qoder/styles.d.ts +16 -0
  52. package/lib/types/client/qoder/styles.d.ts.map +1 -0
  53. package/lib/types/client/qoder/useQoderSection.d.ts +97 -0
  54. package/lib/types/client/qoder/useQoderSection.d.ts.map +1 -0
  55. package/lib/types/host/common/model-request-control.d.ts +1 -1
  56. package/lib/types/host/common/model-request-control.d.ts.map +1 -1
  57. package/lib/types/host/common/request-diagnostics.d.ts +1 -1
  58. package/lib/types/host/common/request-diagnostics.d.ts.map +1 -1
  59. package/lib/types/host/kimi-code/adapter.d.ts +34 -1
  60. package/lib/types/host/kimi-code/adapter.d.ts.map +1 -1
  61. package/lib/types/host/kimi-code/mapper.d.ts +8 -0
  62. package/lib/types/host/kimi-code/mapper.d.ts.map +1 -1
  63. package/lib/types/host/kimi-code/types.d.ts +92 -0
  64. package/lib/types/host/kimi-code/types.d.ts.map +1 -1
  65. package/lib/types/host/opendesign/account-pool.d.ts +54 -0
  66. package/lib/types/host/opendesign/account-pool.d.ts.map +1 -0
  67. package/lib/types/host/opendesign/adapter.d.ts +69 -0
  68. package/lib/types/host/opendesign/adapter.d.ts.map +1 -0
  69. package/lib/types/host/opendesign/catalog.d.ts +44 -0
  70. package/lib/types/host/opendesign/catalog.d.ts.map +1 -0
  71. package/lib/types/host/opendesign/client.d.ts +148 -0
  72. package/lib/types/host/opendesign/client.d.ts.map +1 -0
  73. package/lib/types/host/opendesign/line.d.ts +49 -0
  74. package/lib/types/host/opendesign/line.d.ts.map +1 -0
  75. package/lib/types/host/opendesign/mapper.d.ts +128 -0
  76. package/lib/types/host/opendesign/mapper.d.ts.map +1 -0
  77. package/lib/types/host/opendesign/oauth.d.ts +105 -0
  78. package/lib/types/host/opendesign/oauth.d.ts.map +1 -0
  79. package/lib/types/host/opendesign/routes.d.ts +74 -0
  80. package/lib/types/host/opendesign/routes.d.ts.map +1 -0
  81. package/lib/types/host/opendesign/token-store.d.ts +154 -0
  82. package/lib/types/host/opendesign/token-store.d.ts.map +1 -0
  83. package/lib/types/host/opendesign/types.d.ts +180 -0
  84. package/lib/types/host/opendesign/types.d.ts.map +1 -0
  85. package/lib/types/host/qoder/account-pool.d.ts +137 -0
  86. package/lib/types/host/qoder/account-pool.d.ts.map +1 -0
  87. package/lib/types/host/qoder/adapter.d.ts +158 -0
  88. package/lib/types/host/qoder/adapter.d.ts.map +1 -0
  89. package/lib/types/host/qoder/adopt.d.ts +146 -0
  90. package/lib/types/host/qoder/adopt.d.ts.map +1 -0
  91. package/lib/types/host/qoder/client.d.ts +301 -0
  92. package/lib/types/host/qoder/client.d.ts.map +1 -0
  93. package/lib/types/host/qoder/cosy.d.ts +173 -0
  94. package/lib/types/host/qoder/cosy.d.ts.map +1 -0
  95. package/lib/types/host/qoder/mapper.d.ts +235 -0
  96. package/lib/types/host/qoder/mapper.d.ts.map +1 -0
  97. package/lib/types/host/qoder/model-catalog.d.ts +231 -0
  98. package/lib/types/host/qoder/model-catalog.d.ts.map +1 -0
  99. package/lib/types/host/qoder/oauth.d.ts +134 -0
  100. package/lib/types/host/qoder/oauth.d.ts.map +1 -0
  101. package/lib/types/host/qoder/routes.d.ts +119 -0
  102. package/lib/types/host/qoder/routes.d.ts.map +1 -0
  103. package/lib/types/host/qoder/token-store.d.ts +280 -0
  104. package/lib/types/host/qoder/token-store.d.ts.map +1 -0
  105. package/lib/types/host/qoder/types.d.ts +257 -0
  106. package/lib/types/host/qoder/types.d.ts.map +1 -0
  107. package/lib/types/host/workbuddy/adapter.d.ts.map +1 -1
  108. package/lib/types/host/workbuddy/mapper.d.ts +1 -0
  109. package/lib/types/host/workbuddy/mapper.d.ts.map +1 -1
  110. package/lib/types/index.d.ts +15 -0
  111. package/lib/types/index.d.ts.map +1 -1
  112. package/lib/types/shared/opendesign-contracts.d.ts +159 -0
  113. package/lib/types/shared/opendesign-contracts.d.ts.map +1 -0
  114. package/lib/types/shared/qoder-contracts.d.ts +332 -0
  115. package/lib/types/shared/qoder-contracts.d.ts.map +1 -0
  116. package/package.json +1 -1
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Qoder(订阅)线路对话端的 wire mapping。
3
+ *
4
+ * 这条线路的协议面**不是** OpenAI:它把一份 OpenAI 形状的对话包进 Qoder 自己的
5
+ * \`RemoteChatAsk\` 信封,过一道自定义 body codec,再用 COSY 头签名(cosy.ts)。
6
+ * 本文件只管「对话形状 ⇄ 信封里的 \`messages\`/\`parameters\`」与「信封 SSE ⇄ DSH chunks」;
7
+ * 签名与编码在 cosy.ts,传输在 adapter.ts——三层各管一层,是因为每层都有独立的
8
+ * fixture/测试锁定它(cosy 层有 frozen fixtures,本层有 mapper 测试)。
9
+ *
10
+ * 逐字来源(docs/qoder-line-plan.md §3.5/§3.6):
11
+ *
12
+ * - 请求信封字段集:qodercli2api \`infer-user-no-org.json\` 的 \`body_raw\`(frozen fixture);
13
+ * - \`parameters\` 里的思考控制:pi-provider \`stream.ts\`(\`enable_thinking\` 布尔 +
14
+ * \`reasoning_effort\` 档位,仅当目录的 \`thinking_config.enabled.efforts\` 存在才发档位);
15
+ * - 响应信封:\`data:{headers, body, statusCodeValue}\`,\`body\` 再解析出 OpenAI chunk;
16
+ * \`[DONE]\` 两种形态(裸帧与信封 \`body:"[DONE]"\`)都结束读取;\`event:finish\` 是
17
+ * 权威终止事件(qodercli2api §7);
18
+ * - usage 口径:\`prompt_tokens\` **含** \`cached_tokens\`,DSH 互斥计数所以减回去
19
+ * (pi-provider \`stream.ts\` 同一减法)。
20
+ *
21
+ * 与 step-code mapper 同源的辅助(消息投影、图片预算、tool_call 聚合)按同一套写,
22
+ * 因为上游信封里装的确实是 OpenAI 形状的消息数组。
23
+ *
24
+ * @module dsh-chatgpt-subscription/qoder-mapper
25
+ */
26
+ import type { QoderModelEntry } from './model-catalog.ts';
27
+ import { LlmError, type GenerateOptions, type OutboundContentBlock, type StreamChunk, type TokenUsage } from '../common/llm-compat.ts';
28
+ import { resolveRequestImages, type AttachmentImageReader, type ResolvedRequestImage, type ResolvedRequestImages } from '../common/request-images.ts';
29
+ export { resolveRequestImages };
30
+ export type { AttachmentImageReader, ResolvedRequestImage, ResolvedRequestImages };
31
+ /**
32
+ * 一次请求允许携带的 Base64 图片总量。
33
+ *
34
+ * Qoder 没有公开的逐请求图片上限,所以这是防御性预算而不是文档化限制:
35
+ * 与 step-code 取同一个 12 MB,让失控的对话降级成占位文本而不是拖垮传输。
36
+ */
37
+ export declare const QODER_MAX_REQUEST_IMAGE_BYTES: number;
38
+ /** 共享图片预算,供想要插件保守上限的调用方使用。 */
39
+ export declare const QODER_SHARED_IMAGE_BUDGET = 1500000;
40
+ /**
41
+ * \`request_id\` 重复时上游报的业务错误码(逐字 qodercli2api §5:
42
+ * 服务端对重复值返回 code 103)。它**不是**可安全自动重试的状态——
43
+ * 重试必须用新的 request_id,而不是重发同一份。
44
+ */
45
+ export declare const QODER_ERROR_DUPLICATE_REQUEST_ID = "103";
46
+ /** token 失效的业务错误码(CN 报「Login expired」,pi-provider oauth.ts 注释)。 */
47
+ export declare const QODER_ERROR_LOGIN_EXPIRED = "105";
48
+ /**
49
+ * 响应侧「缓存读入量」的解析优先级,从先到后。
50
+ *
51
+ * 1. \`prompt_tokens_details.cached_tokens\` —— OpenAI 规范的字段(pi-provider 的主读法);
52
+ * 2. **顶层 \`cached_tokens\`** —— Qoder 网关可能直接平铺(step-code 线路的教训:
53
+ * 官方文档只展示顶层字段时,它必须在自己那条分支上被认);
54
+ * 3. \`prompt_cache_hit_tokens\` —— DeepSeek 一族网关的命名(Qoder 的部分模型上游是它);
55
+ * 4. 0。
56
+ *
57
+ * 都不命中时取 0:0 表示「上游没报」,而不是「一定没命中」。
58
+ */
59
+ export declare const QODER_CACHE_READ_FIELD_ORDER: readonly ["prompt_tokens_details.cached_tokens", "cached_tokens", "prompt_cache_hit_tokens"];
60
+ /**
61
+ * 一次请求超过 {@link QODER_MAX_REQUEST_IMAGE_BYTES} 时,把最旧的内联图片换成
62
+ * 可见占位文本。持久历史不动,只有即将发出的这份请求变(与兄弟线路同一机制)。
63
+ */
64
+ export declare function offloadOldestQoderRequestImages(options: GenerateOptions, images?: ResolvedRequestImages): GenerateOptions;
65
+ /** 信封里的消息形状(OpenAI Chat Completions 词汇)。 */
66
+ type QoderWireMessage = Record<string, unknown>;
67
+ /**
68
+ * 收窄一个 tool_call id 到 Qoder 接受的形状(\`^[a-zA-Z0-9_-]{1,64}$\`,
69
+ * 逐字 pi-provider transform.ts 的注释)。线上重写,映射不回内部——
70
+ * DSH 自己的 id 本来就在这个形状里,这只是对上游边界的防守。
71
+ */
72
+ export declare function qoderWireToolCallId(id: string): string;
73
+ /** 线上请求需要的、而对话本身不携带的旋钮。 */
74
+ export interface QoderWireRequestOptions {
75
+ /** 所选模型是否声明图片输入(\`is_vl\`)。 */
76
+ supportsImages?: boolean;
77
+ /** 调用方没给输出上限时用的上限;通常取目录行的 \`defaultMaxTokens\`。 */
78
+ defaultMaxTokens?: number;
79
+ /** 该模型是否推理模型(不是推理模型就一个思考字段都不发)。 */
80
+ reasoning?: boolean;
81
+ /** 该模型声明的真实档位梯子;空 = 没有 effort 字段(toggle 形态或不推理)。 */
82
+ reasoningEfforts?: readonly string[];
83
+ /** 思考能否关闭(目录 \`thinking_config.disabled\`)。 */
84
+ thinkingDisableable?: boolean;
85
+ }
86
+ /** 出厂默认:不认图、不发思考字段、没有梯子。 */
87
+ export declare const DEFAULT_QODER_WIRE_REQUEST_OPTIONS: QoderWireRequestOptions;
88
+ /**
89
+ * 一行目录的线上旋钮(字段逐列复制只住在这一处;adapter 只加它自己的覆盖)。
90
+ */
91
+ export declare function qoderRequestOptionsFor(entry: QoderModelEntry | undefined, overrides?: {
92
+ defaultMaxTokens?: number;
93
+ }): QoderWireRequestOptions;
94
+ /**
95
+ * 发到线上的思考控制(\`parameters\` 里的两个字段),或两个都不发。
96
+ *
97
+ * 逐字 pi-provider \`stream.ts\` 的语义(来源 \`@qoder-ai/qodercli\`):
98
+ *
99
+ * - 模型不是推理模型 → 一个字段都不发;
100
+ * - 推理模型但调用方没选档位 → \`enable_thinking: false\`(不默认让它想——
101
+ * 想了更慢更费额度,用户没要求);
102
+ * - 调用方选了档位:收敛到模型真实梯子(types.ts 的 convergeQoderEffort);
103
+ * 梯子是 effort 形态才发 \`reasoning_effort\`,toggle 形态只发开关;
104
+ * 收敛到 \`none\`(或模型说思考可关而调用方要关)→ \`enable_thinking: false\`。
105
+ */
106
+ export declare function resolveQoderThinking(requested: unknown, request: QoderWireRequestOptions): {
107
+ enable_thinking: boolean;
108
+ reasoning_effort?: string;
109
+ } | undefined;
110
+ /**
111
+ * 会话与请求的稳定 id(缓存亲和)。
112
+ *
113
+ * 逐字 pi-provider \`stream.ts\` 的设计:\`session_id\` 的稳定段来自账号+模型的哈希,
114
+ * 会话段来自宿主给的 sessionId(没有才现造一个);\`request_set_id\` 是会话内容的
115
+ * 稳定哈希(重试同一份请求时不变,服务端去重靠它配合 \`request_id\` 的分工:
116
+ * \`request_id\` 每次请求唯一,重复报 code 103)。
117
+ */
118
+ export declare function qoderSessionId(uid: string, modelKey: string, sessionId: string | undefined): string;
119
+ /** 会话内容的稳定哈希(\`request_set_id\` / \`chat_record_id\`)。 */
120
+ export declare function qoderChatRecordId(modelKey: string, messages: readonly QoderWireMessage[], tools: unknown, maxTokens: number): string;
121
+ /** 装配一份 RemoteChatAsk 的调用方材料。 */
122
+ export interface QoderChatRequestContext {
123
+ /** 上行模型 key(\`X-Model-Key\` / \`model_config.key\`)。 */
124
+ modelKey: string;
125
+ /** 目录行(\`model_config\` 的其余字段从这里还原成上游形状)。 */
126
+ entry: QoderModelEntry | undefined;
127
+ /** 当前生效的 COSY 版本(\`business.version\` 填它,与官方 CLI 一致)。 */
128
+ cosyVersion: string;
129
+ /** DSH 会话 id(缓存亲和的稳定段之外的那一段)。 */
130
+ sessionId?: string;
131
+ }
132
+ /**
133
+ * 拼一份 RemoteChatAsk 请求体(**未编码**的 JSON 对象)。
134
+ *
135
+ * 字段集与取值逐字按 frozen fixture 的 \`body_raw\`(docs/qoder-line-plan.md §3.5);
136
+ * 顶层 \`system\` 与领头的 \`role:system\` 消息**都填**(官方 CLI 两处都填——
137
+ * fixture 锁定;pi-provider 实测顶层字段被服务端忽略,填两份是无害的冗余)。
138
+ *
139
+ * 返回对象之后,调用方(adapter)**必须**用 \`JSON.stringify\` 串行化一次、
140
+ * 拿那一份字节去编码+签名+发送:签名覆盖的是字节,任何中间的一道
141
+ * parse/re-marshal 都会让签名的字节与发送的字节漂移。
142
+ */
143
+ export declare function buildQoderChatRequest(options: GenerateOptions, images: ResolvedRequestImages, request: QoderWireRequestOptions, context: QoderChatRequestContext): Record<string, unknown>;
144
+ /** 一帧 usage 读下来的归一化结果。 */
145
+ export interface QoderParsedUsage {
146
+ /** 端点的聚合 prompt 计数(缓存拆分前)。 */
147
+ promptTokens: number;
148
+ /** 未命中输入,与两个缓存桶互斥。 */
149
+ inputTokens: number;
150
+ outputTokens: number;
151
+ cacheReadTokens: number;
152
+ cacheWriteTokens: number;
153
+ reasoningTokens: number;
154
+ }
155
+ /** 一帧 usage 的缓存读入量,按 {@link QODER_CACHE_READ_FIELD_ORDER} 逐条走。 */
156
+ export declare function readQoderCacheReadTokens(usage: Record<string, unknown>): number;
157
+ /**
158
+ * 归一化一帧 \`usage\` 到 DSH 的互斥计数。
159
+ *
160
+ * Qoder 遵循 OpenAI 语义:\`prompt_tokens\` **含** \`cached_tokens\`,所以缓存两桶
161
+ * 从聚合里减回去(pi-provider \`stream.ts\` 的同一减法)。\`cacheable_tokens\` 是容量
162
+ * 指标而不是写入计数(首轮写入时它也是 0),**不**映射到 cacheWrite。
163
+ *
164
+ * \`usage.credits\` / \`billable\`(Qoder 的计费字段)不进 DSH 的 TokenUsage——
165
+ * 它没有对应的格子,而订阅单价未公开,折成金额是编造(计划 §5)。
166
+ */
167
+ export declare function parseQoderUsage(raw: unknown): QoderParsedUsage | undefined;
168
+ interface PendingToolCall {
169
+ blockIndex: number;
170
+ id: string;
171
+ name: string;
172
+ arguments: string;
173
+ started: boolean;
174
+ }
175
+ /** 一条 Qoder 流式响应的累计状态。 */
176
+ export interface QoderStreamState {
177
+ blocks: OutboundContentBlock[];
178
+ current: OpenTextBlock | null;
179
+ /** wire tool index -> 累计中的调用。 */
180
+ toolCalls: Map<number, PendingToolCall>;
181
+ hasContent: boolean;
182
+ hasToolCall: boolean;
183
+ finishReason: string | null;
184
+ /** 终止依据到了(\`[DONE]\` 任一形态或 \`event:finish\`)。 */
185
+ done: boolean;
186
+ /** 终止 chunks 已经发出过。 */
187
+ finished: boolean;
188
+ inputTokens: number;
189
+ outputTokens: number;
190
+ cacheReadTokens: number;
191
+ cacheWriteTokens: number;
192
+ reasoningTokens: number;
193
+ sawUsage: boolean;
194
+ }
195
+ interface OpenTextBlock {
196
+ index: number;
197
+ type: 'text' | 'reasoning';
198
+ text: string;
199
+ }
200
+ export declare function createQoderStreamState(): QoderStreamState;
201
+ /**
202
+ * 喂一行 SSE。
203
+ *
204
+ * 信封形状(qodercli2api §7,pi-provider \`stream.ts\` 同一读法):
205
+ *
206
+ * - \`data:{"headers":{…},"body":"<inner JSON string>","statusCodeValue":200}\`:
207
+ * \`body\` 再解析一次得到 OpenAI \`chat.completion.chunk\`;
208
+ * - \`statusCodeValue != 200\` 是**错误信封**,转成 LlmError 抛出;
209
+ * - \`[DONE]\` 两种形态都结束:裸 \`data:[DONE]\` 与信封 \`body:"[DONE]"\`;
210
+ * - \`event:finish\` 是权威终止事件(它自己的 data 里是耗时统计,不是内容);
211
+ * - 心跳与其它 \`event:\` 帧不产生任何 chunk(调用方在字节层喂看门狗)。
212
+ */
213
+ export declare function processQoderStreamLine(line: string, state: QoderStreamState): StreamChunk[];
214
+ /** 一次应答的 DSH 记账(缓存字段为 0 时省略)。 */
215
+ export declare function qoderStreamTokenUsage(state: QoderStreamState): TokenUsage;
216
+ /**
217
+ * 冲刷所有打开的块,然后发 usage 与终止 finish。
218
+ *
219
+ * 顺序是硬要求:DSH 在 \`finish\` 上结算一次调用,之后到达的 usage 永远入不了账。
220
+ */
221
+ export declare function closeQoderStream(state: QoderStreamState): StreamChunk[];
222
+ /**
223
+ * 没有终止事件的流是被截断的回复,不是一份完整答案。
224
+ */
225
+ export declare function assertQoderStreamComplete(state: QoderStreamState): void;
226
+ /**
227
+ * 把一次失败(非 2xx 响应,或信封里的错误状态)分类成 DSH failure。
228
+ *
229
+ * 错误码是 harness 的共享词汇而不是本线路自己的:号池认得 \`AUTH\`
230
+ * (「这个账号必须重新登录」),而重试集合不会捡起一次套餐拒绝。
231
+ * Qoder 的两个业务码有自己的归处:\`103\`(重复 request_id)不是可安全
232
+ * 自动重试的状态(qodercli2api §8 原话);\`105\`(Login expired)归为 AUTH。
233
+ */
234
+ export declare function classifyQoderFailure(status: number, detail: string): LlmError;
235
+ //# sourceMappingURL=mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../../src/host/qoder/mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Qoder(订阅)线路的模型目录:目录解析、能力装配、随包兜底表。
3
+ *
4
+ * 存在的原因是本线路的一条硬规则(与兄弟线路同源):**能力不得从模型名推断**。
5
+ * 能力字段一律来自 `GET {base}/algo/api/v2/model/list?Encode=1` 的端点字段
6
+ * (`is_vl` / `is_reasoning` / `thinking_config` / `context_config`),拿不到的走区域兜底。
7
+ *
8
+ * ## 随包兜底表
9
+ *
10
+ * 与 step-code 不同,本线路**有**一张随包表:Qoder 的目录请求需要 COSY 签名,
11
+ * 没登录就拿不到目录,而官方 CLI 要求先登录才可用——随包表让「还没登录」的
12
+ * 选择器不为空。表的内容照录 pi-provider-qoder `src/catalog.ts` 的
13
+ * `staticModels` / `staticCnModels`(逐条在注释里给出处);它是**能力兜底**,
14
+ * 不是权威列表——登录后的运行时目录随时顶替它(client.ts 的缓存与快照)。
15
+ *
16
+ * 真正保证「取不到目录时选择器不为空」的另一半是 {@link undeclaredQoderModelEntry}:
17
+ * 上游给什么 id 就以未声明行进入目录,不猜窗口、不认图、不发档位。
18
+ */
19
+ import type { QoderModelOption, QoderReasoningEffort, QoderRegion } from '../../shared/qoder-contracts.ts';
20
+ /**
21
+ * 一行模型能力。与 `QoderModelOption` 同义,去掉的只是「用户设置」那一半
22
+ * (见 {@link catalogModelOptions})。多了两个只在 host 侧有意义的字段:
23
+ * `upstreamKey`(线上请求用的上游 `key`,与公开 id 是两回事)与
24
+ * `source`(`X-Model-Source` 头与 `model_config.source` 的取值)。
25
+ */
26
+ export interface QoderModelEntry {
27
+ /** 公开 id:上游 `display_name` 去空白。 */
28
+ id: string;
29
+ /** 显示名(上游 `display_name` 原样)。 */
30
+ name: string;
31
+ /** 上行请求用的上游 key(`X-Model-Key` 与 `model_config.key`)。 */
32
+ upstreamKey: string;
33
+ /** 模型来源(`X-Model-Source`,通常 `system` 或 `custom`;pi-provider stream.ts)。 */
34
+ source: string;
35
+ /** 一句话能力描述:思考形态 / 可选档位 / 输入模态 / 上下文窗口。由 {@link describeQoderModel} 生成。 */
36
+ hint: string;
37
+ /** 服务该模型的区域。 */
38
+ regions: readonly QoderRegion[];
39
+ /** 该模型是否推理模型(目录 `is_reasoning` / `thinking_config` 存在);`model_config` 照它填。 */
40
+ reasoning: boolean;
41
+ /** 该模型**真实**接受的思考档位梯子;空数组 = 不发任何思考控制字段。 */
42
+ reasoningEfforts: readonly QoderReasoningEffort[];
43
+ /** 思考能否关闭(目录 `thinking_config.disabled` 存在与否)。 */
44
+ thinkingDisableable: boolean;
45
+ /** 是否接受 image 输入(目录 `is_vl`)。 */
46
+ supportsImages: boolean;
47
+ /** 上下文窗口:`context_config` 里最大的 `token_count`,没有时走区域兜底。 */
48
+ defaultContextWindow: number;
49
+ /** 调用方不指定输出上限时的输出上限(目录不报,取文档化上限 131072)。 */
50
+ defaultMaxTokens: number;
51
+ /** 上游描述;没有逐字来源时为 null(不编文案)。 */
52
+ description: string | null;
53
+ }
54
+ /** 一行能力去掉 `hint` 的样子:hint 由 {@link withHint} 从其余字段生成,不手写。 */
55
+ export type QoderModelFacts = Omit<QoderModelEntry, 'hint'>;
56
+ /**
57
+ * 上游 `/algo/api/v2/model/list` 的一个条目(**任何字段都可能缺失**)。
58
+ *
59
+ * 逐字 pi-provider `catalog.ts` 的 `QoderModelEntry`。`max_input_tokens` 是陈旧的
60
+ * 180K 地板(pi-provider 注释:even for models that accept 1M-token prompts),
61
+ * 所以上下文窗口只信 `context_config` 里最大的 `token_count`。
62
+ */
63
+ export interface QoderUpstreamModelRecord {
64
+ key?: unknown;
65
+ enable?: unknown;
66
+ display_name?: unknown;
67
+ max_input_tokens?: unknown;
68
+ context_config?: unknown;
69
+ is_vl?: unknown;
70
+ is_reasoning?: unknown;
71
+ thinking_config?: unknown;
72
+ source?: unknown;
73
+ description?: unknown;
74
+ }
75
+ /**
76
+ * 上游 `display_name` → 公开模型 id:去掉全部空白字符
77
+ * (逐字 pi-provider `toQoderModelId`:`replace(/\s+/g, "")`)。
78
+ */
79
+ export declare function toQoderModelId(displayName: string | undefined): string;
80
+ /** 上游 `context_config` → 上下文窗口:所有选项里最大的 `token_count`(pi-provider `contextWindowFromCatalog`)。 */
81
+ export declare function contextWindowFromRecord(record: QoderUpstreamModelRecord, region: QoderRegion): number;
82
+ /**
83
+ * 上游 `thinking_config` → 本线路的档位梯子。
84
+ *
85
+ * 逐字 pi-provider `buildThinkingLevelMap` 的两种形态:
86
+ *
87
+ * - **effort 形态**:`thinking_config.enabled.efforts` 的键集就是这个模型完整的档位集合
88
+ * (`none`/关闭值不在这个集合里,它在 `thinking_config.disabled` 里);
89
+ * - **toggle 形态**:`enabled` 存在但没有 `efforts`——只有开/关,没有档位,
90
+ * 梯子为空而 `thinkingDisableable` 照 `disabled` 是否存在决定。
91
+ *
92
+ * 认不出的档位名被丢弃而不是猜:上游加了一个我们没命名过的档位时,
93
+ * 猜一个近似的会让用户选到模型可能拒绝的值。
94
+ */
95
+ export declare function readQoderThinkingConfig(record: QoderUpstreamModelRecord): {
96
+ efforts: readonly QoderReasoningEffort[];
97
+ thinkingDisableable: boolean;
98
+ isReasoning: boolean;
99
+ };
100
+ /**
101
+ * 一行能力 → 落盘快照的条目:**快照读取侧的反格式**。
102
+ *
103
+ * 写成一处而不是各写一遍,是因为写入侧(client.ts 的 refreshQoderModelCatalog)与
104
+ * 读取侧(rehydrateQoderCatalogFromSnapshot)必须**互为反函数**。这两侧曾经对不上,
105
+ * 后果是静默的:写入侧存的是上游原始形状(`display_name` / `context_config`),
106
+ * 读取侧却拿 {@link parseQoderModelListing} 去解析它——那个解析器只认 `payload.chat`,
107
+ * 于是**任何**快照都解析成空数组,被当作「没有可用的快照」丢掉。冷启动于是永远
108
+ * 从兜底表起步,而磁盘上那份真实目录一次都没被读回来过。
109
+ *
110
+ * 形状与 {@link entryFromQoderRecord} 的输入完全对齐(`key` + `display_name` +
111
+ * `context_config.token_count`),所以真实载荷与快照走的是同一个解析器,字段缺了
112
+ * 也走同一套兜底。
113
+ */
114
+ export declare function persistedQoderModelRecord(entry: QoderModelEntry): QoderUpstreamModelRecord;
115
+ /**
116
+ * 解析**落盘快照**的 `models` 字段(`persistedQoderModelRecord` 写出去的那一组)。
117
+ *
118
+ * 单独一个函数而不是把 {@link parseQoderModelListing} 放宽成「也认得裸数组」:
119
+ * 那个函数读的是上游应答(`{ chat: [...] }`)的契约,让它同时接受另一种形状,
120
+ * 下一次有人改上游解析规则时就会顺手改坏快照的回读。两个形状,两个入口,一处口径。
121
+ *
122
+ * @returns 解析出的能力行;一个都解析不出时是空数组(调用方据此判「没有可用快照」)。
123
+ */
124
+ export declare function parsePersistedQoderModelEntries(value: unknown, region: QoderRegion): QoderModelEntry[];
125
+ /**
126
+ * 上游一个条目 → 一行能力。
127
+ *
128
+ * 每一个字段都按「端点说了就用,没说就走兜底」的顺序取值(计划 §4):
129
+ *
130
+ * - 公开 id:`display_name` 去空白;上行 key:`key`。两者缺一不可——
131
+ * 只有 id 没有 key 的条目发不出请求(`X-Model-Key` 是它的取值),跳过而不是猜。
132
+ * - `enable === false` 的条目跳过:它明说自己不可用。
133
+ * - 上下文窗口:`context_config` 最大 `token_count` → 区域兜底。
134
+ * - 思考:`thinking_config` / `is_reasoning`;输入模态:`is_vl`。
135
+ * - 输出上限:目录不报,取 {@link QODER_MAX_OUTPUT_TOKENS}。
136
+ */
137
+ export declare function entryFromQoderRecord(record: QoderUpstreamModelRecord, region: QoderRegion): QoderModelEntry | null;
138
+ /**
139
+ * 解析上游 `GET {base}/algo/api/v2/model/list?Encode=1` 的应答。
140
+ *
141
+ * 应答形状 `{ chat: [...] }`(逐字 pi-provider `updateQoderModelsCache` 的读取)。
142
+ * 无 key / 无 display_name / 显式 `enable:false` 的条目被丢弃。
143
+ *
144
+ * @returns 能力行,顺序与上游一致;解析不出任何东西时是空数组。
145
+ */
146
+ export declare function parseQoderModelListing(payload: unknown, region: QoderRegion): QoderModelEntry[];
147
+ /** 随包发布的全球区目录(能力兜底,登录后被运行时目录顶替)。 */
148
+ export declare const QODER_MODEL_CATALOG_GLOBAL: readonly QoderModelEntry[];
149
+ /** 随包发布的中国站目录。 */
150
+ export declare const QODER_MODEL_CATALOG_CN: readonly QoderModelEntry[];
151
+ /** 一个区域的随包兜底表。 */
152
+ export declare function bundledQoderCatalog(region: QoderRegion): readonly QoderModelEntry[];
153
+ /**
154
+ * 首次安装默认勾选的模型。
155
+ *
156
+ * 本线路的三态里「没挑过」是 `null`(不过滤),不是一张 id 表,所以这里刻意是
157
+ * 空数组、且**不再**参与设置装配——它只是历史常量,保留是为了不打断已有的导入面。
158
+ */
159
+ export declare const DEFAULT_VISIBLE_MODEL_IDS: readonly string[];
160
+ /**
161
+ * 未知模型的**未声明**行。
162
+ *
163
+ * 什么都不主张:`reasoningEfforts: []`(不发思考字段)、`supportsImages: false`
164
+ * (不认图比乱认图安全)、窗口取区域兜底。未声明行**默认可见**:协议面是固定的
165
+ * COSY 对话面,调它是合法的,未知的只是能力(与 step-code 同一决定,与 glm 相反)。
166
+ */
167
+ export declare function undeclaredQoderModelEntry(id: string, options?: {
168
+ region?: QoderRegion;
169
+ upstreamKey?: string;
170
+ }): QoderModelEntry;
171
+ /**
172
+ * 查一行模型能力;给定目录里没有时返回**未声明行**而不是 undefined。
173
+ * 先按公开 id 精确匹配,再按上游 key 匹配(请求面拿的是 key),都不中才未声明。
174
+ */
175
+ export declare function resolveQoderModel(id: string, catalog: readonly QoderModelEntry[], region?: QoderRegion): QoderModelEntry;
176
+ /** 该模型真实接受的思考档位;不在目录里时是空数组(即「不发任何思考控制字段」)。 */
177
+ export declare function qoderReasoningEfforts(id: string, catalog: readonly QoderModelEntry[]): readonly QoderReasoningEffort[];
178
+ /** 该模型的输出上限;不在目录里时取 {@link QODER_MAX_OUTPUT_TOKENS}。 */
179
+ export declare function maxOutputTokensFor(id: string, catalog: readonly QoderModelEntry[]): number;
180
+ /** 该模型的上下文窗口;不在目录里时取区域兜底。 */
181
+ export declare function defaultContextWindowFor(id: string, catalog: readonly QoderModelEntry[], region?: QoderRegion): number;
182
+ /** 目录里的全部公开 id。 */
183
+ export declare function listModelIds(catalog: readonly QoderModelEntry[]): string[];
184
+ /**
185
+ * 把用户存下来的白名单收敛到「这个部署此刻真的有的模型」上。
186
+ *
187
+ * 为什么必须收敛:白名单是用户昨天在**昨天的目录**上勾的,而本线路的目录是登录后
188
+ * 从上游实时发现的(随包表只是兜底)。上游下线一个模型、或用户换了一个区登录,
189
+ * 残留的 id 就会一直留在设置里——它既让「已选 N / M」的分子大于目录条目数,
190
+ * 也让卡片上出现一个勾着却根本不存在的行。
191
+ *
192
+ * 口径只有这一处:适配器的过滤(listModels)与状态面的勾选标记(getQoderStatus)
193
+ * 都从这里读,避免两边各写一份「什么算可用」而慢慢漂移。
194
+ *
195
+ * @param stored - 存下来的选择:`null` = 不过滤(原样返回 null),否则是白名单。
196
+ * @param available - 当前目录里真实存在的 id。
197
+ * @returns `null`(不过滤)或收敛后的白名单;保持 `stored` 的顺序并去重。
198
+ */
199
+ export declare function convergeQoderEnabledModelIds(stored: readonly string[] | null, available: readonly string[]): string[] | null;
200
+ /** 目录条目数,供 hub 概览显示「M 个模型可用」。 */
201
+ export declare function catalogSize(catalog: readonly QoderModelEntry[]): number;
202
+ /** {@link catalogSize} 的别名(与兄弟线路的调用形状一致)。 */
203
+ export declare const catalogTotal: typeof catalogSize;
204
+ /**
205
+ * 从一行能力生成设置卡上的一句话描述(四个要素:思考形态 / 档位 / 输入模态 / 上下文窗口)。
206
+ *
207
+ * 由数据生成而不是逐行手写,是为了让文案**不可能与能力表漂移**(同 step-code 的
208
+ * describeStepCodeModel,连理由都同源)。
209
+ */
210
+ export declare function describeQoderModel(entry: QoderModelEntry, prefix?: string): string;
211
+ /** 用户设置对目录装配的两处覆盖。 */
212
+ export interface QoderCatalogOptionOverrides {
213
+ /**
214
+ * 用户勾选的模型 id,**三态**(与 token-store 的 `QoderModelSettings` 同源):
215
+ *
216
+ * - `null` / 缺省 = 不过滤,目录里的每一行都勾上;
217
+ * - `[]` = 用户明确全关,一个都不勾;
218
+ * - 非空 = 白名单,只有列出的那些勾上。
219
+ */
220
+ enabledModelIds?: readonly string[] | null;
221
+ /** 逐模型上下文窗口覆盖;null / 非正数表示用目录默认值。 */
222
+ contextWindowOverrides?: Readonly<Record<string, number | null | undefined>>;
223
+ }
224
+ /**
225
+ * 把目录装配成设置面的模型行。
226
+ *
227
+ * `hint` 在这里生成(而不是写死在表里),所以「文案与能力表一致」是结构保证的。
228
+ * 未声明行**默认可见**(见 {@link undeclaredQoderModelEntry})。
229
+ */
230
+ export declare function catalogModelOptions(catalog: readonly QoderModelEntry[], overrides?: QoderCatalogOptionOverrides): QoderModelOption[];
231
+ //# sourceMappingURL=model-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-catalog.d.ts","sourceRoot":"","sources":["../../../../src/host/qoder/model-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Qoder(订阅)线路的登录:浏览器设备流(仅全球区)+ PAT 兑换 + 令牌刷新。
3
+ *
4
+ * 协议逐字来源:
5
+ *
6
+ * - 设备流(PKCE 风格 challenge/verifier + nonce 轮询,**不开本地回调端口**):
7
+ * qodercli2api \`docs/oauth.md\` §2(官方 CLI v1.1.34 的 frozen fixtures 互操作基线),
8
+ * 与 pi-provider \`src/auth/login.ts\`(live 验证)互相印证;
9
+ * - PAT 兑换:docs.qoder.com/cli/authentication(官方文档)+ pi-provider \`src/auth/pat.ts\`;
10
+ * - 刷新:pi-provider \`src/auth/oauth.ts\` \`refreshQoderTokenForMode\`(live 验证)。
11
+ *
12
+ * 与 step-code 的 oauth.ts 同构的部分(流程状态机外壳:flow / controller /
13
+ * getXxxLoginStatus / resetXxxLogin / takeXxxLoginCredential)是因为设置卡片跟随的是
14
+ * 同一组四个入口;与它的**差异**(凭据会过期、可刷新)全部集中在
15
+ * {@link refreshQoderCredential} 与凭据装配段。
16
+ *
17
+ * 凭据形状由 token-store.ts 的 \`QoderCredentials\` 定义;本文件只负责「把一次登录
18
+ * 变成一份凭据」,不持有凭据存储。
19
+ */
20
+ import type { QoderLoginFlowStatus, QoderRegion } from '../../shared/qoder-contracts.ts';
21
+ import { type QoderRequestOptions } from './client.ts';
22
+ import { type QoderCredentials } from './token-store.ts';
23
+ /**
24
+ * PKCE 风格参数。
25
+ *
26
+ * - verifier:43..128 字符(A-Z a-z 0-9 -._~)——32 字节 base64url 正好 43 字符;
27
+ * - challenge:base64url_nopad(SHA256(verifier));
28
+ * - nonce:random UUID;
29
+ * - machineId:36 字符 UUID(本机既有那把就用那把,见 cosy.ts 的读取顺序)。
30
+ */
31
+ export declare function createQoderDeviceParams(env?: NodeJS.ProcessEnv): {
32
+ verifier: string;
33
+ challenge: string;
34
+ nonce: string;
35
+ machineId: string;
36
+ };
37
+ /**
38
+ * 授权页 URL(host 拼,卡片打开)。
39
+ *
40
+ * 逐字 docs/oauth.md §2.1 的参数表(challenge / challenge_method=S256 / nonce /
41
+ * machine_id / client_id=官方 CLI 的固定值)。没有 scope、redirect URI 或本地回调。
42
+ */
43
+ export declare function qoderDeviceAuthorizeUrl(params: {
44
+ challenge: string;
45
+ nonce: string;
46
+ machineId: string;
47
+ }): string;
48
+ /** 一次轮询的三种结果。 */
49
+ export type QoderDevicePoll = {
50
+ readonly state: 'pending';
51
+ } | {
52
+ readonly state: 'ready';
53
+ readonly token: string;
54
+ readonly userId: string | null;
55
+ readonly refreshToken: string | null;
56
+ readonly expiresAt: number;
57
+ } | {
58
+ readonly state: 'failed';
59
+ readonly reason: string;
60
+ };
61
+ /**
62
+ * GET {openapi}/api/v1/deviceToken/poll?nonce=…&verifier=…&challenge_method=S256。
63
+ *
64
+ * 逐字 docs/oauth.md §2.2 与 pi-provider \`login.ts\` 的状态语义:
65
+ *
66
+ * - 404 / 202 = pending(用户还没在浏览器里确认);
67
+ * - 200 = 取 token(**缺 token 的 200 立即失败**——看形状,不只看状态码);
68
+ * - 其余非 2xx = 立即失败;
69
+ * - transport 错误由外层轮询循环按间隔重试(到截止为止),不在这里判死。
70
+ */
71
+ export declare function pollQoderDeviceToken(params: {
72
+ nonce: string;
73
+ verifier: string;
74
+ }, options?: QoderRequestOptions): Promise<QoderDevicePoll>;
75
+ /**
76
+ * 设备流轮询结果 → 落盘凭据。
77
+ *
78
+ * userinfo 是 best-effort 的补齐(uid 缺失会让 CN 拒成 105;全球区的设备流
79
+ * 轮询自己带 \`user_id\`),补齐失败不使登录失败(docs/oauth.md §2:
80
+ * enrichment 失败不使登录失败)。
81
+ */
82
+ export declare function qoderCredentialsFromDevicePoll(ready: {
83
+ token: string;
84
+ userId: string | null;
85
+ refreshToken: string | null;
86
+ expiresAt: number;
87
+ }, machineId: string, options?: QoderRequestOptions): Promise<QoderCredentials>;
88
+ /**
89
+ * PAT → 落盘凭据。
90
+ *
91
+ * 兑换 + userinfo 补齐;**PAT 本体留在凭据里**(host-only),因为 PAT 的「刷新」
92
+ * 就是拿它重新兑换一把 job token(pi-provider 把 PAT 编进 refresh 字段,
93
+ * 本线路把它放进一个具名字段——同一件事,更好读)。
94
+ */
95
+ export declare function qoderCredentialsFromPat(personalToken: string, region: QoderRegion, options?: QoderRequestOptions): Promise<QoderCredentials>;
96
+ /**
97
+ * 刷新一份凭据(号池 refresh 钩子的实现)。
98
+ *
99
+ * 两条路径(凭据的 origin 决定):
100
+ *
101
+ * - **PAT**:拿存下的 PAT 重新兑换(pi-provider 的 isPatRefresh 路径同一做法);
102
+ * - **其余**:\`refreshToken\` 走 center 刷新端点;没有 refreshToken 的凭据
103
+ * 无法刷新,抛出明确的错误(号池据此把账号标成需要重新登录)。
104
+ *
105
+ * 失败带上 \`status\`(有 HTTP 状态时),号池据此分类「这个账号要重登」还是
106
+ * 「瞬时故障,别判死」。
107
+ */
108
+ export declare function refreshQoderCredential(credentials: QoderCredentials, fetchFn?: typeof fetch): Promise<QoderCredentials>;
109
+ /** 卡片轮询的状态切片。返回副本,调用方改不到内部状态。 */
110
+ export declare function getQoderLoginStatus(): QoderLoginFlowStatus;
111
+ /** 取消进行中的流程并回到 idle(设置卡片的「取消」)。 */
112
+ export declare function resetQoderLogin(): void;
113
+ /** 看看有没有一份已经拿到、还没被取走的凭据(纯内存读)。 */
114
+ export declare function peekQoderLoginCredential(): QoderCredentials | null;
115
+ /** 取走那份凭据并清空(同一份凭据只该被落盘一次)。 */
116
+ export declare function takeQoderLoginCredential(): QoderCredentials | null;
117
+ export interface QoderLoginOptions {
118
+ /** 测试缝。默认 fetch。 */
119
+ fetchFn?: typeof fetch;
120
+ env?: NodeJS.ProcessEnv;
121
+ /** 完成的登录写到哪里(接入层传号池的保存函数)。 */
122
+ onSave?: (credential: QoderCredentials) => Promise<unknown>;
123
+ /** 本地总时限;缺省 10 分钟,可由 QODER_LOGIN_TIMEOUT_MS 覆盖。 */
124
+ timeoutMs?: number;
125
+ }
126
+ /**
127
+ * 开始一次浏览器设备流登录(**仅全球区**;CN 没有设备流,走 PAT 或 adopt)。
128
+ *
129
+ * 流程跑在 host 上(controller + flow),设置卡片只跟随 getQoderLoginStatus——
130
+ * 与其余各线路的登录面同构。轮询节奏 2 秒一次,总超时取本地总时限
131
+ * (服务端对 verifier 的硬截止由 404→failed 的翻转表达)。
132
+ */
133
+ export declare function beginQoderLogin(region: QoderRegion, options?: QoderLoginOptions): Promise<QoderLoginFlowStatus>;
134
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../src/host/qoder/oauth.ts"],"names":[],"mappings":"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"}