@arnilo/prism-provider-kimi 0.0.96 → 0.1.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,117 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0] - 2026-08-09
4
+
5
+ ### Changed
6
+ - Released with exact 0.1.0 graph.
7
+
8
+ ## [0.0.28] - 2026-08-08
9
+
10
+ ### Changed
11
+ - Released with exact 0.0.28 graph.
12
+
13
+ ## [0.0.27] - 2026-08-07
14
+
15
+ ### Changed
16
+ - Released with exact 0.0.27 graph.
17
+
18
+ ## [0.0.26] - 2026-08-06
19
+
20
+ ### Changed
21
+ - Released with exact 0.0.26 graph.
22
+
23
+ ## [0.0.25] - 2026-08-06
24
+
25
+ ### Changed
26
+ - Released with exact 0.0.25 graph.
27
+
28
+ ## [0.0.24] - 2026-08-04
29
+
30
+ ### Added
31
+ - Durable `AgentEventSource` (memory + PostgreSQL LISTEN/NOTIFY), recoverable `ToolEffectStore`, and AG-UI MCP/MCP Apps/A2A fronting for Phase 7.
32
+
33
+ ### Changed
34
+ - Publishable graph remains **47** manifests at **0.0.24**; peers and lockfile move together.
35
+
36
+ See [migration guide](../../docs/migration.md) for the 0.0.23 → 0.0.24 notes.
37
+
38
+ ## [0.0.23] - 2026-08-03
39
+
40
+ ### Changed
41
+ - Released with exact 0.0.23 graph.
42
+
43
+ ## [0.0.22] - 2026-07-31
44
+
45
+ ### Changed
46
+ - Released with exact 0.0.22 graph.
47
+
48
+ ## [0.0.21] - 2026-07-31
49
+
50
+ ### Changed
51
+ - Released with exact 0.0.21 graph.
52
+
53
+ ## [0.0.20] - 2026-07-31
54
+
55
+ ### Changed
56
+ - Released with exact 0.0.20 graph.
57
+
58
+ ## [0.0.19] - 2026-07-30
59
+
60
+ ### Changed
61
+ - Released with exact 0.0.19 graph.
62
+
63
+ ## [0.0.18] - 2026-07-30
64
+
65
+ ### Changed
66
+ - Released with exact 0.0.18 graph.
67
+
68
+ ## [0.0.17] - 2026-07-29
69
+
70
+ ### Changed
71
+ - HTTP errors now carry numeric `code` and parsed `Retry-After` (`retryAfterMs`) for transient classification and backpressure-aware retries.
72
+ - Released with exact 0.0.17 graph.
73
+
74
+ ## [0.0.16] - 2026-07-26
75
+
76
+ ### Changed
77
+ - Released with exact 0.0.16 graph.
78
+
79
+ ## [0.0.15] - 2026-07-26
80
+
81
+ ### Changed
82
+
83
+ - Released with exact 0.0.15 graph.
84
+
85
+ ## [0.0.14] - 2026-07-26
86
+
87
+ ### Changed
88
+
89
+ - Released with exact 0.0.14 graph.
90
+
91
+ ## [0.0.13] - 2026-07-24
92
+
93
+ ### Changed
94
+
95
+ - Released with exact 0.0.13 graph.
96
+
97
+ ## [0.0.12] - 2026-07-22
98
+
99
+ ### Changed
100
+
101
+ - Released with exact 0.0.12 graph.
102
+
103
+ ## [0.0.11] - 2026-07-22
104
+
105
+ ### Changed
106
+
107
+ - Released with exact 0.0.11 graph.
108
+
109
+ ## [0.0.10] - 2026-07-21
110
+
111
+ ### Changed
112
+
113
+ - Released with exact 0.0.10 graph.
114
+
1
115
  ## [0.0.96] - 2026-07-21
2
116
 
3
117
  ### Changed
@@ -12,7 +126,6 @@
12
126
 
13
127
  - Malformed streamed tool-call arguments yield recoverable tool calls via `toolCallFromArgumentsText` instead of throwing `ProviderTransportError` / terminal stream errors.
14
128
 
15
-
16
129
  ## [0.0.8] - 2026-07-20
17
130
 
18
131
  - Released with the exact 0.0.8 first-party package graph.
