chat-agent-toolkit 1.2.2 → 1.2.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/README.md +6 -6
- package/dist/config/config-manager.d.ts +23 -0
- package/dist/config/config-types.d.ts +58 -0
- package/dist/config/environment-variables.d.ts +6 -0
- package/dist/config/index.d.ts +18 -0
- package/dist/config/language-models-database.d.ts +93 -0
- package/dist/config/mcp-server-registry.d.ts +7 -0
- package/dist/config/model-registry.d.ts +69 -0
- package/dist/config/model-tester.d.ts +51 -0
- package/dist/config/model-utils.d.ts +44 -0
- package/dist/config/provider-ui-config.d.ts +6 -0
- package/dist/index.d.ts +23 -0
- package/dist/memory/agent-memory-manager.d.ts +125 -0
- package/dist/memory/example.d.ts +36 -0
- package/dist/memory/index.d.ts +18 -0
- package/dist/memory/mastra-integration.d.ts +146 -0
- package/dist/memory/storage/drizzle-storage.d.ts +82 -0
- package/dist/memory/storage/in-memory-storage.d.ts +75 -0
- package/dist/memory/storage/storage-interface.d.ts +37 -0
- package/dist/memory/types.d.ts +122 -0
- package/dist/models/providers.d.ts +5 -0
- package/dist/models/registry.d.ts +4 -0
- package/dist/models/types.d.ts +4 -0
- package/dist/research-agent.cjs.js +2 -0
- package/dist/research-agent.cjs.js.map +1 -0
- package/dist/research-agent.es.js +2 -0
- package/dist/research-agent.es.js.map +1 -0
- package/dist/search.d.ts +5 -0
- package/dist/tools/index.d.ts +12 -0
- package/dist/tools/open-connector-mastra.d.ts +137 -0
- package/dist/tools/open-connector-mcp.d.ts +88 -0
- package/dist/tools/qwksearch-api-tools.d.ts +149 -0
- package/dist/tools/search/doc-utils.d.ts +11 -0
- package/dist/tools/search/document.d.ts +14 -0
- package/dist/tools/search/index.d.ts +12 -0
- package/dist/tools/search/link-summarizer.d.ts +7 -0
- package/dist/tools/search/meta-search-types.d.ts +50 -0
- package/dist/tools/search/metaSearchAgent.d.ts +21 -0
- package/dist/tools/search/search-handlers.d.ts +27 -0
- package/dist/tools/search/suggestionGeneratorAgent.d.ts +8 -0
- package/dist/types.d.ts +2 -0
- package/dist/utils/chat-helpers.d.ts +10 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/markdown-to-html.d.ts +5 -0
- package/dist/utils/outputParser.d.ts +22 -0
- package/dist/utils/provider-image-cropper.d.ts +120 -0
- package/package.json +14 -5
- package/src/config/config-manager.ts +0 -8
- package/src/config/environment-variables.ts +11 -3
- package/src/config/language-models-database.ts +50 -42
- package/src/config/model-registry.ts +20 -5
- package/src/config/model-tester.ts +2 -2
- package/src/connectors/{composio.json → open-connector.json} +21 -45
- package/src/index.ts +3 -0
- package/src/memory/ARCHITECTURE.md +1 -1
- package/src/memory/example.ts +6 -6
- package/src/memory/mastra-integration.ts +6 -11
- package/src/memory/storage/drizzle-storage.ts +60 -29
- package/src/memory/storage/in-memory-storage.ts +2 -2
- package/src/memory/storage/storage-interface.ts +1 -1
- package/src/models/types.ts +1 -1
- package/src/tools/{composio-mastra.ts → open-connector-mastra.ts} +58 -93
- package/src/tools/open-connector-mcp.ts +170 -0
- package/src/tools/search/doc-utils.ts +36 -8
- package/src/tools/search/metaSearchAgent.ts +11 -0
- package/src/tools/search/search-handlers.ts +13 -1
- package/src/tools/search/suggestionGeneratorAgent.ts +5 -3
- package/src/tools/composio-mcp.ts +0 -205
|
@@ -3,8 +3,13 @@
|
|
|
3
3
|
* @description Document utilities: fallback docs, reranking, and formatting.
|
|
4
4
|
*/
|
|
5
5
|
import type { Document } from "./document";
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
|
|
7
|
+
export interface R2CredentialsInput {
|
|
8
|
+
accountId: string;
|
|
9
|
+
accessKeyId: string;
|
|
10
|
+
secretAccessKey: string;
|
|
11
|
+
bucket: string;
|
|
12
|
+
}
|
|
8
13
|
|
|
9
14
|
export function buildFallbackDocs(query: string): Document[] {
|
|
10
15
|
const trimmedQuery = (query || "").trim();
|
|
@@ -31,22 +36,45 @@ export function normalizeSourcesOutput(output: unknown, query: string): Document
|
|
|
31
36
|
return buildFallbackDocs(query);
|
|
32
37
|
}
|
|
33
38
|
|
|
39
|
+
async function downloadExtractedContent(fileId: string, r2Credentials: R2CredentialsInput): Promise<{ title: string; content: string } | null> {
|
|
40
|
+
try {
|
|
41
|
+
const { manageStorage } = await import("manage-storage");
|
|
42
|
+
const config = {
|
|
43
|
+
provider: "cloudflare" as const,
|
|
44
|
+
BUCKET_NAME: r2Credentials.bucket,
|
|
45
|
+
ACCESS_KEY_ID: r2Credentials.accessKeyId,
|
|
46
|
+
SECRET_ACCESS_KEY: r2Credentials.secretAccessKey,
|
|
47
|
+
BUCKET_URL: `https://${r2Credentials.accountId}.r2.cloudflarestorage.com`,
|
|
48
|
+
};
|
|
49
|
+
const extractedKey = `${fileId}-extracted.json`;
|
|
50
|
+
const data = await manageStorage("download", { ...config, key: extractedKey });
|
|
51
|
+
const parsed = JSON.parse(data);
|
|
52
|
+
return { title: parsed.title || "Uploaded Document", content: parsed.content || "" };
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error(`[rerankDocs] Failed to download extracted content for fileId ${fileId}:`, error);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
34
59
|
export async function rerankDocs(
|
|
35
60
|
query: string,
|
|
36
61
|
docs: Document[],
|
|
37
62
|
fileIds: string[],
|
|
38
63
|
optimizationMode: "speed" | "balanced" | "quality",
|
|
64
|
+
r2Credentials?: R2CredentialsInput,
|
|
39
65
|
): Promise<Document[]> {
|
|
40
66
|
if (docs.length === 0 && fileIds.length === 0) {
|
|
41
67
|
return docs;
|
|
42
68
|
}
|
|
43
69
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
70
|
+
let filesData: { fileName: string; content: string }[] = [];
|
|
71
|
+
|
|
72
|
+
if (fileIds.length > 0 && r2Credentials) {
|
|
73
|
+
const results = await Promise.all(
|
|
74
|
+
fileIds.map((fileId) => downloadExtractedContent(fileId, r2Credentials))
|
|
75
|
+
);
|
|
76
|
+
filesData = results.filter((r) => r !== null) as { fileName: string; content: string }[];
|
|
77
|
+
}
|
|
50
78
|
|
|
51
79
|
if (query.toLocaleLowerCase() === "summarize") {
|
|
52
80
|
return docs.slice(0, 15);
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
rerankDocs,
|
|
36
36
|
processDocs,
|
|
37
37
|
normalizeSourcesOutput,
|
|
38
|
+
type R2CredentialsInput,
|
|
38
39
|
} from "./doc-utils";
|
|
39
40
|
import { groupAndSummarizeDocs } from "./link-summarizer";
|
|
40
41
|
|
|
@@ -350,11 +351,21 @@ class MetaSearchAgent implements MetaSearchAgentType {
|
|
|
350
351
|
docs = result.docs;
|
|
351
352
|
}
|
|
352
353
|
|
|
354
|
+
const r2Credentials: R2CredentialsInput | undefined = process.env.R2_ACCOUNT_ID
|
|
355
|
+
? {
|
|
356
|
+
accountId: process.env.R2_ACCOUNT_ID,
|
|
357
|
+
accessKeyId: process.env.R2_ACCESS_KEY_ID || "",
|
|
358
|
+
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY || "",
|
|
359
|
+
bucket: process.env.R2_UPLOADS_BUCKET || "qwksearch-uploads",
|
|
360
|
+
}
|
|
361
|
+
: undefined;
|
|
362
|
+
|
|
353
363
|
const sortedDocs = await rerankDocs(
|
|
354
364
|
query,
|
|
355
365
|
docs ?? [],
|
|
356
366
|
fileIds,
|
|
357
367
|
optimizationMode,
|
|
368
|
+
r2Credentials,
|
|
358
369
|
);
|
|
359
370
|
|
|
360
371
|
const sources = normalizeSourcesOutput(sortedDocs, message);
|
|
@@ -7,9 +7,21 @@
|
|
|
7
7
|
* See extract-webpage/src/search/index.ts for an example.
|
|
8
8
|
*/
|
|
9
9
|
import MetaSearchAgent from "./metaSearchAgent";
|
|
10
|
-
import
|
|
10
|
+
import {
|
|
11
|
+
webSearchRetrieverPrompt,
|
|
12
|
+
webSearchResponsePrompt,
|
|
13
|
+
webSearchRetrieverFewShots,
|
|
14
|
+
writingAssistantPrompt,
|
|
15
|
+
} from "write-language";
|
|
11
16
|
import type { Config } from "./meta-search-types";
|
|
12
17
|
|
|
18
|
+
const prompts = {
|
|
19
|
+
webSearchRetrieverPrompt,
|
|
20
|
+
webSearchResponsePrompt,
|
|
21
|
+
webSearchRetrieverFewShots,
|
|
22
|
+
writingAssistantPrompt,
|
|
23
|
+
};
|
|
24
|
+
|
|
13
25
|
/**
|
|
14
26
|
* Creates search handler instances with provided search functions.
|
|
15
27
|
* Pass in search functions from extract-webpage to enable web search.
|
|
@@ -8,8 +8,8 @@ import { LineListOutputParser } from "../../utils/outputParser";
|
|
|
8
8
|
import { formatChatHistoryAsString } from "../../utils";
|
|
9
9
|
import type { ChatTurnMessage } from "./meta-search-types";
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
You are an AI suggestion generator for an AI powered search engine. You will be given a conversation below. You need to generate
|
|
11
|
+
const createSuggestionGeneratorPrompt = (maxQuestions: number = 4) => `
|
|
12
|
+
You are an AI suggestion generator for an AI powered search engine. You will be given a conversation below. You need to generate ${maxQuestions} suggestions based on the conversation. The suggestion should be relevant to the conversation that can be used by the user to ask the chat model for more information.
|
|
13
13
|
You need to make sure the suggestions are relevant to the conversation and are helpful to the user. Keep a note that the user might use these suggestions to ask a chat model for more information.
|
|
14
14
|
Make sure the suggestions are medium in length and are informative and relevant to the conversation.
|
|
15
15
|
|
|
@@ -27,6 +27,7 @@ Conversation:
|
|
|
27
27
|
|
|
28
28
|
type SuggestionGeneratorInput = {
|
|
29
29
|
chat_history: ChatTurnMessage[];
|
|
30
|
+
maxQuestions?: number;
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
const outputParser = new LineListOutputParser({
|
|
@@ -37,7 +38,8 @@ const generateSuggestions = async (
|
|
|
37
38
|
input: SuggestionGeneratorInput,
|
|
38
39
|
llm: LanguageModel,
|
|
39
40
|
): Promise<string[]> => {
|
|
40
|
-
const
|
|
41
|
+
const maxQuestions = input.maxQuestions ?? 4;
|
|
42
|
+
const prompt = createSuggestionGeneratorPrompt(maxQuestions).replace(
|
|
41
43
|
"{chat_history}",
|
|
42
44
|
formatChatHistoryAsString(input.chat_history),
|
|
43
45
|
);
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Composio MCP Integration for AI SDK v5
|
|
3
|
-
*
|
|
4
|
-
* Composio provides dynamic MCP endpoints through sessions/Tool Router.
|
|
5
|
-
* This module creates MCP clients connected to Composio's HTTP endpoints,
|
|
6
|
-
* fetches available tools, and passes them to AI SDK models.
|
|
7
|
-
*
|
|
8
|
-
* Architecture:
|
|
9
|
-
* 1. Create Composio session → Get MCP URL + headers
|
|
10
|
-
* 2. Connect with createMCPClient (HTTP transport)
|
|
11
|
-
* 3. Fetch tools with client.tools()
|
|
12
|
-
* 4. Pass to streamText/generateText
|
|
13
|
-
*
|
|
14
|
-
* @see https://composio.dev/toolkits/ai_ml_api/framework/ai-sdk
|
|
15
|
-
* @see https://ai-sdk.dev/docs/ai-sdk-core/mcp-tools
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { Composio } from '@composio/core';
|
|
19
|
-
import { createMCPClient } from '@ai-sdk/mcp';
|
|
20
|
-
import type { MCPClient } from '@ai-sdk/mcp';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Configuration for Composio MCP session
|
|
24
|
-
*/
|
|
25
|
-
export interface ComposioMCPConfig {
|
|
26
|
-
/** Composio API key */
|
|
27
|
-
apiKey: string;
|
|
28
|
-
/** User ID to scope the session */
|
|
29
|
-
userId: string;
|
|
30
|
-
/** Toolkits to enable (e.g., ['GMAIL', 'NOTION', 'SLACK']) */
|
|
31
|
-
toolkits: string[];
|
|
32
|
-
/** Optional: Additional MCP headers (e.g., x-api-key if org requires it) */
|
|
33
|
-
additionalHeaders?: Record<string, string>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Composio MCP session wrapper
|
|
38
|
-
* Manages the lifecycle of MCP client connections to Composio
|
|
39
|
-
*/
|
|
40
|
-
export class ComposioMCPSession {
|
|
41
|
-
private composio: Composio;
|
|
42
|
-
private client: MCPClient | null = null;
|
|
43
|
-
private mcpEndpoint: { url: string; headers: Record<string, string> } | null = null;
|
|
44
|
-
|
|
45
|
-
constructor(private config: ComposioMCPConfig) {
|
|
46
|
-
this.composio = new Composio({
|
|
47
|
-
apiKey: config.apiKey,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Create Composio Tool Router session and get MCP endpoint
|
|
53
|
-
* This returns the HTTP URL and auth headers for the MCP server
|
|
54
|
-
*/
|
|
55
|
-
private async getOrCreateEndpoint() {
|
|
56
|
-
if (this.mcpEndpoint) {
|
|
57
|
-
return this.mcpEndpoint;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Create dynamic Composio session with specified toolkits
|
|
61
|
-
const session = await this.composio.toolkits.authorize({
|
|
62
|
-
userId: this.config.userId,
|
|
63
|
-
toolkits: this.config.toolkits,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Extract MCP endpoint info
|
|
67
|
-
this.mcpEndpoint = {
|
|
68
|
-
url: session.mcp.url,
|
|
69
|
-
headers: {
|
|
70
|
-
...session.mcp.headers,
|
|
71
|
-
...this.config.additionalHeaders,
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
return this.mcpEndpoint;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Get or create the MCP client connection
|
|
80
|
-
* Uses HTTP transport as recommended by Composio
|
|
81
|
-
*/
|
|
82
|
-
async getClient(): Promise<MCPClient> {
|
|
83
|
-
if (this.client) {
|
|
84
|
-
return this.client;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const endpoint = await this.getOrCreateEndpoint();
|
|
88
|
-
|
|
89
|
-
// Connect to Composio MCP endpoint via HTTP
|
|
90
|
-
this.client = await createMCPClient({
|
|
91
|
-
transport: {
|
|
92
|
-
type: 'http',
|
|
93
|
-
url: endpoint.url,
|
|
94
|
-
headers: endpoint.headers,
|
|
95
|
-
redirect: 'error',
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
return this.client;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Get all available tools from Composio MCP
|
|
104
|
-
* These tools can be passed directly to streamText/generateText
|
|
105
|
-
*
|
|
106
|
-
* @returns Tools object compatible with AI SDK
|
|
107
|
-
*/
|
|
108
|
-
async getTools() {
|
|
109
|
-
const client = await this.getClient();
|
|
110
|
-
return await client.tools();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Close the MCP connection
|
|
115
|
-
* Should be called after request completion or in finally block
|
|
116
|
-
*/
|
|
117
|
-
async close() {
|
|
118
|
-
if (this.client) {
|
|
119
|
-
await this.client.close();
|
|
120
|
-
this.client = null;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Get list of available toolkits from Composio
|
|
126
|
-
* Useful for discovering what integrations are available
|
|
127
|
-
*/
|
|
128
|
-
static async listAvailableToolkits(apiKey: string): Promise<string[]> {
|
|
129
|
-
const composio = new Composio({ apiKey });
|
|
130
|
-
const toolkits = await composio.toolkits.list();
|
|
131
|
-
return toolkits.map((t) => t.name);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Check if a user has authenticated a specific toolkit
|
|
136
|
-
* Returns true if the user can access the toolkit's tools
|
|
137
|
-
*/
|
|
138
|
-
async isToolkitAuthenticated(toolkit: string): Promise<boolean> {
|
|
139
|
-
try {
|
|
140
|
-
const integrations = await this.composio.integrations.list({
|
|
141
|
-
appName: toolkit,
|
|
142
|
-
});
|
|
143
|
-
return integrations.length > 0;
|
|
144
|
-
} catch {
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Helper function to create a one-shot Composio MCP session
|
|
152
|
-
* For quick tool usage without managing session lifecycle
|
|
153
|
-
*
|
|
154
|
-
* @example
|
|
155
|
-
* ```ts
|
|
156
|
-
* const tools = await getComposioTools({
|
|
157
|
-
* apiKey: process.env.COMPOSIO_API_KEY!,
|
|
158
|
-
* userId: 'user-123',
|
|
159
|
-
* toolkits: ['GMAIL', 'SLACK'],
|
|
160
|
-
* });
|
|
161
|
-
*
|
|
162
|
-
* const result = await generateText({
|
|
163
|
-
* model: openai('gpt-4o'),
|
|
164
|
-
* prompt: 'Check my unread emails',
|
|
165
|
-
* tools,
|
|
166
|
-
* });
|
|
167
|
-
* ```
|
|
168
|
-
*/
|
|
169
|
-
export async function getComposioTools(config: ComposioMCPConfig) {
|
|
170
|
-
const session = new ComposioMCPSession(config);
|
|
171
|
-
try {
|
|
172
|
-
return await session.getTools();
|
|
173
|
-
} finally {
|
|
174
|
-
await session.close();
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Create a reusable Composio MCP session
|
|
180
|
-
* Better for multiple requests with the same toolkits
|
|
181
|
-
*
|
|
182
|
-
* @example
|
|
183
|
-
* ```ts
|
|
184
|
-
* const session = await createComposioSession({
|
|
185
|
-
* apiKey: process.env.COMPOSIO_API_KEY!,
|
|
186
|
-
* userId: 'user-123',
|
|
187
|
-
* toolkits: ['GMAIL', 'NOTION'],
|
|
188
|
-
* });
|
|
189
|
-
*
|
|
190
|
-
* try {
|
|
191
|
-
* const tools = await session.getTools();
|
|
192
|
-
* const result = await streamText({ model, messages, tools });
|
|
193
|
-
* } finally {
|
|
194
|
-
* await session.close();
|
|
195
|
-
* }
|
|
196
|
-
* ```
|
|
197
|
-
*/
|
|
198
|
-
export async function createComposioSession(
|
|
199
|
-
config: ComposioMCPConfig
|
|
200
|
-
): Promise<ComposioMCPSession> {
|
|
201
|
-
const session = new ComposioMCPSession(config);
|
|
202
|
-
// Pre-initialize the connection
|
|
203
|
-
await session.getClient();
|
|
204
|
-
return session;
|
|
205
|
-
}
|