@phuetz/code-buddy 0.1.18 → 0.1.19
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/background-tasks.d.ts +49 -0
- package/dist/agent/background-tasks.js +153 -0
- package/dist/agent/background-tasks.js.map +1 -0
- package/dist/agent/definitions/agent-definition-loader.d.ts +21 -0
- package/dist/agent/definitions/agent-definition-loader.js +161 -0
- package/dist/agent/definitions/agent-definition-loader.js.map +1 -0
- package/dist/agent/definitions/index.d.ts +1 -0
- package/dist/agent/definitions/index.js +2 -0
- package/dist/agent/definitions/index.js.map +1 -0
- package/dist/agent/extended-thinking.d.ts +64 -0
- package/dist/agent/extended-thinking.js +103 -0
- package/dist/agent/extended-thinking.js.map +1 -0
- package/dist/agent/prompt-suggestions.d.ts +55 -0
- package/dist/agent/prompt-suggestions.js +125 -0
- package/dist/agent/prompt-suggestions.js.map +1 -0
- package/dist/agent/rewind-manager.d.ts +59 -0
- package/dist/agent/rewind-manager.js +124 -0
- package/dist/agent/rewind-manager.js.map +1 -0
- package/dist/agent/teams/agent-team.d.ts +54 -0
- package/dist/agent/teams/agent-team.js +114 -0
- package/dist/agent/teams/agent-team.js.map +1 -0
- package/dist/agent/teams/index.d.ts +1 -0
- package/dist/agent/teams/index.js +2 -0
- package/dist/agent/teams/index.js.map +1 -0
- package/dist/agent/teams/team-v2.d.ts +166 -0
- package/dist/agent/teams/team-v2.js +376 -0
- package/dist/agent/teams/team-v2.js.map +1 -0
- package/dist/channels/imessage/index.d.ts +40 -0
- package/dist/channels/imessage/index.js +69 -0
- package/dist/channels/imessage/index.js.map +1 -0
- package/dist/channels/line/index.d.ts +36 -0
- package/dist/channels/line/index.js +71 -0
- package/dist/channels/line/index.js.map +1 -0
- package/dist/channels/mattermost/index.d.ts +34 -0
- package/dist/channels/mattermost/index.js +56 -0
- package/dist/channels/mattermost/index.js.map +1 -0
- package/dist/channels/nextcloud-talk/index.d.ts +37 -0
- package/dist/channels/nextcloud-talk/index.js +67 -0
- package/dist/channels/nextcloud-talk/index.js.map +1 -0
- package/dist/channels/niche-channels.d.ts +61 -0
- package/dist/channels/niche-channels.js +131 -0
- package/dist/channels/niche-channels.js.map +1 -0
- package/dist/channels/nostr/index.d.ts +30 -0
- package/dist/channels/nostr/index.js +68 -0
- package/dist/channels/nostr/index.js.map +1 -0
- package/dist/channels/twilio-voice/index.d.ts +37 -0
- package/dist/channels/twilio-voice/index.js +76 -0
- package/dist/channels/twilio-voice/index.js.map +1 -0
- package/dist/channels/whatsapp/index.js +0 -1
- package/dist/channels/whatsapp/index.js.map +1 -1
- package/dist/channels/zalo/index.d.ts +28 -0
- package/dist/channels/zalo/index.js +53 -0
- package/dist/channels/zalo/index.js.map +1 -0
- package/dist/cloud/cloud-sessions.d.ts +56 -0
- package/dist/cloud/cloud-sessions.js +187 -0
- package/dist/cloud/cloud-sessions.js.map +1 -0
- package/dist/codebuddy/tool-definitions/advanced-tools.d.ts +1 -0
- package/dist/codebuddy/tool-definitions/advanced-tools.js +24 -0
- package/dist/codebuddy/tool-definitions/advanced-tools.js.map +1 -1
- package/dist/codebuddy/tool-definitions/index.d.ts +1 -1
- package/dist/codebuddy/tool-definitions/index.js +1 -1
- package/dist/codebuddy/tool-definitions/index.js.map +1 -1
- package/dist/commands/handlers/auth-handler.d.ts +32 -0
- package/dist/commands/handlers/auth-handler.js +137 -0
- package/dist/commands/handlers/auth-handler.js.map +1 -0
- package/dist/commands/handlers/context-handler.d.ts +46 -0
- package/dist/commands/handlers/context-handler.js +102 -0
- package/dist/commands/handlers/context-handler.js.map +1 -0
- package/dist/commands/handlers/keybindings-handler.d.ts +30 -0
- package/dist/commands/handlers/keybindings-handler.js +124 -0
- package/dist/commands/handlers/keybindings-handler.js.map +1 -0
- package/dist/commands/handlers/session-commands.d.ts +17 -0
- package/dist/commands/handlers/session-commands.js +119 -0
- package/dist/commands/handlers/session-commands.js.map +1 -0
- package/dist/commands/slash/builtin-commands.js +1 -1
- package/dist/commands/slash/builtin-commands.js.map +1 -1
- package/dist/config/admin-config.d.ts +54 -0
- package/dist/config/admin-config.js +144 -0
- package/dist/config/admin-config.js.map +1 -0
- package/dist/config/advanced-config.d.ts +118 -0
- package/dist/config/advanced-config.js +364 -0
- package/dist/config/advanced-config.js.map +1 -0
- package/dist/config/managed-policies.d.ts +50 -0
- package/dist/config/managed-policies.js +120 -0
- package/dist/config/managed-policies.js.map +1 -0
- package/dist/config/settings-hierarchy.d.ts +59 -0
- package/dist/config/settings-hierarchy.js +188 -0
- package/dist/config/settings-hierarchy.js.map +1 -0
- package/dist/config/tool-profiles.d.ts +37 -0
- package/dist/config/tool-profiles.js +150 -0
- package/dist/config/tool-profiles.js.map +1 -0
- package/dist/config/user-settings.d.ts +31 -0
- package/dist/config/user-settings.js +66 -0
- package/dist/config/user-settings.js.map +1 -0
- package/dist/context/context-files.d.ts +1 -1
- package/dist/context/context-files.js +2 -2
- package/dist/context/context-files.js.map +1 -1
- package/dist/context/partial-summarizer.d.ts +32 -0
- package/dist/context/partial-summarizer.js +144 -0
- package/dist/context/partial-summarizer.js.map +1 -0
- package/dist/desktop/desktop-app.d.ts +44 -0
- package/dist/desktop/desktop-app.js +136 -0
- package/dist/desktop/desktop-app.js.map +1 -0
- package/dist/git/worktree-sessions.d.ts +24 -0
- package/dist/git/worktree-sessions.js +93 -0
- package/dist/git/worktree-sessions.js.map +1 -0
- package/dist/hooks/advanced-hooks.d.ts +110 -0
- package/dist/hooks/advanced-hooks.js +256 -0
- package/dist/hooks/advanced-hooks.js.map +1 -0
- package/dist/hooks/async-hooks.d.ts +73 -0
- package/dist/hooks/async-hooks.js +213 -0
- package/dist/hooks/async-hooks.js.map +1 -0
- package/dist/hooks/env-persistence.d.ts +58 -0
- package/dist/hooks/env-persistence.js +195 -0
- package/dist/hooks/env-persistence.js.map +1 -0
- package/dist/hooks/hook-events.d.ts +36 -0
- package/dist/hooks/hook-events.js +55 -0
- package/dist/hooks/hook-events.js.map +1 -0
- package/dist/hooks/smart-hooks.d.ts +85 -0
- package/dist/hooks/smart-hooks.js +199 -0
- package/dist/hooks/smart-hooks.js.map +1 -0
- package/dist/ide/jetbrains-plugin.d.ts +55 -0
- package/dist/ide/jetbrains-plugin.js +156 -0
- package/dist/ide/jetbrains-plugin.js.map +1 -0
- package/dist/ide/vscode-extension.d.ts +94 -0
- package/dist/ide/vscode-extension.js +229 -0
- package/dist/ide/vscode-extension.js.map +1 -0
- package/dist/index.js +77 -3
- package/dist/index.js.map +1 -1
- package/dist/input/file-autocomplete.d.ts +42 -0
- package/dist/input/file-autocomplete.js +154 -0
- package/dist/input/file-autocomplete.js.map +1 -0
- package/dist/integrations/chrome-bridge.d.ts +90 -0
- package/dist/integrations/chrome-bridge.js +151 -0
- package/dist/integrations/chrome-bridge.js.map +1 -0
- package/dist/integrations/github-action-runner.d.ts +40 -0
- package/dist/integrations/github-action-runner.js +163 -0
- package/dist/integrations/github-action-runner.js.map +1 -0
- package/dist/integrations/gitlab-ci-runner.d.ts +34 -0
- package/dist/integrations/gitlab-ci-runner.js +104 -0
- package/dist/integrations/gitlab-ci-runner.js.map +1 -0
- package/dist/integrations/pr-session-linker.d.ts +44 -0
- package/dist/integrations/pr-session-linker.js +103 -0
- package/dist/integrations/pr-session-linker.js.map +1 -0
- package/dist/integrations/tailscale.d.ts +36 -0
- package/dist/integrations/tailscale.js +101 -0
- package/dist/integrations/tailscale.js.map +1 -0
- package/dist/lsp/lsp-client.d.ts +68 -0
- package/dist/lsp/lsp-client.js +182 -0
- package/dist/lsp/lsp-client.js.map +1 -0
- package/dist/mcp/connectors.d.ts +28 -0
- package/dist/mcp/connectors.js +148 -0
- package/dist/mcp/connectors.js.map +1 -0
- package/dist/mcp/index.d.ts +7 -4
- package/dist/mcp/index.js +7 -4
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mcp-auto-discovery.d.ts +49 -0
- package/dist/mcp/mcp-auto-discovery.js +104 -0
- package/dist/mcp/mcp-auto-discovery.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +70 -0
- package/dist/mcp/mcp-server.js +374 -0
- package/dist/mcp/mcp-server.js.map +1 -0
- package/dist/memory/auto-memory.d.ts +53 -0
- package/dist/memory/auto-memory.js +250 -0
- package/dist/memory/auto-memory.js.map +1 -0
- package/dist/memory/hybrid-search.d.ts +51 -0
- package/dist/memory/hybrid-search.js +199 -0
- package/dist/memory/hybrid-search.js.map +1 -0
- package/dist/memory/memory-flush.d.ts +51 -0
- package/dist/memory/memory-flush.js +102 -0
- package/dist/memory/memory-flush.js.map +1 -0
- package/dist/memory/subagent-memory.d.ts +73 -0
- package/dist/memory/subagent-memory.js +172 -0
- package/dist/memory/subagent-memory.js.map +1 -0
- package/dist/nodes/device-node.d.ts +40 -0
- package/dist/nodes/device-node.js +117 -0
- package/dist/nodes/device-node.js.map +1 -0
- package/dist/output/json-schema-output.d.ts +67 -0
- package/dist/output/json-schema-output.js +273 -0
- package/dist/output/json-schema-output.js.map +1 -0
- package/dist/persistence/session-picker.d.ts +22 -0
- package/dist/persistence/session-picker.js +47 -0
- package/dist/persistence/session-picker.js.map +1 -0
- package/dist/persistence/session-store.d.ts +11 -0
- package/dist/persistence/session-store.js +17 -0
- package/dist/persistence/session-store.js.map +1 -1
- package/dist/plugins/git-pinned-marketplace.d.ts +39 -0
- package/dist/plugins/git-pinned-marketplace.js +152 -0
- package/dist/plugins/git-pinned-marketplace.js.map +1 -0
- package/dist/plugins/plugin-manifest.d.ts +116 -0
- package/dist/plugins/plugin-manifest.js +283 -0
- package/dist/plugins/plugin-manifest.js.map +1 -0
- package/dist/sandbox/os-sandbox.d.ts +49 -1
- package/dist/sandbox/os-sandbox.js +347 -6
- package/dist/sandbox/os-sandbox.js.map +1 -1
- package/dist/sdk/agent-sdk.d.ts +61 -0
- package/dist/sdk/agent-sdk.js +90 -0
- package/dist/sdk/agent-sdk.js.map +1 -0
- package/dist/security/permission-modes.d.ts +76 -0
- package/dist/security/permission-modes.js +195 -0
- package/dist/security/permission-modes.js.map +1 -0
- package/dist/security/permission-patterns.d.ts +61 -0
- package/dist/security/permission-patterns.js +171 -0
- package/dist/security/permission-patterns.js.map +1 -0
- package/dist/security/safe-binaries.d.ts +23 -0
- package/dist/security/safe-binaries.js +96 -0
- package/dist/security/safe-binaries.js.map +1 -0
- package/dist/security/sender-policies.d.ts +46 -0
- package/dist/security/sender-policies.js +90 -0
- package/dist/security/sender-policies.js.map +1 -0
- package/dist/server/dashboard.d.ts +53 -0
- package/dist/server/dashboard.js +93 -0
- package/dist/server/dashboard.js.map +1 -0
- package/dist/services/system-prompt-override.d.ts +34 -0
- package/dist/services/system-prompt-override.js +64 -0
- package/dist/services/system-prompt-override.js.map +1 -0
- package/dist/skills/skill-enhancements.d.ts +37 -0
- package/dist/skills/skill-enhancements.js +69 -0
- package/dist/skills/skill-enhancements.js.map +1 -0
- package/dist/telemetry/otel-tracer.d.ts +98 -0
- package/dist/telemetry/otel-tracer.js +245 -0
- package/dist/telemetry/otel-tracer.js.map +1 -0
- package/dist/tools/browser-stub.d.ts +61 -0
- package/dist/tools/browser-stub.js +184 -0
- package/dist/tools/browser-stub.js.map +1 -0
- package/dist/tools/gateway-tool.d.ts +43 -0
- package/dist/tools/gateway-tool.js +92 -0
- package/dist/tools/gateway-tool.js.map +1 -0
- package/dist/tools/image-stub.d.ts +32 -0
- package/dist/tools/image-stub.js +97 -0
- package/dist/tools/image-stub.js.map +1 -0
- package/dist/tools/js-repl.d.ts +78 -0
- package/dist/tools/js-repl.js +280 -0
- package/dist/tools/js-repl.js.map +1 -0
- package/dist/tools/message-tool.d.ts +42 -0
- package/dist/tools/message-tool.js +113 -0
- package/dist/tools/message-tool.js.map +1 -0
- package/dist/ui/cli-enhancements.d.ts +178 -0
- package/dist/ui/cli-enhancements.js +430 -0
- package/dist/ui/cli-enhancements.js.map +1 -0
- package/dist/ui/status-line.d.ts +90 -0
- package/dist/ui/status-line.js +160 -0
- package/dist/ui/status-line.js.map +1 -0
- package/dist/ui/terminal-enhancements.d.ts +34 -0
- package/dist/ui/terminal-enhancements.js +97 -0
- package/dist/ui/terminal-enhancements.js.map +1 -0
- package/dist/ui/ui-enhancements.d.ts +38 -0
- package/dist/ui/ui-enhancements.js +116 -0
- package/dist/ui/ui-enhancements.js.map +1 -0
- package/dist/utils/custom-instructions.js +4 -1
- package/dist/utils/custom-instructions.js.map +1 -1
- package/dist/utils/init-project.d.ts +1 -1
- package/dist/utils/init-project.js +20 -20
- package/dist/utils/init-project.js.map +1 -1
- package/dist/utils/output-schema-validator.d.ts +40 -0
- package/dist/utils/output-schema-validator.js +137 -0
- package/dist/utils/output-schema-validator.js.map +1 -0
- package/dist/utils/safety-misc.d.ts +24 -0
- package/dist/utils/safety-misc.js +91 -0
- package/dist/utils/safety-misc.js.map +1 -0
- package/dist/utils/session-enhancements.d.ts +40 -0
- package/dist/utils/session-enhancements.js +118 -0
- package/dist/utils/session-enhancements.js.map +1 -0
- package/dist/utils/shell-snapshot.d.ts +38 -0
- package/dist/utils/shell-snapshot.js +323 -0
- package/dist/utils/shell-snapshot.js.map +1 -0
- package/dist/utils/stream-json-formatter.d.ts +77 -0
- package/dist/utils/stream-json-formatter.js +61 -0
- package/dist/utils/stream-json-formatter.js.map +1 -0
- package/dist/workflows/lobster-engine.d.ts +43 -0
- package/dist/workflows/lobster-engine.js +167 -0
- package/dist/workflows/lobster-engine.js.map +1 -0
- package/package.json +3 -6
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission Modes
|
|
3
|
+
*
|
|
4
|
+
* Five-tier permission system: default, plan, acceptEdits, dontAsk, bypassPermissions.
|
|
5
|
+
* With managed setting to disable bypass, subagent-specific modes, and pattern-based allowlists.
|
|
6
|
+
*/
|
|
7
|
+
export type PermissionMode = 'default' | 'plan' | 'acceptEdits' | 'dontAsk' | 'bypassPermissions';
|
|
8
|
+
export interface PermissionModeConfig {
|
|
9
|
+
mode: PermissionMode;
|
|
10
|
+
disableBypass: boolean;
|
|
11
|
+
subagentMode?: PermissionMode;
|
|
12
|
+
}
|
|
13
|
+
export interface PermissionDecision {
|
|
14
|
+
allowed: boolean;
|
|
15
|
+
reason: string;
|
|
16
|
+
prompted: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare class PermissionModeManager {
|
|
19
|
+
private config;
|
|
20
|
+
private allowedPatterns;
|
|
21
|
+
constructor(config?: Partial<PermissionModeConfig>);
|
|
22
|
+
/**
|
|
23
|
+
* Set the permission mode
|
|
24
|
+
* Returns false if trying to set bypassPermissions when it's disabled
|
|
25
|
+
*/
|
|
26
|
+
setMode(mode: PermissionMode): boolean;
|
|
27
|
+
getMode(): PermissionMode;
|
|
28
|
+
/**
|
|
29
|
+
* Check permission for an action
|
|
30
|
+
*/
|
|
31
|
+
checkPermission(action: string, toolName: string): PermissionDecision;
|
|
32
|
+
/**
|
|
33
|
+
* Default mode: prompt for everything except read-only
|
|
34
|
+
*/
|
|
35
|
+
private checkDefault;
|
|
36
|
+
/**
|
|
37
|
+
* Plan mode: only allow read-only tools, block edits and destructive
|
|
38
|
+
*/
|
|
39
|
+
private checkPlan;
|
|
40
|
+
/**
|
|
41
|
+
* Accept edits mode: auto-approve read and edit tools, prompt for destructive
|
|
42
|
+
*/
|
|
43
|
+
private checkAcceptEdits;
|
|
44
|
+
/**
|
|
45
|
+
* Don't ask mode: auto-approve everything except destructive
|
|
46
|
+
*/
|
|
47
|
+
private checkDontAsk;
|
|
48
|
+
/**
|
|
49
|
+
* Bypass mode: auto-approve everything
|
|
50
|
+
*/
|
|
51
|
+
private checkBypass;
|
|
52
|
+
/**
|
|
53
|
+
* Tool classification
|
|
54
|
+
*/
|
|
55
|
+
isReadOnlyTool(toolName: string): boolean;
|
|
56
|
+
isEditTool(toolName: string): boolean;
|
|
57
|
+
isDestructiveTool(toolName: string): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Add an allowed pattern
|
|
60
|
+
*/
|
|
61
|
+
addAllowedPattern(pattern: string): void;
|
|
62
|
+
/**
|
|
63
|
+
* Check if an action matches any allowed pattern
|
|
64
|
+
*/
|
|
65
|
+
isPatternAllowed(action: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Set subagent mode
|
|
68
|
+
*/
|
|
69
|
+
setSubagentMode(mode: PermissionMode): void;
|
|
70
|
+
getSubagentMode(): PermissionMode;
|
|
71
|
+
/**
|
|
72
|
+
* Set bypass disabled (managed setting)
|
|
73
|
+
*/
|
|
74
|
+
setBypassDisabled(disabled: boolean): void;
|
|
75
|
+
isBypassDisabled(): boolean;
|
|
76
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission Modes
|
|
3
|
+
*
|
|
4
|
+
* Five-tier permission system: default, plan, acceptEdits, dontAsk, bypassPermissions.
|
|
5
|
+
* With managed setting to disable bypass, subagent-specific modes, and pattern-based allowlists.
|
|
6
|
+
*/
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Tool Classifications
|
|
10
|
+
// ============================================================================
|
|
11
|
+
const READ_ONLY_TOOLS = new Set([
|
|
12
|
+
'view_file',
|
|
13
|
+
'read_file',
|
|
14
|
+
'search',
|
|
15
|
+
'list_files',
|
|
16
|
+
'grep',
|
|
17
|
+
'glob',
|
|
18
|
+
'git_log',
|
|
19
|
+
'git_status',
|
|
20
|
+
'git_diff',
|
|
21
|
+
]);
|
|
22
|
+
const EDIT_TOOLS = new Set([
|
|
23
|
+
'str_replace_editor',
|
|
24
|
+
'create_file',
|
|
25
|
+
'write_file',
|
|
26
|
+
'edit_file',
|
|
27
|
+
'apply_patch',
|
|
28
|
+
'multi_edit',
|
|
29
|
+
]);
|
|
30
|
+
const DESTRUCTIVE_TOOLS = new Set([
|
|
31
|
+
'bash',
|
|
32
|
+
'delete_file',
|
|
33
|
+
'rm',
|
|
34
|
+
'git_reset',
|
|
35
|
+
'git_checkout',
|
|
36
|
+
]);
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Permission Mode Manager
|
|
39
|
+
// ============================================================================
|
|
40
|
+
export class PermissionModeManager {
|
|
41
|
+
config;
|
|
42
|
+
allowedPatterns = [];
|
|
43
|
+
constructor(config) {
|
|
44
|
+
this.config = {
|
|
45
|
+
mode: config?.mode || 'default',
|
|
46
|
+
disableBypass: config?.disableBypass ?? false,
|
|
47
|
+
subagentMode: config?.subagentMode,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Set the permission mode
|
|
52
|
+
* Returns false if trying to set bypassPermissions when it's disabled
|
|
53
|
+
*/
|
|
54
|
+
setMode(mode) {
|
|
55
|
+
if (mode === 'bypassPermissions' && this.config.disableBypass) {
|
|
56
|
+
logger.warn('Cannot enable bypassPermissions: disabled by managed setting');
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
this.config.mode = mode;
|
|
60
|
+
logger.info(`Permission mode set to: ${mode}`);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
getMode() {
|
|
64
|
+
return this.config.mode;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Check permission for an action
|
|
68
|
+
*/
|
|
69
|
+
checkPermission(action, toolName) {
|
|
70
|
+
// Check pattern allowlist first
|
|
71
|
+
if (this.isPatternAllowed(action)) {
|
|
72
|
+
return { allowed: true, reason: 'Matched allowed pattern', prompted: false };
|
|
73
|
+
}
|
|
74
|
+
switch (this.config.mode) {
|
|
75
|
+
case 'default':
|
|
76
|
+
return this.checkDefault(action, toolName);
|
|
77
|
+
case 'plan':
|
|
78
|
+
return this.checkPlan(action, toolName);
|
|
79
|
+
case 'acceptEdits':
|
|
80
|
+
return this.checkAcceptEdits(action, toolName);
|
|
81
|
+
case 'dontAsk':
|
|
82
|
+
return this.checkDontAsk(action, toolName);
|
|
83
|
+
case 'bypassPermissions':
|
|
84
|
+
return this.checkBypass(action, toolName);
|
|
85
|
+
default:
|
|
86
|
+
return this.checkDefault(action, toolName);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Default mode: prompt for everything except read-only
|
|
91
|
+
*/
|
|
92
|
+
checkDefault(_action, toolName) {
|
|
93
|
+
if (this.isReadOnlyTool(toolName)) {
|
|
94
|
+
return { allowed: true, reason: 'Read-only tool auto-approved', prompted: false };
|
|
95
|
+
}
|
|
96
|
+
return { allowed: true, reason: 'Requires user confirmation', prompted: true };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Plan mode: only allow read-only tools, block edits and destructive
|
|
100
|
+
*/
|
|
101
|
+
checkPlan(_action, toolName) {
|
|
102
|
+
if (this.isReadOnlyTool(toolName)) {
|
|
103
|
+
return { allowed: true, reason: 'Read-only tool allowed in plan mode', prompted: false };
|
|
104
|
+
}
|
|
105
|
+
return { allowed: false, reason: 'Only read-only tools allowed in plan mode', prompted: false };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Accept edits mode: auto-approve read and edit tools, prompt for destructive
|
|
109
|
+
*/
|
|
110
|
+
checkAcceptEdits(_action, toolName) {
|
|
111
|
+
if (this.isReadOnlyTool(toolName)) {
|
|
112
|
+
return { allowed: true, reason: 'Read-only tool auto-approved', prompted: false };
|
|
113
|
+
}
|
|
114
|
+
if (this.isEditTool(toolName)) {
|
|
115
|
+
return { allowed: true, reason: 'Edit tool auto-approved in acceptEdits mode', prompted: false };
|
|
116
|
+
}
|
|
117
|
+
if (this.isDestructiveTool(toolName)) {
|
|
118
|
+
return { allowed: true, reason: 'Destructive tool requires confirmation', prompted: true };
|
|
119
|
+
}
|
|
120
|
+
return { allowed: true, reason: 'Requires confirmation', prompted: true };
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Don't ask mode: auto-approve everything except destructive
|
|
124
|
+
*/
|
|
125
|
+
checkDontAsk(_action, toolName) {
|
|
126
|
+
if (this.isDestructiveTool(toolName)) {
|
|
127
|
+
return { allowed: true, reason: 'Destructive tool requires confirmation in dontAsk mode', prompted: true };
|
|
128
|
+
}
|
|
129
|
+
return { allowed: true, reason: 'Auto-approved in dontAsk mode', prompted: false };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Bypass mode: auto-approve everything
|
|
133
|
+
*/
|
|
134
|
+
checkBypass(_action, _toolName) {
|
|
135
|
+
return { allowed: true, reason: 'All operations auto-approved in bypass mode', prompted: false };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Tool classification
|
|
139
|
+
*/
|
|
140
|
+
isReadOnlyTool(toolName) {
|
|
141
|
+
return READ_ONLY_TOOLS.has(toolName);
|
|
142
|
+
}
|
|
143
|
+
isEditTool(toolName) {
|
|
144
|
+
return EDIT_TOOLS.has(toolName);
|
|
145
|
+
}
|
|
146
|
+
isDestructiveTool(toolName) {
|
|
147
|
+
return DESTRUCTIVE_TOOLS.has(toolName);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Add an allowed pattern
|
|
151
|
+
*/
|
|
152
|
+
addAllowedPattern(pattern) {
|
|
153
|
+
if (!this.allowedPatterns.includes(pattern)) {
|
|
154
|
+
this.allowedPatterns.push(pattern);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Check if an action matches any allowed pattern
|
|
159
|
+
*/
|
|
160
|
+
isPatternAllowed(action) {
|
|
161
|
+
return this.allowedPatterns.some(pattern => {
|
|
162
|
+
// Convert glob-like pattern to regex
|
|
163
|
+
const regex = pattern
|
|
164
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
165
|
+
.replace(/\*/g, '.*');
|
|
166
|
+
return new RegExp(`^${regex}$`).test(action);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Set subagent mode
|
|
171
|
+
*/
|
|
172
|
+
setSubagentMode(mode) {
|
|
173
|
+
this.config.subagentMode = mode;
|
|
174
|
+
logger.info(`Subagent permission mode set to: ${mode}`);
|
|
175
|
+
}
|
|
176
|
+
getSubagentMode() {
|
|
177
|
+
return this.config.subagentMode || this.config.mode;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Set bypass disabled (managed setting)
|
|
181
|
+
*/
|
|
182
|
+
setBypassDisabled(disabled) {
|
|
183
|
+
this.config.disableBypass = disabled;
|
|
184
|
+
// If bypass was active and we're disabling it, revert to default
|
|
185
|
+
if (disabled && this.config.mode === 'bypassPermissions') {
|
|
186
|
+
this.config.mode = 'default';
|
|
187
|
+
logger.warn('Bypass was active but has been disabled, reverting to default mode');
|
|
188
|
+
}
|
|
189
|
+
logger.info(`Bypass disabled: ${disabled}`);
|
|
190
|
+
}
|
|
191
|
+
isBypassDisabled() {
|
|
192
|
+
return this.config.disableBypass;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=permission-modes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-modes.js","sourceRoot":"","sources":["../../src/security/permission-modes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern-based Permissions
|
|
3
|
+
*
|
|
4
|
+
* Provides fine-grained permission control for tool executions using
|
|
5
|
+
* glob-pattern matching. Rules are evaluated in order; first match wins.
|
|
6
|
+
*
|
|
7
|
+
* Tool specifier format:
|
|
8
|
+
* Bash(npm run *) → matches Bash tool with commands starting "npm run "
|
|
9
|
+
* Edit(./src/**) → matches Edit tool with paths under ./src/
|
|
10
|
+
* Read(./.env) → matches Read tool on exactly ./.env
|
|
11
|
+
* WebFetch(domain:example.com) → matches WebFetch for a specific domain
|
|
12
|
+
* Bash → matches all Bash invocations (no pattern)
|
|
13
|
+
*
|
|
14
|
+
* Pattern rules:
|
|
15
|
+
* * → matches any characters except /
|
|
16
|
+
* ** → matches anything including /
|
|
17
|
+
*/
|
|
18
|
+
export type PermissionAction = 'allow' | 'ask' | 'deny';
|
|
19
|
+
export interface PermissionRule {
|
|
20
|
+
tool: string;
|
|
21
|
+
pattern?: string;
|
|
22
|
+
action: PermissionAction;
|
|
23
|
+
}
|
|
24
|
+
export interface ParsedToolSpecifier {
|
|
25
|
+
tool: string;
|
|
26
|
+
pattern?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare class PermissionPatternMatcher {
|
|
29
|
+
private rules;
|
|
30
|
+
/**
|
|
31
|
+
* Add a permission rule.
|
|
32
|
+
*/
|
|
33
|
+
addRule(rule: PermissionRule): void;
|
|
34
|
+
/**
|
|
35
|
+
* Check permission for a tool call. Evaluates rules in order; first match wins.
|
|
36
|
+
* If no rule matches, returns 'ask' as default.
|
|
37
|
+
*/
|
|
38
|
+
checkPermission(tool: string, input: string): PermissionAction;
|
|
39
|
+
/**
|
|
40
|
+
* Parse a tool specifier string like "Bash(npm run *)" into components.
|
|
41
|
+
*/
|
|
42
|
+
parseToolSpecifier(spec: string): ParsedToolSpecifier;
|
|
43
|
+
/**
|
|
44
|
+
* Load rules from an array of strings like "allow:Bash(npm run *)".
|
|
45
|
+
*/
|
|
46
|
+
loadRules(ruleStrings: string[]): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get all current rules.
|
|
49
|
+
*/
|
|
50
|
+
getRules(): PermissionRule[];
|
|
51
|
+
/**
|
|
52
|
+
* Clear all rules.
|
|
53
|
+
*/
|
|
54
|
+
clearRules(): void;
|
|
55
|
+
/**
|
|
56
|
+
* Remove a rule by index.
|
|
57
|
+
*/
|
|
58
|
+
removeRule(index: number): void;
|
|
59
|
+
}
|
|
60
|
+
export declare function getPermissionMatcher(): PermissionPatternMatcher;
|
|
61
|
+
export declare function resetPermissionMatcher(): void;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern-based Permissions
|
|
3
|
+
*
|
|
4
|
+
* Provides fine-grained permission control for tool executions using
|
|
5
|
+
* glob-pattern matching. Rules are evaluated in order; first match wins.
|
|
6
|
+
*
|
|
7
|
+
* Tool specifier format:
|
|
8
|
+
* Bash(npm run *) → matches Bash tool with commands starting "npm run "
|
|
9
|
+
* Edit(./src/**) → matches Edit tool with paths under ./src/
|
|
10
|
+
* Read(./.env) → matches Read tool on exactly ./.env
|
|
11
|
+
* WebFetch(domain:example.com) → matches WebFetch for a specific domain
|
|
12
|
+
* Bash → matches all Bash invocations (no pattern)
|
|
13
|
+
*
|
|
14
|
+
* Pattern rules:
|
|
15
|
+
* * → matches any characters except /
|
|
16
|
+
* ** → matches anything including /
|
|
17
|
+
*/
|
|
18
|
+
import { logger } from '../utils/logger.js';
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Pattern Matching
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Convert a glob pattern to a RegExp.
|
|
24
|
+
* ** → matches anything (including /)
|
|
25
|
+
* * → matches anything except /
|
|
26
|
+
*/
|
|
27
|
+
function globToRegex(pattern) {
|
|
28
|
+
let result = '';
|
|
29
|
+
let i = 0;
|
|
30
|
+
while (i < pattern.length) {
|
|
31
|
+
const char = pattern[i];
|
|
32
|
+
if (char === '*' && pattern[i + 1] === '*') {
|
|
33
|
+
// ** matches anything including /
|
|
34
|
+
result += '.*';
|
|
35
|
+
i += 2;
|
|
36
|
+
// skip trailing / after **
|
|
37
|
+
if (pattern[i] === '/') {
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (char === '*') {
|
|
42
|
+
// * matches anything except /
|
|
43
|
+
result += '[^/]*';
|
|
44
|
+
i++;
|
|
45
|
+
}
|
|
46
|
+
else if (char === '?') {
|
|
47
|
+
result += '[^/]';
|
|
48
|
+
i++;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Escape regex special characters
|
|
52
|
+
result += char.replace(/[.+^${}()|[\]\\]/g, '\\$&');
|
|
53
|
+
i++;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return new RegExp('^' + result + '$');
|
|
57
|
+
}
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// PermissionPatternMatcher
|
|
60
|
+
// ============================================================================
|
|
61
|
+
export class PermissionPatternMatcher {
|
|
62
|
+
rules = [];
|
|
63
|
+
/**
|
|
64
|
+
* Add a permission rule.
|
|
65
|
+
*/
|
|
66
|
+
addRule(rule) {
|
|
67
|
+
this.rules.push(rule);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Check permission for a tool call. Evaluates rules in order; first match wins.
|
|
71
|
+
* If no rule matches, returns 'ask' as default.
|
|
72
|
+
*/
|
|
73
|
+
checkPermission(tool, input) {
|
|
74
|
+
for (const rule of this.rules) {
|
|
75
|
+
if (rule.tool !== tool) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
// If rule has no pattern, it matches all invocations of this tool
|
|
79
|
+
if (!rule.pattern) {
|
|
80
|
+
return rule.action;
|
|
81
|
+
}
|
|
82
|
+
// Domain-based matching for WebFetch
|
|
83
|
+
if (rule.pattern.startsWith('domain:')) {
|
|
84
|
+
const domain = rule.pattern.slice('domain:'.length);
|
|
85
|
+
if (input.includes(domain)) {
|
|
86
|
+
return rule.action;
|
|
87
|
+
}
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
// Glob pattern matching
|
|
91
|
+
const regex = globToRegex(rule.pattern);
|
|
92
|
+
if (regex.test(input)) {
|
|
93
|
+
return rule.action;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Default: ask
|
|
97
|
+
return 'ask';
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Parse a tool specifier string like "Bash(npm run *)" into components.
|
|
101
|
+
*/
|
|
102
|
+
parseToolSpecifier(spec) {
|
|
103
|
+
const match = spec.match(/^([A-Za-z_]+)(?:\((.+)\))?$/);
|
|
104
|
+
if (!match) {
|
|
105
|
+
throw new Error(`Invalid tool specifier: ${spec}`);
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
tool: match[1],
|
|
109
|
+
pattern: match[2] || undefined,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Load rules from an array of strings like "allow:Bash(npm run *)".
|
|
114
|
+
*/
|
|
115
|
+
loadRules(ruleStrings) {
|
|
116
|
+
for (const ruleStr of ruleStrings) {
|
|
117
|
+
const colonIndex = ruleStr.indexOf(':');
|
|
118
|
+
if (colonIndex === -1) {
|
|
119
|
+
logger.warn('Invalid rule string (missing action prefix)', { rule: ruleStr });
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const action = ruleStr.slice(0, colonIndex);
|
|
123
|
+
if (action !== 'allow' && action !== 'ask' && action !== 'deny') {
|
|
124
|
+
logger.warn('Invalid permission action', { action, rule: ruleStr });
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const specStr = ruleStr.slice(colonIndex + 1);
|
|
128
|
+
const spec = this.parseToolSpecifier(specStr);
|
|
129
|
+
this.addRule({
|
|
130
|
+
tool: spec.tool,
|
|
131
|
+
pattern: spec.pattern,
|
|
132
|
+
action,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get all current rules.
|
|
138
|
+
*/
|
|
139
|
+
getRules() {
|
|
140
|
+
return [...this.rules];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Clear all rules.
|
|
144
|
+
*/
|
|
145
|
+
clearRules() {
|
|
146
|
+
this.rules = [];
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Remove a rule by index.
|
|
150
|
+
*/
|
|
151
|
+
removeRule(index) {
|
|
152
|
+
if (index < 0 || index >= this.rules.length) {
|
|
153
|
+
throw new Error(`Rule index out of bounds: ${index}`);
|
|
154
|
+
}
|
|
155
|
+
this.rules.splice(index, 1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// ============================================================================
|
|
159
|
+
// Singleton
|
|
160
|
+
// ============================================================================
|
|
161
|
+
let instance = null;
|
|
162
|
+
export function getPermissionMatcher() {
|
|
163
|
+
if (!instance) {
|
|
164
|
+
instance = new PermissionPatternMatcher();
|
|
165
|
+
}
|
|
166
|
+
return instance;
|
|
167
|
+
}
|
|
168
|
+
export function resetPermissionMatcher() {
|
|
169
|
+
instance = null;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=permission-patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-patterns.js","sourceRoot":"","sources":["../../src/security/permission-patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe Binaries System
|
|
3
|
+
*
|
|
4
|
+
* Maintains a list of commands that are safe to execute without
|
|
5
|
+
* user approval. These are read-only or informational commands
|
|
6
|
+
* that cannot modify the filesystem or system state.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SAFE_BINARIES: readonly string[];
|
|
9
|
+
export declare class SafeBinariesChecker {
|
|
10
|
+
private static instance;
|
|
11
|
+
private safeBinaries;
|
|
12
|
+
private customized;
|
|
13
|
+
private constructor();
|
|
14
|
+
static getInstance(): SafeBinariesChecker;
|
|
15
|
+
static resetInstance(): void;
|
|
16
|
+
isSafe(command: string): boolean;
|
|
17
|
+
isSafeChain(command: string): boolean;
|
|
18
|
+
getSafeBinaries(): string[];
|
|
19
|
+
addSafeBinary(name: string): void;
|
|
20
|
+
removeSafeBinary(name: string): void;
|
|
21
|
+
isCustomized(): boolean;
|
|
22
|
+
private extractFirstWord;
|
|
23
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe Binaries System
|
|
3
|
+
*
|
|
4
|
+
* Maintains a list of commands that are safe to execute without
|
|
5
|
+
* user approval. These are read-only or informational commands
|
|
6
|
+
* that cannot modify the filesystem or system state.
|
|
7
|
+
*/
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Safe Binaries List
|
|
11
|
+
// ============================================================================
|
|
12
|
+
export const SAFE_BINARIES = [
|
|
13
|
+
'ls', 'cat', 'head', 'tail', 'wc', 'grep', 'rg', 'find',
|
|
14
|
+
'which', 'whoami', 'pwd', 'echo', 'date', 'uname', 'hostname',
|
|
15
|
+
'env', 'printenv', 'file', 'stat', 'du', 'df', 'free', 'uptime',
|
|
16
|
+
'id', 'groups', 'locale', 'tty', 'stty', 'basename', 'dirname',
|
|
17
|
+
'realpath', 'readlink', 'md5sum', 'sha256sum', 'sort', 'uniq',
|
|
18
|
+
'tr', 'cut', 'paste', 'diff', 'comm', 'tee', 'xargs', 'seq',
|
|
19
|
+
'yes', 'true', 'false', 'test', 'expr',
|
|
20
|
+
];
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// SafeBinariesChecker
|
|
23
|
+
// ============================================================================
|
|
24
|
+
export class SafeBinariesChecker {
|
|
25
|
+
static instance = null;
|
|
26
|
+
safeBinaries;
|
|
27
|
+
customized = false;
|
|
28
|
+
constructor() {
|
|
29
|
+
this.safeBinaries = new Set(SAFE_BINARIES);
|
|
30
|
+
}
|
|
31
|
+
static getInstance() {
|
|
32
|
+
if (!SafeBinariesChecker.instance) {
|
|
33
|
+
SafeBinariesChecker.instance = new SafeBinariesChecker();
|
|
34
|
+
}
|
|
35
|
+
return SafeBinariesChecker.instance;
|
|
36
|
+
}
|
|
37
|
+
static resetInstance() {
|
|
38
|
+
SafeBinariesChecker.instance = null;
|
|
39
|
+
}
|
|
40
|
+
isSafe(command) {
|
|
41
|
+
const trimmed = command.trim();
|
|
42
|
+
if (!trimmed)
|
|
43
|
+
return false;
|
|
44
|
+
const firstWord = this.extractFirstWord(trimmed);
|
|
45
|
+
return this.safeBinaries.has(firstWord);
|
|
46
|
+
}
|
|
47
|
+
isSafeChain(command) {
|
|
48
|
+
const trimmed = command.trim();
|
|
49
|
+
if (!trimmed)
|
|
50
|
+
return false;
|
|
51
|
+
// Split on pipes, &&, ||, and ;
|
|
52
|
+
const parts = trimmed.split(/\s*(?:\|{1,2}|&&|;)\s*/);
|
|
53
|
+
for (const part of parts) {
|
|
54
|
+
const cleaned = part.trim();
|
|
55
|
+
if (!cleaned)
|
|
56
|
+
continue;
|
|
57
|
+
if (!this.isSafe(cleaned)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
getSafeBinaries() {
|
|
64
|
+
return Array.from(this.safeBinaries).sort();
|
|
65
|
+
}
|
|
66
|
+
addSafeBinary(name) {
|
|
67
|
+
this.safeBinaries.add(name);
|
|
68
|
+
this.customized = true;
|
|
69
|
+
logger.debug('Added safe binary', { name });
|
|
70
|
+
}
|
|
71
|
+
removeSafeBinary(name) {
|
|
72
|
+
this.safeBinaries.delete(name);
|
|
73
|
+
this.customized = true;
|
|
74
|
+
logger.debug('Removed safe binary', { name });
|
|
75
|
+
}
|
|
76
|
+
isCustomized() {
|
|
77
|
+
return this.customized;
|
|
78
|
+
}
|
|
79
|
+
extractFirstWord(command) {
|
|
80
|
+
// Handle env var prefixes like FOO=bar cmd
|
|
81
|
+
let cmd = command;
|
|
82
|
+
while (/^\w+=\S*\s+/.test(cmd)) {
|
|
83
|
+
cmd = cmd.replace(/^\w+=\S*\s+/, '');
|
|
84
|
+
}
|
|
85
|
+
// Handle sudo/command prefixes
|
|
86
|
+
const prefixes = ['sudo', 'command', 'builtin'];
|
|
87
|
+
let firstWord = cmd.split(/\s+/)[0];
|
|
88
|
+
if (prefixes.includes(firstWord) && cmd.split(/\s+/).length > 1) {
|
|
89
|
+
firstWord = cmd.split(/\s+/)[1];
|
|
90
|
+
}
|
|
91
|
+
// Strip path prefix (e.g., /usr/bin/ls -> ls)
|
|
92
|
+
const basename = firstWord.split('/').pop() || firstWord;
|
|
93
|
+
return basename;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=safe-binaries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-binaries.js","sourceRoot":"","sources":["../../src/security/safe-binaries.ts"],"names":[],"mappings":"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"}
|