llm-agent-runtime 0.1.0 → 0.1.5
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 +2 -2
- package/USAGE.md +391 -0
- package/dist/create-runtime.d.ts +2 -0
- package/dist/create-runtime.d.ts.map +1 -1
- package/dist/create-runtime.js +30 -4
- package/dist/env-llm.d.ts +13 -0
- package/dist/env-llm.d.ts.map +1 -0
- package/dist/env-llm.js +44 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/services/conversation.d.ts.map +1 -1
- package/dist/services/conversation.js +20 -8
- package/dist/services/flow-router.d.ts.map +1 -1
- package/dist/services/flow-router.js +12 -0
- package/dist/services/simple-config.d.ts +32 -0
- package/dist/services/simple-config.d.ts.map +1 -0
- package/dist/services/simple-config.js +70 -0
- package/dist/types.d.ts +40 -7
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# llm-agent-runtime
|
|
2
2
|
|
|
3
|
-
Reusable LangGraph agent runtime
|
|
3
|
+
Reusable LangGraph agent runtime: intent routing, sticky flows, checkpointer, tool outputs.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Docs:** [USAGE.md](./USAGE.md)
|
package/USAGE.md
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# llm-agent-runtime
|
|
2
|
+
|
|
3
|
+
Reusable LangGraph agent engine. Your app supplies **intents, prompts, and tools**. The package runs:
|
|
4
|
+
|
|
5
|
+
`resolveFlow → runAgent → extract tool outputs → finalize`
|
|
6
|
+
|
|
7
|
+
Same shape as Xel-agent, but flexible for any product.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install llm-agent-runtime
|
|
15
|
+
# or
|
|
16
|
+
pnpm add llm-agent-runtime
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Peer dependencies** (usually already in a LangChain app):
|
|
20
|
+
|
|
21
|
+
- `@langchain/core`
|
|
22
|
+
- `@langchain/langgraph`
|
|
23
|
+
- `@langchain/langgraph-checkpoint`
|
|
24
|
+
- `zod`
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { createAgentRuntime } from "llm-agent-runtime";
|
|
32
|
+
import { tool } from "@langchain/core/tools";
|
|
33
|
+
import { z } from "zod";
|
|
34
|
+
|
|
35
|
+
const greet = tool(async () => "ok", {
|
|
36
|
+
name: "noop",
|
|
37
|
+
description: "No-op",
|
|
38
|
+
schema: z.object({}),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const runtime = await createAgentRuntime({
|
|
42
|
+
redisUrl: process.env.REDIS_URL, // omit → in-memory checkpointer
|
|
43
|
+
// llm omitted → reads process.env (see Env vars below)
|
|
44
|
+
|
|
45
|
+
intents: [
|
|
46
|
+
{
|
|
47
|
+
name: "greetings",
|
|
48
|
+
examples: ["hi", "hello", "good morning"],
|
|
49
|
+
description: "hello or small talk",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "create_campaign",
|
|
53
|
+
examples: ["create a campaign", "start fundraising"],
|
|
54
|
+
sticky: true,
|
|
55
|
+
description: "new campaign wizard",
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
|
|
59
|
+
intentRegistry: {
|
|
60
|
+
greetings: {
|
|
61
|
+
prompt: (ctx) =>
|
|
62
|
+
`Greet the user. Name: ${ctx.context?.contactName ?? "friend"}.`,
|
|
63
|
+
tools: () => [greet],
|
|
64
|
+
},
|
|
65
|
+
create_campaign: {
|
|
66
|
+
prompt: () => "Help create a campaign step by step. Call create_campaign when ready.",
|
|
67
|
+
tools: (phoneKey) => [/* your tools scoped by phoneKey */],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
toolOutputMap: {
|
|
72
|
+
create_campaign: "campaign",
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
await runtime.connect();
|
|
77
|
+
|
|
78
|
+
const result = await runtime.invoke({
|
|
79
|
+
message: "hi",
|
|
80
|
+
threadId: "user-123",
|
|
81
|
+
context: { contactName: "Ada" },
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
console.log(result.answer, result.intent, result.flow, result.toolOutputs);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## What you pass vs what the library does
|
|
90
|
+
|
|
91
|
+
| You configure | Library handles |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| `intents` (examples + `sticky`) | Hybrid LLM + embedding router |
|
|
94
|
+
| `intentRegistry` (prompt + tools) | LangGraph agent + Redis/memory checkpointer |
|
|
95
|
+
| `toolOutputMap` | Parse tool calls into structured outputs |
|
|
96
|
+
| `completeOn` | Sticky-flow completion + Redis flow state |
|
|
97
|
+
| `menuMap` (optional) | Digit → intent after a numbered menu |
|
|
98
|
+
| Prompts, API tools, webhooks | — stay in your app |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Config reference
|
|
103
|
+
|
|
104
|
+
### `createAgentRuntime(config)`
|
|
105
|
+
|
|
106
|
+
#### Required
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
intents: IntentDefinition[]
|
|
110
|
+
intentRegistry: Record<string, { prompt: (ctx) => string; tools: (phoneKey) => Tool[] }>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Common optional
|
|
114
|
+
|
|
115
|
+
| Option | Default | Purpose |
|
|
116
|
+
| --- | --- | --- |
|
|
117
|
+
| `redisUrl` | none (MemorySaver) | Checkpointer + flow state + optional answer cache |
|
|
118
|
+
| `llm` | `llmConfigFromEnv()` | Provider / models |
|
|
119
|
+
| `cache.enabled` | `false` | Exact-match answer cache (needs Redis) |
|
|
120
|
+
| `toolOutputMap` | raw tool args | Map tool name → output key |
|
|
121
|
+
| `completeOn` | keys of `toolOutputMap` | Tool names that finish a sticky flow |
|
|
122
|
+
| `menuMap` | `{}` | `{ "1": "create_campaign" }` for digit menus |
|
|
123
|
+
| `intentAliases` | `{}` | Legacy name → catalog name |
|
|
124
|
+
| `defaultIntent` | first intent | Fallback intent |
|
|
125
|
+
| `buildSystemPrompt` | registry `prompt` | One builder for all intents |
|
|
126
|
+
| `resolvePhoneKey` | `phoneKey ?? threadId` | Key passed to `tools(phoneKey)` |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Intents
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
intents: [
|
|
134
|
+
{
|
|
135
|
+
name: "greetings",
|
|
136
|
+
examples: ["hi", "hello"],
|
|
137
|
+
description: "Shown to the LLM router",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "create_campaign",
|
|
141
|
+
examples: ["create a campaign"],
|
|
142
|
+
sticky: true, // keep this flow across turns until completeOn fires
|
|
143
|
+
},
|
|
144
|
+
]
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- **examples** — embedding routing
|
|
148
|
+
- **sticky** — multi-step wizards
|
|
149
|
+
- **description** — LLM intent router
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Prompts & tools (`intentRegistry`)
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
intentRegistry: {
|
|
157
|
+
greetings: {
|
|
158
|
+
prompt: (ctx) => string,
|
|
159
|
+
tools: (phoneKey) => DynamicStructuredTool[],
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`prompt` receives:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
{
|
|
168
|
+
hasConversationHistory: boolean
|
|
169
|
+
intent: string
|
|
170
|
+
intentScore?: number
|
|
171
|
+
message?: string
|
|
172
|
+
context?: Record<string, unknown> // whatever you passed to invoke()
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Or use one builder for everything:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
buildSystemPrompt: (ctx) => combineGeneralAndIntent(ctx)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Tool outputs (`toolOutputMap`)
|
|
185
|
+
|
|
186
|
+
Replaces hand-written extractors:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
toolOutputMap: {
|
|
190
|
+
create_campaign: "campaign",
|
|
191
|
+
buy_airtime: "buyAirtime",
|
|
192
|
+
// Nested field on args + seed:
|
|
193
|
+
propose_tickets: { as: "tickets", from: "tickets", initial: [] },
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Result lands on `result.toolOutputs` and completed keys on `result.extras`.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Flow completion (`completeOn`)
|
|
202
|
+
|
|
203
|
+
Pass tool **names**. When any of them produces output, the sticky flow ends:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
completeOn: ["create_campaign", "buy_airtime", "add_airtime"]
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
If you omit `completeOn`, the library defaults `completeOn` to the keys of `toolOutputMap`.
|
|
210
|
+
|
|
211
|
+
This is tuned to Xel-style wizards: when a sticky flow is already active and the user message looks like wizard input (digits / yes-no), the router LLM call is skipped for that turn to reduce tokens.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Menu digits (`menuMap`)
|
|
216
|
+
|
|
217
|
+
Optional. Needed only if users pick a numbered menu (`1`, `2`, …).
|
|
218
|
+
|
|
219
|
+
The **prompt** shows the menu text. **`menuMap`** tells the **router** that `"1"` means `create_campaign`. Without it, a bare `"1"` is not reliably routed.
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
menuMap: {
|
|
223
|
+
"1": "create_campaign",
|
|
224
|
+
"2": "support_campaign",
|
|
225
|
+
"3": "buy_airtime_and_data",
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Invoke
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
const result = await runtime.invoke({
|
|
235
|
+
message: "hi",
|
|
236
|
+
threadId: "whatsapp:234...", // conversation / checkpoint id
|
|
237
|
+
phoneKey: "234...", // optional; passed to tools()
|
|
238
|
+
explicitIntent: "greetings", // optional; skips hybrid router
|
|
239
|
+
context: {
|
|
240
|
+
contactName: "Ada",
|
|
241
|
+
userInfo: { email: "ada@example.com" },
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Result**
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
{
|
|
250
|
+
messages: unknown[]
|
|
251
|
+
answer?: string
|
|
252
|
+
intent: { intent: string, score: number }
|
|
253
|
+
flow: { active: boolean, intent: string | null }
|
|
254
|
+
toolOutputs: Record<string, unknown>
|
|
255
|
+
flowCompleted: boolean
|
|
256
|
+
extras?: Record<string, unknown>
|
|
257
|
+
router?: { action: "continue" | "switch" | "cancel", reason?: string }
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Lifecycle
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
await runtime.connect() // Redis (if redisUrl set)
|
|
267
|
+
await runtime.invoke(...)
|
|
268
|
+
await runtime.clearFlow(id) // drop sticky flow state
|
|
269
|
+
await runtime.disconnect()
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Env vars (when `llm` is omitted)
|
|
275
|
+
|
|
276
|
+
| Variable | Notes |
|
|
277
|
+
| --- | --- |
|
|
278
|
+
| `LLM_PROVIDER` | `ollama` (default) or `openai` |
|
|
279
|
+
| `EMBEDDINGS_PROVIDER` | defaults to `LLM_PROVIDER` |
|
|
280
|
+
| `OLLAMA_MODEL` | default `qwen2.5:7b` |
|
|
281
|
+
| `OLLAMA_BASE_URL` | e.g. `http://localhost:11434` |
|
|
282
|
+
| `INTENT_ROUTER_MODEL` | optional smaller router model |
|
|
283
|
+
| `OLLAMA_EMBEDDINGS_MODEL` | default `mxbai-embed-large:latest` |
|
|
284
|
+
| `OPENAI_API_KEY` | required for openai |
|
|
285
|
+
| `OPENAI_MODEL` | default `gpt-4o-mini` |
|
|
286
|
+
| `OPENAI_EMBEDDINGS_MODEL` | default `text-embedding-3-small` |
|
|
287
|
+
| `REDIS_URL` | your app usually passes this as `redisUrl` |
|
|
288
|
+
| `ANSWER_CACHE` | app convention: `"1"` to enable cache |
|
|
289
|
+
|
|
290
|
+
Or pass LLM explicitly:
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
import { llmConfigFromEnv } from "llm-agent-runtime";
|
|
294
|
+
|
|
295
|
+
createAgentRuntime({
|
|
296
|
+
llm: llmConfigFromEnv(),
|
|
297
|
+
// or
|
|
298
|
+
llm: { provider: "openai", model: "gpt-4o-mini", apiKey: "..." },
|
|
299
|
+
})
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Minimal app shape (recommended)
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
your-app/
|
|
308
|
+
agent/
|
|
309
|
+
runtime.ts # createAgentRuntime({ ... })
|
|
310
|
+
intents.ts # intents + menuMap + aliases
|
|
311
|
+
prompts/ # prompt strings
|
|
312
|
+
tools/ # LangChain tools / API clients
|
|
313
|
+
controllers/ # HTTP / WhatsApp — call runtime.invoke()
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Keep channel adapters and product APIs **out** of this package.
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Full example (Xel-like)
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
import { createAgentRuntime } from "llm-agent-runtime";
|
|
324
|
+
|
|
325
|
+
const runtime = await createAgentRuntime({
|
|
326
|
+
redisUrl: process.env.REDIS_URL ?? "redis://localhost:6379",
|
|
327
|
+
cache: { enabled: process.env.ANSWER_CACHE === "1" },
|
|
328
|
+
|
|
329
|
+
intents: [
|
|
330
|
+
{ name: "greetings", examples: ["hi", "hello"] },
|
|
331
|
+
{
|
|
332
|
+
name: "create_campaign",
|
|
333
|
+
examples: ["create a campaign"],
|
|
334
|
+
sticky: true,
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
name: "buy_airtime_and_data",
|
|
338
|
+
examples: ["buy airtime", "vend airtime"],
|
|
339
|
+
sticky: true,
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
|
|
343
|
+
menuMap: {
|
|
344
|
+
"1": "create_campaign",
|
|
345
|
+
"4": "buy_airtime_and_data",
|
|
346
|
+
},
|
|
347
|
+
|
|
348
|
+
intentAliases: {
|
|
349
|
+
buy_airtime: "buy_airtime_and_data",
|
|
350
|
+
},
|
|
351
|
+
|
|
352
|
+
intentRegistry: {
|
|
353
|
+
greetings: {
|
|
354
|
+
prompt: (ctx) => `Greet ${ctx.context?.contactName ?? "there"}. Show menu 1–7.`,
|
|
355
|
+
tools: () => [],
|
|
356
|
+
},
|
|
357
|
+
create_campaign: {
|
|
358
|
+
prompt: () => "Walk through campaign creation.",
|
|
359
|
+
tools: (phoneKey) => createCampaignTools(phoneKey),
|
|
360
|
+
},
|
|
361
|
+
buy_airtime_and_data: {
|
|
362
|
+
prompt: () => "Help buy airtime/data.",
|
|
363
|
+
tools: (phoneKey) => airtimeTools(phoneKey),
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
toolOutputMap: {
|
|
368
|
+
create_campaign: "campaign",
|
|
369
|
+
buy_airtime: "buyAirtime",
|
|
370
|
+
add_airtime: "addAirtime",
|
|
371
|
+
},
|
|
372
|
+
completeOn: ["create_campaign", "buy_airtime", "add_airtime"],
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
await runtime.connect();
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Exports
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
import {
|
|
384
|
+
createAgentRuntime,
|
|
385
|
+
llmConfigFromEnv,
|
|
386
|
+
getLastMessageContent,
|
|
387
|
+
// advanced (usually not needed)
|
|
388
|
+
createToolOutputExtractor,
|
|
389
|
+
toolOutputMapToExtractors,
|
|
390
|
+
} from "llm-agent-runtime";
|
|
391
|
+
```
|
package/dist/create-runtime.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export type AgentRuntime = {
|
|
|
4
4
|
connect: () => Promise<void>;
|
|
5
5
|
disconnect: () => Promise<void>;
|
|
6
6
|
clearFlow: (threadId: string) => Promise<void>;
|
|
7
|
+
/** Clears LangGraph checkpoint thread (conversation memory). */
|
|
8
|
+
clearThread: (threadId: string) => Promise<void>;
|
|
7
9
|
getCachedAnswer: (message: string) => Promise<string | undefined>;
|
|
8
10
|
setCachedAnswer: (message: string, answer: string) => Promise<void>;
|
|
9
11
|
/** Invalidate embedding cache after changing intent examples at runtime. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-runtime.d.ts","sourceRoot":"","sources":["../src/create-runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-runtime.d.ts","sourceRoot":"","sources":["../src/create-runtime.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,kBAAkB,EAClB,WAAW,EACX,YAAY,EAEb,MAAM,YAAY,CAAC;AAepB,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACtD,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,gEAAgE;IAChE,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAClE,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,4EAA4E;IAC5E,0BAA0B,EAAE,MAAM,IAAI,CAAC;CACxC,CAAC;AAEF;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,YAAY,CAAC,CA0OvB"}
|
package/dist/create-runtime.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { createAgentFactory } from "./agent.js";
|
|
2
2
|
import { createModels } from "./llm.js";
|
|
3
|
+
import { llmConfigFromEnv } from "./env-llm.js";
|
|
3
4
|
import { createRedis } from "./redis.js";
|
|
4
5
|
import { createAgentRunner } from "./services/agent-runner.js";
|
|
5
6
|
import { createChatCache } from "./services/chat-cache.js";
|
|
6
7
|
import { createConversationService } from "./services/conversation.js";
|
|
7
8
|
import { createToolOutputExtractor, extractRawToolOutputs } from "./services/extract.js";
|
|
9
|
+
import { createCompleteOnFinalize, toolOutputMapToExtractors, } from "./services/simple-config.js";
|
|
8
10
|
import { createFlowRouter, stickySetFromIntents, } from "./services/flow-router.js";
|
|
9
11
|
import { createIntentEmbeddings } from "./services/intent-embeddings.js";
|
|
10
12
|
import { createIntentRouter } from "./services/intent-router.js";
|
|
@@ -40,10 +42,25 @@ export async function createAgentRuntime(config) {
|
|
|
40
42
|
};
|
|
41
43
|
const stickyFlows = stickySetFromIntents(config.intents);
|
|
42
44
|
const menuMap = config.menuMap ?? {};
|
|
43
|
-
const
|
|
45
|
+
const llm = config.llm ?? llmConfigFromEnv();
|
|
46
|
+
const created = createModels(llm);
|
|
44
47
|
const chat = config.models?.chat ?? created.chat;
|
|
45
48
|
const intentRouterModel = config.models?.intentRouter ?? created.intentRouter;
|
|
46
49
|
const embeddings = config.models?.embeddings ?? created.embeddings;
|
|
50
|
+
const fromMap = config.toolOutputMap
|
|
51
|
+
? toolOutputMapToExtractors(config.toolOutputMap)
|
|
52
|
+
: null;
|
|
53
|
+
const toolExtractors = config.toolExtractors ?? fromMap?.toolExtractors;
|
|
54
|
+
const initialToolOutputs = config.initialToolOutputs ?? fromMap?.initialToolOutputs;
|
|
55
|
+
const completeOn = config.completeOn ??
|
|
56
|
+
(config.toolOutputMap ? Object.keys(config.toolOutputMap) : undefined);
|
|
57
|
+
const finalizeFlow = config.finalizeFlow ??
|
|
58
|
+
(completeOn?.length
|
|
59
|
+
? createCompleteOnFinalize({
|
|
60
|
+
completeOn,
|
|
61
|
+
toolOutputMap: config.toolOutputMap,
|
|
62
|
+
})
|
|
63
|
+
: undefined);
|
|
47
64
|
// Redis client when redisUrl is set (flow state + optional answer cache)
|
|
48
65
|
const redis = config.redisUrl
|
|
49
66
|
? createRedis(config.redisUrl)
|
|
@@ -91,12 +108,14 @@ export async function createAgentRuntime(config) {
|
|
|
91
108
|
classifyIntentWithLlm: intentRouter.classifyIntentWithLlm,
|
|
92
109
|
mergeIntentResults: intentRouter.mergeIntentResults,
|
|
93
110
|
chatCache,
|
|
94
|
-
finalizeFlow
|
|
111
|
+
finalizeFlow,
|
|
95
112
|
thresholds: config.thresholds,
|
|
96
113
|
});
|
|
97
114
|
const extractToolOutputs = config.extractToolOutputs ??
|
|
98
|
-
(
|
|
99
|
-
? createToolOutputExtractor(
|
|
115
|
+
(toolExtractors
|
|
116
|
+
? createToolOutputExtractor(toolExtractors, initialToolOutputs, {
|
|
117
|
+
includeUnknown: config.includeUnknownToolOutputs ?? false,
|
|
118
|
+
})
|
|
100
119
|
: extractRawToolOutputs);
|
|
101
120
|
const buildSystemPrompt = config.buildSystemPrompt ??
|
|
102
121
|
((ctx) => {
|
|
@@ -190,6 +209,13 @@ export async function createAgentRuntime(config) {
|
|
|
190
209
|
await redis?.disconnect();
|
|
191
210
|
},
|
|
192
211
|
clearFlow: chatCache.clearChatCacheFlowState,
|
|
212
|
+
clearThread: async (threadId) => {
|
|
213
|
+
const saver = agentFactory.checkpointer;
|
|
214
|
+
if (typeof saver.deleteThread === "function") {
|
|
215
|
+
await saver.deleteThread(threadId);
|
|
216
|
+
}
|
|
217
|
+
await chatCache.clearChatCacheFlowState(threadId);
|
|
218
|
+
},
|
|
193
219
|
getCachedAnswer: chatCache.getCachedAnswer,
|
|
194
220
|
setCachedAnswer: chatCache.setCachedAnswer,
|
|
195
221
|
invalidateIntentEmbeddings: intentEmbeddings.invalidate,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LlmConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build LlmConfig from process.env (Xel / recharge defaults).
|
|
4
|
+
*
|
|
5
|
+
* Env knobs:
|
|
6
|
+
* - LLM_PROVIDER / EMBEDDINGS_PROVIDER — ollama | openai
|
|
7
|
+
* - OLLAMA_MODEL / OPENAI_MODEL
|
|
8
|
+
* - INTENT_ROUTER_MODEL / OPENAI_INTENT_ROUTER_MODEL
|
|
9
|
+
* - OLLAMA_EMBEDDINGS_MODEL / OPENAI_EMBEDDINGS_MODEL
|
|
10
|
+
* - OLLAMA_BASE_URL / OPENAI_API_KEY
|
|
11
|
+
*/
|
|
12
|
+
export declare function llmConfigFromEnv(env?: NodeJS.ProcessEnv): LlmConfig;
|
|
13
|
+
//# sourceMappingURL=env-llm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-llm.d.ts","sourceRoot":"","sources":["../src/env-llm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,YAAY,CAAC;AAezD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,SAAS,CA6BX"}
|
package/dist/env-llm.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const asProvider = (value, fallback) => {
|
|
2
|
+
const normalized = value?.trim().toLowerCase();
|
|
3
|
+
if (normalized === "openai" ||
|
|
4
|
+
normalized === "gpt" ||
|
|
5
|
+
normalized === "chatgpt") {
|
|
6
|
+
return "openai";
|
|
7
|
+
}
|
|
8
|
+
if (normalized === "ollama")
|
|
9
|
+
return "ollama";
|
|
10
|
+
return fallback;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Build LlmConfig from process.env (Xel / recharge defaults).
|
|
14
|
+
*
|
|
15
|
+
* Env knobs:
|
|
16
|
+
* - LLM_PROVIDER / EMBEDDINGS_PROVIDER — ollama | openai
|
|
17
|
+
* - OLLAMA_MODEL / OPENAI_MODEL
|
|
18
|
+
* - INTENT_ROUTER_MODEL / OPENAI_INTENT_ROUTER_MODEL
|
|
19
|
+
* - OLLAMA_EMBEDDINGS_MODEL / OPENAI_EMBEDDINGS_MODEL
|
|
20
|
+
* - OLLAMA_BASE_URL / OPENAI_API_KEY
|
|
21
|
+
*/
|
|
22
|
+
export function llmConfigFromEnv(env = process.env) {
|
|
23
|
+
const provider = asProvider(env.LLM_PROVIDER, "ollama");
|
|
24
|
+
const embeddingsProvider = asProvider(env.EMBEDDINGS_PROVIDER ?? env.LLM_PROVIDER, provider);
|
|
25
|
+
return {
|
|
26
|
+
provider,
|
|
27
|
+
embeddingsProvider,
|
|
28
|
+
model: provider === "openai"
|
|
29
|
+
? (env.OPENAI_MODEL ?? "gpt-4o-mini")
|
|
30
|
+
: (env.OLLAMA_MODEL ?? "qwen2.5:7b"),
|
|
31
|
+
intentRouterModel: provider === "openai"
|
|
32
|
+
? (env.OPENAI_INTENT_ROUTER_MODEL ??
|
|
33
|
+
env.OPENAI_MODEL ??
|
|
34
|
+
"gpt-4o-mini")
|
|
35
|
+
: (env.INTENT_ROUTER_MODEL ??
|
|
36
|
+
env.OLLAMA_INTENT_ROUTER_MODEL ??
|
|
37
|
+
"qwen2.5:7b"),
|
|
38
|
+
embeddingsModel: embeddingsProvider === "openai"
|
|
39
|
+
? (env.OPENAI_EMBEDDINGS_MODEL ?? "text-embedding-3-small")
|
|
40
|
+
: (env.OLLAMA_EMBEDDINGS_MODEL ?? "mxbai-embed-large:latest"),
|
|
41
|
+
baseUrl: env.OLLAMA_BASE_URL,
|
|
42
|
+
apiKey: env.OPENAI_API_KEY,
|
|
43
|
+
};
|
|
44
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export { createAgentRuntime, type AgentRuntime } from "./create-runtime.js";
|
|
2
2
|
export { createModels } from "./llm.js";
|
|
3
|
+
export { llmConfigFromEnv } from "./env-llm.js";
|
|
3
4
|
export { createRedis } from "./redis.js";
|
|
4
5
|
export { extractRawToolOutputs, extractToolCallArgs, getToolCallsFromMessages, createToolOutputExtractor, } from "./services/extract.js";
|
|
6
|
+
export { toolOutputMapToExtractors, createCompleteOnFinalize, } from "./services/simple-config.js";
|
|
5
7
|
export { isWizardInput } from "./services/flow-router.js";
|
|
6
8
|
export { getLastMessageContent } from "./utils/message.js";
|
|
7
9
|
export { normalize } from "./utils/normalize.js";
|
|
8
|
-
export type { AgentRuntimeConfig, CacheConfig, ChatFlowState, DetectedIntentResult, FinalizeFlowInput, FinalizeFlowResult, FlowResolution, FlowState, IntentBinding, IntentDefinition, IntentRegistry, InvokeInput, InvokeResult, LlmConfig, LlmIntentResult, LlmProvider, PromptContext, ToolCall, ToolExtractor, ToolExtractorMap, TracingConfig, } from "./types.js";
|
|
10
|
+
export type { AgentRuntimeConfig, CacheConfig, ChatFlowState, DetectedIntentResult, FinalizeFlowInput, FinalizeFlowResult, FlowResolution, FlowState, IntentBinding, IntentDefinition, IntentRegistry, InvokeInput, InvokeResult, LlmConfig, LlmIntentResult, LlmProvider, PromptContext, ToolCall, ToolExtractor, ToolExtractorMap, ToolOutputMap, TracingConfig, } from "./types.js";
|
|
9
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,SAAS,EACT,eAAe,EACf,WAAW,EACX,aAAa,EACb,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,SAAS,EACT,eAAe,EACf,WAAW,EACX,aAAa,EACb,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { createAgentRuntime } from "./create-runtime.js";
|
|
2
2
|
export { createModels } from "./llm.js";
|
|
3
|
+
export { llmConfigFromEnv } from "./env-llm.js";
|
|
3
4
|
export { createRedis } from "./redis.js";
|
|
4
5
|
export { extractRawToolOutputs, extractToolCallArgs, getToolCallsFromMessages, createToolOutputExtractor, } from "./services/extract.js";
|
|
6
|
+
export { toolOutputMapToExtractors, createCompleteOnFinalize, } from "./services/simple-config.js";
|
|
5
7
|
export { isWizardInput } from "./services/flow-router.js";
|
|
6
8
|
export { getLastMessageContent } from "./utils/message.js";
|
|
7
9
|
export { normalize } from "./utils/normalize.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/services/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,YAAY;+
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/services/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,YAAY;+CAWV,MAAM;kDAwCT,OAAO,EAAE,KAAG,MAAM;gDAkB3D,MAAM,KACf,OAAO,CAAC,MAAM,CAAC;EAUnB"}
|
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
export function createConversationService(agentFactory) {
|
|
2
|
+
// Keep intent-router prompts small (matches Xel-agent defaults).
|
|
3
|
+
const AGENT_HISTORY_LIMIT = 4;
|
|
4
|
+
const INTENT_ROUTER_HISTORY_LIMIT = 3;
|
|
5
|
+
const INTENT_ROUTER_MESSAGE_CHAR_LIMIT = 200;
|
|
6
|
+
const isHumanOrAiMessage = (message) => {
|
|
7
|
+
const type = message._getType?.() ?? message.type ?? "";
|
|
8
|
+
return type === "human" || type === "ai";
|
|
9
|
+
};
|
|
2
10
|
const getManagedConversationMessages = async (threadId) => {
|
|
3
11
|
const state = await agentFactory.getAgentState(threadId);
|
|
4
12
|
const messages = state.values.messages ?? [];
|
|
5
13
|
return messages
|
|
6
14
|
.filter((message) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
15
|
+
if (!isHumanOrAiMessage(message))
|
|
16
|
+
return false;
|
|
17
|
+
const content = String(message?.content ?? "")
|
|
18
|
+
.toLowerCase();
|
|
19
|
+
return !(content.includes("tool failed") ||
|
|
20
|
+
content.includes("error") ||
|
|
21
|
+
content.includes("undefined"));
|
|
11
22
|
})
|
|
12
|
-
.slice(-
|
|
23
|
+
.slice(-AGENT_HISTORY_LIMIT);
|
|
13
24
|
};
|
|
14
25
|
const getMessageRole = (message) => {
|
|
15
26
|
const type = message._getType?.() ?? message.type ?? "";
|
|
@@ -17,7 +28,8 @@ export function createConversationService(agentFactory) {
|
|
|
17
28
|
return "User";
|
|
18
29
|
if (type === "ai")
|
|
19
30
|
return "Assistant";
|
|
20
|
-
|
|
31
|
+
// Should not happen due to isHumanOrAiMessage filter.
|
|
32
|
+
return "User";
|
|
21
33
|
};
|
|
22
34
|
const getMessageText = (message) => {
|
|
23
35
|
const content = message.content;
|
|
@@ -35,10 +47,10 @@ export function createConversationService(agentFactory) {
|
|
|
35
47
|
if (messages.length === 0)
|
|
36
48
|
return "(no prior messages)";
|
|
37
49
|
return messages
|
|
38
|
-
.slice(-
|
|
50
|
+
.slice(-INTENT_ROUTER_HISTORY_LIMIT)
|
|
39
51
|
.map((message) => {
|
|
40
52
|
const role = getMessageRole(message);
|
|
41
|
-
const text = getMessageText(message).slice(0,
|
|
53
|
+
const text = getMessageText(message).slice(0, INTENT_ROUTER_MESSAGE_CHAR_LIMIT);
|
|
42
54
|
return text ? `${role}: ${text}` : null;
|
|
43
55
|
})
|
|
44
56
|
.filter(Boolean)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-router.d.ts","sourceRoot":"","sources":["../../src/services/flow-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAOjD,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,OAI/C,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,kBAAkB,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC,CAAC;IAC3E,sBAAsB,EAAE,CACtB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,KAC9C,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACrC,qBAAqB,EAAE,CAAC,KAAK,EAAE;QAC7B,OAAO,EAAE,MAAM,CAAC;QAChB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAC/B,kBAAkB,EAAE,CAClB,YAAY,EAAE,oBAAoB,EAClC,SAAS,EAAE,eAAe,KACvB,oBAAoB,GAAG;QAAE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;IAClE,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,CAAC,EAAE,CACb,KAAK,EAAE,iBAAiB,KACrB,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtD,UAAU,CAAC,EAAE;QACX,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;sFAoBI;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,EAAE,aAAa,GAAG,IAAI,CAAC;QACtC,mBAAmB,EAAE,MAAM,CAAC;KAC7B,KAAG,OAAO,CAAC,cAAc,CAAC;+
|
|
1
|
+
{"version":3,"file":"flow-router.d.ts","sourceRoot":"","sources":["../../src/services/flow-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAOjD,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,OAI/C,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,kBAAkB,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC,CAAC;IAC3E,sBAAsB,EAAE,CACtB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,KAC9C,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACrC,qBAAqB,EAAE,CAAC,KAAK,EAAE;QAC7B,OAAO,EAAE,MAAM,CAAC;QAChB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAC/B,kBAAkB,EAAE,CAClB,YAAY,EAAE,oBAAoB,EAClC,SAAS,EAAE,eAAe,KACvB,oBAAoB,GAAG;QAAE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;IAClE,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,CAAC,EAAE,CACb,KAAK,EAAE,iBAAiB,KACrB,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtD,UAAU,CAAC,EAAE;QACX,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;sFAoBI;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,EAAE,aAAa,GAAG,IAAI,CAAC;QACtC,mBAAmB,EAAE,MAAM,CAAC;KAC7B,KAAG,OAAO,CAAC,cAAc,CAAC;+BA4KlB,iBAAiB,KACvB,OAAO,CAAC,kBAAkB,CAAC;EAkB/B;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAE7E;AAED,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -31,6 +31,18 @@ export function createFlowRouter(options) {
|
|
|
31
31
|
const cachedIntent = cachedFlowState?.intent
|
|
32
32
|
? options.normalizeIntent(cachedFlowState.intent)
|
|
33
33
|
: null;
|
|
34
|
+
// Token reduction: when we already know a sticky wizard intent,
|
|
35
|
+
// and the user replies with wizard-like input, skip router LLM.
|
|
36
|
+
// (Xel-agent equivalent: shouldSkipIntentClassification()).
|
|
37
|
+
if (cachedIntent !== null &&
|
|
38
|
+
options.stickyFlows.has(cachedIntent) &&
|
|
39
|
+
isWizardInput(message)) {
|
|
40
|
+
return {
|
|
41
|
+
messageIntent: { intent: cachedIntent, score: 1 },
|
|
42
|
+
flow: { active: true, intent: cachedIntent },
|
|
43
|
+
promptIntent: cachedIntent,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
34
46
|
const menuIntent = resolveGreetingMenuSelection(message, cachedIntent);
|
|
35
47
|
if (menuIntent) {
|
|
36
48
|
const sticky = options.stickyFlows.has(menuIntent);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ToolExtractorMap, ToolOutputMap } from "../types.js";
|
|
2
|
+
export type { ToolOutputMap };
|
|
3
|
+
export declare function resolveToolOutputKey(toolName: string, map: ToolOutputMap): string;
|
|
4
|
+
/** Build first-wins extractors + initial seed from a simple map. */
|
|
5
|
+
export declare function toolOutputMapToExtractors(map: ToolOutputMap): {
|
|
6
|
+
toolExtractors: ToolExtractorMap;
|
|
7
|
+
initialToolOutputs: () => Record<string, unknown>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Default finalize: complete sticky flow when any listed tool produced output.
|
|
11
|
+
* `completeOn` is tool names (keys of toolOutputMap / LangChain tool name).
|
|
12
|
+
*/
|
|
13
|
+
export declare function createCompleteOnFinalize(options: {
|
|
14
|
+
completeOn: string[];
|
|
15
|
+
toolOutputMap?: ToolOutputMap;
|
|
16
|
+
}): ({ flow, toolOutputs, }: {
|
|
17
|
+
threadId: string;
|
|
18
|
+
promptIntent: string;
|
|
19
|
+
flow: {
|
|
20
|
+
active: boolean;
|
|
21
|
+
intent: string | null;
|
|
22
|
+
};
|
|
23
|
+
toolOutputs: Record<string, unknown>;
|
|
24
|
+
}) => {
|
|
25
|
+
flowCompleted: boolean;
|
|
26
|
+
flow: {
|
|
27
|
+
active: boolean;
|
|
28
|
+
intent: string | null;
|
|
29
|
+
};
|
|
30
|
+
extras: Record<string, unknown>;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=simple-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-config.d.ts","sourceRoot":"","sources":["../../src/services/simple-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE,YAAY,EAAE,aAAa,EAAE,CAAC;AAE9B,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,aAAa,GACjB,MAAM,CAIR;AAED,oEAAoE;AACpE,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,aAAa,GAAG;IAC7D,cAAc,EAAE,gBAAgB,CAAC;IACjC,kBAAkB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnD,CAkCA;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IAChD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B,IAGS,wBAGL;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACjD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;;;;;;;EA0BF"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export function resolveToolOutputKey(toolName, map) {
|
|
2
|
+
const entry = map[toolName];
|
|
3
|
+
if (!entry)
|
|
4
|
+
return toolName;
|
|
5
|
+
return typeof entry === "string" ? entry : entry.as;
|
|
6
|
+
}
|
|
7
|
+
/** Build first-wins extractors + initial seed from a simple map. */
|
|
8
|
+
export function toolOutputMapToExtractors(map) {
|
|
9
|
+
const toolExtractors = {};
|
|
10
|
+
const initial = {};
|
|
11
|
+
for (const [toolName, entry] of Object.entries(map)) {
|
|
12
|
+
if (typeof entry === "string") {
|
|
13
|
+
toolExtractors[toolName] = (args, acc) => {
|
|
14
|
+
if (acc[entry] !== undefined)
|
|
15
|
+
return;
|
|
16
|
+
acc[entry] = args;
|
|
17
|
+
};
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const key = entry.as;
|
|
21
|
+
if (entry.initial !== undefined && !(key in initial)) {
|
|
22
|
+
initial[key] = entry.initial;
|
|
23
|
+
}
|
|
24
|
+
toolExtractors[toolName] = (args, acc) => {
|
|
25
|
+
const current = acc[key];
|
|
26
|
+
if (Array.isArray(current) && current.length > 0)
|
|
27
|
+
return;
|
|
28
|
+
if (current !== undefined && !Array.isArray(current))
|
|
29
|
+
return;
|
|
30
|
+
acc[key] =
|
|
31
|
+
entry.from !== undefined
|
|
32
|
+
? (args[entry.from] ?? entry.initial ?? [])
|
|
33
|
+
: args;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
toolExtractors,
|
|
38
|
+
initialToolOutputs: () => ({ ...initial }),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Default finalize: complete sticky flow when any listed tool produced output.
|
|
43
|
+
* `completeOn` is tool names (keys of toolOutputMap / LangChain tool name).
|
|
44
|
+
*/
|
|
45
|
+
export function createCompleteOnFinalize(options) {
|
|
46
|
+
const { completeOn, toolOutputMap = {} } = options;
|
|
47
|
+
return ({ flow, toolOutputs, }) => {
|
|
48
|
+
const extras = {};
|
|
49
|
+
let flowCompleted = false;
|
|
50
|
+
for (const toolName of completeOn) {
|
|
51
|
+
const key = resolveToolOutputKey(toolName, toolOutputMap);
|
|
52
|
+
const value = toolOutputs[key];
|
|
53
|
+
const hit = Array.isArray(value)
|
|
54
|
+
? value.length > 0
|
|
55
|
+
: value !== undefined && value !== null;
|
|
56
|
+
if (hit) {
|
|
57
|
+
flowCompleted = true;
|
|
58
|
+
extras[key] = value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
flowCompleted,
|
|
63
|
+
flow: {
|
|
64
|
+
active: flow.active && !flowCompleted,
|
|
65
|
+
intent: flowCompleted ? null : flow.intent,
|
|
66
|
+
},
|
|
67
|
+
extras,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -2,6 +2,24 @@ import type { BaseChatModel } from "@langchain/core/language_models/chat_models"
|
|
|
2
2
|
import type { Embeddings } from "@langchain/core/embeddings";
|
|
3
3
|
import type { DynamicStructuredTool } from "@langchain/core/tools";
|
|
4
4
|
import type { BaseCheckpointSaver } from "@langchain/langgraph-checkpoint";
|
|
5
|
+
/**
|
|
6
|
+
* Simple tool → output key map.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* {
|
|
10
|
+
* create_campaign: "campaign",
|
|
11
|
+
* buy_airtime: "buyAirtime",
|
|
12
|
+
* propose_tickets: { as: "tickets", from: "tickets", initial: [] },
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
export type ToolOutputMap = Record<string, string | {
|
|
16
|
+
/** Key written onto toolOutputs / extras. */
|
|
17
|
+
as: string;
|
|
18
|
+
/** Nested field on tool args (e.g. args.tickets). */
|
|
19
|
+
from?: string;
|
|
20
|
+
/** Seed value when nothing extracted yet. */
|
|
21
|
+
initial?: unknown;
|
|
22
|
+
}>;
|
|
5
23
|
/** Intent catalog entry used for embedding routing + sticky-flow rules. */
|
|
6
24
|
export type IntentDefinition = {
|
|
7
25
|
name: string;
|
|
@@ -118,12 +136,19 @@ export type InvokeResult = {
|
|
|
118
136
|
};
|
|
119
137
|
export type AgentRuntimeConfig = {
|
|
120
138
|
redisUrl?: string;
|
|
121
|
-
|
|
139
|
+
/**
|
|
140
|
+
* LLM config. Omit to use `llmConfigFromEnv()` (OLLAMA_* / OPENAI_* env vars).
|
|
141
|
+
*/
|
|
142
|
+
llm?: LlmConfig;
|
|
122
143
|
/** Intent catalog for embeddings + sticky flags. */
|
|
123
144
|
intents: IntentDefinition[];
|
|
124
145
|
/** Per-intent prompt + tools factory. */
|
|
125
146
|
intentRegistry: IntentRegistry;
|
|
126
|
-
/**
|
|
147
|
+
/**
|
|
148
|
+
* Optional digit → intent routing (e.g. menu "1" → create_campaign).
|
|
149
|
+
* Prompt text alone cannot switch intent when the user types a number —
|
|
150
|
+
* keep this if you use a numbered menu. Safe to omit otherwise.
|
|
151
|
+
*/
|
|
127
152
|
menuMap?: Record<string, string>;
|
|
128
153
|
/** Map legacy/alias names onto catalog intents. */
|
|
129
154
|
intentAliases?: Record<string, string>;
|
|
@@ -133,19 +158,27 @@ export type AgentRuntimeConfig = {
|
|
|
133
158
|
/** Custom system prompt builder; default uses intentRegistry[intent].prompt. */
|
|
134
159
|
buildSystemPrompt?: (ctx: PromptContext) => string;
|
|
135
160
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
161
|
+
* Simple toolName → output key map (preferred).
|
|
162
|
+
* @example { create_campaign: "campaign", buy_airtime: "buyAirtime" }
|
|
163
|
+
*/
|
|
164
|
+
toolOutputMap?: ToolOutputMap;
|
|
165
|
+
/**
|
|
166
|
+
* Tool names that complete a sticky flow when they produce output.
|
|
167
|
+
* Library owns finalize logic — you only pass the list.
|
|
168
|
+
*/
|
|
169
|
+
completeOn?: string[];
|
|
170
|
+
/**
|
|
171
|
+
* Per-tool extractors (advanced). Prefer `toolOutputMap` instead.
|
|
138
172
|
*/
|
|
139
173
|
toolExtractors?: ToolExtractorMap;
|
|
140
174
|
/** Seed object for tool extractors (e.g. () => ({ tickets: [] })). */
|
|
141
175
|
initialToolOutputs?: () => Record<string, unknown>;
|
|
142
176
|
/** If true, unknown tool names are kept as raw args. Default false when using toolExtractors. */
|
|
143
177
|
includeUnknownToolOutputs?: boolean;
|
|
144
|
-
/** Full custom extractor. Overrides toolExtractors when provided. */
|
|
178
|
+
/** Full custom extractor. Overrides toolOutputMap / toolExtractors when provided. */
|
|
145
179
|
extractToolOutputs?: (messages: unknown[]) => Record<string, unknown>;
|
|
146
180
|
/**
|
|
147
|
-
*
|
|
148
|
-
* Default: never auto-complete (app must clear via finalize or clearFlow).
|
|
181
|
+
* Custom finalize. Prefer `completeOn` for the common case.
|
|
149
182
|
*/
|
|
150
183
|
finalizeFlow?: (input: FinalizeFlowInput) => FinalizeFlowResult | Promise<FinalizeFlowResult>;
|
|
151
184
|
/** Derive phone/session key for tools. Default: phoneKey ?? threadId. */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-agent-runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Reusable LangGraph agent runtime: intent routing, sticky flows, Redis checkpointer, optional answer cache",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"type": "module",
|
|
@@ -13,13 +13,15 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
|
-
"dist"
|
|
16
|
+
"dist",
|
|
17
|
+
"USAGE.md",
|
|
18
|
+
"README.md"
|
|
17
19
|
],
|
|
18
20
|
"scripts": {
|
|
19
21
|
"build": "tsc -p tsconfig.json",
|
|
20
22
|
"dev": "tsc -p tsconfig.json --watch",
|
|
21
23
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
22
|
-
"test": "tsx --test src
|
|
24
|
+
"test": "tsx --test src/services/extract.test.ts && tsx --test src/services/simple-config.test.ts",
|
|
23
25
|
"prepublishOnly": "pnpm build && pnpm test"
|
|
24
26
|
},
|
|
25
27
|
"publishConfig": {
|