@arnilo/prism-provider-kimi 0.0.16 → 0.0.18
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 +11 -0
- package/dist/models.js +1 -1
- package/dist/moonshot.js +26 -104
- package/dist/provider.js +3 -3
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.18] - 2026-07-30
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Released with exact 0.0.18 graph.
|
|
7
|
+
|
|
8
|
+
## [0.0.17] - 2026-07-29
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- HTTP errors now carry numeric `code` and parsed `Retry-After` (`retryAfterMs`) for transient classification and backpressure-aware retries.
|
|
12
|
+
- Released with exact 0.0.17 graph.
|
|
13
|
+
|
|
3
14
|
## [0.0.16] - 2026-07-26
|
|
4
15
|
|
|
5
16
|
### Changed
|
package/dist/models.js
CHANGED
|
@@ -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",
|
package/dist/moonshot.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
...
|
|
34
|
+
...rest,
|
|
61
35
|
max_tokens: maxTokens ?? request.model.limits?.maxOutputTokens,
|
|
62
36
|
...stripKimiThinkingCompat(request.options?.compat),
|
|
63
37
|
...request.options?.extra,
|
|
64
38
|
};
|
|
65
|
-
applyOpenAIChatStructuredOutput(
|
|
66
|
-
return clean(
|
|
39
|
+
applyOpenAIChatStructuredOutput(transformed, request.options?.structuredOutput);
|
|
40
|
+
return clean(transformed);
|
|
67
41
|
}
|
|
68
|
-
export
|
|
69
|
-
|
|
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
|
package/dist/provider.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { assertStructuredOutputRequestSupported, providerDone, providerError, providerTextDelta, providerThinkingDelta, providerToolCall, providerToolCallDelta, providerUsage, resolveCredentialValue, toolCallFromArgumentsText, } from "@arnilo/prism";
|
|
2
2
|
import { bytesToBase64, isPdfMediaType, rejectProviderMediaBlock, resolveProviderMediaMessages, serializePdfDocumentWireBlock, } from "@arnilo/prism/providers/media";
|
|
3
|
-
import { readBoundedResponseText, readSseData } from "@arnilo/prism/providers/transport";
|
|
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) {
|
|
@@ -32,7 +32,7 @@ export function createKimiCodingProvider(options = {}) {
|
|
|
32
32
|
signal: request.signal,
|
|
33
33
|
});
|
|
34
34
|
if (!response.ok) {
|
|
35
|
-
return yield providerError(
|
|
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);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arnilo/prism-provider-kimi",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
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.
|
|
28
|
+
"@arnilo/prism": "0.0.18"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@arnilo/prism": "file:../.."
|