TypeScript SDK Configuration
Public Solwyn TypeScript options, environment variables, strict validation, defaults, and qualified runtime boundaries.
The public wrapper accepts camelCase SolwynOptions. Each option is copied once into a strict,
validated internal configuration; unknown keys are rejected instead of being ignored. Pass
provider request settings to the provider client or request, not to Solwyn.
import { Solwyn } from "@solwyn/sdk";
import OpenAI from "openai";
const solwynApiKey = process.env.SOLWYN_API_KEY;
if (!solwynApiKey) throw new Error("SOLWYN_API_KEY is required");
const client = new Solwyn(new OpenAI(), {
apiKey: solwynApiKey,
model: "gpt-4o",
failOpen: true,
onUnmetered: "raise",
leaseEnabled: true,
reporterShutdownDeadline: 5,
});
try {
await client.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Return one short greeting." }],
});
} finally {
await client.close();
}In this example, the provider-required model is explicit on the request. Per-call request values
win over defaultParams and constructor-level model defaults.
Identity, attribution, and coverage
| Option | Environment variable | Default | Meaning |
|---|---|---|---|
apiKey | SOLWYN_API_KEY | Required | Solwyn project key: sk_proj_ plus 64 lowercase hexadecimal characters. |
apiUrl | SOLWYN_API_URL | https://api.solwyn.ai | Solwyn Cloud API base URL. |
model | — | None | Primary model default; a per-call model takes precedence. |
provider | — | Auto-detect | Primary provider identity pin. It bypasses detection, then validates the client family. |
fallback | — | [] | Ordered tuples of [client, model], optionally followed by defaultParams and a provider override. |
defaultParams | — | {} | Fill-absent provider request values. Per-call values win. |
tags | SOLWYN_TAGS | None | Default content-free attribution tags. Environment form is comma-separated key=value. |
onUnmetered | SOLWYN_ON_UNMETERED | "warn" | "warn", "raise", or "allow" for unmetered or newly observed spend surfaces. |
acknowledgeUntracked | SOLWYN_ACKNOWLEDGE_UNTRACKED | [] | Exact reviewed terminal surface tokens. Environment form is comma-separated. |
reportUntrackedSurfaces | SOLWYN_REPORT_UNTRACKED_SURFACES | true | Send content-free untracked-surface advisories to Solwyn Cloud. |
traceCorrelation | SOLWYN_TRACE_CORRELATION | true | Add the caller's active OpenTelemetry trace ID, span ID, and sampled flag to metadata events when an active span exists. false disables capture. |
Set apiUrl only to the trusted HTTPS Solwyn control-plane endpoint you intend to use. The SDK
sends the Solwyn project key to that endpoint as a bearer credential.
Valid provider identities are openai, anthropic, google, bedrock, xai, deepseek,
mistral, qwen, groq, together, fireworks, perplexity, azure_openai, openrouter,
zai, ollama, vllm, lmstudio, and openai_compatible. Provider name controls attribution,
budgets, and circuit breakers; provider dialect controls dispatch and translation. See
TypeScript SDK providers before adding an explicit pin.
Trace correlation adds no OpenTelemetry dependency and creates no spans. It reads only the active span's trace ID, span ID, and sampled flag through an already-registered OpenTelemetry API, once at call start; see TypeScript SDK privacy.
Tags are never inferred from prompt or response content. A per-call solwyn_tags property is
removed only from an intercepted provider request and used as explicit attribution. Tagged calls
remain in the per-call budget-check path rather than using a run lease, so tag-scoped policy stays
authoritative.
Budgets and leases
| Option | Environment variable | Default | Meaning |
|---|---|---|---|
failOpen | SOLWYN_FAIL_OPEN | true | Outage posture after applicable retained-denial checks. |
budgetMode | SOLWYN_BUDGET_MODE | "alert_only" | "alert_only" or "hard_deny", attached to SDK-local outage results. It does not override the mode returned by a live Cloud check. |
budgetCheckCacheTtl | SOLWYN_BUDGET_CHECK_CACHE_TTL | 5 | Unscoped allow-cache lifetime in integer seconds; 0 disables it. |
budgetCheckTimeout | SOLWYN_BUDGET_CHECK_TIMEOUT | 1 | Budget pre-flight timeout in seconds, at least 0.1, capped by the whole-chain deadline. |
leaseEnabled | SOLWYN_LEASE_ENABLED | true | Enable local token leases for eligible, untagged, run-scoped text calls. |
leaseOutputBoundDefault | SOLWYN_LEASE_OUTPUT_BOUND_DEFAULT | 4096 | Output-token reservation when a request has no usable structural cap. |
The live mode returned by Solwyn Cloud is authoritative for that call. An applicable retained
hard denial is preserved during a later outage even when failOpen is true. Read
TypeScript SDK budgets before changing fail-open or lease behavior.
Failover and provider breakers
| Option | Environment variable | Default | Meaning |
|---|---|---|---|
selectionPolicy | — | HealthBasedPolicy | Candidate ordering policy. |
failoverIdempotency | — | "safe" | "safe", "never", or "always" for cross-provider failover. |
sameProviderRetries | — | 0 | Same-provider retries for HTTP 429 responses with usable Retry-After. |
failoverTotalTimeout | — | 30 | Seconds for pre-flight, retry sleeps, and between-hop admission. It does not cap an in-flight provider read. |
failoverHopReadTimeout | — | 600 | Per-attempt provider timeout in seconds; the phases it covers vary by provider SDK. |
circuitBreakerRecoveryTimeoutJitter | — | 0.2 | Provider-breaker recovery jitter fraction. |
circuitBreakerFailureThreshold | SOLWYN_CIRCUIT_BREAKER_FAILURE_THRESHOLD | 3 | Consecutive failures before a provider breaker opens. |
circuitBreakerRecoveryTimeout | SOLWYN_CIRCUIT_BREAKER_RECOVERY_TIMEOUT | 60 | Base recovery timeout in integer seconds. |
circuitBreakerSuccessThreshold | SOLWYN_CIRCUIT_BREAKER_SUCCESS_THRESHOLD | 2 | Half-open successes required to close a provider breaker. |
Both timeout options reject booleans and non-finite values. failoverHopReadTimeout must be
positive. A zero failoverTotalTimeout is valid and prevents new work from starting after call
entry. JavaScript provider SDKs expose one per-request timeout carrier, and what it covers differs
by SDK. For OpenAI, OpenAI-compatible, and Anthropic clients, failoverHopReadTimeout covers only
connecting and receiving response headers: a response body or stream that stalls after its first
bytes is not interrupted. For Google, Solwyn keeps the bound armed until the buffered response or
stream finishes, so it also limits the total duration of a healthy stream. To bound a stalled
stream on the other SDKs, pass an AbortSignal in the request options or apply your own idle
timeout while iterating. Bedrock's request timeout is not a universal hard abort for every
Converse stream handler; configure a finite socket timeout on the AWS request handler too.
See TypeScript SDK failover for fallback tuple shapes, first-byte stream behavior, and fail-loud translation limits.
Control-plane and reporter behavior
| Option | Environment variable | Default | Meaning |
|---|---|---|---|
fetch | — | globalThis.fetch | Caller-owned Solwyn control-plane transport seam. |
logger | — | Console-backed logger | debug, info, warn, and error logger implementation. |
controlPlaneFailureThreshold | SOLWYN_CONTROL_PLANE_FAILURE_THRESHOLD | 3 | Consecutive budget-check, confirmation, or lease-operation outages before the shared control-plane breaker opens. |
controlPlaneRecoveryTimeout | SOLWYN_CONTROL_PLANE_RECOVERY_TIMEOUT | 30 | Control-plane breaker recovery timeout in seconds. |
breakerReportingEnabled | SOLWYN_BREAKER_REPORTING_ENABLED | true | Include provider-breaker snapshots in reporter cycles. |
reporterBatchSize | SOLWYN_REPORTER_BATCH_SIZE | 50 | Events per metadata-ingest batch; 1–1000. |
reporterFlushInterval | SOLWYN_REPORTER_FLUSH_INTERVAL | 5 | Background flush interval in seconds. |
reporterMaxQueueSize | SOLWYN_REPORTER_MAX_QUEUE_SIZE | 10000 | Reporter queue cap; overflow drops the oldest event. |
reporterMaxInFlight | SOLWYN_REPORTER_MAX_IN_FLIGHT | 3 | Maximum concurrent settlement-confirmation sends. Metadata-ingest batches remain serial. |
reporterMaxSendAttempts | SOLWYN_REPORTER_MAX_SEND_ATTEMPTS | 5 | Ordinary retryable send attempts before telemetry is disposed. HTTP 429 responses have a separate cap of 20. |
reporterRetryBackoffBase | SOLWYN_REPORTER_RETRY_BACKOFF_BASE | 1 | Retry backoff base in seconds. |
reporterRetryBackoffCap | SOLWYN_REPORTER_RETRY_BACKOFF_CAP | 60 | Retry backoff cap in seconds. |
reporterShutdownDeadline | SOLWYN_REPORTER_SHUTDOWN_DEADLINE | 5 | Shared close() deadline in seconds for in-flight calls, open-stream settlement, reporting, and advisory delivery; 0 is valid. |
breakerReportHeartbeat | SOLWYN_BREAKER_REPORT_HEARTBEAT | 60 | Full provider-breaker refresh interval in seconds; greater than 0 and at most 60. |
Reporter batch size, flush interval, queue size, maximum in-flight sends, and retry backoffs must
be positive. Send attempts must be at least one. The shutdown deadline may be zero. Timeout, cache,
recovery, flush, backoff, and shutdown durations must be finite and no greater than 2147483.647
seconds, so their millisecond delays fit the runtime timer range. A present fetch value must be a function, and an injected logger must
provide all four debug, info, warn, and error methods; both are rejected synchronously
otherwise.
Local velocity monitoring
| Option | Environment variable | Default | Meaning |
|---|---|---|---|
velocityMode | SOLWYN_VELOCITY_MODE | "warn" | "off", "warn", or "deny". |
velocityRepeatCount | SOLWYN_VELOCITY_REPEAT_COUNT | 5 | Near-identical calls required inside the repeat window; range 2–64. |
velocityRepeatWindowS | SOLWYN_VELOCITY_REPEAT_WINDOW_S | 60 | Repeat detection window in seconds. |
velocityGrowthStreak | SOLWYN_VELOCITY_GROWTH_STREAK | 8 | Strictly growing call sizes required; range 3–64. |
velocityGrowthFactor | SOLWYN_VELOCITY_GROWTH_FACTOR | 3 | Required latest-to-first estimated-input ratio; greater than one. |
velocityAccelFloorPerMin | SOLWYN_VELOCITY_ACCEL_FLOOR_PER_MIN | 30 | Minimum current-minute call count for acceleration detection; integer 1–64. |
velocityAccelFactor | SOLWYN_VELOCITY_ACCEL_FACTOR | 3 | Required current-to-prior-minute rate ratio; greater than one. |
The repeat window and the growth and acceleration factors also accept positive infinity to disable the corresponding bound. Only repeat size and monotonic growth are deny-eligible. Rate acceleration is advisory. Velocity history is structural and content-blind; see TypeScript SDK runs.
Environment precedence
For mapped fields, resolution is:
- a constructor option when it is not
undefined; - the matching
SOLWYN_*environment variable; - the documented default.
This is a presence check, not a truthiness check. Explicit false, 0, and "" values win over
the environment and are then validated. Boolean environment values use true, 1, or yes
case-insensitively for true; all other strings resolve to false. This applies to
SOLWYN_FAIL_OPEN, SOLWYN_LEASE_ENABLED, SOLWYN_REPORT_UNTRACKED_SURFACES,
SOLWYN_TRACE_CORRELATION, and SOLWYN_BREAKER_REPORTING_ENABLED. Numeric environment values
are coerced and validated; empty strings and booleans are rejected for numeric options. SOLWYN_TAGS uses comma-separated key=value entries, while
SOLWYN_ACKNOWLEDGE_UNTRACKED uses comma-separated exact surface tokens.
Where process.env is unavailable, environment loading is an empty snapshot. Pass apiKey and
other required settings explicitly in edge runtimes.
Strict validation
Construction fails synchronously with ConfigurationError for:
- a missing or malformed Solwyn project key;
- any unknown or snake_case constructor option;
- an unknown provider identity or incompatible provider/client pin;
- a malformed fallback tuple;
- an invalid enum, tag, acknowledgment token, timeout, reporter limit, or velocity threshold;
- a present non-function
fetch, aloggermissing any of its four methods, or aselectionPolicywithoutorder(); - wrapping a client that is already a Solwyn wrapper.
ConfigurationError.field identifies the rejected field when one is available. Constructor and
environment schema errors use the internal snake_case field name, for example
budget_check_timeout or failover_hop_read_timeout. Response and
request wire schemas are also strict: unexpected control-plane fields are treated as contract
drift rather than silently defaulted. Provider errors remain provider errors and pass through
unchanged; see TypeScript SDK errors.
Runtime and compiler support
0.2.0 is qualified on these exact full runtime lanes:
| Runtime | Qualification |
|---|---|
Node.js 22.23.2 | Full ESM/CommonJS, package, consumer, provider, and runtime gates. |
Node.js 24.21.0 | Full ESM/CommonJS, package, consumer, provider, and runtime gates. |
Node.js 20.20.2 | Legacy installed-artifact lane for the provider-free core, @solwyn/sdk/node, and @solwyn/sdk/testing only, while the manifest continues to declare >=20. It is not a source-build, provider-surface, Vercel AI SDK 7, LangChain, or OpenAI Agents lane. |
Use Node.js 22 or 24 for new applications. The package publishes dual ESM and CommonJS entries.
Its declarations are consumer-checked with exact TypeScript 5.8.3 and 6.0.3, under
strict: true, skipLibCheck: false, and a lib set that includes ESNext.Disposable. These two compiler cells are the tested boundary; no
claim is made for every compiler version between them.
Provider compatibility is likewise stated as exact tested cells rather than inferred continuous ranges. See the provider qualification table.
Browser and edge qualification
The core @solwyn/sdk entry uses web-standard fetch, AbortController, crypto.randomUUID,
timers, and web streams, and it imports no node:* module. Release checks exercise a
browser-target bundle, an edge-like VM without Node globals, and a real browser execution path.
Those checks establish browser/edge-compatible packaging; they do not certify deployment on
every named edge platform, provider transport, or hosting product.
@solwyn/sdk/node is Node-only because callback run(...), createRun(), and
RunHandle.activate(...) use AsyncLocalStorage. Do not import that entry into an edge bundle.
Without it, calls still budget-check and report, but ambient run IDs and names are absent. The
LangChain and OpenAI Agents attribution entries also require @solwyn/sdk/node and throw
ConfigurationError without it; on edge runtimes the wrapped client alone still enforces budgets.
Browser-compatible code is not permission to expose secrets. Provider and Solwyn project keys belong in a trusted server or edge secret store. Validate network policy, streaming behavior, provider SDK compatibility, and shutdown semantics on your actual deployment platform.
Shutdown is configuration too
The client owns queued settlement, advisory, budget, lease, and provider-lifecycle work. Always
await client.close() in a finally block or use await using. One reporterShutdownDeadline
bounds the wait for in-flight calls, open-stream settlement, reporting, and advisory delivery, and
the provider's own close() runs last. Calls made after close() begins reject with
SolwynError("client is closed"). See the
TypeScript SDK overview for both patterns.