praisonai 1.2.0 → 1.2.2
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/cache/index.d.ts +78 -0
- package/dist/cache/index.js +235 -0
- package/dist/db/postgres.d.ts +84 -0
- package/dist/db/postgres.js +266 -0
- package/dist/db/redis.d.ts +109 -0
- package/dist/db/redis.js +307 -0
- package/dist/db/sqlite.d.ts +66 -0
- package/dist/db/sqlite.js +339 -0
- package/dist/events/index.d.ts +84 -0
- package/dist/events/index.js +153 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.js +88 -2
- package/dist/integrations/index.d.ts +7 -0
- package/dist/integrations/index.js +26 -0
- package/dist/integrations/observability/base.d.ts +123 -0
- package/dist/integrations/observability/base.js +183 -0
- package/dist/integrations/observability/index.d.ts +8 -0
- package/dist/integrations/observability/index.js +29 -0
- package/dist/integrations/observability/langfuse.d.ts +32 -0
- package/dist/integrations/observability/langfuse.js +174 -0
- package/dist/integrations/vector/base.d.ts +110 -0
- package/dist/integrations/vector/base.js +158 -0
- package/dist/integrations/vector/chroma.d.ts +25 -0
- package/dist/integrations/vector/chroma.js +143 -0
- package/dist/integrations/vector/index.d.ts +14 -0
- package/dist/integrations/vector/index.js +37 -0
- package/dist/integrations/vector/pinecone.d.ts +28 -0
- package/dist/integrations/vector/pinecone.js +172 -0
- package/dist/integrations/vector/qdrant.d.ts +25 -0
- package/dist/integrations/vector/qdrant.js +146 -0
- package/dist/integrations/vector/weaviate.d.ts +30 -0
- package/dist/integrations/vector/weaviate.js +206 -0
- package/dist/integrations/voice/base.d.ts +76 -0
- package/dist/integrations/voice/base.js +168 -0
- package/dist/integrations/voice/index.d.ts +6 -0
- package/dist/integrations/voice/index.js +26 -0
- package/dist/knowledge/graph-rag.d.ts +125 -0
- package/dist/knowledge/graph-rag.js +289 -0
- package/dist/knowledge/index.d.ts +2 -0
- package/dist/knowledge/index.js +18 -0
- package/dist/knowledge/reranker.d.ts +86 -0
- package/dist/knowledge/reranker.js +196 -0
- package/dist/tools/arxivTools.d.ts +19 -6
- package/dist/tools/arxivTools.js +13 -7
- package/dist/tools/base.d.ts +97 -0
- package/dist/tools/base.js +147 -0
- package/dist/tools/index.d.ts +1 -11
- package/dist/tools/index.js +7 -11
- package/dist/tools/mcpSse.d.ts +5 -3
- package/dist/tools/mcpSse.js +6 -4
- package/dist/workflows/yaml-parser.d.ts +48 -0
- package/dist/workflows/yaml-parser.js +304 -0
- package/package.json +1 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reranker - Rerank search results for improved relevance
|
|
3
|
+
* Inspired by mastra's rerank module
|
|
4
|
+
*/
|
|
5
|
+
export interface RerankResult {
|
|
6
|
+
id: string;
|
|
7
|
+
score: number;
|
|
8
|
+
content: string;
|
|
9
|
+
metadata?: Record<string, any>;
|
|
10
|
+
originalRank: number;
|
|
11
|
+
newRank: number;
|
|
12
|
+
}
|
|
13
|
+
export interface RerankConfig {
|
|
14
|
+
model?: string;
|
|
15
|
+
topK?: number;
|
|
16
|
+
threshold?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Abstract base class for rerankers
|
|
20
|
+
*/
|
|
21
|
+
export declare abstract class BaseReranker {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
constructor(name: string);
|
|
24
|
+
abstract rerank(query: string, documents: Array<{
|
|
25
|
+
id: string;
|
|
26
|
+
content: string;
|
|
27
|
+
metadata?: Record<string, any>;
|
|
28
|
+
}>, config?: RerankConfig): Promise<RerankResult[]>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Cohere Reranker - Uses Cohere's rerank API
|
|
32
|
+
*/
|
|
33
|
+
export declare class CohereReranker extends BaseReranker {
|
|
34
|
+
private apiKey;
|
|
35
|
+
private model;
|
|
36
|
+
constructor(config?: {
|
|
37
|
+
apiKey?: string;
|
|
38
|
+
model?: string;
|
|
39
|
+
});
|
|
40
|
+
rerank(query: string, documents: Array<{
|
|
41
|
+
id: string;
|
|
42
|
+
content: string;
|
|
43
|
+
metadata?: Record<string, any>;
|
|
44
|
+
}>, config?: RerankConfig): Promise<RerankResult[]>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Cross-Encoder Reranker - Uses sentence similarity for reranking
|
|
48
|
+
* This is a simple implementation using cosine similarity
|
|
49
|
+
*/
|
|
50
|
+
export declare class CrossEncoderReranker extends BaseReranker {
|
|
51
|
+
private embedFn?;
|
|
52
|
+
constructor(config?: {
|
|
53
|
+
embedFn?: (texts: string[]) => Promise<number[][]>;
|
|
54
|
+
});
|
|
55
|
+
rerank(query: string, documents: Array<{
|
|
56
|
+
id: string;
|
|
57
|
+
content: string;
|
|
58
|
+
metadata?: Record<string, any>;
|
|
59
|
+
}>, config?: RerankConfig): Promise<RerankResult[]>;
|
|
60
|
+
private keywordRerank;
|
|
61
|
+
private cosineSimilarity;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* LLM Reranker - Uses an LLM to score relevance
|
|
65
|
+
*/
|
|
66
|
+
export declare class LLMReranker extends BaseReranker {
|
|
67
|
+
private generateFn;
|
|
68
|
+
constructor(config: {
|
|
69
|
+
generateFn: (prompt: string) => Promise<string>;
|
|
70
|
+
});
|
|
71
|
+
rerank(query: string, documents: Array<{
|
|
72
|
+
id: string;
|
|
73
|
+
content: string;
|
|
74
|
+
metadata?: Record<string, any>;
|
|
75
|
+
}>, config?: RerankConfig): Promise<RerankResult[]>;
|
|
76
|
+
}
|
|
77
|
+
export declare function createCohereReranker(config?: {
|
|
78
|
+
apiKey?: string;
|
|
79
|
+
model?: string;
|
|
80
|
+
}): CohereReranker;
|
|
81
|
+
export declare function createCrossEncoderReranker(config?: {
|
|
82
|
+
embedFn?: (texts: string[]) => Promise<number[][]>;
|
|
83
|
+
}): CrossEncoderReranker;
|
|
84
|
+
export declare function createLLMReranker(config: {
|
|
85
|
+
generateFn: (prompt: string) => Promise<string>;
|
|
86
|
+
}): LLMReranker;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Reranker - Rerank search results for improved relevance
|
|
4
|
+
* Inspired by mastra's rerank module
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.LLMReranker = exports.CrossEncoderReranker = exports.CohereReranker = exports.BaseReranker = void 0;
|
|
8
|
+
exports.createCohereReranker = createCohereReranker;
|
|
9
|
+
exports.createCrossEncoderReranker = createCrossEncoderReranker;
|
|
10
|
+
exports.createLLMReranker = createLLMReranker;
|
|
11
|
+
/**
|
|
12
|
+
* Abstract base class for rerankers
|
|
13
|
+
*/
|
|
14
|
+
class BaseReranker {
|
|
15
|
+
constructor(name) {
|
|
16
|
+
this.name = name;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.BaseReranker = BaseReranker;
|
|
20
|
+
/**
|
|
21
|
+
* Cohere Reranker - Uses Cohere's rerank API
|
|
22
|
+
*/
|
|
23
|
+
class CohereReranker extends BaseReranker {
|
|
24
|
+
constructor(config = {}) {
|
|
25
|
+
super('CohereReranker');
|
|
26
|
+
this.apiKey = config.apiKey || process.env.COHERE_API_KEY || '';
|
|
27
|
+
this.model = config.model || 'rerank-english-v3.0';
|
|
28
|
+
}
|
|
29
|
+
async rerank(query, documents, config) {
|
|
30
|
+
if (!this.apiKey) {
|
|
31
|
+
throw new Error('Cohere API key required for reranking');
|
|
32
|
+
}
|
|
33
|
+
const response = await fetch('https://api.cohere.ai/v1/rerank', {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: {
|
|
36
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
37
|
+
'Content-Type': 'application/json'
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify({
|
|
40
|
+
model: config?.model || this.model,
|
|
41
|
+
query,
|
|
42
|
+
documents: documents.map(d => d.content),
|
|
43
|
+
top_n: config?.topK || documents.length,
|
|
44
|
+
return_documents: true
|
|
45
|
+
})
|
|
46
|
+
});
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
const error = await response.text();
|
|
49
|
+
throw new Error(`Cohere rerank error: ${response.status} - ${error}`);
|
|
50
|
+
}
|
|
51
|
+
const data = await response.json();
|
|
52
|
+
const threshold = config?.threshold || 0;
|
|
53
|
+
return (data.results || [])
|
|
54
|
+
.filter((r) => r.relevance_score >= threshold)
|
|
55
|
+
.map((r, newRank) => ({
|
|
56
|
+
id: documents[r.index].id,
|
|
57
|
+
score: r.relevance_score,
|
|
58
|
+
content: documents[r.index].content,
|
|
59
|
+
metadata: documents[r.index].metadata,
|
|
60
|
+
originalRank: r.index,
|
|
61
|
+
newRank
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.CohereReranker = CohereReranker;
|
|
66
|
+
/**
|
|
67
|
+
* Cross-Encoder Reranker - Uses sentence similarity for reranking
|
|
68
|
+
* This is a simple implementation using cosine similarity
|
|
69
|
+
*/
|
|
70
|
+
class CrossEncoderReranker extends BaseReranker {
|
|
71
|
+
constructor(config = {}) {
|
|
72
|
+
super('CrossEncoderReranker');
|
|
73
|
+
this.embedFn = config.embedFn;
|
|
74
|
+
}
|
|
75
|
+
async rerank(query, documents, config) {
|
|
76
|
+
if (!this.embedFn) {
|
|
77
|
+
// Fallback to simple keyword matching
|
|
78
|
+
return this.keywordRerank(query, documents, config);
|
|
79
|
+
}
|
|
80
|
+
// Get embeddings for query and all documents
|
|
81
|
+
const texts = [query, ...documents.map(d => d.content)];
|
|
82
|
+
const embeddings = await this.embedFn(texts);
|
|
83
|
+
const queryEmbedding = embeddings[0];
|
|
84
|
+
const docEmbeddings = embeddings.slice(1);
|
|
85
|
+
// Calculate similarity scores
|
|
86
|
+
const scores = docEmbeddings.map((docEmb, i) => ({
|
|
87
|
+
index: i,
|
|
88
|
+
score: this.cosineSimilarity(queryEmbedding, docEmb)
|
|
89
|
+
}));
|
|
90
|
+
// Sort by score descending
|
|
91
|
+
scores.sort((a, b) => b.score - a.score);
|
|
92
|
+
const threshold = config?.threshold || 0;
|
|
93
|
+
const topK = config?.topK || documents.length;
|
|
94
|
+
return scores
|
|
95
|
+
.filter(s => s.score >= threshold)
|
|
96
|
+
.slice(0, topK)
|
|
97
|
+
.map((s, newRank) => ({
|
|
98
|
+
id: documents[s.index].id,
|
|
99
|
+
score: s.score,
|
|
100
|
+
content: documents[s.index].content,
|
|
101
|
+
metadata: documents[s.index].metadata,
|
|
102
|
+
originalRank: s.index,
|
|
103
|
+
newRank
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
keywordRerank(query, documents, config) {
|
|
107
|
+
const queryTerms = query.toLowerCase().split(/\s+/);
|
|
108
|
+
const scores = documents.map((doc, i) => {
|
|
109
|
+
const content = doc.content.toLowerCase();
|
|
110
|
+
let score = 0;
|
|
111
|
+
for (const term of queryTerms) {
|
|
112
|
+
if (content.includes(term)) {
|
|
113
|
+
score += 1;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Normalize by query length
|
|
117
|
+
score = score / queryTerms.length;
|
|
118
|
+
return { index: i, score };
|
|
119
|
+
});
|
|
120
|
+
scores.sort((a, b) => b.score - a.score);
|
|
121
|
+
const threshold = config?.threshold || 0;
|
|
122
|
+
const topK = config?.topK || documents.length;
|
|
123
|
+
return scores
|
|
124
|
+
.filter(s => s.score >= threshold)
|
|
125
|
+
.slice(0, topK)
|
|
126
|
+
.map((s, newRank) => ({
|
|
127
|
+
id: documents[s.index].id,
|
|
128
|
+
score: s.score,
|
|
129
|
+
content: documents[s.index].content,
|
|
130
|
+
metadata: documents[s.index].metadata,
|
|
131
|
+
originalRank: s.index,
|
|
132
|
+
newRank
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
cosineSimilarity(a, b) {
|
|
136
|
+
const dot = a.reduce((sum, x, i) => sum + x * b[i], 0);
|
|
137
|
+
const normA = Math.sqrt(a.reduce((sum, x) => sum + x * x, 0));
|
|
138
|
+
const normB = Math.sqrt(b.reduce((sum, x) => sum + x * x, 0));
|
|
139
|
+
return dot / (normA * normB);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.CrossEncoderReranker = CrossEncoderReranker;
|
|
143
|
+
/**
|
|
144
|
+
* LLM Reranker - Uses an LLM to score relevance
|
|
145
|
+
*/
|
|
146
|
+
class LLMReranker extends BaseReranker {
|
|
147
|
+
constructor(config) {
|
|
148
|
+
super('LLMReranker');
|
|
149
|
+
this.generateFn = config.generateFn;
|
|
150
|
+
}
|
|
151
|
+
async rerank(query, documents, config) {
|
|
152
|
+
const scores = [];
|
|
153
|
+
// Score each document
|
|
154
|
+
for (let i = 0; i < documents.length; i++) {
|
|
155
|
+
const doc = documents[i];
|
|
156
|
+
const prompt = `Rate the relevance of the following document to the query on a scale of 0 to 10.
|
|
157
|
+
Query: ${query}
|
|
158
|
+
Document: ${doc.content.slice(0, 500)}
|
|
159
|
+
|
|
160
|
+
Respond with only a number between 0 and 10.`;
|
|
161
|
+
try {
|
|
162
|
+
const response = await this.generateFn(prompt);
|
|
163
|
+
const score = parseFloat(response.trim()) / 10;
|
|
164
|
+
scores.push({ index: i, score: isNaN(score) ? 0 : Math.min(1, Math.max(0, score)) });
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
scores.push({ index: i, score: 0 });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
scores.sort((a, b) => b.score - a.score);
|
|
171
|
+
const threshold = config?.threshold || 0;
|
|
172
|
+
const topK = config?.topK || documents.length;
|
|
173
|
+
return scores
|
|
174
|
+
.filter(s => s.score >= threshold)
|
|
175
|
+
.slice(0, topK)
|
|
176
|
+
.map((s, newRank) => ({
|
|
177
|
+
id: documents[s.index].id,
|
|
178
|
+
score: s.score,
|
|
179
|
+
content: documents[s.index].content,
|
|
180
|
+
metadata: documents[s.index].metadata,
|
|
181
|
+
originalRank: s.index,
|
|
182
|
+
newRank
|
|
183
|
+
}));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
exports.LLMReranker = LLMReranker;
|
|
187
|
+
// Factory functions
|
|
188
|
+
function createCohereReranker(config) {
|
|
189
|
+
return new CohereReranker(config);
|
|
190
|
+
}
|
|
191
|
+
function createCrossEncoderReranker(config) {
|
|
192
|
+
return new CrossEncoderReranker(config);
|
|
193
|
+
}
|
|
194
|
+
function createLLMReranker(config) {
|
|
195
|
+
return new LLMReranker(config);
|
|
196
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseTool } from './
|
|
1
|
+
import { BaseTool } from './base';
|
|
2
2
|
export interface ArxivPaper {
|
|
3
3
|
id: string;
|
|
4
4
|
title: string;
|
|
@@ -8,12 +8,25 @@ export interface ArxivPaper {
|
|
|
8
8
|
updated: string;
|
|
9
9
|
link: string;
|
|
10
10
|
}
|
|
11
|
-
export declare class ArxivSearchTool extends BaseTool
|
|
11
|
+
export declare class ArxivSearchTool extends BaseTool<{
|
|
12
|
+
query: string;
|
|
13
|
+
maxResults?: number;
|
|
14
|
+
}, ArxivPaper[]> {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
12
17
|
private parser;
|
|
13
18
|
constructor();
|
|
14
|
-
|
|
19
|
+
run(params: {
|
|
20
|
+
query: string;
|
|
21
|
+
maxResults?: number;
|
|
22
|
+
}): Promise<ArxivPaper[]>;
|
|
15
23
|
}
|
|
16
|
-
export declare class ArxivDownloadTool extends BaseTool
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
export declare class ArxivDownloadTool extends BaseTool<{
|
|
25
|
+
paperId: string;
|
|
26
|
+
}, Buffer> {
|
|
27
|
+
name: string;
|
|
28
|
+
description: string;
|
|
29
|
+
run(params: {
|
|
30
|
+
paperId: string;
|
|
31
|
+
}): Promise<Buffer>;
|
|
19
32
|
}
|
package/dist/tools/arxivTools.js
CHANGED
|
@@ -5,17 +5,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ArxivDownloadTool = exports.ArxivSearchTool = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
|
-
const index_1 = require("./index");
|
|
9
8
|
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
10
|
-
|
|
9
|
+
const base_1 = require("./base");
|
|
10
|
+
class ArxivSearchTool extends base_1.BaseTool {
|
|
11
11
|
constructor() {
|
|
12
|
-
super(
|
|
12
|
+
super();
|
|
13
|
+
this.name = 'arxiv-search';
|
|
14
|
+
this.description = 'Search for academic papers on arXiv';
|
|
13
15
|
this.parser = new fast_xml_parser_1.XMLParser({
|
|
14
16
|
ignoreAttributes: false,
|
|
15
17
|
attributeNamePrefix: '@_'
|
|
16
18
|
});
|
|
17
19
|
}
|
|
18
|
-
async
|
|
20
|
+
async run(params) {
|
|
21
|
+
const { query, maxResults = 10 } = params;
|
|
19
22
|
try {
|
|
20
23
|
const response = await axios_1.default.get(`http://export.arxiv.org/api/query`, {
|
|
21
24
|
params: {
|
|
@@ -53,11 +56,14 @@ class ArxivSearchTool extends index_1.BaseTool {
|
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
exports.ArxivSearchTool = ArxivSearchTool;
|
|
56
|
-
class ArxivDownloadTool extends
|
|
59
|
+
class ArxivDownloadTool extends base_1.BaseTool {
|
|
57
60
|
constructor() {
|
|
58
|
-
super(
|
|
61
|
+
super(...arguments);
|
|
62
|
+
this.name = 'arxiv-download';
|
|
63
|
+
this.description = 'Download PDF of an arXiv paper';
|
|
59
64
|
}
|
|
60
|
-
async
|
|
65
|
+
async run(params) {
|
|
66
|
+
const { paperId } = params;
|
|
61
67
|
try {
|
|
62
68
|
const response = await axios_1.default.get(`https://arxiv.org/pdf/${paperId}.pdf`, {
|
|
63
69
|
responseType: 'arraybuffer'
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BaseTool - Abstract base class for creating custom tools (plugins)
|
|
3
|
+
*
|
|
4
|
+
* This provides the same extensibility pattern as Python's BaseTool.
|
|
5
|
+
* External developers can create plugins by extending BaseTool.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { BaseTool } from 'praisonai';
|
|
9
|
+
*
|
|
10
|
+
* class MyTool extends BaseTool {
|
|
11
|
+
* name = 'my_tool';
|
|
12
|
+
* description = 'Does something useful';
|
|
13
|
+
*
|
|
14
|
+
* async run(params: { query: string }): Promise<string> {
|
|
15
|
+
* return `Result for ${params.query}`;
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
19
|
+
export interface ToolResult<T = any> {
|
|
20
|
+
output: T;
|
|
21
|
+
success: boolean;
|
|
22
|
+
error?: string;
|
|
23
|
+
metadata?: Record<string, any>;
|
|
24
|
+
}
|
|
25
|
+
export declare class ToolValidationError extends Error {
|
|
26
|
+
constructor(message: string);
|
|
27
|
+
}
|
|
28
|
+
export interface ToolParameters {
|
|
29
|
+
type: 'object';
|
|
30
|
+
properties: Record<string, {
|
|
31
|
+
type: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
enum?: string[];
|
|
34
|
+
default?: any;
|
|
35
|
+
}>;
|
|
36
|
+
required?: string[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Abstract base class for all PraisonAI tools.
|
|
40
|
+
*
|
|
41
|
+
* Subclass this to create custom tools that can be:
|
|
42
|
+
* - Used directly by agents
|
|
43
|
+
* - Distributed as npm packages (plugins)
|
|
44
|
+
* - Auto-discovered via package.json
|
|
45
|
+
*/
|
|
46
|
+
export declare abstract class BaseTool<TParams = any, TResult = any> {
|
|
47
|
+
/** Unique identifier for the tool */
|
|
48
|
+
abstract name: string;
|
|
49
|
+
/** Human-readable description (used by LLM) */
|
|
50
|
+
abstract description: string;
|
|
51
|
+
/** Tool version string */
|
|
52
|
+
version: string;
|
|
53
|
+
/** JSON Schema for parameters */
|
|
54
|
+
parameters?: ToolParameters;
|
|
55
|
+
/**
|
|
56
|
+
* Execute the tool with given arguments.
|
|
57
|
+
* This method must be implemented by subclasses.
|
|
58
|
+
*/
|
|
59
|
+
abstract run(params: TParams): Promise<TResult> | TResult;
|
|
60
|
+
/**
|
|
61
|
+
* Allow tool to be called directly like a function.
|
|
62
|
+
*/
|
|
63
|
+
execute(params: TParams): Promise<TResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Execute tool with error handling, returning ToolResult.
|
|
66
|
+
*/
|
|
67
|
+
safeRun(params: TParams): Promise<ToolResult<TResult>>;
|
|
68
|
+
/**
|
|
69
|
+
* Get OpenAI-compatible function schema for this tool.
|
|
70
|
+
*/
|
|
71
|
+
getSchema(): {
|
|
72
|
+
type: 'function';
|
|
73
|
+
function: {
|
|
74
|
+
name: string;
|
|
75
|
+
description: string;
|
|
76
|
+
parameters: any;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Validate the tool configuration.
|
|
81
|
+
*/
|
|
82
|
+
validate(): boolean;
|
|
83
|
+
toString(): string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Validate any tool-like object.
|
|
87
|
+
*/
|
|
88
|
+
export declare function validateTool(tool: any): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Create a simple tool from a function (alternative to class-based approach)
|
|
91
|
+
*/
|
|
92
|
+
export declare function createTool<TParams = any, TResult = any>(config: {
|
|
93
|
+
name: string;
|
|
94
|
+
description: string;
|
|
95
|
+
parameters?: ToolParameters;
|
|
96
|
+
run: (params: TParams) => Promise<TResult> | TResult;
|
|
97
|
+
}): BaseTool<TParams, TResult>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* BaseTool - Abstract base class for creating custom tools (plugins)
|
|
4
|
+
*
|
|
5
|
+
* This provides the same extensibility pattern as Python's BaseTool.
|
|
6
|
+
* External developers can create plugins by extending BaseTool.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* import { BaseTool } from 'praisonai';
|
|
10
|
+
*
|
|
11
|
+
* class MyTool extends BaseTool {
|
|
12
|
+
* name = 'my_tool';
|
|
13
|
+
* description = 'Does something useful';
|
|
14
|
+
*
|
|
15
|
+
* async run(params: { query: string }): Promise<string> {
|
|
16
|
+
* return `Result for ${params.query}`;
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.BaseTool = exports.ToolValidationError = void 0;
|
|
22
|
+
exports.validateTool = validateTool;
|
|
23
|
+
exports.createTool = createTool;
|
|
24
|
+
class ToolValidationError extends Error {
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'ToolValidationError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.ToolValidationError = ToolValidationError;
|
|
31
|
+
/**
|
|
32
|
+
* Abstract base class for all PraisonAI tools.
|
|
33
|
+
*
|
|
34
|
+
* Subclass this to create custom tools that can be:
|
|
35
|
+
* - Used directly by agents
|
|
36
|
+
* - Distributed as npm packages (plugins)
|
|
37
|
+
* - Auto-discovered via package.json
|
|
38
|
+
*/
|
|
39
|
+
class BaseTool {
|
|
40
|
+
constructor() {
|
|
41
|
+
/** Tool version string */
|
|
42
|
+
this.version = '1.0.0';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Allow tool to be called directly like a function.
|
|
46
|
+
*/
|
|
47
|
+
async execute(params) {
|
|
48
|
+
return this.run(params);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Execute tool with error handling, returning ToolResult.
|
|
52
|
+
*/
|
|
53
|
+
async safeRun(params) {
|
|
54
|
+
try {
|
|
55
|
+
const output = await this.run(params);
|
|
56
|
+
return { output, success: true };
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
return {
|
|
60
|
+
output: null,
|
|
61
|
+
success: false,
|
|
62
|
+
error: error.message
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get OpenAI-compatible function schema for this tool.
|
|
68
|
+
*/
|
|
69
|
+
getSchema() {
|
|
70
|
+
return {
|
|
71
|
+
type: 'function',
|
|
72
|
+
function: {
|
|
73
|
+
name: this.name,
|
|
74
|
+
description: this.description,
|
|
75
|
+
parameters: this.parameters || { type: 'object', properties: {}, required: [] }
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Validate the tool configuration.
|
|
81
|
+
*/
|
|
82
|
+
validate() {
|
|
83
|
+
const errors = [];
|
|
84
|
+
if (!this.name || typeof this.name !== 'string') {
|
|
85
|
+
errors.push("Tool must have a non-empty string 'name'");
|
|
86
|
+
}
|
|
87
|
+
if (!this.description || typeof this.description !== 'string') {
|
|
88
|
+
errors.push("Tool must have a non-empty string 'description'");
|
|
89
|
+
}
|
|
90
|
+
if (errors.length > 0) {
|
|
91
|
+
throw new ToolValidationError(`Tool '${this.name}' validation failed: ${errors.join('; ')}`);
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
toString() {
|
|
96
|
+
return `${this.constructor.name}(name='${this.name}')`;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.BaseTool = BaseTool;
|
|
100
|
+
/**
|
|
101
|
+
* Validate any tool-like object.
|
|
102
|
+
*/
|
|
103
|
+
function validateTool(tool) {
|
|
104
|
+
if (tool instanceof BaseTool) {
|
|
105
|
+
return tool.validate();
|
|
106
|
+
}
|
|
107
|
+
if (typeof tool === 'function' || (tool && typeof tool.run === 'function')) {
|
|
108
|
+
const name = tool.name || tool.__name__;
|
|
109
|
+
if (!name) {
|
|
110
|
+
throw new ToolValidationError('Tool must have a name');
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
throw new ToolValidationError(`Invalid tool type: ${typeof tool}`);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Create a simple tool from a function (alternative to class-based approach)
|
|
118
|
+
*/
|
|
119
|
+
function createTool(config) {
|
|
120
|
+
return {
|
|
121
|
+
name: config.name,
|
|
122
|
+
description: config.description,
|
|
123
|
+
version: '1.0.0',
|
|
124
|
+
parameters: config.parameters,
|
|
125
|
+
run: config.run,
|
|
126
|
+
execute: async (params) => config.run(params),
|
|
127
|
+
safeRun: async (params) => {
|
|
128
|
+
try {
|
|
129
|
+
const output = await config.run(params);
|
|
130
|
+
return { output, success: true };
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
return { output: null, success: false, error: error.message };
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
getSchema: () => ({
|
|
137
|
+
type: 'function',
|
|
138
|
+
function: {
|
|
139
|
+
name: config.name,
|
|
140
|
+
description: config.description,
|
|
141
|
+
parameters: config.parameters || { type: 'object', properties: {}, required: [] }
|
|
142
|
+
}
|
|
143
|
+
}),
|
|
144
|
+
validate: () => true,
|
|
145
|
+
toString: () => `Tool(name='${config.name}')`
|
|
146
|
+
};
|
|
147
|
+
}
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
export
|
|
2
|
-
name: string;
|
|
3
|
-
description: string;
|
|
4
|
-
execute(...args: any[]): Promise<any>;
|
|
5
|
-
}
|
|
6
|
-
export declare class BaseTool implements Tool {
|
|
7
|
-
name: string;
|
|
8
|
-
description: string;
|
|
9
|
-
constructor(name: string, description: string);
|
|
10
|
-
execute(...args: any[]): Promise<any>;
|
|
11
|
-
}
|
|
1
|
+
export { BaseTool, ToolResult, ToolValidationError, validateTool, createTool, type ToolParameters } from './base';
|
|
12
2
|
export * from './decorator';
|
|
13
3
|
export * from './arxivTools';
|
|
14
4
|
export * from './mcpSse';
|
package/dist/tools/index.js
CHANGED
|
@@ -14,17 +14,13 @@ 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.BaseTool = void 0;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
throw new Error('Method not implemented.');
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
exports.BaseTool = BaseTool;
|
|
17
|
+
exports.createTool = exports.validateTool = exports.ToolValidationError = exports.BaseTool = void 0;
|
|
18
|
+
// Export base tool interfaces and classes
|
|
19
|
+
var base_1 = require("./base");
|
|
20
|
+
Object.defineProperty(exports, "BaseTool", { enumerable: true, get: function () { return base_1.BaseTool; } });
|
|
21
|
+
Object.defineProperty(exports, "ToolValidationError", { enumerable: true, get: function () { return base_1.ToolValidationError; } });
|
|
22
|
+
Object.defineProperty(exports, "validateTool", { enumerable: true, get: function () { return base_1.validateTool; } });
|
|
23
|
+
Object.defineProperty(exports, "createTool", { enumerable: true, get: function () { return base_1.createTool; } });
|
|
28
24
|
// Export decorator and registry
|
|
29
25
|
__exportStar(require("./decorator"), exports);
|
|
30
26
|
// Export all tool modules
|
package/dist/tools/mcpSse.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
-
import { BaseTool } from './
|
|
2
|
+
import { BaseTool } from './base';
|
|
3
3
|
export interface MCPToolInfo {
|
|
4
4
|
name: string;
|
|
5
5
|
description?: string;
|
|
6
6
|
inputSchema?: any;
|
|
7
7
|
}
|
|
8
|
-
export declare class MCPTool extends BaseTool {
|
|
8
|
+
export declare class MCPTool extends BaseTool<any, any> {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
9
11
|
private client;
|
|
10
12
|
private inputSchema;
|
|
11
13
|
constructor(info: MCPToolInfo, client: Client);
|
|
12
14
|
get schemaProperties(): Record<string, any> | undefined;
|
|
13
|
-
|
|
15
|
+
run(args?: any): Promise<any>;
|
|
14
16
|
toOpenAITool(): {
|
|
15
17
|
type: string;
|
|
16
18
|
function: {
|