veto-sdk 2.2.1 → 2.4.0
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 +933 -57
- package/dist/admin/client.d.ts +93 -0
- package/dist/admin/client.d.ts.map +1 -0
- package/dist/admin/client.js +365 -0
- package/dist/admin/client.js.map +1 -0
- package/dist/admin/types.d.ts +206 -0
- package/dist/admin/types.d.ts.map +1 -0
- package/dist/admin/types.js +2 -0
- package/dist/admin/types.js.map +1 -0
- package/dist/audit/chain.d.ts +13 -0
- package/dist/audit/chain.d.ts.map +1 -0
- package/dist/audit/chain.js +32 -0
- package/dist/audit/chain.js.map +1 -0
- package/dist/browser/types.d.ts +1 -1
- package/dist/browser/types.d.ts.map +1 -1
- package/dist/browser/veto.d.ts.map +1 -1
- package/dist/browser/veto.js +24 -2
- package/dist/browser/veto.js.map +1 -1
- package/dist/cli/compile.d.ts.map +1 -1
- package/dist/cli/compile.js +6 -5
- package/dist/cli/compile.js.map +1 -1
- package/dist/cli/repl-generate.js +1 -1
- package/dist/cli/repl-generate.js.map +1 -1
- package/dist/cli/runner.d.ts.map +1 -1
- package/dist/cli/runner.js +129 -8
- package/dist/cli/runner.js.map +1 -1
- package/dist/cli/templates.d.ts +1 -1
- package/dist/cli/templates.d.ts.map +1 -1
- package/dist/cli/templates.js +1 -1
- package/dist/core/history.d.ts +14 -0
- package/dist/core/history.d.ts.map +1 -1
- package/dist/core/history.js +73 -13
- package/dist/core/history.js.map +1 -1
- package/dist/core/tool-pack-heuristics.d.ts.map +1 -1
- package/dist/core/tool-pack-heuristics.js +33 -0
- package/dist/core/tool-pack-heuristics.js.map +1 -1
- package/dist/core/validator.d.ts +4 -0
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +119 -97
- package/dist/core/validator.js.map +1 -1
- package/dist/core/veto.d.ts +53 -2
- package/dist/core/veto.d.ts.map +1 -1
- package/dist/core/veto.js +137 -7
- package/dist/core/veto.js.map +1 -1
- package/dist/custom/types.d.ts +1 -1
- package/dist/custom/types.d.ts.map +1 -1
- package/dist/deterministic/types.d.ts +2 -0
- package/dist/deterministic/types.d.ts.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/langchain/middleware.d.ts +1 -1
- package/dist/integrations/langchain/middleware.js +1 -1
- package/dist/integrations/openclaw/hooks.d.ts +30 -0
- package/dist/integrations/openclaw/hooks.d.ts.map +1 -0
- package/dist/integrations/openclaw/hooks.js +130 -0
- package/dist/integrations/openclaw/hooks.js.map +1 -0
- package/dist/integrations/openclaw/index.d.ts +3 -0
- package/dist/integrations/openclaw/index.d.ts.map +1 -0
- package/dist/integrations/openclaw/index.js +2 -0
- package/dist/integrations/openclaw/index.js.map +1 -0
- package/dist/integrations/vercel-ai/middleware.d.ts +1 -1
- package/dist/integrations/vercel-ai/middleware.js +1 -1
- package/dist/observability/otel.d.ts +29 -0
- package/dist/observability/otel.d.ts.map +1 -0
- package/dist/observability/otel.js +43 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/proxy/anthropic-interceptor.d.ts +51 -0
- package/dist/proxy/anthropic-interceptor.d.ts.map +1 -0
- package/dist/proxy/anthropic-interceptor.js +132 -0
- package/dist/proxy/anthropic-interceptor.js.map +1 -0
- package/dist/proxy/interceptor.d.ts +55 -0
- package/dist/proxy/interceptor.d.ts.map +1 -0
- package/dist/proxy/interceptor.js +111 -0
- package/dist/proxy/interceptor.js.map +1 -0
- package/dist/proxy/server.d.ts +21 -0
- package/dist/proxy/server.d.ts.map +1 -0
- package/dist/proxy/server.js +545 -0
- package/dist/proxy/server.js.map +1 -0
- package/dist/proxy/types.d.ts +18 -0
- package/dist/proxy/types.d.ts.map +1 -0
- package/dist/proxy/types.js +7 -0
- package/dist/proxy/types.js.map +1 -0
- package/dist/rate-limiting/evaluator.d.ts +17 -0
- package/dist/rate-limiting/evaluator.d.ts.map +1 -0
- package/dist/rate-limiting/evaluator.js +48 -0
- package/dist/rate-limiting/evaluator.js.map +1 -0
- package/dist/rate-limiting/redis-store.d.ts +36 -0
- package/dist/rate-limiting/redis-store.d.ts.map +1 -0
- package/dist/rate-limiting/redis-store.js +68 -0
- package/dist/rate-limiting/redis-store.js.map +1 -0
- package/dist/rate-limiting/store.d.ts +8 -0
- package/dist/rate-limiting/store.d.ts.map +1 -0
- package/dist/rate-limiting/store.js +60 -0
- package/dist/rate-limiting/store.js.map +1 -0
- package/dist/rate-limiting/types.d.ts +9 -0
- package/dist/rate-limiting/types.d.ts.map +1 -0
- package/dist/rate-limiting/types.js +2 -0
- package/dist/rate-limiting/types.js.map +1 -0
- package/dist/rules/condition-evaluator.d.ts.map +1 -1
- package/dist/rules/condition-evaluator.js +29 -0
- package/dist/rules/condition-evaluator.js.map +1 -1
- package/dist/rules/loader.d.ts.map +1 -1
- package/dist/rules/loader.js +5 -0
- package/dist/rules/loader.js.map +1 -1
- package/dist/rules/local-evaluator.d.ts.map +1 -1
- package/dist/rules/local-evaluator.js +9 -1
- package/dist/rules/local-evaluator.js.map +1 -1
- package/dist/rules/policy-ir-schema.d.ts +145 -4
- package/dist/rules/policy-ir-schema.d.ts.map +1 -1
- package/dist/rules/policy-ir-schema.js +122 -3
- package/dist/rules/policy-ir-schema.js.map +1 -1
- package/dist/rules/policy-packs.d.ts.map +1 -1
- package/dist/rules/policy-packs.js +1 -0
- package/dist/rules/policy-packs.js.map +1 -1
- package/dist/rules/types.d.ts +29 -2
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js.map +1 -1
- package/dist/testing/runner.d.ts +21 -0
- package/dist/testing/runner.d.ts.map +1 -0
- package/dist/testing/runner.js +239 -0
- package/dist/testing/runner.js.map +1 -0
- package/dist/testing/types.d.ts +39 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +7 -0
- package/dist/testing/types.js.map +1 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js.map +1 -1
- package/package.json +24 -14
- package/packs/crypto-trading.yaml +320 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA4kB9C;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAuBxF"}
|
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* veto intercept — HTTP proxy for OpenAI and Anthropic streaming APIs.
|
|
3
|
+
*
|
|
4
|
+
* Intercepts tool calls in streaming responses (SSE format) and validates
|
|
5
|
+
* them against Veto policies before forwarding to the client.
|
|
6
|
+
*
|
|
7
|
+
* Architecture — full buffering:
|
|
8
|
+
* 1. Non-tool-call responses → passthrough chunks as they arrive
|
|
9
|
+
* 2. Tool-call responses → buffer all chunks until stream signals completion
|
|
10
|
+
* 3. Validate assembled tool call → allow (flush buffer) or block (synthetic error)
|
|
11
|
+
* 4. Buffer overflow (> maxBufferBytes) → flush + passthrough, skip validation
|
|
12
|
+
*
|
|
13
|
+
* @module proxy/server
|
|
14
|
+
*/
|
|
15
|
+
import http from 'node:http';
|
|
16
|
+
import https from 'node:https';
|
|
17
|
+
import { URL } from 'node:url';
|
|
18
|
+
import { finalizeToolCall, mergeToolCallDeltas, parseSSELine, synthBlockedEvent, } from './interceptor.js';
|
|
19
|
+
import { finalizeAnthropicToolUse, mergeAnthropicToolUseDelta, parseAnthropicSSELines, synthAnthropicBlockedEvent, } from './anthropic-interceptor.js';
|
|
20
|
+
import { Veto } from '../core/veto.js';
|
|
21
|
+
const MAX_REQUEST_BODY_BYTES = 10 * 1024 * 1024; // 10 MB
|
|
22
|
+
function resolveFormat(config) {
|
|
23
|
+
const fmt = config.format ?? 'auto';
|
|
24
|
+
if (fmt === 'openai' || fmt === 'anthropic')
|
|
25
|
+
return fmt;
|
|
26
|
+
return config.target.includes('anthropic') ? 'anthropic' : 'openai';
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Handle one proxied request.
|
|
30
|
+
*/
|
|
31
|
+
async function handleRequest(clientReq, clientRes, config, veto) {
|
|
32
|
+
const target = new URL(config.target);
|
|
33
|
+
const reqUrl = clientReq.url ?? '/';
|
|
34
|
+
const format = resolveFormat(config);
|
|
35
|
+
const isInterceptTarget = format === 'anthropic'
|
|
36
|
+
? reqUrl.includes('/v1/messages')
|
|
37
|
+
: reqUrl.includes('/chat/completions');
|
|
38
|
+
// Forward request headers, replacing host
|
|
39
|
+
const headers = {
|
|
40
|
+
...clientReq.headers,
|
|
41
|
+
host: target.host,
|
|
42
|
+
};
|
|
43
|
+
// Remove transfer-encoding since we may buffer the body
|
|
44
|
+
delete headers['content-length'];
|
|
45
|
+
// Collect request body with size limit
|
|
46
|
+
const bodyChunks = [];
|
|
47
|
+
let bodySize = 0;
|
|
48
|
+
let bodyLimitExceeded = false;
|
|
49
|
+
for await (const chunk of clientReq) {
|
|
50
|
+
const buf = chunk;
|
|
51
|
+
bodySize += buf.length;
|
|
52
|
+
if (bodySize > MAX_REQUEST_BODY_BYTES) {
|
|
53
|
+
bodyLimitExceeded = true;
|
|
54
|
+
clientReq.destroy();
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
bodyChunks.push(buf);
|
|
58
|
+
}
|
|
59
|
+
if (bodyLimitExceeded) {
|
|
60
|
+
clientRes.writeHead(413, { 'Content-Type': 'text/plain' });
|
|
61
|
+
clientRes.end('Request body too large');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const body = Buffer.concat(bodyChunks);
|
|
65
|
+
let parsedBody = null;
|
|
66
|
+
if (isInterceptTarget) {
|
|
67
|
+
try {
|
|
68
|
+
parsedBody = JSON.parse(body.toString('utf-8'));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Not valid JSON — treat as non-streaming passthrough
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const isStream = parsedBody?.['stream'] === true;
|
|
75
|
+
const upstreamOptions = {
|
|
76
|
+
hostname: target.hostname,
|
|
77
|
+
port: target.port || (target.protocol === 'https:' ? 443 : 80),
|
|
78
|
+
path: reqUrl,
|
|
79
|
+
method: clientReq.method,
|
|
80
|
+
headers: {
|
|
81
|
+
...headers,
|
|
82
|
+
'content-length': body.length.toString(),
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
const upstreamLib = target.protocol === 'https:' ? https : http;
|
|
86
|
+
await new Promise((resolve, reject) => {
|
|
87
|
+
const upstreamReq = upstreamLib.request(upstreamOptions, (upstreamRes) => {
|
|
88
|
+
if (!isInterceptTarget) {
|
|
89
|
+
clientRes.writeHead(upstreamRes.statusCode ?? 200, upstreamRes.headers);
|
|
90
|
+
upstreamRes.pipe(clientRes);
|
|
91
|
+
upstreamRes.on('end', resolve);
|
|
92
|
+
upstreamRes.on('error', reject);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (format === 'anthropic') {
|
|
96
|
+
if (isStream) {
|
|
97
|
+
clientRes.writeHead(upstreamRes.statusCode ?? 200, upstreamRes.headers);
|
|
98
|
+
interceptAnthropicSSEStream(upstreamRes, clientRes, config, veto).then(resolve).catch(reject);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
interceptAnthropicNonStreamResponse(upstreamRes, clientRes, veto).then(resolve).catch(reject);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
if (isStream) {
|
|
106
|
+
clientRes.writeHead(upstreamRes.statusCode ?? 200, upstreamRes.headers);
|
|
107
|
+
interceptSSEStream(upstreamRes, clientRes, config, veto).then(resolve).catch(reject);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
interceptNonStreamResponse(upstreamRes, clientRes, veto).then(resolve).catch(reject);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
upstreamReq.on('error', (err) => {
|
|
115
|
+
console.error('[veto intercept] Upstream connection error:', err.message);
|
|
116
|
+
if (!clientRes.headersSent) {
|
|
117
|
+
clientRes.writeHead(502, { 'Content-Type': 'text/plain' });
|
|
118
|
+
clientRes.end('Bad Gateway');
|
|
119
|
+
}
|
|
120
|
+
reject(err);
|
|
121
|
+
});
|
|
122
|
+
upstreamReq.write(body);
|
|
123
|
+
upstreamReq.end();
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Intercept a non-streaming chat completion response.
|
|
128
|
+
* Buffer the full response, extract tool calls, validate, then forward or block.
|
|
129
|
+
*/
|
|
130
|
+
async function interceptNonStreamResponse(upstream, clientRes, veto) {
|
|
131
|
+
const chunks = [];
|
|
132
|
+
for await (const chunk of upstream) {
|
|
133
|
+
chunks.push(chunk);
|
|
134
|
+
}
|
|
135
|
+
const responseBody = Buffer.concat(chunks).toString('utf-8');
|
|
136
|
+
let parsed;
|
|
137
|
+
try {
|
|
138
|
+
parsed = JSON.parse(responseBody);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Not JSON — forward as-is
|
|
142
|
+
clientRes.writeHead(upstream.statusCode ?? 200, upstream.headers);
|
|
143
|
+
clientRes.end(responseBody);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const choices = Array.isArray(parsed['choices']) ? parsed['choices'] : [];
|
|
147
|
+
let blocked = false;
|
|
148
|
+
let blockReason = 'Tool call blocked by veto policy';
|
|
149
|
+
for (const choice of choices) {
|
|
150
|
+
if (typeof choice !== 'object' || choice === null)
|
|
151
|
+
continue;
|
|
152
|
+
const c = choice;
|
|
153
|
+
const message = c['message'];
|
|
154
|
+
if (!message || !Array.isArray(message['tool_calls']))
|
|
155
|
+
continue;
|
|
156
|
+
for (const tc of message['tool_calls']) {
|
|
157
|
+
const fn = tc['function'];
|
|
158
|
+
if (!fn || typeof fn['name'] !== 'string')
|
|
159
|
+
continue;
|
|
160
|
+
let args = {};
|
|
161
|
+
if (typeof fn['arguments'] === 'string') {
|
|
162
|
+
try {
|
|
163
|
+
const p = JSON.parse(fn['arguments']);
|
|
164
|
+
if (p && typeof p === 'object' && !Array.isArray(p))
|
|
165
|
+
args = p;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
console.warn(`[veto intercept] Malformed tool arguments for '${fn['name']}', validating with empty args`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const result = await veto.guard(fn['name'], args);
|
|
173
|
+
if (result.decision !== 'allow') {
|
|
174
|
+
blocked = true;
|
|
175
|
+
blockReason = result.reason ?? `Tool call '${fn['name']}' blocked`;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
console.error('[veto intercept] Unexpected guard error:', err instanceof Error ? err.message : String(err));
|
|
181
|
+
blocked = true;
|
|
182
|
+
blockReason = 'Tool call validation failed';
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (blocked)
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
if (blocked) {
|
|
190
|
+
const blockedResponse = {
|
|
191
|
+
...parsed,
|
|
192
|
+
choices: [
|
|
193
|
+
{
|
|
194
|
+
index: 0,
|
|
195
|
+
message: { role: 'assistant', content: `[BLOCKED by veto] ${blockReason}` },
|
|
196
|
+
finish_reason: 'stop',
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
const body = JSON.stringify(blockedResponse);
|
|
201
|
+
const headers = { ...upstream.headers };
|
|
202
|
+
headers['content-length'] = Buffer.byteLength(body).toString();
|
|
203
|
+
clientRes.writeHead(200, headers);
|
|
204
|
+
clientRes.end(body);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
clientRes.writeHead(upstream.statusCode ?? 200, upstream.headers);
|
|
208
|
+
clientRes.end(responseBody);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Read the upstream SSE stream, buffer tool-call chunks, validate, then
|
|
213
|
+
* either flush the buffer or send a synthetic error.
|
|
214
|
+
*/
|
|
215
|
+
async function interceptSSEStream(upstream, clientRes, config, veto) {
|
|
216
|
+
const maxBufferBytes = config.maxBufferBytes;
|
|
217
|
+
// Decoder for SSE text
|
|
218
|
+
let partial = '';
|
|
219
|
+
const pendingToolCalls = new Map();
|
|
220
|
+
let bufferedLines = [];
|
|
221
|
+
let bufferedBytes = 0;
|
|
222
|
+
let mode = 'passthrough';
|
|
223
|
+
let bufferOverflowed = false;
|
|
224
|
+
const flushBuffer = () => {
|
|
225
|
+
for (const line of bufferedLines) {
|
|
226
|
+
clientRes.write(line + '\n');
|
|
227
|
+
}
|
|
228
|
+
bufferedLines = [];
|
|
229
|
+
bufferedBytes = 0;
|
|
230
|
+
};
|
|
231
|
+
for await (const rawChunk of upstream) {
|
|
232
|
+
const chunk = rawChunk.toString('utf-8');
|
|
233
|
+
partial += chunk;
|
|
234
|
+
// SSE lines are separated by \n (or \r\n)
|
|
235
|
+
const lines = partial.split('\n');
|
|
236
|
+
partial = lines.pop() ?? '';
|
|
237
|
+
for (const rawLine of lines) {
|
|
238
|
+
const line = rawLine.replace(/\r$/, '');
|
|
239
|
+
const parsed = parseSSELine(line);
|
|
240
|
+
if (parsed.done) {
|
|
241
|
+
if (mode === 'buffer') {
|
|
242
|
+
// Stream ended during buffering without finishing tool calls — flush
|
|
243
|
+
flushBuffer();
|
|
244
|
+
}
|
|
245
|
+
clientRes.write('data: [DONE]\n\n');
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (mode === 'overflow') {
|
|
249
|
+
// Buffer overflowed — just passthrough
|
|
250
|
+
clientRes.write(line + '\n');
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (mode === 'passthrough') {
|
|
254
|
+
if (parsed.hasToolCalls) {
|
|
255
|
+
// Switch to buffer mode
|
|
256
|
+
mode = 'buffer';
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
clientRes.write(line + '\n');
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Buffer mode: accumulate
|
|
264
|
+
if (parsed.data) {
|
|
265
|
+
mergeToolCallDeltas(pendingToolCalls, parsed.data);
|
|
266
|
+
}
|
|
267
|
+
const lineBytes = Buffer.byteLength(line, 'utf-8');
|
|
268
|
+
bufferedBytes += lineBytes;
|
|
269
|
+
bufferedLines.push(line);
|
|
270
|
+
if (bufferedBytes > maxBufferBytes) {
|
|
271
|
+
// Overflow: flush everything and passthrough rest
|
|
272
|
+
bufferOverflowed = true;
|
|
273
|
+
mode = 'overflow';
|
|
274
|
+
flushBuffer();
|
|
275
|
+
console.warn('[veto intercept] Buffer limit exceeded — flushing without validation');
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (parsed.finishReasonToolCalls) {
|
|
279
|
+
// Validate assembled tool calls
|
|
280
|
+
let blocked = false;
|
|
281
|
+
let blockReason = 'Tool call blocked by veto policy';
|
|
282
|
+
for (const [, tc] of pendingToolCalls) {
|
|
283
|
+
const finalized = finalizeToolCall(tc);
|
|
284
|
+
try {
|
|
285
|
+
const result = await veto.guard(finalized.name, finalized.arguments);
|
|
286
|
+
if (result.decision !== 'allow') {
|
|
287
|
+
blocked = true;
|
|
288
|
+
blockReason = result.reason ?? `Tool call '${finalized.name}' blocked`;
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
console.error('[veto intercept] Unexpected guard error:', err instanceof Error ? err.message : String(err));
|
|
294
|
+
blocked = true;
|
|
295
|
+
blockReason = 'Tool call validation failed';
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (blocked) {
|
|
300
|
+
// Clear buffered chunks — send synthetic block event
|
|
301
|
+
bufferedLines = [];
|
|
302
|
+
clientRes.write(synthBlockedEvent(blockReason));
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
flushBuffer();
|
|
306
|
+
}
|
|
307
|
+
mode = 'passthrough';
|
|
308
|
+
pendingToolCalls.clear();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// Flush any remaining partial line (shouldn't happen with well-formed SSE)
|
|
313
|
+
if (partial.trim()) {
|
|
314
|
+
clientRes.write(partial + '\n');
|
|
315
|
+
}
|
|
316
|
+
if (mode === 'buffer' && !bufferOverflowed) {
|
|
317
|
+
// Stream ended mid-buffer (connection closed?) — flush what we have
|
|
318
|
+
flushBuffer();
|
|
319
|
+
}
|
|
320
|
+
clientRes.end();
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Intercept a non-streaming Anthropic Messages response.
|
|
324
|
+
* Tool calls are content blocks with type "tool_use", where input is an object (not stringified).
|
|
325
|
+
*/
|
|
326
|
+
async function interceptAnthropicNonStreamResponse(upstream, clientRes, veto) {
|
|
327
|
+
const chunks = [];
|
|
328
|
+
for await (const chunk of upstream) {
|
|
329
|
+
chunks.push(chunk);
|
|
330
|
+
}
|
|
331
|
+
const responseBody = Buffer.concat(chunks).toString('utf-8');
|
|
332
|
+
let parsed;
|
|
333
|
+
try {
|
|
334
|
+
parsed = JSON.parse(responseBody);
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
clientRes.writeHead(upstream.statusCode ?? 200, upstream.headers);
|
|
338
|
+
clientRes.end(responseBody);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const content = Array.isArray(parsed['content']) ? parsed['content'] : [];
|
|
342
|
+
let blocked = false;
|
|
343
|
+
let blockReason = 'Tool call blocked by veto policy';
|
|
344
|
+
for (const block of content) {
|
|
345
|
+
if (typeof block !== 'object' || block === null)
|
|
346
|
+
continue;
|
|
347
|
+
const b = block;
|
|
348
|
+
if (b['type'] !== 'tool_use')
|
|
349
|
+
continue;
|
|
350
|
+
const name = typeof b['name'] === 'string' ? b['name'] : '';
|
|
351
|
+
let args = {};
|
|
352
|
+
if (b['input'] && typeof b['input'] === 'object' && !Array.isArray(b['input'])) {
|
|
353
|
+
args = b['input'];
|
|
354
|
+
}
|
|
355
|
+
try {
|
|
356
|
+
const result = await veto.guard(name, args);
|
|
357
|
+
if (result.decision !== 'allow') {
|
|
358
|
+
blocked = true;
|
|
359
|
+
blockReason = result.reason ?? `Tool call '${name}' blocked`;
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
console.error('[veto intercept] Unexpected guard error:', err instanceof Error ? err.message : String(err));
|
|
365
|
+
blocked = true;
|
|
366
|
+
blockReason = 'Tool call validation failed';
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (blocked) {
|
|
371
|
+
const blockedResponse = {
|
|
372
|
+
...parsed,
|
|
373
|
+
content: [{ type: 'text', text: `[BLOCKED by veto] ${blockReason}` }],
|
|
374
|
+
stop_reason: 'end_turn',
|
|
375
|
+
};
|
|
376
|
+
const body = JSON.stringify(blockedResponse);
|
|
377
|
+
const headers = { ...upstream.headers };
|
|
378
|
+
headers['content-length'] = Buffer.byteLength(body).toString();
|
|
379
|
+
clientRes.writeHead(200, headers);
|
|
380
|
+
clientRes.end(body);
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
clientRes.writeHead(upstream.statusCode ?? 200, upstream.headers);
|
|
384
|
+
clientRes.end(responseBody);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Intercept an Anthropic SSE stream.
|
|
389
|
+
*
|
|
390
|
+
* Anthropic events come as `event: <type>\ndata: <json>\n\n` pairs.
|
|
391
|
+
* Tool calls span content_block_start → content_block_delta(s) → content_block_stop.
|
|
392
|
+
* We buffer from the first tool_use block start until message_stop, then validate.
|
|
393
|
+
*/
|
|
394
|
+
async function interceptAnthropicSSEStream(upstream, clientRes, config, veto) {
|
|
395
|
+
const maxBufferBytes = config.maxBufferBytes;
|
|
396
|
+
let partial = '';
|
|
397
|
+
const pendingToolUses = new Map();
|
|
398
|
+
let bufferedChunks = [];
|
|
399
|
+
let bufferedBytes = 0;
|
|
400
|
+
let mode = 'passthrough';
|
|
401
|
+
let bufferOverflowed = false;
|
|
402
|
+
// Track which content block indexes are tool_use blocks
|
|
403
|
+
const toolUseIndexes = new Set();
|
|
404
|
+
// Accumulate event: + data: line pairs
|
|
405
|
+
let eventLineBuf = [];
|
|
406
|
+
const flushBuffer = () => {
|
|
407
|
+
for (const chunk of bufferedChunks) {
|
|
408
|
+
clientRes.write(chunk);
|
|
409
|
+
}
|
|
410
|
+
bufferedChunks = [];
|
|
411
|
+
bufferedBytes = 0;
|
|
412
|
+
};
|
|
413
|
+
for await (const rawChunk of upstream) {
|
|
414
|
+
const chunk = rawChunk.toString('utf-8');
|
|
415
|
+
partial += chunk;
|
|
416
|
+
const lines = partial.split('\n');
|
|
417
|
+
partial = lines.pop() ?? '';
|
|
418
|
+
for (const rawLine of lines) {
|
|
419
|
+
const line = rawLine.replace(/\r$/, '');
|
|
420
|
+
// Accumulate event: + data: pairs; empty line signals end of an SSE event
|
|
421
|
+
if (line !== '') {
|
|
422
|
+
eventLineBuf.push(line);
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
// Empty line = end of SSE event
|
|
426
|
+
if (eventLineBuf.length === 0) {
|
|
427
|
+
if (mode === 'passthrough')
|
|
428
|
+
clientRes.write('\n');
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
const sseBlock = eventLineBuf.join('\n') + '\n\n';
|
|
432
|
+
const parsed = parseAnthropicSSELines(eventLineBuf);
|
|
433
|
+
eventLineBuf = [];
|
|
434
|
+
// Track tool_use block indexes
|
|
435
|
+
if (parsed.eventType === 'content_block_start' && parsed.data) {
|
|
436
|
+
const block = parsed.data['content_block'];
|
|
437
|
+
if (block && block['type'] === 'tool_use') {
|
|
438
|
+
const idx = typeof parsed.data['index'] === 'number' ? parsed.data['index'] : 0;
|
|
439
|
+
toolUseIndexes.add(idx);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
// Determine if this event relates to a tool_use block
|
|
443
|
+
const isToolUseEvent = parsed.hasToolUse
|
|
444
|
+
|| (parsed.toolUseStop && parsed.data && toolUseIndexes.has(typeof parsed.data['index'] === 'number' ? parsed.data['index'] : -1));
|
|
445
|
+
if (mode === 'overflow') {
|
|
446
|
+
clientRes.write(sseBlock);
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
if (mode === 'passthrough') {
|
|
450
|
+
if (isToolUseEvent) {
|
|
451
|
+
mode = 'buffer';
|
|
452
|
+
}
|
|
453
|
+
else if (parsed.messageStop) {
|
|
454
|
+
clientRes.write(sseBlock);
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
clientRes.write(sseBlock);
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
// Buffer mode
|
|
463
|
+
if (parsed.data && parsed.eventType) {
|
|
464
|
+
mergeAnthropicToolUseDelta(pendingToolUses, parsed.data, parsed.eventType);
|
|
465
|
+
}
|
|
466
|
+
const blockBytes = Buffer.byteLength(sseBlock, 'utf-8');
|
|
467
|
+
bufferedBytes += blockBytes;
|
|
468
|
+
bufferedChunks.push(sseBlock);
|
|
469
|
+
if (bufferedBytes > maxBufferBytes) {
|
|
470
|
+
bufferOverflowed = true;
|
|
471
|
+
mode = 'overflow';
|
|
472
|
+
flushBuffer();
|
|
473
|
+
console.warn('[veto intercept] Buffer limit exceeded — flushing without validation');
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
if (parsed.messageStop) {
|
|
477
|
+
// Validate all assembled tool uses
|
|
478
|
+
let blocked = false;
|
|
479
|
+
let blockReason = 'Tool call blocked by veto policy';
|
|
480
|
+
for (const [, tc] of pendingToolUses) {
|
|
481
|
+
const finalized = finalizeAnthropicToolUse(tc);
|
|
482
|
+
try {
|
|
483
|
+
const result = await veto.guard(finalized.name, finalized.arguments);
|
|
484
|
+
if (result.decision !== 'allow') {
|
|
485
|
+
blocked = true;
|
|
486
|
+
blockReason = result.reason ?? `Tool call '${finalized.name}' blocked`;
|
|
487
|
+
break;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch (err) {
|
|
491
|
+
console.error('[veto intercept] Unexpected guard error:', err instanceof Error ? err.message : String(err));
|
|
492
|
+
blocked = true;
|
|
493
|
+
blockReason = 'Tool call validation failed';
|
|
494
|
+
break;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (blocked) {
|
|
498
|
+
bufferedChunks = [];
|
|
499
|
+
clientRes.write(synthAnthropicBlockedEvent(blockReason));
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
flushBuffer();
|
|
503
|
+
}
|
|
504
|
+
mode = 'passthrough';
|
|
505
|
+
pendingToolUses.clear();
|
|
506
|
+
toolUseIndexes.clear();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
// Flush remaining partial event lines
|
|
511
|
+
if (partial.trim()) {
|
|
512
|
+
clientRes.write(partial + '\n');
|
|
513
|
+
}
|
|
514
|
+
if (mode === 'buffer' && !bufferOverflowed) {
|
|
515
|
+
flushBuffer();
|
|
516
|
+
}
|
|
517
|
+
clientRes.end();
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Start the veto intercept proxy server.
|
|
521
|
+
* Returns a cleanup function that stops the server and destroys the Veto instance.
|
|
522
|
+
*/
|
|
523
|
+
export async function startProxyServer(config) {
|
|
524
|
+
const veto = await Veto.init({ configDir: config.configDir });
|
|
525
|
+
return new Promise((resolve, reject) => {
|
|
526
|
+
const server = http.createServer((req, res) => {
|
|
527
|
+
handleRequest(req, res, config, veto).catch((err) => {
|
|
528
|
+
if (!res.headersSent) {
|
|
529
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
530
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
531
|
+
console.error('[veto intercept] Internal proxy error:', detail);
|
|
532
|
+
res.end('Internal proxy error');
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
server.on('error', reject);
|
|
537
|
+
server.listen(config.port, '127.0.0.1', () => {
|
|
538
|
+
resolve(async () => {
|
|
539
|
+
await new Promise((r, e) => server.close((err) => (err ? e(err) : r())));
|
|
540
|
+
veto.dispose();
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for veto intercept proxy.
|
|
3
|
+
*
|
|
4
|
+
* @module proxy/types
|
|
5
|
+
*/
|
|
6
|
+
export interface ProxyConfig {
|
|
7
|
+
/** Port for the local proxy to listen on. Default: 8080 */
|
|
8
|
+
port: number;
|
|
9
|
+
/** Upstream target URL. Default: https://api.openai.com */
|
|
10
|
+
target: string;
|
|
11
|
+
/** Max bytes to buffer before giving up and flushing. Default: 1MB */
|
|
12
|
+
maxBufferBytes: number;
|
|
13
|
+
/** Path to veto config directory. Default: ./veto */
|
|
14
|
+
configDir: string;
|
|
15
|
+
/** SSE format to intercept. 'auto' detects from target URL. Default: 'auto' */
|
|
16
|
+
format?: 'openai' | 'anthropic' | 'auto';
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/proxy/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,cAAc,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAC;CAC1C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/proxy/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RateLimitEntry } from './types.js';
|
|
2
|
+
import type { ValidationContext } from '../types/config.js';
|
|
3
|
+
import type { Logger } from '../utils/logger.js';
|
|
4
|
+
export interface RateLimitStore {
|
|
5
|
+
checkAndRecord(key: string, maxCalls: number, windowMs: number): boolean | Promise<boolean>;
|
|
6
|
+
clear(): void | Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare function buildScopeKey(entry: RateLimitEntry, ctx: Pick<ValidationContext, 'agentId' | 'userId' | 'sessionId'>, toolName: string, logger: Logger, ruleId?: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Evaluate rate limits for a tool call.
|
|
11
|
+
* Returns null if all limits pass, or a denial reason string if any limit is exceeded.
|
|
12
|
+
*
|
|
13
|
+
* When no store is provided, falls back to the built-in in-memory sliding window store.
|
|
14
|
+
* Accepts async stores (e.g. Redis) — callers must await the result.
|
|
15
|
+
*/
|
|
16
|
+
export declare function evaluateRateLimits(rateLimits: RateLimitEntry[], ctx: Pick<ValidationContext, 'agentId' | 'userId' | 'sessionId'>, toolName: string, logger: Logger, ruleId?: string, store?: RateLimitStore): Promise<string | null>;
|
|
17
|
+
//# sourceMappingURL=evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/rate-limiting/evaluator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5F,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC,EAChE,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAgBR;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,cAAc,EAAE,EAC5B,GAAG,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC,EAChE,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,cAAc,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBxB"}
|