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,130 @@
|
|
|
1
|
+
import { ApprovalTimeoutError } from '../../cloud/client.js';
|
|
2
|
+
import { generateToolCallId } from '../../utils/id.js';
|
|
3
|
+
function resolveSessionId(context, options) {
|
|
4
|
+
return options?.sessionId ?? context.sessionId;
|
|
5
|
+
}
|
|
6
|
+
function resolveAgentId(context, options) {
|
|
7
|
+
return options?.agentId ?? context.agentId;
|
|
8
|
+
}
|
|
9
|
+
function resolveApprovalMode(options) {
|
|
10
|
+
return options?.approvalMode ?? 'openclaw-native';
|
|
11
|
+
}
|
|
12
|
+
function resolveToolCallId(context) {
|
|
13
|
+
return context.toolCallId ?? generateToolCallId();
|
|
14
|
+
}
|
|
15
|
+
export function createVetoBeforeToolCallHook(veto, options) {
|
|
16
|
+
const approvalMode = resolveApprovalMode(options);
|
|
17
|
+
const onAllow = options?.onAllow;
|
|
18
|
+
const onDeny = options?.onDeny;
|
|
19
|
+
const onApprovalRequired = options?.onApprovalRequired;
|
|
20
|
+
const approvalWaiter = veto;
|
|
21
|
+
return async (context) => {
|
|
22
|
+
const toolName = context.toolName;
|
|
23
|
+
const args = context.toolArgs ?? {};
|
|
24
|
+
resolveToolCallId(context);
|
|
25
|
+
const result = await veto.guard(toolName, args, {
|
|
26
|
+
sessionId: resolveSessionId(context, options),
|
|
27
|
+
agentId: resolveAgentId(context, options),
|
|
28
|
+
});
|
|
29
|
+
if (result.shadow === true) {
|
|
30
|
+
if (onAllow)
|
|
31
|
+
await onAllow(toolName, args);
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
if (result.decision === 'allow') {
|
|
35
|
+
if (onAllow)
|
|
36
|
+
await onAllow(toolName, args);
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
if (result.decision === 'deny') {
|
|
40
|
+
const reason = result.reason ?? 'Policy violation';
|
|
41
|
+
if (onDeny)
|
|
42
|
+
await onDeny(toolName, args, reason);
|
|
43
|
+
return { block: true, message: reason };
|
|
44
|
+
}
|
|
45
|
+
if (onApprovalRequired) {
|
|
46
|
+
await onApprovalRequired(toolName, args, result.approvalId);
|
|
47
|
+
}
|
|
48
|
+
if (approvalMode === 'openclaw-native') {
|
|
49
|
+
return {
|
|
50
|
+
requireApproval: true,
|
|
51
|
+
message: result.reason,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (!result.approvalId) {
|
|
55
|
+
const reason = result.reason ?? 'Approval required';
|
|
56
|
+
if (onDeny)
|
|
57
|
+
await onDeny(toolName, args, reason);
|
|
58
|
+
return { block: true, message: reason };
|
|
59
|
+
}
|
|
60
|
+
if (!approvalWaiter.waitForApproval) {
|
|
61
|
+
throw new Error('veto.waitForApproval() is required for approvalMode="veto-cloud"');
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const approval = await approvalWaiter.waitForApproval(result.approvalId);
|
|
65
|
+
if (approval.status === 'approved') {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
if (approval.status === 'expired') {
|
|
69
|
+
const reason = 'Approval expired';
|
|
70
|
+
if (onDeny)
|
|
71
|
+
await onDeny(toolName, args, reason);
|
|
72
|
+
return { block: true, message: reason };
|
|
73
|
+
}
|
|
74
|
+
const reason = result.reason ?? 'Approval denied';
|
|
75
|
+
if (onDeny)
|
|
76
|
+
await onDeny(toolName, args, reason);
|
|
77
|
+
return { block: true, message: reason };
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (error instanceof ApprovalTimeoutError) {
|
|
81
|
+
const reason = 'Approval expired';
|
|
82
|
+
if (onDeny)
|
|
83
|
+
await onDeny(toolName, args, reason);
|
|
84
|
+
return { block: true, message: reason };
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export function createVetoAfterToolCallHook(veto, options) {
|
|
91
|
+
const vetoWithLogger = veto;
|
|
92
|
+
return async (context) => {
|
|
93
|
+
const toolCallId = resolveToolCallId(context);
|
|
94
|
+
const toolName = context.toolName;
|
|
95
|
+
const args = context.toolArgs ?? {};
|
|
96
|
+
const metadata = {
|
|
97
|
+
toolCallId,
|
|
98
|
+
source: 'openclaw-after-tool-call',
|
|
99
|
+
};
|
|
100
|
+
const sessionId = resolveSessionId(context, options);
|
|
101
|
+
const agentId = resolveAgentId(context, options);
|
|
102
|
+
if (sessionId)
|
|
103
|
+
metadata.sessionId = sessionId;
|
|
104
|
+
if (agentId)
|
|
105
|
+
metadata.agentId = agentId;
|
|
106
|
+
if (context.error !== undefined) {
|
|
107
|
+
metadata.executionError = context.error instanceof Error
|
|
108
|
+
? { name: context.error.name, message: context.error.message }
|
|
109
|
+
: String(context.error);
|
|
110
|
+
}
|
|
111
|
+
if (vetoWithLogger.logToolExecution) {
|
|
112
|
+
vetoWithLogger.logToolExecution(toolName, args, context.result, {
|
|
113
|
+
toolCallId,
|
|
114
|
+
sessionId,
|
|
115
|
+
agentId,
|
|
116
|
+
error: context.error,
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
vetoWithLogger.historyTracker?.record(toolName, args, {
|
|
121
|
+
decision: 'allow',
|
|
122
|
+
reason: context.error === undefined ? 'Tool execution completed' : 'Tool execution failed',
|
|
123
|
+
metadata: {
|
|
124
|
+
...metadata,
|
|
125
|
+
executionResult: context.result,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/integrations/openclaw/hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { createVetoBeforeToolCallHook, createVetoAfterToolCallHook } from './hooks.js';
|
|
2
|
+
export type { OpenClawBeforeToolCallHook, OpenClawAfterToolCallHook, OpenClawToolCallContext, OpenClawBeforeToolCallResult, CreateVetoOpenClawHookOptions, VetoApprovalMode, } from './hooks.js';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/openclaw/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AACvF,YAAY,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/integrations/openclaw/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional OpenTelemetry integration.
|
|
3
|
+
*
|
|
4
|
+
* Uses dynamic import so @opentelemetry/api is a zero-cost optional peer dep.
|
|
5
|
+
* If not installed, all functions return no-ops.
|
|
6
|
+
*/
|
|
7
|
+
export interface VetoTracer {
|
|
8
|
+
startSpan(name: string): VetoSpan;
|
|
9
|
+
}
|
|
10
|
+
export interface VetoSpan {
|
|
11
|
+
setAttribute(key: string, value: string | number | boolean): void;
|
|
12
|
+
setStatus(status: {
|
|
13
|
+
code: number;
|
|
14
|
+
message?: string;
|
|
15
|
+
}): void;
|
|
16
|
+
end(): void;
|
|
17
|
+
}
|
|
18
|
+
export declare const SpanStatusCode: {
|
|
19
|
+
readonly OK: 1;
|
|
20
|
+
readonly ERROR: 2;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Attempt to load @opentelemetry/api. Returns a VetoTracer wrapping the real
|
|
24
|
+
* tracer, or a no-op tracer if the package is not installed.
|
|
25
|
+
*
|
|
26
|
+
* Call once during Veto.init() and store the result.
|
|
27
|
+
*/
|
|
28
|
+
export declare function tryLoadOtel(serviceName?: string): Promise<VetoTracer>;
|
|
29
|
+
//# sourceMappingURL=otel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel.d.ts","sourceRoot":"","sources":["../../src/observability/otel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CACnC;AAED,MAAM,WAAW,QAAQ;IACvB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAClE,SAAS,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5D,GAAG,IAAI,IAAI,CAAC;CACb;AAGD,eAAO,MAAM,cAAc;;;CAA+B,CAAC;AAY3D;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,WAAW,SAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAkB/E"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional OpenTelemetry integration.
|
|
3
|
+
*
|
|
4
|
+
* Uses dynamic import so @opentelemetry/api is a zero-cost optional peer dep.
|
|
5
|
+
* If not installed, all functions return no-ops.
|
|
6
|
+
*/
|
|
7
|
+
// Canonical OTEL status codes (avoid importing from @opentelemetry/api directly)
|
|
8
|
+
export const SpanStatusCode = { OK: 1, ERROR: 2 };
|
|
9
|
+
const noopSpan = {
|
|
10
|
+
setAttribute() { },
|
|
11
|
+
setStatus() { },
|
|
12
|
+
end() { },
|
|
13
|
+
};
|
|
14
|
+
const noopTracer = {
|
|
15
|
+
startSpan() { return noopSpan; },
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Attempt to load @opentelemetry/api. Returns a VetoTracer wrapping the real
|
|
19
|
+
* tracer, or a no-op tracer if the package is not installed.
|
|
20
|
+
*
|
|
21
|
+
* Call once during Veto.init() and store the result.
|
|
22
|
+
*/
|
|
23
|
+
export async function tryLoadOtel(serviceName = 'veto-sdk') {
|
|
24
|
+
try {
|
|
25
|
+
// Dynamic import — works in Node.js 20+ ESM. Throws ERR_MODULE_NOT_FOUND if not installed.
|
|
26
|
+
const api = await import('@opentelemetry/api');
|
|
27
|
+
const tracer = api.trace.getTracer(serviceName);
|
|
28
|
+
return {
|
|
29
|
+
startSpan(name) {
|
|
30
|
+
const span = tracer.startSpan(name);
|
|
31
|
+
return {
|
|
32
|
+
setAttribute(key, value) { span.setAttribute(key, value); },
|
|
33
|
+
setStatus(status) { span.setStatus(status); },
|
|
34
|
+
end() { span.end(); },
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return noopTracer;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=otel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel.js","sourceRoot":"","sources":["../../src/observability/otel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,iFAAiF;AACjF,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAW,CAAC;AAE3D,MAAM,QAAQ,GAAa;IACzB,YAAY,KAAI,CAAC;IACjB,SAAS,KAAI,CAAC;IACd,GAAG,KAAI,CAAC;CACT,CAAC;AAEF,MAAM,UAAU,GAAe;IAC7B,SAAS,KAAK,OAAO,QAAQ,CAAC,CAAC,CAAC;CACjC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAW,GAAG,UAAU;IACxD,IAAI,CAAC;QACH,2FAA2F;QAC3F,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAChD,OAAO;YACL,SAAS,CAAC,IAAY;gBACpB,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBACpC,OAAO;oBACL,YAAY,CAAC,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;oBAC3D,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBAC7C,GAAG,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;iBACtB,CAAC;YACJ,CAAC;SACF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,UAAU,CAAC;IACpB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE stream interceptor for Anthropic Messages API.
|
|
3
|
+
*
|
|
4
|
+
* Anthropic SSE differs from OpenAI: events carry an `event:` type line
|
|
5
|
+
* followed by a `data:` JSON line. Tool calls arrive as content blocks
|
|
6
|
+
* (content_block_start → content_block_delta → content_block_stop) and
|
|
7
|
+
* the input JSON is streamed as partial fragments across deltas.
|
|
8
|
+
*
|
|
9
|
+
* @module proxy/anthropic-interceptor
|
|
10
|
+
*/
|
|
11
|
+
export interface AnthropicPendingToolUse {
|
|
12
|
+
index: number;
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
inputRaw: string;
|
|
16
|
+
}
|
|
17
|
+
export interface AnthropicSSELineResult {
|
|
18
|
+
line: string;
|
|
19
|
+
eventType?: string;
|
|
20
|
+
data?: Record<string, unknown> | null;
|
|
21
|
+
hasToolUse?: boolean;
|
|
22
|
+
toolUseStop?: boolean;
|
|
23
|
+
messageStop?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parse buffered SSE lines (an event: + data: pair) into a structured result.
|
|
27
|
+
* Anthropic sends `event: <type>\ndata: <json>` pairs.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseAnthropicSSELines(lines: string[]): AnthropicSSELineResult;
|
|
30
|
+
/**
|
|
31
|
+
* Merge tool use data from Anthropic SSE events into the pending map.
|
|
32
|
+
*
|
|
33
|
+
* - content_block_start with type=tool_use: create a new pending entry
|
|
34
|
+
* - content_block_delta with type=input_json_delta: append partial_json
|
|
35
|
+
* - content_block_stop: no-op (signals block completion)
|
|
36
|
+
*/
|
|
37
|
+
export declare function mergeAnthropicToolUseDelta(pending: Map<number, AnthropicPendingToolUse>, data: Record<string, unknown>, eventType: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* Parse the accumulated input JSON into an arguments object.
|
|
40
|
+
*/
|
|
41
|
+
export declare function finalizeAnthropicToolUse(tc: AnthropicPendingToolUse): {
|
|
42
|
+
name: string;
|
|
43
|
+
id: string;
|
|
44
|
+
arguments: Record<string, unknown>;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Synthesize Anthropic SSE events that replace a tool_use block with a
|
|
48
|
+
* text block containing the block reason, followed by message_stop.
|
|
49
|
+
*/
|
|
50
|
+
export declare function synthAnthropicBlockedEvent(reason: string): string;
|
|
51
|
+
//# sourceMappingURL=anthropic-interceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic-interceptor.d.ts","sourceRoot":"","sources":["../../src/proxy/anthropic-interceptor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,sBAAsB,CA2C9E;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAC7C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,GAChB,IAAI,CAqBN;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,uBAAuB,GAAG;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,CAWA;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAwBjE"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE stream interceptor for Anthropic Messages API.
|
|
3
|
+
*
|
|
4
|
+
* Anthropic SSE differs from OpenAI: events carry an `event:` type line
|
|
5
|
+
* followed by a `data:` JSON line. Tool calls arrive as content blocks
|
|
6
|
+
* (content_block_start → content_block_delta → content_block_stop) and
|
|
7
|
+
* the input JSON is streamed as partial fragments across deltas.
|
|
8
|
+
*
|
|
9
|
+
* @module proxy/anthropic-interceptor
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Parse buffered SSE lines (an event: + data: pair) into a structured result.
|
|
13
|
+
* Anthropic sends `event: <type>\ndata: <json>` pairs.
|
|
14
|
+
*/
|
|
15
|
+
export function parseAnthropicSSELines(lines) {
|
|
16
|
+
let eventType;
|
|
17
|
+
let dataStr;
|
|
18
|
+
const raw = lines.join('\n');
|
|
19
|
+
for (const line of lines) {
|
|
20
|
+
if (line.startsWith('event: ')) {
|
|
21
|
+
eventType = line.slice(7).trim();
|
|
22
|
+
}
|
|
23
|
+
else if (line.startsWith('data: ')) {
|
|
24
|
+
dataStr = line.slice(6);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!dataStr) {
|
|
28
|
+
return { line: raw, eventType };
|
|
29
|
+
}
|
|
30
|
+
let data = null;
|
|
31
|
+
try {
|
|
32
|
+
data = JSON.parse(dataStr);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return { line: raw, eventType };
|
|
36
|
+
}
|
|
37
|
+
let hasToolUse = false;
|
|
38
|
+
let toolUseStop = false;
|
|
39
|
+
const messageStop = eventType === 'message_stop';
|
|
40
|
+
if (eventType === 'content_block_start') {
|
|
41
|
+
const block = data['content_block'];
|
|
42
|
+
if (block && block['type'] === 'tool_use') {
|
|
43
|
+
hasToolUse = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (eventType === 'content_block_delta') {
|
|
47
|
+
const delta = data['delta'];
|
|
48
|
+
if (delta && delta['type'] === 'input_json_delta') {
|
|
49
|
+
hasToolUse = true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (eventType === 'content_block_stop') {
|
|
53
|
+
toolUseStop = true;
|
|
54
|
+
}
|
|
55
|
+
return { line: raw, eventType, data, hasToolUse, toolUseStop, messageStop };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Merge tool use data from Anthropic SSE events into the pending map.
|
|
59
|
+
*
|
|
60
|
+
* - content_block_start with type=tool_use: create a new pending entry
|
|
61
|
+
* - content_block_delta with type=input_json_delta: append partial_json
|
|
62
|
+
* - content_block_stop: no-op (signals block completion)
|
|
63
|
+
*/
|
|
64
|
+
export function mergeAnthropicToolUseDelta(pending, data, eventType) {
|
|
65
|
+
const index = typeof data['index'] === 'number' ? data['index'] : 0;
|
|
66
|
+
if (eventType === 'content_block_start') {
|
|
67
|
+
const block = data['content_block'];
|
|
68
|
+
if (!block || block['type'] !== 'tool_use')
|
|
69
|
+
return;
|
|
70
|
+
pending.set(index, {
|
|
71
|
+
index,
|
|
72
|
+
id: typeof block['id'] === 'string' ? block['id'] : '',
|
|
73
|
+
name: typeof block['name'] === 'string' ? block['name'] : '',
|
|
74
|
+
inputRaw: '',
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else if (eventType === 'content_block_delta') {
|
|
78
|
+
const delta = data['delta'];
|
|
79
|
+
if (!delta || delta['type'] !== 'input_json_delta')
|
|
80
|
+
return;
|
|
81
|
+
const existing = pending.get(index);
|
|
82
|
+
if (existing && typeof delta['partial_json'] === 'string') {
|
|
83
|
+
existing.inputRaw += delta['partial_json'];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// content_block_stop: nothing to accumulate
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Parse the accumulated input JSON into an arguments object.
|
|
90
|
+
*/
|
|
91
|
+
export function finalizeAnthropicToolUse(tc) {
|
|
92
|
+
let args = {};
|
|
93
|
+
try {
|
|
94
|
+
const parsed = JSON.parse(tc.inputRaw);
|
|
95
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
96
|
+
args = parsed;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
console.warn(`[veto intercept] Malformed tool input for '${tc.name}', validating with empty args`);
|
|
101
|
+
}
|
|
102
|
+
return { name: tc.name, id: tc.id, arguments: args };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Synthesize Anthropic SSE events that replace a tool_use block with a
|
|
106
|
+
* text block containing the block reason, followed by message_stop.
|
|
107
|
+
*/
|
|
108
|
+
export function synthAnthropicBlockedEvent(reason) {
|
|
109
|
+
const blockStart = {
|
|
110
|
+
type: 'content_block_start',
|
|
111
|
+
index: 0,
|
|
112
|
+
content_block: { type: 'text', text: '' },
|
|
113
|
+
};
|
|
114
|
+
const blockDelta = {
|
|
115
|
+
type: 'content_block_delta',
|
|
116
|
+
index: 0,
|
|
117
|
+
delta: { type: 'text_delta', text: `[BLOCKED by veto] ${reason}` },
|
|
118
|
+
};
|
|
119
|
+
const blockStop = {
|
|
120
|
+
type: 'content_block_stop',
|
|
121
|
+
index: 0,
|
|
122
|
+
};
|
|
123
|
+
return [
|
|
124
|
+
`event: content_block_start\ndata: ${JSON.stringify(blockStart)}`,
|
|
125
|
+
`event: content_block_delta\ndata: ${JSON.stringify(blockDelta)}`,
|
|
126
|
+
`event: content_block_stop\ndata: ${JSON.stringify(blockStop)}`,
|
|
127
|
+
`event: message_stop\ndata: {}`,
|
|
128
|
+
]
|
|
129
|
+
.map((s) => s + '\n\n')
|
|
130
|
+
.join('');
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=anthropic-interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic-interceptor.js","sourceRoot":"","sources":["../../src/proxy/anthropic-interceptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE stream interceptor for OpenAI chat completions.
|
|
3
|
+
*
|
|
4
|
+
* Buffers streaming chunks, assembles tool call arguments, validates
|
|
5
|
+
* the assembled tool call against Veto policies, then either flushes
|
|
6
|
+
* the buffer or sends a synthetic error event.
|
|
7
|
+
*
|
|
8
|
+
* @module proxy/interceptor
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* A partially assembled tool call from SSE deltas.
|
|
12
|
+
*/
|
|
13
|
+
export interface PendingToolCall {
|
|
14
|
+
index: number;
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
argumentsRaw: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Result of processing one SSE line.
|
|
21
|
+
*/
|
|
22
|
+
export interface SSELineResult {
|
|
23
|
+
/** Raw line to forward (for passthrough mode) */
|
|
24
|
+
line: string;
|
|
25
|
+
/** Parsed JSON data if this is a data line */
|
|
26
|
+
data?: Record<string, unknown> | null;
|
|
27
|
+
/** True if this line is `data: [DONE]` */
|
|
28
|
+
done?: boolean;
|
|
29
|
+
/** True if this line contains a tool_calls delta */
|
|
30
|
+
hasToolCalls?: boolean;
|
|
31
|
+
/** True if finish_reason === "tool_calls" */
|
|
32
|
+
finishReasonToolCalls?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** Parse a single SSE line. Returns null for non-data/comment lines. */
|
|
35
|
+
export declare function parseSSELine(line: string): SSELineResult;
|
|
36
|
+
/**
|
|
37
|
+
* Merge tool call deltas from one SSE chunk into the pending map.
|
|
38
|
+
* OpenAI streams arguments across multiple chunks.
|
|
39
|
+
*/
|
|
40
|
+
export declare function mergeToolCallDeltas(pending: Map<number, PendingToolCall>, data: Record<string, unknown>): void;
|
|
41
|
+
/**
|
|
42
|
+
* Parse assembled argument strings into objects.
|
|
43
|
+
* Returns the tool call with a best-effort parsed arguments object.
|
|
44
|
+
*/
|
|
45
|
+
export declare function finalizeToolCall(tc: PendingToolCall): {
|
|
46
|
+
name: string;
|
|
47
|
+
id: string;
|
|
48
|
+
arguments: Record<string, unknown>;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Synthesize a blocked response as a valid SSE event.
|
|
52
|
+
* Sends a finish_reason: "stop" chunk with an error message in the content.
|
|
53
|
+
*/
|
|
54
|
+
export declare function synthBlockedEvent(reason: string, requestId?: string): string;
|
|
55
|
+
//# sourceMappingURL=interceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../../src/proxy/interceptor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,0CAA0C;IAC1C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,oDAAoD;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6CAA6C;IAC7C,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CA2BxD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI,CA8BN;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,eAAe,GAAG;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,CAYA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAa5E"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE stream interceptor for OpenAI chat completions.
|
|
3
|
+
*
|
|
4
|
+
* Buffers streaming chunks, assembles tool call arguments, validates
|
|
5
|
+
* the assembled tool call against Veto policies, then either flushes
|
|
6
|
+
* the buffer or sends a synthetic error event.
|
|
7
|
+
*
|
|
8
|
+
* @module proxy/interceptor
|
|
9
|
+
*/
|
|
10
|
+
/** Parse a single SSE line. Returns null for non-data/comment lines. */
|
|
11
|
+
export function parseSSELine(line) {
|
|
12
|
+
if (line === 'data: [DONE]')
|
|
13
|
+
return { line, done: true };
|
|
14
|
+
if (!line.startsWith('data: '))
|
|
15
|
+
return { line };
|
|
16
|
+
const jsonStr = line.slice(6);
|
|
17
|
+
let data;
|
|
18
|
+
try {
|
|
19
|
+
data = JSON.parse(jsonStr);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return { line };
|
|
23
|
+
}
|
|
24
|
+
const choices = Array.isArray(data['choices']) ? data['choices'] : [];
|
|
25
|
+
let hasToolCalls = false;
|
|
26
|
+
let finishReasonToolCalls = false;
|
|
27
|
+
for (const choice of choices) {
|
|
28
|
+
if (typeof choice !== 'object' || choice === null)
|
|
29
|
+
continue;
|
|
30
|
+
const c = choice;
|
|
31
|
+
if (c['finish_reason'] === 'tool_calls')
|
|
32
|
+
finishReasonToolCalls = true;
|
|
33
|
+
const delta = c['delta'];
|
|
34
|
+
if (delta && Array.isArray(delta['tool_calls']) && delta['tool_calls'].length > 0) {
|
|
35
|
+
hasToolCalls = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { line, data, hasToolCalls, finishReasonToolCalls };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Merge tool call deltas from one SSE chunk into the pending map.
|
|
42
|
+
* OpenAI streams arguments across multiple chunks.
|
|
43
|
+
*/
|
|
44
|
+
export function mergeToolCallDeltas(pending, data) {
|
|
45
|
+
const choices = Array.isArray(data['choices']) ? data['choices'] : [];
|
|
46
|
+
for (const choice of choices) {
|
|
47
|
+
if (typeof choice !== 'object' || choice === null)
|
|
48
|
+
continue;
|
|
49
|
+
const c = choice;
|
|
50
|
+
const delta = c['delta'];
|
|
51
|
+
if (!delta || !Array.isArray(delta['tool_calls']))
|
|
52
|
+
continue;
|
|
53
|
+
for (const tc of delta['tool_calls']) {
|
|
54
|
+
const idx = typeof tc['index'] === 'number' ? tc['index'] : 0;
|
|
55
|
+
if (!pending.has(idx)) {
|
|
56
|
+
pending.set(idx, {
|
|
57
|
+
index: idx,
|
|
58
|
+
id: typeof tc['id'] === 'string' ? tc['id'] : '',
|
|
59
|
+
name: typeof tc['function']?.['name'] === 'string'
|
|
60
|
+
? tc['function']['name']
|
|
61
|
+
: '',
|
|
62
|
+
argumentsRaw: '',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
const existing = pending.get(idx);
|
|
66
|
+
const fn = tc['function'];
|
|
67
|
+
if (fn && typeof fn['name'] === 'string' && fn['name'] && !existing.name) {
|
|
68
|
+
existing.name = fn['name'];
|
|
69
|
+
}
|
|
70
|
+
if (fn && typeof fn['arguments'] === 'string') {
|
|
71
|
+
existing.argumentsRaw += fn['arguments'];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Parse assembled argument strings into objects.
|
|
78
|
+
* Returns the tool call with a best-effort parsed arguments object.
|
|
79
|
+
*/
|
|
80
|
+
export function finalizeToolCall(tc) {
|
|
81
|
+
let args = {};
|
|
82
|
+
try {
|
|
83
|
+
const parsed = JSON.parse(tc.argumentsRaw);
|
|
84
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
85
|
+
args = parsed;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
console.warn(`[veto intercept] Malformed tool arguments for '${tc.name}', validating with empty args`);
|
|
90
|
+
}
|
|
91
|
+
return { name: tc.name, id: tc.id, arguments: args };
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Synthesize a blocked response as a valid SSE event.
|
|
95
|
+
* Sends a finish_reason: "stop" chunk with an error message in the content.
|
|
96
|
+
*/
|
|
97
|
+
export function synthBlockedEvent(reason, requestId) {
|
|
98
|
+
const chunk = {
|
|
99
|
+
id: requestId ?? 'veto-blocked',
|
|
100
|
+
object: 'chat.completion.chunk',
|
|
101
|
+
choices: [
|
|
102
|
+
{
|
|
103
|
+
index: 0,
|
|
104
|
+
delta: { role: 'assistant', content: `[BLOCKED by veto] ${reason}` },
|
|
105
|
+
finish_reason: 'stop',
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
};
|
|
109
|
+
return `data: ${JSON.stringify(chunk)}\n\ndata: [DONE]\n\n`;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptor.js","sourceRoot":"","sources":["../../src/proxy/interceptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
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 type { ProxyConfig } from './types.js';
|
|
16
|
+
/**
|
|
17
|
+
* Start the veto intercept proxy server.
|
|
18
|
+
* Returns a cleanup function that stops the server and destroys the Veto instance.
|
|
19
|
+
*/
|
|
20
|
+
export declare function startProxyServer(config: ProxyConfig): Promise<() => Promise<void>>;
|
|
21
|
+
//# sourceMappingURL=server.d.ts.map
|