@matimo/core 0.1.0-alpha.10

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 (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/destructive-keywords.yaml +70 -0
  4. package/dist/approval/approval-handler.d.ts +74 -0
  5. package/dist/approval/approval-handler.d.ts.map +1 -0
  6. package/dist/approval/approval-handler.js +210 -0
  7. package/dist/approval/approval-handler.js.map +1 -0
  8. package/dist/auth/oauth2-config.d.ts +104 -0
  9. package/dist/auth/oauth2-config.d.ts.map +1 -0
  10. package/dist/auth/oauth2-config.js +38 -0
  11. package/dist/auth/oauth2-config.js.map +1 -0
  12. package/dist/auth/oauth2-handler.d.ts +130 -0
  13. package/dist/auth/oauth2-handler.d.ts.map +1 -0
  14. package/dist/auth/oauth2-handler.js +265 -0
  15. package/dist/auth/oauth2-handler.js.map +1 -0
  16. package/dist/auth/oauth2-provider-loader.d.ts +68 -0
  17. package/dist/auth/oauth2-provider-loader.d.ts.map +1 -0
  18. package/dist/auth/oauth2-provider-loader.js +120 -0
  19. package/dist/auth/oauth2-provider-loader.js.map +1 -0
  20. package/dist/core/schema.d.ts +259 -0
  21. package/dist/core/schema.d.ts.map +1 -0
  22. package/dist/core/schema.js +187 -0
  23. package/dist/core/schema.js.map +1 -0
  24. package/dist/core/tool-loader.d.ts +57 -0
  25. package/dist/core/tool-loader.d.ts.map +1 -0
  26. package/dist/core/tool-loader.js +250 -0
  27. package/dist/core/tool-loader.js.map +1 -0
  28. package/dist/core/tool-registry.d.ts +48 -0
  29. package/dist/core/tool-registry.d.ts.map +1 -0
  30. package/dist/core/tool-registry.js +93 -0
  31. package/dist/core/tool-registry.js.map +1 -0
  32. package/dist/core/types.d.ts +162 -0
  33. package/dist/core/types.d.ts.map +1 -0
  34. package/dist/core/types.js +5 -0
  35. package/dist/core/types.js.map +1 -0
  36. package/dist/decorators/index.d.ts +2 -0
  37. package/dist/decorators/index.d.ts.map +1 -0
  38. package/dist/decorators/index.js +2 -0
  39. package/dist/decorators/index.js.map +1 -0
  40. package/dist/decorators/tool-decorator.d.ts +97 -0
  41. package/dist/decorators/tool-decorator.d.ts.map +1 -0
  42. package/dist/decorators/tool-decorator.js +157 -0
  43. package/dist/decorators/tool-decorator.js.map +1 -0
  44. package/dist/encodings/parameter-encoding.d.ts +51 -0
  45. package/dist/encodings/parameter-encoding.d.ts.map +1 -0
  46. package/dist/encodings/parameter-encoding.js +124 -0
  47. package/dist/encodings/parameter-encoding.js.map +1 -0
  48. package/dist/errors/matimo-error.d.ts +41 -0
  49. package/dist/errors/matimo-error.d.ts.map +1 -0
  50. package/dist/errors/matimo-error.js +71 -0
  51. package/dist/errors/matimo-error.js.map +1 -0
  52. package/dist/executors/command-executor.d.ts +19 -0
  53. package/dist/executors/command-executor.d.ts.map +1 -0
  54. package/dist/executors/command-executor.js +98 -0
  55. package/dist/executors/command-executor.js.map +1 -0
  56. package/dist/executors/function-executor.d.ts +23 -0
  57. package/dist/executors/function-executor.d.ts.map +1 -0
  58. package/dist/executors/function-executor.js +181 -0
  59. package/dist/executors/function-executor.js.map +1 -0
  60. package/dist/executors/http-executor.d.ts +78 -0
  61. package/dist/executors/http-executor.d.ts.map +1 -0
  62. package/dist/executors/http-executor.js +279 -0
  63. package/dist/executors/http-executor.js.map +1 -0
  64. package/dist/index.d.ts +30 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +33 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/integrations/langchain.d.ts +46 -0
  69. package/dist/integrations/langchain.d.ts.map +1 -0
  70. package/dist/integrations/langchain.js +197 -0
  71. package/dist/integrations/langchain.js.map +1 -0
  72. package/dist/logging/index.d.ts +3 -0
  73. package/dist/logging/index.d.ts.map +1 -0
  74. package/dist/logging/index.js +3 -0
  75. package/dist/logging/index.js.map +1 -0
  76. package/dist/logging/logger.d.ts +96 -0
  77. package/dist/logging/logger.d.ts.map +1 -0
  78. package/dist/logging/logger.js +53 -0
  79. package/dist/logging/logger.js.map +1 -0
  80. package/dist/logging/winston-logger.d.ts +29 -0
  81. package/dist/logging/winston-logger.d.ts.map +1 -0
  82. package/dist/logging/winston-logger.js +73 -0
  83. package/dist/logging/winston-logger.js.map +1 -0
  84. package/dist/matimo-instance.d.ts +140 -0
  85. package/dist/matimo-instance.d.ts.map +1 -0
  86. package/dist/matimo-instance.js +412 -0
  87. package/dist/matimo-instance.js.map +1 -0
  88. package/package.json +96 -0
  89. package/tools/calculator/calculator.ts +145 -0
  90. package/tools/calculator/definition.yaml +70 -0
  91. package/tools/edit/definition.yaml +115 -0
  92. package/tools/edit/edit.ts +187 -0
  93. package/tools/execute/definition.yaml +90 -0
  94. package/tools/execute/execute.ts +207 -0
  95. package/tools/read/definition.yaml +106 -0
  96. package/tools/read/read.ts +118 -0
  97. package/tools/search/definition.yaml +148 -0
  98. package/tools/search/search.ts +192 -0
  99. package/tools/web/definition.yaml +132 -0
  100. package/tools/web/web.ts +134 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tallclub
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,252 @@
1
+ # @matimo/core — Core SDK for Matimo
2
+
3
+ Matimo core provides the TypeScript SDK that loads, validates, and executes YAML-defined tools across frameworks.
4
+
5
+ ## 📦 Installation
6
+
7
+ Install the unified package (includes core exports):
8
+
9
+ ```bash
10
+ # install unscope package which includes core and cli
11
+ npm install matimo
12
+ pnpm add matimo
13
+ # or install scoped core package directly
14
+ npm insatll @matimo/core
15
+ pnpm add @matimo/core
16
+ ```
17
+
18
+ ## 🔧 Purpose
19
+
20
+ `@matimo/core` contains:
21
+
22
+ - `MatimoInstance` — initialization, discovery, registry, and execution API
23
+ - **Executors** — Command (shell), HTTP (REST with object/array embedding), Function (JS/TS)
24
+ - Decorator utilities (`@tool`, `setGlobalMatimoInstance`)
25
+ - Zod-based schema validation for YAML tool definitions
26
+ - **Structured error handling** — `MatimoError` with error chaining via optional `cause` field
27
+ - OAuth2 authentication support (provider integrations in separate packages)
28
+
29
+ This package is intended to be imported by applications, CLIs, and provider packages.
30
+
31
+ ## 🚀 Quick Start
32
+
33
+ ```typescript
34
+ import { MatimoInstance } from 'matimo';
35
+
36
+ // Auto-discover installed @matimo/* tool packages
37
+ const matimo = await MatimoInstance.init({ autoDiscover: true });
38
+
39
+ // List tools
40
+ console.log('Loaded', matimo.listTools().length, 'tools');
41
+
42
+ // Execute a tool
43
+ await matimo.execute('calculator', { operation: 'add', a: 1, b: 2 });
44
+ ```
45
+
46
+ ## 🛠 Included Core Tools
47
+
48
+ `@matimo/core` includes 6 built-in tools for common operations:
49
+
50
+ - **`execute`** — Run shell commands with output capture, timeout, and working directory control
51
+ - **`read`** — Read files with line range support and encoding detection
52
+ - **`edit`** — Edit/replace content in files with backup
53
+ - **`search`** — Search files with grep patterns and context
54
+ - **`web`** — Fetch and parse web content
55
+ - **`calculator`** — Basic arithmetic operations
56
+
57
+ All core tools use **function-based execution** (not shell commands) for better performance and reliability.
58
+
59
+ ## 🧩 Usage Patterns
60
+
61
+ - Factory pattern: `MatimoInstance.init()` + `matimo.execute()`
62
+ - Decorator pattern: use `@tool()` and `setGlobalMatimoInstance()` for class-based code
63
+ - LangChain integration: convert Matimo tools to LangChain function schemas
64
+
65
+ See the full SDK docs: [docs/api-reference/SDK.md](../../docs/api-reference/SDK.md)
66
+
67
+ ## ⚙️ Executors
68
+
69
+ `@matimo/core` provides three execution engines:
70
+
71
+ ### FunctionExecutor (Recommended for Core Tools)
72
+ Executes TypeScript/JavaScript functions with type-safe parameters:
73
+ - ✅ **Direct execution** — No subprocess overhead
74
+ - ✅ **Better performance** — Direct async function calls
75
+ - ✅ **Type safety** — Proper TypeScript integration
76
+ - ✅ **Error handling** — Native exception handling
77
+
78
+ **Core tools** (`execute`, `read`, `edit`, `search`, `web`, `calculator`) all use function-based execution:
79
+ ```yaml
80
+ # Tool YAML:
81
+ execution:
82
+ type: function
83
+ code: './execute.ts' # Relative path to implementation
84
+
85
+ # File: execute.ts
86
+ export default async function execute(params: {
87
+ command: string
88
+ args?: string[]
89
+ cwd?: string
90
+ timeout?: number
91
+ }): Promise<{ success: boolean; stdout: string; stderr: string; exitCode: number }> {
92
+ // Implementation here
93
+ }
94
+ ```
95
+
96
+ ### HttpExecutor
97
+ Makes HTTP requests with automatic parameter embedding and response validation:
98
+ ```yaml
99
+ # Tool YAML:
100
+ execution:
101
+ type: http
102
+ method: POST
103
+ url: https://api.example.com/data
104
+ headers:
105
+ Authorization: 'Bearer {AUTH_TOKEN}'
106
+ body:
107
+ text: '{text}'
108
+ metadata: '{metadata}' # Objects/arrays automatically JSON-encoded
109
+ ```
110
+
111
+ **Key features:**
112
+ - ✅ **Parameter embedding** — Objects and arrays automatically JSON-encoded in request body
113
+ - ✅ **Response validation** — Validates output against `output_schema` using Zod
114
+ - ✅ **Error normalization** — Converts Axios/HTTP errors to structured `MatimoError`
115
+ - ✅ **Structured error details** — Original error preserved via `error.cause` field
116
+
117
+ ### CommandExecutor (Legacy Shell Execution)
118
+ Spawns shell processes for external commands:
119
+ ```typescript
120
+ // Tool YAML:
121
+ execution:
122
+ type: command
123
+ command: node
124
+ args: ["script.js", "{param1}"]
125
+
126
+ // Spawns: node script.js value1
127
+ ```
128
+
129
+ **Use when:**
130
+ - Executing external shell commands or legacy scripts
131
+ - Running tools from other packages that expect shell execution
132
+ - Most core Matimo tools now use function-based execution instead
133
+
134
+ ## 🚨 Error Handling
135
+
136
+ All executors throw `MatimoError` (never generic `Error`) with structured context:
137
+
138
+ ```typescript
139
+ import { MatimoError, ErrorCode } from '@matimo/core';
140
+
141
+ try {
142
+ await matimo.execute('my-tool', params);
143
+ } catch (error) {
144
+ if (error instanceof MatimoError) {
145
+ console.error(`Error: ${error.message}`);
146
+ console.error(`Code: ${error.code}`);
147
+ console.error(`Details:`, error.details);
148
+
149
+ // Access original exception (if available)
150
+ if (error.cause) {
151
+ console.error(`Original error:`, error.cause);
152
+ }
153
+ }
154
+ }
155
+ ```
156
+
157
+ **Error codes:**
158
+ - `INVALID_SCHEMA` — Tool definition or parameters invalid
159
+ - `EXECUTION_FAILED` — Tool execution failed (network, timeout, etc.)
160
+ - `AUTH_FAILED` — Authentication/authorization error
161
+ - `TOOL_NOT_FOUND` — Tool not found in registry
162
+
163
+ **Error chaining:**
164
+ The optional `cause` field preserves the original error for debugging:
165
+ ```typescript
166
+ throw new MatimoError('HTTP request failed', ErrorCode.EXECUTION_FAILED, {
167
+ toolName: 'slack_send',
168
+ statusCode: 500,
169
+ details: { originalError: axiosError }
170
+ });
171
+ // Access via: error.cause or error.details.originalError
172
+ ```
173
+
174
+ ## 🔐 Authentication & Security
175
+
176
+ Tools declare authentication requirements in YAML. `@matimo/core` supports:
177
+
178
+ - **API keys** (header/query injection)
179
+ - **Bearer/basic tokens** (automatic injection)
180
+ - **OAuth2** (provider configurations via OAuth2Handler)
181
+
182
+ Credentials are loaded from environment variables by convention:
183
+ ```bash
184
+ export SLACK_BOT_TOKEN=xoxb-...
185
+ export GMAIL_ACCESS_TOKEN=ya29-...
186
+ export NOTION_API_KEY=ntn_...
187
+ ```
188
+
189
+ **Security notes:**
190
+ - ✅ Secrets never logged (error messages exclude credential values)
191
+ - ✅ OAuth tokens refreshed automatically when expired
192
+ - ✅ HTTP Executor validates all authentication before making requests
193
+ - ✅ Missing credentials throw `MatimoError(AUTH_FAILED)` with helpful guidance
194
+
195
+ ## ✅ Validation & Output Schema
196
+
197
+ All tool execution includes automatic validation:
198
+
199
+ **Input Validation:**
200
+ - Tool YAML definitions validated against Zod schema on load
201
+ - Parameters validated against tool's declared `parameters` schema
202
+ - Invalid parameters throw `MatimoError(INVALID_SCHEMA)`
203
+
204
+ **Output Validation:**
205
+ - HTTP executor validates response against tool's `output_schema`
206
+ - Function executor validates return value against `output_schema` (for HTTP tools)
207
+ - Invalid responses/returns throw `MatimoError(EXECUTION_FAILED)`
208
+ - Zod provides detailed validation error messages
209
+
210
+ **Example (core `execute` tool):**
211
+ ```yaml
212
+ # Definition: packages/core/tools/execute/definition.yaml
213
+ execution:
214
+ type: function
215
+ code: './execute.ts'
216
+
217
+ output_schema:
218
+ type: object
219
+ properties:
220
+ success: { type: boolean }
221
+ exitCode: { type: number }
222
+ stdout: { type: string }
223
+ stderr: { type: string }
224
+ required: [success, exitCode, stdout, stderr]
225
+ ```
226
+
227
+ Invalid parameters or responses trigger validation errors with structured details.
228
+
229
+ ## 🧪 Testing & Development
230
+
231
+ To run core package tests:
232
+
233
+ ```bash
234
+ pnpm --filter "@matimo/core" test
235
+ ```
236
+
237
+ To build:
238
+
239
+ ```bash
240
+ pnpm --filter "@matimo/core" build
241
+ ```
242
+
243
+ ## 📚 Contributing
244
+
245
+ See the project CONTRIBUTING guide and `docs/tool-development/ADDING_TOOLS.md` for adding provider packages and tools.
246
+
247
+ - Contributing: https://github.com/tallclub/matimo/blob/main/CONTRIBUTING.md
248
+ - Add tools: ../../docs/tool-development/ADDING_TOOLS.md
249
+
250
+ ---
251
+
252
+ Part of the Matimo ecosystem — define tools once, use them everywhere.
@@ -0,0 +1,70 @@
1
+ # Destructive keywords used by ApprovalHandler and execution tools to auto-detect operations requiring approval
2
+ # These are checked against SQL content, command parameters, and shell commands to determine if approval is needed
3
+
4
+ sql:
5
+ - CREATE
6
+ - DELETE
7
+ - DROP
8
+ - ALTER
9
+ - TRUNCATE
10
+ - UPDATE
11
+ - INSERT
12
+ - UPSERT
13
+ - REPLACE
14
+ - MERGE
15
+ - GRANT
16
+ - REVOKE
17
+
18
+ file:
19
+ - EDIT
20
+ - WRITE
21
+ - APPEND
22
+ - REMOVE
23
+ - RENAME
24
+
25
+ system:
26
+ - SHUTDOWN
27
+ - EXECUTE
28
+ - EXEC
29
+ - system
30
+ - cmd
31
+ - shell
32
+ - bash
33
+ - powershell
34
+ - "rm -rf"
35
+ - "del /f"
36
+
37
+ shell_commands:
38
+ # File deletion/removal
39
+ - rm
40
+ - rmdir
41
+ - del
42
+ - "del /f"
43
+ - "rd /s"
44
+ # File/directory creation (modifies filesystem)
45
+ - mkdir
46
+ - mkfile
47
+ - touch
48
+ # File operations (modify destination)
49
+ - cp
50
+ - mv
51
+ - copy
52
+ - move
53
+ # Version control modifications
54
+ - "git push"
55
+ - "git merge"
56
+ - "git commit"
57
+ - "git reset"
58
+ - "git rebase"
59
+ # Database CLIs
60
+ - isql
61
+ - sqlcmd
62
+ - psql
63
+ - mysql
64
+ # Disk/system modifications
65
+ - format
66
+ - fastboot
67
+ - "adb shell su"
68
+ - "adb shell rm"
69
+ - "adb shell mount"
70
+ - "adb shell reboot"
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Approval request for any tool operation
3
+ */
4
+ export interface ApprovalRequest {
5
+ toolName: string;
6
+ description?: string;
7
+ params: Record<string, unknown>;
8
+ }
9
+ /**
10
+ * Generic approval callback - simple and scalable
11
+ * Returns true if approved, false if rejected or user declines
12
+ */
13
+ export type ApprovalCallback = (request: ApprovalRequest) => Promise<boolean>;
14
+ /**
15
+ * Generic, simple approval handler for all tools
16
+ *
17
+ * Design: Single, scalable approval flow for any number of tools
18
+ * - Tools declare requires_approval in YAML OR contain destructive keywords
19
+ * - Check MATIMO_AUTO_APPROVE env var (approve all)
20
+ * - Check MATIMO_APPROVED_PATTERNS env var (pre-approved patterns)
21
+ * - If not pre-approved, invoke single generic callback
22
+ * - No per-provider validators or custom logic needed
23
+ */
24
+ export declare class ApprovalHandler {
25
+ private autoApprove;
26
+ private approvedPatterns;
27
+ private approvalCallback;
28
+ private destructiveKeywords;
29
+ constructor();
30
+ /**
31
+ * Load destructive keywords from YAML configuration file
32
+ * Searches for destructive-keywords.yaml in:
33
+ * 1. packages/core/ (development/workspace)
34
+ * 2. node_modules/@matimo/core/ (installed package)
35
+ * 3. Relative to current working directory
36
+ */
37
+ private loadDestructiveKeywords;
38
+ /**
39
+ * Set default destructive keywords
40
+ */
41
+ private useDefaultKeywords;
42
+ /**
43
+ * Set approval callback for interactive/custom approval
44
+ */
45
+ setApprovalCallback(callback: ApprovalCallback): void;
46
+ /**
47
+ * Check if a tool requires approval based on YAML definition or supplied content.
48
+ * @param requiresApproval In Yaml - From tool definition `requires_approval` field
49
+ * @param content - Optional content (SQL, shell command, etc.) to check for destructive keywords
50
+ *
51
+ * Notes:
52
+ * - We now accept any textual content so keyword detection also applies to command/shell and sql
53
+ * based tools (e.g. `params.command`).
54
+ */
55
+ requiresApproval(requiresApprovalInYaml: boolean | undefined, content?: string): boolean;
56
+ /**
57
+ * Check if operation is pre-approved via env vars
58
+ */
59
+ isPreApproved(toolName: string): boolean;
60
+ /**
61
+ * Request approval for an operation
62
+ * Throws if not approved and no callback available
63
+ */
64
+ requestApproval(request: ApprovalRequest): Promise<void>;
65
+ /**
66
+ * Simple pattern matching (supports wildcards)
67
+ */
68
+ private matchesPattern;
69
+ }
70
+ /**
71
+ * Get or create global approval handler
72
+ */
73
+ export declare function getGlobalApprovalHandler(): ApprovalHandler;
74
+ //# sourceMappingURL=approval-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-handler.d.ts","sourceRoot":"","sources":["../../src/approval/approval-handler.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9E;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,mBAAmB,CAAgB;;IAsB3C;;;;;;OAMG;IACH,OAAO,CAAC,uBAAuB;IAqD/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAyB1B;;OAEG;IACH,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAIrD;;;;;;;;OAQG;IACH,gBAAgB,CAAC,sBAAsB,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;IAexF;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAgBxC;;;OAGG;IACG,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B9D;;OAEG;IACH,OAAO,CAAC,cAAc;CAavB;AAKD;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,eAAe,CAK1D"}
@@ -0,0 +1,210 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { MatimoError, ErrorCode } from '../errors/matimo-error';
4
+ /**
5
+ * Generic, simple approval handler for all tools
6
+ *
7
+ * Design: Single, scalable approval flow for any number of tools
8
+ * - Tools declare requires_approval in YAML OR contain destructive keywords
9
+ * - Check MATIMO_AUTO_APPROVE env var (approve all)
10
+ * - Check MATIMO_APPROVED_PATTERNS env var (pre-approved patterns)
11
+ * - If not pre-approved, invoke single generic callback
12
+ * - No per-provider validators or custom logic needed
13
+ */
14
+ export class ApprovalHandler {
15
+ constructor() {
16
+ this.autoApprove = false;
17
+ this.approvedPatterns = new Set();
18
+ this.approvalCallback = null;
19
+ this.destructiveKeywords = [];
20
+ // Load destructive keywords from YAML configuration
21
+ this.loadDestructiveKeywords();
22
+ // Load from environment variables
23
+ this.autoApprove = process.env.MATIMO_AUTO_APPROVE === 'true';
24
+ // Load pre-approved patterns (comma-separated)
25
+ // Example: "tool-name,pattern-*,prefix-*"
26
+ const approvedEnv = process.env.MATIMO_APPROVED_PATTERNS || '';
27
+ if (approvedEnv) {
28
+ approvedEnv.split(',').forEach((pattern) => {
29
+ const trimmed = pattern.trim();
30
+ if (trimmed) {
31
+ this.approvedPatterns.add(trimmed);
32
+ }
33
+ });
34
+ }
35
+ }
36
+ /**
37
+ * Load destructive keywords from YAML configuration file
38
+ * Searches for destructive-keywords.yaml in:
39
+ * 1. packages/core/ (development/workspace)
40
+ * 2. node_modules/@matimo/core/ (installed package)
41
+ * 3. Relative to current working directory
42
+ */
43
+ loadDestructiveKeywords() {
44
+ try {
45
+ // Possible locations for destructive-keywords.yaml
46
+ const possiblePaths = [
47
+ path.join(process.cwd(), 'packages/core/destructive-keywords.yaml'), // workspace root
48
+ path.join(process.cwd(), 'node_modules/@matimo/core/destructive-keywords.yaml'), // installed
49
+ path.join(process.cwd(), 'destructive-keywords.yaml'), // current directory
50
+ ];
51
+ let configContent = null;
52
+ for (const filePath of possiblePaths) {
53
+ try {
54
+ if (fs.existsSync(filePath)) {
55
+ configContent = fs.readFileSync(filePath, 'utf8');
56
+ break;
57
+ }
58
+ }
59
+ catch {
60
+ // Continue to next path
61
+ }
62
+ }
63
+ // If file not found, use fallback keywords defined below
64
+ if (!configContent) {
65
+ this.useDefaultKeywords();
66
+ return;
67
+ }
68
+ // Simple YAML parsing for flat structure
69
+ // Parse lines and extract keywords from each section
70
+ const lines = configContent.split('\n');
71
+ for (const line of lines) {
72
+ const trimmed = line.trim();
73
+ // Skip comments and empty lines and section headers
74
+ if (trimmed && !trimmed.startsWith('#') && !trimmed.endsWith(':')) {
75
+ // Extract keyword (remove leading dash and whitespace)
76
+ const keyword = trimmed.replace(/^-\s*/, '').trim();
77
+ if (keyword) {
78
+ this.destructiveKeywords.push(keyword);
79
+ }
80
+ }
81
+ }
82
+ // Fallback: If no keywords loaded, use defaults
83
+ if (this.destructiveKeywords.length === 0) {
84
+ this.useDefaultKeywords();
85
+ }
86
+ }
87
+ catch {
88
+ // Fallback to hardcoded keywords if file parsing fails
89
+ this.useDefaultKeywords();
90
+ }
91
+ }
92
+ /**
93
+ * Set default destructive keywords
94
+ */
95
+ useDefaultKeywords() {
96
+ this.destructiveKeywords = [
97
+ 'CREATE',
98
+ 'DELETE',
99
+ 'DROP',
100
+ 'ALTER',
101
+ 'TRUNCATE',
102
+ 'UPDATE',
103
+ 'INSERT',
104
+ 'UPSERT',
105
+ 'REPLACE',
106
+ 'MERGE',
107
+ 'GRANT',
108
+ 'REVOKE',
109
+ 'EDIT',
110
+ 'WRITE',
111
+ 'APPEND',
112
+ 'REMOVE',
113
+ 'RENAME',
114
+ 'SHUTDOWN',
115
+ 'EXECUTE',
116
+ 'EXEC',
117
+ ];
118
+ }
119
+ /**
120
+ * Set approval callback for interactive/custom approval
121
+ */
122
+ setApprovalCallback(callback) {
123
+ this.approvalCallback = callback;
124
+ }
125
+ /**
126
+ * Check if a tool requires approval based on YAML definition or supplied content.
127
+ * @param requiresApproval In Yaml - From tool definition `requires_approval` field
128
+ * @param content - Optional content (SQL, shell command, etc.) to check for destructive keywords
129
+ *
130
+ * Notes:
131
+ * - We now accept any textual content so keyword detection also applies to command/shell and sql
132
+ * based tools (e.g. `params.command`).
133
+ */
134
+ requiresApproval(requiresApprovalInYaml, content) {
135
+ // Explicit YAML definition takes precedence
136
+ if (requiresApprovalInYaml === true) {
137
+ return true;
138
+ }
139
+ // Check provided content (SQL, shell command, etc.) for destructive keywords
140
+ if (content) {
141
+ const upper = String(content).toUpperCase();
142
+ return this.destructiveKeywords.some((keyword) => upper.includes(keyword));
143
+ }
144
+ return false;
145
+ }
146
+ /**
147
+ * Check if operation is pre-approved via env vars
148
+ */
149
+ isPreApproved(toolName) {
150
+ // Auto-approve everything
151
+ if (this.autoApprove) {
152
+ return true;
153
+ }
154
+ // Check against patterns
155
+ for (const pattern of this.approvedPatterns) {
156
+ if (this.matchesPattern(toolName, pattern)) {
157
+ return true;
158
+ }
159
+ }
160
+ return false;
161
+ }
162
+ /**
163
+ * Request approval for an operation
164
+ * Throws if not approved and no callback available
165
+ */
166
+ async requestApproval(request) {
167
+ // If no callback set, fail safely
168
+ if (!this.approvalCallback) {
169
+ throw new MatimoError(`Destructive operation requires approval: ${request.toolName}`, ErrorCode.EXECUTION_FAILED, {
170
+ toolName: request.toolName,
171
+ hint: 'Set MATIMO_AUTO_APPROVE=true or MATIMO_APPROVED_PATTERNS or install approval callback',
172
+ });
173
+ }
174
+ // Call callback to get approval
175
+ const approved = await this.approvalCallback(request);
176
+ if (!approved) {
177
+ throw new MatimoError(`Operation rejected by approval handler: ${request.toolName}`, ErrorCode.EXECUTION_FAILED, {
178
+ toolName: request.toolName,
179
+ message: 'User or policy rejected the operation',
180
+ });
181
+ }
182
+ }
183
+ /**
184
+ * Simple pattern matching (supports wildcards)
185
+ */
186
+ matchesPattern(toolName, pattern) {
187
+ if (pattern === '*') {
188
+ return true;
189
+ }
190
+ // Convert glob pattern to regex:
191
+ // 1. Escape all regex metacharacters, including backslashes.
192
+ // 2. Turn escaped '*' back into a wildcard '.*'.
193
+ const escapedPattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
194
+ const regexPattern = escapedPattern.replace(/\\\*/g, '.*');
195
+ const regex = new RegExp(`^${regexPattern}$`, 'i');
196
+ return regex.test(toolName);
197
+ }
198
+ }
199
+ // Global instance
200
+ let globalApprovalHandler = null;
201
+ /**
202
+ * Get or create global approval handler
203
+ */
204
+ export function getGlobalApprovalHandler() {
205
+ if (!globalApprovalHandler) {
206
+ globalApprovalHandler = new ApprovalHandler();
207
+ }
208
+ return globalApprovalHandler;
209
+ }
210
+ //# sourceMappingURL=approval-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-handler.js","sourceRoot":"","sources":["../../src/approval/approval-handler.ts"],"names":[],"mappings":"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"}