@@ -45,7 +158,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
45
158
 
46
159
  - Pinned the required `@arnilo/prism` peer and package metadata to 0.0.5; runtime behavior is unchanged.
47
160
 
48
-
49
161
  ## [0.0.4] - 2026-07-14
50
162
 
51
163
  ### Changed
package/dist/index.d.ts CHANGED
@@ -20,8 +20,8 @@ export interface KimiProviderPackageOptions {
20
20
  readonly moonshotModels?: readonly ModelConfig[];
21
21
  }
22
22
  export declare function createKimiProviderPackage(options?: KimiProviderPackageOptions): ProviderPackage;
23
- export { defineKimiModel, kimiCodingModels, listKimiModels, mapKimiModel, moonshotKimiModels, type KimiModelConfig, type KimiModelEntry, type ListKimiModelsOptions, } from "./models.js";
24
- export { createKimiCodingProvider, kimiAnthropicBody, kimiAnthropicEvents, type KimiCodingProviderOptions, } from "./provider.js";
25
- export { createMoonshotProvider, moonshotBody, moonshotEvents, serializeMoonshotMessage, type MoonshotProviderOptions, } from "./moonshot.js";
26
- export { kimiPreserveThinking, kimiReasoningEffort, kimiThinking, stripKimiThinkingCompat, } from "./thinking.js";
27
23
  export { applyKimiAnthropicCacheControl, kimiAnthropicCacheEnabled, } from "./cache.js";
24
+ export { defineKimiModel, type KimiModelConfig, type KimiModelEntry, kimiCodingModels, type ListKimiModelsOptions, listKimiModels, mapKimiModel, moonshotKimiModels, } from "./models.js";
25
+ export { createMoonshotProvider, type MoonshotProviderOptions, moonshotBody, moonshotEvents, serializeMoonshotMessage, } from "./moonshot.js";
26
+ export { createKimiCodingProvider, type KimiCodingProviderOptions, kimiAnthropicBody, kimiAnthropicEvents, } from "./provider.js";
27
+ export { kimiPreserveThinking, kimiReasoningEffort, kimiThinking, stripKimiThinkingCompat, } from "./thinking.js";
package/dist/index.js CHANGED
@@ -36,9 +36,9 @@ export function createKimiProviderPackage(options = {}) {
36
36
  },
37
37
  });
38
38
  }
39
+ export { applyKimiAnthropicCacheControl, kimiAnthropicCacheEnabled, } from "./cache.js";
39
40
  export { defineKimiModel, kimiCodingModels, listKimiModels, mapKimiModel, moonshotKimiModels, } from "./models.js";
40
- export { createKimiCodingProvider, kimiAnthropicBody, kimiAnthropicEvents, } from "./provider.js";
41
41
  export { createMoonshotProvider, moonshotBody, moonshotEvents, serializeMoonshotMessage, } from "./moonshot.js";
42
+ export { createKimiCodingProvider, kimiAnthropicBody, kimiAnthropicEvents, } from "./provider.js";
42
43
  export { kimiPreserveThinking, kimiReasoningEffort, kimiThinking, stripKimiThinkingCompat, } from "./thinking.js";
43
- export { applyKimiAnthropicCacheControl, kimiAnthropicCacheEnabled, } from "./cache.js";
44
44
  //# sourceMappingURL=index.js.map
package/dist/models.js CHANGED
@@ -1,4 +1,4 @@
1
- import { redactSecrets, resolveCredentialValue, } from "@arnilo/prism";
1
+ import { redactSecrets, resolveCredentialValue } from "@arnilo/prism";
2
2
  import { readBoundedResponseText } from "@arnilo/prism/providers/transport";
