llm-exe 3.0.0-beta.1 → 3.0.0-beta.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/index.d.mts +38 -20
- package/dist/index.d.ts +38 -20
- package/dist/index.js +180 -51
- package/dist/index.mjs +180 -51
- package/package.json +1 -1
- package/readme.md +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -92,7 +92,7 @@ declare abstract class BaseParser<T = any, TInput = string> {
|
|
|
92
92
|
declare abstract class BaseParserWithJson<S extends JSONSchema | undefined = undefined, T = S extends JSONSchema ? FromSchema<S> : Record<string, any>, TInput = string> extends BaseParser<T, TInput> {
|
|
93
93
|
schema: S;
|
|
94
94
|
validateSchema: boolean;
|
|
95
|
-
constructor(name: string, options:
|
|
95
|
+
constructor(name: string, options: ParserSchemaOptions<S>);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
@@ -111,25 +111,31 @@ declare class StringParser extends BaseParser<string> {
|
|
|
111
111
|
parse(text: string, _attributes?: Record<string, any>): string;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
type BooleanParserMatch = "exact" | "extract";
|
|
115
|
+
interface BooleanParserOptions {
|
|
116
|
+
match?: BooleanParserMatch;
|
|
117
|
+
}
|
|
114
118
|
/**
|
|
115
119
|
* v3 parser contract:
|
|
116
120
|
* Category: strict
|
|
117
|
-
* Mode:
|
|
121
|
+
* Mode: exact
|
|
118
122
|
*
|
|
119
123
|
* Accepts only documented boolean literals after trim/lowercase.
|
|
120
|
-
* Returns true/false only when input is recognized.
|
|
121
|
-
*
|
|
122
|
-
*
|
|
124
|
+
* Returns true/false only when input is recognized. Pass match: "extract" to
|
|
125
|
+
* extract one documented boolean literal from surrounding text.
|
|
126
|
+
* Throws LlmExeError(parser.parse_failed) for empty or unrecognized input.
|
|
127
|
+
* Invalid input types throw LlmExeError(parser.invalid_input).
|
|
123
128
|
* Error context does not include input content unless LLM_EXE_DEBUG is enabled.
|
|
124
129
|
*
|
|
125
130
|
*/
|
|
126
131
|
declare class BooleanParser extends BaseParser<boolean> {
|
|
127
|
-
|
|
132
|
+
private match;
|
|
133
|
+
constructor(options?: BooleanParserOptions);
|
|
128
134
|
private getInputErrorContext;
|
|
129
135
|
parse(text: string, _attributes?: Record<string, any>): boolean;
|
|
130
136
|
}
|
|
131
137
|
|
|
132
|
-
type NumberParserMatch = "
|
|
138
|
+
type NumberParserMatch = "exact" | "extract";
|
|
133
139
|
interface NumberParserOptions {
|
|
134
140
|
match?: NumberParserMatch;
|
|
135
141
|
}
|
|
@@ -138,7 +144,7 @@ interface NumberParserOptions {
|
|
|
138
144
|
* Category: extractor
|
|
139
145
|
* Mode: numeric token extraction
|
|
140
146
|
*
|
|
141
|
-
* Extracts one documented numeric token from text. Pass match: "
|
|
147
|
+
* Extracts one documented numeric token from text. Pass match: "exact" to
|
|
142
148
|
* require the input to consist of exactly one numeric token (after trim) with
|
|
143
149
|
* no surrounding prose.
|
|
144
150
|
*
|
|
@@ -156,14 +162,16 @@ type JsonParserInput = string | Record<string, unknown> | unknown[];
|
|
|
156
162
|
type JsonParserOutput<S extends JSONSchema | undefined> = S extends JSONSchema ? FromSchema<S> : Record<string, any>;
|
|
157
163
|
declare class JsonParser<S extends JSONSchema | undefined = undefined> extends BaseParserWithJson<S, JsonParserOutput<S>, JsonParserInput> {
|
|
158
164
|
private shouldValidateSchema;
|
|
165
|
+
private match;
|
|
159
166
|
constructor(options?: JsonParserOptions<S>);
|
|
160
167
|
/**
|
|
161
168
|
* v3 parser contract:
|
|
162
169
|
* Category: strict
|
|
163
|
-
* Mode:
|
|
170
|
+
* Mode: exact
|
|
164
171
|
*
|
|
165
|
-
* Parses strict JSON object/array output
|
|
166
|
-
*
|
|
172
|
+
* Parses strict JSON object/array output by default. Pass match: "extract"
|
|
173
|
+
* to extract one JSON object or array from surrounding text. Invalid JSON,
|
|
174
|
+
* empty input, JSON primitives, and non-plain runtime objects throw typed parser errors.
|
|
167
175
|
* Schema validation is on by default when a schema is provided unless
|
|
168
176
|
* validateSchema: false is explicitly set.
|
|
169
177
|
*
|
|
@@ -314,7 +322,7 @@ declare class MarkdownCodeBlocksParser extends BaseParser<{
|
|
|
314
322
|
}[];
|
|
315
323
|
}
|
|
316
324
|
|
|
317
|
-
type StringExtractMatch = "
|
|
325
|
+
type StringExtractMatch = "exact" | "word" | "substring";
|
|
318
326
|
interface StringExtractParserOptions<E extends readonly string[] = readonly string[]> {
|
|
319
327
|
enum: E;
|
|
320
328
|
ignoreCase?: boolean;
|
|
@@ -331,14 +339,14 @@ declare class StringExtractParser<E extends readonly string[] = readonly string[
|
|
|
331
339
|
* Mode: configured value extraction
|
|
332
340
|
*
|
|
333
341
|
* Returns the single configured enum value found in input. Matching is
|
|
334
|
-
* word-bounded by default; pass match: "
|
|
342
|
+
* word-bounded by default; pass match: "exact" to require exact input or
|
|
335
343
|
* match: "substring" for legacy contains() behavior. Case-insensitive by
|
|
336
344
|
* default.
|
|
337
345
|
*
|
|
338
346
|
*/
|
|
339
347
|
parse(text: string, _attributes?: Record<string, any>): E[number];
|
|
340
348
|
private findMatches;
|
|
341
|
-
private
|
|
349
|
+
private matchExact;
|
|
342
350
|
private matchSubstring;
|
|
343
351
|
private matchWord;
|
|
344
352
|
}
|
|
@@ -350,16 +358,22 @@ declare class StringExtractParser<E extends readonly string[] = readonly string[
|
|
|
350
358
|
* (e.g. "Source has 1 element(s) but target requires 2" when stringExtract
|
|
351
359
|
* is called without options) instead of overload-resolution mystery.
|
|
352
360
|
*/
|
|
353
|
-
type CreateParserArgs = [type: "string", options?: never] | [type: "boolean", options?:
|
|
361
|
+
type CreateParserArgs = [type: "string", options?: never] | [type: "boolean", options?: BooleanParserOptions] | [type: "listToArray", options?: never] | [type: "markdownCodeBlock", options?: never] | [type: "markdownCodeBlocks", options?: never] | [type: "replaceStringTemplate", options?: never] | [type: "number", options?: NumberParserOptions] | [type: "listToKeyValue", options?: ListToKeyValueParserOptions] | [type: "json", options?: JsonParserOptions<JSONSchema | undefined>] | [
|
|
354
362
|
type: "listToJson",
|
|
355
363
|
options?: ListToJsonParserOptions<JSONSchema | undefined>
|
|
356
|
-
] | [
|
|
364
|
+
] | [
|
|
365
|
+
type: "stringExtract",
|
|
366
|
+
options: StringExtractParserOptions<readonly string[]>
|
|
367
|
+
];
|
|
357
368
|
/**
|
|
358
369
|
* Maps a concrete argument tuple back to the parser instance type, preserving
|
|
359
370
|
* schema inference for json/listToJson and enum literal narrowing for
|
|
360
371
|
* stringExtract.
|
|
361
372
|
*/
|
|
362
|
-
type CreateParserReturn<A extends readonly unknown[]> = A extends readonly ["string", ...unknown[]] ? StringParser : A extends readonly ["boolean", ...unknown[]] ? BooleanParser : A extends readonly ["number", ...unknown[]] ? NumberParser : A extends readonly ["listToArray", ...unknown[]] ? ListToArrayParser : A extends readonly ["listToKeyValue", ...unknown[]] ? ListToKeyValueParser : A extends readonly ["markdownCodeBlock", ...unknown[]] ? MarkdownCodeBlockParser : A extends readonly ["markdownCodeBlocks", ...unknown[]] ? MarkdownCodeBlocksParser : A extends readonly ["replaceStringTemplate", ...unknown[]] ? ReplaceStringTemplateParser : A extends readonly ["json"] | readonly ["json", undefined] ? JsonParser<undefined> : A extends readonly ["json", JsonParserOptions<infer S>] ? JsonParser<S> : A extends readonly ["listToJson"] | readonly ["listToJson", undefined] ? ListToJsonParser<undefined> : A extends readonly [
|
|
373
|
+
type CreateParserReturn<A extends readonly unknown[]> = A extends readonly ["string", ...unknown[]] ? StringParser : A extends readonly ["boolean", ...unknown[]] ? BooleanParser : A extends readonly ["number", ...unknown[]] ? NumberParser : A extends readonly ["listToArray", ...unknown[]] ? ListToArrayParser : A extends readonly ["listToKeyValue", ...unknown[]] ? ListToKeyValueParser : A extends readonly ["markdownCodeBlock", ...unknown[]] ? MarkdownCodeBlockParser : A extends readonly ["markdownCodeBlocks", ...unknown[]] ? MarkdownCodeBlocksParser : A extends readonly ["replaceStringTemplate", ...unknown[]] ? ReplaceStringTemplateParser : A extends readonly ["json"] | readonly ["json", undefined] ? JsonParser<undefined> : A extends readonly ["json", JsonParserOptions<infer S>] ? JsonParser<S> : A extends readonly ["listToJson"] | readonly ["listToJson", undefined] ? ListToJsonParser<undefined> : A extends readonly [
|
|
374
|
+
"listToJson",
|
|
375
|
+
ListToJsonParserOptions<infer S>
|
|
376
|
+
] ? ListToJsonParser<S> : A extends readonly [
|
|
363
377
|
"stringExtract",
|
|
364
378
|
StringExtractParserOptions<infer E extends readonly string[]>
|
|
365
379
|
] ? StringExtractParser<E> : never;
|
|
@@ -1057,11 +1071,15 @@ interface LlmExecutorWithFunctionsOptions<T extends GenericFunctionCall = "auto"
|
|
|
1057
1071
|
jsonSchema?: Record<string, any>;
|
|
1058
1072
|
}
|
|
1059
1073
|
|
|
1060
|
-
interface
|
|
1074
|
+
interface ParserSchemaOptions<S extends JSONSchema | undefined = undefined> {
|
|
1061
1075
|
schema?: S;
|
|
1062
1076
|
validateSchema?: boolean;
|
|
1063
1077
|
}
|
|
1064
|
-
|
|
1078
|
+
type JsonParserMatch = "exact" | "extract";
|
|
1079
|
+
interface JsonParserOptions<S extends JSONSchema | undefined = undefined> extends ParserSchemaOptions<S> {
|
|
1080
|
+
match?: JsonParserMatch;
|
|
1081
|
+
}
|
|
1082
|
+
interface ListToJsonParserOptions<S extends JSONSchema | undefined = undefined> extends ParserSchemaOptions<S> {
|
|
1065
1083
|
keyTransform?: "camelCase" | "preserve";
|
|
1066
1084
|
}
|
|
1067
1085
|
|
|
@@ -2069,4 +2087,4 @@ declare function createEmbedding<T extends EmbeddingProviderKey>(provider: T, op
|
|
|
2069
2087
|
};
|
|
2070
2088
|
};
|
|
2071
2089
|
|
|
2072
|
-
export { BaseExecutor, type BaseLlm, BaseParser, BasePrompt, BaseStateItem, ChatPrompt, CustomParser, DefaultState, DefaultStateItem, type EmbeddingProviderKey, type ErrorCategory, type ErrorCodes, type ErrorContextByCode, type ExecutionContext, type ExecutorContext, type ExecutorExecutionMetadata, type HookErrorRecord, type IChatMessages, LLM_EXE_ERROR_SYMBOL, LlmExeError, LlmExecutorOpenAiFunctions, LlmExecutorWithFunctions, LlmNativeFunctionParser, type LlmProvider, type LlmProviderKey, type NormalizedProviderError, type OpenAIModelName, OpenAiFunctionParser, type ProviderErrorContext, TextPrompt, type UseLlmKey, createCallableExecutor, createChatPrompt, createCoreExecutor, createCustomParser, createDialogue, createEmbedding, createLlmExecutor, createLlmFunctionExecutor, createOpenAiCompatibleConfiguration, createParser, createPrompt, createState, createStateItem, defineSchema, guards, isLlmExeError, registerHelpers, registerPartials, useExecutors, useLlm, useLlmConfiguration, index as utils };
|
|
2090
|
+
export { BaseExecutor, type BaseLlm, BaseParser, BasePrompt, BaseStateItem, type BooleanParserMatch, type BooleanParserOptions, ChatPrompt, CustomParser, DefaultState, DefaultStateItem, type EmbeddingProviderKey, type ErrorCategory, type ErrorCodes, type ErrorContextByCode, type ExecutionContext, type ExecutorContext, type ExecutorExecutionMetadata, type HookErrorRecord, type IChatMessages, type JsonParserMatch, type JsonParserOptions, LLM_EXE_ERROR_SYMBOL, LlmExeError, LlmExecutorOpenAiFunctions, LlmExecutorWithFunctions, LlmNativeFunctionParser, type LlmProvider, type LlmProviderKey, type NormalizedProviderError, type NumberParserMatch, type NumberParserOptions, type OpenAIModelName, OpenAiFunctionParser, type ProviderErrorContext, type StringExtractMatch, type StringExtractParserOptions, TextPrompt, type UseLlmKey, createCallableExecutor, createChatPrompt, createCoreExecutor, createCustomParser, createDialogue, createEmbedding, createLlmExecutor, createLlmFunctionExecutor, createOpenAiCompatibleConfiguration, createParser, createPrompt, createState, createStateItem, defineSchema, guards, isLlmExeError, registerHelpers, registerPartials, useExecutors, useLlm, useLlmConfiguration, index as utils };
|
package/dist/index.d.ts
CHANGED
|
@@ -92,7 +92,7 @@ declare abstract class BaseParser<T = any, TInput = string> {
|
|
|
92
92
|
declare abstract class BaseParserWithJson<S extends JSONSchema | undefined = undefined, T = S extends JSONSchema ? FromSchema<S> : Record<string, any>, TInput = string> extends BaseParser<T, TInput> {
|
|
93
93
|
schema: S;
|
|
94
94
|
validateSchema: boolean;
|
|
95
|
-
constructor(name: string, options:
|
|
95
|
+
constructor(name: string, options: ParserSchemaOptions<S>);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
@@ -111,25 +111,31 @@ declare class StringParser extends BaseParser<string> {
|
|
|
111
111
|
parse(text: string, _attributes?: Record<string, any>): string;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
type BooleanParserMatch = "exact" | "extract";
|
|
115
|
+
interface BooleanParserOptions {
|
|
116
|
+
match?: BooleanParserMatch;
|
|
117
|
+
}
|
|
114
118
|
/**
|
|
115
119
|
* v3 parser contract:
|
|
116
120
|
* Category: strict
|
|
117
|
-
* Mode:
|
|
121
|
+
* Mode: exact
|
|
118
122
|
*
|
|
119
123
|
* Accepts only documented boolean literals after trim/lowercase.
|
|
120
|
-
* Returns true/false only when input is recognized.
|
|
121
|
-
*
|
|
122
|
-
*
|
|
124
|
+
* Returns true/false only when input is recognized. Pass match: "extract" to
|
|
125
|
+
* extract one documented boolean literal from surrounding text.
|
|
126
|
+
* Throws LlmExeError(parser.parse_failed) for empty or unrecognized input.
|
|
127
|
+
* Invalid input types throw LlmExeError(parser.invalid_input).
|
|
123
128
|
* Error context does not include input content unless LLM_EXE_DEBUG is enabled.
|
|
124
129
|
*
|
|
125
130
|
*/
|
|
126
131
|
declare class BooleanParser extends BaseParser<boolean> {
|
|
127
|
-
|
|
132
|
+
private match;
|
|
133
|
+
constructor(options?: BooleanParserOptions);
|
|
128
134
|
private getInputErrorContext;
|
|
129
135
|
parse(text: string, _attributes?: Record<string, any>): boolean;
|
|
130
136
|
}
|
|
131
137
|
|
|
132
|
-
type NumberParserMatch = "
|
|
138
|
+
type NumberParserMatch = "exact" | "extract";
|
|
133
139
|
interface NumberParserOptions {
|
|
134
140
|
match?: NumberParserMatch;
|
|
135
141
|
}
|
|
@@ -138,7 +144,7 @@ interface NumberParserOptions {
|
|
|
138
144
|
* Category: extractor
|
|
139
145
|
* Mode: numeric token extraction
|
|
140
146
|
*
|
|
141
|
-
* Extracts one documented numeric token from text. Pass match: "
|
|
147
|
+
* Extracts one documented numeric token from text. Pass match: "exact" to
|
|
142
148
|
* require the input to consist of exactly one numeric token (after trim) with
|
|
143
149
|
* no surrounding prose.
|
|
144
150
|
*
|
|
@@ -156,14 +162,16 @@ type JsonParserInput = string | Record<string, unknown> | unknown[];
|
|
|
156
162
|
type JsonParserOutput<S extends JSONSchema | undefined> = S extends JSONSchema ? FromSchema<S> : Record<string, any>;
|
|
157
163
|
declare class JsonParser<S extends JSONSchema | undefined = undefined> extends BaseParserWithJson<S, JsonParserOutput<S>, JsonParserInput> {
|
|
158
164
|
private shouldValidateSchema;
|
|
165
|
+
private match;
|
|
159
166
|
constructor(options?: JsonParserOptions<S>);
|
|
160
167
|
/**
|
|
161
168
|
* v3 parser contract:
|
|
162
169
|
* Category: strict
|
|
163
|
-
* Mode:
|
|
170
|
+
* Mode: exact
|
|
164
171
|
*
|
|
165
|
-
* Parses strict JSON object/array output
|
|
166
|
-
*
|
|
172
|
+
* Parses strict JSON object/array output by default. Pass match: "extract"
|
|
173
|
+
* to extract one JSON object or array from surrounding text. Invalid JSON,
|
|
174
|
+
* empty input, JSON primitives, and non-plain runtime objects throw typed parser errors.
|
|
167
175
|
* Schema validation is on by default when a schema is provided unless
|
|
168
176
|
* validateSchema: false is explicitly set.
|
|
169
177
|
*
|
|
@@ -314,7 +322,7 @@ declare class MarkdownCodeBlocksParser extends BaseParser<{
|
|
|
314
322
|
}[];
|
|
315
323
|
}
|
|
316
324
|
|
|
317
|
-
type StringExtractMatch = "
|
|
325
|
+
type StringExtractMatch = "exact" | "word" | "substring";
|
|
318
326
|
interface StringExtractParserOptions<E extends readonly string[] = readonly string[]> {
|
|
319
327
|
enum: E;
|
|
320
328
|
ignoreCase?: boolean;
|
|
@@ -331,14 +339,14 @@ declare class StringExtractParser<E extends readonly string[] = readonly string[
|
|
|
331
339
|
* Mode: configured value extraction
|
|
332
340
|
*
|
|
333
341
|
* Returns the single configured enum value found in input. Matching is
|
|
334
|
-
* word-bounded by default; pass match: "
|
|
342
|
+
* word-bounded by default; pass match: "exact" to require exact input or
|
|
335
343
|
* match: "substring" for legacy contains() behavior. Case-insensitive by
|
|
336
344
|
* default.
|
|
337
345
|
*
|
|
338
346
|
*/
|
|
339
347
|
parse(text: string, _attributes?: Record<string, any>): E[number];
|
|
340
348
|
private findMatches;
|
|
341
|
-
private
|
|
349
|
+
private matchExact;
|
|
342
350
|
private matchSubstring;
|
|
343
351
|
private matchWord;
|
|
344
352
|
}
|
|
@@ -350,16 +358,22 @@ declare class StringExtractParser<E extends readonly string[] = readonly string[
|
|
|
350
358
|
* (e.g. "Source has 1 element(s) but target requires 2" when stringExtract
|
|
351
359
|
* is called without options) instead of overload-resolution mystery.
|
|
352
360
|
*/
|
|
353
|
-
type CreateParserArgs = [type: "string", options?: never] | [type: "boolean", options?:
|
|
361
|
+
type CreateParserArgs = [type: "string", options?: never] | [type: "boolean", options?: BooleanParserOptions] | [type: "listToArray", options?: never] | [type: "markdownCodeBlock", options?: never] | [type: "markdownCodeBlocks", options?: never] | [type: "replaceStringTemplate", options?: never] | [type: "number", options?: NumberParserOptions] | [type: "listToKeyValue", options?: ListToKeyValueParserOptions] | [type: "json", options?: JsonParserOptions<JSONSchema | undefined>] | [
|
|
354
362
|
type: "listToJson",
|
|
355
363
|
options?: ListToJsonParserOptions<JSONSchema | undefined>
|
|
356
|
-
] | [
|
|
364
|
+
] | [
|
|
365
|
+
type: "stringExtract",
|
|
366
|
+
options: StringExtractParserOptions<readonly string[]>
|
|
367
|
+
];
|
|
357
368
|
/**
|
|
358
369
|
* Maps a concrete argument tuple back to the parser instance type, preserving
|
|
359
370
|
* schema inference for json/listToJson and enum literal narrowing for
|
|
360
371
|
* stringExtract.
|
|
361
372
|
*/
|
|
362
|
-
type CreateParserReturn<A extends readonly unknown[]> = A extends readonly ["string", ...unknown[]] ? StringParser : A extends readonly ["boolean", ...unknown[]] ? BooleanParser : A extends readonly ["number", ...unknown[]] ? NumberParser : A extends readonly ["listToArray", ...unknown[]] ? ListToArrayParser : A extends readonly ["listToKeyValue", ...unknown[]] ? ListToKeyValueParser : A extends readonly ["markdownCodeBlock", ...unknown[]] ? MarkdownCodeBlockParser : A extends readonly ["markdownCodeBlocks", ...unknown[]] ? MarkdownCodeBlocksParser : A extends readonly ["replaceStringTemplate", ...unknown[]] ? ReplaceStringTemplateParser : A extends readonly ["json"] | readonly ["json", undefined] ? JsonParser<undefined> : A extends readonly ["json", JsonParserOptions<infer S>] ? JsonParser<S> : A extends readonly ["listToJson"] | readonly ["listToJson", undefined] ? ListToJsonParser<undefined> : A extends readonly [
|
|
373
|
+
type CreateParserReturn<A extends readonly unknown[]> = A extends readonly ["string", ...unknown[]] ? StringParser : A extends readonly ["boolean", ...unknown[]] ? BooleanParser : A extends readonly ["number", ...unknown[]] ? NumberParser : A extends readonly ["listToArray", ...unknown[]] ? ListToArrayParser : A extends readonly ["listToKeyValue", ...unknown[]] ? ListToKeyValueParser : A extends readonly ["markdownCodeBlock", ...unknown[]] ? MarkdownCodeBlockParser : A extends readonly ["markdownCodeBlocks", ...unknown[]] ? MarkdownCodeBlocksParser : A extends readonly ["replaceStringTemplate", ...unknown[]] ? ReplaceStringTemplateParser : A extends readonly ["json"] | readonly ["json", undefined] ? JsonParser<undefined> : A extends readonly ["json", JsonParserOptions<infer S>] ? JsonParser<S> : A extends readonly ["listToJson"] | readonly ["listToJson", undefined] ? ListToJsonParser<undefined> : A extends readonly [
|
|
374
|
+
"listToJson",
|
|
375
|
+
ListToJsonParserOptions<infer S>
|
|
376
|
+
] ? ListToJsonParser<S> : A extends readonly [
|
|
363
377
|
"stringExtract",
|
|
364
378
|
StringExtractParserOptions<infer E extends readonly string[]>
|
|
365
379
|
] ? StringExtractParser<E> : never;
|
|
@@ -1057,11 +1071,15 @@ interface LlmExecutorWithFunctionsOptions<T extends GenericFunctionCall = "auto"
|
|
|
1057
1071
|
jsonSchema?: Record<string, any>;
|
|
1058
1072
|
}
|
|
1059
1073
|
|
|
1060
|
-
interface
|
|
1074
|
+
interface ParserSchemaOptions<S extends JSONSchema | undefined = undefined> {
|
|
1061
1075
|
schema?: S;
|
|
1062
1076
|
validateSchema?: boolean;
|
|
1063
1077
|
}
|
|
1064
|
-
|
|
1078
|
+
type JsonParserMatch = "exact" | "extract";
|
|
1079
|
+
interface JsonParserOptions<S extends JSONSchema | undefined = undefined> extends ParserSchemaOptions<S> {
|
|
1080
|
+
match?: JsonParserMatch;
|
|
1081
|
+
}
|
|
1082
|
+
interface ListToJsonParserOptions<S extends JSONSchema | undefined = undefined> extends ParserSchemaOptions<S> {
|
|
1065
1083
|
keyTransform?: "camelCase" | "preserve";
|
|
1066
1084
|
}
|
|
1067
1085
|
|
|
@@ -2069,4 +2087,4 @@ declare function createEmbedding<T extends EmbeddingProviderKey>(provider: T, op
|
|
|
2069
2087
|
};
|
|
2070
2088
|
};
|
|
2071
2089
|
|
|
2072
|
-
export { BaseExecutor, type BaseLlm, BaseParser, BasePrompt, BaseStateItem, ChatPrompt, CustomParser, DefaultState, DefaultStateItem, type EmbeddingProviderKey, type ErrorCategory, type ErrorCodes, type ErrorContextByCode, type ExecutionContext, type ExecutorContext, type ExecutorExecutionMetadata, type HookErrorRecord, type IChatMessages, LLM_EXE_ERROR_SYMBOL, LlmExeError, LlmExecutorOpenAiFunctions, LlmExecutorWithFunctions, LlmNativeFunctionParser, type LlmProvider, type LlmProviderKey, type NormalizedProviderError, type OpenAIModelName, OpenAiFunctionParser, type ProviderErrorContext, TextPrompt, type UseLlmKey, createCallableExecutor, createChatPrompt, createCoreExecutor, createCustomParser, createDialogue, createEmbedding, createLlmExecutor, createLlmFunctionExecutor, createOpenAiCompatibleConfiguration, createParser, createPrompt, createState, createStateItem, defineSchema, guards, isLlmExeError, registerHelpers, registerPartials, useExecutors, useLlm, useLlmConfiguration, index as utils };
|
|
2090
|
+
export { BaseExecutor, type BaseLlm, BaseParser, BasePrompt, BaseStateItem, type BooleanParserMatch, type BooleanParserOptions, ChatPrompt, CustomParser, DefaultState, DefaultStateItem, type EmbeddingProviderKey, type ErrorCategory, type ErrorCodes, type ErrorContextByCode, type ExecutionContext, type ExecutorContext, type ExecutorExecutionMetadata, type HookErrorRecord, type IChatMessages, type JsonParserMatch, type JsonParserOptions, LLM_EXE_ERROR_SYMBOL, LlmExeError, LlmExecutorOpenAiFunctions, LlmExecutorWithFunctions, LlmNativeFunctionParser, type LlmProvider, type LlmProviderKey, type NormalizedProviderError, type NumberParserMatch, type NumberParserOptions, type OpenAIModelName, OpenAiFunctionParser, type ProviderErrorContext, type StringExtractMatch, type StringExtractParserOptions, TextPrompt, type UseLlmKey, createCallableExecutor, createChatPrompt, createCoreExecutor, createCustomParser, createDialogue, createEmbedding, createLlmExecutor, createLlmFunctionExecutor, createOpenAiCompatibleConfiguration, createParser, createPrompt, createState, createStateItem, defineSchema, guards, isLlmExeError, registerHelpers, registerPartials, useExecutors, useLlm, useLlmConfiguration, index as utils };
|
package/dist/index.js
CHANGED
|
@@ -1266,9 +1266,12 @@ var BOOLEAN_VALUES = ["true", "false", "yes", "no", "y", "n", "1", "0"];
|
|
|
1266
1266
|
var TRUTHY_VALUES = /* @__PURE__ */ new Set(["true", "yes", "y", "1"]);
|
|
1267
1267
|
var FALSY_VALUES = /* @__PURE__ */ new Set(["false", "no", "n", "0"]);
|
|
1268
1268
|
var MAX_ERROR_INPUT_EXCERPT_LENGTH = 500;
|
|
1269
|
+
var BOOLEAN_TOKEN_PATTERN = /(?<![\p{L}\p{N}])(?:true|false|yes|no|y|n|1|0)(?![\p{L}\p{N}])/giu;
|
|
1269
1270
|
var BooleanParser = class extends BaseParser {
|
|
1270
|
-
constructor() {
|
|
1271
|
+
constructor(options) {
|
|
1271
1272
|
super("boolean");
|
|
1273
|
+
__publicField(this, "match");
|
|
1274
|
+
this.match = options?.match ?? "exact";
|
|
1272
1275
|
}
|
|
1273
1276
|
getInputErrorContext(text) {
|
|
1274
1277
|
const context = {
|
|
@@ -1316,6 +1319,36 @@ var BooleanParser = class extends BaseParser {
|
|
|
1316
1319
|
if (FALSY_VALUES.has(clean)) {
|
|
1317
1320
|
return false;
|
|
1318
1321
|
}
|
|
1322
|
+
if (this.match === "extract") {
|
|
1323
|
+
const matches = Array.from(
|
|
1324
|
+
text.toLowerCase().matchAll(BOOLEAN_TOKEN_PATTERN)
|
|
1325
|
+
).map((match) => match[0]);
|
|
1326
|
+
const values = Array.from(
|
|
1327
|
+
new Set(
|
|
1328
|
+
matches.map((match) => {
|
|
1329
|
+
if (TRUTHY_VALUES.has(match)) return true;
|
|
1330
|
+
return false;
|
|
1331
|
+
})
|
|
1332
|
+
)
|
|
1333
|
+
);
|
|
1334
|
+
if (values.length === 1) {
|
|
1335
|
+
return values[0];
|
|
1336
|
+
}
|
|
1337
|
+
if (values.length > 1) {
|
|
1338
|
+
throw new LlmExeError(`Multiple boolean values found in input.`, {
|
|
1339
|
+
code: "parser.parse_failed",
|
|
1340
|
+
context: {
|
|
1341
|
+
operation: "BooleanParser.parse",
|
|
1342
|
+
parser: "boolean",
|
|
1343
|
+
reason: "ambiguous_boolean",
|
|
1344
|
+
expected: "one boolean value",
|
|
1345
|
+
match: this.match,
|
|
1346
|
+
matchCount: values.length,
|
|
1347
|
+
...this.getInputErrorContext(text)
|
|
1348
|
+
}
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1319
1352
|
throw new LlmExeError(`No boolean value found in input.`, {
|
|
1320
1353
|
code: "parser.parse_failed",
|
|
1321
1354
|
context: {
|
|
@@ -1323,6 +1356,7 @@ var BooleanParser = class extends BaseParser {
|
|
|
1323
1356
|
parser: "boolean",
|
|
1324
1357
|
reason: "unrecognized_boolean",
|
|
1325
1358
|
expected: BOOLEAN_VALUES,
|
|
1359
|
+
match: this.match,
|
|
1326
1360
|
...this.getInputErrorContext(text)
|
|
1327
1361
|
}
|
|
1328
1362
|
});
|
|
@@ -1347,7 +1381,7 @@ function toNumber(value) {
|
|
|
1347
1381
|
|
|
1348
1382
|
// src/parser/parsers/NumberParser.ts
|
|
1349
1383
|
var NUMERIC_TOKEN_PATTERN = /(^|[^\w.,])([+-]?(?:(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?|\.\d+)(?:[eE][+-]?\d+)?)(?![\w,])/g;
|
|
1350
|
-
var
|
|
1384
|
+
var EXACT_NUMERIC_PATTERN = /^[+-]?(?:(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?|\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
1351
1385
|
var NumberParser = class extends BaseParser {
|
|
1352
1386
|
constructor(options) {
|
|
1353
1387
|
super("number");
|
|
@@ -1382,16 +1416,16 @@ var NumberParser = class extends BaseParser {
|
|
|
1382
1416
|
}
|
|
1383
1417
|
});
|
|
1384
1418
|
}
|
|
1385
|
-
if (this.match === "
|
|
1419
|
+
if (this.match === "exact") {
|
|
1386
1420
|
const trimmed = text.trim();
|
|
1387
|
-
if (!
|
|
1388
|
-
throw new LlmExeError(`Input is not
|
|
1421
|
+
if (!EXACT_NUMERIC_PATTERN.test(trimmed)) {
|
|
1422
|
+
throw new LlmExeError(`Input is not an exact numeric value.`, {
|
|
1389
1423
|
code: "parser.parse_failed",
|
|
1390
1424
|
context: {
|
|
1391
1425
|
operation: "NumberParser.parse",
|
|
1392
1426
|
parser: "number",
|
|
1393
1427
|
reason: "no_numeric_value",
|
|
1394
|
-
expected: "
|
|
1428
|
+
expected: "exact number",
|
|
1395
1429
|
match: this.match,
|
|
1396
1430
|
inputLength: text.length
|
|
1397
1431
|
}
|
|
@@ -1658,9 +1692,11 @@ function isPlainObject2(value) {
|
|
|
1658
1692
|
const proto = Object.getPrototypeOf(value);
|
|
1659
1693
|
return proto === Object.prototype || proto === null;
|
|
1660
1694
|
}
|
|
1661
|
-
function
|
|
1695
|
+
function normalizeExactResponseJsonText(input) {
|
|
1662
1696
|
const trimmed = input.trim();
|
|
1663
|
-
const fenceMatch = trimmed.match(
|
|
1697
|
+
const fenceMatch = trimmed.match(
|
|
1698
|
+
/^```([a-zA-Z]*)[^\S\r\n]*\r?\n([\s\S]*)```$/
|
|
1699
|
+
);
|
|
1664
1700
|
if (!fenceMatch) {
|
|
1665
1701
|
return trimmed;
|
|
1666
1702
|
}
|
|
@@ -1670,19 +1706,82 @@ function normalizeWholeResponseJsonText(input) {
|
|
|
1670
1706
|
}
|
|
1671
1707
|
return body.trim();
|
|
1672
1708
|
}
|
|
1709
|
+
function findBalancedJsonEnd(input, start) {
|
|
1710
|
+
const first = input[start];
|
|
1711
|
+
const stack = first === "{" ? ["}"] : first === "[" ? ["]"] : [];
|
|
1712
|
+
let inString = false;
|
|
1713
|
+
let escaping = false;
|
|
1714
|
+
for (let index = start + 1; index < input.length; index += 1) {
|
|
1715
|
+
const char = input[index];
|
|
1716
|
+
if (inString) {
|
|
1717
|
+
if (escaping) {
|
|
1718
|
+
escaping = false;
|
|
1719
|
+
} else if (char === "\\") {
|
|
1720
|
+
escaping = true;
|
|
1721
|
+
} else if (char === '"') {
|
|
1722
|
+
inString = false;
|
|
1723
|
+
}
|
|
1724
|
+
continue;
|
|
1725
|
+
}
|
|
1726
|
+
if (char === '"') {
|
|
1727
|
+
inString = true;
|
|
1728
|
+
continue;
|
|
1729
|
+
}
|
|
1730
|
+
if (char === "{" || char === "[") {
|
|
1731
|
+
stack.push(char === "{" ? "}" : "]");
|
|
1732
|
+
continue;
|
|
1733
|
+
}
|
|
1734
|
+
if (char !== "}" && char !== "]") {
|
|
1735
|
+
continue;
|
|
1736
|
+
}
|
|
1737
|
+
if (stack[stack.length - 1] !== char) {
|
|
1738
|
+
return void 0;
|
|
1739
|
+
}
|
|
1740
|
+
stack.pop();
|
|
1741
|
+
if (stack.length === 0) {
|
|
1742
|
+
return index;
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
return void 0;
|
|
1746
|
+
}
|
|
1747
|
+
function extractJsonCandidates(input) {
|
|
1748
|
+
const candidates = [];
|
|
1749
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
1750
|
+
const char = input[index];
|
|
1751
|
+
if (char !== "{" && char !== "[") {
|
|
1752
|
+
continue;
|
|
1753
|
+
}
|
|
1754
|
+
const end = findBalancedJsonEnd(input, index);
|
|
1755
|
+
if (end === void 0) {
|
|
1756
|
+
continue;
|
|
1757
|
+
}
|
|
1758
|
+
const candidate = input.slice(index, end + 1);
|
|
1759
|
+
try {
|
|
1760
|
+
candidates.push({
|
|
1761
|
+
parsed: JSON.parse(candidate)
|
|
1762
|
+
});
|
|
1763
|
+
index = end;
|
|
1764
|
+
} catch {
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
return candidates;
|
|
1768
|
+
}
|
|
1673
1769
|
var JsonParser = class extends BaseParserWithJson {
|
|
1674
1770
|
constructor(options = {}) {
|
|
1675
1771
|
super("json", options);
|
|
1676
1772
|
__publicField(this, "shouldValidateSchema");
|
|
1773
|
+
__publicField(this, "match");
|
|
1774
|
+
this.match = options.match ?? "exact";
|
|
1677
1775
|
this.shouldValidateSchema = !!options.schema && options.validateSchema !== false;
|
|
1678
1776
|
}
|
|
1679
1777
|
/**
|
|
1680
1778
|
* v3 parser contract:
|
|
1681
1779
|
* Category: strict
|
|
1682
|
-
* Mode:
|
|
1780
|
+
* Mode: exact
|
|
1683
1781
|
*
|
|
1684
|
-
* Parses strict JSON object/array output
|
|
1685
|
-
*
|
|
1782
|
+
* Parses strict JSON object/array output by default. Pass match: "extract"
|
|
1783
|
+
* to extract one JSON object or array from surrounding text. Invalid JSON,
|
|
1784
|
+
* empty input, JSON primitives, and non-plain runtime objects throw typed parser errors.
|
|
1686
1785
|
* Schema validation is on by default when a schema is provided unless
|
|
1687
1786
|
* validateSchema: false is explicitly set.
|
|
1688
1787
|
*
|
|
@@ -1705,19 +1804,52 @@ var JsonParser = class extends BaseParserWithJson {
|
|
|
1705
1804
|
});
|
|
1706
1805
|
}
|
|
1707
1806
|
try {
|
|
1708
|
-
parsed = JSON.parse(
|
|
1807
|
+
parsed = JSON.parse(normalizeExactResponseJsonText(text));
|
|
1709
1808
|
} catch (cause) {
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1809
|
+
if (this.match === "extract") {
|
|
1810
|
+
const candidates = extractJsonCandidates(text);
|
|
1811
|
+
if (candidates.length === 1) {
|
|
1812
|
+
parsed = candidates[0].parsed;
|
|
1813
|
+
} else if (candidates.length > 1) {
|
|
1814
|
+
throw new LlmExeError(`Multiple JSON values found in input.`, {
|
|
1815
|
+
code: "parser.parse_failed",
|
|
1816
|
+
context: {
|
|
1817
|
+
operation: "JsonParser.parse",
|
|
1818
|
+
parser: "json",
|
|
1819
|
+
reason: "ambiguous_json_match",
|
|
1820
|
+
expected: "one JSON object or array",
|
|
1821
|
+
match: this.match,
|
|
1822
|
+
inputLength,
|
|
1823
|
+
matchCount: candidates.length
|
|
1824
|
+
}
|
|
1825
|
+
});
|
|
1826
|
+
} else {
|
|
1827
|
+
throw new LlmExeError(`No JSON value found in input.`, {
|
|
1828
|
+
code: "parser.parse_failed",
|
|
1829
|
+
context: {
|
|
1830
|
+
operation: "JsonParser.parse",
|
|
1831
|
+
parser: "json",
|
|
1832
|
+
reason: "no_json_value",
|
|
1833
|
+
expected: "JSON object or array",
|
|
1834
|
+
match: this.match,
|
|
1835
|
+
inputLength
|
|
1836
|
+
},
|
|
1837
|
+
cause
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1840
|
+
} else {
|
|
1841
|
+
throw new LlmExeError(`Invalid JSON input.`, {
|
|
1842
|
+
code: "parser.parse_failed",
|
|
1843
|
+
context: {
|
|
1844
|
+
operation: "JsonParser.parse",
|
|
1845
|
+
parser: "json",
|
|
1846
|
+
reason: "invalid_json",
|
|
1847
|
+
expected: "JSON object or array",
|
|
1848
|
+
inputLength
|
|
1849
|
+
},
|
|
1850
|
+
cause
|
|
1851
|
+
});
|
|
1852
|
+
}
|
|
1721
1853
|
}
|
|
1722
1854
|
} else if (Array.isArray(text) || isPlainObject2(text)) {
|
|
1723
1855
|
parsed = text;
|
|
@@ -2988,7 +3120,7 @@ var StringExtractParser = class extends BaseParser {
|
|
|
2988
3120
|
* Mode: configured value extraction
|
|
2989
3121
|
*
|
|
2990
3122
|
* Returns the single configured enum value found in input. Matching is
|
|
2991
|
-
* word-bounded by default; pass match: "
|
|
3123
|
+
* word-bounded by default; pass match: "exact" to require exact input or
|
|
2992
3124
|
* match: "substring" for legacy contains() behavior. Case-insensitive by
|
|
2993
3125
|
* default.
|
|
2994
3126
|
*
|
|
@@ -3070,8 +3202,8 @@ var StringExtractParser = class extends BaseParser {
|
|
|
3070
3202
|
}
|
|
3071
3203
|
findMatches(text) {
|
|
3072
3204
|
switch (this.match) {
|
|
3073
|
-
case "
|
|
3074
|
-
return this.
|
|
3205
|
+
case "exact":
|
|
3206
|
+
return this.matchExact(text);
|
|
3075
3207
|
case "substring":
|
|
3076
3208
|
return this.matchSubstring(text);
|
|
3077
3209
|
case "word":
|
|
@@ -3079,7 +3211,7 @@ var StringExtractParser = class extends BaseParser {
|
|
|
3079
3211
|
return this.matchWord(text);
|
|
3080
3212
|
}
|
|
3081
3213
|
}
|
|
3082
|
-
|
|
3214
|
+
matchExact(text) {
|
|
3083
3215
|
const candidate = this.ignoreCase ? text.trim().toLowerCase() : text.trim();
|
|
3084
3216
|
return this.enum.filter((option) => {
|
|
3085
3217
|
if (option === "") return false;
|
|
@@ -3129,36 +3261,33 @@ function createParser(...args) {
|
|
|
3129
3261
|
case "replaceStringTemplate":
|
|
3130
3262
|
return new ReplaceStringTemplateParser();
|
|
3131
3263
|
case "boolean":
|
|
3132
|
-
return new BooleanParser();
|
|
3264
|
+
return new BooleanParser(options);
|
|
3133
3265
|
case "number":
|
|
3134
3266
|
return new NumberParser(options);
|
|
3135
3267
|
case "string":
|
|
3136
3268
|
return new StringParser();
|
|
3137
3269
|
default:
|
|
3138
|
-
throw new LlmExeError(
|
|
3139
|
-
|
|
3140
|
-
{
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
],
|
|
3158
|
-
resolution: "Use a registered parser type, or define a custom parser."
|
|
3159
|
-
}
|
|
3270
|
+
throw new LlmExeError(`Invalid parser type: "${type}"`, {
|
|
3271
|
+
code: "parser.invalid_type",
|
|
3272
|
+
context: {
|
|
3273
|
+
operation: "createParser",
|
|
3274
|
+
parser: type,
|
|
3275
|
+
availableParsers: [
|
|
3276
|
+
"json",
|
|
3277
|
+
"string",
|
|
3278
|
+
"boolean",
|
|
3279
|
+
"number",
|
|
3280
|
+
"stringExtract",
|
|
3281
|
+
"listToArray",
|
|
3282
|
+
"listToJson",
|
|
3283
|
+
"listToKeyValue",
|
|
3284
|
+
"replaceStringTemplate",
|
|
3285
|
+
"markdownCodeBlock",
|
|
3286
|
+
"markdownCodeBlocks"
|
|
3287
|
+
],
|
|
3288
|
+
resolution: "Use a registered parser type, or define a custom parser."
|
|
3160
3289
|
}
|
|
3161
|
-
);
|
|
3290
|
+
});
|
|
3162
3291
|
}
|
|
3163
3292
|
}
|
|
3164
3293
|
function createCustomParser(name, parserFn) {
|
package/dist/index.mjs
CHANGED
|
@@ -1200,9 +1200,12 @@ var BOOLEAN_VALUES = ["true", "false", "yes", "no", "y", "n", "1", "0"];
|
|
|
1200
1200
|
var TRUTHY_VALUES = /* @__PURE__ */ new Set(["true", "yes", "y", "1"]);
|
|
1201
1201
|
var FALSY_VALUES = /* @__PURE__ */ new Set(["false", "no", "n", "0"]);
|
|
1202
1202
|
var MAX_ERROR_INPUT_EXCERPT_LENGTH = 500;
|
|
1203
|
+
var BOOLEAN_TOKEN_PATTERN = /(?<![\p{L}\p{N}])(?:true|false|yes|no|y|n|1|0)(?![\p{L}\p{N}])/giu;
|
|
1203
1204
|
var BooleanParser = class extends BaseParser {
|
|
1204
|
-
constructor() {
|
|
1205
|
+
constructor(options) {
|
|
1205
1206
|
super("boolean");
|
|
1207
|
+
__publicField(this, "match");
|
|
1208
|
+
this.match = options?.match ?? "exact";
|
|
1206
1209
|
}
|
|
1207
1210
|
getInputErrorContext(text) {
|
|
1208
1211
|
const context = {
|
|
@@ -1250,6 +1253,36 @@ var BooleanParser = class extends BaseParser {
|
|
|
1250
1253
|
if (FALSY_VALUES.has(clean)) {
|
|
1251
1254
|
return false;
|
|
1252
1255
|
}
|
|
1256
|
+
if (this.match === "extract") {
|
|
1257
|
+
const matches = Array.from(
|
|
1258
|
+
text.toLowerCase().matchAll(BOOLEAN_TOKEN_PATTERN)
|
|
1259
|
+
).map((match) => match[0]);
|
|
1260
|
+
const values = Array.from(
|
|
1261
|
+
new Set(
|
|
1262
|
+
matches.map((match) => {
|
|
1263
|
+
if (TRUTHY_VALUES.has(match)) return true;
|
|
1264
|
+
return false;
|
|
1265
|
+
})
|
|
1266
|
+
)
|
|
1267
|
+
);
|
|
1268
|
+
if (values.length === 1) {
|
|
1269
|
+
return values[0];
|
|
1270
|
+
}
|
|
1271
|
+
if (values.length > 1) {
|
|
1272
|
+
throw new LlmExeError(`Multiple boolean values found in input.`, {
|
|
1273
|
+
code: "parser.parse_failed",
|
|
1274
|
+
context: {
|
|
1275
|
+
operation: "BooleanParser.parse",
|
|
1276
|
+
parser: "boolean",
|
|
1277
|
+
reason: "ambiguous_boolean",
|
|
1278
|
+
expected: "one boolean value",
|
|
1279
|
+
match: this.match,
|
|
1280
|
+
matchCount: values.length,
|
|
1281
|
+
...this.getInputErrorContext(text)
|
|
1282
|
+
}
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1253
1286
|
throw new LlmExeError(`No boolean value found in input.`, {
|
|
1254
1287
|
code: "parser.parse_failed",
|
|
1255
1288
|
context: {
|
|
@@ -1257,6 +1290,7 @@ var BooleanParser = class extends BaseParser {
|
|
|
1257
1290
|
parser: "boolean",
|
|
1258
1291
|
reason: "unrecognized_boolean",
|
|
1259
1292
|
expected: BOOLEAN_VALUES,
|
|
1293
|
+
match: this.match,
|
|
1260
1294
|
...this.getInputErrorContext(text)
|
|
1261
1295
|
}
|
|
1262
1296
|
});
|
|
@@ -1281,7 +1315,7 @@ function toNumber(value) {
|
|
|
1281
1315
|
|
|
1282
1316
|
// src/parser/parsers/NumberParser.ts
|
|
1283
1317
|
var NUMERIC_TOKEN_PATTERN = /(^|[^\w.,])([+-]?(?:(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?|\.\d+)(?:[eE][+-]?\d+)?)(?![\w,])/g;
|
|
1284
|
-
var
|
|
1318
|
+
var EXACT_NUMERIC_PATTERN = /^[+-]?(?:(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?|\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
1285
1319
|
var NumberParser = class extends BaseParser {
|
|
1286
1320
|
constructor(options) {
|
|
1287
1321
|
super("number");
|
|
@@ -1316,16 +1350,16 @@ var NumberParser = class extends BaseParser {
|
|
|
1316
1350
|
}
|
|
1317
1351
|
});
|
|
1318
1352
|
}
|
|
1319
|
-
if (this.match === "
|
|
1353
|
+
if (this.match === "exact") {
|
|
1320
1354
|
const trimmed = text.trim();
|
|
1321
|
-
if (!
|
|
1322
|
-
throw new LlmExeError(`Input is not
|
|
1355
|
+
if (!EXACT_NUMERIC_PATTERN.test(trimmed)) {
|
|
1356
|
+
throw new LlmExeError(`Input is not an exact numeric value.`, {
|
|
1323
1357
|
code: "parser.parse_failed",
|
|
1324
1358
|
context: {
|
|
1325
1359
|
operation: "NumberParser.parse",
|
|
1326
1360
|
parser: "number",
|
|
1327
1361
|
reason: "no_numeric_value",
|
|
1328
|
-
expected: "
|
|
1362
|
+
expected: "exact number",
|
|
1329
1363
|
match: this.match,
|
|
1330
1364
|
inputLength: text.length
|
|
1331
1365
|
}
|
|
@@ -1592,9 +1626,11 @@ function isPlainObject2(value) {
|
|
|
1592
1626
|
const proto = Object.getPrototypeOf(value);
|
|
1593
1627
|
return proto === Object.prototype || proto === null;
|
|
1594
1628
|
}
|
|
1595
|
-
function
|
|
1629
|
+
function normalizeExactResponseJsonText(input) {
|
|
1596
1630
|
const trimmed = input.trim();
|
|
1597
|
-
const fenceMatch = trimmed.match(
|
|
1631
|
+
const fenceMatch = trimmed.match(
|
|
1632
|
+
/^```([a-zA-Z]*)[^\S\r\n]*\r?\n([\s\S]*)```$/
|
|
1633
|
+
);
|
|
1598
1634
|
if (!fenceMatch) {
|
|
1599
1635
|
return trimmed;
|
|
1600
1636
|
}
|
|
@@ -1604,19 +1640,82 @@ function normalizeWholeResponseJsonText(input) {
|
|
|
1604
1640
|
}
|
|
1605
1641
|
return body.trim();
|
|
1606
1642
|
}
|
|
1643
|
+
function findBalancedJsonEnd(input, start) {
|
|
1644
|
+
const first = input[start];
|
|
1645
|
+
const stack = first === "{" ? ["}"] : first === "[" ? ["]"] : [];
|
|
1646
|
+
let inString = false;
|
|
1647
|
+
let escaping = false;
|
|
1648
|
+
for (let index = start + 1; index < input.length; index += 1) {
|
|
1649
|
+
const char = input[index];
|
|
1650
|
+
if (inString) {
|
|
1651
|
+
if (escaping) {
|
|
1652
|
+
escaping = false;
|
|
1653
|
+
} else if (char === "\\") {
|
|
1654
|
+
escaping = true;
|
|
1655
|
+
} else if (char === '"') {
|
|
1656
|
+
inString = false;
|
|
1657
|
+
}
|
|
1658
|
+
continue;
|
|
1659
|
+
}
|
|
1660
|
+
if (char === '"') {
|
|
1661
|
+
inString = true;
|
|
1662
|
+
continue;
|
|
1663
|
+
}
|
|
1664
|
+
if (char === "{" || char === "[") {
|
|
1665
|
+
stack.push(char === "{" ? "}" : "]");
|
|
1666
|
+
continue;
|
|
1667
|
+
}
|
|
1668
|
+
if (char !== "}" && char !== "]") {
|
|
1669
|
+
continue;
|
|
1670
|
+
}
|
|
1671
|
+
if (stack[stack.length - 1] !== char) {
|
|
1672
|
+
return void 0;
|
|
1673
|
+
}
|
|
1674
|
+
stack.pop();
|
|
1675
|
+
if (stack.length === 0) {
|
|
1676
|
+
return index;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
return void 0;
|
|
1680
|
+
}
|
|
1681
|
+
function extractJsonCandidates(input) {
|
|
1682
|
+
const candidates = [];
|
|
1683
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
1684
|
+
const char = input[index];
|
|
1685
|
+
if (char !== "{" && char !== "[") {
|
|
1686
|
+
continue;
|
|
1687
|
+
}
|
|
1688
|
+
const end = findBalancedJsonEnd(input, index);
|
|
1689
|
+
if (end === void 0) {
|
|
1690
|
+
continue;
|
|
1691
|
+
}
|
|
1692
|
+
const candidate = input.slice(index, end + 1);
|
|
1693
|
+
try {
|
|
1694
|
+
candidates.push({
|
|
1695
|
+
parsed: JSON.parse(candidate)
|
|
1696
|
+
});
|
|
1697
|
+
index = end;
|
|
1698
|
+
} catch {
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
return candidates;
|
|
1702
|
+
}
|
|
1607
1703
|
var JsonParser = class extends BaseParserWithJson {
|
|
1608
1704
|
constructor(options = {}) {
|
|
1609
1705
|
super("json", options);
|
|
1610
1706
|
__publicField(this, "shouldValidateSchema");
|
|
1707
|
+
__publicField(this, "match");
|
|
1708
|
+
this.match = options.match ?? "exact";
|
|
1611
1709
|
this.shouldValidateSchema = !!options.schema && options.validateSchema !== false;
|
|
1612
1710
|
}
|
|
1613
1711
|
/**
|
|
1614
1712
|
* v3 parser contract:
|
|
1615
1713
|
* Category: strict
|
|
1616
|
-
* Mode:
|
|
1714
|
+
* Mode: exact
|
|
1617
1715
|
*
|
|
1618
|
-
* Parses strict JSON object/array output
|
|
1619
|
-
*
|
|
1716
|
+
* Parses strict JSON object/array output by default. Pass match: "extract"
|
|
1717
|
+
* to extract one JSON object or array from surrounding text. Invalid JSON,
|
|
1718
|
+
* empty input, JSON primitives, and non-plain runtime objects throw typed parser errors.
|
|
1620
1719
|
* Schema validation is on by default when a schema is provided unless
|
|
1621
1720
|
* validateSchema: false is explicitly set.
|
|
1622
1721
|
*
|
|
@@ -1639,19 +1738,52 @@ var JsonParser = class extends BaseParserWithJson {
|
|
|
1639
1738
|
});
|
|
1640
1739
|
}
|
|
1641
1740
|
try {
|
|
1642
|
-
parsed = JSON.parse(
|
|
1741
|
+
parsed = JSON.parse(normalizeExactResponseJsonText(text));
|
|
1643
1742
|
} catch (cause) {
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1743
|
+
if (this.match === "extract") {
|
|
1744
|
+
const candidates = extractJsonCandidates(text);
|
|
1745
|
+
if (candidates.length === 1) {
|
|
1746
|
+
parsed = candidates[0].parsed;
|
|
1747
|
+
} else if (candidates.length > 1) {
|
|
1748
|
+
throw new LlmExeError(`Multiple JSON values found in input.`, {
|
|
1749
|
+
code: "parser.parse_failed",
|
|
1750
|
+
context: {
|
|
1751
|
+
operation: "JsonParser.parse",
|
|
1752
|
+
parser: "json",
|
|
1753
|
+
reason: "ambiguous_json_match",
|
|
1754
|
+
expected: "one JSON object or array",
|
|
1755
|
+
match: this.match,
|
|
1756
|
+
inputLength,
|
|
1757
|
+
matchCount: candidates.length
|
|
1758
|
+
}
|
|
1759
|
+
});
|
|
1760
|
+
} else {
|
|
1761
|
+
throw new LlmExeError(`No JSON value found in input.`, {
|
|
1762
|
+
code: "parser.parse_failed",
|
|
1763
|
+
context: {
|
|
1764
|
+
operation: "JsonParser.parse",
|
|
1765
|
+
parser: "json",
|
|
1766
|
+
reason: "no_json_value",
|
|
1767
|
+
expected: "JSON object or array",
|
|
1768
|
+
match: this.match,
|
|
1769
|
+
inputLength
|
|
1770
|
+
},
|
|
1771
|
+
cause
|
|
1772
|
+
});
|
|
1773
|
+
}
|
|
1774
|
+
} else {
|
|
1775
|
+
throw new LlmExeError(`Invalid JSON input.`, {
|
|
1776
|
+
code: "parser.parse_failed",
|
|
1777
|
+
context: {
|
|
1778
|
+
operation: "JsonParser.parse",
|
|
1779
|
+
parser: "json",
|
|
1780
|
+
reason: "invalid_json",
|
|
1781
|
+
expected: "JSON object or array",
|
|
1782
|
+
inputLength
|
|
1783
|
+
},
|
|
1784
|
+
cause
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1655
1787
|
}
|
|
1656
1788
|
} else if (Array.isArray(text) || isPlainObject2(text)) {
|
|
1657
1789
|
parsed = text;
|
|
@@ -2922,7 +3054,7 @@ var StringExtractParser = class extends BaseParser {
|
|
|
2922
3054
|
* Mode: configured value extraction
|
|
2923
3055
|
*
|
|
2924
3056
|
* Returns the single configured enum value found in input. Matching is
|
|
2925
|
-
* word-bounded by default; pass match: "
|
|
3057
|
+
* word-bounded by default; pass match: "exact" to require exact input or
|
|
2926
3058
|
* match: "substring" for legacy contains() behavior. Case-insensitive by
|
|
2927
3059
|
* default.
|
|
2928
3060
|
*
|
|
@@ -3004,8 +3136,8 @@ var StringExtractParser = class extends BaseParser {
|
|
|
3004
3136
|
}
|
|
3005
3137
|
findMatches(text) {
|
|
3006
3138
|
switch (this.match) {
|
|
3007
|
-
case "
|
|
3008
|
-
return this.
|
|
3139
|
+
case "exact":
|
|
3140
|
+
return this.matchExact(text);
|
|
3009
3141
|
case "substring":
|
|
3010
3142
|
return this.matchSubstring(text);
|
|
3011
3143
|
case "word":
|
|
@@ -3013,7 +3145,7 @@ var StringExtractParser = class extends BaseParser {
|
|
|
3013
3145
|
return this.matchWord(text);
|
|
3014
3146
|
}
|
|
3015
3147
|
}
|
|
3016
|
-
|
|
3148
|
+
matchExact(text) {
|
|
3017
3149
|
const candidate = this.ignoreCase ? text.trim().toLowerCase() : text.trim();
|
|
3018
3150
|
return this.enum.filter((option) => {
|
|
3019
3151
|
if (option === "") return false;
|
|
@@ -3063,36 +3195,33 @@ function createParser(...args) {
|
|
|
3063
3195
|
case "replaceStringTemplate":
|
|
3064
3196
|
return new ReplaceStringTemplateParser();
|
|
3065
3197
|
case "boolean":
|
|
3066
|
-
return new BooleanParser();
|
|
3198
|
+
return new BooleanParser(options);
|
|
3067
3199
|
case "number":
|
|
3068
3200
|
return new NumberParser(options);
|
|
3069
3201
|
case "string":
|
|
3070
3202
|
return new StringParser();
|
|
3071
3203
|
default:
|
|
3072
|
-
throw new LlmExeError(
|
|
3073
|
-
|
|
3074
|
-
{
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
],
|
|
3092
|
-
resolution: "Use a registered parser type, or define a custom parser."
|
|
3093
|
-
}
|
|
3204
|
+
throw new LlmExeError(`Invalid parser type: "${type}"`, {
|
|
3205
|
+
code: "parser.invalid_type",
|
|
3206
|
+
context: {
|
|
3207
|
+
operation: "createParser",
|
|
3208
|
+
parser: type,
|
|
3209
|
+
availableParsers: [
|
|
3210
|
+
"json",
|
|
3211
|
+
"string",
|
|
3212
|
+
"boolean",
|
|
3213
|
+
"number",
|
|
3214
|
+
"stringExtract",
|
|
3215
|
+
"listToArray",
|
|
3216
|
+
"listToJson",
|
|
3217
|
+
"listToKeyValue",
|
|
3218
|
+
"replaceStringTemplate",
|
|
3219
|
+
"markdownCodeBlock",
|
|
3220
|
+
"markdownCodeBlocks"
|
|
3221
|
+
],
|
|
3222
|
+
resolution: "Use a registered parser type, or define a custom parser."
|
|
3094
3223
|
}
|
|
3095
|
-
);
|
|
3224
|
+
});
|
|
3096
3225
|
}
|
|
3097
3226
|
}
|
|
3098
3227
|
function createCustomParser(name, parserFn) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-exe",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.2",
|
|
4
4
|
"description": "Simplify building LLM-powered apps with easy-to-use base components, supporting text and chat-based prompts with handlebars template engine, output parsers, and flexible function calling capabilities.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
package/readme.md
CHANGED
|
@@ -85,7 +85,7 @@ Welcome back!
|
|
|
85
85
|
```ts
|
|
86
86
|
createParser("string"); // pass-through, returns string
|
|
87
87
|
createParser("json", { schema }); // JSON with optional schema validation
|
|
88
|
-
createParser("boolean"); //
|
|
88
|
+
createParser("boolean"); // parses a boolean token
|
|
89
89
|
createParser("number"); // extracts number from response
|
|
90
90
|
createParser("stringExtract", { enum: ["yes", "no"] }); // match one of the enum values
|
|
91
91
|
createParser("listToArray"); // newline-separated list → string[]
|