llm-agent-runtime 0.1.6 → 0.1.17
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 +8 -2
- package/USAGE.md +528 -283
- package/dist/agent.d.ts +2 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +36 -4
- package/dist/create-runtime.d.ts +14 -4
- package/dist/create-runtime.d.ts.map +1 -1
- package/dist/create-runtime.js +108 -20
- package/dist/embeddings/xenova.d.ts +19 -0
- package/dist/embeddings/xenova.d.ts.map +1 -0
- package/dist/embeddings/xenova.js +69 -0
- package/dist/env-llm.d.ts +17 -4
- package/dist/env-llm.d.ts.map +1 -1
- package/dist/env-llm.js +66 -16
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +17 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/intents/define.d.ts +35 -0
- package/dist/intents/define.d.ts.map +1 -0
- package/dist/intents/define.js +52 -0
- package/dist/intents/general.d.ts +37 -0
- package/dist/intents/general.d.ts.map +1 -0
- package/dist/intents/general.js +67 -0
- package/dist/llm.d.ts +2 -2
- package/dist/llm.d.ts.map +1 -1
- package/dist/llm.js +45 -15
- package/dist/rag/index.d.ts +67 -0
- package/dist/rag/index.d.ts.map +1 -0
- package/dist/rag/index.js +140 -0
- package/dist/rag/loaders.d.ts +11 -0
- package/dist/rag/loaders.d.ts.map +1 -0
- package/dist/rag/loaders.js +80 -0
- package/dist/rag/sources.d.ts +29 -0
- package/dist/rag/sources.d.ts.map +1 -0
- package/dist/rag/sources.js +101 -0
- package/dist/services/intent-embeddings.d.ts.map +1 -1
- package/dist/services/intent-embeddings.js +5 -6
- package/dist/services/token-usage.d.ts +26 -0
- package/dist/services/token-usage.d.ts.map +1 -0
- package/dist/services/token-usage.js +63 -0
- package/dist/services/usage-store.d.ts +24 -0
- package/dist/services/usage-store.d.ts.map +1 -0
- package/dist/services/usage-store.js +92 -0
- package/dist/types.d.ts +47 -15
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type RagSourceKind = "pdf" | "docx" | "txt" | "unknown";
|
|
2
|
+
export type ResolvedRagSource = {
|
|
3
|
+
/** Original path or URL from config. */
|
|
4
|
+
source: string;
|
|
5
|
+
/** Local file path after download (URL) or as given (path). */
|
|
6
|
+
localPath: string;
|
|
7
|
+
kind: RagSourceKind;
|
|
8
|
+
/** True when we downloaded a remote file into a temp location. */
|
|
9
|
+
isTemp: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function isHttpUrl(value: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Collect RAG sources from env.
|
|
14
|
+
*
|
|
15
|
+
* Preferred:
|
|
16
|
+
* RAG_SOURCES=/path/a.pdf,https://cdn.example.com/b.docx
|
|
17
|
+
*
|
|
18
|
+
* Also accepted:
|
|
19
|
+
* RAG_PDF_PATH=/one.pdf
|
|
20
|
+
* RAG_PDF_PATHS=/a.pdf,/b.pdf
|
|
21
|
+
* RAG_DOC_URLS=https://.../a.pdf,https://.../b.docx
|
|
22
|
+
*/
|
|
23
|
+
export declare function ragSourcesFromEnv(env?: NodeJS.ProcessEnv): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a single source (local path or http(s) URL) to a local file.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveRagSource(source: string): Promise<ResolvedRagSource>;
|
|
28
|
+
export declare function resolveRagSources(sources: string[]): Promise<ResolvedRagSource[]>;
|
|
29
|
+
//# sourceMappingURL=sources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../src/rag/sources.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAE/D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,aAAa,CAAC;IACpB,kEAAkE;IAClE,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAUF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAiBV;AAwBD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC,CA6B5B;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAM9B"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
function detectKind(nameOrUrl) {
|
|
5
|
+
const lower = nameOrUrl.split("?")[0].toLowerCase();
|
|
6
|
+
if (lower.endsWith(".pdf"))
|
|
7
|
+
return "pdf";
|
|
8
|
+
if (lower.endsWith(".docx"))
|
|
9
|
+
return "docx";
|
|
10
|
+
if (lower.endsWith(".txt") || lower.endsWith(".md"))
|
|
11
|
+
return "txt";
|
|
12
|
+
return "unknown";
|
|
13
|
+
}
|
|
14
|
+
export function isHttpUrl(value) {
|
|
15
|
+
return /^https?:\/\//i.test(value.trim());
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Collect RAG sources from env.
|
|
19
|
+
*
|
|
20
|
+
* Preferred:
|
|
21
|
+
* RAG_SOURCES=/path/a.pdf,https://cdn.example.com/b.docx
|
|
22
|
+
*
|
|
23
|
+
* Also accepted:
|
|
24
|
+
* RAG_PDF_PATH=/one.pdf
|
|
25
|
+
* RAG_PDF_PATHS=/a.pdf,/b.pdf
|
|
26
|
+
* RAG_DOC_URLS=https://.../a.pdf,https://.../b.docx
|
|
27
|
+
*/
|
|
28
|
+
export function ragSourcesFromEnv(env = process.env) {
|
|
29
|
+
const parts = [];
|
|
30
|
+
const pushCsv = (raw) => {
|
|
31
|
+
if (!raw?.trim())
|
|
32
|
+
return;
|
|
33
|
+
for (const item of raw.split(",")) {
|
|
34
|
+
const s = item.trim();
|
|
35
|
+
if (s)
|
|
36
|
+
parts.push(s);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
pushCsv(env.RAG_SOURCES);
|
|
40
|
+
pushCsv(env.RAG_PDF_PATH);
|
|
41
|
+
pushCsv(env.RAG_PDF_PATHS);
|
|
42
|
+
pushCsv(env.RAG_DOC_URLS);
|
|
43
|
+
return [...new Set(parts)];
|
|
44
|
+
}
|
|
45
|
+
async function downloadToTemp(url) {
|
|
46
|
+
const res = await fetch(url);
|
|
47
|
+
if (!res.ok) {
|
|
48
|
+
throw new Error(`Failed to download RAG source (${res.status}): ${url}`);
|
|
49
|
+
}
|
|
50
|
+
const kind = detectKind(url);
|
|
51
|
+
const ext = kind === "pdf"
|
|
52
|
+
? ".pdf"
|
|
53
|
+
: kind === "docx"
|
|
54
|
+
? ".docx"
|
|
55
|
+
: kind === "txt"
|
|
56
|
+
? ".txt"
|
|
57
|
+
: path.extname(new URL(url).pathname) || ".bin";
|
|
58
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "llm-agent-rag-"));
|
|
59
|
+
const localPath = path.join(dir, `doc${ext}`);
|
|
60
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
61
|
+
await fs.writeFile(localPath, buf);
|
|
62
|
+
return localPath;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Resolve a single source (local path or http(s) URL) to a local file.
|
|
66
|
+
*/
|
|
67
|
+
export async function resolveRagSource(source) {
|
|
68
|
+
const trimmed = source.trim();
|
|
69
|
+
if (!trimmed) {
|
|
70
|
+
throw new Error("Empty RAG source");
|
|
71
|
+
}
|
|
72
|
+
if (isHttpUrl(trimmed)) {
|
|
73
|
+
const localPath = await downloadToTemp(trimmed);
|
|
74
|
+
return {
|
|
75
|
+
source: trimmed,
|
|
76
|
+
localPath,
|
|
77
|
+
kind: detectKind(trimmed),
|
|
78
|
+
isTemp: true,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const localPath = path.resolve(trimmed);
|
|
82
|
+
try {
|
|
83
|
+
await fs.access(localPath);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
throw new Error(`RAG file not found: ${localPath}`);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
source: trimmed,
|
|
90
|
+
localPath,
|
|
91
|
+
kind: detectKind(localPath),
|
|
92
|
+
isTemp: false,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export async function resolveRagSources(sources) {
|
|
96
|
+
const out = [];
|
|
97
|
+
for (const source of sources) {
|
|
98
|
+
out.push(await resolveRagSource(source));
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent-embeddings.d.ts","sourceRoot":"","sources":["../../src/services/intent-embeddings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAgB1E,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE;IAC9C,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CAC7C;
|
|
1
|
+
{"version":3,"file":"intent-embeddings.d.ts","sourceRoot":"","sources":["../../src/services/intent-embeddings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAgB1E,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE;IAC9C,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CAC7C;8BAqBsC,OAAO,CAAC,cAAc,EAAE,CAAC;sCAQnD,MAAM,mBACE,cAAc,EAAE,KAChC,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAchC,uDAAuD;;EAK1D"}
|
|
@@ -12,13 +12,12 @@ function cosineSimilarity(a, b) {
|
|
|
12
12
|
export function createIntentEmbeddings(options) {
|
|
13
13
|
let cached = null;
|
|
14
14
|
const build = async () => {
|
|
15
|
-
|
|
16
|
-
for (const intent of options.intents) {
|
|
15
|
+
return Promise.all(options.intents.map(async (intent) => {
|
|
17
16
|
const embeddings = await Promise.all(intent.examples.map((ex) => options.embeddings.embedQuery(ex)));
|
|
18
|
-
const avgEmbedding = embeddings[0].map((_, i) => embeddings.reduce((sum, emb) => sum + emb[i], 0) /
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
const avgEmbedding = embeddings[0].map((_, i) => embeddings.reduce((sum, emb) => sum + emb[i], 0) /
|
|
18
|
+
embeddings.length);
|
|
19
|
+
return { name: intent.name, embedding: avgEmbedding };
|
|
20
|
+
}));
|
|
22
21
|
};
|
|
23
22
|
const getEmbeddedIntents = async () => {
|
|
24
23
|
if (!cached) {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type TokenCounts = {
|
|
2
|
+
inputTokens: number;
|
|
3
|
+
outputTokens: number;
|
|
4
|
+
totalTokens: number;
|
|
5
|
+
};
|
|
6
|
+
export type FlowTokenUsage = TokenCounts & {
|
|
7
|
+
/** Sticky / active flow intent, or null when not in a sticky flow. */
|
|
8
|
+
intent: string | null;
|
|
9
|
+
};
|
|
10
|
+
/** Returned on every `invoke`. */
|
|
11
|
+
export type TokenUsageReport = {
|
|
12
|
+
/** Tokens for this invoke only (agent turn messages). */
|
|
13
|
+
turn: TokenCounts;
|
|
14
|
+
/** Accumulated tokens for the current sticky flow (falls back to turn). */
|
|
15
|
+
flow: FlowTokenUsage;
|
|
16
|
+
/** Accumulated tokens for the whole thread/session. */
|
|
17
|
+
total: TokenCounts;
|
|
18
|
+
};
|
|
19
|
+
export declare function emptyTokenCounts(): TokenCounts;
|
|
20
|
+
export declare function addTokenCounts(a: TokenCounts, b: TokenCounts): TokenCounts;
|
|
21
|
+
/**
|
|
22
|
+
* Sum token usage from LangChain AI messages
|
|
23
|
+
* (`usage_metadata` and/or `response_metadata.tokenUsage` / `usage`).
|
|
24
|
+
*/
|
|
25
|
+
export declare function extractTokenUsageFromMessages(messages: unknown[]): TokenCounts;
|
|
26
|
+
//# sourceMappingURL=token-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-usage.d.ts","sourceRoot":"","sources":["../../src/services/token-usage.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG;IACzC,sEAAsE;IACtE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,kCAAkC;AAClC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,yDAAyD;IACzD,IAAI,EAAE,WAAW,CAAC;IAClB,2EAA2E;IAC3E,IAAI,EAAE,cAAc,CAAC;IACrB,uDAAuD;IACvD,KAAK,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF,wBAAgB,gBAAgB,IAAI,WAAW,CAE9C;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,GAAG,WAAW,CAM1E;AAiCD;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,WAAW,CA0B9E"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export function emptyTokenCounts() {
|
|
2
|
+
return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
3
|
+
}
|
|
4
|
+
export function addTokenCounts(a, b) {
|
|
5
|
+
return {
|
|
6
|
+
inputTokens: a.inputTokens + b.inputTokens,
|
|
7
|
+
outputTokens: a.outputTokens + b.outputTokens,
|
|
8
|
+
totalTokens: a.totalTokens + b.totalTokens,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function readUsageBlob(raw) {
|
|
12
|
+
if (!raw || typeof raw !== "object")
|
|
13
|
+
return null;
|
|
14
|
+
const u = raw;
|
|
15
|
+
const input = numberOrZero(u.input_tokens) ||
|
|
16
|
+
numberOrZero(u.inputTokens) ||
|
|
17
|
+
numberOrZero(u.prompt_tokens) ||
|
|
18
|
+
numberOrZero(u.promptTokens);
|
|
19
|
+
const output = numberOrZero(u.output_tokens) ||
|
|
20
|
+
numberOrZero(u.outputTokens) ||
|
|
21
|
+
numberOrZero(u.completion_tokens) ||
|
|
22
|
+
numberOrZero(u.completionTokens);
|
|
23
|
+
const total = numberOrZero(u.total_tokens) ||
|
|
24
|
+
numberOrZero(u.totalTokens) ||
|
|
25
|
+
input + output;
|
|
26
|
+
if (!input && !output && !total)
|
|
27
|
+
return null;
|
|
28
|
+
return {
|
|
29
|
+
inputTokens: input,
|
|
30
|
+
outputTokens: output,
|
|
31
|
+
totalTokens: total || input + output,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function numberOrZero(v) {
|
|
35
|
+
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Sum token usage from LangChain AI messages
|
|
39
|
+
* (`usage_metadata` and/or `response_metadata.tokenUsage` / `usage`).
|
|
40
|
+
*/
|
|
41
|
+
export function extractTokenUsageFromMessages(messages) {
|
|
42
|
+
let sum = emptyTokenCounts();
|
|
43
|
+
for (const msg of messages) {
|
|
44
|
+
if (!msg || typeof msg !== "object")
|
|
45
|
+
continue;
|
|
46
|
+
const m = msg;
|
|
47
|
+
const fromUsageMeta = readUsageBlob(m.usage_metadata);
|
|
48
|
+
if (fromUsageMeta) {
|
|
49
|
+
sum = addTokenCounts(sum, fromUsageMeta);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const responseMeta = m.response_metadata;
|
|
53
|
+
if (responseMeta) {
|
|
54
|
+
const fromTokenUsage = readUsageBlob(responseMeta.tokenUsage) ||
|
|
55
|
+
readUsageBlob(responseMeta.usage) ||
|
|
56
|
+
readUsageBlob(responseMeta.token_usage);
|
|
57
|
+
if (fromTokenUsage) {
|
|
58
|
+
sum = addTokenCounts(sum, fromTokenUsage);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return sum;
|
|
63
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { RedisClientType } from "redis";
|
|
2
|
+
import { type TokenCounts } from "./token-usage.js";
|
|
3
|
+
/**
|
|
4
|
+
* Persist per-thread and per-flow token totals in Redis (or memory fallback).
|
|
5
|
+
*/
|
|
6
|
+
export declare function createUsageStore(options: {
|
|
7
|
+
redis?: RedisClientType;
|
|
8
|
+
ttlSeconds?: number;
|
|
9
|
+
}): {
|
|
10
|
+
getThreadUsage: (threadId: string) => Promise<TokenCounts>;
|
|
11
|
+
getFlowUsage: (threadId: string, intent: string | null) => Promise<TokenCounts>;
|
|
12
|
+
recordTurn: (options: {
|
|
13
|
+
threadId: string;
|
|
14
|
+
flowIntent: string | null;
|
|
15
|
+
turn: TokenCounts;
|
|
16
|
+
}) => Promise<{
|
|
17
|
+
total: TokenCounts;
|
|
18
|
+
flow: TokenCounts;
|
|
19
|
+
}>;
|
|
20
|
+
clearFlowUsage: (threadId: string, intent: string) => Promise<void>;
|
|
21
|
+
clearThreadUsage: (threadId: string) => Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
export type UsageStore = ReturnType<typeof createUsageStore>;
|
|
24
|
+
//# sourceMappingURL=usage-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-store.d.ts","sourceRoot":"","sources":["../../src/services/usage-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAM1B;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;+BA0CmC,MAAM;6BAER,MAAM,UAAU,MAAM,GAAG,IAAI;0BAK1B;QACjC,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,IAAI,EAAE,WAAW,CAAC;KACnB;;;;+BAcuC,MAAM,UAAU,MAAM;iCAMpB,MAAM;EA2BjD;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { addTokenCounts, emptyTokenCounts, } from "./token-usage.js";
|
|
2
|
+
const DEFAULT_TTL = 60 * 60 * 24 * 7; // 7 days
|
|
3
|
+
/**
|
|
4
|
+
* Persist per-thread and per-flow token totals in Redis (or memory fallback).
|
|
5
|
+
*/
|
|
6
|
+
export function createUsageStore(options) {
|
|
7
|
+
const redis = options.redis;
|
|
8
|
+
const ttl = options.ttlSeconds ?? DEFAULT_TTL;
|
|
9
|
+
const memory = new Map();
|
|
10
|
+
const threadKey = (threadId) => `usage:thread:${threadId}`;
|
|
11
|
+
const flowKey = (threadId, intent) => `usage:flow:${threadId}:${intent}`;
|
|
12
|
+
const read = async (key) => {
|
|
13
|
+
if (redis) {
|
|
14
|
+
const raw = await redis.get(key);
|
|
15
|
+
if (!raw)
|
|
16
|
+
return emptyTokenCounts();
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(raw);
|
|
19
|
+
return {
|
|
20
|
+
inputTokens: parsed.inputTokens ?? 0,
|
|
21
|
+
outputTokens: parsed.outputTokens ?? 0,
|
|
22
|
+
totalTokens: parsed.totalTokens ?? 0,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return emptyTokenCounts();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return memory.get(key) ?? emptyTokenCounts();
|
|
30
|
+
};
|
|
31
|
+
const write = async (key, counts) => {
|
|
32
|
+
const payload = { ...counts, updatedAt: Date.now() };
|
|
33
|
+
if (redis) {
|
|
34
|
+
await redis.set(key, JSON.stringify(payload), { EX: ttl });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
memory.set(key, payload);
|
|
38
|
+
};
|
|
39
|
+
const addToKey = async (key, delta) => {
|
|
40
|
+
const next = addTokenCounts(await read(key), delta);
|
|
41
|
+
await write(key, next);
|
|
42
|
+
return next;
|
|
43
|
+
};
|
|
44
|
+
const getThreadUsage = (threadId) => read(threadKey(threadId));
|
|
45
|
+
const getFlowUsage = (threadId, intent) => {
|
|
46
|
+
if (!intent)
|
|
47
|
+
return Promise.resolve(emptyTokenCounts());
|
|
48
|
+
return read(flowKey(threadId, intent));
|
|
49
|
+
};
|
|
50
|
+
const recordTurn = async (options) => {
|
|
51
|
+
const total = await addToKey(threadKey(options.threadId), options.turn);
|
|
52
|
+
let flow = emptyTokenCounts();
|
|
53
|
+
if (options.flowIntent) {
|
|
54
|
+
flow = await addToKey(flowKey(options.threadId, options.flowIntent), options.turn);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
flow = options.turn;
|
|
58
|
+
}
|
|
59
|
+
return { total, flow };
|
|
60
|
+
};
|
|
61
|
+
const clearFlowUsage = async (threadId, intent) => {
|
|
62
|
+
const key = flowKey(threadId, intent);
|
|
63
|
+
if (redis)
|
|
64
|
+
await redis.del(key);
|
|
65
|
+
else
|
|
66
|
+
memory.delete(key);
|
|
67
|
+
};
|
|
68
|
+
const clearThreadUsage = async (threadId) => {
|
|
69
|
+
if (redis) {
|
|
70
|
+
const pattern = `usage:flow:${threadId}:*`;
|
|
71
|
+
// SCAN + DEL for flow keys; also delete thread total
|
|
72
|
+
await redis.del(threadKey(threadId));
|
|
73
|
+
for await (const key of redis.scanIterator({ MATCH: pattern, COUNT: 50 })) {
|
|
74
|
+
await redis.del(key);
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
for (const key of [...memory.keys()]) {
|
|
79
|
+
if (key === threadKey(threadId) ||
|
|
80
|
+
key.startsWith(`usage:flow:${threadId}:`)) {
|
|
81
|
+
memory.delete(key);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
return {
|
|
86
|
+
getThreadUsage,
|
|
87
|
+
getFlowUsage,
|
|
88
|
+
recordTurn,
|
|
89
|
+
clearFlowUsage,
|
|
90
|
+
clearThreadUsage,
|
|
91
|
+
};
|
|
92
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ 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
|
+
import type { TokenUsageReport } from "./services/token-usage.js";
|
|
6
|
+
export type { TokenCounts, FlowTokenUsage, TokenUsageReport } from "./services/token-usage.js";
|
|
5
7
|
/**
|
|
6
8
|
* Simple tool → output key map.
|
|
7
9
|
*
|
|
@@ -31,20 +33,24 @@ export type IntentDefinition = {
|
|
|
31
33
|
/** Fast-path regex: if message matches, skip LLM/embeddings and use this intent directly. */
|
|
32
34
|
regex?: RegExp;
|
|
33
35
|
};
|
|
34
|
-
/** Context passed into prompt builders (app-defined shape). */
|
|
35
|
-
export type PromptContext = {
|
|
36
|
+
/** Context passed into prompt builders (app-defined shape via generic). */
|
|
37
|
+
export type PromptContext<TContext = unknown> = {
|
|
36
38
|
hasConversationHistory: boolean;
|
|
37
39
|
intent: string;
|
|
38
40
|
intentScore?: number;
|
|
39
41
|
message?: string;
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
+
/**
|
|
43
|
+
* App payload from `invoke({ context })`.
|
|
44
|
+
* Default is `unknown` — pass your type to `createAgentRuntime<MyContext>(...)`
|
|
45
|
+
* or cast: `(ctx.context as MyContext)?.userInfo?.name`.
|
|
46
|
+
*/
|
|
47
|
+
context?: TContext;
|
|
42
48
|
};
|
|
43
|
-
export type IntentBinding = {
|
|
44
|
-
prompt: (ctx: PromptContext) => string;
|
|
49
|
+
export type IntentBinding<TContext = unknown> = {
|
|
50
|
+
prompt: (ctx: PromptContext<TContext>) => string;
|
|
45
51
|
tools: (phoneKey: string) => DynamicStructuredTool[];
|
|
46
52
|
};
|
|
47
|
-
export type IntentRegistry = Record<string, IntentBinding
|
|
53
|
+
export type IntentRegistry<TContext = unknown> = Record<string, IntentBinding<TContext>>;
|
|
48
54
|
export type DetectedIntentResult = {
|
|
49
55
|
intent: string;
|
|
50
56
|
score: number;
|
|
@@ -68,14 +74,29 @@ export type FlowResolution = {
|
|
|
68
74
|
llmResult?: LlmIntentResult;
|
|
69
75
|
};
|
|
70
76
|
export type LlmProvider = "ollama" | "openai" | "openrouter";
|
|
77
|
+
/**
|
|
78
|
+
* Intent-embedding backends.
|
|
79
|
+
* - ollama — local Ollama server
|
|
80
|
+
* - openai — paid OpenAI embeddings API (required on Vercel/Lambda; auto-selected there when OPENAI_API_KEY is set)
|
|
81
|
+
* - xenova — free in-process Transformers.js (local default when chat is not ollama and EMBEDDINGS_PROVIDER unset)
|
|
82
|
+
*/
|
|
83
|
+
export type EmbeddingsProvider = "ollama" | "openai" | "xenova";
|
|
71
84
|
export type LlmConfig = {
|
|
72
85
|
provider: LlmProvider;
|
|
73
86
|
model: string;
|
|
74
87
|
intentRouterModel?: string;
|
|
75
88
|
embeddingsModel?: string;
|
|
76
|
-
embeddingsProvider?:
|
|
89
|
+
embeddingsProvider?: EmbeddingsProvider;
|
|
90
|
+
/** Chat provider base URL (Ollama host or OpenRouter/OpenAI API root). */
|
|
77
91
|
baseUrl?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Embeddings host when different from chat (e.g. OpenRouter chat + local Ollama embeddings).
|
|
94
|
+
* Defaults to `baseUrl` for ollama chat, else `http://localhost:11434`.
|
|
95
|
+
*/
|
|
96
|
+
embeddingsBaseUrl?: string;
|
|
78
97
|
apiKey?: string;
|
|
98
|
+
/** Separate key for OpenAI embeddings when chat uses OpenRouter. */
|
|
99
|
+
embeddingsApiKey?: string;
|
|
79
100
|
temperature?: number;
|
|
80
101
|
};
|
|
81
102
|
export type CacheConfig = {
|
|
@@ -114,11 +135,11 @@ export type FinalizeFlowResult = {
|
|
|
114
135
|
/** Extra fields the app wants returned from invoke (campaign, tickets, …). */
|
|
115
136
|
extras?: Record<string, unknown>;
|
|
116
137
|
};
|
|
117
|
-
export type InvokeInput = {
|
|
138
|
+
export type InvokeInput<TContext = unknown> = {
|
|
118
139
|
message: string;
|
|
119
140
|
threadId: string;
|
|
120
141
|
/** App context passed to prompts and optional phoneKey helper. */
|
|
121
|
-
context?:
|
|
142
|
+
context?: TContext;
|
|
122
143
|
/** Force an intent (skips hybrid routing). */
|
|
123
144
|
explicitIntent?: string;
|
|
124
145
|
phoneKey?: string;
|
|
@@ -135,8 +156,13 @@ export type InvokeResult = {
|
|
|
135
156
|
reason?: string;
|
|
136
157
|
};
|
|
137
158
|
extras?: Record<string, unknown>;
|
|
159
|
+
/**
|
|
160
|
+
* Token usage for this turn, current sticky flow, and whole thread.
|
|
161
|
+
* Persisted in Redis when `redisUrl` is set (else in-memory).
|
|
162
|
+
*/
|
|
163
|
+
usage?: TokenUsageReport;
|
|
138
164
|
};
|
|
139
|
-
export type AgentRuntimeConfig = {
|
|
165
|
+
export type AgentRuntimeConfig<TContext = unknown> = {
|
|
140
166
|
redisUrl?: string;
|
|
141
167
|
/**
|
|
142
168
|
* LLM config. Omit to use `llmConfigFromEnv()` (OLLAMA_* / OPENAI_* env vars).
|
|
@@ -145,7 +171,7 @@ export type AgentRuntimeConfig = {
|
|
|
145
171
|
/** Intent catalog for embeddings + sticky flags. */
|
|
146
172
|
intents: IntentDefinition[];
|
|
147
173
|
/** Per-intent prompt + tools factory. */
|
|
148
|
-
intentRegistry: IntentRegistry
|
|
174
|
+
intentRegistry: IntentRegistry<TContext>;
|
|
149
175
|
/**
|
|
150
176
|
* Optional digit → intent routing (e.g. menu "1" → create_campaign).
|
|
151
177
|
* Prompt text alone cannot switch intent when the user types a number —
|
|
@@ -157,8 +183,14 @@ export type AgentRuntimeConfig = {
|
|
|
157
183
|
defaultIntent?: string;
|
|
158
184
|
/** Override LLM router system prompt. */
|
|
159
185
|
routerSystemPrompt?: string | ((intents: IntentDefinition[]) => string);
|
|
160
|
-
/**
|
|
161
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Optional rules prepended to **every** intent prompt (emojis, tone, language, …).
|
|
188
|
+
* Not the same as `withGeneralIntent` (that adds a catch-all *routing* intent).
|
|
189
|
+
* Skipped when you supply a custom `buildSystemPrompt` (compose it yourself there).
|
|
190
|
+
*/
|
|
191
|
+
sharedPrompt?: string | ((ctx: PromptContext<TContext>) => string);
|
|
192
|
+
/** Custom system prompt builder; default uses intentRegistry[intent].prompt (+ sharedPrompt). */
|
|
193
|
+
buildSystemPrompt?: (ctx: PromptContext<TContext>) => string;
|
|
162
194
|
/**
|
|
163
195
|
* Simple toolName → output key map (preferred).
|
|
164
196
|
* @example { create_campaign: "campaign", buy_airtime: "buyAirtime" }
|
|
@@ -187,7 +219,7 @@ export type AgentRuntimeConfig = {
|
|
|
187
219
|
resolvePhoneKey?: (input: {
|
|
188
220
|
threadId: string;
|
|
189
221
|
phoneKey?: string;
|
|
190
|
-
context?:
|
|
222
|
+
context?: TContext;
|
|
191
223
|
}) => string;
|
|
192
224
|
cache?: CacheConfig;
|
|
193
225
|
tracing?: TracingConfig;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;
|
|
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.17",
|
|
4
4
|
"description": "Reusable LangGraph agent runtime: intent routing, sticky flows, Redis checkpointer, optional answer cache",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"build": "tsc -p tsconfig.json",
|
|
22
22
|
"dev": "tsc -p tsconfig.json --watch",
|
|
23
23
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
24
|
-
"
|
|
24
|
+
"docs:pdf": "node generate-usage-pdf.mjs",
|
|
25
|
+
"test": "tsx --test src/services/extract.test.ts && tsx --test src/services/simple-config.test.ts && tsx --test src/services/embeddings-provider.test.ts && tsx --test src/rag/sources.test.ts && tsx --test src/intents/general.test.ts && tsx --test src/intents/define.test.ts && tsx --test src/services/token-usage.test.ts",
|
|
25
26
|
"prepublishOnly": "pnpm build && pnpm test"
|
|
26
27
|
},
|
|
27
28
|
"publishConfig": {
|
|
@@ -43,13 +44,19 @@
|
|
|
43
44
|
"redis": "^6.0.0"
|
|
44
45
|
},
|
|
45
46
|
"optionalDependencies": {
|
|
46
|
-
"
|
|
47
|
+
"@xenova/transformers": "^2.17.2",
|
|
48
|
+
"langsmith": "^0.7.10",
|
|
49
|
+
"mammoth": "^1.9.0",
|
|
50
|
+
"pdf-parse": "^1.1.1"
|
|
47
51
|
},
|
|
48
52
|
"devDependencies": {
|
|
49
53
|
"@langchain/core": "^1.2.0",
|
|
50
54
|
"@langchain/langgraph": "^1.4.4",
|
|
51
55
|
"@langchain/langgraph-checkpoint": "^1.1.2",
|
|
52
56
|
"@types/node": "^25.9.3",
|
|
57
|
+
"@xenova/transformers": "^2.17.2",
|
|
58
|
+
"mammoth": "^1.12.0",
|
|
59
|
+
"pdf-parse": "^1.1.4",
|
|
53
60
|
"tsx": "^4.23.0",
|
|
54
61
|
"typescript": "^6.0.3",
|
|
55
62
|
"zod": "^4.4.3"
|