goblin-agents 3.2.0 → 3.3.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/contextCache.js +4 -0
- package/lib/contextCache.js +69 -0
- package/lib/llm/aiAgent.js +25 -18
- package/lib/llm/utils.js +3 -0
- package/package.json +1 -1
package/contextCache.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const {Elf} = require('xcraft-core-goblin');
|
|
3
|
+
const {record, string} = require('xcraft-core-stones');
|
|
4
|
+
|
|
5
|
+
class ContextCacheShape {
|
|
6
|
+
id = string;
|
|
7
|
+
contexts = record(string, string);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
class ContextCacheState extends Elf.Sculpt(ContextCacheShape) {}
|
|
11
|
+
|
|
12
|
+
class ContextCacheLogic extends Elf.Spirit {
|
|
13
|
+
state = new ContextCacheState({
|
|
14
|
+
id: 'contextCache',
|
|
15
|
+
contexts: {},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
append(contextId, markdown) {
|
|
19
|
+
const current = this.state.contexts[contextId] || '';
|
|
20
|
+
this.state.contexts[contextId] = current + markdown;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
clear(contextId) {
|
|
24
|
+
delete this.state.contexts[contextId];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class ContextCache extends Elf.Alone {
|
|
29
|
+
logic = Elf.getLogic(ContextCacheLogic);
|
|
30
|
+
state = new ContextCacheState();
|
|
31
|
+
|
|
32
|
+
async init() {
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async append(contextId, markdown) {
|
|
37
|
+
if (typeof contextId !== 'string') {
|
|
38
|
+
throw new TypeError('contextId must be a string');
|
|
39
|
+
}
|
|
40
|
+
if (typeof markdown !== 'string') {
|
|
41
|
+
throw new TypeError('markdown must be a string');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.logic.append(contextId, markdown);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async read(contextId) {
|
|
48
|
+
if (typeof contextId !== 'string') {
|
|
49
|
+
throw new TypeError('contextId must be a string');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return this.state.contexts[contextId] || '';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async clear(contextId) {
|
|
56
|
+
if (typeof contextId !== 'string') {
|
|
57
|
+
throw new TypeError('contextId must be a string');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.logic.clear(contextId);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = {
|
|
65
|
+
ContextCache,
|
|
66
|
+
ContextCacheLogic,
|
|
67
|
+
ContextCacheShape,
|
|
68
|
+
ContextCacheState,
|
|
69
|
+
};
|
package/lib/llm/aiAgent.js
CHANGED
|
@@ -497,8 +497,8 @@ class AiAgent extends Elf {
|
|
|
497
497
|
return cleanText(res);
|
|
498
498
|
}
|
|
499
499
|
|
|
500
|
-
async reset(contextId, save = false) {
|
|
501
|
-
if (
|
|
500
|
+
async reset(contextId = null, save = false) {
|
|
501
|
+
if (contextId === null) {
|
|
502
502
|
for (const contextId of Object.keys(this.state.messages)) {
|
|
503
503
|
await this.reset(contextId);
|
|
504
504
|
}
|
|
@@ -770,7 +770,7 @@ ${context}
|
|
|
770
770
|
|
|
771
771
|
async callTools(contextId, message, userDesktopId) {
|
|
772
772
|
const {tool_calls} = message;
|
|
773
|
-
if (!tool_calls || !userDesktopId) {
|
|
773
|
+
if (!tool_calls?.length || !userDesktopId) {
|
|
774
774
|
return false;
|
|
775
775
|
}
|
|
776
776
|
this.logic.callTools(contextId, tool_calls);
|
|
@@ -780,20 +780,19 @@ ${context}
|
|
|
780
780
|
function: {name},
|
|
781
781
|
} = tool;
|
|
782
782
|
|
|
783
|
-
let result = '';
|
|
784
|
-
let toolArguments = {};
|
|
785
|
-
if (
|
|
786
|
-
tool.function.arguments &&
|
|
787
|
-
typeof tool.function.arguments === 'string'
|
|
788
|
-
) {
|
|
789
|
-
toolArguments = JSON.parse(tool.function.arguments);
|
|
790
|
-
} else if (
|
|
791
|
-
tool.function.arguments &&
|
|
792
|
-
typeof tool.function.arguments === 'object'
|
|
793
|
-
) {
|
|
794
|
-
toolArguments = tool.function.arguments;
|
|
795
|
-
}
|
|
796
783
|
try {
|
|
784
|
+
let toolArguments = {};
|
|
785
|
+
if (
|
|
786
|
+
tool.function.arguments &&
|
|
787
|
+
typeof tool.function.arguments === 'string'
|
|
788
|
+
) {
|
|
789
|
+
toolArguments = JSON.parse(tool.function.arguments);
|
|
790
|
+
} else if (
|
|
791
|
+
tool.function.arguments &&
|
|
792
|
+
typeof tool.function.arguments === 'object'
|
|
793
|
+
) {
|
|
794
|
+
toolArguments = tool.function.arguments;
|
|
795
|
+
}
|
|
797
796
|
const payload = {
|
|
798
797
|
id: this.state.toolServiceId,
|
|
799
798
|
desktopId: userDesktopId,
|
|
@@ -803,10 +802,18 @@ ${context}
|
|
|
803
802
|
const toolNamespace = this.state.toolServiceId?.split('@', 1)[0];
|
|
804
803
|
const toolCmd = `${toolNamespace}.${name}`;
|
|
805
804
|
this.log.dbg(`🔧 Tool call: ${toolCmd}(${JSON.stringify(payload)})`);
|
|
806
|
-
result = await this.quest.cmd(toolCmd, payload);
|
|
807
|
-
|
|
805
|
+
const result = await this.quest.cmd(toolCmd, payload);
|
|
806
|
+
const content =
|
|
807
|
+
typeof result === 'string' ? result : JSON.stringify(result ?? null);
|
|
808
|
+
await this.addToolMessage(contextId, id, name, content);
|
|
808
809
|
} catch (err) {
|
|
809
810
|
this.log.dbg(`🔧 Tool error : ${err.message}`);
|
|
811
|
+
await this.addToolMessage(
|
|
812
|
+
contextId,
|
|
813
|
+
id,
|
|
814
|
+
name,
|
|
815
|
+
JSON.stringify({status: 'error', message: err.message})
|
|
816
|
+
);
|
|
810
817
|
}
|
|
811
818
|
}
|
|
812
819
|
return true;
|
package/lib/llm/utils.js
CHANGED
|
@@ -49,6 +49,9 @@ const getPDFImages = async (pdfPath, pagesToProcess) => {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
const cleanHtmlContent = (html) => {
|
|
52
|
+
if (typeof html !== 'string') {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
52
55
|
const decodedHtml = HtmlEntities.decode(html);
|
|
53
56
|
const textOnly = decodedHtml.replace(/<[^>]+>/g, '');
|
|
54
57
|
const cleanedText = textOnly.replace(/\s+/g, ' ').trim();
|