3
3
  export function defineKimiModel(config) {
4
4
  return {
@@ -24,7 +24,7 @@ export function defineKimiModel(config) {
24
24
  */
25
25
  export async function listKimiModels(options = {}) {
26
26
  const provider = options.provider ?? "moonshot";
27
- const baseUrl = (options.baseUrl ?? "https://api.moonshot.ai/v1").replace(/\/$/, "");
27
+ const baseUrl = (options.baseUrl ?? "https://api.moonshot.ai/v1").replace(/\/+$/, "");
28
28
  const token = await resolveCredentialValue(options.apiKey, { provider, name: "apiKey" });
29
29
  const response = await (options.fetch ?? fetch)(`${baseUrl}/models`, {
30
30
  method: "GET",
@@ -191,13 +191,13 @@ export const moonshotKimiModels = [
191
191
  ];
192
192
  function looksLikeReasoningModel(modelId) {
193
193
  const id = modelId.toLowerCase();
194
- return (id.includes("kimi-k3")
195
- || id === "k3"
196
- || id.includes("k2.7")
197
- || id.includes("k2.6")
198
- || id.includes("k2.5")
199
- || id.includes("thinking")
200
- || id.includes("for-coding"));
194
+ return (id.includes("kimi-k3") ||
195
+ id === "k3" ||
196
+ id.includes("k2.7") ||
197
+ id.includes("k2.6") ||
198
+ id.includes("k2.5") ||
199
+ id.includes("thinking") ||
200
+ id.includes("for-coding"));
201
201
  }
202
202
  function shouldPreserveThinkingByDefault(modelId) {
203
203
  const id = modelId.toLowerCase();
package/dist/moonshot.js CHANGED
@@ -1,6 +1,5 @@
1
- import { assertStructuredOutputRequestSupported, providerDone, providerError, providerTextDelta, providerThinkingDelta, providerToolCall, providerToolCallDelta, providerUsage, resolveCredentialValue, toolCallFromArgumentsText } from "@arnilo/prism";
2
- import { applyOpenAIChatStructuredOutput, mapOpenAIChatUsage, serializeOpenAITool } from "@arnilo/prism/providers/openai";
3
- import { readBoundedResponseText, readSseData } from "@arnilo/prism/providers/transport";
1
+ import { applyOpenAIChatStructuredOutput } from "@arnilo/prism/providers/openai";
2
+ import { buildOpenAIChatBody, createOpenAICompatibleProvider, openAIChatEvents } from "@arnilo/prism/providers/openai-compatible";
4
3
  import { kimiPreserveThinking, kimiReasoningEffort, kimiThinking, stripKimiThinkingCompat } from "./thinking.js";
5
4
  /**
6
5
  * Moonshot / Kimi Open Platform Chat Completions provider (`POST /chat/completions`).
@@ -9,116 +8,39 @@ import { kimiPreserveThinking, kimiReasoningEffort, kimiThinking, stripKimiThink
9
8
  * @see https://platform.kimi.ai/docs/api/overview
10
9
  */
11
10
  export function createMoonshotProvider(options = {}) {
12
- const id = options.id ?? "moonshot";
13
- const baseUrl = (options.baseUrl ?? "https://api.moonshot.ai/v1").replace(/\/$/, "");
14
- return {
15
- id,
16
- async *generate(request) {
17
- if (request.signal?.aborted)
18
- throw request.signal.reason ?? new Error("aborted");
19
- let token;
20
- const secrets = [];
21
- try {
22
- const body = moonshotBody(request);
23
- token = await resolveCredentialValue(options.apiKey, { provider: id, name: "apiKey" });
24
- secrets.push(token);
25
- const response = await (options.fetch ?? fetch)(`${baseUrl}/chat/completions`, {
26
- method: "POST",
27
- headers: {
28
- ...request.options?.headers,
29
- "content-type": "application/json",
30
- ...(token ? { authorization: `Bearer ${token}` } : {})
31
- },
32
- body: JSON.stringify(body),
33
- signal: request.signal
34
- });
35
- if (!response.ok) {
36
- return yield providerError(new Error(`Moonshot request failed: ${response.status} ${await readBoundedResponseText(response, { secrets })}`), secrets);
37
- }
38
- if (!response.body)
39
- return yield providerError(new Error("Moonshot response had no body"), secrets);
40
- yield* moonshotEvents(response.body, request.signal);
41
- }
42
- catch (error) {
43
- yield providerError(error, secrets);
44
- }
45
- }
46
- };
11
+ return createOpenAICompatibleProvider({
12
+ id: options.id ?? "moonshot",
13
+ baseUrl: (options.baseUrl ?? "https://api.moonshot.ai/v1").replace(/\/+$/, ""),
14
+ apiKey: options.apiKey,
15
+ fetch: options.fetch,
16
+ strictCompletion: true,
17
+ requestFailedPrefix: "Moonshot request failed",
18
+ serializeMessage: (message, request) => serializeMoonshotMessage(message, request.model.capabilities ?? {}, kimiPreserveThinking(request)),
19
+ transformBody: (body, request) => moonshotTransform(body, request),
20
+ });
47
21
  }
48
22
  export function moonshotBody(request) {
49
- assertStructuredOutputRequestSupported(request.model, request.options);
50
- const preserveThinking = kimiPreserveThinking(request);
51
- const { maxTokens, ...parameters } = request.model.parameters ?? {};
52
- const body = {
53
- model: request.model.model,
54
- messages: request.messages.map((message) => serializeMoonshotMessage(message, request.model.capabilities ?? {}, preserveThinking)),
55
- tools: request.tools?.map(serializeOpenAITool),
56
- stream: true,
57
- stream_options: { include_usage: true },
23
+ return buildOpenAIChatBody(request, {
24
+ serializeMessage: (message, req) => serializeMoonshotMessage(message, req.model.capabilities ?? {}, kimiPreserveThinking(req)),
25
+ transformBody: (body, req) => moonshotTransform(body, req),
26
+ });
27
+ }
28
+ function moonshotTransform(body, request) {
29
+ const { maxTokens, ...rest } = body;
30
+ const transformed = {
31
+ // Resolved thinking fields first: model `parameters` may override them (legacy order).
58
32
  thinking: kimiThinking(request),
59
33
  reasoning_effort: kimiReasoningEffort(request),
60
- ...parameters,
34
+ ...rest,
61
35
  max_tokens: maxTokens ?? request.model.limits?.maxOutputTokens,
62
36
  ...stripKimiThinkingCompat(request.options?.compat),
63
- ...request.options?.extra
37
+ ...request.options?.extra,
64
38
  };
65
- applyOpenAIChatStructuredOutput(body, request.options?.structuredOutput);
66
- return clean(body);
39
+ applyOpenAIChatStructuredOutput(transformed, request.options?.structuredOutput);
40
+ return clean(transformed);
67
41
  }
68
- export async function* moonshotEvents(body, signal) {
69
- const tools = new Map();
70
- let usage;
71
- let sawDoneMarker = false;
72
- let sawFinishReason = false;
73
- for await (const data of readSseData(body, { signal })) {
74
- if (data === "[DONE]") {
75
- sawDoneMarker = true;
76
- break;
77
- }
78
- const chunk = JSON.parse(data);
79
- usage = mapOpenAIChatUsage(chunk.usage) ?? usage;
80
- if (chunk.usage) {
81
- const mapped = mapOpenAIChatUsage(chunk.usage);
82
- if (mapped)
83
- yield providerUsage(mapped);
84
- }
85
- for (const choice of chunk.choices ?? []) {
86
- if (choice.finish_reason)
87
- sawFinishReason = true;
88
- const delta = choice.delta ?? {};
89
- if (delta.content)
90
- yield providerTextDelta(delta.content);
91
- if (delta.reasoning_content)
92
- yield providerThinkingDelta(delta.reasoning_content);
93
- for (const tool of delta.tool_calls ?? []) {
94
- const index = tool.index ?? 0;
95
- const current = tools.get(index) ?? { argumentsText: "" };
96
- current.id = tool.id ?? current.id;
97
- current.name = tool.function?.name ?? current.name;
98
- current.argumentsText += tool.function?.arguments ?? "";
99
- tools.set(index, current);
100
- yield providerToolCallDelta({
101
- index,
102
- id: tool.id,
103
- name: tool.function?.name,
104
- argumentsText: tool.function?.arguments
105
- });
106
- }
107
- }
108
- }
109
- const danglingToolCall = [...tools.values()].some((call) => !call.id || !call.name);
110
- if (!sawDoneMarker || !sawFinishReason || danglingToolCall) {
111
- // Truncated streams must fail loudly — emitting done would mark partial output as succeeded.
112
- yield providerError(new Error(`Moonshot chat stream ended without completion evidence `
113
- + `([DONE]: ${sawDoneMarker ? "received" : "missing"}, `
114
- + `finish_reason: ${sawFinishReason ? "received" : "missing"}, `
115
- + `tool calls complete: ${danglingToolCall ? "no" : "yes"})`));
116
- return;
117
- }
118
- for (const call of tools.values()) {
119
- yield providerToolCall(toolCallFromArgumentsText(call.id, call.name, call.argumentsText));
120
- }
121
- yield providerDone(usage);
42
+ export function moonshotEvents(body, signal) {
43
+ return openAIChatEvents(body, { signal, strictCompletion: true });
122
44
  }
123
45
  /**
124
46
  * Open Platform message serialization. When `preserveThinking`, historical thinking
@@ -131,7 +53,7 @@ export function serializeMoonshotMessage(message, capabilities = {}, preserveThi
131
53
  return {
132
54
  role: "tool",
133
55
  tool_call_id: result?.toolCallId ?? "",
134
- content: result ? JSON.stringify(result.result ?? result.error ?? null) : ""
56
+ content: result ? JSON.stringify(result.result ?? result.error ?? null) : "",
135
57
  };
136
58
  }
137
59
  if (message.role === "assistant") {
@@ -142,7 +64,7 @@ export function serializeMoonshotMessage(message, capabilities = {}, preserveThi
142
64
  const reasoning = thinkingParts.map((part) => part.text).join("\n");
143
65
  const base = {
144
66
  role: "assistant",
145
- content: text || (toolCalls.length > 0 ? null : "")
67
+ content: text || (toolCalls.length > 0 ? null : ""),
146
68
  };
147
69
  if (preserveThinking && reasoning)
148
70
  base.reasoning_content = reasoning;
@@ -150,7 +72,7 @@ export function serializeMoonshotMessage(message, capabilities = {}, preserveThi
150
72
  base.tool_calls = toolCalls.map((call) => ({
151
73
  id: call.id,
152
74
  type: "function",
153
- function: { name: call.name, arguments: JSON.stringify(call.arguments) }
75
+ function: { name: call.name, arguments: JSON.stringify(call.arguments) },
154
76
  }));
155
77
  }
156
78
  return base;
package/dist/provider.js CHANGED
@@ -1,11 +1,11 @@
1
- import { assertStructuredOutputRequestSupported, providerDone, providerError, providerTextDelta, providerThinkingDelta, providerToolCall, providerToolCallDelta, providerUsage, resolveCredentialValue, toolCallFromArgumentsText } from "@arnilo/prism";
2
- import { bytesToBase64, isPdfMediaType, rejectProviderMediaBlock, resolveProviderMediaMessages, serializePdfDocumentWireBlock } from "@arnilo/prism/providers/media";
3
- import { readBoundedResponseText, readSseData } from "@arnilo/prism/providers/transport";
1
+ import { assertStructuredOutputRequestSupported, providerDone, providerError, providerTextDelta, providerThinkingDelta, providerToolCall, providerToolCallDelta, providerUsage, resolveCredentialValue, toolCallFromArgumentsText, } from "@arnilo/prism";
2
+ import { bytesToBase64, isPdfMediaType, rejectProviderMediaBlock, resolveProviderMediaMessages, serializePdfDocumentWireBlock, } from "@arnilo/prism/providers/media";
3
+ import { httpStatusError, readBoundedResponseText, readSseData } from "@arnilo/prism/providers/transport";
4
4
  import { applyKimiAnthropicCacheControl } from "./cache.js";
5
5
  import { kimiPreserveThinking, kimiReasoningEffort, kimiThinking, stripKimiThinkingCompat } from "./thinking.js";
6
6
  export function createKimiCodingProvider(options = {}) {
7
7
  const id = options.id ?? "kimi-coding";
8
- const baseUrl = (options.baseUrl ?? "https://api.kimi.com/coding").replace(/\/$/, "");
8
+ const baseUrl = (options.baseUrl ?? "https://api.kimi.com/coding").replace(/\/+$/, "");
9
9
  return {
10
10
  id,
11
11
  async *generate(request) {
@@ -26,13 +26,13 @@ export function createKimiCodingProvider(options = {}) {
26
26
  ...(token ? { authorization: `Bearer ${token}` } : {}),
27
27
  // Provider-owned Anthropic-route auth: official third-party setup uses
28
28
  // ANTHROPIC_API_KEY semantics (x-api-key + anthropic-version).
29
- ...(token ? { "x-api-key": token, "anthropic-version": "2023-06-01" } : {})
29
+ ...(token ? { "x-api-key": token, "anthropic-version": "2023-06-01" } : {}),
30
30
  },
31
31
  body: JSON.stringify(body),
32
- signal: request.signal
32
+ signal: request.signal,
33
33
  });
34
34
  if (!response.ok) {
35
- return yield providerError(new Error(`Kimi request failed: ${response.status} ${await readBoundedResponseText(response, { secrets })}`), secrets);
35
+ return yield providerError(httpStatusError("Kimi request failed", response, await readBoundedResponseText(response, { secrets })), secrets);
36
36
  }
37
37
  if (!response.body)
38
38
  return yield providerError(new Error("Kimi response had no body"), secrets);
@@ -41,7 +41,7 @@ export function createKimiCodingProvider(options = {}) {
41
41
  catch (error) {
42
42
  yield providerError(error, secrets);
43
43
  }
44
- }
44
+ },
45
45
  };
46
46
  }
47
47
  export async function kimiAnthropicBody(request) {
@@ -55,7 +55,10 @@ export async function kimiAnthropicBody(request) {
55
55
  return clean({
56
56
  model: request.model.model,
57
57
  messages: await Promise.all(messages.filter((m) => m.role !== "system").map((message) => toMessage(message, request.model, preserveThinking, resolvedMedia))),
58
- system: messages.filter((m) => m.role === "system").map((m) => text(m, preserveThinking)).join("\n\n") || undefined,
58
+ system: messages
59
+ .filter((m) => m.role === "system")
60
+ .map((m) => text(m, preserveThinking))
61
+ .join("\n\n") || undefined,
59
62
  tools: request.tools?.map(toTool),
60
63
  stream: true,
61
64
  thinking: kimiThinking(request),
@@ -63,7 +66,7 @@ export async function kimiAnthropicBody(request) {
63
66
  ...parameters,
64
67
  max_tokens: maxTokens ?? request.model.limits?.maxOutputTokens ?? 4096,
65
68
  ...stripKimiThinkingCompat(request.options?.compat),
66
- ...request.options?.extra
69
+ ...request.options?.extra,
67
70
  });
68
71
  }
69
72
  export async function* kimiAnthropicEvents(body, signal) {
@@ -104,9 +107,9 @@ export async function* kimiAnthropicEvents(body, signal) {
104
107
  const danglingBlock = [...blocks.values()].some((call) => !call.id || !call.name || !call.complete);
105
108
  if (!sawMessageStop || danglingBlock) {
106
109
  // Truncated streams must fail loudly — emitting done would mark partial output as succeeded.
107
- yield providerError(new Error(`Kimi messages stream ended without completion evidence `
108
- + `(message_stop: ${sawMessageStop ? "received" : "missing"}, `
109
- + `content blocks complete: ${danglingBlock ? "no" : "yes"})`));
110
+ yield providerError(new Error(`Kimi messages stream ended without completion evidence ` +
111
+ `(message_stop: ${sawMessageStop ? "received" : "missing"}, ` +
112
+ `content blocks complete: ${danglingBlock ? "no" : "yes"})`));
110
113
  return;
111
114
  }
112
115
  for (const call of blocks.values()) {
@@ -121,12 +124,14 @@ async function toMessage(message, model, preserveThinking, resolvedMedia) {
121
124
  const last = message.content[message.content.length - 1];
122
125
  return {
123
126
  role: "user",
124
- content: [{
127
+ content: [
128
+ {
125
129
  type: "tool_result",
126
130
  tool_use_id: result?.toolCallId ?? "",
127
131
  content: result ? JSON.stringify(result.result ?? result.error ?? null) : "",
128
- ...(last?.cache_control ? { cache_control: last.cache_control } : {})
129
- }]
132
+ ...(last?.cache_control ? { cache_control: last.cache_control } : {}),
133
+ },
134
+ ],
130
135
  };
131
136
  }
132
137
  const content = [];
@@ -137,7 +142,9 @@ async function toMessage(message, model, preserveThinking, resolvedMedia) {
137
142
  }
138
143
  else if (part.type === "thinking") {
139
144
  if (preserveThinking) {
140
- content.push(withMarker(part.signature ? { type: "thinking", thinking: part.text, signature: part.signature } : { type: "thinking", thinking: part.text }, marker));
145
+ content.push(withMarker(part.signature
146
+ ? { type: "thinking", thinking: part.text, signature: part.signature }
147
+ : { type: "thinking", thinking: part.text }, marker));
141
148
  }
142
149
  else {
143
150
  content.push(withMarker({ type: "text", text: part.text }, marker));
@@ -164,14 +171,17 @@ async function toMessage(message, model, preserveThinking, resolvedMedia) {
164
171
  throw new Error("Kimi tool_result blocks must appear in role=tool messages");
165
172
  }
166
173
  }
167
- return { role: message.role === "assistant" ? "assistant" : "user", content: content.length > 0 ? content : [{ type: "text", text: "" }] };
174
+ return {
175
+ role: message.role === "assistant" ? "assistant" : "user",
176
+ content: content.length > 0 ? content : [{ type: "text", text: "" }],
177
+ };
168
178
  }
169
179
  function toAnthropicDocument(part, resolvedMedia) {
170
180
  const resolved = resolvedMedia.get(part);
171
181
  return serializePdfDocumentWireBlock({
172
182
  mediaType: resolved.mediaType,
173
183
  data: bytesToBase64(resolved.bytes),
174
- title: resolved.name
184
+ title: resolved.name,
175
185
  });
176
186
  }
177
187
  function toAnthropicFile(part, resolvedMedia) {
@@ -182,7 +192,7 @@ function toAnthropicFile(part, resolvedMedia) {
182
192
  return serializePdfDocumentWireBlock({
183
193
  mediaType: resolved.mediaType,
184
194
  data: bytesToBase64(resolved.bytes),
185
- title: resolved.name
195
+ title: resolved.name,
186
196
  });
187
197
  }
188
198
  function withMarker(item, marker) {
@@ -192,16 +202,25 @@ function toTool(tool) {
192
202
  return clean({ name: tool.name, description: tool.description, input_schema: tool.parameters ?? { type: "object" } });
193
203
  }
194
204
  function text(message, preserveThinking = false) {
195
- return message.content.map((part) => {
205
+ return message.content
206
+ .map((part) => {
196
207
  if (part.type === "text")
197
208
  return part.text;
198
209
  if (part.type === "thinking")
199
210
  return preserveThinking ? part.text : part.text;
200
211
  return "";
201
- }).join("");
212
+ })
213
+ .join("");
202
214
  }
203
215
  function toUsage(usage) {
204
- return usage ? { inputTokens: usage.input_tokens, outputTokens: usage.output_tokens, cacheReadTokens: usage.cache_read_input_tokens, cacheWriteTokens: usage.cache_creation_input_tokens } : undefined;
216
+ return usage
217
+ ? {
218
+ inputTokens: usage.input_tokens,
219
+ outputTokens: usage.output_tokens,
220
+ cacheReadTokens: usage.cache_read_input_tokens,
221
+ cacheWriteTokens: usage.cache_creation_input_tokens,
222
+ }
223
+ : undefined;
205
224
  }
206
225
  function clean(value) {
207
226
  return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined && !(Array.isArray(item) && item.length === 0)));
package/dist/thinking.js CHANGED
@@ -18,9 +18,7 @@ export function kimiThinking(request) {
18
18
  * @see https://platform.kimi.ai/docs/guide/use-thinking-effort
19
19
  */
20
20
  export function kimiReasoningEffort(request) {
21
- const effort = request.options?.compat?.reasoning_effort
22
- ?? request.options?.compat?.reasoningEffort
23
- ?? request.model.compat?.reasoning_effort;
21
+ const effort = request.options?.compat?.reasoning_effort ?? request.options?.compat?.reasoningEffort ?? request.model.compat?.reasoning_effort;
24
22
  return typeof effort === "string" ? effort : undefined;
25
23
  }
26
24
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism-provider-kimi",
3
- "version": "0.0.96",
3
+ "version": "0.1.0",
4
4
  "description": "Kimi provider package for Prism.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,7 @@
25
25
  "pack:dry-run": "npm pack --dry-run"
26
26
  },
27
27
  "peerDependencies": {
28
- "@arnilo/prism": "0.0.96"
28
+ "@arnilo/prism": "0.1.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@arnilo/prism": "file:../.."