@rulemetric/proxy 0.2.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.
Files changed (47) hide show
  1. package/Dockerfile +28 -0
  2. package/addon/context_classifier.py +375 -0
  3. package/addon/providers.py +483 -0
  4. package/addon/reporter.py +778 -0
  5. package/addon/requirements.txt +1 -0
  6. package/addon/rulemetric_addon.py +1288 -0
  7. package/addon/secret_redactor.py +130 -0
  8. package/addon/security_scanner.py +828 -0
  9. package/addon/session_linker.py +206 -0
  10. package/addon/sse_parser.py +364 -0
  11. package/dist/index.d.ts +10 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +9 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/providers/anthropic.d.ts +8 -0
  16. package/dist/providers/anthropic.d.ts.map +1 -0
  17. package/dist/providers/anthropic.js +135 -0
  18. package/dist/providers/anthropic.js.map +1 -0
  19. package/dist/providers/base.d.ts +11 -0
  20. package/dist/providers/base.d.ts.map +1 -0
  21. package/dist/providers/base.js +43 -0
  22. package/dist/providers/base.js.map +1 -0
  23. package/dist/providers/bedrock.d.ts +8 -0
  24. package/dist/providers/bedrock.d.ts.map +1 -0
  25. package/dist/providers/bedrock.js +125 -0
  26. package/dist/providers/bedrock.js.map +1 -0
  27. package/dist/providers/gemini.d.ts +9 -0
  28. package/dist/providers/gemini.d.ts.map +1 -0
  29. package/dist/providers/gemini.js +140 -0
  30. package/dist/providers/gemini.js.map +1 -0
  31. package/dist/providers/index.d.ts +8 -0
  32. package/dist/providers/index.d.ts.map +1 -0
  33. package/dist/providers/index.js +116 -0
  34. package/dist/providers/index.js.map +1 -0
  35. package/dist/providers/openai.d.ts +9 -0
  36. package/dist/providers/openai.d.ts.map +1 -0
  37. package/dist/providers/openai.js +129 -0
  38. package/dist/providers/openai.js.map +1 -0
  39. package/dist/session-linker.d.ts +6 -0
  40. package/dist/session-linker.d.ts.map +1 -0
  41. package/dist/session-linker.js +68 -0
  42. package/dist/session-linker.js.map +1 -0
  43. package/dist/types.d.ts +41 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +2 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +33 -0
