flex-md 4.3.0 → 4.4.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/README.md +23 -32
- package/dist/ofs/adapter.d.ts +12 -2
- package/dist/ofs/adapter.js +28 -11
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -523,46 +523,37 @@ if (status === 'validated' || status === 'fixed') {
|
|
|
523
523
|
}
|
|
524
524
|
```
|
|
525
525
|
|
|
526
|
-
|
|
526
|
+
Flex-MD allows you to use its native **Output Format Spec (OFS)** as the source of truth for **NX-MD-Parser's** structured extraction.
|
|
527
527
|
|
|
528
|
-
|
|
528
|
+
### Modern "Smart" Transformation
|
|
529
529
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
import { parseOutputFormatSpec, transformWithOfs } from 'flex-md';
|
|
530
|
+
The `transformWithOfs` function is now smarter. It performs **dual parsing**:
|
|
531
|
+
1. **Automatic Parsing**: Even if you don't have a spec, it extracts all sections and camel-cases keys.
|
|
532
|
+
2. **Contract Enforcement**: If you provide a spec, it uses `nx-md-parser` to validate, type-cast (lists/tables), and repair the output.
|
|
534
533
|
|
|
535
|
-
|
|
536
|
-
const spec = parseOutputFormatSpec(`
|
|
537
|
-
## Output format
|
|
538
|
-
- Executive Summary — text (required)
|
|
539
|
-
- Key Findings — ordered list (required)
|
|
540
|
-
- Technical Specs — table (optional)
|
|
541
|
-
Columns: Component, Version, Notes
|
|
542
|
-
`);
|
|
534
|
+
#### Usage with LLM Outputs:
|
|
543
535
|
|
|
544
|
-
|
|
545
|
-
const md = `
|
|
546
|
-
### Summary
|
|
547
|
-
The system is fully operational with 99.9% uptime.
|
|
536
|
+
When working with LLMs, pass the **entire response text** directly. Flex-MD handles internal normalization (like escaped `\n` characters) automatically.
|
|
548
537
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
2. Memory leak in cache module fixed
|
|
552
|
-
`;
|
|
538
|
+
```typescript
|
|
539
|
+
import { transformWithOfs } from 'flex-md';
|
|
553
540
|
|
|
554
|
-
|
|
541
|
+
// Pass the RAW content string from your LLM provider
|
|
542
|
+
const {
|
|
543
|
+
parsedOutput, // Always populated (auto-extraction)
|
|
544
|
+
contractOutput, // Populated if spec was provided
|
|
545
|
+
contractStatus, // "ok" | "different" | "skipped"
|
|
546
|
+
status // "validated" | "fixed" | "failed"
|
|
547
|
+
} = transformWithOfs(llmResponseText, spec);
|
|
555
548
|
|
|
556
|
-
|
|
557
|
-
console.log(result['Executive Summary']); // "The system is fully operational..."
|
|
558
|
-
console.log(result['Key Findings']); // ["Scalability improved...", "Memory leak..."]
|
|
559
|
-
}
|
|
549
|
+
console.log(parsedOutput.shortAnswer);
|
|
560
550
|
```
|
|
561
551
|
|
|
562
552
|
### Why use this?
|
|
563
|
-
1. **
|
|
564
|
-
2. **
|
|
565
|
-
3. **
|
|
553
|
+
1. **Zero-Config Extraction**: Get structured data without writing a schema first.
|
|
554
|
+
2. **Dual-Safe**: Compare what the LLM *sent* (`parsedOutput`) with what the contract *required* (`contractOutput`).
|
|
555
|
+
3. **Internal Normalization**: Handles messy data (escaped newlines, merged code blocks) so you don't have to.
|
|
556
|
+
4. **Fuzzy Matching**: Even if the LLM slightly changes the heading (e.g., "Summary" vs "Executive Summary"), the contract will correctly map it.
|
|
566
557
|
|
|
567
558
|
## Advanced AI Features (via NX-MD-Parser 1.4.0)
|
|
568
559
|
|
|
@@ -622,8 +613,8 @@ const md = `
|
|
|
622
613
|
Everything looks correctly formatted based on initial evidence.
|
|
623
614
|
`;
|
|
624
615
|
|
|
625
|
-
const {
|
|
626
|
-
console.log(
|
|
616
|
+
const { contractOutput } = transformWithOfs(md, recallId);
|
|
617
|
+
console.log(contractOutput.Confidence); // 0.95
|
|
627
618
|
```
|
|
628
619
|
|
|
629
620
|
### Why use this?
|
package/dist/ofs/adapter.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
import { type SchemaType
|
|
1
|
+
import { type SchemaType } from "nx-md-parser";
|
|
2
2
|
import { type OutputFormatSpec } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Result of a Flex-MD transformation.
|
|
5
|
+
*/
|
|
6
|
+
export interface FlexTransformResult<T = any> {
|
|
7
|
+
parsedOutput: Record<string, any>;
|
|
8
|
+
contractOutput: T | null;
|
|
9
|
+
contractStatus: "ok" | "different" | "skipped";
|
|
10
|
+
status: "validated" | "fixed" | "failed";
|
|
11
|
+
errors: string[];
|
|
12
|
+
}
|
|
3
13
|
/**
|
|
4
14
|
* Converts a Flex-MD OutputFormatSpec to an nx-md-parser Schema.
|
|
5
15
|
*/
|
|
@@ -8,4 +18,4 @@ export declare function ofsToSchema(spec: OutputFormatSpec): SchemaType;
|
|
|
8
18
|
* Transforms markdown text using a Flex-MD OutputFormatSpec or a recallId.
|
|
9
19
|
* If no spec is provided, it attempts to infer it from the markdown (autospecs).
|
|
10
20
|
*/
|
|
11
|
-
export declare function transformWithOfs<T = any>(md: string, specOrRecallId?: OutputFormatSpec | string):
|
|
21
|
+
export declare function transformWithOfs<T = any>(md: string, specOrRecallId?: OutputFormatSpec | string): FlexTransformResult<T>;
|
package/dist/ofs/adapter.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { JSONTransformer, Schema } from "nx-md-parser";
|
|
2
2
|
import { recall } from "./memory.js";
|
|
3
|
-
import { parseHeadingsAndSections, extractBullets, parseMarkdownTable, normalizeName
|
|
3
|
+
import { parseHeadingsAndSections, extractBullets, parseMarkdownTable, normalizeName } from "../md/parse.js";
|
|
4
4
|
import { normalizeMarkdownInput } from "../md/normalize.js";
|
|
5
|
+
import { toCamelCase } from "nx-helpers";
|
|
6
|
+
import { markdownToJson as autoMarkdownToJson } from "nx-json-parser";
|
|
5
7
|
/**
|
|
6
8
|
* Converts a Flex-MD OutputFormatSpec to an nx-md-parser Schema.
|
|
7
9
|
*/
|
|
@@ -53,13 +55,14 @@ export function ofsToSchema(spec) {
|
|
|
53
55
|
export function transformWithOfs(md, specOrRecallId) {
|
|
54
56
|
// 0. Normalize input (handle literal \n common in LLM outputs)
|
|
55
57
|
const normalizedMd = normalizeMarkdownInput(md);
|
|
58
|
+
// 1. Automatic parsing (Dual-Response) using nx-json-parser
|
|
59
|
+
const parsedOutput = autoMarkdownToJson(normalizedMd);
|
|
56
60
|
if (!specOrRecallId) {
|
|
57
|
-
// AUTOSPECS: If no spec is provided, use internal logic ONLY.
|
|
58
|
-
// This avoids complex schema generation and keeps it robust for unknown structures.
|
|
59
|
-
const result = markdownToJson(normalizedMd);
|
|
60
61
|
return {
|
|
62
|
+
parsedOutput,
|
|
63
|
+
contractOutput: null,
|
|
64
|
+
contractStatus: "skipped",
|
|
61
65
|
status: "validated",
|
|
62
|
-
result: result,
|
|
63
66
|
errors: []
|
|
64
67
|
};
|
|
65
68
|
}
|
|
@@ -68,8 +71,10 @@ export function transformWithOfs(md, specOrRecallId) {
|
|
|
68
71
|
const recalled = recall(specOrRecallId);
|
|
69
72
|
if (!recalled) {
|
|
70
73
|
return {
|
|
74
|
+
parsedOutput,
|
|
75
|
+
contractOutput: null,
|
|
76
|
+
contractStatus: "skipped",
|
|
71
77
|
status: "failed",
|
|
72
|
-
result: null,
|
|
73
78
|
errors: [`Recall ID "${specOrRecallId}" not found in memory.`]
|
|
74
79
|
};
|
|
75
80
|
}
|
|
@@ -78,14 +83,13 @@ export function transformWithOfs(md, specOrRecallId) {
|
|
|
78
83
|
else {
|
|
79
84
|
spec = specOrRecallId;
|
|
80
85
|
}
|
|
81
|
-
//
|
|
86
|
+
// 2. Parse sections using Flex-MD parser for the contract mapping
|
|
82
87
|
const bulletNames = spec.sections.map(s => s.name);
|
|
88
|
+
// Note: We use the local headings parser to find the specific sections defined in the spec
|
|
83
89
|
const parsedSections = parseHeadingsAndSections(normalizedMd, { bulletNames });
|
|
84
90
|
const parsedObj = {};
|
|
85
|
-
// 2. Map sections to OFS and apply complex parsing (tables/lists)
|
|
86
91
|
for (const sectionSpec of spec.sections) {
|
|
87
92
|
const normName = normalizeName(sectionSpec.name);
|
|
88
|
-
// Find section with similar name
|
|
89
93
|
const found = parsedSections.find(s => normalizeName(s.heading.name) === normName);
|
|
90
94
|
if (found) {
|
|
91
95
|
let value;
|
|
@@ -110,8 +114,21 @@ export function transformWithOfs(md, specOrRecallId) {
|
|
|
110
114
|
parsedObj[sectionSpec.name] = value;
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
|
-
// 3. Transform using nx-md-parser for schema validation and
|
|
117
|
+
// 3. Transform using nx-md-parser (latest v2.2.0) for schema validation and fixing
|
|
114
118
|
const schema = ofsToSchema(spec);
|
|
115
119
|
const transformer = new JSONTransformer(schema);
|
|
116
|
-
|
|
120
|
+
const transformResult = transformer.transform(parsedObj);
|
|
121
|
+
// 4. Compare parsed results with contract results
|
|
122
|
+
const autoKeys = Object.keys(parsedOutput).sort();
|
|
123
|
+
const contractKeys = transformResult.result ? Object.keys(transformResult.result).map(k => toCamelCase(k)).sort() : [];
|
|
124
|
+
const isSame = autoKeys.length > 0 &&
|
|
125
|
+
autoKeys.every(k => contractKeys.includes(k)) &&
|
|
126
|
+
contractKeys.length === autoKeys.length;
|
|
127
|
+
return {
|
|
128
|
+
parsedOutput,
|
|
129
|
+
contractOutput: transformResult.result,
|
|
130
|
+
contractStatus: isSame ? "ok" : "different",
|
|
131
|
+
status: transformResult.status,
|
|
132
|
+
errors: transformResult.errors || []
|
|
133
|
+
};
|
|
117
134
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flex-md",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.2",
|
|
4
4
|
"description": "Parse and stringify FlexMD: semi-structured Markdown with three powerful layers - Frames, Output Format Spec (OFS), and Detection/Extraction.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "",
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
"detection",
|
|
17
17
|
"extraction"
|
|
18
18
|
],
|
|
19
|
+
"ts-node": {
|
|
20
|
+
"esm": true
|
|
21
|
+
},
|
|
19
22
|
"type": "module",
|
|
20
23
|
"main": "./dist/index.cjs",
|
|
21
24
|
"module": "./dist/index.js",
|
|
@@ -44,12 +47,14 @@
|
|
|
44
47
|
},
|
|
45
48
|
"devDependencies": {
|
|
46
49
|
"@types/node": "^25.0.3",
|
|
50
|
+
"tsx": "^4.21.0",
|
|
47
51
|
"typescript": "^5.6.3",
|
|
48
52
|
"vitest": "^4.0.16"
|
|
49
53
|
},
|
|
50
54
|
"dependencies": {
|
|
51
55
|
"nd": "^1.2.0",
|
|
52
56
|
"nx-helpers": "^1.5.0",
|
|
53
|
-
"nx-
|
|
57
|
+
"nx-json-parser": "^1.1.0",
|
|
58
|
+
"nx-md-parser": "^2.2.0"
|
|
54
59
|
}
|
|
55
|
-
}
|
|
60
|
+
}
|