teckel-ai 0.3.3 → 0.3.6

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.
@@ -1,310 +0,0 @@
1
- "use strict";
2
- /**
3
- * Conversation class for teckel-ai SDK v0.3.2
4
- * Manages a single conversation with fire-and-forget semantics
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.Conversation = void 0;
8
- const schemas_1 = require("./schemas");
9
- class Conversation {
10
- constructor(apiKey, endpoint, options, debug = false, extras = { timeoutMs: 5000 }) {
11
- this.turnCount = 0;
12
- this.sendQueue = Promise.resolve();
13
- this.apiKey = apiKey;
14
- this.endpoint = endpoint;
15
- this.sessionRef = options.sessionRef;
16
- this.userId = options.userId;
17
- this.metadata = options.metadata;
18
- this.startedAt = new Date();
19
- this.debug = debug;
20
- this.timeoutMs = extras.timeoutMs;
21
- if (this.debug) {
22
- console.log('[Teckel] Conversation started:', {
23
- sessionRef: this.sessionRef,
24
- userId: this.userId
25
- });
26
- }
27
- // Start conversation and store promise
28
- this.startPromise = this._startConversation().catch(err => {
29
- if (this.debug) {
30
- console.warn('[Teckel] Start failed:', err.message);
31
- }
32
- });
33
- }
34
- /**
35
- * Record a trace (single query-response interaction)
36
- * Fire-and-forget by default - never blocks
37
- * For serverless, call flush() before function termination
38
- */
39
- trace(data) {
40
- var _a;
41
- try {
42
- // Validate with Zod
43
- const validated = schemas_1.TraceDataSchema.parse(data);
44
- // Increment local turn number immediately (client-side counter)
45
- const localTurn = ++this.turnCount;
46
- // Ensure we have a client-provided traceRef; if missing, generate a deterministic one
47
- const finalTraceRef = validated.traceRef && validated.traceRef.length > 0
48
- ? validated.traceRef
49
- : `${this.sessionRef}:${localTurn}`;
50
- if (this.debug) {
51
- console.log('[Teckel] Queueing trace (fire-and-forget):', {
52
- sessionRef: this.sessionRef,
53
- turnNumber: localTurn,
54
- queryLength: validated.query.length,
55
- responseLength: validated.response.length,
56
- documentCount: ((_a = validated.documents) === null || _a === void 0 ? void 0 : _a.length) || 0
57
- });
58
- }
59
- const toSend = Object.assign(Object.assign({}, validated), { traceRef: finalTraceRef });
60
- // Fire-and-forget: enqueue and return immediately
61
- this.enqueueSend(async () => {
62
- try {
63
- await this.startPromise; // ensure conversation exists
64
- await this._sendTrace(toSend);
65
- }
66
- catch (err) {
67
- if (this.debug) {
68
- const msg = err instanceof Error ? err.message : String(err);
69
- console.warn('[Teckel] Trace send failed (non-blocking):', msg);
70
- }
71
- }
72
- });
73
- return { traceRef: finalTraceRef, turnNumber: localTurn };
74
- }
75
- catch (err) {
76
- // Validation failed - log and continue (never throw to user)
77
- if (this.debug) {
78
- console.warn('[Teckel] Invalid trace data:', err);
79
- }
80
- }
81
- }
82
- /**
83
- * Add user feedback signal
84
- * Never throws - gracefully handles errors
85
- */
86
- async feedback(data) {
87
- try {
88
- // Validate with Zod
89
- const validated = schemas_1.FeedbackDataSchema.parse(data);
90
- if (this.debug) {
91
- console.log('[Teckel] Sending feedback:', {
92
- sessionRef: this.sessionRef,
93
- type: validated.type
94
- });
95
- }
96
- // Enqueue feedback so flush() covers it in serverless
97
- this.enqueueSend(async () => {
98
- try {
99
- await this._sendFeedback(validated);
100
- }
101
- catch (err) {
102
- if (this.debug) {
103
- const msg = err instanceof Error ? err.message : String(err);
104
- console.warn('[Teckel] Feedback failed:', msg);
105
- }
106
- }
107
- });
108
- }
109
- catch (err) {
110
- // Validation failed - log and continue
111
- if (this.debug) {
112
- console.warn('[Teckel] Invalid feedback data:', err);
113
- }
114
- }
115
- }
116
- /**
117
- * End the conversation
118
- * Flushes all pending traces before sending end signal
119
- * Never throws - gracefully handles errors
120
- */
121
- async end() {
122
- const duration = Date.now() - this.startedAt.getTime();
123
- if (this.debug) {
124
- console.log('[Teckel] Ending conversation:', {
125
- sessionRef: this.sessionRef,
126
- durationMs: duration,
127
- turnCount: this.turnCount
128
- });
129
- }
130
- // Enqueue end so it occurs after any pending sends
131
- this.enqueueSend(async () => {
132
- try {
133
- await this._endConversation(duration);
134
- }
135
- catch (err) {
136
- if (this.debug) {
137
- const msg = err instanceof Error ? err.message : String(err);
138
- console.warn('[Teckel] End failed:', msg);
139
- }
140
- }
141
- });
142
- // Flush queue (serverless-safe)
143
- await this.flush();
144
- }
145
- /**
146
- * Read-only properties
147
- */
148
- get id() {
149
- return this.sessionRef;
150
- }
151
- get turns() {
152
- return this.turnCount;
153
- }
154
- get started() {
155
- return this.startedAt;
156
- }
157
- // Private HTTP methods
158
- // Lightweight fetch with a single retry on transient errors (429/5xx or network)
159
- async fetchWithRetry(url, init, opts) {
160
- var _a, _b;
161
- const retries = (_a = opts === null || opts === void 0 ? void 0 : opts.retries) !== null && _a !== void 0 ? _a : 1;
162
- const retryDelayMs = (_b = opts === null || opts === void 0 ? void 0 : opts.retryDelayMs) !== null && _b !== void 0 ? _b : 250;
163
- let attempt = 0;
164
- // Simple jittered delay
165
- const sleep = (ms) => new Promise(res => setTimeout(res, ms));
166
- // We reuse the same init; AbortSignal.timeout recreates a fresh signal per call
167
- while (true) {
168
- try {
169
- const response = await fetch(url, init);
170
- if (!response.ok && (response.status === 429 || (response.status >= 500 && response.status <= 599))) {
171
- if (attempt < retries) {
172
- attempt++;
173
- if (this.debug)
174
- console.warn('[Teckel] HTTP retry', { url, status: response.status, attempt });
175
- await sleep(retryDelayMs + Math.floor(Math.random() * 100));
176
- continue;
177
- }
178
- }
179
- return response;
180
- }
181
- catch (err) {
182
- if (attempt < retries) {
183
- attempt++;
184
- if (this.debug)
185
- console.warn('[Teckel] Network retry', { url, attempt, error: err instanceof Error ? err.message : String(err) });
186
- await sleep(retryDelayMs + Math.floor(Math.random() * 100));
187
- continue;
188
- }
189
- throw err;
190
- }
191
- }
192
- }
193
- async _startConversation() {
194
- const response = await this.fetchWithRetry(`${this.endpoint}/conversations`, {
195
- method: 'POST',
196
- headers: {
197
- 'Authorization': `Bearer ${this.apiKey}`,
198
- 'Content-Type': 'application/json'
199
- },
200
- keepalive: true,
201
- signal: getTimeoutSignal(this.timeoutMs),
202
- body: JSON.stringify({
203
- sessionRef: this.sessionRef,
204
- userId: this.userId,
205
- metadata: this.metadata
206
- })
207
- }, { retries: 1, retryDelayMs: 300 });
208
- if (!response.ok) {
209
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
210
- }
211
- }
212
- async _sendTrace(data, opt) {
213
- var _a;
214
- const response = await this.fetchWithRetry(`${this.endpoint}/conversations/${this.sessionRef}/traces`, {
215
- method: 'POST',
216
- headers: {
217
- 'Authorization': `Bearer ${this.apiKey}`,
218
- 'Content-Type': 'application/json'
219
- },
220
- keepalive: true,
221
- signal: getTimeoutSignal((_a = opt === null || opt === void 0 ? void 0 : opt.timeoutMs) !== null && _a !== void 0 ? _a : this.timeoutMs),
222
- body: JSON.stringify(data)
223
- }, { retries: 1, retryDelayMs: 300 });
224
- if (!response.ok) {
225
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
226
- }
227
- const result = await response.json();
228
- return result;
229
- }
230
- async _sendFeedback(data) {
231
- const response = await this.fetchWithRetry(`${this.endpoint}/conversations/${this.sessionRef}/feedback`, {
232
- method: 'POST',
233
- headers: {
234
- 'Authorization': `Bearer ${this.apiKey}`,
235
- 'Content-Type': 'application/json'
236
- },
237
- keepalive: true,
238
- signal: getTimeoutSignal(this.timeoutMs),
239
- body: JSON.stringify(data)
240
- }, { retries: 1, retryDelayMs: 300 });
241
- if (!response.ok) {
242
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
243
- }
244
- }
245
- async _endConversation(duration) {
246
- const response = await this.fetchWithRetry(`${this.endpoint}/conversations/${this.sessionRef}`, {
247
- method: 'PATCH',
248
- headers: {
249
- 'Authorization': `Bearer ${this.apiKey}`,
250
- 'Content-Type': 'application/json'
251
- },
252
- keepalive: true,
253
- signal: getTimeoutSignal(this.timeoutMs),
254
- body: JSON.stringify({
255
- durationMs: duration,
256
- turnCount: this.turnCount
257
- })
258
- }, { retries: 1, retryDelayMs: 300 });
259
- if (!response.ok) {
260
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
261
- }
262
- }
263
- // Utility: append a send task to the queue
264
- enqueueSend(task) {
265
- this.sendQueue = this.sendQueue.then(() => task()).catch(() => {
266
- // Errors are handled where task is defined; keep queue alive
267
- });
268
- }
269
- /**
270
- * Flush queued sends with a bounded timeout.
271
- * Returns when the queue is empty or the timeout elapses (whichever comes first).
272
- */
273
- async flush(timeoutMs) {
274
- const waitMs = (typeof timeoutMs === 'number' && Number.isFinite(timeoutMs) && timeoutMs >= 0)
275
- ? timeoutMs
276
- : this.timeoutMs;
277
- // Snapshot current queue to cover all work up to this call
278
- const done = this.sendQueue.catch(() => { });
279
- let timer;
280
- try {
281
- await Promise.race([
282
- done,
283
- new Promise((_, reject) => {
284
- timer = setTimeout(() => reject(new Error('Flush timeout')), waitMs);
285
- })
286
- ]);
287
- }
288
- catch (err) {
289
- if (this.debug) {
290
- const msg = err instanceof Error ? err.message : String(err);
291
- console.warn('[Teckel] Flush incomplete:', msg);
292
- }
293
- // Surface timeout so callers can react in serverless
294
- throw err;
295
- }
296
- finally {
297
- if (timer)
298
- clearTimeout(timer);
299
- }
300
- }
301
- }
302
- exports.Conversation = Conversation;
303
- // Helper: get AbortSignal.timeout if available
304
- function getTimeoutSignal(ms) {
305
- const timeout = AbortSignal.timeout;
306
- if (typeof timeout === 'function' && typeof ms === 'number') {
307
- return timeout(ms);
308
- }
309
- return undefined;
310
- }
package/dist/schemas.js DELETED
@@ -1,69 +0,0 @@
1
- "use strict";
2
- /**
3
- * Zod validation schemas for teckel-ai SDK v0.3.2
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.TeckelConfigSchema = exports.FeedbackDataSchema = exports.ConversationOptionsSchema = exports.TraceDataSchema = exports.TokenUsageSchema = exports.DocumentSchema = void 0;
7
- const zod_1 = require("zod");
8
- /**
9
- * Document schema
10
- */
11
- exports.DocumentSchema = zod_1.z.object({
12
- documentRef: zod_1.z.string().min(1, 'documentRef is required'),
13
- documentName: zod_1.z.string().min(1, 'documentName is required'),
14
- documentText: zod_1.z.string().min(1, 'documentText is required'),
15
- documentLastUpdated: zod_1.z.string().optional(),
16
- sourceUri: zod_1.z.string().optional(),
17
- sourceType: zod_1.z.string().optional(),
18
- similarity: zod_1.z.number().min(0).max(1).optional(),
19
- rank: zod_1.z.number().int().nonnegative().optional(),
20
- ownerEmail: zod_1.z.string().email().optional(),
21
- documentType: zod_1.z.string().optional()
22
- });
23
- /**
24
- * Token usage schema
25
- */
26
- exports.TokenUsageSchema = zod_1.z.object({
27
- prompt: zod_1.z.number().int().nonnegative(),
28
- completion: zod_1.z.number().int().nonnegative(),
29
- total: zod_1.z.number().int().nonnegative()
30
- });
31
- /**
32
- * Trace data schema
33
- */
34
- exports.TraceDataSchema = zod_1.z.object({
35
- query: zod_1.z.string().min(1, 'query is required').max(10000, 'query too long (max 10,000 characters)'),
36
- response: zod_1.z.string().min(1, 'response is required').max(50000, 'response too long (max 50,000 characters)'),
37
- model: zod_1.z.string().optional(),
38
- responseTimeMs: zod_1.z.number().positive().optional(),
39
- documents: zod_1.z.array(exports.DocumentSchema).max(50, 'Too many documents (max 50)').optional(),
40
- tokens: exports.TokenUsageSchema.optional(),
41
- metadata: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
42
- traceRef: zod_1.z.string().min(1).optional()
43
- });
44
- /**
45
- * Conversation options schema
46
- */
47
- exports.ConversationOptionsSchema = zod_1.z.object({
48
- sessionRef: zod_1.z.string().min(1, 'sessionRef is required'),
49
- userId: zod_1.z.string().optional(),
50
- metadata: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional()
51
- });
52
- /**
53
- * Feedback data schema
54
- */
55
- exports.FeedbackDataSchema = zod_1.z.object({
56
- type: zod_1.z.enum(['thumbs_up', 'thumbs_down', 'flag', 'rating']),
57
- value: zod_1.z.string().optional(),
58
- comment: zod_1.z.string().optional(),
59
- traceRef: zod_1.z.string().optional()
60
- });
61
- /**
62
- * Config schema
63
- */
64
- exports.TeckelConfigSchema = zod_1.z.object({
65
- apiKey: zod_1.z.string().min(1, 'apiKey is required'),
66
- endpoint: zod_1.z.string().url().optional(),
67
- debug: zod_1.z.boolean().optional(),
68
- timeoutMs: zod_1.z.number().int().positive().max(60000).optional()
69
- });
package/dist/tracer.d.ts DELETED
@@ -1,18 +0,0 @@
1
- /**
2
- * TeckelTracer - Main SDK class for teckel-ai v0.3.2
3
- * Simple, lightweight SDK for AI conversation tracking
4
- */
5
- import { Conversation } from './conversation';
6
- import type { TeckelConfig, ConversationOptions } from './types';
7
- export declare class TeckelTracer {
8
- private readonly apiKey;
9
- private readonly endpoint;
10
- private readonly debug;
11
- private readonly timeoutMs;
12
- constructor(config: TeckelConfig);
13
- /**
14
- * Start a new conversation
15
- * sessionRef IS the public conversation identifier
16
- */
17
- start(options: ConversationOptions): Conversation;
18
- }
package/dist/tracer.js DELETED
@@ -1,45 +0,0 @@
1
- "use strict";
2
- /**
3
- * TeckelTracer - Main SDK class for teckel-ai v0.3.2
4
- * Simple, lightweight SDK for AI conversation tracking
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.TeckelTracer = void 0;
8
- const conversation_1 = require("./conversation");
9
- const schemas_1 = require("./schemas");
10
- class TeckelTracer {
11
- constructor(config) {
12
- // Validate config with Zod
13
- const validated = schemas_1.TeckelConfigSchema.parse(config);
14
- // API key format warning
15
- if (!validated.apiKey.startsWith('tk_live_')) {
16
- console.warn('[Teckel] API key should start with "tk_live_". ' +
17
- 'Current key: ' + validated.apiKey.substring(0, 10) + '...');
18
- }
19
- this.apiKey = validated.apiKey;
20
- this.endpoint = validated.endpoint || 'https://app.teckel.ai/api';
21
- this.debug = validated.debug || false;
22
- // Default timeout mirrors common telemetry SDKs (3–5s) to tolerate cold starts
23
- this.timeoutMs = typeof validated.timeoutMs === 'number' ? validated.timeoutMs : 5000;
24
- if (this.debug) {
25
- console.log('[Teckel] SDK initialized:', {
26
- endpoint: this.endpoint,
27
- version: '0.3.2',
28
- timeoutMs: this.timeoutMs
29
- });
30
- }
31
- }
32
- /**
33
- * Start a new conversation
34
- * sessionRef IS the public conversation identifier
35
- */
36
- start(options) {
37
- // Validate options with Zod
38
- const validated = schemas_1.ConversationOptionsSchema.parse(options);
39
- // Create and return conversation instance
40
- return new conversation_1.Conversation(this.apiKey, this.endpoint, validated, this.debug, {
41
- timeoutMs: this.timeoutMs
42
- });
43
- }
44
- }
45
- exports.TeckelTracer = TeckelTracer;
package/dist/types.d.ts DELETED
@@ -1,88 +0,0 @@
1
- /**
2
- * Type definitions for teckel-ai SDK v0.3.2
3
- * Simple, clean types matching existing database schema
4
- */
5
- /**
6
- * SDK Configuration
7
- */
8
- export interface TeckelConfig {
9
- apiKey: string;
10
- endpoint?: string;
11
- debug?: boolean;
12
- timeoutMs?: number;
13
- }
14
- /**
15
- * Conversation options
16
- * sessionId IS the conversation identifier
17
- */
18
- export interface ConversationOptions {
19
- sessionRef: string;
20
- userId?: string;
21
- metadata?: Record<string, unknown>;
22
- }
23
- /**
24
- * Document structure for RAG systems
25
- * Matches existing documents + chunk_events schema
26
- */
27
- export interface Document {
28
- documentRef: string;
29
- documentName: string;
30
- documentText: string;
31
- documentLastUpdated?: string;
32
- sourceUri?: string;
33
- sourceType?: string;
34
- similarity?: number;
35
- rank?: number;
36
- ownerEmail?: string;
37
- documentType?: string;
38
- }
39
- /**
40
- * Token usage tracking
41
- */
42
- export interface TokenUsage {
43
- prompt: number;
44
- completion: number;
45
- total: number;
46
- }
47
- /**
48
- * Trace data for a single query-response interaction
49
- * Matches existing traces table schema
50
- */
51
- export interface TraceData {
52
- query: string;
53
- response: string;
54
- model?: string;
55
- responseTimeMs?: number;
56
- documents?: Document[];
57
- tokens?: TokenUsage;
58
- metadata?: Record<string, unknown>;
59
- traceRef?: string;
60
- }
61
- /**
62
- * Feedback types
63
- */
64
- export type FeedbackType = 'thumbs_up' | 'thumbs_down' | 'flag' | 'rating';
65
- /**
66
- * User feedback signal
67
- */
68
- export interface FeedbackData {
69
- type: FeedbackType;
70
- value?: string;
71
- comment?: string;
72
- traceRef?: string;
73
- }
74
- /**
75
- * Result returned when a trace is created
76
- */
77
- export interface TraceResult {
78
- traceRef: string;
79
- turnNumber: number;
80
- }
81
- /**
82
- * Validation result structure
83
- */
84
- export interface ValidationResult {
85
- valid: boolean;
86
- errors: string[];
87
- warnings: string[];
88
- }
package/dist/types.js DELETED
@@ -1,6 +0,0 @@
1
- "use strict";
2
- /**
3
- * Type definitions for teckel-ai SDK v0.3.2
4
- * Simple, clean types matching existing database schema
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });