@tenova/swt3-ai 0.3.4 → 0.4.1

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.
Files changed (58) hide show
  1. package/README.md +150 -18
  2. package/dist/adapters/anthropic.d.ts +32 -0
  3. package/dist/adapters/anthropic.d.ts.map +1 -0
  4. package/dist/adapters/anthropic.js +301 -0
  5. package/dist/adapters/anthropic.js.map +1 -0
  6. package/dist/adapters/bedrock.d.ts +33 -0
  7. package/dist/adapters/bedrock.d.ts.map +1 -0
  8. package/dist/adapters/bedrock.js +269 -0
  9. package/dist/adapters/bedrock.js.map +1 -0
  10. package/dist/adapters/openai.d.ts +19 -0
  11. package/dist/adapters/openai.d.ts.map +1 -0
  12. package/dist/adapters/openai.js +289 -0
  13. package/dist/adapters/openai.js.map +1 -0
  14. package/dist/adapters/vercel-ai.d.ts +64 -0
  15. package/dist/adapters/vercel-ai.d.ts.map +1 -0
  16. package/dist/adapters/vercel-ai.js +68 -0
  17. package/dist/adapters/vercel-ai.js.map +1 -0
  18. package/dist/buffer.d.ts +43 -0
  19. package/dist/buffer.d.ts.map +1 -0
  20. package/dist/buffer.js +172 -0
  21. package/dist/buffer.js.map +1 -0
  22. package/dist/clearing.d.ts +39 -0
  23. package/dist/clearing.d.ts.map +1 -0
  24. package/dist/clearing.js +338 -0
  25. package/dist/clearing.js.map +1 -0
  26. package/dist/demo.d.ts +11 -0
  27. package/dist/demo.d.ts.map +1 -0
  28. package/dist/demo.js +238 -0
  29. package/dist/demo.js.map +1 -0
  30. package/dist/exporters/otel.d.ts +36 -0
  31. package/dist/exporters/otel.d.ts.map +1 -0
  32. package/dist/exporters/otel.js +94 -0
  33. package/dist/exporters/otel.js.map +1 -0
  34. package/dist/fingerprint.d.ts +29 -0
  35. package/dist/fingerprint.d.ts.map +1 -0
  36. package/dist/fingerprint.js +57 -0
  37. package/dist/fingerprint.js.map +1 -0
  38. package/dist/handoff.d.ts +17 -0
  39. package/dist/handoff.d.ts.map +1 -0
  40. package/dist/handoff.js +82 -0
  41. package/dist/handoff.js.map +1 -0
  42. package/dist/index.d.ts +22 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +20 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/signing.d.ts +20 -0
  47. package/dist/signing.d.ts.map +1 -0
  48. package/dist/signing.js +28 -0
  49. package/dist/signing.js.map +1 -0
  50. package/dist/types.d.ts +108 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +20 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/witness.d.ts +193 -0
  55. package/dist/witness.d.ts.map +1 -0
  56. package/dist/witness.js +487 -0
  57. package/dist/witness.js.map +1 -0
  58. package/package.json +10 -2
package/README.md CHANGED
@@ -8,9 +8,9 @@ Witness your AI. Prove it followed the rules. Cryptographic accountability for e
8
8
 
9
9
  **SWT3 AI Witness SDK for TypeScript**: tamper-proof evidence that your AI is doing what you say it does. Every inference hashed. Every tool call recorded. Every resource access checked against scope. No prompts or responses ever leave your infrastructure.
10
10
 
11
- Works with OpenAI, Anthropic, Vercel AI SDK, and any OpenAI-compatible endpoint (vLLM, Ollama, Azure, Llama.cpp).
11
+ Works with OpenAI, Anthropic, AWS Bedrock, Vercel AI SDK, and any OpenAI-compatible endpoint (vLLM, Ollama, Azure, Llama.cpp).
12
12
 
13
- The EU AI Act takes effect **August 2, 2026**. When regulators ask "prove your AI followed the rules," you need more than logs. You need cryptographic proof.
13
+ GPAI transparency obligations are enforceable now. EU AI Act high-risk enforcement begins **December 2, 2027**. This SDK gives you the evidence chain.
14
14
 
15
15
  ## See It Work (No Account Needed)
16
16
 
