@prestyj/ai 4.2.77 → 4.3.15
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 +360 -237
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -11
- package/dist/index.d.ts +18 -11
- package/dist/index.js +360 -237
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -104,44 +104,62 @@ var EventStream = class {
|
|
|
104
104
|
}
|
|
105
105
|
};
|
|
106
106
|
var StreamResult = class {
|
|
107
|
-
events;
|
|
108
107
|
response;
|
|
108
|
+
buffer = [];
|
|
109
|
+
done = false;
|
|
110
|
+
error = null;
|
|
109
111
|
resolveResponse;
|
|
110
112
|
rejectResponse;
|
|
111
|
-
|
|
112
|
-
constructor() {
|
|
113
|
-
this.events = new EventStream();
|
|
113
|
+
resolveWait = null;
|
|
114
|
+
constructor(generator) {
|
|
114
115
|
this.response = new Promise((resolve, reject) => {
|
|
115
116
|
this.resolveResponse = resolve;
|
|
116
117
|
this.rejectResponse = reject;
|
|
117
118
|
});
|
|
119
|
+
this.pump(generator);
|
|
118
120
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
async pump(generator) {
|
|
122
|
+
try {
|
|
123
|
+
let next = await generator.next();
|
|
124
|
+
while (!next.done) {
|
|
125
|
+
this.buffer.push(next.value);
|
|
126
|
+
this.resolveWait?.();
|
|
127
|
+
this.resolveWait = null;
|
|
128
|
+
next = await generator.next();
|
|
129
|
+
}
|
|
130
|
+
this.done = true;
|
|
131
|
+
this.resolveResponse(next.value);
|
|
132
|
+
this.resolveWait?.();
|
|
133
|
+
this.resolveWait = null;
|
|
134
|
+
} catch (err) {
|
|
135
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
136
|
+
this.error = error;
|
|
137
|
+
this.done = true;
|
|
138
|
+
this.rejectResponse(error);
|
|
139
|
+
this.resolveWait?.();
|
|
140
|
+
this.resolveWait = null;
|
|
141
|
+
}
|
|
129
142
|
}
|
|
130
|
-
[Symbol.asyncIterator]() {
|
|
131
|
-
|
|
132
|
-
|
|
143
|
+
async *[Symbol.asyncIterator]() {
|
|
144
|
+
let index = 0;
|
|
145
|
+
while (true) {
|
|
146
|
+
while (index < this.buffer.length) {
|
|
147
|
+
yield this.buffer[index++];
|
|
148
|
+
}
|
|
149
|
+
if (this.error) throw this.error;
|
|
150
|
+
if (this.done) return;
|
|
151
|
+
await new Promise((r) => {
|
|
152
|
+
this.resolveWait = r;
|
|
153
|
+
if (this.buffer.length > index || this.done || this.error) {
|
|
154
|
+
this.resolveWait = null;
|
|
155
|
+
r();
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
133
159
|
}
|
|
134
160
|
then(onfulfilled, onrejected) {
|
|
135
|
-
this.drainEvents().catch(() => {
|
|
136
|
-
});
|
|
137
161
|
return this.response.then(onfulfilled, onrejected);
|
|
138
162
|
}
|
|
139
|
-
async drainEvents() {
|
|
140
|
-
if (this.hasConsumer) return;
|
|
141
|
-
this.hasConsumer = true;
|
|
142
|
-
for await (const _ of this.events) {
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
163
|
};
|
|
146
164
|
|
|
147
165
|
// src/providers/anthropic.ts
|
|
@@ -215,6 +233,7 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
215
233
|
if (part.type === "raw") return part.data;
|
|
216
234
|
return null;
|
|
217
235
|
}).filter(Boolean);
|
|
236
|
+
if (Array.isArray(content) && content.length === 0) continue;
|
|
218
237
|
out.push({ role: "assistant", content });
|
|
219
238
|
continue;
|
|
220
239
|
}
|
|
@@ -378,13 +397,16 @@ function toOpenAIMessages(messages, options) {
|
|
|
378
397
|
) : void 0;
|
|
379
398
|
const textParts = typeof msg.content !== "string" ? msg.content.filter((p) => p.type === "text").map((p) => p.text).join("") : void 0;
|
|
380
399
|
const thinkingParts = typeof msg.content !== "string" ? msg.content.filter((p) => p.type === "thinking").map((p) => p.text).join("") : void 0;
|
|
400
|
+
const contentValue = parts || textParts || null;
|
|
401
|
+
const hasToolCalls = toolCalls && toolCalls.length > 0;
|
|
402
|
+
if (!contentValue && !hasToolCalls) continue;
|
|
381
403
|
const assistantMsg = {
|
|
382
404
|
role: "assistant",
|
|
383
|
-
content:
|
|
384
|
-
...
|
|
405
|
+
content: contentValue,
|
|
406
|
+
...hasToolCalls ? { tool_calls: toolCalls } : {}
|
|
385
407
|
};
|
|
386
|
-
if (thinkingParts
|
|
387
|
-
assistantMsg.reasoning_content = thinkingParts
|
|
408
|
+
if (thinkingParts) {
|
|
409
|
+
assistantMsg.reasoning_content = thinkingParts;
|
|
388
410
|
}
|
|
389
411
|
out.push(assistantMsg);
|
|
390
412
|
continue;
|
|
@@ -450,17 +472,16 @@ function normalizeOpenAIStopReason(reason) {
|
|
|
450
472
|
}
|
|
451
473
|
|
|
452
474
|
// src/providers/anthropic.ts
|
|
453
|
-
function
|
|
454
|
-
const result = new StreamResult();
|
|
455
|
-
runStream(options, result).catch((err) => result.abort(toError(err)));
|
|
456
|
-
return result;
|
|
457
|
-
}
|
|
458
|
-
async function runStream(options, result) {
|
|
475
|
+
function createClient(options) {
|
|
459
476
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
460
|
-
|
|
477
|
+
return new import_sdk.default({
|
|
461
478
|
...isOAuth ? { apiKey: null, authToken: options.apiKey } : { apiKey: options.apiKey },
|
|
462
479
|
...options.baseUrl ? { baseURL: options.baseUrl } : {},
|
|
463
480
|
...options.fetch ? { fetch: options.fetch } : {},
|
|
481
|
+
// Allow SDK retries for connection-level failures (socket hang up, 500s,
|
|
482
|
+
// connection refused). Our stall detection handles abort-initiated retries
|
|
483
|
+
// separately — SDK retries only fire on genuine transport errors.
|
|
484
|
+
maxRetries: 2,
|
|
464
485
|
...isOAuth ? {
|
|
465
486
|
defaultHeaders: {
|
|
466
487
|
"user-agent": "claude-cli/2.1.75",
|
|
@@ -468,6 +489,13 @@ async function runStream(options, result) {
|
|
|
468
489
|
}
|
|
469
490
|
} : {}
|
|
470
491
|
});
|
|
492
|
+
}
|
|
493
|
+
function streamAnthropic(options) {
|
|
494
|
+
return new StreamResult(runStream(options));
|
|
495
|
+
}
|
|
496
|
+
async function* runStream(options) {
|
|
497
|
+
const client = createClient(options);
|
|
498
|
+
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
471
499
|
const cacheControl = toAnthropicCacheControl(options.cacheRetention, options.baseUrl);
|
|
472
500
|
const { system: rawSystem, messages } = toAnthropicMessages(options.messages, cacheControl);
|
|
473
501
|
const system = isOAuth ? [
|
|
@@ -515,126 +543,209 @@ async function runStream(options, result) {
|
|
|
515
543
|
})(),
|
|
516
544
|
stream: true
|
|
517
545
|
};
|
|
546
|
+
const hasAdaptiveThinking = options.model.includes("opus-4-6") || options.model.includes("opus-4.6") || options.model.includes("sonnet-4-6") || options.model.includes("sonnet-4.6");
|
|
518
547
|
const betaHeaders = [
|
|
519
548
|
...isOAuth ? ["claude-code-20250219", "oauth-2025-04-20"] : [],
|
|
520
549
|
...options.compaction ? ["compact-2026-01-12"] : [],
|
|
521
|
-
...options.clearToolUses ? ["context-management-2025-06-27"] : []
|
|
550
|
+
...options.clearToolUses ? ["context-management-2025-06-27"] : [],
|
|
551
|
+
"fine-grained-tool-streaming-2025-05-14",
|
|
552
|
+
...!hasAdaptiveThinking ? ["interleaved-thinking-2025-05-14"] : []
|
|
522
553
|
];
|
|
523
554
|
const stream2 = client.messages.stream(params, {
|
|
524
555
|
signal: options.signal ?? void 0,
|
|
525
556
|
...betaHeaders.length ? { headers: { "anthropic-beta": betaHeaders.join(",") } } : {}
|
|
526
557
|
});
|
|
527
558
|
const contentParts = [];
|
|
528
|
-
|
|
529
|
-
let
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
});
|
|
536
|
-
stream2.on("streamEvent", (event) => {
|
|
537
|
-
if (event.type === "content_block_start") {
|
|
538
|
-
if (event.content_block.type === "tool_use") {
|
|
539
|
-
currentToolId = event.content_block.id;
|
|
540
|
-
currentToolName = event.content_block.name;
|
|
541
|
-
}
|
|
542
|
-
if (event.content_block.type === "server_tool_use") {
|
|
543
|
-
currentToolId = event.content_block.id;
|
|
544
|
-
currentToolName = event.content_block.name;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
});
|
|
548
|
-
stream2.on("inputJson", (delta) => {
|
|
549
|
-
result.push({
|
|
550
|
-
type: "toolcall_delta",
|
|
551
|
-
id: currentToolId,
|
|
552
|
-
name: currentToolName,
|
|
553
|
-
argsJson: delta
|
|
554
|
-
});
|
|
555
|
-
});
|
|
556
|
-
stream2.on("contentBlock", (block) => {
|
|
557
|
-
if (block.type === "text") {
|
|
558
|
-
contentParts.push({ type: "text", text: block.text });
|
|
559
|
-
} else if (block.type === "thinking") {
|
|
560
|
-
contentParts.push({ type: "thinking", text: block.thinking, signature: block.signature });
|
|
561
|
-
} else if (block.type === "tool_use") {
|
|
562
|
-
const tc = {
|
|
563
|
-
type: "tool_call",
|
|
564
|
-
id: block.id,
|
|
565
|
-
name: block.name,
|
|
566
|
-
args: block.input
|
|
567
|
-
};
|
|
568
|
-
contentParts.push(tc);
|
|
569
|
-
result.push({
|
|
570
|
-
type: "toolcall_done",
|
|
571
|
-
id: tc.id,
|
|
572
|
-
name: tc.name,
|
|
573
|
-
args: tc.args
|
|
574
|
-
});
|
|
575
|
-
} else if (block.type === "server_tool_use") {
|
|
576
|
-
const stc = {
|
|
577
|
-
type: "server_tool_call",
|
|
578
|
-
id: block.id,
|
|
579
|
-
name: block.name,
|
|
580
|
-
input: block.input
|
|
581
|
-
};
|
|
582
|
-
contentParts.push(stc);
|
|
583
|
-
result.push({
|
|
584
|
-
type: "server_toolcall",
|
|
585
|
-
id: stc.id,
|
|
586
|
-
name: stc.name,
|
|
587
|
-
input: stc.input
|
|
588
|
-
});
|
|
589
|
-
} else {
|
|
590
|
-
const raw = block;
|
|
591
|
-
const blockType = raw.type;
|
|
592
|
-
if (blockType === "web_search_tool_result") {
|
|
593
|
-
const str = {
|
|
594
|
-
type: "server_tool_result",
|
|
595
|
-
toolUseId: raw.tool_use_id,
|
|
596
|
-
resultType: blockType,
|
|
597
|
-
data: raw
|
|
598
|
-
};
|
|
599
|
-
contentParts.push(str);
|
|
600
|
-
result.push({
|
|
601
|
-
type: "server_toolresult",
|
|
602
|
-
toolUseId: str.toolUseId,
|
|
603
|
-
resultType: str.resultType,
|
|
604
|
-
data: str.data
|
|
605
|
-
});
|
|
606
|
-
} else {
|
|
607
|
-
contentParts.push({ type: "raw", data: raw });
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
});
|
|
559
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
560
|
+
let inputTokens = 0;
|
|
561
|
+
let outputTokens = 0;
|
|
562
|
+
let cacheRead;
|
|
563
|
+
let cacheWrite;
|
|
564
|
+
let stopReason = null;
|
|
565
|
+
const keepalive = { type: "keepalive" };
|
|
611
566
|
try {
|
|
612
|
-
const
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
567
|
+
for await (const event of stream2) {
|
|
568
|
+
switch (event.type) {
|
|
569
|
+
case "message_start": {
|
|
570
|
+
const usage = event.message.usage;
|
|
571
|
+
inputTokens = usage.input_tokens;
|
|
572
|
+
const usageAny = usage;
|
|
573
|
+
if (usageAny.cache_read_input_tokens != null) {
|
|
574
|
+
cacheRead = usageAny.cache_read_input_tokens;
|
|
575
|
+
}
|
|
576
|
+
if (usageAny.cache_creation_input_tokens != null) {
|
|
577
|
+
cacheWrite = usageAny.cache_creation_input_tokens;
|
|
578
|
+
}
|
|
579
|
+
yield keepalive;
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
582
|
+
case "content_block_start": {
|
|
583
|
+
const block = event.content_block;
|
|
584
|
+
const idx = event.index;
|
|
585
|
+
const accum = {
|
|
586
|
+
type: block.type,
|
|
587
|
+
text: "",
|
|
588
|
+
thinking: "",
|
|
589
|
+
signature: "",
|
|
590
|
+
toolId: "",
|
|
591
|
+
toolName: "",
|
|
592
|
+
argsJson: "",
|
|
593
|
+
input: void 0,
|
|
594
|
+
raw: null
|
|
595
|
+
};
|
|
596
|
+
if (block.type === "tool_use") {
|
|
597
|
+
accum.toolId = block.id;
|
|
598
|
+
accum.toolName = block.name;
|
|
599
|
+
} else if (block.type === "server_tool_use") {
|
|
600
|
+
accum.toolId = block.id;
|
|
601
|
+
accum.toolName = block.name;
|
|
602
|
+
accum.input = block.input;
|
|
603
|
+
} else if (block.type === "redacted_thinking") {
|
|
604
|
+
accum.raw = block;
|
|
605
|
+
}
|
|
606
|
+
blocks.set(idx, accum);
|
|
607
|
+
yield keepalive;
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
610
|
+
case "content_block_delta": {
|
|
611
|
+
const accum = blocks.get(event.index);
|
|
612
|
+
if (!accum) break;
|
|
613
|
+
const delta = event.delta;
|
|
614
|
+
const deltaType = delta.type;
|
|
615
|
+
if (deltaType === "text_delta") {
|
|
616
|
+
const text = delta.text;
|
|
617
|
+
accum.text += text;
|
|
618
|
+
yield { type: "text_delta", text };
|
|
619
|
+
} else if (deltaType === "thinking_delta") {
|
|
620
|
+
const text = delta.thinking;
|
|
621
|
+
accum.thinking += text;
|
|
622
|
+
yield { type: "thinking_delta", text };
|
|
623
|
+
} else if (deltaType === "input_json_delta") {
|
|
624
|
+
const partialJson = delta.partial_json;
|
|
625
|
+
accum.argsJson += partialJson;
|
|
626
|
+
yield {
|
|
627
|
+
type: "toolcall_delta",
|
|
628
|
+
id: accum.toolId,
|
|
629
|
+
name: accum.toolName,
|
|
630
|
+
argsJson: partialJson
|
|
631
|
+
};
|
|
632
|
+
} else if (deltaType === "signature_delta") {
|
|
633
|
+
accum.signature = delta.signature;
|
|
634
|
+
}
|
|
635
|
+
break;
|
|
636
|
+
}
|
|
637
|
+
case "content_block_stop": {
|
|
638
|
+
const accum = blocks.get(event.index);
|
|
639
|
+
if (!accum) break;
|
|
640
|
+
if (accum.type === "text") {
|
|
641
|
+
contentParts.push({ type: "text", text: accum.text });
|
|
642
|
+
} else if (accum.type === "thinking") {
|
|
643
|
+
contentParts.push({
|
|
644
|
+
type: "thinking",
|
|
645
|
+
text: accum.thinking,
|
|
646
|
+
signature: accum.signature
|
|
647
|
+
});
|
|
648
|
+
yield keepalive;
|
|
649
|
+
} else if (accum.type === "tool_use") {
|
|
650
|
+
let args = {};
|
|
651
|
+
try {
|
|
652
|
+
args = JSON.parse(accum.argsJson);
|
|
653
|
+
} catch {
|
|
654
|
+
}
|
|
655
|
+
const tc = {
|
|
656
|
+
type: "tool_call",
|
|
657
|
+
id: accum.toolId,
|
|
658
|
+
name: accum.toolName,
|
|
659
|
+
args
|
|
660
|
+
};
|
|
661
|
+
contentParts.push(tc);
|
|
662
|
+
yield {
|
|
663
|
+
type: "toolcall_done",
|
|
664
|
+
id: tc.id,
|
|
665
|
+
name: tc.name,
|
|
666
|
+
args: tc.args
|
|
667
|
+
};
|
|
668
|
+
} else if (accum.type === "server_tool_use") {
|
|
669
|
+
const stc = {
|
|
670
|
+
type: "server_tool_call",
|
|
671
|
+
id: accum.toolId,
|
|
672
|
+
name: accum.toolName,
|
|
673
|
+
input: accum.input
|
|
674
|
+
};
|
|
675
|
+
contentParts.push(stc);
|
|
676
|
+
yield {
|
|
677
|
+
type: "server_toolcall",
|
|
678
|
+
id: stc.id,
|
|
679
|
+
name: stc.name,
|
|
680
|
+
input: stc.input
|
|
681
|
+
};
|
|
682
|
+
} else if (accum.type === "redacted_thinking" && accum.raw) {
|
|
683
|
+
contentParts.push({ type: "raw", data: accum.raw });
|
|
684
|
+
yield keepalive;
|
|
685
|
+
} else {
|
|
686
|
+
const msg = stream2.currentMessage;
|
|
687
|
+
const rawBlock = msg?.content[event.index];
|
|
688
|
+
if (rawBlock) {
|
|
689
|
+
const blockType = rawBlock.type;
|
|
690
|
+
if (blockType === "web_search_tool_result") {
|
|
691
|
+
const str = {
|
|
692
|
+
type: "server_tool_result",
|
|
693
|
+
toolUseId: rawBlock.tool_use_id,
|
|
694
|
+
resultType: blockType,
|
|
695
|
+
data: rawBlock
|
|
696
|
+
};
|
|
697
|
+
contentParts.push(str);
|
|
698
|
+
yield {
|
|
699
|
+
type: "server_toolresult",
|
|
700
|
+
toolUseId: str.toolUseId,
|
|
701
|
+
resultType: str.resultType,
|
|
702
|
+
data: str.data
|
|
703
|
+
};
|
|
704
|
+
} else {
|
|
705
|
+
contentParts.push({ type: "raw", data: rawBlock });
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
blocks.delete(event.index);
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
712
|
+
case "message_delta": {
|
|
713
|
+
const delta = event.delta;
|
|
714
|
+
if (delta.stop_reason) {
|
|
715
|
+
stopReason = delta.stop_reason;
|
|
716
|
+
}
|
|
717
|
+
const usage = event.usage;
|
|
718
|
+
if (usage?.output_tokens != null) {
|
|
719
|
+
outputTokens = usage.output_tokens;
|
|
720
|
+
}
|
|
721
|
+
yield keepalive;
|
|
722
|
+
break;
|
|
628
723
|
}
|
|
724
|
+
// message_stop — loop exits naturally
|
|
725
|
+
default:
|
|
726
|
+
yield keepalive;
|
|
727
|
+
break;
|
|
629
728
|
}
|
|
630
|
-
}
|
|
631
|
-
result.push({ type: "done", stopReason });
|
|
632
|
-
result.complete(response);
|
|
729
|
+
}
|
|
633
730
|
} catch (err) {
|
|
634
|
-
|
|
635
|
-
result.push({ type: "error", error });
|
|
636
|
-
result.abort(error);
|
|
731
|
+
throw toError(err);
|
|
637
732
|
}
|
|
733
|
+
const normalizedStop = normalizeAnthropicStopReason(stopReason);
|
|
734
|
+
const response = {
|
|
735
|
+
message: {
|
|
736
|
+
role: "assistant",
|
|
737
|
+
content: contentParts.length > 0 ? contentParts : ""
|
|
738
|
+
},
|
|
739
|
+
stopReason: normalizedStop,
|
|
740
|
+
usage: {
|
|
741
|
+
inputTokens,
|
|
742
|
+
outputTokens,
|
|
743
|
+
...cacheRead != null && { cacheRead },
|
|
744
|
+
...cacheWrite != null && { cacheWrite }
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
yield { type: "done", stopReason: normalizedStop };
|
|
748
|
+
return response;
|
|
638
749
|
}
|
|
639
750
|
function toError(err) {
|
|
640
751
|
if (err instanceof import_sdk.default.APIError) {
|
|
@@ -651,19 +762,20 @@ function toError(err) {
|
|
|
651
762
|
|
|
652
763
|
// src/providers/openai.ts
|
|
653
764
|
var import_openai = __toESM(require("openai"), 1);
|
|
654
|
-
function
|
|
655
|
-
|
|
656
|
-
const providerName = options.provider ?? "openai";
|
|
657
|
-
runStream2(options, result).catch((err) => result.abort(toError2(err, providerName)));
|
|
658
|
-
return result;
|
|
659
|
-
}
|
|
660
|
-
async function runStream2(options, result) {
|
|
661
|
-
const client = new import_openai.default({
|
|
765
|
+
function createClient2(options) {
|
|
766
|
+
return new import_openai.default({
|
|
662
767
|
apiKey: options.apiKey,
|
|
663
768
|
...options.baseUrl ? { baseURL: options.baseUrl } : {},
|
|
664
769
|
...options.fetch ? { fetch: options.fetch } : {}
|
|
665
770
|
});
|
|
666
|
-
|
|
771
|
+
}
|
|
772
|
+
function streamOpenAI(options) {
|
|
773
|
+
return new StreamResult(runStream2(options));
|
|
774
|
+
}
|
|
775
|
+
async function* runStream2(options) {
|
|
776
|
+
const providerName = options.provider ?? "openai";
|
|
777
|
+
const client = createClient2(options);
|
|
778
|
+
const usesThinkingParam = options.provider === "glm" || options.provider === "moonshot" || options.provider === "xiaomi";
|
|
667
779
|
const messages = toOpenAIMessages(options.messages, { provider: options.provider });
|
|
668
780
|
const defaultTemp = options.provider === "glm" ? 0.6 : void 0;
|
|
669
781
|
const effectiveTemp = options.temperature ?? defaultTemp;
|
|
@@ -671,7 +783,7 @@ async function runStream2(options, result) {
|
|
|
671
783
|
model: options.model,
|
|
672
784
|
messages,
|
|
673
785
|
stream: true,
|
|
674
|
-
...options.maxTokens ? {
|
|
786
|
+
...options.maxTokens ? { max_completion_tokens: options.maxTokens } : {},
|
|
675
787
|
...effectiveTemp != null && !options.thinking ? { temperature: effectiveTemp } : {},
|
|
676
788
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
677
789
|
...options.stop ? { stop: options.stop } : {},
|
|
@@ -689,11 +801,31 @@ async function runStream2(options, result) {
|
|
|
689
801
|
}
|
|
690
802
|
}
|
|
691
803
|
if (usesThinkingParam) {
|
|
692
|
-
|
|
804
|
+
if (options.thinking) {
|
|
805
|
+
params.thinking = { type: "enabled" };
|
|
806
|
+
} else {
|
|
807
|
+
params.thinking = { type: "disabled" };
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
if (globalThis.process && globalThis.process.env?.GGAI_DUMP_REQUEST) {
|
|
811
|
+
const fs = await import("fs");
|
|
812
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
813
|
+
const dumpPath = `/tmp/ggai-request-${ts}.json`;
|
|
814
|
+
fs.writeFileSync(dumpPath, JSON.stringify(params, null, 2));
|
|
815
|
+
fs.appendFileSync(
|
|
816
|
+
"/tmp/ggai-requests.log",
|
|
817
|
+
`[${ts}] ${dumpPath} messages=${params.messages.length}
|
|
818
|
+
`
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
let stream2;
|
|
822
|
+
try {
|
|
823
|
+
stream2 = await client.chat.completions.create(params, {
|
|
824
|
+
signal: options.signal ?? void 0
|
|
825
|
+
});
|
|
826
|
+
} catch (err) {
|
|
827
|
+
throw toError2(err, providerName);
|
|
693
828
|
}
|
|
694
|
-
const stream2 = await client.chat.completions.create(params, {
|
|
695
|
-
signal: options.signal ?? void 0
|
|
696
|
-
});
|
|
697
829
|
const contentParts = [];
|
|
698
830
|
const toolCallAccum = /* @__PURE__ */ new Map();
|
|
699
831
|
let textAccum = "";
|
|
@@ -720,11 +852,13 @@ async function runStream2(options, result) {
|
|
|
720
852
|
const reasoningContent = delta.reasoning_content;
|
|
721
853
|
if (typeof reasoningContent === "string" && reasoningContent) {
|
|
722
854
|
thinkingAccum += reasoningContent;
|
|
723
|
-
|
|
855
|
+
if (options.thinking) {
|
|
856
|
+
yield { type: "thinking_delta", text: reasoningContent };
|
|
857
|
+
}
|
|
724
858
|
}
|
|
725
859
|
if (delta.content) {
|
|
726
860
|
textAccum += delta.content;
|
|
727
|
-
|
|
861
|
+
yield { type: "text_delta", text: delta.content };
|
|
728
862
|
}
|
|
729
863
|
if (delta.tool_calls) {
|
|
730
864
|
for (const tc of delta.tool_calls) {
|
|
@@ -741,12 +875,12 @@ async function runStream2(options, result) {
|
|
|
741
875
|
if (tc.function?.name) accum.name = tc.function.name;
|
|
742
876
|
if (tc.function?.arguments) {
|
|
743
877
|
accum.argsJson += tc.function.arguments;
|
|
744
|
-
|
|
878
|
+
yield {
|
|
745
879
|
type: "toolcall_delta",
|
|
746
880
|
id: accum.id,
|
|
747
881
|
name: accum.name,
|
|
748
882
|
argsJson: tc.function.arguments
|
|
749
|
-
}
|
|
883
|
+
};
|
|
750
884
|
}
|
|
751
885
|
}
|
|
752
886
|
}
|
|
@@ -770,12 +904,12 @@ async function runStream2(options, result) {
|
|
|
770
904
|
args
|
|
771
905
|
};
|
|
772
906
|
contentParts.push(toolCall);
|
|
773
|
-
|
|
907
|
+
yield {
|
|
774
908
|
type: "toolcall_done",
|
|
775
909
|
id: tc.id,
|
|
776
910
|
name: tc.name,
|
|
777
911
|
args
|
|
778
|
-
}
|
|
912
|
+
};
|
|
779
913
|
}
|
|
780
914
|
const stopReason = normalizeOpenAIStopReason(finishReason);
|
|
781
915
|
const response = {
|
|
@@ -786,14 +920,20 @@ async function runStream2(options, result) {
|
|
|
786
920
|
stopReason,
|
|
787
921
|
usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
|
|
788
922
|
};
|
|
789
|
-
|
|
790
|
-
|
|
923
|
+
yield { type: "done", stopReason };
|
|
924
|
+
return response;
|
|
791
925
|
}
|
|
792
926
|
function toError2(err, provider = "openai") {
|
|
793
927
|
if (err instanceof import_openai.default.APIError) {
|
|
794
928
|
let msg = err.message;
|
|
795
929
|
const body = err.error;
|
|
796
930
|
if (body) {
|
|
931
|
+
const modelName = body.model || "";
|
|
932
|
+
const _code = body.code || "";
|
|
933
|
+
const message = body.message || "";
|
|
934
|
+
if (modelName === "codex-mini-latest" || message.includes("codex-mini-latest")) {
|
|
935
|
+
msg = `codex-mini-latest requires an OpenAI Pro or Max subscription. You currently have access to GPT-5.4 and GPT-5.4 Mini with your account.`;
|
|
936
|
+
}
|
|
797
937
|
msg += ` | body: ${JSON.stringify(body)}`;
|
|
798
938
|
}
|
|
799
939
|
return new ProviderError(provider, msg, {
|
|
@@ -811,11 +951,9 @@ function toError2(err, provider = "openai") {
|
|
|
811
951
|
var import_node_os = __toESM(require("os"), 1);
|
|
812
952
|
var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
|
|
813
953
|
function streamOpenAICodex(options) {
|
|
814
|
-
|
|
815
|
-
runStream3(options, result).catch((err) => result.abort(toError3(err)));
|
|
816
|
-
return result;
|
|
954
|
+
return new StreamResult(runStream3(options));
|
|
817
955
|
}
|
|
818
|
-
async function runStream3(options
|
|
956
|
+
async function* runStream3(options) {
|
|
819
957
|
const baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
820
958
|
const url = `${baseUrl}/codex/responses`;
|
|
821
959
|
const { system, input } = toCodexInput(options.messages);
|
|
@@ -865,6 +1003,11 @@ async function runStream3(options, result) {
|
|
|
865
1003
|
message += `
|
|
866
1004
|
|
|
867
1005
|
Hint: Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription. The "codex-spark" variants require ChatGPT Pro. Ensure your account has an active subscription at https://chatgpt.com/settings`;
|
|
1006
|
+
}
|
|
1007
|
+
if (response.status === 404 && text.includes("does not exist")) {
|
|
1008
|
+
message += `
|
|
1009
|
+
|
|
1010
|
+
Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GPT-5.4 and GPT-5.4 Mini work with any active ChatGPT plan.`;
|
|
868
1011
|
}
|
|
869
1012
|
throw new ProviderError("openai", message, {
|
|
870
1013
|
statusCode: response.status
|
|
@@ -892,11 +1035,11 @@ Hint: Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription
|
|
|
892
1035
|
if (type === "response.output_text.delta") {
|
|
893
1036
|
const delta = event.delta;
|
|
894
1037
|
textAccum += delta;
|
|
895
|
-
|
|
1038
|
+
yield { type: "text_delta", text: delta };
|
|
896
1039
|
}
|
|
897
1040
|
if (type === "response.reasoning_summary_text.delta") {
|
|
898
1041
|
const delta = event.delta;
|
|
899
|
-
|
|
1042
|
+
yield { type: "thinking_delta", text: delta };
|
|
900
1043
|
}
|
|
901
1044
|
if (type === "response.output_item.added") {
|
|
902
1045
|
const item = event.item;
|
|
@@ -914,12 +1057,12 @@ Hint: Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription
|
|
|
914
1057
|
for (const [key, tc] of toolCalls) {
|
|
915
1058
|
if (key.endsWith(`|${itemId}`)) {
|
|
916
1059
|
tc.argsJson += delta;
|
|
917
|
-
|
|
1060
|
+
yield {
|
|
918
1061
|
type: "toolcall_delta",
|
|
919
1062
|
id: tc.id,
|
|
920
1063
|
name: tc.name,
|
|
921
1064
|
argsJson: delta
|
|
922
|
-
}
|
|
1065
|
+
};
|
|
923
1066
|
break;
|
|
924
1067
|
}
|
|
925
1068
|
}
|
|
@@ -947,12 +1090,12 @@ Hint: Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription
|
|
|
947
1090
|
args = JSON.parse(tc.argsJson);
|
|
948
1091
|
} catch {
|
|
949
1092
|
}
|
|
950
|
-
|
|
1093
|
+
yield {
|
|
951
1094
|
type: "toolcall_done",
|
|
952
1095
|
id: tc.id,
|
|
953
1096
|
name: tc.name,
|
|
954
1097
|
args
|
|
955
|
-
}
|
|
1098
|
+
};
|
|
956
1099
|
}
|
|
957
1100
|
}
|
|
958
1101
|
}
|
|
@@ -992,8 +1135,8 @@ Hint: Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription
|
|
|
992
1135
|
stopReason,
|
|
993
1136
|
usage: { inputTokens, outputTokens }
|
|
994
1137
|
};
|
|
995
|
-
|
|
996
|
-
|
|
1138
|
+
yield { type: "done", stopReason };
|
|
1139
|
+
return streamResponse;
|
|
997
1140
|
}
|
|
998
1141
|
async function* parseSSE(body) {
|
|
999
1142
|
const reader = body.getReader();
|
|
@@ -1107,13 +1250,6 @@ function toCodexTools(tools) {
|
|
|
1107
1250
|
strict: null
|
|
1108
1251
|
}));
|
|
1109
1252
|
}
|
|
1110
|
-
function toError3(err) {
|
|
1111
|
-
if (err instanceof ProviderError) return err;
|
|
1112
|
-
if (err instanceof Error) {
|
|
1113
|
-
return new ProviderError("openai", err.message, { cause: err });
|
|
1114
|
-
}
|
|
1115
|
-
return new ProviderError("openai", String(err));
|
|
1116
|
-
}
|
|
1117
1253
|
|
|
1118
1254
|
// src/provider-registry.ts
|
|
1119
1255
|
var ProviderRegistryImpl = class {
|
|
@@ -1153,10 +1289,16 @@ var providerRegistry = new ProviderRegistryImpl();
|
|
|
1153
1289
|
|
|
1154
1290
|
// src/stream.ts
|
|
1155
1291
|
var GLM_CODING_BASE_URL = "https://api.z.ai/api/coding/paas/v4";
|
|
1156
|
-
var GLM_REGULAR_BASE_URL = "https://api.z.ai/api/paas/v4";
|
|
1157
1292
|
providerRegistry.register("anthropic", {
|
|
1158
1293
|
stream: (options) => streamAnthropic(options)
|
|
1159
1294
|
});
|
|
1295
|
+
providerRegistry.register("xiaomi", {
|
|
1296
|
+
stream: (options) => streamOpenAI({
|
|
1297
|
+
...options,
|
|
1298
|
+
baseUrl: options.baseUrl ?? "https://token-plan-sgp.xiaomimimo.com/v1",
|
|
1299
|
+
webSearch: false
|
|
1300
|
+
})
|
|
1301
|
+
});
|
|
1160
1302
|
providerRegistry.register("openai", {
|
|
1161
1303
|
stream: (options) => {
|
|
1162
1304
|
if (options.accountId) {
|
|
@@ -1166,10 +1308,10 @@ providerRegistry.register("openai", {
|
|
|
1166
1308
|
}
|
|
1167
1309
|
});
|
|
1168
1310
|
providerRegistry.register("glm", {
|
|
1169
|
-
stream: (options) => {
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
}
|
|
1311
|
+
stream: (options) => streamOpenAI({
|
|
1312
|
+
...options,
|
|
1313
|
+
baseUrl: options.baseUrl ?? GLM_CODING_BASE_URL
|
|
1314
|
+
})
|
|
1173
1315
|
});
|
|
1174
1316
|
providerRegistry.register("moonshot", {
|
|
1175
1317
|
stream: (options) => streamOpenAI({
|
|
@@ -1177,6 +1319,18 @@ providerRegistry.register("moonshot", {
|
|
|
1177
1319
|
baseUrl: options.baseUrl ?? "https://api.moonshot.ai/v1"
|
|
1178
1320
|
})
|
|
1179
1321
|
});
|
|
1322
|
+
providerRegistry.register("minimax", {
|
|
1323
|
+
stream: (options) => streamAnthropic({
|
|
1324
|
+
...options,
|
|
1325
|
+
baseUrl: options.baseUrl ?? "https://api.minimax.io/anthropic",
|
|
1326
|
+
// MiniMax's Anthropic-compatible API does not support Anthropic-specific
|
|
1327
|
+
// server tools (web_search), context_management, or server-side tools.
|
|
1328
|
+
webSearch: false,
|
|
1329
|
+
compaction: false,
|
|
1330
|
+
clearToolUses: false,
|
|
1331
|
+
serverTools: void 0
|
|
1332
|
+
})
|
|
1333
|
+
});
|
|
1180
1334
|
function stream(options) {
|
|
1181
1335
|
const entry = providerRegistry.get(options.provider);
|
|
1182
1336
|
if (!entry) {
|
|
@@ -1186,32 +1340,6 @@ function stream(options) {
|
|
|
1186
1340
|
}
|
|
1187
1341
|
return entry.stream(options);
|
|
1188
1342
|
}
|
|
1189
|
-
function streamGLMWithFallback(options) {
|
|
1190
|
-
const result = new StreamResult();
|
|
1191
|
-
runGLMWithFallback(options, result).catch((err) => {
|
|
1192
|
-
result.abort(err instanceof Error ? err : new Error(String(err)));
|
|
1193
|
-
});
|
|
1194
|
-
return result;
|
|
1195
|
-
}
|
|
1196
|
-
async function runGLMWithFallback(options, result) {
|
|
1197
|
-
const codingResult = streamOpenAI({ ...options, baseUrl: GLM_CODING_BASE_URL });
|
|
1198
|
-
try {
|
|
1199
|
-
for await (const event of codingResult) {
|
|
1200
|
-
result.push(event);
|
|
1201
|
-
}
|
|
1202
|
-
result.complete(await codingResult.response);
|
|
1203
|
-
} catch {
|
|
1204
|
-
const regularResult = streamOpenAI({ ...options, baseUrl: GLM_REGULAR_BASE_URL });
|
|
1205
|
-
try {
|
|
1206
|
-
for await (const event of regularResult) {
|
|
1207
|
-
result.push(event);
|
|
1208
|
-
}
|
|
1209
|
-
result.complete(await regularResult.response);
|
|
1210
|
-
} catch (fallbackErr) {
|
|
1211
|
-
result.abort(fallbackErr instanceof Error ? fallbackErr : new Error(String(fallbackErr)));
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
1343
|
|
|
1216
1344
|
// src/providers/palsu.ts
|
|
1217
1345
|
function palsuText(text) {
|
|
@@ -1239,31 +1367,29 @@ function chunkText(text, size) {
|
|
|
1239
1367
|
}
|
|
1240
1368
|
return chunks.length > 0 ? chunks : [""];
|
|
1241
1369
|
}
|
|
1242
|
-
function simulateStream(message, stopReason,
|
|
1370
|
+
async function* simulateStream(message, stopReason, signal, cacheUsage) {
|
|
1243
1371
|
if (signal?.aborted) {
|
|
1244
|
-
|
|
1245
|
-
return;
|
|
1372
|
+
throw new Error("aborted");
|
|
1246
1373
|
}
|
|
1247
1374
|
const content = typeof message.content === "string" ? message.content ? [{ type: "text", text: message.content }] : [] : message.content;
|
|
1248
1375
|
let outputChars = 0;
|
|
1249
1376
|
for (const part of content) {
|
|
1250
1377
|
if (signal?.aborted) {
|
|
1251
|
-
|
|
1252
|
-
return;
|
|
1378
|
+
throw new Error("aborted");
|
|
1253
1379
|
}
|
|
1254
1380
|
if (part.type === "text") {
|
|
1255
1381
|
const chunks = chunkText(part.text, DEFAULT_CHUNK_SIZE);
|
|
1256
1382
|
for (const chunk of chunks) {
|
|
1257
|
-
|
|
1383
|
+
yield { type: "text_delta", text: chunk };
|
|
1258
1384
|
outputChars += chunk.length;
|
|
1259
1385
|
}
|
|
1260
1386
|
} else if (part.type === "thinking") {
|
|
1261
|
-
|
|
1387
|
+
yield { type: "thinking_delta", text: part.text };
|
|
1262
1388
|
outputChars += part.text.length;
|
|
1263
1389
|
} else if (part.type === "tool_call") {
|
|
1264
1390
|
const argsJson = JSON.stringify(part.args);
|
|
1265
|
-
|
|
1266
|
-
|
|
1391
|
+
yield { type: "toolcall_delta", id: part.id, name: part.name, argsJson };
|
|
1392
|
+
yield { type: "toolcall_done", id: part.id, name: part.name, args: part.args };
|
|
1267
1393
|
outputChars += argsJson.length;
|
|
1268
1394
|
}
|
|
1269
1395
|
}
|
|
@@ -1274,8 +1400,8 @@ function simulateStream(message, stopReason, result, signal, cacheUsage) {
|
|
|
1274
1400
|
...cacheUsage?.cacheRead ? { cacheRead: cacheUsage.cacheRead } : {},
|
|
1275
1401
|
...cacheUsage?.cacheWrite ? { cacheWrite: cacheUsage.cacheWrite } : {}
|
|
1276
1402
|
};
|
|
1277
|
-
|
|
1278
|
-
|
|
1403
|
+
yield { type: "done", stopReason };
|
|
1404
|
+
return { message, stopReason, usage };
|
|
1279
1405
|
}
|
|
1280
1406
|
function computeCacheUsage(current, previous) {
|
|
1281
1407
|
if (!previous) {
|
|
@@ -1347,24 +1473,21 @@ function registerPalsuProvider(config) {
|
|
|
1347
1473
|
state.callCount++;
|
|
1348
1474
|
const ms = modelStates.get(options.model);
|
|
1349
1475
|
const responseDef = (ms && ms.responses.length > 0 ? ms.responses.shift() : void 0) ?? (responses.length > 0 ? responses.shift() : void 0) ?? ms?.defaultResponse ?? defaultResponse;
|
|
1350
|
-
const result = new StreamResult();
|
|
1351
1476
|
let cacheUsage;
|
|
1352
1477
|
if (enableCache) {
|
|
1353
1478
|
const serialized = JSON.stringify(options.messages);
|
|
1354
1479
|
cacheUsage = computeCacheUsage(serialized, lastMessagesSerialized);
|
|
1355
1480
|
lastMessagesSerialized = serialized;
|
|
1356
1481
|
}
|
|
1357
|
-
const
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
);
|
|
1367
|
-
return result;
|
|
1482
|
+
const gen = (async function* () {
|
|
1483
|
+
const rawMessage = typeof responseDef === "function" ? responseDef(options.messages, options, state) : responseDef;
|
|
1484
|
+
const message = await Promise.resolve(rawMessage);
|
|
1485
|
+
const hasToolCalls = Array.isArray(message.content) && message.content.some((p) => p.type === "tool_call");
|
|
1486
|
+
const explicitStop = message._stopReason;
|
|
1487
|
+
const stopReason = explicitStop ?? (hasToolCalls ? "tool_use" : "end_turn");
|
|
1488
|
+
return yield* simulateStream(message, stopReason, options.signal, cacheUsage);
|
|
1489
|
+
})();
|
|
1490
|
+
return new StreamResult(gen);
|
|
1368
1491
|
}
|
|
1369
1492
|
});
|
|
1370
1493
|
return handle;
|