@agentix-e/nl2spel 1.3.0 → 1.4.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 +1 -1
- package/dist/index.cjs +935 -276
- package/dist/index.d.cts +228 -22
- package/dist/index.d.ts +228 -22
- package/dist/index.js +930 -275
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -334,6 +334,25 @@ interface SlotDefinition {
|
|
|
334
334
|
}
|
|
335
335
|
type SlotTransform = 'toNumber' | 'toBoolean' | 'toString' | 'trim' | 'lowercase' | 'normalize';
|
|
336
336
|
|
|
337
|
+
/**
|
|
338
|
+
* How to treat a field word the dictionary does not know.
|
|
339
|
+
*
|
|
340
|
+
* `passthrough` emits the word verbatim, which is legal Spring — `Character.isLetter`
|
|
341
|
+
* accepts any Unicode letter — and is the default, because a caller whose schema
|
|
342
|
+
* uses Chinese property names depends on it. `strict` refuses instead, for callers
|
|
343
|
+
* who would rather see an error than an unresolved name.
|
|
344
|
+
*/
|
|
345
|
+
type FieldPolicy = 'passthrough' | 'strict';
|
|
346
|
+
/** Thrown under `strict` when a field word has no dictionary entry. */
|
|
347
|
+
declare class UnmappedFieldError extends Error {
|
|
348
|
+
/** The field word that could not be resolved. */
|
|
349
|
+
readonly field: string;
|
|
350
|
+
constructor(field: string);
|
|
351
|
+
}
|
|
352
|
+
interface PatternMatcherOptions {
|
|
353
|
+
/** How to treat a field word with no dictionary entry. Default `passthrough`. */
|
|
354
|
+
fieldPolicy?: FieldPolicy;
|
|
355
|
+
}
|
|
337
356
|
interface PatternMatchResult {
|
|
338
357
|
/** Whether matched */
|
|
339
358
|
matched: boolean;
|
|
@@ -347,13 +366,17 @@ interface PatternMatchResult {
|
|
|
347
366
|
latencyMs: number;
|
|
348
367
|
/** Extracted slot values */
|
|
349
368
|
slots?: Record<string, string>;
|
|
369
|
+
/**
|
|
370
|
+
* Field words emitted verbatim because the dictionary had no entry, in
|
|
371
|
+
* encounter order. Populated under either policy, so a caller can always see
|
|
372
|
+
* what was not resolved rather than having to infer it.
|
|
373
|
+
*/
|
|
374
|
+
unmappedFields?: string[];
|
|
350
375
|
}
|
|
351
|
-
/**
|
|
352
|
-
* PatternMatcher — Layer 0 pattern matching core.
|
|
353
|
-
*/
|
|
354
376
|
declare class PatternMatcher {
|
|
355
377
|
private _patterns;
|
|
356
|
-
|
|
378
|
+
private readonly fieldPolicy;
|
|
379
|
+
constructor(patterns?: PatternDefinition[], options?: PatternMatcherOptions);
|
|
357
380
|
get patternCount(): number;
|
|
358
381
|
register(pattern: PatternDefinition): void;
|
|
359
382
|
registerAll(patterns: PatternDefinition[]): void;
|
|
@@ -374,18 +397,29 @@ declare class PatternMatcher {
|
|
|
374
397
|
* Infer SpEL root object name from Chinese input
|
|
375
398
|
*/
|
|
376
399
|
private inferRoot;
|
|
400
|
+
/**
|
|
401
|
+
* The first whitespace- or punctuation-delimited chunk of `input`.
|
|
402
|
+
*/
|
|
403
|
+
private firstWord;
|
|
377
404
|
/**
|
|
378
405
|
* Extract Chinese field names from input and map to SpEL fields
|
|
379
406
|
*/
|
|
380
407
|
private extractChineseField;
|
|
381
408
|
/**
|
|
382
|
-
*
|
|
409
|
+
* Resolve a captured field word into the identifier to emit, and report whether
|
|
410
|
+
* the dictionary recognised it.
|
|
411
|
+
*
|
|
412
|
+
* An ASCII word is already an identifier and is emitted unchanged. Anything else
|
|
413
|
+
* is looked up: a word the dictionary knows becomes its English identifier, and a
|
|
414
|
+
* word it does not know is emitted verbatim and reported as unmapped. Emitting it
|
|
415
|
+
* verbatim is legal Spring, but it is a guess about the caller's schema, so the
|
|
416
|
+
* guess is never silent.
|
|
383
417
|
*/
|
|
384
|
-
private
|
|
418
|
+
private resolveField;
|
|
385
419
|
/**
|
|
386
|
-
*
|
|
420
|
+
* Template filling and value transformation
|
|
387
421
|
*/
|
|
388
|
-
private
|
|
422
|
+
private fillTemplate;
|
|
389
423
|
}
|
|
390
424
|
|
|
391
425
|
/**
|
|
@@ -399,6 +433,60 @@ declare class PatternMatcher {
|
|
|
399
433
|
*/
|
|
400
434
|
declare const BUILTIN_PATTERNS: PatternDefinition[];
|
|
401
435
|
|
|
436
|
+
/**
|
|
437
|
+
* Clause decomposition for compound natural-language rules.
|
|
438
|
+
*
|
|
439
|
+
* A single comparison pattern matches a prefix and ignores the rest, so a
|
|
440
|
+
* sentence that joins two conditions is silently answered with only the first
|
|
441
|
+
* one: `金额大于1000且订单已确认` used to produce `#amount > 1000`, dropping the
|
|
442
|
+
* confirmation requirement entirely. The result parses, so nothing downstream
|
|
443
|
+
* notices — a materially weaker rule than the one that was asked for.
|
|
444
|
+
*
|
|
445
|
+
* This module splits such a sentence on its top-level logical connectors, has the
|
|
446
|
+
* caller convert each clause independently, and joins the results with SpEL's
|
|
447
|
+
* `and`/`or`. A clause that cannot be converted is reported rather than dropped:
|
|
448
|
+
* a partial rule is never emitted.
|
|
449
|
+
*/
|
|
450
|
+
interface Clause {
|
|
451
|
+
/** Clause text, trimmed. */
|
|
452
|
+
text: string;
|
|
453
|
+
/**
|
|
454
|
+
* How this clause attaches to the previous one. The first clause carries
|
|
455
|
+
* `'and'`, which is never used because a single clause needs no join.
|
|
456
|
+
*/
|
|
457
|
+
connector: 'and' | 'or';
|
|
458
|
+
}
|
|
459
|
+
/** Raised when a compound sentence contains a clause that cannot be converted. */
|
|
460
|
+
declare class UnconvertibleClauseError extends Error {
|
|
461
|
+
/** The clause texts that could not be converted. */
|
|
462
|
+
readonly unconvertible: readonly string[];
|
|
463
|
+
/** The full input that was being decomposed. */
|
|
464
|
+
readonly input: string;
|
|
465
|
+
constructor(input: string, unconvertible: readonly string[]);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Split `input` on its top-level logical connectors.
|
|
469
|
+
*
|
|
470
|
+
* Returns a single clause when there is no top-level connector, so the caller can
|
|
471
|
+
* treat "one clause" and "no decomposition needed" identically.
|
|
472
|
+
*/
|
|
473
|
+
declare function splitClauses(input: string): Clause[];
|
|
474
|
+
interface Decomposition {
|
|
475
|
+
/** The joined expression, with every operand parenthesised. */
|
|
476
|
+
expression: string;
|
|
477
|
+
/** The clause texts, in order. */
|
|
478
|
+
clauses: string[];
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Decompose `input` and convert every clause with `convert`.
|
|
482
|
+
*
|
|
483
|
+
* Returns `null` when the input has no top-level connector — the caller should
|
|
484
|
+
* run its ordinary single-pass conversion instead. Throws
|
|
485
|
+
* {@link UnconvertibleClauseError} when any clause cannot be converted, so a
|
|
486
|
+
* partially understood sentence is never answered with a partial rule.
|
|
487
|
+
*/
|
|
488
|
+
declare function decompose(input: string, convert: (clause: string) => string | null): Decomposition | null;
|
|
489
|
+
|
|
402
490
|
/**
|
|
403
491
|
* NLIntent — Natural language intent classification system.
|
|
404
492
|
*
|
|
@@ -514,6 +602,22 @@ declare class TemplateEngine {
|
|
|
514
602
|
generate(input: string, intentResult: IntentResult): TemplateResult | null;
|
|
515
603
|
private selectBestTemplate;
|
|
516
604
|
private fillTemplate;
|
|
605
|
+
/**
|
|
606
|
+
* Resolve the SpEL root name for `input`: the configured schema root when one
|
|
607
|
+
* exists, otherwise a keyword heuristic over the well-known roots.
|
|
608
|
+
*/
|
|
609
|
+
private resolveRootName;
|
|
610
|
+
/**
|
|
611
|
+
* Resolve the field name for `input`.
|
|
612
|
+
*
|
|
613
|
+
* The previous implementation only compared schema *keys* and otherwise left
|
|
614
|
+
* the literal placeholder default in place, which is how "#order.field == null"
|
|
615
|
+
* reached callers. The lookup now falls back in order: schema key, schema
|
|
616
|
+
* field description (Chinese inputs name the field by its description),
|
|
617
|
+
* Chinese field word, first English identifier, and finally "value" — the
|
|
618
|
+
* neutral default the pattern layer already uses for an unknown field.
|
|
619
|
+
*/
|
|
620
|
+
private resolveFieldName;
|
|
517
621
|
}
|
|
518
622
|
|
|
519
623
|
interface PromptBuilderOptions {
|
|
@@ -534,6 +638,10 @@ declare class PromptBuilder {
|
|
|
534
638
|
private buildExamples;
|
|
535
639
|
}
|
|
536
640
|
|
|
641
|
+
/** Stage a diagnostic was produced by. */
|
|
642
|
+
type ValidationStage = 'parse' | 'type' | 'semantic' | 'context' | 'final';
|
|
643
|
+
/** Whether a diagnostic rejects the expression or merely observes it. */
|
|
644
|
+
type ValidationSeverity = 'error' | 'warning';
|
|
537
645
|
interface ValidationResult {
|
|
538
646
|
/** Whether all validation stages passed */
|
|
539
647
|
valid: boolean;
|
|
@@ -543,6 +651,7 @@ interface ValidationResult {
|
|
|
543
651
|
type: StageResult;
|
|
544
652
|
semantic: StageResult;
|
|
545
653
|
context: StageResult;
|
|
654
|
+
final: StageResult;
|
|
546
655
|
};
|
|
547
656
|
/** All errors */
|
|
548
657
|
errors: ValidationError[];
|
|
@@ -557,28 +666,38 @@ interface StageResult {
|
|
|
557
666
|
interface ValidationError {
|
|
558
667
|
code: string;
|
|
559
668
|
message: string;
|
|
669
|
+
/** Severity of this diagnostic — always `error`. */
|
|
670
|
+
severity?: ValidationSeverity;
|
|
560
671
|
/** Error position in expression */
|
|
561
672
|
position?: number;
|
|
562
673
|
/** Stage the error belongs to */
|
|
563
|
-
stage:
|
|
674
|
+
stage: ValidationStage;
|
|
564
675
|
/** Whether LLM regeneration is needed */
|
|
565
676
|
requiresLLM?: boolean;
|
|
566
677
|
}
|
|
567
678
|
interface ValidationWarning {
|
|
568
679
|
code: string;
|
|
569
680
|
message: string;
|
|
681
|
+
/** Severity of this diagnostic — always `warning`. */
|
|
682
|
+
severity?: ValidationSeverity;
|
|
570
683
|
/** Warning position in expression */
|
|
571
684
|
position?: number;
|
|
572
685
|
/** Stage the warning belongs to */
|
|
573
|
-
stage:
|
|
686
|
+
stage: ValidationStage;
|
|
574
687
|
}
|
|
575
688
|
/**
|
|
576
|
-
* ValidationPipeline —
|
|
689
|
+
* ValidationPipeline — five-stage validation pipeline.
|
|
577
690
|
*
|
|
578
|
-
* 1. Parse: syntax validity (
|
|
579
|
-
*
|
|
580
|
-
*
|
|
581
|
-
*
|
|
691
|
+
* 1. Parse: syntax validity (empty, delimiter balance, JS operators, evaluator)
|
|
692
|
+
* 2. Type: type checking (operator-operand type matching) — advisory
|
|
693
|
+
* 3. Semantic: semantic reasonableness — advisory
|
|
694
|
+
* 4. Context: context references (do all references exist in ContextSchema)
|
|
695
|
+
* 5. Final: the expression must parse — structural completeness gate
|
|
696
|
+
*
|
|
697
|
+
* Stages 1, 4 and 5 can reject an expression; the type and semantic stages only
|
|
698
|
+
* observe. Reference checks are only meaningful when a schema is supplied,
|
|
699
|
+
* because without one an undeclared `#unknownRef` and a legitimate runtime
|
|
700
|
+
* variable are indistinguishable.
|
|
582
701
|
*/
|
|
583
702
|
declare class ValidationPipeline {
|
|
584
703
|
private evaluator;
|
|
@@ -590,36 +709,103 @@ declare class ValidationPipeline {
|
|
|
590
709
|
validate(expression: string, contextSchema?: ContextSchema): Promise<ValidationResult>;
|
|
591
710
|
/**
|
|
592
711
|
* Stage 1: Parse Check — syntax validation
|
|
712
|
+
*
|
|
713
|
+
* Delimiter balance and JavaScript operators are checked against a copy of
|
|
714
|
+
* the expression with string literals blanked out, so literal text can never
|
|
715
|
+
* be mistaken for syntax.
|
|
593
716
|
*/
|
|
594
717
|
private validateParse;
|
|
595
718
|
/**
|
|
596
|
-
* Stage 2: Type Check — type validation
|
|
719
|
+
* Stage 2: Type Check — advisory type validation
|
|
597
720
|
*/
|
|
598
721
|
private validateTypes;
|
|
599
722
|
/**
|
|
600
|
-
* Stage 3: Semantic Check — semantic
|
|
723
|
+
* Stage 3: Semantic Check — advisory semantic validation
|
|
601
724
|
*/
|
|
602
725
|
private validateSemantic;
|
|
603
726
|
/**
|
|
604
727
|
* Stage 4: Context Check — context reference validation
|
|
728
|
+
*
|
|
729
|
+
* A supplied schema turns this stage into a real gate: an undeclared bean,
|
|
730
|
+
* a missing root field or an undeclared variable is an error. Without a
|
|
731
|
+
* schema nothing can be judged, so the stage stays advisory.
|
|
605
732
|
*/
|
|
606
733
|
private validateContext;
|
|
607
734
|
/**
|
|
608
|
-
* Check
|
|
735
|
+
* Stage 5: Final Check — the generated expression must parse.
|
|
736
|
+
*
|
|
737
|
+
* When an evaluator is configured the parse stage already performed a real
|
|
738
|
+
* parse; this mandatory final gate adds the structural check that a truncated
|
|
739
|
+
* tail (an expression ending on an operator) is never accepted, even when no
|
|
740
|
+
* engine is wired in. It is deliberately conservative: only a trailing
|
|
741
|
+
* operator or an unterminated literal fails, so no well-formed expression is
|
|
742
|
+
* rejected.
|
|
743
|
+
*/
|
|
744
|
+
private validateFinal;
|
|
745
|
+
/**
|
|
746
|
+
* Whether the expression is obviously incomplete.
|
|
747
|
+
*
|
|
748
|
+
* The last token is obtained from spel-ts's tokenizer, so a trailing
|
|
749
|
+
* operator keyword or an unterminated string literal is detected exactly,
|
|
750
|
+
* and text inside a literal is never read as a trailing operator.
|
|
751
|
+
*/
|
|
752
|
+
private isManifestlyIncomplete;
|
|
753
|
+
/**
|
|
754
|
+
* Check if parentheses are balanced. Expects a literal-masked expression.
|
|
609
755
|
*/
|
|
610
756
|
private hasBalancedParentheses;
|
|
611
757
|
/**
|
|
612
|
-
* Extract all identifier references from expression
|
|
758
|
+
* Extract all identifier references from expression.
|
|
759
|
+
*
|
|
760
|
+
* A bare `#x` that is only the head of a dotted reference (`#x.y`) is not
|
|
761
|
+
* emitted on its own: a dotted reference names a property of some object,
|
|
762
|
+
* not a variable of that name.
|
|
613
763
|
*/
|
|
614
764
|
private extractReferences;
|
|
615
765
|
}
|
|
616
766
|
|
|
617
767
|
/**
|
|
618
|
-
* AutoFixer —
|
|
768
|
+
* AutoFixer — rewrites the JavaScript spellings an LLM commonly emits into the
|
|
769
|
+
* SpEL equivalents, without ever touching the contents of a string literal.
|
|
770
|
+
*
|
|
771
|
+
* Literal boundaries come from a quote-state scan. In SpEL a quote character is
|
|
772
|
+
* always a string-literal delimiter — the language has no comments and no other
|
|
773
|
+
* construct that uses `'` or `"` — so the scan is exact by construction rather
|
|
774
|
+
* than an approximation of the parser. It is also independent of the engine
|
|
775
|
+
* build: deriving the boundaries from the lexer made every structural check
|
|
776
|
+
* depend on the lexer being able to tokenize the *whole* expression, which fails
|
|
777
|
+
* for input the engine cannot lex at all, such as a field name in Chinese on a
|
|
778
|
+
* build without Unicode identifier support. A whole-string regex (the previous
|
|
779
|
+
* implementation) rewrote literal contents and appended closers for delimiters
|
|
780
|
+
* it could only see inside literals, turning valid expressions into broken
|
|
781
|
+
* ones.
|
|
619
782
|
*/
|
|
620
783
|
declare class AutoFixer {
|
|
621
784
|
fix(expression: string): AutoFixResult;
|
|
622
|
-
|
|
785
|
+
/**
|
|
786
|
+
* Apply one global replacement rule to every unprotected chunk.
|
|
787
|
+
*
|
|
788
|
+
* The replacement is only reported when it actually matched, and the count
|
|
789
|
+
* is the number of matches across all chunks, so the human-readable change
|
|
790
|
+
* log is unchanged from the previous implementation.
|
|
791
|
+
*/
|
|
792
|
+
private applyRule;
|
|
793
|
+
/**
|
|
794
|
+
* Normalise the Elvis operator only when it was written with whitespace
|
|
795
|
+
* between `?` and `:`. A correctly written `?:` must be left untouched so
|
|
796
|
+
* that `fix()` is a no-op on already-valid input.
|
|
797
|
+
*/
|
|
798
|
+
private applyElvisRule;
|
|
799
|
+
/**
|
|
800
|
+
* Split the expression into alternating protected (string literal) and
|
|
801
|
+
* unprotected chunks. Ranges come from spel-ts's tokenizer so they agree
|
|
802
|
+
* exactly with what the parser considers opaque.
|
|
803
|
+
*/
|
|
804
|
+
private split;
|
|
805
|
+
/**
|
|
806
|
+
* Turn protected spans into a chunk list covering the whole expression.
|
|
807
|
+
*/
|
|
808
|
+
private toChunks;
|
|
623
809
|
}
|
|
624
810
|
interface AutoFixResult {
|
|
625
811
|
expression: string;
|
|
@@ -685,6 +871,8 @@ interface StrategyResult {
|
|
|
685
871
|
interface StrategyMetadata {
|
|
686
872
|
/** Matched pattern ID (pattern strategy only) */
|
|
687
873
|
patternId?: string;
|
|
874
|
+
/** Clause texts, when a compound sentence was decomposed */
|
|
875
|
+
clauses?: string[];
|
|
688
876
|
/** Intent type (template strategy only) */
|
|
689
877
|
intent?: string;
|
|
690
878
|
/** Template name (template strategy only) */
|
|
@@ -698,6 +886,15 @@ interface StrategyMetadata {
|
|
|
698
886
|
/** Raw LLM output (llm strategy only) */
|
|
699
887
|
rawOutput?: string;
|
|
700
888
|
}
|
|
889
|
+
/** A compound sentence converted clause by clause. */
|
|
890
|
+
interface DecomposedConversion {
|
|
891
|
+
/** The joined expression, with every operand parenthesised. */
|
|
892
|
+
expression: string;
|
|
893
|
+
/** The clause texts, in order. */
|
|
894
|
+
clauses: string[];
|
|
895
|
+
/** The lowest confidence among the converted clauses. */
|
|
896
|
+
confidence: number;
|
|
897
|
+
}
|
|
701
898
|
interface StrategyRouterConfig {
|
|
702
899
|
/** Pattern confidence threshold (default 0.7) */
|
|
703
900
|
patternMinConfidence?: number;
|
|
@@ -727,6 +924,15 @@ declare class StrategyRouter {
|
|
|
727
924
|
/**
|
|
728
925
|
* Get PatternMatcher (for external testing/debugging)
|
|
729
926
|
*/
|
|
927
|
+
/**
|
|
928
|
+
* Convert a sentence that joins its clauses with a logical connector.
|
|
929
|
+
*
|
|
930
|
+
* Returns `null` when `nl` has no top-level connector, in which case the caller
|
|
931
|
+
* should use its ordinary single-pass conversion. Throws
|
|
932
|
+
* {@link UnconvertibleClauseError} when a clause cannot be converted, so the
|
|
933
|
+
* caller can refuse instead of emitting a partial rule.
|
|
934
|
+
*/
|
|
935
|
+
decomposeClauses(nl: string): DecomposedConversion | null;
|
|
730
936
|
getPatternMatcher(): PatternMatcher;
|
|
731
937
|
/**
|
|
732
938
|
* Get TemplateEngine
|
|
@@ -914,4 +1120,4 @@ declare class ChineseNumberParser {
|
|
|
914
1120
|
static parseSafe(text: string): number | null;
|
|
915
1121
|
}
|
|
916
1122
|
|
|
917
|
-
export { type AutoFixResult, AutoFixer, BUILTIN_PATTERNS, ChineseNumberParser, ContextExtractor, type CorrectionLog, type DebugInfo, type ExplainResult, type FewShotExample, type GenerateOptions, type GenerateResult, IntentClassifier, type IntentEntity, type IntentResult, type LLMCapabilities, type LLMGenerateOptions, type LLMPrompt, type LLMProvider, type LLMResponse, type LLMStreamChunk, type LLMUsage, NL2SpelEngine, NLIntent, type PatternDefinition, type PatternMatchResult, PatternMatcher, PromptBuilder, type PromptBuilderOptions, ProviderRegistry, SchemaFormatter, type SelfCorrectionConfig, SelfCorrectionLoop, type SelfCorrectionResult, type SlotDefinition, type SlotTransform, type StageResult, type StrategyMetadata, type StrategyResult, StrategyRouter, type StrategyRouterConfig, type StrategyType, TemplateEngine, type TemplateResult, type ValidationError, ValidationPipeline, type ValidationResult, type ValidationWarning };
|
|
1123
|
+
export { type AutoFixResult, AutoFixer, BUILTIN_PATTERNS, ChineseNumberParser, type Clause, ContextExtractor, type CorrectionLog, type DebugInfo, type Decomposition, type ExplainResult, type FewShotExample, type FieldPolicy, type GenerateOptions, type GenerateResult, IntentClassifier, type IntentEntity, type IntentResult, type LLMCapabilities, type LLMGenerateOptions, type LLMPrompt, type LLMProvider, type LLMResponse, type LLMStreamChunk, type LLMUsage, NL2SpelEngine, NLIntent, type PatternDefinition, type PatternMatchResult, PatternMatcher, type PatternMatcherOptions, PromptBuilder, type PromptBuilderOptions, ProviderRegistry, SchemaFormatter, type SelfCorrectionConfig, SelfCorrectionLoop, type SelfCorrectionResult, type SlotDefinition, type SlotTransform, type StageResult, type StrategyMetadata, type StrategyResult, StrategyRouter, type StrategyRouterConfig, type StrategyType, TemplateEngine, type TemplateResult, UnconvertibleClauseError, UnmappedFieldError, type ValidationError, ValidationPipeline, type ValidationResult, type ValidationWarning, decompose, splitClauses };
|