@@ -0,0 +1,135 @@
1
+ import { BaseAdapter } from './base.js';
2
+ export class AnthropicAdapter extends BaseAdapter {
3
+ provider = 'anthropic';
4
+ canHandle(host, path) {
5
+ return host.includes('anthropic') && path.startsWith('/v1/messages');
6
+ }
7
+ parse(body) {
8
+ const parsed = this.safeJsonParse(body);
9
+ if (!parsed || typeof parsed !== 'object')
10
+ return null;
11
+ const raw = parsed;
12
+ // Model
13
+ const model = typeof raw.model === 'string' ? raw.model : 'unknown';
14
+ // System blocks
15
+ const systemBlocks = [];
16
+ if (typeof raw.system === 'string') {
17
+ systemBlocks.push({ text: raw.system });
18
+ }
19
+ else if (Array.isArray(raw.system)) {
20
+ for (const block of raw.system) {
21
+ if (block && typeof block === 'object') {
22
+ const b = block;
23
+ const sb = { text: typeof b.text === 'string' ? b.text : '' };
24
+ if (b.cache_control !== undefined) {
25
+ sb.cacheControl = b.cache_control;
26
+ }
27
+ systemBlocks.push(sb);
28
+ }
29
+ }
30
+ }
31
+ // System prompt = concatenation of all system block texts
32
+ const systemPrompt = systemBlocks.map((b) => b.text).join('\n');
33
+ // Messages
34
+ const messages = [];
35
+ const rawMessages = Array.isArray(raw.messages) ? raw.messages : [];
36
+ for (const msg of rawMessages) {
37
+ if (!msg || typeof msg !== 'object')
38
+ continue;
39
+ const m = msg;
40
+ const role = m.role;
41
+ if (typeof m.content === 'string') {
42
+ messages.push({
43
+ role: role === 'user' ? 'user' : 'assistant',
44
+ content: m.content,
45
+ });
46
+ }
47
+ else if (Array.isArray(m.content)) {
48
+ const textParts = [];
49
+ let hasToolCalls = false;
50
+ let isToolResult = false;
51
+ for (const block of m.content) {
52
+ if (!block || typeof block !== 'object')
53
+ continue;
54
+ const bl = block;
55
+ if (bl.type === 'text' && typeof bl.text === 'string') {
56
+ textParts.push(bl.text);
57
+ }
58
+ else if (bl.type === 'tool_use') {
59
+ hasToolCalls = true;
60
+ }
61
+ else if (bl.type === 'tool_result') {
62
+ isToolResult = true;
63
+ // Extract text from tool_result content
64
+ if (typeof bl.content === 'string') {
65
+ textParts.push(bl.content);
66
+ }
67
+ else if (Array.isArray(bl.content)) {
68
+ for (const inner of bl.content) {
69
+ if (inner && typeof inner === 'object') {
70
+ const ib = inner;
71
+ if (ib.type === 'text' && typeof ib.text === 'string') {
72
+ textParts.push(ib.text);
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ // type: "image" → skip
79
+ }
80
+ const normalized = {
81
+ role: isToolResult ? 'tool' : role === 'user' ? 'user' : 'assistant',
82
+ content: textParts.join('\n'),
83
+ };
84
+ if (hasToolCalls) {
85
+ normalized.hasToolCalls = true;
86
+ }
87
+ messages.push(normalized);
88
+ }
89
+ }
90
+ // Tools
91
+ const tools = [];
92
+ if (Array.isArray(raw.tools)) {
93
+ for (const tool of raw.tools) {
94
+ if (!tool || typeof tool !== 'object')
95
+ continue;
96
+ const t = tool;
97
+ tools.push({
98
+ name: typeof t.name === 'string' ? t.name : '',
99
+ description: typeof t.description === 'string' ? t.description : '',
100
+ parameters: t.input_schema ?? {},
101
+ });
102
+ }
103
+ }
104
+ // Injected instructions: extract from system prompt and user messages only
105
+ const injectedInstructions = [];
106
+ injectedInstructions.push(...this.extractInjectedInstructions(systemPrompt));
107
+ for (const msg of messages) {
108
+ if (msg.role === 'user') {
109
+ injectedInstructions.push(...this.extractInjectedInstructions(msg.content));
110
+ }
111
+ }
112
+ // Build snapshot
113
+ const snapshot = {
114
+ provider: 'anthropic',
115
+ model,
116
+ systemPrompt,
117
+ systemBlocks,
118
+ messages,
119
+ tools,
120
+ maxTokens: typeof raw.max_tokens === 'number' ? raw.max_tokens : 0,
121
+ injectedInstructions,
122
+ systemPromptHash: this.computeSystemHash(systemPrompt),
123
+ messageCount: messages.length,
124
+ toolCount: tools.length,
125
+ estimatedTokens: 0,
126
+ capturedAt: new Date().toISOString(),
127
+ };
128
+ if (typeof raw.temperature === 'number') {
129
+ snapshot.temperature = raw.temperature;
130
+ }
131
+ snapshot.estimatedTokens = this.estimateTokens(snapshot);
132
+ return snapshot;
133
+ }
134
+ }
135
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,OAAO,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,GAAa,WAAW,CAAC;IAEjC,SAAS,CAAC,IAAY,EAAE,IAAY;QAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAEvD,MAAM,GAAG,GAAG,MAAiC,CAAC;QAE9C,QAAQ;QACR,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QAEpE,gBAAgB;QAChB,MAAM,YAAY,GAAkB,EAAE,CAAC;QACvC,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACnC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACrC,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC/B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACvC,MAAM,CAAC,GAAG,KAAgC,CAAC;oBAC3C,MAAM,EAAE,GAAgB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;oBAC3E,IAAI,CAAC,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;wBAClC,EAAE,CAAC,YAAY,GAAG,CAAC,CAAC,aAAa,CAAC;oBACpC,CAAC;oBACD,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;QAED,0DAA0D;QAC1D,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEhE,WAAW;QACX,MAAM,QAAQ,GAAwB,EAAE,CAAC;QACzC,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAEpE,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,SAAS;YAC9C,MAAM,CAAC,GAAG,GAA8B,CAAC;YACzC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAc,CAAC;YAE9B,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAClC,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW;oBAC5C,OAAO,EAAE,CAAC,CAAC,OAAO;iBACnB,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpC,MAAM,SAAS,GAAa,EAAE,CAAC;gBAC/B,IAAI,YAAY,GAAG,KAAK,CAAC;gBACzB,IAAI,YAAY,GAAG,KAAK,CAAC;gBAEzB,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;oBAC9B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;wBAAE,SAAS;oBAClD,MAAM,EAAE,GAAG,KAAgC,CAAC;oBAE5C,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBACtD,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;oBAC1B,CAAC;yBAAM,IAAI,EAAE,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;wBAClC,YAAY,GAAG,IAAI,CAAC;oBACtB,CAAC;yBAAM,IAAI,EAAE,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;wBACrC,YAAY,GAAG,IAAI,CAAC;wBACpB,wCAAwC;wBACxC,IAAI,OAAO,EAAE,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;4BACnC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;wBAC7B,CAAC;6BAAM,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;4BACrC,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;gCAC/B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oCACvC,MAAM,EAAE,GAAG,KAAgC,CAAC;oCAC5C,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wCACtD,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;oCAC1B,CAAC;gCACH,CAAC;4BACH,CAAC;wBACH,CAAC;oBACH,CAAC;oBACD,uBAAuB;gBACzB,CAAC;gBAED,MAAM,UAAU,GAAsB;oBACpC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW;oBACpE,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;iBAC9B,CAAC;gBACF,IAAI,YAAY,EAAE,CAAC;oBACjB,UAAU,CAAC,YAAY,GAAG,IAAI,CAAC;gBACjC,CAAC;gBACD,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,QAAQ;QACR,MAAM,KAAK,GAAqB,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;oBAAE,SAAS;gBAChD,MAAM,CAAC,GAAG,IAA+B,CAAC;gBAC1C,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;oBAC9C,WAAW,EAAE,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;oBACnE,UAAU,EAAG,CAAC,CAAC,YAAwC,IAAI,EAAE;iBAC9D,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,2EAA2E;QAC3E,MAAM,oBAAoB,GAAa,EAAE,CAAC;QAC1C,oBAAoB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,2BAA2B,CAAC,YAAY,CAAC,CAAC,CAAC;QAC7E,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACxB,oBAAoB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,MAAM,QAAQ,GAAoB;YAChC,QAAQ,EAAE,WAAW;YACrB,KAAK;YACL,YAAY;YACZ,YAAY;YACZ,QAAQ;YACR,KAAK;YACL,SAAS,EAAE,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAClE,oBAAoB;YACpB,gBAAgB,EAAE,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;YACtD,YAAY,EAAE,QAAQ,CAAC,MAAM;YAC7B,SAAS,EAAE,KAAK,CAAC,MAAM;YACvB,eAAe,EAAE,CAAC;YAClB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC;QAEF,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACxC,QAAQ,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;QACzC,CAAC;QAED,QAAQ,CAAC,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAEzD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import type { ContextSnapshot, Provider, ProviderAdapter } from '../types.js';
2
+ export declare abstract class BaseAdapter implements ProviderAdapter {
3
+ abstract provider: Provider;
4
+ abstract canHandle(host: string, path: string): boolean;
5
+ abstract parse(body: string): ContextSnapshot | null;
6
+ extractInjectedInstructions(text: string): string[];
7
+ computeSystemHash(systemPrompt: string): string;
8
+ estimateTokens(snapshot: ContextSnapshot): number;
9
+ safeJsonParse(body: string): unknown | null;
10
+ }
11
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/providers/base.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAK9E,8BAAsB,WAAY,YAAW,eAAe;IAC1D,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IACvD,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAEpD,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAanD,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAI/C,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM;IAWjD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;CAW5C"}
@@ -0,0 +1,43 @@
1
+ import { createHash } from 'node:crypto';
2
+ const SYSTEM_REMINDER_RE = /<system-reminder>([\s\S]*?)<\/system-reminder>/g;
3
+ const MAX_BODY_SIZE = 2 * 1024 * 1024; // 2MB safety limit
4
+ export class BaseAdapter {
5
+ extractInjectedInstructions(text) {
6
+ const results = [];
7
+ let match;
8
+ const re = new RegExp(SYSTEM_REMINDER_RE.source, 'gs');
9
+ while ((match = re.exec(text)) !== null) {
10
+ const content = match[1].trim();
11
+ if (content) {
12
+ results.push(content);
13
+ }
14
+ }
15
+ return results;
16
+ }
17
+ computeSystemHash(systemPrompt) {
18
+ return createHash('sha256').update(systemPrompt).digest('hex');
19
+ }
20
+ estimateTokens(snapshot) {
21
+ let chars = snapshot.systemPrompt.length;
22
+ for (const msg of snapshot.messages) {
23
+ chars += msg.content.length;
24
+ }
25
+ for (const tool of snapshot.tools) {
26
+ chars += tool.name.length + tool.description.length + JSON.stringify(tool.parameters).length;
27
+ }
28
+ return Math.ceil(chars / 4);
29
+ }
30
+ safeJsonParse(body) {
31
+ if (body.length > MAX_BODY_SIZE) {
32
+ console.warn(`[rulemetric] Request body truncated from ${body.length} to ${MAX_BODY_SIZE} bytes — snapshot may be incomplete`);
33
+ body = body.slice(0, MAX_BODY_SIZE);
34
+ }
35
+ try {
36
+ return JSON.parse(body);
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ }
43
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/providers/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,kBAAkB,GAAG,iDAAiD,CAAC;AAC7E,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,mBAAmB;AAE1D,MAAM,OAAgB,WAAW;IAK/B,2BAA2B,CAAC,IAAY;QACtC,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,KAA6B,CAAC;QAClC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACvD,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACxC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAChC,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,iBAAiB,CAAC,YAAoB;QACpC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IAED,cAAc,CAAC,QAAyB;QACtC,IAAI,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACpC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;QAC9B,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YAClC,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;QAC/F,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC9B,CAAC;IAED,aAAa,CAAC,IAAY;QACxB,IAAI,IAAI,CAAC,MAAM,GAAG,aAAa,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,4CAA4C,IAAI,CAAC,MAAM,OAAO,aAAa,qCAAqC,CAAC,CAAC;YAC/H,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ import type { ContextSnapshot, Provider } from '../types.js';
2
+ import { BaseAdapter } from './base.js';
3
+ export declare class BedrockAdapter extends BaseAdapter {
4
+ provider: Provider;
5
+ canHandle(host: string, path: string): boolean;
6
+ parse(body: string): ContextSnapshot | null;
7
+ }
8
+ //# sourceMappingURL=bedrock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock.d.ts","sourceRoot":"","sources":["../../src/providers/bedrock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAqC,QAAQ,EAAe,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,qBAAa,cAAe,SAAQ,WAAW;IAC7C,QAAQ,EAAE,QAAQ,CAAa;IAE/B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAI9C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;CAiI5C"}
@@ -0,0 +1,125 @@
1
+ import { BaseAdapter } from './base.js';
2
+ export class BedrockAdapter extends BaseAdapter {
3
+ provider = 'bedrock';
4
+ canHandle(host, path) {
5
+ return host.includes('bedrock-runtime') && path.includes('/converse');
6
+ }
7
+ parse(body) {
8
+ const parsed = this.safeJsonParse(body);
9
+ if (!parsed || typeof parsed !== 'object')
10
+ return null;
11
+ const raw = parsed;
12
+ // Model
13
+ const model = typeof raw.modelId === 'string' ? raw.modelId : 'unknown';
14
+ // System blocks — always an array of { text: string }
15
+ const systemBlocks = [];
16
+ if (Array.isArray(raw.system)) {
17
+ for (const block of raw.system) {
18
+ if (block && typeof block === 'object') {
19
+ const b = block;
20
+ systemBlocks.push({ text: typeof b.text === 'string' ? b.text : '' });
21
+ }
22
+ }
23
+ }
24
+ const systemPrompt = systemBlocks.map((b) => b.text).join('\n');
25
+ // Messages
26
+ const messages = [];
27
+ const rawMessages = Array.isArray(raw.messages) ? raw.messages : [];
28
+ for (const msg of rawMessages) {
29
+ if (!msg || typeof msg !== 'object')
30
+ continue;
31
+ const m = msg;
32
+ const role = m.role;
33
+ if (Array.isArray(m.content)) {
34
+ const textParts = [];
35
+ let hasToolCalls = false;
36
+ let isToolResult = false;
37
+ for (const block of m.content) {
38
+ if (!block || typeof block !== 'object')
39
+ continue;
40
+ const bl = block;
41
+ if (typeof bl.text === 'string') {
42
+ textParts.push(bl.text);
43
+ }
44
+ else if (bl.toolUse !== undefined) {
45
+ hasToolCalls = true;
46
+ }
47
+ else if (bl.toolResult !== undefined) {
48
+ isToolResult = true;
49
+ // Extract text from toolResult.content[].text
50
+ const tr = bl.toolResult;
51
+ if (tr && Array.isArray(tr.content)) {
52
+ for (const inner of tr.content) {
53
+ if (inner && typeof inner === 'object') {
54
+ const ib = inner;
55
+ if (typeof ib.text === 'string') {
56
+ textParts.push(ib.text);
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ const normalized = {
64
+ role: isToolResult ? 'tool' : role === 'user' ? 'user' : 'assistant',
65
+ content: textParts.join('\n'),
66
+ };
67
+ if (hasToolCalls) {
68
+ normalized.hasToolCalls = true;
69
+ }
70
+ messages.push(normalized);
71
+ }
72
+ }
73
+ // Tools — toolConfig.tools[].toolSpec
74
+ const tools = [];
75
+ const toolConfig = raw.toolConfig;
76
+ if (toolConfig && Array.isArray(toolConfig.tools)) {
77
+ for (const tool of toolConfig.tools) {
78
+ if (!tool || typeof tool !== 'object')
79
+ continue;
80
+ const t = tool;
81
+ const spec = t.toolSpec;
82
+ if (!spec)
83
+ continue;
84
+ const inputSchema = spec.inputSchema;
85
+ const parameters = inputSchema?.json ?? {};
86
+ tools.push({
87
+ name: typeof spec.name === 'string' ? spec.name : '',
88
+ description: typeof spec.description === 'string' ? spec.description : '',
89
+ parameters,
90
+ });
91
+ }
92
+ }
93
+ // Injected instructions from system prompt and user messages
94
+ const injectedInstructions = [];
95
+ injectedInstructions.push(...this.extractInjectedInstructions(systemPrompt));
96
+ for (const msg of messages) {
97
+ if (msg.role === 'user') {
98
+ injectedInstructions.push(...this.extractInjectedInstructions(msg.content));
99
+ }
100
+ }
101
+ // Inference config
102
+ const inferenceConfig = raw.inferenceConfig;
103
+ const snapshot = {
104
+ provider: 'bedrock',
105
+ model,
106
+ systemPrompt,
107
+ systemBlocks,
108
+ messages,
109
+ tools,
110
+ maxTokens: typeof inferenceConfig?.maxTokens === 'number' ? inferenceConfig.maxTokens : 0,
111
+ injectedInstructions,
112
+ systemPromptHash: this.computeSystemHash(systemPrompt),
113
+ messageCount: messages.length,
114
+ toolCount: tools.length,
115
+ estimatedTokens: 0,
116
+ capturedAt: new Date().toISOString(),
117
+ };
118
+ if (typeof inferenceConfig?.temperature === 'number') {
119
+ snapshot.temperature = inferenceConfig.temperature;
120
+ }
121
+ snapshot.estimatedTokens = this.estimateTokens(snapshot);
122
+ return snapshot;
123
+ }
124
+ }
125
+ //# sourceMappingURL=bedrock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock.js","sourceRoot":"","sources":["../../src/providers/bedrock.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,OAAO,cAAe,SAAQ,WAAW;IAC7C,QAAQ,GAAa,SAAS,CAAC;IAE/B,SAAS,CAAC,IAAY,EAAE,IAAY;QAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAEvD,MAAM,GAAG,GAAG,MAAiC,CAAC;QAE9C,QAAQ;QACR,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAExE,sDAAsD;QACtD,MAAM,YAAY,GAAkB,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC/B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACvC,MAAM,CAAC,GAAG,KAAgC,CAAC;oBAC3C,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEhE,WAAW;QACX,MAAM,QAAQ,GAAwB,EAAE,CAAC;QACzC,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAEpE,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,SAAS;YAC9C,MAAM,CAAC,GAAG,GAA8B,CAAC;YACzC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAc,CAAC;YAE9B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7B,MAAM,SAAS,GAAa,EAAE,CAAC;gBAC/B,IAAI,YAAY,GAAG,KAAK,CAAC;gBACzB,IAAI,YAAY,GAAG,KAAK,CAAC;gBAEzB,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;oBAC9B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;wBAAE,SAAS;oBAClD,MAAM,EAAE,GAAG,KAAgC,CAAC;oBAE5C,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBAChC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;oBAC1B,CAAC;yBAAM,IAAI,EAAE,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;wBACpC,YAAY,GAAG,IAAI,CAAC;oBACtB,CAAC;yBAAM,IAAI,EAAE,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;wBACvC,YAAY,GAAG,IAAI,CAAC;wBACpB,8CAA8C;wBAC9C,MAAM,EAAE,GAAG,EAAE,CAAC,UAAqC,CAAC;wBACpD,IAAI,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;4BACpC,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;gCAC/B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oCACvC,MAAM,EAAE,GAAG,KAAgC,CAAC;oCAC5C,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wCAChC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;oCAC1B,CAAC;gCACH,CAAC;4BACH,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,MAAM,UAAU,GAAsB;oBACpC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW;oBACpE,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;iBAC9B,CAAC;gBACF,IAAI,YAAY,EAAE,CAAC;oBACjB,UAAU,CAAC,YAAY,GAAG,IAAI,CAAC;gBACjC,CAAC;gBACD,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,sCAAsC;QACtC,MAAM,KAAK,GAAqB,EAAE,CAAC;QACnC,MAAM,UAAU,GAAG,GAAG,CAAC,UAAiD,CAAC;QACzE,IAAI,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;gBACpC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;oBAAE,SAAS;gBAChD,MAAM,CAAC,GAAG,IAA+B,CAAC;gBAC1C,MAAM,IAAI,GAAG,CAAC,CAAC,QAA+C,CAAC;gBAC/D,IAAI,CAAC,IAAI;oBAAE,SAAS;gBAEpB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAkD,CAAC;gBAC5E,MAAM,UAAU,GAAG,WAAW,EAAE,IAA+B,IAAI,EAAE,CAAC;gBAEtE,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;oBACpD,WAAW,EAAE,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;oBACzE,UAAU;iBACX,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,6DAA6D;QAC7D,MAAM,oBAAoB,GAAa,EAAE,CAAC;QAC1C,oBAAoB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,2BAA2B,CAAC,YAAY,CAAC,CAAC,CAAC;QAC7E,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACxB,oBAAoB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;QAED,mBAAmB;QACnB,MAAM,eAAe,GAAG,GAAG,CAAC,eAAsD,CAAC;QAEnF,MAAM,QAAQ,GAAoB;YAChC,QAAQ,EAAE,SAAS;YACnB,KAAK;YACL,YAAY;YACZ,YAAY;YACZ,QAAQ;YACR,KAAK;YACL,SAAS,EAAE,OAAO,eAAe,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACzF,oBAAoB;YACpB,gBAAgB,EAAE,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC;YACtD,YAAY,EAAE,QAAQ,CAAC,MAAM;YAC7B,SAAS,EAAE,KAAK,CAAC,MAAM;YACvB,eAAe,EAAE,CAAC;YAClB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC;QAEF,IAAI,OAAO,eAAe,EAAE,WAAW,KAAK,QAAQ,EAAE,CAAC;YACrD,QAAQ,CAAC,WAAW,GAAG,eAAe,CAAC,WAAW,CAAC;QACrD,CAAC;QAED,QAAQ,CAAC,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAEzD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ import type { ContextSnapshot, Provider } from '../types.js';
2
+ import { BaseAdapter } from './base.js';
3
+ export declare class GeminiAdapter extends BaseAdapter {
4
+ provider: Provider;
5
+ private estimateGeminiTokens;
6
+ canHandle(host: string, path: string): boolean;
7
+ parse(body: string): ContextSnapshot | null;
8
+ }
9
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAqC,QAAQ,EAAe,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,EAAE,QAAQ,CAAY;IAE9B,OAAO,CAAC,oBAAoB;IAI5B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAI9C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;CA4I5C"}
@@ -0,0 +1,140 @@
1
+ import { BaseAdapter } from './base.js';
2
+ export class GeminiAdapter extends BaseAdapter {
3
+ provider = 'gemini';
4
+ estimateGeminiTokens(snapshot) {
5
+ return Math.floor(snapshot.systemPrompt.length / 4);
6
+ }
7
+ canHandle(host, path) {
8
+ return host.includes('googleapis.com') && path.includes(':generateContent');
9
+ }
10
+ parse(body) {
11
+ const parsed = this.safeJsonParse(body);
12
+ if (!parsed || typeof parsed !== 'object')
13
+ return null;
14
+ const raw = parsed;
15
+ // Model
16
+ const model = typeof raw.model === 'string' ? raw.model : 'unknown';
17
+ // System blocks from systemInstruction
18
+ const systemBlocks = [];
19
+ const sysInst = raw.systemInstruction;
20
+ if (sysInst && typeof sysInst === 'object' && Array.isArray(sysInst.parts)) {
21
+ for (const part of sysInst.parts) {
22
+ if (part && typeof part === 'object') {
23
+ const p = part;
24
+ if (typeof p.text === 'string') {
25
+ systemBlocks.push({ text: p.text });
26
+ }
27
+ }
28
+ }
29
+ }
30
+ // System prompt = concatenation of all system block texts
31
+ const systemPrompt = systemBlocks.map((b) => b.text).join('\n');
32
+ // Messages from contents[]
33
+ const messages = [];
34
+ const rawContents = Array.isArray(raw.contents) ? raw.contents : [];
35
+ for (const content of rawContents) {
36
+ if (!content || typeof content !== 'object')
37
+ continue;
38
+ const c = content;
39
+ const role = c.role;
40
+ const textParts = [];
41
+ let hasToolCalls = false;
42
+ let hasFunctionResponse = false;
43
+ if (Array.isArray(c.parts)) {
44
+ for (const part of c.parts) {
45
+ if (!part || typeof part !== 'object')
46
+ continue;
47
+ const p = part;
48
+ if (typeof p.text === 'string') {
49
+ textParts.push(p.text);
50
+ }
51
+ else if (p.inlineData !== undefined) {
52
+ // skip inline data
53
+ }
54
+ else if (p.functionCall !== undefined) {
55
+ hasToolCalls = true;
56
+ }
57
+ else if (p.functionResponse !== undefined) {
58
+ hasFunctionResponse = true;
59
+ }
60
+ }
61
+ }
62
+ let normalizedRole;
63
+ if (hasFunctionResponse) {
64
+ normalizedRole = 'tool';
65
+ }
66
+ else if (role === 'model') {
67
+ normalizedRole = 'assistant';
68
+ }
69
+ else {
70
+ normalizedRole = 'user';
71
+ }
72
+ const normalized = {
73
+ role: normalizedRole,
74
+ content: textParts.join(''),
75
+ };
76
+ if (hasToolCalls) {
77
+ normalized.hasToolCalls = true;
78
+ }
79
+ messages.push(normalized);
80
+ }
81
+ // Tools from tools[].functionDeclarations[]
82
+ const tools = [];
83
+ if (Array.isArray(raw.tools)) {
84
+ for (const toolGroup of raw.tools) {
85
+ if (!toolGroup || typeof toolGroup !== 'object')
86
+ continue;
87
+ const tg = toolGroup;
88
+ if (Array.isArray(tg.functionDeclarations)) {
89
+ for (const decl of tg.functionDeclarations) {
90
+ if (!decl || typeof decl !== 'object')
91
+ continue;
92
+ const d = decl;
93
+ tools.push({
94
+ name: typeof d.name === 'string' ? d.name : '',
95
+ description: typeof d.description === 'string' ? d.description : '',
96
+ parameters: d.parameters ?? {},
97
+ });
98
+ }
99
+ }
100
+ }
101
+ }
102
+ // Generation config
103
+ const genConfig = raw.generationConfig;
104
+ const maxTokens = genConfig && typeof genConfig === 'object' && typeof genConfig.maxOutputTokens === 'number'
105
+ ? genConfig.maxOutputTokens
106
+ : 0;
107
+ // Injected instructions: extract from system prompt and user messages
108
+ const injectedInstructions = [];
109
+ injectedInstructions.push(...this.extractInjectedInstructions(systemPrompt));
110
+ for (const msg of messages) {
111
+ if (msg.role === 'user') {
112
+ injectedInstructions.push(...this.extractInjectedInstructions(msg.content));
113
+ }
114
+ }
115
+ // Build snapshot
116
+ const snapshot = {
117
+ provider: 'gemini',
118
+ model,
119
+ systemPrompt,
120
+ systemBlocks,
121
+ messages,
122
+ tools,
123
+ maxTokens,
124
+ injectedInstructions,
125
+ systemPromptHash: this.computeSystemHash(systemPrompt),
126
+ messageCount: messages.length,
127
+ toolCount: tools.length,
128
+ estimatedTokens: 0,
129
+ capturedAt: new Date().toISOString(),
130
+ };
131
+ if (genConfig &&
132
+ typeof genConfig === 'object' &&
133
+ typeof genConfig.temperature === 'number') {
134
+ snapshot.temperature = genConfig.temperature;
135
+ }
136
+ snapshot.estimatedTokens = this.estimateGeminiTokens(snapshot);
137
+ return snapshot;
138
+ }
139
+ }
140
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Provider, ProviderAdapter } from '../types.js';
2
+ export declare function detectProvider(host: string, path: string): Provider | null;
3
+ export declare class ProviderRegistry {
4
+ private adapters;
5
+ register(adapter: ProviderAdapter): void;
6
+ detect(host: string, path: string): ProviderAdapter | null;
7
+ }
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAsF7D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAmC1E;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAyB;IAEzC,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAIxC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;CAQ3D"}
@@ -0,0 +1,116 @@
1
+ /** Map of known OpenAI-compatible hostnames to provider names. */
2
+ const KNOWN_OPENAI_COMPAT_HOSTS = {
3
+ 'api.openai.com': 'openai',
4
+ 'api.groq.com': 'groq',
5
+ 'api.together.xyz': 'together',
6
+ 'api.fireworks.ai': 'fireworks',
7
+ 'api.deepseek.com': 'deepseek',
8
+ 'api.perplexity.ai': 'perplexity',
9
+ 'api.cerebras.ai': 'cerebras',
10
+ 'api.sambanova.ai': 'sambanova',
11
+ 'api.x.ai': 'xai',
12
+ 'api.mistral.ai': 'mistral',
13
+ 'integrate.api.nvidia.com': 'nvidia_nim',
14
+ 'api.ai21.com': 'ai21',
15
+ 'api.cohere.com': 'cohere',
16
+ 'openrouter.ai': 'openrouter',
17
+ 'openai-proxy.replicate.com': 'replicate',
18
+ };
19
+ /** Derive a short provider name from a hostname (for unknown OpenAI-compat providers). */
20
+ function providerFromHost(host) {
21
+ const h = host.split(':')[0];
22
+ const parts = h.split('.');
23
+ if (parts.length >= 2) {
24
+ const candidate = parts[parts.length - 2];
25
+ if (['co', 'com', 'net', 'org', 'io', 'ai'].includes(candidate)) {
26
+ return parts.length >= 3 ? parts[parts.length - 3] : parts[0];
27
+ }
28
+ return candidate;
29
+ }
30
+ return parts[0];
31
+ }
32
+ /**
33
+ * Specific rules for non-OpenAI formats. These are checked first,
34
+ * before the generic OpenAI-compatible catch-all.
35
+ */
36
+ const specificRules = [
37
+ {
38
+ provider: 'anthropic',
39
+ match: (host, path) => host === 'api.anthropic.com' && path.startsWith('/v1/messages'),
40
+ },
41
+ {
42
+ provider: 'gemini',
43
+ match: (host, path) => host === 'generativelanguage.googleapis.com' && path.includes(':generateContent'),
44
+ },
45
+ {
46
+ provider: 'bedrock',
47
+ match: (host, path) => host.includes('bedrock-runtime') && path.includes('/converse'),
48
+ },
49
+ {
50
+ provider: 'cortex',
51
+ match: (host, path) => host.endsWith('.snowflakecomputing.com') &&
52
+ path.includes('/api/v2/cortex/inference:complete'),
53
+ },
54
+ {
55
+ provider: 'azure_openai',
56
+ match: (host, path) => host.endsWith('.openai.azure.com') && path.includes('/chat/completions'),
57
+ },
58
+ {
59
+ provider: 'azure_ai',
60
+ match: (host, path) => host.endsWith('.models.ai.azure.com') && path.includes('/chat/completions'),
61
+ },
62
+ {
63
+ provider: 'cloudflare',
64
+ match: (host, path) => host === 'api.cloudflare.com' && path.includes('/ai/v1/chat/completions'),
65
+ },
66
+ {
67
+ provider: 'databricks',
68
+ match: (host, path) => host.endsWith('.cloud.databricks.com') && path.includes('/invocations'),
69
+ },
70
+ ];
71
+ export function detectProvider(host, path) {
72
+ if (!host)
73
+ return null;
74
+ // 1. Check specific non-OpenAI and special-case rules
75
+ for (const rule of specificRules) {
76
+ if (rule.match(host, path)) {
77
+ return rule.provider;
78
+ }
79
+ }
80
+ // 2. Check known OpenAI-compatible hosts
81
+ for (const [knownHost, provider] of Object.entries(KNOWN_OPENAI_COMPAT_HOSTS)) {
82
+ if (host === knownHost || host.endsWith('.' + knownHost)) {
83
+ if (path.includes('chat/completions') || path.includes('/completions')) {
84
+ return provider;
85
+ }
86
+ }
87
+ }
88
+ // 3. Ollama native API
89
+ if (host.startsWith('localhost') && path.startsWith('/api/chat')) {
90
+ return 'ollama';
91
+ }
92
+ // 4. Ollama OpenAI-compat endpoint
93
+ if (host.startsWith('localhost') && path.includes('/v1/chat/completions')) {
94
+ return 'ollama';
95
+ }
96
+ // 5. Generic catch-all: any request to a chat/completions path
97
+ if (path.includes('chat/completions')) {
98
+ return providerFromHost(host);
99
+ }
100
+ return null;
101
+ }
102
+ export class ProviderRegistry {
103
+ adapters = [];
104
+ register(adapter) {
105
+ this.adapters.push(adapter);
106
+ }
107
+ detect(host, path) {
108
+ for (const adapter of this.adapters) {
109
+ if (adapter.canHandle(host, path)) {
110
+ return adapter;
111
+ }
112
+ }
113
+ return null;
114
+ }
115
+ }
116
+ //# sourceMappingURL=index.js.map