@@ -127,7 +127,7 @@ const results = await search("SELECT * FROM transactions WHERE amount > 10000");
127
127
  // An AI-TOOL.1 anchor is minted recording: tool name, latency, success/failure
128
128
  ```
129
129
 
130
- When an auditor asks "what tools did your agent use?" you have the cryptographic record.
130
+ Each anchor records the tool name, input/output hashes, latency, and success or failure.
131
131
 
132
132
  ## Witness Agent Resource Access
133
133
 
@@ -147,7 +147,7 @@ const results = await queryCustomers("SELECT name FROM customers");
147
147
  // - Was access granted? (yes)
148
148
  ```
149
149
 
150
- If the agent tries to access something outside its declared scope, the anchor records a FAIL verdict. When a CISO asks "can you prove your AI agent only accessed what it was authorized to access?" this is the answer.
150
+ If the agent tries to access something outside its declared scope, the anchor records a FAIL verdict with a full evidence trail.
151
151
 
152
152
  ## Detect Instruction Drift
153
153
 
@@ -178,6 +178,75 @@ The `agentId` survives all clearing levels. The `signingKey` produces a cryptogr
178
178
  - Fleet-wide governance dashboards
179
179
  - Agent-scoped evidence packages for auditors
180
180
 
181
+ ## Gatekeeper Mode (Pre-Call Enforcement)
182
+
183
+ New in v0.3.4. Require guardrails to be active *before* the model is called, not just observed after:
184
+
185
+ ```typescript
186
+ import { Witness, GatekeeperError } from "@tenova/swt3-ai";
187
+
188
+ const witness = new Witness({
189
+ endpoint: "...",
190
+ apiKey: "axm_...",
191
+ tenantId: "...",
192
+ strict: true,
193
+ guardrailsRequired: 2,
194
+ guardrailNames: ["content-filter", "pii-scanner"],
195
+ });
196
+
197
+ const client = witness.wrap(new OpenAI()) as OpenAI;
198
+
199
+ // If fewer than 2 guardrails are active, this throws GatekeeperError
200
+ // BEFORE the model call happens. No inference runs without safeguards.
201
+ try {
202
+ const response = await client.chat.completions.create({
203
+ model: "gpt-4o",
204
+ messages: [{ role: "user", content: "..." }],
205
+ });
206
+ } catch (e) {
207
+ if (e instanceof GatekeeperError) {
208
+ console.log(`Blocked: ${e.message}`);
209
+ // An AI-GRD.3 FAIL anchor is minted recording the gate failure
210
+ }
211
+ }
212
+ ```
213
+
214
+ Gatekeeper mode mints an **AI-GRD.3** anchor with:
215
+ - **factor_a** = required guardrail count
216
+ - **factor_b** = actual guardrail count
217
+ - **factor_c** = 1 if gate passed, 0 if blocked
218
+
219
+ ## Multi-Agent Chain Linking
220
+
221
+ New in v0.3.4. Link anchors across agents in a multi-step pipeline using `cycleId`:
222
+
223
+ ```typescript
224
+ const witness = new Witness({
225
+ endpoint: "...",
226
+ apiKey: "axm_...",
227
+ tenantId: "...",
228
+ agentId: "step-1-classifier",
229
+ cycleId: "txn-review-abc123", // shared across all agents in the chain
230
+ });
231
+ ```
232
+
233
+ The `cycleId` survives all clearing levels and appears in every anchor. An auditor can reconstruct the full decision chain by filtering on a single cycle ID.
234
+
235
+ ## Policy Version Binding
236
+
237
+ New in v0.3.4. Tie every anchor to the specific policy configuration that was in effect:
238
+
239
+ ```typescript
240
+ const witness = new Witness({
241
+ endpoint: "...",
242
+ apiKey: "axm_...",
243
+ tenantId: "...",
244
+ policyVersion: "v2.1.0-prod-2026-04-20",
245
+ });
246
+ ```
247
+
248
+ The SDK hashes the policy version string (SHA-256, first 12 characters) and includes it in every payload. When policies change between audit periods, the hash changes -proving which rules were in effect for each inference.
249
+
181
250
  ## What Gets Witnessed
182
251
 
183
252
  Each inference produces anchors for these checks. Every check maps to a regulation.
@@ -196,24 +265,24 @@ Each inference produces anchors for these checks. Every check maps to a regulati
196
265
 
