codebot-ai 1.6.0 → 1.7.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/dist/agent.d.ts +12 -0
- package/dist/agent.js +51 -4
- package/dist/audit.d.ts +31 -9
- package/dist/audit.js +85 -11
- package/dist/cli.js +181 -26
- package/dist/policy.d.ts +123 -0
- package/dist/policy.js +418 -0
- package/dist/sandbox.d.ts +65 -0
- package/dist/sandbox.js +214 -0
- package/dist/telemetry.d.ts +73 -0
- package/dist/telemetry.js +286 -0
- package/dist/tools/execute.js +29 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -35,6 +35,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.main = main;
|
|
37
37
|
const readline = __importStar(require("readline"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
38
40
|
const agent_1 = require("./agent");
|
|
39
41
|
const openai_1 = require("./providers/openai");
|
|
40
42
|
const anthropic_1 = require("./providers/anthropic");
|
|
@@ -44,9 +46,10 @@ const setup_1 = require("./setup");
|
|
|
44
46
|
const banner_1 = require("./banner");
|
|
45
47
|
const tools_1 = require("./tools");
|
|
46
48
|
const scheduler_1 = require("./scheduler");
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
const audit_1 = require("./audit");
|
|
50
|
+
const policy_1 = require("./policy");
|
|
51
|
+
const sandbox_1 = require("./sandbox");
|
|
52
|
+
const VERSION = '1.7.0';
|
|
50
53
|
const C = {
|
|
51
54
|
reset: '\x1b[0m',
|
|
52
55
|
bold: '\x1b[1m',
|
|
@@ -86,12 +89,89 @@ async function main() {
|
|
|
86
89
|
await (0, setup_1.runSetup)();
|
|
87
90
|
return;
|
|
88
91
|
}
|
|
92
|
+
// ── v1.7.0: New standalone commands ──
|
|
93
|
+
// --init-policy: Generate default policy file
|
|
94
|
+
if (args['init-policy']) {
|
|
95
|
+
const policyPath = path.join(process.cwd(), '.codebot', 'policy.json');
|
|
96
|
+
const policyDir = path.dirname(policyPath);
|
|
97
|
+
if (!fs.existsSync(policyDir))
|
|
98
|
+
fs.mkdirSync(policyDir, { recursive: true });
|
|
99
|
+
if (fs.existsSync(policyPath)) {
|
|
100
|
+
console.log(c(`Policy file already exists at ${policyPath}`, 'yellow'));
|
|
101
|
+
console.log(c('Delete it first if you want to regenerate.', 'dim'));
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
fs.writeFileSync(policyPath, (0, policy_1.generateDefaultPolicyFile)(), 'utf-8');
|
|
105
|
+
console.log(c(`Created default policy at ${policyPath}`, 'green'));
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// --verify-audit: Verify audit chain integrity
|
|
110
|
+
if (args['verify-audit']) {
|
|
111
|
+
const logger = new audit_1.AuditLogger();
|
|
112
|
+
const sessionId = typeof args['verify-audit'] === 'string' ? args['verify-audit'] : undefined;
|
|
113
|
+
if (sessionId) {
|
|
114
|
+
const entries = logger.query({ sessionId });
|
|
115
|
+
if (entries.length === 0) {
|
|
116
|
+
console.log(c(`No audit entries found for session ${sessionId}`, 'yellow'));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const result = audit_1.AuditLogger.verify(entries);
|
|
120
|
+
if (result.valid) {
|
|
121
|
+
console.log(c(`Audit chain valid (${result.entriesChecked} entries checked)`, 'green'));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
console.log(c(`Audit chain INVALID at sequence ${result.firstInvalidAt}`, 'red'));
|
|
125
|
+
console.log(c(`Reason: ${result.reason}`, 'red'));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// Verify all entries from today's log
|
|
130
|
+
const entries = logger.query();
|
|
131
|
+
if (entries.length === 0) {
|
|
132
|
+
console.log(c('No audit entries found.', 'yellow'));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
// Group by session and verify each
|
|
136
|
+
const sessions = new Map();
|
|
137
|
+
for (const e of entries) {
|
|
138
|
+
if (!sessions.has(e.sessionId))
|
|
139
|
+
sessions.set(e.sessionId, []);
|
|
140
|
+
sessions.get(e.sessionId).push(e);
|
|
141
|
+
}
|
|
142
|
+
let allValid = true;
|
|
143
|
+
for (const [sid, sessionEntries] of sessions) {
|
|
144
|
+
const result = audit_1.AuditLogger.verify(sessionEntries);
|
|
145
|
+
const shortId = sid.substring(0, 12);
|
|
146
|
+
if (result.valid) {
|
|
147
|
+
console.log(c(` ${shortId} ${result.entriesChecked} entries valid`, 'green'));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
console.log(c(` ${shortId} INVALID at seq ${result.firstInvalidAt}: ${result.reason}`, 'red'));
|
|
151
|
+
allValid = false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
console.log(allValid
|
|
155
|
+
? c(`\nAll ${sessions.size} session chains verified.`, 'green')
|
|
156
|
+
: c(`\nSome chains are invalid — possible tampering detected.`, 'red'));
|
|
157
|
+
}
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// --sandbox-info: Show sandbox status
|
|
161
|
+
if (args['sandbox-info']) {
|
|
162
|
+
const info = (0, sandbox_1.getSandboxInfo)();
|
|
163
|
+
console.log(c('Sandbox Status:', 'bold'));
|
|
164
|
+
console.log(` Docker: ${info.available ? c('available', 'green') : c('not available', 'yellow')}`);
|
|
165
|
+
console.log(` Image: ${info.image}`);
|
|
166
|
+
console.log(` CPU: ${info.defaults.cpus} cores max`);
|
|
167
|
+
console.log(` Memory: ${info.defaults.memoryMb}MB max`);
|
|
168
|
+
console.log(` Network: ${info.defaults.network ? 'enabled' : 'disabled'} by default`);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
89
171
|
// First run: auto-launch setup if nothing is configured
|
|
90
172
|
if ((0, setup_1.isFirstRun)() && process.stdin.isTTY && !args.message) {
|
|
91
173
|
console.log(c('Welcome! No configuration found — launching setup...', 'cyan'));
|
|
92
174
|
await (0, setup_1.runSetup)();
|
|
93
|
-
// If setup saved a config, continue to main flow
|
|
94
|
-
// Otherwise exit
|
|
95
175
|
if ((0, setup_1.isFirstRun)())
|
|
96
176
|
return;
|
|
97
177
|
}
|
|
@@ -118,6 +198,7 @@ async function main() {
|
|
|
118
198
|
const agent = new agent_1.Agent({
|
|
119
199
|
provider,
|
|
120
200
|
model: config.model,
|
|
201
|
+
providerName: config.provider,
|
|
121
202
|
maxIterations: config.maxIterations,
|
|
122
203
|
autoApprove: config.autoApprove,
|
|
123
204
|
onMessage: (msg) => session.save(msg),
|
|
@@ -133,6 +214,7 @@ async function main() {
|
|
|
133
214
|
// Non-interactive: single message from CLI args
|
|
134
215
|
if (typeof args.message === 'string') {
|
|
135
216
|
await runOnce(agent, args.message);
|
|
217
|
+
printSessionSummary(agent);
|
|
136
218
|
return;
|
|
137
219
|
}
|
|
138
220
|
// Non-interactive: piped stdin
|
|
@@ -140,6 +222,7 @@ async function main() {
|
|
|
140
222
|
const input = await readStdin();
|
|
141
223
|
if (input.trim()) {
|
|
142
224
|
await runOnce(agent, input.trim());
|
|
225
|
+
printSessionSummary(agent);
|
|
143
226
|
}
|
|
144
227
|
return;
|
|
145
228
|
}
|
|
@@ -151,6 +234,22 @@ async function main() {
|
|
|
151
234
|
// Cleanup scheduler on exit
|
|
152
235
|
scheduler.stop();
|
|
153
236
|
}
|
|
237
|
+
/** Print session summary with tokens, cost, tool calls, files modified */
|
|
238
|
+
function printSessionSummary(agent) {
|
|
239
|
+
const tracker = agent.getTokenTracker();
|
|
240
|
+
tracker.saveUsage();
|
|
241
|
+
const summary = tracker.getSummary();
|
|
242
|
+
const duration = (new Date(summary.endTime).getTime() - new Date(summary.startTime).getTime()) / 1000;
|
|
243
|
+
const mins = Math.floor(duration / 60);
|
|
244
|
+
const secs = Math.floor(duration % 60);
|
|
245
|
+
console.log(c('\n── Session Summary ──', 'dim'));
|
|
246
|
+
console.log(` Duration: ${mins}m ${secs}s`);
|
|
247
|
+
console.log(` Model: ${summary.model} via ${summary.provider}`);
|
|
248
|
+
console.log(` Tokens: ${summary.totalInputTokens.toLocaleString()} in / ${summary.totalOutputTokens.toLocaleString()} out (${tracker.formatCost()})`);
|
|
249
|
+
console.log(` Requests: ${summary.requestCount}`);
|
|
250
|
+
console.log(` Tools: ${summary.toolCalls} calls`);
|
|
251
|
+
console.log(` Files: ${summary.filesModified} modified`);
|
|
252
|
+
}
|
|
154
253
|
function createProvider(config) {
|
|
155
254
|
if (config.provider === 'anthropic') {
|
|
156
255
|
return new anthropic_1.AnthropicProvider({
|
|
@@ -159,7 +258,6 @@ function createProvider(config) {
|
|
|
159
258
|
model: config.model,
|
|
160
259
|
});
|
|
161
260
|
}
|
|
162
|
-
// All other providers use OpenAI-compatible format
|
|
163
261
|
return new openai_1.OpenAIProvider({
|
|
164
262
|
baseUrl: config.baseUrl,
|
|
165
263
|
apiKey: config.apiKey,
|
|
@@ -186,7 +284,7 @@ async function repl(agent, config, session) {
|
|
|
186
284
|
}
|
|
187
285
|
try {
|
|
188
286
|
for await (const event of agent.run(input)) {
|
|
189
|
-
renderEvent(event);
|
|
287
|
+
renderEvent(event, agent);
|
|
190
288
|
}
|
|
191
289
|
}
|
|
192
290
|
catch (err) {
|
|
@@ -197,18 +295,19 @@ async function repl(agent, config, session) {
|
|
|
197
295
|
rl.prompt();
|
|
198
296
|
});
|
|
199
297
|
rl.on('close', () => {
|
|
298
|
+
printSessionSummary(agent);
|
|
200
299
|
console.log(c('\nBye!', 'dim'));
|
|
201
300
|
process.exit(0);
|
|
202
301
|
});
|
|
203
302
|
}
|
|
204
303
|
async function runOnce(agent, message) {
|
|
205
304
|
for await (const event of agent.run(message)) {
|
|
206
|
-
renderEvent(event);
|
|
305
|
+
renderEvent(event, agent);
|
|
207
306
|
}
|
|
208
307
|
console.log();
|
|
209
308
|
}
|
|
210
309
|
let isThinking = false;
|
|
211
|
-
function renderEvent(event) {
|
|
310
|
+
function renderEvent(event, agent) {
|
|
212
311
|
switch (event.type) {
|
|
213
312
|
case 'thinking':
|
|
214
313
|
if (!isThinking) {
|
|
@@ -248,20 +347,15 @@ function renderEvent(event) {
|
|
|
248
347
|
}
|
|
249
348
|
break;
|
|
250
349
|
case 'usage':
|
|
251
|
-
if (event.usage) {
|
|
252
|
-
|
|
253
|
-
sessionTokens.input += event.usage.inputTokens;
|
|
254
|
-
if (event.usage.outputTokens)
|
|
255
|
-
sessionTokens.output += event.usage.outputTokens;
|
|
256
|
-
if (event.usage.totalTokens)
|
|
257
|
-
sessionTokens.total += event.usage.totalTokens;
|
|
350
|
+
if (event.usage && agent) {
|
|
351
|
+
const tracker = agent.getTokenTracker();
|
|
258
352
|
const parts = [];
|
|
259
353
|
if (event.usage.inputTokens)
|
|
260
354
|
parts.push(`in: ${event.usage.inputTokens}`);
|
|
261
355
|
if (event.usage.outputTokens)
|
|
262
356
|
parts.push(`out: ${event.usage.outputTokens}`);
|
|
263
357
|
if (parts.length > 0) {
|
|
264
|
-
console.log(c(` [${parts.join(', ')} tokens]`, 'dim'));
|
|
358
|
+
console.log(c(` [${parts.join(', ')} tokens | ${tracker.formatCost()}]`, 'dim'));
|
|
265
359
|
}
|
|
266
360
|
}
|
|
267
361
|
break;
|
|
@@ -306,7 +400,10 @@ function handleSlashCommand(input, agent, config) {
|
|
|
306
400
|
/auto Toggle autonomous mode
|
|
307
401
|
/routines List scheduled routines
|
|
308
402
|
/undo Undo last file edit (/undo [path])
|
|
309
|
-
/usage Show token usage for this session
|
|
403
|
+
/usage Show token usage & cost for this session
|
|
404
|
+
/cost Show running cost
|
|
405
|
+
/policy Show current security policy
|
|
406
|
+
/audit Verify audit chain for this session
|
|
310
407
|
/config Show current config
|
|
311
408
|
/quit Exit`);
|
|
312
409
|
break;
|
|
@@ -365,10 +462,41 @@ function handleSlashCommand(input, agent, config) {
|
|
|
365
462
|
break;
|
|
366
463
|
}
|
|
367
464
|
case '/usage': {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
console.log(
|
|
371
|
-
console.log(`
|
|
465
|
+
const tracker = agent.getTokenTracker();
|
|
466
|
+
const summary = tracker.getSummary();
|
|
467
|
+
console.log(c('\nSession Usage:', 'bold'));
|
|
468
|
+
console.log(` Input: ${summary.totalInputTokens.toLocaleString()} tokens`);
|
|
469
|
+
console.log(` Output: ${summary.totalOutputTokens.toLocaleString()} tokens`);
|
|
470
|
+
console.log(` Cost: ${tracker.formatCost()}`);
|
|
471
|
+
console.log(` Requests: ${summary.requestCount}`);
|
|
472
|
+
console.log(` Tools: ${summary.toolCalls} calls`);
|
|
473
|
+
console.log(` Files: ${summary.filesModified} modified`);
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
case '/cost': {
|
|
477
|
+
const tracker = agent.getTokenTracker();
|
|
478
|
+
console.log(c(` ${tracker.formatStatusLine()}`, 'dim'));
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
case '/policy': {
|
|
482
|
+
const policy = agent.getPolicyEnforcer().getPolicy();
|
|
483
|
+
console.log(c('\nCurrent Policy:', 'bold'));
|
|
484
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
case '/audit': {
|
|
488
|
+
const auditLogger = agent.getAuditLogger();
|
|
489
|
+
const result = auditLogger.verifySession();
|
|
490
|
+
if (result.entriesChecked === 0) {
|
|
491
|
+
console.log(c('No audit entries yet.', 'dim'));
|
|
492
|
+
}
|
|
493
|
+
else if (result.valid) {
|
|
494
|
+
console.log(c(`Audit chain valid (${result.entriesChecked} entries)`, 'green'));
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
console.log(c(`Audit chain INVALID at sequence ${result.firstInvalidAt}`, 'red'));
|
|
498
|
+
console.log(c(` ${result.reason}`, 'red'));
|
|
499
|
+
}
|
|
372
500
|
break;
|
|
373
501
|
}
|
|
374
502
|
case '/routines': {
|
|
@@ -409,7 +537,6 @@ function showModels() {
|
|
|
409
537
|
}
|
|
410
538
|
}
|
|
411
539
|
async function resolveConfig(args) {
|
|
412
|
-
// Load saved config (CLI args override saved config)
|
|
413
540
|
const saved = (0, setup_1.loadConfig)();
|
|
414
541
|
const model = args.model || process.env.CODEBOT_MODEL || saved.model || 'qwen2.5-coder:32b';
|
|
415
542
|
const detected = (0, registry_1.detectProvider)(model);
|
|
@@ -421,7 +548,6 @@ async function resolveConfig(args) {
|
|
|
421
548
|
maxIterations: parseInt(args['max-iterations'] || String(saved.maxIterations || 50), 10),
|
|
422
549
|
autoApprove: !!args['auto-approve'] || !!args.autonomous || !!args.auto || !!saved.autoApprove,
|
|
423
550
|
};
|
|
424
|
-
// Auto-resolve base URL and API key from provider
|
|
425
551
|
if (!config.baseUrl || !config.apiKey) {
|
|
426
552
|
const defaults = registry_1.PROVIDER_DEFAULTS[config.provider];
|
|
427
553
|
if (defaults) {
|
|
@@ -431,14 +557,12 @@ async function resolveConfig(args) {
|
|
|
431
557
|
config.apiKey = process.env[defaults.envKey] || process.env.CODEBOT_API_KEY || '';
|
|
432
558
|
}
|
|
433
559
|
}
|
|
434
|
-
// Fallback: try saved config API key, then generic env vars
|
|
435
560
|
if (!config.apiKey && saved.apiKey) {
|
|
436
561
|
config.apiKey = saved.apiKey;
|
|
437
562
|
}
|
|
438
563
|
if (!config.apiKey) {
|
|
439
564
|
config.apiKey = process.env.CODEBOT_API_KEY || process.env.OPENAI_API_KEY || '';
|
|
440
565
|
}
|
|
441
|
-
// If still no base URL, auto-detect local provider
|
|
442
566
|
if (!config.baseUrl) {
|
|
443
567
|
config.baseUrl = await autoDetectProvider();
|
|
444
568
|
}
|
|
@@ -494,6 +618,25 @@ function parseArgs(argv) {
|
|
|
494
618
|
result.setup = true;
|
|
495
619
|
continue;
|
|
496
620
|
}
|
|
621
|
+
if (arg === '--init-policy') {
|
|
622
|
+
result['init-policy'] = true;
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
if (arg === '--sandbox-info') {
|
|
626
|
+
result['sandbox-info'] = true;
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
if (arg === '--verify-audit') {
|
|
630
|
+
const next = argv[i + 1];
|
|
631
|
+
if (next && !next.startsWith('--')) {
|
|
632
|
+
result['verify-audit'] = next;
|
|
633
|
+
i++;
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
result['verify-audit'] = true;
|
|
637
|
+
}
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
497
640
|
if (arg.startsWith('--')) {
|
|
498
641
|
const key = arg.slice(2);
|
|
499
642
|
const next = argv[i + 1];
|
|
@@ -540,9 +683,15 @@ ${c('Options:', 'bold')}
|
|
|
540
683
|
--resume <id> Resume a previous session by ID
|
|
541
684
|
--continue, -c Resume the most recent session
|
|
542
685
|
--max-iterations <n> Max agent loop iterations (default: 50)
|
|
686
|
+
--sandbox <mode> Execution sandbox: docker, host, auto (default: auto)
|
|
543
687
|
-h, --help Show this help
|
|
544
688
|
-v, --version Show version
|
|
545
689
|
|
|
690
|
+
${c('Security & Policy:', 'bold')}
|
|
691
|
+
--init-policy Generate default .codebot/policy.json
|
|
692
|
+
--verify-audit [id] Verify audit log hash chain integrity
|
|
693
|
+
--sandbox-info Show Docker sandbox status
|
|
694
|
+
|
|
546
695
|
${c('Supported Providers:', 'bold')}
|
|
547
696
|
Local: Ollama, LM Studio, vLLM (auto-detected)
|
|
548
697
|
Anthropic: Claude Opus/Sonnet/Haiku (ANTHROPIC_API_KEY)
|
|
@@ -560,6 +709,8 @@ ${c('Examples:', 'bold')}
|
|
|
560
709
|
codebot --model deepseek-chat Uses DeepSeek API
|
|
561
710
|
codebot --model qwen2.5-coder:32b Uses local Ollama
|
|
562
711
|
codebot --autonomous "refactor src/" Full auto, no prompts
|
|
712
|
+
codebot --init-policy Create security policy
|
|
713
|
+
codebot --verify-audit Check audit integrity
|
|
563
714
|
|
|
564
715
|
${c('Interactive Commands:', 'bold')}
|
|
565
716
|
/help Show commands
|
|
@@ -569,6 +720,10 @@ ${c('Interactive Commands:', 'bold')}
|
|
|
569
720
|
/auto Toggle autonomous mode
|
|
570
721
|
/clear Clear conversation
|
|
571
722
|
/compact Force context compaction
|
|
723
|
+
/usage Show token usage & cost
|
|
724
|
+
/cost Show running cost
|
|
725
|
+
/policy Show security policy
|
|
726
|
+
/audit Verify session audit chain
|
|
572
727
|
/config Show configuration
|
|
573
728
|
/quit Exit`);
|
|
574
729
|
}
|
package/dist/policy.d.ts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy Engine for CodeBot v1.7.0
|
|
3
|
+
*
|
|
4
|
+
* Loads, validates, and enforces declarative security policies.
|
|
5
|
+
* Policy files: .codebot/policy.json (project) + ~/.codebot/policy.json (global)
|
|
6
|
+
* Project policy overrides global policy where specified.
|
|
7
|
+
*/
|
|
8
|
+
export interface PolicyExecution {
|
|
9
|
+
sandbox?: 'docker' | 'host' | 'auto';
|
|
10
|
+
network?: boolean;
|
|
11
|
+
timeout_seconds?: number;
|
|
12
|
+
max_memory_mb?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface PolicyFilesystem {
|
|
15
|
+
writable_paths?: string[];
|
|
16
|
+
read_only_paths?: string[];
|
|
17
|
+
denied_paths?: string[];
|
|
18
|
+
allow_outside_project?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface PolicyToolPermission {
|
|
21
|
+
[toolName: string]: 'auto' | 'prompt' | 'always-ask';
|
|
22
|
+
}
|
|
23
|
+
export interface PolicyTools {
|
|
24
|
+
enabled?: string[];
|
|
25
|
+
disabled?: string[];
|
|
26
|
+
permissions?: PolicyToolPermission;
|
|
27
|
+
}
|
|
28
|
+
export interface PolicySecrets {
|
|
29
|
+
block_on_detect?: boolean;
|
|
30
|
+
scan_on_write?: boolean;
|
|
31
|
+
allowed_patterns?: string[];
|
|
32
|
+
}
|
|
33
|
+
export interface PolicyGit {
|
|
34
|
+
always_branch?: boolean;
|
|
35
|
+
branch_prefix?: string;
|
|
36
|
+
require_tests_before_commit?: boolean;
|
|
37
|
+
never_push_main?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface PolicyMcp {
|
|
40
|
+
allowed_servers?: string[];
|
|
41
|
+
blocked_servers?: string[];
|
|
42
|
+
}
|
|
43
|
+
export interface PolicyLimits {
|
|
44
|
+
max_iterations?: number;
|
|
45
|
+
max_file_size_kb?: number;
|
|
46
|
+
max_files_per_operation?: number;
|
|
47
|
+
cost_limit_usd?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface Policy {
|
|
50
|
+
version?: string;
|
|
51
|
+
execution?: PolicyExecution;
|
|
52
|
+
filesystem?: PolicyFilesystem;
|
|
53
|
+
tools?: PolicyTools;
|
|
54
|
+
secrets?: PolicySecrets;
|
|
55
|
+
git?: PolicyGit;
|
|
56
|
+
mcp?: PolicyMcp;
|
|
57
|
+
limits?: PolicyLimits;
|
|
58
|
+
}
|
|
59
|
+
export declare const DEFAULT_POLICY: Required<Policy>;
|
|
60
|
+
/**
|
|
61
|
+
* Load and merge policies from project + global locations.
|
|
62
|
+
* Project policy overrides global where specified.
|
|
63
|
+
*/
|
|
64
|
+
export declare function loadPolicy(projectRoot?: string): Policy;
|
|
65
|
+
export declare class PolicyEnforcer {
|
|
66
|
+
private policy;
|
|
67
|
+
private projectRoot;
|
|
68
|
+
constructor(policy?: Policy, projectRoot?: string);
|
|
69
|
+
getPolicy(): Policy;
|
|
70
|
+
/** Check if a tool is enabled by policy. Returns { allowed, reason }. */
|
|
71
|
+
isToolAllowed(toolName: string): {
|
|
72
|
+
allowed: boolean;
|
|
73
|
+
reason?: string;
|
|
74
|
+
};
|
|
75
|
+
/** Get the permission level for a tool (policy override or null for default). */
|
|
76
|
+
getToolPermission(toolName: string): 'auto' | 'prompt' | 'always-ask' | null;
|
|
77
|
+
/** Check if a path is writable according to policy. */
|
|
78
|
+
isPathWritable(filePath: string): {
|
|
79
|
+
allowed: boolean;
|
|
80
|
+
reason?: string;
|
|
81
|
+
};
|
|
82
|
+
/** Get sandbox mode. */
|
|
83
|
+
getSandboxMode(): 'docker' | 'host' | 'auto';
|
|
84
|
+
/** Check if network is allowed for executed commands. */
|
|
85
|
+
isNetworkAllowed(): boolean;
|
|
86
|
+
/** Get execution timeout in milliseconds. */
|
|
87
|
+
getTimeoutMs(): number;
|
|
88
|
+
/** Get max memory in MB for sandbox. */
|
|
89
|
+
getMaxMemoryMb(): number;
|
|
90
|
+
/** Check if agent should always work on a branch. */
|
|
91
|
+
shouldAlwaysBranch(): boolean;
|
|
92
|
+
/** Get branch prefix for auto-created branches. */
|
|
93
|
+
getBranchPrefix(): string;
|
|
94
|
+
/** Check if pushing to main/master is blocked. */
|
|
95
|
+
isMainPushBlocked(): boolean;
|
|
96
|
+
/** Should secrets block writes (vs just warn)? */
|
|
97
|
+
shouldBlockSecrets(): boolean;
|
|
98
|
+
/** Should scan for secrets on write? */
|
|
99
|
+
shouldScanSecrets(): boolean;
|
|
100
|
+
/** Check if an MCP server is allowed. */
|
|
101
|
+
isMcpServerAllowed(serverName: string): {
|
|
102
|
+
allowed: boolean;
|
|
103
|
+
reason?: string;
|
|
104
|
+
};
|
|
105
|
+
/** Get max iterations for the agent loop. */
|
|
106
|
+
getMaxIterations(): number;
|
|
107
|
+
/** Get max file size in bytes for write operations. */
|
|
108
|
+
getMaxFileSizeBytes(): number;
|
|
109
|
+
/** Get cost limit in USD (0 = no limit). */
|
|
110
|
+
getCostLimitUsd(): number;
|
|
111
|
+
/**
|
|
112
|
+
* Simple glob-like pattern matching:
|
|
113
|
+
* - `*` matches any single path component
|
|
114
|
+
* - `**` matches any number of path components
|
|
115
|
+
* - `.env` matches exact filename
|
|
116
|
+
*/
|
|
117
|
+
private matchesPattern;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Generate a default policy file content for `codebot --init-policy`.
|
|
121
|
+
*/
|
|
122
|
+
export declare function generateDefaultPolicyFile(): string;
|
|
123
|
+
//# sourceMappingURL=policy.d.ts.map
|