@malcomsonbrothers/claude-code-permission-hook 0.1.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/index.js ADDED
@@ -0,0 +1,529 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { readFileSync, writeFileSync, existsSync } from "fs";
4
+ import { join } from "path";
5
+ import { homedir } from "os";
6
+ import chalk from "chalk";
7
+ import inquirer from "inquirer";
8
+ import { handlePermissionRequest } from "./permission-handler.js";
9
+ import { loadConfig, saveConfig, getConfigPath, getConfigDir, } from "./config.js";
10
+ import { clearCache, clearCacheByDecision, clearCacheByKey, clearCacheByGrep, listCacheEntries, getCacheStats, } from "./cache.js";
11
+ import { DEFAULT_SYSTEM_PROMPT } from "./types.js";
12
+ import { resolveProjectRoot } from "./project.js";
13
+ const program = new Command();
14
+ program
15
+ .name("cc-approve")
16
+ .description("Claude Code Permission Hook - Intelligent auto-approval for Claude Code")
17
+ .version("0.1.0");
18
+ // Main permission handler command
19
+ program
20
+ .command("permission")
21
+ .description("Handle a PermissionRequest hook (reads from stdin)")
22
+ .action(async () => {
23
+ try {
24
+ // Read input from stdin
25
+ const chunks = [];
26
+ for await (const chunk of process.stdin) {
27
+ chunks.push(chunk);
28
+ }
29
+ const rawInput = Buffer.concat(chunks).toString("utf-8");
30
+ const input = JSON.parse(rawInput);
31
+ // Process the permission request
32
+ const result = await handlePermissionRequest(input);
33
+ // Handle passthrough: null means exit 0 with no output
34
+ // This triggers Claude Code's native permission dialog
35
+ if (result === null) {
36
+ process.exit(0);
37
+ }
38
+ // Output result to stdout for allow/deny
39
+ console.log(JSON.stringify(result));
40
+ }
41
+ catch (error) {
42
+ // On any error, output a deny response
43
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
44
+ const denyResponse = {
45
+ hookSpecificOutput: {
46
+ hookEventName: "PermissionRequest",
47
+ decision: {
48
+ behavior: "deny",
49
+ message: `Hook error: ${errorMessage}`,
50
+ },
51
+ },
52
+ };
53
+ console.log(JSON.stringify(denyResponse));
54
+ process.exit(1);
55
+ }
56
+ });
57
+ // Install command
58
+ program
59
+ .command("install")
60
+ .description("Install the hook into Claude Code settings")
61
+ .action(async () => {
62
+ // Welcome message
63
+ console.log(chalk.cyan("╔══════════════════════════════════════════════════════════════╗"));
64
+ console.log(chalk.cyan("║ Claude Code Permission Hook - Auto-approval for Claude ║"));
65
+ console.log(chalk.cyan("╚══════════════════════════════════════════════════════════════╝"));
66
+ console.log();
67
+ console.log("This hook automatically approves safe development operations");
68
+ console.log("and blocks destructive commands.");
69
+ console.log();
70
+ // Provider selection
71
+ const { provider } = await inquirer.prompt([
72
+ {
73
+ type: "list",
74
+ name: "provider",
75
+ message: "Choose your LLM provider:",
76
+ choices: [
77
+ {
78
+ name: "OpenRouter (recommended - lowest latency)",
79
+ value: "openrouter",
80
+ },
81
+ { name: "OpenAI", value: "openai" },
82
+ { name: "Anthropic", value: "anthropic" },
83
+ ],
84
+ },
85
+ ]);
86
+ // API key input
87
+ const { apiKey } = await inquirer.prompt([
88
+ {
89
+ type: "password",
90
+ name: "apiKey",
91
+ message: "Enter your API key:",
92
+ mask: "X",
93
+ validate: (input) => {
94
+ if (!input || input.trim() === "") {
95
+ return "API key is required";
96
+ }
97
+ return true;
98
+ },
99
+ },
100
+ ]);
101
+ // Set provider-specific defaults
102
+ let baseUrl;
103
+ let model = "gpt-4o-mini";
104
+ if (provider === "openrouter") {
105
+ baseUrl = "https://openrouter.ai/api/v1";
106
+ }
107
+ else if (provider === "anthropic") {
108
+ baseUrl = "https://api.anthropic.com/v1";
109
+ model = "claude-3-5-sonnet-20241022";
110
+ }
111
+ // OpenAI uses default baseUrl (undefined)
112
+ // Test API key
113
+ console.log(chalk.gray("\nValidating API key..."));
114
+ try {
115
+ const OpenAI = (await import("openai")).default;
116
+ const testClient = new OpenAI({
117
+ apiKey: apiKey.trim(),
118
+ baseURL: baseUrl,
119
+ });
120
+ await testClient.chat.completions.create({
121
+ model,
122
+ messages: [{ role: "user", content: "test" }],
123
+ max_tokens: 1,
124
+ });
125
+ console.log(chalk.green("✓ API key validated"));
126
+ }
127
+ catch (error) {
128
+ const message = error instanceof Error ? error.message : "Unknown error";
129
+ console.log(chalk.red("✗ API key validation failed: " + message));
130
+ console.log(chalk.yellow("Please check your API key and try again."));
131
+ return;
132
+ }
133
+ // Save config
134
+ const newConfig = {
135
+ llm: {
136
+ provider,
137
+ apiKey: apiKey.trim(),
138
+ model,
139
+ baseUrl,
140
+ systemPrompt: DEFAULT_SYSTEM_PROMPT,
141
+ },
142
+ cache: {
143
+ enabled: true,
144
+ ttlHours: 168,
145
+ },
146
+ logging: {
147
+ enabled: true,
148
+ level: "info",
149
+ },
150
+ customAllowPatterns: [],
151
+ customDenyPatterns: [],
152
+ customPassthroughPatterns: [],
153
+ };
154
+ saveConfig(newConfig);
155
+ // Find Claude Code settings
156
+ const settingsLocations = [
157
+ join(homedir(), ".claude", "settings.json"),
158
+ join(homedir(), "AppData", "Roaming", "Claude", "settings.json"),
159
+ ];
160
+ let settingsPath = null;
161
+ for (const loc of settingsLocations) {
162
+ if (existsSync(loc)) {
163
+ settingsPath = loc;
164
+ break;
165
+ }
166
+ }
167
+ if (!settingsPath) {
168
+ // Create default location
169
+ settingsPath = settingsLocations[0];
170
+ const dir = join(homedir(), ".claude");
171
+ if (!existsSync(dir)) {
172
+ const { mkdirSync } = await import("fs");
173
+ mkdirSync(dir, { recursive: true });
174
+ }
175
+ writeFileSync(settingsPath, JSON.stringify({ hooks: {} }, null, 2));
176
+ }
177
+ // Read and update settings
178
+ const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
179
+ if (!settings.hooks) {
180
+ settings.hooks = {};
181
+ }
182
+ settings.hooks.PermissionRequest = [
183
+ {
184
+ matcher: "*",
185
+ hooks: [
186
+ {
187
+ type: "command",
188
+ command: "cc-approve permission",
189
+ },
190
+ ],
191
+ },
192
+ ];
193
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
194
+ console.log();
195
+ console.log(chalk.green("✓ Hook installed to " + settingsPath));
196
+ console.log(chalk.green("✓ Configuration saved to " + getConfigPath()));
197
+ console.log();
198
+ console.log(chalk.gray("Run 'cc-approve doctor' to verify setup."));
199
+ });
200
+ // Uninstall command
201
+ program
202
+ .command("uninstall")
203
+ .description("Remove the hook from Claude Code settings")
204
+ .action(async () => {
205
+ const settingsPath = join(homedir(), ".claude", "settings.json");
206
+ if (!existsSync(settingsPath)) {
207
+ console.log(chalk.yellow("Settings file not found"));
208
+ return;
209
+ }
210
+ const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
211
+ if (settings.hooks?.PermissionRequest) {
212
+ delete settings.hooks.PermissionRequest;
213
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
214
+ console.log(chalk.green("✓ Uninstalled successfully!"));
215
+ }
216
+ else {
217
+ console.log(chalk.yellow("Hook was not installed"));
218
+ }
219
+ });
220
+ // Config command
221
+ program
222
+ .command("config")
223
+ .description("Configure API keys and settings")
224
+ .option("--model <model>", "Set the LLM model without running full interactive setup")
225
+ .action(async (options) => {
226
+ // Quick model update
227
+ if (options.model) {
228
+ const config = loadConfig();
229
+ const DEFAULT_MODEL = "gpt-4o-mini";
230
+ const model = options.model === "default" ? DEFAULT_MODEL : options.model;
231
+ config.llm.model = model;
232
+ saveConfig(config);
233
+ if (options.model === "default") {
234
+ console.log(chalk.green(`✓ Model reset to default (${DEFAULT_MODEL})`));
235
+ }
236
+ else {
237
+ console.log(chalk.green(`✓ Model set to ${model}`));
238
+ }
239
+ return;
240
+ }
241
+ const config = loadConfig();
242
+ // Provider selection
243
+ const { provider } = await inquirer.prompt([
244
+ {
245
+ type: "list",
246
+ name: "provider",
247
+ message: "Choose your LLM provider:",
248
+ choices: [
249
+ {
250
+ name: "OpenRouter (recommended - lowest latency)",
251
+ value: "openrouter",
252
+ },
253
+ { name: "OpenAI", value: "openai" },
254
+ { name: "Anthropic", value: "anthropic" },
255
+ ],
256
+ default: config.llm.provider,
257
+ },
258
+ ]);
259
+ // API key input
260
+ const { apiKey } = await inquirer.prompt([
261
+ {
262
+ type: "password",
263
+ name: "apiKey",
264
+ message: "Enter your API key:",
265
+ mask: "X",
266
+ validate: (input) => {
267
+ if (!input || input.trim() === "") {
268
+ return "API key is required";
269
+ }
270
+ return true;
271
+ },
272
+ },
273
+ ]);
274
+ // Set provider-specific defaults
275
+ let baseUrl;
276
+ let model = "gpt-4o-mini";
277
+ if (provider === "openrouter") {
278
+ baseUrl = "https://openrouter.ai/api/v1";
279
+ }
280
+ else if (provider === "anthropic") {
281
+ baseUrl = "https://api.anthropic.com/v1";
282
+ model = "claude-3-5-sonnet-20241022";
283
+ }
284
+ // Test API key
285
+ console.log(chalk.gray("\nValidating API key..."));
286
+ try {
287
+ const OpenAI = (await import("openai")).default;
288
+ const testClient = new OpenAI({
289
+ apiKey: apiKey.trim(),
290
+ baseURL: baseUrl,
291
+ });
292
+ await testClient.chat.completions.create({
293
+ model,
294
+ messages: [{ role: "user", content: "test" }],
295
+ max_tokens: 1,
296
+ });
297
+ console.log(chalk.green("✓ API key validated"));
298
+ }
299
+ catch (error) {
300
+ const message = error instanceof Error ? error.message : "Unknown error";
301
+ console.log(chalk.red("✗ API key validation failed: " + message));
302
+ console.log(chalk.yellow("Please check your API key and try again."));
303
+ return;
304
+ }
305
+ const newConfig = {
306
+ llm: {
307
+ provider,
308
+ apiKey: apiKey.trim(),
309
+ model,
310
+ baseUrl,
311
+ systemPrompt: config.llm?.systemPrompt || DEFAULT_SYSTEM_PROMPT,
312
+ },
313
+ cache: {
314
+ enabled: true,
315
+ ttlHours: 168,
316
+ },
317
+ logging: {
318
+ enabled: true,
319
+ level: "info",
320
+ },
321
+ customAllowPatterns: config.customAllowPatterns || [],
322
+ customDenyPatterns: config.customDenyPatterns || [],
323
+ customPassthroughPatterns: config.customPassthroughPatterns || [],
324
+ };
325
+ saveConfig(newConfig);
326
+ console.log(chalk.green("✓ Configuration saved!"));
327
+ console.log(chalk.gray(` Config file: ${getConfigPath()}`));
328
+ });
329
+ // Clear cache command
330
+ program
331
+ .command("clear-cache")
332
+ .description("Clear cached decisions (all by default, or selectively)")
333
+ .option("--deny-only", "Only clear entries with 'deny' decision")
334
+ .option("--allow-only", "Only clear entries with 'allow' decision")
335
+ .option("--key <hash>", "Clear a specific entry by its SHA256 key")
336
+ .option("--grep <substring>", "Clear entries matching a substring in toolName, reason, or input")
337
+ .action((options) => {
338
+ if (options.key) {
339
+ const found = clearCacheByKey(options.key);
340
+ if (found) {
341
+ console.log(chalk.green(`✓ Cleared cache entry with key ${options.key}`));
342
+ }
343
+ else {
344
+ console.log(chalk.yellow(`No cache entry found with key ${options.key}`));
345
+ }
346
+ return;
347
+ }
348
+ if (options.grep) {
349
+ const count = clearCacheByGrep(options.grep);
350
+ console.log(chalk.green(`✓ Cleared ${count} cached decisions matching "${options.grep}"`));
351
+ return;
352
+ }
353
+ if (options.denyOnly) {
354
+ const count = clearCacheByDecision("deny");
355
+ console.log(chalk.green(`✓ Cleared ${count} denied cached decisions`));
356
+ return;
357
+ }
358
+ if (options.allowOnly) {
359
+ const count = clearCacheByDecision("allow");
360
+ console.log(chalk.green(`✓ Cleared ${count} allowed cached decisions`));
361
+ return;
362
+ }
363
+ // Default: clear all
364
+ const count = clearCache();
365
+ console.log(chalk.green(`✓ Cleared ${count} cached decisions`));
366
+ });
367
+ // Cache list command
368
+ program
369
+ .command("cache")
370
+ .description("View cached decisions for the current project")
371
+ .option("--page <number>", "Page number", "1")
372
+ .option("--per-page <number>", "Entries per page", "20")
373
+ .option("--all", "Show all projects, not just the current one")
374
+ .action((options) => {
375
+ const page = Math.max(1, parseInt(options.page, 10) || 1);
376
+ const perPage = Math.max(1, parseInt(options.perPage, 10) || 20);
377
+ const projectRoot = options.all
378
+ ? undefined
379
+ : resolveProjectRoot(process.cwd());
380
+ const entries = listCacheEntries(projectRoot);
381
+ if (entries.length === 0) {
382
+ if (options.all) {
383
+ console.log(chalk.yellow("No cached decisions found."));
384
+ }
385
+ else {
386
+ console.log(chalk.yellow(`No cached decisions for project: ${projectRoot}`));
387
+ console.log(chalk.gray("Use --all to see entries for all projects."));
388
+ }
389
+ return;
390
+ }
391
+ const totalPages = Math.ceil(entries.length / perPage);
392
+ const start = (page - 1) * perPage;
393
+ const pageEntries = entries.slice(start, start + perPage);
394
+ if (!options.all) {
395
+ console.log(chalk.bold(`Project: ${projectRoot}`));
396
+ }
397
+ console.log(chalk.bold(`Cache entries: ${entries.length} total (page ${page}/${totalPages})\n`));
398
+ for (const entry of pageEntries) {
399
+ const age = formatAge(Date.now() - entry.timestamp);
400
+ const decisionColor = entry.decision === "allow" ? chalk.green : chalk.red;
401
+ console.log(` ${decisionColor(entry.decision.toUpperCase().padEnd(5))} ${chalk.cyan(entry.toolName)} ${chalk.gray(age)}`);
402
+ console.log(` ${chalk.gray(entry.reason)}`);
403
+ if (entry.toolInput) {
404
+ const inputStr = summarizeInput(entry.toolInput);
405
+ if (inputStr) {
406
+ console.log(` ${chalk.dim(inputStr)}`);
407
+ }
408
+ }
409
+ if (options.all && entry.projectRoot) {
410
+ console.log(` ${chalk.dim("project: " + entry.projectRoot)}`);
411
+ }
412
+ console.log(` ${chalk.dim("key: " + entry.key)}`);
413
+ console.log();
414
+ }
415
+ if (totalPages > 1) {
416
+ console.log(chalk.gray(`Page ${page} of ${totalPages}. Use --page ${page + 1} to see more.`));
417
+ }
418
+ });
419
+ // Doctor command
420
+ program
421
+ .command("doctor")
422
+ .description("Diagnose configuration and connectivity")
423
+ .action(async () => {
424
+ console.log(chalk.blue("Running diagnostics...\n"));
425
+ // Check config
426
+ console.log(chalk.bold("Configuration:"));
427
+ const config = loadConfig();
428
+ console.log(` Provider: ${config.llm.provider}`);
429
+ console.log(` Model: ${config.llm.model}`);
430
+ console.log(` API Key: ${config.llm.apiKey ? "✓ Set in config" : "✗ Not in config"}`);
431
+ console.log(` Base URL: ${config.llm.baseUrl || "Default"}`);
432
+ console.log(` Cache: ${config.cache.enabled ? `Enabled (${config.cache.ttlHours}h TTL)` : "Disabled"}`);
433
+ // Check cache stats
434
+ console.log(chalk.bold("\nCache Stats:"));
435
+ const cacheStats = getCacheStats();
436
+ console.log(` Entries: ${cacheStats.entries}`);
437
+ if (cacheStats.oldestTimestamp) {
438
+ const age = Math.round((Date.now() - cacheStats.oldestTimestamp) / 1000 / 60 / 60);
439
+ console.log(` Oldest entry: ${age} hours ago`);
440
+ }
441
+ // Check settings installation across all locations
442
+ console.log(chalk.bold("\nInstallation:"));
443
+ const settingsLocations = [
444
+ {
445
+ label: "User settings",
446
+ path: join(homedir(), ".claude", "settings.json"),
447
+ },
448
+ {
449
+ label: "Project settings",
450
+ path: join(process.cwd(), ".claude", "settings.json"),
451
+ },
452
+ {
453
+ label: "Project local",
454
+ path: join(process.cwd(), ".claude", "settings.local.json"),
455
+ },
456
+ ];
457
+ let anyInstalled = false;
458
+ for (const { label, path } of settingsLocations) {
459
+ if (existsSync(path)) {
460
+ try {
461
+ const settings = JSON.parse(readFileSync(path, "utf-8"));
462
+ const installed = settings.hooks?.PermissionRequest != null;
463
+ if (installed) {
464
+ console.log(` ${label}: ${chalk.green("✓ Hook configured")}`);
465
+ anyInstalled = true;
466
+ }
467
+ else {
468
+ console.log(` ${label}: ${chalk.yellow("File exists, hook not configured")}`);
469
+ }
470
+ console.log(chalk.gray(` ${path}`));
471
+ }
472
+ catch {
473
+ console.log(` ${label}: ${chalk.red("✗ File exists but could not be parsed")}`);
474
+ console.log(chalk.gray(` ${path}`));
475
+ }
476
+ }
477
+ else {
478
+ console.log(` ${label}: ${chalk.gray("- File not found")}`);
479
+ console.log(chalk.gray(` ${path}`));
480
+ }
481
+ }
482
+ if (!anyInstalled) {
483
+ console.log(chalk.yellow("\n ⚠ Hook not found in any settings file. Run 'cc-approve install' to set up."));
484
+ }
485
+ // Check API connectivity
486
+ console.log(chalk.bold("\nConnectivity:"));
487
+ const { getApiKey } = await import("./config.js");
488
+ const apiKey = getApiKey();
489
+ console.log(` API Key available: ${apiKey ? "✓ Yes" : "✗ No"}`);
490
+ console.log(chalk.bold("\nPaths:"));
491
+ console.log(` Config dir: ${getConfigDir()}`);
492
+ console.log(` Config file: ${getConfigPath()}`);
493
+ });
494
+ // Status command (show current config)
495
+ program
496
+ .command("status")
497
+ .description("Show current configuration status")
498
+ .action(() => {
499
+ const config = loadConfig();
500
+ console.log(chalk.blue("Claude Code Permission Hook Status\n"));
501
+ console.log(JSON.stringify(config, null, 2));
502
+ });
503
+ function formatAge(ms) {
504
+ const seconds = Math.floor(ms / 1000);
505
+ if (seconds < 60)
506
+ return `${seconds}s ago`;
507
+ const minutes = Math.floor(seconds / 60);
508
+ if (minutes < 60)
509
+ return `${minutes}m ago`;
510
+ const hours = Math.floor(minutes / 60);
511
+ if (hours < 24)
512
+ return `${hours}h ago`;
513
+ const days = Math.floor(hours / 24);
514
+ return `${days}d ago`;
515
+ }
516
+ function summarizeInput(toolInput) {
517
+ const command = toolInput.command;
518
+ if (typeof command === "string") {
519
+ const truncated = command.length > 100 ? command.slice(0, 100) + "..." : command;
520
+ return `$ ${truncated}`;
521
+ }
522
+ const filePath = toolInput.file_path || toolInput.filePath;
523
+ if (typeof filePath === "string") {
524
+ return filePath;
525
+ }
526
+ return "";
527
+ }
528
+ program.parse();
529
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { LLMResponse } from "./types.js";
2
+ export declare function queryLLM(toolName: string, toolInput: Record<string, unknown>, projectRoot?: string): Promise<LLMResponse>;
3
+ //# sourceMappingURL=llm-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-client.d.ts","sourceRoot":"","sources":["../src/llm-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAqB,MAAM,YAAY,CAAC;AAE5D,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,WAAW,CAAC,CA2EtB"}
@@ -0,0 +1,67 @@
1
+ import OpenAI from "openai";
2
+ import { loadConfig, getApiKey } from "./config.js";
3
+ import { LLMResponseSchema } from "./types.js";
4
+ export async function queryLLM(toolName, toolInput, projectRoot) {
5
+ const config = loadConfig();
6
+ const apiKey = getApiKey();
7
+ if (!apiKey) {
8
+ // No API key, conservative deny
9
+ return {
10
+ decision: "deny",
11
+ reason: "No LLM API key configured - cannot make intelligent decision",
12
+ };
13
+ }
14
+ const client = new OpenAI({
15
+ apiKey,
16
+ baseURL: config.llm.baseUrl,
17
+ });
18
+ // Use configurable system prompt from config
19
+ const systemPrompt = config.llm.systemPrompt;
20
+ const userPrompt = `Evaluate this tool request for auto-approval:
21
+
22
+ Tool: ${toolName}
23
+ Project Root: ${projectRoot || "unknown"}
24
+ Input: ${JSON.stringify(toolInput, null, 2)}
25
+
26
+ Should this be automatically approved or denied?`;
27
+ try {
28
+ // Models that support reasoning control via OpenRouter
29
+ const REASONING_MODELS = new Set([
30
+ "openai/gpt-5.2",
31
+ ]);
32
+ const params = {
33
+ model: config.llm.model,
34
+ messages: [
35
+ { role: "system", content: systemPrompt },
36
+ { role: "user", content: userPrompt },
37
+ ],
38
+ temperature: 0,
39
+ max_tokens: 200,
40
+ response_format: { type: "json_object" },
41
+ };
42
+ if (config.llm.provider === "openrouter" &&
43
+ REASONING_MODELS.has(config.llm.model)) {
44
+ params.reasoning = { effort: "none" };
45
+ }
46
+ const response = await client.chat.completions.create(params);
47
+ const content = response.choices[0]?.message?.content;
48
+ if (!content) {
49
+ return {
50
+ decision: "deny",
51
+ reason: "Empty LLM response",
52
+ };
53
+ }
54
+ // Parse and validate response
55
+ const parsed = JSON.parse(content);
56
+ return LLMResponseSchema.parse(parsed);
57
+ }
58
+ catch (error) {
59
+ // On any error, conservative deny
60
+ const message = error instanceof Error ? error.message : "Unknown error";
61
+ return {
62
+ decision: "deny",
63
+ reason: `LLM error: ${message}`,
64
+ };
65
+ }
66
+ }
67
+ //# sourceMappingURL=llm-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-client.js","sourceRoot":"","sources":["../src/llm-client.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAe,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,QAAgB,EAChB,SAAkC,EAClC,WAAoB;IAEpB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,gCAAgC;QAChC,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,8DAA8D;SACvE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;QACxB,MAAM;QACN,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO;KAC5B,CAAC,CAAC;IAEH,6CAA6C;IAC7C,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;IAE7C,MAAM,UAAU,GAAG;;QAEb,QAAQ;gBACA,WAAW,IAAI,SAAS;SAC/B,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;;iDAEM,CAAC;IAEhD,IAAI,CAAC;QACH,uDAAuD;QACvD,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;YAC/B,gBAAgB;SACjB,CAAC,CAAC;QAEH,MAAM,MAAM,GAA4B;YACtC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK;YACvB,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;gBACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;aACtC;YACD,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,GAAG;YACf,eAAe,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE;SACzC,CAAC;QAEF,IACE,MAAM,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;YACpC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EACtC,CAAC;YACD,MAAM,CAAC,SAAS,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACxC,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CACnD,MAAkE,CACnE,CAAC;QAEF,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;QACtD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAE,oBAAoB;aAC7B,CAAC;QACJ,CAAC;QAED,8BAA8B;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,OAAO,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,kCAAkC;QAClC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,cAAc,OAAO,EAAE;SAChC,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { LogEntry } from "./types.js";
2
+ export declare function logDecision(entry: Omit<LogEntry, "timestamp">): void;
3
+ export declare function getLogPath_(): string;
4
+ export declare function logExists(): boolean;
5
+ export declare function getLogStats(): {
6
+ entries: number;
7
+ sizeBytes: number;
8
+ } | null;
9
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAQtC,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,IAAI,CAepE;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,wBAAgB,WAAW,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAkB3E"}