matimo 0.1.0-alpha.8 → 0.1.1
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/package.json +10 -8
- package/packages/cli/dist/bin.d.ts +3 -0
- package/packages/cli/dist/bin.d.ts.map +1 -0
- package/packages/cli/dist/bin.js +50 -0
- package/packages/cli/dist/bin.js.map +1 -0
- package/packages/cli/dist/cli.d.ts.map +1 -1
- package/packages/cli/dist/cli.js +64 -2
- package/packages/cli/dist/cli.js.map +1 -1
- package/packages/cli/dist/commands/doctor.d.ts +2 -0
- package/packages/cli/dist/commands/doctor.d.ts.map +1 -0
- package/packages/cli/dist/commands/doctor.js +174 -0
- package/packages/cli/dist/commands/doctor.js.map +1 -0
- package/packages/cli/dist/commands/mcp-setup.d.ts +9 -0
- package/packages/cli/dist/commands/mcp-setup.d.ts.map +1 -0
- package/packages/cli/dist/commands/mcp-setup.js +106 -0
- package/packages/cli/dist/commands/mcp-setup.js.map +1 -0
- package/packages/cli/dist/commands/mcp.d.ts +17 -0
- package/packages/cli/dist/commands/mcp.d.ts.map +1 -0
- package/packages/cli/dist/commands/mcp.js +228 -0
- package/packages/cli/dist/commands/mcp.js.map +1 -0
- package/packages/cli/dist/commands/review.d.ts +10 -0
- package/packages/cli/dist/commands/review.d.ts.map +1 -0
- package/packages/cli/dist/commands/review.js +176 -0
- package/packages/cli/dist/commands/review.js.map +1 -0
- package/packages/core/dist/approval/approval-handler.d.ts +5 -1
- package/packages/core/dist/approval/approval-handler.d.ts.map +1 -1
- package/packages/core/dist/approval/approval-handler.js +6 -0
- package/packages/core/dist/approval/approval-handler.js.map +1 -1
- package/packages/core/dist/core/schema.d.ts +41 -10
- package/packages/core/dist/core/schema.d.ts.map +1 -1
- package/packages/core/dist/core/schema.js +40 -4
- package/packages/core/dist/core/schema.js.map +1 -1
- package/packages/core/dist/core/skill-content-parser.d.ts +91 -0
- package/packages/core/dist/core/skill-content-parser.d.ts.map +1 -0
- package/packages/core/dist/core/skill-content-parser.js +248 -0
- package/packages/core/dist/core/skill-content-parser.js.map +1 -0
- package/packages/core/dist/core/skill-loader.d.ts +46 -0
- package/packages/core/dist/core/skill-loader.d.ts.map +1 -0
- package/packages/core/dist/core/skill-loader.js +310 -0
- package/packages/core/dist/core/skill-loader.js.map +1 -0
- package/packages/core/dist/core/skill-registry.d.ts +131 -0
- package/packages/core/dist/core/skill-registry.d.ts.map +1 -0
- package/packages/core/dist/core/skill-registry.js +316 -0
- package/packages/core/dist/core/skill-registry.js.map +1 -0
- package/packages/core/dist/core/tfidf-embedding.d.ts +45 -0
- package/packages/core/dist/core/tfidf-embedding.d.ts.map +1 -0
- package/packages/core/dist/core/tfidf-embedding.js +199 -0
- package/packages/core/dist/core/tfidf-embedding.js.map +1 -0
- package/packages/core/dist/core/tool-loader.d.ts +3 -1
- package/packages/core/dist/core/tool-loader.d.ts.map +1 -1
- package/packages/core/dist/core/tool-loader.js +33 -10
- package/packages/core/dist/core/tool-loader.js.map +1 -1
- package/packages/core/dist/core/types.d.ts +203 -6
- package/packages/core/dist/core/types.d.ts.map +1 -1
- package/packages/core/dist/encodings/parameter-encoding.d.ts +1 -1
- package/packages/core/dist/encodings/parameter-encoding.d.ts.map +1 -1
- package/packages/core/dist/encodings/parameter-encoding.js +9 -4
- package/packages/core/dist/encodings/parameter-encoding.js.map +1 -1
- package/packages/core/dist/errors/matimo-error.d.ts +11 -2
- package/packages/core/dist/errors/matimo-error.d.ts.map +1 -1
- package/packages/core/dist/errors/matimo-error.js +25 -1
- package/packages/core/dist/errors/matimo-error.js.map +1 -1
- package/packages/core/dist/executors/command-executor.d.ts +9 -2
- package/packages/core/dist/executors/command-executor.d.ts.map +1 -1
- package/packages/core/dist/executors/command-executor.js +29 -5
- package/packages/core/dist/executors/command-executor.js.map +1 -1
- package/packages/core/dist/executors/function-executor.d.ts +10 -3
- package/packages/core/dist/executors/function-executor.d.ts.map +1 -1
- package/packages/core/dist/executors/function-executor.js +44 -24
- package/packages/core/dist/executors/function-executor.js.map +1 -1
- package/packages/core/dist/executors/http-executor.d.ts +79 -4
- package/packages/core/dist/executors/http-executor.d.ts.map +1 -1
- package/packages/core/dist/executors/http-executor.js +232 -28
- package/packages/core/dist/executors/http-executor.js.map +1 -1
- package/packages/core/dist/index.d.ts +25 -3
- package/packages/core/dist/index.d.ts.map +1 -1
- package/packages/core/dist/index.js +19 -1
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/integrations/langchain.d.ts +55 -0
- package/packages/core/dist/integrations/langchain.d.ts.map +1 -1
- package/packages/core/dist/integrations/langchain.js +71 -4
- package/packages/core/dist/integrations/langchain.js.map +1 -1
- package/packages/core/dist/logging/logger.d.ts +8 -2
- package/packages/core/dist/logging/logger.d.ts.map +1 -1
- package/packages/core/dist/logging/logger.js.map +1 -1
- package/packages/core/dist/logging/winston-logger.d.ts.map +1 -1
- package/packages/core/dist/logging/winston-logger.js +9 -1
- package/packages/core/dist/logging/winston-logger.js.map +1 -1
- package/packages/core/dist/matimo-instance.d.ts +230 -18
- package/packages/core/dist/matimo-instance.d.ts.map +1 -1
- package/packages/core/dist/matimo-instance.js +739 -40
- package/packages/core/dist/matimo-instance.js.map +1 -1
- package/packages/core/dist/mcp/index.d.ts +18 -0
- package/packages/core/dist/mcp/index.d.ts.map +1 -0
- package/packages/core/dist/mcp/index.js +24 -0
- package/packages/core/dist/mcp/index.js.map +1 -0
- package/packages/core/dist/mcp/mcp-server.d.ts +141 -0
- package/packages/core/dist/mcp/mcp-server.d.ts.map +1 -0
- package/packages/core/dist/mcp/mcp-server.js +754 -0
- package/packages/core/dist/mcp/mcp-server.js.map +1 -0
- package/packages/core/dist/mcp/secrets/aws-resolver.d.ts +41 -0
- package/packages/core/dist/mcp/secrets/aws-resolver.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/aws-resolver.js +141 -0
- package/packages/core/dist/mcp/secrets/aws-resolver.js.map +1 -0
- package/packages/core/dist/mcp/secrets/dotenv-resolver.d.ts +23 -0
- package/packages/core/dist/mcp/secrets/dotenv-resolver.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/dotenv-resolver.js +94 -0
- package/packages/core/dist/mcp/secrets/dotenv-resolver.js.map +1 -0
- package/packages/core/dist/mcp/secrets/env-resolver.d.ts +14 -0
- package/packages/core/dist/mcp/secrets/env-resolver.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/env-resolver.js +27 -0
- package/packages/core/dist/mcp/secrets/env-resolver.js.map +1 -0
- package/packages/core/dist/mcp/secrets/index.d.ts +14 -0
- package/packages/core/dist/mcp/secrets/index.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/index.js +13 -0
- package/packages/core/dist/mcp/secrets/index.js.map +1 -0
- package/packages/core/dist/mcp/secrets/resolver-chain.d.ts +34 -0
- package/packages/core/dist/mcp/secrets/resolver-chain.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/resolver-chain.js +141 -0
- package/packages/core/dist/mcp/secrets/resolver-chain.js.map +1 -0
- package/packages/core/dist/mcp/secrets/types.d.ts +73 -0
- package/packages/core/dist/mcp/secrets/types.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/types.js +8 -0
- package/packages/core/dist/mcp/secrets/types.js.map +1 -0
- package/packages/core/dist/mcp/secrets/vault-resolver.d.ts +43 -0
- package/packages/core/dist/mcp/secrets/vault-resolver.d.ts.map +1 -0
- package/packages/core/dist/mcp/secrets/vault-resolver.js +127 -0
- package/packages/core/dist/mcp/secrets/vault-resolver.js.map +1 -0
- package/packages/core/dist/mcp/tool-converter.d.ts +40 -0
- package/packages/core/dist/mcp/tool-converter.d.ts.map +1 -0
- package/packages/core/dist/mcp/tool-converter.js +185 -0
- package/packages/core/dist/mcp/tool-converter.js.map +1 -0
- package/packages/core/dist/policy/approval-manifest.d.ts +76 -0
- package/packages/core/dist/policy/approval-manifest.d.ts.map +1 -0
- package/packages/core/dist/policy/approval-manifest.js +197 -0
- package/packages/core/dist/policy/approval-manifest.js.map +1 -0
- package/packages/core/dist/policy/content-validator.d.ts +19 -0
- package/packages/core/dist/policy/content-validator.d.ts.map +1 -0
- package/packages/core/dist/policy/content-validator.js +196 -0
- package/packages/core/dist/policy/content-validator.js.map +1 -0
- package/packages/core/dist/policy/default-policy.d.ts +46 -0
- package/packages/core/dist/policy/default-policy.d.ts.map +1 -0
- package/packages/core/dist/policy/default-policy.js +241 -0
- package/packages/core/dist/policy/default-policy.js.map +1 -0
- package/packages/core/dist/policy/events.d.ts +71 -0
- package/packages/core/dist/policy/events.d.ts.map +1 -0
- package/packages/core/dist/policy/events.js +8 -0
- package/packages/core/dist/policy/events.js.map +1 -0
- package/packages/core/dist/policy/index.d.ts +13 -0
- package/packages/core/dist/policy/index.d.ts.map +1 -0
- package/packages/core/dist/policy/index.js +9 -0
- package/packages/core/dist/policy/index.js.map +1 -0
- package/packages/core/dist/policy/integrity-tracker.d.ts +62 -0
- package/packages/core/dist/policy/integrity-tracker.d.ts.map +1 -0
- package/packages/core/dist/policy/integrity-tracker.js +79 -0
- package/packages/core/dist/policy/integrity-tracker.js.map +1 -0
- package/packages/core/dist/policy/policy-loader.d.ts +58 -0
- package/packages/core/dist/policy/policy-loader.d.ts.map +1 -0
- package/packages/core/dist/policy/policy-loader.js +156 -0
- package/packages/core/dist/policy/policy-loader.js.map +1 -0
- package/packages/core/dist/policy/risk-classifier.d.ts +18 -0
- package/packages/core/dist/policy/risk-classifier.d.ts.map +1 -0
- package/packages/core/dist/policy/risk-classifier.js +47 -0
- package/packages/core/dist/policy/risk-classifier.js.map +1 -0
- package/packages/core/dist/policy/types.d.ts +131 -0
- package/packages/core/dist/policy/types.d.ts.map +1 -0
- package/packages/core/dist/policy/types.js +8 -0
- package/packages/core/dist/policy/types.js.map +1 -0
- package/LICENSE +0 -21
- package/README.md +0 -243
- package/packages/cli/bin/matimo.cjs +0 -26
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
1
|
import path from 'path';
|
|
3
2
|
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import axios from 'axios';
|
|
5
3
|
import { MatimoError, ErrorCode } from '../errors/matimo-error';
|
|
6
4
|
import { getGlobalMatimoLogger } from '../logging/logger';
|
|
7
5
|
/**
|
|
@@ -20,10 +18,17 @@ export class FunctionExecutor {
|
|
|
20
18
|
this.toolsPath = toolsPath || process.cwd();
|
|
21
19
|
}
|
|
22
20
|
/**
|
|
23
|
-
* Execute a tool that runs an async function
|
|
24
|
-
* Supports both embedded code and external .ts/.js files
|
|
21
|
+
* Execute a tool that runs an async function.
|
|
22
|
+
* Supports both embedded code and external .ts/.js files.
|
|
23
|
+
*
|
|
24
|
+
* @param tool - Tool definition
|
|
25
|
+
* @param params - Tool parameters
|
|
26
|
+
* @param credentials - Optional per-call credential overrides passed as `context.credentials`
|
|
27
|
+
* to the tool function. The function can use them with:
|
|
28
|
+
* `const token = context?.credentials?.MY_TOKEN ?? process.env.MY_TOKEN;`
|
|
29
|
+
* Values are never logged. Falls back to undefined when not provided.
|
|
25
30
|
*/
|
|
26
|
-
async execute(tool, params) {
|
|
31
|
+
async execute(tool, params, credentials) {
|
|
27
32
|
if (tool.execution.type !== 'function') {
|
|
28
33
|
throw new MatimoError('Tool execution type is not function', ErrorCode.EXECUTION_FAILED, {
|
|
29
34
|
expectedType: 'function',
|
|
@@ -129,7 +134,7 @@ export class FunctionExecutor {
|
|
|
129
134
|
import(fileUrl)
|
|
130
135
|
.then((module) => {
|
|
131
136
|
const fn = (module.default || module);
|
|
132
|
-
const result = fn(params);
|
|
137
|
+
const result = fn(params, credentials ? { credentials } : undefined);
|
|
133
138
|
// Handle both Promise and non-Promise returns
|
|
134
139
|
if (result instanceof Promise) {
|
|
135
140
|
result.then(handleSuccess).catch(handleError);
|
|
@@ -141,28 +146,43 @@ export class FunctionExecutor {
|
|
|
141
146
|
.catch(handleError);
|
|
142
147
|
}
|
|
143
148
|
else {
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
if (
|
|
150
|
-
throw new MatimoError('
|
|
149
|
+
// ── Embedded code execution ──────────────────────────────────────
|
|
150
|
+
// Requires explicit admin opt-in: MATIMO_ALLOW_EMBEDDED_CODE=true
|
|
151
|
+
// Even when enabled, a static security scan runs before evaluation
|
|
152
|
+
// to block known exploit patterns. No dangerous globals are passed
|
|
153
|
+
// into the sandbox — only `params` is accessible.
|
|
154
|
+
if (process.env.MATIMO_ALLOW_EMBEDDED_CODE !== 'true') {
|
|
155
|
+
throw new MatimoError(`Tool '${tool.name}': embedded code execution is disabled by default. ` +
|
|
156
|
+
'Set MATIMO_ALLOW_EMBEDDED_CODE=true to enable, or use a colocated .ts/.js file instead ' +
|
|
157
|
+
"(set execution.code to its relative path, e.g. './my-tool.ts').", ErrorCode.EXECUTION_FAILED, {
|
|
151
158
|
toolName: tool.name,
|
|
152
|
-
recommendation: 'Create a separate .ts file in the tool directory
|
|
153
|
-
enableFeatureFlag: 'Set MATIMO_ALLOW_EMBEDDED_CODE=true to enable (not recommended)',
|
|
159
|
+
recommendation: 'Create a separate .ts file in the tool directory and set execution.code to its relative path',
|
|
154
160
|
});
|
|
155
161
|
}
|
|
156
|
-
//
|
|
162
|
+
// Static security scan — reject code containing dangerous constructs
|
|
163
|
+
// BEFORE new Function() is ever called.
|
|
164
|
+
const BLOCKED_PATTERNS = [
|
|
165
|
+
{ re: /\brequire\s*\(/u, label: 'require()' },
|
|
166
|
+
{ re: /\bimport\s*\(/u, label: 'dynamic import()' },
|
|
167
|
+
{ re: /\bprocess\b/u, label: 'process object' },
|
|
168
|
+
{ re: /\b__dirname\b|\b__filename\b/u, label: '__dirname / __filename' },
|
|
169
|
+
{ re: /\beval\s*\(/u, label: 'eval()' },
|
|
170
|
+
{ re: /\bnew\s+Function\b/u, label: 'new Function()' },
|
|
171
|
+
{ re: /\bglobalThis\b|\bglobal\b/u, label: 'global / globalThis' },
|
|
172
|
+
];
|
|
173
|
+
for (const { re, label } of BLOCKED_PATTERNS) {
|
|
174
|
+
if (re.test(code)) {
|
|
175
|
+
throw new MatimoError(`Embedded code in tool '${tool.name}' contains a blocked construct: '${label}'. ` +
|
|
176
|
+
'Embedded code may only access the provided params argument.', ErrorCode.EXECUTION_FAILED, { toolName: tool.name, blockedConstruct: label });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
157
179
|
const logger = getGlobalMatimoLogger();
|
|
158
|
-
logger.warn(
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
|
|
162
|
-
const fn = new Function(
|
|
163
|
-
|
|
164
|
-
const result = fn(params, {}, fs, path, axios, undefined);
|
|
165
|
-
// Handle both Promise and non-Promise returns
|
|
180
|
+
logger.warn(`Executing embedded code for tool '${tool.name}'. Ensure this tool YAML is from a trusted source.`, { toolName: tool.name });
|
|
181
|
+
// Execute with strict mode and only params in scope.
|
|
182
|
+
// No fs, path, axios, or require are passed — embedded code is
|
|
183
|
+
// intentionally limited to pure data transformation of params.
|
|
184
|
+
const fn = new Function('params', '"use strict";\nreturn (' + code + ')(params);');
|
|
185
|
+
const result = fn(params);
|
|
166
186
|
if (result instanceof Promise) {
|
|
167
187
|
result.then(handleSuccess).catch(handleError);
|
|
168
188
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"function-executor.js","sourceRoot":"","sources":["../../src/executors/function-executor.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"function-executor.js","sourceRoot":"","sources":["../../src/executors/function-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,20 +5,95 @@ import { ToolDefinition } from '../core/schema';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare class HttpExecutor {
|
|
7
7
|
/**
|
|
8
|
-
* Execute a tool that makes an HTTP request
|
|
8
|
+
* Execute a tool that makes an HTTP request.
|
|
9
|
+
*
|
|
10
|
+
* @param tool - Tool definition
|
|
11
|
+
* @param params - Tool parameters (already env-injected by MatimoInstance)
|
|
12
|
+
* @param credentials - Optional per-call credential overrides. Used for
|
|
13
|
+
* `authentication.type: basic` (username_env / password_env keys) instead of
|
|
14
|
+
* reading from `process.env`. Other auth schemes (bearer, api_key) are handled
|
|
15
|
+
* upstream via parameter templating in MatimoInstance.injectAuthParameters().
|
|
16
|
+
* Values are never logged.
|
|
9
17
|
*/
|
|
10
|
-
execute(tool: ToolDefinition, params: Record<string, unknown>): Promise<unknown>;
|
|
18
|
+
execute(tool: ToolDefinition, params: Record<string, unknown>, credentials?: Record<string, string>): Promise<unknown>;
|
|
19
|
+
/**
|
|
20
|
+
* Automatically inject `Authorization: Basic <base64(username:password)>` when
|
|
21
|
+
* the tool declares `authentication.type: basic` with `username_env` and `password_env`.
|
|
22
|
+
*
|
|
23
|
+
* This is a zero-friction pattern: developers only set two natural env vars
|
|
24
|
+
* (e.g. TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN) and Matimo handles encoding.
|
|
25
|
+
* No pre-computed base64 credential string required.
|
|
26
|
+
*
|
|
27
|
+
* When `credentials` is provided the lookup order is:
|
|
28
|
+
* 1. `credentials[envVarName]` (per-call override — multi-tenant use)
|
|
29
|
+
* 2. `process.env[envVarName]` (singleton / single-tenant fallback)
|
|
30
|
+
*
|
|
31
|
+
* Credential values are never logged or included in error details.
|
|
32
|
+
*/
|
|
33
|
+
private applyBasicAuth;
|
|
11
34
|
/**
|
|
12
35
|
* Replace parameter placeholders in a string
|
|
13
36
|
*/
|
|
14
37
|
private templateString;
|
|
38
|
+
/**
|
|
39
|
+
* Check if a string is an unfilled placeholder
|
|
40
|
+
* Only matches single placeholders like "{param}", not "{...}" or embedded placeholders
|
|
41
|
+
*/
|
|
42
|
+
private isUnfilledPlaceholder;
|
|
43
|
+
/**
|
|
44
|
+
* Validate that all URL parameters are provided
|
|
45
|
+
*/
|
|
46
|
+
private validateUrlParameters;
|
|
15
47
|
/**
|
|
16
48
|
* Build query string from query_params, only including provided values
|
|
17
49
|
*/
|
|
18
50
|
private buildQueryString;
|
|
19
51
|
/**
|
|
20
|
-
* Replace parameter placeholders in an object (headers, body)
|
|
21
|
-
*
|
|
52
|
+
* Replace parameter placeholders in an object (headers, body, query params)
|
|
53
|
+
*
|
|
54
|
+
* CORE PRINCIPLE: "Define once in YAML, embed correctly at execution time"
|
|
55
|
+
*
|
|
56
|
+
* This method intelligently handles different parameter types:
|
|
57
|
+
* - STRING placeholders like "{title}": Always templated as strings
|
|
58
|
+
* - OBJECT placeholders like "{parent}": Embedded directly as JSON objects (not stringified) if paramDefinitions specifies type:object
|
|
59
|
+
* - ARRAY placeholders like "{items}": Embedded directly as JSON arrays (not stringified) if paramDefinitions specifies type:array
|
|
60
|
+
*
|
|
61
|
+
* Key behaviors:
|
|
62
|
+
* - Recursively processes nested objects
|
|
63
|
+
* - Skips keys with unfilled placeholders (e.g., "{sort_by}" when sort_by not provided)
|
|
64
|
+
* - Uses parameter schema type from YAML to determine how to embed values
|
|
65
|
+
* - Preserves JSON structure for complex types (objects/arrays) sent to APIs
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```
|
|
69
|
+
* // YAML definition:
|
|
70
|
+
* parameters:
|
|
71
|
+
* parent:
|
|
72
|
+
* type: object // <-- Tells executor to embed as-is, not stringify
|
|
73
|
+
* items:
|
|
74
|
+
* type: array // <-- Tells executor to embed as-is, not stringify
|
|
75
|
+
* title:
|
|
76
|
+
* type: string // <-- String templating applies
|
|
77
|
+
*
|
|
78
|
+
* body:
|
|
79
|
+
* parent: "{parent}" // Object embedded as {"id": "123", ...}
|
|
80
|
+
* items: "{items}" // Array embedded as [{"name": "a"}, ...]
|
|
81
|
+
* title: "{title}" // String embedded as "My Title"
|
|
82
|
+
*
|
|
83
|
+
* // JavaScript call:
|
|
84
|
+
* const result = await matimo.execute('notion_create_page', {
|
|
85
|
+
* parent: { database_id: 'abc123' }, // JavaScript object
|
|
86
|
+
* items: [{ type: 'text' }], // JavaScript array
|
|
87
|
+
* title: 'Create This Page' // String
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* // HTTP body sent to API:
|
|
91
|
+
* {
|
|
92
|
+
* "parent": {"database_id": "abc123"}, // Proper JSON object
|
|
93
|
+
* "items": [{"type": "text"}], // Proper JSON array
|
|
94
|
+
* "title": "Create This Page" // String
|
|
95
|
+
* }
|
|
96
|
+
* ```
|
|
22
97
|
*/
|
|
23
98
|
private templateObject;
|
|
24
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-executor.d.ts","sourceRoot":"","sources":["../../src/executors/http-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIhD;;;GAGG;AAEH,qBAAa,YAAY;IACvB
|
|
1
|
+
{"version":3,"file":"http-executor.d.ts","sourceRoot":"","sources":["../../src/executors/http-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIhD;;;GAGG;AAEH,qBAAa,YAAY;IACvB;;;;;;;;;;OAUG;IACG,OAAO,CACX,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,OAAO,CAAC;IAmHnB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,cAAc;IA4BtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAK7B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAyB7B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAexB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8CG;IACH,OAAO,CAAC,cAAc;CA+GvB;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import { applyParameterEncodings } from '../encodings/parameter-encoding';
|
|
3
|
-
import { MatimoError, ErrorCode } from '../errors/matimo-error';
|
|
3
|
+
import { MatimoError, ErrorCode, fromHttpError } from '../errors/matimo-error';
|
|
4
4
|
/**
|
|
5
5
|
* HttpExecutor - Executes HTTP requests
|
|
6
6
|
* Handles authentication, retries, and response validation
|
|
7
7
|
*/
|
|
8
8
|
export class HttpExecutor {
|
|
9
9
|
/**
|
|
10
|
-
* Execute a tool that makes an HTTP request
|
|
10
|
+
* Execute a tool that makes an HTTP request.
|
|
11
|
+
*
|
|
12
|
+
* @param tool - Tool definition
|
|
13
|
+
* @param params - Tool parameters (already env-injected by MatimoInstance)
|
|
14
|
+
* @param credentials - Optional per-call credential overrides. Used for
|
|
15
|
+
* `authentication.type: basic` (username_env / password_env keys) instead of
|
|
16
|
+
* reading from `process.env`. Other auth schemes (bearer, api_key) are handled
|
|
17
|
+
* upstream via parameter templating in MatimoInstance.injectAuthParameters().
|
|
18
|
+
* Values are never logged.
|
|
11
19
|
*/
|
|
12
|
-
async execute(tool, params) {
|
|
20
|
+
async execute(tool, params, credentials) {
|
|
13
21
|
if (tool.execution.type !== 'http') {
|
|
14
22
|
throw new MatimoError('Tool execution type is not http', ErrorCode.EXECUTION_FAILED, {
|
|
15
23
|
expectedType: 'http',
|
|
@@ -24,6 +32,8 @@ export class HttpExecutor {
|
|
|
24
32
|
if (parameterEncodings && parameterEncodings.length > 0) {
|
|
25
33
|
finalParams = applyParameterEncodings(params, parameterEncodings);
|
|
26
34
|
}
|
|
35
|
+
// Validate URL parameters are provided
|
|
36
|
+
this.validateUrlParameters(url, finalParams);
|
|
27
37
|
// Implement parameter templating
|
|
28
38
|
let finalUrl = this.templateString(url, finalParams);
|
|
29
39
|
// Handle query parameters - only include non-empty ones
|
|
@@ -33,10 +43,17 @@ export class HttpExecutor {
|
|
|
33
43
|
finalUrl += '?' + queryString;
|
|
34
44
|
}
|
|
35
45
|
}
|
|
36
|
-
const templatedHeaders = this.templateObject(headers, finalParams);
|
|
46
|
+
const templatedHeaders = this.templateObject(headers, finalParams, tool.parameters);
|
|
47
|
+
// Natively handle HTTP Basic Auth when authentication.type === 'basic' and
|
|
48
|
+
// username_env/password_env are declared. This eliminates the need for
|
|
49
|
+
// developers to pre-compute base64 credentials as a separate env var step.
|
|
50
|
+
// Credentials override takes precedence over process.env when provided.
|
|
51
|
+
this.applyBasicAuth(tool, templatedHeaders, credentials);
|
|
37
52
|
const templatedBody = body && typeof body === 'object'
|
|
38
|
-
? this.templateObject(body, finalParams)
|
|
39
|
-
: body
|
|
53
|
+
? this.templateObject(body, finalParams, tool.parameters)
|
|
54
|
+
: typeof body === 'string'
|
|
55
|
+
? this.templateString(body, finalParams)
|
|
56
|
+
: body;
|
|
40
57
|
// Build request config
|
|
41
58
|
const requestConfig = {
|
|
42
59
|
method,
|
|
@@ -46,7 +63,25 @@ export class HttpExecutor {
|
|
|
46
63
|
requestConfig.headers = templatedHeaders;
|
|
47
64
|
}
|
|
48
65
|
if (templatedBody !== undefined) {
|
|
49
|
-
|
|
66
|
+
// If Content-Type is application/x-www-form-urlencoded and body is an object,
|
|
67
|
+
// convert to URLSearchParams for proper form encoding by axios
|
|
68
|
+
const contentType = templatedHeaders['Content-Type'] ||
|
|
69
|
+
templatedHeaders['content-type'];
|
|
70
|
+
if (contentType?.includes('application/x-www-form-urlencoded') &&
|
|
71
|
+
typeof templatedBody === 'object' &&
|
|
72
|
+
templatedBody !== null &&
|
|
73
|
+
!(templatedBody instanceof FormData)) {
|
|
74
|
+
const params = new URLSearchParams();
|
|
75
|
+
for (const [key, value] of Object.entries(templatedBody)) {
|
|
76
|
+
if (value !== undefined && value !== null) {
|
|
77
|
+
params.append(key, String(value));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
requestConfig.data = params;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
requestConfig.data = templatedBody;
|
|
84
|
+
}
|
|
50
85
|
}
|
|
51
86
|
if (timeout !== undefined) {
|
|
52
87
|
requestConfig.timeout = timeout;
|
|
@@ -62,17 +97,43 @@ export class HttpExecutor {
|
|
|
62
97
|
};
|
|
63
98
|
}
|
|
64
99
|
catch (error) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
details,
|
|
73
|
-
};
|
|
100
|
+
// If this is already a MatimoError, rethrow to preserve semantics
|
|
101
|
+
if (error instanceof MatimoError) {
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
// Normalize any HTTP/axios-like or generic errors into MatimoError.
|
|
105
|
+
// This keeps callers consistent and preserves original cause via details.cause.
|
|
106
|
+
throw fromHttpError(error, 'HTTP request failed');
|
|
74
107
|
}
|
|
75
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Automatically inject `Authorization: Basic <base64(username:password)>` when
|
|
111
|
+
* the tool declares `authentication.type: basic` with `username_env` and `password_env`.
|
|
112
|
+
*
|
|
113
|
+
* This is a zero-friction pattern: developers only set two natural env vars
|
|
114
|
+
* (e.g. TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN) and Matimo handles encoding.
|
|
115
|
+
* No pre-computed base64 credential string required.
|
|
116
|
+
*
|
|
117
|
+
* When `credentials` is provided the lookup order is:
|
|
118
|
+
* 1. `credentials[envVarName]` (per-call override — multi-tenant use)
|
|
119
|
+
* 2. `process.env[envVarName]` (singleton / single-tenant fallback)
|
|
120
|
+
*
|
|
121
|
+
* Credential values are never logged or included in error details.
|
|
122
|
+
*/
|
|
123
|
+
applyBasicAuth(tool, headers, credentials) {
|
|
124
|
+
const auth = tool.authentication;
|
|
125
|
+
if (auth?.type !== 'basic' || !auth.username_env || !auth.password_env) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
// Prefer per-call credentials, fall back to process.env
|
|
129
|
+
const username = (credentials && credentials[auth.username_env]) ?? process.env[auth.username_env];
|
|
130
|
+
const password = (credentials && credentials[auth.password_env]) ?? process.env[auth.password_env];
|
|
131
|
+
if (!username || !password) {
|
|
132
|
+
throw new MatimoError(`Basic Auth requires env vars '${auth.username_env}' and '${auth.password_env}' to be set`, ErrorCode.AUTH_FAILED, { toolName: tool.name, username_env: auth.username_env, password_env: auth.password_env });
|
|
133
|
+
}
|
|
134
|
+
const encoded = Buffer.from(`${username}:${password}`).toString('base64');
|
|
135
|
+
headers['Authorization'] = `Basic ${encoded}`;
|
|
136
|
+
}
|
|
76
137
|
/**
|
|
77
138
|
* Replace parameter placeholders in a string
|
|
78
139
|
*/
|
|
@@ -80,12 +141,42 @@ export class HttpExecutor {
|
|
|
80
141
|
let result = str;
|
|
81
142
|
for (const [key, value] of Object.entries(params)) {
|
|
82
143
|
const placeholder = `{${key}}`;
|
|
83
|
-
|
|
84
|
-
|
|
144
|
+
// Allow empty-string values to be substituted (validation allows empty strings)
|
|
145
|
+
if (value !== undefined && value !== null) {
|
|
146
|
+
const replacement = String(value);
|
|
147
|
+
result = result.replace(new RegExp(placeholder, 'g'), () => replacement);
|
|
85
148
|
}
|
|
86
149
|
}
|
|
87
150
|
return result;
|
|
88
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if a string is an unfilled placeholder
|
|
154
|
+
* Only matches single placeholders like "{param}", not "{...}" or embedded placeholders
|
|
155
|
+
*/
|
|
156
|
+
isUnfilledPlaceholder(str) {
|
|
157
|
+
// Match exactly "{word}" where word is a valid identifier
|
|
158
|
+
return /^\{[a-zA-Z_][a-zA-Z0-9_]*\}$/.test(str);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Validate that all URL parameters are provided
|
|
162
|
+
*/
|
|
163
|
+
validateUrlParameters(url, params) {
|
|
164
|
+
// Extract all placeholders from URL like {param_name}
|
|
165
|
+
const urlParamMatches = url.match(/\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g);
|
|
166
|
+
if (!urlParamMatches) {
|
|
167
|
+
return; // No parameters in URL
|
|
168
|
+
}
|
|
169
|
+
for (const match of urlParamMatches) {
|
|
170
|
+
const paramName = match.slice(1, -1); // Remove { }
|
|
171
|
+
const paramValue = params[paramName];
|
|
172
|
+
// Check if parameter is missing or undefined
|
|
173
|
+
if (paramValue === undefined) {
|
|
174
|
+
throw new MatimoError(`Required URL parameter '${paramName}' is missing`, ErrorCode.INVALID_SCHEMA, { url, missingParam: paramName });
|
|
175
|
+
}
|
|
176
|
+
// Allow null, empty string, 0, false, etc. as valid values
|
|
177
|
+
// Just ensure the parameter is defined
|
|
178
|
+
}
|
|
179
|
+
}
|
|
89
180
|
/**
|
|
90
181
|
* Build query string from query_params, only including provided values
|
|
91
182
|
*/
|
|
@@ -101,32 +192,145 @@ export class HttpExecutor {
|
|
|
101
192
|
return parts.join('&');
|
|
102
193
|
}
|
|
103
194
|
/**
|
|
104
|
-
* Replace parameter placeholders in an object (headers, body)
|
|
105
|
-
*
|
|
195
|
+
* Replace parameter placeholders in an object (headers, body, query params)
|
|
196
|
+
*
|
|
197
|
+
* CORE PRINCIPLE: "Define once in YAML, embed correctly at execution time"
|
|
198
|
+
*
|
|
199
|
+
* This method intelligently handles different parameter types:
|
|
200
|
+
* - STRING placeholders like "{title}": Always templated as strings
|
|
201
|
+
* - OBJECT placeholders like "{parent}": Embedded directly as JSON objects (not stringified) if paramDefinitions specifies type:object
|
|
202
|
+
* - ARRAY placeholders like "{items}": Embedded directly as JSON arrays (not stringified) if paramDefinitions specifies type:array
|
|
203
|
+
*
|
|
204
|
+
* Key behaviors:
|
|
205
|
+
* - Recursively processes nested objects
|
|
206
|
+
* - Skips keys with unfilled placeholders (e.g., "{sort_by}" when sort_by not provided)
|
|
207
|
+
* - Uses parameter schema type from YAML to determine how to embed values
|
|
208
|
+
* - Preserves JSON structure for complex types (objects/arrays) sent to APIs
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```
|
|
212
|
+
* // YAML definition:
|
|
213
|
+
* parameters:
|
|
214
|
+
* parent:
|
|
215
|
+
* type: object // <-- Tells executor to embed as-is, not stringify
|
|
216
|
+
* items:
|
|
217
|
+
* type: array // <-- Tells executor to embed as-is, not stringify
|
|
218
|
+
* title:
|
|
219
|
+
* type: string // <-- String templating applies
|
|
220
|
+
*
|
|
221
|
+
* body:
|
|
222
|
+
* parent: "{parent}" // Object embedded as {"id": "123", ...}
|
|
223
|
+
* items: "{items}" // Array embedded as [{"name": "a"}, ...]
|
|
224
|
+
* title: "{title}" // String embedded as "My Title"
|
|
225
|
+
*
|
|
226
|
+
* // JavaScript call:
|
|
227
|
+
* const result = await matimo.execute('notion_create_page', {
|
|
228
|
+
* parent: { database_id: 'abc123' }, // JavaScript object
|
|
229
|
+
* items: [{ type: 'text' }], // JavaScript array
|
|
230
|
+
* title: 'Create This Page' // String
|
|
231
|
+
* });
|
|
232
|
+
*
|
|
233
|
+
* // HTTP body sent to API:
|
|
234
|
+
* {
|
|
235
|
+
* "parent": {"database_id": "abc123"}, // Proper JSON object
|
|
236
|
+
* "items": [{"type": "text"}], // Proper JSON array
|
|
237
|
+
* "title": "Create This Page" // String
|
|
238
|
+
* }
|
|
239
|
+
* ```
|
|
106
240
|
*/
|
|
107
|
-
templateObject(obj, params) {
|
|
241
|
+
templateObject(obj, params, paramDefinitions) {
|
|
108
242
|
const result = {};
|
|
109
243
|
for (const [key, value] of Object.entries(obj)) {
|
|
110
244
|
if (typeof value === 'string') {
|
|
111
|
-
|
|
245
|
+
// Check if this is exactly a placeholder like "{parent}"
|
|
246
|
+
const paramNameMatch = value.match(/^\{([a-zA-Z_][a-zA-Z0-9_]*)\}$/);
|
|
247
|
+
if (paramNameMatch) {
|
|
248
|
+
const paramName = paramNameMatch[1];
|
|
249
|
+
const paramValue = params[paramName];
|
|
250
|
+
// If parameter is defined in schema with type object or array,
|
|
251
|
+
// embed the value directly instead of stringifying
|
|
252
|
+
if (paramValue !== undefined && paramDefinitions?.[paramName]) {
|
|
253
|
+
const paramType = paramDefinitions[paramName].type;
|
|
254
|
+
if ((paramType === 'object' || paramType === 'array') && paramValue !== null) {
|
|
255
|
+
result[key] = paramValue;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Otherwise, do normal string templating
|
|
261
|
+
const templated = this.templateString(value, params);
|
|
262
|
+
if (templated !== undefined &&
|
|
263
|
+
templated !== null &&
|
|
264
|
+
!this.isUnfilledPlaceholder(templated)) {
|
|
265
|
+
// Extract parameter name from template (e.g., "{page_size}" → "page_size")
|
|
266
|
+
const paramName = paramNameMatch ? paramNameMatch[1] : null;
|
|
267
|
+
// If this is a single parameter placeholder, use the parameter's defined type
|
|
268
|
+
if (paramName && paramDefinitions?.[paramName]) {
|
|
269
|
+
const paramType = paramDefinitions[paramName].type;
|
|
270
|
+
if (paramType === 'number' && !isNaN(Number(templated))) {
|
|
271
|
+
result[key] = Number(templated);
|
|
272
|
+
}
|
|
273
|
+
else if (paramType === 'boolean') {
|
|
274
|
+
result[key] = templated === 'true' || templated === '1' || templated === 'yes';
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
result[key] = templated;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
result[key] = templated;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
112
284
|
}
|
|
113
285
|
else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
114
286
|
// Recursively template nested objects
|
|
115
|
-
|
|
287
|
+
const nestedResult = this.templateObject(value, params, paramDefinitions);
|
|
288
|
+
// Only include nested object if it has content
|
|
289
|
+
if (Object.keys(nestedResult).length > 0) {
|
|
290
|
+
result[key] = nestedResult;
|
|
291
|
+
}
|
|
116
292
|
}
|
|
117
293
|
else if (Array.isArray(value)) {
|
|
118
294
|
// Handle arrays of objects
|
|
119
|
-
|
|
295
|
+
const templatedArray = value
|
|
296
|
+
.map((item) => {
|
|
120
297
|
if (typeof item === 'string') {
|
|
121
|
-
|
|
298
|
+
const templated = this.templateString(item, params);
|
|
299
|
+
// Skip unfilled placeholders; allow empty strings
|
|
300
|
+
if (templated !== undefined &&
|
|
301
|
+
templated !== null &&
|
|
302
|
+
!this.isUnfilledPlaceholder(templated)) {
|
|
303
|
+
// Extract parameter name from template
|
|
304
|
+
const paramNameMatch = item.match(/^\{([a-zA-Z_][a-zA-Z0-9_]*)\}$/);
|
|
305
|
+
const paramName = paramNameMatch ? paramNameMatch[1] : null;
|
|
306
|
+
// If this is a single parameter placeholder, use the parameter's defined type
|
|
307
|
+
if (paramName && paramDefinitions?.[paramName]) {
|
|
308
|
+
const paramType = paramDefinitions[paramName].type;
|
|
309
|
+
if (paramType === 'number' && !isNaN(Number(templated))) {
|
|
310
|
+
return Number(templated);
|
|
311
|
+
}
|
|
312
|
+
else if (paramType === 'boolean') {
|
|
313
|
+
return templated === 'true' || templated === '1' || templated === 'yes';
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return templated;
|
|
317
|
+
}
|
|
318
|
+
return null;
|
|
122
319
|
}
|
|
123
320
|
else if (typeof item === 'object' && item !== null && !Array.isArray(item)) {
|
|
124
|
-
|
|
321
|
+
const templated = this.templateObject(item, params, paramDefinitions);
|
|
322
|
+
// Only include if has content
|
|
323
|
+
return Object.keys(templated).length > 0 ? templated : null;
|
|
125
324
|
}
|
|
126
325
|
return item;
|
|
127
|
-
})
|
|
326
|
+
})
|
|
327
|
+
.filter((item) => item !== null);
|
|
328
|
+
// Only include array if it has items
|
|
329
|
+
if (templatedArray.length > 0) {
|
|
330
|
+
result[key] = templatedArray;
|
|
331
|
+
}
|
|
128
332
|
}
|
|
129
|
-
else {
|
|
333
|
+
else if (value !== undefined && value !== null) {
|
|
130
334
|
result[key] = value;
|
|
131
335
|
}
|
|
132
336
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-executor.js","sourceRoot":"","sources":["../../src/executors/http-executor.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"http-executor.js","sourceRoot":"","sources":["../../src/executors/http-executor.ts"],"names":[],"mappings":"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"}
|