Proxy-client
Functions
startProxySession
async function startProxySession(apiKey: string): Promise<{
sessionId: string
plan: 'free' | 'pro'
remaining: number
used: number
}>
Use startProxySession to authenticate with the skrypt proxy and retrieve your session token before generating documentation.
Call this at the start of any generation workflow — the sessionId it returns is required by subsequent generation calls, and the usage fields let you gate or warn users before they exhaust their quota.
The session validates your API key against the skrypt proxy, determines your plan tier, and returns a snapshot of your current usage. The remaining count reflects generations left in your current billing period at the moment of the call.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes | Your skrypt API key — find it at skrypt.dev/dashboard/keys. Determines your plan tier and generation quota. |
Returns
Returns a session object. Pass sessionId to generation calls to authenticate them. Check remaining before starting large batch jobs — if it's 0, generation calls will fail.
| Field | Type | Description |
|---|---|---|
sessionId | string | Short-lived token that authorizes generation requests in this session. |
plan | 'free' | 'pro' | Your current plan. free plans have lower rate limits and generation caps. |
remaining | number | Generations left in the current billing period. |
used | number | Generations consumed so far in the current billing period. |
Heads up
sessionIdis short-lived — don't cache it across long-running processes or between CLI invocations. CallstartProxySessionfresh each time.- On
freeplans,remainingcan drop to0quickly during batch generation. Check it before looping over large source directories.
Example:
async function startProxySession(apiKey) {
const response = await fetch("https://proxy.skrypt.dev/v1/sessions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Failed to start session: ${error.message}`);
}
return response.json();
}
async function generateDocs(sourceDir, apiKey) {
try {
const session = await startProxySession(apiKey);
console.log(`Plan: ${session.plan}`);
console.log(`Usage: ${session.used} used, ${session.remaining} remaining`);
if (session.remaining === 0) {
throw new Error("No generations remaining. Upgrade at skrypt.dev/billing.");
}
if (session.remaining < 10) {
console.warn(`Warning: only ${session.remaining} generations left this period.`);
}
// Pass sessionId to your generation calls
console.log(`Session started: ${session.sessionId}`);
console.log("Ready to generate docs for:", sourceDir);
// Expected output:
// Plan: pro
// Usage: 142 used, 858 remaining
// Session started: sess_4kR9mXpL2nQw8vYt
// Ready to generate docs for: ./src
} catch (err) {
console.error("Session error:", err.message);
process.exit(1);
}
}
generateDocs("./src", "sk_live_4kR9mXpL2nQw8vYtJd3HbCeF");
completeProxySession
async function completeProxySession(apiKey: string, sessionId: string): Promise<void>
Use completeProxySession to finalize a proxy generation session and register it against your monthly usage quota.
Call this after a proxied LLM generation succeeds — it's the signal to skrypt's backend that a billable session concluded. Without it, your usage counter won't increment and your quota tracking will drift out of sync.
The function posts to skrypt's completion endpoint with your API key and the session ID returned when the session was opened. It resolves with no value on success and throws if the request fails.
| Name | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes | Your skrypt API key — find it at your skrypt dashboard under API Keys |
sessionId | string | Yes | The session ID returned when the proxy session was opened; ties this completion event to the correct session record |
Returns Promise<void>. On success, nothing is returned — the resolved promise is your confirmation that usage was recorded. If the request fails (invalid key, unknown session ID, network error), the promise rejects with an error describing the cause.
Heads up:
- Call this exactly once per session. Calling it multiple times with the same
sessionIdwill increment your usage counter multiple times. - If your generation step throws, skip this call — only complete sessions where content was actually produced.
Example:
async function completeProxySession(apiKey: string, sessionId: string): Promise<void> {
const response = await fetch("https://api.skrypt.ai/api/proxy/generate/complete", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ sessionId }),
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Failed to complete proxy session: ${response.status} ${error}`);
}
}
async function main() {
const apiKey = "sk_live_4f8a2b1c9d3e7f6a0b5c8d2e1f4a7b3c";
const sessionId = "psess_01HX9MKTBF3YNZQ7R2VD6CWPAE";
// Simulate a generation step that produced content
const generationSucceeded = true;
if (generationSucceeded) {
try {
await completeProxySession(apiKey, sessionId);
console.log("Session completed — usage recorded.");
// Output: Session completed — usage recorded.
} catch (err) {
console.error("Could not record session usage:", err);
}
}
}
main();
Classes
ProxyClient
class ProxyClient implements LLMClient
Use ProxyClient to generate AI-powered documentation without managing your own OpenAI API key — Skrypt's proxy handles model selection and routing on your behalf.
Reach for this when you're running skrypt generate programmatically and your users authenticate via Skrypt accounts rather than supplying their own LLM credentials. It's the default client in Skrypt's generation pipeline when a SKRYPT_API_KEY is present.
Requests are forwarded to https://app.skrypt.sh (or SKRYPT_API_URL if set), where Skrypt authenticates your session and selects the appropriate model. You don't control which model runs — the proxy decides based on your account tier and current availability.
Constructor parameters
| Name | Type | Required | Description |
|---|---|---|---|
config.apiKey | string | Yes | Your Skrypt API key — find it at app.skrypt.sh/settings/api |
config.sessionId | string | Yes | Unique identifier for this generation run, used to correlate logs and usage in your Skrypt dashboard |
config.timeout | number | No | Milliseconds before a proxied request is abandoned and throws. Defaults to 120000 (2 minutes) — increase this for large files with many exports |
Returns an LLMClient-compatible instance. Pass it directly to any Skrypt generation function that accepts an LLMClient — it's a drop-in replacement for OpenAIClient or AnthropicClient.
Heads up
- The
providerproperty is always"openai"regardless of which model the proxy actually uses. Don't rely on it to infer the underlying model. - If
SKRYPT_API_URLis set in your environment, all requests route there instead of the default — useful for self-hosted Skrypt deployments but easy to misconfigure in CI.
Example:
const API_BASE = process.env.SKRYPT_API_URL || 'https://app.skrypt.sh'
interface CompletionRequest {
prompt: string
maxTokens?: number
}
interface CompletionResponse {
content: string
usage: { promptTokens: number; completionTokens: number }
}
interface LLMClient {
provider: string
complete(request: CompletionRequest): Promise<CompletionResponse>
}
class ProxyClient implements LLMClient {
provider = 'openai' as const
private apiKey: string
private sessionId: string
private timeout: number
constructor(config: { apiKey: string; sessionId: string; timeout?: number }) {
this.apiKey = config.apiKey
this.sessionId = config.sessionId
this.timeout = config.timeout ?? 120_000
}
async complete(request: CompletionRequest): Promise<CompletionResponse> {
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), this.timeout)
try {
const response = await fetch(`${API_BASE}/api/proxy/complete`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
'X-Session-ID': this.sessionId,
},
body: JSON.stringify(request),
signal: controller.signal,
})
if (!response.ok) {
throw new Error(`Proxy request failed: ${response.status} ${response.statusText}`)
}
return response.json()
} finally {
clearTimeout(timer)
}
}
}
async function generateDocs(source: string, client: LLMClient): Promise<string> {
const response = await client.complete({
prompt: `Generate concise API documentation for: ${source}`,
maxTokens: 500,
})
return response.content
}
async function main() {
const client = new ProxyClient({
apiKey: 'sk_live_4xKj9mN2pQr8vWz3',
sessionId: 'gen_run_20240315_a7f2c1',
timeout: 90_000,
})
try {
const docs = await generateDocs('function createUser(email: string): Promise<User>', client)
console.log('Generated docs:', docs)
// Generated docs: Creates a new user with the given email address...
} catch (err) {
console.error('Documentation generation failed:', err)
}
}
main()
Methods
constructor
constructor(config: { apiKey: string; sessionId: string; timeout?: number })
Use ProxyClient to connect to skrypt's AI proxy and send completion requests without managing model selection yourself.
Instantiate ProxyClient at the start of a documentation generation session. The proxy handles routing to the appropriate underlying model (OpenAI by default), so you only need to supply your API key and a session identifier to tie requests together.
The sessionId groups all LLM calls made during a single skrypt generate run, which lets the proxy correlate usage, enforce rate limits per session, and return consistent behavior across a batch of documentation requests.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
config.apiKey | string | Yes | Your skrypt API key — find it in your skrypt dashboard under API Keys |
config.sessionId | string | Yes | A unique identifier for this generation session — use a UUID or a hash of the run timestamp to group all requests from a single skrypt generate invocation |
config.timeout | number | No | Milliseconds before a completion request is abandoned and throws. Defaults to 120000 (2 minutes) — lower this in CI environments where you'd rather fail fast |
Returns
A ProxyClient instance ready to send completion requests. Pass this instance into the generation pipeline to process each extracted API signature.
Heads up
- The default 2-minute timeout is intentionally generous for large codebases where individual completions can be slow. If you're generating docs for a small project and want faster failure feedback, set
timeoutto30000or less. sessionIdis not validated for uniqueness — passing the same ID across separate runs won't cause an error, but will conflate usage metrics for those runs in your dashboard.
Example:
type CompletionRequest = {
prompt: string
maxTokens?: number
}
type CompletionResponse = {
text: string
usage: { promptTokens: number; completionTokens: number }
}
class ProxyClient {
provider = 'openai' as const
private apiKey: string
private sessionId: string
private timeout: number
constructor(config: { apiKey: string; sessionId: string; timeout?: number }) {
this.apiKey = config.apiKey
this.sessionId = config.sessionId
this.timeout = config.timeout ?? 120_000
}
async complete(request: CompletionRequest): Promise<CompletionResponse> {
// Simulated proxy response for demonstration
return {
text: `Generated docs for: ${request.prompt.slice(0, 40)}...`,
usage: { promptTokens: 120, completionTokens: 340 },
}
}
}
async function generateDocs() {
const client = new ProxyClient({
apiKey: 'sk-proxy-4f8a2b1c9d3e7f6a0b5c8d2e1f4a7b3c',
sessionId: 'session-2024-11-15-a3f9c2d1',
timeout: 30_000,
})
try {
const response = await client.complete({
prompt: 'Document this function: getUserById(id: string): Promise<User>',
maxTokens: 512,
})
console.log('Provider:', client.provider)
console.log('Generated:', response.text)
console.log('Tokens used:', response.usage.promptTokens + response.usage.completionTokens)
// Provider: openai
// Generated: Generated docs for: Document this function: getUserById...
// Tokens used: 460
} catch (err) {
console.error('Completion failed:', err)
}
}
generateDocs()
complete
async complete(request: CompletionRequest): Promise<CompletionResponse>
Use complete to send a prompt to an LLM through the skrypt proxy and get back a generated completion — without exposing your provider API keys to the client.
This is the core method you'll call when building documentation generation pipelines or any feature that needs AI-generated text. It sits at the heart of ProxyClient, which handles auth, routing, and timeouts so you don't have to manage provider SDKs directly.
The method opens an authenticated request to the skrypt proxy, which forwards it to your configured LLM provider. If the request exceeds the configured timeout, it's automatically aborted and throws — preventing hung processes during large doc generation runs.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
request | CompletionRequest | Yes | The prompt payload to send to the LLM. Must include at minimum a messages array. Additional fields like model, temperature, and maxTokens control generation behavior. |
request.messages | Array<{role, content}> | Yes | Conversation turns passed to the model. Use role: "user" for prompts and role: "system" to set model behavior. |
request.model | string | No | The model identifier to use (e.g. "gpt-4o", "claude-3-5-sonnet"). Falls back to your proxy's default if omitted. |
request.temperature | number | No | Controls output randomness from 0 (deterministic) to 1 (creative). Lower values produce more consistent documentation. |
Returns
Returns a CompletionResponse containing the generated text in response.content and token usage metadata in response.usage. Pass response.content directly to your MDX writer or post-process it to extract structured documentation blocks.
Heads up
- Throws an
AbortErrorif the request exceeds thetimeoutset onProxyClient(default: 120 seconds). For large files with many functions, consider increasing the timeout at construction time rather than splitting requests. - The proxy validates your
apiKeyandsessionIdon every call — a 401 here means your session has expired, not that the LLM is unavailable.
Example:
const API_BASE = "https://proxy.skrypt.ai";
interface Message {
role: "system" | "user" | "assistant";
content: string;
}
interface CompletionRequest {
messages: Message[];
model?: string;
temperature?: number;
maxTokens?: number;
}
interface CompletionResponse {
content: string;
usage: {
promptTokens: number;
completionTokens: number;
totalTokens: number;
};
}
class ProxyClient {
private apiKey: string;
private sessionId: string;
private timeout: number;
constructor(config: { apiKey: string; sessionId: string; timeout?: number }) {
this.apiKey = config.apiKey;
this.sessionId = config.sessionId;
this.timeout = config.timeout ?? 120_000;
}
async complete(request: CompletionRequest): Promise<CompletionResponse> {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), this.timeout);
try {
const response = await fetch(`${API_BASE}/api/proxy/generate`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": this.apiKey,
"x-session-id": this.sessionId,
},
body: JSON.stringify(request),
signal: controller.signal,
});
if (!response.ok) {
throw new Error(`Proxy request failed: ${response.status} ${response.statusText}`);
}
return await response.json() as CompletionResponse;
} finally {
clearTimeout(timer);
}
}
}
const client = new ProxyClient({
apiKey: "sk_live_4f8a2b1c9d3e7f6a",
sessionId: "sess_9x2mK4pL8nQr",
timeout: 60_000,
});
async function generateFunctionDocs(signature: string, sourceCode: string) {
try {
const result = await client.complete({
model: "gpt-4o",
temperature: 0.2,
messages: [
{
role: "system",
content: "You are a technical writer. Generate concise API documentation in MDX format.",
},
{
role: "user",
content: `Document this function:\n\nSignature: ${signature}\n\nSource:\n${sourceCode}`,
},
],
});
console.log("Generated docs:\n", result.content);
console.log(`Tokens used: ${result.usage.totalTokens}`);
} catch (error) {
if (error instanceof Error && error.name === "AbortError") {
console.error("Request timed out — try increasing the timeout or simplifying the prompt");
} else {
throw error;
}
}
}
generateFunctionDocs(
"async function createUser(email: string, role: UserRole): Promise<User>",
`async function createUser(email: string, role: UserRole): Promise<User> {
const user = await db.users.create({ email, role, createdAt: new Date() });
await sendWelcomeEmail(user);
return user;
}`
);
// Expected output:
// Generated docs:
// Use `createUser` to register a new user and trigger a welcome email in one step...
// Tokens used: 312
isConfigured
isConfigured(): boolean
Use isConfigured() to verify that a ProxyClient instance has everything it needs before making API calls.
Call this before kicking off a documentation generation run — or any operation that routes through the proxy — to catch missing credentials early and give users a clear error rather than a cryptic network failure.
It checks that both an API key and a session ID are present on the client. If either was omitted during initialization or has been cleared, this returns false.
Returns: true if both apiKey and sessionId are set, false otherwise. Use the result to gate your generation logic or surface a configuration error to the user before any requests are attempted.
Heads up:
- This only checks that the values exist, not that they're valid. A malformed or expired API key will still return
true— you'll catch that on the first actual request.
Example:
class ProxyClient {
private apiKey: string | undefined
private sessionId: string | undefined
constructor(config: { apiKey?: string; sessionId?: string }) {
this.apiKey = config.apiKey
this.sessionId = config.sessionId
}
isConfigured(): boolean {
return !!this.apiKey && !!this.sessionId
}
async generateDocs(sourcePath: string): Promise<void> {
if (!this.isConfigured()) {
throw new Error(
"ProxyClient is not configured. Provide both apiKey and sessionId before generating docs."
)
}
console.log(`Generating docs for: ${sourcePath}`)
}
}
async function main() {
const unconfigured = new ProxyClient({ apiKey: "sk-live-abc123" })
console.log("Configured (missing sessionId):", unconfigured.isConfigured())
// → false
const configured = new ProxyClient({
apiKey: "sk-live-abc123",
sessionId: "sess_7f4e2d91b0c3a856",
})
console.log("Configured (both present):", configured.isConfigured())
// → true
try {
await configured.generateDocs("./src")
} catch (err) {
console.error(err)
}
}
main()