praisonai 1.7.1 → 1.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/agent-loop.d.ts +4 -0
- package/dist/ai/agent-loop.js +33 -10
- package/dist/cli/features/external-agents.d.ts +23 -0
- package/dist/cli/features/external-agents.js +84 -0
- package/dist/cli/features/sandbox-executor.d.ts +7 -1
- package/dist/cli/features/sandbox-executor.js +65 -15
- package/dist/index.d.ts +2 -2
- package/dist/index.js +20 -15
- package/dist/mcp/security.d.ts +4 -0
- package/dist/mcp/security.js +33 -10
- package/dist/mcp/server.d.ts +7 -0
- package/dist/mcp/server.js +25 -0
- package/dist/os/agentos.js +19 -0
- package/dist/os/config.d.ts +3 -1
- package/dist/os/config.js +10 -2
- package/dist/tools/builtins/code-mode.js +16 -16
- package/dist/tools/index.d.ts +5 -2
- package/dist/tools/index.js +32 -5
- package/dist/tools/registry/index.d.ts +2 -2
- package/dist/tools/registry/index.js +10 -1
- package/dist/tools/registry/registry.d.ts +33 -0
- package/dist/tools/registry/registry.js +79 -1
- package/dist/tools/registry/types.d.ts +17 -0
- package/dist/tools/registry/types.js +22 -1
- package/dist/tools/utility-tools.js +39 -9
- package/dist/workflows/yaml-parser.d.ts +4 -1
- package/dist/workflows/yaml-parser.js +42 -5
- package/package.json +3 -3
package/dist/mcp/security.js
CHANGED
|
@@ -115,6 +115,32 @@ class MCPSecurity {
|
|
|
115
115
|
return config.requests;
|
|
116
116
|
return Math.max(0, config.requests - state.count);
|
|
117
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Validate credentials for a given auth method (fail closed by default)
|
|
120
|
+
*/
|
|
121
|
+
async validateCredentials(auth, token) {
|
|
122
|
+
switch (auth.method) {
|
|
123
|
+
case 'none':
|
|
124
|
+
return true;
|
|
125
|
+
case 'api-key':
|
|
126
|
+
case 'bearer':
|
|
127
|
+
if (auth.validate) {
|
|
128
|
+
return auth.validate(token);
|
|
129
|
+
}
|
|
130
|
+
if (this.apiKeys.size === 0) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
return this.validateApiKey(token);
|
|
134
|
+
case 'basic':
|
|
135
|
+
case 'oauth':
|
|
136
|
+
if (!auth.validate) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return auth.validate(token);
|
|
140
|
+
default:
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
118
144
|
/**
|
|
119
145
|
* Match policy against request
|
|
120
146
|
*/
|
|
@@ -141,19 +167,16 @@ class MCPSecurity {
|
|
|
141
167
|
case 'allow':
|
|
142
168
|
return { allowed: true };
|
|
143
169
|
case 'authenticate':
|
|
144
|
-
if (!policy.auth)
|
|
145
|
-
return { allowed:
|
|
170
|
+
if (!policy.auth) {
|
|
171
|
+
return { allowed: false, reason: 'Authentication policy misconfigured' };
|
|
172
|
+
}
|
|
146
173
|
const token = request.headers ? this.extractToken(request.headers) : null;
|
|
147
|
-
if (!token) {
|
|
174
|
+
if (!token || !token.trim()) {
|
|
148
175
|
return { allowed: false, reason: 'Authentication required' };
|
|
149
176
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
: this.validateApiKey(token);
|
|
154
|
-
if (!valid) {
|
|
155
|
-
return { allowed: false, reason: 'Invalid credentials' };
|
|
156
|
-
}
|
|
177
|
+
const valid = await this.validateCredentials(policy.auth, token);
|
|
178
|
+
if (!valid) {
|
|
179
|
+
return { allowed: false, reason: 'Invalid credentials' };
|
|
157
180
|
}
|
|
158
181
|
return { allowed: true, context: { authenticated: true } };
|
|
159
182
|
case 'rate-limit':
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -85,6 +85,8 @@ export interface MCPServerConfig {
|
|
|
85
85
|
port?: number | null;
|
|
86
86
|
/** Enable logging */
|
|
87
87
|
logging?: boolean;
|
|
88
|
+
/** Optional bearer token for HTTP transport (or set PRAISONAI_MCP_AUTH_TOKEN) */
|
|
89
|
+
authToken?: string;
|
|
88
90
|
}
|
|
89
91
|
/**
|
|
90
92
|
* MCP Request
|
|
@@ -121,6 +123,7 @@ export declare class MCPServer {
|
|
|
121
123
|
private logging;
|
|
122
124
|
private running;
|
|
123
125
|
private httpServer;
|
|
126
|
+
private authToken?;
|
|
124
127
|
constructor(config?: MCPServerConfig);
|
|
125
128
|
/**
|
|
126
129
|
* Register a tool
|
|
@@ -174,6 +177,10 @@ export declare class MCPServer {
|
|
|
174
177
|
* Start stdio transport
|
|
175
178
|
*/
|
|
176
179
|
startStdio(): Promise<void>;
|
|
180
|
+
/**
|
|
181
|
+
* Verify HTTP bearer token when authToken is configured
|
|
182
|
+
*/
|
|
183
|
+
private verifyHttpAuth;
|
|
177
184
|
/**
|
|
178
185
|
* Start HTTP transport
|
|
179
186
|
*/
|
package/dist/mcp/server.js
CHANGED
|
@@ -65,6 +65,7 @@ class MCPServer {
|
|
|
65
65
|
this.resources = new Map();
|
|
66
66
|
this.prompts = new Map();
|
|
67
67
|
this.logging = config.logging ?? false;
|
|
68
|
+
this.authToken = config.authToken ?? process.env.PRAISONAI_MCP_AUTH_TOKEN ?? undefined;
|
|
68
69
|
// Register initial tools
|
|
69
70
|
if (config.tools) {
|
|
70
71
|
for (const tool of config.tools) {
|
|
@@ -315,6 +316,25 @@ class MCPServer {
|
|
|
315
316
|
this.running = false;
|
|
316
317
|
});
|
|
317
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Verify HTTP bearer token when authToken is configured
|
|
321
|
+
*/
|
|
322
|
+
verifyHttpAuth(req) {
|
|
323
|
+
if (!this.authToken) {
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
const authHeader = req.headers.authorization ?? req.headers['Authorization'];
|
|
327
|
+
if (typeof authHeader === 'string') {
|
|
328
|
+
if (authHeader.startsWith('Bearer ') && authHeader.slice(7) === this.authToken) {
|
|
329
|
+
return true;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const xAuth = req.headers['x-auth-token'] ?? req.headers['X-Auth-Token'];
|
|
333
|
+
if (typeof xAuth === 'string' && xAuth === this.authToken) {
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
318
338
|
/**
|
|
319
339
|
* Start HTTP transport
|
|
320
340
|
*/
|
|
@@ -325,6 +345,11 @@ class MCPServer {
|
|
|
325
345
|
const http = await Promise.resolve().then(() => __importStar(require('http')));
|
|
326
346
|
this.httpServer = http.createServer(async (req, res) => {
|
|
327
347
|
if (req.method === 'POST') {
|
|
348
|
+
if (!this.verifyHttpAuth(req)) {
|
|
349
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
350
|
+
res.end(JSON.stringify({ error: 'Unauthorized' }));
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
328
353
|
let body = '';
|
|
329
354
|
req.on('data', chunk => body += chunk);
|
|
330
355
|
req.on('end', async () => {
|
package/dist/os/agentos.js
CHANGED
|
@@ -112,6 +112,25 @@ class AgentOS {
|
|
|
112
112
|
next();
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
|
+
// Optional API key middleware (except /health)
|
|
116
|
+
if (this.config.apiKey) {
|
|
117
|
+
app.use((req, res, next) => {
|
|
118
|
+
if (req.path === '/health') {
|
|
119
|
+
return next();
|
|
120
|
+
}
|
|
121
|
+
const authHeader = req.headers.authorization;
|
|
122
|
+
if (typeof authHeader === 'string' && authHeader.startsWith('Bearer ')) {
|
|
123
|
+
if (authHeader.slice(7) === this.config.apiKey) {
|
|
124
|
+
return next();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const xAuth = req.headers['x-auth-token'] ?? req.headers['X-Auth-Token'];
|
|
128
|
+
if (typeof xAuth === 'string' && xAuth === this.config.apiKey) {
|
|
129
|
+
return next();
|
|
130
|
+
}
|
|
131
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
132
|
+
});
|
|
133
|
+
}
|
|
115
134
|
// Register routes
|
|
116
135
|
this._registerRoutes(app);
|
|
117
136
|
return app;
|
package/dist/os/config.d.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
export interface AgentOSConfig {
|
|
22
22
|
/** Name of the application (default: "PraisonAI App") */
|
|
23
23
|
name?: string;
|
|
24
|
-
/** Host address to bind to (default: "
|
|
24
|
+
/** Host address to bind to (default: "127.0.0.1") */
|
|
25
25
|
host?: string;
|
|
26
26
|
/** Port number to listen on (default: 8000) */
|
|
27
27
|
port?: number;
|
|
@@ -45,6 +45,8 @@ export interface AgentOSConfig {
|
|
|
45
45
|
timeout?: number;
|
|
46
46
|
/** Additional metadata for the app */
|
|
47
47
|
metadata?: Record<string, any>;
|
|
48
|
+
/** Optional API key for route protection (or set PRAISONAI_AGENTOS_API_KEY) */
|
|
49
|
+
apiKey?: string;
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
50
52
|
* Default configuration values for AgentOS.
|
package/dist/os/config.js
CHANGED
|
@@ -22,7 +22,7 @@ exports.mergeConfig = mergeConfig;
|
|
|
22
22
|
*/
|
|
23
23
|
exports.DEFAULT_AGENTOS_CONFIG = {
|
|
24
24
|
name: 'PraisonAI App',
|
|
25
|
-
host: '
|
|
25
|
+
host: '127.0.0.1',
|
|
26
26
|
port: 8000,
|
|
27
27
|
reload: false,
|
|
28
28
|
corsOrigins: ['*'],
|
|
@@ -33,18 +33,26 @@ exports.DEFAULT_AGENTOS_CONFIG = {
|
|
|
33
33
|
logLevel: 'info',
|
|
34
34
|
workers: 1,
|
|
35
35
|
timeout: 60,
|
|
36
|
+
apiKey: '',
|
|
36
37
|
metadata: {},
|
|
37
38
|
};
|
|
38
39
|
/**
|
|
39
40
|
* Merge user config with defaults.
|
|
40
41
|
*/
|
|
41
42
|
function mergeConfig(userConfig) {
|
|
42
|
-
|
|
43
|
+
const apiKey = userConfig?.apiKey ?? process.env.PRAISONAI_AGENTOS_API_KEY ?? '';
|
|
44
|
+
const merged = {
|
|
43
45
|
...exports.DEFAULT_AGENTOS_CONFIG,
|
|
44
46
|
...userConfig,
|
|
47
|
+
apiKey,
|
|
45
48
|
metadata: {
|
|
46
49
|
...exports.DEFAULT_AGENTOS_CONFIG.metadata,
|
|
47
50
|
...userConfig?.metadata,
|
|
48
51
|
},
|
|
49
52
|
};
|
|
53
|
+
const exposedHosts = new Set(['0.0.0.0', '::', '::0']);
|
|
54
|
+
if (exposedHosts.has(merged.host) && !merged.apiKey) {
|
|
55
|
+
throw new Error('AgentOS requires apiKey (or PRAISONAI_AGENTOS_API_KEY) when binding to a network-exposed host');
|
|
56
|
+
}
|
|
57
|
+
return merged;
|
|
50
58
|
}
|
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.CODE_MODE_METADATA = void 0;
|
|
10
10
|
exports.codeMode = codeMode;
|
|
11
11
|
exports.createCodeModeTool = createCodeModeTool;
|
|
12
|
+
const node_vm_1 = require("node:vm");
|
|
12
13
|
exports.CODE_MODE_METADATA = {
|
|
13
14
|
id: 'code-mode',
|
|
14
15
|
displayName: 'Code Mode',
|
|
@@ -69,6 +70,10 @@ function codeMode(config) {
|
|
|
69
70
|
/import\s+.*from\s+['"]child_process['"]/,
|
|
70
71
|
/process\.exit/,
|
|
71
72
|
/eval\s*\(/,
|
|
73
|
+
/Function\s*\(/,
|
|
74
|
+
/\.constructor/,
|
|
75
|
+
/globalThis/,
|
|
76
|
+
/\bprocess\b/,
|
|
72
77
|
];
|
|
73
78
|
if (!settings.allowNetwork) {
|
|
74
79
|
blockedPatterns.push(/require\s*\(\s*['"]http['"]\s*\)/, /require\s*\(\s*['"]https['"]\s*\)/, /require\s*\(\s*['"]net['"]\s*\)/, /fetch\s*\(/);
|
|
@@ -101,37 +106,32 @@ function codeMode(config) {
|
|
|
101
106
|
}
|
|
102
107
|
}
|
|
103
108
|
try {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const sandbox = {
|
|
109
|
+
const stdout = [];
|
|
110
|
+
const stderr = [];
|
|
111
|
+
const sandboxContext = {
|
|
108
112
|
console: {
|
|
109
113
|
log: (...args) => stdout.push(args.map(String).join(' ')),
|
|
110
114
|
error: (...args) => stderr.push(args.map(String).join(' ')),
|
|
111
115
|
warn: (...args) => stderr.push(args.map(String).join(' ')),
|
|
112
116
|
},
|
|
113
|
-
setTimeout: undefined,
|
|
114
|
-
setInterval: undefined,
|
|
115
|
-
setImmediate: undefined,
|
|
116
|
-
process: undefined,
|
|
117
|
-
require: undefined,
|
|
118
117
|
__dirname: '/sandbox',
|
|
119
118
|
__filename: '/sandbox/index.js',
|
|
120
119
|
env: env || {},
|
|
121
120
|
files: files || {},
|
|
122
121
|
};
|
|
123
|
-
const stdout = [];
|
|
124
|
-
const stderr = [];
|
|
125
|
-
// Execute with timeout
|
|
126
122
|
const timeoutPromise = new Promise((_, reject) => {
|
|
127
123
|
setTimeout(() => reject(new Error('Execution timeout')), settings.timeoutMs);
|
|
128
124
|
});
|
|
129
125
|
const executePromise = new Promise((resolve, reject) => {
|
|
130
126
|
try {
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
127
|
+
const wrappedCode = `(async function() { ${code} })()`;
|
|
128
|
+
const result = (0, node_vm_1.runInNewContext)(wrappedCode, sandboxContext, {
|
|
129
|
+
timeout: settings.timeoutMs,
|
|
130
|
+
displayErrors: true,
|
|
131
|
+
});
|
|
132
|
+
Promise.resolve(result)
|
|
133
|
+
.then((value) => resolve(String(value ?? '')))
|
|
134
|
+
.catch(reject);
|
|
135
135
|
}
|
|
136
136
|
catch (error) {
|
|
137
137
|
reject(error);
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export { BaseTool, ToolResult, ToolValidationError, validateTool, createTool, type ToolParameters } from './base';
|
|
2
|
-
export
|
|
2
|
+
export { tool, FunctionTool, ToolRegistry, getRegistry, registerTool, getTool, type ToolConfig, type ToolContext, } from './decorator';
|
|
3
3
|
export * from './arxivTools';
|
|
4
4
|
export * from './mcpSse';
|
|
5
|
-
export
|
|
5
|
+
export { ToolsRegistry, getToolsRegistry, createToolsRegistry, resetToolsRegistry, get_registry, get_tool, register_tool, validate_tool, } from './registry';
|
|
6
|
+
export type { ToolExecutionContext, ToolLimits, RedactionHooks, ToolLogger, ToolCapabilities, InstallHints, ToolMetadata, ToolExecutionResult, PraisonTool, ToolParameterSchema, ToolParameterProperty, ToolMiddleware, ToolHooks, ToolFactory, RegisteredTool, ToolInstallStatus, } from './registry';
|
|
7
|
+
export { MissingDependencyError, MissingEnvVarError, BudgetExceededError } from './registry';
|
|
8
|
+
export { createLoggingMiddleware, createTimeoutMiddleware, createRedactionMiddleware, createRateLimitMiddleware, createRetryMiddleware, createTracingMiddleware, createValidationMiddleware, composeMiddleware, } from './registry';
|
|
6
9
|
export * from './builtins';
|
|
7
10
|
export { tools, registerBuiltinTools } from './tools';
|
|
8
11
|
export type { default as ToolsFacade } from './tools';
|
package/dist/tools/index.js
CHANGED
|
@@ -14,20 +14,47 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.createDelegator = exports.createSubagentTools = exports.createSubagentTool = exports.SubagentTool = exports.registerBuiltinTools = exports.tools = exports.createTool = exports.validateTool = exports.ToolValidationError = exports.BaseTool = void 0;
|
|
17
|
+
exports.createDelegator = exports.createSubagentTools = exports.createSubagentTool = exports.SubagentTool = exports.registerBuiltinTools = exports.tools = exports.composeMiddleware = exports.createValidationMiddleware = exports.createTracingMiddleware = exports.createRetryMiddleware = exports.createRateLimitMiddleware = exports.createRedactionMiddleware = exports.createTimeoutMiddleware = exports.createLoggingMiddleware = exports.BudgetExceededError = exports.MissingEnvVarError = exports.MissingDependencyError = exports.validate_tool = exports.register_tool = exports.get_tool = exports.get_registry = exports.resetToolsRegistry = exports.createToolsRegistry = exports.getToolsRegistry = exports.ToolsRegistry = exports.getTool = exports.registerTool = exports.getRegistry = exports.ToolRegistry = exports.FunctionTool = exports.tool = exports.createTool = exports.validateTool = exports.ToolValidationError = exports.BaseTool = void 0;
|
|
18
18
|
// Export base tool interfaces and classes
|
|
19
19
|
var base_1 = require("./base");
|
|
20
20
|
Object.defineProperty(exports, "BaseTool", { enumerable: true, get: function () { return base_1.BaseTool; } });
|
|
21
21
|
Object.defineProperty(exports, "ToolValidationError", { enumerable: true, get: function () { return base_1.ToolValidationError; } });
|
|
22
22
|
Object.defineProperty(exports, "validateTool", { enumerable: true, get: function () { return base_1.validateTool; } });
|
|
23
23
|
Object.defineProperty(exports, "createTool", { enumerable: true, get: function () { return base_1.createTool; } });
|
|
24
|
-
//
|
|
25
|
-
|
|
24
|
+
// Legacy @tool decorator registry (camelCase names reserved for this API)
|
|
25
|
+
var decorator_1 = require("./decorator");
|
|
26
|
+
Object.defineProperty(exports, "tool", { enumerable: true, get: function () { return decorator_1.tool; } });
|
|
27
|
+
Object.defineProperty(exports, "FunctionTool", { enumerable: true, get: function () { return decorator_1.FunctionTool; } });
|
|
28
|
+
Object.defineProperty(exports, "ToolRegistry", { enumerable: true, get: function () { return decorator_1.ToolRegistry; } });
|
|
29
|
+
Object.defineProperty(exports, "getRegistry", { enumerable: true, get: function () { return decorator_1.getRegistry; } });
|
|
30
|
+
Object.defineProperty(exports, "registerTool", { enumerable: true, get: function () { return decorator_1.registerTool; } });
|
|
31
|
+
Object.defineProperty(exports, "getTool", { enumerable: true, get: function () { return decorator_1.getTool; } });
|
|
26
32
|
// Export all tool modules
|
|
27
33
|
__exportStar(require("./arxivTools"), exports);
|
|
28
34
|
__exportStar(require("./mcpSse"), exports);
|
|
29
|
-
//
|
|
30
|
-
|
|
35
|
+
// New AI SDK tools registry — snake_case parity names (avoid camelCase clash with decorator)
|
|
36
|
+
var registry_1 = require("./registry");
|
|
37
|
+
Object.defineProperty(exports, "ToolsRegistry", { enumerable: true, get: function () { return registry_1.ToolsRegistry; } });
|
|
38
|
+
Object.defineProperty(exports, "getToolsRegistry", { enumerable: true, get: function () { return registry_1.getToolsRegistry; } });
|
|
39
|
+
Object.defineProperty(exports, "createToolsRegistry", { enumerable: true, get: function () { return registry_1.createToolsRegistry; } });
|
|
40
|
+
Object.defineProperty(exports, "resetToolsRegistry", { enumerable: true, get: function () { return registry_1.resetToolsRegistry; } });
|
|
41
|
+
Object.defineProperty(exports, "get_registry", { enumerable: true, get: function () { return registry_1.get_registry; } });
|
|
42
|
+
Object.defineProperty(exports, "get_tool", { enumerable: true, get: function () { return registry_1.get_tool; } });
|
|
43
|
+
Object.defineProperty(exports, "register_tool", { enumerable: true, get: function () { return registry_1.register_tool; } });
|
|
44
|
+
Object.defineProperty(exports, "validate_tool", { enumerable: true, get: function () { return registry_1.validate_tool; } });
|
|
45
|
+
var registry_2 = require("./registry");
|
|
46
|
+
Object.defineProperty(exports, "MissingDependencyError", { enumerable: true, get: function () { return registry_2.MissingDependencyError; } });
|
|
47
|
+
Object.defineProperty(exports, "MissingEnvVarError", { enumerable: true, get: function () { return registry_2.MissingEnvVarError; } });
|
|
48
|
+
Object.defineProperty(exports, "BudgetExceededError", { enumerable: true, get: function () { return registry_2.BudgetExceededError; } });
|
|
49
|
+
var registry_3 = require("./registry");
|
|
50
|
+
Object.defineProperty(exports, "createLoggingMiddleware", { enumerable: true, get: function () { return registry_3.createLoggingMiddleware; } });
|
|
51
|
+
Object.defineProperty(exports, "createTimeoutMiddleware", { enumerable: true, get: function () { return registry_3.createTimeoutMiddleware; } });
|
|
52
|
+
Object.defineProperty(exports, "createRedactionMiddleware", { enumerable: true, get: function () { return registry_3.createRedactionMiddleware; } });
|
|
53
|
+
Object.defineProperty(exports, "createRateLimitMiddleware", { enumerable: true, get: function () { return registry_3.createRateLimitMiddleware; } });
|
|
54
|
+
Object.defineProperty(exports, "createRetryMiddleware", { enumerable: true, get: function () { return registry_3.createRetryMiddleware; } });
|
|
55
|
+
Object.defineProperty(exports, "createTracingMiddleware", { enumerable: true, get: function () { return registry_3.createTracingMiddleware; } });
|
|
56
|
+
Object.defineProperty(exports, "createValidationMiddleware", { enumerable: true, get: function () { return registry_3.createValidationMiddleware; } });
|
|
57
|
+
Object.defineProperty(exports, "composeMiddleware", { enumerable: true, get: function () { return registry_3.composeMiddleware; } });
|
|
31
58
|
// Export built-in tools
|
|
32
59
|
__exportStar(require("./builtins"), exports);
|
|
33
60
|
// Export tools facade
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Lazy-loaded exports for the tools registry system.
|
|
5
5
|
*/
|
|
6
6
|
export type { ToolExecutionContext, ToolLimits, RedactionHooks, ToolLogger, ToolCapabilities, InstallHints, ToolMetadata, ToolExecutionResult, PraisonTool, ToolParameterSchema, ToolParameterProperty, ToolMiddleware, ToolHooks, ToolFactory, RegisteredTool, ToolInstallStatus, } from './types';
|
|
7
|
-
export { MissingDependencyError, MissingEnvVarError } from './types';
|
|
8
|
-
export { ToolsRegistry, getToolsRegistry, createToolsRegistry, resetToolsRegistry, } from './registry';
|
|
7
|
+
export { MissingDependencyError, MissingEnvVarError, BudgetExceededError } from './types';
|
|
8
|
+
export { ToolsRegistry, getToolsRegistry, createToolsRegistry, resetToolsRegistry, get_registry, getRegistry, get_tool, getTool, register_tool, registerTool, validate_tool, validateTool, } from './registry';
|
|
9
9
|
export { createLoggingMiddleware, createTimeoutMiddleware, createRedactionMiddleware, createRateLimitMiddleware, createRetryMiddleware, createTracingMiddleware, createValidationMiddleware, composeMiddleware, } from './middleware';
|
|
@@ -5,17 +5,26 @@
|
|
|
5
5
|
* Lazy-loaded exports for the tools registry system.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.composeMiddleware = exports.createValidationMiddleware = exports.createTracingMiddleware = exports.createRetryMiddleware = exports.createRateLimitMiddleware = exports.createRedactionMiddleware = exports.createTimeoutMiddleware = exports.createLoggingMiddleware = exports.resetToolsRegistry = exports.createToolsRegistry = exports.getToolsRegistry = exports.ToolsRegistry = exports.MissingEnvVarError = exports.MissingDependencyError = void 0;
|
|
8
|
+
exports.composeMiddleware = exports.createValidationMiddleware = exports.createTracingMiddleware = exports.createRetryMiddleware = exports.createRateLimitMiddleware = exports.createRedactionMiddleware = exports.createTimeoutMiddleware = exports.createLoggingMiddleware = exports.validateTool = exports.validate_tool = exports.registerTool = exports.register_tool = exports.getTool = exports.get_tool = exports.getRegistry = exports.get_registry = exports.resetToolsRegistry = exports.createToolsRegistry = exports.getToolsRegistry = exports.ToolsRegistry = exports.BudgetExceededError = exports.MissingEnvVarError = exports.MissingDependencyError = void 0;
|
|
9
9
|
// Errors
|
|
10
10
|
var types_1 = require("./types");
|
|
11
11
|
Object.defineProperty(exports, "MissingDependencyError", { enumerable: true, get: function () { return types_1.MissingDependencyError; } });
|
|
12
12
|
Object.defineProperty(exports, "MissingEnvVarError", { enumerable: true, get: function () { return types_1.MissingEnvVarError; } });
|
|
13
|
+
Object.defineProperty(exports, "BudgetExceededError", { enumerable: true, get: function () { return types_1.BudgetExceededError; } });
|
|
13
14
|
// Registry
|
|
14
15
|
var registry_1 = require("./registry");
|
|
15
16
|
Object.defineProperty(exports, "ToolsRegistry", { enumerable: true, get: function () { return registry_1.ToolsRegistry; } });
|
|
16
17
|
Object.defineProperty(exports, "getToolsRegistry", { enumerable: true, get: function () { return registry_1.getToolsRegistry; } });
|
|
17
18
|
Object.defineProperty(exports, "createToolsRegistry", { enumerable: true, get: function () { return registry_1.createToolsRegistry; } });
|
|
18
19
|
Object.defineProperty(exports, "resetToolsRegistry", { enumerable: true, get: function () { return registry_1.resetToolsRegistry; } });
|
|
20
|
+
Object.defineProperty(exports, "get_registry", { enumerable: true, get: function () { return registry_1.get_registry; } });
|
|
21
|
+
Object.defineProperty(exports, "getRegistry", { enumerable: true, get: function () { return registry_1.getRegistry; } });
|
|
22
|
+
Object.defineProperty(exports, "get_tool", { enumerable: true, get: function () { return registry_1.get_tool; } });
|
|
23
|
+
Object.defineProperty(exports, "getTool", { enumerable: true, get: function () { return registry_1.getTool; } });
|
|
24
|
+
Object.defineProperty(exports, "register_tool", { enumerable: true, get: function () { return registry_1.register_tool; } });
|
|
25
|
+
Object.defineProperty(exports, "registerTool", { enumerable: true, get: function () { return registry_1.registerTool; } });
|
|
26
|
+
Object.defineProperty(exports, "validate_tool", { enumerable: true, get: function () { return registry_1.validate_tool; } });
|
|
27
|
+
Object.defineProperty(exports, "validateTool", { enumerable: true, get: function () { return registry_1.validateTool; } });
|
|
19
28
|
// Middleware
|
|
20
29
|
var middleware_1 = require("./middleware");
|
|
21
30
|
Object.defineProperty(exports, "createLoggingMiddleware", { enumerable: true, get: function () { return middleware_1.createLoggingMiddleware; } });
|
|
@@ -90,3 +90,36 @@ export declare function createToolsRegistry(): ToolsRegistry;
|
|
|
90
90
|
* Reset the global registry (mainly for testing)
|
|
91
91
|
*/
|
|
92
92
|
export declare function resetToolsRegistry(): void;
|
|
93
|
+
/**
|
|
94
|
+
* Get the global registry instance (alias for getToolsRegistry)
|
|
95
|
+
* For Python SDK parity: get_registry()
|
|
96
|
+
*/
|
|
97
|
+
export declare function get_registry(): ToolsRegistry;
|
|
98
|
+
/** camelCase alias for get_registry — idiomatic TypeScript */
|
|
99
|
+
export declare const getRegistry: typeof get_registry;
|
|
100
|
+
/**
|
|
101
|
+
* Get a single tool by name from the global registry
|
|
102
|
+
* For Python SDK parity: get_tool()
|
|
103
|
+
*/
|
|
104
|
+
export declare function get_tool<TConfig = unknown, TInput = unknown, TOutput = unknown>(id: string, config?: TConfig): PraisonTool<TInput, TOutput> | null;
|
|
105
|
+
/** camelCase alias for get_tool — idiomatic TypeScript */
|
|
106
|
+
export declare const getTool: typeof get_tool;
|
|
107
|
+
/**
|
|
108
|
+
* Register a tool with the global registry
|
|
109
|
+
* For Python SDK parity: register_tool()
|
|
110
|
+
*/
|
|
111
|
+
export declare function register_tool(metadata: ToolMetadata, factory: ToolFactory): void;
|
|
112
|
+
/** camelCase alias for register_tool — idiomatic TypeScript */
|
|
113
|
+
export declare const registerTool: typeof register_tool;
|
|
114
|
+
/**
|
|
115
|
+
* Validate a tool's configuration and dependencies
|
|
116
|
+
* For Python SDK parity: validate_tool()
|
|
117
|
+
*/
|
|
118
|
+
export declare function validate_tool(id: string): Promise<{
|
|
119
|
+
valid: boolean;
|
|
120
|
+
installed: boolean;
|
|
121
|
+
missingEnvVars: string[];
|
|
122
|
+
errors: string[];
|
|
123
|
+
}>;
|
|
124
|
+
/** camelCase alias for validate_tool — idiomatic TypeScript */
|
|
125
|
+
export declare const validateTool: typeof validate_tool;
|
|
@@ -39,10 +39,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
};
|
|
40
40
|
})();
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.ToolsRegistry = void 0;
|
|
42
|
+
exports.validateTool = exports.registerTool = exports.getTool = exports.getRegistry = exports.ToolsRegistry = void 0;
|
|
43
43
|
exports.getToolsRegistry = getToolsRegistry;
|
|
44
44
|
exports.createToolsRegistry = createToolsRegistry;
|
|
45
45
|
exports.resetToolsRegistry = resetToolsRegistry;
|
|
46
|
+
exports.get_registry = get_registry;
|
|
47
|
+
exports.get_tool = get_tool;
|
|
48
|
+
exports.register_tool = register_tool;
|
|
49
|
+
exports.validate_tool = validate_tool;
|
|
46
50
|
/**
|
|
47
51
|
* Tools Registry - Manages tool registration, lookup, and instantiation
|
|
48
52
|
*/
|
|
@@ -278,3 +282,77 @@ function resetToolsRegistry() {
|
|
|
278
282
|
}
|
|
279
283
|
globalRegistry = null;
|
|
280
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Get the global registry instance (alias for getToolsRegistry)
|
|
287
|
+
* For Python SDK parity: get_registry()
|
|
288
|
+
*/
|
|
289
|
+
function get_registry() {
|
|
290
|
+
return getToolsRegistry();
|
|
291
|
+
}
|
|
292
|
+
/** camelCase alias for get_registry — idiomatic TypeScript */
|
|
293
|
+
exports.getRegistry = get_registry;
|
|
294
|
+
/**
|
|
295
|
+
* Get a single tool by name from the global registry
|
|
296
|
+
* For Python SDK parity: get_tool()
|
|
297
|
+
*/
|
|
298
|
+
function get_tool(id, config) {
|
|
299
|
+
try {
|
|
300
|
+
const registry = getToolsRegistry();
|
|
301
|
+
return registry.create(id, config);
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/** camelCase alias for get_tool — idiomatic TypeScript */
|
|
308
|
+
exports.getTool = get_tool;
|
|
309
|
+
/**
|
|
310
|
+
* Register a tool with the global registry
|
|
311
|
+
* For Python SDK parity: register_tool()
|
|
312
|
+
*/
|
|
313
|
+
function register_tool(metadata, factory) {
|
|
314
|
+
const registry = getToolsRegistry();
|
|
315
|
+
registry.register(metadata, factory);
|
|
316
|
+
}
|
|
317
|
+
/** camelCase alias for register_tool — idiomatic TypeScript */
|
|
318
|
+
exports.registerTool = register_tool;
|
|
319
|
+
/**
|
|
320
|
+
* Validate a tool's configuration and dependencies
|
|
321
|
+
* For Python SDK parity: validate_tool()
|
|
322
|
+
*/
|
|
323
|
+
async function validate_tool(id) {
|
|
324
|
+
const registry = getToolsRegistry();
|
|
325
|
+
if (!registry.has(id)) {
|
|
326
|
+
return {
|
|
327
|
+
valid: false,
|
|
328
|
+
installed: false,
|
|
329
|
+
missingEnvVars: [],
|
|
330
|
+
errors: [`Tool "${id}" is not registered`]
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
const status = await registry.getInstallStatus(id);
|
|
334
|
+
if (!status) {
|
|
335
|
+
return {
|
|
336
|
+
valid: false,
|
|
337
|
+
installed: false,
|
|
338
|
+
missingEnvVars: [],
|
|
339
|
+
errors: [`Failed to get status for tool "${id}"`]
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
const errors = [];
|
|
343
|
+
if (!status.installed) {
|
|
344
|
+
const installCmd = status.installCommand ?? `npm install ${registry.getMetadata(id)?.packageName ?? id}`;
|
|
345
|
+
errors.push(`Package dependency not installed. Run: ${installCmd}`);
|
|
346
|
+
}
|
|
347
|
+
if (status.missingEnvVars.length > 0) {
|
|
348
|
+
errors.push(`Missing environment variables: ${status.missingEnvVars.join(', ')}`);
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
valid: status.installed && status.missingEnvVars.length === 0,
|
|
352
|
+
installed: status.installed,
|
|
353
|
+
missingEnvVars: status.missingEnvVars,
|
|
354
|
+
errors
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/** camelCase alias for validate_tool — idiomatic TypeScript */
|
|
358
|
+
exports.validateTool = validate_tool;
|
|
@@ -215,3 +215,20 @@ export declare class MissingEnvVarError extends Error {
|
|
|
215
215
|
readonly docsSlug: string;
|
|
216
216
|
constructor(toolId: string, envVar: string, docsSlug: string);
|
|
217
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Error thrown when an agent exceeds its budget/cost limit.
|
|
220
|
+
* Mirrors Python SDK: BudgetExceededError(agent_name, total_cost, max_budget)
|
|
221
|
+
*
|
|
222
|
+
* Usage:
|
|
223
|
+
* try { await agent.start("..."); }
|
|
224
|
+
* catch (e) {
|
|
225
|
+
* if (e instanceof BudgetExceededError)
|
|
226
|
+
* console.log(`Agent '${e.agentName}' spent $${e.totalCost} of $${e.maxBudget}`);
|
|
227
|
+
* }
|
|
228
|
+
*/
|
|
229
|
+
export declare class BudgetExceededError extends Error {
|
|
230
|
+
readonly agentName: string;
|
|
231
|
+
readonly totalCost: number;
|
|
232
|
+
readonly maxBudget: number;
|
|
233
|
+
constructor(agentName: string, totalCost: number, maxBudget: number);
|
|
234
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Standard interfaces for tool registration, execution, and middleware.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.MissingEnvVarError = exports.MissingDependencyError = void 0;
|
|
8
|
+
exports.BudgetExceededError = exports.MissingEnvVarError = exports.MissingDependencyError = void 0;
|
|
9
9
|
/**
|
|
10
10
|
* Error thrown when optional dependency is missing
|
|
11
11
|
*/
|
|
@@ -47,3 +47,24 @@ class MissingEnvVarError extends Error {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
exports.MissingEnvVarError = MissingEnvVarError;
|
|
50
|
+
/**
|
|
51
|
+
* Error thrown when an agent exceeds its budget/cost limit.
|
|
52
|
+
* Mirrors Python SDK: BudgetExceededError(agent_name, total_cost, max_budget)
|
|
53
|
+
*
|
|
54
|
+
* Usage:
|
|
55
|
+
* try { await agent.start("..."); }
|
|
56
|
+
* catch (e) {
|
|
57
|
+
* if (e instanceof BudgetExceededError)
|
|
58
|
+
* console.log(`Agent '${e.agentName}' spent $${e.totalCost} of $${e.maxBudget}`);
|
|
59
|
+
* }
|
|
60
|
+
*/
|
|
61
|
+
class BudgetExceededError extends Error {
|
|
62
|
+
constructor(agentName, totalCost, maxBudget) {
|
|
63
|
+
super(`Agent '${agentName}' exceeded budget: $${totalCost.toFixed(4)} >= $${maxBudget.toFixed(4)}`);
|
|
64
|
+
this.agentName = agentName;
|
|
65
|
+
this.totalCost = totalCost;
|
|
66
|
+
this.maxBudget = maxBudget;
|
|
67
|
+
this.name = 'BudgetExceededError';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.BudgetExceededError = BudgetExceededError;
|
|
@@ -250,22 +250,52 @@ async function scrapeUrl(url) {
|
|
|
250
250
|
// ============================================================================
|
|
251
251
|
// UTILITY TOOLS
|
|
252
252
|
// ============================================================================
|
|
253
|
+
/** Shell metacharacters that enable command chaining or substitution */
|
|
254
|
+
const SHELL_METACHAR_PATTERN = /[;|&`><]|\$\([^)]*\)|\$\{/;
|
|
255
|
+
function containsShellMetacharacters(command) {
|
|
256
|
+
return SHELL_METACHAR_PATTERN.test(command);
|
|
257
|
+
}
|
|
258
|
+
function parseCommandParts(command) {
|
|
259
|
+
const parts = command.trim().match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) ?? [];
|
|
260
|
+
return parts.map((part) => part.replace(/^["']|["']$/g, ''));
|
|
261
|
+
}
|
|
253
262
|
/**
|
|
254
263
|
* Execute shell command (safe version - read-only commands)
|
|
255
264
|
*/
|
|
256
265
|
async function shell(command) {
|
|
257
|
-
// Only allow safe read-only commands
|
|
258
266
|
const safeCommands = ['ls', 'cat', 'head', 'tail', 'wc', 'grep', 'find', 'echo', 'date', 'pwd', 'which'];
|
|
259
|
-
const
|
|
260
|
-
if (!
|
|
261
|
-
return { success: false, error:
|
|
267
|
+
const trimmed = command.trim();
|
|
268
|
+
if (!trimmed) {
|
|
269
|
+
return { success: false, error: 'Empty command' };
|
|
270
|
+
}
|
|
271
|
+
if (containsShellMetacharacters(trimmed)) {
|
|
272
|
+
return { success: false, error: 'Shell metacharacters are not allowed' };
|
|
273
|
+
}
|
|
274
|
+
const parts = parseCommandParts(trimmed);
|
|
275
|
+
const cmd = parts[0];
|
|
276
|
+
if (!safeCommands.includes(cmd)) {
|
|
277
|
+
return { success: false, error: `Command not allowed: ${cmd}` };
|
|
262
278
|
}
|
|
263
279
|
try {
|
|
264
|
-
const {
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
280
|
+
const { spawn } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
281
|
+
const result = await new Promise((resolve, reject) => {
|
|
282
|
+
const proc = spawn(cmd, parts.slice(1), {
|
|
283
|
+
shell: false,
|
|
284
|
+
timeout: 5000,
|
|
285
|
+
});
|
|
286
|
+
let stdout = '';
|
|
287
|
+
let stderr = '';
|
|
288
|
+
proc.stdout?.on('data', (data) => { stdout += data.toString(); });
|
|
289
|
+
proc.stderr?.on('data', (data) => { stderr += data.toString(); });
|
|
290
|
+
proc.on('close', (code) => {
|
|
291
|
+
resolve({ stdout, stderr, code: code ?? 1 });
|
|
292
|
+
});
|
|
293
|
+
proc.on('error', reject);
|
|
294
|
+
});
|
|
295
|
+
if (result.code !== 0) {
|
|
296
|
+
return { success: false, error: result.stderr || `Exit code ${result.code}` };
|
|
297
|
+
}
|
|
298
|
+
return { success: true, data: result.stdout || result.stderr };
|
|
269
299
|
}
|
|
270
300
|
catch (error) {
|
|
271
301
|
return { success: false, error: error.message ?? String(error) };
|