@life-ai-tools/claude-code-sdk 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/auth.d.ts +31 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
Use your **Claude Max/Pro subscription** programmatically — no API key needed.
|
|
4
4
|
|
|
5
5
|
This toolkit provides:
|
|
6
|
-
- **`@
|
|
7
|
-
- **`@
|
|
6
|
+
- **`@life-ai-tools/claude-code-sdk`** — TypeScript SDK for the Claude Code API (streaming, tool use, conversation management)
|
|
7
|
+
- **`@life-ai-tools/opencode-proxy`** — OpenAI-compatible proxy server that lets you use Claude Max/Pro in [opencode](https://github.com/opencode-ai/opencode), Cursor, or any OpenAI-compatible client
|
|
8
8
|
|
|
9
9
|
> **Why this exists?** Read our [Open Letter to Anthropic](OPEN-LETTER.md) about token efficiency, developer freedom, and collaboration.
|
|
10
10
|
|
|
@@ -49,7 +49,7 @@ Before you start, make sure you have:
|
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
51
|
# Start proxy and launch opencode in one go
|
|
52
|
-
bunx @
|
|
52
|
+
bunx @life-ai-tools/opencode-proxy &
|
|
53
53
|
LOCAL_ENDPOINT=http://localhost:4040/v1 opencode
|
|
54
54
|
```
|
|
55
55
|
|
|
@@ -57,7 +57,7 @@ Or step by step:
|
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
59
|
# Terminal 1: Start the proxy
|
|
60
|
-
bunx @
|
|
60
|
+
bunx @life-ai-tools/opencode-proxy --port 4040
|
|
61
61
|
|
|
62
62
|
# Terminal 2: Launch opencode pointing to the proxy
|
|
63
63
|
LOCAL_ENDPOINT=http://localhost:4040/v1 opencode
|
|
@@ -106,7 +106,7 @@ export LOCAL_ENDPOINT=http://localhost:4040/v1
|
|
|
106
106
|
## SDK Usage
|
|
107
107
|
|
|
108
108
|
```typescript
|
|
109
|
-
import { ClaudeCodeSDK } from '@
|
|
109
|
+
import { ClaudeCodeSDK } from '@life-ai-tools/claude-code-sdk'
|
|
110
110
|
|
|
111
111
|
const sdk = new ClaudeCodeSDK()
|
|
112
112
|
|
|
@@ -130,7 +130,7 @@ for await (const event of sdk.stream({
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
// Multi-turn conversation
|
|
133
|
-
import { Conversation } from '@
|
|
133
|
+
import { Conversation } from '@life-ai-tools/claude-code-sdk'
|
|
134
134
|
|
|
135
135
|
const conv = new Conversation(sdk, { model: 'claude-sonnet-4-6-20250415' })
|
|
136
136
|
const reply1 = await conv.send('What is TypeScript?')
|
|
@@ -182,7 +182,7 @@ If opencode shows a timeout while waiting for a response (especially with Opus):
|
|
|
182
182
|
lsof -i :4040
|
|
183
183
|
|
|
184
184
|
# Use a different port
|
|
185
|
-
bunx @
|
|
185
|
+
bunx @life-ai-tools/opencode-proxy --port 4041
|
|
186
186
|
```
|
|
187
187
|
|
|
188
188
|
### "Token expired" / 401 errors
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth 2.0 Authorization Code + PKCE flow for Claude.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Claude Code CLI OAuth implementation:
|
|
5
|
+
* - Generates PKCE code_verifier + challenge (S256)
|
|
6
|
+
* - Opens browser to Anthropic's auth page
|
|
7
|
+
* - Listens on localhost for callback with auth code
|
|
8
|
+
* - Exchanges code for access/refresh tokens
|
|
9
|
+
* - Saves credentials to .credentials.json
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* const creds = await oauthLogin({ credentialsPath: '~/.claude/.credentials.json' })
|
|
13
|
+
*/
|
|
14
|
+
export interface OAuthLoginOptions {
|
|
15
|
+
/** Where to save credentials. Default: ~/.claude/.credentials.json */
|
|
16
|
+
credentialsPath?: string;
|
|
17
|
+
/** Port for localhost callback. Default: 0 (OS-assigned) */
|
|
18
|
+
port?: number;
|
|
19
|
+
/** Callback when the auth URL is ready — display to user. If not provided, prints to stdout. */
|
|
20
|
+
onAuthUrl?: (url: string, manualUrl: string) => void;
|
|
21
|
+
/** Try to open browser automatically. Default: true */
|
|
22
|
+
openBrowser?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface OAuthResult {
|
|
25
|
+
accessToken: string;
|
|
26
|
+
refreshToken: string;
|
|
27
|
+
expiresAt: number;
|
|
28
|
+
credentialsPath: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function oauthLogin(options?: OAuthLoginOptions): Promise<OAuthResult>;
|
|
31
|
+
//# sourceMappingURL=auth.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -4,4 +4,6 @@ export { saveSession, loadSession } from './session.js';
|
|
|
4
4
|
export type { ClaudeCodeSDKOptions, GenerateOptions, GenerateResponse, StreamEvent, TokenUsage, RateLimitInfo, CredentialsFile, MessageParam, ContentBlockParam, TextBlockParam, ToolDef, ToolChoice, SystemParam, ContentBlock, TextBlock, ThinkingBlock, ToolUseBlock, ConversationOptions, TurnOptions, CredentialStore, StoredCredentials, } from './types.js';
|
|
5
5
|
export { ClaudeCodeSDKError, AuthError, APIError, RateLimitError, } from './types.js';
|
|
6
6
|
export type { SessionEntry } from './session.js';
|
|
7
|
+
export { oauthLogin } from './auth.js';
|
|
8
|
+
export type { OAuthLoginOptions, OAuthResult } from './auth.js';
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* (c) 2026 Kiberos. Compiled distribution.
|
|
4
4
|
* Source access: see REQUEST-SOURCE.md in the GitHub repo.
|
|
5
5
|
*/
|
|
6
|
-
var t=Object.defineProperty,e=(e,s)=>t(e,"name",{value:s,configurable:!0});import{createHash as s,randomBytes as i,randomUUID as r}from"crypto";import{readFileSync as n,writeFileSync as o,chmodSync as a,mkdirSync as l,statSync as h}from"fs";import{join as u}from"path";import{homedir as c}from"os";var d=class extends Error{constructor(t,e){super(t),this.cause=e,this.name="ClaudeCodeSDKError"}static{e(this,"ClaudeCodeSDKError")}},p=class extends d{static{e(this,"AuthError")}constructor(t,e){super(t,e),this.name="AuthError"}},f=class extends d{constructor(t,e,s,i){super(t,i),this.status=e,this.requestId=s,this.name="APIError"}static{e(this,"APIError")}},y=class extends d{constructor(t,e,s=429,i){super(t,i),this.rateLimitInfo=e,this.status=s,this.name="RateLimitError"}static{e(this,"RateLimitError")}},m=3e5,_=class{static{e(this,"ClaudeCodeSDK")}accessToken=null;refreshToken=null;expiresAt=null;credentialStore;sessionId;deviceId;accountUuid;version;timeout;maxRetries;lastRateLimitInfo={status:null,resetAt:null,claim:null,retryAfter:null};pending401=null;lastFailedToken=null;constructor(t={}){this.sessionId=r(),this.deviceId=t.deviceId??i(32).toString("hex"),this.accountUuid=t.accountUuid??this.readAccountUuid(),this.version=t.version??"0.1.0",this.timeout=t.timeout??6e5,this.maxRetries=t.maxRetries??3,t.credentialStore?this.credentialStore=t.credentialStore:t.accessToken?(this.accessToken=t.accessToken,this.refreshToken=t.refreshToken??null,this.expiresAt=t.expiresAt??null,this.credentialStore=new w({accessToken:t.accessToken,refreshToken:t.refreshToken??"",expiresAt:t.expiresAt??0})):this.credentialStore=new k(t.credentialsPath??u(c(),".claude",".credentials.json"))}async generate(t){let e=[];for await(let s of this.stream(t))e.push(s);return this.assembleResponse(e,t.model)}async*stream(t){await this.ensureAuth();let e,s=this.buildRequestBody(t),i=this.buildHeaders(t);for(let r=1;r<=this.maxRetries+1;r++){if(t.signal?.aborted)throw new d("Aborted");try{return void(yield*this.doStreamRequest(s,i,t.signal))}catch(s){if(e=s,s instanceof f){if(401===s.status&&r<=this.maxRetries){await this.handleAuth401(),i.Authorization=`Bearer ${this.accessToken}`;continue}if(429===s.status)throw s instanceof y?s:new y("Rate limited",this.lastRateLimitInfo,429,s);if(s.status>=500&&r<=this.maxRetries){let e=this.getRetryDelay(r,this.lastRateLimitInfo.retryAfter?.toString()??null);await this.sleep(e,t.signal);continue}}throw s}}throw e}getRateLimitInfo(){return this.lastRateLimitInfo}async*doStreamRequest(t,e,s){let i,r=new AbortController,n=setTimeout(()=>r.abort(),this.timeout);s&&s.addEventListener("abort",()=>r.abort(),{once:!0});try{i=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:e,body:JSON.stringify(t),signal:r.signal})}catch(t){throw clearTimeout(n),new d("Network error",t)}if(clearTimeout(n),this.lastRateLimitInfo=this.parseRateLimitHeaders(i.headers),!i.ok){let t="";try{t=await i.text()}catch{}let e=i.headers.get("request-id");throw 429===i.status?new y(`Rate limited: ${t}`,this.lastRateLimitInfo,429):new f(`API error ${i.status}: ${t}`,i.status,e)}if(!i.body)throw new d("No response body");yield*this.parseSSE(i.body,s)}async*parseSSE(t,e){let s=new TextDecoder,i=t.getReader(),r="",n=new Map,o={inputTokens:0,outputTokens:0},a=null;try{for(;;){if(e?.aborted)return void i.cancel();let{done:t,value:l}=await i.read();if(t)break;r+=s.decode(l,{stream:!0});let h=r.split("\n");r=h.pop()??"";for(let t of h){if(!t.startsWith("data: "))continue;let e,s=t.slice(6);if("[DONE]"===s)continue;try{e=JSON.parse(s)}catch{continue}let i=e.type;if("message_start"===i){let t=e.message?.usage;t&&(o={inputTokens:t.input_tokens??0,outputTokens:t.output_tokens??0,cacheCreationInputTokens:t.cache_creation_input_tokens,cacheReadInputTokens:t.cache_read_input_tokens});continue}if("content_block_start"===i){let t=e.index,s=e.content_block;"tool_use"===s.type?(n.set(t,{type:"tool_use",id:s.id,name:s.name,input:""}),yield{type:"tool_use_start",id:s.id,name:s.name}):"text"===s.type?n.set(t,{type:"text",text:""}):"thinking"===s.type&&n.set(t,{type:"thinking",thinking:""});continue}if("content_block_delta"===i){let t=e.index,s=n.get(t),i=e.delta;"text_delta"===i.type&&void 0!==i.text?(s&&(s.text=(s.text??"")+i.text),i.text&&(yield{type:"text_delta",text:i.text})):"thinking_delta"===i.type&&void 0!==i.thinking?(s&&(s.thinking=(s.thinking??"")+i.thinking),i.thinking&&(yield{type:"thinking_delta",text:i.thinking})):"input_json_delta"===i.type&&void 0!==i.partial_json&&(s&&(s.input=(s.input??"")+i.partial_json),i.partial_json&&(yield{type:"tool_use_delta",partialInput:i.partial_json}));continue}if("content_block_stop"===i){let t=e.index,s=n.get(t);if("tool_use"===s?.type&&s.id&&s.name){let t={};try{t=JSON.parse(s.input??"{}")}catch{}yield{type:"tool_use_end",id:s.id,name:s.name,input:t}}continue}if("message_delta"===i){let t=e.delta;t?.stop_reason&&(a=t.stop_reason);let s=e.usage;s?.output_tokens&&(o={...o,outputTokens:s.output_tokens});continue}"message_stop"===i&&(yield{type:"message_stop",usage:o,stopReason:a})}}}finally{i.releaseLock()}}buildHeaders(t){let e=this.buildBetas(t);return{"Content-Type":"application/json",Authorization:`Bearer ${this.accessToken}`,"anthropic-version":"2023-06-01","anthropic-beta":e.join(","),"x-app":"cli","User-Agent":`claude-code/${this.version} (external, sdk)`,"X-Claude-Code-Session-Id":this.sessionId}}buildRequestBody(t){let e,s=this.computeFingerprint(t.messages),i=`x-anthropic-billing-header: cc_version=${this.version}.${s}; cc_entrypoint=cli;`;e="string"==typeof t.system?i+"\n"+t.system:Array.isArray(t.system)?[{type:"text",text:i},...t.system]:i;let r={model:t.model,messages:t.messages,max_tokens:t.maxTokens??16384,stream:!0,system:e,metadata:{user_id:JSON.stringify({device_id:this.deviceId,account_uuid:this.accountUuid,session_id:this.sessionId})}};t.tools&&t.tools.length>0&&(r.tools=t.tools,t.toolChoice&&(r.tool_choice="string"==typeof t.toolChoice?{type:t.toolChoice}:t.toolChoice)),!1!==t.caching&&this.addCacheMarkers(r);let n=t.model.toLowerCase(),o=n.includes("opus-4-6")||n.includes("sonnet-4-6"),a="disabled"===t.thinking?.type;return!a&&o?r.thinking={type:"adaptive"}:"enabled"===t.thinking?.type&&(r.thinking={type:"enabled",budget_tokens:t.thinking.budgetTokens}),!(!a&&(o||"enabled"===t.thinking?.type))&&void 0!==t.temperature&&(r.temperature=t.temperature),void 0!==t.topP&&(r.top_p=t.topP),t.effort&&o&&(r.output_config={effort:t.effort}),t.stopSequences?.length&&(r.stop_sequences=t.stopSequences),t.fast&&(r.speed="fast"),r}addCacheMarkers(t){let e=t.system;if("string"==typeof e)t.system=[{type:"text",text:e,cache_control:{type:"ephemeral"}}];else if(Array.isArray(e)){let t=e;t.length>0&&(t[t.length-1]={...t[t.length-1],cache_control:{type:"ephemeral"}})}let s=t.messages;if(0===s.length)return;let i=s[s.length-1];if("string"==typeof i.content)i.content=[{type:"text",text:i.content,cache_control:{type:"ephemeral"}}];else if(Array.isArray(i.content)&&i.content.length>0){let t=i.content[i.content.length-1];i.content[i.content.length-1]={...t,cache_control:{type:"ephemeral"}}}}buildBetas(t){let e=[],s=t.model.toLowerCase().includes("haiku");return s||e.push("claude-code-20250219"),e.push("oauth-2025-04-20"),/\[1m\]/i.test(t.model)&&e.push("context-1m-2025-08-07"),!s&&"disabled"!==t.thinking?.type&&e.push("interleaved-thinking-2025-05-14"),t.effort&&e.push("effort-2025-11-24"),t.fast&&e.push("fast-mode-2026-02-01"),e.push("prompt-caching-scope-2026-01-05"),t.extraBetas&&e.push(...t.extraBetas),e}async ensureAuth(){this.accessToken&&!this.isTokenExpired()||this.credentialStore.hasChanged&&await this.credentialStore.hasChanged()&&(await this.loadFromStore(),this.accessToken&&!this.isTokenExpired())||!this.accessToken&&(await this.loadFromStore(),this.accessToken&&!this.isTokenExpired())||this.accessToken&&this.isTokenExpired()&&await this.refreshTokenWithTripleCheck()}async loadFromStore(){let t=await this.credentialStore.read();if(!t?.accessToken)throw new p('No OAuth tokens found. Run "claude login" first or provide credentials.');this.accessToken=t.accessToken,this.refreshToken=t.refreshToken,this.expiresAt=t.expiresAt}isTokenExpired(){return!!this.expiresAt&&Date.now()+m>=this.expiresAt}async refreshTokenWithTripleCheck(){let t=await this.credentialStore.read();if(t&&!(Date.now()+m>=t.expiresAt))return this.accessToken=t.accessToken,this.refreshToken=t.refreshToken,void(this.expiresAt=t.expiresAt);await this.doTokenRefresh()}async handleAuth401(){let t=this.accessToken;this.pending401&&this.lastFailedToken===t||(this.lastFailedToken=t,this.pending401=(async()=>{let e=await this.credentialStore.read();return e&&e.accessToken!==t?(this.accessToken=e.accessToken,this.refreshToken=e.refreshToken,this.expiresAt=e.expiresAt,!0):(await this.doTokenRefresh(),!0)})().finally(()=>{this.pending401=null,this.lastFailedToken=null})),await this.pending401}async doTokenRefresh(){if(!this.refreshToken)throw new p("Token expired and no refresh token available.");let t=await fetch("https://platform.claude.com/v1/oauth/token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:this.refreshToken,client_id:"9d1c250a-e61b-44d9-88ed-5944d1962f5e"}),signal:AbortSignal.timeout(15e3)});if(!t.ok){let e=await this.credentialStore.read();if(e&&!(Date.now()+m>=e.expiresAt))return this.accessToken=e.accessToken,this.refreshToken=e.refreshToken,void(this.expiresAt=e.expiresAt);throw new p(`Token refresh failed: ${t.status} ${t.statusText}`)}let e=await t.json();this.accessToken=e.access_token,this.refreshToken=e.refresh_token??this.refreshToken,this.expiresAt=Date.now()+1e3*e.expires_in,await this.credentialStore.write({accessToken:this.accessToken,refreshToken:this.refreshToken,expiresAt:this.expiresAt})}computeFingerprint(t){let e=t.find(t=>"user"===t.role);if(!e)return this.hashFingerprint("000");let s="";"string"==typeof e.content?s=e.content:Array.isArray(e.content)&&(s=e.content.find(t=>"text"===t.type)?.text??"");let i=[4,7,20].map(t=>s[t]||"0").join("");return this.hashFingerprint(i)}hashFingerprint(t){let e=`59cf53e54c78${t}${this.version}`;return s("sha256").update(e).digest("hex").slice(0,3)}assembleResponse(t,e){let s=[],i=[],r=[],n={inputTokens:0,outputTokens:0},o=null,a="",l="";for(let e of t)switch(e.type){case"text_delta":a+=e.text;break;case"thinking_delta":l+=e.text;break;case"tool_use_end":r.push({type:"tool_use",id:e.id,name:e.name,input:e.input});break;case"message_stop":n=e.usage,o=e.stopReason;break;case"error":throw e.error}return a&&s.push({type:"text",text:a}),l&&i.push({type:"thinking",thinking:l}),s.push(...r),{content:s,thinking:i.length>0?i:void 0,toolCalls:r.length>0?r:void 0,usage:n,stopReason:o,rateLimitInfo:this.lastRateLimitInfo,model:e}}parseRateLimitHeaders(t){let e=t.get("retry-after"),s=t.get("anthropic-ratelimit-unified-reset"),i=s?Number(s):null;return{status:t.get("anthropic-ratelimit-unified-status"),resetAt:Number.isFinite(i)?i:null,claim:t.get("anthropic-ratelimit-unified-representative-claim"),retryAfter:e?parseFloat(e):null}}getRetryDelay(t,e){if(e){let t=parseInt(e,10);if(!isNaN(t))return 1e3*t}let s=Math.min(500*Math.pow(2,t-1),32e3);return s+.25*Math.random()*s}sleep(t,e){return new Promise((s,i)=>{if(e?.aborted)return void i(new d("Aborted"));let r=setTimeout(s,t);e?.addEventListener("abort",()=>{clearTimeout(r),i(new d("Aborted"))},{once:!0})})}readAccountUuid(){try{let t=u(c(),".claude","claude_code_config.json");return JSON.parse(n(t,"utf8")).oauthAccount?.accountUuid??""}catch{return""}}},k=class{constructor(t){this.path=t}static{e(this,"FileCredentialStore")}lastMtimeMs=0;async read(){try{let t=n(this.path,"utf8");return this.lastMtimeMs=this.getMtime(),JSON.parse(t).claudeAiOauth??null}catch{return null}}async write(t){let e={};try{e=JSON.parse(n(this.path,"utf8"))}catch{}e.claudeAiOauth=t;let s=u(this.path,"..");try{l(s,{recursive:!0})}catch{}o(this.path,JSON.stringify(e,null,2),"utf8"),a(this.path,384),this.lastMtimeMs=this.getMtime()}async hasChanged(){let t=this.getMtime();return t!==this.lastMtimeMs&&(this.lastMtimeMs=t,!0)}getMtime(){try{return h(this.path).mtimeMs}catch{return 0}}},w=class{static{e(this,"MemoryCredentialStore")}credentials;constructor(t){this.credentials={...t}}async read(){return this.credentials.accessToken?{...this.credentials}:null}async write(t){this.credentials={...t}}},g=class _Conversation{static{e(this,"Conversation")}sdk;options;t=[];i={inputTokens:0,outputTokens:0};constructor(t,e){this.sdk=t,this.options=e}get messages(){return this.t}get totalUsage(){return{...this.i}}get length(){return this.t.length}async send(t,e){this.appendUserMessage(t);let s=this.buildGenerateOptions(e),i=await this.sdk.generate(s);return this.appendAssistantFromResponse(i),this.accumulateUsage(i.usage),i}async*stream(t,e){this.appendUserMessage(t);let s=this.buildGenerateOptions(e),i=[],r=[],n=[],o={inputTokens:0,outputTokens:0};for await(let t of this.sdk.stream(s))switch(yield t,t.type){case"text_delta":i.push(t.text);break;case"thinking_delta":r.push(t.text);break;case"tool_use_end":n.push({type:"tool_use",id:t.id,name:t.name,input:t.input});break;case"message_stop":o=t.usage}let a=[];i.length>0&&a.push({type:"text",text:i.join("")});for(let t of n)a.push({type:"tool_use",id:t.id,name:t.name,input:t.input});a.length>0&&this.t.push({role:"assistant",content:a}),this.accumulateUsage(o)}addToolResult(t,e,s){let i={type:"tool_result",tool_use_id:t,content:e,...s&&{is_error:!0}};this.t.push({role:"user",content:[i]})}addToolResults(t){let e=t.map(t=>({type:"tool_result",tool_use_id:t.toolUseId,content:t.content,...t.isError&&{is_error:!0}}));this.t.push({role:"user",content:e})}async continue(t){let e=this.buildGenerateOptions(t),s=await this.sdk.generate(e);return this.appendAssistantFromResponse(s),this.accumulateUsage(s.usage),s}async*continueStream(t){let e=this.buildGenerateOptions(t),s=[],i=[],r={inputTokens:0,outputTokens:0};for await(let t of this.sdk.stream(e))switch(yield t,t.type){case"text_delta":s.push(t.text);break;case"tool_use_end":i.push({type:"tool_use",id:t.id,name:t.name,input:t.input});break;case"message_stop":r=t.usage}let n=[];s.length>0&&n.push({type:"text",text:s.join("")});for(let t of i)n.push({type:"tool_use",id:t.id,name:t.name,input:t.input});n.length>0&&this.t.push({role:"assistant",content:n}),this.accumulateUsage(r)}rewind(t){if(t<0||t>=this.t.length)throw new Error(`Invalid rewind index: ${t}`);return this.t.splice(t)}undoLastTurn(){for(let t=this.t.length-1;t>=0;t--){let e=this.t[t];if("user"===e.role){let s=e.content;if(!(Array.isArray(s)&&s.length>0&&"tool_result"===s[0].type))return this.rewind(t)}}return[]}branch(){let t=new _Conversation(this.sdk,{...this.options});return t.t=[...this.t],t.i={...this.i},t}getHistory(){return this.t.map((t,e)=>{let s="";if("string"==typeof t.content)s=t.content.slice(0,100);else if(Array.isArray(t.content)){let e=t.content[0];"text"===e?.type?s=e.text?.slice(0,100)??"":"tool_result"===e?.type?s=`[tool_result: ${e.tool_use_id}]`:"tool_use"===e?.type&&(s=`[tool_use: ${e.name}]`)}return{index:e,role:t.role,preview:s}})}appendUserMessage(t){this.t.push({role:"user",content:t})}appendAssistantFromResponse(t){let e=[];for(let s of t.content)"text"===s.type?e.push({type:"text",text:s.text}):"tool_use"===s.type&&e.push({type:"tool_use",id:s.id,name:s.name,input:s.input});e.length>0&&this.t.push({role:"assistant",content:e})}buildGenerateOptions(t){return{model:this.options.model,messages:[...this.t],system:this.options.system,tools:t?.tools??this.options.tools,toolChoice:t?.toolChoice??this.options.toolChoice,maxTokens:this.options.maxTokens,thinking:this.options.thinking,effort:this.options.effort,fast:this.options.fast,signal:t?.signal??this.options.signal,extraBetas:this.options.extraBetas,caching:this.options.caching}}accumulateUsage(t){this.i.inputTokens+=t.inputTokens,this.i.outputTokens+=t.outputTokens,this.i.cacheCreationInputTokens=(this.i.cacheCreationInputTokens??0)+(t.cacheCreationInputTokens??0),this.i.cacheReadInputTokens=(this.i.cacheReadInputTokens??0)+(t.cacheReadInputTokens??0)}};import{readFileSync as x,writeFileSync as b,mkdirSync as T}from"fs";import{dirname as v}from"path";import{randomUUID as S}from"crypto";function A(t,e){T(v(t),{recursive:!0});let s=null,i=[];for(let t of e){let e=S(),r={type:"user"===t.role?"user":"assistant",uuid:e,parentUuid:s,timestamp:Date.now(),content:t.content};i.push(JSON.stringify(r)),s=e}b(t,i.join("\n")+"\n","utf8")}function C(t){let e=x(t,"utf8"),s=[];for(let t of e.split("\n")){if(!t.trim())continue;let e;try{e=JSON.parse(t)}catch{continue}("user"===e.type||"assistant"===e.type)&&s.push({role:"user"===e.type?"user":"assistant",content:e.content})}return s}e(A,"saveSession"),e(C,"loadSession");export{f as APIError,p as AuthError,_ as ClaudeCodeSDK,d as ClaudeCodeSDKError,g as Conversation,k as FileCredentialStore,w as MemoryCredentialStore,y as RateLimitError,C as loadSession,A as saveSession};
|
|
6
|
+
var t=Object.defineProperty,e=(e,s)=>t(e,"name",{value:s,configurable:!0});import{createHash as s,randomBytes as i,randomUUID as r}from"crypto";import{readFileSync as n,writeFileSync as o,chmodSync as a,mkdirSync as l,statSync as h}from"fs";import{join as c}from"path";import{homedir as u}from"os";var d=class extends Error{constructor(t,e){super(t),this.cause=e,this.name="ClaudeCodeSDKError"}static{e(this,"ClaudeCodeSDKError")}},p=class extends d{static{e(this,"AuthError")}constructor(t,e){super(t,e),this.name="AuthError"}},f=class extends d{constructor(t,e,s,i){super(t,i),this.status=e,this.requestId=s,this.name="APIError"}static{e(this,"APIError")}},m=class extends d{constructor(t,e,s=429,i){super(t,i),this.rateLimitInfo=e,this.status=s,this.name="RateLimitError"}static{e(this,"RateLimitError")}},y=3e5,_=class{static{e(this,"ClaudeCodeSDK")}accessToken=null;refreshToken=null;expiresAt=null;credentialStore;sessionId;deviceId;accountUuid;version;timeout;maxRetries;lastRateLimitInfo={status:null,resetAt:null,claim:null,retryAfter:null};pending401=null;lastFailedToken=null;constructor(t={}){this.sessionId=r(),this.deviceId=t.deviceId??i(32).toString("hex"),this.accountUuid=t.accountUuid??this.readAccountUuid(),this.version=t.version??"0.1.0",this.timeout=t.timeout??6e5,this.maxRetries=t.maxRetries??3,t.credentialStore?this.credentialStore=t.credentialStore:t.accessToken?(this.accessToken=t.accessToken,this.refreshToken=t.refreshToken??null,this.expiresAt=t.expiresAt??null,this.credentialStore=new g({accessToken:t.accessToken,refreshToken:t.refreshToken??"",expiresAt:t.expiresAt??0})):this.credentialStore=new w(t.credentialsPath??c(u(),".claude",".credentials.json"))}async generate(t){let e=[];for await(let s of this.stream(t))e.push(s);return this.assembleResponse(e,t.model)}async*stream(t){await this.ensureAuth();let e,s=this.buildRequestBody(t),i=this.buildHeaders(t);for(let r=1;r<=this.maxRetries+1;r++){if(t.signal?.aborted)throw new d("Aborted");try{return void(yield*this.doStreamRequest(s,i,t.signal))}catch(s){if(e=s,s instanceof f){if(401===s.status&&r<=this.maxRetries){await this.handleAuth401(),i.Authorization=`Bearer ${this.accessToken}`;continue}if(429===s.status)throw s instanceof m?s:new m("Rate limited",this.lastRateLimitInfo,429,s);if(s.status>=500&&r<=this.maxRetries){let e=this.getRetryDelay(r,this.lastRateLimitInfo.retryAfter?.toString()??null);await this.sleep(e,t.signal);continue}}throw s}}throw e}getRateLimitInfo(){return this.lastRateLimitInfo}async*doStreamRequest(t,e,s){let i,r=new AbortController,n=setTimeout(()=>r.abort(),this.timeout);s&&s.addEventListener("abort",()=>r.abort(),{once:!0});try{i=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:e,body:JSON.stringify(t),signal:r.signal})}catch(t){throw clearTimeout(n),new d("Network error",t)}if(clearTimeout(n),this.lastRateLimitInfo=this.parseRateLimitHeaders(i.headers),!i.ok){let t="";try{t=await i.text()}catch{}let e=i.headers.get("request-id");throw 429===i.status?new m(`Rate limited: ${t}`,this.lastRateLimitInfo,429):new f(`API error ${i.status}: ${t}`,i.status,e)}if(!i.body)throw new d("No response body");yield*this.parseSSE(i.body,s)}async*parseSSE(t,e){let s=new TextDecoder,i=t.getReader(),r="",n=new Map,o={inputTokens:0,outputTokens:0},a=null;try{for(;;){if(e?.aborted)return void i.cancel();let{done:t,value:l}=await i.read();if(t)break;r+=s.decode(l,{stream:!0});let h=r.split("\n");r=h.pop()??"";for(let t of h){if(!t.startsWith("data: "))continue;let e,s=t.slice(6);if("[DONE]"===s)continue;try{e=JSON.parse(s)}catch{continue}let i=e.type;if("message_start"===i){let t=e.message?.usage;t&&(o={inputTokens:t.input_tokens??0,outputTokens:t.output_tokens??0,cacheCreationInputTokens:t.cache_creation_input_tokens,cacheReadInputTokens:t.cache_read_input_tokens});continue}if("content_block_start"===i){let t=e.index,s=e.content_block;"tool_use"===s.type?(n.set(t,{type:"tool_use",id:s.id,name:s.name,input:""}),yield{type:"tool_use_start",id:s.id,name:s.name}):"text"===s.type?n.set(t,{type:"text",text:""}):"thinking"===s.type&&n.set(t,{type:"thinking",thinking:""});continue}if("content_block_delta"===i){let t=e.index,s=n.get(t),i=e.delta;"text_delta"===i.type&&void 0!==i.text?(s&&(s.text=(s.text??"")+i.text),i.text&&(yield{type:"text_delta",text:i.text})):"thinking_delta"===i.type&&void 0!==i.thinking?(s&&(s.thinking=(s.thinking??"")+i.thinking),i.thinking&&(yield{type:"thinking_delta",text:i.thinking})):"input_json_delta"===i.type&&void 0!==i.partial_json&&(s&&(s.input=(s.input??"")+i.partial_json),i.partial_json&&(yield{type:"tool_use_delta",partialInput:i.partial_json}));continue}if("content_block_stop"===i){let t=e.index,s=n.get(t);if("tool_use"===s?.type&&s.id&&s.name){let t={};try{t=JSON.parse(s.input??"{}")}catch{}yield{type:"tool_use_end",id:s.id,name:s.name,input:t}}continue}if("message_delta"===i){let t=e.delta;t?.stop_reason&&(a=t.stop_reason);let s=e.usage;s?.output_tokens&&(o={...o,outputTokens:s.output_tokens});continue}"message_stop"===i&&(yield{type:"message_stop",usage:o,stopReason:a})}}}finally{i.releaseLock()}}buildHeaders(t){let e=this.buildBetas(t);return{"Content-Type":"application/json",Authorization:`Bearer ${this.accessToken}`,"anthropic-version":"2023-06-01","anthropic-beta":e.join(","),"x-app":"cli","User-Agent":`claude-code/${this.version} (external, sdk)`,"X-Claude-Code-Session-Id":this.sessionId}}buildRequestBody(t){let e,s=this.computeFingerprint(t.messages),i=`x-anthropic-billing-header: cc_version=${this.version}.${s}; cc_entrypoint=cli;`;e="string"==typeof t.system?i+"\n"+t.system:Array.isArray(t.system)?[{type:"text",text:i},...t.system]:i;let r={model:t.model,messages:t.messages,max_tokens:t.maxTokens??16384,stream:!0,system:e,metadata:{user_id:JSON.stringify({device_id:this.deviceId,account_uuid:this.accountUuid,session_id:this.sessionId})}};t.tools&&t.tools.length>0&&(r.tools=t.tools,t.toolChoice&&(r.tool_choice="string"==typeof t.toolChoice?{type:t.toolChoice}:t.toolChoice)),!1!==t.caching&&this.addCacheMarkers(r);let n=t.model.toLowerCase(),o=n.includes("opus-4-6")||n.includes("sonnet-4-6"),a="disabled"===t.thinking?.type;return!a&&o?r.thinking={type:"adaptive"}:"enabled"===t.thinking?.type&&(r.thinking={type:"enabled",budget_tokens:t.thinking.budgetTokens}),!(!a&&(o||"enabled"===t.thinking?.type))&&void 0!==t.temperature&&(r.temperature=t.temperature),void 0!==t.topP&&(r.top_p=t.topP),t.effort&&o&&(r.output_config={effort:t.effort}),t.stopSequences?.length&&(r.stop_sequences=t.stopSequences),t.fast&&(r.speed="fast"),r}addCacheMarkers(t){let e=t.system;if("string"==typeof e)t.system=[{type:"text",text:e,cache_control:{type:"ephemeral"}}];else if(Array.isArray(e)){let t=e;t.length>0&&(t[t.length-1]={...t[t.length-1],cache_control:{type:"ephemeral"}})}let s=t.messages;if(0===s.length)return;let i=s[s.length-1];if("string"==typeof i.content)i.content=[{type:"text",text:i.content,cache_control:{type:"ephemeral"}}];else if(Array.isArray(i.content)&&i.content.length>0){let t=i.content[i.content.length-1];i.content[i.content.length-1]={...t,cache_control:{type:"ephemeral"}}}}buildBetas(t){let e=[],s=t.model.toLowerCase().includes("haiku");return s||e.push("claude-code-20250219"),e.push("oauth-2025-04-20"),/\[1m\]/i.test(t.model)&&e.push("context-1m-2025-08-07"),!s&&"disabled"!==t.thinking?.type&&e.push("interleaved-thinking-2025-05-14"),t.effort&&e.push("effort-2025-11-24"),t.fast&&e.push("fast-mode-2026-02-01"),e.push("prompt-caching-scope-2026-01-05"),t.extraBetas&&e.push(...t.extraBetas),e}async ensureAuth(){this.accessToken&&!this.isTokenExpired()||this.credentialStore.hasChanged&&await this.credentialStore.hasChanged()&&(await this.loadFromStore(),this.accessToken&&!this.isTokenExpired())||!this.accessToken&&(await this.loadFromStore(),this.accessToken&&!this.isTokenExpired())||this.accessToken&&this.isTokenExpired()&&await this.refreshTokenWithTripleCheck()}async loadFromStore(){let t=await this.credentialStore.read();if(!t?.accessToken)throw new p('No OAuth tokens found. Run "claude login" first or provide credentials.');this.accessToken=t.accessToken,this.refreshToken=t.refreshToken,this.expiresAt=t.expiresAt}isTokenExpired(){return!!this.expiresAt&&Date.now()+y>=this.expiresAt}async refreshTokenWithTripleCheck(){let t=await this.credentialStore.read();if(t&&!(Date.now()+y>=t.expiresAt))return this.accessToken=t.accessToken,this.refreshToken=t.refreshToken,void(this.expiresAt=t.expiresAt);await this.doTokenRefresh()}async handleAuth401(){let t=this.accessToken;this.pending401&&this.lastFailedToken===t||(this.lastFailedToken=t,this.pending401=(async()=>{let e=await this.credentialStore.read();return e&&e.accessToken!==t?(this.accessToken=e.accessToken,this.refreshToken=e.refreshToken,this.expiresAt=e.expiresAt,!0):(await this.doTokenRefresh(),!0)})().finally(()=>{this.pending401=null,this.lastFailedToken=null})),await this.pending401}async doTokenRefresh(){if(!this.refreshToken)throw new p("Token expired and no refresh token available.");let t=await fetch("https://platform.claude.com/v1/oauth/token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:this.refreshToken,client_id:"9d1c250a-e61b-44d9-88ed-5944d1962f5e"}),signal:AbortSignal.timeout(15e3)});if(!t.ok){let e=await this.credentialStore.read();if(e&&!(Date.now()+y>=e.expiresAt))return this.accessToken=e.accessToken,this.refreshToken=e.refreshToken,void(this.expiresAt=e.expiresAt);throw new p(`Token refresh failed: ${t.status} ${t.statusText}`)}let e=await t.json();this.accessToken=e.access_token,this.refreshToken=e.refresh_token??this.refreshToken,this.expiresAt=Date.now()+1e3*e.expires_in,await this.credentialStore.write({accessToken:this.accessToken,refreshToken:this.refreshToken,expiresAt:this.expiresAt})}computeFingerprint(t){let e=t.find(t=>"user"===t.role);if(!e)return this.hashFingerprint("000");let s="";"string"==typeof e.content?s=e.content:Array.isArray(e.content)&&(s=e.content.find(t=>"text"===t.type)?.text??"");let i=[4,7,20].map(t=>s[t]||"0").join("");return this.hashFingerprint(i)}hashFingerprint(t){let e=`59cf53e54c78${t}${this.version}`;return s("sha256").update(e).digest("hex").slice(0,3)}assembleResponse(t,e){let s=[],i=[],r=[],n={inputTokens:0,outputTokens:0},o=null,a="",l="";for(let e of t)switch(e.type){case"text_delta":a+=e.text;break;case"thinking_delta":l+=e.text;break;case"tool_use_end":r.push({type:"tool_use",id:e.id,name:e.name,input:e.input});break;case"message_stop":n=e.usage,o=e.stopReason;break;case"error":throw e.error}return a&&s.push({type:"text",text:a}),l&&i.push({type:"thinking",thinking:l}),s.push(...r),{content:s,thinking:i.length>0?i:void 0,toolCalls:r.length>0?r:void 0,usage:n,stopReason:o,rateLimitInfo:this.lastRateLimitInfo,model:e}}parseRateLimitHeaders(t){let e=t.get("retry-after"),s=t.get("anthropic-ratelimit-unified-reset"),i=s?Number(s):null;return{status:t.get("anthropic-ratelimit-unified-status"),resetAt:Number.isFinite(i)?i:null,claim:t.get("anthropic-ratelimit-unified-representative-claim"),retryAfter:e?parseFloat(e):null}}getRetryDelay(t,e){if(e){let t=parseInt(e,10);if(!isNaN(t))return 1e3*t}let s=Math.min(500*Math.pow(2,t-1),32e3);return s+.25*Math.random()*s}sleep(t,e){return new Promise((s,i)=>{if(e?.aborted)return void i(new d("Aborted"));let r=setTimeout(s,t);e?.addEventListener("abort",()=>{clearTimeout(r),i(new d("Aborted"))},{once:!0})})}readAccountUuid(){try{let t=c(u(),".claude","claude_code_config.json");return JSON.parse(n(t,"utf8")).oauthAccount?.accountUuid??""}catch{return""}}},w=class{constructor(t){this.path=t}static{e(this,"FileCredentialStore")}lastMtimeMs=0;async read(){try{let t=n(this.path,"utf8");return this.lastMtimeMs=this.getMtime(),JSON.parse(t).claudeAiOauth??null}catch{return null}}async write(t){let e={};try{e=JSON.parse(n(this.path,"utf8"))}catch{}e.claudeAiOauth=t;let s=c(this.path,"..");try{l(s,{recursive:!0})}catch{}o(this.path,JSON.stringify(e,null,2),"utf8"),a(this.path,384),this.lastMtimeMs=this.getMtime()}async hasChanged(){let t=this.getMtime();return t!==this.lastMtimeMs&&(this.lastMtimeMs=t,!0)}getMtime(){try{return h(this.path).mtimeMs}catch{return 0}}},g=class{static{e(this,"MemoryCredentialStore")}credentials;constructor(t){this.credentials={...t}}async read(){return this.credentials.accessToken?{...this.credentials}:null}async write(t){this.credentials={...t}}},k=class _Conversation{static{e(this,"Conversation")}sdk;options;t=[];i={inputTokens:0,outputTokens:0};constructor(t,e){this.sdk=t,this.options=e}get messages(){return this.t}get totalUsage(){return{...this.i}}get length(){return this.t.length}async send(t,e){this.appendUserMessage(t);let s=this.buildGenerateOptions(e),i=await this.sdk.generate(s);return this.appendAssistantFromResponse(i),this.accumulateUsage(i.usage),i}async*stream(t,e){this.appendUserMessage(t);let s=this.buildGenerateOptions(e),i=[],r=[],n=[],o={inputTokens:0,outputTokens:0};for await(let t of this.sdk.stream(s))switch(yield t,t.type){case"text_delta":i.push(t.text);break;case"thinking_delta":r.push(t.text);break;case"tool_use_end":n.push({type:"tool_use",id:t.id,name:t.name,input:t.input});break;case"message_stop":o=t.usage}let a=[];i.length>0&&a.push({type:"text",text:i.join("")});for(let t of n)a.push({type:"tool_use",id:t.id,name:t.name,input:t.input});a.length>0&&this.t.push({role:"assistant",content:a}),this.accumulateUsage(o)}addToolResult(t,e,s){let i={type:"tool_result",tool_use_id:t,content:e,...s&&{is_error:!0}};this.t.push({role:"user",content:[i]})}addToolResults(t){let e=t.map(t=>({type:"tool_result",tool_use_id:t.toolUseId,content:t.content,...t.isError&&{is_error:!0}}));this.t.push({role:"user",content:e})}async continue(t){let e=this.buildGenerateOptions(t),s=await this.sdk.generate(e);return this.appendAssistantFromResponse(s),this.accumulateUsage(s.usage),s}async*continueStream(t){let e=this.buildGenerateOptions(t),s=[],i=[],r={inputTokens:0,outputTokens:0};for await(let t of this.sdk.stream(e))switch(yield t,t.type){case"text_delta":s.push(t.text);break;case"tool_use_end":i.push({type:"tool_use",id:t.id,name:t.name,input:t.input});break;case"message_stop":r=t.usage}let n=[];s.length>0&&n.push({type:"text",text:s.join("")});for(let t of i)n.push({type:"tool_use",id:t.id,name:t.name,input:t.input});n.length>0&&this.t.push({role:"assistant",content:n}),this.accumulateUsage(r)}rewind(t){if(t<0||t>=this.t.length)throw new Error(`Invalid rewind index: ${t}`);return this.t.splice(t)}undoLastTurn(){for(let t=this.t.length-1;t>=0;t--){let e=this.t[t];if("user"===e.role){let s=e.content;if(!(Array.isArray(s)&&s.length>0&&"tool_result"===s[0].type))return this.rewind(t)}}return[]}branch(){let t=new _Conversation(this.sdk,{...this.options});return t.t=[...this.t],t.i={...this.i},t}getHistory(){return this.t.map((t,e)=>{let s="";if("string"==typeof t.content)s=t.content.slice(0,100);else if(Array.isArray(t.content)){let e=t.content[0];"text"===e?.type?s=e.text?.slice(0,100)??"":"tool_result"===e?.type?s=`[tool_result: ${e.tool_use_id}]`:"tool_use"===e?.type&&(s=`[tool_use: ${e.name}]`)}return{index:e,role:t.role,preview:s}})}appendUserMessage(t){this.t.push({role:"user",content:t})}appendAssistantFromResponse(t){let e=[];for(let s of t.content)"text"===s.type?e.push({type:"text",text:s.text}):"tool_use"===s.type&&e.push({type:"tool_use",id:s.id,name:s.name,input:s.input});e.length>0&&this.t.push({role:"assistant",content:e})}buildGenerateOptions(t){return{model:this.options.model,messages:[...this.t],system:this.options.system,tools:t?.tools??this.options.tools,toolChoice:t?.toolChoice??this.options.toolChoice,maxTokens:this.options.maxTokens,thinking:this.options.thinking,effort:this.options.effort,fast:this.options.fast,signal:t?.signal??this.options.signal,extraBetas:this.options.extraBetas,caching:this.options.caching}}accumulateUsage(t){this.i.inputTokens+=t.inputTokens,this.i.outputTokens+=t.outputTokens,this.i.cacheCreationInputTokens=(this.i.cacheCreationInputTokens??0)+(t.cacheCreationInputTokens??0),this.i.cacheReadInputTokens=(this.i.cacheReadInputTokens??0)+(t.cacheReadInputTokens??0)}};import{readFileSync as b,writeFileSync as x,mkdirSync as T}from"fs";import{dirname as v}from"path";import{randomUUID as S}from"crypto";function C(t,e){T(v(t),{recursive:!0});let s=null,i=[];for(let t of e){let e=S(),r={type:"user"===t.role?"user":"assistant",uuid:e,parentUuid:s,timestamp:Date.now(),content:t.content};i.push(JSON.stringify(r)),s=e}x(t,i.join("\n")+"\n","utf8")}function A(t){let e=b(t,"utf8"),s=[];for(let t of e.split("\n")){if(!t.trim())continue;let e;try{e=JSON.parse(t)}catch{continue}("user"===e.type||"assistant"===e.type)&&s.push({role:"user"===e.type?"user":"assistant",content:e.content})}return s}e(C,"saveSession"),e(A,"loadSession");import{createHash as $,randomBytes as R}from"crypto";import{writeFileSync as O,readFileSync as N,mkdirSync as I,chmodSync as E}from"fs";import{dirname as L,join as U}from"path";import{homedir as J}from"os";var D="9d1c250a-e61b-44d9-88ed-5944d1962f5e",F="https://platform.claude.com",M=`${F}/oauth/authorize`,P=`${F}/v1/oauth/token`,j=`${F}/oauth/code/callback`,B=["user:profile","user:inference","org:create_api_key","user:sessions:claude_code","user:mcp_servers","user:file_upload"].join(" ");function q(){return K(R(32))}function H(t){return K($("sha256").update(t).digest())}function z(){return K(R(32))}function K(t){return t.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function G(t={}){let e,s,i=t.credentialsPath??U(J(),".claude",".credentials.json"),r=q(),n=H(r),o=z(),{port:a,waitForCode:l,close:h}=await V(o,t.port),c=`http://localhost:${a}/callback`,u=new URLSearchParams({client_id:D,response_type:"code",scope:B,code_challenge:n,code_challenge_method:"S256",state:o,code:"true"}),d=`${M}?${u.toString()}&redirect_uri=${encodeURIComponent(c)}`,p=`${M}?${u.toString()}&redirect_uri=${encodeURIComponent(j)}`;t.onAuthUrl?t.onAuthUrl(d,p):(console.log("\n🔐 Login to Claude\n"),console.log("Open this URL in your browser:\n"),console.log(` ${p}\n`)),!1!==t.openBrowser&&W(d).catch(()=>{});try{e=await l,s=c}catch(t){throw h(),t}h();let f=await fetch(P,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"authorization_code",code:e,redirect_uri:s,client_id:D,code_verifier:r,state:o})});if(!f.ok){let t=await f.text();throw new Error(`Token exchange failed (${f.status}): ${t}`)}let m=await f.json(),y=Date.now()+1e3*m.expires_in,_={accessToken:m.access_token,refreshToken:m.refresh_token,expiresAt:y,scopes:m.scope?.split(" ")??[]},w={};try{w=JSON.parse(N(i,"utf8"))}catch{}w.claudeAiOauth=_;let g=L(i);try{I(g,{recursive:!0})}catch{}return O(i,JSON.stringify(w,null,2),"utf8"),E(i,384),console.log(`\n✅ Login successful! Credentials saved to ${i}\n`),{accessToken:_.accessToken,refreshToken:_.refreshToken,expiresAt:_.expiresAt,credentialsPath:i}}async function V(t,s){let i,r,n=new Promise((t,e)=>{i=t,r=e}),o=Bun.serve({port:s??0,async fetch(e){let s=new URL(e.url);if("/callback"!==s.pathname)return new Response("Not found",{status:404});let n=s.searchParams.get("code"),o=s.searchParams.get("state"),a=s.searchParams.get("error");return a?(r(new Error(`OAuth error: ${a} — ${s.searchParams.get("error_description")??""}`)),new Response("<html><body><h1>Login failed</h1><p>You can close this tab.</p></body></html>",{status:400,headers:{"Content-Type":"text/html"}})):n&&o===t?(i(n),new Response(null,{status:302,headers:{Location:`${F}/oauth/code/success?app=claude-code`}})):(r(new Error("Invalid callback: missing code or state mismatch")),new Response("Invalid request",{status:400}))}}),a=setTimeout(()=>{r(new Error("Login timed out (5 minutes). Try again.")),o.stop()},3e5);return{port:o.port,waitForCode:n.finally(()=>clearTimeout(a)),close:e(()=>{clearTimeout(a),o.stop()},"close")}}async function W(t){let e=(()=>{switch(process.platform){case"darwin":return[["open",t]];case"win32":return[["cmd","/c","start",t]];default:return[["xdg-open",t],["wslview",t],["sensible-browser",t]]}})();for(let t of e)try{let e=Bun.spawn({cmd:t,stdout:"ignore",stderr:"ignore"});if(await e.exited,0===e.exitCode)return}catch{}}e(q,"generateCodeVerifier"),e(H,"generateCodeChallenge"),e(z,"generateState"),e(K,"base64url"),e(G,"oauthLogin"),e(V,"startCallbackServer"),e(W,"tryOpenBrowser");export{f as APIError,p as AuthError,_ as ClaudeCodeSDK,d as ClaudeCodeSDKError,k as Conversation,w as FileCredentialStore,g as MemoryCredentialStore,m as RateLimitError,A as loadSession,G as oauthLogin,C as saveSession};
|
package/package.json
CHANGED