197
266
  ### EU AI Act Article Mapping
198
267
 
199
- All 12 SWT3 AI witnessing procedures map to specific EU AI Act obligations:
268
+ All 36 SWT3 AI witnessing procedures map to specific EU AI Act obligations:
200
269
 
201
270
  | Procedure | EU AI Act Article | Obligation | Demo | Production |
202
271
  |-----------|-------------------|------------|------|------------|
203
272
  | AI-INF.1 | Art. 12(1) | Automatic Logging of Use Periods | ✓ | ✓ |
204
- | AI-INF.2 | Art. 15(3) | Performance Consistency Monitoring | | ✓ |
205
- | AI-INF.3 | Art. 12(1) | Volume & Usage Logging | | ✓ |
273
+ | AI-INF.2 | Art. 15(3) | Performance Consistency Monitoring | -| ✓ |
274
+ | AI-INF.3 | Art. 12(1) | Volume & Usage Logging | -| ✓ |
206
275
  | AI-MDL.1 | Art. 9(4a) | Model Risk Identification | ✓ | ✓ |
207
- | AI-MDL.2 | Art. 12(2b) | Version & Lineage Tracking | | ✓ |
208
- | AI-MDL.3 | Art. 72(1) | Post-Market Drift Monitoring | | ✓ |
209
- | AI-MDL.4 | Art. 15(4) | Feedback Loop Isolation | | ✓ |
276
+ | AI-MDL.2 | Art. 12(2b) | Version & Lineage Tracking | -| ✓ |
277
+ | AI-MDL.3 | Art. 72(1) | Post-Market Drift Monitoring | -| ✓ |
278
+ | AI-MDL.4 | Art. 15(4) | Feedback Loop Isolation | -| ✓ |
210
279
  | AI-GRD.1 | Art. 9(2a) | Risk Mitigation Measures | ✓ | ✓ |
211
- | AI-GRD.2 | Art. 9(4b) | Content Safety Filtering | | ✓ |
212
- | AI-GRD.3 | Art. 10(2f) | PII & Data Protection | | ✓ |
213
- | AI-EXPL.1 | Art. 13(1) | Transparency & Explainability | | ✓ |
214
- | AI-EXPL.2 | Art. 13(3b) | Confidence Calibration | | ✓ |
280
+ | AI-GRD.2 | Art. 9(4b) | Content Safety Filtering | -| ✓ |
281
+ | AI-GRD.3 | Art. 10(2f) | PII & Data Protection | -| ✓ |
282
+ | AI-EXPL.1 | Art. 13(1) | Transparency & Explainability | -| ✓ |
283
+ | AI-EXPL.2 | Art. 13(3b) | Confidence Calibration | -| ✓ |
215
284
 
