@kenkaiiii/gg-ai 5.91.0 → 5.91.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/LICENSE +661 -21
- package/NOTICE +52 -0
- package/README.md +72 -68
- package/dist/index.cjs +15 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/NOTICE
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
GG Coder
|
|
2
|
+
Copyright (C) 2025-2026 KenKai
|
|
3
|
+
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU Affero General Public License as published by the Free
|
|
6
|
+
Software Foundation, version 3 only (AGPL-3.0-only). See LICENSE.
|
|
7
|
+
|
|
8
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
9
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
10
|
+
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
11
|
+
details.
|
|
12
|
+
|
|
13
|
+
Releases before 4 November 2026 (up to and including v0.102.0 of the desktop
|
|
14
|
+
app and 5.91.0 of the npm packages) were published under the MIT License, and
|
|
15
|
+
copies already received under those terms keep them.
|
|
16
|
+
|
|
17
|
+
--------------------------------------------------------------------------------
|
|
18
|
+
Contributions under the MIT License
|
|
19
|
+
|
|
20
|
+
The WSL-to-Windows-host audio playback in packages/ggcoder/src/core/radio.ts
|
|
21
|
+
(isWsl and tryPlayOnWindowsHost) is derived from contributions by
|
|
22
|
+
creativeprofit22 (pull requests #15 and #16, May 2026), made under these terms:
|
|
23
|
+
|
|
24
|
+
Copyright (c) 2026 creativeprofit22
|
|
25
|
+
|
|
26
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
27
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
28
|
+
in the Software without restriction, including without limitation the rights
|
|
29
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
30
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
31
|
+
furnished to do so, subject to the following conditions:
|
|
32
|
+
|
|
33
|
+
The above copyright notice and this permission notice shall be included in
|
|
34
|
+
all copies or substantial portions of the Software.
|
|
35
|
+
|
|
36
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
37
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
38
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
39
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
40
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
41
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
42
|
+
SOFTWARE.
|
|
43
|
+
|
|
44
|
+
--------------------------------------------------------------------------------
|
|
45
|
+
Third-party components
|
|
46
|
+
|
|
47
|
+
Bundled third-party code, fonts and media keep their own licenses, listed in:
|
|
48
|
+
gg-app/src/assets/fonts/THIRD-PARTY.md
|
|
49
|
+
packages/ggcoder/assets/motion/THIRD-PARTY.md
|
|
50
|
+
packages/gg-world/CREDITS.md
|
|
51
|
+
and in the LICENSE / OFL.txt files beside each component. npm and Cargo
|
|
52
|
+
dependencies are installed under their own licenses.
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="https://www.npmjs.com/package/@kenkaiiii/gg-ai"><img src="https://img.shields.io/npm/v/@kenkaiiii/gg-ai?style=for-the-badge" alt="npm version"></a>
|
|
9
|
-
<a href="../../LICENSE"><img src="https://img.shields.io/badge/License-
|
|
9
|
+
<a href="../../LICENSE"><img src="https://img.shields.io/badge/License-AGPL--3.0-blue.svg?style=for-the-badge" alt="AGPL-3.0 License"></a>
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
One function. Flat options. Switch providers by changing a string. No adapters, no plugins, no wrapper classes.
|
|
@@ -38,21 +38,21 @@ Tool parameters are Zod schemas. Converted to JSON Schema at the provider bounda
|
|
|
38
38
|
|
|
39
39
|
## Providers
|
|
40
40
|
|
|
41
|
-
| Provider
|
|
42
|
-
|
|
43
|
-
| `anthropic`
|
|
44
|
-
| `openai`
|
|
45
|
-
| `gemini`
|
|
46
|
-
| `xai`
|
|
47
|
-
| `moonshot`
|
|
48
|
-
| `glm`
|
|
49
|
-
| `minimax`
|
|
50
|
-
| `xiaomi`
|
|
51
|
-
| `deepseek`
|
|
52
|
-
| `sakana`
|
|
53
|
-
| `openrouter`
|
|
54
|
-
| `huggingface` | Kimi K2.7 Code, DeepSeek V4.1 Flash, GPT-OSS 120B
|
|
55
|
-
| `local`
|
|
41
|
+
| Provider | Models | Notes |
|
|
42
|
+
| ------------- | --------------------------------------------------------------------- | --------------------------------------------------------- |
|
|
43
|
+
| `anthropic` | Claude Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5 | Extended thinking, prompt caching, server-side compaction |
|
|
44
|
+
| `openai` | GPT-6 Astra, GPT-6.1 Sol, GPT-6 Luna | OAuth (Codex endpoint) or API key |
|
|
45
|
+
| `gemini` | Gemini 3.1 Pro (Preview), 3.8 / 3.7 / 3.5 Flash, 3.5 / 3.1 Flash Lite | OAuth (Code Assist); native video input |
|
|
46
|
+
| `xai` | Grok 4.7 | OpenAI-compatible, `https://api.x.ai/v1` |
|
|
47
|
+
| `moonshot` | Kimi K3, K2.8 Preview, K2.7 Code, K2.7 Code HighSpeed | OpenAI-compatible; native video input |
|
|
48
|
+
| `glm` | GLM-5.3, GLM-5.3-Flash | Z.AI coding endpoint, OpenAI-compatible |
|
|
49
|
+
| `minimax` | MiniMax M3 | Anthropic-compatible endpoint |
|
|
50
|
+
| `xiaomi` | MiMo-V2.6-Pro, MiMo-V2.6-Flash, MiMo-V2.6-Pro-UltraSpeed | OpenAI-compatible |
|
|
51
|
+
| `deepseek` | DeepSeek V4 Pro, V4.1 Flash | OpenAI-compatible |
|
|
52
|
+
| `sakana` | Fugu, Fugu Max, Fugu Ultra | OpenAI-compatible |
|
|
53
|
+
| `openrouter` | Qwen3.8 Max, or any OpenRouter model id | OpenAI-compatible gateway |
|
|
54
|
+
| `huggingface` | Kimi K2.7 Code, DeepSeek V4.1 Flash, GPT-OSS 120B | Inference Providers router, OpenAI-compatible |
|
|
55
|
+
| `local` | Any model your server exposes | Ollama, LM Studio, llama.cpp, vLLM; `baseUrl` is required |
|
|
56
56
|
|
|
57
57
|
The model lists are the ones GG Coder ships in its registry (`@kenkaiiii/gg-core`). `stream()` passes `model` straight through, so any id the provider accepts works. Every provider's default endpoint can be overridden with `baseUrl`, and `providerRegistry.register()` adds your own.
|
|
58
58
|
|
|
@@ -60,45 +60,45 @@ The model lists are the ones GG Coder ships in its registry (`@kenkaiiii/gg-core
|
|
|
60
60
|
|
|
61
61
|
## Stream events
|
|
62
62
|
|
|
63
|
-
| Event
|
|
64
|
-
|
|
65
|
-
| `text_delta`
|
|
66
|
-
| `thinking_delta`
|
|
67
|
-
| `toolcall_delta`
|
|
68
|
-
| `toolcall_done`
|
|
69
|
-
| `server_toolcall`
|
|
70
|
-
| `server_toolresult` | Server-side tool result
|
|
71
|
-
| `keepalive`
|
|
72
|
-
| `done`
|
|
73
|
-
| `error`
|
|
63
|
+
| Event | Description |
|
|
64
|
+
| ------------------- | ------------------------------------------------------------------ |
|
|
65
|
+
| `text_delta` | Incremental text output |
|
|
66
|
+
| `thinking_delta` | Reasoning output, from any provider that streams it |
|
|
67
|
+
| `toolcall_delta` | Streaming tool call arguments |
|
|
68
|
+
| `toolcall_done` | Completed tool call with parsed args |
|
|
69
|
+
| `server_toolcall` | Server-side tool invocation |
|
|
70
|
+
| `server_toolresult` | Server-side tool result |
|
|
71
|
+
| `keepalive` | Provider heartbeat: the stream is alive but has no new content yet |
|
|
72
|
+
| `done` | Stream finished, includes stop reason |
|
|
73
|
+
| `error` | Error occurred |
|
|
74
74
|
|
|
75
75
|
---
|
|
76
76
|
|
|
77
77
|
## Options
|
|
78
78
|
|
|
79
|
-
| Option
|
|
80
|
-
|
|
81
|
-
| `provider`
|
|
82
|
-
| `model`
|
|
83
|
-
| `messages`
|
|
84
|
-
| `tools`
|
|
85
|
-
| `toolChoice`
|
|
86
|
-
| `serverTools`
|
|
87
|
-
| `maxTokens`
|
|
88
|
-
| `temperature`
|
|
89
|
-
| `topP`
|
|
90
|
-
| `stop`
|
|
91
|
-
| `thinking`
|
|
92
|
-
| `apiKey`
|
|
93
|
-
| `baseUrl`
|
|
94
|
-
| `signal`
|
|
95
|
-
| `cacheRetention`
|
|
96
|
-
| `promptCacheKey`
|
|
97
|
-
| `webSearch`
|
|
98
|
-
| `compaction`
|
|
99
|
-
| `clearToolUses`
|
|
100
|
-
| `fetch`
|
|
101
|
-
| `providerOptions` | `Record<string, unknown>`
|
|
79
|
+
| Option | Type | Description |
|
|
80
|
+
| ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------------ |
|
|
81
|
+
| `provider` | `Provider` (any id in the table above) | Required |
|
|
82
|
+
| `model` | `string` | Required |
|
|
83
|
+
| `messages` | `Message[]` | Required |
|
|
84
|
+
| `tools` | `Tool[]` | Tool definitions with Zod schemas |
|
|
85
|
+
| `toolChoice` | `"auto" \| "none" \| "required" \| { name }` | Tool selection strategy |
|
|
86
|
+
| `serverTools` | `ServerToolDefinition[]` | Server-side tool definitions |
|
|
87
|
+
| `maxTokens` | `number` | Max output tokens |
|
|
88
|
+
| `temperature` | `number` | Sampling temperature |
|
|
89
|
+
| `topP` | `number` | Nucleus sampling |
|
|
90
|
+
| `stop` | `string[]` | Stop sequences |
|
|
91
|
+
| `thinking` | `"low" \| "medium" \| "high" \| "xhigh" \| "max" \| "ultra"` | Reasoning effort; each provider maps it to what the model supports |
|
|
92
|
+
| `apiKey` | `string` | Provider API key |
|
|
93
|
+
| `baseUrl` | `string` | Custom endpoint |
|
|
94
|
+
| `signal` | `AbortSignal` | Cancellation |
|
|
95
|
+
| `cacheRetention` | `"none" \| "short" \| "long"` | Prompt cache preference |
|
|
96
|
+
| `promptCacheKey` | `string` | Stable cache routing key (OpenAI, Moonshot, Gemini) |
|
|
97
|
+
| `webSearch` | `boolean` | Provider-native web search where supported |
|
|
98
|
+
| `compaction` | `boolean` | Server-side compaction (Anthropic only) |
|
|
99
|
+
| `clearToolUses` | `boolean` | Server-side clearing of old tool results (Anthropic only) |
|
|
100
|
+
| `fetch` | `typeof fetch` | Custom fetch, e.g. for React Native |
|
|
101
|
+
| `providerOptions` | `Record<string, unknown>` | Provider-specific body fields; see below |
|
|
102
102
|
|
|
103
103
|
### Provider-specific body fields
|
|
104
104
|
|
|
@@ -152,6 +152,7 @@ const { results } = await rerank({
|
|
|
152
152
|
```
|
|
153
153
|
|
|
154
154
|
**What `embed()` guarantees**
|
|
155
|
+
|
|
155
156
|
- Vectors come back in input order, even when the provider returns them out of order (gg-ai sorts by `index`).
|
|
156
157
|
- Long inputs are split at the provider's per-request limit (table below; override with `batchSize`). Batches run one at a time, in order.
|
|
157
158
|
- The response is checked: exactly one vector per input, all numbers, all the same length, and `dimensions` long when you asked for that. If any check fails it throws `ProviderError`. Nothing is padded or truncated.
|
|
@@ -163,18 +164,19 @@ const { results } = await rerank({
|
|
|
163
164
|
|
|
164
165
|
### Provider support
|
|
165
166
|
|
|
166
|
-
| Provider
|
|
167
|
-
|
|
168
|
-
| `openai`
|
|
169
|
-
| `openrouter`
|
|
170
|
-
| `gemini`
|
|
171
|
-
| `local`
|
|
172
|
-
| `palsu`
|
|
173
|
-
| `anthropic`, `xiaomi`, `glm`, `moonshot`, `minimax`, `deepseek`, `sakana`, `xai`, `huggingface` | —
|
|
167
|
+
| Provider | `embed` | Max inputs per request | `inputType` | `rerank` |
|
|
168
|
+
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------ |
|
|
169
|
+
| `openai` | ✓ `/v1/embeddings` | 2048 | ignored | — |
|
|
170
|
+
| `openrouter` | ✓ `/api/v1/embeddings` | 64 (gg-ai default; OpenRouter documents no limit) | `input_type` | ✓ `/api/v1/rerank` |
|
|
171
|
+
| `gemini` | ✓ native `batchEmbedContents` | 100 | `taskType` | — |
|
|
172
|
+
| `local` | ✓ `{baseUrl}/embeddings` (Ollama, LM Studio, llama.cpp, vLLM) | 64 (gg-ai default) | ignored | ✓ `{baseUrl}/rerank` (llama.cpp `--rerank`, vLLM; Ollama and LM Studio have none and return 404) |
|
|
173
|
+
| `palsu` | ✓ deterministic fake | all | ignored | ✓ deterministic fake |
|
|
174
|
+
| `anthropic`, `xiaomi`, `glm`, `moonshot`, `minimax`, `deepseek`, `sakana`, `xai`, `huggingface` | — | | | — |
|
|
174
175
|
|
|
175
176
|
Calling `embed()` or `rerank()` on a provider without that capability throws `GGAIError` with `source: "capability"`. Check first with `providerRegistry.supports(name, "embed")`.
|
|
176
177
|
|
|
177
178
|
Notes:
|
|
179
|
+
|
|
178
180
|
- **Gemini** embeddings use the Gemini API with an AI Studio key, sent as `x-goog-api-key`. The Code Assist sign-in that `stream()` uses for Gemini chat has no embeddings endpoint.
|
|
179
181
|
- **OpenAI** embeddings need a platform API key. ChatGPT-subscription (Codex) tokens can't call `/embeddings`.
|
|
180
182
|
- Anthropic has no embeddings API (it points to Voyage AI). The other providers in the last row don't document an embeddings or rerank endpoint on the API gg-ai talks to, so none is registered for them.
|
|
@@ -184,14 +186,14 @@ Notes:
|
|
|
184
186
|
|
|
185
187
|
Failures use the same error model as `stream()`:
|
|
186
188
|
|
|
187
|
-
| Failure
|
|
188
|
-
|
|
189
|
-
| HTTP 401 / 403
|
|
190
|
-
| HTTP 402, or billing text such as `insufficient_quota` | `ProviderError` with "usage limit reached" (`isUsageLimitError()` is true)
|
|
191
|
-
| HTTP 429
|
|
192
|
-
| Other HTTP errors
|
|
193
|
-
| Connection failure
|
|
194
|
-
| `signal` aborted
|
|
189
|
+
| Failure | Error |
|
|
190
|
+
| ------------------------------------------------------ | --------------------------------------------------------------------------- |
|
|
191
|
+
| HTTP 401 / 403 | `ProviderError`, `source: "auth"` |
|
|
192
|
+
| HTTP 402, or billing text such as `insufficient_quota` | `ProviderError` with "usage limit reached" (`isUsageLimitError()` is true) |
|
|
193
|
+
| HTTP 429 | `ProviderError`, `statusCode: 429`, `resetsAt` from `Retry-After` when sent |
|
|
194
|
+
| Other HTTP errors | `ProviderError` with `statusCode` and `requestId` |
|
|
195
|
+
| Connection failure | `GGAIError`, `source: "network"` |
|
|
196
|
+
| `signal` aborted | `AbortError` (`DOMException`); remaining batches are skipped |
|
|
195
197
|
|
|
196
198
|
Provider error bodies are trimmed to their message, then redacted and truncated, so API keys never end up in an error message.
|
|
197
199
|
|
|
@@ -205,7 +207,9 @@ A provider registered at runtime can offer embeddings and reranking too. `stream
|
|
|
205
207
|
import { providerRegistry, embed, type Provider, type ProviderEntry } from "@kenkaiiii/gg-ai";
|
|
206
208
|
|
|
207
209
|
providerRegistry.register("my-search", {
|
|
208
|
-
stream: () => {
|
|
210
|
+
stream: () => {
|
|
211
|
+
throw new Error("chat not supported");
|
|
212
|
+
},
|
|
209
213
|
embedBatchSize: 128,
|
|
210
214
|
embed: async ({ model, input, dimensions, apiKey, signal, fetch = globalThis.fetch }) => {
|
|
211
215
|
const res = await fetch("https://example.com/embed", {
|
|
@@ -234,4 +238,4 @@ await embed({ provider: "my-search" as Provider, model: "v1", input: ["hello"] }
|
|
|
234
238
|
|
|
235
239
|
## License
|
|
236
240
|
|
|
237
|
-
|
|
241
|
+
AGPL-3.0-only. See [LICENSE](../../LICENSE).
|
package/dist/index.cjs
CHANGED
|
@@ -2068,6 +2068,14 @@ function toCodexReasoningEffort(level, model) {
|
|
|
2068
2068
|
if (level !== "ultra") return level;
|
|
2069
2069
|
return model === "gpt-6-astra" || model === "gpt-6.1-sol" ? "xhigh" : "max";
|
|
2070
2070
|
}
|
|
2071
|
+
var DECLARED_EFFORT_ORDER = ["low", "medium", "high", "xhigh", "max"];
|
|
2072
|
+
function effortForRequest(level, model, declared) {
|
|
2073
|
+
const rungs = DECLARED_EFFORT_ORDER.filter((rung) => declared?.includes(rung));
|
|
2074
|
+
if (rungs.length === 0) return toOpenAIReasoningEffort(level, model);
|
|
2075
|
+
const wanted = level === "ultra" ? DECLARED_EFFORT_ORDER.length - 1 : DECLARED_EFFORT_ORDER.indexOf(level);
|
|
2076
|
+
const atOrBelow = rungs.filter((rung) => DECLARED_EFFORT_ORDER.indexOf(rung) <= wanted);
|
|
2077
|
+
return atOrBelow[atOrBelow.length - 1] ?? rungs[0];
|
|
2078
|
+
}
|
|
2071
2079
|
function toOpenAIReasoningEffort(level, model) {
|
|
2072
2080
|
const effort = level === "max" || level === "ultra" ? "xhigh" : level;
|
|
2073
2081
|
if (model.startsWith("fugu") && (effort === "low" || effort === "medium")) {
|
|
@@ -3103,7 +3111,13 @@ async function* runStream2(options) {
|
|
|
3103
3111
|
...effectiveTemp != null && !options.thinking && !hasFixedKimiSampling ? { temperature: effectiveTemp } : {},
|
|
3104
3112
|
...options.topP != null && !hasFixedKimiSampling ? { top_p: options.topP } : {},
|
|
3105
3113
|
...options.stop ? { stop: options.stop } : {},
|
|
3106
|
-
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 && !isLocal ? {
|
|
3114
|
+
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 && !isLocal ? {
|
|
3115
|
+
reasoning_effort: effortForRequest(
|
|
3116
|
+
options.thinking,
|
|
3117
|
+
options.model,
|
|
3118
|
+
options.thinkingLevels
|
|
3119
|
+
)
|
|
3120
|
+
} : {},
|
|
3107
3121
|
...options.tools?.length ? {
|
|
3108
3122
|
tools: toOpenAITools(options.tools, {
|
|
3109
3123
|
strict: supportsStrictToolSampling(options.provider) && (options.strictTools ?? true)
|