@axiom-lattice/gateway 2.1.44 → 2.1.45
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +11 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +234 -561
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -399
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -4
- package/src/controllers/assistant.ts +5 -4
- package/src/controllers/memory.ts +17 -13
- package/src/controllers/run.ts +62 -52
- package/src/controllers/thread_status.ts +228 -0
- package/src/index.ts +8 -1
- package/src/routes/index.ts +18 -0
- package/src/services/agent_task_consumer.ts +12 -107
- package/src/__tests__/agent_service.test.ts +0 -238
- package/src/services/agent_service.ts +0 -375
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AIMessage,
|
|
3
|
-
AIMessageChunk,
|
|
4
|
-
BaseMessage,
|
|
5
|
-
filterMessages,
|
|
6
|
-
HumanMessage,
|
|
7
|
-
ToolMessage,
|
|
8
|
-
ToolMessageChunk,
|
|
9
|
-
} from "@langchain/core/messages";
|
|
10
|
-
import { Command, CommandParams } from "@langchain/langgraph";
|
|
11
|
-
import { v4 } from "uuid";
|
|
12
|
-
import {
|
|
13
|
-
getAgentClient,
|
|
14
|
-
agentLatticeManager,
|
|
15
|
-
InMemoryChunkBuffer,
|
|
16
|
-
registerChunkBuffer,
|
|
17
|
-
getChunkBuffer,
|
|
18
|
-
hasChunkBuffer,
|
|
19
|
-
} from "@axiom-lattice/core";
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Check if an agent exists for the given tenant and assistant ID
|
|
23
|
-
*/
|
|
24
|
-
export async function checkAgentExists(
|
|
25
|
-
tenant_id: string,
|
|
26
|
-
assistant_id: string
|
|
27
|
-
): Promise<boolean> {
|
|
28
|
-
try {
|
|
29
|
-
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
30
|
-
return agentLattice !== undefined;
|
|
31
|
-
} catch {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Get or create the global ChunkBuffer instance
|
|
38
|
-
*/
|
|
39
|
-
function getOrCreateChunkBuffer(): InMemoryChunkBuffer {
|
|
40
|
-
if (!hasChunkBuffer("default")) {
|
|
41
|
-
const buffer = new InMemoryChunkBuffer({
|
|
42
|
-
ttl: 60 * 60 * 1000, // 1 hour TTL
|
|
43
|
-
cleanupInterval: 5 * 60 * 1000, // Clean every 5 minutes
|
|
44
|
-
});
|
|
45
|
-
registerChunkBuffer("default", buffer);
|
|
46
|
-
}
|
|
47
|
-
return getChunkBuffer("default") as InMemoryChunkBuffer;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export async function agent_invoke({
|
|
51
|
-
input,
|
|
52
|
-
thread_id,
|
|
53
|
-
assistant_id,
|
|
54
|
-
tenant_id,
|
|
55
|
-
workspace_id,
|
|
56
|
-
project_id,
|
|
57
|
-
command,
|
|
58
|
-
run_id,
|
|
59
|
-
custom_run_config,
|
|
60
|
-
}: {
|
|
61
|
-
assistant_id: string;
|
|
62
|
-
input: any;
|
|
63
|
-
thread_id: string;
|
|
64
|
-
tenant_id: string;
|
|
65
|
-
workspace_id?: string;
|
|
66
|
-
project_id?: string;
|
|
67
|
-
run_id?: string;
|
|
68
|
-
command?: CommandParams<any>;
|
|
69
|
-
custom_run_config?: Record<string, any>;
|
|
70
|
-
}) {
|
|
71
|
-
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
72
|
-
const runnable_agent = agentLattice?.client;
|
|
73
|
-
|
|
74
|
-
const { message, ...rest } = input;
|
|
75
|
-
const humanMessage = new HumanMessage(message || "");
|
|
76
|
-
const messages = [humanMessage];
|
|
77
|
-
if (!runnable_agent) {
|
|
78
|
-
throw new Error(`Agent ${assistant_id} not found`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Get runConfig from agent config and merge with custom_run_config
|
|
82
|
-
const runConfig = {
|
|
83
|
-
...agentLattice?.config?.runConfig || {},
|
|
84
|
-
tenantId: tenant_id,
|
|
85
|
-
workspaceId: workspace_id,
|
|
86
|
-
projectId: project_id,
|
|
87
|
-
...custom_run_config || {},
|
|
88
|
-
assistant_id,
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const result = await runnable_agent.invoke(
|
|
93
|
-
command
|
|
94
|
-
? new Command(command)
|
|
95
|
-
: { ...rest, messages, "x-tenant-id": tenant_id },
|
|
96
|
-
{
|
|
97
|
-
context: {
|
|
98
|
-
runConfig
|
|
99
|
-
},
|
|
100
|
-
configurable: {
|
|
101
|
-
thread_id: thread_id,
|
|
102
|
-
run_id: run_id || v4(),
|
|
103
|
-
"x-tenant-id": tenant_id,
|
|
104
|
-
"x-workspace-id": workspace_id,
|
|
105
|
-
"x-project-id": project_id,
|
|
106
|
-
"x-request-id": run_id,
|
|
107
|
-
"x-thread-id": thread_id,
|
|
108
|
-
"x-assistant-id": assistant_id,
|
|
109
|
-
runConfig,
|
|
110
|
-
},
|
|
111
|
-
recursionLimit: 200,
|
|
112
|
-
}
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
const data = result.messages.map((message: BaseMessage) => {
|
|
116
|
-
const { type, data } = message.toDict();
|
|
117
|
-
return {
|
|
118
|
-
...data,
|
|
119
|
-
role: type,
|
|
120
|
-
};
|
|
121
|
-
});
|
|
122
|
-
return { messages: data };
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export async function agent_stream({
|
|
126
|
-
input,
|
|
127
|
-
thread_id,
|
|
128
|
-
command,
|
|
129
|
-
tenant_id,
|
|
130
|
-
workspace_id,
|
|
131
|
-
project_id,
|
|
132
|
-
assistant_id,
|
|
133
|
-
run_id,
|
|
134
|
-
custom_run_config,
|
|
135
|
-
}: {
|
|
136
|
-
assistant_id: string;
|
|
137
|
-
input: any;
|
|
138
|
-
thread_id: string;
|
|
139
|
-
command?: CommandParams<any>;
|
|
140
|
-
tenant_id: string;
|
|
141
|
-
workspace_id?: string;
|
|
142
|
-
project_id?: string;
|
|
143
|
-
run_id?: string;
|
|
144
|
-
custom_run_config?: Record<string, any>;
|
|
145
|
-
}) {
|
|
146
|
-
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
147
|
-
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
148
|
-
const { message, ...rest } = input;
|
|
149
|
-
let messages: BaseMessage[] = [];
|
|
150
|
-
if (!command) {
|
|
151
|
-
const humanMessage = new HumanMessage(message);
|
|
152
|
-
messages = [humanMessage];
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Get ChunkBuffer instance
|
|
156
|
-
const chunkBuffer = getOrCreateChunkBuffer();
|
|
157
|
-
|
|
158
|
-
// Get runConfig from agent config and merge with custom_run_config
|
|
159
|
-
const runConfig = {
|
|
160
|
-
...agentLattice?.config?.runConfig || {},
|
|
161
|
-
tenantId: tenant_id,
|
|
162
|
-
workspaceId: workspace_id,
|
|
163
|
-
projectId: project_id,
|
|
164
|
-
...custom_run_config || {},
|
|
165
|
-
assistant_id,
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
try {
|
|
170
|
-
if (!runnable_agent) {
|
|
171
|
-
throw new Error(`Agent ${assistant_id} not found`);
|
|
172
|
-
}
|
|
173
|
-
const agentStream = await (runnable_agent as any).stream(
|
|
174
|
-
command
|
|
175
|
-
? new Command(command)
|
|
176
|
-
: {
|
|
177
|
-
...rest,
|
|
178
|
-
messages,
|
|
179
|
-
"x-tenant-id": tenant_id,
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
{
|
|
183
|
-
context: {
|
|
184
|
-
runConfig
|
|
185
|
-
},
|
|
186
|
-
configurable: {
|
|
187
|
-
thread_id: thread_id,
|
|
188
|
-
run_id: run_id || v4(),
|
|
189
|
-
"x-tenant-id": tenant_id,
|
|
190
|
-
"x-workspace-id": workspace_id,
|
|
191
|
-
"x-project-id": project_id,
|
|
192
|
-
"x-request-id": run_id,
|
|
193
|
-
"x-thread-id": thread_id,
|
|
194
|
-
"x-assistant-id": assistant_id,
|
|
195
|
-
runConfig, // Inject runConfig for tools to access
|
|
196
|
-
},
|
|
197
|
-
streamMode: ["updates", "messages"],
|
|
198
|
-
subgraphs: false,
|
|
199
|
-
recursionLimit: 200,
|
|
200
|
-
}
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
// 创建一个可迭代的 ReadableStream with ChunkBuffer integration
|
|
204
|
-
return {
|
|
205
|
-
[Symbol.asyncIterator]: async function* () {
|
|
206
|
-
try {
|
|
207
|
-
for await (const chunk of agentStream) {
|
|
208
|
-
let data;
|
|
209
|
-
let chunkContent = "";
|
|
210
|
-
|
|
211
|
-
if (chunk[0] === "updates") {
|
|
212
|
-
const update = chunk[1];
|
|
213
|
-
const values = Object.values(update);
|
|
214
|
-
const messages = (values[0] as any)?.messages;
|
|
215
|
-
if (messages?.[0]?.tool_call_id) {
|
|
216
|
-
data = messages[0].toDict();
|
|
217
|
-
}
|
|
218
|
-
} else if (chunk[0] === "messages") {
|
|
219
|
-
const messages = chunk[1];
|
|
220
|
-
// console.log(messages);
|
|
221
|
-
data = messages?.[0]?.toDict();
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if ((chunk?.[1] as any)?.__interrupt__) {
|
|
225
|
-
//data = chunk?.[1]?.[0]?.toDict();
|
|
226
|
-
// 原有的中断消息处理
|
|
227
|
-
data = {
|
|
228
|
-
type: "interrupt",
|
|
229
|
-
id: (chunk?.[1] as any)?.__interrupt__[0].id,
|
|
230
|
-
data: { content: (chunk?.[1] as any)?.__interrupt__[0].value },
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (data) {
|
|
235
|
-
//console.log(data);
|
|
236
|
-
if (data.type !== "interrupt") {
|
|
237
|
-
await chunkBuffer.addChunk(thread_id, data);
|
|
238
|
-
}
|
|
239
|
-
yield data;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Mark thread as completed when streaming finishes successfully
|
|
244
|
-
await chunkBuffer.completeThread(thread_id);
|
|
245
|
-
} catch (error) {
|
|
246
|
-
console.error("Stream error:", error);
|
|
247
|
-
// Mark thread as aborted on error
|
|
248
|
-
await chunkBuffer.abortThread(thread_id);
|
|
249
|
-
throw error;
|
|
250
|
-
}
|
|
251
|
-
},
|
|
252
|
-
};
|
|
253
|
-
} catch (error) {
|
|
254
|
-
// Mark thread as aborted on initialization error
|
|
255
|
-
await chunkBuffer.abortThread(thread_id);
|
|
256
|
-
throw error;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
export async function agent_state({
|
|
261
|
-
assistant_id,
|
|
262
|
-
thread_id,
|
|
263
|
-
tenant_id,
|
|
264
|
-
}: {
|
|
265
|
-
assistant_id: string;
|
|
266
|
-
thread_id: string;
|
|
267
|
-
tenant_id: string;
|
|
268
|
-
}) {
|
|
269
|
-
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
270
|
-
if (!runnable_agent) {
|
|
271
|
-
throw new Error(`Agent ${assistant_id} not found`);
|
|
272
|
-
}
|
|
273
|
-
const state = await runnable_agent.getState({
|
|
274
|
-
configurable: { thread_id: thread_id, subgraphs: false },
|
|
275
|
-
});
|
|
276
|
-
return state;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export async function agent_messages({
|
|
280
|
-
thread_id,
|
|
281
|
-
tenant_id,
|
|
282
|
-
assistant_id,
|
|
283
|
-
}: {
|
|
284
|
-
assistant_id: string;
|
|
285
|
-
thread_id: string;
|
|
286
|
-
tenant_id: string;
|
|
287
|
-
}) {
|
|
288
|
-
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
289
|
-
if (!runnable_agent) {
|
|
290
|
-
throw new Error(`Agent ${assistant_id} not found`);
|
|
291
|
-
}
|
|
292
|
-
const state = await runnable_agent.getState({
|
|
293
|
-
configurable: { thread_id: thread_id, subgraphs: false },
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
const messages = state.values.messages || [];
|
|
297
|
-
const filteredMessages = filterMessages(messages, {
|
|
298
|
-
includeTypes: ["ai", "human", "tool"], //["human", "ai", "tool"],
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
// console.log(filteredMessages);
|
|
302
|
-
|
|
303
|
-
let messagesArray = filteredMessages.map((message: BaseMessage) => ({
|
|
304
|
-
id: message.id,
|
|
305
|
-
role: message.getType(),
|
|
306
|
-
content: message.content,
|
|
307
|
-
...message.lc_kwargs,
|
|
308
|
-
}));
|
|
309
|
-
|
|
310
|
-
// const action_messages = state.tasks.flatMap((task) => {
|
|
311
|
-
// return task.interrupts.map((interrupt) => {
|
|
312
|
-
// return {
|
|
313
|
-
// role: "ai",
|
|
314
|
-
// content: interrupt.value,
|
|
315
|
-
// type: "action",
|
|
316
|
-
// };
|
|
317
|
-
// });
|
|
318
|
-
// });
|
|
319
|
-
|
|
320
|
-
const new_messages = messagesArray;
|
|
321
|
-
// console.log(messagesArray);
|
|
322
|
-
|
|
323
|
-
return new_messages;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
export async function draw_graph(assistant_id: string, tenant_id: string) {
|
|
327
|
-
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
328
|
-
if (!runnable_agent) {
|
|
329
|
-
throw new Error(`Agent ${assistant_id} not found`);
|
|
330
|
-
}
|
|
331
|
-
const drawableGraph = await runnable_agent.getGraphAsync();
|
|
332
|
-
const image = await drawableGraph.drawMermaid();
|
|
333
|
-
return image;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Resume streaming from a known position
|
|
338
|
-
* Creates an async iterator that yields new chunks as they arrive
|
|
339
|
-
*
|
|
340
|
-
* @param thread_id - Thread identifier
|
|
341
|
-
* @param message_id - Message identifier (usually run_id)
|
|
342
|
-
* @param known_content - Content already received (used to find resume position)
|
|
343
|
-
* @param poll_interval - Polling interval in milliseconds (default: 100ms)
|
|
344
|
-
*/
|
|
345
|
-
export async function resume_stream({
|
|
346
|
-
thread_id,
|
|
347
|
-
message_id,
|
|
348
|
-
known_content,
|
|
349
|
-
poll_interval = 100,
|
|
350
|
-
}: {
|
|
351
|
-
thread_id: string;
|
|
352
|
-
message_id: string;
|
|
353
|
-
known_content: string;
|
|
354
|
-
poll_interval?: number;
|
|
355
|
-
}) {
|
|
356
|
-
const chunkBuffer = getOrCreateChunkBuffer();
|
|
357
|
-
|
|
358
|
-
const stream = await chunkBuffer.getNewChunksSinceContentIterator(
|
|
359
|
-
thread_id,
|
|
360
|
-
message_id,
|
|
361
|
-
known_content
|
|
362
|
-
);
|
|
363
|
-
return {
|
|
364
|
-
[Symbol.asyncIterator]: async function* () {
|
|
365
|
-
try {
|
|
366
|
-
for await (const chunk of stream) {
|
|
367
|
-
yield chunk;
|
|
368
|
-
}
|
|
369
|
-
} catch (error) {
|
|
370
|
-
console.error("Resume stream error:", error);
|
|
371
|
-
throw error;
|
|
372
|
-
}
|
|
373
|
-
},
|
|
374
|
-
};
|
|
375
|
-
}
|