@mondaydotcomorg/atp-protocol 0.17.14
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 +241 -0
- package/dist/auth.d.ts +173 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +202 -0
- package/dist/auth.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth.d.ts +63 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +5 -0
- package/dist/oauth.js.map +1 -0
- package/dist/providers.d.ts +167 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +33 -0
- package/dist/providers.js.map +1 -0
- package/dist/schemas.d.ts +6 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +51 -0
- package/dist/schemas.js.map +1 -0
- package/dist/types.d.ts +489 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +88 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +76 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +129 -0
- package/dist/validation.js.map +1 -0
- package/package.json +41 -0
- package/src/auth.ts +404 -0
- package/src/index.ts +6 -0
- package/src/oauth.ts +74 -0
- package/src/providers.ts +227 -0
- package/src/schemas.ts +55 -0
- package/src/types.ts +547 -0
- package/src/validation.ts +162 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
import type { ProvenanceMode, SecurityPolicy } from '@mondaydotcomorg/atp-provenance';
|
|
2
|
+
export { ProvenanceMode, type SecurityPolicy } from '@mondaydotcomorg/atp-provenance';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Callback types that can pause execution
|
|
6
|
+
*/
|
|
7
|
+
export enum CallbackType {
|
|
8
|
+
LLM = 'llm',
|
|
9
|
+
APPROVAL = 'approval',
|
|
10
|
+
EMBEDDING = 'embedding',
|
|
11
|
+
TOOL = 'tool',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Tool callback operations
|
|
16
|
+
*/
|
|
17
|
+
export enum ToolOperation {
|
|
18
|
+
CALL = 'call',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface AgentToolProtocolRequest {
|
|
22
|
+
jsonrpc: '2.0';
|
|
23
|
+
id: string | number;
|
|
24
|
+
method: string;
|
|
25
|
+
params: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface AgentToolProtocolResponse {
|
|
29
|
+
jsonrpc: '2.0';
|
|
30
|
+
id: string | number;
|
|
31
|
+
result?: unknown;
|
|
32
|
+
error?: {
|
|
33
|
+
code: number;
|
|
34
|
+
message: string;
|
|
35
|
+
data?: unknown;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface AgentToolProtocolNotification {
|
|
40
|
+
jsonrpc: '2.0';
|
|
41
|
+
method: string;
|
|
42
|
+
params: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Client-provided service availability
|
|
47
|
+
*/
|
|
48
|
+
export interface ClientServices {
|
|
49
|
+
/** Whether client provides LLM implementation */
|
|
50
|
+
hasLLM: boolean;
|
|
51
|
+
/** Whether client provides approval handler */
|
|
52
|
+
hasApproval: boolean;
|
|
53
|
+
/** Whether client provides embedding model */
|
|
54
|
+
hasEmbedding: boolean;
|
|
55
|
+
/** Whether client provides custom tools */
|
|
56
|
+
hasTools: boolean;
|
|
57
|
+
/** Names of client-provided tools (for discovery) */
|
|
58
|
+
toolNames?: string[];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Client-provided LLM handler
|
|
63
|
+
*/
|
|
64
|
+
export interface ClientLLMHandler {
|
|
65
|
+
call: (
|
|
66
|
+
prompt: string,
|
|
67
|
+
options?: {
|
|
68
|
+
context?: Record<string, unknown>;
|
|
69
|
+
model?: string;
|
|
70
|
+
temperature?: number;
|
|
71
|
+
systemPrompt?: string;
|
|
72
|
+
}
|
|
73
|
+
) => Promise<string>;
|
|
74
|
+
extract?: <T>(
|
|
75
|
+
prompt: string,
|
|
76
|
+
schema: Record<string, unknown>,
|
|
77
|
+
options?: {
|
|
78
|
+
context?: Record<string, unknown>;
|
|
79
|
+
}
|
|
80
|
+
) => Promise<T>;
|
|
81
|
+
classify?: (
|
|
82
|
+
text: string,
|
|
83
|
+
categories: string[],
|
|
84
|
+
options?: {
|
|
85
|
+
context?: Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
) => Promise<string>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Client-provided approval handler
|
|
92
|
+
*/
|
|
93
|
+
export interface ClientApprovalHandler {
|
|
94
|
+
request: (
|
|
95
|
+
message: string,
|
|
96
|
+
context?: Record<string, unknown>
|
|
97
|
+
) => Promise<{
|
|
98
|
+
approved: boolean;
|
|
99
|
+
response?: unknown;
|
|
100
|
+
timestamp: number;
|
|
101
|
+
}>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Client-provided embedding handler
|
|
106
|
+
*/
|
|
107
|
+
export interface ClientEmbeddingHandler {
|
|
108
|
+
embed: (text: string) => Promise<number[]>;
|
|
109
|
+
similarity?: (text1: string, text2: string) => Promise<number>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Client-provided tool handler
|
|
114
|
+
* Function that executes on the client side when a client tool is invoked
|
|
115
|
+
*/
|
|
116
|
+
export interface ClientToolHandler {
|
|
117
|
+
(input: unknown): Promise<unknown>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Client tool definition (metadata sent to server)
|
|
122
|
+
* The actual handler function remains on the client side
|
|
123
|
+
*/
|
|
124
|
+
export interface ClientToolDefinition {
|
|
125
|
+
/** Tool name (unique per client session) */
|
|
126
|
+
name: string;
|
|
127
|
+
/** API namespace (e.g., 'playwright', 'browser'). Defaults to 'client' if not specified */
|
|
128
|
+
namespace?: string;
|
|
129
|
+
/** Human-readable description of what the tool does */
|
|
130
|
+
description: string;
|
|
131
|
+
/** JSON Schema for tool input validation */
|
|
132
|
+
inputSchema: JSONSchema;
|
|
133
|
+
/** JSON Schema for tool output (optional, for documentation) */
|
|
134
|
+
outputSchema?: JSONSchema;
|
|
135
|
+
/** Tool metadata for security and risk management */
|
|
136
|
+
metadata?: ToolMetadata;
|
|
137
|
+
/** Whether this tool supports parallel execution with other tools */
|
|
138
|
+
supportsConcurrency?: boolean;
|
|
139
|
+
/** Keywords for search/discovery (optional) */
|
|
140
|
+
keywords?: string[];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Client tool with handler (used client-side only)
|
|
145
|
+
* Extends ClientToolDefinition to include the actual handler function
|
|
146
|
+
*/
|
|
147
|
+
export interface ClientTool extends ClientToolDefinition {
|
|
148
|
+
/** Handler function that executes on client side */
|
|
149
|
+
handler: ClientToolHandler;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Tool operation type classification
|
|
154
|
+
*/
|
|
155
|
+
export enum ToolOperationType {
|
|
156
|
+
/** Safe read-only operations */
|
|
157
|
+
READ = 'read',
|
|
158
|
+
/** Operations that modify data */
|
|
159
|
+
WRITE = 'write',
|
|
160
|
+
/** Operations that delete or destroy data */
|
|
161
|
+
DESTRUCTIVE = 'destructive',
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Tool sensitivity level
|
|
166
|
+
*/
|
|
167
|
+
export enum ToolSensitivityLevel {
|
|
168
|
+
/** Public data, no sensitivity concerns */
|
|
169
|
+
PUBLIC = 'public',
|
|
170
|
+
/** Internal data, requires authentication */
|
|
171
|
+
INTERNAL = 'internal',
|
|
172
|
+
/** Sensitive data (PII, financial data, etc.) */
|
|
173
|
+
SENSITIVE = 'sensitive',
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Client-side tool execution rules
|
|
178
|
+
* Allows clients to control which tools can be executed and under what conditions
|
|
179
|
+
*/
|
|
180
|
+
export interface ClientToolRules {
|
|
181
|
+
/** Block all tools of specific operation types */
|
|
182
|
+
blockOperationTypes?: ToolOperationType[];
|
|
183
|
+
/** Block all tools with specific sensitivity levels */
|
|
184
|
+
blockSensitivityLevels?: ToolSensitivityLevel[];
|
|
185
|
+
/** Require approval for specific operation types */
|
|
186
|
+
requireApprovalForOperationTypes?: ToolOperationType[];
|
|
187
|
+
/** Require approval for specific sensitivity levels */
|
|
188
|
+
requireApprovalForSensitivityLevels?: ToolSensitivityLevel[];
|
|
189
|
+
/** Block specific tools by name (e.g., ['deleteDatabase', 'dropTable']) */
|
|
190
|
+
blockTools?: string[];
|
|
191
|
+
/** Allow only specific tools by name (whitelist mode) */
|
|
192
|
+
allowOnlyTools?: string[];
|
|
193
|
+
/** Block entire API groups (e.g., ['admin', 'system']) */
|
|
194
|
+
blockApiGroups?: string[];
|
|
195
|
+
/** Allow only specific API groups (whitelist mode) */
|
|
196
|
+
allowOnlyApiGroups?: string[];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Tool/API metadata for security and risk management
|
|
201
|
+
*
|
|
202
|
+
* What can clients do with these annotations?
|
|
203
|
+
*
|
|
204
|
+
* 1. **Block Execution**:
|
|
205
|
+
* - Block all WRITE operations: blockOperationTypes: [ToolOperationType.WRITE]
|
|
206
|
+
* - Block all DESTRUCTIVE operations: blockOperationTypes: [ToolOperationType.DESTRUCTIVE]
|
|
207
|
+
* - Block SENSITIVE data access: blockSensitivityLevels: [ToolSensitivityLevel.SENSITIVE]
|
|
208
|
+
*
|
|
209
|
+
* 2. **Require Approval**:
|
|
210
|
+
* - Require approval for WRITE: requireApprovalForOperationTypes: [ToolOperationType.WRITE]
|
|
211
|
+
* - Require approval for DESTRUCTIVE: requireApprovalForOperationTypes: [ToolOperationType.DESTRUCTIVE]
|
|
212
|
+
* - Require approval for SENSITIVE: requireApprovalForSensitivityLevels: [ToolSensitivityLevel.SENSITIVE]
|
|
213
|
+
*
|
|
214
|
+
* 3. **Whitelist/Blacklist**:
|
|
215
|
+
* - Block specific tools: blockTools: ['deleteDatabase', 'dropTable']
|
|
216
|
+
* - Allow only safe tools: allowOnlyTools: ['getUser', 'listItems']
|
|
217
|
+
* - Block admin APIs: blockApiGroups: ['admin', 'system']
|
|
218
|
+
*
|
|
219
|
+
* 4. **Audit & Logging**:
|
|
220
|
+
* - Log all DESTRUCTIVE operations
|
|
221
|
+
* - Track access to SENSITIVE data
|
|
222
|
+
* - Monitor WRITE operations
|
|
223
|
+
*
|
|
224
|
+
* Granularity levels:
|
|
225
|
+
* - Operation Type: READ, WRITE, DESTRUCTIVE (coarse-grained)
|
|
226
|
+
* - Sensitivity Level: PUBLIC, INTERNAL, SENSITIVE (data classification)
|
|
227
|
+
* - Tool Name: Specific function names (fine-grained)
|
|
228
|
+
* - API Group: Entire namespaces (medium-grained)
|
|
229
|
+
*/
|
|
230
|
+
export interface ToolMetadata {
|
|
231
|
+
/** Operation type classification */
|
|
232
|
+
operationType?: ToolOperationType;
|
|
233
|
+
/** Sensitivity level of data handled */
|
|
234
|
+
sensitivityLevel?: ToolSensitivityLevel;
|
|
235
|
+
/** Require explicit approval before execution (server-side enforcement) */
|
|
236
|
+
requiresApproval?: boolean;
|
|
237
|
+
/** Category for grouping/filtering (e.g., 'database', 'user-management') */
|
|
238
|
+
category?: string;
|
|
239
|
+
/** Additional tags for classification */
|
|
240
|
+
tags?: string[];
|
|
241
|
+
/** Human-readable description of potential impact */
|
|
242
|
+
impactDescription?: string;
|
|
243
|
+
/**
|
|
244
|
+
* Required OAuth scopes to use this tool
|
|
245
|
+
* Used for scope-based filtering when user credentials have limited permissions
|
|
246
|
+
* @example ['repo', 'read:user'] for GitHub
|
|
247
|
+
* @example ['https://www.googleapis.com/auth/calendar'] for Google
|
|
248
|
+
*/
|
|
249
|
+
requiredScopes?: string[];
|
|
250
|
+
/**
|
|
251
|
+
* Generic permissions required (for non-OAuth providers)
|
|
252
|
+
* @example ['admin', 'write:users']
|
|
253
|
+
*/
|
|
254
|
+
requiredPermissions?: string[];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Client service providers
|
|
259
|
+
*/
|
|
260
|
+
export interface ClientServiceProviders {
|
|
261
|
+
llm?: ClientLLMHandler;
|
|
262
|
+
approval?: ClientApprovalHandler;
|
|
263
|
+
embedding?: ClientEmbeddingHandler;
|
|
264
|
+
/** Client-provided tools that execute locally */
|
|
265
|
+
tools?: ClientTool[];
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface ExecutionConfig {
|
|
269
|
+
timeout: number;
|
|
270
|
+
maxMemory: number;
|
|
271
|
+
maxLLMCalls: number;
|
|
272
|
+
allowedAPIs: string[];
|
|
273
|
+
allowLLMCalls: boolean;
|
|
274
|
+
progressCallback?: (message: string, fraction: number) => void;
|
|
275
|
+
customLLMHandler?: (prompt: string, options?: any) => Promise<string>;
|
|
276
|
+
clientServices?: ClientServices;
|
|
277
|
+
provenanceMode?: ProvenanceMode;
|
|
278
|
+
securityPolicies?: SecurityPolicy[];
|
|
279
|
+
provenanceHints?: string[];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Execution status codes for fine-grained error reporting
|
|
284
|
+
*/
|
|
285
|
+
export enum ExecutionStatus {
|
|
286
|
+
COMPLETED = 'completed',
|
|
287
|
+
FAILED = 'failed',
|
|
288
|
+
TIMEOUT = 'timeout',
|
|
289
|
+
CANCELLED = 'cancelled',
|
|
290
|
+
PAUSED = 'paused',
|
|
291
|
+
MEMORY_EXCEEDED = 'memory_exceeded',
|
|
292
|
+
LLM_CALLS_EXCEEDED = 'llm_calls_exceeded',
|
|
293
|
+
SECURITY_VIOLATION = 'security_violation',
|
|
294
|
+
VALIDATION_FAILED = 'validation_failed',
|
|
295
|
+
LOOP_DETECTED = 'loop_detected',
|
|
296
|
+
RATE_LIMITED = 'rate_limited',
|
|
297
|
+
NETWORK_ERROR = 'network_error',
|
|
298
|
+
PARSE_ERROR = 'parse_error',
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Execution error codes for categorizing failures
|
|
303
|
+
*/
|
|
304
|
+
export enum ExecutionErrorCode {
|
|
305
|
+
UNKNOWN_ERROR = 'UNKNOWN_ERROR',
|
|
306
|
+
EXECUTION_FAILED = 'EXECUTION_FAILED',
|
|
307
|
+
TIMEOUT_ERROR = 'TIMEOUT_ERROR',
|
|
308
|
+
|
|
309
|
+
MEMORY_LIMIT_EXCEEDED = 'MEMORY_LIMIT_EXCEEDED',
|
|
310
|
+
LLM_CALL_LIMIT_EXCEEDED = 'LLM_CALL_LIMIT_EXCEEDED',
|
|
311
|
+
HTTP_CALL_LIMIT_EXCEEDED = 'HTTP_CALL_LIMIT_EXCEEDED',
|
|
312
|
+
|
|
313
|
+
SECURITY_VIOLATION = 'SECURITY_VIOLATION',
|
|
314
|
+
VALIDATION_FAILED = 'VALIDATION_FAILED',
|
|
315
|
+
FORBIDDEN_OPERATION = 'FORBIDDEN_OPERATION',
|
|
316
|
+
|
|
317
|
+
PARSE_ERROR = 'PARSE_ERROR',
|
|
318
|
+
SYNTAX_ERROR = 'SYNTAX_ERROR',
|
|
319
|
+
TYPE_ERROR = 'TYPE_ERROR',
|
|
320
|
+
REFERENCE_ERROR = 'REFERENCE_ERROR',
|
|
321
|
+
|
|
322
|
+
INFINITE_LOOP_DETECTED = 'INFINITE_LOOP_DETECTED',
|
|
323
|
+
LOOP_TIMEOUT = 'LOOP_TIMEOUT',
|
|
324
|
+
|
|
325
|
+
NETWORK_ERROR = 'NETWORK_ERROR',
|
|
326
|
+
HTTP_ERROR = 'HTTP_ERROR',
|
|
327
|
+
DNS_ERROR = 'DNS_ERROR',
|
|
328
|
+
|
|
329
|
+
RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',
|
|
330
|
+
CONCURRENT_LIMIT_EXCEEDED = 'CONCURRENT_LIMIT_EXCEEDED',
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export interface ExecutionResult {
|
|
334
|
+
executionId: string;
|
|
335
|
+
status: ExecutionStatus;
|
|
336
|
+
result?: unknown;
|
|
337
|
+
error?: {
|
|
338
|
+
message: string;
|
|
339
|
+
code?: ExecutionErrorCode;
|
|
340
|
+
stack?: string;
|
|
341
|
+
line?: number;
|
|
342
|
+
context?: Record<string, unknown>;
|
|
343
|
+
retryable?: boolean;
|
|
344
|
+
suggestion?: string;
|
|
345
|
+
};
|
|
346
|
+
stats: {
|
|
347
|
+
duration: number;
|
|
348
|
+
memoryUsed: number;
|
|
349
|
+
llmCallsCount: number;
|
|
350
|
+
approvalCallsCount: number;
|
|
351
|
+
statementsExecuted?: number;
|
|
352
|
+
statementsCached?: number;
|
|
353
|
+
};
|
|
354
|
+
needsCallback?: {
|
|
355
|
+
type: CallbackType;
|
|
356
|
+
operation: string;
|
|
357
|
+
payload: Record<string, unknown>;
|
|
358
|
+
};
|
|
359
|
+
needsCallbacks?: BatchCallbackRequest[];
|
|
360
|
+
callbackHistory?: Array<{
|
|
361
|
+
type: CallbackType;
|
|
362
|
+
operation: string;
|
|
363
|
+
payload: Record<string, unknown>;
|
|
364
|
+
result?: unknown;
|
|
365
|
+
timestamp: number;
|
|
366
|
+
sequenceNumber: number;
|
|
367
|
+
}>;
|
|
368
|
+
transformedCode?: string;
|
|
369
|
+
provenanceSnapshot?: unknown;
|
|
370
|
+
provenanceTokens?: Array<{
|
|
371
|
+
path: string;
|
|
372
|
+
token: string;
|
|
373
|
+
}>;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Batch callback request for parallel execution
|
|
378
|
+
*/
|
|
379
|
+
export interface BatchCallbackRequest {
|
|
380
|
+
/** Unique callback ID */
|
|
381
|
+
id: string;
|
|
382
|
+
/** Callback type */
|
|
383
|
+
type: CallbackType;
|
|
384
|
+
/** Operation name */
|
|
385
|
+
operation: string;
|
|
386
|
+
/** Operation payload */
|
|
387
|
+
payload: Record<string, unknown>;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Batch callback result from client
|
|
392
|
+
*/
|
|
393
|
+
export interface BatchCallbackResult {
|
|
394
|
+
/** Callback ID (matches BatchCallbackRequest.id) */
|
|
395
|
+
id: string;
|
|
396
|
+
/** Callback result */
|
|
397
|
+
result: unknown;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export interface SearchOptions {
|
|
401
|
+
query: string;
|
|
402
|
+
apiGroups?: string[];
|
|
403
|
+
maxResults?: number;
|
|
404
|
+
useEmbeddings?: boolean;
|
|
405
|
+
embeddingModel?: string;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export interface SearchResult {
|
|
409
|
+
apiGroup: string;
|
|
410
|
+
functionName: string;
|
|
411
|
+
description: string;
|
|
412
|
+
signature: string;
|
|
413
|
+
example?: string;
|
|
414
|
+
relevanceScore: number;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export interface ExploreRequest {
|
|
418
|
+
path: string;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export interface ExploreDirectoryResult {
|
|
422
|
+
type: 'directory';
|
|
423
|
+
path: string;
|
|
424
|
+
items: Array<{ name: string; type: 'directory' | 'function' }>;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export interface ExploreFunctionResult {
|
|
428
|
+
type: 'function';
|
|
429
|
+
path: string;
|
|
430
|
+
name: string;
|
|
431
|
+
description: string;
|
|
432
|
+
definition: string;
|
|
433
|
+
group: string;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export type ExploreResult = ExploreDirectoryResult | ExploreFunctionResult;
|
|
437
|
+
|
|
438
|
+
export interface ValidationResult {
|
|
439
|
+
valid: boolean;
|
|
440
|
+
errors?: ValidationError[];
|
|
441
|
+
warnings?: ValidationError[];
|
|
442
|
+
securityIssues?: SecurityIssue[];
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export interface ValidationError {
|
|
446
|
+
line: number;
|
|
447
|
+
message: string;
|
|
448
|
+
severity: 'error' | 'warning';
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export interface SecurityIssue {
|
|
452
|
+
line: number;
|
|
453
|
+
issue: string;
|
|
454
|
+
risk: 'low' | 'medium' | 'high';
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export interface APISource {
|
|
458
|
+
type: 'mcp' | 'openapi' | 'custom';
|
|
459
|
+
name: string;
|
|
460
|
+
url?: string;
|
|
461
|
+
spec?: unknown;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export interface ServerConfig {
|
|
465
|
+
apiGroups: APIGroupConfig[];
|
|
466
|
+
security: SecurityConfig;
|
|
467
|
+
execution: ExecutionLimits;
|
|
468
|
+
search: SearchConfig;
|
|
469
|
+
logging: LoggingConfig;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
export interface APIGroupConfig {
|
|
473
|
+
name: string;
|
|
474
|
+
type: 'mcp' | 'openapi' | 'custom';
|
|
475
|
+
url?: string;
|
|
476
|
+
spec?: unknown;
|
|
477
|
+
functions?: CustomFunctionDef[];
|
|
478
|
+
/** Authentication configuration for this API group */
|
|
479
|
+
auth?: import('./auth.js').AuthConfig;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export interface SecurityConfig {
|
|
483
|
+
allowedOrigins: string[];
|
|
484
|
+
apiKeyRequired: boolean;
|
|
485
|
+
rateLimits: {
|
|
486
|
+
requestsPerMinute: number;
|
|
487
|
+
executionsPerHour: number;
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export interface ExecutionLimits {
|
|
492
|
+
defaultTimeout: number;
|
|
493
|
+
maxTimeout: number;
|
|
494
|
+
defaultMemoryLimit: number;
|
|
495
|
+
maxMemoryLimit: number;
|
|
496
|
+
defaultLLMCallLimit: number;
|
|
497
|
+
maxLLMCallLimit: number;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
export interface SearchConfig {
|
|
501
|
+
enableEmbeddings: boolean;
|
|
502
|
+
embeddingProvider?: 'openai' | 'cohere' | 'custom';
|
|
503
|
+
customSearcher?: (query: string) => Promise<SearchResult[]>;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
export interface LoggingConfig {
|
|
507
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
508
|
+
destination: 'console' | 'file' | 'remote';
|
|
509
|
+
auditEnabled: boolean;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
export interface CustomFunctionDef {
|
|
513
|
+
name: string;
|
|
514
|
+
description: string;
|
|
515
|
+
inputSchema: JSONSchema;
|
|
516
|
+
outputSchema?: JSONSchema;
|
|
517
|
+
handler: (params: unknown) => Promise<unknown>;
|
|
518
|
+
keywords?: string[];
|
|
519
|
+
metadata?: ToolMetadata; // NEW: Tool metadata for security
|
|
520
|
+
requiredScopes?: string[]; // OAuth scopes required to use this function
|
|
521
|
+
auth?: {
|
|
522
|
+
source?: 'server' | 'user';
|
|
523
|
+
oauthProvider?: string;
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
export interface JSONSchema {
|
|
528
|
+
type: string;
|
|
529
|
+
properties?: Record<string, unknown>;
|
|
530
|
+
required?: string[];
|
|
531
|
+
[key: string]: unknown;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export interface ClientConfig {
|
|
535
|
+
serverUrl: string;
|
|
536
|
+
apiKey: string;
|
|
537
|
+
timeout?: number;
|
|
538
|
+
llmProvider: 'anthropic' | 'openai' | 'custom';
|
|
539
|
+
llmModel?: string;
|
|
540
|
+
temperature?: number;
|
|
541
|
+
defaultExecutionConfig?: Partial<ExecutionConfig>;
|
|
542
|
+
searchPreferences?: {
|
|
543
|
+
useEmbeddings?: boolean;
|
|
544
|
+
embeddingModel?: string;
|
|
545
|
+
maxResults?: number;
|
|
546
|
+
};
|
|
547
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input validation utilities for ExecutionConfig and other types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import type { ExecutionConfig } from './types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Maximum allowed code size (1MB)
|
|
10
|
+
*/
|
|
11
|
+
export const MAX_CODE_SIZE = 1000000;
|
|
12
|
+
|
|
13
|
+
export class ConfigValidationError extends Error {
|
|
14
|
+
constructor(
|
|
15
|
+
message: string,
|
|
16
|
+
public readonly field: string,
|
|
17
|
+
public readonly value: unknown
|
|
18
|
+
) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'ConfigValidationError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class SecurityViolationError extends Error {
|
|
25
|
+
constructor(
|
|
26
|
+
message: string,
|
|
27
|
+
public readonly violations: string[]
|
|
28
|
+
) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = 'SecurityViolationError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Sanitizes input string by removing control characters and normalizing whitespace
|
|
36
|
+
*/
|
|
37
|
+
export function sanitizeInput(input: string, maxLength = MAX_CODE_SIZE): string {
|
|
38
|
+
if (typeof input !== 'string') {
|
|
39
|
+
return '';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let sanitized = input.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, '');
|
|
43
|
+
|
|
44
|
+
sanitized = sanitized.replace(/[\u200B-\u200D\uFEFF]/g, '');
|
|
45
|
+
|
|
46
|
+
sanitized = sanitized.replace(/\n{10,}/g, '\n\n\n');
|
|
47
|
+
|
|
48
|
+
if (sanitized.length > maxLength) {
|
|
49
|
+
sanitized = sanitized.substring(0, maxLength);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return sanitized;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Frames user code in a secure execution context to prevent injection attacks
|
|
57
|
+
* Similar to SQL parameterized queries - treats user code as data within a safe boundary
|
|
58
|
+
*/
|
|
59
|
+
export function frameCodeExecution(userCode: string): string {
|
|
60
|
+
const cleaned = sanitizeInput(userCode);
|
|
61
|
+
|
|
62
|
+
return `
|
|
63
|
+
(async function __user_code_context__() {
|
|
64
|
+
"use strict";
|
|
65
|
+
${cleaned}
|
|
66
|
+
})();
|
|
67
|
+
`.trim();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Zod schema for ExecutionConfig validation
|
|
72
|
+
*/
|
|
73
|
+
export const executionConfigSchema = z.object({
|
|
74
|
+
timeout: z
|
|
75
|
+
.number({
|
|
76
|
+
invalid_type_error: 'timeout must be a number',
|
|
77
|
+
})
|
|
78
|
+
.positive('timeout must be positive')
|
|
79
|
+
.max(300000, 'timeout cannot exceed 300000ms (5 minutes)')
|
|
80
|
+
.optional(),
|
|
81
|
+
|
|
82
|
+
maxMemory: z
|
|
83
|
+
.number({
|
|
84
|
+
invalid_type_error: 'maxMemory must be a number',
|
|
85
|
+
})
|
|
86
|
+
.positive('maxMemory must be positive')
|
|
87
|
+
.max(512 * 1024 * 1024, 'maxMemory cannot exceed 512MB')
|
|
88
|
+
.optional(),
|
|
89
|
+
|
|
90
|
+
maxLLMCalls: z
|
|
91
|
+
.number({
|
|
92
|
+
invalid_type_error: 'maxLLMCalls must be a number',
|
|
93
|
+
})
|
|
94
|
+
.nonnegative('maxLLMCalls cannot be negative')
|
|
95
|
+
.max(1000, 'maxLLMCalls cannot exceed 1000')
|
|
96
|
+
.optional(),
|
|
97
|
+
|
|
98
|
+
allowedAPIs: z
|
|
99
|
+
.array(
|
|
100
|
+
z.string().refine((val) => val.trim().length > 0, {
|
|
101
|
+
message: 'allowedAPIs must contain non-empty strings',
|
|
102
|
+
})
|
|
103
|
+
)
|
|
104
|
+
.optional(),
|
|
105
|
+
|
|
106
|
+
allowLLMCalls: z
|
|
107
|
+
.boolean({
|
|
108
|
+
invalid_type_error: 'allowLLMCalls must be a boolean',
|
|
109
|
+
})
|
|
110
|
+
.optional(),
|
|
111
|
+
|
|
112
|
+
progressCallback: z.function().optional(),
|
|
113
|
+
customLLMHandler: z.function().optional(),
|
|
114
|
+
clientServices: z.any().optional(),
|
|
115
|
+
provenanceMode: z.any().optional(),
|
|
116
|
+
securityPolicies: z.array(z.any()).optional(),
|
|
117
|
+
provenanceHints: z.array(z.string()).optional(),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Validates ExecutionConfig parameters using Zod
|
|
122
|
+
*/
|
|
123
|
+
export function validateExecutionConfig(config: Partial<ExecutionConfig>): void {
|
|
124
|
+
try {
|
|
125
|
+
executionConfigSchema.parse(config);
|
|
126
|
+
} catch (error) {
|
|
127
|
+
if (error instanceof z.ZodError) {
|
|
128
|
+
const errors = error.errors.map((err) => err.message);
|
|
129
|
+
throw new ConfigValidationError(
|
|
130
|
+
`Invalid ExecutionConfig: ${errors.join(', ')}`,
|
|
131
|
+
'ExecutionConfig',
|
|
132
|
+
config
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Validates client ID format
|
|
141
|
+
*/
|
|
142
|
+
export function validateClientId(clientId: string): void {
|
|
143
|
+
if (typeof clientId !== 'string') {
|
|
144
|
+
throw new ConfigValidationError('clientId must be a string', 'clientId', clientId);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (clientId.trim().length === 0) {
|
|
148
|
+
throw new ConfigValidationError('clientId cannot be empty', 'clientId', clientId);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (clientId.length > 256) {
|
|
152
|
+
throw new ConfigValidationError('clientId cannot exceed 256 characters', 'clientId', clientId);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(clientId)) {
|
|
156
|
+
throw new ConfigValidationError(
|
|
157
|
+
'clientId can only contain alphanumeric characters, dashes, and underscores',
|
|
158
|
+
'clientId',
|
|
159
|
+
clientId
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|