@x-otto/provider 0.1.0-alpha.39 → 0.1.0-alpha.40

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.ts CHANGED
@@ -944,5 +944,4 @@ declare class ReplayProviderStream implements ProviderStream {
944
944
  }
945
945
  declare function createReplayProviderFactory(filePath: string, options?: ReplayOptions): () => ProviderStream;
946
946
  //#endregion
947
- export { type Api, type AssistantContent, type AssistantMessage, type AssistantMessageMeta, type AuthErrorType, type AuthMode, type CacheRetention, type ChatCompletionsStreamParams, type ContentPart, DeviceFlowOAuthTemplate, type DeviceFlowOAuthTemplateParams, type FlatStreamState, type FlatToolCallAcc, type ImageContent, type LoopbackCallback, type LoopbackServer, type LoopbackServerOptions, MAX_PLUGIN_RETRIES, type Message, type Model, type OAuthCredentials, type OAuthInfo, type OAuthLoginOptions, type OAuthPrompt, type OAuthProvider, type OAuthProviderFactory, type OAuthProviderId, type OAuthRefreshTokenOptions, PKCEOAuthTemplate, type PKCEOAuthTemplateParams, type PkcePair, type Provider, type ProviderFactory, type ProviderRetryPolicy, type ProviderRetryPolicyBinding, type ProviderStream, REPLAY_API, type Recording, type RecordingHeader, type RecordingLine, type ReplayOptions, ReplayProviderStream, type RequestHeaderSources, type ResolveRetryPolicy, type ResolvedAuth, type RetryDecision, type RetryDecisionContext, type StopReason, type StreamBlock, type StreamContext, type StreamErrorClass, type StreamEvent, type StreamFunction, type StreamOptions, type StreamUsage, type SystemPromptSegment, type TextContent, type ThinkingContent, type TokenDerivedHeader, type ToolCall, type ToolDefinition, type ToolResultMessage, type TurnRetryPolicy, type UserMessage, type WireProtocolFactoryInput, type WireProtocolLogger, type WireProtocolMeta, type WireProtocolRegistration, type WireRequestCustomization, type WireRequestCustomizeInput, type WireSystemTextBlock, assembleAssistantMessage, assertSystemNotificationPlacement, blocksContent, buildChatCompletionsBody, buildChatCompletionsMessages, buildReplayModel, buildRequestHeaders, clampThinkingLevel, classifyAuthErrorType, classifyStreamError, createPkcePair, createReplayProviderFactory, degradedSystemNotificationText, extractAbortKind, extractAnthropicRateLimit, extractCode, extractJwtClaim, extractRetryAfterMs, extractStandardRateLimitHeaders, extractStatus, flatContent, generateChallenge, generateState, generateVerifier, hasTrailingInvokeXml, initFlatStreamState, initStreamUsage, isAuthError, isContextOverflowError, isNetworkDisconnectError, isNonRetryableStreamError, loadRecording, mapChatFinishReason, mergeConsecutiveSystemNotifications, noopWireProtocolLogger, parseToolArguments, parseToolArgumentsWithStatus, recordStream, recordingsDir, recoverLiteralInvokeToolCalls, registeredToolNames, replayStream, resolveProviderBaseUrl, sanitizeSurrogates, sanitizeToolRoundtrips, startLoopbackServer, streamChatCompletions, toJsonSchema, toolCallFromParsed };
948
- //# sourceMappingURL=index.d.ts.map
947
+ export { type Api, type AssistantContent, type AssistantMessage, type AssistantMessageMeta, type AuthErrorType, type AuthMode, type CacheRetention, type ChatCompletionsStreamParams, type ContentPart, DeviceFlowOAuthTemplate, type DeviceFlowOAuthTemplateParams, type FlatStreamState, type FlatToolCallAcc, type ImageContent, type LoopbackCallback, type LoopbackServer, type LoopbackServerOptions, MAX_PLUGIN_RETRIES, type Message, type Model, type OAuthCredentials, type OAuthInfo, type OAuthLoginOptions, type OAuthPrompt, type OAuthProvider, type OAuthProviderFactory, type OAuthProviderId, type OAuthRefreshTokenOptions, PKCEOAuthTemplate, type PKCEOAuthTemplateParams, type PkcePair, type Provider, type ProviderFactory, type ProviderRetryPolicy, type ProviderRetryPolicyBinding, type ProviderStream, REPLAY_API, type Recording, type RecordingHeader, type RecordingLine, type ReplayOptions, ReplayProviderStream, type RequestHeaderSources, type ResolveRetryPolicy, type ResolvedAuth, type RetryDecision, type RetryDecisionContext, type StopReason, type StreamBlock, type StreamContext, type StreamErrorClass, type StreamEvent, type StreamFunction, type StreamOptions, type StreamUsage, type SystemPromptSegment, type TextContent, type ThinkingContent, type TokenDerivedHeader, type ToolCall, type ToolDefinition, type ToolResultMessage, type TurnRetryPolicy, type UserMessage, type WireProtocolFactoryInput, type WireProtocolLogger, type WireProtocolMeta, type WireProtocolRegistration, type WireRequestCustomization, type WireRequestCustomizeInput, type WireSystemTextBlock, assembleAssistantMessage, assertSystemNotificationPlacement, blocksContent, buildChatCompletionsBody, buildChatCompletionsMessages, buildReplayModel, buildRequestHeaders, clampThinkingLevel, classifyAuthErrorType, classifyStreamError, createPkcePair, createReplayProviderFactory, degradedSystemNotificationText, extractAbortKind, extractAnthropicRateLimit, extractCode, extractJwtClaim, extractRetryAfterMs, extractStandardRateLimitHeaders, extractStatus, flatContent, generateChallenge, generateState, generateVerifier, hasTrailingInvokeXml, initFlatStreamState, initStreamUsage, isAuthError, isContextOverflowError, isNetworkDisconnectError, isNonRetryableStreamError, loadRecording, mapChatFinishReason, mergeConsecutiveSystemNotifications, noopWireProtocolLogger, parseToolArguments, parseToolArgumentsWithStatus, recordStream, recordingsDir, recoverLiteralInvokeToolCalls, registeredToolNames, replayStream, resolveProviderBaseUrl, sanitizeSurrogates, sanitizeToolRoundtrips, startLoopbackServer, streamChatCompletions, toJsonSchema, toolCallFromParsed };
package/dist/index.js CHANGED
@@ -7,4 +7,4 @@ import{normalizeImageData as e}from"@x-otto/interchange";import{DEFAULT_LOOPBACK
7
7
  `))}return t?{status:`unknown`,standardLimits:t}:null}const se=i(`@x-otto/provider:stream-state`);function N(){return{inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0}}function P(e,t){try{return{args:JSON.parse(e),parseFailed:!1}}catch{return se.debug({toolName:t,argumentsJson:e.slice(0,500),length:e.length},`Failed to parse tool arguments JSON`),{args:{},parseFailed:!0}}}function ce(e,t){return P(e,t).args}function le(e){return new Set(e?.map(e=>e.name)??[])}function F(e,t,n){let{args:r,parseFailed:i}=P(n,t);return{type:`tool_call`,id:e,name:t,arguments:r,...i?{argumentsParseFailed:!0}:{}}}function I(e,t){if(e.content.some(e=>e.type===`tool_call`))return e;let n=e.content.findLastIndex(e=>e.type===`text`);if(n<0)return e;let r=e.content[n],i=R(r.text,t);if(!i)return e;let a=[...e.content],o=r.text.slice(0,i.matchStart).trimEnd();return o.length>0?a[n]={...r,text:o}:a.splice(n,1),a.push(F(`recovered_${n}`,i.name,i.argumentsJson)),{...e,content:a}}const ue=/<invoke name="([^"]+)">((?:(?!<invoke name=")[\s\S])*?)<\/invoke>\s*$/,L=/<parameter name="([^"]+)">([\s\S]*?)<\/parameter>/g;function de(e,t){return R(e,t)!==null}function R(e,t){let n=e.trimEnd(),r=ue.exec(n);if(!r)return null;let i=r[1];if(!t.has(i))return null;let a={},o=r[2],s;for(L.lastIndex=0;(s=L.exec(o))!==null;)a[s[1]]=s[2];return{name:i,argumentsJson:JSON.stringify(a),matchStart:r.index}}function z(){return{...N(),textContent:``,thinkingText:``,toolCalls:new Map,stopReason:`end_turn`}}function B(e,t=!0){let n=[];if(e.thinkingText&&n.push({type:`thinking`,text:e.thinkingText}),e.textContent&&n.push({type:`text`,text:e.textContent}),t)for(let[,t]of e.toolCalls)n.push(F(t.id,t.name,t.argumentsJson));return n}function fe(e,t=!0){let n=[],r=[...e.entries()].sort(([e],[t])=>e-t);for(let[,e]of r)e.kind===`thinking`?e.text&&n.push({type:`thinking`,text:e.text,...e.signature===void 0?{}:{signature:e.signature}}):e.kind===`text`?e.text&&n.push({type:`text`,text:e.text}):t&&n.push(F(e.id,e.name,e.argumentsJson));return n}function V(e,t,n,r){return{role:`assistant`,content:r===`max_tokens`?t:t.map(e=>{if(e.type!==`tool_call`||!(`argumentsParseFailed`in e))return e;let{argumentsParseFailed:t,...n}=e;return n}),api:e.api,provider:e.provider,model:e.model,usage:{inputTokens:n.inputTokens,outputTokens:n.outputTokens,cacheReadTokens:n.cacheReadTokens,cacheWriteTokens:n.cacheWriteTokens},stopReason:r}}const pe=i(`@x-otto/provider:chat-completions-stream`);function H(e){switch(e){case`stop`:return`end_turn`;case`length`:return`max_tokens`;case`tool_calls`:return`tool_use`;case`content_filter`:return`refusal`;default:return pe.warn(`Unknown chat-completions finish_reason: ${e}`),`end_turn`}}async function*me(e){let{url:t,headers:n,body:i,identity:a,signal:o,timeout:s,idleTimeout:c,onResponse:l,registeredToolNames:u}=e,d=z(),f=(e=!1)=>V(a,B(d,e),d,d.stopReason),m=!1,h=!1,g=!1,_=!1,v,y=p({url:t,body:i,headers:n,signal:o,timeout:s,idleTimeout:c,onResponse:e=>{v=e,l?.(e)}});try{for await(let e of y){if(e.data===`[DONE]`)break;let t;try{t=JSON.parse(e.data)}catch{continue}if(t.error){let e=t.error,n=typeof e.message==`string`?e.message:JSON.stringify(e),i=e.code,a=typeof i==`number`?i:typeof i==`string`&&/^\d+/.test(i)?Number(i.match(/^\d+/)?.[0]):void 0;throw new r(`Chat Completions stream error: ${n}`,{code:`PROVIDER_API_ERROR`,status:a})}if(t.usage){let e=t.usage,n=e.prompt_tokens??0,r=e.completion_tokens??0,i=e.prompt_tokens_details?.cached_tokens??e.prompt_cache_hit_tokens??0;d.inputTokens=n-i,d.cacheReadTokens=i,d.outputTokens=r}let n=t.choices?.[0];if(!n)continue;let i=n.delta;if(m||(m=!0,yield{type:`start`,partial:f()}),n.finish_reason&&(_=!0,d.stopReason=H(n.finish_reason)),!i)continue;if(i.content){let e=i.content;h||(h=!0,yield{type:`text_start`,index:0,partial:f()}),d.textContent+=e,yield{type:`text_delta`,index:0,delta:e,partial:f()}}let a=i.reasoning_content??i.reasoning??i.reasoning_text??null;if(a&&(g||(g=!0,yield{type:`thinking_start`,index:0,partial:f()}),d.thinkingText+=a,yield{type:`thinking_delta`,index:0,delta:a,partial:f()}),i.tool_calls)for(let e of i.tool_calls){let t=e.index,n=e.function;d.toolCalls.has(t)||(d.toolCalls.set(t,{id:e.id??`call_${t}`,name:n?.name??``,argumentsJson:``}),yield{type:`tool_call_start`,index:t,partial:f()});let r=d.toolCalls.get(t);if(n?.arguments){let e=n.arguments;r.argumentsJson+=e,yield{type:`tool_call_delta`,index:t,delta:e,partial:f()}}}}g&&(yield{type:`thinking_end`,index:0,content:d.thinkingText,partial:f()}),h&&(yield{type:`text_end`,index:0,content:d.textContent,partial:f()});for(let[e,t]of d.toolCalls)yield{type:`tool_call_end`,index:e,toolCall:F(t.id,t.name,t.argumentsJson),partial:f()};_||(d.stopReason=`incomplete`),yield{type:`done`,reason:d.stopReason,message:I(f(!0),u??new Set),providerUsage:M(v)}}catch(e){yield{type:`error`,error:e instanceof Error?e:new r(`Unknown Chat Completions stream error`,{code:`PROVIDER_STREAM_ERROR`})}}}function U(e,t,n){for(let r of e){if(!r)continue;let e=r.split(`.`)[1];if(e)try{let r=JSON.parse(Buffer.from(e,`base64url`).toString(`utf-8`));if(n){let e=r[n]?.[t]??r[t];if(typeof e==`string`)return e}else{let e=r[t];if(typeof e==`string`)return e}}catch{}}}const he=new Set([`authorization`,`x-api-key`]),ge=/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/,_e=/[\u0000-\u001f\u007f]/g;function W(e,t,n,r){let i=new Map;if(!e)return i;for(let[a,o]of Object.entries(e)){let e=a.trim();if(!ge.test(e)){n?.warn({provider:r,source:t,header:a},`dropped request header with invalid name (RFC 7230 token expected)`);continue}if(typeof o!=`string`)continue;let s=o.replace(_e,``).trim();s&&i.set(e.toLowerCase(),{name:e,value:s})}return i}function ve(e){if(!e?.headers.length)return;let t={};for(let n of e.headers){if(n.source.kind!==`jwt-claim`)continue;let r=U(n.source.tokenSources?.length?n.source.tokenSources.map(t=>t===`access_token`?e.token:void 0):[e.token],n.source.claim,n.source.namespace);r&&(t[n.header]=r)}return Object.keys(t).length>0?t:void 0}function ye(e){let{logger:t,diagnosticLabel:n,allowAuthHeaderOverride:r}=e,i=[{label:`protocolDefaults`,entries:W(e.protocolDefaults,`protocolDefaults`,t,n)},{label:`staticHeaders`,entries:W(e.staticHeaders,`staticHeaders`,t,n)},{label:`tokenDerived`,entries:W(ve(e.tokenDerived),`tokenDerived`,t,n)},{label:`customized`,entries:W(e.customized,`customized`,t,n)}],a=new Set([`staticHeaders`,`tokenDerived`,`customized`]),o=new Map;for(let{label:e,entries:s}of i)for(let[i,c]of s){if(!r&&a.has(e)&&he.has(i)){t?.warn({provider:n,source:e,header:c.name},`dropped attempt to override auth header (declare allowAuthHeaderOverride to permit)`);continue}let s=o.get(i);s&&e===`customized`&&s.value!==c.value&&t?.debug({provider:n,header:c.name},`customizeRequest overrode a previously declared request header`),o.set(i,c)}for(let[i,a]of W(e.auth,`auth`,t,n)){if(r&&o.has(i)){t?.debug({provider:n,header:a.name},`provider-declared auth header kept (allowAuthHeaderOverride); otto-resolved credential not applied`);continue}o.set(i,a)}let s={};for(let{name:e,value:t}of o.values())s[e]=t;return s}const G=i(`@x-otto/provider:oauth:templates`);function K(e,t){return new Promise((r,i)=>{if(t?.aborted){i(new n(`Login cancelled`,{code:`OAUTH_CANCELLED`}));return}let a=setTimeout(r,e);t?.addEventListener(`abort`,()=>{clearTimeout(a),i(new n(`Login cancelled`,{code:`OAUTH_CANCELLED`}))},{once:!0})})}function q(e){if(e?.aborted)throw new n(`Login cancelled`,{code:`OAUTH_CANCELLED`})}function J(e){let t=e.trim(),n=t.indexOf(`#`);return{code:n>=0?t.slice(0,n):t,returnedState:n>=0?t.slice(n+1):void 0}}function be(e){let{id:r,name:i,clientId:a,authorizeUrl:s,tokenUrl:c,redirectUri:l,scope:u,loopbackPorts:d,callbackPath:p=t,assumesLoopbackAlways:m=!1,extraAuthParams:h,tokenExchangeEncoding:g=`form`,subscriptionScoped:_=!1,oauthBeta:v}=e,y=!m&&Array.isArray(d)&&d.length>0;async function b(e){return J(await e.onManualCode())}async function x(e){let t=await e.waitForCallback();return{code:t.code,returnedState:t.state}}async function S(e,t){let n=new AbortController,r=t.waitForCallback().then(e=>({code:e.code,returnedState:e.state})),i=e.onManualCode?e.onManualCode(n.signal).then(J):new Promise(()=>{});r.catch(()=>{}),i.catch(()=>{});try{return await Promise.race([r,i.then(t=>t.code?t:(e.onProgress?.(`Waiting for browser authorization…`),r))])}finally{n.abort()}}async function C(e,t){if(!t){if(m)throw new n(`${i}: loopback required but all ports are unavailable. Configured ports: ${(d??[]).join(`, `)||`none`}.`,{code:`OAUTH_LOOPBACK_FAILED`});return b(e)}return m?x(t):S(e,t)}function w(e,t,n){let r=new URL(s);if(r.searchParams.set(`client_id`,a),r.searchParams.set(`response_type`,`code`),r.searchParams.set(`redirect_uri`,e),r.searchParams.set(`scope`,u),r.searchParams.set(`code_challenge`,t),r.searchParams.set(`code_challenge_method`,`S256`),r.searchParams.set(`state`,n),h)for(let[e,t]of Object.entries(h))r.searchParams.set(e,t);return r.toString().replace(/\+/g,`%20`)}async function T(e,t){let r=g===`json`,a={Accept:`application/json`},o;r?(a[`Content-Type`]=`application/json`,o=JSON.stringify(e)):(a[`Content-Type`]=`application/x-www-form-urlencoded`,o=new URLSearchParams(e).toString());let s;try{s=await fetch(c,{method:`POST`,headers:a,body:o})}catch(e){let t=e.cause;throw new n(`${i} token endpoint unreachable (${t?.code??t?.message??e.message}) — ${c}`,{code:`OAUTH_TOKEN_NETWORK`,cause:e})}let l;try{l=await s.json()}catch(e){throw new n(`${i} token endpoint returned non-JSON response (HTTP ${s.status})`,{code:`OAUTH_TOKEN_FAILED`,cause:e})}if(!l.access_token)throw new n(`${i} token exchange failed: ${l.error_description||l.error||`HTTP ${s.status}`}`,{code:`OAUTH_TOKEN_FAILED`,status:s.status,errorType:l.error});return{access:l.access_token,refresh:l.refresh_token??t??``,expires:Date.now()+(l.expires_in??0)*1e3}}return{id:r,name:i,usesCallbackServer:!1,oauthBeta:v,subscriptionScoped:_,async login(e){if(!y&&!m&&!e.onManualCode)throw new n(`${i} OAuth requires an onManualCode callback to paste the code.`,{code:`OAUTH_MANUAL_CODE_REQUIRED`});q(e.signal);let{verifier:t,challenge:r}=o(),s=t,c;if(Array.isArray(d)&&d.length>0)try{c=await f({ports:d,callbackPath:p,expectedState:s,signal:e.signal})}catch(e){if(G.info(`${i}: loopback ports [${d.join(`,`)}] unavailable; `+(m?``:`falling back to manual paste.`)+` (${e.message})`),m)throw new n(`${i}: loopback required but all ports [${d.join(`,`)}] are unavailable.`,{code:`OAUTH_LOOPBACK_FAILED`})}let u=c?`http://localhost:${c.port}${p}`:l;try{let o=w(u,r,s);e.onAuth({url:o,instructions:c?`Open the URL and authorize; login completes automatically. If it does not, paste the code shown (format: code#state).`:`Open the URL, authorize, then paste the code shown (format: code#state).`});let{code:l,returnedState:d}=await C(e,c);if(q(e.signal),!l)throw new n(`Empty authorization code.`,{code:`OAUTH_AUTHORIZE_FAILED`});if(d!==void 0&&d!==s)throw new n(`OAuth state mismatch (possible CSRF).`,{code:`OAUTH_STATE_MISMATCH`});d===void 0&&G.warn(`Authorization code returned without state; skipping CSRF state check.`);let f=await T({grant_type:`authorization_code`,code:l,state:d??s,client_id:a,redirect_uri:u,code_verifier:t});return G.info(`${i} OAuth login completed`),f}finally{await c?.close()}},async refreshToken(e){return T({grant_type:`refresh_token`,refresh_token:e.refresh,client_id:a},e.refresh)},getAccessKey(e){return e.access}}}function xe(e){let{id:t,name:r,clientId:i,deviceCodeUrlTemplate:a,tokenUrlTemplate:o,refreshUrlTemplate:s,scope:c,allowCustomDomain:l=!1,userAgent:u}=e,d={Accept:`application/json`};u&&(d[`User-Agent`]=u);async function f(e,t,r){let i=await e.text();if(!e.ok)throw new n(`${r} failed: HTTP ${e.status}${i?`: ${i.slice(0,200)}`:``}`,{code:t,status:e.status});try{return JSON.parse(i)}catch{throw new n(`${r} returned a non-JSON response.`,{code:t})}}function p(e,t){return e.replace(/\{domain\}/g,t)}async function m(e,t,a,s,c){let l=Date.now()+s*1e3;for(;Date.now()<l;){if(c?.aborted)throw new n(`Login cancelled`,{code:`OAUTH_CANCELLED`});let s=p(o,e),u=await f(await fetch(s,{method:`POST`,headers:{...d,"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({client_id:i,device_code:t,grant_type:`urn:ietf:params:oauth:grant-type:device_code`})}),`OAUTH_AUTHORIZE_FAILED`,`${r} access token exchange`);if(u.error){if(u.error===`authorization_pending`){await K(Math.max(1e3,Math.min(Math.floor(a*1e3),l-Date.now())),c);continue}if(u.error===`slow_down`){a+=5,await K(Math.max(1e3,Math.min(Math.floor(a*1e3),l-Date.now())),c);continue}throw new n(`Authorize failed: ${u.error}${u.error_description?`: ${u.error_description}`:``}`,{code:`OAUTH_AUTHORIZE_FAILED`})}if(u.access_token)return u.access_token}throw new n(`Timed out while waiting for ${r} device authorization.`,{code:`OAUTH_AUTHORIZE_TIMEOUT`})}async function h(e,t){if(!s)throw new n(`${r} device-flow OAuth requires refreshUrlTemplate to be declared.`,{code:`OAUTH_REFRESH_URL_MISSING`});let i=p(s,t),a=await f(await fetch(i,{headers:{...d,Authorization:`Bearer ${e}`}}),`OAUTH_REFRESH_FAILED`,`${r} token refresh`),o=a.token??a.access_token;if(!o)throw new n(`${r}: invalid token response fields.`,{code:`OAUTH_REFRESH_FAILED`});return{access:o,expires:(a.expires_at??Math.floor(Date.now()/1e3)+3600)*1e3}}return{id:t,name:r,async login(e){let t=`github.com`;if(l){let i=await e.onPrompt({message:`${r} URL/domain (blank for default)`,placeholder:`company.ghe.com`,allowEmpty:!0});if(e.signal?.aborted)throw new n(`Login cancelled`,{code:`OAUTH_CANCELLED`});let a=i.trim()||`github.com`;t=a.startsWith(`http://`)||a.startsWith(`https://`)?new URL(a).hostname:a}let o=p(a,t),s=await f(await fetch(o,{method:`POST`,headers:{...d,"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({client_id:i,scope:c})}),`OAUTH_AUTHORIZE_FAILED`,`${r} device authorization`);if(!s.device_code)throw new n(`${r} device authorization returned invalid response fields.`,{code:`OAUTH_AUTHORIZE_FAILED`});await e.onAuth({url:s.verification_uri,code:s.user_code,instructions:`Enter code: ${s.user_code}`});let u=await m(t,s.device_code,s.interval,s.expires_in,e.signal),{access:g,expires:_}=await h(u,t),v={access:g,refresh:u,expires:_};return l&&t!==`github.com`&&(v.domain=t),await e.onProgress?.(`...`),G.info(`${r} OAuth login completed`),v},async refreshToken(e){let t=e.domain??`github.com`,{access:n,expires:r}=await h(e.refresh,t);return{access:n,refresh:e.refresh,expires:r,...t===`github.com`?{}:{domain:t}}},getAccessKey(e){return e.access}}}function Y(e,t){let n=e;for(let e=0;e<3&&n!=null;e++){let e=t(n);if(e!==void 0)return e;n=n.cause}}function X(e){return Y(e,e=>{if(typeof e.status==`number`)return e.status;if(typeof e.statusCode==`number`)return e.statusCode})}function Z(e){let t=[],n=e;for(let e=0;e<3&&n!=null;e++){let e=n.message;typeof e==`string`&&t.push(e),n=n.cause}return t.join(` ← `).toLowerCase()}const Se=[/prompt is too long/i,/context[\s_-]{0,3}(?:length|window|limit)/i,/context_length_exceeded/i,/maximum[\s_-]{0,3}context/i,/too many (?:input )?tokens/i,/exceeds? the maximum/i,/reduce the length/i,/input is too large/i,/request too large/i];function Ce(e){if(e==null)return!1;if(X(e)===413)return!0;let t=Z(e);return t?!!Se.some(e=>e.test(t)):!1}const we=[/econnreset/i,/econnrefused/i,/etimedout/i,/timed? ?out/i,/enotfound/i,/eai_again/i,/socket hang ?up/i,/network/i,/fetch failed/i,/stream (?:ended|closed|disconnected|interrupted)/i,/premature close/i,/connection (?:closed|reset|error)/i,/overloaded/i,/\bterminated\b/i,/other side closed/i],Te=new Set([`PROVIDER_INCOMPLETE_STREAM`,`PROVIDER_STREAM_ERROR`]),Ee=[/rate_limit_error/i,/overloaded_error/i,/throttling/i,/flow[\s_-]?control/i,/流量控制/,/限流/,/请求过于频繁/];function De(e){return Y(e,e=>{let t=e.headers;return t===void 0?void 0:t})}function Oe(e){let t=De(e);if(!t)return null;let n=u(t,`anthropic-ratelimit-unified-status`);if(n!==`rejected`&&n!==`allowed_warning`)return null;let r=u(t,`anthropic-ratelimit-unified-representative-claim`),i=u(t,`anthropic-ratelimit-unified-reset`);return{status:n,type:r,resetsAt:i?Number(i):void 0}}function Q(e){return Y(e,e=>typeof e.code==`string`?e.code:void 0)}function ke(e){return Y(e,e=>{let t=e.abortKind;if(t===`idle`||t===`wallclock`||t===`external`)return t})}const Ae=[/many-image requests/i,/image dimensions exceed/i,/image exceeds \d+\s*(?:mb|bytes)/i];function je(e){if(e==null||X(e)!==void 0||ke(e)!==void 0)return!1;let t=Z(e);if(t&&Ee.some(e=>e.test(t)))return!1;let n=Q(e);return n&&Te.has(n)?!0:!!t&&we.some(e=>e.test(t))}function Me(e){if(e==null)return!1;let t=Q(e);return t===`PROVIDER_AUTH_MISSING`||t===`PROVIDER_AUTH_REFRESH_FAILED`?!0:X(e)===401}function Ne(e){let t=Q(e);return t===`PROVIDER_AUTH_MISSING`?`credential-missing`:t===`PROVIDER_AUTH_REFRESH_FAILED`?`refresh-failed`:`server-rejected`}function Pe(e){if(e==null)return`fatal`;let t=X(e);if(t===400){let t=Z(e);if(Ae.some(e=>e.test(t)))return`image-constraint`}if(Ce(e))return`context-overflow`;if(Oe(e)?.status===`rejected`)return`fatal`;if(t===429||t!==void 0&&t>=500&&t<=599)return`retryable`;let n=Z(e);if(t===void 0&&n&&Ee.some(e=>e.test(n)))return`retryable`;if(t!==void 0&&t>=400&&t<500)return`fatal`;let r=Q(e);return r&&Te.has(r)||n&&we.some(e=>e.test(n))?`retryable`:`fatal`}const Fe=new Set([`invalid_request_error`,`invalid_api_key`,`authentication_error`,`permission_error`,`permission_denied`,`insufficient_quota`]);function Ie(e){if(Pe(e)!==`fatal`)return!1;let t=X(e);return t!==void 0&&t>=400&&t<500||Me(e)?!0:Y(e,e=>typeof e.errorType==`string`&&Fe.has(e.errorType)?!0:void 0)===!0}function Le(e){return Y(e,e=>Re(e.headers))}function Re(e){let t=u(e,`retry-after-ms`);if(t!==void 0){let e=Number(t);if(Number.isFinite(e)&&e>=0)return e}let n=u(e,`retry-after`);if(n!==void 0){let e=Number(n);if(Number.isFinite(e)&&e>=0)return e*1e3}}function ze(e){return _(e,`recordings`)}async function*Be(e,t,n){h(_(n,`..`),{recursive:!0,mode:448});let r=m(n,{flags:`w`,mode:384}),i={version:1,modelId:t.id,api:String(t.api),recordedAt:new Date().toISOString(),contextWindow:t.contextWindow};r.write(JSON.stringify(i)+`
8
8
  `);let a;try{for await(let t of e){let e=Date.now();a===void 0&&(a=e);let n={t:e-a,e:t};r.write(JSON.stringify(n)+`
9
9
  `),yield t}}finally{await new Promise(e=>r.end(()=>e()))}}async function Ve(e){let t=(await g(e,`utf-8`)).split(`
10
- `).filter(e=>e.trim().length>0),n=t[0];if(n===void 0)throw Error(`录制文件为空: ${e}`);let r=JSON.parse(n);if(r.version!==1)throw Error(`不支持的录制版本 ${r.version}(本实现支持 1)`);let i=t.slice(1).map(e=>JSON.parse(e));if(i.length===0)throw Error(`录制文件无事件: ${e}`);return{header:r,events:i}}async function*He(e,t={},n){let r=Date.now();for(let i of e.events){if(n?.aborted)throw Error(`Replay aborted`);if(!t.fast&&i.t>0){let e=i.t-(Date.now()-r);e>0&&await new Promise(t=>setTimeout(t,e))}yield i.e}}const $=`replay`;function Ue(e){return{id:`replay/${e.header.modelId}`,name:`Replay of ${e.header.modelId}`,api:$,provider:`replay`,contextWindow:e.header.contextWindow}}var We=class{id=$;displayName=`Replay Provider (RFC-200)`;recording;constructor(e,t={}){this.filePath=e,this.options=t}async preload(){return this.recording??=await Ve(this.filePath),this.recording}async*converse(e,t,n,r){yield*He(await this.preload(),this.options,n.signal??r)}};function Ge(e,t={}){return()=>new We(e,t)}export{xe as DeviceFlowOAuthTemplate,v as MAX_PLUGIN_RETRIES,be as PKCEOAuthTemplate,$ as REPLAY_API,We as ReplayProviderStream,V as assembleAssistantMessage,ee as assertSystemNotificationPlacement,fe as blocksContent,ae as buildChatCompletionsBody,re as buildChatCompletionsMessages,Ue as buildReplayModel,ye as buildRequestHeaders,k as clampThinkingLevel,Ne as classifyAuthErrorType,Pe as classifyStreamError,a as createPkcePair,Ge as createReplayProviderFactory,w as degradedSystemNotificationText,ke as extractAbortKind,Oe as extractAnthropicRateLimit,Q as extractCode,U as extractJwtClaim,Le as extractRetryAfterMs,M as extractStandardRateLimitHeaders,X as extractStatus,B as flatContent,s as generateChallenge,c as generateState,l as generateVerifier,de as hasTrailingInvokeXml,z as initFlatStreamState,N as initStreamUsage,Me as isAuthError,Ce as isContextOverflowError,je as isNetworkDisconnectError,Ie as isNonRetryableStreamError,Ve as loadRecording,H as mapChatFinishReason,T as mergeConsecutiveSystemNotifications,y as noopWireProtocolLogger,ce as parseToolArguments,P as parseToolArgumentsWithStatus,Be as recordStream,ze as recordingsDir,I as recoverLiteralInvokeToolCalls,le as registeredToolNames,He as replayStream,b as resolveProviderBaseUrl,E as sanitizeSurrogates,S as sanitizeToolRoundtrips,d as startLoopbackServer,me as streamChatCompletions,D as toJsonSchema,F as toolCallFromParsed};
10
+ `).filter(e=>e.trim().length>0),n=t[0];if(n===void 0)throw Error(`录制文件为空: ${e}`);let r=JSON.parse(n);if(r.version!==1)throw Error(`不支持的录制版本 ${r.version}(本实现支持 1)`);let i=t.slice(1).map(e=>JSON.parse(e));if(i.length===0)throw Error(`录制文件无事件: ${e}`);return{header:r,events:i}}async function*He(e,t={},n){let r=Date.now();for(let i of e.events){if(n?.aborted)throw Error(`Replay aborted`);if(!t.fast&&i.t>0){let e=i.t-(Date.now()-r);e>0&&await new Promise(t=>setTimeout(t,e))}yield i.e}}const $=`replay`;function Ue(e){return{id:`replay/${e.header.modelId}`,name:`Replay of ${e.header.modelId}`,api:$,provider:`replay`,contextWindow:e.header.contextWindow}}var We=class{id=$;displayName=`Replay Provider (RFC-200)`;recording;constructor(e,t={}){this.filePath=e,this.options=t}async preload(){return this.recording??=await Ve(this.filePath),this.recording}async*converse(e,t,n,r){yield*He(await this.preload(),this.options,n.signal??r)}};function Ge(e,t={}){return()=>new We(e,t)}export{xe as DeviceFlowOAuthTemplate,v as MAX_PLUGIN_RETRIES,be as PKCEOAuthTemplate,$ as REPLAY_API,We as ReplayProviderStream,V as assembleAssistantMessage,ee as assertSystemNotificationPlacement,fe as blocksContent,ae as buildChatCompletionsBody,re as buildChatCompletionsMessages,Ue as buildReplayModel,ye as buildRequestHeaders,k as clampThinkingLevel,Ne as classifyAuthErrorType,Pe as classifyStreamError,a as createPkcePair,Ge as createReplayProviderFactory,w as degradedSystemNotificationText,ke as extractAbortKind,Oe as extractAnthropicRateLimit,Q as extractCode,U as extractJwtClaim,Le as extractRetryAfterMs,M as extractStandardRateLimitHeaders,X as extractStatus,B as flatContent,s as generateChallenge,c as generateState,l as generateVerifier,de as hasTrailingInvokeXml,z as initFlatStreamState,N as initStreamUsage,Me as isAuthError,Ce as isContextOverflowError,je as isNetworkDisconnectError,Ie as isNonRetryableStreamError,Ve as loadRecording,H as mapChatFinishReason,T as mergeConsecutiveSystemNotifications,y as noopWireProtocolLogger,ce as parseToolArguments,P as parseToolArgumentsWithStatus,Be as recordStream,ze as recordingsDir,I as recoverLiteralInvokeToolCalls,le as registeredToolNames,He as replayStream,b as resolveProviderBaseUrl,E as sanitizeSurrogates,S as sanitizeToolRoundtrips,d as startLoopbackServer,me as streamChatCompletions,D as toJsonSchema,F as toolCallFromParsed};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x-otto/provider",
3
- "version": "0.1.0-alpha.39",
3
+ "version": "0.1.0-alpha.40",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -19,11 +19,11 @@
19
19
  "tag": "alpha"
20
20
  },
21
21
  "dependencies": {
22
- "@x-otto/interchange": "0.1.0-alpha.39",
23
- "@x-otto/shared": "0.1.0-alpha.39"
22
+ "@x-otto/interchange": "0.1.0-alpha.40",
23
+ "@x-otto/shared": "0.1.0-alpha.40"
24
24
  },
25
25
  "scripts": {
26
- "build": "tsdown && rm -f dist/*.map && sed -i '' '\\|//# sourceMappingURL=|d' dist/*.js 2>/dev/null; true",
26
+ "build": "tsdown",
27
27
  "typecheck:project": "tsc -p tsconfig.json --noEmit",
28
28
  "typecheck:file": "tsc src/index.ts --noEmit --target ES2024 --module ESNext --moduleResolution bundler --esModuleInterop --skipLibCheck",
29
29
  "typecheck": "tsc --noEmit",