@librechat/agents 4.0.1 → 4.0.2
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/cjs/decisions/deadline.cjs +52 -0
- package/dist/cjs/decisions/deadline.cjs.map +1 -0
- package/dist/cjs/decisions/dialect.cjs +88 -0
- package/dist/cjs/decisions/dialect.cjs.map +1 -0
- package/dist/cjs/decisions/http.cjs +77 -0
- package/dist/cjs/decisions/http.cjs.map +1 -0
- package/dist/cjs/decisions/index.cjs +7 -0
- package/dist/cjs/decisions/presets.cjs +82 -0
- package/dist/cjs/decisions/presets.cjs.map +1 -0
- package/dist/cjs/decisions/questions.cjs +70 -0
- package/dist/cjs/decisions/questions.cjs.map +1 -0
- package/dist/cjs/decisions/structuredChat.cjs +178 -0
- package/dist/cjs/decisions/structuredChat.cjs.map +1 -0
- package/dist/cjs/decisions/traceMarker.cjs +6 -0
- package/dist/cjs/decisions/traceMarker.cjs.map +1 -0
- package/dist/cjs/decisions/transport.cjs +166 -0
- package/dist/cjs/decisions/transport.cjs.map +1 -0
- package/dist/cjs/decisions/types.cjs +44 -0
- package/dist/cjs/decisions/types.cjs.map +1 -0
- package/dist/cjs/graphs/Graph.cjs +4 -1
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs +6 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
- package/dist/cjs/main.cjs +39 -0
- package/dist/cjs/rerank/index.cjs +2 -0
- package/dist/cjs/rerank/search.cjs +45 -0
- package/dist/cjs/rerank/search.cjs.map +1 -0
- package/dist/cjs/rerank/systemone.cjs +70 -0
- package/dist/cjs/rerank/systemone.cjs.map +1 -0
- package/dist/cjs/run.cjs +4 -0
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs +1 -0
- package/dist/cjs/tools/search/search.cjs +3 -3
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +4 -3
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs +11 -0
- package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +87 -14
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/tools/subagent/diagnostics.cjs +45 -2
- package/dist/cjs/tools/subagent/diagnostics.cjs.map +1 -1
- package/dist/cjs/tools/subagent/index.cjs +1 -0
- package/dist/esm/decisions/deadline.mjs +52 -0
- package/dist/esm/decisions/deadline.mjs.map +1 -0
- package/dist/esm/decisions/dialect.mjs +87 -0
- package/dist/esm/decisions/dialect.mjs.map +1 -0
- package/dist/esm/decisions/http.mjs +75 -0
- package/dist/esm/decisions/http.mjs.map +1 -0
- package/dist/esm/decisions/index.mjs +8 -0
- package/dist/esm/decisions/presets.mjs +77 -0
- package/dist/esm/decisions/presets.mjs.map +1 -0
- package/dist/esm/decisions/questions.mjs +67 -0
- package/dist/esm/decisions/questions.mjs.map +1 -0
- package/dist/esm/decisions/structuredChat.mjs +178 -0
- package/dist/esm/decisions/structuredChat.mjs.map +1 -0
- package/dist/esm/decisions/traceMarker.mjs +6 -0
- package/dist/esm/decisions/traceMarker.mjs.map +1 -0
- package/dist/esm/decisions/transport.mjs +164 -0
- package/dist/esm/decisions/transport.mjs.map +1 -0
- package/dist/esm/decisions/types.mjs +39 -0
- package/dist/esm/decisions/types.mjs.map +1 -0
- package/dist/esm/graphs/Graph.mjs +4 -1
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/langfuseToolOutputTracing.mjs +6 -1
- package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
- package/dist/esm/main.mjs +13 -1
- package/dist/esm/rerank/index.mjs +3 -0
- package/dist/esm/rerank/search.mjs +45 -0
- package/dist/esm/rerank/search.mjs.map +1 -0
- package/dist/esm/rerank/systemone.mjs +70 -0
- package/dist/esm/rerank/systemone.mjs.map +1 -0
- package/dist/esm/run.mjs +4 -0
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs +1 -1
- package/dist/esm/tools/search/search.mjs +3 -3
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +4 -3
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs +11 -0
- package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +88 -15
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/tools/subagent/diagnostics.mjs +44 -3
- package/dist/esm/tools/subagent/diagnostics.mjs.map +1 -1
- package/dist/esm/tools/subagent/index.mjs +1 -0
- package/dist/types/decisions/deadline.d.ts +3 -0
- package/dist/types/decisions/dialect.d.ts +11 -0
- package/dist/types/decisions/http.d.ts +22 -0
- package/dist/types/decisions/index.d.ts +10 -0
- package/dist/types/decisions/presets.d.ts +17 -0
- package/dist/types/decisions/questions.d.ts +8 -0
- package/dist/types/decisions/structuredChat.d.ts +16 -0
- package/dist/types/decisions/traceMarker.d.ts +2 -0
- package/dist/types/decisions/transport.d.ts +29 -0
- package/dist/types/decisions/types.d.ts +119 -0
- package/dist/types/graphs/Graph.d.ts +2 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/rerank/index.d.ts +4 -0
- package/dist/types/rerank/search.d.ts +7 -0
- package/dist/types/rerank/systemone.d.ts +13 -0
- package/dist/types/rerank/types.d.ts +24 -0
- package/dist/types/run.d.ts +1 -0
- package/dist/types/tools/search/types.d.ts +3 -1
- package/dist/types/tools/subagent/SubagentExecutionRegistry.d.ts +4 -0
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +13 -0
- package/dist/types/tools/subagent/diagnostics.d.ts +32 -8
- package/dist/types/tools/subagent/index.d.ts +2 -0
- package/dist/types/types/graph.d.ts +3 -0
- package/dist/types/types/run.d.ts +2 -0
- package/package.json +1 -1
- package/src/decisions/deadline.ts +92 -0
- package/src/decisions/dialect.ts +200 -0
- package/src/decisions/http.ts +175 -0
- package/src/decisions/index.ts +14 -0
- package/src/decisions/presets.ts +111 -0
- package/src/decisions/questions.ts +128 -0
- package/src/decisions/structuredChat.ts +364 -0
- package/src/decisions/traceMarker.ts +2 -0
- package/src/decisions/transport.ts +335 -0
- package/src/decisions/types.ts +193 -0
- package/src/graphs/Graph.ts +4 -0
- package/src/index.ts +2 -0
- package/src/langfuseToolOutputTracing.ts +8 -1
- package/src/rerank/index.ts +4 -0
- package/src/rerank/search.ts +85 -0
- package/src/rerank/systemone.ts +140 -0
- package/src/rerank/types.ts +28 -0
- package/src/run.ts +4 -0
- package/src/tools/search/search.ts +4 -4
- package/src/tools/search/tool.ts +27 -25
- package/src/tools/search/types.ts +4 -1
- package/src/tools/subagent/SubagentExecutionRegistry.ts +21 -0
- package/src/tools/subagent/SubagentExecutor.ts +190 -22
- package/src/tools/subagent/diagnostics.ts +88 -9
- package/src/tools/subagent/index.ts +11 -0
- package/src/types/graph.ts +3 -0
- package/src/types/run.ts +2 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { createHttpDecisionModel } from "./http.mjs";
|
|
2
|
+
//#region src/decisions/presets.ts
|
|
3
|
+
const DEFAULT_API_KEY_ENV = "DECISION_API_KEY";
|
|
4
|
+
const DECISION_PRESETS = Object.freeze({
|
|
5
|
+
http: Object.freeze({
|
|
6
|
+
dialect: "port",
|
|
7
|
+
requiresAuth: true,
|
|
8
|
+
apiKeyEnv: DEFAULT_API_KEY_ENV
|
|
9
|
+
}),
|
|
10
|
+
typesafe: Object.freeze({
|
|
11
|
+
baseURL: "https://api.typesafe.ai/v1/systemone",
|
|
12
|
+
model: "jev-latest",
|
|
13
|
+
dialect: "systemone",
|
|
14
|
+
requiresAuth: true,
|
|
15
|
+
apiKeyEnv: "TYPESAFE_API_KEY"
|
|
16
|
+
}),
|
|
17
|
+
laya: Object.freeze({
|
|
18
|
+
dialect: "systemone",
|
|
19
|
+
requiresAuth: false
|
|
20
|
+
}),
|
|
21
|
+
clickhouse: Object.freeze({
|
|
22
|
+
baseURL: "https://inference-internal.clickhouse.cloud/v1/systemone",
|
|
23
|
+
model: "jev-latest",
|
|
24
|
+
dialect: "systemone",
|
|
25
|
+
requiresAuth: true,
|
|
26
|
+
apiKeyEnv: "CHAI_AUTH_TOKEN"
|
|
27
|
+
}),
|
|
28
|
+
openrouter: Object.freeze({
|
|
29
|
+
baseURL: "https://openrouter.ai/api/alpha/decisions",
|
|
30
|
+
model: "~typesafe/jev-latest",
|
|
31
|
+
dialect: "systemone",
|
|
32
|
+
requiresAuth: true,
|
|
33
|
+
apiKeyEnv: "OPENROUTER_KEY"
|
|
34
|
+
}),
|
|
35
|
+
cloudflare: Object.freeze({
|
|
36
|
+
model: "typesafe/jev",
|
|
37
|
+
dialect: "systemone",
|
|
38
|
+
requestKey: "input",
|
|
39
|
+
responseKey: "result",
|
|
40
|
+
requiresAuth: true,
|
|
41
|
+
apiKeyEnv: "CLOUDFLARE_API_TOKEN"
|
|
42
|
+
})
|
|
43
|
+
});
|
|
44
|
+
function decisionPreset(name) {
|
|
45
|
+
if (name == null || name === "") return null;
|
|
46
|
+
return Object.hasOwn(DECISION_PRESETS, name) ? { ...DECISION_PRESETS[name] } : null;
|
|
47
|
+
}
|
|
48
|
+
function mergeDecisionSettings(preset, configured) {
|
|
49
|
+
return {
|
|
50
|
+
...preset ?? {},
|
|
51
|
+
...configured ?? {},
|
|
52
|
+
...preset?.requiresAuth === true ? { requiresAuth: true } : {}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function decisionProviderNames() {
|
|
56
|
+
return Object.keys(DECISION_PRESETS);
|
|
57
|
+
}
|
|
58
|
+
function createDecisionModel(settings, apiKey, options) {
|
|
59
|
+
return createHttpDecisionModel({
|
|
60
|
+
providerId: options?.providerId,
|
|
61
|
+
apiKey,
|
|
62
|
+
requiresAuth: settings.requiresAuth,
|
|
63
|
+
endpoint: settings.baseURL ?? "",
|
|
64
|
+
model: settings.model,
|
|
65
|
+
dialect: settings.dialect,
|
|
66
|
+
requestKey: settings.requestKey,
|
|
67
|
+
responseKey: settings.responseKey,
|
|
68
|
+
timeoutMs: settings.timeoutMs,
|
|
69
|
+
maxRetries: settings.maxRetries,
|
|
70
|
+
fetch: options?.fetch,
|
|
71
|
+
onAnswered: options?.onAnswered
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { DECISION_PRESETS, DEFAULT_API_KEY_ENV, createDecisionModel, decisionPreset, decisionProviderNames, mergeDecisionSettings };
|
|
76
|
+
|
|
77
|
+
//# sourceMappingURL=presets.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.mjs","names":[],"sources":["../../../src/decisions/presets.ts"],"mappings":";;AAQA,MAAa,sBAAsB;AAMnC,MAAa,mBAET,OAAO,OAAO;CAChB,MAAM,OAAO,OAAO;EAClB,SAAS;EACT,cAAc;EACd,WAAW;CACb,CAAC;CACD,UAAU,OAAO,OAAO;EACtB,SAAS;EACT,OAAO;EACP,SAAS;EACT,cAAc;EACd,WAAW;CACb,CAAC;CACD,MAAM,OAAO,OAAO;EAElB,SAAS;EACT,cAAc;CAChB,CAAC;CACD,YAAY,OAAO,OAAO;EAExB,SAAS;EACT,OAAO;EACP,SAAS;EACT,cAAc;EACd,WAAW;CACb,CAAC;CACD,YAAY,OAAO,OAAO;EACxB,SAAS;EACT,OAAO;EACP,SAAS;EACT,cAAc;EACd,WAAW;CACb,CAAC;CACD,YAAY,OAAO,OAAO;EAExB,OAAO;EACP,SAAS;EACT,YAAY;EACZ,aAAa;EACb,cAAc;EACd,WAAW;CACb,CAAC;AACH,CAAC;AAED,SAAgB,eACd,MACiC;CACjC,IAAI,QAAQ,QAAQ,SAAS,IAC3B,OAAO;CAET,OAAO,OAAO,OAAO,kBAAkB,IAAI,IACvC,EAAE,GAAG,iBAAiB,MAAM,IAC5B;AACN;AAGA,SAAgB,sBACd,QACA,YAC0B;CAC1B,OAAO;EACL,GAAI,UAAU,CAAC;EACf,GAAI,cAAc,CAAC;EACnB,GAAI,QAAQ,iBAAiB,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;CAChE;AACF;AAEA,SAAgB,wBAAkC;CAChD,OAAO,OAAO,KAAK,gBAAgB;AACrC;AAEA,SAAgB,oBACd,UACA,QACA,SAKe;CACf,OAAO,wBAAwB;EAC7B,YAAY,SAAS;EACrB;EACA,cAAc,SAAS;EACvB,UAAU,SAAS,WAAW;EAC9B,OAAO,SAAS;EAChB,SAAS,SAAS;EAClB,YAAY,SAAS;EACrB,aAAa,SAAS;EACtB,WAAW,SAAS;EACpB,YAAY,SAAS;EACrB,OAAO,SAAS;EAChB,YAAY,SAAS;CACvB,CAAC;AACH"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { DecisionError, isDecisionObject } from "./types.mjs";
|
|
2
|
+
//#region src/decisions/questions.ts
|
|
3
|
+
function validQuestionId(id) {
|
|
4
|
+
if (id.length === 0 || id.length > 128) return false;
|
|
5
|
+
for (let index = 0; index < id.length; index++) if (id.charCodeAt(index) < 32) return false;
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
function validBooleanCriteria(criteria) {
|
|
9
|
+
if (criteria === void 0 || typeof criteria === "string") return true;
|
|
10
|
+
if (!isDecisionObject(criteria)) return false;
|
|
11
|
+
for (const [side, description] of Object.entries(criteria)) if (side !== "true" && side !== "false" || description !== void 0 && typeof description !== "string" && !Array.isArray(description) && !isDecisionObject(description)) return false;
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
function validateDecisionQuestions(questions, provider) {
|
|
15
|
+
if (!isDecisionObject(questions)) throw new DecisionError("bad_request", "invalid decision model questions", { provider });
|
|
16
|
+
const supplied = Object.entries(questions);
|
|
17
|
+
if (supplied.length === 0) throw new DecisionError("bad_request", "decision model requires questions", { provider });
|
|
18
|
+
const entries = [];
|
|
19
|
+
for (const [id, question] of supplied) {
|
|
20
|
+
if (!validQuestionId(id) || !isDecisionObject(question) || ![
|
|
21
|
+
"boolean",
|
|
22
|
+
"choice",
|
|
23
|
+
"score"
|
|
24
|
+
].includes(question.type) || question.type === "boolean" && !validBooleanCriteria(question.criteria) || question.type === "choice" && (!isDecisionObject(question.criteria) || Object.keys(question.criteria).length === 0) || question.type === "score" && (!Array.isArray(question.criteria) || question.criteria.length < 2)) throw new DecisionError("bad_request", "invalid decision model question", { provider });
|
|
25
|
+
if (question.type === "choice") entries.push([id, {
|
|
26
|
+
...question,
|
|
27
|
+
criteria: { ...question.criteria }
|
|
28
|
+
}]);
|
|
29
|
+
else if (question.type === "score") entries.push([id, {
|
|
30
|
+
...question,
|
|
31
|
+
criteria: [...question.criteria]
|
|
32
|
+
}]);
|
|
33
|
+
else entries.push([id, {
|
|
34
|
+
...question,
|
|
35
|
+
...isDecisionObject(question.criteria) ? { criteria: { ...question.criteria } } : {}
|
|
36
|
+
}]);
|
|
37
|
+
}
|
|
38
|
+
return entries;
|
|
39
|
+
}
|
|
40
|
+
function booleanQuestion(instructions, criteria) {
|
|
41
|
+
return criteria == null ? {
|
|
42
|
+
type: "boolean",
|
|
43
|
+
instructions
|
|
44
|
+
} : {
|
|
45
|
+
type: "boolean",
|
|
46
|
+
instructions,
|
|
47
|
+
criteria
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function choiceQuestion(instructions, criteria) {
|
|
51
|
+
return {
|
|
52
|
+
type: "choice",
|
|
53
|
+
instructions,
|
|
54
|
+
criteria
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function scoreQuestion(instructions, levels) {
|
|
58
|
+
return {
|
|
59
|
+
type: "score",
|
|
60
|
+
instructions,
|
|
61
|
+
criteria: levels
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
export { booleanQuestion, choiceQuestion, scoreQuestion, validateDecisionQuestions };
|
|
66
|
+
|
|
67
|
+
//# sourceMappingURL=questions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions.mjs","names":[],"sources":["../../../src/decisions/questions.ts"],"mappings":";;AAUA,SAAS,gBAAgB,IAAqB;CAC5C,IAAI,GAAG,WAAW,KAAK,GAAG,SAAS,KACjC,OAAO;CAET,KAAK,IAAI,QAAQ,GAAG,QAAQ,GAAG,QAAQ,SACrC,IAAI,GAAG,WAAW,KAAK,IAAI,IACzB,OAAO;CAGX,OAAO;AACT;AAEA,SAAS,qBAAqB,UAAgD;CAC5E,IAAI,aAAa,KAAA,KAAa,OAAO,aAAa,UAChD,OAAO;CAET,IAAI,CAAC,iBAAiB,QAAQ,GAC5B,OAAO;CAET,KAAK,MAAM,CAAC,MAAM,gBAAgB,OAAO,QAAQ,QAAQ,GACvD,IACG,SAAS,UAAU,SAAS,WAC5B,gBAAgB,KAAA,KACf,OAAO,gBAAgB,YACvB,CAAC,MAAM,QAAQ,WAAW,KAC1B,CAAC,iBAAiB,WAAW,GAE/B,OAAO;CAGX,OAAO;AACT;AAEA,SAAgB,0BACd,WACA,UACmC;CACnC,IAAI,CAAC,iBAAiB,SAAS,GAC7B,MAAM,IAAI,cAAc,eAAe,oCAAoC,EACzE,SACF,CAAC;CAEH,MAAM,WAAW,OAAO,QAAQ,SAAS;CACzC,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,cACR,eACA,qCACA,EACE,SACF,CACF;CAEF,MAAM,UAA6C,CAAC;CACpD,KAAK,MAAM,CAAC,IAAI,aAAa,UAAU;EACrC,IACE,CAAC,gBAAgB,EAAE,KACnB,CAAC,iBAAiB,QAAQ,KAC1B,CAAC;GAAC;GAAW;GAAU;EAAO,CAAC,CAAC,SAAS,SAAS,IAAI,KACrD,SAAS,SAAS,aACjB,CAAC,qBAAqB,SAAS,QAAQ,KACxC,SAAS,SAAS,aAChB,CAAC,iBAAiB,SAAS,QAAQ,KAClC,OAAO,KAAK,SAAS,QAAQ,CAAC,CAAC,WAAW,MAC7C,SAAS,SAAS,YAChB,CAAC,MAAM,QAAQ,SAAS,QAAQ,KAAK,SAAS,SAAS,SAAS,IAEnE,MAAM,IAAI,cACR,eACA,mCACA,EACE,SACF,CACF;EAEF,IAAI,SAAS,SAAS,UACpB,QAAQ,KAAK,CAAC,IAAI;GAAE,GAAG;GAAU,UAAU,EAAE,GAAG,SAAS,SAAS;EAAE,CAAC,CAAC;OACjE,IAAI,SAAS,SAAS,SAC3B,QAAQ,KAAK,CAAC,IAAI;GAAE,GAAG;GAAU,UAAU,CAAC,GAAG,SAAS,QAAQ;EAAE,CAAC,CAAC;OAEpE,QAAQ,KAAK,CACX,IACA;GACE,GAAG;GACH,GAAI,iBAAiB,SAAS,QAAQ,IAClC,EAAE,UAAU,EAAE,GAAG,SAAS,SAAS,EAAE,IACrC,CAAC;EACP,CACF,CAAC;CAEL;CACA,OAAO;AACT;AAGA,SAAgB,gBACd,cACA,UACiB;CACjB,OAAO,YAAY,OACf;EAAE,MAAM;EAAW;CAAa,IAChC;EAAE,MAAM;EAAW;EAAc;CAAS;AAChD;AAGA,SAAgB,eACd,cACA,UACgB;CAChB,OAAO;EAAE,MAAM;EAAU;EAAc;CAAS;AAClD;AAGA,SAAgB,cACd,cACA,QACe;CACf,OAAO;EAAE,MAAM;EAAS;EAAc,UAAU;CAAO;AACzD"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { DECISION_PROMPT_PREFIX } from "./traceMarker.mjs";
|
|
2
|
+
import { DecisionError, isDecisionObject, readDecisionUsage } from "./types.mjs";
|
|
3
|
+
import { validateDecisionQuestions } from "./questions.mjs";
|
|
4
|
+
import { withDecisionDeadline } from "./deadline.mjs";
|
|
5
|
+
import { failureForStatus, retryAfterMs } from "./transport.mjs";
|
|
6
|
+
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
7
|
+
//#region src/decisions/structuredChat.ts
|
|
8
|
+
const MAX_QUESTIONS = 32;
|
|
9
|
+
const MAX_CHOICE_OPTIONS = 128;
|
|
10
|
+
const DEFAULT_TIMEOUT_MS = 2e4;
|
|
11
|
+
const PROVIDER_ID = "structured-chat";
|
|
12
|
+
function readChatUsage(raw) {
|
|
13
|
+
if (!isDecisionObject(raw)) return null;
|
|
14
|
+
const usage = readDecisionUsage(raw.usage_metadata);
|
|
15
|
+
const response = isDecisionObject(raw.response_metadata) ? raw.response_metadata : null;
|
|
16
|
+
const nested = isDecisionObject(response?.metadata) ? response.metadata : null;
|
|
17
|
+
const bedrock = isDecisionObject(nested?.usage) ? nested.usage : response?.usage;
|
|
18
|
+
if (usage?.inputTokens === void 0 || !isDecisionObject(bedrock) || usage.inputTokens !== bedrock.inputTokens) return usage;
|
|
19
|
+
const read = bedrock.cacheReadInputTokens;
|
|
20
|
+
const write = bedrock.cacheWriteInputTokens;
|
|
21
|
+
if (read != null && (typeof read !== "number" || !Number.isSafeInteger(read) || read < 0) || write != null && (typeof write !== "number" || !Number.isSafeInteger(write) || write < 0)) return usage;
|
|
22
|
+
const inputTokens = usage.inputTokens + (typeof read === "number" ? read : 0) + (typeof write === "number" ? write : 0);
|
|
23
|
+
return Number.isSafeInteger(inputTokens) ? {
|
|
24
|
+
...usage,
|
|
25
|
+
inputTokens
|
|
26
|
+
} : usage;
|
|
27
|
+
}
|
|
28
|
+
function providerFailure(error, provider) {
|
|
29
|
+
const details = isDecisionObject(error) ? error : null;
|
|
30
|
+
const metadata = isDecisionObject(details?.$metadata) ? details.$metadata : null;
|
|
31
|
+
const rawStatus = details?.status ?? details?.statusCode ?? metadata?.httpStatusCode;
|
|
32
|
+
const status = typeof rawStatus === "number" && Number.isInteger(rawStatus) && rawStatus >= 100 && rawStatus <= 599 ? rawStatus : void 0;
|
|
33
|
+
const failure = new DecisionError(status == null ? "network" : failureForStatus(status), "structured decision model request failed", {
|
|
34
|
+
provider,
|
|
35
|
+
status
|
|
36
|
+
});
|
|
37
|
+
const headers = details?.headers;
|
|
38
|
+
if (headers instanceof Headers) failure.retryAfterMs = retryAfterMs(headers.get("retry-after"));
|
|
39
|
+
return failure;
|
|
40
|
+
}
|
|
41
|
+
function decisionSchema(entries) {
|
|
42
|
+
const properties = Object.create(null);
|
|
43
|
+
for (const [id, question] of entries) {
|
|
44
|
+
if (question.type === "boolean") {
|
|
45
|
+
properties[id] = {
|
|
46
|
+
type: "object",
|
|
47
|
+
properties: { decision: { type: "boolean" } },
|
|
48
|
+
required: ["decision"],
|
|
49
|
+
additionalProperties: false
|
|
50
|
+
};
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
properties[id] = {
|
|
54
|
+
type: "object",
|
|
55
|
+
properties: { choice: {
|
|
56
|
+
type: "string",
|
|
57
|
+
enum: Object.keys(question.criteria)
|
|
58
|
+
} },
|
|
59
|
+
required: ["choice"],
|
|
60
|
+
additionalProperties: false
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
type: "object",
|
|
65
|
+
properties: { answers: {
|
|
66
|
+
type: "object",
|
|
67
|
+
properties,
|
|
68
|
+
required: entries.map(([id]) => id),
|
|
69
|
+
additionalProperties: false
|
|
70
|
+
} },
|
|
71
|
+
required: ["answers"],
|
|
72
|
+
additionalProperties: false
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function readDecisions(parsed, entries, provider) {
|
|
76
|
+
const invalid = () => new DecisionError("malformed_response", "invalid structured decision model answer", { provider });
|
|
77
|
+
if (!isDecisionObject(parsed) || Object.keys(parsed).length !== 1 || !isDecisionObject(parsed.answers) || Object.keys(parsed.answers).length !== entries.length) throw invalid();
|
|
78
|
+
const answers = Object.create(null);
|
|
79
|
+
for (const [id, question] of entries) {
|
|
80
|
+
if (!Object.hasOwn(parsed.answers, id)) throw invalid();
|
|
81
|
+
const raw = parsed.answers[id];
|
|
82
|
+
if (!isDecisionObject(raw) || Object.keys(raw).length !== 1) throw invalid();
|
|
83
|
+
if (question.type === "boolean") {
|
|
84
|
+
if (typeof raw.decision !== "boolean") throw invalid();
|
|
85
|
+
answers[id] = {
|
|
86
|
+
type: "boolean",
|
|
87
|
+
decision: raw.decision,
|
|
88
|
+
probability: null
|
|
89
|
+
};
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (question.type !== "choice" || typeof raw.choice !== "string" || !Object.hasOwn(question.criteria, raw.choice)) throw invalid();
|
|
93
|
+
answers[id] = {
|
|
94
|
+
type: "choice",
|
|
95
|
+
choice: raw.choice,
|
|
96
|
+
confidence: null,
|
|
97
|
+
probabilities: null
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return answers;
|
|
101
|
+
}
|
|
102
|
+
function questionsForChat(questions, provider, maxQuestions) {
|
|
103
|
+
const entries = validateDecisionQuestions(questions, provider);
|
|
104
|
+
let choices = 0;
|
|
105
|
+
for (const [, question] of entries) {
|
|
106
|
+
if (question.type === "score") throw new DecisionError("unsupported_question", "chat decision cannot score expected values", { provider });
|
|
107
|
+
if (question.type === "choice") choices += Object.keys(question.criteria).length;
|
|
108
|
+
}
|
|
109
|
+
if (entries.length > maxQuestions || choices > MAX_CHOICE_OPTIONS) throw new DecisionError("unsupported_question", "decision model question batch too large", { provider });
|
|
110
|
+
return entries;
|
|
111
|
+
}
|
|
112
|
+
function createStructuredChatDecisionModel(options) {
|
|
113
|
+
const provider = options.providerId ?? PROVIDER_ID;
|
|
114
|
+
if (!["jsonSchema", "functionCalling"].includes(options.method)) throw new DecisionError("unsupported_mode", "unsupported structured decision model mode", { provider });
|
|
115
|
+
if (!options.modelId.trim()) throw new DecisionError("bad_request", "decision model requires a model id", { provider });
|
|
116
|
+
const maxQuestions = options.maxQuestions ?? MAX_QUESTIONS;
|
|
117
|
+
if (!Number.isSafeInteger(maxQuestions) || maxQuestions < 1 || maxQuestions > MAX_QUESTIONS) throw new DecisionError("bad_request", "invalid decision model question limit", { provider });
|
|
118
|
+
const { model, method } = options;
|
|
119
|
+
const modelId = options.modelId.trim();
|
|
120
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
121
|
+
const onAnswered = options.onAnswered;
|
|
122
|
+
return {
|
|
123
|
+
id: provider,
|
|
124
|
+
model: modelId,
|
|
125
|
+
async decide(request) {
|
|
126
|
+
const started = performance.now();
|
|
127
|
+
return withDecisionDeadline(provider, request.timeoutMs ?? timeoutMs, request.signal, async (signal, waitFor) => {
|
|
128
|
+
let entries;
|
|
129
|
+
let input;
|
|
130
|
+
try {
|
|
131
|
+
entries = questionsForChat(request.questions, provider, maxQuestions);
|
|
132
|
+
input = DECISION_PROMPT_PREFIX + JSON.stringify({
|
|
133
|
+
state: request.state,
|
|
134
|
+
questions: Object.fromEntries(entries)
|
|
135
|
+
});
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (error instanceof DecisionError) throw error;
|
|
138
|
+
throw new DecisionError("bad_request", "invalid decision model request", { provider });
|
|
139
|
+
}
|
|
140
|
+
let structured;
|
|
141
|
+
try {
|
|
142
|
+
const adapter = model._llmType();
|
|
143
|
+
if (adapter !== "openai" && (adapter !== "anthropic" || method !== "functionCalling")) throw new Error("unverified strict decision model adapter");
|
|
144
|
+
structured = model.withStructuredOutput(decisionSchema(entries), {
|
|
145
|
+
name: "DecideQuestions",
|
|
146
|
+
method,
|
|
147
|
+
strict: true,
|
|
148
|
+
includeRaw: true
|
|
149
|
+
});
|
|
150
|
+
} catch {
|
|
151
|
+
throw new DecisionError("unsupported_mode", "model cannot enforce the requested strict mode", { provider });
|
|
152
|
+
}
|
|
153
|
+
await waitFor(Promise.resolve());
|
|
154
|
+
let output;
|
|
155
|
+
try {
|
|
156
|
+
output = await waitFor(structured.invoke([new SystemMessage("Classify the state using the questions. Return only the required decisions. Do not estimate probabilities, confidence, or token usage."), new HumanMessage(input)], { signal }));
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if (error instanceof DecisionError) throw error;
|
|
159
|
+
throw providerFailure(error, provider);
|
|
160
|
+
}
|
|
161
|
+
const result = {
|
|
162
|
+
model: modelId,
|
|
163
|
+
answers: readDecisions(output.parsed, entries, provider),
|
|
164
|
+
usage: readChatUsage(output.raw)
|
|
165
|
+
};
|
|
166
|
+
await waitFor(Promise.resolve());
|
|
167
|
+
try {
|
|
168
|
+
onAnswered?.(request.label ?? "decide", performance.now() - started);
|
|
169
|
+
} catch {}
|
|
170
|
+
return result;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
176
|
+
export { createStructuredChatDecisionModel };
|
|
177
|
+
|
|
178
|
+
//# sourceMappingURL=structuredChat.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structuredChat.mjs","names":[],"sources":["../../../src/decisions/structuredChat.ts"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traceMarker.mjs","names":[],"sources":["../../../src/decisions/traceMarker.ts"],"mappings":";AACA,MAAa,yBAAyB"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { DecisionError } from "./types.mjs";
|
|
2
|
+
import { withDecisionDeadline } from "./deadline.mjs";
|
|
3
|
+
//#region src/decisions/transport.ts
|
|
4
|
+
const DEFAULT_TIMEOUT_MS = 4e3;
|
|
5
|
+
const DEFAULT_MAX_RETRIES = 2;
|
|
6
|
+
const MAX_RESPONSE_BYTES = 256 * 1024;
|
|
7
|
+
const BACKOFF_MS = [
|
|
8
|
+
250,
|
|
9
|
+
750,
|
|
10
|
+
1500,
|
|
11
|
+
3e3,
|
|
12
|
+
6e3
|
|
13
|
+
];
|
|
14
|
+
const MAX_RETRY_AFTER_MS = 1e4;
|
|
15
|
+
function failureForStatus(status) {
|
|
16
|
+
if (status === 401 || status === 403) return "unauthorized";
|
|
17
|
+
if (status === 429) return "rate_limited";
|
|
18
|
+
if (status >= 500) return "server_error";
|
|
19
|
+
return "bad_request";
|
|
20
|
+
}
|
|
21
|
+
function retryAfterMs(header) {
|
|
22
|
+
if (header == null || header === "") return;
|
|
23
|
+
const seconds = Number(header);
|
|
24
|
+
if (Number.isFinite(seconds) && seconds >= 0) return Math.min(seconds * 1e3, MAX_RETRY_AFTER_MS);
|
|
25
|
+
const at = Date.parse(header);
|
|
26
|
+
return Number.isFinite(at) ? Math.min(Math.max(at - Date.now(), 0), MAX_RETRY_AFTER_MS) : void 0;
|
|
27
|
+
}
|
|
28
|
+
function defaultSleep(ms, signal) {
|
|
29
|
+
if (signal?.aborted === true) return Promise.resolve();
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
const done = () => {
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
signal?.removeEventListener("abort", done);
|
|
34
|
+
resolve();
|
|
35
|
+
};
|
|
36
|
+
const timer = setTimeout(done, ms);
|
|
37
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async function readResponse(body, waitFor, provider) {
|
|
41
|
+
if (!body) return "";
|
|
42
|
+
const reader = body.getReader();
|
|
43
|
+
const decoder = new TextDecoder();
|
|
44
|
+
let bytes = 0;
|
|
45
|
+
let text = "";
|
|
46
|
+
try {
|
|
47
|
+
for (;;) {
|
|
48
|
+
const chunk = await waitFor(reader.read());
|
|
49
|
+
if (chunk.done) return text + decoder.decode();
|
|
50
|
+
bytes += chunk.value.byteLength;
|
|
51
|
+
if (bytes > MAX_RESPONSE_BYTES) throw new DecisionError("malformed_response", "decision model response too large", { provider });
|
|
52
|
+
text += decoder.decode(chunk.value, { stream: true });
|
|
53
|
+
}
|
|
54
|
+
} catch (error) {
|
|
55
|
+
reader.cancel().catch(() => {});
|
|
56
|
+
throw error;
|
|
57
|
+
} finally {
|
|
58
|
+
try {
|
|
59
|
+
reader.releaseLock();
|
|
60
|
+
} catch {}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function createTransport(options) {
|
|
64
|
+
const { providerId } = options;
|
|
65
|
+
const credential = options.apiKey;
|
|
66
|
+
if (options.requiresAuth !== false && (credential == null || typeof credential === "string" && credential.trim() === "")) throw new DecisionError("unauthorized", "decision model requires an API key", { provider: providerId });
|
|
67
|
+
const endpoint = options.endpoint.trim();
|
|
68
|
+
if (!endpoint) throw new DecisionError("bad_request", "decision model requires an endpoint", { provider: providerId });
|
|
69
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
70
|
+
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
71
|
+
const sleep = options.sleep ?? defaultSleep;
|
|
72
|
+
const onAnswered = options.onAnswered;
|
|
73
|
+
if (!Number.isSafeInteger(maxRetries) || maxRetries < 0 || maxRetries > 5) throw new DecisionError("bad_request", "invalid decision model retry limit", { provider: providerId });
|
|
74
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
75
|
+
if (typeof fetchImpl !== "function") throw new DecisionError("network", "no fetch implementation available", { provider: providerId });
|
|
76
|
+
async function resolveKey(refresh, signal) {
|
|
77
|
+
if (typeof credential === "string") return credential.trim() || null;
|
|
78
|
+
if (!credential) return null;
|
|
79
|
+
const minted = await credential({
|
|
80
|
+
refresh,
|
|
81
|
+
signal
|
|
82
|
+
});
|
|
83
|
+
const token = typeof minted === "string" ? minted.trim() : "";
|
|
84
|
+
if (!token) throw new DecisionError("unauthorized", "credential function returned no token", { provider: providerId });
|
|
85
|
+
return token;
|
|
86
|
+
}
|
|
87
|
+
return async function send(prepare, callerSignal, label, timeoutOverrideMs) {
|
|
88
|
+
const started = performance.now();
|
|
89
|
+
return withDecisionDeadline(providerId, timeoutOverrideMs ?? timeoutMs, callerSignal, async (signal, waitFor) => {
|
|
90
|
+
let prepared;
|
|
91
|
+
try {
|
|
92
|
+
prepared = prepare();
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (error instanceof DecisionError) throw error;
|
|
95
|
+
throw new DecisionError("bad_request", "invalid decision model request", { provider: providerId });
|
|
96
|
+
}
|
|
97
|
+
const { payload, parse } = prepared;
|
|
98
|
+
await waitFor(Promise.resolve());
|
|
99
|
+
const wasAborted = () => signal.aborted;
|
|
100
|
+
const interrupted = () => new DecisionError(callerSignal?.aborted === true ? "aborted" : "timeout", "decision model request interrupted", { provider: providerId });
|
|
101
|
+
let refreshed = false;
|
|
102
|
+
let key;
|
|
103
|
+
let lastError;
|
|
104
|
+
for (let attemptNo = 0; attemptNo <= maxRetries; attemptNo++) {
|
|
105
|
+
if (wasAborted()) throw interrupted();
|
|
106
|
+
try {
|
|
107
|
+
if (key === void 0) key = await waitFor(resolveKey(refreshed, signal));
|
|
108
|
+
const response = await waitFor(fetchImpl(endpoint, {
|
|
109
|
+
method: "POST",
|
|
110
|
+
headers: {
|
|
111
|
+
...key !== null ? { Authorization: `Bearer ${key}` } : {},
|
|
112
|
+
"Content-Type": "application/json"
|
|
113
|
+
},
|
|
114
|
+
body: payload,
|
|
115
|
+
signal,
|
|
116
|
+
redirect: "error"
|
|
117
|
+
}));
|
|
118
|
+
if (!response.ok) {
|
|
119
|
+
response.body?.cancel().catch(() => {});
|
|
120
|
+
const error = new DecisionError(failureForStatus(response.status), `decision model returned HTTP ${response.status}`, {
|
|
121
|
+
provider: providerId,
|
|
122
|
+
status: response.status
|
|
123
|
+
});
|
|
124
|
+
error.retryAfterMs = retryAfterMs(response.headers.get("retry-after"));
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
const body = await readResponse(response.body, waitFor, providerId);
|
|
128
|
+
const result = await waitFor(Promise.resolve(parse(body)));
|
|
129
|
+
try {
|
|
130
|
+
onAnswered?.(label, performance.now() - started);
|
|
131
|
+
} catch {}
|
|
132
|
+
return result;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (wasAborted()) throw interrupted();
|
|
135
|
+
if (error instanceof DecisionError) lastError = error;
|
|
136
|
+
else lastError = new DecisionError("network", "decision model request failed", { provider: providerId });
|
|
137
|
+
if (lastError.status === 401 && typeof credential === "function" && !refreshed) {
|
|
138
|
+
refreshed = true;
|
|
139
|
+
key = void 0;
|
|
140
|
+
attemptNo -= 1;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (attemptNo === maxRetries || ![
|
|
144
|
+
"rate_limited",
|
|
145
|
+
"server_error",
|
|
146
|
+
"network"
|
|
147
|
+
].includes(lastError.failure)) break;
|
|
148
|
+
const wait = lastError.retryAfterMs ?? BACKOFF_MS[Math.min(attemptNo, BACKOFF_MS.length - 1)];
|
|
149
|
+
try {
|
|
150
|
+
await waitFor(sleep(wait, signal));
|
|
151
|
+
} catch (error) {
|
|
152
|
+
if (error instanceof DecisionError) throw error;
|
|
153
|
+
throw new DecisionError("network", "decision model backoff failed", { provider: providerId });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
throw lastError ?? new DecisionError("network", "decision model request failed", { provider: providerId });
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
export { createTransport, failureForStatus, retryAfterMs };
|
|
163
|
+
|
|
164
|
+
//# sourceMappingURL=transport.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.mjs","names":[],"sources":["../../../src/decisions/transport.ts"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/decisions/types.ts
|
|
2
|
+
var DecisionError = class extends Error {
|
|
3
|
+
failure;
|
|
4
|
+
provider;
|
|
5
|
+
status;
|
|
6
|
+
retryAfterMs;
|
|
7
|
+
constructor(failure, message, options) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "DecisionError";
|
|
10
|
+
this.failure = failure;
|
|
11
|
+
this.provider = options?.provider ?? "unknown";
|
|
12
|
+
this.status = options?.status;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
function isDecisionObject(value) {
|
|
16
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
17
|
+
}
|
|
18
|
+
function readDecisionUsage(raw) {
|
|
19
|
+
if (!isDecisionObject(raw)) return null;
|
|
20
|
+
const input = raw.input_tokens;
|
|
21
|
+
const output = raw.output_tokens;
|
|
22
|
+
const usage = {};
|
|
23
|
+
if (typeof input === "number" && Number.isSafeInteger(input) && input >= 0) usage.inputTokens = input;
|
|
24
|
+
if (typeof output === "number" && Number.isSafeInteger(output) && output >= 0) usage.outputTokens = output;
|
|
25
|
+
return Object.keys(usage).length > 0 ? usage : null;
|
|
26
|
+
}
|
|
27
|
+
function isBooleanAnswer(answer) {
|
|
28
|
+
return answer?.type === "boolean";
|
|
29
|
+
}
|
|
30
|
+
function isChoiceAnswer(answer) {
|
|
31
|
+
return answer?.type === "choice";
|
|
32
|
+
}
|
|
33
|
+
function isScoreAnswer(answer) {
|
|
34
|
+
return answer?.type === "score";
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { DecisionError, isBooleanAnswer, isChoiceAnswer, isDecisionObject, isScoreAnswer, readDecisionUsage };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../../../src/decisions/types.ts"],"mappings":";AAkIA,IAAa,gBAAb,cAAmC,MAAM;CACvC;CACA;CACA;CACA;CAEA,YACE,SACA,SACA,SACA;EACA,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,UAAU;EACf,KAAK,WAAW,SAAS,YAAY;EACrC,KAAK,SAAS,SAAS;CACzB;AACF;AAGA,SAAgB,iBACd,OACqC;CACrC,OAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAgB,kBAAkB,KAAoC;CACpE,IAAI,CAAC,iBAAiB,GAAG,GACvB,OAAO;CAET,MAAM,QAAQ,IAAI;CAClB,MAAM,SAAS,IAAI;CACnB,MAAM,QAAuB,CAAC;CAC9B,IAAI,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK,KAAK,SAAS,GACvE,MAAM,cAAc;CAEtB,IACE,OAAO,WAAW,YAClB,OAAO,cAAc,MAAM,KAC3B,UAAU,GAEV,MAAM,eAAe;CAEvB,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,IAAI,QAAQ;AACjD;AAEA,SAAgB,gBACd,QACyB;CACzB,OAAO,QAAQ,SAAS;AAC1B;AAEA,SAAgB,eACd,QACwB;CACxB,OAAO,QAAQ,SAAS;AAC1B;AAEA,SAAgB,cACd,QACuB;CACvB,OAAO,QAAQ,SAAS;AAC1B"}
|
|
@@ -558,6 +558,7 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
558
558
|
subagentTasks;
|
|
559
559
|
subagentExecutionContext;
|
|
560
560
|
subagentContext;
|
|
561
|
+
onSubagentResolutionFailure;
|
|
561
562
|
preemption;
|
|
562
563
|
streamLimits;
|
|
563
564
|
streamedToolCallArgTallies = /* @__PURE__ */ new Map();
|
|
@@ -585,7 +586,7 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
585
586
|
preemptHaltReason;
|
|
586
587
|
pendingPreemptReturn = /* @__PURE__ */ new Set();
|
|
587
588
|
preemptRestartPending = /* @__PURE__ */ new Set();
|
|
588
|
-
constructor({ runId, signal, agents, langfuse, tokenCounter, indexTokenCountMap, calibrationRatio, fadingTier, fadingTiers, subagentUsageSink, subagentTasks, subagentScope, subagentExecutionContext, subagentContext, preemption, streamLimits, toolExecution, clientDelegatedToolNames }, dependencies) {
|
|
589
|
+
constructor({ runId, signal, agents, langfuse, tokenCounter, indexTokenCountMap, calibrationRatio, fadingTier, fadingTiers, subagentUsageSink, subagentTasks, subagentScope, subagentExecutionContext, subagentContext, onSubagentResolutionFailure, preemption, streamLimits, toolExecution, clientDelegatedToolNames }, dependencies) {
|
|
589
590
|
super();
|
|
590
591
|
this.supportsMultiAgentChildren = dependencies != null;
|
|
591
592
|
this.graphFactory = dependencies?.graphFactory ?? ((request) => {
|
|
@@ -601,6 +602,7 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
601
602
|
this.subagentScope = subagentScope === true;
|
|
602
603
|
this.subagentExecutionContext = subagentExecutionContext;
|
|
603
604
|
this.subagentContext = subagentContext;
|
|
605
|
+
this.onSubagentResolutionFailure = onSubagentResolutionFailure;
|
|
604
606
|
this.preemption = preemption;
|
|
605
607
|
this.streamLimits = resolveStreamLimits(streamLimits);
|
|
606
608
|
this.toolExecution = toolExecution;
|
|
@@ -2235,6 +2237,7 @@ var StandardGraph = class StandardGraph extends Graph {
|
|
|
2235
2237
|
usageSink: this.subagentUsageSink,
|
|
2236
2238
|
taskConfig: this.subagentTasks,
|
|
2237
2239
|
subagentContext: this.subagentContext,
|
|
2240
|
+
onResolutionFailure: this.onSubagentResolutionFailure,
|
|
2238
2241
|
streamLimits: this.streamLimits,
|
|
2239
2242
|
humanInTheLoop: this.humanInTheLoop,
|
|
2240
2243
|
checkpointer: this.compileOptions?.checkpointer,
|