@bowenqt/qiniu-ai-sdk 0.14.0 → 0.16.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/dist/ai/agent-graph.d.ts +8 -0
- package/dist/ai/agent-graph.d.ts.map +1 -1
- package/dist/ai/agent-graph.js +23 -3
- package/dist/ai/agent-graph.js.map +1 -1
- package/dist/ai/agent-graph.mjs +23 -3
- package/dist/ai/create-agent.d.ts +101 -0
- package/dist/ai/create-agent.d.ts.map +1 -0
- package/dist/ai/create-agent.js +88 -0
- package/dist/ai/create-agent.js.map +1 -0
- package/dist/ai/create-agent.mjs +85 -0
- package/dist/ai/generate-object.d.ts +99 -0
- package/dist/ai/generate-object.d.ts.map +1 -0
- package/dist/ai/generate-object.js +237 -0
- package/dist/ai/generate-object.js.map +1 -0
- package/dist/ai/generate-object.mjs +201 -0
- package/dist/ai/generate-text.d.ts +13 -1
- package/dist/ai/generate-text.d.ts.map +1 -1
- package/dist/ai/generate-text.js +35 -5
- package/dist/ai/generate-text.js.map +1 -1
- package/dist/ai/generate-text.mjs +35 -5
- package/dist/ai/graph/checkpointer.d.ts +72 -2
- package/dist/ai/graph/checkpointer.d.ts.map +1 -1
- package/dist/ai/graph/checkpointer.js +99 -1
- package/dist/ai/graph/checkpointer.js.map +1 -1
- package/dist/ai/graph/checkpointer.mjs +96 -1
- package/dist/ai/graph/index.d.ts +2 -2
- package/dist/ai/graph/index.d.ts.map +1 -1
- package/dist/ai/graph/index.js +5 -1
- package/dist/ai/graph/index.js.map +1 -1
- package/dist/ai/graph/index.mjs +3 -1
- package/dist/ai/graph/postgres-checkpointer.d.ts +1 -1
- package/dist/ai/graph/postgres-checkpointer.d.ts.map +1 -1
- package/dist/ai/graph/postgres-checkpointer.js +13 -3
- package/dist/ai/graph/postgres-checkpointer.js.map +1 -1
- package/dist/ai/graph/postgres-checkpointer.mjs +13 -3
- package/dist/ai/graph/redis-checkpointer.d.ts +1 -1
- package/dist/ai/graph/redis-checkpointer.d.ts.map +1 -1
- package/dist/ai/graph/redis-checkpointer.js +6 -2
- package/dist/ai/graph/redis-checkpointer.js.map +1 -1
- package/dist/ai/graph/redis-checkpointer.mjs +6 -2
- package/dist/ai/internal-types.d.ts +14 -0
- package/dist/ai/internal-types.d.ts.map +1 -1
- package/dist/ai/internal-types.js +15 -0
- package/dist/ai/internal-types.js.map +1 -1
- package/dist/ai/internal-types.mjs +13 -0
- package/dist/ai/memory/index.d.ts +147 -0
- package/dist/ai/memory/index.d.ts.map +1 -0
- package/dist/ai/memory/index.js +240 -0
- package/dist/ai/memory/index.js.map +1 -0
- package/dist/ai/memory/index.mjs +234 -0
- package/dist/ai/nodes/execute-node.d.ts +2 -1
- package/dist/ai/nodes/execute-node.d.ts.map +1 -1
- package/dist/ai/nodes/execute-node.js +11 -33
- package/dist/ai/nodes/execute-node.js.map +1 -1
- package/dist/ai/nodes/execute-node.mjs +11 -33
- package/dist/ai/nodes/memory-node.d.ts.map +1 -1
- package/dist/ai/nodes/memory-node.js +14 -16
- package/dist/ai/nodes/memory-node.js.map +1 -1
- package/dist/ai/nodes/memory-node.mjs +15 -17
- package/dist/ai/stream-object.d.ts +109 -0
- package/dist/ai/stream-object.d.ts.map +1 -0
- package/dist/ai/stream-object.js +383 -0
- package/dist/ai/stream-object.js.map +1 -0
- package/dist/ai/stream-object.mjs +347 -0
- package/dist/ai/tool-approval.d.ts +90 -0
- package/dist/ai/tool-approval.d.ts.map +1 -0
- package/dist/ai/tool-approval.js +151 -0
- package/dist/ai/tool-approval.js.map +1 -0
- package/dist/ai/tool-approval.mjs +147 -0
- package/dist/index.d.ts +17 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -4
- package/dist/lib/capability-cache.d.ts +72 -0
- package/dist/lib/capability-cache.d.ts.map +1 -0
- package/dist/lib/capability-cache.js +117 -0
- package/dist/lib/capability-cache.js.map +1 -0
- package/dist/lib/capability-cache.mjs +113 -0
- package/dist/lib/content-converter.d.ts +33 -0
- package/dist/lib/content-converter.d.ts.map +1 -0
- package/dist/lib/content-converter.js +166 -0
- package/dist/lib/content-converter.js.map +1 -0
- package/dist/lib/content-converter.mjs +161 -0
- package/dist/lib/errors.d.ts +15 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +13 -1
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/errors.mjs +11 -0
- package/dist/lib/messages.js +4 -3
- package/dist/lib/messages.js.map +1 -1
- package/dist/lib/messages.mjs +4 -3
- package/dist/lib/partial-json-parser.d.ts +63 -0
- package/dist/lib/partial-json-parser.d.ts.map +1 -0
- package/dist/lib/partial-json-parser.js +142 -0
- package/dist/lib/partial-json-parser.js.map +1 -0
- package/dist/lib/partial-json-parser.mjs +137 -0
- package/dist/lib/token-estimator.d.ts.map +1 -1
- package/dist/lib/token-estimator.js +3 -2
- package/dist/lib/token-estimator.js.map +1 -1
- package/dist/lib/token-estimator.mjs +3 -2
- package/dist/lib/tool-registry.d.ts +21 -0
- package/dist/lib/tool-registry.d.ts.map +1 -1
- package/dist/lib/tool-registry.js.map +1 -1
- package/dist/lib/types.d.ts +20 -4
- package/dist/lib/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Manager for Agent conversations.
|
|
3
|
+
* Provides short-term and long-term memory management with automatic summarization.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { MemoryManager, InMemoryVectorStore } from '@bowenqt/qiniu-ai-sdk';
|
|
8
|
+
*
|
|
9
|
+
* const memory = new MemoryManager({
|
|
10
|
+
* shortTerm: { maxMessages: 20 },
|
|
11
|
+
* summarizer: {
|
|
12
|
+
* enabled: true,
|
|
13
|
+
* threshold: 50,
|
|
14
|
+
* client,
|
|
15
|
+
* model: 'gemini-2.5-flash',
|
|
16
|
+
* },
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Apply memory to messages before sending to LLM
|
|
20
|
+
* const processedMessages = await memory.process(messages, options);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// In-Memory Vector Store (Simple Implementation)
|
|
25
|
+
// ============================================================================
|
|
26
|
+
/**
|
|
27
|
+
* Simple in-memory vector store for testing and small-scale use.
|
|
28
|
+
* Uses cosine similarity for search (requires embeddings).
|
|
29
|
+
*/
|
|
30
|
+
export class InMemoryVectorStore {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.documents = [];
|
|
33
|
+
}
|
|
34
|
+
async add(documents) {
|
|
35
|
+
this.documents.push(...documents);
|
|
36
|
+
}
|
|
37
|
+
async search(query, limit = 5) {
|
|
38
|
+
// Simple text search (no embeddings)
|
|
39
|
+
// In production, use proper embeddings and vector similarity
|
|
40
|
+
const queryLower = query.toLowerCase();
|
|
41
|
+
const scored = this.documents.map(doc => ({
|
|
42
|
+
doc,
|
|
43
|
+
score: this.textSimilarity(queryLower, doc.content.toLowerCase()),
|
|
44
|
+
}));
|
|
45
|
+
return scored
|
|
46
|
+
.sort((a, b) => b.score - a.score)
|
|
47
|
+
.slice(0, limit)
|
|
48
|
+
.map(s => s.doc);
|
|
49
|
+
}
|
|
50
|
+
async clear() {
|
|
51
|
+
this.documents = [];
|
|
52
|
+
}
|
|
53
|
+
textSimilarity(a, b) {
|
|
54
|
+
// Simple word overlap score
|
|
55
|
+
const wordsA = new Set(a.split(/\s+/));
|
|
56
|
+
const wordsB = new Set(b.split(/\s+/));
|
|
57
|
+
let overlap = 0;
|
|
58
|
+
for (const word of wordsA) {
|
|
59
|
+
if (wordsB.has(word))
|
|
60
|
+
overlap++;
|
|
61
|
+
}
|
|
62
|
+
return overlap / Math.max(wordsA.size, wordsB.size, 1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// Memory Manager
|
|
67
|
+
// ============================================================================
|
|
68
|
+
/**
|
|
69
|
+
* Memory manager for agent conversations.
|
|
70
|
+
* Handles short-term (sliding window) and long-term (vector) memory.
|
|
71
|
+
*/
|
|
72
|
+
export class MemoryManager {
|
|
73
|
+
constructor(config = {}) {
|
|
74
|
+
this.summaries = new Map(); // threadId -> summary
|
|
75
|
+
this.config = {
|
|
76
|
+
shortTerm: { maxMessages: 50, ...config.shortTerm },
|
|
77
|
+
...config,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Process messages with memory management.
|
|
82
|
+
* Applies summarization, trimming, and long-term retrieval.
|
|
83
|
+
*/
|
|
84
|
+
async process(messages, options = {}) {
|
|
85
|
+
const { threadId = 'default', generateSummary = true } = options;
|
|
86
|
+
let processedMessages = [...messages];
|
|
87
|
+
let summarized = false;
|
|
88
|
+
let summary;
|
|
89
|
+
let droppedCount = 0;
|
|
90
|
+
// 1. Check if summarization is needed
|
|
91
|
+
const threshold = this.config.summarizer?.threshold ?? 50;
|
|
92
|
+
if (this.config.summarizer?.enabled &&
|
|
93
|
+
generateSummary &&
|
|
94
|
+
messages.length > threshold) {
|
|
95
|
+
// Generate summary from older messages
|
|
96
|
+
const messagesToSummarize = messages.slice(0, messages.length - Math.floor(threshold / 2));
|
|
97
|
+
summary = await this.generateSummary(messagesToSummarize, threadId);
|
|
98
|
+
this.summaries.set(threadId, summary);
|
|
99
|
+
summarized = true;
|
|
100
|
+
}
|
|
101
|
+
// 2. Apply short-term memory (sliding window)
|
|
102
|
+
const maxMessages = this.config.shortTerm?.maxMessages ?? 50;
|
|
103
|
+
if (processedMessages.length > maxMessages) {
|
|
104
|
+
droppedCount = processedMessages.length - maxMessages;
|
|
105
|
+
processedMessages = processedMessages.slice(-maxMessages);
|
|
106
|
+
}
|
|
107
|
+
// 3. Inject summary if available
|
|
108
|
+
const existingSummary = this.summaries.get(threadId);
|
|
109
|
+
if (existingSummary) {
|
|
110
|
+
const summaryMessage = {
|
|
111
|
+
role: 'system',
|
|
112
|
+
content: `[CONVERSATION SUMMARY]\n${existingSummary}`,
|
|
113
|
+
_meta: {
|
|
114
|
+
summaryId: `summary_${threadId}`,
|
|
115
|
+
droppable: true,
|
|
116
|
+
priority: 100, // Low priority (drop first)
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
// Insert after first system message
|
|
120
|
+
const firstSystemIdx = processedMessages.findIndex(m => m.role === 'system');
|
|
121
|
+
if (firstSystemIdx >= 0) {
|
|
122
|
+
processedMessages.splice(firstSystemIdx + 1, 0, summaryMessage);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
processedMessages.unshift(summaryMessage);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// 4. Long-term retrieval (if configured)
|
|
129
|
+
if (this.config.longTerm) {
|
|
130
|
+
const lastUserMessage = [...messages].reverse().find(m => m.role === 'user');
|
|
131
|
+
if (lastUserMessage && typeof lastUserMessage.content === 'string') {
|
|
132
|
+
const retrieved = await this.config.longTerm.store.search(lastUserMessage.content, this.config.longTerm.retrieveLimit ?? 3);
|
|
133
|
+
if (retrieved.length > 0) {
|
|
134
|
+
const contextMessage = {
|
|
135
|
+
role: 'system',
|
|
136
|
+
content: `[RELEVANT CONTEXT]\n${retrieved.map(d => d.content).join('\n---\n')}`,
|
|
137
|
+
_meta: {
|
|
138
|
+
summaryId: `context_${threadId}`,
|
|
139
|
+
droppable: true,
|
|
140
|
+
priority: 90,
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
// Insert after summary (or first system)
|
|
144
|
+
const insertIdx = processedMessages.findIndex(m => m._meta?.summaryId?.startsWith('summary_'));
|
|
145
|
+
if (insertIdx >= 0) {
|
|
146
|
+
processedMessages.splice(insertIdx + 1, 0, contextMessage);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const firstSystemIdx = processedMessages.findIndex(m => m.role === 'system');
|
|
150
|
+
processedMessages.splice(firstSystemIdx + 1, 0, contextMessage);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
messages: processedMessages,
|
|
157
|
+
summarized,
|
|
158
|
+
summary,
|
|
159
|
+
droppedCount,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Generate summary from messages.
|
|
164
|
+
* Override this method for custom summarization logic.
|
|
165
|
+
*/
|
|
166
|
+
async generateSummary(messages, _threadId) {
|
|
167
|
+
// Default: Simple concatenation (override for LLM-based summarization)
|
|
168
|
+
const userMessages = messages
|
|
169
|
+
.filter(m => m.role === 'user' && typeof m.content === 'string')
|
|
170
|
+
.map(m => m.content);
|
|
171
|
+
const assistantMessages = messages
|
|
172
|
+
.filter(m => m.role === 'assistant' && typeof m.content === 'string')
|
|
173
|
+
.map(m => m.content);
|
|
174
|
+
return [
|
|
175
|
+
`User discussed: ${userMessages.slice(0, 3).join(', ').slice(0, 200)}...`,
|
|
176
|
+
`Assistant covered: ${assistantMessages.slice(0, 3).join(', ').slice(0, 200)}...`,
|
|
177
|
+
].join('\n');
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Store messages to long-term memory.
|
|
181
|
+
*/
|
|
182
|
+
async persist(messages, threadId) {
|
|
183
|
+
if (!this.config.longTerm)
|
|
184
|
+
return;
|
|
185
|
+
const documents = messages
|
|
186
|
+
.filter(m => typeof m.content === 'string' && m.content.length > 20)
|
|
187
|
+
.map((m, i) => ({
|
|
188
|
+
id: `${threadId}_${Date.now()}_${i}`,
|
|
189
|
+
content: m.content,
|
|
190
|
+
metadata: { role: m.role, threadId },
|
|
191
|
+
}));
|
|
192
|
+
await this.config.longTerm.store.add(documents);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Clear memory for a thread.
|
|
196
|
+
*/
|
|
197
|
+
clearThread(threadId) {
|
|
198
|
+
this.summaries.delete(threadId);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Clear all memory.
|
|
202
|
+
*/
|
|
203
|
+
async clearAll() {
|
|
204
|
+
this.summaries.clear();
|
|
205
|
+
if (this.config.longTerm) {
|
|
206
|
+
await this.config.longTerm.store.clear();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get current summary for a thread.
|
|
211
|
+
*/
|
|
212
|
+
getSummary(threadId) {
|
|
213
|
+
return this.summaries.get(threadId);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Set summary for a thread (manual override).
|
|
217
|
+
*/
|
|
218
|
+
setSummary(threadId, summary) {
|
|
219
|
+
this.summaries.set(threadId, summary);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// ============================================================================
|
|
223
|
+
// Helper: Check if message is droppable
|
|
224
|
+
// ============================================================================
|
|
225
|
+
/**
|
|
226
|
+
* Check if a message is droppable (skill or summary).
|
|
227
|
+
*/
|
|
228
|
+
export function isDroppable(message) {
|
|
229
|
+
const meta = message._meta;
|
|
230
|
+
if (!meta?.droppable)
|
|
231
|
+
return false;
|
|
232
|
+
return meta.skillId != null || meta.summaryId != null;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { ChatMessage, ToolCall } from '../../lib/types';
|
|
6
6
|
import type { RegisteredTool } from '../../lib/tool-registry';
|
|
7
|
+
import { type ApprovalConfig } from '../tool-approval';
|
|
7
8
|
/** Tool execution context */
|
|
8
9
|
export interface ExecutionContext {
|
|
9
10
|
toolCallId: string;
|
|
@@ -19,7 +20,7 @@ export interface ToolExecutionResult {
|
|
|
19
20
|
/**
|
|
20
21
|
* Execute tools based on tool calls from LLM.
|
|
21
22
|
*/
|
|
22
|
-
export declare function executeTools(toolCalls: ToolCall[], tools: Map<string, RegisteredTool>, context: Omit<ExecutionContext, 'toolCallId'
|
|
23
|
+
export declare function executeTools(toolCalls: ToolCall[], tools: Map<string, RegisteredTool>, context: Omit<ExecutionContext, 'toolCallId'>, approvalConfig?: ApprovalConfig): Promise<ToolExecutionResult[]>;
|
|
23
24
|
/**
|
|
24
25
|
* Convert tool execution results to chat messages.
|
|
25
26
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute-node.d.ts","sourceRoot":"","sources":["../../../src/ai/nodes/execute-node.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"execute-node.d.ts","sourceRoot":"","sources":["../../../src/ai/nodes/execute-node.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE9D,OAAO,EAA2B,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEhF,6BAA6B;AAC7B,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC7B;AAED,kBAAkB;AAClB,MAAM,WAAW,mBAAmB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAC9B,SAAS,EAAE,QAAQ,EAAE,EACrB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EAClC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,EAC7C,cAAc,CAAC,EAAE,cAAc,GAChC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA8ChC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,WAAW,EAAE,CAMnF"}
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.executeTools = executeTools;
|
|
8
8
|
exports.toolResultsToMessages = toolResultsToMessages;
|
|
9
|
+
const tool_approval_1 = require("../tool-approval");
|
|
9
10
|
/**
|
|
10
11
|
* Execute tools based on tool calls from LLM.
|
|
11
12
|
*/
|
|
12
|
-
async function executeTools(toolCalls, tools, context) {
|
|
13
|
+
async function executeTools(toolCalls, tools, context, approvalConfig) {
|
|
13
14
|
const results = [];
|
|
14
15
|
for (const call of toolCalls) {
|
|
15
16
|
// Check abort signal
|
|
@@ -30,38 +31,15 @@ async function executeTools(toolCalls, tools, context) {
|
|
|
30
31
|
});
|
|
31
32
|
continue;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
}
|
|
34
|
+
// Parse arguments
|
|
35
|
+
const args = parseToolArguments(call.function.arguments);
|
|
36
|
+
// Execute with approval check using unified function
|
|
37
|
+
const execResult = await (0, tool_approval_1.executeToolWithApproval)(tool, call, args, context.messages, approvalConfig, context.abortSignal);
|
|
38
|
+
results.push({
|
|
39
|
+
toolCallId: call.id,
|
|
40
|
+
result: execResult.result,
|
|
41
|
+
isError: execResult.isError,
|
|
42
|
+
});
|
|
65
43
|
}
|
|
66
44
|
return results;
|
|
67
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute-node.js","sourceRoot":"","sources":["../../../src/ai/nodes/execute-node.ts"],"names":[],"mappings":";AAAA;;;GAGG;;
|
|
1
|
+
{"version":3,"file":"execute-node.js","sourceRoot":"","sources":["../../../src/ai/nodes/execute-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
* ExecuteNode - Tool execution abstraction.
|
|
3
3
|
* Extracted from generateText for modular use in Graph Runtime.
|
|
4
4
|
*/
|
|
5
|
+
import { executeToolWithApproval } from '../tool-approval.mjs';
|
|
5
6
|
/**
|
|
6
7
|
* Execute tools based on tool calls from LLM.
|
|
7
8
|
*/
|
|
8
|
-
export async function executeTools(toolCalls, tools, context) {
|
|
9
|
+
export async function executeTools(toolCalls, tools, context, approvalConfig) {
|
|
9
10
|
const results = [];
|
|
10
11
|
for (const call of toolCalls) {
|
|
11
12
|
// Check abort signal
|
|
@@ -26,38 +27,15 @@ export async function executeTools(toolCalls, tools, context) {
|
|
|
26
27
|
});
|
|
27
28
|
continue;
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
}
|
|
30
|
+
// Parse arguments
|
|
31
|
+
const args = parseToolArguments(call.function.arguments);
|
|
32
|
+
// Execute with approval check using unified function
|
|
33
|
+
const execResult = await executeToolWithApproval(tool, call, args, context.messages, approvalConfig, context.abortSignal);
|
|
34
|
+
results.push({
|
|
35
|
+
toolCallId: call.id,
|
|
36
|
+
result: execResult.result,
|
|
37
|
+
isError: execResult.isError,
|
|
38
|
+
});
|
|
61
39
|
}
|
|
62
40
|
return results;
|
|
63
41
|
}
|
|
@@ -1 +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,
|
|
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,CAuHlB;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"}
|
|
@@ -69,38 +69,36 @@ function compactMessages(messages, config, injectedSkills = []) {
|
|
|
69
69
|
break;
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
// Step 1: Drop droppable skill messages (lowest priority first)
|
|
73
|
-
// Collect all droppable messages with their
|
|
72
|
+
// Step 1: Drop droppable skill/summary messages (lowest priority first)
|
|
73
|
+
// Collect all droppable messages with their IDs, tokens, and priority
|
|
74
74
|
const droppableIndices = [];
|
|
75
75
|
result.messages.forEach((msg, idx) => {
|
|
76
76
|
if ((0, internal_types_1.isDroppable)(msg)) {
|
|
77
|
-
const
|
|
78
|
-
if (
|
|
77
|
+
const droppableId = (0, internal_types_1.getDroppableId)(msg);
|
|
78
|
+
if (droppableId) {
|
|
79
|
+
const internalMsg = msg;
|
|
80
|
+
const skillIdx = injectedSkills.findIndex(s => s.name === droppableId);
|
|
79
81
|
droppableIndices.push({
|
|
80
82
|
idx,
|
|
81
|
-
|
|
83
|
+
droppableId,
|
|
82
84
|
tokens: config.estimateTokens([msg]),
|
|
85
|
+
// Use _meta.priority if set, else fallback to skill order, else 0
|
|
86
|
+
priority: internalMsg._meta?.priority ?? (skillIdx >= 0 ? skillIdx + 1 : 0),
|
|
83
87
|
});
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
});
|
|
87
|
-
// Sort by priority (
|
|
88
|
-
|
|
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
|
-
});
|
|
91
|
+
// Sort by priority (higher priority = keep, lower priority = drop first)
|
|
92
|
+
droppableIndices.sort((a, b) => a.priority - b.priority);
|
|
95
93
|
// Drop droppable messages until under budget
|
|
96
94
|
const indicesToRemove = new Set();
|
|
97
|
-
for (const { idx,
|
|
95
|
+
for (const { idx, droppableId, tokens } of droppableIndices) {
|
|
98
96
|
if (currentTokens <= config.maxTokens)
|
|
99
97
|
break;
|
|
100
98
|
indicesToRemove.add(idx);
|
|
101
99
|
currentTokens -= tokens;
|
|
102
|
-
if (!result.droppedSkills.includes(
|
|
103
|
-
result.droppedSkills.push(
|
|
100
|
+
if (!result.droppedSkills.includes(droppableId)) {
|
|
101
|
+
result.droppedSkills.push(droppableId);
|
|
104
102
|
}
|
|
105
103
|
}
|
|
106
104
|
// Step 2: Drop oldest unprotected non-skill messages
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-node.js","sourceRoot":"","sources":["../../../src/ai/nodes/memory-node.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAyBH,
|
|
1
|
+
{"version":3,"file":"memory-node.js","sourceRoot":"","sources":["../../../src/ai/nodes/memory-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* 2. Drop oldest unprotected messages
|
|
7
7
|
* 3. Throw ContextOverflowError
|
|
8
8
|
*/
|
|
9
|
-
import { isDroppable,
|
|
9
|
+
import { isDroppable, getDroppableId } from '../internal-types.mjs';
|
|
10
10
|
/** Context overflow error */
|
|
11
11
|
export class ContextOverflowError extends Error {
|
|
12
12
|
constructor(currentTokens, maxTokens, recommendation) {
|
|
@@ -63,38 +63,36 @@ export function compactMessages(messages, config, injectedSkills = []) {
|
|
|
63
63
|
break;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
// Step 1: Drop droppable skill messages (lowest priority first)
|
|
67
|
-
// Collect all droppable messages with their
|
|
66
|
+
// Step 1: Drop droppable skill/summary messages (lowest priority first)
|
|
67
|
+
// Collect all droppable messages with their IDs, tokens, and priority
|
|
68
68
|
const droppableIndices = [];
|
|
69
69
|
result.messages.forEach((msg, idx) => {
|
|
70
70
|
if (isDroppable(msg)) {
|
|
71
|
-
const
|
|
72
|
-
if (
|
|
71
|
+
const droppableId = getDroppableId(msg);
|
|
72
|
+
if (droppableId) {
|
|
73
|
+
const internalMsg = msg;
|
|
74
|
+
const skillIdx = injectedSkills.findIndex(s => s.name === droppableId);
|
|
73
75
|
droppableIndices.push({
|
|
74
76
|
idx,
|
|
75
|
-
|
|
77
|
+
droppableId,
|
|
76
78
|
tokens: config.estimateTokens([msg]),
|
|
79
|
+
// Use _meta.priority if set, else fallback to skill order, else 0
|
|
80
|
+
priority: internalMsg._meta?.priority ?? (skillIdx >= 0 ? skillIdx + 1 : 0),
|
|
77
81
|
});
|
|
78
82
|
}
|
|
79
83
|
}
|
|
80
84
|
});
|
|
81
|
-
// Sort by priority (
|
|
82
|
-
|
|
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
|
-
});
|
|
85
|
+
// Sort by priority (higher priority = keep, lower priority = drop first)
|
|
86
|
+
droppableIndices.sort((a, b) => a.priority - b.priority);
|
|
89
87
|
// Drop droppable messages until under budget
|
|
90
88
|
const indicesToRemove = new Set();
|
|
91
|
-
for (const { idx,
|
|
89
|
+
for (const { idx, droppableId, tokens } of droppableIndices) {
|
|
92
90
|
if (currentTokens <= config.maxTokens)
|
|
93
91
|
break;
|
|
94
92
|
indicesToRemove.add(idx);
|
|
95
93
|
currentTokens -= tokens;
|
|
96
|
-
if (!result.droppedSkills.includes(
|
|
97
|
-
result.droppedSkills.push(
|
|
94
|
+
if (!result.droppedSkills.includes(droppableId)) {
|
|
95
|
+
result.droppedSkills.push(droppableId);
|
|
98
96
|
}
|
|
99
97
|
}
|
|
100
98
|
// Step 2: Drop oldest unprotected non-skill messages
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* streamObject - Stream structured output with incremental parsing.
|
|
3
|
+
* Bypasses predict-node to enable streaming with JSON schema.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { streamObject } from '@bowenqt/qiniu-ai-sdk';
|
|
8
|
+
* import { z } from 'zod';
|
|
9
|
+
*
|
|
10
|
+
* const { partialObjectStream, object } = await streamObject({
|
|
11
|
+
* client,
|
|
12
|
+
* model: 'gemini-2.5-flash',
|
|
13
|
+
* schema: z.object({
|
|
14
|
+
* title: z.string(),
|
|
15
|
+
* chapters: z.array(z.object({
|
|
16
|
+
* title: z.string(),
|
|
17
|
+
* content: z.string(),
|
|
18
|
+
* })),
|
|
19
|
+
* }),
|
|
20
|
+
* prompt: 'Generate a book outline about AI',
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // Stream partial objects
|
|
24
|
+
* for await (const partial of partialObjectStream) {
|
|
25
|
+
* console.log(partial);
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* // Get final validated object
|
|
29
|
+
* const result = await object;
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
import type { QiniuAI } from '../client';
|
|
33
|
+
import type { ChatMessage } from '../lib/types';
|
|
34
|
+
/** Options for streamObject */
|
|
35
|
+
export interface StreamObjectOptions<T> {
|
|
36
|
+
/** Qiniu AI client */
|
|
37
|
+
client: QiniuAI;
|
|
38
|
+
/** Model to use */
|
|
39
|
+
model: string;
|
|
40
|
+
/** Zod schema for validation */
|
|
41
|
+
schema: ZodSchema<T>;
|
|
42
|
+
/** User prompt */
|
|
43
|
+
prompt?: string;
|
|
44
|
+
/** Message history */
|
|
45
|
+
messages?: ChatMessage[];
|
|
46
|
+
/** System prompt */
|
|
47
|
+
system?: string;
|
|
48
|
+
/** Temperature (0-2) */
|
|
49
|
+
temperature?: number;
|
|
50
|
+
/** Top-p sampling */
|
|
51
|
+
topP?: number;
|
|
52
|
+
/** Maximum output tokens */
|
|
53
|
+
maxTokens?: number;
|
|
54
|
+
/** Abort signal */
|
|
55
|
+
abortSignal?: AbortSignal;
|
|
56
|
+
/**
|
|
57
|
+
* Allow fallback to non-streaming if API doesn't support streaming JSON.
|
|
58
|
+
* Default: false (will throw if streaming not supported)
|
|
59
|
+
*/
|
|
60
|
+
allowFallback?: boolean;
|
|
61
|
+
}
|
|
62
|
+
/** Result from streamObject */
|
|
63
|
+
export interface StreamObjectResult<T> {
|
|
64
|
+
/** Async iterator of partial objects */
|
|
65
|
+
partialObjectStream: AsyncIterable<DeepPartial<T>>;
|
|
66
|
+
/** Promise resolving to final validated object */
|
|
67
|
+
object: Promise<T>;
|
|
68
|
+
/** Promise resolving to raw text */
|
|
69
|
+
rawText: Promise<string>;
|
|
70
|
+
/** Promise resolving to usage info */
|
|
71
|
+
usage: Promise<{
|
|
72
|
+
prompt_tokens: number;
|
|
73
|
+
completion_tokens: number;
|
|
74
|
+
total_tokens: number;
|
|
75
|
+
} | undefined>;
|
|
76
|
+
/** Whether streaming was used (false if fell back to non-streaming) */
|
|
77
|
+
streamed: boolean;
|
|
78
|
+
}
|
|
79
|
+
/** Deep partial type for partial objects */
|
|
80
|
+
export type DeepPartial<T> = T extends object ? {
|
|
81
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
|
82
|
+
} : T;
|
|
83
|
+
/** Minimal Zod schema interface */
|
|
84
|
+
interface ZodSchema<T = unknown> {
|
|
85
|
+
parse: (data: unknown) => T;
|
|
86
|
+
safeParse: (data: unknown) => {
|
|
87
|
+
success: true;
|
|
88
|
+
data: T;
|
|
89
|
+
} | {
|
|
90
|
+
success: false;
|
|
91
|
+
error: ZodError;
|
|
92
|
+
};
|
|
93
|
+
_def?: {
|
|
94
|
+
typeName?: string;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** Zod error interface */
|
|
98
|
+
interface ZodError {
|
|
99
|
+
errors: Array<{
|
|
100
|
+
path: (string | number)[];
|
|
101
|
+
message: string;
|
|
102
|
+
}>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Stream structured output with JSON schema validation.
|
|
106
|
+
*/
|
|
107
|
+
export declare function streamObject<T>(options: StreamObjectOptions<T>): Promise<StreamObjectResult<T>>;
|
|
108
|
+
export {};
|
|
109
|
+
//# sourceMappingURL=stream-object.d.ts.map
|