@compilr-dev/agents 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1277 -0
- package/dist/agent.d.ts +1272 -0
- package/dist/agent.js +1912 -0
- package/dist/anchors/builtin.d.ts +24 -0
- package/dist/anchors/builtin.js +61 -0
- package/dist/anchors/index.d.ts +6 -0
- package/dist/anchors/index.js +5 -0
- package/dist/anchors/manager.d.ts +115 -0
- package/dist/anchors/manager.js +412 -0
- package/dist/anchors/types.d.ts +168 -0
- package/dist/anchors/types.js +10 -0
- package/dist/context/index.d.ts +12 -0
- package/dist/context/index.js +10 -0
- package/dist/context/manager.d.ts +224 -0
- package/dist/context/manager.js +770 -0
- package/dist/context/types.d.ts +377 -0
- package/dist/context/types.js +7 -0
- package/dist/costs/index.d.ts +8 -0
- package/dist/costs/index.js +7 -0
- package/dist/costs/tracker.d.ts +121 -0
- package/dist/costs/tracker.js +295 -0
- package/dist/costs/types.d.ts +157 -0
- package/dist/costs/types.js +8 -0
- package/dist/errors.d.ts +178 -0
- package/dist/errors.js +249 -0
- package/dist/guardrails/builtin.d.ts +27 -0
- package/dist/guardrails/builtin.js +223 -0
- package/dist/guardrails/index.d.ts +6 -0
- package/dist/guardrails/index.js +5 -0
- package/dist/guardrails/manager.d.ts +117 -0
- package/dist/guardrails/manager.js +288 -0
- package/dist/guardrails/types.d.ts +159 -0
- package/dist/guardrails/types.js +7 -0
- package/dist/hooks/index.d.ts +31 -0
- package/dist/hooks/index.js +29 -0
- package/dist/hooks/manager.d.ts +147 -0
- package/dist/hooks/manager.js +600 -0
- package/dist/hooks/types.d.ts +368 -0
- package/dist/hooks/types.js +12 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +73 -0
- package/dist/mcp/client.d.ts +93 -0
- package/dist/mcp/client.js +287 -0
- package/dist/mcp/errors.d.ts +60 -0
- package/dist/mcp/errors.js +78 -0
- package/dist/mcp/index.d.ts +43 -0
- package/dist/mcp/index.js +45 -0
- package/dist/mcp/manager.d.ts +120 -0
- package/dist/mcp/manager.js +276 -0
- package/dist/mcp/tools.d.ts +54 -0
- package/dist/mcp/tools.js +99 -0
- package/dist/mcp/types.d.ts +150 -0
- package/dist/mcp/types.js +40 -0
- package/dist/memory/index.d.ts +8 -0
- package/dist/memory/index.js +7 -0
- package/dist/memory/loader.d.ts +114 -0
- package/dist/memory/loader.js +463 -0
- package/dist/memory/types.d.ts +182 -0
- package/dist/memory/types.js +8 -0
- package/dist/messages/index.d.ts +82 -0
- package/dist/messages/index.js +155 -0
- package/dist/permissions/index.d.ts +5 -0
- package/dist/permissions/index.js +4 -0
- package/dist/permissions/manager.d.ts +125 -0
- package/dist/permissions/manager.js +379 -0
- package/dist/permissions/types.d.ts +162 -0
- package/dist/permissions/types.js +7 -0
- package/dist/providers/claude.d.ts +90 -0
- package/dist/providers/claude.js +348 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.js +11 -0
- package/dist/providers/mock.d.ts +133 -0
- package/dist/providers/mock.js +204 -0
- package/dist/providers/types.d.ts +168 -0
- package/dist/providers/types.js +4 -0
- package/dist/rate-limit/index.d.ts +45 -0
- package/dist/rate-limit/index.js +47 -0
- package/dist/rate-limit/limiter.d.ts +104 -0
- package/dist/rate-limit/limiter.js +326 -0
- package/dist/rate-limit/provider-wrapper.d.ts +112 -0
- package/dist/rate-limit/provider-wrapper.js +201 -0
- package/dist/rate-limit/retry.d.ts +108 -0
- package/dist/rate-limit/retry.js +287 -0
- package/dist/rate-limit/types.d.ts +181 -0
- package/dist/rate-limit/types.js +22 -0
- package/dist/rehearsal/file-analyzer.d.ts +22 -0
- package/dist/rehearsal/file-analyzer.js +351 -0
- package/dist/rehearsal/git-analyzer.d.ts +22 -0
- package/dist/rehearsal/git-analyzer.js +472 -0
- package/dist/rehearsal/index.d.ts +35 -0
- package/dist/rehearsal/index.js +36 -0
- package/dist/rehearsal/manager.d.ts +100 -0
- package/dist/rehearsal/manager.js +290 -0
- package/dist/rehearsal/types.d.ts +235 -0
- package/dist/rehearsal/types.js +8 -0
- package/dist/skills/index.d.ts +160 -0
- package/dist/skills/index.js +282 -0
- package/dist/state/agent-state.d.ts +41 -0
- package/dist/state/agent-state.js +88 -0
- package/dist/state/checkpointer.d.ts +110 -0
- package/dist/state/checkpointer.js +362 -0
- package/dist/state/errors.d.ts +66 -0
- package/dist/state/errors.js +88 -0
- package/dist/state/index.d.ts +35 -0
- package/dist/state/index.js +37 -0
- package/dist/state/serializer.d.ts +55 -0
- package/dist/state/serializer.js +172 -0
- package/dist/state/types.d.ts +312 -0
- package/dist/state/types.js +14 -0
- package/dist/tools/builtin/bash-output.d.ts +61 -0
- package/dist/tools/builtin/bash-output.js +90 -0
- package/dist/tools/builtin/bash.d.ts +150 -0
- package/dist/tools/builtin/bash.js +354 -0
- package/dist/tools/builtin/edit.d.ts +50 -0
- package/dist/tools/builtin/edit.js +215 -0
- package/dist/tools/builtin/glob.d.ts +62 -0
- package/dist/tools/builtin/glob.js +244 -0
- package/dist/tools/builtin/grep.d.ts +74 -0
- package/dist/tools/builtin/grep.js +363 -0
- package/dist/tools/builtin/index.d.ts +44 -0
- package/dist/tools/builtin/index.js +69 -0
- package/dist/tools/builtin/kill-shell.d.ts +44 -0
- package/dist/tools/builtin/kill-shell.js +80 -0
- package/dist/tools/builtin/read-file.d.ts +57 -0
- package/dist/tools/builtin/read-file.js +184 -0
- package/dist/tools/builtin/shell-manager.d.ts +176 -0
- package/dist/tools/builtin/shell-manager.js +337 -0
- package/dist/tools/builtin/task.d.ts +202 -0
- package/dist/tools/builtin/task.js +350 -0
- package/dist/tools/builtin/todo.d.ts +207 -0
- package/dist/tools/builtin/todo.js +453 -0
- package/dist/tools/builtin/utils.d.ts +27 -0
- package/dist/tools/builtin/utils.js +70 -0
- package/dist/tools/builtin/web-fetch.d.ts +96 -0
- package/dist/tools/builtin/web-fetch.js +290 -0
- package/dist/tools/builtin/write-file.d.ts +54 -0
- package/dist/tools/builtin/write-file.js +147 -0
- package/dist/tools/define.d.ts +60 -0
- package/dist/tools/define.js +65 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.js +37 -0
- package/dist/tools/registry.d.ts +79 -0
- package/dist/tools/registry.js +151 -0
- package/dist/tools/types.d.ts +59 -0
- package/dist/tools/types.js +4 -0
- package/dist/tracing/hooks.d.ts +58 -0
- package/dist/tracing/hooks.js +377 -0
- package/dist/tracing/index.d.ts +51 -0
- package/dist/tracing/index.js +55 -0
- package/dist/tracing/logging.d.ts +78 -0
- package/dist/tracing/logging.js +310 -0
- package/dist/tracing/manager.d.ts +160 -0
- package/dist/tracing/manager.js +468 -0
- package/dist/tracing/otel.d.ts +102 -0
- package/dist/tracing/otel.js +246 -0
- package/dist/tracing/types.d.ts +346 -0
- package/dist/tracing/types.js +38 -0
- package/dist/utils/index.d.ts +23 -0
- package/dist/utils/index.js +44 -0
- package/package.json +79 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PermissionManager - Manages tool-level permissions
|
|
3
|
+
*
|
|
4
|
+
* Provides fine-grained control over which tools can execute and when
|
|
5
|
+
* user approval is required.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const permissions = new PermissionManager({
|
|
10
|
+
* defaultLevel: 'always',
|
|
11
|
+
* rules: [
|
|
12
|
+
* { toolName: 'bash', level: 'once', description: 'Shell commands' },
|
|
13
|
+
* { toolName: 'write_file', level: 'session', description: 'File writes' },
|
|
14
|
+
* { toolName: 'delete_*', level: 'deny', description: 'Delete operations' },
|
|
15
|
+
* ],
|
|
16
|
+
* onPermissionRequest: async (request) => {
|
|
17
|
+
* return await askUser(`Allow ${request.toolName}?`);
|
|
18
|
+
* },
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Default permission rules for commonly dangerous tools
|
|
24
|
+
*/
|
|
25
|
+
const DEFAULT_PERMISSION_RULES = [
|
|
26
|
+
{
|
|
27
|
+
toolName: 'bash',
|
|
28
|
+
level: 'once',
|
|
29
|
+
description: 'Execute shell commands',
|
|
30
|
+
tags: ['shell', 'dangerous'],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
toolName: 'write_file',
|
|
34
|
+
level: 'session',
|
|
35
|
+
description: 'Write to files',
|
|
36
|
+
tags: ['filesystem'],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
toolName: 'edit',
|
|
40
|
+
level: 'session',
|
|
41
|
+
description: 'Edit files',
|
|
42
|
+
tags: ['filesystem'],
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Default preview generator that formats tool input for display
|
|
47
|
+
*/
|
|
48
|
+
function defaultPreviewGenerator(toolName, input) {
|
|
49
|
+
// Generate previews for common tools
|
|
50
|
+
switch (toolName) {
|
|
51
|
+
case 'bash': {
|
|
52
|
+
const command = input.command;
|
|
53
|
+
if (typeof command === 'string') {
|
|
54
|
+
return `Execute: ${command.slice(0, 200)}${command.length > 200 ? '...' : ''}`;
|
|
55
|
+
}
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case 'write_file':
|
|
59
|
+
case 'writeFile': {
|
|
60
|
+
const path = input.path ?? input.file_path;
|
|
61
|
+
if (typeof path === 'string') {
|
|
62
|
+
return `Write to: ${path}`;
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case 'edit': {
|
|
67
|
+
const path = input.path ?? input.file_path;
|
|
68
|
+
if (typeof path === 'string') {
|
|
69
|
+
return `Edit: ${path}`;
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case 'read_file':
|
|
74
|
+
case 'readFile': {
|
|
75
|
+
const path = input.path ?? input.file_path;
|
|
76
|
+
if (typeof path === 'string') {
|
|
77
|
+
return `Read: ${path}`;
|
|
78
|
+
}
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Generic preview: show first property
|
|
83
|
+
const keys = Object.keys(input);
|
|
84
|
+
if (keys.length > 0) {
|
|
85
|
+
const firstKey = keys[0];
|
|
86
|
+
const firstValue = input[firstKey];
|
|
87
|
+
const valueStr = typeof firstValue === 'string'
|
|
88
|
+
? firstValue.slice(0, 100)
|
|
89
|
+
: JSON.stringify(firstValue).slice(0, 100);
|
|
90
|
+
return `${toolName}: ${firstKey}=${valueStr}${String(firstValue).length > 100 ? '...' : ''}`;
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Convert a tool name pattern to a RegExp
|
|
96
|
+
* Supports wildcards: * matches any characters
|
|
97
|
+
*/
|
|
98
|
+
function patternToRegex(pattern) {
|
|
99
|
+
// Escape special regex characters except *
|
|
100
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
101
|
+
// Convert * to .*
|
|
102
|
+
const regexStr = escaped.replace(/\*/g, '.*');
|
|
103
|
+
return new RegExp(`^${regexStr}$`);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* PermissionManager handles tool-level permission checks
|
|
107
|
+
*/
|
|
108
|
+
export class PermissionManager {
|
|
109
|
+
enabled;
|
|
110
|
+
defaultLevel;
|
|
111
|
+
rules = new Map();
|
|
112
|
+
wildcardRules = [];
|
|
113
|
+
handler;
|
|
114
|
+
previewGenerator;
|
|
115
|
+
eventHandlers = new Set();
|
|
116
|
+
/**
|
|
117
|
+
* Track session-level permissions that have been granted
|
|
118
|
+
*/
|
|
119
|
+
sessionGrants = new Set();
|
|
120
|
+
constructor(options = {}) {
|
|
121
|
+
this.enabled = options.enabled ?? true;
|
|
122
|
+
this.defaultLevel = options.defaultLevel ?? 'always';
|
|
123
|
+
this.handler = options.onPermissionRequest;
|
|
124
|
+
this.previewGenerator = options.previewGenerator ?? defaultPreviewGenerator;
|
|
125
|
+
// Add default rules if requested
|
|
126
|
+
if (options.includeDefaults) {
|
|
127
|
+
for (const rule of DEFAULT_PERMISSION_RULES) {
|
|
128
|
+
this.addRule(rule);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Add custom rules
|
|
132
|
+
if (options.rules) {
|
|
133
|
+
for (const rule of options.rules) {
|
|
134
|
+
this.addRule(rule);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Add a permission rule
|
|
140
|
+
*/
|
|
141
|
+
addRule(rule) {
|
|
142
|
+
if (rule.toolName.includes('*')) {
|
|
143
|
+
// Wildcard pattern
|
|
144
|
+
this.wildcardRules.push({
|
|
145
|
+
pattern: patternToRegex(rule.toolName),
|
|
146
|
+
rule,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// Exact match
|
|
151
|
+
this.rules.set(rule.toolName, rule);
|
|
152
|
+
}
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Remove a permission rule by tool name
|
|
157
|
+
*/
|
|
158
|
+
removeRule(toolName) {
|
|
159
|
+
if (toolName.includes('*')) {
|
|
160
|
+
const index = this.wildcardRules.findIndex((wr) => wr.rule.toolName === toolName);
|
|
161
|
+
if (index >= 0) {
|
|
162
|
+
this.wildcardRules.splice(index, 1);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
return this.rules.delete(toolName);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get a permission rule by tool name
|
|
171
|
+
*/
|
|
172
|
+
getRule(toolName) {
|
|
173
|
+
// Check exact match first
|
|
174
|
+
const exact = this.rules.get(toolName);
|
|
175
|
+
if (exact)
|
|
176
|
+
return exact;
|
|
177
|
+
// Check wildcard patterns
|
|
178
|
+
for (const { pattern, rule } of this.wildcardRules) {
|
|
179
|
+
if (pattern.test(toolName)) {
|
|
180
|
+
return rule;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get all permission rules
|
|
187
|
+
*/
|
|
188
|
+
getAllRules() {
|
|
189
|
+
const exact = Array.from(this.rules.values());
|
|
190
|
+
const wildcards = this.wildcardRules.map((wr) => wr.rule);
|
|
191
|
+
return [...exact, ...wildcards];
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Check if a tool has permission to execute
|
|
195
|
+
*
|
|
196
|
+
* @param toolName - Name of the tool
|
|
197
|
+
* @param input - Tool input arguments
|
|
198
|
+
* @returns Permission check result
|
|
199
|
+
*/
|
|
200
|
+
async check(toolName, input) {
|
|
201
|
+
// If disabled, always allow
|
|
202
|
+
if (!this.enabled) {
|
|
203
|
+
return { allowed: true, level: 'always', askedUser: false };
|
|
204
|
+
}
|
|
205
|
+
// Find matching rule
|
|
206
|
+
const rule = this.getRule(toolName);
|
|
207
|
+
const level = rule?.level ?? this.defaultLevel;
|
|
208
|
+
// Handle based on permission level
|
|
209
|
+
switch (level) {
|
|
210
|
+
case 'always':
|
|
211
|
+
this.emit({ type: 'permission:granted', toolName, level, input, rule });
|
|
212
|
+
return { allowed: true, level, askedUser: false, rule };
|
|
213
|
+
case 'deny':
|
|
214
|
+
this.emit({ type: 'permission:denied', toolName, level, input, rule });
|
|
215
|
+
return {
|
|
216
|
+
allowed: false,
|
|
217
|
+
level,
|
|
218
|
+
askedUser: false,
|
|
219
|
+
rule,
|
|
220
|
+
reason: rule?.description ?? `Tool '${toolName}' is denied`,
|
|
221
|
+
};
|
|
222
|
+
case 'session': {
|
|
223
|
+
// Check if already granted this session
|
|
224
|
+
if (this.sessionGrants.has(toolName)) {
|
|
225
|
+
this.emit({ type: 'permission:granted', toolName, level, input, rule });
|
|
226
|
+
return { allowed: true, level, askedUser: false, rule };
|
|
227
|
+
}
|
|
228
|
+
// Ask for permission
|
|
229
|
+
const allowed = await this.askPermission(toolName, input, level, rule);
|
|
230
|
+
if (allowed) {
|
|
231
|
+
this.sessionGrants.add(toolName);
|
|
232
|
+
this.emit({ type: 'permission:session_granted', toolName, level, input, rule });
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
this.emit({ type: 'permission:denied', toolName, level, input, rule });
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
allowed,
|
|
239
|
+
level,
|
|
240
|
+
askedUser: true,
|
|
241
|
+
rule,
|
|
242
|
+
reason: allowed ? undefined : 'User denied permission',
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
case 'once': {
|
|
246
|
+
// Always ask for permission
|
|
247
|
+
const allowed = await this.askPermission(toolName, input, level, rule);
|
|
248
|
+
if (allowed) {
|
|
249
|
+
this.emit({ type: 'permission:granted', toolName, level, input, rule });
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
this.emit({ type: 'permission:denied', toolName, level, input, rule });
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
allowed,
|
|
256
|
+
level,
|
|
257
|
+
askedUser: true,
|
|
258
|
+
rule,
|
|
259
|
+
reason: allowed ? undefined : 'User denied permission',
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Check and handle permission, returning whether to proceed
|
|
266
|
+
*
|
|
267
|
+
* Convenience method that combines check() with handling
|
|
268
|
+
*/
|
|
269
|
+
async checkAndProceed(toolName, input) {
|
|
270
|
+
const result = await this.check(toolName, input);
|
|
271
|
+
return { proceed: result.allowed, result };
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Ask the user for permission
|
|
275
|
+
*/
|
|
276
|
+
async askPermission(toolName, input, level, rule) {
|
|
277
|
+
// If no handler, default to allow
|
|
278
|
+
if (!this.handler) {
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
const preview = this.previewGenerator(toolName, input);
|
|
282
|
+
const request = {
|
|
283
|
+
toolName,
|
|
284
|
+
input,
|
|
285
|
+
level,
|
|
286
|
+
description: rule?.description,
|
|
287
|
+
preview,
|
|
288
|
+
};
|
|
289
|
+
this.emit({ type: 'permission:asked', toolName, level, input, rule });
|
|
290
|
+
return this.handler(request);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Grant session-level permission for a tool
|
|
294
|
+
*
|
|
295
|
+
* This allows the tool to execute for the remainder of the session
|
|
296
|
+
* without asking again.
|
|
297
|
+
*/
|
|
298
|
+
grantSession(toolName) {
|
|
299
|
+
this.sessionGrants.add(toolName);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Revoke session-level permission for a tool
|
|
303
|
+
*/
|
|
304
|
+
revokeSession(toolName) {
|
|
305
|
+
return this.sessionGrants.delete(toolName);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Clear all session-level permissions
|
|
309
|
+
*/
|
|
310
|
+
clearSessionGrants() {
|
|
311
|
+
this.sessionGrants.clear();
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Get all tools with session-level permission
|
|
315
|
+
*/
|
|
316
|
+
getSessionGrants() {
|
|
317
|
+
return Array.from(this.sessionGrants);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Check if a tool has session-level permission
|
|
321
|
+
*/
|
|
322
|
+
hasSessionGrant(toolName) {
|
|
323
|
+
return this.sessionGrants.has(toolName);
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Set the permission level for a tool
|
|
327
|
+
*
|
|
328
|
+
* Convenience method for adding/updating a rule
|
|
329
|
+
*/
|
|
330
|
+
setLevel(toolName, level, description) {
|
|
331
|
+
const existing = this.rules.get(toolName);
|
|
332
|
+
this.addRule({
|
|
333
|
+
toolName,
|
|
334
|
+
level,
|
|
335
|
+
description: description ?? existing?.description,
|
|
336
|
+
tags: existing?.tags,
|
|
337
|
+
});
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Get the effective permission level for a tool
|
|
342
|
+
*/
|
|
343
|
+
getLevel(toolName) {
|
|
344
|
+
const rule = this.getRule(toolName);
|
|
345
|
+
return rule?.level ?? this.defaultLevel;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Register an event handler
|
|
349
|
+
*/
|
|
350
|
+
onEvent(handler) {
|
|
351
|
+
this.eventHandlers.add(handler);
|
|
352
|
+
return () => this.eventHandlers.delete(handler);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Emit an event
|
|
356
|
+
*/
|
|
357
|
+
emit(event) {
|
|
358
|
+
for (const handler of this.eventHandlers) {
|
|
359
|
+
try {
|
|
360
|
+
handler(event);
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
// Ignore handler errors
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Get the number of rules
|
|
369
|
+
*/
|
|
370
|
+
get size() {
|
|
371
|
+
return this.rules.size + this.wildcardRules.length;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Check if permissions are enabled
|
|
375
|
+
*/
|
|
376
|
+
get isEnabled() {
|
|
377
|
+
return this.enabled;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-level permissions - Explicit approval for specific tools
|
|
3
|
+
*
|
|
4
|
+
* Permissions provide fine-grained control over which tools can execute
|
|
5
|
+
* and when user approval is required.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Permission levels for tool execution
|
|
9
|
+
*
|
|
10
|
+
* - 'always': Tool can execute without asking (trusted tools)
|
|
11
|
+
* - 'session': Ask once per session, then allow for remainder
|
|
12
|
+
* - 'once': Ask every time the tool is invoked
|
|
13
|
+
* - 'deny': Never allow execution (blocked tools)
|
|
14
|
+
*/
|
|
15
|
+
export type PermissionLevel = 'always' | 'session' | 'once' | 'deny';
|
|
16
|
+
/**
|
|
17
|
+
* Permission rule for a specific tool
|
|
18
|
+
*/
|
|
19
|
+
export interface ToolPermission {
|
|
20
|
+
/**
|
|
21
|
+
* Tool name or pattern (supports wildcards like 'bash*', '*_file')
|
|
22
|
+
*/
|
|
23
|
+
toolName: string;
|
|
24
|
+
/**
|
|
25
|
+
* Permission level for this tool
|
|
26
|
+
*/
|
|
27
|
+
level: PermissionLevel;
|
|
28
|
+
/**
|
|
29
|
+
* Human-readable description of why permission is needed
|
|
30
|
+
*/
|
|
31
|
+
description?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Tags for grouping permissions
|
|
34
|
+
*/
|
|
35
|
+
tags?: string[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Permission request passed to the handler
|
|
39
|
+
*/
|
|
40
|
+
export interface PermissionRequest {
|
|
41
|
+
/**
|
|
42
|
+
* Name of the tool requesting permission
|
|
43
|
+
*/
|
|
44
|
+
toolName: string;
|
|
45
|
+
/**
|
|
46
|
+
* Input arguments for the tool
|
|
47
|
+
*/
|
|
48
|
+
input: Record<string, unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* Permission level that triggered the request
|
|
51
|
+
*/
|
|
52
|
+
level: PermissionLevel;
|
|
53
|
+
/**
|
|
54
|
+
* Description of why permission is needed
|
|
55
|
+
*/
|
|
56
|
+
description?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Formatted preview of what the tool will do
|
|
59
|
+
*/
|
|
60
|
+
preview?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Result of a permission check
|
|
64
|
+
*/
|
|
65
|
+
export interface PermissionCheckResult {
|
|
66
|
+
/**
|
|
67
|
+
* Whether execution is allowed
|
|
68
|
+
*/
|
|
69
|
+
allowed: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* The permission level that applied
|
|
72
|
+
*/
|
|
73
|
+
level: PermissionLevel;
|
|
74
|
+
/**
|
|
75
|
+
* Whether user confirmation was required
|
|
76
|
+
*/
|
|
77
|
+
askedUser: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* The tool permission rule that matched (if any)
|
|
80
|
+
*/
|
|
81
|
+
rule?: ToolPermission;
|
|
82
|
+
/**
|
|
83
|
+
* Reason for denial (if not allowed)
|
|
84
|
+
*/
|
|
85
|
+
reason?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Handler called when permission is needed
|
|
89
|
+
*
|
|
90
|
+
* @param request - Information about the permission request
|
|
91
|
+
* @returns true to allow execution, false to deny
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const handler: PermissionHandler = async (request) => {
|
|
96
|
+
* // Show UI prompt to user
|
|
97
|
+
* const allowed = await showConfirmDialog(
|
|
98
|
+
* `Allow ${request.toolName}?`,
|
|
99
|
+
* request.description
|
|
100
|
+
* );
|
|
101
|
+
* return allowed;
|
|
102
|
+
* };
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export type PermissionHandler = (request: PermissionRequest) => boolean | Promise<boolean>;
|
|
106
|
+
/**
|
|
107
|
+
* Preview generator for permission requests
|
|
108
|
+
*
|
|
109
|
+
* @param toolName - Name of the tool
|
|
110
|
+
* @param input - Tool input arguments
|
|
111
|
+
* @returns Human-readable preview of the operation
|
|
112
|
+
*/
|
|
113
|
+
export type PreviewGenerator = (toolName: string, input: Record<string, unknown>) => string | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Configuration for the PermissionManager
|
|
116
|
+
*/
|
|
117
|
+
export interface PermissionManagerOptions {
|
|
118
|
+
/**
|
|
119
|
+
* Enable permission checking (default: true)
|
|
120
|
+
*/
|
|
121
|
+
enabled?: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Default permission level for tools not explicitly configured
|
|
124
|
+
* @default 'always'
|
|
125
|
+
*/
|
|
126
|
+
defaultLevel?: PermissionLevel;
|
|
127
|
+
/**
|
|
128
|
+
* Handler called when permission is needed (for 'session' and 'once' levels)
|
|
129
|
+
*/
|
|
130
|
+
onPermissionRequest?: PermissionHandler;
|
|
131
|
+
/**
|
|
132
|
+
* Tool-specific permission rules
|
|
133
|
+
*/
|
|
134
|
+
rules?: ToolPermission[];
|
|
135
|
+
/**
|
|
136
|
+
* Custom preview generator for permission requests
|
|
137
|
+
*/
|
|
138
|
+
previewGenerator?: PreviewGenerator;
|
|
139
|
+
/**
|
|
140
|
+
* Whether to include default permission rules for dangerous tools
|
|
141
|
+
* @default false
|
|
142
|
+
*/
|
|
143
|
+
includeDefaults?: boolean;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Event types for permission operations
|
|
147
|
+
*/
|
|
148
|
+
export type PermissionEventType = 'permission:granted' | 'permission:denied' | 'permission:asked' | 'permission:session_granted';
|
|
149
|
+
/**
|
|
150
|
+
* Permission event payload
|
|
151
|
+
*/
|
|
152
|
+
export interface PermissionEvent {
|
|
153
|
+
type: PermissionEventType;
|
|
154
|
+
toolName: string;
|
|
155
|
+
level: PermissionLevel;
|
|
156
|
+
input?: Record<string, unknown>;
|
|
157
|
+
rule?: ToolPermission;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Event handler for permission events
|
|
161
|
+
*/
|
|
162
|
+
export type PermissionEventHandler = (event: PermissionEvent) => void;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClaudeProvider - Anthropic Claude API implementation
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* const provider = new ClaudeProvider({
|
|
7
|
+
* apiKey: process.env.ANTHROPIC_API_KEY,
|
|
8
|
+
* });
|
|
9
|
+
*
|
|
10
|
+
* const agent = new Agent({ provider });
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
import type { LLMProvider, Message, ChatOptions, StreamChunk } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Configuration for ClaudeProvider
|
|
16
|
+
*/
|
|
17
|
+
export interface ClaudeProviderConfig {
|
|
18
|
+
/**
|
|
19
|
+
* Anthropic API key
|
|
20
|
+
*/
|
|
21
|
+
apiKey: string;
|
|
22
|
+
/**
|
|
23
|
+
* Default model to use
|
|
24
|
+
* @default 'claude-sonnet-4-20250514'
|
|
25
|
+
*/
|
|
26
|
+
model?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Base URL for API (useful for proxies)
|
|
29
|
+
*/
|
|
30
|
+
baseURL?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Default max tokens
|
|
33
|
+
* @default 4096
|
|
34
|
+
*/
|
|
35
|
+
maxTokens?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* ClaudeProvider implements LLMProvider for Anthropic's Claude API
|
|
39
|
+
*/
|
|
40
|
+
export declare class ClaudeProvider implements LLMProvider {
|
|
41
|
+
readonly name = "claude";
|
|
42
|
+
private readonly client;
|
|
43
|
+
private readonly defaultModel;
|
|
44
|
+
private readonly defaultMaxTokens;
|
|
45
|
+
constructor(config: ClaudeProviderConfig);
|
|
46
|
+
/**
|
|
47
|
+
* Send messages and stream the response
|
|
48
|
+
*/
|
|
49
|
+
chat(messages: Message[], options?: ChatOptions): AsyncIterable<StreamChunk>;
|
|
50
|
+
/**
|
|
51
|
+
* Count tokens in messages (not yet available in SDK v0.30)
|
|
52
|
+
*
|
|
53
|
+
* Note: Token counting API is available via Anthropic's beta endpoints
|
|
54
|
+
* but not yet exposed in the stable SDK. For now, this provides an
|
|
55
|
+
* approximation based on character count.
|
|
56
|
+
*/
|
|
57
|
+
countTokens(messages: Message[]): Promise<number>;
|
|
58
|
+
/**
|
|
59
|
+
* Convert our Message format to Anthropic's format
|
|
60
|
+
*/
|
|
61
|
+
private convertMessages;
|
|
62
|
+
/**
|
|
63
|
+
* Convert content to Anthropic's content block format
|
|
64
|
+
*/
|
|
65
|
+
private convertContent;
|
|
66
|
+
/**
|
|
67
|
+
* Convert our ToolDefinition to Anthropic's Tool format
|
|
68
|
+
*/
|
|
69
|
+
private convertTools;
|
|
70
|
+
/**
|
|
71
|
+
* Convert thinking config to Anthropic API format
|
|
72
|
+
*/
|
|
73
|
+
private convertThinking;
|
|
74
|
+
/**
|
|
75
|
+
* Process a stream event into StreamChunks
|
|
76
|
+
*/
|
|
77
|
+
private processEvent;
|
|
78
|
+
/**
|
|
79
|
+
* Process a content block delta event
|
|
80
|
+
*/
|
|
81
|
+
private processDelta;
|
|
82
|
+
/**
|
|
83
|
+
* Map Anthropic SDK errors to ProviderError
|
|
84
|
+
*/
|
|
85
|
+
private mapError;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Create a ClaudeProvider with API key from environment
|
|
89
|
+
*/
|
|
90
|
+
export declare function createClaudeProvider(config?: Partial<ClaudeProviderConfig>): ClaudeProvider;
|