@tenova/swt3-ai 0.3.4 → 0.3.5
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/README.md +77 -2
- package/dist/adapters/anthropic.d.ts +32 -0
- package/dist/adapters/anthropic.d.ts.map +1 -0
- package/dist/adapters/anthropic.js +299 -0
- package/dist/adapters/anthropic.js.map +1 -0
- package/dist/adapters/bedrock.d.ts +33 -0
- package/dist/adapters/bedrock.d.ts.map +1 -0
- package/dist/adapters/bedrock.js +267 -0
- package/dist/adapters/bedrock.js.map +1 -0
- package/dist/adapters/openai.d.ts +19 -0
- package/dist/adapters/openai.d.ts.map +1 -0
- package/dist/adapters/openai.js +288 -0
- package/dist/adapters/openai.js.map +1 -0
- package/dist/adapters/vercel-ai.d.ts +64 -0
- package/dist/adapters/vercel-ai.d.ts.map +1 -0
- package/dist/adapters/vercel-ai.js +68 -0
- package/dist/adapters/vercel-ai.js.map +1 -0
- package/dist/buffer.d.ts +42 -0
- package/dist/buffer.d.ts.map +1 -0
- package/dist/buffer.js +161 -0
- package/dist/buffer.js.map +1 -0
- package/dist/clearing.d.ts +29 -0
- package/dist/clearing.d.ts.map +1 -0
- package/dist/clearing.js +308 -0
- package/dist/clearing.js.map +1 -0
- package/dist/demo.d.ts +11 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +238 -0
- package/dist/demo.js.map +1 -0
- package/dist/fingerprint.d.ts +29 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingerprint.js +57 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/handoff.d.ts +17 -0
- package/dist/handoff.d.ts.map +1 -0
- package/dist/handoff.js +82 -0
- package/dist/handoff.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/signing.d.ts +20 -0
- package/dist/signing.d.ts.map +1 -0
- package/dist/signing.js +28 -0
- package/dist/signing.js.map +1 -0
- package/dist/types.d.ts +98 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/witness.d.ts +142 -0
- package/dist/witness.d.ts.map +1 -0
- package/dist/witness.js +345 -0
- package/dist/witness.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SWT3 AI Witness SDK — AWS Bedrock Adapter (ES6 Proxy).
|
|
3
|
+
*
|
|
4
|
+
* Wraps the @aws-sdk/client-bedrock-runtime client so that
|
|
5
|
+
* `client.send(new ConverseCommand(...))` and
|
|
6
|
+
* `client.send(new InvokeModelCommand(...))` are intercepted.
|
|
7
|
+
*
|
|
8
|
+
* AWS Bedrock uses the Command pattern:
|
|
9
|
+
* const response = await client.send(new ConverseCommand({ modelId, messages }));
|
|
10
|
+
*
|
|
11
|
+
* The adapter intercepts `send()` and checks if the command is a
|
|
12
|
+
* ConverseCommand or InvokeModelCommand to extract factors.
|
|
13
|
+
*
|
|
14
|
+
* Copyright (c) 2026 Tenable Nova LLC. Apache 2.0. Patent pending.
|
|
15
|
+
*/
|
|
16
|
+
import { sha256Truncated } from "../fingerprint.js";
|
|
17
|
+
/**
|
|
18
|
+
* Wrap a BedrockRuntimeClient with transparent witnessing.
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* import { BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime";
|
|
22
|
+
* import { Witness } from "@tenova/swt3-ai";
|
|
23
|
+
*
|
|
24
|
+
* const witness = new Witness({ endpoint, apiKey, tenantId });
|
|
25
|
+
* const client = witness.wrap(new BedrockRuntimeClient({ region: "us-east-1" }));
|
|
26
|
+
*
|
|
27
|
+
* const response = await client.send(new ConverseCommand({
|
|
28
|
+
* modelId: "anthropic.claude-3-5-sonnet-20241022-v2:0",
|
|
29
|
+
* messages: [{ role: "user", content: [{ text: "Hello" }] }],
|
|
30
|
+
* }));
|
|
31
|
+
*/
|
|
32
|
+
export function wrapBedrock(client, witness) {
|
|
33
|
+
return new Proxy(client, {
|
|
34
|
+
get(target, prop) {
|
|
35
|
+
if (typeof prop === "symbol")
|
|
36
|
+
return Reflect.get(target, prop);
|
|
37
|
+
const real = Reflect.get(target, prop);
|
|
38
|
+
if (prop === "send" && typeof real === "function") {
|
|
39
|
+
return createSendInterceptor(real, witness, target);
|
|
40
|
+
}
|
|
41
|
+
return real;
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function createSendInterceptor(realSend, witness, thisArg) {
|
|
46
|
+
return async function interceptedSend(...args) {
|
|
47
|
+
const command = args[0];
|
|
48
|
+
if (!command)
|
|
49
|
+
return realSend.call(thisArg, ...args);
|
|
50
|
+
// Detect command type by constructor name
|
|
51
|
+
const commandName = command.constructor?.name ?? "";
|
|
52
|
+
if (commandName === "ConverseCommand") {
|
|
53
|
+
return handleConverse(realSend, thisArg, command, witness, args);
|
|
54
|
+
}
|
|
55
|
+
if (commandName === "InvokeModelCommand") {
|
|
56
|
+
return handleInvokeModel(realSend, thisArg, command, witness, args);
|
|
57
|
+
}
|
|
58
|
+
// Not a command we intercept — pass through
|
|
59
|
+
return realSend.call(thisArg, ...args);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// ── Converse Command Handler ──────────────────────────────────────
|
|
63
|
+
async function handleConverse(realSend, thisArg, command, witness, args) {
|
|
64
|
+
const input = command.input ?? command;
|
|
65
|
+
const modelId = input.modelId ?? "unknown";
|
|
66
|
+
const messages = input.messages ?? [];
|
|
67
|
+
const promptText = extractConversePrompt(messages);
|
|
68
|
+
const promptHash = sha256Truncated(promptText);
|
|
69
|
+
// Gatekeeper pre-call check (strict mode only)
|
|
70
|
+
if (witness.strict) {
|
|
71
|
+
witness.gateCheck(messages, modelId);
|
|
72
|
+
}
|
|
73
|
+
const start = performance.now();
|
|
74
|
+
const response = await realSend.call(thisArg, ...args);
|
|
75
|
+
const elapsedMs = Math.round(performance.now() - start);
|
|
76
|
+
const resp = response;
|
|
77
|
+
const record = extractConverseRecord(resp, modelId, promptHash, elapsedMs);
|
|
78
|
+
witness.record(record);
|
|
79
|
+
return response;
|
|
80
|
+
}
|
|
81
|
+
// ── InvokeModel Command Handler ──────────────────────────────────
|
|
82
|
+
async function handleInvokeModel(realSend, thisArg, command, witness, args) {
|
|
83
|
+
const input = command.input ?? command;
|
|
84
|
+
const modelId = input.modelId ?? "unknown";
|
|
85
|
+
// Parse the body to get prompt
|
|
86
|
+
let body = {};
|
|
87
|
+
const rawBody = input.body;
|
|
88
|
+
if (typeof rawBody === "string") {
|
|
89
|
+
try {
|
|
90
|
+
body = JSON.parse(rawBody);
|
|
91
|
+
}
|
|
92
|
+
catch { /* empty */ }
|
|
93
|
+
}
|
|
94
|
+
else if (rawBody instanceof Uint8Array) {
|
|
95
|
+
try {
|
|
96
|
+
body = JSON.parse(new TextDecoder().decode(rawBody));
|
|
97
|
+
}
|
|
98
|
+
catch { /* empty */ }
|
|
99
|
+
}
|
|
100
|
+
const promptText = extractInvokePrompt(body, modelId);
|
|
101
|
+
const promptHash = sha256Truncated(promptText);
|
|
102
|
+
// Gatekeeper pre-call check (strict mode only)
|
|
103
|
+
if (witness.strict) {
|
|
104
|
+
witness.gateCheck(body, modelId);
|
|
105
|
+
}
|
|
106
|
+
const start = performance.now();
|
|
107
|
+
const response = await realSend.call(thisArg, ...args);
|
|
108
|
+
const elapsedMs = Math.round(performance.now() - start);
|
|
109
|
+
const resp = response;
|
|
110
|
+
const record = extractInvokeRecord(resp, modelId, promptHash, elapsedMs);
|
|
111
|
+
witness.record(record);
|
|
112
|
+
return response;
|
|
113
|
+
}
|
|
114
|
+
// ── Prompt Extraction ─────────────────────────────────────────────
|
|
115
|
+
function extractConversePrompt(messages) {
|
|
116
|
+
const parts = [];
|
|
117
|
+
for (const msg of messages) {
|
|
118
|
+
const m = msg;
|
|
119
|
+
const content = m.content;
|
|
120
|
+
if (Array.isArray(content)) {
|
|
121
|
+
for (const block of content) {
|
|
122
|
+
const b = block;
|
|
123
|
+
if (b.text)
|
|
124
|
+
parts.push(b.text);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else if (typeof content === "string") {
|
|
128
|
+
parts.push(content);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return parts.join("\n");
|
|
132
|
+
}
|
|
133
|
+
function extractInvokePrompt(body, modelId) {
|
|
134
|
+
// Anthropic on Bedrock
|
|
135
|
+
const messages = body.messages;
|
|
136
|
+
if (messages?.length) {
|
|
137
|
+
const parts = [];
|
|
138
|
+
for (const msg of messages) {
|
|
139
|
+
const m = msg;
|
|
140
|
+
const content = m.content;
|
|
141
|
+
if (typeof content === "string") {
|
|
142
|
+
parts.push(content);
|
|
143
|
+
}
|
|
144
|
+
else if (Array.isArray(content)) {
|
|
145
|
+
for (const block of content) {
|
|
146
|
+
const b = block;
|
|
147
|
+
if (b.type === "text" && b.text)
|
|
148
|
+
parts.push(b.text);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (parts.length)
|
|
153
|
+
return parts.join("\n");
|
|
154
|
+
}
|
|
155
|
+
// Amazon Titan
|
|
156
|
+
if (body.inputText)
|
|
157
|
+
return body.inputText;
|
|
158
|
+
// Meta Llama
|
|
159
|
+
if (body.prompt)
|
|
160
|
+
return body.prompt;
|
|
161
|
+
return JSON.stringify(body);
|
|
162
|
+
}
|
|
163
|
+
// ── Record Extraction ─────────────────────────────────────────────
|
|
164
|
+
function extractConverseRecord(response, modelId, promptHash, elapsedMs) {
|
|
165
|
+
let responseText = "";
|
|
166
|
+
let hasRefusal = false;
|
|
167
|
+
const output = response.output;
|
|
168
|
+
const message = output?.message;
|
|
169
|
+
const content = message?.content;
|
|
170
|
+
if (content) {
|
|
171
|
+
for (const block of content) {
|
|
172
|
+
if (block.text)
|
|
173
|
+
responseText += block.text;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const stopReason = response.stopReason;
|
|
177
|
+
if (stopReason === "content_filtered")
|
|
178
|
+
hasRefusal = true;
|
|
179
|
+
const usage = response.usage;
|
|
180
|
+
const inputTokens = usage?.inputTokens;
|
|
181
|
+
const outputTokens = usage?.outputTokens;
|
|
182
|
+
return {
|
|
183
|
+
modelId: modelId,
|
|
184
|
+
modelHash: sha256Truncated(modelId),
|
|
185
|
+
promptHash: promptHash,
|
|
186
|
+
responseHash: sha256Truncated(responseText || ""),
|
|
187
|
+
latencyMs: elapsedMs,
|
|
188
|
+
inputTokens: inputTokens ?? undefined,
|
|
189
|
+
outputTokens: outputTokens ?? undefined,
|
|
190
|
+
hasRefusal: hasRefusal,
|
|
191
|
+
provider: "bedrock",
|
|
192
|
+
systemFingerprint: undefined,
|
|
193
|
+
guardrailsActive: 0,
|
|
194
|
+
guardrailsRequired: 0,
|
|
195
|
+
guardrailPassed: true,
|
|
196
|
+
guardrailNames: [],
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function extractInvokeRecord(response, modelId, promptHash, elapsedMs) {
|
|
200
|
+
let responseText = "";
|
|
201
|
+
let hasRefusal = false;
|
|
202
|
+
let inputTokens = null;
|
|
203
|
+
let outputTokens = null;
|
|
204
|
+
try {
|
|
205
|
+
let body = {};
|
|
206
|
+
const rawBody = response.body;
|
|
207
|
+
if (rawBody instanceof Uint8Array) {
|
|
208
|
+
body = JSON.parse(new TextDecoder().decode(rawBody));
|
|
209
|
+
}
|
|
210
|
+
else if (typeof rawBody === "string") {
|
|
211
|
+
body = JSON.parse(rawBody);
|
|
212
|
+
}
|
|
213
|
+
// Anthropic on Bedrock
|
|
214
|
+
if (body.content) {
|
|
215
|
+
const content = body.content;
|
|
216
|
+
if (Array.isArray(content)) {
|
|
217
|
+
for (const block of content) {
|
|
218
|
+
if (block.type === "text" && block.text)
|
|
219
|
+
responseText += block.text;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else if (typeof content === "string") {
|
|
223
|
+
responseText = content;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Amazon Titan
|
|
227
|
+
else if (body.results) {
|
|
228
|
+
const results = body.results;
|
|
229
|
+
if (results[0]?.outputText)
|
|
230
|
+
responseText = results[0].outputText;
|
|
231
|
+
}
|
|
232
|
+
// Meta Llama
|
|
233
|
+
else if (body.generation) {
|
|
234
|
+
responseText = body.generation;
|
|
235
|
+
}
|
|
236
|
+
// Usage
|
|
237
|
+
const usage = body.usage;
|
|
238
|
+
if (usage) {
|
|
239
|
+
inputTokens = (usage.input_tokens ?? usage.inputTokens ?? null);
|
|
240
|
+
outputTokens = (usage.output_tokens ?? usage.outputTokens ?? null);
|
|
241
|
+
}
|
|
242
|
+
// Refusal
|
|
243
|
+
const stopReason = (body.stop_reason ?? body.stopReason ?? "");
|
|
244
|
+
if (stopReason.toLowerCase().includes("content_filter"))
|
|
245
|
+
hasRefusal = true;
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
// Parse failure — still witness with what we have
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
modelId: modelId,
|
|
252
|
+
modelHash: sha256Truncated(modelId),
|
|
253
|
+
promptHash: promptHash,
|
|
254
|
+
responseHash: sha256Truncated(responseText || ""),
|
|
255
|
+
latencyMs: elapsedMs,
|
|
256
|
+
inputTokens: inputTokens ?? undefined,
|
|
257
|
+
outputTokens: outputTokens ?? undefined,
|
|
258
|
+
hasRefusal: hasRefusal,
|
|
259
|
+
provider: "bedrock",
|
|
260
|
+
systemFingerprint: undefined,
|
|
261
|
+
guardrailsActive: 0,
|
|
262
|
+
guardrailsRequired: 0,
|
|
263
|
+
guardrailPassed: true,
|
|
264
|
+
guardrailNames: [],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=bedrock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bedrock.js","sourceRoot":"","sources":["../../src/adapters/bedrock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SWT3 AI Witness SDK — OpenAI Adapter (ES6 Proxy).
|
|
3
|
+
*
|
|
4
|
+
* Uses JavaScript's native Proxy to intercept property access on the
|
|
5
|
+
* OpenAI client, following the chain: client.chat.completions.create()
|
|
6
|
+
*
|
|
7
|
+
* Handles both:
|
|
8
|
+
* - Non-streaming: ChatCompletion response object
|
|
9
|
+
* - Streaming: AsyncIterable<ChatCompletionChunk> — accumulates chunks
|
|
10
|
+
* for hashing, then witnesses after stream completes
|
|
11
|
+
*
|
|
12
|
+
* The developer's code sees zero difference from using the raw client.
|
|
13
|
+
*/
|
|
14
|
+
import type { Witness } from "../witness.js";
|
|
15
|
+
/**
|
|
16
|
+
* Wrap an OpenAI client with an ES6 Proxy for transparent witnessing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function wrapOpenAI(client: unknown, witness: Witness): unknown;
|
|
19
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAU7C;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAErE"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SWT3 AI Witness SDK — OpenAI Adapter (ES6 Proxy).
|
|
3
|
+
*
|
|
4
|
+
* Uses JavaScript's native Proxy to intercept property access on the
|
|
5
|
+
* OpenAI client, following the chain: client.chat.completions.create()
|
|
6
|
+
*
|
|
7
|
+
* Handles both:
|
|
8
|
+
* - Non-streaming: ChatCompletion response object
|
|
9
|
+
* - Streaming: AsyncIterable<ChatCompletionChunk> — accumulates chunks
|
|
10
|
+
* for hashing, then witnesses after stream completes
|
|
11
|
+
*
|
|
12
|
+
* The developer's code sees zero difference from using the raw client.
|
|
13
|
+
*/
|
|
14
|
+
import { sha256Truncated } from "../fingerprint.js";
|
|
15
|
+
/**
|
|
16
|
+
* Methods to intercept at each path level.
|
|
17
|
+
* "chat.completions" → intercept "create"
|
|
18
|
+
*/
|
|
19
|
+
const INTERCEPT_PATHS = {
|
|
20
|
+
"chat.completions": new Set(["create"]),
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Wrap an OpenAI client with an ES6 Proxy for transparent witnessing.
|
|
24
|
+
*/
|
|
25
|
+
export function wrapOpenAI(client, witness) {
|
|
26
|
+
return createProxy(client, witness, "");
|
|
27
|
+
}
|
|
28
|
+
function createProxy(target, witness, path) {
|
|
29
|
+
return new Proxy(target, {
|
|
30
|
+
get(obj, prop) {
|
|
31
|
+
if (typeof prop === "symbol")
|
|
32
|
+
return Reflect.get(obj, prop);
|
|
33
|
+
const realValue = Reflect.get(obj, prop);
|
|
34
|
+
const currentPath = path ? `${path}.${prop}` : prop;
|
|
35
|
+
// Check if this property is an interceptable method
|
|
36
|
+
if (path in INTERCEPT_PATHS && INTERCEPT_PATHS[path].has(prop)) {
|
|
37
|
+
// This IS the method to intercept
|
|
38
|
+
return createInterceptor(realValue, witness);
|
|
39
|
+
}
|
|
40
|
+
// Check if this path could lead to interceptable methods
|
|
41
|
+
const hasChildren = Object.keys(INTERCEPT_PATHS).some((p) => p === currentPath || p.startsWith(currentPath + "."));
|
|
42
|
+
if (hasChildren && typeof realValue === "object" && realValue !== null) {
|
|
43
|
+
return createProxy(realValue, witness, currentPath);
|
|
44
|
+
}
|
|
45
|
+
// Pass through
|
|
46
|
+
return realValue;
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function createInterceptor(realMethod, witness) {
|
|
51
|
+
return function interceptedCreate(...args) {
|
|
52
|
+
const kwargs = (args[0] ?? {});
|
|
53
|
+
const messages = kwargs.messages;
|
|
54
|
+
const model = kwargs.model ?? "unknown";
|
|
55
|
+
const isStreaming = kwargs.stream === true;
|
|
56
|
+
// Hash prompt before the call
|
|
57
|
+
const promptText = extractPromptText(messages);
|
|
58
|
+
const promptHash = sha256Truncated(promptText);
|
|
59
|
+
// Hash system prompt separately (instruction drift detection)
|
|
60
|
+
const systemPromptText = extractSystemPrompt(messages);
|
|
61
|
+
const systemPromptHash = systemPromptText ? sha256Truncated(systemPromptText) : undefined;
|
|
62
|
+
// Gatekeeper pre-call check (strict mode only)
|
|
63
|
+
if (witness.strict) {
|
|
64
|
+
witness.gateCheck(messages, model);
|
|
65
|
+
}
|
|
66
|
+
// Start latency timer
|
|
67
|
+
const start = performance.now();
|
|
68
|
+
// Call the real method (bound to its original this)
|
|
69
|
+
const result = realMethod.call(this, ...args);
|
|
70
|
+
if (isStreaming) {
|
|
71
|
+
// Streaming: wrap the async iterable to accumulate chunks
|
|
72
|
+
return handleStreaming(result, witness, model, promptHash, start, systemPromptHash);
|
|
73
|
+
}
|
|
74
|
+
// Non-streaming: result is a Promise<ChatCompletion>
|
|
75
|
+
return result.then((response) => {
|
|
76
|
+
const elapsedMs = Math.round(performance.now() - start);
|
|
77
|
+
const record = extractRecord(response, model, promptHash, elapsedMs, systemPromptHash);
|
|
78
|
+
witness.record(record);
|
|
79
|
+
return response; // Return UNTOUCHED
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// ── Streaming Handler ──────────────────────────────────────────────
|
|
84
|
+
//
|
|
85
|
+
// OpenAI's streaming returns an object with:
|
|
86
|
+
// - Symbol.asyncIterator (for `for await...of`)
|
|
87
|
+
// - .controller for abort
|
|
88
|
+
// - .toReadableStream() for web streams
|
|
89
|
+
//
|
|
90
|
+
// We wrap the async iterator to accumulate content chunks, then
|
|
91
|
+
// witness after the stream completes. The developer's stream
|
|
92
|
+
// behavior is completely unchanged.
|
|
93
|
+
async function* streamAccumulator(stream, witness, model, promptHash, startTime, systemPromptHash) {
|
|
94
|
+
const textParts = [];
|
|
95
|
+
let actualModel = model;
|
|
96
|
+
let systemFingerprint;
|
|
97
|
+
let hasRefusal = false;
|
|
98
|
+
let finishReason = "";
|
|
99
|
+
let inputTokens;
|
|
100
|
+
let outputTokens;
|
|
101
|
+
for await (const chunk of stream) {
|
|
102
|
+
// Yield chunk to the developer immediately (untouched)
|
|
103
|
+
yield chunk;
|
|
104
|
+
// Extract data from chunk for witnessing
|
|
105
|
+
const c = chunk;
|
|
106
|
+
if (c.model)
|
|
107
|
+
actualModel = c.model;
|
|
108
|
+
if (c.system_fingerprint)
|
|
109
|
+
systemFingerprint = c.system_fingerprint;
|
|
110
|
+
const choices = c.choices;
|
|
111
|
+
if (choices?.[0]) {
|
|
112
|
+
const delta = choices[0].delta;
|
|
113
|
+
if (delta?.content) {
|
|
114
|
+
textParts.push(delta.content);
|
|
115
|
+
}
|
|
116
|
+
if (delta?.refusal) {
|
|
117
|
+
hasRefusal = true;
|
|
118
|
+
}
|
|
119
|
+
if (choices[0].finish_reason) {
|
|
120
|
+
finishReason = choices[0].finish_reason;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Usage info comes in the final chunk (stream_options: {include_usage: true})
|
|
124
|
+
const usage = c.usage;
|
|
125
|
+
if (usage) {
|
|
126
|
+
inputTokens = usage.prompt_tokens;
|
|
127
|
+
outputTokens = usage.completion_tokens;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Stream complete — witness the full inference
|
|
131
|
+
const elapsedMs = Math.round(performance.now() - startTime);
|
|
132
|
+
const responseText = textParts.join("");
|
|
133
|
+
if (finishReason === "content_filter")
|
|
134
|
+
hasRefusal = true;
|
|
135
|
+
const modelHashInput = systemFingerprint
|
|
136
|
+
? `${actualModel}:${systemFingerprint}`
|
|
137
|
+
: actualModel;
|
|
138
|
+
const record = {
|
|
139
|
+
modelId: actualModel,
|
|
140
|
+
modelHash: sha256Truncated(modelHashInput),
|
|
141
|
+
promptHash,
|
|
142
|
+
responseHash: sha256Truncated(responseText),
|
|
143
|
+
latencyMs: elapsedMs,
|
|
144
|
+
inputTokens,
|
|
145
|
+
outputTokens,
|
|
146
|
+
guardrailsActive: 0,
|
|
147
|
+
guardrailsRequired: 0,
|
|
148
|
+
guardrailPassed: true,
|
|
149
|
+
hasRefusal,
|
|
150
|
+
provider: "openai",
|
|
151
|
+
systemFingerprint,
|
|
152
|
+
systemPromptHash,
|
|
153
|
+
guardrailNames: [],
|
|
154
|
+
};
|
|
155
|
+
witness.record(record);
|
|
156
|
+
}
|
|
157
|
+
function handleStreaming(streamResult, witness, model, promptHash, startTime, systemPromptHash) {
|
|
158
|
+
// The stream result is a Promise that resolves to the stream object
|
|
159
|
+
// (OpenAI SDK returns Promise<Stream<ChatCompletionChunk>>)
|
|
160
|
+
if (streamResult && typeof streamResult.then === "function") {
|
|
161
|
+
return streamResult.then((stream) => {
|
|
162
|
+
return wrapStream(stream, witness, model, promptHash, startTime, systemPromptHash);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// Direct stream object (shouldn't happen but handle gracefully)
|
|
166
|
+
return wrapStream(streamResult, witness, model, promptHash, startTime, systemPromptHash);
|
|
167
|
+
}
|
|
168
|
+
function wrapStream(stream, witness, model, promptHash, startTime, systemPromptHash) {
|
|
169
|
+
const s = stream;
|
|
170
|
+
// Create the accumulating async generator
|
|
171
|
+
const gen = streamAccumulator(s, witness, model, promptHash, startTime, systemPromptHash);
|
|
172
|
+
// Return a proxy that preserves all stream methods but overrides the iterator
|
|
173
|
+
return new Proxy(s, {
|
|
174
|
+
get(target, prop) {
|
|
175
|
+
// Override the async iterator
|
|
176
|
+
if (prop === Symbol.asyncIterator) {
|
|
177
|
+
return () => gen;
|
|
178
|
+
}
|
|
179
|
+
// Preserve other methods (controller, toReadableStream, etc.)
|
|
180
|
+
const value = Reflect.get(target, prop);
|
|
181
|
+
if (typeof value === "function") {
|
|
182
|
+
return value.bind(target);
|
|
183
|
+
}
|
|
184
|
+
return value;
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
// ── Factor Extraction ──────────────────────────────────────────────
|
|
189
|
+
function extractSystemPrompt(messages) {
|
|
190
|
+
if (!Array.isArray(messages))
|
|
191
|
+
return undefined;
|
|
192
|
+
const parts = [];
|
|
193
|
+
for (const msg of messages) {
|
|
194
|
+
if (typeof msg === "object" && msg !== null) {
|
|
195
|
+
const m = msg;
|
|
196
|
+
if (m.role !== "system")
|
|
197
|
+
continue;
|
|
198
|
+
const content = m.content;
|
|
199
|
+
if (typeof content === "string") {
|
|
200
|
+
parts.push(content);
|
|
201
|
+
}
|
|
202
|
+
else if (Array.isArray(content)) {
|
|
203
|
+
for (const part of content) {
|
|
204
|
+
if (typeof part === "object" && part !== null) {
|
|
205
|
+
const p = part;
|
|
206
|
+
if (p.type === "text" && typeof p.text === "string") {
|
|
207
|
+
parts.push(p.text);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return parts.length > 0 ? parts.join("\n") : undefined;
|
|
215
|
+
}
|
|
216
|
+
function extractPromptText(messages) {
|
|
217
|
+
if (typeof messages === "string")
|
|
218
|
+
return messages;
|
|
219
|
+
if (!Array.isArray(messages))
|
|
220
|
+
return "";
|
|
221
|
+
const parts = [];
|
|
222
|
+
for (const msg of messages) {
|
|
223
|
+
if (typeof msg === "object" && msg !== null) {
|
|
224
|
+
const m = msg;
|
|
225
|
+
const content = m.content;
|
|
226
|
+
if (typeof content === "string") {
|
|
227
|
+
parts.push(content);
|
|
228
|
+
}
|
|
229
|
+
else if (Array.isArray(content)) {
|
|
230
|
+
for (const part of content) {
|
|
231
|
+
if (typeof part === "object" && part !== null) {
|
|
232
|
+
const p = part;
|
|
233
|
+
if (p.type === "text" && typeof p.text === "string") {
|
|
234
|
+
parts.push(p.text);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return parts.join("\n");
|
|
242
|
+
}
|
|
243
|
+
function extractRecord(response, model, promptHash, elapsedMs, systemPromptHash) {
|
|
244
|
+
const r = response;
|
|
245
|
+
let responseText = "";
|
|
246
|
+
let hasRefusal = false;
|
|
247
|
+
const choices = r.choices;
|
|
248
|
+
if (choices?.[0]) {
|
|
249
|
+
const message = choices[0].message;
|
|
250
|
+
if (message) {
|
|
251
|
+
responseText = message.content ?? "";
|
|
252
|
+
if (message.refusal)
|
|
253
|
+
hasRefusal = true;
|
|
254
|
+
}
|
|
255
|
+
if (choices[0].finish_reason === "content_filter")
|
|
256
|
+
hasRefusal = true;
|
|
257
|
+
}
|
|
258
|
+
let inputTokens;
|
|
259
|
+
let outputTokens;
|
|
260
|
+
const usage = r.usage;
|
|
261
|
+
if (usage) {
|
|
262
|
+
inputTokens = usage.prompt_tokens;
|
|
263
|
+
outputTokens = usage.completion_tokens;
|
|
264
|
+
}
|
|
265
|
+
const actualModel = r.model ?? model;
|
|
266
|
+
const systemFingerprint = r.system_fingerprint;
|
|
267
|
+
const modelHashInput = systemFingerprint
|
|
268
|
+
? `${actualModel}:${systemFingerprint}`
|
|
269
|
+
: actualModel;
|
|
270
|
+
return {
|
|
271
|
+
modelId: actualModel,
|
|
272
|
+
modelHash: sha256Truncated(modelHashInput),
|
|
273
|
+
promptHash,
|
|
274
|
+
responseHash: sha256Truncated(responseText),
|
|
275
|
+
latencyMs: elapsedMs,
|
|
276
|
+
inputTokens,
|
|
277
|
+
outputTokens,
|
|
278
|
+
guardrailsActive: 0,
|
|
279
|
+
guardrailsRequired: 0,
|
|
280
|
+
guardrailPassed: true,
|
|
281
|
+
hasRefusal,
|
|
282
|
+
provider: "openai",
|
|
283
|
+
systemFingerprint,
|
|
284
|
+
systemPromptHash,
|
|
285
|
+
guardrailNames: [],
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SWT3 AI Witness SDK — Vercel AI SDK Integration.
|
|
3
|
+
*
|
|
4
|
+
* Provides an `onFinish` callback factory for the Vercel AI SDK's
|
|
5
|
+
* `streamText()` and `generateText()` functions. This is the most
|
|
6
|
+
* idiomatic integration for Next.js / React developers.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* import { streamText } from "ai";
|
|
10
|
+
* import { openai } from "@ai-sdk/openai";
|
|
11
|
+
*
|
|
12
|
+
* const result = await streamText({
|
|
13
|
+
* model: openai("gpt-4o"),
|
|
14
|
+
* prompt: "Summarize this contract...",
|
|
15
|
+
* onFinish: witness.vercelOnFinish(),
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* The `onFinish` callback receives a normalized result regardless of
|
|
19
|
+
* provider (OpenAI, Anthropic, Google, custom), so this single hook
|
|
20
|
+
* works with any Vercel AI SDK provider — no per-provider adapters needed.
|
|
21
|
+
*
|
|
22
|
+
* Vercel AI SDK onFinish payload:
|
|
23
|
+
* {
|
|
24
|
+
* text: string, // Complete response text
|
|
25
|
+
* usage: { promptTokens, completionTokens },
|
|
26
|
+
* finishReason: "stop" | "length" | "content-filter" | "tool-calls" | ...,
|
|
27
|
+
* response: { id, model, timestamp, headers },
|
|
28
|
+
* experimental_providerMetadata?: { ... },
|
|
29
|
+
* }
|
|
30
|
+
*/
|
|
31
|
+
import type { Witness } from "../witness.js";
|
|
32
|
+
/**
|
|
33
|
+
* Vercel AI SDK onFinish callback shape.
|
|
34
|
+
* We define this locally to avoid requiring `ai` as a dependency.
|
|
35
|
+
*/
|
|
36
|
+
interface VercelOnFinishResult {
|
|
37
|
+
text: string;
|
|
38
|
+
usage: {
|
|
39
|
+
promptTokens: number;
|
|
40
|
+
completionTokens: number;
|
|
41
|
+
};
|
|
42
|
+
finishReason: string;
|
|
43
|
+
response: {
|
|
44
|
+
id?: string;
|
|
45
|
+
model?: string;
|
|
46
|
+
timestamp?: Date;
|
|
47
|
+
headers?: Record<string, string>;
|
|
48
|
+
};
|
|
49
|
+
experimental_providerMetadata?: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
export interface VercelOnFinishOptions {
|
|
52
|
+
/** Override the prompt text for hashing (if not using the `prompt` param). */
|
|
53
|
+
promptText?: string;
|
|
54
|
+
/** Model name override (if response.model is missing). */
|
|
55
|
+
modelId?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a Vercel AI SDK `onFinish` callback that witnesses the inference.
|
|
59
|
+
*
|
|
60
|
+
* Works with both `streamText()` and `generateText()`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function createVercelOnFinish(witness: Witness, options?: VercelOnFinishOptions): (result: VercelOnFinishResult) => void;
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=vercel-ai.d.ts.map
|