@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.
Files changed (273) hide show
  1. package/dist/agent/background-tasks.d.ts +49 -0
  2. package/dist/agent/background-tasks.js +153 -0
  3. package/dist/agent/background-tasks.js.map +1 -0
  4. package/dist/agent/definitions/agent-definition-loader.d.ts +21 -0
  5. package/dist/agent/definitions/agent-definition-loader.js +161 -0
  6. package/dist/agent/definitions/agent-definition-loader.js.map +1 -0
  7. package/dist/agent/definitions/index.d.ts +1 -0
  8. package/dist/agent/definitions/index.js +2 -0
  9. package/dist/agent/definitions/index.js.map +1 -0
  10. package/dist/agent/extended-thinking.d.ts +64 -0
  11. package/dist/agent/extended-thinking.js +103 -0
  12. package/dist/agent/extended-thinking.js.map +1 -0
  13. package/dist/agent/prompt-suggestions.d.ts +55 -0
  14. package/dist/agent/prompt-suggestions.js +125 -0
  15. package/dist/agent/prompt-suggestions.js.map +1 -0
  16. package/dist/agent/rewind-manager.d.ts +59 -0
  17. package/dist/agent/rewind-manager.js +124 -0
  18. package/dist/agent/rewind-manager.js.map +1 -0
  19. package/dist/agent/teams/agent-team.d.ts +54 -0
  20. package/dist/agent/teams/agent-team.js +114 -0
  21. package/dist/agent/teams/agent-team.js.map +1 -0
  22. package/dist/agent/teams/index.d.ts +1 -0
  23. package/dist/agent/teams/index.js +2 -0
  24. package/dist/agent/teams/index.js.map +1 -0
  25. package/dist/agent/teams/team-v2.d.ts +166 -0
  26. package/dist/agent/teams/team-v2.js +376 -0
  27. package/dist/agent/teams/team-v2.js.map +1 -0
  28. package/dist/channels/imessage/index.d.ts +40 -0
  29. package/dist/channels/imessage/index.js +69 -0
  30. package/dist/channels/imessage/index.js.map +1 -0
  31. package/dist/channels/line/index.d.ts +36 -0
  32. package/dist/channels/line/index.js +71 -0
  33. package/dist/channels/line/index.js.map +1 -0
  34. package/dist/channels/mattermost/index.d.ts +34 -0
  35. package/dist/channels/mattermost/index.js +56 -0
  36. package/dist/channels/mattermost/index.js.map +1 -0
  37. package/dist/channels/nextcloud-talk/index.d.ts +37 -0
  38. package/dist/channels/nextcloud-talk/index.js +67 -0
  39. package/dist/channels/nextcloud-talk/index.js.map +1 -0
  40. package/dist/channels/niche-channels.d.ts +61 -0
  41. package/dist/channels/niche-channels.js +131 -0
  42. package/dist/channels/niche-channels.js.map +1 -0
  43. package/dist/channels/nostr/index.d.ts +30 -0
  44. package/dist/channels/nostr/index.js +68 -0
  45. package/dist/channels/nostr/index.js.map +1 -0
  46. package/dist/channels/twilio-voice/index.d.ts +37 -0
  47. package/dist/channels/twilio-voice/index.js +76 -0
  48. package/dist/channels/twilio-voice/index.js.map +1 -0
  49. package/dist/channels/whatsapp/index.js +0 -1
  50. package/dist/channels/whatsapp/index.js.map +1 -1
  51. package/dist/channels/zalo/index.d.ts +28 -0
  52. package/dist/channels/zalo/index.js +53 -0
  53. package/dist/channels/zalo/index.js.map +1 -0
  54. package/dist/cloud/cloud-sessions.d.ts +56 -0
  55. package/dist/cloud/cloud-sessions.js +187 -0
  56. package/dist/cloud/cloud-sessions.js.map +1 -0
  57. package/dist/codebuddy/tool-definitions/advanced-tools.d.ts +1 -0
  58. package/dist/codebuddy/tool-definitions/advanced-tools.js +24 -0
  59. package/dist/codebuddy/tool-definitions/advanced-tools.js.map +1 -1
  60. package/dist/codebuddy/tool-definitions/index.d.ts +1 -1
  61. package/dist/codebuddy/tool-definitions/index.js +1 -1
  62. package/dist/codebuddy/tool-definitions/index.js.map +1 -1
  63. package/dist/commands/handlers/auth-handler.d.ts +32 -0
  64. package/dist/commands/handlers/auth-handler.js +137 -0
  65. package/dist/commands/handlers/auth-handler.js.map +1 -0
  66. package/dist/commands/handlers/context-handler.d.ts +46 -0
  67. package/dist/commands/handlers/context-handler.js +102 -0
  68. package/dist/commands/handlers/context-handler.js.map +1 -0
  69. package/dist/commands/handlers/keybindings-handler.d.ts +30 -0
  70. package/dist/commands/handlers/keybindings-handler.js +124 -0
  71. package/dist/commands/handlers/keybindings-handler.js.map +1 -0
  72. package/dist/commands/handlers/session-commands.d.ts +17 -0
  73. package/dist/commands/handlers/session-commands.js +119 -0
  74. package/dist/commands/handlers/session-commands.js.map +1 -0
  75. package/dist/commands/slash/builtin-commands.js +1 -1
  76. package/dist/commands/slash/builtin-commands.js.map +1 -1
  77. package/dist/config/admin-config.d.ts +54 -0
  78. package/dist/config/admin-config.js +144 -0
  79. package/dist/config/admin-config.js.map +1 -0
  80. package/dist/config/advanced-config.d.ts +118 -0
  81. package/dist/config/advanced-config.js +364 -0
  82. package/dist/config/advanced-config.js.map +1 -0
  83. package/dist/config/managed-policies.d.ts +50 -0
  84. package/dist/config/managed-policies.js +120 -0
  85. package/dist/config/managed-policies.js.map +1 -0
  86. package/dist/config/settings-hierarchy.d.ts +59 -0
  87. package/dist/config/settings-hierarchy.js +188 -0
  88. package/dist/config/settings-hierarchy.js.map +1 -0
  89. package/dist/config/tool-profiles.d.ts +37 -0
  90. package/dist/config/tool-profiles.js +150 -0
  91. package/dist/config/tool-profiles.js.map +1 -0
  92. package/dist/config/user-settings.d.ts +31 -0
  93. package/dist/config/user-settings.js +66 -0
  94. package/dist/config/user-settings.js.map +1 -0
  95. package/dist/context/context-files.d.ts +1 -1
  96. package/dist/context/context-files.js +2 -2
  97. package/dist/context/context-files.js.map +1 -1
  98. package/dist/context/partial-summarizer.d.ts +32 -0
  99. package/dist/context/partial-summarizer.js +144 -0
  100. package/dist/context/partial-summarizer.js.map +1 -0
  101. package/dist/desktop/desktop-app.d.ts +44 -0
  102. package/dist/desktop/desktop-app.js +136 -0
  103. package/dist/desktop/desktop-app.js.map +1 -0
  104. package/dist/git/worktree-sessions.d.ts +24 -0
  105. package/dist/git/worktree-sessions.js +93 -0
  106. package/dist/git/worktree-sessions.js.map +1 -0
  107. package/dist/hooks/advanced-hooks.d.ts +110 -0
  108. package/dist/hooks/advanced-hooks.js +256 -0
  109. package/dist/hooks/advanced-hooks.js.map +1 -0
  110. package/dist/hooks/async-hooks.d.ts +73 -0
  111. package/dist/hooks/async-hooks.js +213 -0
  112. package/dist/hooks/async-hooks.js.map +1 -0
  113. package/dist/hooks/env-persistence.d.ts +58 -0
  114. package/dist/hooks/env-persistence.js +195 -0
  115. package/dist/hooks/env-persistence.js.map +1 -0
  116. package/dist/hooks/hook-events.d.ts +36 -0
  117. package/dist/hooks/hook-events.js +55 -0
  118. package/dist/hooks/hook-events.js.map +1 -0
  119. package/dist/hooks/smart-hooks.d.ts +85 -0
  120. package/dist/hooks/smart-hooks.js +199 -0
  121. package/dist/hooks/smart-hooks.js.map +1 -0
  122. package/dist/ide/jetbrains-plugin.d.ts +55 -0
  123. package/dist/ide/jetbrains-plugin.js +156 -0
  124. package/dist/ide/jetbrains-plugin.js.map +1 -0
  125. package/dist/ide/vscode-extension.d.ts +94 -0
  126. package/dist/ide/vscode-extension.js +229 -0
  127. package/dist/ide/vscode-extension.js.map +1 -0
  128. package/dist/index.js +77 -3
  129. package/dist/index.js.map +1 -1
  130. package/dist/input/file-autocomplete.d.ts +42 -0
  131. package/dist/input/file-autocomplete.js +154 -0
  132. package/dist/input/file-autocomplete.js.map +1 -0
  133. package/dist/integrations/chrome-bridge.d.ts +90 -0
  134. package/dist/integrations/chrome-bridge.js +151 -0
  135. package/dist/integrations/chrome-bridge.js.map +1 -0
  136. package/dist/integrations/github-action-runner.d.ts +40 -0
  137. package/dist/integrations/github-action-runner.js +163 -0
  138. package/dist/integrations/github-action-runner.js.map +1 -0
  139. package/dist/integrations/gitlab-ci-runner.d.ts +34 -0
  140. package/dist/integrations/gitlab-ci-runner.js +104 -0
  141. package/dist/integrations/gitlab-ci-runner.js.map +1 -0
  142. package/dist/integrations/pr-session-linker.d.ts +44 -0
  143. package/dist/integrations/pr-session-linker.js +103 -0
  144. package/dist/integrations/pr-session-linker.js.map +1 -0
  145. package/dist/integrations/tailscale.d.ts +36 -0
  146. package/dist/integrations/tailscale.js +101 -0
  147. package/dist/integrations/tailscale.js.map +1 -0
  148. package/dist/lsp/lsp-client.d.ts +68 -0
  149. package/dist/lsp/lsp-client.js +182 -0
  150. package/dist/lsp/lsp-client.js.map +1 -0
  151. package/dist/mcp/connectors.d.ts +28 -0
  152. package/dist/mcp/connectors.js +148 -0
  153. package/dist/mcp/connectors.js.map +1 -0
  154. package/dist/mcp/index.d.ts +7 -4
  155. package/dist/mcp/index.js +7 -4
  156. package/dist/mcp/index.js.map +1 -1
  157. package/dist/mcp/mcp-auto-discovery.d.ts +49 -0
  158. package/dist/mcp/mcp-auto-discovery.js +104 -0
  159. package/dist/mcp/mcp-auto-discovery.js.map +1 -0
  160. package/dist/mcp/mcp-server.d.ts +70 -0
  161. package/dist/mcp/mcp-server.js +374 -0
  162. package/dist/mcp/mcp-server.js.map +1 -0
  163. package/dist/memory/auto-memory.d.ts +53 -0
  164. package/dist/memory/auto-memory.js +250 -0
  165. package/dist/memory/auto-memory.js.map +1 -0
  166. package/dist/memory/hybrid-search.d.ts +51 -0
  167. package/dist/memory/hybrid-search.js +199 -0
  168. package/dist/memory/hybrid-search.js.map +1 -0
  169. package/dist/memory/memory-flush.d.ts +51 -0
  170. package/dist/memory/memory-flush.js +102 -0
  171. package/dist/memory/memory-flush.js.map +1 -0
  172. package/dist/memory/subagent-memory.d.ts +73 -0
  173. package/dist/memory/subagent-memory.js +172 -0
  174. package/dist/memory/subagent-memory.js.map +1 -0
  175. package/dist/nodes/device-node.d.ts +40 -0
  176. package/dist/nodes/device-node.js +117 -0
  177. package/dist/nodes/device-node.js.map +1 -0
  178. package/dist/output/json-schema-output.d.ts +67 -0
  179. package/dist/output/json-schema-output.js +273 -0
  180. package/dist/output/json-schema-output.js.map +1 -0
  181. package/dist/persistence/session-picker.d.ts +22 -0
  182. package/dist/persistence/session-picker.js +47 -0
  183. package/dist/persistence/session-picker.js.map +1 -0
  184. package/dist/persistence/session-store.d.ts +11 -0
  185. package/dist/persistence/session-store.js +17 -0
  186. package/dist/persistence/session-store.js.map +1 -1
  187. package/dist/plugins/git-pinned-marketplace.d.ts +39 -0
  188. package/dist/plugins/git-pinned-marketplace.js +152 -0
  189. package/dist/plugins/git-pinned-marketplace.js.map +1 -0
  190. package/dist/plugins/plugin-manifest.d.ts +116 -0
  191. package/dist/plugins/plugin-manifest.js +283 -0
  192. package/dist/plugins/plugin-manifest.js.map +1 -0
  193. package/dist/sandbox/os-sandbox.d.ts +49 -1
  194. package/dist/sandbox/os-sandbox.js +347 -6
  195. package/dist/sandbox/os-sandbox.js.map +1 -1
  196. package/dist/sdk/agent-sdk.d.ts +61 -0
  197. package/dist/sdk/agent-sdk.js +90 -0
  198. package/dist/sdk/agent-sdk.js.map +1 -0
  199. package/dist/security/permission-modes.d.ts +76 -0
  200. package/dist/security/permission-modes.js +195 -0
  201. package/dist/security/permission-modes.js.map +1 -0
  202. package/dist/security/permission-patterns.d.ts +61 -0
  203. package/dist/security/permission-patterns.js +171 -0
  204. package/dist/security/permission-patterns.js.map +1 -0
  205. package/dist/security/safe-binaries.d.ts +23 -0
  206. package/dist/security/safe-binaries.js +96 -0
  207. package/dist/security/safe-binaries.js.map +1 -0
  208. package/dist/security/sender-policies.d.ts +46 -0
  209. package/dist/security/sender-policies.js +90 -0
  210. package/dist/security/sender-policies.js.map +1 -0
  211. package/dist/server/dashboard.d.ts +53 -0
  212. package/dist/server/dashboard.js +93 -0
  213. package/dist/server/dashboard.js.map +1 -0
  214. package/dist/services/system-prompt-override.d.ts +34 -0
  215. package/dist/services/system-prompt-override.js +64 -0
  216. package/dist/services/system-prompt-override.js.map +1 -0
  217. package/dist/skills/skill-enhancements.d.ts +37 -0
  218. package/dist/skills/skill-enhancements.js +69 -0
  219. package/dist/skills/skill-enhancements.js.map +1 -0
  220. package/dist/telemetry/otel-tracer.d.ts +98 -0
  221. package/dist/telemetry/otel-tracer.js +245 -0
  222. package/dist/telemetry/otel-tracer.js.map +1 -0
  223. package/dist/tools/browser-stub.d.ts +61 -0
  224. package/dist/tools/browser-stub.js +184 -0
  225. package/dist/tools/browser-stub.js.map +1 -0
  226. package/dist/tools/gateway-tool.d.ts +43 -0
  227. package/dist/tools/gateway-tool.js +92 -0
  228. package/dist/tools/gateway-tool.js.map +1 -0
  229. package/dist/tools/image-stub.d.ts +32 -0
  230. package/dist/tools/image-stub.js +97 -0
  231. package/dist/tools/image-stub.js.map +1 -0
  232. package/dist/tools/js-repl.d.ts +78 -0
  233. package/dist/tools/js-repl.js +280 -0
  234. package/dist/tools/js-repl.js.map +1 -0
  235. package/dist/tools/message-tool.d.ts +42 -0
  236. package/dist/tools/message-tool.js +113 -0
  237. package/dist/tools/message-tool.js.map +1 -0
  238. package/dist/ui/cli-enhancements.d.ts +178 -0
  239. package/dist/ui/cli-enhancements.js +430 -0
  240. package/dist/ui/cli-enhancements.js.map +1 -0
  241. package/dist/ui/status-line.d.ts +90 -0
  242. package/dist/ui/status-line.js +160 -0
  243. package/dist/ui/status-line.js.map +1 -0
  244. package/dist/ui/terminal-enhancements.d.ts +34 -0
  245. package/dist/ui/terminal-enhancements.js +97 -0
  246. package/dist/ui/terminal-enhancements.js.map +1 -0
  247. package/dist/ui/ui-enhancements.d.ts +38 -0
  248. package/dist/ui/ui-enhancements.js +116 -0
  249. package/dist/ui/ui-enhancements.js.map +1 -0
  250. package/dist/utils/custom-instructions.js +4 -1
  251. package/dist/utils/custom-instructions.js.map +1 -1
  252. package/dist/utils/init-project.d.ts +1 -1
  253. package/dist/utils/init-project.js +20 -20
  254. package/dist/utils/init-project.js.map +1 -1
  255. package/dist/utils/output-schema-validator.d.ts +40 -0
  256. package/dist/utils/output-schema-validator.js +137 -0
  257. package/dist/utils/output-schema-validator.js.map +1 -0
  258. package/dist/utils/safety-misc.d.ts +24 -0
  259. package/dist/utils/safety-misc.js +91 -0
  260. package/dist/utils/safety-misc.js.map +1 -0
  261. package/dist/utils/session-enhancements.d.ts +40 -0
  262. package/dist/utils/session-enhancements.js +118 -0
  263. package/dist/utils/session-enhancements.js.map +1 -0
  264. package/dist/utils/shell-snapshot.d.ts +38 -0
  265. package/dist/utils/shell-snapshot.js +323 -0
  266. package/dist/utils/shell-snapshot.js.map +1 -0
  267. package/dist/utils/stream-json-formatter.d.ts +77 -0
  268. package/dist/utils/stream-json-formatter.js +61 -0
  269. package/dist/utils/stream-json-formatter.js.map +1 -0
  270. package/dist/workflows/lobster-engine.d.ts +43 -0
  271. package/dist/workflows/lobster-engine.js +167 -0
  272. package/dist/workflows/lobster-engine.js.map +1 -0
  273. 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":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IACvD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;IAC7D,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ;IAC/D,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS;IAC9D,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM;IAC7D,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK;IAC3D,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM;CAC9B,CAAC;AAEX,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E,MAAM,OAAO,mBAAmB;IACtB,MAAM,CAAC,QAAQ,GAA+B,IAAI,CAAC;IAEnD,YAAY,CAAc;IAC1B,UAAU,GAAG,KAAK,CAAC;IAE3B;QACE,IAAI,CAAC,YAAY,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC;YAClC,mBAAmB,CAAC,QAAQ,GAAG,IAAI,mBAAmB,EAAE,CAAC;QAC3D,CAAC;QACD,OAAO,mBAAmB,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED,MAAM,CAAC,aAAa;QAClB,mBAAmB,CAAC,QAAQ,GAAG,IAAI,CAAC;IACtC,CAAC;IAED,MAAM,CAAC,OAAe;QACpB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAE3B,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,WAAW,CAAC,OAAe;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAE3B,gCAAgC;QAChC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAEtD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,eAAe;QACb,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAED,aAAa,CAAC,IAAY;QACxB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,gBAAgB,CAAC,IAAY;QAC3B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAEO,gBAAgB,CAAC,OAAe;QACtC,2CAA2C;QAC3C,IAAI,GAAG,GAAG,OAAO,CAAC;QAClB,OAAO,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,+BAA+B;QAC/B,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAChD,IAAI,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEpC,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC;QAED,8CAA8C;QAC9C,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,SAAS,CAAC;QACzD,OAAO,QAAQ,CAAC;IAClB,CAAC"}