deadpipe 1.0.0 → 2.0.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/dist/index.d.ts CHANGED
@@ -1,105 +1,162 @@
1
1
  /**
2
- * Deadpipe - Dead simple pipeline monitoring.
2
+ * Deadpipe - LLM observability that answers one question:
3
+ * "Is this prompt behaving the same as when it was last safe?"
3
4
  *
4
5
  * @example
5
- * import { Deadpipe } from 'deadpipe';
6
+ * import { track } from 'deadpipe';
7
+ * import OpenAI from 'openai';
6
8
  *
7
- * const dp = new Deadpipe('your-api-key');
9
+ * const client = new OpenAI();
8
10
  *
9
- * // Option 1: Wrapper
10
- * await dp.run('my-pipeline', async () => {
11
- * // your code here
11
+ * const { response, tracker } = await track('checkout_agent', async (t) => {
12
+ * const response = await client.chat.completions.create({
13
+ * model: 'gpt-4',
14
+ * messages: [{ role: 'user', content: 'Process refund for order 1938' }]
15
+ * });
16
+ * t.record(response);
17
+ * return response;
12
18
  * });
13
19
  *
14
- * // Option 2: Manual
15
- * await dp.ping('my-pipeline', { status: 'success' });
20
+ * @example Auto-wrapping (zero code changes):
21
+ * import { wrapOpenAI } from 'deadpipe';
22
+ * import OpenAI from 'openai';
23
+ *
24
+ * const client = wrapOpenAI(new OpenAI(), { promptId: 'checkout_agent' });
25
+ * // All calls automatically tracked
26
+ * const response = await client.chat.completions.create(...);
16
27
  */
