@xalia/agent 0.5.7 → 0.6.0
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 +23 -8
- package/dist/agent/src/agent/agent.js +176 -96
- package/dist/agent/src/agent/agentUtils.js +82 -59
- package/dist/agent/src/agent/compressingContextManager.js +102 -0
- package/dist/agent/src/agent/context.js +189 -0
- package/dist/agent/src/agent/dummyLLM.js +46 -5
- package/dist/agent/src/agent/mcpServerManager.js +23 -24
- package/dist/agent/src/agent/nullAgentEventHandler.js +21 -0
- package/dist/agent/src/agent/nullPlatform.js +14 -0
- package/dist/agent/src/agent/openAILLMStreaming.js +26 -14
- package/dist/agent/src/agent/promptProvider.js +63 -0
- package/dist/agent/src/agent/repeatLLM.js +5 -5
- package/dist/agent/src/agent/sudoMcpServerManager.js +23 -21
- package/dist/agent/src/agent/tokenAuth.js +7 -7
- package/dist/agent/src/agent/tools.js +1 -1
- package/dist/agent/src/chat/client/chatClient.js +733 -0
- package/dist/agent/src/chat/client/connection.js +209 -0
- package/dist/agent/src/chat/client/connection.test.js +188 -0
- package/dist/agent/src/chat/client/constants.js +5 -0
- package/dist/agent/src/chat/client/index.js +15 -0
- package/dist/agent/src/chat/client/interfaces.js +2 -0
- package/dist/agent/src/chat/client/responseHandler.js +105 -0
- package/dist/agent/src/chat/client/sessionClient.js +331 -0
- package/dist/agent/src/chat/client/teamManager.js +2 -0
- package/dist/agent/src/chat/{apiKeyManager.js → data/apiKeyManager.js} +4 -0
- package/dist/agent/src/chat/data/dataModels.js +2 -0
- package/dist/agent/src/chat/data/database.js +749 -0
- package/dist/agent/src/chat/data/dbMcpServerConfigs.js +47 -0
- package/dist/agent/src/chat/protocol/connectionMessages.js +5 -0
- package/dist/agent/src/chat/protocol/constants.js +50 -0
- package/dist/agent/src/chat/protocol/errors.js +22 -0
- package/dist/agent/src/chat/protocol/messages.js +110 -0
- package/dist/agent/src/chat/server/chatContextManager.js +405 -0
- package/dist/agent/src/chat/server/connectionManager.js +352 -0
- package/dist/agent/src/chat/server/connectionManager.test.js +159 -0
- package/dist/agent/src/chat/server/conversation.js +198 -0
- package/dist/agent/src/chat/server/errorUtils.js +23 -0
- package/dist/agent/src/chat/server/openSession.js +869 -0
- package/dist/agent/src/chat/server/server.js +177 -0
- package/dist/agent/src/chat/server/sessionFileManager.js +161 -0
- package/dist/agent/src/chat/server/sessionRegistry.js +700 -0
- package/dist/agent/src/chat/server/sessionRegistry.test.js +97 -0
- package/dist/agent/src/chat/server/test-utils/mockFactories.js +307 -0
- package/dist/agent/src/chat/server/tools.js +243 -0
- package/dist/agent/src/chat/utils/agentSessionMap.js +66 -0
- package/dist/agent/src/chat/utils/approvalManager.js +85 -0
- package/dist/agent/src/{utils → chat/utils}/asyncLock.js +3 -3
- package/dist/agent/src/chat/{asyncQueue.js → utils/asyncQueue.js} +12 -2
- package/dist/agent/src/chat/utils/htmlToText.js +84 -0
- package/dist/agent/src/chat/utils/multiAsyncQueue.js +42 -0
- package/dist/agent/src/chat/utils/search.js +145 -0
- package/dist/agent/src/chat/utils/userResolver.js +46 -0
- package/dist/agent/src/chat/utils/websocket.js +16 -0
- package/dist/agent/src/test/agent.test.js +332 -0
- package/dist/agent/src/test/approvalManager.test.js +58 -0
- package/dist/agent/src/test/chatContextManager.test.js +392 -0
- package/dist/agent/src/test/clientServerConnection.test.js +158 -0
- package/dist/agent/src/test/compressingContextManager.test.js +65 -0
- package/dist/agent/src/test/context.test.js +83 -0
- package/dist/agent/src/test/conversation.test.js +89 -0
- package/dist/agent/src/test/db.test.js +271 -83
- package/dist/agent/src/test/dbMcpServerConfigs.test.js +72 -0
- package/dist/agent/src/test/dbTestTools.js +99 -0
- package/dist/agent/src/test/imageLoad.test.js +8 -7
- package/dist/agent/src/test/mcpServerManager.test.js +23 -20
- package/dist/agent/src/test/multiAsyncQueue.test.js +101 -0
- package/dist/agent/src/test/openaiStreaming.test.js +64 -35
- package/dist/agent/src/test/prompt.test.js +5 -4
- package/dist/agent/src/test/promptProvider.test.js +28 -0
- package/dist/agent/src/test/responseHandler.test.js +61 -0
- package/dist/agent/src/test/sudoMcpServerManager.test.js +24 -25
- package/dist/agent/src/test/testTools.js +109 -0
- package/dist/agent/src/test/tools.test.js +31 -0
- package/dist/agent/src/tool/agentChat.js +21 -10
- package/dist/agent/src/tool/agentMain.js +1 -1
- package/dist/agent/src/tool/chatMain.js +241 -58
- package/dist/agent/src/tool/commandPrompt.js +22 -17
- package/dist/agent/src/tool/files.js +20 -16
- package/dist/agent/src/tool/nodePlatform.js +47 -3
- package/dist/agent/src/tool/options.js +4 -4
- package/dist/agent/src/tool/prompt.js +19 -13
- package/eslint.config.mjs +14 -1
- package/package.json +14 -6
- package/scripts/chat_server +8 -0
- package/scripts/setup_chat +7 -2
- package/scripts/shutdown_chat_server +3 -0
- package/scripts/test_chat +135 -17
- package/src/agent/agent.ts +283 -138
- package/src/agent/agentUtils.ts +143 -108
- package/src/agent/compressingContextManager.ts +164 -0
- package/src/agent/context.ts +268 -0
- package/src/agent/dummyLLM.ts +76 -8
- package/src/agent/iAgentEventHandler.ts +54 -0
- package/src/agent/iplatform.ts +1 -0
- package/src/agent/mcpServerManager.ts +35 -31
- package/src/agent/nullAgentEventHandler.ts +20 -0
- package/src/agent/nullPlatform.ts +13 -0
- package/src/agent/openAILLMStreaming.ts +26 -13
- package/src/agent/promptProvider.ts +87 -0
- package/src/agent/repeatLLM.ts +5 -5
- package/src/agent/sudoMcpServerManager.ts +30 -29
- package/src/agent/tokenAuth.ts +7 -7
- package/src/agent/tools.ts +3 -1
- package/src/chat/client/chatClient.ts +900 -0
- package/src/chat/client/connection.test.ts +241 -0
- package/src/chat/client/connection.ts +276 -0
- package/src/chat/client/constants.ts +3 -0
- package/src/chat/client/index.ts +18 -0
- package/src/chat/client/interfaces.ts +34 -0
- package/src/chat/client/responseHandler.ts +131 -0
- package/src/chat/client/sessionClient.ts +443 -0
- package/src/chat/client/teamManager.ts +29 -0
- package/src/chat/{apiKeyManager.ts → data/apiKeyManager.ts} +6 -2
- package/src/chat/data/dataModels.ts +85 -0
- package/src/chat/data/database.ts +982 -0
- package/src/chat/data/dbMcpServerConfigs.ts +59 -0
- package/src/chat/protocol/connectionMessages.ts +49 -0
- package/src/chat/protocol/constants.ts +55 -0
- package/src/chat/protocol/errors.ts +16 -0
- package/src/chat/protocol/messages.ts +682 -0
- package/src/chat/server/README.md +127 -0
- package/src/chat/server/chatContextManager.ts +612 -0
- package/src/chat/server/connectionManager.test.ts +266 -0
- package/src/chat/server/connectionManager.ts +541 -0
- package/src/chat/server/conversation.ts +269 -0
- package/src/chat/server/errorUtils.ts +28 -0
- package/src/chat/server/openSession.ts +1332 -0
- package/src/chat/server/server.ts +177 -0
- package/src/chat/server/sessionFileManager.ts +239 -0
- package/src/chat/server/sessionRegistry.test.ts +138 -0
- package/src/chat/server/sessionRegistry.ts +1064 -0
- package/src/chat/server/test-utils/mockFactories.ts +422 -0
- package/src/chat/server/tools.ts +265 -0
- package/src/chat/utils/agentSessionMap.ts +76 -0
- package/src/chat/utils/approvalManager.ts +111 -0
- package/src/{utils → chat/utils}/asyncLock.ts +3 -3
- package/src/chat/{asyncQueue.ts → utils/asyncQueue.ts} +14 -3
- package/src/chat/utils/htmlToText.ts +61 -0
- package/src/chat/utils/multiAsyncQueue.ts +52 -0
- package/src/chat/utils/search.ts +139 -0
- package/src/chat/utils/userResolver.ts +48 -0
- package/src/chat/utils/websocket.ts +16 -0
- package/src/test/agent.test.ts +487 -0
- package/src/test/approvalManager.test.ts +73 -0
- package/src/test/chatContextManager.test.ts +521 -0
- package/src/test/clientServerConnection.test.ts +207 -0
- package/src/test/compressingContextManager.test.ts +82 -0
- package/src/test/context.test.ts +105 -0
- package/src/test/conversation.test.ts +109 -0
- package/src/test/db.test.ts +358 -89
- package/src/test/dbMcpServerConfigs.test.ts +112 -0
- package/src/test/dbTestTools.ts +153 -0
- package/src/test/imageLoad.test.ts +7 -6
- package/src/test/mcpServerManager.test.ts +21 -16
- package/src/test/multiAsyncQueue.test.ts +125 -0
- package/src/test/openaiStreaming.test.ts +71 -36
- package/src/test/prompt.test.ts +4 -3
- package/src/test/promptProvider.test.ts +33 -0
- package/src/test/responseHandler.test.ts +78 -0
- package/src/test/sudoMcpServerManager.test.ts +32 -30
- package/src/test/testTools.ts +146 -0
- package/src/test/tools.test.ts +39 -0
- package/src/tool/agentChat.ts +26 -12
- package/src/tool/agentMain.ts +1 -1
- package/src/tool/chatMain.ts +292 -100
- package/src/tool/commandPrompt.ts +28 -19
- package/src/tool/files.ts +25 -19
- package/src/tool/nodePlatform.ts +52 -3
- package/src/tool/options.ts +4 -2
- package/src/tool/prompt.ts +22 -15
- package/test_data/dummyllm_script_crash.json +32 -0
- package/test_data/frog.png.b64 +1 -0
- package/vitest.config.ts +39 -0
- package/dist/agent/src/chat/client.js +0 -349
- package/dist/agent/src/chat/conversationManager.js +0 -392
- package/dist/agent/src/chat/db.js +0 -209
- package/dist/agent/src/chat/frontendClient.js +0 -74
- package/dist/agent/src/chat/server.js +0 -158
- package/src/chat/client.ts +0 -455
- package/src/chat/conversationManager.ts +0 -595
- package/src/chat/db.ts +0 -290
- package/src/chat/frontendClient.ts +0 -123
- package/src/chat/messages.ts +0 -235
- package/src/chat/server.ts +0 -177
- /package/dist/agent/src/{chat/messages.js → agent/iAgentEventHandler.js} +0 -0
- /package/{frog.png → test_data/frog.png} +0 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
// -*- typescript -*-
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.OpenSession = exports.ConnectionManager = void 0;
|
|
39
|
+
exports.runServer = runServer;
|
|
40
|
+
exports.resolveSessionIdFromIdentifier = resolveSessionIdFromIdentifier;
|
|
41
|
+
exports.resolveAgentProfileId = resolveAgentProfileId;
|
|
42
|
+
const dotenv = __importStar(require("dotenv"));
|
|
43
|
+
const sdk_1 = require("@xalia/xmcp/sdk");
|
|
44
|
+
const ws_1 = require("ws");
|
|
45
|
+
const connectionManager_1 = require("./connectionManager");
|
|
46
|
+
const database_1 = require("../data/database");
|
|
47
|
+
const apiKeyManager_1 = require("../data/apiKeyManager");
|
|
48
|
+
const errors_1 = require("../protocol/errors");
|
|
49
|
+
const sessionRegistry_1 = require("./sessionRegistry");
|
|
50
|
+
dotenv.config();
|
|
51
|
+
const logger = (0, sdk_1.getLogger)();
|
|
52
|
+
/**
|
|
53
|
+
* Extract error message from unknown error type
|
|
54
|
+
*/
|
|
55
|
+
function extractErrorMessage(e) {
|
|
56
|
+
if (typeof e === "string")
|
|
57
|
+
return e;
|
|
58
|
+
if (e instanceof Error)
|
|
59
|
+
return e.message;
|
|
60
|
+
return "Unknown connection error";
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Send error response and close WebSocket connection
|
|
64
|
+
*/
|
|
65
|
+
function sendErrorAndClose(ws, message) {
|
|
66
|
+
try {
|
|
67
|
+
sendErrorResponse(ws, message);
|
|
68
|
+
}
|
|
69
|
+
catch (closeError) {
|
|
70
|
+
logger.error(`[server] Error closing connection:`, closeError);
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
ws.close(4000, message);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Send error response but keep connection open
|
|
78
|
+
*/
|
|
79
|
+
function sendErrorResponse(ws, message) {
|
|
80
|
+
try {
|
|
81
|
+
ws.send(JSON.stringify({
|
|
82
|
+
t: "error",
|
|
83
|
+
e: message,
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
catch (sendError) {
|
|
87
|
+
logger.error(`[server] Error sending error response:`, sendError);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function runServer(port, supabaseUrl, supabaseKey, llmUrl, xmcpUrl) {
|
|
91
|
+
return new Promise((r, _e) => {
|
|
92
|
+
const wss = new ws_1.WebSocketServer({ port });
|
|
93
|
+
const db = new database_1.Database(supabaseUrl, supabaseKey);
|
|
94
|
+
const apiKeyManager = new apiKeyManager_1.ApiKeyManager(db);
|
|
95
|
+
const createSessionRegistry = (connManager) => {
|
|
96
|
+
return new sessionRegistry_1.SessionRegistry(db, connManager, llmUrl, xmcpUrl);
|
|
97
|
+
};
|
|
98
|
+
const connectionManager = connectionManager_1.ConnectionManager.init(apiKeyManager, createSessionRegistry);
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
100
|
+
wss.on("connection", async (ws, req) => {
|
|
101
|
+
try {
|
|
102
|
+
logger.info(`[server] connection: ${req.url || "unknown"}`);
|
|
103
|
+
logger.info(`[server] headers: ${JSON.stringify(req.headers)}`);
|
|
104
|
+
// Extract API key and clientMessageId from WebSocket subprotocol header
|
|
105
|
+
// Format: "apiKey, clientMessageId" (comma-separated)
|
|
106
|
+
const subprotocols = req.headers["sec-websocket-protocol"];
|
|
107
|
+
if (!subprotocols) {
|
|
108
|
+
throw new errors_1.ChatFatalError("empty api key");
|
|
109
|
+
}
|
|
110
|
+
// Parse the subprotocols - they come as comma-separated string
|
|
111
|
+
if (typeof subprotocols !== "string") {
|
|
112
|
+
throw new errors_1.ChatFatalError("subprotocols was not a string");
|
|
113
|
+
}
|
|
114
|
+
const protocols = subprotocols.split(",").map((p) => p.trim());
|
|
115
|
+
const apiKey = protocols[0];
|
|
116
|
+
if (!apiKey) {
|
|
117
|
+
throw new errors_1.ChatFatalError("empty api key");
|
|
118
|
+
}
|
|
119
|
+
// Handle via ConnectionManager (multi-session protocol only)
|
|
120
|
+
await connectionManager.handleConnection(ws, apiKey, req);
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
logger.error(`[server] Connection error:`, e);
|
|
124
|
+
// Extract error message consistently
|
|
125
|
+
const errorMessage = extractErrorMessage(e);
|
|
126
|
+
if (e instanceof errors_1.ChatFatalError) {
|
|
127
|
+
// Fatal errors: send error response and close connection
|
|
128
|
+
sendErrorAndClose(ws, errorMessage);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// Non-fatal errors: send error response but keep connection open
|
|
132
|
+
sendErrorResponse(ws, errorMessage);
|
|
133
|
+
logger.error(`[server] Client error:`, errorMessage);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
logger.info(`[server] started: ws://localhost:${String(port)}/`);
|
|
138
|
+
r(wss);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
async function resolveSessionIdFromIdentifier(db, sessionIdentifier) {
|
|
142
|
+
logger.info(`[resolveSessionIdFromIdentifier] ${sessionIdentifier}`);
|
|
143
|
+
let session = undefined;
|
|
144
|
+
const compound = (0, database_1.resolveCompoundName)(sessionIdentifier);
|
|
145
|
+
logger.info(`[resolveSessionIdFromIdentifier] compound: ${JSON.stringify(compound)}`);
|
|
146
|
+
if (typeof compound === "string") {
|
|
147
|
+
// Interpret as an id
|
|
148
|
+
session = await db.sessionGetById(compound);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
session = await db.sessionGetByName(compound[0], compound[1]);
|
|
152
|
+
}
|
|
153
|
+
logger.info(`[resolveSessionIdFromIdentifier] ${JSON.stringify(session)}`);
|
|
154
|
+
return session?.session_uuid;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Try as id, then by user/name and return the AgentProfile uuid.
|
|
158
|
+
*/
|
|
159
|
+
async function resolveAgentProfileId(db, userData, agentProfileIdentifier) {
|
|
160
|
+
let ap = await db.getSavedAgentProfileById(agentProfileIdentifier);
|
|
161
|
+
logger.debug(`[resolveAgentProfileId]: by id: {JSON.stringify(ap)}`);
|
|
162
|
+
if (ap) {
|
|
163
|
+
return agentProfileIdentifier;
|
|
164
|
+
}
|
|
165
|
+
ap = await db.getSavedAgentProfileByName(userData.uuid, agentProfileIdentifier);
|
|
166
|
+
logger.debug(`[resolveAgentProfileId]: by name: {JSON.stringify(ap)}`);
|
|
167
|
+
if (ap) {
|
|
168
|
+
return ap.uuid;
|
|
169
|
+
}
|
|
170
|
+
logger.debug("[resolveAgentProfileId]: agent profile not found");
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
// Export main classes for external use
|
|
174
|
+
var connectionManager_2 = require("./connectionManager");
|
|
175
|
+
Object.defineProperty(exports, "ConnectionManager", { enumerable: true, get: function () { return connectionManager_2.ConnectionManager; } });
|
|
176
|
+
var openSession_1 = require("./openSession");
|
|
177
|
+
Object.defineProperty(exports, "OpenSession", { enumerable: true, get: function () { return openSession_1.OpenSession; } });
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChatSessionFileManager = exports.MemoryFileManager = exports.SESSION_FILE_TYPES = void 0;
|
|
4
|
+
exports.listFilesForLLM = listFilesForLLM;
|
|
5
|
+
exports.fileManagerTool = fileManagerTool;
|
|
6
|
+
const uuid_1 = require("uuid");
|
|
7
|
+
const tools_1 = require("./tools");
|
|
8
|
+
exports.SESSION_FILE_TYPES = ["text", "image", "pdf"];
|
|
9
|
+
/**
|
|
10
|
+
* In-memory implementation of ISessionFileManager
|
|
11
|
+
*/
|
|
12
|
+
class MemoryFileManager {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.files = new Map();
|
|
15
|
+
this.eventHandler = undefined;
|
|
16
|
+
}
|
|
17
|
+
// ISessionFileManager.listFiles
|
|
18
|
+
listFiles() {
|
|
19
|
+
return Array.from(this.files.values());
|
|
20
|
+
}
|
|
21
|
+
// ISessionFileManager.getFileContent
|
|
22
|
+
getFileContent(name) {
|
|
23
|
+
return new Promise((r, e) => {
|
|
24
|
+
const entry = this.files.get(name);
|
|
25
|
+
if (entry) {
|
|
26
|
+
r(entry.content);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
e(new Error(`no such file ${name}`));
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// ISessionFileManager.addFile
|
|
34
|
+
putFileContent(name, file_type, summary, content) {
|
|
35
|
+
return new Promise((r, e) => {
|
|
36
|
+
if (!name) {
|
|
37
|
+
name = (0, uuid_1.v4)();
|
|
38
|
+
}
|
|
39
|
+
if (!summary) {
|
|
40
|
+
summary = "";
|
|
41
|
+
}
|
|
42
|
+
if (!isSingleLine(summary)) {
|
|
43
|
+
e(new Error("summary must no contain new-lines"));
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const entry = { name, file_type, summary, content };
|
|
47
|
+
this.eventHandler?.onFileChange(entry);
|
|
48
|
+
this.files.set(name, entry);
|
|
49
|
+
r(name);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// ISessionFileManager.setEventHandler
|
|
54
|
+
setEventHandler(eventHandler) {
|
|
55
|
+
this.eventHandler = eventHandler;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.MemoryFileManager = MemoryFileManager;
|
|
59
|
+
/**
|
|
60
|
+
* Implementation of ISessionFileManager which can store files in the DB.
|
|
61
|
+
*/
|
|
62
|
+
class ChatSessionFileManager extends MemoryFileManager {
|
|
63
|
+
// private readonly db: Database;
|
|
64
|
+
// private readonly sessionUUID: string;
|
|
65
|
+
constructor(_sessionUUID, _db) {
|
|
66
|
+
super();
|
|
67
|
+
// this.db = db;
|
|
68
|
+
// this.sessionUUID = sessionUUID;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.ChatSessionFileManager = ChatSessionFileManager;
|
|
72
|
+
/**
|
|
73
|
+
* Return the file list in a form easily parsable by the LLM.
|
|
74
|
+
*/
|
|
75
|
+
function listFilesForLLM(fm) {
|
|
76
|
+
const files = fm.listFiles();
|
|
77
|
+
if (files.length === 0) {
|
|
78
|
+
return "";
|
|
79
|
+
}
|
|
80
|
+
let summary = "Available files:\nname,type,summary\n";
|
|
81
|
+
for (const f of files) {
|
|
82
|
+
summary += `${f.name},${f.file_type},${f.summary || ""}\n`;
|
|
83
|
+
}
|
|
84
|
+
return summary;
|
|
85
|
+
}
|
|
86
|
+
const GET_FILE_CONTENT_TOOL = {
|
|
87
|
+
type: "function",
|
|
88
|
+
function: {
|
|
89
|
+
name: "get_file_content",
|
|
90
|
+
description: "Obtain the contents of a file listed in the system prompt",
|
|
91
|
+
parameters: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: {
|
|
94
|
+
name: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description: "File name",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
required: ["name"],
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
const PUT_FILE_CONTENT_TOOL = {
|
|
104
|
+
type: "function",
|
|
105
|
+
function: {
|
|
106
|
+
name: "put_file_content",
|
|
107
|
+
description: "Create or update file content",
|
|
108
|
+
parameters: {
|
|
109
|
+
type: "object",
|
|
110
|
+
properties: {
|
|
111
|
+
name: {
|
|
112
|
+
type: "string",
|
|
113
|
+
description: "File name",
|
|
114
|
+
},
|
|
115
|
+
file_type: {
|
|
116
|
+
type: "string",
|
|
117
|
+
enum: exports.SESSION_FILE_TYPES,
|
|
118
|
+
},
|
|
119
|
+
summary: {
|
|
120
|
+
type: "string",
|
|
121
|
+
description: "Content summary",
|
|
122
|
+
},
|
|
123
|
+
content: {
|
|
124
|
+
type: "string",
|
|
125
|
+
description: "Content (text/dataurl)",
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
required: ["name", "type", "summary", "content"],
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
function fileManagerTool(fileManager) {
|
|
133
|
+
// get_file_content
|
|
134
|
+
const getName = (0, tools_1.makeParseArgsFn)(["name"]);
|
|
135
|
+
const getFileContentFn = async (_agent, args) => {
|
|
136
|
+
const { name } = getName(args);
|
|
137
|
+
const response = await fileManager.getFileContent(name);
|
|
138
|
+
return { response };
|
|
139
|
+
};
|
|
140
|
+
// set_file_content
|
|
141
|
+
const putArgs = ["name", "file_type", "summary", "content"];
|
|
142
|
+
const getNameSummaryContent = (0, tools_1.makeParseArgsFn)(putArgs);
|
|
143
|
+
const putFileContentFn = async (_, args) => {
|
|
144
|
+
const { name, file_type, summary, content } = getNameSummaryContent(args);
|
|
145
|
+
const response = await fileManager.putFileContent(name, file_type, summary, content);
|
|
146
|
+
return { response };
|
|
147
|
+
};
|
|
148
|
+
const provider = {
|
|
149
|
+
setup: (agent) => {
|
|
150
|
+
agent.addAgentTool(GET_FILE_CONTENT_TOOL, getFileContentFn);
|
|
151
|
+
agent.addAgentTool(PUT_FILE_CONTENT_TOOL, putFileContentFn);
|
|
152
|
+
return new Promise((r) => {
|
|
153
|
+
r();
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
return provider;
|
|
158
|
+
}
|
|
159
|
+
function isSingleLine(str) {
|
|
160
|
+
return !/[\r\n]/.test(str);
|
|
161
|
+
}
|