pi-provider-kimi-code 0.2.2 → 0.3.1
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/README.md +9 -11
- package/index.ts +208 -89
- package/package.json +1 -3
package/README.md
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
**Reuse your [Kimi Code Plan](https://www.kimi.com/code/docs/en/) inside [pi-coding-agent](https://pi.dev/)** — no separate API credits, no second billing dashboard. Every request draws from your Kimi Code membership quota (the 5-hour token bucket) instead of billing per-token on the Moonshot Open Platform.
|
|
6
6
|
|
|
7
|
-
It's **"Claude Code for Kimi"** — log in with your Kimi account, with `KIMI_API_KEY` still supported as a fallback for CI. You get
|
|
7
|
+
It's **"Claude Code for Kimi"** — log in with your Kimi account, with `KIMI_API_KEY` still supported as a fallback for CI. You get `kimi-for-coding` (the Kimi-k2.6 latest alias, backed by the same Kimi Code Plan that covers K2.6 and K2.5) with a 262K-token context window, automatic prompt caching, automatic large-image and video upload, and compatibility with both Anthropic-style and OpenAI-style clients.
|
|
8
8
|
|
|
9
9
|
## Who is this for?
|
|
10
10
|
|
|
11
11
|
- You already pay for a **[Kimi Code Plan](https://www.kimi.com/code/docs/en/)** and want to use it inside `pi-coding-agent` instead of the official `kimi-cli` — see [MoonshotAI/kimi-cli#757](https://github.com/MoonshotAI/kimi-cli/issues/757) for the canonical feature request this extension answers.
|
|
12
12
|
- You want **"Claude Code for Kimi"**: log in with your Kimi account instead of buying separate API credits. (`KIMI_API_KEY` is also supported as a fallback for CI.)
|
|
13
|
-
- You're in the [pi / pi-mono](https://github.com/badlogic/pi-mono) ecosystem and want **Kimi K2.6
|
|
13
|
+
- You're in the [pi / pi-mono](https://github.com/badlogic/pi-mono) ecosystem and want **Kimi K2.6** (and the K2.5 coverage that comes with the Code Plan) as a pi provider.
|
|
14
14
|
|
|
15
15
|
Pay-per-token via `KIMI_API_KEY` also works if you just want to try Kimi in CI or without a subscription.
|
|
16
16
|
|
|
@@ -72,18 +72,16 @@ KIMI_API_KEY=sk-... pi
|
|
|
72
72
|
|
|
73
73
|
## Models
|
|
74
74
|
|
|
75
|
-
| ID
|
|
76
|
-
|
|
|
77
|
-
| `kimi-for-coding`
|
|
78
|
-
| `kimi-k2.6-code-preview` | Kimi K2.6 Code Preview | yes | text, image, video | 262 144 | 32 000 |
|
|
79
|
-
| `kimi-code` | Kimi Code (kimi-k2.5) | yes | text, image | 262 144 | 32 000 |
|
|
80
|
-
| `kimi-k2.5` | Kimi K2.5 | yes | text, image | 262 144 | 32 000 |
|
|
81
|
-
| `kimi-k2-thinking-turbo` | Kimi K2 Thinking Turbo | yes | text | 262 144 | 32 000 |
|
|
75
|
+
| ID | Name | Reasoning | Input | Context | Max Output |
|
|
76
|
+
| ----------------- | --------------- | --------- | ------------------ | ------- | ---------- |
|
|
77
|
+
| `kimi-for-coding` | Kimi for Coding | yes | text, image, video | 262 144 | 32 000 |
|
|
82
78
|
|
|
83
|
-
|
|
79
|
+
`kimi-for-coding` is the latest alias on the Kimi Code Plan — today it points at Kimi-k2.6. The Plan itself still covers K2.5; the upstream routes older model IDs to the current alias, but this provider only publishes the canonical `kimi-for-coding` entry.
|
|
80
|
+
|
|
81
|
+
Select it inside `pi`:
|
|
84
82
|
|
|
85
83
|
```
|
|
86
|
-
/model kimi-coding/kimi-
|
|
84
|
+
/model kimi-coding/kimi-for-coding
|
|
87
85
|
```
|
|
88
86
|
|
|
89
87
|
## Environment variables
|
package/index.ts
CHANGED
|
@@ -29,7 +29,8 @@ import {
|
|
|
29
29
|
streamSimpleOpenAICompletions,
|
|
30
30
|
AssistantMessageEventStream,
|
|
31
31
|
} from "@mariozechner/pi-ai";
|
|
32
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
32
|
+
import type { ExtensionAPI, OAuthCredential } from "@mariozechner/pi-coding-agent";
|
|
33
|
+
import { AuthStorage } from "@mariozechner/pi-coding-agent";
|
|
33
34
|
|
|
34
35
|
// =============================================================================
|
|
35
36
|
// Constants
|
|
@@ -39,6 +40,9 @@ const CLIENT_ID = "17e5f671-d194-4dfb-9706-5516cb48c098";
|
|
|
39
40
|
const DEFAULT_OAUTH_HOST = "https://auth.kimi.com";
|
|
40
41
|
const PROTOCOL =
|
|
41
42
|
process.env.KIMI_CODE_PROTOCOL === "openai" ? "openai-completions" : "anthropic-messages";
|
|
43
|
+
// Use a custom api identifier so this provider never conflicts with the
|
|
44
|
+
// built-in "anthropic-messages" or "openai-completions" stream handlers.
|
|
45
|
+
const KIMI_API_TYPE = PROTOCOL === "openai-completions" ? "kimi-openai-completions" : "kimi-anthropic-messages";
|
|
42
46
|
const DEFAULT_BASE_URL =
|
|
43
47
|
PROTOCOL === "openai-completions"
|
|
44
48
|
? "https://api.kimi.com/coding/v1"
|
|
@@ -111,11 +115,32 @@ function getDeviceModel(): string {
|
|
|
111
115
|
return version && arch ? `macOS ${version} ${arch}` : `macOS ${arch}`;
|
|
112
116
|
}
|
|
113
117
|
if (platform === "win32") {
|
|
114
|
-
|
|
118
|
+
// Only show the major release (e.g. "Windows 10", "Windows 11") to match
|
|
119
|
+
// the upstream kimi-cli behavior in `def _device_model() -> str:`.
|
|
120
|
+
// See: https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/auth/oauth.py
|
|
121
|
+
const parts = os.release().split(".");
|
|
122
|
+
let release = parts[0];
|
|
123
|
+
if (release === "10" && parts.length >= 3) {
|
|
124
|
+
const build = parseInt(parts[2], 10);
|
|
125
|
+
if (!isNaN(build) && build >= 22000) {
|
|
126
|
+
release = "11";
|
|
127
|
+
}
|
|
128
|
+
}
|
|
115
129
|
return release && arch ? `Windows ${release} ${arch}` : `Windows ${arch}`;
|
|
116
130
|
}
|
|
131
|
+
// Normalize platform name to match Python `platform.system()` casing used by
|
|
132
|
+
// upstream kimi-cli (e.g. "Linux", "FreeBSD", "SunOS"), since Node's
|
|
133
|
+
// `process.platform` is always lower-case.
|
|
134
|
+
const SYSTEM_NAME: Record<string, string> = {
|
|
135
|
+
aix: "AIX",
|
|
136
|
+
freebsd: "FreeBSD",
|
|
137
|
+
linux: "Linux",
|
|
138
|
+
openbsd: "OpenBSD",
|
|
139
|
+
sunos: "SunOS",
|
|
140
|
+
};
|
|
141
|
+
const system = SYSTEM_NAME[platform] ?? platform;
|
|
117
142
|
const release = os.release();
|
|
118
|
-
return release && arch ? `${
|
|
143
|
+
return release && arch ? `${system} ${release} ${arch}` : `${system} ${arch}`;
|
|
119
144
|
}
|
|
120
145
|
|
|
121
146
|
function asciiHeaderValue(value: string, fallback = "unknown"): string {
|
|
@@ -709,6 +734,54 @@ async function* filterEmptyResponseStream(
|
|
|
709
734
|
}
|
|
710
735
|
}
|
|
711
736
|
|
|
737
|
+
// =============================================================================
|
|
738
|
+
// Auth refresh: recover from server-side token invalidation
|
|
739
|
+
// =============================================================================
|
|
740
|
+
// pi-coding-agent only refreshes an OAuth token when the locally cached
|
|
741
|
+
// `expires` is in the past. If the server rotates/revokes the access token
|
|
742
|
+
// before that (common with short-lived session tokens), every request keeps
|
|
743
|
+
// returning 401. We detect that situation by inspecting the first event of
|
|
744
|
+
// the upstream stream, force a refresh through AuthStorage (which persists
|
|
745
|
+
// the new credentials under a file lock), and retry once.
|
|
746
|
+
|
|
747
|
+
const PROVIDER_ID = "kimi-coding";
|
|
748
|
+
|
|
749
|
+
async function refreshKimiAuthToken(currentKey: string): Promise<string | null> {
|
|
750
|
+
try {
|
|
751
|
+
const storage = AuthStorage.create();
|
|
752
|
+
const cred = storage.get(PROVIDER_ID);
|
|
753
|
+
if (!cred || cred.type !== "oauth") {
|
|
754
|
+
console.error(
|
|
755
|
+
`[kimi-coding] auth refresh skipped: no OAuth credentials for ${PROVIDER_ID} on disk`,
|
|
756
|
+
);
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// If disk already has a different valid token (e.g., another process or a
|
|
761
|
+
// previous retry refreshed it while the caller's in-memory cache went
|
|
762
|
+
// stale), reuse it without hitting the OAuth endpoint.
|
|
763
|
+
if (cred.access !== currentKey && Date.now() < cred.expires) {
|
|
764
|
+
console.error("[kimi-coding] auth refresh: reusing newer on-disk token");
|
|
765
|
+
return cred.access;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
console.error("[kimi-coding] auth refresh: requesting new access token");
|
|
769
|
+
const refreshed = await refreshAccessToken(cred.refresh);
|
|
770
|
+
const newCred: OAuthCredential = {
|
|
771
|
+
type: "oauth",
|
|
772
|
+
access: refreshed.access_token,
|
|
773
|
+
refresh: refreshed.refresh_token,
|
|
774
|
+
expires: Date.now() + refreshed.expires_in * 1000,
|
|
775
|
+
};
|
|
776
|
+
storage.set(PROVIDER_ID, newCred);
|
|
777
|
+
console.error("[kimi-coding] auth refresh: new token persisted");
|
|
778
|
+
return newCred.access;
|
|
779
|
+
} catch (err) {
|
|
780
|
+
console.error("[kimi-coding] auth refresh failed:", err);
|
|
781
|
+
return null;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
712
785
|
// =============================================================================
|
|
713
786
|
// Stream wrapper: orchestrates payload mutation + event filter
|
|
714
787
|
// =============================================================================
|
|
@@ -723,7 +796,7 @@ function streamSimpleKimi(
|
|
|
723
796
|
options?: SimpleStreamOptions,
|
|
724
797
|
): AssistantMessageEventStream {
|
|
725
798
|
const filtered = new AssistantMessageEventStream();
|
|
726
|
-
const
|
|
799
|
+
const initialKey = options?.apiKey || process.env.KIMI_API_KEY || "";
|
|
727
800
|
|
|
728
801
|
const cacheKeyOverride = (
|
|
729
802
|
options as (SimpleStreamOptions & { prompt_cache_key?: unknown }) | undefined
|
|
@@ -731,61 +804,143 @@ function streamSimpleKimi(
|
|
|
731
804
|
const cacheKey = (typeof cacheKeyOverride === "string" && cacheKeyOverride) || options?.sessionId;
|
|
732
805
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention);
|
|
733
806
|
const envOverrides = readEnvOverrides();
|
|
734
|
-
const upload: Uploader | undefined = apiKey
|
|
735
|
-
? (mimeType, data) => uploadKimiFile(apiKey, mimeType, data)
|
|
736
|
-
: undefined;
|
|
737
|
-
|
|
738
807
|
const originalOnPayload = options?.onPayload;
|
|
739
|
-
const patchedOptions: SimpleStreamOptions = {
|
|
740
|
-
...options,
|
|
741
|
-
onPayload: async (payload, modelData) => {
|
|
742
|
-
let nextPayload: unknown = payload;
|
|
743
|
-
|
|
744
|
-
if (isRecord(nextPayload)) {
|
|
745
|
-
await applyKimiPayloadMutations(nextPayload, {
|
|
746
|
-
api: model.api,
|
|
747
|
-
upload,
|
|
748
|
-
cacheKey,
|
|
749
|
-
cacheRetention,
|
|
750
|
-
reasoning: options?.reasoning,
|
|
751
|
-
envOverrides,
|
|
752
|
-
});
|
|
753
|
-
}
|
|
754
808
|
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
809
|
+
const buildPatchedOptions = (apiKey: string): SimpleStreamOptions => {
|
|
810
|
+
const upload: Uploader | undefined = apiKey
|
|
811
|
+
? (mimeType, data) => uploadKimiFile(apiKey, mimeType, data)
|
|
812
|
+
: undefined;
|
|
813
|
+
// Only forward apiKey if we actually have one — never override the
|
|
814
|
+
// caller's credential (e.g. Claude Code OAuth token) with an empty string.
|
|
815
|
+
const apiKeyOverride = apiKey ? { apiKey } : {};
|
|
816
|
+
return {
|
|
817
|
+
...options,
|
|
818
|
+
...apiKeyOverride,
|
|
819
|
+
onPayload: async (payload, modelData) => {
|
|
820
|
+
let nextPayload: unknown = payload;
|
|
821
|
+
|
|
822
|
+
if (isRecord(nextPayload)) {
|
|
823
|
+
await applyKimiPayloadMutations(nextPayload, {
|
|
824
|
+
api: model.api,
|
|
825
|
+
upload,
|
|
826
|
+
cacheKey,
|
|
827
|
+
cacheRetention,
|
|
828
|
+
reasoning: options?.reasoning,
|
|
829
|
+
envOverrides,
|
|
830
|
+
});
|
|
831
|
+
}
|
|
759
832
|
|
|
760
|
-
|
|
761
|
-
|
|
833
|
+
if (originalOnPayload) {
|
|
834
|
+
const res = await originalOnPayload(nextPayload, modelData);
|
|
835
|
+
if (res !== undefined) nextPayload = res;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
return nextPayload;
|
|
839
|
+
},
|
|
840
|
+
};
|
|
762
841
|
};
|
|
763
842
|
|
|
764
843
|
void (async () => {
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
844
|
+
let attempt = 0;
|
|
845
|
+
let currentKey = initialKey;
|
|
846
|
+
|
|
847
|
+
while (true) {
|
|
848
|
+
const patchedOptions = buildPatchedOptions(currentKey);
|
|
849
|
+
// Route by the module-level PROTOCOL, not model.api, since we register
|
|
850
|
+
// with a custom api type (kimi-openai-completions / kimi-anthropic-messages)
|
|
851
|
+
// to avoid overriding the built-in Anthropic/OpenAI stream handlers.
|
|
852
|
+
const upstream =
|
|
853
|
+
PROTOCOL === "openai-completions"
|
|
854
|
+
? streamSimpleOpenAICompletions(
|
|
855
|
+
model as Model<"openai-completions">,
|
|
856
|
+
context,
|
|
857
|
+
patchedOptions,
|
|
858
|
+
)
|
|
859
|
+
: streamSimpleAnthropic(model as Model<"anthropic-messages">, context, patchedOptions);
|
|
860
|
+
|
|
861
|
+
let shouldRetry = false;
|
|
862
|
+
let prefixBuffer: AssistantMessageEvent[] = [];
|
|
863
|
+
|
|
864
|
+
try {
|
|
865
|
+
for await (const event of filterEmptyResponseStream(upstream)) {
|
|
866
|
+
// streamAnthropic emits a synthetic "start" event synchronously,
|
|
867
|
+
// before the for-await loop begins iterating and therefore before
|
|
868
|
+
// the HTTP request is actually made. If the request 401s, the loop
|
|
869
|
+
// throws and the catch block emits "error". Without buffering, the
|
|
870
|
+
// "start" event (which carries an empty AssistantMessage) leaks into
|
|
871
|
+
// the session history and the TUI, leaving a phantom empty assistant
|
|
872
|
+
// bubble. We buffer "start" events and only flush them once we see
|
|
873
|
+
// a non-error event that proves the stream is alive.
|
|
874
|
+
if (event.type === "start") {
|
|
875
|
+
prefixBuffer.push(event);
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// Speculative OAuth refresh on the first error. We retry once so
|
|
880
|
+
// that short-lived Kimi tokens invalidated by the server before the
|
|
881
|
+
// local expires timestamp lapses don't surface as raw 401s to the
|
|
882
|
+
// user. Non-auth errors still trigger one wasted refresh, but the
|
|
883
|
+
// retried request fails the same way and we forward it.
|
|
884
|
+
if (attempt === 0 && event.type === "error") {
|
|
885
|
+
console.error(
|
|
886
|
+
`[kimi-coding] upstream error on first event, attempting refresh: ${event.error?.errorMessage?.slice(0, 200)}`,
|
|
887
|
+
);
|
|
888
|
+
const refreshed = await refreshKimiAuthToken(currentKey);
|
|
889
|
+
if (refreshed && refreshed !== currentKey) {
|
|
890
|
+
console.error("[kimi-coding] retrying stream with refreshed token");
|
|
891
|
+
currentKey = refreshed;
|
|
892
|
+
shouldRetry = true;
|
|
893
|
+
break; // discard prefixBuffer — don't leak the stale start
|
|
894
|
+
}
|
|
895
|
+
console.error(
|
|
896
|
+
"[kimi-coding] refresh did not yield a new token, forwarding original error",
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// First non-start, non-retry event: flush buffered prefix, then
|
|
901
|
+
// stream normally.
|
|
902
|
+
for (const e of prefixBuffer) filtered.push(e);
|
|
903
|
+
prefixBuffer = [];
|
|
904
|
+
filtered.push(event);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// Stream ended normally: flush any remaining buffered starts.
|
|
908
|
+
for (const e of prefixBuffer) filtered.push(e);
|
|
909
|
+
} catch (err) {
|
|
910
|
+
// Upstream threw rather than emitting a stream `error` event. This can
|
|
911
|
+
// be the same stale-token 401 surfaced as an exception (depending on
|
|
912
|
+
// the SDK path / network layer), so mirror the in-stream refresh
|
|
913
|
+
// branch: on attempt 0, try one OAuth refresh + retry. Either way,
|
|
914
|
+
// discard `prefixBuffer` — we never confirmed the stream actually
|
|
915
|
+
// started, and flushing the buffered `start` would resurrect the
|
|
916
|
+
// phantom empty assistant message this PR set out to fix.
|
|
917
|
+
console.error("[kimi-coding] stream error:", err);
|
|
918
|
+
if (attempt === 0) {
|
|
919
|
+
const refreshed = await refreshKimiAuthToken(currentKey);
|
|
920
|
+
if (refreshed && refreshed !== currentKey) {
|
|
921
|
+
console.error("[kimi-coding] retrying stream after thrown error with refreshed token");
|
|
922
|
+
currentKey = refreshed;
|
|
923
|
+
shouldRetry = true;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
if (!shouldRetry) {
|
|
927
|
+
filtered.push({
|
|
928
|
+
type: "error",
|
|
929
|
+
reason: "error",
|
|
930
|
+
error: {
|
|
931
|
+
content: [],
|
|
932
|
+
stopReason: "error",
|
|
933
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0 },
|
|
934
|
+
},
|
|
935
|
+
} as AssistantMessageEvent & { type: "error" });
|
|
936
|
+
}
|
|
777
937
|
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
content: [],
|
|
785
|
-
stopReason: "error",
|
|
786
|
-
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0 },
|
|
787
|
-
},
|
|
788
|
-
} as AssistantMessageEvent & { type: "error" });
|
|
938
|
+
|
|
939
|
+
if (shouldRetry) {
|
|
940
|
+
attempt++;
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
break;
|
|
789
944
|
}
|
|
790
945
|
})();
|
|
791
946
|
|
|
@@ -800,7 +955,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
800
955
|
pi.registerProvider("kimi-coding", {
|
|
801
956
|
baseUrl: getBaseUrl(),
|
|
802
957
|
apiKey: "KIMI_API_KEY",
|
|
803
|
-
api:
|
|
958
|
+
api: KIMI_API_TYPE,
|
|
804
959
|
streamSimple: streamSimpleKimi,
|
|
805
960
|
|
|
806
961
|
headers: getCommonHeaders(),
|
|
@@ -815,42 +970,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
815
970
|
contextWindow: 262144,
|
|
816
971
|
maxTokens: 32000,
|
|
817
972
|
},
|
|
818
|
-
{
|
|
819
|
-
id: "kimi-k2.6-code-preview",
|
|
820
|
-
name: "Kimi K2.6 Code Preview",
|
|
821
|
-
reasoning: true,
|
|
822
|
-
input: ["text", "image", "video"],
|
|
823
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
824
|
-
contextWindow: 262144,
|
|
825
|
-
maxTokens: 32000,
|
|
826
|
-
},
|
|
827
|
-
{
|
|
828
|
-
id: "kimi-code",
|
|
829
|
-
name: "Kimi Code (kimi-k2.5)",
|
|
830
|
-
reasoning: true,
|
|
831
|
-
input: ["text", "image"],
|
|
832
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
833
|
-
contextWindow: 262144,
|
|
834
|
-
maxTokens: 32000,
|
|
835
|
-
},
|
|
836
|
-
{
|
|
837
|
-
id: "kimi-k2.5",
|
|
838
|
-
name: "Kimi K2.5",
|
|
839
|
-
reasoning: true,
|
|
840
|
-
input: ["text", "image"],
|
|
841
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
842
|
-
contextWindow: 262144,
|
|
843
|
-
maxTokens: 32000,
|
|
844
|
-
},
|
|
845
|
-
{
|
|
846
|
-
id: "kimi-k2-thinking-turbo",
|
|
847
|
-
name: "Kimi K2 Thinking Turbo",
|
|
848
|
-
reasoning: true,
|
|
849
|
-
input: ["text"],
|
|
850
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
851
|
-
contextWindow: 262144,
|
|
852
|
-
maxTokens: 32000,
|
|
853
|
-
},
|
|
854
973
|
],
|
|
855
974
|
|
|
856
975
|
oauth: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-provider-kimi-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Pi extension for Kimi Code — reuse your Kimi Code Plan in pi-coding-agent (K2.6, K2.5)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -14,13 +14,11 @@
|
|
|
14
14
|
"llm",
|
|
15
15
|
"llm-provider",
|
|
16
16
|
"kimi",
|
|
17
|
-
"kimi-code",
|
|
18
17
|
"kimi-for-coding",
|
|
19
18
|
"kimi-coder",
|
|
20
19
|
"kimi-k2",
|
|
21
20
|
"kimi-k2.6",
|
|
22
21
|
"kimi-k2.5",
|
|
23
|
-
"kimi-k2-thinking",
|
|
24
22
|
"moonshot",
|
|
25
23
|
"moonshotai",
|
|
26
24
|
"oauth",
|