17
- type Status = 'success' | 'failed';
18
- interface PingOptions {
19
- status?: Status;
20
- durationMs?: number;
21
- recordsProcessed?: number;
22
- appName?: string;
28
+ declare const VERSION = "2.0.0";
29
+ type StatusType = 'success' | 'error' | 'timeout' | 'empty' | 'schema_violation' | 'refusal';
30
+ interface PromptTelemetry {
31
+ prompt_id: string;
32
+ model?: string;
33
+ provider?: string;
34
+ app_id?: string;
35
+ environment?: string;
36
+ version?: string;
37
+ request_start?: string;
38
+ first_token_time?: number;
39
+ end_time?: string;
40
+ total_latency?: number;
41
+ input_tokens?: number;
42
+ output_tokens?: number;
43
+ total_tokens?: number;
44
+ estimated_cost_usd?: number;
45
+ http_status?: number;
46
+ timeout?: boolean;
47
+ retry_count?: number;
48
+ provider_error_code?: string;
49
+ error_message?: string;
50
+ output_length?: number;
51
+ empty_output?: boolean;
52
+ truncated?: boolean;
53
+ json_parse_success?: boolean;
54
+ schema_validation_pass?: boolean;
55
+ missing_required_fields?: string;
56
+ output_hash?: string;
57
+ output_embedding?: string;
58
+ top_logprob_mean?: number;
59
+ refusal_flag?: boolean;
60
+ tool_call_flag?: boolean;
61
+ tool_calls_count?: number;
62
+ enum_out_of_range?: boolean;
63
+ numeric_out_of_bounds?: boolean;
64
+ hallucination_flags?: string;
65
+ prompt_hash?: string;
66
+ tool_schema_hash?: string;
67
+ system_prompt_hash?: string;
68
+ status?: StatusType;
23
69
  }
24
- interface DeadpipeOptions {
70
+ interface TrackOptions {
25
71
  apiKey?: string;
26
72
  baseUrl?: string;
27
73
  timeout?: number;
74
+ appId?: string;
75
+ environment?: string;
76
+ version?: string;
77
+ provider?: 'openai' | 'anthropic' | string;
78
+ schema?: SchemaValidator;
79
+ enumFields?: Record<string, unknown[]>;
80
+ numericBounds?: Record<string, [number | null, number | null]>;
81
+ messages?: Array<{
82
+ role: string;
83
+ content: string;
84
+ [key: string]: unknown;
85
+ }>;
86
+ tools?: Array<Record<string, unknown>>;
87
+ systemPrompt?: string;
88
+ }
89
+ interface SchemaValidator {
90
+ validate: (data: unknown) => {
91
+ success: boolean;
92
+ data?: unknown;
93
+ errors?: string[];
94
+ };
95
+ }
96
+ interface WrapOpenAIOptions extends Omit<TrackOptions, 'messages' | 'tools' | 'systemPrompt'> {
97
+ promptId: string;
28
98
  }
29
- interface HeartbeatResponse {
30
- received: boolean;
31
- pipeline_id: string;
32
- timestamp: string;
33
- freshness: 'fresh' | 'stale' | 'critical';
34
- next_expected: string;
35
- created?: boolean;
36
- message?: string;
99
+ declare function estimateCost(model: string, inputTokens: number, outputTokens: number): number | null;
100
+ declare function detectRefusal(text: string): boolean;
101
+ declare function validateEnumBounds(data: Record<string, unknown>, enumFields?: Record<string, unknown[]>): boolean;
102
+ declare function validateNumericBounds(data: Record<string, unknown>, numericBounds?: Record<string, [number | null, number | null]>): boolean;
103
+ interface ExtractedResponse {
104
+ model: string;
105
+ content: string;
106
+ inputTokens: number | null;
107
+ outputTokens: number | null;
108
+ totalTokens: number | null;
109
+ finishReason: string | null;
110
+ toolCalls: Array<{
111
+ name: string;
112
+ arguments: string;
113
+ }>;
114
+ logprobs: unknown;
37
115
  }
38
- declare class Deadpipe {
116
+ declare function extractOpenAIResponse(response: any): ExtractedResponse;
117
+ declare function extractAnthropicResponse(response: any): ExtractedResponse;
118
+ declare class PromptTracker {
119
+ private promptId;
39
120
  private apiKey;
40
121
  private baseUrl;
41
- private timeout;
42
- /**
43
- * Create a Deadpipe client.
44
- *
45
- * @param apiKey - Your Deadpipe API key. Falls back to DEADPIPE_API_KEY env var.
46
- * @param options - Configuration options.
47
- */
48
- constructor(apiKey?: string, options?: Omit<DeadpipeOptions, 'apiKey'>);
49
- /**
50
- * Send a heartbeat ping for a pipeline.
51
- *
52
- * @param pipelineId - Unique identifier for this pipeline.
53
- * @param options - Ping options.
54
- * @returns The heartbeat response, or null if the request failed.
55
- */
56
- ping(pipelineId: string, options?: PingOptions): Promise<HeartbeatResponse | null>;
57
- /**
58
- * Run a function with automatic heartbeat on completion.
59
- *
60
- * @param pipelineId - Unique identifier for this pipeline.
61
- * @param fn - The function to run.
62
- * @param options - Additional options.
63
- * @returns The result of the function.
64
- *
65
- * @example
66
- * const result = await dp.run('daily-etl', async () => {
67
- * const records = await processData();
68
- * return { recordsProcessed: records.length };
69
- * });
70
- */
71
- run<T>(pipelineId: string, fn: () => T | Promise<T>, options?: {
72
- appName?: string;
73
- }): Promise<T>;
74
- /**
75
- * Create a wrapper function that auto-sends heartbeats.
76
- *
77
- * @param pipelineId - Unique identifier for this pipeline.
78
- * @param fn - The function to wrap.
79
- * @param options - Additional options.
80
- * @returns A wrapped function.
81
- *
82
- * @example
83
- * const myPipeline = dp.wrap('daily-etl', async () => {
84
- * await processData();
85
- * });
86
- *
87
- * // Later...
88
- * await myPipeline();
89
- */
90
- wrap<T extends (...args: unknown[]) => unknown>(pipelineId: string, fn: T, options?: {
91
- appName?: string;
92
- }): (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>;
122
+ private timeoutMs;
123
+ private appId;
124
+ private environment;
125
+ private versionStr;
126
+ private provider;
127
+ private schema;
128
+ private enumFields;
129
+ private numericBounds;
130
+ private promptHash;
131
+ private toolSchemaHash;
132
+ private systemPromptHash;
133
+ private startTime;
134
+ private firstTokenTime;
135
+ private endTime;
136
+ private telemetry;
137
+ private recorded;
138
+ private retryCount;
139
+ constructor(promptId: string, options?: TrackOptions);
140
+ start(): void;
141
+ markFirstToken(): void;
142
+ markRetry(): void;
143
+ record(response: any, parsedOutput?: unknown): unknown;
144
+ recordError(error: Error): void;
145
+ private send;
146
+ isRecorded(): boolean;
147
+ getTelemetry(): PromptTelemetry;
93
148
  }
94
- /**
95
- * Send a heartbeat using DEADPIPE_API_KEY from environment.
96
- */
97
- declare function ping(pipelineId: string, options?: PingOptions): Promise<HeartbeatResponse | null>;
98
- /**
99
- * Run a function with automatic heartbeat using DEADPIPE_API_KEY from environment.
100
- */
101
- declare function run<T>(pipelineId: string, fn: () => T | Promise<T>, options?: {
102
- appName?: string;
103
- }): Promise<T>;
149
+ declare function track<T>(promptId: string, fn: (tracker: PromptTracker) => Promise<T>, options?: TrackOptions): Promise<T>;
150
+ type OpenAIClient = any;
151
+ interface TrackedCompletions {
152
+ create: (params: any) => Promise<any>;
153
+ }
154
+ interface TrackedChat {
155
+ completions: TrackedCompletions;
156
+ }
157
+ interface TrackedOpenAIClient extends OpenAIClient {
158
+ chat: TrackedChat;
159
+ }
160
+ declare function wrapOpenAI(client: OpenAIClient, options: WrapOpenAIOptions): TrackedOpenAIClient;
104
161
 
105
- export { Deadpipe, type DeadpipeOptions, type HeartbeatResponse, type PingOptions, type Status, Deadpipe as default, ping, run };
162
+ export { type PromptTelemetry, PromptTracker, type SchemaValidator, type StatusType, type TrackOptions, VERSION, type WrapOpenAIOptions, detectRefusal, estimateCost, extractAnthropicResponse, extractOpenAIResponse, track, validateEnumBounds, validateNumericBounds, wrapOpenAI };