nestjs-langchain 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -5
- package/dist/agent.d.ts +16 -2
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +31 -23
- package/dist/agent.js.map +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -1
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +2 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/messages.d.ts +7 -0
- package/dist/errors/messages.d.ts.map +1 -1
- package/dist/errors/messages.js +18 -3
- package/dist/errors/messages.js.map +1 -1
- package/dist/errors/structured-output.error.d.ts +22 -0
- package/dist/errors/structured-output.error.d.ts.map +1 -0
- package/dist/errors/structured-output.error.js +23 -0
- package/dist/errors/structured-output.error.js.map +1 -0
- package/dist/errors/unwrap-middleware-error.util.d.ts +10 -0
- package/dist/errors/unwrap-middleware-error.util.d.ts.map +1 -0
- package/dist/errors/unwrap-middleware-error.util.js +17 -0
- package/dist/errors/unwrap-middleware-error.util.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/completed-run.interface.d.ts +1 -1
- package/dist/interfaces/completed-run.interface.d.ts.map +1 -1
- package/dist/interfaces/run-options.interface.d.ts +21 -0
- package/dist/interfaces/run-options.interface.d.ts.map +1 -0
- package/dist/interfaces/run-options.interface.js +2 -0
- package/dist/interfaces/run-options.interface.js.map +1 -0
- package/dist/output/index.d.ts +3 -0
- package/dist/output/index.d.ts.map +1 -0
- package/dist/output/index.js +3 -0
- package/dist/output/index.js.map +1 -0
- package/dist/output/run-output.d.ts +43 -0
- package/dist/output/run-output.d.ts.map +1 -0
- package/dist/output/run-output.js +107 -0
- package/dist/output/run-output.js.map +1 -0
- package/dist/output/structured-output.middleware.d.ts +22 -0
- package/dist/output/structured-output.middleware.d.ts.map +1 -0
- package/dist/output/structured-output.middleware.js +40 -0
- package/dist/output/structured-output.middleware.js.map +1 -0
- package/dist/run/answered-calls.util.d.ts +10 -0
- package/dist/run/answered-calls.util.d.ts.map +1 -0
- package/dist/run/answered-calls.util.js +12 -0
- package/dist/run/answered-calls.util.js.map +1 -0
- package/dist/run/index.d.ts +2 -0
- package/dist/run/index.d.ts.map +1 -1
- package/dist/run/index.js +2 -0
- package/dist/run/index.js.map +1 -1
- package/dist/run/run-summary.util.d.ts +10 -3
- package/dist/run/run-summary.util.d.ts.map +1 -1
- package/dist/run/run-summary.util.js +18 -6
- package/dist/run/run-summary.util.js.map +1 -1
- package/dist/run/usage-aside.d.ts +23 -0
- package/dist/run/usage-aside.d.ts.map +1 -0
- package/dist/run/usage-aside.js +33 -0
- package/dist/run/usage-aside.js.map +1 -0
- package/dist/tools/tool-errors.middleware.d.ts +7 -1
- package/dist/tools/tool-errors.middleware.d.ts.map +1 -1
- package/dist/tools/tool-errors.middleware.js +81 -16
- package/dist/tools/tool-errors.middleware.js.map +1 -1
- package/dist/tools/tool-name.util.d.ts.map +1 -1
- package/dist/tools/tool-name.util.js +1 -3
- package/dist/tools/tool-name.util.js.map +1 -1
- package/lib/agent.ts +61 -15
- package/lib/constants.ts +8 -0
- package/lib/errors/index.ts +2 -0
- package/lib/errors/messages.ts +43 -3
- package/lib/errors/structured-output.error.ts +23 -0
- package/lib/errors/unwrap-middleware-error.util.ts +19 -0
- package/lib/index.ts +6 -1
- package/lib/interfaces/completed-run.interface.ts +1 -1
- package/lib/interfaces/run-options.interface.ts +21 -0
- package/lib/output/index.ts +5 -0
- package/lib/output/run-output.ts +154 -0
- package/lib/output/structured-output.middleware.ts +44 -0
- package/lib/run/answered-calls.util.ts +16 -0
- package/lib/run/index.ts +2 -0
- package/lib/run/run-summary.util.ts +33 -11
- package/lib/run/usage-aside.ts +41 -0
- package/lib/tools/tool-errors.middleware.ts +104 -10
- package/lib/tools/tool-name.util.ts +1 -4
- package/package.json +28 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-options.interface.d.ts","sourceRoot":"","sources":["../../lib/interfaces/run-options.interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAEnC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-options.interface.js","sourceRoot":"","sources":["../../lib/interfaces/run-options.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/output/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EACL,YAAY,EACZ,gBAAgB,GACjB,MAAM,mCAAmC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/output/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EACL,YAAY,EACZ,gBAAgB,GACjB,MAAM,mCAAmC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { TypedToolStrategy } from 'langchain';
|
|
2
|
+
import { ZodType } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* The structured output one run asked for: the strategy its model calls use,
|
|
5
|
+
* and the answer parsed by the schema.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare class RunOutput {
|
|
10
|
+
#private;
|
|
11
|
+
private readonly schema;
|
|
12
|
+
private readonly agent;
|
|
13
|
+
/**
|
|
14
|
+
* Through a tool, whatever the model (see #274). One per run, which counts
|
|
15
|
+
* its own retries (see #151).
|
|
16
|
+
*/
|
|
17
|
+
readonly strategy: TypedToolStrategy;
|
|
18
|
+
/** The tool the model answers through. */
|
|
19
|
+
readonly toolName = "extract-output";
|
|
20
|
+
private readonly prefix;
|
|
21
|
+
/**
|
|
22
|
+
* @param schema The run's `output` schema.
|
|
23
|
+
* @param agent The agent's name, for the errors.
|
|
24
|
+
* @throws AgentRunError when the schema has no JSON Schema form, or is not
|
|
25
|
+
* an object with named fields.
|
|
26
|
+
*/
|
|
27
|
+
constructor(schema: ZodType, agent: string);
|
|
28
|
+
private retry;
|
|
29
|
+
/**
|
|
30
|
+
* @param error What a model call threw.
|
|
31
|
+
* @returns A `StructuredOutputError` for LangChain's parsing failures, the
|
|
32
|
+
* error itself otherwise.
|
|
33
|
+
*/
|
|
34
|
+
failure(error: unknown): unknown;
|
|
35
|
+
/**
|
|
36
|
+
* @param structuredResponse What the run left in `structuredResponse`.
|
|
37
|
+
* @returns The answer, as the schema parses it.
|
|
38
|
+
* @throws StructuredOutputError when the answer is missing or invalid.
|
|
39
|
+
*/
|
|
40
|
+
read(structuredResponse: unknown): unknown;
|
|
41
|
+
private invalid;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=run-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-output.d.ts","sourceRoot":"","sources":["../../lib/output/run-output.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,iBAAiB,EAClB,MAAM,WAAW,CAAC;AACnB,OAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAqBjC;;;;;GAKG;AACH,qBAAa,SAAS;;IAkBlB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAlBxB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,oBAAe;IAEhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;OAKG;gBAEgB,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,MAAM;IAqChC,OAAO,CAAC,KAAK;IAUb;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAiBhC;;;;OAIG;IACH,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,OAAO;IAmB1C,OAAO,CAAC,OAAO;CAOhB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { toJsonSchema } from '@langchain/core/utils/json_schema';
|
|
2
|
+
import { MultipleStructuredOutputsError, StructuredOutputParsingError, toolStrategy, } from 'langchain';
|
|
3
|
+
import z from 'zod';
|
|
4
|
+
import { OUTPUT_TOOL } from '../constants.js';
|
|
5
|
+
import { AgentRunError, StructuredOutputError } from '../errors/index.js';
|
|
6
|
+
import { agentPrefix, noOutputJsonSchemaForm, outputNotAnObject, structuredOutputInvalid, structuredOutputMissing, structuredOutputMultiple, } from '../errors/messages.js';
|
|
7
|
+
import { messageOf } from '../logging/index.js';
|
|
8
|
+
// The default of LangChain's own retry middlewares. See #151.
|
|
9
|
+
const MAX_RETRIES = 2;
|
|
10
|
+
// LangChain's default for a Zod schema, which its JSON Schema path leaves
|
|
11
|
+
// empty. See #282.
|
|
12
|
+
const OUTPUT_DESCRIPTION = "Tool for extracting structured output from the model's response.";
|
|
13
|
+
/**
|
|
14
|
+
* The structured output one run asked for: the strategy its model calls use,
|
|
15
|
+
* and the answer parsed by the schema.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export class RunOutput {
|
|
20
|
+
schema;
|
|
21
|
+
agent;
|
|
22
|
+
/**
|
|
23
|
+
* Through a tool, whatever the model (see #274). One per run, which counts
|
|
24
|
+
* its own retries (see #151).
|
|
25
|
+
*/
|
|
26
|
+
strategy;
|
|
27
|
+
/** The tool the model answers through. */
|
|
28
|
+
toolName = OUTPUT_TOOL;
|
|
29
|
+
#retries = 0;
|
|
30
|
+
prefix;
|
|
31
|
+
/**
|
|
32
|
+
* @param schema The run's `output` schema.
|
|
33
|
+
* @param agent The agent's name, for the errors.
|
|
34
|
+
* @throws AgentRunError when the schema has no JSON Schema form, or is not
|
|
35
|
+
* an object with named fields.
|
|
36
|
+
*/
|
|
37
|
+
constructor(schema, agent) {
|
|
38
|
+
this.schema = schema;
|
|
39
|
+
this.agent = agent;
|
|
40
|
+
this.prefix = agentPrefix(agent);
|
|
41
|
+
// LangChain's own conversion, run before any model call.
|
|
42
|
+
let json;
|
|
43
|
+
try {
|
|
44
|
+
json = toJsonSchema(schema);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw new AgentRunError(noOutputJsonSchemaForm(this.prefix, messageOf(error)), agent, { cause: error });
|
|
48
|
+
}
|
|
49
|
+
// A tool's parameters. LangChain takes them as a JSON Schema with
|
|
50
|
+
// `properties` at every version, as a Zod schema other than an object at
|
|
51
|
+
// recent ones only. See #282.
|
|
52
|
+
if (json.type !== 'object' || !('properties' in json)) {
|
|
53
|
+
throw new AgentRunError(outputNotAnObject(this.prefix), agent);
|
|
54
|
+
}
|
|
55
|
+
// LangChain names the tool after the title.
|
|
56
|
+
this.strategy = toolStrategy({
|
|
57
|
+
...json,
|
|
58
|
+
type: 'object',
|
|
59
|
+
title: OUTPUT_TOOL,
|
|
60
|
+
description: json.description ?? OUTPUT_DESCRIPTION,
|
|
61
|
+
}, { handleError: (error) => this.retry(error) });
|
|
62
|
+
}
|
|
63
|
+
// What LangChain sends back by default, until the retries run out.
|
|
64
|
+
retry(error) {
|
|
65
|
+
this.#retries += 1;
|
|
66
|
+
if (this.#retries > MAX_RETRIES) {
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
return error.message;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* @param error What a model call threw.
|
|
73
|
+
* @returns A `StructuredOutputError` for LangChain's parsing failures, the
|
|
74
|
+
* error itself otherwise.
|
|
75
|
+
*/
|
|
76
|
+
failure(error) {
|
|
77
|
+
// Never LangChain's messages, which name the internal tool.
|
|
78
|
+
if (error instanceof StructuredOutputParsingError) {
|
|
79
|
+
return this.invalid(error.errors.join(' '), error);
|
|
80
|
+
}
|
|
81
|
+
if (error instanceof MultipleStructuredOutputsError) {
|
|
82
|
+
return new StructuredOutputError(structuredOutputMultiple(this.prefix, error.toolNames.length), this.agent, { cause: error });
|
|
83
|
+
}
|
|
84
|
+
return error;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* @param structuredResponse What the run left in `structuredResponse`.
|
|
88
|
+
* @returns The answer, as the schema parses it.
|
|
89
|
+
* @throws StructuredOutputError when the answer is missing or invalid.
|
|
90
|
+
*/
|
|
91
|
+
read(structuredResponse) {
|
|
92
|
+
if (structuredResponse === undefined) {
|
|
93
|
+
throw new StructuredOutputError(structuredOutputMissing(this.prefix), this.agent);
|
|
94
|
+
}
|
|
95
|
+
// LangChain checks the JSON Schema only: Zod also applies transforms and
|
|
96
|
+
// refinements. See #151.
|
|
97
|
+
const parsed = this.schema.safeParse(structuredResponse);
|
|
98
|
+
if (!parsed.success) {
|
|
99
|
+
throw this.invalid(z.prettifyError(parsed.error), parsed.error);
|
|
100
|
+
}
|
|
101
|
+
return parsed.data;
|
|
102
|
+
}
|
|
103
|
+
invalid(reason, cause) {
|
|
104
|
+
return new StructuredOutputError(structuredOutputInvalid(this.prefix, reason), this.agent, { cause });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=run-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-output.js","sourceRoot":"","sources":["../../lib/output/run-output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RunOutput } from './run-output.js';
|
|
2
|
+
/**
|
|
3
|
+
* The `configurable` entry that hands a run's output to the middleware. A
|
|
4
|
+
* text run sets it to `null`, or it would inherit the output of the run it is
|
|
5
|
+
* nested in, which LangChain hands down. See #295.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
* @param output The run's output, if it asked for one.
|
|
9
|
+
* @returns The entry to put in `configurable`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const outputConfig: (output: RunOutput | undefined) => {
|
|
12
|
+
"nestjs-langchain:output": RunOutput | null;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Sets the `responseFormat` of each model call of a run that asked for an
|
|
16
|
+
* `output`, so that one compiled agent serves text and structured runs.
|
|
17
|
+
* LangChain's parsing failures come out as a `StructuredOutputError`.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export declare const structuredOutput: () => import("langchain").AgentMiddleware<undefined, undefined, unknown, readonly (import("@langchain/core/tools").ServerTool | import("@langchain/core/tools").ClientTool)[], readonly []>;
|
|
22
|
+
//# sourceMappingURL=structured-output.middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-output.middleware.d.ts","sourceRoot":"","sources":["../../lib/output/structured-output.middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,SAAS,GAAG,SAAS;;CAExD,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,6LAgBzB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createMiddleware } from 'langchain';
|
|
2
|
+
import { RunOutput } from './run-output.js';
|
|
3
|
+
// The run's output travels under our own key in `configurable`, which
|
|
4
|
+
// LangGraph keeps out of the trace metadata and checkpoints. See #151.
|
|
5
|
+
const OUTPUT_KEY = 'nestjs-langchain:output';
|
|
6
|
+
/**
|
|
7
|
+
* The `configurable` entry that hands a run's output to the middleware. A
|
|
8
|
+
* text run sets it to `null`, or it would inherit the output of the run it is
|
|
9
|
+
* nested in, which LangChain hands down. See #295.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
* @param output The run's output, if it asked for one.
|
|
13
|
+
* @returns The entry to put in `configurable`.
|
|
14
|
+
*/
|
|
15
|
+
export const outputConfig = (output) => ({
|
|
16
|
+
[OUTPUT_KEY]: output ?? null,
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Sets the `responseFormat` of each model call of a run that asked for an
|
|
20
|
+
* `output`, so that one compiled agent serves text and structured runs.
|
|
21
|
+
* LangChain's parsing failures come out as a `StructuredOutputError`.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export const structuredOutput = () => createMiddleware({
|
|
26
|
+
name: 'structuredOutput',
|
|
27
|
+
wrapModelCall: async (request, handler) => {
|
|
28
|
+
const output = request.runtime.configurable?.[OUTPUT_KEY];
|
|
29
|
+
if (!(output instanceof RunOutput)) {
|
|
30
|
+
return handler(request);
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
return await handler({ ...request, responseFormat: output.strategy });
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throw output.failure(error);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=structured-output.middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-output.middleware.js","sourceRoot":"","sources":["../../lib/output/structured-output.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,sEAAsE;AACtE,uEAAuE;AACvE,MAAM,UAAU,GAAG,yBAAyB,CAAC;AAE7C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAA6B,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC,UAAU,CAAC,EAAE,MAAM,IAAI,IAAI;CAC7B,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE,CACnC,gBAAgB,CAAC;IACf,IAAI,EAAE,kBAAkB;IACxB,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QACxC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,CAAC,CAAC;QAE1D,IAAI,CAAC,CAAC,MAAM,YAAY,SAAS,CAAC,EAAE,CAAC;YACnC,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ids of the tool calls the messages answer: the tool node answers every
|
|
3
|
+
* call it runs. Structural rather than `BaseMessage`. See #52.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
* @param messages A run's messages.
|
|
7
|
+
* @returns The ids their `tool_call_id`s answer.
|
|
8
|
+
*/
|
|
9
|
+
export declare const answeredCalls: (messages: readonly object[]) => Set<string>;
|
|
10
|
+
//# sourceMappingURL=answered-calls.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answered-calls.util.d.ts","sourceRoot":"","sources":["../../lib/run/answered-calls.util.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,UAAU,SAAS,MAAM,EAAE,KAAG,GAAG,CAAC,MAAM,CAOnE,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ids of the tool calls the messages answer: the tool node answers every
|
|
3
|
+
* call it runs. Structural rather than `BaseMessage`. See #52.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
* @param messages A run's messages.
|
|
7
|
+
* @returns The ids their `tool_call_id`s answer.
|
|
8
|
+
*/
|
|
9
|
+
export const answeredCalls = (messages) => new Set(messages.flatMap((message) => 'tool_call_id' in message && typeof message.tool_call_id === 'string'
|
|
10
|
+
? [message.tool_call_id]
|
|
11
|
+
: []));
|
|
12
|
+
//# sourceMappingURL=answered-calls.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answered-calls.util.js","sourceRoot":"","sources":["../../lib/run/answered-calls.util.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAA2B,EAAe,EAAE,CACxE,IAAI,GAAG,CACL,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAC3B,cAAc,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ;IACnE,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IACxB,CAAC,CAAC,EAAE,CACP,CACF,CAAC"}
|
package/dist/run/index.d.ts
CHANGED
package/dist/run/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/run/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/run/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/run/index.js
CHANGED
package/dist/run/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/run/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/run/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -3,11 +3,16 @@ interface MessageLike {
|
|
|
3
3
|
usage_metadata?: UsageMetadata;
|
|
4
4
|
tool_calls?: {
|
|
5
5
|
name: string;
|
|
6
|
+
id?: string;
|
|
6
7
|
}[];
|
|
8
|
+
tool_call_id?: string;
|
|
7
9
|
}
|
|
8
10
|
/** What a run did and cost. */
|
|
9
11
|
export interface RunSummary {
|
|
10
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Every tool call that reached the agent's tools, failed and unknown ones
|
|
14
|
+
* included, but not the one returning a structured output.
|
|
15
|
+
*/
|
|
11
16
|
tools: string[];
|
|
12
17
|
/**
|
|
13
18
|
* Summed over the run's model calls; absent when the provider reports no
|
|
@@ -24,8 +29,10 @@ export interface RunSummary {
|
|
|
24
29
|
*
|
|
25
30
|
* @internal
|
|
26
31
|
* @param messages The messages of the finished run.
|
|
27
|
-
* @
|
|
32
|
+
* @param outputTool The tool the model returned a structured output through.
|
|
33
|
+
* @param aside The usage of the replies the run left out of its messages.
|
|
34
|
+
* @returns The tool calls that reached the tools, and the tokens if reported.
|
|
28
35
|
*/
|
|
29
|
-
export declare const summariseRun: (messages: readonly MessageLike[]) => RunSummary;
|
|
36
|
+
export declare const summariseRun: (messages: readonly MessageLike[], outputTool?: string, aside?: readonly UsageMetadata[]) => RunSummary;
|
|
30
37
|
export {};
|
|
31
38
|
//# sourceMappingURL=run-summary.util.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-summary.util.d.ts","sourceRoot":"","sources":["../../lib/run/run-summary.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,aAAa,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"run-summary.util.d.ts","sourceRoot":"","sources":["../../lib/run/run-summary.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAI7E,UAAU,WAAW;IACnB,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,+BAA+B;AAC/B,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,SAAS,WAAW,EAAE,EAChC,aAAa,MAAM,EACnB,QAAO,SAAS,aAAa,EAAO,KACnC,UAmCF,CAAC"}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
import { mergeUsageMetadata } from '@langchain/core/messages';
|
|
2
|
+
import { answeredCalls } from './answered-calls.util.js';
|
|
2
3
|
/**
|
|
3
4
|
* What a finished run cost, read off the messages it returned.
|
|
4
5
|
*
|
|
5
6
|
* @internal
|
|
6
7
|
* @param messages The messages of the finished run.
|
|
7
|
-
* @
|
|
8
|
+
* @param outputTool The tool the model returned a structured output through.
|
|
9
|
+
* @param aside The usage of the replies the run left out of its messages.
|
|
10
|
+
* @returns The tool calls that reached the tools, and the tokens if reported.
|
|
8
11
|
*/
|
|
9
|
-
export const summariseRun = (messages) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
export const summariseRun = (messages, outputTool, aside = []) => {
|
|
13
|
+
// One that did not run has no answer (see #290). One with no id cannot be
|
|
14
|
+
// told, and counts (see #295).
|
|
15
|
+
const answered = answeredCalls(messages);
|
|
16
|
+
const tools = messages
|
|
17
|
+
.flatMap((message) => message.tool_calls ?? [])
|
|
18
|
+
.filter(({ name, id }) => name !== outputTool && (id === undefined || answered.has(id)))
|
|
19
|
+
.map((call) => call.name);
|
|
20
|
+
const reported = [
|
|
21
|
+
...messages
|
|
22
|
+
.map((message) => message.usage_metadata)
|
|
23
|
+
.filter((usage) => usage !== undefined),
|
|
24
|
+
...aside,
|
|
25
|
+
];
|
|
14
26
|
if (reported.length === 0) {
|
|
15
27
|
return { tools };
|
|
16
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-summary.util.js","sourceRoot":"","sources":["../../lib/run/run-summary.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAiB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"run-summary.util.js","sourceRoot":"","sources":["../../lib/run/run-summary.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAiB,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAuBzD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,QAAgC,EAChC,UAAmB,EACnB,QAAkC,EAAE,EACxB,EAAE;IACd,0EAA0E;IAC1E,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEzC,MAAM,KAAK,GAAG,QAAQ;SACnB,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;SAC9C,MAAM,CACL,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,CACf,IAAI,KAAK,UAAU,IAAI,CAAC,EAAE,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAChE;SACA,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE5B,MAAM,QAAQ,GAAG;QACf,GAAG,QAAQ;aACR,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC;aACxC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;QACzC,GAAG,KAAK;KACT,CAAC;IAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,oEAAoE;IACpE,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAExE,OAAO;QACL,KAAK;QACL,MAAM,EAAE;YACN,KAAK,EAAE,KAAK,CAAC,YAAY;YACzB,MAAM,EAAE,KAAK,CAAC,aAAa;YAC3B,KAAK,EAAE,KAAK,CAAC,YAAY;SAC1B;KACF,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { UsageMetadata } from '@langchain/core/messages';
|
|
2
|
+
/**
|
|
3
|
+
* The usage of the model's replies a run leaves out of its messages, which its
|
|
4
|
+
* `tokens` still count: those the `unknownTools` re-ask asks again about. One
|
|
5
|
+
* per run, handed to the middlewares in `configurable`. See #296.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare class UsageAside {
|
|
10
|
+
readonly usage: UsageMetadata[];
|
|
11
|
+
/** The `configurable` entry that hands it to the middlewares. */
|
|
12
|
+
get config(): Record<string, UsageAside>;
|
|
13
|
+
/**
|
|
14
|
+
* @param usage A left-out reply's usage, when the provider reported it.
|
|
15
|
+
*/
|
|
16
|
+
add(usage: UsageMetadata | undefined): void;
|
|
17
|
+
/**
|
|
18
|
+
* @param configurable A middleware's `runtime.configurable`.
|
|
19
|
+
* @returns The run's aside, when it set one.
|
|
20
|
+
*/
|
|
21
|
+
static of(configurable: Record<string, unknown> | undefined): UsageAside | undefined;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=usage-aside.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-aside.d.ts","sourceRoot":"","sources":["../../lib/run/usage-aside.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAKzD;;;;;;GAMG;AACH,qBAAa,UAAU;IACrB,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,CAAM;IAErC,iEAAiE;IACjE,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAEvC;IAED;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI;IAM3C;;;OAGG;IACH,MAAM,CAAC,EAAE,CACP,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAChD,UAAU,GAAG,SAAS;CAK1B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Our own key in `configurable`, like the run's output. See #296.
|
|
2
|
+
const USAGE_ASIDE_KEY = 'nestjs-langchain:usage-aside';
|
|
3
|
+
/**
|
|
4
|
+
* The usage of the model's replies a run leaves out of its messages, which its
|
|
5
|
+
* `tokens` still count: those the `unknownTools` re-ask asks again about. One
|
|
6
|
+
* per run, handed to the middlewares in `configurable`. See #296.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export class UsageAside {
|
|
11
|
+
usage = [];
|
|
12
|
+
/** The `configurable` entry that hands it to the middlewares. */
|
|
13
|
+
get config() {
|
|
14
|
+
return { [USAGE_ASIDE_KEY]: this };
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* @param usage A left-out reply's usage, when the provider reported it.
|
|
18
|
+
*/
|
|
19
|
+
add(usage) {
|
|
20
|
+
if (usage) {
|
|
21
|
+
this.usage.push(usage);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @param configurable A middleware's `runtime.configurable`.
|
|
26
|
+
* @returns The run's aside, when it set one.
|
|
27
|
+
*/
|
|
28
|
+
static of(configurable) {
|
|
29
|
+
const aside = configurable?.[USAGE_ASIDE_KEY];
|
|
30
|
+
return aside instanceof UsageAside ? aside : undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=usage-aside.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-aside.js","sourceRoot":"","sources":["../../lib/run/usage-aside.ts"],"names":[],"mappings":"AAEA,kEAAkE;AAClE,MAAM,eAAe,GAAG,8BAA8B,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,OAAO,UAAU;IACZ,KAAK,GAAoB,EAAE,CAAC;IAErC,iEAAiE;IACjE,IAAI,MAAM;QACR,OAAO,EAAE,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,KAAgC;QAClC,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,EAAE,CACP,YAAiD;QAEjD,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC,eAAe,CAAC,CAAC;QAE9C,OAAO,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACzD,CAAC;CACF"}
|
|
@@ -16,6 +16,12 @@ export declare const toolErrors: (reporter: RunReporter) => import("langchain").
|
|
|
16
16
|
/**
|
|
17
17
|
* Reports a call to a tool the agent does not have. LangChain's tool node
|
|
18
18
|
* answers the model itself, without throwing, so `toolErrors` never sees it.
|
|
19
|
+
* One the model invents with the `extract-` prefix never reaches the tool
|
|
20
|
+
* node: it is answered here, as the tool node answers any other, and so is
|
|
21
|
+
* any call LangChain leaves unanswered.
|
|
22
|
+
*
|
|
23
|
+
* @param reporter The agent's reporter.
|
|
24
|
+
* @param tools The names of the agent's tools, which the answer lists.
|
|
19
25
|
*/
|
|
20
|
-
export declare const unknownTools: (reporter: RunReporter) => import("langchain").AgentMiddleware<undefined, undefined, unknown, readonly (import("@langchain/core/tools").ServerTool | import("@langchain/core/tools").ClientTool)[], readonly []>;
|
|
26
|
+
export declare const unknownTools: (reporter: RunReporter, tools: string[]) => import("langchain").AgentMiddleware<undefined, undefined, unknown, readonly (import("@langchain/core/tools").ServerTool | import("@langchain/core/tools").ClientTool)[], readonly []>;
|
|
21
27
|
//# sourceMappingURL=tool-errors.middleware.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-errors.middleware.d.ts","sourceRoot":"","sources":["../../lib/tools/tool-errors.middleware.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tool-errors.middleware.d.ts","sourceRoot":"","sources":["../../lib/tools/tool-errors.middleware.ts"],"names":[],"mappings":"AAaA,OAAO,EAAmB,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAkBnE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,GAAI,UAAU,WAAW,0LAwB5C,CAAC;AAEL;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,UAAU,WAAW,EAAE,OAAO,MAAM,EAAE,0LAiFlE,CAAC"}
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
+
import { AIMessage, ToolMessage, } from '@langchain/core/messages';
|
|
1
2
|
import { createMiddleware, toolErrorMiddleware, ToolInvocationError, } from 'langchain';
|
|
2
|
-
import {
|
|
3
|
+
import { OUTPUT_TOOL, STRUCTURED_OUTPUT_PREFIX } from '../constants.js';
|
|
4
|
+
import { invalidTool, toolNotRun, unknownTool } from '../errors/messages.js';
|
|
3
5
|
import { reportToolError } from '../logging/index.js';
|
|
6
|
+
import { answeredCalls, UsageAside } from '../run/index.js';
|
|
7
|
+
// The default of LangChain's own retry middlewares. See #151.
|
|
8
|
+
const MAX_REASKS = 2;
|
|
9
|
+
// LangChain routes every `extract-` call to structured output, never to the
|
|
10
|
+
// tools: one the model invents, which is not the run's output, neither runs
|
|
11
|
+
// nor gets an answer. See #264.
|
|
12
|
+
const isInvented = ({ name }) => name.startsWith(STRUCTURED_OUTPUT_PREFIX) && name !== OUTPUT_TOOL;
|
|
13
|
+
const invented = (calls) => calls.filter(isInvented);
|
|
14
|
+
const callsOf = (message) => AIMessage.isInstance(message) ? (message.tool_calls ?? []) : [];
|
|
4
15
|
/**
|
|
5
16
|
* Turns a failed tool call into the text the model receives, LangChain's own,
|
|
6
17
|
* without the stack (and its server paths) LangChain puts in a schema failure.
|
|
@@ -36,20 +47,74 @@ export const toolErrors = (reporter) => toolErrorMiddleware({
|
|
|
36
47
|
/**
|
|
37
48
|
* Reports a call to a tool the agent does not have. LangChain's tool node
|
|
38
49
|
* answers the model itself, without throwing, so `toolErrors` never sees it.
|
|
50
|
+
* One the model invents with the `extract-` prefix never reaches the tool
|
|
51
|
+
* node: it is answered here, as the tool node answers any other, and so is
|
|
52
|
+
* any call LangChain leaves unanswered.
|
|
53
|
+
*
|
|
54
|
+
* @param reporter The agent's reporter.
|
|
55
|
+
* @param tools The names of the agent's tools, which the answer lists.
|
|
39
56
|
*/
|
|
40
|
-
export const unknownTools = (reporter) =>
|
|
41
|
-
name
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
export const unknownTools = (reporter, tools) => {
|
|
58
|
+
const report = ({ name, id }) => reportToolError(reporter, {
|
|
59
|
+
tool: name,
|
|
60
|
+
callId: id ?? '',
|
|
61
|
+
reason: 'unknown-tool',
|
|
62
|
+
error: new Error(unknownTool()),
|
|
63
|
+
durationMs: 0,
|
|
64
|
+
});
|
|
65
|
+
const answer = (call) => new ToolMessage({
|
|
66
|
+
content: isInvented(call)
|
|
67
|
+
? invalidTool(call.name, tools)
|
|
68
|
+
: toolNotRun(call.name),
|
|
69
|
+
tool_call_id: call.id ?? '',
|
|
70
|
+
name: call.name,
|
|
71
|
+
status: 'error',
|
|
72
|
+
});
|
|
73
|
+
// Every call without an answer gets one right after its message, which
|
|
74
|
+
// providers require: an invented one (see #264), or one LangChain left out
|
|
75
|
+
// next to the output (see #290). In the request, which the output's retry
|
|
76
|
+
// reaches without `beforeModel`; rebuilt on every model call, so only the
|
|
77
|
+
// reply just made is reported. See #297.
|
|
78
|
+
const answerLeft = (messages) => {
|
|
79
|
+
const done = answeredCalls(messages);
|
|
80
|
+
const left = (message) => callsOf(message).filter(({ id }) => id !== undefined && !done.has(id));
|
|
81
|
+
invented(left(messages.findLast((m) => AIMessage.isInstance(m)))).forEach(report);
|
|
82
|
+
return messages.flatMap((message) => [
|
|
83
|
+
message,
|
|
84
|
+
...left(message).map(answer),
|
|
85
|
+
]);
|
|
86
|
+
};
|
|
87
|
+
return createMiddleware({
|
|
88
|
+
name: 'unknownTools',
|
|
89
|
+
// Alone, LangChain would end the run: answered, and the model asked again,
|
|
90
|
+
// as `modelRetryMiddleware` asks it again. See #264.
|
|
91
|
+
wrapModelCall: async (request, handler) => {
|
|
92
|
+
let current = { ...request, messages: answerLeft(request.messages) };
|
|
93
|
+
for (let asked = 0;; asked += 1) {
|
|
94
|
+
const reply = await handler(current);
|
|
95
|
+
const calls = callsOf(reply);
|
|
96
|
+
const left = invented(calls);
|
|
97
|
+
if (calls.length === 0 || left.length < calls.length) {
|
|
98
|
+
return reply;
|
|
99
|
+
}
|
|
100
|
+
left.forEach(report);
|
|
101
|
+
if (asked === MAX_REASKS) {
|
|
102
|
+
return reply;
|
|
103
|
+
}
|
|
104
|
+
// Left out of the run's messages, but paid for. See #296.
|
|
105
|
+
UsageAside.of(request.runtime.configurable)?.add(AIMessage.isInstance(reply) ? reply.usage_metadata : undefined);
|
|
106
|
+
current = {
|
|
107
|
+
...current,
|
|
108
|
+
messages: [...current.messages, reply, ...left.map(answer)],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
wrapToolCall: (request, handler) => {
|
|
113
|
+
if (!request.tool) {
|
|
114
|
+
report(request.toolCall);
|
|
115
|
+
}
|
|
116
|
+
return handler(request);
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
};
|
|
55
120
|
//# sourceMappingURL=tool-errors.middleware.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-errors.middleware.js","sourceRoot":"","sources":["../../lib/tools/tool-errors.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-errors.middleware.js","sourceRoot":"","sources":["../../lib/tools/tool-errors.middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-name.util.d.ts","sourceRoot":"","sources":["../../lib/tools/tool-name.util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tool-name.util.d.ts","sourceRoot":"","sources":["../../lib/tools/tool-name.util.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,eAAe,GAC1B,UAAU,MAAM,GAAG,SAAS,EAC5B,QAAQ,MAAM,EACd,OAAO,MAAM,KACZ,MAcF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GACjC,OAAO;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,KACvC,MAAM,EAgBR,CAAC"}
|