Replace the openai SDK with a lean fetch-based client. - #2
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Drop the
openaidependency — lean fetch-basedgenerateTextclientSummary
smart-decisions now talks to OpenAI-compatible endpoints through ~100 lines of its own
transport code instead of the
openaiSDK. The library ships zero runtime dependencies.The public API is unchanged:
choice()keeps its shape and signature.Questiongains twooptional provider settings:
maxRetries(default2) andtimeoutMs(default600000).What changed
New transport —
src/utils/llms/generate-text.tsPOST {apiBaseUrl}/chat/completionswithAuthorization: Bearerand aJSON body including
stream: false— the same wire format the SDK produced (verified bycapturing the exact request).
2, SDK-style counting: total attempts =maxRetries + 1) withexponential backoff (500ms doubling, capped at 8s), honoring
retry-after-ms/retry-afterand the
x-should-retryheader. Retryable statuses: 408, 409, 429, ≥ 500.AbortSignal.timeout. Timeouts are deliberatelynot retried — doubling a 10-minute wait for a one-token decision is worse than failing fast.
Errors carrying the HTTP status, a truncated response body, and theoriginal failure as
cause.User-Agent: smart-decisions/<version>(src/version.ts, kept in sync withpackage.jsonby a test).
Repo structure
src/utils/{time,network,error,text}/— eight focused helpers (sleep,backoffDelay,numericHeader,retryDelayFromHeaders,shouldRetryStatus,isTimeoutError,messageOf,truncate).src/types/— seven granular internal types describing the chat-completionsrequest/response shapes.
@param,@returns,@throwsand@exampleon every exported symbol.Tooling
tsconfig.jsonis now a repo-wide typecheck project (src+test+examples,noEmit);emitting lives in
tsconfig.build.json. Newtypecheckscript, wired intoprepublishOnly.Tests and
expectTypeOfassertions are now enforced by the compiler..vscodewatch task now runs the full-repo typecheck (nodist/churn on save).Tests
fetchwith realResponseobjects and faketimers;
system1-choicetests re-wired the same way; new unit suites for every helper andtype; a version-sync test.
Behavior deltas vs the SDK
openaiSDK (before)APIErrorsubclassesError(status + body +cause)OpenAI/JS x.y.z,X-Stainless-*telemetrysmart-decisions/x.y.z, nothing elseopenaiVerification
typecheck,lint,format:check,build,testwith enforced 100% coveragenpm run exampleagainst llama.cpp (movie@ 0.9991, matches theREADME's documented numbers)
ranking; the small logprob deltas were proven to be server-side run-to-run noise via a
same-client control (two identical requests through one transport also wobble)
npm pack— 51 files, 47.3 kB, zeroopenaireferences in dist or lockfile