216
- The demo demonstrates 3 procedures using simulated data. All 12 are available in production with real inference data. [See live conformity →](https://sovereign.tenova.io/audit/axm_audit_demo_eu_ai_act_public)
285
+ The demo demonstrates 3 procedures using simulated data. All 36 are available in production with real inference data. [See live conformity →](https://sovereign.tenova.io/audit/axm_audit_demo_eu_ai_act_public)
217
286
 
218
287
  ## How Verdicts Work
219
288
 
@@ -249,6 +318,7 @@ Translation: "Access attempt occurred. Target was outside declared scope. Access
249
318
  | AI-MDL.2 | 1 (required) | 1 if version recorded | 0 | PASS if b >= a |
250
319
  | AI-GRD.1 | Required count | Active count | 1 if all passed | PASS if b >= a |
251
320
  | AI-GRD.2 | 1 (clean expected) | 0 if refusal | 0 | PASS if b >= a |
321
+ | AI-GRD.3 | Required count | Active count | 1=passed, 0=blocked | PASS if b >= a AND c == 1 |
252
322
  | AI-TOOL.1 | 1 (called) | Latency (ms) | 1=success, 0=error | PASS if b >= a |
253
323
  | AI-ACC.1 | 1 (accessed) | 1=in scope, 0=out | 1=granted, 0=denied | PASS if b >= a |
254
324
  | AI-ID.1 | 1 (required) | 1 if identity present | 0 | PASS if b >= a |
@@ -336,9 +406,9 @@ const witness = new Witness({
336
406
  | EU AI Act conformity | No | Yes (Pro) |
337
407
  | Auditor evidence packages | No | Yes (Pro) |
338
408
  | Access violation tracking | No | Yes (Pro) |
339
- | **Survives an audit** | **No** | **Yes** |
409
+ | Audit-ready evidence chain | No | Yes |
340
410
 
341
- > Local anchors prove it to you. A connected engine proves it to your auditor.
411
+ > Local mode is for development and testing. Connected mode is for production evidence.
342
412
 
343
413
  ## Resilience (Flight Recorder)
344
414
 
@@ -372,6 +442,12 @@ const witness = new Witness({
372
442
  | `guardrailNames` | [] | Active guardrail names |
373
443
  | `agentId` | - | Agent identity (survives all clearing levels) |
374
444
  | `signingKey` | - | HMAC-SHA256 key for payload signing |
445
+ | `cycleId` | - | Multi-agent chain link (survives all clearing levels) |
446
+ | `policyVersion` | - | Policy config identifier (hashed in payloads) |
447
+ | `strict` | false | Gatekeeper mode: block inference if guardrails insufficient |
448
+ | `latencyThresholdMs` | 30000 | AI-INF.2 latency limit (ms) |
449
+ | `guardrailsRequired` | 0 | AI-GRD.1 minimum guardrail count |
450
+ | `onFlush` | - | Callback `(payloads, receipts) => void` after each flush |
375
451
  | `factorHandoff` | - | "file" for local factor export |
376
452
  | `factorHandoffPath` | - | Directory for handoff files |
377
453
 
@@ -379,13 +455,37 @@ const witness = new Witness({
379
455
 
380
456
  | Method | Description |
381
457
  |--------|-------------|
382
- | `witness.wrap(client)` | Returns a Proxy that behaves identically to the original client. Supports OpenAI and Anthropic. |
458
+ | `witness.wrap(client)` | Returns a Proxy that behaves identically to the original client. Supports OpenAI, Anthropic, and AWS Bedrock. |
383
459
  | `witness.wrapTool(fn, name?)` | Wraps a function for tool call witnessing (AI-TOOL.1). |
384
460
  | `witness.wrapAccess(fn, resource?, scope?)` | Wraps a function for resource access witnessing (AI-ACC.1). |
385
461
  | `witness.vercelOnFinish(opts?)` | Returns an onFinish callback for Vercel AI SDK streamText/generateText. |
386
462
  | `witness.flush()` | Force-flush all buffered payloads. Returns receipts. |
387
463
  | `witness.stop()` | Stop the witness and flush remaining payloads. |
388
464
 
465
+ ## OpenTelemetry Export
466
+
467
+ New in v0.3.6. Send SWT3 anchors to your existing observability stack as OTel spans:
468
+
469
+ ```typescript
470
+ import { Witness } from "@tenova/swt3-ai";
471
+ import { OTelExporter } from "@tenova/swt3-ai/exporters/otel";
472
+
473
+ const exporter = new OTelExporter({ tracerName: "swt3-witness" });
474
+ const witness = new Witness({
475
+ endpoint: "...",
476
+ apiKey: "axm_...",
477
+ tenantId: "...",
478
+ onFlush: exporter.export.bind(exporter),
479
+ });
480
+
481
+ // Anchors now appear as spans in Datadog, Grafana, Jaeger, Honeycomb, etc.
482
+ // Span attributes: swt3.procedure_id, swt3.verdict, swt3.fingerprint, swt3.model_id, ...
483
+ ```
484
+
485
+ Install: `npm install @opentelemetry/api`
486
+
487
+ The `onFlush` callback fires after each successful batch transmission. You can use it for any custom export destination, not just OTel.
488
+
389
489
  ## Installation
390
490
 
391
491
  ```bash
@@ -394,6 +494,7 @@ npm install @tenova/swt3-ai
394
494
  # Peer dependencies (install whichever you use)
395
495
  npm install openai # for OpenAI adapter
396
496
  npm install @anthropic-ai/sdk # for Anthropic adapter
497
+ npm install @opentelemetry/api # for OTel exporter
397
498
  ```
398
499
 
399
500
  ## Regulatory Coverage
@@ -420,12 +521,43 @@ This SDK produces identical fingerprints to the Python SDK (`swt3-ai`). A unifie
420
521
  | API routes / Edge | TypeScript | @tenova/swt3-ai |
421
522
  | Frontend (Next.js) | TypeScript | @tenova/swt3-ai + Vercel AI SDK |
422
523
 
524
+ ## MCP Server (Agentic AI)
525
+
526
+ AI agents can discover SWT3 compliance tools automatically via the Model Context Protocol. No developer integration required. The agent finds the tools and uses them on its own.
527
+
528
+ ```bash
529
+ npm install @tenova/swt3-mcp
530
+ ```
531
+
532
+ Add to your MCP config:
533
+
534
+ ```json
535
+ { "mcpServers": { "swt3": { "command": "npx", "args": ["@tenova/swt3-mcp"] } } }
536
+ ```
537
+
538
+ Zero configuration required. Works immediately in demo mode. Add `SWT3_API_KEY` to connect to a production ledger. Compatible with Claude, GPT, and any MCP-compatible agent.
539
+
540
+ **Tools provided:** `witness_inference`, `verify_anchor`, `list_anchors`, `posture`, `signup`, `health`
541
+
542
+ This is the first compliance protocol with native MCP support. Agents discover witnessing through standard tool enumeration, making compliance an infrastructure capability rather than a developer burden.
543
+
423
544
  ## Privacy
424
545
 
425
546
  Your prompts and responses **never leave your infrastructure**. The SDK computes SHA-256 hashes locally and transmits only irreversible hashes and numeric factors. At Clearing Level 3, even the model name is hashed. The witness endpoint is a blind registrar: it stores cryptographic proofs, not your data.
426
547
 
427
548
  ---
428
549
 
550
+ ## Documentation
551
+
552
+ - [SDK Reference](https://sovereign.tenova.io/docs/) -- full API, all providers, clearing levels, configuration
553
+ - [10-Minute Quickstart](https://sovereign.tenova.io/guides/ai-witness-quickstart.html) -- from install to first anchor
554
+ - [SWT3 Protocol Spec](https://sovereign.tenova.io/guides/swt3-protocol.html) -- formal specification with ABNF grammar
555
+ - [Design Rationale](https://sovereign.tenova.io/guides/swt3-design-rationale.html) -- why every protocol decision was made
556
+ - [UCT Registry](https://sovereign.tenova.io/registry) -- 162 procedures, full factor definitions
557
+ - [Anchor Verifier](https://sovereign.tenova.io/verify) -- verify any anchor, zero server calls
558
+
559
+ ---
560
+
429
561
  *SWT3: Sovereign Witness Traceability. We don't run your models. We witness them.*
430
562
 
431
563
  SWT3 and Sovereign Witness Traceability are trademarks of Tenable Nova LLC. Patent pending. Apache 2.0 licensed.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * SWT3 AI Witness SDK — Anthropic Adapter (ES6 Proxy).
3
+ *
4
+ * Wraps the Anthropic client so that `client.messages.create()` is
5
+ * intercepted for witnessing. Two levels deep (simpler than OpenAI).
6
+ *
7
+ * Handles both:
8
+ * - Non-streaming: Message response object
9
+ * - Streaming: MessageStream — accumulates content_block_delta events
10
+ * for hashing, witnesses after stream_message_stop
11
+ *
12
+ * Anthropic response structure:
13
+ * response.content → ContentBlock[] (text, tool_use, etc.)
14
+ * response.model → string
15
+ * response.stop_reason → "end_turn" | "max_tokens" | "stop_sequence" | "tool_use"
16
+ * response.usage → { input_tokens, output_tokens }
17
+ *
18
+ * Anthropic streaming:
19
+ * The SDK returns a MessageStream with:
20
+ * - Symbol.asyncIterator → yields MessageStreamEvent objects
21
+ * - .on("message", cb) → fires when complete message is assembled
22
+ * - .finalMessage() → Promise<Message> (the assembled message)
23
+ *
24
+ * Events: message_start, content_block_start, content_block_delta,
25
+ * content_block_stop, message_delta, message_stop
26
+ */
27
+ import type { Witness } from "../witness.js";
28
+ /**
29
+ * Wrap an Anthropic client with an ES6 Proxy for transparent witnessing.
30
+ */
31
+ export declare function wrapAnthropic(client: unknown, witness: Witness): unknown;
32
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAYxE"}
@@ -0,0 +1,301 @@
1
+ /**
2
+ * SWT3 AI Witness SDK — Anthropic Adapter (ES6 Proxy).
3
+ *
4
+ * Wraps the Anthropic client so that `client.messages.create()` is
5
+ * intercepted for witnessing. Two levels deep (simpler than OpenAI).
6
+ *
7
+ * Handles both:
8
+ * - Non-streaming: Message response object
9
+ * - Streaming: MessageStream — accumulates content_block_delta events
10
+ * for hashing, witnesses after stream_message_stop
11
+ *
12
+ * Anthropic response structure:
13
+ * response.content → ContentBlock[] (text, tool_use, etc.)
14
+ * response.model → string
15
+ * response.stop_reason → "end_turn" | "max_tokens" | "stop_sequence" | "tool_use"
16
+ * response.usage → { input_tokens, output_tokens }
17
+ *
18
+ * Anthropic streaming:
19
+ * The SDK returns a MessageStream with:
20
+ * - Symbol.asyncIterator → yields MessageStreamEvent objects
21
+ * - .on("message", cb) → fires when complete message is assembled
22
+ * - .finalMessage() → Promise<Message> (the assembled message)
23
+ *
24
+ * Events: message_start, content_block_start, content_block_delta,
25
+ * content_block_stop, message_delta, message_stop
26
+ */
27
+ import { sha256Truncated } from "../fingerprint.js";
28
+ /**
29
+ * Wrap an Anthropic client with an ES6 Proxy for transparent witnessing.
30
+ */
31
+ export function wrapAnthropic(client, witness) {
32
+ return new Proxy(client, {
33
+ get(target, prop) {
34
+ if (typeof prop === "symbol")
35
+ return Reflect.get(target, prop);
36
+ const real = Reflect.get(target, prop);
37
+ if (prop === "messages") {
38
+ return createMessagesProxy(real, witness);
39
+ }
40
+ return real;
41
+ },
42
+ });
43
+ }
44
+ function createMessagesProxy(messages, witness) {
45
+ return new Proxy(messages, {
46
+ get(target, prop) {
47
+ if (typeof prop === "symbol")
48
+ return Reflect.get(target, prop);
49
+ const real = Reflect.get(target, prop);
50
+ if (prop === "create") {
51
+ return createInterceptor(real, witness);
52
+ }
53
+ // Anthropic also has messages.stream() — intercept that too
54
+ if (prop === "stream") {
55
+ return createStreamInterceptor(real, witness);
56
+ }
57
+ return real;
58
+ },
59
+ });
60
+ }
61
+ // ── Non-streaming / auto-detect interceptor ─────────────────────────
62
+ function createInterceptor(realMethod, witness) {
63
+ return function interceptedCreate(...args) {
64
+ const kwargs = (args[0] ?? {});
65
+ const messages = kwargs.messages;
66
+ const system = kwargs.system;
67
+ const model = kwargs.model ?? "unknown";
68
+ const isStreaming = kwargs.stream === true;
69
+ const promptText = extractPromptText(messages, system);
70
+ const promptHash = sha256Truncated(promptText);
71
+ // Hash system prompt separately (instruction drift detection)
72
+ const systemPromptText = extractSystemOnly(system);
73
+ const systemPromptHash = systemPromptText ? sha256Truncated(systemPromptText) : undefined;
74
+ // Gatekeeper pre-call check (strict mode only)
75
+ let authorizationId;
76
+ if (witness.strict) {
77
+ authorizationId = witness.gateCheck(messages, model);
78
+ }
79
+ const start = performance.now();
80
+ const result = realMethod.call(this, ...args);
81
+ if (isStreaming) {
82
+ // Streaming via create({ stream: true }) — returns a Stream
83
+ return handleStreaming(result, witness, model, promptHash, start, systemPromptHash, authorizationId);
84
+ }
85
+ // Non-streaming — result is Promise<Message>
86
+ return result.then((response) => {
87
+ const elapsedMs = Math.round(performance.now() - start);
88
+ const record = extractRecord(response, model, promptHash, elapsedMs, systemPromptHash);
89
+ witness.record(record, authorizationId);
90
+ return response;
91
+ });
92
+ };
93
+ }
94
+ // ── Explicit .stream() interceptor ──────────────────────────────────
95
+ function createStreamInterceptor(realMethod, witness) {
96
+ return function interceptedStream(...args) {
97
+ const kwargs = (args[0] ?? {});
98
+ const messages = kwargs.messages;
99
+ const system = kwargs.system;
100
+ const model = kwargs.model ?? "unknown";
101
+ const promptText = extractPromptText(messages, system);
102
+ const promptHash = sha256Truncated(promptText);
103
+ const systemPromptText = extractSystemOnly(system);
104
+ const systemPromptHash = systemPromptText ? sha256Truncated(systemPromptText) : undefined;
105
+ // Gatekeeper pre-call check (strict mode only)
106
+ let authorizationId;
107
+ if (witness.strict) {
108
+ authorizationId = witness.gateCheck(messages, model);
109
+ }
110
+ const start = performance.now();
111
+ const result = realMethod.call(this, ...args);
112
+ return handleStreaming(result, witness, model, promptHash, start, systemPromptHash, authorizationId);
113
+ };
114
+ }
115
+ // ── Streaming Handler ───────────────────────────────────────────────
116
+ async function* streamAccumulator(stream, witness, model, promptHash, startTime, systemPromptHash, authorizationId) {
117
+ const textParts = [];
118
+ let actualModel = model;
119
+ let stopReason = "";
120
+ let inputTokens;
121
+ let outputTokens;
122
+ for await (const event of stream) {
123
+ // Yield to developer immediately
124
+ yield event;
125
+ const e = event;
126
+ const type = e.type;
127
+ if (type === "message_start") {
128
+ const msg = e.message;
129
+ if (msg?.model)
130
+ actualModel = msg.model;
131
+ const usage = msg?.usage;
132
+ if (usage?.input_tokens)
133
+ inputTokens = usage.input_tokens;
134
+ }
135
+ if (type === "content_block_delta") {
136
+ const delta = e.delta;
137
+ if (delta?.type === "text_delta" && delta?.text) {
138
+ textParts.push(delta.text);
139
+ }
140
+ }
141
+ if (type === "message_delta") {
142
+ const delta = e.delta;
143
+ if (delta?.stop_reason)
144
+ stopReason = delta.stop_reason;
145
+ const usage = e.usage;
146
+ if (usage?.output_tokens)
147
+ outputTokens = usage.output_tokens;
148
+ }
149
+ }
150
+ // Stream complete — witness
151
+ const elapsedMs = Math.round(performance.now() - startTime);
152
+ const responseText = textParts.join("");
153
+ const hasRefusal = !["end_turn", "max_tokens", "stop_sequence", "tool_use"].includes(stopReason);
154
+ const record = {
155
+ modelId: actualModel,
156
+ modelHash: sha256Truncated(actualModel),
157
+ promptHash,
158
+ responseHash: sha256Truncated(responseText),
159
+ latencyMs: elapsedMs,
160
+ inputTokens,
161
+ outputTokens,
162
+ guardrailsActive: 0,
163
+ guardrailsRequired: 0,
164
+ guardrailPassed: true,
165
+ hasRefusal,
166
+ provider: "anthropic",
167
+ systemPromptHash,
168
+ guardrailNames: [],
169
+ };
170
+ witness.record(record, authorizationId);
171
+ }
172
+ function handleStreaming(streamResult, witness, model, promptHash, startTime, systemPromptHash, authorizationId) {
173
+ // Anthropic's stream() returns a MessageStream directly (not a Promise)
174
+ // But create({ stream: true }) may return a Promise<Stream>
175
+ if (streamResult && typeof streamResult.then === "function") {
176
+ return streamResult.then((stream) => wrapAnthropicStream(stream, witness, model, promptHash, startTime, systemPromptHash, authorizationId));
177
+ }
178
+ return wrapAnthropicStream(streamResult, witness, model, promptHash, startTime, systemPromptHash, authorizationId);
179
+ }
180
+ function wrapAnthropicStream(stream, witness, model, promptHash, startTime, systemPromptHash, authorizationId) {
181
+ const s = stream;
182
+ const gen = streamAccumulator(s, witness, model, promptHash, startTime, systemPromptHash, authorizationId);
183
+ return new Proxy(s, {
184
+ get(target, prop) {
185
+ if (prop === Symbol.asyncIterator) {
186
+ return () => gen;
187
+ }
188
+ const value = Reflect.get(target, prop);
189
+ if (typeof value === "function") {
190
+ // Wrap finalMessage() to also witness the complete response
191
+ if (prop === "finalMessage") {
192
+ return async function wrappedFinalMessage() {
193
+ const msg = await value.call(target);
194
+ // The stream accumulator will have already witnessed via iteration,
195
+ // but if someone calls finalMessage() WITHOUT iterating, we need
196
+ // to witness from the assembled message.
197
+ return msg;
198
+ };
199
+ }
200
+ return value.bind(target);
201
+ }
202
+ return value;
203
+ },
204
+ });
205
+ }
206
+ // ── Factor Extraction ──────────────────────────────────────────────
207
+ function extractSystemOnly(system) {
208
+ if (typeof system === "string" && system)
209
+ return system;
210
+ if (Array.isArray(system)) {
211
+ const parts = [];
212
+ for (const block of system) {
213
+ if (typeof block === "object" && block !== null) {
214
+ const b = block;
215
+ if (b.type === "text" && typeof b.text === "string") {
216
+ parts.push(b.text);
217
+ }
218
+ }
219
+ }
220
+ return parts.length > 0 ? parts.join("\n") : undefined;
221
+ }
222
+ return undefined;
223
+ }
224
+ function extractPromptText(messages, system = "") {
225
+ const parts = [];
226
+ // System prompt
227
+ if (typeof system === "string" && system) {
228
+ parts.push(system);
229
+ }
230
+ else if (Array.isArray(system)) {
231
+ for (const block of system) {
232
+ if (typeof block === "object" && block !== null) {
233
+ const b = block;
234
+ if (b.type === "text" && typeof b.text === "string") {
235
+ parts.push(b.text);
236
+ }
237
+ }
238
+ }
239
+ }
240
+ // Messages
241
+ if (Array.isArray(messages)) {
242
+ for (const msg of messages) {
243
+ if (typeof msg === "object" && msg !== null) {
244
+ const m = msg;
245
+ const content = m.content;
246
+ if (typeof content === "string") {
247
+ parts.push(content);
248
+ }
249
+ else if (Array.isArray(content)) {
250
+ for (const block of content) {
251
+ if (typeof block === "object" && block !== null) {
252
+ const b = block;
253
+ if (b.type === "text" && typeof b.text === "string") {
254
+ parts.push(b.text);
255
+ }
256
+ }
257
+ }
258
+ }
259
+ }
260
+ }
261
+ }
262
+ return parts.join("\n");
263
+ }
264
+ function extractRecord(response, model, promptHash, elapsedMs, systemPromptHash) {
265
+ const r = response;
266
+ // Extract text from content blocks
267
+ let responseText = "";
268
+ const contentBlocks = r.content;
269
+ if (Array.isArray(contentBlocks)) {
270
+ const texts = [];
271
+ for (const block of contentBlocks) {
272
+ if (block.type === "text" && typeof block.text === "string") {
273
+ texts.push(block.text);
274
+ }
275
+ }
276
+ responseText = texts.join("\n");
277
+ }
278
+ const stopReason = r.stop_reason ?? "";
279
+ const hasRefusal = !["end_turn", "max_tokens", "stop_sequence", "tool_use"].includes(stopReason);
280
+ const usage = r.usage;
281
+ const inputTokens = usage?.input_tokens;
282
+ const outputTokens = usage?.output_tokens;
283
+ const actualModel = r.model ?? model;
284
+ return {
285
+ modelId: actualModel,
286
+ modelHash: sha256Truncated(actualModel),
287
+ promptHash,
288
+ responseHash: sha256Truncated(responseText),
289
+ latencyMs: elapsedMs,
290
+ inputTokens,
291
+ outputTokens,
292
+ guardrailsActive: 0,
293
+ guardrailsRequired: 0,
294
+ guardrailPassed: true,
295
+ hasRefusal,
296
+ provider: "anthropic",
297
+ systemPromptHash,
298
+ guardrailNames: [],
299
+ };
300
+ }
301
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
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 type { Witness } from "../witness.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 declare function wrapBedrock(client: unknown, witness: Witness): unknown;
33
+ //# sourceMappingURL=bedrock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock.d.ts","sourceRoot":"","sources":["../../src/adapters/bedrock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAatE"}