@bowenqt/qiniu-ai-sdk 0.10.0 → 0.14.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 +225 -0
- package/dist/ai/agent-graph.d.ts +101 -0
- package/dist/ai/agent-graph.d.ts.map +1 -0
- package/dist/ai/agent-graph.js +322 -0
- package/dist/ai/agent-graph.js.map +1 -0
- package/dist/ai/agent-graph.mjs +318 -0
- package/dist/ai/generate-text.d.ts +58 -0
- package/dist/ai/generate-text.d.ts.map +1 -1
- package/dist/ai/generate-text.js +157 -0
- package/dist/ai/generate-text.js.map +1 -1
- package/dist/ai/generate-text.mjs +156 -0
- package/dist/ai/graph/checkpointer.d.ts +112 -0
- package/dist/ai/graph/checkpointer.d.ts.map +1 -0
- package/dist/ai/graph/checkpointer.js +131 -0
- package/dist/ai/graph/checkpointer.js.map +1 -0
- package/dist/ai/graph/checkpointer.mjs +126 -0
- package/dist/ai/graph/index.d.ts +13 -0
- package/dist/ai/graph/index.d.ts.map +1 -0
- package/dist/ai/graph/index.js +22 -0
- package/dist/ai/graph/index.js.map +1 -0
- package/dist/ai/graph/index.mjs +12 -0
- package/dist/ai/graph/postgres-checkpointer.d.ts +54 -0
- package/dist/ai/graph/postgres-checkpointer.d.ts.map +1 -0
- package/dist/ai/graph/postgres-checkpointer.js +134 -0
- package/dist/ai/graph/postgres-checkpointer.js.map +1 -0
- package/dist/ai/graph/postgres-checkpointer.mjs +130 -0
- package/dist/ai/graph/redis-checkpointer.d.ts +51 -0
- package/dist/ai/graph/redis-checkpointer.d.ts.map +1 -0
- package/dist/ai/graph/redis-checkpointer.js +124 -0
- package/dist/ai/graph/redis-checkpointer.js.map +1 -0
- package/dist/ai/graph/redis-checkpointer.mjs +120 -0
- package/dist/ai/graph/state-graph.d.ts +41 -0
- package/dist/ai/graph/state-graph.d.ts.map +1 -0
- package/dist/ai/graph/state-graph.js +149 -0
- package/dist/ai/graph/state-graph.js.map +1 -0
- package/dist/ai/graph/state-graph.mjs +144 -0
- package/dist/ai/graph/types.d.ts +41 -0
- package/dist/ai/graph/types.d.ts.map +1 -0
- package/dist/ai/graph/types.js +10 -0
- package/dist/ai/graph/types.js.map +1 -0
- package/dist/ai/graph/types.mjs +7 -0
- package/dist/ai/internal-types.d.ts +109 -0
- package/dist/ai/internal-types.d.ts.map +1 -0
- package/dist/ai/internal-types.js +28 -0
- package/dist/ai/internal-types.js.map +1 -0
- package/dist/ai/internal-types.mjs +23 -0
- package/dist/ai/nodes/execute-node.d.ts +27 -0
- package/dist/ai/nodes/execute-node.d.ts.map +1 -0
- package/dist/ai/nodes/execute-node.js +118 -0
- package/dist/ai/nodes/execute-node.js.map +1 -0
- package/dist/ai/nodes/execute-node.mjs +114 -0
- package/dist/ai/nodes/index.d.ts +8 -0
- package/dist/ai/nodes/index.d.ts.map +1 -0
- package/dist/ai/nodes/index.js +16 -0
- package/dist/ai/nodes/index.js.map +1 -0
- package/dist/ai/nodes/index.mjs +7 -0
- package/dist/ai/nodes/memory-node.d.ts +34 -0
- package/dist/ai/nodes/memory-node.d.ts.map +1 -0
- package/dist/ai/nodes/memory-node.js +164 -0
- package/dist/ai/nodes/memory-node.js.map +1 -0
- package/dist/ai/nodes/memory-node.mjs +158 -0
- package/dist/ai/nodes/predict-node.d.ts +42 -0
- package/dist/ai/nodes/predict-node.d.ts.map +1 -0
- package/dist/ai/nodes/predict-node.js +89 -0
- package/dist/ai/nodes/predict-node.js.map +1 -0
- package/dist/ai/nodes/predict-node.mjs +86 -0
- package/dist/ai/nodes/types.d.ts +44 -0
- package/dist/ai/nodes/types.d.ts.map +1 -0
- package/dist/ai/nodes/types.js +6 -0
- package/dist/ai/nodes/types.js.map +1 -0
- package/dist/ai/nodes/types.mjs +5 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +80 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +34 -0
- package/dist/lib/otel-tracer.d.ts +47 -0
- package/dist/lib/otel-tracer.d.ts.map +1 -0
- package/dist/lib/otel-tracer.js +79 -0
- package/dist/lib/otel-tracer.js.map +1 -0
- package/dist/lib/otel-tracer.mjs +75 -0
- package/dist/lib/token-estimator.d.ts +62 -0
- package/dist/lib/token-estimator.d.ts.map +1 -0
- package/dist/lib/token-estimator.js +106 -0
- package/dist/lib/token-estimator.js.map +1 -0
- package/dist/lib/token-estimator.mjs +100 -0
- package/dist/lib/tool-registry.d.ts +103 -0
- package/dist/lib/tool-registry.d.ts.map +1 -0
- package/dist/lib/tool-registry.js +159 -0
- package/dist/lib/tool-registry.js.map +1 -0
- package/dist/lib/tool-registry.mjs +154 -0
- package/dist/lib/tracer.d.ts +85 -0
- package/dist/lib/tracer.d.ts.map +1 -0
- package/dist/lib/tracer.js +170 -0
- package/dist/lib/tracer.js.map +1 -0
- package/dist/lib/tracer.mjs +161 -0
- package/dist/lib/types.d.ts +11 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/modules/mcp/adapter.d.ts +23 -0
- package/dist/modules/mcp/adapter.d.ts.map +1 -0
- package/dist/modules/mcp/adapter.js +63 -0
- package/dist/modules/mcp/adapter.js.map +1 -0
- package/dist/modules/mcp/adapter.mjs +58 -0
- package/dist/modules/mcp/client.d.ts +75 -0
- package/dist/modules/mcp/client.d.ts.map +1 -0
- package/dist/modules/mcp/client.js +300 -0
- package/dist/modules/mcp/client.js.map +1 -0
- package/dist/modules/mcp/client.mjs +295 -0
- package/dist/modules/mcp/http-transport.d.ts +51 -0
- package/dist/modules/mcp/http-transport.d.ts.map +1 -0
- package/dist/modules/mcp/http-transport.js +146 -0
- package/dist/modules/mcp/http-transport.js.map +1 -0
- package/dist/modules/mcp/http-transport.mjs +141 -0
- package/dist/modules/mcp/index.d.ts +11 -0
- package/dist/modules/mcp/index.d.ts.map +1 -0
- package/dist/modules/mcp/index.js +34 -0
- package/dist/modules/mcp/index.js.map +1 -0
- package/dist/modules/mcp/index.mjs +14 -0
- package/dist/modules/mcp/oauth.d.ts +101 -0
- package/dist/modules/mcp/oauth.d.ts.map +1 -0
- package/dist/modules/mcp/oauth.js +347 -0
- package/dist/modules/mcp/oauth.js.map +1 -0
- package/dist/modules/mcp/oauth.mjs +304 -0
- package/dist/modules/mcp/token-store.d.ts +69 -0
- package/dist/modules/mcp/token-store.d.ts.map +1 -0
- package/dist/modules/mcp/token-store.js +174 -0
- package/dist/modules/mcp/token-store.js.map +1 -0
- package/dist/modules/mcp/token-store.mjs +135 -0
- package/dist/modules/mcp/types.d.ts +91 -0
- package/dist/modules/mcp/types.d.ts.map +1 -0
- package/dist/modules/mcp/types.js +14 -0
- package/dist/modules/mcp/types.js.map +1 -0
- package/dist/modules/mcp/types.mjs +11 -0
- package/dist/modules/skills/index.d.ts +7 -0
- package/dist/modules/skills/index.d.ts.map +1 -0
- package/dist/modules/skills/index.js +14 -0
- package/dist/modules/skills/index.js.map +1 -0
- package/dist/modules/skills/index.mjs +6 -0
- package/dist/modules/skills/loader.d.ts +51 -0
- package/dist/modules/skills/loader.d.ts.map +1 -0
- package/dist/modules/skills/loader.js +237 -0
- package/dist/modules/skills/loader.js.map +1 -0
- package/dist/modules/skills/loader.mjs +198 -0
- package/dist/modules/skills/types.d.ts +60 -0
- package/dist/modules/skills/types.d.ts.map +1 -0
- package/dist/modules/skills/types.js +20 -0
- package/dist/modules/skills/types.js.map +1 -0
- package/dist/modules/skills/types.mjs +17 -0
- package/package.json +4 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ExecuteNode - Tool execution abstraction.
|
|
4
|
+
* Extracted from generateText for modular use in Graph Runtime.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.executeTools = executeTools;
|
|
8
|
+
exports.toolResultsToMessages = toolResultsToMessages;
|
|
9
|
+
/**
|
|
10
|
+
* Execute tools based on tool calls from LLM.
|
|
11
|
+
*/
|
|
12
|
+
async function executeTools(toolCalls, tools, context) {
|
|
13
|
+
const results = [];
|
|
14
|
+
for (const call of toolCalls) {
|
|
15
|
+
// Check abort signal
|
|
16
|
+
if (context.abortSignal?.aborted) {
|
|
17
|
+
results.push({
|
|
18
|
+
toolCallId: call.id,
|
|
19
|
+
result: 'Execution cancelled',
|
|
20
|
+
isError: true,
|
|
21
|
+
});
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const tool = tools.get(call.function.name);
|
|
25
|
+
if (!tool) {
|
|
26
|
+
results.push({
|
|
27
|
+
toolCallId: call.id,
|
|
28
|
+
result: `Tool not found: ${call.function.name}`,
|
|
29
|
+
isError: true,
|
|
30
|
+
});
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (!tool.execute) {
|
|
34
|
+
results.push({
|
|
35
|
+
toolCallId: call.id,
|
|
36
|
+
result: `Tool ${call.function.name} has no execute function`,
|
|
37
|
+
isError: true,
|
|
38
|
+
});
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
// Parse arguments
|
|
43
|
+
const args = parseToolArguments(call.function.arguments);
|
|
44
|
+
// Execute tool
|
|
45
|
+
const execContext = {
|
|
46
|
+
toolCallId: call.id,
|
|
47
|
+
messages: context.messages,
|
|
48
|
+
abortSignal: context.abortSignal,
|
|
49
|
+
};
|
|
50
|
+
const result = await tool.execute(args, execContext);
|
|
51
|
+
results.push({
|
|
52
|
+
toolCallId: call.id,
|
|
53
|
+
result: serializeResult(result),
|
|
54
|
+
isError: false,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
59
|
+
results.push({
|
|
60
|
+
toolCallId: call.id,
|
|
61
|
+
result: `Error: ${errorMessage}`,
|
|
62
|
+
isError: true,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return results;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Convert tool execution results to chat messages.
|
|
70
|
+
*/
|
|
71
|
+
function toolResultsToMessages(results) {
|
|
72
|
+
return results.map(r => ({
|
|
73
|
+
role: 'tool',
|
|
74
|
+
content: r.result,
|
|
75
|
+
tool_call_id: r.toolCallId,
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Parse tool arguments from JSON string.
|
|
80
|
+
*/
|
|
81
|
+
function parseToolArguments(payload) {
|
|
82
|
+
if (!payload || payload.trim() === '') {
|
|
83
|
+
return {};
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
return JSON.parse(payload);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Try to fix common JSON issues
|
|
90
|
+
try {
|
|
91
|
+
const fixed = payload
|
|
92
|
+
.replace(/'/g, '"')
|
|
93
|
+
.replace(/(\w+):/g, '"$1":');
|
|
94
|
+
return JSON.parse(fixed);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return { _raw: payload };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Serialize tool result to string.
|
|
103
|
+
*/
|
|
104
|
+
function serializeResult(result) {
|
|
105
|
+
if (result === undefined || result === null) {
|
|
106
|
+
return '';
|
|
107
|
+
}
|
|
108
|
+
if (typeof result === 'string') {
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
return JSON.stringify(result, null, 2);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return String(result);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=execute-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute-node.js","sourceRoot":"","sources":["../../../src/ai/nodes/execute-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExecuteNode - Tool execution abstraction.
|
|
3
|
+
* Extracted from generateText for modular use in Graph Runtime.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Execute tools based on tool calls from LLM.
|
|
7
|
+
*/
|
|
8
|
+
export async function executeTools(toolCalls, tools, context) {
|
|
9
|
+
const results = [];
|
|
10
|
+
for (const call of toolCalls) {
|
|
11
|
+
// Check abort signal
|
|
12
|
+
if (context.abortSignal?.aborted) {
|
|
13
|
+
results.push({
|
|
14
|
+
toolCallId: call.id,
|
|
15
|
+
result: 'Execution cancelled',
|
|
16
|
+
isError: true,
|
|
17
|
+
});
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const tool = tools.get(call.function.name);
|
|
21
|
+
if (!tool) {
|
|
22
|
+
results.push({
|
|
23
|
+
toolCallId: call.id,
|
|
24
|
+
result: `Tool not found: ${call.function.name}`,
|
|
25
|
+
isError: true,
|
|
26
|
+
});
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (!tool.execute) {
|
|
30
|
+
results.push({
|
|
31
|
+
toolCallId: call.id,
|
|
32
|
+
result: `Tool ${call.function.name} has no execute function`,
|
|
33
|
+
isError: true,
|
|
34
|
+
});
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
// Parse arguments
|
|
39
|
+
const args = parseToolArguments(call.function.arguments);
|
|
40
|
+
// Execute tool
|
|
41
|
+
const execContext = {
|
|
42
|
+
toolCallId: call.id,
|
|
43
|
+
messages: context.messages,
|
|
44
|
+
abortSignal: context.abortSignal,
|
|
45
|
+
};
|
|
46
|
+
const result = await tool.execute(args, execContext);
|
|
47
|
+
results.push({
|
|
48
|
+
toolCallId: call.id,
|
|
49
|
+
result: serializeResult(result),
|
|
50
|
+
isError: false,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
55
|
+
results.push({
|
|
56
|
+
toolCallId: call.id,
|
|
57
|
+
result: `Error: ${errorMessage}`,
|
|
58
|
+
isError: true,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return results;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Convert tool execution results to chat messages.
|
|
66
|
+
*/
|
|
67
|
+
export function toolResultsToMessages(results) {
|
|
68
|
+
return results.map(r => ({
|
|
69
|
+
role: 'tool',
|
|
70
|
+
content: r.result,
|
|
71
|
+
tool_call_id: r.toolCallId,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parse tool arguments from JSON string.
|
|
76
|
+
*/
|
|
77
|
+
function parseToolArguments(payload) {
|
|
78
|
+
if (!payload || payload.trim() === '') {
|
|
79
|
+
return {};
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
return JSON.parse(payload);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Try to fix common JSON issues
|
|
86
|
+
try {
|
|
87
|
+
const fixed = payload
|
|
88
|
+
.replace(/'/g, '"')
|
|
89
|
+
.replace(/(\w+):/g, '"$1":');
|
|
90
|
+
return JSON.parse(fixed);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return { _raw: payload };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Serialize tool result to string.
|
|
99
|
+
*/
|
|
100
|
+
function serializeResult(result) {
|
|
101
|
+
if (result === undefined || result === null) {
|
|
102
|
+
return '';
|
|
103
|
+
}
|
|
104
|
+
if (typeof result === 'string') {
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
return JSON.stringify(result, null, 2);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return String(result);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=execute-node.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Nodes - Modular components for agent execution.
|
|
3
|
+
*/
|
|
4
|
+
export { predict, type PredictOptions, type PredictResult } from './predict-node';
|
|
5
|
+
export { executeTools, toolResultsToMessages, type ExecutionContext, type ToolExecutionResult } from './execute-node';
|
|
6
|
+
export { compactMessages, buildToolPairs, ContextOverflowError } from './memory-node';
|
|
7
|
+
export type { CompactionResult, CompactionConfig, ToolPair, InjectedSkill } from './types';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ai/nodes/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,KAAK,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACtH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACtF,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AI Nodes - Modular components for agent execution.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ContextOverflowError = exports.buildToolPairs = exports.compactMessages = exports.toolResultsToMessages = exports.executeTools = exports.predict = void 0;
|
|
7
|
+
var predict_node_1 = require("./predict-node");
|
|
8
|
+
Object.defineProperty(exports, "predict", { enumerable: true, get: function () { return predict_node_1.predict; } });
|
|
9
|
+
var execute_node_1 = require("./execute-node");
|
|
10
|
+
Object.defineProperty(exports, "executeTools", { enumerable: true, get: function () { return execute_node_1.executeTools; } });
|
|
11
|
+
Object.defineProperty(exports, "toolResultsToMessages", { enumerable: true, get: function () { return execute_node_1.toolResultsToMessages; } });
|
|
12
|
+
var memory_node_1 = require("./memory-node");
|
|
13
|
+
Object.defineProperty(exports, "compactMessages", { enumerable: true, get: function () { return memory_node_1.compactMessages; } });
|
|
14
|
+
Object.defineProperty(exports, "buildToolPairs", { enumerable: true, get: function () { return memory_node_1.buildToolPairs; } });
|
|
15
|
+
Object.defineProperty(exports, "ContextOverflowError", { enumerable: true, get: function () { return memory_node_1.ContextOverflowError; } });
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ai/nodes/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,+CAAkF;AAAzE,uGAAA,OAAO,OAAA;AAChB,+CAAsH;AAA7G,4GAAA,YAAY,OAAA;AAAE,qHAAA,qBAAqB,OAAA;AAC5C,6CAAsF;AAA7E,8GAAA,eAAe,OAAA;AAAE,6GAAA,cAAc,OAAA;AAAE,mHAAA,oBAAoB,OAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Nodes - Modular components for agent execution.
|
|
3
|
+
*/
|
|
4
|
+
export { predict } from './predict-node.mjs';
|
|
5
|
+
export { executeTools, toolResultsToMessages } from './execute-node.mjs';
|
|
6
|
+
export { compactMessages, buildToolPairs, ContextOverflowError } from './memory-node.mjs';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Node - Context Compaction with deterministic fallback.
|
|
3
|
+
*
|
|
4
|
+
* Fallback order:
|
|
5
|
+
* 1. Drop low-priority skill messages (_meta.droppable)
|
|
6
|
+
* 2. Drop oldest unprotected messages
|
|
7
|
+
* 3. Throw ContextOverflowError
|
|
8
|
+
*/
|
|
9
|
+
import type { ChatMessage } from '../../lib/types';
|
|
10
|
+
import type { CompactionResult, CompactionConfig, ToolPair, InjectedSkill } from './types';
|
|
11
|
+
import type { InternalMessage } from '../internal-types';
|
|
12
|
+
/** Context overflow error */
|
|
13
|
+
export declare class ContextOverflowError extends Error {
|
|
14
|
+
readonly currentTokens: number;
|
|
15
|
+
readonly maxTokens: number;
|
|
16
|
+
readonly recommendation: string;
|
|
17
|
+
constructor(currentTokens: number, maxTokens: number, recommendation: string);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Compact messages to fit within token budget.
|
|
21
|
+
* Implements deterministic fallback: droppable skills → old messages → error
|
|
22
|
+
*
|
|
23
|
+
* Key feature: recognizes _meta.droppable messages (skill-injected) for selective removal.
|
|
24
|
+
*/
|
|
25
|
+
export declare function compactMessages(messages: InternalMessage[], config: CompactionConfig, injectedSkills?: InjectedSkill[]): CompactionResult;
|
|
26
|
+
/**
|
|
27
|
+
* Build tool call/result pairs.
|
|
28
|
+
* Returns pairs and orphan call IDs.
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildToolPairs(messages: ChatMessage[]): {
|
|
31
|
+
toolPairs: ToolPair[];
|
|
32
|
+
orphanCalls: string[];
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=memory-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-node.d.ts","sourceRoot":"","sources":["../../../src/ai/nodes/memory-node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD,6BAA6B;AAC7B,qBAAa,oBAAqB,SAAQ,KAAK;aAEvB,aAAa,EAAE,MAAM;aACrB,SAAS,EAAE,MAAM;aACjB,cAAc,EAAE,MAAM;gBAFtB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM;CAK7C;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC3B,QAAQ,EAAE,eAAe,EAAE,EAC3B,MAAM,EAAE,gBAAgB,EACxB,cAAc,GAAE,aAAa,EAAO,GACrC,gBAAgB,CA0HlB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG;IACrD,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB,CAgCA"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Memory Node - Context Compaction with deterministic fallback.
|
|
4
|
+
*
|
|
5
|
+
* Fallback order:
|
|
6
|
+
* 1. Drop low-priority skill messages (_meta.droppable)
|
|
7
|
+
* 2. Drop oldest unprotected messages
|
|
8
|
+
* 3. Throw ContextOverflowError
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ContextOverflowError = void 0;
|
|
12
|
+
exports.compactMessages = compactMessages;
|
|
13
|
+
exports.buildToolPairs = buildToolPairs;
|
|
14
|
+
const internal_types_1 = require("../internal-types");
|
|
15
|
+
/** Context overflow error */
|
|
16
|
+
class ContextOverflowError extends Error {
|
|
17
|
+
constructor(currentTokens, maxTokens, recommendation) {
|
|
18
|
+
super(`Context overflow: ${currentTokens} tokens exceeds max ${maxTokens}. ${recommendation}`);
|
|
19
|
+
this.currentTokens = currentTokens;
|
|
20
|
+
this.maxTokens = maxTokens;
|
|
21
|
+
this.recommendation = recommendation;
|
|
22
|
+
this.name = 'ContextOverflowError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.ContextOverflowError = ContextOverflowError;
|
|
26
|
+
/**
|
|
27
|
+
* Compact messages to fit within token budget.
|
|
28
|
+
* Implements deterministic fallback: droppable skills → old messages → error
|
|
29
|
+
*
|
|
30
|
+
* Key feature: recognizes _meta.droppable messages (skill-injected) for selective removal.
|
|
31
|
+
*/
|
|
32
|
+
function compactMessages(messages, config, injectedSkills = []) {
|
|
33
|
+
const result = {
|
|
34
|
+
messages: [...messages],
|
|
35
|
+
occurred: false,
|
|
36
|
+
droppedSkills: [],
|
|
37
|
+
droppedMessages: 0,
|
|
38
|
+
orphanToolCalls: [],
|
|
39
|
+
recommendation: undefined,
|
|
40
|
+
};
|
|
41
|
+
// Check if compaction needed
|
|
42
|
+
let currentTokens = config.estimateTokens(result.messages);
|
|
43
|
+
if (currentTokens <= config.maxTokens) {
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
result.occurred = true;
|
|
47
|
+
// Build tool pairs (must be kept together)
|
|
48
|
+
const { toolPairs, orphanCalls } = buildToolPairs(result.messages);
|
|
49
|
+
result.orphanToolCalls = orphanCalls;
|
|
50
|
+
// Identify protected indices
|
|
51
|
+
const protectedIndices = new Set();
|
|
52
|
+
// Non-droppable system messages are protected
|
|
53
|
+
result.messages.forEach((msg, idx) => {
|
|
54
|
+
if (msg.role === 'system' && !(0, internal_types_1.isDroppable)(msg)) {
|
|
55
|
+
protectedIndices.add(idx);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
// Tool pairs are protected
|
|
59
|
+
for (const pair of toolPairs) {
|
|
60
|
+
protectedIndices.add(pair.callMessageIndex);
|
|
61
|
+
if (pair.resultMessageIndex !== null) {
|
|
62
|
+
protectedIndices.add(pair.resultMessageIndex);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Last user message is protected
|
|
66
|
+
for (let i = result.messages.length - 1; i >= 0; i--) {
|
|
67
|
+
if (result.messages[i].role === 'user') {
|
|
68
|
+
protectedIndices.add(i);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Step 1: Drop droppable skill messages (lowest priority first)
|
|
73
|
+
// Collect all droppable messages with their skill IDs
|
|
74
|
+
const droppableIndices = [];
|
|
75
|
+
result.messages.forEach((msg, idx) => {
|
|
76
|
+
if ((0, internal_types_1.isDroppable)(msg)) {
|
|
77
|
+
const skillId = (0, internal_types_1.getSkillId)(msg);
|
|
78
|
+
if (skillId) {
|
|
79
|
+
droppableIndices.push({
|
|
80
|
+
idx,
|
|
81
|
+
skillId,
|
|
82
|
+
tokens: config.estimateTokens([msg]),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
// Sort by priority (using injectedSkills order) - lowest priority first
|
|
88
|
+
const skillPriorityMap = new Map();
|
|
89
|
+
injectedSkills.forEach((skill, i) => skillPriorityMap.set(skill.name, i));
|
|
90
|
+
droppableIndices.sort((a, b) => {
|
|
91
|
+
const priorityA = skillPriorityMap.get(a.skillId) ?? 0;
|
|
92
|
+
const priorityB = skillPriorityMap.get(b.skillId) ?? 0;
|
|
93
|
+
return priorityA - priorityB; // Lower priority (earlier in list) dropped first
|
|
94
|
+
});
|
|
95
|
+
// Drop droppable messages until under budget
|
|
96
|
+
const indicesToRemove = new Set();
|
|
97
|
+
for (const { idx, skillId, tokens } of droppableIndices) {
|
|
98
|
+
if (currentTokens <= config.maxTokens)
|
|
99
|
+
break;
|
|
100
|
+
indicesToRemove.add(idx);
|
|
101
|
+
currentTokens -= tokens;
|
|
102
|
+
if (!result.droppedSkills.includes(skillId)) {
|
|
103
|
+
result.droppedSkills.push(skillId);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Step 2: Drop oldest unprotected non-skill messages
|
|
107
|
+
for (let i = 0; i < result.messages.length && currentTokens > config.maxTokens; i++) {
|
|
108
|
+
if (!protectedIndices.has(i) && !indicesToRemove.has(i) && !(0, internal_types_1.isDroppable)(result.messages[i])) {
|
|
109
|
+
indicesToRemove.add(i);
|
|
110
|
+
currentTokens -= config.estimateTokens([result.messages[i]]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Apply removals
|
|
114
|
+
if (indicesToRemove.size > 0) {
|
|
115
|
+
const droppedSkillCount = droppableIndices.filter(d => indicesToRemove.has(d.idx)).length;
|
|
116
|
+
const droppedNonSkillCount = indicesToRemove.size - droppedSkillCount;
|
|
117
|
+
result.messages = result.messages.filter((_, idx) => !indicesToRemove.has(idx));
|
|
118
|
+
result.droppedMessages = droppedNonSkillCount;
|
|
119
|
+
}
|
|
120
|
+
// Step 3: Check if still over budget
|
|
121
|
+
currentTokens = config.estimateTokens(result.messages);
|
|
122
|
+
if (currentTokens > config.maxTokens) {
|
|
123
|
+
result.recommendation = `Reduce system prompt or decrease skill count. Current: ${currentTokens}, Max: ${config.maxTokens}`;
|
|
124
|
+
throw new ContextOverflowError(currentTokens, config.maxTokens, result.recommendation);
|
|
125
|
+
}
|
|
126
|
+
if (result.droppedSkills.length > 0 || result.droppedMessages > 0) {
|
|
127
|
+
result.recommendation = `Dropped ${result.droppedSkills.length} skills and ${result.droppedMessages} messages to fit context.`;
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Build tool call/result pairs.
|
|
133
|
+
* Returns pairs and orphan call IDs.
|
|
134
|
+
*/
|
|
135
|
+
function buildToolPairs(messages) {
|
|
136
|
+
const toolPairs = [];
|
|
137
|
+
const orphanCalls = [];
|
|
138
|
+
messages.forEach((msg, idx) => {
|
|
139
|
+
if (msg.role === 'assistant' && msg.tool_calls) {
|
|
140
|
+
for (const call of msg.tool_calls) {
|
|
141
|
+
// Find matching result
|
|
142
|
+
const resultIdx = messages.findIndex((m, i) => i > idx && m.role === 'tool' && m.tool_call_id === call.id);
|
|
143
|
+
if (resultIdx !== -1) {
|
|
144
|
+
toolPairs.push({
|
|
145
|
+
callMessageIndex: idx,
|
|
146
|
+
callId: call.id,
|
|
147
|
+
resultMessageIndex: resultIdx,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Orphan call - keep but warn
|
|
152
|
+
orphanCalls.push(call.id);
|
|
153
|
+
toolPairs.push({
|
|
154
|
+
callMessageIndex: idx,
|
|
155
|
+
callId: call.id,
|
|
156
|
+
resultMessageIndex: null,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
return { toolPairs, orphanCalls };
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=memory-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-node.js","sourceRoot":"","sources":["../../../src/ai/nodes/memory-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Node - Context Compaction with deterministic fallback.
|
|
3
|
+
*
|
|
4
|
+
* Fallback order:
|
|
5
|
+
* 1. Drop low-priority skill messages (_meta.droppable)
|
|
6
|
+
* 2. Drop oldest unprotected messages
|
|
7
|
+
* 3. Throw ContextOverflowError
|
|
8
|
+
*/
|
|
9
|
+
import { isDroppable, getSkillId } from '../internal-types.mjs';
|
|
10
|
+
/** Context overflow error */
|
|
11
|
+
export class ContextOverflowError extends Error {
|
|
12
|
+
constructor(currentTokens, maxTokens, recommendation) {
|
|
13
|
+
super(`Context overflow: ${currentTokens} tokens exceeds max ${maxTokens}. ${recommendation}`);
|
|
14
|
+
this.currentTokens = currentTokens;
|
|
15
|
+
this.maxTokens = maxTokens;
|
|
16
|
+
this.recommendation = recommendation;
|
|
17
|
+
this.name = 'ContextOverflowError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Compact messages to fit within token budget.
|
|
22
|
+
* Implements deterministic fallback: droppable skills → old messages → error
|
|
23
|
+
*
|
|
24
|
+
* Key feature: recognizes _meta.droppable messages (skill-injected) for selective removal.
|
|
25
|
+
*/
|
|
26
|
+
export function compactMessages(messages, config, injectedSkills = []) {
|
|
27
|
+
const result = {
|
|
28
|
+
messages: [...messages],
|
|
29
|
+
occurred: false,
|
|
30
|
+
droppedSkills: [],
|
|
31
|
+
droppedMessages: 0,
|
|
32
|
+
orphanToolCalls: [],
|
|
33
|
+
recommendation: undefined,
|
|
34
|
+
};
|
|
35
|
+
// Check if compaction needed
|
|
36
|
+
let currentTokens = config.estimateTokens(result.messages);
|
|
37
|
+
if (currentTokens <= config.maxTokens) {
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
result.occurred = true;
|
|
41
|
+
// Build tool pairs (must be kept together)
|
|
42
|
+
const { toolPairs, orphanCalls } = buildToolPairs(result.messages);
|
|
43
|
+
result.orphanToolCalls = orphanCalls;
|
|
44
|
+
// Identify protected indices
|
|
45
|
+
const protectedIndices = new Set();
|
|
46
|
+
// Non-droppable system messages are protected
|
|
47
|
+
result.messages.forEach((msg, idx) => {
|
|
48
|
+
if (msg.role === 'system' && !isDroppable(msg)) {
|
|
49
|
+
protectedIndices.add(idx);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
// Tool pairs are protected
|
|
53
|
+
for (const pair of toolPairs) {
|
|
54
|
+
protectedIndices.add(pair.callMessageIndex);
|
|
55
|
+
if (pair.resultMessageIndex !== null) {
|
|
56
|
+
protectedIndices.add(pair.resultMessageIndex);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Last user message is protected
|
|
60
|
+
for (let i = result.messages.length - 1; i >= 0; i--) {
|
|
61
|
+
if (result.messages[i].role === 'user') {
|
|
62
|
+
protectedIndices.add(i);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Step 1: Drop droppable skill messages (lowest priority first)
|
|
67
|
+
// Collect all droppable messages with their skill IDs
|
|
68
|
+
const droppableIndices = [];
|
|
69
|
+
result.messages.forEach((msg, idx) => {
|
|
70
|
+
if (isDroppable(msg)) {
|
|
71
|
+
const skillId = getSkillId(msg);
|
|
72
|
+
if (skillId) {
|
|
73
|
+
droppableIndices.push({
|
|
74
|
+
idx,
|
|
75
|
+
skillId,
|
|
76
|
+
tokens: config.estimateTokens([msg]),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
// Sort by priority (using injectedSkills order) - lowest priority first
|
|
82
|
+
const skillPriorityMap = new Map();
|
|
83
|
+
injectedSkills.forEach((skill, i) => skillPriorityMap.set(skill.name, i));
|
|
84
|
+
droppableIndices.sort((a, b) => {
|
|
85
|
+
const priorityA = skillPriorityMap.get(a.skillId) ?? 0;
|
|
86
|
+
const priorityB = skillPriorityMap.get(b.skillId) ?? 0;
|
|
87
|
+
return priorityA - priorityB; // Lower priority (earlier in list) dropped first
|
|
88
|
+
});
|
|
89
|
+
// Drop droppable messages until under budget
|
|
90
|
+
const indicesToRemove = new Set();
|
|
91
|
+
for (const { idx, skillId, tokens } of droppableIndices) {
|
|
92
|
+
if (currentTokens <= config.maxTokens)
|
|
93
|
+
break;
|
|
94
|
+
indicesToRemove.add(idx);
|
|
95
|
+
currentTokens -= tokens;
|
|
96
|
+
if (!result.droppedSkills.includes(skillId)) {
|
|
97
|
+
result.droppedSkills.push(skillId);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Step 2: Drop oldest unprotected non-skill messages
|
|
101
|
+
for (let i = 0; i < result.messages.length && currentTokens > config.maxTokens; i++) {
|
|
102
|
+
if (!protectedIndices.has(i) && !indicesToRemove.has(i) && !isDroppable(result.messages[i])) {
|
|
103
|
+
indicesToRemove.add(i);
|
|
104
|
+
currentTokens -= config.estimateTokens([result.messages[i]]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Apply removals
|
|
108
|
+
if (indicesToRemove.size > 0) {
|
|
109
|
+
const droppedSkillCount = droppableIndices.filter(d => indicesToRemove.has(d.idx)).length;
|
|
110
|
+
const droppedNonSkillCount = indicesToRemove.size - droppedSkillCount;
|
|
111
|
+
result.messages = result.messages.filter((_, idx) => !indicesToRemove.has(idx));
|
|
112
|
+
result.droppedMessages = droppedNonSkillCount;
|
|
113
|
+
}
|
|
114
|
+
// Step 3: Check if still over budget
|
|
115
|
+
currentTokens = config.estimateTokens(result.messages);
|
|
116
|
+
if (currentTokens > config.maxTokens) {
|
|
117
|
+
result.recommendation = `Reduce system prompt or decrease skill count. Current: ${currentTokens}, Max: ${config.maxTokens}`;
|
|
118
|
+
throw new ContextOverflowError(currentTokens, config.maxTokens, result.recommendation);
|
|
119
|
+
}
|
|
120
|
+
if (result.droppedSkills.length > 0 || result.droppedMessages > 0) {
|
|
121
|
+
result.recommendation = `Dropped ${result.droppedSkills.length} skills and ${result.droppedMessages} messages to fit context.`;
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Build tool call/result pairs.
|
|
127
|
+
* Returns pairs and orphan call IDs.
|
|
128
|
+
*/
|
|
129
|
+
export function buildToolPairs(messages) {
|
|
130
|
+
const toolPairs = [];
|
|
131
|
+
const orphanCalls = [];
|
|
132
|
+
messages.forEach((msg, idx) => {
|
|
133
|
+
if (msg.role === 'assistant' && msg.tool_calls) {
|
|
134
|
+
for (const call of msg.tool_calls) {
|
|
135
|
+
// Find matching result
|
|
136
|
+
const resultIdx = messages.findIndex((m, i) => i > idx && m.role === 'tool' && m.tool_call_id === call.id);
|
|
137
|
+
if (resultIdx !== -1) {
|
|
138
|
+
toolPairs.push({
|
|
139
|
+
callMessageIndex: idx,
|
|
140
|
+
callId: call.id,
|
|
141
|
+
resultMessageIndex: resultIdx,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Orphan call - keep but warn
|
|
146
|
+
orphanCalls.push(call.id);
|
|
147
|
+
toolPairs.push({
|
|
148
|
+
callMessageIndex: idx,
|
|
149
|
+
callId: call.id,
|
|
150
|
+
resultMessageIndex: null,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
return { toolPairs, orphanCalls };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=memory-node.js.map
|