teckel-ai 0.3.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Teckel AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # teckel-ai
2
+
3
+ ## What is Teckel AI?
4
+
5
+ Teckel AI helps you understand and improve your AI chatbots by analyzing conversations your users are having. We track what questions users ask, how well your AI answers them, and tell you which areas needs improvement.
6
+
7
+ **Your Problem**: Your RAG or MCP referencing AI chat system gives incomplete or incorrect answers because your knowledge base has gaps. Users get frustrated, support tickets increase, and you don't know which areas to focus on.
8
+
9
+ **Our Service**: We analyze every AI response for accuracy and completeness, cluster similar queries to identify trending topics (or let you define an area of interest and see related questions), and tell you exactly which AI-retrieved documentation to add or update, prioritized by impact. We write your document templates for you to fill in with info your users need, and give you updates on your AI system's health via Slack.
10
+
11
+ ## What This SDK Does
12
+
13
+ This lightweight SDK (one dependency, 20-minute integration) sends your AI conversations to Teckel for analysis. You get:
14
+
15
+ - **Completeness Scoring** - How well each response answers the user's question (0-100%)
16
+ - **Accuracy Analysis** - Whether AI claims are supported by your source documents
17
+ - **Topic Intelligence** - Automatic clustering of queries to reveal documentation gaps
18
+ - **Actionable Feedback** - Specific recommendations on what knowledge your AI needs to better answer user questions
19
+
20
+ Works with any RAG system or AI conversational framework: LangChain, LlamaIndex, Vercel AI SDK, custom implementations using vector database retrieval, or direct OpenAI/Anthropic calls.
21
+
22
+ ## Getting Started
23
+
24
+ 1. **Sign up** at [app.teckel.ai](https://app.teckel.ai) with a 14 day free trial
25
+ 2. **Generate an API key** from your dashboard (Admin Panel > API Keys)
26
+ 3. **Install the SDK**: `npm install teckel-ai`
27
+ 4. **Follow the integration guide** at [docs.teckel.ai/docs/getting-started](https://docs.teckel.ai/docs/getting-started)
28
+
29
+ ## Documentation
30
+
31
+ - [Getting Started Guide](https://docs.teckel.ai/docs/getting-started) - Step-by-step integration
32
+ - [API & SDK Reference](https://docs.teckel.ai/docs/api-sdk-reference) - Complete field documentation and framework examples
33
+ - [Troubleshooting](https://docs.teckel.ai/docs/troubleshooting) - Common issues and solutions
34
+
35
+ ## Requirements
36
+
37
+ - Node.js 18+ (or Bun, Deno, serverless runtimes)
38
+ - A Teckel AI account with API key
39
+ - An LLM-based application (RAG system, chatbot, AI agent)
40
+
41
+ ## Support
42
+
43
+ - **Documentation**: [docs.teckel.ai](https://docs.teckel.ai)
44
+ - **Dashboard**: [app.teckel.ai](https://app.teckel.ai)
45
+ - **Email**: support@teckel.ai
46
+
47
+ ## License
48
+
49
+ MIT
50
+
51
+ ---
52
+
53
+ Version 0.3.2
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Conversation class for teckel-ai SDK v0.3.1
3
+ * Manages a single conversation with fire-and-forget semantics
4
+ */
5
+ import type { TraceData, FeedbackData, ConversationOptions, TraceResult } from './types';
6
+ export declare class Conversation {
7
+ private readonly apiKey;
8
+ private readonly endpoint;
9
+ private readonly sessionRef;
10
+ private readonly userId?;
11
+ private readonly metadata?;
12
+ private readonly startedAt;
13
+ private readonly debug;
14
+ private readonly timeoutMs;
15
+ private turnCount;
16
+ private startPromise;
17
+ private sendQueue;
18
+ constructor(apiKey: string, endpoint: string, options: ConversationOptions, debug?: boolean, extras?: {
19
+ timeoutMs: number;
20
+ });
21
+ /**
22
+ * Record a trace (single query-response interaction)
23
+ * Fire-and-forget by default - never blocks
24
+ * For serverless, call flush() before function termination
25
+ */
26
+ trace(data: TraceData): TraceResult | void;
27
+ /**
28
+ * Synchronous trace: waits for HTTP send to complete.
29
+ * Throws on network/validation errors.
30
+ * Respects send queue to maintain trace ordering.
31
+ */
32
+ traceSync(data: TraceData, opt?: {
33
+ timeoutMs?: number;
34
+ }): Promise<TraceResult>;
35
+ /**
36
+ * Add user feedback signal
37
+ * Never throws - gracefully handles errors
38
+ */
39
+ feedback(data: FeedbackData): Promise<void>;
40
+ /**
41
+ * End the conversation
42
+ * Flushes all pending traces before sending end signal
43
+ * Never throws - gracefully handles errors
44
+ */
45
+ end(): Promise<void>;
46
+ /**
47
+ * Read-only properties
48
+ */
49
+ get id(): string;
50
+ get turns(): number;
51
+ get started(): Date;
52
+ private fetchWithRetry;
53
+ private _startConversation;
54
+ private _sendTrace;
55
+ private _sendFeedback;
56
+ private _endConversation;
57
+ private enqueueSend;
58
+ /**
59
+ * Flush queued sends with a bounded timeout.
60
+ * Returns when the queue is empty or the timeout elapses (whichever comes first).
61
+ */
62
+ flush(timeoutMs?: number): Promise<void>;
63
+ private mapOTelAliases;
64
+ }
@@ -0,0 +1,363 @@
1
+ "use strict";
2
+ /**
3
+ * Conversation class for teckel-ai SDK v0.3.1
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
+ // Apply OTel alias mapping (beta): infer canonical fields from metadata if missing
45
+ const mapped = this.mapOTelAliases(validated);
46
+ // Increment local turn number immediately (client-side counter)
47
+ const localTurn = ++this.turnCount;
48
+ // Ensure we have a client-provided traceRef; if missing, generate a deterministic one
49
+ const finalTraceRef = mapped.traceRef && mapped.traceRef.length > 0
50
+ ? mapped.traceRef
51
+ : `${this.sessionRef}:${localTurn}`;
52
+ if (this.debug) {
53
+ console.log('[Teckel] Queueing trace (fire-and-forget):', {
54
+ sessionRef: this.sessionRef,
55
+ turnNumber: localTurn,
56
+ queryLength: mapped.query.length,
57
+ responseLength: mapped.response.length,
58
+ documentCount: ((_a = mapped.documents) === null || _a === void 0 ? void 0 : _a.length) || 0
59
+ });
60
+ }
61
+ const toSend = Object.assign(Object.assign({}, mapped), { traceRef: finalTraceRef });
62
+ // Fire-and-forget: enqueue and return immediately
63
+ this.enqueueSend(async () => {
64
+ try {
65
+ await this.startPromise; // ensure conversation exists
66
+ await this._sendTrace(toSend);
67
+ }
68
+ catch (err) {
69
+ if (this.debug) {
70
+ console.warn('[Teckel] Trace send failed (non-blocking):', (err === null || err === void 0 ? void 0 : err.message) || err);
71
+ }
72
+ }
73
+ });
74
+ return { traceRef: finalTraceRef, turnNumber: localTurn };
75
+ }
76
+ catch (err) {
77
+ // Validation failed - log and continue (never throw to user)
78
+ if (this.debug) {
79
+ console.warn('[Teckel] Invalid trace data:', err);
80
+ }
81
+ }
82
+ }
83
+ /**
84
+ * Synchronous trace: waits for HTTP send to complete.
85
+ * Throws on network/validation errors.
86
+ * Respects send queue to maintain trace ordering.
87
+ */
88
+ async traceSync(data, opt) {
89
+ // Validate with Zod
90
+ const validated = schemas_1.TraceDataSchema.parse(data);
91
+ // Apply OTel alias mapping
92
+ const mapped = this.mapOTelAliases(validated);
93
+ // Increment local turn and compute final traceRef
94
+ const localTurn = ++this.turnCount;
95
+ const finalTraceRef = mapped.traceRef && mapped.traceRef.length > 0
96
+ ? mapped.traceRef
97
+ : `${this.sessionRef}:${localTurn}`;
98
+ const toSend = Object.assign(Object.assign({}, mapped), { traceRef: finalTraceRef });
99
+ try {
100
+ await this.startPromise;
101
+ // Wait for any queued operations to complete first (maintains ordering)
102
+ await this.sendQueue.catch(() => { });
103
+ await this._sendTrace(toSend, { timeoutMs: opt === null || opt === void 0 ? void 0 : opt.timeoutMs });
104
+ return { traceRef: finalTraceRef, turnNumber: localTurn };
105
+ }
106
+ catch (err) {
107
+ if (this.debug) {
108
+ console.warn('[Teckel] Sync trace failed:', (err === null || err === void 0 ? void 0 : err.message) || err);
109
+ }
110
+ throw err;
111
+ }
112
+ }
113
+ /**
114
+ * Add user feedback signal
115
+ * Never throws - gracefully handles errors
116
+ */
117
+ async feedback(data) {
118
+ try {
119
+ // Validate with Zod
120
+ const validated = schemas_1.FeedbackDataSchema.parse(data);
121
+ if (this.debug) {
122
+ console.log('[Teckel] Sending feedback:', {
123
+ sessionRef: this.sessionRef,
124
+ type: validated.type
125
+ });
126
+ }
127
+ // Enqueue feedback so flush() covers it in serverless
128
+ this.enqueueSend(async () => {
129
+ try {
130
+ await this._sendFeedback(validated);
131
+ }
132
+ catch (err) {
133
+ if (this.debug) {
134
+ console.warn('[Teckel] Feedback failed:', (err === null || err === void 0 ? void 0 : err.message) || err);
135
+ }
136
+ }
137
+ });
138
+ }
139
+ catch (err) {
140
+ // Validation failed - log and continue
141
+ if (this.debug) {
142
+ console.warn('[Teckel] Invalid feedback data:', err);
143
+ }
144
+ }
145
+ }
146
+ /**
147
+ * End the conversation
148
+ * Flushes all pending traces before sending end signal
149
+ * Never throws - gracefully handles errors
150
+ */
151
+ async end() {
152
+ const duration = Date.now() - this.startedAt.getTime();
153
+ if (this.debug) {
154
+ console.log('[Teckel] Ending conversation:', {
155
+ sessionRef: this.sessionRef,
156
+ durationMs: duration,
157
+ turnCount: this.turnCount
158
+ });
159
+ }
160
+ // Enqueue end so it occurs after any pending sends
161
+ this.enqueueSend(async () => {
162
+ try {
163
+ await this._endConversation(duration);
164
+ }
165
+ catch (err) {
166
+ if (this.debug) {
167
+ console.warn('[Teckel] End failed:', (err === null || err === void 0 ? void 0 : err.message) || err);
168
+ }
169
+ }
170
+ });
171
+ // Flush queue (serverless-safe)
172
+ await this.flush();
173
+ }
174
+ /**
175
+ * Read-only properties
176
+ */
177
+ get id() {
178
+ return this.sessionRef;
179
+ }
180
+ get turns() {
181
+ return this.turnCount;
182
+ }
183
+ get started() {
184
+ return this.startedAt;
185
+ }
186
+ // Private HTTP methods
187
+ // Lightweight fetch with a single retry on transient errors (429/5xx or network)
188
+ async fetchWithRetry(url, init, opts) {
189
+ var _a, _b;
190
+ const retries = (_a = opts === null || opts === void 0 ? void 0 : opts.retries) !== null && _a !== void 0 ? _a : 1;
191
+ const retryDelayMs = (_b = opts === null || opts === void 0 ? void 0 : opts.retryDelayMs) !== null && _b !== void 0 ? _b : 250;
192
+ let attempt = 0;
193
+ // Simple jittered delay
194
+ const sleep = (ms) => new Promise(res => setTimeout(res, ms));
195
+ // We reuse the same init; AbortSignal.timeout recreates a fresh signal per call
196
+ while (true) {
197
+ try {
198
+ const response = await fetch(url, init);
199
+ if (!response.ok && (response.status === 429 || (response.status >= 500 && response.status <= 599))) {
200
+ if (attempt < retries) {
201
+ attempt++;
202
+ if (this.debug)
203
+ console.warn('[Teckel] HTTP retry', { url, status: response.status, attempt });
204
+ await sleep(retryDelayMs + Math.floor(Math.random() * 100));
205
+ continue;
206
+ }
207
+ }
208
+ return response;
209
+ }
210
+ catch (err) {
211
+ if (attempt < retries) {
212
+ attempt++;
213
+ if (this.debug)
214
+ console.warn('[Teckel] Network retry', { url, attempt, error: err instanceof Error ? err.message : String(err) });
215
+ await sleep(retryDelayMs + Math.floor(Math.random() * 100));
216
+ continue;
217
+ }
218
+ throw err;
219
+ }
220
+ }
221
+ }
222
+ async _startConversation() {
223
+ const response = await this.fetchWithRetry(`${this.endpoint}/conversations`, {
224
+ method: 'POST',
225
+ headers: {
226
+ 'Authorization': `Bearer ${this.apiKey}`,
227
+ 'Content-Type': 'application/json'
228
+ },
229
+ keepalive: true,
230
+ signal: AbortSignal.timeout ? AbortSignal.timeout(this.timeoutMs) : undefined,
231
+ body: JSON.stringify({
232
+ sessionRef: this.sessionRef,
233
+ userId: this.userId,
234
+ metadata: this.metadata
235
+ })
236
+ }, { retries: 1, retryDelayMs: 300 });
237
+ if (!response.ok) {
238
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
239
+ }
240
+ }
241
+ async _sendTrace(data, opt) {
242
+ var _a;
243
+ const response = await this.fetchWithRetry(`${this.endpoint}/conversations/${this.sessionRef}/traces`, {
244
+ method: 'POST',
245
+ headers: {
246
+ 'Authorization': `Bearer ${this.apiKey}`,
247
+ 'Content-Type': 'application/json'
248
+ },
249
+ keepalive: true,
250
+ signal: AbortSignal.timeout ? AbortSignal.timeout((_a = opt === null || opt === void 0 ? void 0 : opt.timeoutMs) !== null && _a !== void 0 ? _a : this.timeoutMs) : undefined,
251
+ body: JSON.stringify(data)
252
+ }, { retries: 1, retryDelayMs: 300 });
253
+ if (!response.ok) {
254
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
255
+ }
256
+ const result = await response.json();
257
+ return result;
258
+ }
259
+ async _sendFeedback(data) {
260
+ const response = await this.fetchWithRetry(`${this.endpoint}/conversations/${this.sessionRef}/feedback`, {
261
+ method: 'POST',
262
+ headers: {
263
+ 'Authorization': `Bearer ${this.apiKey}`,
264
+ 'Content-Type': 'application/json'
265
+ },
266
+ keepalive: true,
267
+ signal: AbortSignal.timeout ? AbortSignal.timeout(this.timeoutMs) : undefined,
268
+ body: JSON.stringify(data)
269
+ }, { retries: 1, retryDelayMs: 300 });
270
+ if (!response.ok) {
271
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
272
+ }
273
+ }
274
+ async _endConversation(duration) {
275
+ const response = await this.fetchWithRetry(`${this.endpoint}/conversations/${this.sessionRef}`, {
276
+ method: 'PATCH',
277
+ headers: {
278
+ 'Authorization': `Bearer ${this.apiKey}`,
279
+ 'Content-Type': 'application/json'
280
+ },
281
+ keepalive: true,
282
+ signal: AbortSignal.timeout ? AbortSignal.timeout(this.timeoutMs) : undefined,
283
+ body: JSON.stringify({
284
+ durationMs: duration,
285
+ turnCount: this.turnCount
286
+ })
287
+ }, { retries: 1, retryDelayMs: 300 });
288
+ if (!response.ok) {
289
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
290
+ }
291
+ }
292
+ // Utility: append a send task to the queue
293
+ enqueueSend(task) {
294
+ this.sendQueue = this.sendQueue.then(() => task()).catch(() => {
295
+ // Errors are handled where task is defined; keep queue alive
296
+ });
297
+ }
298
+ /**
299
+ * Flush queued sends with a bounded timeout.
300
+ * Returns when the queue is empty or the timeout elapses (whichever comes first).
301
+ */
302
+ async flush(timeoutMs) {
303
+ const waitMs = (typeof timeoutMs === 'number' && Number.isFinite(timeoutMs) && timeoutMs >= 0)
304
+ ? timeoutMs
305
+ : this.timeoutMs;
306
+ // Snapshot current queue to cover all work up to this call
307
+ const done = this.sendQueue.catch(() => { });
308
+ let timer;
309
+ try {
310
+ await Promise.race([
311
+ done,
312
+ new Promise((_, reject) => {
313
+ timer = setTimeout(() => reject(new Error('Flush timeout')), waitMs);
314
+ })
315
+ ]);
316
+ }
317
+ catch (err) {
318
+ if (this.debug) {
319
+ console.warn('[Teckel] Flush incomplete:', (err === null || err === void 0 ? void 0 : err.message) || err);
320
+ }
321
+ // Surface timeout so callers can react in serverless
322
+ throw err;
323
+ }
324
+ finally {
325
+ if (timer)
326
+ clearTimeout(timer);
327
+ }
328
+ }
329
+ // Utility: map OpenTelemetry-like metadata to canonical fields (beta)
330
+ mapOTelAliases(data) {
331
+ try {
332
+ const meta = data.metadata;
333
+ if (!meta)
334
+ return data;
335
+ const mapped = Object.assign({}, data);
336
+ // Model
337
+ if (!mapped.model && typeof meta['gen_ai.request.model'] === 'string') {
338
+ mapped.model = meta['gen_ai.request.model'];
339
+ }
340
+ // Tokens
341
+ const inTok = meta['gen_ai.usage.input_tokens'];
342
+ const outTok = meta['gen_ai.usage.output_tokens'];
343
+ const totTok = meta['gen_ai.usage.total_tokens'];
344
+ if (!mapped.tokens && (typeof inTok === 'number' || typeof outTok === 'number')) {
345
+ mapped.tokens = {
346
+ prompt: typeof inTok === 'number' ? inTok : 0,
347
+ completion: typeof outTok === 'number' ? outTok : 0,
348
+ total: typeof totTok === 'number' ? totTok : ((typeof inTok === 'number' ? inTok : 0) + (typeof outTok === 'number' ? outTok : 0))
349
+ };
350
+ }
351
+ // Latency
352
+ const latency = meta['gen_ai.response.latency'];
353
+ if (!mapped.responseTimeMs && typeof latency === 'number') {
354
+ mapped.responseTimeMs = latency;
355
+ }
356
+ return mapped;
357
+ }
358
+ catch (_a) {
359
+ return data;
360
+ }
361
+ }
362
+ }
363
+ exports.Conversation = Conversation;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * teckel-ai v0.3.1
3
+ * Simple SDK for AI conversation tracking and RAG observability
4
+ *
5
+ * @packageDocumentation
6
+ */
7
+ export { TeckelTracer } from './tracer';
8
+ export { Conversation } from './conversation';
9
+ export type { TeckelConfig, ConversationOptions, TraceData, Document, TokenUsage, FeedbackData, FeedbackType, ValidationResult, TraceResult } from './types';
10
+ export { TeckelConfigSchema, ConversationOptionsSchema, TraceDataSchema, DocumentSchema, TokenUsageSchema, FeedbackDataSchema } from './schemas';
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /**
3
+ * teckel-ai v0.3.1
4
+ * Simple SDK for AI conversation tracking and RAG observability
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.FeedbackDataSchema = exports.TokenUsageSchema = exports.DocumentSchema = exports.TraceDataSchema = exports.ConversationOptionsSchema = exports.TeckelConfigSchema = exports.Conversation = exports.TeckelTracer = void 0;
10
+ // Main SDK exports
11
+ var tracer_1 = require("./tracer");
12
+ Object.defineProperty(exports, "TeckelTracer", { enumerable: true, get: function () { return tracer_1.TeckelTracer; } });
13
+ var conversation_1 = require("./conversation");
14
+ Object.defineProperty(exports, "Conversation", { enumerable: true, get: function () { return conversation_1.Conversation; } });
15
+ // Schema exports (for advanced use cases)
16
+ var schemas_1 = require("./schemas");
17
+ Object.defineProperty(exports, "TeckelConfigSchema", { enumerable: true, get: function () { return schemas_1.TeckelConfigSchema; } });
18
+ Object.defineProperty(exports, "ConversationOptionsSchema", { enumerable: true, get: function () { return schemas_1.ConversationOptionsSchema; } });
19
+ Object.defineProperty(exports, "TraceDataSchema", { enumerable: true, get: function () { return schemas_1.TraceDataSchema; } });
20
+ Object.defineProperty(exports, "DocumentSchema", { enumerable: true, get: function () { return schemas_1.DocumentSchema; } });
21
+ Object.defineProperty(exports, "TokenUsageSchema", { enumerable: true, get: function () { return schemas_1.TokenUsageSchema; } });
22
+ Object.defineProperty(exports, "FeedbackDataSchema", { enumerable: true, get: function () { return schemas_1.FeedbackDataSchema; } });
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Zod validation schemas for teckel-ai SDK v0.3.1
3
+ */
4
+ import { z } from 'zod';
5
+ /**
6
+ * Document schema
7
+ */
8
+ export declare const DocumentSchema: z.ZodObject<{
9
+ documentRef: z.ZodString;
10
+ documentName: z.ZodString;
11
+ documentText: z.ZodString;
12
+ documentLastUpdated: z.ZodOptional<z.ZodString>;
13
+ sourceUri: z.ZodOptional<z.ZodString>;
14
+ sourceType: z.ZodOptional<z.ZodString>;
15
+ similarity: z.ZodOptional<z.ZodNumber>;
16
+ rank: z.ZodOptional<z.ZodNumber>;
17
+ ownerEmail: z.ZodOptional<z.ZodString>;
18
+ documentType: z.ZodOptional<z.ZodString>;
19
+ }, "strip", z.ZodTypeAny, {
20
+ documentRef: string;
21
+ documentName: string;
22
+ documentText: string;
23
+ documentLastUpdated?: string | undefined;
24
+ sourceUri?: string | undefined;
25
+ sourceType?: string | undefined;
26
+ similarity?: number | undefined;
27
+ rank?: number | undefined;
28
+ ownerEmail?: string | undefined;
29
+ documentType?: string | undefined;
30
+ }, {
31
+ documentRef: string;
32
+ documentName: string;
33
+ documentText: string;
34
+ documentLastUpdated?: string | undefined;
35
+ sourceUri?: string | undefined;
36
+ sourceType?: string | undefined;
37
+ similarity?: number | undefined;
38
+ rank?: number | undefined;
39
+ ownerEmail?: string | undefined;
40
+ documentType?: string | undefined;
41
+ }>;
42
+ /**
43
+ * Token usage schema
44
+ */
45
+ export declare const TokenUsageSchema: z.ZodObject<{
46
+ prompt: z.ZodNumber;
47
+ completion: z.ZodNumber;
48
+ total: z.ZodNumber;
49
+ }, "strip", z.ZodTypeAny, {
50
+ prompt: number;
51
+ completion: number;
52
+ total: number;
53
+ }, {
54
+ prompt: number;
55
+ completion: number;
56
+ total: number;
57
+ }>;
58
+ /**
59
+ * Trace data schema
60
+ */
61
+ export declare const TraceDataSchema: z.ZodObject<{
62
+ query: z.ZodString;
63
+ response: z.ZodString;
64
+ model: z.ZodOptional<z.ZodString>;
65
+ responseTimeMs: z.ZodOptional<z.ZodNumber>;
66
+ documents: z.ZodOptional<z.ZodArray<z.ZodObject<{
67
+ documentRef: z.ZodString;
68
+ documentName: z.ZodString;
69
+ documentText: z.ZodString;
70
+ documentLastUpdated: z.ZodOptional<z.ZodString>;
71
+ sourceUri: z.ZodOptional<z.ZodString>;
72
+ sourceType: z.ZodOptional<z.ZodString>;
73
+ similarity: z.ZodOptional<z.ZodNumber>;
74
+ rank: z.ZodOptional<z.ZodNumber>;
75
+ ownerEmail: z.ZodOptional<z.ZodString>;
76
+ documentType: z.ZodOptional<z.ZodString>;
77
+ }, "strip", z.ZodTypeAny, {
78
+ documentRef: string;
79
+ documentName: string;
80
+ documentText: string;
81
+ documentLastUpdated?: string | undefined;
82
+ sourceUri?: string | undefined;
83
+ sourceType?: string | undefined;
84
+ similarity?: number | undefined;
85
+ rank?: number | undefined;
86
+ ownerEmail?: string | undefined;
87
+ documentType?: string | undefined;
88
+ }, {
89
+ documentRef: string;
90
+ documentName: string;
91
+ documentText: string;
92
+ documentLastUpdated?: string | undefined;
93
+ sourceUri?: string | undefined;
94
+ sourceType?: string | undefined;
95
+ similarity?: number | undefined;
96
+ rank?: number | undefined;
97
+ ownerEmail?: string | undefined;
98
+ documentType?: string | undefined;
99
+ }>, "many">>;
100
+ tokens: z.ZodOptional<z.ZodObject<{
101
+ prompt: z.ZodNumber;
102
+ completion: z.ZodNumber;
103
+ total: z.ZodNumber;
104
+ }, "strip", z.ZodTypeAny, {
105
+ prompt: number;
106
+ completion: number;
107
+ total: number;
108
+ }, {
109
+ prompt: number;
110
+ completion: number;
111
+ total: number;
112
+ }>>;
113
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
114
+ traceRef: z.ZodOptional<z.ZodString>;
115
+ }, "strip", z.ZodTypeAny, {
116
+ query: string;
117
+ response: string;
118
+ model?: string | undefined;
119
+ responseTimeMs?: number | undefined;
120
+ documents?: {
121
+ documentRef: string;
122
+ documentName: string;
123
+ documentText: string;
124
+ documentLastUpdated?: string | undefined;
125
+ sourceUri?: string | undefined;
126
+ sourceType?: string | undefined;
127
+ similarity?: number | undefined;
128
+ rank?: number | undefined;
129
+ ownerEmail?: string | undefined;
130
+ documentType?: string | undefined;
131
+ }[] | undefined;
132
+ tokens?: {
133
+ prompt: number;
134
+ completion: number;
135
+ total: number;
136
+ } | undefined;
137
+ metadata?: Record<string, any> | undefined;
138
+ traceRef?: string | undefined;
139
+ }, {
140
+ query: string;
141
+ response: string;
142
+ model?: string | undefined;
143
+ responseTimeMs?: number | undefined;
144
+ documents?: {
145
+ documentRef: string;
146
+ documentName: string;
147
+ documentText: string;
148
+ documentLastUpdated?: string | undefined;
149
+ sourceUri?: string | undefined;
150
+ sourceType?: string | undefined;
151
+ similarity?: number | undefined;
152
+ rank?: number | undefined;
153
+ ownerEmail?: string | undefined;
154
+ documentType?: string | undefined;
155
+ }[] | undefined;
156
+ tokens?: {
157
+ prompt: number;
158
+ completion: number;
159
+ total: number;
160
+ } | undefined;
161
+ metadata?: Record<string, any> | undefined;
162
+ traceRef?: string | undefined;
163
+ }>;
164
+ /**
165
+ * Conversation options schema
166
+ */
167
+ export declare const ConversationOptionsSchema: z.ZodObject<{
168
+ sessionRef: z.ZodString;
169
+ userId: z.ZodOptional<z.ZodString>;
170
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
171
+ }, "strip", z.ZodTypeAny, {
172
+ sessionRef: string;
173
+ metadata?: Record<string, any> | undefined;
174
+ userId?: string | undefined;
175
+ }, {
176
+ sessionRef: string;
177
+ metadata?: Record<string, any> | undefined;
178
+ userId?: string | undefined;
179
+ }>;
180
+ /**
181
+ * Feedback data schema
182
+ */
183
+ export declare const FeedbackDataSchema: z.ZodObject<{
184
+ type: z.ZodEnum<["thumbs_up", "thumbs_down", "flag", "rating"]>;
185
+ value: z.ZodOptional<z.ZodString>;
186
+ comment: z.ZodOptional<z.ZodString>;
187
+ traceRef: z.ZodOptional<z.ZodString>;
188
+ }, "strip", z.ZodTypeAny, {
189
+ type: "thumbs_up" | "thumbs_down" | "flag" | "rating";
190
+ value?: string | undefined;
191
+ traceRef?: string | undefined;
192
+ comment?: string | undefined;
193
+ }, {
194
+ type: "thumbs_up" | "thumbs_down" | "flag" | "rating";
195
+ value?: string | undefined;
196
+ traceRef?: string | undefined;
197
+ comment?: string | undefined;
198
+ }>;
199
+ /**
200
+ * Config schema
201
+ */
202
+ export declare const TeckelConfigSchema: z.ZodObject<{
203
+ apiKey: z.ZodString;
204
+ endpoint: z.ZodOptional<z.ZodString>;
205
+ debug: z.ZodOptional<z.ZodBoolean>;
206
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
207
+ }, "strip", z.ZodTypeAny, {
208
+ apiKey: string;
209
+ endpoint?: string | undefined;
210
+ debug?: boolean | undefined;
211
+ timeoutMs?: number | undefined;
212
+ }, {
213
+ apiKey: string;
214
+ endpoint?: string | undefined;
215
+ debug?: boolean | undefined;
216
+ timeoutMs?: number | undefined;
217
+ }>;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * Zod validation schemas for teckel-ai SDK v0.3.1
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.any()).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.any()).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
+ });
@@ -0,0 +1,18 @@
1
+ /**
2
+ * TeckelTracer - Main SDK class for teckel-ai v0.3.1
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 (sessionId is legacy alias)
16
+ */
17
+ start(options: ConversationOptions): Conversation;
18
+ }
package/dist/tracer.js ADDED
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /**
3
+ * TeckelTracer - Main SDK class for teckel-ai v0.3.1
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.1',
28
+ timeoutMs: this.timeoutMs
29
+ });
30
+ }
31
+ }
32
+ /**
33
+ * Start a new conversation
34
+ * sessionRef IS the public conversation identifier (sessionId is legacy alias)
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;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Type definitions for teckel-ai SDK v0.3.1
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, any>;
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, any>;
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 ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Type definitions for teckel-ai SDK v0.3.1
4
+ * Simple, clean types matching existing database schema
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "teckel-ai",
3
+ "version": "0.3.2",
4
+ "description": "Simple SDK for AI conversation tracking and RAG observability",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist/**/*",
9
+ "README.md"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "clean": "rm -rf dist",
14
+ "prepublishOnly": "npm run clean && npm run build"
15
+ },
16
+ "keywords": [
17
+ "llm",
18
+ "rag",
19
+ "monitoring",
20
+ "ai",
21
+ "audit",
22
+ "trace",
23
+ "observability",
24
+ "teckel"
25
+ ],
26
+ "author": "Teckel AI",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "zod": "^3.23.8"
30
+ },
31
+ "devDependencies": {
32
+ "typescript": "^5.0.0"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/spencine/AI-Audit-Tool.git",
37
+ "directory": "packages/tracer"
38
+ },
39
+ "homepage": "https://teckel.ai",
40
+ "bugs": {
41
+ "url": "https://github.com/spencine/AI-Audit-Tool/issues"
42
+ }
43
+ }