Skip to content

Commit f2ee56f

Browse files
committed
refactor(sdk): extract helpers from promptAiSdkStream (Commit 2.15)
1 parent 6da4431 commit f2ee56f

File tree

5 files changed

+300
-261
lines changed

5 files changed

+300
-261
lines changed

REFACTORING_PLAN.md

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ This document outlines a prioritized refactoring plan for the 51 issues identifi
4545
| 2.12 | Refactor suggestion-engine | ✅ Complete | Codebuff |
4646
| 2.13 | Fix browser actions + string utils | ✅ Complete | Codebuff |
4747
| 2.14 | Refactor agent-builder.ts | ✅ Complete | Codebuff |
48-
| 2.15 | Refactor promptAiSdkStream | ⬜ Not Started | - |
48+
| 2.15 | Refactor promptAiSdkStream | ✅ Complete | Codebuff |
4949
| 2.16 | Simplify run-state.ts | ⬜ Not Started | - |
5050

5151
### Phase 3 Progress
@@ -1078,21 +1078,47 @@ Extracted pure utility modules instead of React hooks (as originally planned) be
10781078

10791079
---
10801080

1081-
### Commit 2.15: Refactor `promptAiSdkStream` in SDK
1081+
### Commit 2.15: Refactor `promptAiSdkStream` in SDK ✅ COMPLETE
10821082
**Files:** `sdk/src/impl/llm.ts`
10831083
**Est. Time:** 3-4 hours
1084-
**Est. LOC Changed:** ~350-450
1084+
**Actual Time:** ~2 hours
1085+
**Est. LOC Changed:** ~350-450
1086+
**Actual LOC Changed:** ~250 lines extracted to 3 new files
10851087

1086-
| Task | Description |
1087-
|------|-------------|
1088-
| Extract `StreamConfig` builder | Configuration handling |
1089-
| Extract `StreamEventEmitter` | Event emission |
1090-
| Extract `StreamErrorHandler` | Error handling |
1091-
| Simplify main function | Orchestration only |
1088+
| Task | Description | Status |
1089+
|------|-------------|--------|
1090+
| Create `tool-call-repair.ts` | Tool call repair handler with agent transformation logic ||
1091+
| Create `claude-oauth-errors.ts` | OAuth error detection (rate limit + auth errors) ||
1092+
| Create `stream-cost-tracker.ts` | Cost extraction and tracking utilities ||
1093+
| Simplify main function | Uses extracted helpers, reduced from ~540 to ~380 lines ||
1094+
1095+
**New Files Created:**
1096+
- `sdk/src/impl/tool-call-repair.ts` (~140 lines) - Tool call repair handler:
1097+
- `createToolCallRepairHandler()` - factory for experimental_repairToolCall
1098+
- `deepParseJson()` - recursive JSON parsing helper
1099+
- Transforms agent tool calls to spawn_agents
1100+
- `sdk/src/impl/claude-oauth-errors.ts` (~65 lines) - OAuth error detection:
1101+
- `isClaudeOAuthRateLimitError()` - detects 429 and rate limit messages
1102+
- `isClaudeOAuthAuthError()` - detects 401/403 and auth error messages
1103+
- `sdk/src/impl/stream-cost-tracker.ts` (~55 lines) - Cost tracking:
1104+
- `OpenRouterUsageAccounting` type
1105+
- `calculateUsedCredits()` - credit calculation with profit margin
1106+
- `extractAndTrackCost()` - provider metadata extraction and callback
1107+
1108+
**Code Reduction:**
1109+
- `llm.ts`: ~540 → ~380 lines (-30%)
1110+
- Tool call repair logic: ~85 lines moved
1111+
- OAuth error functions: ~65 lines moved
1112+
- Cost tracking: ~25 lines moved + deduplicated across 3 functions
1113+
1114+
**Test Results:**
1115+
- 281 SDK tests pass
1116+
- TypeScript compiles cleanly
10921117

10931118
**Dependencies:** Commits 2.9, 2.10 (streaming patterns)
10941119
**Risk:** Medium
1095-
**Rollback:** Revert single commit
1120+
**Rollback:** Revert single commit
1121+
**Commit:** Pending
10961122

10971123
---
10981124

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/** Detects rate limit and authentication errors for Claude OAuth fallback. */
2+
3+
import { getErrorStatusCode } from '../error-utils'
4+
5+
type ErrorDetails = {
6+
statusCode: number | null
7+
message: string
8+
responseBody: string
9+
}
10+
11+
function getErrorDetails(error: unknown): ErrorDetails {
12+
const statusCode = getErrorStatusCode(error) ?? null
13+
const err = error as { message?: string; responseBody?: string }
14+
return {
15+
statusCode,
16+
message: (err.message || '').toLowerCase(),
17+
responseBody: (err.responseBody || '').toLowerCase(),
18+
}
19+
}
20+
21+
export function isClaudeOAuthRateLimitError(error: unknown): boolean {
22+
if (!error || typeof error !== 'object') return false
23+
24+
const { statusCode, message, responseBody } = getErrorDetails(error)
25+
26+
if (statusCode === 429) return true
27+
if (message.includes('rate_limit') || message.includes('rate limit')) return true
28+
if (message.includes('overloaded')) return true
29+
if (responseBody.includes('rate_limit') || responseBody.includes('overloaded')) return true
30+
31+
return false
32+
}
33+
34+
/** Indicates we should try refreshing the token. */
35+
export function isClaudeOAuthAuthError(error: unknown): boolean {
36+
if (!error || typeof error !== 'object') return false
37+
38+
const { statusCode, message, responseBody } = getErrorDetails(error)
39+
40+
if (statusCode === 401 || statusCode === 403) return true
41+
if (message.includes('unauthorized') || message.includes('invalid_token')) return true
42+
if (message.includes('authentication') || message.includes('expired')) return true
43+
if (responseBody.includes('unauthorized') || responseBody.includes('invalid_token')) return true
44+
if (responseBody.includes('authentication') || responseBody.includes('expired')) return true
45+
46+
return false
47+
}

0 commit comments

Comments
 (0)