@cetusai/sdk 0.2.0
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/CHANGELOG.md +33 -0
- package/LICENSE +21 -0
- package/README.md +409 -0
- package/dist/index.cjs +910 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +518 -0
- package/dist/index.d.ts +518 -0
- package/dist/index.mjs +880 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +77 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for all Songlines SDK errors.
|
|
3
|
+
*
|
|
4
|
+
* The SDK never throws — all errors are surfaced via the `onError` callback
|
|
5
|
+
* configured on the client. This class is provided for type-safe error handling
|
|
6
|
+
* in the callback.
|
|
7
|
+
*/
|
|
8
|
+
declare class SonglinesError extends Error {
|
|
9
|
+
readonly code: SonglinesErrorCode;
|
|
10
|
+
readonly statusCode: number | undefined;
|
|
11
|
+
readonly retryable: boolean;
|
|
12
|
+
constructor(message: string, code: SonglinesErrorCode, options?: {
|
|
13
|
+
statusCode?: number;
|
|
14
|
+
retryable?: boolean;
|
|
15
|
+
cause?: unknown;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
declare class InvalidConfigError extends SonglinesError {
|
|
19
|
+
constructor(message: string);
|
|
20
|
+
}
|
|
21
|
+
declare class InvalidApiKeyError extends SonglinesError {
|
|
22
|
+
constructor();
|
|
23
|
+
}
|
|
24
|
+
declare class NetworkError extends SonglinesError {
|
|
25
|
+
constructor(message: string, cause?: unknown);
|
|
26
|
+
}
|
|
27
|
+
declare class TimeoutError extends SonglinesError {
|
|
28
|
+
constructor(timeoutMs: number);
|
|
29
|
+
}
|
|
30
|
+
declare class RateLimitedError extends SonglinesError {
|
|
31
|
+
readonly retryAfterMs: number | undefined;
|
|
32
|
+
constructor(retryAfterMs?: number);
|
|
33
|
+
}
|
|
34
|
+
declare class ServerError extends SonglinesError {
|
|
35
|
+
constructor(statusCode: number, body?: string);
|
|
36
|
+
}
|
|
37
|
+
declare class QueueOverflowError extends SonglinesError {
|
|
38
|
+
readonly droppedCount: number;
|
|
39
|
+
constructor(droppedCount: number);
|
|
40
|
+
}
|
|
41
|
+
declare class PartialFailureError extends SonglinesError {
|
|
42
|
+
readonly accepted: number;
|
|
43
|
+
readonly failed: number;
|
|
44
|
+
readonly failedIds: string[];
|
|
45
|
+
constructor(accepted: number, failed: number, failedIds: string[]);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @songlines/sdk — Core Types
|
|
50
|
+
*
|
|
51
|
+
* All public-facing TypeScript types exported from the SDK.
|
|
52
|
+
* Prompt and completion text are intentionally excluded — the SDK
|
|
53
|
+
* captures metadata only. No prompt content is ever transmitted.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
type Environment = "production" | "staging" | "development" | "test";
|
|
57
|
+
type RequestStatus = "success" | "error" | "blocked" | "pending";
|
|
58
|
+
interface SonglinesClientConfig {
|
|
59
|
+
/**
|
|
60
|
+
* Your Songlines API key. Must start with `sk-sl-`.
|
|
61
|
+
* Always load from an environment variable — never hardcode.
|
|
62
|
+
* @example process.env.SONGLINES_API_KEY
|
|
63
|
+
*/
|
|
64
|
+
apiKey: string;
|
|
65
|
+
/**
|
|
66
|
+
* Base URL of the Songlines Control ingest API.
|
|
67
|
+
* @default "https://api.songlinesai.com"
|
|
68
|
+
*/
|
|
69
|
+
baseUrl?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Deployment environment tag applied to all events from this client instance.
|
|
72
|
+
* @default "production"
|
|
73
|
+
*/
|
|
74
|
+
environment?: Environment;
|
|
75
|
+
/**
|
|
76
|
+
* Maximum number of events to accumulate before flushing to the API.
|
|
77
|
+
* @default 10
|
|
78
|
+
*/
|
|
79
|
+
batchSize?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Maximum time in milliseconds to wait before flushing a partial batch.
|
|
82
|
+
* @default 5000
|
|
83
|
+
*/
|
|
84
|
+
flushIntervalMs?: number;
|
|
85
|
+
/**
|
|
86
|
+
* HTTP request timeout in milliseconds.
|
|
87
|
+
* @default 10000
|
|
88
|
+
*/
|
|
89
|
+
timeout?: number;
|
|
90
|
+
/**
|
|
91
|
+
* Number of times to retry a failed flush before dropping events.
|
|
92
|
+
* Uses exponential backoff with jitter.
|
|
93
|
+
* @default 3
|
|
94
|
+
*/
|
|
95
|
+
retries?: number;
|
|
96
|
+
/**
|
|
97
|
+
* Called when events are dropped due to network failure or queue overflow.
|
|
98
|
+
* The SDK never throws — all errors are surfaced here.
|
|
99
|
+
*/
|
|
100
|
+
onError?: (error: SonglinesError) => void;
|
|
101
|
+
/**
|
|
102
|
+
* When true, logs internal SDK activity to console.debug.
|
|
103
|
+
* @default false
|
|
104
|
+
*/
|
|
105
|
+
debug?: boolean;
|
|
106
|
+
}
|
|
107
|
+
interface TrackAIRequestParams {
|
|
108
|
+
/**
|
|
109
|
+
* Caller-generated unique identifier for this request.
|
|
110
|
+
* Used for idempotency — duplicate IDs within a 24-hour window are ignored.
|
|
111
|
+
* UUID v4 recommended. If omitted, the SDK generates one automatically.
|
|
112
|
+
*/
|
|
113
|
+
requestId?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Model name exactly as called.
|
|
116
|
+
* @example "gpt-4o", "claude-3-5-sonnet-20241022", "mistral-large-latest"
|
|
117
|
+
*/
|
|
118
|
+
model: string;
|
|
119
|
+
/**
|
|
120
|
+
* Provider name.
|
|
121
|
+
* @example "openai", "anthropic", "azure", "bedrock", "mistral", "groq"
|
|
122
|
+
*/
|
|
123
|
+
provider?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Logical workflow or application name. Used for cost attribution and grouping.
|
|
126
|
+
* @example "invoice-processor", "customer-support", "document-review"
|
|
127
|
+
*/
|
|
128
|
+
workflow?: string;
|
|
129
|
+
/**
|
|
130
|
+
* Step within a multi-step workflow.
|
|
131
|
+
* @example "extract", "summarise", "classify", "generate"
|
|
132
|
+
*/
|
|
133
|
+
step?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Agent or service identifier for multi-agent architectures.
|
|
136
|
+
* @example "orchestrator", "researcher", "writer"
|
|
137
|
+
*/
|
|
138
|
+
agentId?: string;
|
|
139
|
+
/**
|
|
140
|
+
* Opaque user identifier. Must not contain PII — use an internal ID or hash.
|
|
141
|
+
* @example "user_8f3a2b", "team_finance"
|
|
142
|
+
*/
|
|
143
|
+
user?: string;
|
|
144
|
+
/**
|
|
145
|
+
* Number of input (prompt) tokens consumed.
|
|
146
|
+
*/
|
|
147
|
+
inputTokens: number;
|
|
148
|
+
/**
|
|
149
|
+
* Number of output (completion) tokens generated.
|
|
150
|
+
*/
|
|
151
|
+
outputTokens: number;
|
|
152
|
+
/**
|
|
153
|
+
* End-to-end wall time in milliseconds from request dispatch to response received.
|
|
154
|
+
*/
|
|
155
|
+
latencyMs?: number;
|
|
156
|
+
/**
|
|
157
|
+
* Actual cost in USD. If omitted, the SDK estimates cost from built-in model rates.
|
|
158
|
+
*/
|
|
159
|
+
cost?: number;
|
|
160
|
+
/**
|
|
161
|
+
* Request outcome.
|
|
162
|
+
* @default "success"
|
|
163
|
+
*/
|
|
164
|
+
status?: RequestStatus;
|
|
165
|
+
/**
|
|
166
|
+
* Error message if status is "error".
|
|
167
|
+
*/
|
|
168
|
+
errorMessage?: string;
|
|
169
|
+
/**
|
|
170
|
+
* Timestamp of when the request was made.
|
|
171
|
+
* @default new Date()
|
|
172
|
+
*/
|
|
173
|
+
timestamp?: Date;
|
|
174
|
+
/**
|
|
175
|
+
* Additional key-value metadata stored alongside the event.
|
|
176
|
+
* Do not include PII or sensitive data — values are visible in the dashboard.
|
|
177
|
+
*/
|
|
178
|
+
metadata?: Record<string, string | number | boolean>;
|
|
179
|
+
}
|
|
180
|
+
interface IngestEvent {
|
|
181
|
+
request_id: string;
|
|
182
|
+
model: string;
|
|
183
|
+
provider?: string;
|
|
184
|
+
workflow?: string;
|
|
185
|
+
step?: string;
|
|
186
|
+
agent_id?: string;
|
|
187
|
+
user?: string;
|
|
188
|
+
environment: Environment;
|
|
189
|
+
input_tokens: number;
|
|
190
|
+
output_tokens: number;
|
|
191
|
+
latency_ms?: number;
|
|
192
|
+
status: RequestStatus;
|
|
193
|
+
error_message?: string;
|
|
194
|
+
timestamp?: string;
|
|
195
|
+
}
|
|
196
|
+
interface IngestResult {
|
|
197
|
+
request_id: string;
|
|
198
|
+
cost: number;
|
|
199
|
+
}
|
|
200
|
+
interface IngestError {
|
|
201
|
+
request_id: string;
|
|
202
|
+
error: string;
|
|
203
|
+
}
|
|
204
|
+
interface IngestResponse {
|
|
205
|
+
accepted: number;
|
|
206
|
+
failed: number;
|
|
207
|
+
results: IngestResult[];
|
|
208
|
+
errors?: IngestError[];
|
|
209
|
+
}
|
|
210
|
+
type SonglinesErrorCode = "INVALID_API_KEY" | "NETWORK_ERROR" | "TIMEOUT" | "RATE_LIMITED" | "SERVER_ERROR" | "INVALID_CONFIG" | "QUEUE_OVERFLOW" | "PARTIAL_FAILURE";
|
|
211
|
+
interface WrapOptions {
|
|
212
|
+
/**
|
|
213
|
+
* Workflow name applied to all calls made through this wrapped client.
|
|
214
|
+
*/
|
|
215
|
+
workflow?: string;
|
|
216
|
+
/**
|
|
217
|
+
* Step name applied to all calls made through this wrapped client.
|
|
218
|
+
*/
|
|
219
|
+
step?: string;
|
|
220
|
+
/**
|
|
221
|
+
* Agent ID applied to all calls made through this wrapped client.
|
|
222
|
+
*/
|
|
223
|
+
agentId?: string;
|
|
224
|
+
/**
|
|
225
|
+
* User identifier applied to all calls made through this wrapped client.
|
|
226
|
+
*/
|
|
227
|
+
user?: string;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @songlines/sdk — Guardrail Evaluation (v0.2.0)
|
|
232
|
+
*
|
|
233
|
+
* Provides real-time policy evaluation via the Songlines Gateway API.
|
|
234
|
+
* Call evaluateGuardrail() before sending a prompt to an LLM to enforce
|
|
235
|
+
* policies inline — blocking, redacting, or alerting as configured.
|
|
236
|
+
*
|
|
237
|
+
* Architecture note: This feature uses the Songlines Gateway / Enforce path,
|
|
238
|
+
* which is distinct from the Control Ingest API used by trackAIRequest().
|
|
239
|
+
* The Gateway sits inline in the request path; the Control Ingest API
|
|
240
|
+
* receives telemetry after the model response.
|
|
241
|
+
*/
|
|
242
|
+
|
|
243
|
+
/** The outcome of a guardrail evaluation. */
|
|
244
|
+
type GuardrailDecision = "allow" | "block" | "modify";
|
|
245
|
+
/** The action configured on the policy that triggered this violation. */
|
|
246
|
+
type PolicyAction = "block" | "alert" | "redact" | "log";
|
|
247
|
+
/** A single policy violation detected during evaluation. */
|
|
248
|
+
interface GuardrailViolation {
|
|
249
|
+
/** Internal policy identifier. */
|
|
250
|
+
policyId: string;
|
|
251
|
+
/** Human-readable policy name. */
|
|
252
|
+
policyName: string;
|
|
253
|
+
/** The action the policy is configured to take. */
|
|
254
|
+
action: PolicyAction;
|
|
255
|
+
/** Human-readable reason for the violation. */
|
|
256
|
+
reason: string;
|
|
257
|
+
/** The field that triggered the violation (e.g. "prompt", "model", "workflow"). */
|
|
258
|
+
field: string;
|
|
259
|
+
}
|
|
260
|
+
/** The result of a guardrail evaluation. */
|
|
261
|
+
interface GuardrailResult {
|
|
262
|
+
/** The overall decision: allow, block, or modify. */
|
|
263
|
+
decision: GuardrailDecision;
|
|
264
|
+
/** All violations detected across all evaluated policies. */
|
|
265
|
+
violations: GuardrailViolation[];
|
|
266
|
+
/**
|
|
267
|
+
* The modified prompt to send to the LLM.
|
|
268
|
+
* Only present when `decision === "modify"` (e.g. PII redaction).
|
|
269
|
+
* Use this instead of the original prompt when decision is "modify".
|
|
270
|
+
*/
|
|
271
|
+
modifiedInput?: string;
|
|
272
|
+
/** Evaluation latency in milliseconds. */
|
|
273
|
+
latencyMs: number;
|
|
274
|
+
/** Unique identifier for this evaluation (for audit correlation). */
|
|
275
|
+
evaluationId: string;
|
|
276
|
+
}
|
|
277
|
+
/** Parameters for evaluateGuardrail(). */
|
|
278
|
+
interface EvaluateGuardrailParams {
|
|
279
|
+
/**
|
|
280
|
+
* The prompt text to evaluate. This is the only content sent to the
|
|
281
|
+
* Gateway — it is evaluated against policies and then discarded.
|
|
282
|
+
* It is never stored in the Songlines platform.
|
|
283
|
+
*/
|
|
284
|
+
prompt: string;
|
|
285
|
+
/**
|
|
286
|
+
* The model identifier the prompt will be sent to.
|
|
287
|
+
* Used for model allowlist/denylist policy evaluation.
|
|
288
|
+
*/
|
|
289
|
+
model: string;
|
|
290
|
+
/**
|
|
291
|
+
* The logical workflow or feature name.
|
|
292
|
+
* Used for workflow-scoped policy evaluation.
|
|
293
|
+
*/
|
|
294
|
+
workflow?: string;
|
|
295
|
+
/**
|
|
296
|
+
* The provider name (e.g. "openai", "anthropic", "azure-openai").
|
|
297
|
+
* Used for provider-level policy enforcement.
|
|
298
|
+
*/
|
|
299
|
+
provider?: string;
|
|
300
|
+
/**
|
|
301
|
+
* When true, throws a GuardrailBlockedError if the decision is "block".
|
|
302
|
+
* When false (default), returns the result and lets the caller decide.
|
|
303
|
+
* @default false
|
|
304
|
+
*/
|
|
305
|
+
throwOnBlock?: boolean;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Thrown by evaluateGuardrail() when `throwOnBlock: true` and the
|
|
309
|
+
* guardrail returns `decision: "block"`.
|
|
310
|
+
*
|
|
311
|
+
* The full GuardrailResult is available on the `result` property.
|
|
312
|
+
*/
|
|
313
|
+
declare class GuardrailBlockedError extends Error {
|
|
314
|
+
readonly result: GuardrailResult;
|
|
315
|
+
constructor(result: GuardrailResult);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Songlines Control SDK client.
|
|
320
|
+
*
|
|
321
|
+
* Instruments AI workloads with a single `trackAIRequest()` call per LLM
|
|
322
|
+
* invocation. All telemetry is batched and sent asynchronously — the SDK
|
|
323
|
+
* never blocks or slows down your AI calls.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```typescript
|
|
327
|
+
* import { SonglinesClient } from "@songlines/sdk";
|
|
328
|
+
*
|
|
329
|
+
* const songlines = new SonglinesClient({
|
|
330
|
+
* apiKey: process.env.SONGLINES_API_KEY!,
|
|
331
|
+
* });
|
|
332
|
+
*
|
|
333
|
+
* // After every LLM call:
|
|
334
|
+
* await songlines.trackAIRequest({
|
|
335
|
+
* model: "gpt-4o",
|
|
336
|
+
* provider: "openai",
|
|
337
|
+
* workflow: "invoice-processor",
|
|
338
|
+
* inputTokens: response.usage.prompt_tokens,
|
|
339
|
+
* outputTokens: response.usage.completion_tokens,
|
|
340
|
+
* latencyMs: Date.now() - startTime,
|
|
341
|
+
* });
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
344
|
+
declare class SonglinesClient {
|
|
345
|
+
private readonly config;
|
|
346
|
+
private readonly queue;
|
|
347
|
+
constructor(config: SonglinesClientConfig);
|
|
348
|
+
/**
|
|
349
|
+
* Records an AI request event. The event is queued immediately and sent
|
|
350
|
+
* asynchronously — this method returns as soon as the event is enqueued.
|
|
351
|
+
*
|
|
352
|
+
* The returned Promise resolves when the event has been enqueued (not when
|
|
353
|
+
* it has been sent). Use `flush()` if you need confirmation of delivery.
|
|
354
|
+
*/
|
|
355
|
+
trackAIRequest(params: TrackAIRequestParams): Promise<void>;
|
|
356
|
+
/**
|
|
357
|
+
* Forces an immediate flush of all queued events to the API.
|
|
358
|
+
* Resolves when the flush completes (successfully or not).
|
|
359
|
+
*/
|
|
360
|
+
flush(): Promise<void>;
|
|
361
|
+
/**
|
|
362
|
+
* Flushes all remaining events and shuts down the background timer.
|
|
363
|
+
* Call this during graceful shutdown (e.g. in a `process.on("SIGTERM")` handler).
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* ```typescript
|
|
367
|
+
* process.on("SIGTERM", async () => {
|
|
368
|
+
* await songlines.shutdown();
|
|
369
|
+
* process.exit(0);
|
|
370
|
+
* });
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
shutdown(): Promise<void>;
|
|
374
|
+
/**
|
|
375
|
+
* Evaluates a prompt against all active Songlines policies in real time.
|
|
376
|
+
*
|
|
377
|
+
* This method uses the **Songlines Gateway / Enforce** path, which is
|
|
378
|
+
* distinct from `trackAIRequest()`. Call it *before* sending the prompt
|
|
379
|
+
* to an LLM to enforce policies inline.
|
|
380
|
+
*
|
|
381
|
+
* @returns A `GuardrailResult` with `decision`, `violations`, and optionally
|
|
382
|
+
* a `modifiedInput` (when a redaction policy fires).
|
|
383
|
+
*
|
|
384
|
+
* @example
|
|
385
|
+
* ```typescript
|
|
386
|
+
* const result = await songlines.evaluateGuardrail({
|
|
387
|
+
* prompt: userMessage,
|
|
388
|
+
* model: "gpt-4o",
|
|
389
|
+
* workflow: "customer-support",
|
|
390
|
+
* });
|
|
391
|
+
*
|
|
392
|
+
* if (result.decision === "block") {
|
|
393
|
+
* return { error: "Request blocked by policy", violations: result.violations };
|
|
394
|
+
* }
|
|
395
|
+
*
|
|
396
|
+
* const promptToSend = result.modifiedInput ?? userMessage;
|
|
397
|
+
* const response = await openai.chat.completions.create({ ... });
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
400
|
+
evaluateGuardrail(params: EvaluateGuardrailParams): Promise<GuardrailResult>;
|
|
401
|
+
/**
|
|
402
|
+
* Converts TrackAIRequestParams into the wire format expected by /api/ingest.
|
|
403
|
+
*/
|
|
404
|
+
private buildEvent;
|
|
405
|
+
/**
|
|
406
|
+
* Sends a batch of events to POST /api/ingest.
|
|
407
|
+
* Called by the BatchQueue — never called directly.
|
|
408
|
+
*/
|
|
409
|
+
private sendBatch;
|
|
410
|
+
/**
|
|
411
|
+
* Performs a single HTTP POST with timeout and error classification.
|
|
412
|
+
*/
|
|
413
|
+
private httpPost;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* OpenAI SDK wrapper for Songlines Control.
|
|
418
|
+
*
|
|
419
|
+
* Wraps an OpenAI client instance so that every `chat.completions.create()`
|
|
420
|
+
* and `completions.create()` call is automatically instrumented with telemetry.
|
|
421
|
+
*
|
|
422
|
+
* Prompt and completion text are NEVER captured — only metadata
|
|
423
|
+
* (model, tokens, latency, cost) is sent to the Songlines ingest API.
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* ```typescript
|
|
427
|
+
* import OpenAI from "openai";
|
|
428
|
+
* import { SonglinesClient } from "@songlines/sdk";
|
|
429
|
+
*
|
|
430
|
+
* const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
431
|
+
* const songlines = new SonglinesClient({ apiKey: process.env.SONGLINES_API_KEY! });
|
|
432
|
+
*
|
|
433
|
+
* const instrumentedOpenAI = songlines.wrapOpenAI(openai, {
|
|
434
|
+
* workflow: "invoice-processor",
|
|
435
|
+
* });
|
|
436
|
+
*
|
|
437
|
+
* // All calls through instrumentedOpenAI are automatically tracked
|
|
438
|
+
* const response = await instrumentedOpenAI.chat.completions.create({
|
|
439
|
+
* model: "gpt-4o",
|
|
440
|
+
* messages: [{ role: "user", content: "Hello" }],
|
|
441
|
+
* });
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Wraps an OpenAI client to automatically track all LLM calls.
|
|
447
|
+
* Returns a Proxy that is type-compatible with the original client.
|
|
448
|
+
*/
|
|
449
|
+
declare function wrapOpenAI<T extends object>(client: T, songlines: SonglinesClient, defaults?: WrapOptions): T;
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Anthropic SDK wrapper for Songlines Control.
|
|
453
|
+
*
|
|
454
|
+
* Wraps an Anthropic client instance so that every `messages.create()` call
|
|
455
|
+
* is automatically instrumented with telemetry.
|
|
456
|
+
*
|
|
457
|
+
* Prompt and completion text are NEVER captured — only metadata
|
|
458
|
+
* (model, tokens, latency, cost) is sent to the Songlines ingest API.
|
|
459
|
+
*
|
|
460
|
+
* @example
|
|
461
|
+
* ```typescript
|
|
462
|
+
* import Anthropic from "@anthropic-ai/sdk";
|
|
463
|
+
* import { SonglinesClient } from "@songlines/sdk";
|
|
464
|
+
*
|
|
465
|
+
* const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
466
|
+
* const songlines = new SonglinesClient({ apiKey: process.env.SONGLINES_API_KEY! });
|
|
467
|
+
*
|
|
468
|
+
* const instrumentedAnthropic = songlines.wrapAnthropic(anthropic, {
|
|
469
|
+
* workflow: "document-review",
|
|
470
|
+
* });
|
|
471
|
+
*
|
|
472
|
+
* const response = await instrumentedAnthropic.messages.create({
|
|
473
|
+
* model: "claude-3-5-sonnet-20241022",
|
|
474
|
+
* max_tokens: 1024,
|
|
475
|
+
* messages: [{ role: "user", content: "Hello" }],
|
|
476
|
+
* });
|
|
477
|
+
* ```
|
|
478
|
+
*/
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Wraps an Anthropic client to automatically track all `messages.create()` calls.
|
|
482
|
+
*/
|
|
483
|
+
declare function wrapAnthropic<T extends object>(client: T, songlines: SonglinesClient, defaults?: WrapOptions): T;
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Client-side cost estimation.
|
|
487
|
+
*
|
|
488
|
+
* Provides approximate USD costs based on publicly available per-million-token
|
|
489
|
+
* pricing. Actual costs may differ due to batch discounts, enterprise agreements,
|
|
490
|
+
* or provider pricing changes.
|
|
491
|
+
*
|
|
492
|
+
* Rates are per 1,000,000 tokens (input / output) in USD.
|
|
493
|
+
* Last updated: June 2026.
|
|
494
|
+
*/
|
|
495
|
+
interface ModelRates {
|
|
496
|
+
/** Cost per 1M input tokens in USD */
|
|
497
|
+
input: number;
|
|
498
|
+
/** Cost per 1M output tokens in USD */
|
|
499
|
+
output: number;
|
|
500
|
+
}
|
|
501
|
+
interface CostEstimateParams {
|
|
502
|
+
model: string;
|
|
503
|
+
inputTokens: number;
|
|
504
|
+
outputTokens: number;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Estimates the USD cost of an AI request based on public model pricing.
|
|
508
|
+
*
|
|
509
|
+
* @returns Estimated cost in USD, rounded to 8 decimal places.
|
|
510
|
+
* Returns 0 if token counts are 0.
|
|
511
|
+
*/
|
|
512
|
+
declare function estimateCost({ model, inputTokens, outputTokens }: CostEstimateParams): number;
|
|
513
|
+
/**
|
|
514
|
+
* Returns the known rate table. Useful for displaying pricing information.
|
|
515
|
+
*/
|
|
516
|
+
declare function getModelRates(): Readonly<Record<string, ModelRates>>;
|
|
517
|
+
|
|
518
|
+
export { type Environment, type EvaluateGuardrailParams, GuardrailBlockedError, type GuardrailDecision, type GuardrailResult, type GuardrailViolation, type IngestError, type IngestEvent, type IngestResponse, type IngestResult, InvalidApiKeyError, InvalidConfigError, NetworkError, PartialFailureError, type PolicyAction, QueueOverflowError, RateLimitedError, type RequestStatus, ServerError, SonglinesClient, type SonglinesClientConfig, SonglinesError, type SonglinesErrorCode, TimeoutError, type TrackAIRequestParams, type WrapOptions, estimateCost, getModelRates, wrapAnthropic, wrapOpenAI };
|