@hiper2d/ai-agents 0.5.0 → 0.5.2
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.d.mts +29 -8
- package/dist/index.d.ts +29 -8
- package/dist/index.js +67 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +66 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -714,9 +714,11 @@ var ModelInvalidResponseError = class extends ModelError {
|
|
|
714
714
|
}
|
|
715
715
|
};
|
|
716
716
|
var ModelRefusalError = class extends ModelError {
|
|
717
|
-
|
|
717
|
+
reason;
|
|
718
|
+
constructor(modelType, message = `${modelType} refused to answer (stop_reason: refusal)`, reason) {
|
|
718
719
|
super(message, modelType);
|
|
719
720
|
this.name = "ModelRefusalError";
|
|
721
|
+
this.reason = reason;
|
|
720
722
|
}
|
|
721
723
|
};
|
|
722
724
|
|
|
@@ -1830,6 +1832,21 @@ function pcmToWav(pcmData, sampleRate = SAMPLE_RATE) {
|
|
|
1830
1832
|
new Uint8Array(buffer, headerSize).set(pcmData);
|
|
1831
1833
|
return buffer;
|
|
1832
1834
|
}
|
|
1835
|
+
function describeEmptyTtsResponse(response) {
|
|
1836
|
+
const candidate = response?.candidates?.[0];
|
|
1837
|
+
const parts = candidate?.content?.parts ?? [];
|
|
1838
|
+
const bits = [];
|
|
1839
|
+
bits.push(`finishReason=${candidate?.finishReason ?? "none"}`);
|
|
1840
|
+
if (!response?.candidates?.length) bits.push("no candidates");
|
|
1841
|
+
const block = response?.promptFeedback?.blockReason;
|
|
1842
|
+
if (block) bits.push(`blockReason=${block}`);
|
|
1843
|
+
const text = parts.map((p) => typeof p?.text === "string" ? p.text : "").join(" ").trim();
|
|
1844
|
+
if (text) bits.push(`text="${text.slice(0, 120)}"`);
|
|
1845
|
+
const otherMimes = parts.map((p) => p?.inlineData?.mimeType).filter(Boolean);
|
|
1846
|
+
if (otherMimes.length) bits.push(`inlineData=${otherMimes.join(",")}`);
|
|
1847
|
+
if (!parts.length) bits.push("no parts");
|
|
1848
|
+
return bits.join(", ");
|
|
1849
|
+
}
|
|
1833
1850
|
async function generateGoogleTtsAudio(text, apiKey, options) {
|
|
1834
1851
|
const client = new GoogleGenAI({ apiKey });
|
|
1835
1852
|
const response = await client.models.generateContent({
|
|
@@ -1840,10 +1857,11 @@ async function generateGoogleTtsAudio(text, apiKey, options) {
|
|
|
1840
1857
|
speechConfig: { voiceConfig: { prebuiltVoiceConfig: { voiceName: options.voiceName } } }
|
|
1841
1858
|
}
|
|
1842
1859
|
});
|
|
1843
|
-
const
|
|
1860
|
+
const candidate = response.candidates?.[0];
|
|
1861
|
+
const parts = candidate?.content?.parts ?? [];
|
|
1844
1862
|
const audioPart = parts.find((part) => part.inlineData?.mimeType?.startsWith("audio/"));
|
|
1845
1863
|
if (!audioPart?.inlineData?.data) {
|
|
1846
|
-
throw new Error(
|
|
1864
|
+
throw new Error(`No audio data in Google TTS response (${describeEmptyTtsResponse(response)})`);
|
|
1847
1865
|
}
|
|
1848
1866
|
const pcmData = new Uint8Array(Buffer.from(audioPart.inlineData.data, "base64"));
|
|
1849
1867
|
const usageMetadata = response.usageMetadata ?? {};
|
|
@@ -2638,7 +2656,7 @@ ${schemaDescription}`;
|
|
|
2638
2656
|
throw new Error(this.errorMessages.apiError(apiError));
|
|
2639
2657
|
}
|
|
2640
2658
|
if (response.stop_reason === "refusal") {
|
|
2641
|
-
throw new ModelRefusalError(this.model);
|
|
2659
|
+
throw new ModelRefusalError(this.model, void 0, "refusal");
|
|
2642
2660
|
}
|
|
2643
2661
|
if (!("content" in response) || !Array.isArray(response.content) || response.content.length === 0) {
|
|
2644
2662
|
throw new Error(this.errorMessages.emptyResponse);
|
|
@@ -2732,7 +2750,7 @@ ${schemaDescription}`;
|
|
|
2732
2750
|
throw new Error(this.errorMessages.apiError(apiError));
|
|
2733
2751
|
}
|
|
2734
2752
|
if (response.stop_reason === "refusal") {
|
|
2735
|
-
throw new ModelRefusalError(this.model);
|
|
2753
|
+
throw new ModelRefusalError(this.model, void 0, "refusal");
|
|
2736
2754
|
}
|
|
2737
2755
|
if (!("content" in response) || !Array.isArray(response.content) || response.content.length === 0) {
|
|
2738
2756
|
throw new Error(this.errorMessages.emptyResponse);
|
|
@@ -2788,6 +2806,45 @@ ${schemaDescription}`;
|
|
|
2788
2806
|
|
|
2789
2807
|
// src/agents/google-agent.ts
|
|
2790
2808
|
import { GoogleGenAI as GoogleGenAI3 } from "@google/genai";
|
|
2809
|
+
var GEMINI_REFUSAL_FINISH_REASONS = /* @__PURE__ */ new Set([
|
|
2810
|
+
"SAFETY",
|
|
2811
|
+
"RECITATION",
|
|
2812
|
+
"BLOCKLIST",
|
|
2813
|
+
"PROHIBITED_CONTENT",
|
|
2814
|
+
"SPII",
|
|
2815
|
+
"IMAGE_SAFETY",
|
|
2816
|
+
"IMAGE_PROHIBITED_CONTENT",
|
|
2817
|
+
"IMAGE_RECITATION"
|
|
2818
|
+
]);
|
|
2819
|
+
function throwForEmptyGeminiResponse(model, response, fallback) {
|
|
2820
|
+
const blockReason = response?.promptFeedback?.blockReason;
|
|
2821
|
+
const candidate = response?.candidates?.[0];
|
|
2822
|
+
const finishReason = candidate?.finishReason;
|
|
2823
|
+
const finishMessage = candidate?.finishMessage;
|
|
2824
|
+
const ratings = (candidate?.safetyRatings ?? response?.promptFeedback?.safetyRatings ?? []).filter((r) => r?.blocked || r?.probability && r.probability !== "NEGLIGIBLE");
|
|
2825
|
+
const ratingText = ratings.length ? `; safetyRatings: ${ratings.map((r) => `${r.category}=${r.probability ?? (r.blocked ? "blocked" : "?")}`).join(", ")}` : "";
|
|
2826
|
+
if (blockReason) {
|
|
2827
|
+
throw new ModelRefusalError(
|
|
2828
|
+
model,
|
|
2829
|
+
`${model} refused the prompt (blockReason: ${blockReason}${finishMessage ? `, ${finishMessage}` : ""}${ratingText})`,
|
|
2830
|
+
blockReason
|
|
2831
|
+
);
|
|
2832
|
+
}
|
|
2833
|
+
if (finishReason && GEMINI_REFUSAL_FINISH_REASONS.has(finishReason)) {
|
|
2834
|
+
throw new ModelRefusalError(
|
|
2835
|
+
model,
|
|
2836
|
+
`${model} refused to answer (finishReason: ${finishReason}${finishMessage ? `, ${finishMessage}` : ""}${ratingText})`,
|
|
2837
|
+
finishReason
|
|
2838
|
+
);
|
|
2839
|
+
}
|
|
2840
|
+
if (finishReason === "MAX_TOKENS") {
|
|
2841
|
+
throw new ModelInvalidResponseError(model, "empty response, finishReason MAX_TOKENS (thinking consumed the whole output budget)", true);
|
|
2842
|
+
}
|
|
2843
|
+
const bits = [`finishReason=${finishReason ?? "none"}`];
|
|
2844
|
+
if (!response?.candidates?.length) bits.push("no candidates");
|
|
2845
|
+
if (finishMessage) bits.push(`finishMessage="${finishMessage}"`);
|
|
2846
|
+
throw new Error(`${fallback} (${bits.join(", ")})`);
|
|
2847
|
+
}
|
|
2791
2848
|
var GoogleAgent = class extends AbstractAgent {
|
|
2792
2849
|
client;
|
|
2793
2850
|
defaultConfig = {
|
|
@@ -2799,7 +2856,7 @@ var GoogleAgent = class extends AbstractAgent {
|
|
|
2799
2856
|
};
|
|
2800
2857
|
// Error message templates
|
|
2801
2858
|
errorMessages = {
|
|
2802
|
-
emptyResponse: "Empty response from Google API
|
|
2859
|
+
emptyResponse: "Empty response from Google API",
|
|
2803
2860
|
invalidFormat: "Invalid response format from Google API",
|
|
2804
2861
|
apiError: (error) => `Failed to get response from Google API: ${error instanceof Error ? error.message : String(error)}`,
|
|
2805
2862
|
unsupportedRole: (role) => `Unsupported role type: ${role}`
|
|
@@ -2971,7 +3028,7 @@ var GoogleAgent = class extends AbstractAgent {
|
|
|
2971
3028
|
}
|
|
2972
3029
|
this.logger(`Zod schema response received - hasText: ${!!response.text}, textLength: ${response.text ? response.text.length : 0}`);
|
|
2973
3030
|
if (!response.text) {
|
|
2974
|
-
|
|
3031
|
+
throwForEmptyGeminiResponse(this.model, response, this.errorMessages.emptyResponse);
|
|
2975
3032
|
}
|
|
2976
3033
|
const parsedData = parseAndValidateLlmJson(response.text, zodSchema, (m) => this.logger(m));
|
|
2977
3034
|
if (parsedData) {
|
|
@@ -3059,7 +3116,7 @@ var GoogleAgent = class extends AbstractAgent {
|
|
|
3059
3116
|
}
|
|
3060
3117
|
this.logger(`Plain text response received - hasText: ${!!response.text}, textLength: ${response.text ? response.text.length : 0}`);
|
|
3061
3118
|
if (!response.text) {
|
|
3062
|
-
|
|
3119
|
+
throwForEmptyGeminiResponse(this.model, response, this.errorMessages.emptyResponse);
|
|
3063
3120
|
}
|
|
3064
3121
|
this.logReply(response.text, thinkingContent || void 0, tokenUsage);
|
|
3065
3122
|
return [response.text, thinkingContent, tokenUsage, googleThoughtSignature || void 0];
|
|
@@ -5093,6 +5150,7 @@ export {
|
|
|
5093
5150
|
cleanResponse,
|
|
5094
5151
|
createCatalog,
|
|
5095
5152
|
createVoiceAgent,
|
|
5153
|
+
describeEmptyTtsResponse,
|
|
5096
5154
|
evaluateBudget,
|
|
5097
5155
|
extractAnthropicTokenUsage,
|
|
5098
5156
|
extractTokenUsageFromResponse6 as extractAnthropicTokenUsageFromResponse,
|