hydra-aidirector 1.3.0
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 +21 -0
- package/README.md +302 -0
- package/dist/index.d.mts +1028 -0
- package/dist/index.d.ts +1028 -0
- package/dist/index.js +4 -0
- package/dist/index.mjs +4 -0
- package/package.json +87 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
'use strict';var K=typeof process<"u"&&process.versions?.node;async function H(n){let{createHash:e}=await import('crypto');return e("sha256").update(n).digest("hex")}async function G(n,e,t,r,o){let{createHmac:s}=await import('crypto'),c=[e.toUpperCase(),t,o.toString(),r].join(`
|
|
2
|
+
`),d=await H(n);return s("sha256",d).update(c).digest("hex")}async function L(n){let t=new TextEncoder().encode(n),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(s=>s.toString(16).padStart(2,"0")).join("")}async function W(n,e,t,r,o){let s=new TextEncoder,c=[e.toUpperCase(),t,o.toString(),r].join(`
|
|
3
|
+
`),d=await L(n),a=s.encode(d),i=await crypto.subtle.importKey("raw",a,{name:"HMAC",hash:"SHA-256"},false,["sign"]),m=await crypto.subtle.sign("HMAC",i,s.encode(c));return Array.from(new Uint8Array(m)).map(p=>p.toString(16).padStart(2,"0")).join("")}async function T(n,e,t,r,o){return K?G(n,e,t,r,o):W(n,e,t,r,o)}function U(n){return n.slice(0,12)}function C(n){return typeof n=="string"&&n.startsWith("hyd_sk_")&&n.length>=20}var u=class extends Error{constructor(e,t,r){super(e),this.name="HydraError",this.code=t,this.retryable=r?.retryable??false,this.statusCode=r?.statusCode,this.originalError=r?.cause;}},k=class extends u{constructor(e){super(e,"CONFIGURATION_ERROR",{retryable:false}),this.name="ConfigurationError";}},x=class extends u{constructor(e,t){super(e,"AUTH_ERROR",{retryable:false,statusCode:t}),this.name="AuthenticationError";}},E=class extends u{constructor(e,t=6e4){super(e,"RATE_LIMITED",{retryable:true,statusCode:429}),this.name="RateLimitError",this.retryAfterMs=t;}},R=class extends u{constructor(e){super(`Request timed out after ${e}ms`,"TIMEOUT",{retryable:true}),this.name="TimeoutError",this.timeoutMs=e;}},w=class extends u{constructor(e,t){super(e,"NETWORK_ERROR",{retryable:true,cause:t}),this.name="NetworkError";}},f=class extends u{constructor(e,t=[]){super(e,"CHAIN_FAILED",{retryable:false}),this.name="ChainExecutionError",this.attemptedModels=t;}},P=class extends u{constructor(e,t=[]){super(e,"VALIDATION_ERROR",{retryable:false}),this.name="ValidationError",this.validationErrors=t;}},g=class extends u{constructor(e,t=500){super(e,"SERVER_ERROR",{retryable:true,statusCode:t}),this.name="ServerError";}},v=class extends u{constructor(e,t){super(e,"QUOTA_EXCEEDED",{retryable:false,statusCode:402}),this.name="QuotaExceededError",this.tier=t.tier,this.limit=t.limit,this.used=t.used;}},O=class extends u{constructor(e,t){super(e,"WORKER_ERROR",{retryable:true}),this.name="WorkerError",this.workerDurationMs=t;}},I=class extends u{constructor(e,t){super(e,"FILE_PROCESSING_ERROR",{retryable:false}),this.name="FileProcessingError",this.filename=t.filename,this.mimeType=t.mimeType,this.reason=t.reason;}},M=class extends u{constructor(e,t){super(e,"INVALID_SCHEMA",{retryable:false}),this.name="InvalidSchemaError",this.schemaPath=t;}};function _(n){return n instanceof u}function q(n){return _(n)?n.retryable:false}var F="http://localhost:3000",$=6e5,B=3,N=[1e3,2e3,5e3];function J(n){let e=n.trim(),t=e.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);t&&(e=t[1].trim());let r=e.indexOf("{"),o=e.indexOf("["),s;if(r===-1&&o===-1)return e;r===-1?s=o:o===-1?s=r:s=Math.min(r,o);let c=e[s],d=c==="{"?"}":"]",a=0,i=false,m=false,y=-1;for(let h=s;h<e.length;h++){let b=e[h];if(m){m=false;continue}if(b==="\\"&&i){m=true;continue}if(b==='"'&&!m){i=!i;continue}if(!i){if(b===c)a++;else if(b===d&&(a--,a===0)){y=h;break}}}if(y!==-1)return e.slice(s,y+1);let p=e.lastIndexOf(d);return p>s?e.slice(s,p+1):e}var D=class n{constructor(e){if(!e.secretKey)throw new k("secretKey is required");if(!C(e.secretKey))throw new k("Invalid secret key format. Expected format: hyd_sk_<key>");this.secretKey=e.secretKey,this.baseUrl=(e.baseUrl||F).replace(/\/$/,""),this.timeout=e.timeout??$,this.maxRetries=e.maxRetries??B,this.keyPrefix=U(e.secretKey),this.debug=e.debug??false,this.debug&&this.log("Initialized",{baseUrl:this.baseUrl,timeout:this.timeout});}async generate(e){if(e.useOptimized!==false)try{return await this.generateOptimized(e)}catch(r){this.debug&&this.log("3-step generation failed, falling back to legacy",{error:r instanceof Error?r.message:String(r)});}return this.generateLegacy(e)}async generateOptimized(e){let t=Date.now(),r="/api/v1/generate/token",o=JSON.stringify({chainId:e.chainId,prompt:e.prompt,systemPrompt:e.options?.systemPrompt,temperature:e.options?.temperature,maxTokens:e.options?.maxTokens,topP:e.options?.topP,topK:e.options?.topK,files:e.files}),s=await this.makeAuthenticatedRequest(r,"POST",o);if(s.cached&&s.data)return this.debug&&this.log("generate cache hit (optimized)",{latencyMs:Date.now()-t}),{success:true,data:s.data,meta:{cached:true,modelUsed:s.meta?.modelUsed||"",tokensUsed:{input:0,output:0},latencyMs:Date.now()-t,attemptedModels:[]}};if(!s.token||!s.workerUrl)throw new f("Token generation failed - no token or worker URL returned",[]);let c=JSON.stringify({token:s.token,prompt:e.prompt,systemPrompt:e.options?.systemPrompt,timeout:e.timeout??this.timeout}),a=await(await this.fetchWithTimeout(s.workerUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:c},e.timeout??this.timeout)).json();if(!a.success||!a.content)return {success:false,data:{valid:[],invalid:[]},meta:{cached:false,modelUsed:a.modelId||"",tokensUsed:a.tokensUsed||{input:0,output:0},latencyMs:Date.now()-t,attemptedModels:[a.modelId||""]},error:{code:a.errorCode||"GENERATION_FAILED",message:a.errorMessage||"Generation failed",retryable:false}};let i=[],m=[],y=J(a.content);try{let h=JSON.parse(y);Array.isArray(h)?i=h:i=[h];}catch{i=[y];}a.completionToken&&this.cacheCompletionAsync({completionToken:a.completionToken,content:a.content,tokensUsed:a.tokensUsed||{input:0,output:0},finishReason:a.finishReason||"stop",chainId:e.chainId,modelUsed:a.modelId,prompt:e.prompt,systemPrompt:e.options?.systemPrompt,temperature:e.options?.temperature,maxTokens:e.options?.maxTokens,topP:e.options?.topP,topK:e.options?.topK}).catch(h=>{this.debug&&this.log("cacheCompletion failed (non-blocking)",{error:h});});let p=Date.now()-t;return this.debug&&this.log("generate success (optimized 3-step)",{latencyMs:p,modelUsed:a.modelId,tokensUsed:a.tokensUsed}),{success:true,data:{valid:i,invalid:m},meta:{cached:false,modelUsed:a.modelId,tokensUsed:a.tokensUsed||{input:0,output:0},latencyMs:p,attemptedModels:[a.modelId]}}}async cacheCompletionAsync(e){let t="/api/v1/generate/complete",r=JSON.stringify(e);await this.makeAuthenticatedRequest(t,"POST",r);}async generateLegacy(e){let t=Date.now(),r="/api/v1/generate",o=JSON.stringify({chainId:e.chainId,prompt:e.prompt,schema:e.schema,noCache:e.noCache,files:e.files,options:{...e.options,timeout:e.timeout??this.timeout}}),s=null;for(let a=0;a<=this.maxRetries;a++)try{let i=await this.makeAuthenticatedRequest(r,"POST",o,e.timeout),m=Date.now()-t;return this.debug&&this.log("generate success (legacy)",{latencyMs:m,attempt:a+1}),i.meta&&(i.meta.latencyMs=m),i}catch(i){if(s=i instanceof Error?i:new Error(String(i)),this.debug&&this.log(`generate attempt ${a+1} failed`,{error:s.message}),!this.isRetryable(i)||a>=this.maxRetries)break;let m=N[Math.min(a,N.length-1)];i instanceof E&&i.retryAfterMs>m?await this.sleep(i.retryAfterMs):await this.sleep(m);}let c=Date.now()-t,d=s instanceof R;return {success:false,data:{valid:[],invalid:[]},meta:{cached:false,modelUsed:"",tokensUsed:{input:0,output:0},latencyMs:c,attemptedModels:[]},error:{code:d?"TIMEOUT":"REQUEST_FAILED",message:s?.message||"Request failed after all retries",retryable:false}}}async generateStream(e,t){let r="/api/v1/generate/stream",o=JSON.stringify({chainId:e.chainId,prompt:e.prompt,schema:e.schema,options:e.options});try{let s=Date.now(),c=await T(this.secretKey,"POST",r,o,s),d=await this.fetchWithTimeout(`${this.baseUrl}${r}`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream","x-hydra-signature":c,"x-hydra-timestamp":s.toString(),"x-hydra-key":this.keyPrefix},body:o},e.timeout??this.timeout);if(!d.ok){let p=await d.json();throw this.parseError(d.status,p)}let a=d.body?.getReader();if(!a)throw new w("Response body is not readable");let i=new TextDecoder,m="",y=[];for(;;){let{done:p,value:h}=await a.read();if(p)break;m+=i.decode(h,{stream:!0});let b=m.split(`
|
|
4
|
+
`);m=b.pop()||"";let A="";for(let S of b){if(S.startsWith("event: ")){A=S.slice(7).trim();continue}if(S.startsWith("data: ")){let j=S.slice(6);if(j==="[DONE]")break;try{let l=JSON.parse(j);switch(A){case "start":this.debug&&this.log("Stream started",l);break;case "object":l.object!==void 0&&(y.push(l.object),t.onObject?.(l.object,l.index)),t.onChunk&&l.object&&t.onChunk(JSON.stringify(l.object));break;case "array_start":t.onArrayStart?.();break;case "complete":t.onComplete&&t.onComplete({objects:y,objectCount:l.objectCount,tokensUsed:l.tokensUsed,cached:l.cached});break;case "error":t.onError&&t.onError(new f(l.error||"Stream error",["STREAM_ERROR"]));break;default:l.chunk&&t.onChunk?.(l.chunk);}}catch{}A="";}}}}catch(s){if(t.onError)t.onError(s instanceof Error?s:new Error(String(s)));else throw s}}async listModels(){let t=await(await this.fetchWithTimeout(`${this.baseUrl}/api/v1/models`,{method:"GET",headers:{Accept:"application/json"}})).json();if(!t.success)throw new g(t.error?.message||"Failed to list models");return t.data}async listChains(){let t=await(await this.fetchWithTimeout(`${this.baseUrl}/api/v1/chains`,{method:"GET",credentials:"include",headers:{Accept:"application/json"}})).json();if(!t.success)throw new g(t.error?.message||"Failed to list chains");return t.data}async getUsage(e){let t=new URLSearchParams;e?.startDate&&t.set("startDate",e.startDate.toISOString()),e?.endDate&&t.set("endDate",e.endDate.toISOString());let r=`${this.baseUrl}/api/v1/usage${t.toString()?"?"+t:""}`,s=await(await this.fetchWithTimeout(r,{method:"GET",credentials:"include",headers:{Accept:"application/json"}})).json();if(!s.success)throw new g(s.error?.message||"Failed to get usage");return s.data}async health(){let e=Date.now();try{let t=await this.fetchWithTimeout(`${this.baseUrl}/api/health`,{method:"GET"},5e3),r=Date.now()-e,o=await t.json().catch(()=>({}));return {ok:t.ok,latencyMs:r,version:o.version}}catch{return {ok:false,latencyMs:Date.now()-e}}}withConfig(e){return new n({secretKey:this.secretKey,baseUrl:this.baseUrl,timeout:this.timeout,maxRetries:this.maxRetries,debug:this.debug,...e})}async registerWebhook(e){let t=await this.makeAuthenticatedRequest("/api/v1/webhooks","POST",JSON.stringify(e));if(!t.success||!t.data)throw new g(t.error?.message||"Failed to register webhook");return t.data}async unregisterWebhook(e){let t=await this.makeAuthenticatedRequest(`/api/v1/webhooks/${e}`,"DELETE","");if(!t.success||!t.data)throw new g(t.error?.message||"Failed to unregister webhook");return t.data}async listWebhooks(){let e=await this.makeAuthenticatedRequest("/api/v1/webhooks","GET","");if(!e.success)throw new g(e.error?.message||"Failed to list webhooks");return e.data||[]}async updateWebhook(e,t){let r=await this.makeAuthenticatedRequest(`/api/v1/webhooks/${e}`,"PATCH",JSON.stringify(t));if(!r.success||!r.data)throw new g(r.error?.message||"Failed to update webhook");return r.data}async healthDetailed(){return (await fetch(`${this.baseUrl}/api/v1/health/detailed`,{headers:{Accept:"application/json"}})).json()}async generateBatch(e,t,r={}){let o=await this.makeAuthenticatedRequest("/api/v1/generate/batch","POST",JSON.stringify({chainId:e,items:t,continueOnError:r.continueOnError??true}));if(!o.success||!o.data)throw new f(o.error?.message||"Batch generation failed",[]);return o.data}async makeAuthenticatedRequest(e,t,r,o){let s=Date.now(),c=await T(this.secretKey,t,e,r,s),d=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:t,headers:{"Content-Type":"application/json",Accept:"application/json","x-hydra-signature":c,"x-hydra-timestamp":s.toString(),"x-hydra-key":this.keyPrefix},body:r},o??this.timeout),a=await d.json();if(!d.ok)throw this.parseError(d.status,a);return a}async fetchWithTimeout(e,t,r=this.timeout){let o=new AbortController,s=setTimeout(()=>o.abort(),r);try{return await fetch(e,{...t,signal:o.signal})}catch(c){throw c instanceof Error&&c.name==="AbortError"?new R(r):c instanceof Error?new w(c.message,c):new w(String(c))}finally{clearTimeout(s);}}parseError(e,t){let r=t?.error?.message||`HTTP ${e}`,o=t?.error?.code||"UNKNOWN";switch(e){case 401:return new x(r,e);case 429:let s=t?.retryAfterMs||6e4;return new E(r,s);case 500:case 502:case 503:case 504:return new g(r,e);default:return o==="CHAIN_FAILED"?new f(r,t?.error?.attemptedModels||[]):new u(r,o,{statusCode:e,retryable:e>=500})}}isRetryable(e){if(e instanceof u)return e.retryable;if(e instanceof Error){let t=e.message.toLowerCase();return t.includes("network")||t.includes("timeout")||e.name==="AbortError"}return false}sleep(e){return new Promise(t=>setTimeout(t,e))}log(e,t){let r="[Hydra]";t?console.log(r,e,t):console.log(r,e);}};exports.AuthenticationError=x;exports.ChainExecutionError=f;exports.ConfigurationError=k;exports.FileProcessingError=I;exports.Hydra=D;exports.HydraError=u;exports.InvalidSchemaError=M;exports.NetworkError=w;exports.QuotaExceededError=v;exports.RateLimitError=E;exports.ServerError=g;exports.TimeoutError=R;exports.ValidationError=P;exports.WorkerError=O;exports.generateSignature=T;exports.getKeyPrefix=U;exports.isHydraError=_;exports.isRetryableError=q;exports.isValidSecretKey=C;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var K=typeof process<"u"&&process.versions?.node;async function H(n){let{createHash:e}=await import('crypto');return e("sha256").update(n).digest("hex")}async function G(n,e,t,r,o){let{createHmac:s}=await import('crypto'),c=[e.toUpperCase(),t,o.toString(),r].join(`
|
|
2
|
+
`),d=await H(n);return s("sha256",d).update(c).digest("hex")}async function L(n){let t=new TextEncoder().encode(n),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(s=>s.toString(16).padStart(2,"0")).join("")}async function W(n,e,t,r,o){let s=new TextEncoder,c=[e.toUpperCase(),t,o.toString(),r].join(`
|
|
3
|
+
`),d=await L(n),a=s.encode(d),i=await crypto.subtle.importKey("raw",a,{name:"HMAC",hash:"SHA-256"},false,["sign"]),m=await crypto.subtle.sign("HMAC",i,s.encode(c));return Array.from(new Uint8Array(m)).map(p=>p.toString(16).padStart(2,"0")).join("")}async function T(n,e,t,r,o){return K?G(n,e,t,r,o):W(n,e,t,r,o)}function U(n){return n.slice(0,12)}function C(n){return typeof n=="string"&&n.startsWith("hyd_sk_")&&n.length>=20}var u=class extends Error{constructor(e,t,r){super(e),this.name="HydraError",this.code=t,this.retryable=r?.retryable??false,this.statusCode=r?.statusCode,this.originalError=r?.cause;}},k=class extends u{constructor(e){super(e,"CONFIGURATION_ERROR",{retryable:false}),this.name="ConfigurationError";}},x=class extends u{constructor(e,t){super(e,"AUTH_ERROR",{retryable:false,statusCode:t}),this.name="AuthenticationError";}},E=class extends u{constructor(e,t=6e4){super(e,"RATE_LIMITED",{retryable:true,statusCode:429}),this.name="RateLimitError",this.retryAfterMs=t;}},R=class extends u{constructor(e){super(`Request timed out after ${e}ms`,"TIMEOUT",{retryable:true}),this.name="TimeoutError",this.timeoutMs=e;}},w=class extends u{constructor(e,t){super(e,"NETWORK_ERROR",{retryable:true,cause:t}),this.name="NetworkError";}},f=class extends u{constructor(e,t=[]){super(e,"CHAIN_FAILED",{retryable:false}),this.name="ChainExecutionError",this.attemptedModels=t;}},P=class extends u{constructor(e,t=[]){super(e,"VALIDATION_ERROR",{retryable:false}),this.name="ValidationError",this.validationErrors=t;}},g=class extends u{constructor(e,t=500){super(e,"SERVER_ERROR",{retryable:true,statusCode:t}),this.name="ServerError";}},v=class extends u{constructor(e,t){super(e,"QUOTA_EXCEEDED",{retryable:false,statusCode:402}),this.name="QuotaExceededError",this.tier=t.tier,this.limit=t.limit,this.used=t.used;}},O=class extends u{constructor(e,t){super(e,"WORKER_ERROR",{retryable:true}),this.name="WorkerError",this.workerDurationMs=t;}},I=class extends u{constructor(e,t){super(e,"FILE_PROCESSING_ERROR",{retryable:false}),this.name="FileProcessingError",this.filename=t.filename,this.mimeType=t.mimeType,this.reason=t.reason;}},M=class extends u{constructor(e,t){super(e,"INVALID_SCHEMA",{retryable:false}),this.name="InvalidSchemaError",this.schemaPath=t;}};function _(n){return n instanceof u}function q(n){return _(n)?n.retryable:false}var F="http://localhost:3000",$=6e5,B=3,N=[1e3,2e3,5e3];function J(n){let e=n.trim(),t=e.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);t&&(e=t[1].trim());let r=e.indexOf("{"),o=e.indexOf("["),s;if(r===-1&&o===-1)return e;r===-1?s=o:o===-1?s=r:s=Math.min(r,o);let c=e[s],d=c==="{"?"}":"]",a=0,i=false,m=false,y=-1;for(let h=s;h<e.length;h++){let b=e[h];if(m){m=false;continue}if(b==="\\"&&i){m=true;continue}if(b==='"'&&!m){i=!i;continue}if(!i){if(b===c)a++;else if(b===d&&(a--,a===0)){y=h;break}}}if(y!==-1)return e.slice(s,y+1);let p=e.lastIndexOf(d);return p>s?e.slice(s,p+1):e}var D=class n{constructor(e){if(!e.secretKey)throw new k("secretKey is required");if(!C(e.secretKey))throw new k("Invalid secret key format. Expected format: hyd_sk_<key>");this.secretKey=e.secretKey,this.baseUrl=(e.baseUrl||F).replace(/\/$/,""),this.timeout=e.timeout??$,this.maxRetries=e.maxRetries??B,this.keyPrefix=U(e.secretKey),this.debug=e.debug??false,this.debug&&this.log("Initialized",{baseUrl:this.baseUrl,timeout:this.timeout});}async generate(e){if(e.useOptimized!==false)try{return await this.generateOptimized(e)}catch(r){this.debug&&this.log("3-step generation failed, falling back to legacy",{error:r instanceof Error?r.message:String(r)});}return this.generateLegacy(e)}async generateOptimized(e){let t=Date.now(),r="/api/v1/generate/token",o=JSON.stringify({chainId:e.chainId,prompt:e.prompt,systemPrompt:e.options?.systemPrompt,temperature:e.options?.temperature,maxTokens:e.options?.maxTokens,topP:e.options?.topP,topK:e.options?.topK,files:e.files}),s=await this.makeAuthenticatedRequest(r,"POST",o);if(s.cached&&s.data)return this.debug&&this.log("generate cache hit (optimized)",{latencyMs:Date.now()-t}),{success:true,data:s.data,meta:{cached:true,modelUsed:s.meta?.modelUsed||"",tokensUsed:{input:0,output:0},latencyMs:Date.now()-t,attemptedModels:[]}};if(!s.token||!s.workerUrl)throw new f("Token generation failed - no token or worker URL returned",[]);let c=JSON.stringify({token:s.token,prompt:e.prompt,systemPrompt:e.options?.systemPrompt,timeout:e.timeout??this.timeout}),a=await(await this.fetchWithTimeout(s.workerUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:c},e.timeout??this.timeout)).json();if(!a.success||!a.content)return {success:false,data:{valid:[],invalid:[]},meta:{cached:false,modelUsed:a.modelId||"",tokensUsed:a.tokensUsed||{input:0,output:0},latencyMs:Date.now()-t,attemptedModels:[a.modelId||""]},error:{code:a.errorCode||"GENERATION_FAILED",message:a.errorMessage||"Generation failed",retryable:false}};let i=[],m=[],y=J(a.content);try{let h=JSON.parse(y);Array.isArray(h)?i=h:i=[h];}catch{i=[y];}a.completionToken&&this.cacheCompletionAsync({completionToken:a.completionToken,content:a.content,tokensUsed:a.tokensUsed||{input:0,output:0},finishReason:a.finishReason||"stop",chainId:e.chainId,modelUsed:a.modelId,prompt:e.prompt,systemPrompt:e.options?.systemPrompt,temperature:e.options?.temperature,maxTokens:e.options?.maxTokens,topP:e.options?.topP,topK:e.options?.topK}).catch(h=>{this.debug&&this.log("cacheCompletion failed (non-blocking)",{error:h});});let p=Date.now()-t;return this.debug&&this.log("generate success (optimized 3-step)",{latencyMs:p,modelUsed:a.modelId,tokensUsed:a.tokensUsed}),{success:true,data:{valid:i,invalid:m},meta:{cached:false,modelUsed:a.modelId,tokensUsed:a.tokensUsed||{input:0,output:0},latencyMs:p,attemptedModels:[a.modelId]}}}async cacheCompletionAsync(e){let t="/api/v1/generate/complete",r=JSON.stringify(e);await this.makeAuthenticatedRequest(t,"POST",r);}async generateLegacy(e){let t=Date.now(),r="/api/v1/generate",o=JSON.stringify({chainId:e.chainId,prompt:e.prompt,schema:e.schema,noCache:e.noCache,files:e.files,options:{...e.options,timeout:e.timeout??this.timeout}}),s=null;for(let a=0;a<=this.maxRetries;a++)try{let i=await this.makeAuthenticatedRequest(r,"POST",o,e.timeout),m=Date.now()-t;return this.debug&&this.log("generate success (legacy)",{latencyMs:m,attempt:a+1}),i.meta&&(i.meta.latencyMs=m),i}catch(i){if(s=i instanceof Error?i:new Error(String(i)),this.debug&&this.log(`generate attempt ${a+1} failed`,{error:s.message}),!this.isRetryable(i)||a>=this.maxRetries)break;let m=N[Math.min(a,N.length-1)];i instanceof E&&i.retryAfterMs>m?await this.sleep(i.retryAfterMs):await this.sleep(m);}let c=Date.now()-t,d=s instanceof R;return {success:false,data:{valid:[],invalid:[]},meta:{cached:false,modelUsed:"",tokensUsed:{input:0,output:0},latencyMs:c,attemptedModels:[]},error:{code:d?"TIMEOUT":"REQUEST_FAILED",message:s?.message||"Request failed after all retries",retryable:false}}}async generateStream(e,t){let r="/api/v1/generate/stream",o=JSON.stringify({chainId:e.chainId,prompt:e.prompt,schema:e.schema,options:e.options});try{let s=Date.now(),c=await T(this.secretKey,"POST",r,o,s),d=await this.fetchWithTimeout(`${this.baseUrl}${r}`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream","x-hydra-signature":c,"x-hydra-timestamp":s.toString(),"x-hydra-key":this.keyPrefix},body:o},e.timeout??this.timeout);if(!d.ok){let p=await d.json();throw this.parseError(d.status,p)}let a=d.body?.getReader();if(!a)throw new w("Response body is not readable");let i=new TextDecoder,m="",y=[];for(;;){let{done:p,value:h}=await a.read();if(p)break;m+=i.decode(h,{stream:!0});let b=m.split(`
|
|
4
|
+
`);m=b.pop()||"";let A="";for(let S of b){if(S.startsWith("event: ")){A=S.slice(7).trim();continue}if(S.startsWith("data: ")){let j=S.slice(6);if(j==="[DONE]")break;try{let l=JSON.parse(j);switch(A){case "start":this.debug&&this.log("Stream started",l);break;case "object":l.object!==void 0&&(y.push(l.object),t.onObject?.(l.object,l.index)),t.onChunk&&l.object&&t.onChunk(JSON.stringify(l.object));break;case "array_start":t.onArrayStart?.();break;case "complete":t.onComplete&&t.onComplete({objects:y,objectCount:l.objectCount,tokensUsed:l.tokensUsed,cached:l.cached});break;case "error":t.onError&&t.onError(new f(l.error||"Stream error",["STREAM_ERROR"]));break;default:l.chunk&&t.onChunk?.(l.chunk);}}catch{}A="";}}}}catch(s){if(t.onError)t.onError(s instanceof Error?s:new Error(String(s)));else throw s}}async listModels(){let t=await(await this.fetchWithTimeout(`${this.baseUrl}/api/v1/models`,{method:"GET",headers:{Accept:"application/json"}})).json();if(!t.success)throw new g(t.error?.message||"Failed to list models");return t.data}async listChains(){let t=await(await this.fetchWithTimeout(`${this.baseUrl}/api/v1/chains`,{method:"GET",credentials:"include",headers:{Accept:"application/json"}})).json();if(!t.success)throw new g(t.error?.message||"Failed to list chains");return t.data}async getUsage(e){let t=new URLSearchParams;e?.startDate&&t.set("startDate",e.startDate.toISOString()),e?.endDate&&t.set("endDate",e.endDate.toISOString());let r=`${this.baseUrl}/api/v1/usage${t.toString()?"?"+t:""}`,s=await(await this.fetchWithTimeout(r,{method:"GET",credentials:"include",headers:{Accept:"application/json"}})).json();if(!s.success)throw new g(s.error?.message||"Failed to get usage");return s.data}async health(){let e=Date.now();try{let t=await this.fetchWithTimeout(`${this.baseUrl}/api/health`,{method:"GET"},5e3),r=Date.now()-e,o=await t.json().catch(()=>({}));return {ok:t.ok,latencyMs:r,version:o.version}}catch{return {ok:false,latencyMs:Date.now()-e}}}withConfig(e){return new n({secretKey:this.secretKey,baseUrl:this.baseUrl,timeout:this.timeout,maxRetries:this.maxRetries,debug:this.debug,...e})}async registerWebhook(e){let t=await this.makeAuthenticatedRequest("/api/v1/webhooks","POST",JSON.stringify(e));if(!t.success||!t.data)throw new g(t.error?.message||"Failed to register webhook");return t.data}async unregisterWebhook(e){let t=await this.makeAuthenticatedRequest(`/api/v1/webhooks/${e}`,"DELETE","");if(!t.success||!t.data)throw new g(t.error?.message||"Failed to unregister webhook");return t.data}async listWebhooks(){let e=await this.makeAuthenticatedRequest("/api/v1/webhooks","GET","");if(!e.success)throw new g(e.error?.message||"Failed to list webhooks");return e.data||[]}async updateWebhook(e,t){let r=await this.makeAuthenticatedRequest(`/api/v1/webhooks/${e}`,"PATCH",JSON.stringify(t));if(!r.success||!r.data)throw new g(r.error?.message||"Failed to update webhook");return r.data}async healthDetailed(){return (await fetch(`${this.baseUrl}/api/v1/health/detailed`,{headers:{Accept:"application/json"}})).json()}async generateBatch(e,t,r={}){let o=await this.makeAuthenticatedRequest("/api/v1/generate/batch","POST",JSON.stringify({chainId:e,items:t,continueOnError:r.continueOnError??true}));if(!o.success||!o.data)throw new f(o.error?.message||"Batch generation failed",[]);return o.data}async makeAuthenticatedRequest(e,t,r,o){let s=Date.now(),c=await T(this.secretKey,t,e,r,s),d=await this.fetchWithTimeout(`${this.baseUrl}${e}`,{method:t,headers:{"Content-Type":"application/json",Accept:"application/json","x-hydra-signature":c,"x-hydra-timestamp":s.toString(),"x-hydra-key":this.keyPrefix},body:r},o??this.timeout),a=await d.json();if(!d.ok)throw this.parseError(d.status,a);return a}async fetchWithTimeout(e,t,r=this.timeout){let o=new AbortController,s=setTimeout(()=>o.abort(),r);try{return await fetch(e,{...t,signal:o.signal})}catch(c){throw c instanceof Error&&c.name==="AbortError"?new R(r):c instanceof Error?new w(c.message,c):new w(String(c))}finally{clearTimeout(s);}}parseError(e,t){let r=t?.error?.message||`HTTP ${e}`,o=t?.error?.code||"UNKNOWN";switch(e){case 401:return new x(r,e);case 429:let s=t?.retryAfterMs||6e4;return new E(r,s);case 500:case 502:case 503:case 504:return new g(r,e);default:return o==="CHAIN_FAILED"?new f(r,t?.error?.attemptedModels||[]):new u(r,o,{statusCode:e,retryable:e>=500})}}isRetryable(e){if(e instanceof u)return e.retryable;if(e instanceof Error){let t=e.message.toLowerCase();return t.includes("network")||t.includes("timeout")||e.name==="AbortError"}return false}sleep(e){return new Promise(t=>setTimeout(t,e))}log(e,t){let r="[Hydra]";t?console.log(r,e,t):console.log(r,e);}};export{x as AuthenticationError,f as ChainExecutionError,k as ConfigurationError,I as FileProcessingError,D as Hydra,u as HydraError,M as InvalidSchemaError,w as NetworkError,v as QuotaExceededError,E as RateLimitError,g as ServerError,R as TimeoutError,P as ValidationError,O as WorkerError,T as generateSignature,U as getKeyPrefix,_ as isHydraError,q as isRetryableError,C as isValidSecretKey};
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hydra-aidirector",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Official TypeScript SDK for Hydra - Intelligent AI API Gateway with automatic failover, caching, and JSON extraction",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"default": "./dist/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"dev": "tsup --watch",
|
|
29
|
+
"lint": "tsc --noEmit",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest",
|
|
32
|
+
"prepublishOnly": "npm run build",
|
|
33
|
+
"clean": "rimraf dist",
|
|
34
|
+
"publish:check": "npm pack --dry-run",
|
|
35
|
+
"release": "npm run build && npm publish",
|
|
36
|
+
"release:beta": "npm run build && npm publish --tag beta"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"ai",
|
|
40
|
+
"api",
|
|
41
|
+
"gateway",
|
|
42
|
+
"gemini",
|
|
43
|
+
"openrouter",
|
|
44
|
+
"openai",
|
|
45
|
+
"llm",
|
|
46
|
+
"fallback",
|
|
47
|
+
"sdk",
|
|
48
|
+
"typescript",
|
|
49
|
+
"json",
|
|
50
|
+
"cache",
|
|
51
|
+
"hmac"
|
|
52
|
+
],
|
|
53
|
+
"author": {
|
|
54
|
+
"name": "Hydra",
|
|
55
|
+
"url": "https://hydrai.dev"
|
|
56
|
+
},
|
|
57
|
+
"license": "MIT",
|
|
58
|
+
"homepage": "https://hydrai.dev",
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/hydrai/client/issues"
|
|
61
|
+
},
|
|
62
|
+
"repository": {
|
|
63
|
+
"type": "git",
|
|
64
|
+
"url": "git+https://github.com/hydrai/client.git"
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public",
|
|
68
|
+
"registry": "https://registry.npmjs.org/"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"rimraf": "^5.0.0",
|
|
72
|
+
"tsup": "^8.0.0",
|
|
73
|
+
"typescript": "^5.0.0",
|
|
74
|
+
"vitest": "^4.0.0"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"typescript": ">=5.0.0"
|
|
78
|
+
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"typescript": {
|
|
81
|
+
"optional": true
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": ">=18.0.0"
|
|
86
|
+
}
|
|
87
|
+
}
|