@eddyskywalker/dsh-chatgpt-subscription 0.2.20 → 0.3.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 (78) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +116 -1
  3. package/lib/client.js +2825 -512
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +8758 -352
  6. package/lib/types/client/ProviderHubSection.d.ts +15 -0
  7. package/lib/types/client/ProviderHubSection.d.ts.map +1 -0
  8. package/lib/types/client/command-code/CommandCodeComposerQuota.d.ts +24 -0
  9. package/lib/types/client/command-code/CommandCodeComposerQuota.d.ts.map +1 -0
  10. package/lib/types/client/command-code/CommandCodeSection.d.ts +11 -0
  11. package/lib/types/client/command-code/CommandCodeSection.d.ts.map +1 -0
  12. package/lib/types/client/command-code/locales.d.ts +401 -0
  13. package/lib/types/client/command-code/locales.d.ts.map +1 -0
  14. package/lib/types/client/index.d.ts +2 -0
  15. package/lib/types/client/index.d.ts.map +1 -1
  16. package/lib/types/client/kimi-code/KimiCodeComposerQuota.d.ts +25 -0
  17. package/lib/types/client/kimi-code/KimiCodeComposerQuota.d.ts.map +1 -0
  18. package/lib/types/client/kimi-code/KimiCodeSection.d.ts +11 -0
  19. package/lib/types/client/kimi-code/KimiCodeSection.d.ts.map +1 -0
  20. package/lib/types/client/kimi-code/KimiModelCapabilities.d.ts +16 -0
  21. package/lib/types/client/kimi-code/KimiModelCapabilities.d.ts.map +1 -0
  22. package/lib/types/client/kimi-code/locales.d.ts +665 -0
  23. package/lib/types/client/kimi-code/locales.d.ts.map +1 -0
  24. package/lib/types/client/kimi-code/styles.d.ts +4 -0
  25. package/lib/types/client/kimi-code/styles.d.ts.map +1 -0
  26. package/lib/types/client/locales.d.ts +3 -1
  27. package/lib/types/client/locales.d.ts.map +1 -1
  28. package/lib/types/client/styles.d.ts.map +1 -1
  29. package/lib/types/host/antigravity/adapter.d.ts +2 -0
  30. package/lib/types/host/antigravity/adapter.d.ts.map +1 -1
  31. package/lib/types/host/antigravity/mapper.d.ts +51 -2
  32. package/lib/types/host/antigravity/mapper.d.ts.map +1 -1
  33. package/lib/types/host/command-code/adapter.d.ts +34 -0
  34. package/lib/types/host/command-code/adapter.d.ts.map +1 -0
  35. package/lib/types/host/command-code/client.d.ts +99 -0
  36. package/lib/types/host/command-code/client.d.ts.map +1 -0
  37. package/lib/types/host/command-code/mapper.d.ts +102 -0
  38. package/lib/types/host/command-code/mapper.d.ts.map +1 -0
  39. package/lib/types/host/command-code/model-catalog.d.ts +31 -0
  40. package/lib/types/host/command-code/model-catalog.d.ts.map +1 -0
  41. package/lib/types/host/command-code/oauth.d.ts +89 -0
  42. package/lib/types/host/command-code/oauth.d.ts.map +1 -0
  43. package/lib/types/host/command-code/plans.d.ts +40 -0
  44. package/lib/types/host/command-code/plans.d.ts.map +1 -0
  45. package/lib/types/host/command-code/routes.d.ts +27 -0
  46. package/lib/types/host/command-code/routes.d.ts.map +1 -0
  47. package/lib/types/host/command-code/token-store.d.ts +88 -0
  48. package/lib/types/host/command-code/token-store.d.ts.map +1 -0
  49. package/lib/types/host/command-code/types.d.ts +138 -0
  50. package/lib/types/host/command-code/types.d.ts.map +1 -0
  51. package/lib/types/host/kimi-code/adapter.d.ts +112 -0
  52. package/lib/types/host/kimi-code/adapter.d.ts.map +1 -0
  53. package/lib/types/host/kimi-code/client.d.ts +161 -0
  54. package/lib/types/host/kimi-code/client.d.ts.map +1 -0
  55. package/lib/types/host/kimi-code/mapper.d.ts +334 -0
  56. package/lib/types/host/kimi-code/mapper.d.ts.map +1 -0
  57. package/lib/types/host/kimi-code/modalities.d.ts +94 -0
  58. package/lib/types/host/kimi-code/modalities.d.ts.map +1 -0
  59. package/lib/types/host/kimi-code/model-catalog.d.ts +77 -0
  60. package/lib/types/host/kimi-code/model-catalog.d.ts.map +1 -0
  61. package/lib/types/host/kimi-code/oauth.d.ts +133 -0
  62. package/lib/types/host/kimi-code/oauth.d.ts.map +1 -0
  63. package/lib/types/host/kimi-code/routes.d.ts +26 -0
  64. package/lib/types/host/kimi-code/routes.d.ts.map +1 -0
  65. package/lib/types/host/kimi-code/token-store.d.ts +135 -0
  66. package/lib/types/host/kimi-code/token-store.d.ts.map +1 -0
  67. package/lib/types/host/kimi-code/types.d.ts +174 -0
  68. package/lib/types/host/kimi-code/types.d.ts.map +1 -0
  69. package/lib/types/host/relay-probe.d.ts +161 -0
  70. package/lib/types/host/relay-probe.d.ts.map +1 -0
  71. package/lib/types/host/responses-client.d.ts.map +1 -1
  72. package/lib/types/index.d.ts +13 -0
  73. package/lib/types/index.d.ts.map +1 -1
  74. package/lib/types/shared/command-code-contracts.d.ts +119 -0
  75. package/lib/types/shared/command-code-contracts.d.ts.map +1 -0
  76. package/lib/types/shared/kimi-code-contracts.d.ts +203 -0
  77. package/lib/types/shared/kimi-code-contracts.d.ts.map +1 -0
  78. package/package.json +1 -1
