@kenkaiiii/gg-ai 4.5.0 → 4.6.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/dist/index.cjs +127 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +127 -68
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -255,8 +255,9 @@ declare class StreamResult implements AsyncIterable<StreamEvent> {
|
|
|
255
255
|
private resolveResponse;
|
|
256
256
|
private rejectResponse;
|
|
257
257
|
private resolveWait;
|
|
258
|
-
constructor(generator: AsyncGenerator<StreamEvent, StreamResponse
|
|
258
|
+
constructor(generator: AsyncGenerator<StreamEvent, StreamResponse>, signal?: AbortSignal);
|
|
259
259
|
private pump;
|
|
260
|
+
private _nextWithAbort;
|
|
260
261
|
[Symbol.asyncIterator](): AsyncIterator<StreamEvent>;
|
|
261
262
|
then<TResult1 = StreamResponse, TResult2 = never>(onfulfilled?: ((value: StreamResponse) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
262
263
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -255,8 +255,9 @@ declare class StreamResult implements AsyncIterable<StreamEvent> {
|
|
|
255
255
|
private resolveResponse;
|
|
256
256
|
private rejectResponse;
|
|
257
257
|
private resolveWait;
|
|
258
|
-
constructor(generator: AsyncGenerator<StreamEvent, StreamResponse
|
|
258
|
+
constructor(generator: AsyncGenerator<StreamEvent, StreamResponse>, signal?: AbortSignal);
|
|
259
259
|
private pump;
|
|
260
|
+
private _nextWithAbort;
|
|
260
261
|
[Symbol.asyncIterator](): AsyncIterator<StreamEvent>;
|
|
261
262
|
then<TResult1 = StreamResponse, TResult2 = never>(onfulfilled?: ((value: StreamResponse) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
262
263
|
}
|
package/dist/index.js
CHANGED
|
@@ -151,7 +151,7 @@ function finaliseBySource(source, message, requestId, hint) {
|
|
|
151
151
|
headline: message,
|
|
152
152
|
source,
|
|
153
153
|
message: "",
|
|
154
|
-
guidance: hint ?? "Only Kimi, Gemini, and
|
|
154
|
+
guidance: hint ?? "Only Kimi, Gemini, MiniMax, and MiMo-V2.5 can analyze video. Switch with /model.",
|
|
155
155
|
...requestId ? { requestId } : {}
|
|
156
156
|
};
|
|
157
157
|
case "ggcoder":
|
|
@@ -274,21 +274,21 @@ var StreamResult = class {
|
|
|
274
274
|
resolveResponse;
|
|
275
275
|
rejectResponse;
|
|
276
276
|
resolveWait = null;
|
|
277
|
-
constructor(generator) {
|
|
277
|
+
constructor(generator, signal) {
|
|
278
278
|
this.response = new Promise((resolve, reject) => {
|
|
279
279
|
this.resolveResponse = resolve;
|
|
280
280
|
this.rejectResponse = reject;
|
|
281
281
|
});
|
|
282
|
-
this.pump(generator);
|
|
282
|
+
this.pump(generator, signal);
|
|
283
283
|
}
|
|
284
|
-
async pump(generator) {
|
|
284
|
+
async pump(generator, signal) {
|
|
285
285
|
try {
|
|
286
|
-
let next = await
|
|
286
|
+
let next = await this._nextWithAbort(generator, signal);
|
|
287
287
|
while (!next.done) {
|
|
288
288
|
this.buffer.push(next.value);
|
|
289
289
|
this.resolveWait?.();
|
|
290
290
|
this.resolveWait = null;
|
|
291
|
-
next = await
|
|
291
|
+
next = await this._nextWithAbort(generator, signal);
|
|
292
292
|
}
|
|
293
293
|
this.done = true;
|
|
294
294
|
this.resolveResponse(next.value);
|
|
@@ -303,6 +303,28 @@ var StreamResult = class {
|
|
|
303
303
|
this.resolveWait = null;
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
|
+
async _nextWithAbort(generator, signal) {
|
|
307
|
+
if (!signal) {
|
|
308
|
+
return generator.next();
|
|
309
|
+
}
|
|
310
|
+
if (signal.aborted) {
|
|
311
|
+
return Promise.reject(new DOMException("Aborted", "AbortError"));
|
|
312
|
+
}
|
|
313
|
+
let onAbort;
|
|
314
|
+
const abortPromise = new Promise((_, reject) => {
|
|
315
|
+
onAbort = () => {
|
|
316
|
+
generator.return?.(void 0).catch(() => {
|
|
317
|
+
});
|
|
318
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
319
|
+
};
|
|
320
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
321
|
+
});
|
|
322
|
+
try {
|
|
323
|
+
return await Promise.race([generator.next(), abortPromise]);
|
|
324
|
+
} finally {
|
|
325
|
+
if (onAbort) signal.removeEventListener("abort", onAbort);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
306
328
|
async *[Symbol.asyncIterator]() {
|
|
307
329
|
let index = 0;
|
|
308
330
|
while (true) {
|
|
@@ -794,13 +816,14 @@ function toOpenAIMessages(messages, options) {
|
|
|
794
816
|
}
|
|
795
817
|
if (msg.role === "tool") {
|
|
796
818
|
const isMoonshot = options?.provider === "moonshot";
|
|
797
|
-
const
|
|
819
|
+
const followUpMediaBlocks = [];
|
|
820
|
+
let followUpHasVideo = false;
|
|
798
821
|
for (const result of msg.content) {
|
|
799
822
|
const text = toolResultText(result.content);
|
|
800
823
|
const images = toolResultImages(result.content);
|
|
801
|
-
const videos =
|
|
824
|
+
const videos = toolResultVideos(result.content);
|
|
802
825
|
const hasText = text.length > 0;
|
|
803
|
-
if (videos.length > 0) {
|
|
826
|
+
if (isMoonshot && videos.length > 0) {
|
|
804
827
|
const parts = [];
|
|
805
828
|
if (hasText) parts.push({ type: "text", text });
|
|
806
829
|
const videoParts = videos.map((v) => {
|
|
@@ -817,21 +840,31 @@ function toOpenAIMessages(messages, options) {
|
|
|
817
840
|
out.push({
|
|
818
841
|
role: "tool",
|
|
819
842
|
tool_call_id: remapToolCallId(result.toolCallId, idMap),
|
|
820
|
-
content: hasText ? text : "(see attached
|
|
843
|
+
content: hasText ? text : "(see attached media)"
|
|
821
844
|
});
|
|
822
845
|
if (images.length > 0 && options?.supportsImages !== false) {
|
|
823
846
|
for (const img of images) {
|
|
824
|
-
|
|
847
|
+
followUpMediaBlocks.push({
|
|
825
848
|
type: "image_url",
|
|
826
849
|
image_url: { url: `data:${img.mediaType};base64,${img.data}` }
|
|
827
850
|
});
|
|
828
851
|
}
|
|
829
852
|
}
|
|
853
|
+
if (!isMoonshot && videos.length > 0) {
|
|
854
|
+
for (const v of videos) {
|
|
855
|
+
followUpMediaBlocks.push({
|
|
856
|
+
type: "video_url",
|
|
857
|
+
video_url: { url: `data:${v.mediaType};base64,${v.data}` }
|
|
858
|
+
});
|
|
859
|
+
followUpHasVideo = true;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
830
862
|
}
|
|
831
|
-
if (
|
|
863
|
+
if (followUpMediaBlocks.length > 0) {
|
|
864
|
+
const label = followUpHasVideo ? "Attached media from tool result:" : "Attached image(s) from tool result:";
|
|
832
865
|
out.push({
|
|
833
866
|
role: "user",
|
|
834
|
-
content: [{ type: "text", text:
|
|
867
|
+
content: [{ type: "text", text: label }, ...followUpMediaBlocks]
|
|
835
868
|
});
|
|
836
869
|
}
|
|
837
870
|
}
|
|
@@ -908,10 +941,10 @@ function createClient(options) {
|
|
|
908
941
|
...isOAuth ? { apiKey: null, authToken: options.apiKey } : { apiKey: options.apiKey },
|
|
909
942
|
...options.baseUrl ? { baseURL: options.baseUrl } : {},
|
|
910
943
|
...options.fetch ? { fetch: options.fetch } : {},
|
|
911
|
-
//
|
|
912
|
-
//
|
|
913
|
-
//
|
|
914
|
-
maxRetries:
|
|
944
|
+
// Disable SDK retries — the agent loop has its own stall/overload retry
|
|
945
|
+
// logic that surfaces errors properly. SDK retries on 429s can cause
|
|
946
|
+
// multi-minute hangs when the provider stops responding mid-retry.
|
|
947
|
+
maxRetries: 0,
|
|
915
948
|
...isOAuth ? {
|
|
916
949
|
defaultHeaders: {
|
|
917
950
|
// Anthropic's OAuth edge validates the claude-cli version. Callers
|
|
@@ -924,7 +957,7 @@ function createClient(options) {
|
|
|
924
957
|
});
|
|
925
958
|
}
|
|
926
959
|
function streamAnthropic(options) {
|
|
927
|
-
return new StreamResult(runStream(options));
|
|
960
|
+
return new StreamResult(runStream(options), options.signal);
|
|
928
961
|
}
|
|
929
962
|
async function* runStream(options) {
|
|
930
963
|
const client = createClient(options);
|
|
@@ -1019,7 +1052,6 @@ async function* runStream(options) {
|
|
|
1019
1052
|
throw toError(err);
|
|
1020
1053
|
}
|
|
1021
1054
|
}
|
|
1022
|
-
const stream2 = client.messages.stream(params, requestOptions);
|
|
1023
1055
|
const contentParts = [];
|
|
1024
1056
|
const blocks = /* @__PURE__ */ new Map();
|
|
1025
1057
|
let inputTokens = 0;
|
|
@@ -1028,8 +1060,14 @@ async function* runStream(options) {
|
|
|
1028
1060
|
let cacheWrite;
|
|
1029
1061
|
let stopReason = null;
|
|
1030
1062
|
const keepalive = { type: "keepalive" };
|
|
1063
|
+
let receivedAnyEvent = false;
|
|
1031
1064
|
try {
|
|
1065
|
+
const stream2 = await client.messages.create(
|
|
1066
|
+
params,
|
|
1067
|
+
requestOptions
|
|
1068
|
+
);
|
|
1032
1069
|
for await (const event of stream2) {
|
|
1070
|
+
receivedAnyEvent = true;
|
|
1033
1071
|
switch (event.type) {
|
|
1034
1072
|
case "message_start": {
|
|
1035
1073
|
const usage = event.message.usage;
|
|
@@ -1066,7 +1104,7 @@ async function* runStream(options) {
|
|
|
1066
1104
|
accum.toolId = block.id;
|
|
1067
1105
|
accum.toolName = block.name;
|
|
1068
1106
|
accum.input = block.input;
|
|
1069
|
-
} else if (block.type
|
|
1107
|
+
} else if (block.type !== "text" && block.type !== "thinking") {
|
|
1070
1108
|
accum.raw = block;
|
|
1071
1109
|
}
|
|
1072
1110
|
blocks.set(idx, accum);
|
|
@@ -1163,8 +1201,7 @@ async function* runStream(options) {
|
|
|
1163
1201
|
contentParts.push({ type: "raw", data: accum.raw });
|
|
1164
1202
|
yield keepalive;
|
|
1165
1203
|
} else {
|
|
1166
|
-
const
|
|
1167
|
-
const rawBlock = msg?.content[event.index];
|
|
1204
|
+
const rawBlock = accum.raw;
|
|
1168
1205
|
if (rawBlock) {
|
|
1169
1206
|
const blockType = rawBlock.type;
|
|
1170
1207
|
if (blockType === "web_search_tool_result") {
|
|
@@ -1210,6 +1247,11 @@ async function* runStream(options) {
|
|
|
1210
1247
|
} catch (err) {
|
|
1211
1248
|
throw toError(err);
|
|
1212
1249
|
}
|
|
1250
|
+
if (!receivedAnyEvent) {
|
|
1251
|
+
throw new ProviderError("anthropic", "Stream ended without producing any events.", {
|
|
1252
|
+
statusCode: 504
|
|
1253
|
+
});
|
|
1254
|
+
}
|
|
1213
1255
|
const normalizedStop = normalizeAnthropicStopReason(stopReason);
|
|
1214
1256
|
const response = {
|
|
1215
1257
|
message: {
|
|
@@ -1501,7 +1543,7 @@ function createClient2(options) {
|
|
|
1501
1543
|
});
|
|
1502
1544
|
}
|
|
1503
1545
|
function streamOpenAI(options) {
|
|
1504
|
-
return new StreamResult(runStream2(options));
|
|
1546
|
+
return new StreamResult(runStream2(options), options.signal);
|
|
1505
1547
|
}
|
|
1506
1548
|
async function* runStream2(options) {
|
|
1507
1549
|
const providerName = options.provider ?? "openai";
|
|
@@ -1593,51 +1635,62 @@ async function* runStream2(options) {
|
|
|
1593
1635
|
let outputTokens = 0;
|
|
1594
1636
|
let cacheRead = 0;
|
|
1595
1637
|
let finishReason = null;
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
finishReason = choice.finish_reason;
|
|
1604
|
-
}
|
|
1605
|
-
const delta = choice.delta;
|
|
1606
|
-
const reasoningContent = delta.reasoning_content;
|
|
1607
|
-
if (typeof reasoningContent === "string" && reasoningContent) {
|
|
1608
|
-
thinkingAccum += reasoningContent;
|
|
1609
|
-
if (options.thinking) {
|
|
1610
|
-
yield { type: "thinking_delta", text: reasoningContent };
|
|
1638
|
+
let receivedAnyChunk = false;
|
|
1639
|
+
try {
|
|
1640
|
+
for await (const chunk of stream2) {
|
|
1641
|
+
receivedAnyChunk = true;
|
|
1642
|
+
const choice = chunk.choices?.[0];
|
|
1643
|
+
if (chunk.usage) {
|
|
1644
|
+
({ inputTokens, outputTokens, cacheRead } = extractOpenAIUsage(chunk.usage));
|
|
1611
1645
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
if (
|
|
1621
|
-
|
|
1622
|
-
id: tc.id ?? "",
|
|
1623
|
-
name: tc.function?.name ?? "",
|
|
1624
|
-
argsJson: ""
|
|
1625
|
-
};
|
|
1626
|
-
toolCallAccum.set(tc.index, accum);
|
|
1646
|
+
if (!choice) continue;
|
|
1647
|
+
if (choice.finish_reason) {
|
|
1648
|
+
finishReason = choice.finish_reason;
|
|
1649
|
+
}
|
|
1650
|
+
const delta = choice.delta;
|
|
1651
|
+
const reasoningContent = delta.reasoning_content;
|
|
1652
|
+
if (typeof reasoningContent === "string" && reasoningContent) {
|
|
1653
|
+
thinkingAccum += reasoningContent;
|
|
1654
|
+
if (options.thinking) {
|
|
1655
|
+
yield { type: "thinking_delta", text: reasoningContent };
|
|
1627
1656
|
}
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1657
|
+
}
|
|
1658
|
+
if (delta.content) {
|
|
1659
|
+
textAccum += delta.content;
|
|
1660
|
+
yield { type: "text_delta", text: delta.content };
|
|
1661
|
+
}
|
|
1662
|
+
if (delta.tool_calls) {
|
|
1663
|
+
for (const tc of delta.tool_calls) {
|
|
1664
|
+
let accum = toolCallAccum.get(tc.index);
|
|
1665
|
+
if (!accum) {
|
|
1666
|
+
accum = {
|
|
1667
|
+
id: tc.id ?? "",
|
|
1668
|
+
name: tc.function?.name ?? "",
|
|
1669
|
+
argsJson: ""
|
|
1670
|
+
};
|
|
1671
|
+
toolCallAccum.set(tc.index, accum);
|
|
1672
|
+
}
|
|
1673
|
+
if (tc.id) accum.id = tc.id;
|
|
1674
|
+
if (tc.function?.name) accum.name = tc.function.name;
|
|
1675
|
+
if (tc.function?.arguments) {
|
|
1676
|
+
accum.argsJson += tc.function.arguments;
|
|
1677
|
+
yield {
|
|
1678
|
+
type: "toolcall_delta",
|
|
1679
|
+
id: accum.id,
|
|
1680
|
+
name: accum.name,
|
|
1681
|
+
argsJson: tc.function.arguments
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1638
1684
|
}
|
|
1639
1685
|
}
|
|
1640
1686
|
}
|
|
1687
|
+
} catch (err) {
|
|
1688
|
+
throw toError2(err, providerName);
|
|
1689
|
+
}
|
|
1690
|
+
if (!receivedAnyChunk) {
|
|
1691
|
+
throw new ProviderError(providerName, "Stream ended without producing any chunks.", {
|
|
1692
|
+
statusCode: 504
|
|
1693
|
+
});
|
|
1641
1694
|
}
|
|
1642
1695
|
if (thinkingAccum) {
|
|
1643
1696
|
contentParts.push({ type: "thinking", text: thinkingAccum });
|
|
@@ -1880,7 +1933,7 @@ function isVisibleOutputItem(itemType) {
|
|
|
1880
1933
|
return itemType === "message";
|
|
1881
1934
|
}
|
|
1882
1935
|
function streamOpenAICodex(options) {
|
|
1883
|
-
return new StreamResult(runStream3(options));
|
|
1936
|
+
return new StreamResult(runStream3(options), options.signal);
|
|
1884
1937
|
}
|
|
1885
1938
|
async function* runStream3(options) {
|
|
1886
1939
|
const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
@@ -2210,10 +2263,16 @@ async function* parseSSE(body) {
|
|
|
2210
2263
|
}
|
|
2211
2264
|
}
|
|
2212
2265
|
function remapCodexId(id, idMap) {
|
|
2213
|
-
if (id.startsWith("fc_") || id.startsWith("fc-")) return id;
|
|
2214
2266
|
const existing = idMap.get(id);
|
|
2215
2267
|
if (existing) return existing;
|
|
2216
|
-
const
|
|
2268
|
+
const withPrefix = id.startsWith("fc_") || id.startsWith("fc-") ? id : `fc_${id.replace(/^toolu_/, "")}`;
|
|
2269
|
+
const sanitized = withPrefix.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
2270
|
+
let mapped = sanitized;
|
|
2271
|
+
let suffix = 2;
|
|
2272
|
+
const used = new Set(idMap.values());
|
|
2273
|
+
while (used.has(mapped)) {
|
|
2274
|
+
mapped = `${sanitized}_${suffix++}`;
|
|
2275
|
+
}
|
|
2217
2276
|
idMap.set(id, mapped);
|
|
2218
2277
|
return mapped;
|
|
2219
2278
|
}
|
|
@@ -2736,7 +2795,7 @@ async function fetchCodeAssistWithRetry(plan, options) {
|
|
|
2736
2795
|
throw lastError ?? new ProviderError("gemini", "Gemini Code Assist request failed.");
|
|
2737
2796
|
}
|
|
2738
2797
|
function streamGemini(options) {
|
|
2739
|
-
return new StreamResult(runStream4(options));
|
|
2798
|
+
return new StreamResult(runStream4(options), options.signal);
|
|
2740
2799
|
}
|
|
2741
2800
|
async function* runStream4(options) {
|
|
2742
2801
|
const useStreaming = options.streaming !== false;
|
|
@@ -3192,7 +3251,7 @@ function registerPalsuProvider(config) {
|
|
|
3192
3251
|
const stopReason = explicitStop ?? (hasToolCalls ? "tool_use" : "end_turn");
|
|
3193
3252
|
return yield* simulateStream(message, stopReason, options.signal, cacheUsage);
|
|
3194
3253
|
})();
|
|
3195
|
-
return new StreamResult(gen);
|
|
3254
|
+
return new StreamResult(gen, options.signal);
|
|
3196
3255
|
}
|
|
3197
3256
|
});
|
|
3198
3257
|
return handle;
|