@@ -0,0 +1,334 @@
1
+ /**
2
+ * Provider-wire mapping for the Kimi Code coding endpoints.
3
+ *
4
+ * Two surfaces serve the same models:
5
+ *
6
+ * - the OpenAI-compatible `/coding/v1/chat/completions`, which is what the
7
+ * official CLI configures for its managed provider and therefore the default
8
+ * here; and
9
+ * - the Anthropic-compatible `/coding/v1/messages?beta=true`, which authenticates
10
+ * with `x-api-key` rather than a bearer token.
11
+ *
12
+ * Both are mapped here, and both streams are normalized into DSH's block/delta
13
+ * vocabulary.
14
+ *
15
+ * Two Kimi-specific behaviours shape the request builders:
16
+ *
17
+ * 1. Thinking is selected with `reasoning_effort` and accepts only
18
+ * low/high/max; anything else the client sends is answered with HTTP 400, so
19
+ * a caller's broader effort vocabulary is narrowed here rather than passed
20
+ * through. Thinking off is expressed as `thinking: {type: "disabled"}`.
21
+ * 2. When thinking is on, Kimi requires `reasoning_content` on an assistant
22
+ * message that also carries tool calls — the service answers 400
23
+ * "thinking is enabled but reasoning_content is missing" otherwise. Reasoning
24
+ * blocks are therefore replayed on the OpenAI wire, unlike the sibling routes
25
+ * which drop them.
26
+ *
27
+ * See https://www.kimi.com/code/docs/en/kimi-code/error-reference.html
28
+ */
29
+ import { type ContentBlock, type GenerateOptions, type Message, type StreamChunk } from '@deepseek-ai/dsh-llm';
30
+ import type { AttachmentStore } from '@deepseek-ai/dsh-attachment';
31
+ import { type VideoAttachmentRef } from './modalities.ts';
32
+ import type { KimiCodeReasoningEffort, KimiCodeWire } from '../../shared/kimi-code-contracts.ts';
33
+ /**
34
+ * Kimi caps a tool-call id at 64 characters and rejects a longer one.
35
+ *
36
+ * DSH ids are usually short, but a provider that prefixes them with a session
37
+ * or turn marker can exceed the bound, so a long id is truncated
38
+ * deterministically rather than allowed to fail the whole request.
39
+ */
40
+ export declare function clampToolCallId(id: string): string;
41
+ /**
42
+ * Service limits on the request shape, from the official error reference.
43
+ *
44
+ * Both were documented as hard 400s, so exceeding them costs the whole turn
45
+ * rather than degrading gracefully — which is why the request is trimmed to fit
46
+ * instead of being sent and rejected.
47
+ */
48
+ export declare const MAX_STOP_SEQUENCES = 5;
49
+ export declare const MAX_STOP_SEQUENCE_BYTES = 32;
50
+ /**
51
+ * Whether one request asks the service to keep reasoning across turns.
52
+ *
53
+ * Kimi's models reason by default and the official CLI ships Preserved Thinking
54
+ * ON (`[thinking] keep = "all"`), which is what its own error reference assumes
55
+ * when it demands `reasoning_content` on every assistant message. An
56
+ * environment opt-out exists for a deployment that would rather not pay for the
57
+ * replayed reasoning tokens.
58
+ */
59
+ export declare function preserveThinkingEnabled(env?: NodeJS.ProcessEnv): boolean;
60
+ /**
61
+ * Trim stop sequences to what the service accepts.
62
+ *
63
+ * At most five entries, each at most 32 bytes; a longer sequence is dropped
64
+ * rather than truncated, because a shortened stop string would halt generation
65
+ * at the wrong place — silently changing the answer is worse than not stopping.
66
+ */
67
+ export declare function stopSequences(stop: readonly string[] | undefined): string[];
68
+ /**
69
+ * Narrow a caller's effort onto the levels Kimi accepts.
70
+ *
71
+ * DSH exposes low/high/max/none for these models, but a conversation can hold
72
+ * an effort chosen for a different provider, so the broader vocabulary the rest
73
+ * of the plugin uses is mapped rather than rejected: an unknown value would be
74
+ * answered with HTTP 400 and fail the turn.
75
+ */
76
+ export declare function mapReasoningEffort(effort: string | undefined | null): KimiCodeReasoningEffort | undefined;
77
+ /**
78
+ * Thinking-token budget one Anthropic-route level asks for.
79
+ *
80
+ * Kimi's Anthropic surface takes the standard `thinking` block, so the budget is
81
+ * derived from the same three levels the OpenAI surface uses.
82
+ */
83
+ export declare function thinkingBudgetFor(effort: KimiCodeReasoningEffort | undefined, maxTokens: number): number | undefined;
84
+ /** Attachment seam this route needs: verified bytes for one durable image. */
85
+ export type AttachmentImageReader = Pick<AttachmentStore, 'readImage'>;
86
+ /** One durable user image resolved for an in-flight request, or proven unreadable. */
87
+ export type ResolvedRequestImage = {
88
+ readonly kind: 'inline';
89
+ readonly mediaType: string;
90
+ readonly data: string;
91
+ } | {
92
+ readonly kind: 'unavailable';
93
+ };
94
+ /** Resolved images keyed by durable attachment id; consumed by one request build. */
95
+ export type ResolvedRequestImages = ReadonlyMap<string, ResolvedRequestImage>;
96
+ /**
97
+ * Base64 image payload one request may carry.
98
+ *
99
+ * Kimi rejects a request whose total message size exceeds 2 MB with a 400, and
100
+ * the image bytes share that budget with the conversation text, tool schemas,
101
+ * and system prompt — so the bound is deliberately the smaller of the two
102
+ * documented limits rather than the largest body the transport would accept.
103
+ */
104
+ export declare const MAX_REQUEST_IMAGE_BYTES = 1500000;
105
+ /** Message-body ceiling the service documents for one request. */
106
+ export declare const MAX_MESSAGE_BODY_BYTES = 2097152;
107
+ /**
108
+ * Body ceiling once a request carries video.
109
+ *
110
+ * The 2 MB figure above is the documented limit for text and images, and it is
111
+ * far too small for video: a single frame-sequence clip dwarfs it. Kimi's own
112
+ * video guidance carries a separate, much larger request budget, so the ceiling
113
+ * is raised only for a request that actually attaches video. A text-only or
114
+ * image-only request keeps the tighter guard, because catching that 400 locally
115
+ * is the whole reason it exists.
116
+ */
117
+ export declare const MAX_VIDEO_MESSAGE_BODY_BYTES: number;
118
+ /**
119
+ * Base64 video budget for one request.
120
+ *
121
+ * Deliberately below {@link MAX_VIDEO_MESSAGE_BODY_BYTES} so the surrounding
122
+ * JSON envelope, tool schemas and text still fit; the oldest clips are dropped
123
+ * first once the total would exceed it.
124
+ */
125
+ export declare const MAX_REQUEST_VIDEO_BYTES: number;
126
+ /**
127
+ * Replace the oldest inline images with a text placeholder once one request
128
+ * would carry more than {@link MAX_REQUEST_IMAGE_BYTES} of base64 image data.
129
+ * Durable history is untouched; only the request about to be sent changes.
130
+ */
131
+ export declare function offloadOldestRequestImages(options: GenerateOptions): GenerateOptions;
132
+ /**
133
+ * Read every durable `{ type: 'image', attachment }` block one request carries.
134
+ * An unreadable image resolves to `unavailable` rather than disappearing, so
135
+ * the model is told the picture is missing instead of answering about a blank.
136
+ */
137
+ export declare function resolveRequestImages(options: GenerateOptions, attachments: AttachmentImageReader | undefined, signal?: AbortSignal): Promise<ResolvedRequestImages>;
138
+ /**
139
+ * One durable video resolved for an in-flight request, or proven unreadable.
140
+ *
141
+ * The shape mirrors {@link ResolvedRequestImage} so the two media kinds travel
142
+ * the same path and differ only in the wire part each produces.
143
+ */
144
+ export type ResolvedRequestVideo = {
145
+ readonly kind: 'inline';
146
+ readonly mediaType: string;
147
+ readonly data: string;
148
+ } | {
149
+ readonly kind: 'unavailable';
150
+ };
151
+ /** Resolved videos keyed by attachment id; consumed by one request build. */
152
+ export type ResolvedRequestVideos = ReadonlyMap<string, ResolvedRequestVideo>;
153
+ /**
154
+ * Attachment seam for video bytes.
155
+ *
156
+ * DSH's own attachment service stores images only, so a video reference can
157
+ * only exist if some producer in this deployment created it. Rather than
158
+ * pretend otherwise, the reader is an injected seam: absent means every video
159
+ * resolves to `unavailable` and the model is told the clip is missing, which is
160
+ * strictly better than silently sending a request with no video at all.
161
+ */
162
+ export type AttachmentVideoReader = {
163
+ readVideo(ref: VideoAttachmentRef, signal?: AbortSignal): Promise<{
164
+ data: Uint8Array;
165
+ mediaType: string;
166
+ }>;
167
+ };
168
+ /**
169
+ * Drop the oldest videos once one request would carry more than
170
+ * {@link MAX_REQUEST_VIDEO_BYTES} of base64 video data, replacing each with a
171
+ * text placeholder. Durable history is untouched; only the request about to be
172
+ * sent changes. Images are left alone — they have their own, much smaller
173
+ * budget and their own offload pass.
174
+ */
175
+ export declare function offloadOldestRequestVideos(options: GenerateOptions): GenerateOptions;
176
+ /**
177
+ * Read every durable `{ type: 'video', attachment }` block one request carries.
178
+ * An unreadable clip resolves to `unavailable` rather than disappearing, so the
179
+ * model is told the video is missing instead of answering about a blank.
180
+ */
181
+ export declare function resolveRequestVideos(options: GenerateOptions, attachments: AttachmentVideoReader | undefined, signal?: AbortSignal): Promise<ResolvedRequestVideos>;
182
+ /** True when the request carries any video occurrence at all. */
183
+ export declare function requestHasVideo(options: GenerateOptions): boolean;
184
+ /**
185
+ * Media a single request build may carry.
186
+ *
187
+ * Passed as one object so adding a media kind never grows a positional
188
+ * signature the existing callers already bind.
189
+ */
190
+ export interface RequestMediaOptions {
191
+ /** Videos read for this request; absent means none are readable. */
192
+ videos?: ResolvedRequestVideos;
193
+ /** Whether the selected model declares video input. */
194
+ videoAccepted?: boolean;
195
+ /**
196
+ * Whether the selected model accepts message-level tool declarations
197
+ * (`messages[].tools`), Kimi's `dynamically_loaded_tools` capability.
198
+ */
199
+ messageTools?: boolean;
200
+ }
201
+ /** Drop the JSON-Schema keywords provider gateways reject or ignore. */
202
+ export declare function stripMetaSchema(schema: unknown): Record<string, unknown>;
203
+ /**
204
+ * One complete tool definition, in the shape the function-calling wire wants.
205
+ *
206
+ * The service rejects a bare tool name: a message-level declaration must carry
207
+ * the same name/description/parameters triple the top-level list carries, so
208
+ * the caller cannot pass a reference and let the model guess.
209
+ */
210
+ export interface DynamicToolDeclaration {
211
+ name: string;
212
+ description: string;
213
+ parameters: Record<string, unknown>;
214
+ }
215
+ /**
216
+ * A tool declaration that belongs to a message rather than the request.
217
+ *
218
+ * DSH has no message-level tool field, so the producer sets this symbol on a
219
+ * system-role {@link Message} to ask for one. A symbol is used rather than a
220
+ * string key because every other reader of a message — the session log, the
221
+ * transcript UI, another adapter — must not start seeing a field it cannot
222
+ * honor; the property is invisible to them and only this mapper looks for it.
223
+ */
224
+ export declare const MESSAGE_TOOLS: unique symbol;
225
+ /** Attach message-level tool declarations to one system message. */
226
+ export declare function withMessageTools<T extends Message>(message: T, tools: readonly DynamicToolDeclaration[]): T;
227
+ /** Message-level tool declarations one message carries, when any. */
228
+ export declare function messageToolsOf(message: Message): readonly DynamicToolDeclaration[] | undefined;
229
+ /**
230
+ * Rough prompt size for one request, in tokens.
231
+ *
232
+ * Derived from the serialized text with the usual ~4 characters per token
233
+ * heuristic. It is deliberately an estimate: the purpose is only to keep
234
+ * `max_tokens` from making a request the service will reject outright, and the
235
+ * service's own count remains authoritative. Undefined is returned for an empty
236
+ * request so the caller leaves the cap alone rather than clamping against zero.
237
+ */
238
+ export declare function estimatedInputTokens(options: GenerateOptions): number | undefined;
239
+ /** Build one `/chat/completions` body. */
240
+ export declare function buildOpenAIRequest(options: GenerateOptions, images?: ResolvedRequestImages, preserveThinking?: boolean, media?: RequestMediaOptions): Record<string, unknown>;
241
+ /**
242
+ * Stable identifier for the conversation this request belongs to.
243
+ *
244
+ * Derived from the first user turn rather than a fresh value per request, so it
245
+ * stays identical across the steps of one session and changes when a new
246
+ * conversation starts.
247
+ */
248
+ export declare function promptCacheKey(options: GenerateOptions): string | undefined;
249
+ /** Build one `/v1/messages` body. */
250
+ export declare function buildAnthropicRequest(options: GenerateOptions, images?: ResolvedRequestImages, _media?: RequestMediaOptions): Record<string, unknown>;
251
+ /** Build the body for whichever endpoint serves `wire`. */
252
+ export declare function buildRequest(options: GenerateOptions, wire: KimiCodeWire, images?: ResolvedRequestImages, preserveThinking?: boolean, media?: RequestMediaOptions): Record<string, unknown>;
253
+ /**
254
+ * Reject a request the service would answer with its 2 MB body 400.
255
+ *
256
+ * This is the most frequently reported 400 on the coding endpoint, and it is
257
+ * worth catching locally for two reasons: the message can name the actual
258
+ * remedy (DSH's compaction), and a request that cannot succeed should not be
259
+ * sent at all. The measured size is the real serialized body, so it accounts
260
+ * for tool schemas and inlined images the caller cannot easily estimate.
261
+ */
262
+ export declare function assertRequestBodyFits(body: Record<string, unknown>): void;
263
+ /** One tool call accumulating across `chat/completions` deltas. */
264
+ interface PendingToolCall {
265
+ blockIndex: number;
266
+ id: string;
267
+ name: string;
268
+ arguments: string;
269
+ started: boolean;
270
+ }
271
+ export interface KimiCodeStreamState {
272
+ wire: KimiCodeWire;
273
+ blocks: ContentBlock[];
274
+ current: {
275
+ index: number;
276
+ type: 'text' | 'reasoning';
277
+ text: string;
278
+ } | null;
279
+ /** wire tool index -> accumulating call (OpenAI route). */
280
+ toolCalls: Map<number, PendingToolCall>;
281
+ /** anthropic content-block index -> our block index. */
282
+ contentIndexes: Map<number, number>;
283
+ /** anthropic content index of the block currently open. */
284
+ openContentIndex: number | null;
285
+ hasContent: boolean;
286
+ hasToolCall: boolean;
287
+ finishReason: string | null;
288
+ done: boolean;
289
+ finished: boolean;
290
+ inputTokens: number;
291
+ outputTokens: number;
292
+ cacheReadTokens: number;
293
+ cacheWriteTokens: number;
294
+ reasoningTokens: number;
295
+ sawUsage: boolean;
296
+ }
297
+ export declare function createStreamState(wire: KimiCodeWire): KimiCodeStreamState;
298
+ /** Feed one SSE `data:` payload from `/chat/completions`. */
299
+ export declare function processOpenAIStreamLine(line: string, state: KimiCodeStreamState): StreamChunk[];
300
+ /** Feed one SSE `data:` payload from `/v1/messages`. */
301
+ export declare function processAnthropicStreamLine(line: string, state: KimiCodeStreamState): StreamChunk[];
302
+ /**
303
+ * Rolling per-process view of how well the prefix cache is working.
304
+ *
305
+ * Kimi's cache is automatic and content-hash based, so the only way to know
306
+ * whether a session is actually benefiting is to watch the read ratio. It is a
307
+ * diagnostic: nothing here changes a request.
308
+ */
309
+ export interface KimiCodeCacheStats {
310
+ /** Requests that reported usage. */
311
+ requests: number;
312
+ /** Prompt tokens that were served from cache. */
313
+ cachedTokens: number;
314
+ /** Prompt tokens that had to be processed fresh. */
315
+ freshTokens: number;
316
+ /** Output tokens, which reasoning is billed against. */
317
+ outputTokens: number;
318
+ /** Prompt tokens the provider counted as cache writes (always 0 on this route). */
319
+ cacheWriteTokens: number;
320
+ }
321
+ /** Record one request's usage into the rolling totals. */
322
+ export declare function recordCacheStats(state: KimiCodeStreamState): void;
323
+ /** Current rolling totals, plus the derived hit ratio. */
324
+ export declare function getCacheStats(): KimiCodeCacheStats & {
325
+ hitRatio: number | null;
326
+ };
327
+ /** Test seam and an explicit reset for a new session. */
328
+ export declare function resetCacheStats(): void;
329
+ /** Flush every open block, then emit usage and the terminal finish. */
330
+ export declare function closeStream(state: KimiCodeStreamState): StreamChunk[];
331
+ /** Model families whose stream never carried a terminal event. */
332
+ export declare function assertStreamComplete(state: KimiCodeStreamState): void;
333
+ export {};
334
+ //# sourceMappingURL=mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../../src/host/kimi-code/mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Kimi Code's extra request modalities, declared into DSH's provider-neutral
3
+ * vocabularies by this plugin alone.
4
+ *
5
+ * DSH ships ModelModalityMap = { text, image } and a ContentBlockMap with no
6
+ * video entry, but both are merge-extensible interfaces: a plugin may widen
7
+ * them with a TypeScript module augmentation. That is what this file does, so
8
+ * Kimi's documented video_in capability can travel through DSH's real
9
+ * capability pipeline - the same one that gates read_image, prompt admission,
10
+ * and subagent delegation - instead of being display-only trivia in a tooltip.
11
+ *
12
+ * Nothing here modifies DSH. The augmentation lives in this plugin's
13
+ * compilation unit; DSH's own sources keep compiling against the two
14
+ * modalities they already know.
15
+ *
16
+ * The block shape deliberately mirrors ImageAttachmentRef field for field.
17
+ * DSH itself never constructs a video block - the attachment service only
18
+ * promotes images - so the only readers are this plugin's request mapper and
19
+ * its tests.
20
+ */
21
+ /**
22
+ * Container formats the Kimi coding endpoint accepts as video input.
23
+ *
24
+ * Transcribed from the official vision guide and file-upload reference; the
25
+ * service validates the media type, so an unlisted container is reported
26
+ * before it is base64-expanded into a request that would be rejected.
27
+ */
28
+ export declare const KIMI_VIDEO_MEDIA_TYPES: readonly string[];
29
+ /** Runtime membership test for one video container. */
30
+ export declare function isVideoMediaType(mediaType: string): boolean;
31
+ /**
32
+ * One durable video reference carried by a request.
33
+ *
34
+ * attachmentId is a plain string rather than DSH's branded AttachmentId: no
35
+ * DSH service issues this identifier, so branding it would imply an origin
36
+ * that does not exist. The field name matches ImageAttachmentRef so one
37
+ * traversal helper can walk both block kinds.
38
+ */
39
+ export interface VideoAttachmentRef {
40
+ attachmentId: string;
41
+ /** Verified media type, for example video/mp4. */
42
+ mediaType: string;
43
+ /** Exact encoded byte length. */
44
+ bytes: number;
45
+ /** Intrinsic duration in milliseconds, when the producer knows it. */
46
+ durationMs?: number;
47
+ /** Optional display name, stripped of any local path. */
48
+ name?: string;
49
+ }
50
+ /** One video occurrence in message content. */
51
+ export interface VideoBlock {
52
+ type: 'video';
53
+ attachment: VideoAttachmentRef;
54
+ }
55
+ declare module '@deepseek-ai/dsh-llm' {
56
+ interface ModelModalityMap {
57
+ /** Widened by this plugin: Kimi's k3 and kimi-for-coding accept video. */
58
+ video: 'video';
59
+ }
60
+ interface ContentBlockMap {
61
+ /** Widened by this plugin; only the Kimi Code mapper reads it. */
62
+ video: VideoBlock;
63
+ }
64
+ }
65
+ /** Base64 length of raw bytes, including padding. */
66
+ export declare function base64LengthOf(bytes: number): number;
67
+ /** Canonical data URL the OpenAI-compatible video part carries. */
68
+ export declare function videoDataUrl(mediaType: string, base64: string): string;
69
+ /**
70
+ * Human-readable byte size for a refusal message.
71
+ * @param bytes - exact encoded byte length.
72
+ */
73
+ export declare function formatMediaBytes(bytes: number): string;
74
+ /** Why one video occurrence was replaced by text instead of being sent. */
75
+ export type VideoOmissionReason = 'unsupported-model' | 'unreadable' | 'unsupported-container'
76
+ /** The selected protocol has no documented video part, so none is sent. */
77
+ | 'unsupported-wire';
78
+ /**
79
+ * Deterministic text standing in for a video the request cannot carry.
80
+ *
81
+ * The model is told the video existed and why it is absent, so it asks for a
82
+ * description instead of answering as though the message were empty.
83
+ * @param reason - why the occurrence was omitted.
84
+ * @param label - display name or attachment id, when known.
85
+ */
86
+ export declare function videoOmissionText(reason: VideoOmissionReason, label?: string): string;
87
+ /** Attachment id or display name for one block, whichever is present. */
88
+ export declare function videoBlockLabel(block: {
89
+ attachment?: {
90
+ name?: string;
91
+ attachmentId?: string;
92
+ };
93
+ }): string | undefined;
94
+ //# sourceMappingURL=modalities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modalities.d.ts","sourceRoot":"","sources":["../../../../src/host/kimi-code/modalities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAUnD,CAAA;AAED,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAA;IACpB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAA;IACjB,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,UAAU,EAAE,kBAAkB,CAAA;CAC/B;AAED,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,gBAAgB;QACxB,0EAA0E;QAC1E,KAAK,EAAE,OAAO,CAAA;KACf;IAED,UAAU,eAAe;QACvB,kEAAkE;QAClE,KAAK,EAAE,UAAU,CAAA;KAClB;CACF;AAED,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtE;AACD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,2EAA2E;AAC3E,MAAM,MAAM,mBAAmB,GAC3B,mBAAmB,GACnB,YAAY,GACZ,uBAAuB;AACzB,2EAA2E;GACzE,kBAAkB,CAAA;AAEtB;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAYrF;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,UAAU,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAIpH"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Static catalog of the models the Kimi Code subscription serves.
3
+ *
4
+ * Transcribed from the official model table at
5
+ * https://www.kimi.com/code/docs/en/kimi-code/models.html. Model version names
6
+ * (K3, K2.8 Preview) are NOT valid request ids: only the ids below may appear in
7
+ * a request body, or the service answers 401 "Your model id does not exist".
8
+ */
9
+ import type { KimiCodeReasoningEffort } from '../../shared/kimi-code-contracts.ts';
10
+ /** One model the Kimi Code endpoint serves to subscription accounts. */
11
+ export interface KimiCodeCatalogModel {
12
+ /** Exact model id to put on the wire. */
13
+ id: string;
14
+ /** Display name shown in the picker. */
15
+ name: string;
16
+ /** Marketing version the id maps to, e.g. K3. */
17
+ version: string;
18
+ /**
19
+ * Context window used unless the user overrides it.
20
+ *
21
+ * For `k3` this is deliberately the Moderato-tier 256K bound rather than the
22
+ * 1M the model can reach: the server rejects a request that exceeds the
23
+ * signed-in plan's entitlement with a 401, so a session that silently grew
24
+ * past 256K on a Moderato account would fail hard instead of compacting.
25
+ * Allegretto-and-above users raise it with the context-window override.
26
+ */
27
+ contextWindow: number;
28
+ /** Context the highest tier unlocks, when it is larger than {@link contextWindow}. */
29
+ maxContextWindow: number | null;
30
+ /** Output cap requested when the caller omits one. */
31
+ maxTokens: number;
32
+ /** Input the model accepts; DSH only maps the text and image entries. */
33
+ inputModalities: readonly ('text' | 'image' | 'video')[];
34
+ /** Thinking levels the model accepts, in escalating order. */
35
+ reasoningEfforts: readonly KimiCodeReasoningEffort[];
36
+ /** Thinking level used when the conversation does not pick one. */
37
+ defaultReasoningEffort: KimiCodeReasoningEffort | null;
38
+ /** Subscription tier needed for the full model, when not every member has it. */
39
+ minimumPlan: string | null;
40
+ /** Subscription tier needed for the full context window, when it differs. */
41
+ contextPlan: string | null;
42
+ /** One-line description from the official table. */
43
+ description: string;
44
+ /**
45
+ * Whether the model accepts message-level tool declarations.
46
+ *
47
+ * Taken from the capability list the official client ships in its own managed
48
+ * model table, which is more specific than the wire documentation (that names
49
+ * K3 alone, because it describes the K3 request schema):
50
+ *
51
+ * - k3, k3-256k, kimi-for-coding -> declared;
52
+ * - kimi-for-coding-highspeed -> NOT declared.
53
+ *
54
+ * The live `/v1/models` listing remains authoritative when it speaks: its own
55
+ * `supports_dynamic_tools` overrides this flag, including to turn it off.
56
+ */
57
+ supportsDynamicTools: boolean;
58
+ /** Relative quota cost of this model against the cheapest one. */
59
+ quotaMultiplier: number;
60
+ /** How fast the model emits output. */
61
+ speed: 'regular' | 'highspeed';
62
+ }
63
+ /**
64
+ * The four ids the subscription serves today.
65
+ *
66
+ * `kimi-for-coding` is the alias that never changes: Moonshot upgrades the model
67
+ * behind it in place (K2.7 Code became K2.8 Preview without a config change), so
68
+ * this entry is the durable default a user can leave selected.
69
+ */
70
+ export declare const KIMI_CODE_MODELS: readonly KimiCodeCatalogModel[];
71
+ /** Registry entry for one model id, or undefined when the id is unknown. */
72
+ export declare function kimiCodeModelDef(modelId: string): KimiCodeCatalogModel | undefined;
73
+ /** Membership test for one known model id. */
74
+ export declare function isKimiCodeModelId(value: unknown): boolean;
75
+ /** Display name for one model id, falling back to the raw id so nothing is hidden. */
76
+ export declare function kimiCodeModelName(modelId: string): string;
77
+ //# sourceMappingURL=model-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-catalog.d.ts","sourceRoot":"","sources":["../../../../src/host/kimi-code/model-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAA;AAElF,wEAAwE;AACxE,MAAM,WAAW,oBAAoB;IACnC,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAA;IACV,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;;OAQG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB,sFAAsF;IACtF,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,eAAe,EAAE,SAAS,CAAC,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,EAAE,CAAA;IACxD,8DAA8D;IAC9D,gBAAgB,EAAE,SAAS,uBAAuB,EAAE,CAAA;IACpD,mEAAmE;IACnE,sBAAsB,EAAE,uBAAuB,GAAG,IAAI,CAAA;IACtD,iFAAiF;IACjF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,6EAA6E;IAC7E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;;;;;;;;OAYG;IACH,oBAAoB,EAAE,OAAO,CAAA;IAC7B,kEAAkE;IAClE,eAAe,EAAE,MAAM,CAAA;IACvB,uCAAuC;IACvC,KAAK,EAAE,SAAS,GAAG,WAAW,CAAA;CAC/B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,oBAAoB,EAwE3D,CAAA;AAID,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAElF;AAED,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzD"}
@@ -0,0 +1,133 @@
1
+ import { FileCredentialStore, type KimiCodeCredentials } from './token-store.ts';
2
+ import type { KimiCodeLoginFlowStatus, KimiCodeRegion } from '../../shared/kimi-code-contracts.ts';
3
+ /** Raised when the stored refresh token was rejected and a new login is required. */
4
+ export declare class KimiCodeUnauthorizedError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ /** Raised when a transient failure outlived its retry budget. */
8
+ export declare class KimiCodeRetryableError extends Error {
9
+ readonly cause?: unknown | undefined;
10
+ constructor(message: string, cause?: unknown | undefined);
11
+ }
12
+ /** Raised when the user denied the device authorization request. */
13
+ export declare class KimiCodeAccessDeniedError extends Error {
14
+ constructor(message: string);
15
+ }
16
+ /** Test seam: forget every remembered rejection. */
17
+ export declare function resetRefreshRejections(): void;
18
+ /**
19
+ * Whether the given refresh token was recently rejected by the service.
20
+ *
21
+ * The settings card uses this to say "sign in again" instead of showing an
22
+ * account that merely looks signed in while every call is failing.
23
+ */
24
+ export declare function isRefreshTokenRejected(refreshToken: string): boolean;
25
+ /**
26
+ * Read the stable device id, creating it exactly once.
27
+ *
28
+ * The managed service treats this as the installation's identity. It is not a
29
+ * secret; it only has to stay stable, so a failed write degrades to a
30
+ * per-process value instead of failing the login.
31
+ */
32
+ export declare function getDeviceId(): Promise<string>;
33
+ /** Identity headers every Kimi Code OAuth and account request carries. */
34
+ export declare function kimiIdentityHeaders(extra?: Record<string, string>): Promise<Record<string, string>>;
35
+ /** Parsed device authorization response. */
36
+ export interface DeviceAuthorization {
37
+ userCode: string;
38
+ deviceCode: string;
39
+ verificationUri: string;
40
+ verificationUriComplete: string;
41
+ expiresIn: number;
42
+ interval: number;
43
+ }
44
+ /**
45
+ * Start a device authorization (RFC 8628 section 3.1).
46
+ *
47
+ * A public client sends only its `client_id`; no scope, no PKCE.
48
+ */
49
+ export declare function requestDeviceAuthorization(options?: {
50
+ fetchFn?: typeof fetch;
51
+ signal?: AbortSignal;
52
+ region?: KimiCodeRegion;
53
+ }): Promise<{
54
+ authorization: DeviceAuthorization;
55
+ host: string;
56
+ }>;
57
+ /** Identity claims a Kimi token carries about the signed-in account. */
58
+ export interface KimiTokenIdentity {
59
+ userId?: string;
60
+ email?: string;
61
+ }
62
+ /**
63
+ * Decode one JWT payload without verifying it.
64
+ *
65
+ * Kimi's access and refresh tokens are JWTs whose payload names the account,
66
+ * and there is NO account-profile endpoint on the coding API — the identity
67
+ * exists only inside the token. The claims are read for display only and the
68
+ * token itself is what authenticates, so no signature check applies here.
69
+ */
70
+ export declare function decodeJwtPayload(token: string): Record<string, unknown> | undefined;
71
+ /**
72
+ * Account identity carried by a token pair.
73
+ *
74
+ * `user_id` is preferred across BOTH tokens before `sub` is considered: the two
75
+ * claims share an issuer namespace but `sub` is the weaker one, so a refresh
76
+ * token's `user_id` must beat an access token's `sub`.
77
+ */
78
+ export declare function identityFromTokens(accessToken: string, refreshToken?: string): KimiTokenIdentity;
79
+ /** OAuth token response, in the shape the rest of the plugin stores. */
80
+ export interface OAuthToken {
81
+ accessToken: string;
82
+ refreshToken: string;
83
+ expiresAt: number;
84
+ expiresIn: number;
85
+ scope: string;
86
+ tokenType: string;
87
+ }
88
+ /** How long before expiry a token must be replaced, from its own lifetime. */
89
+ export declare function refreshThresholdMs(expiresIn: number): number;
90
+ /**
91
+ * Refresh an access token, with the official client's bounded retry.
92
+ *
93
+ * Only a transient status or a transport failure is retried; a 401/403 (or an
94
+ * `invalid_grant` body) is a verdict that the refresh token is dead and stops
95
+ * immediately, because retrying it can never succeed.
96
+ */
97
+ export declare function refreshAccessToken(refreshToken: string, options?: {
98
+ fetchFn?: typeof fetch;
99
+ signal?: AbortSignal;
100
+ host?: string;
101
+ region?: KimiCodeRegion;
102
+ }): Promise<OAuthToken>;
103
+ export interface EnsureTokenOptions {
104
+ fetchFn?: typeof fetch;
105
+ signal?: AbortSignal;
106
+ /** Refresh even when the current token is not near expiry. */
107
+ force?: boolean;
108
+ }
109
+ /**
110
+ * Return a usable access token, refreshing and persisting when needed.
111
+ *
112
+ * Concurrent callers share one refresh request: a subscription is rate limited,
113
+ * and a burst of tool calls at token expiry would otherwise each try to rotate
114
+ * the same refresh token.
115
+ */
116
+ export declare function ensureAccessToken(store: FileCredentialStore, options?: EnsureTokenOptions): Promise<KimiCodeCredentials>;
117
+ export declare function getWebLoginStatus(): KimiCodeLoginFlowStatus;
118
+ /** Reset the flow so a cancelled attempt cannot keep a later one from starting. */
119
+ export declare function resetWebLogin(): void;
120
+ export declare function openBrowser(url: string): void;
121
+ /**
122
+ * Start the browser sign-in.
123
+ *
124
+ * Resolves immediately with the flow state the settings card polls; the device
125
+ * code is fetched, opened, and polled in the background so the HTTP request
126
+ * behind the button never has to stay open for the whole authorization.
127
+ */
128
+ export declare function beginWebLogin(store: FileCredentialStore, options?: {
129
+ fetchFn?: typeof fetch;
130
+ openBrowser?: (url: string) => void;
131
+ region?: KimiCodeRegion;
132
+ }): Promise<KimiCodeLoginFlowStatus>;
133
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../src/host/kimi-code/oauth.ts"],"names":[],"mappings":"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"}