flex-md 4.7.1 → 4.7.3
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 +5 -0
- package/athenices-ai-gateway.md +25 -0
- package/dist/__tests__/diagnostics.test.js +45 -47
- package/dist/__tests__/ofs.test.js +28 -30
- package/dist/__tests__/structural.test.js +19 -21
- package/dist/__tests__/validate.test.js +27 -29
- package/dist/cli/index.js +13 -15
- package/dist/detect/json/detectIntent.js +1 -4
- package/dist/detect/json/detectMarkdown.js +29 -35
- package/dist/detect/json/detectPresence.js +2 -6
- package/dist/detect/json/index.js +10 -31
- package/dist/detect/json/types.js +1 -2
- package/dist/extract/extract.js +11 -14
- package/dist/extract/types.js +1 -2
- package/dist/index.js +22 -69
- package/dist/logger.js +3 -6
- package/dist/md/match.js +1 -4
- package/dist/md/normalize.js +1 -4
- package/dist/md/outline.js +4 -8
- package/dist/md/parse.js +11 -20
- package/dist/ofs/adapter.js +45 -49
- package/dist/ofs/enricher.js +3 -8
- package/dist/ofs/infer.js +4 -7
- package/dist/ofs/issuesEnvelope.js +5 -10
- package/dist/ofs/memory.js +6 -10
- package/dist/ofs/parser.js +7 -13
- package/dist/ofs/stringify.js +1 -4
- package/dist/pipeline/enforce.js +12 -15
- package/dist/pipeline/kind.js +3 -6
- package/dist/pipeline/repair.js +8 -11
- package/dist/strictness/container.js +1 -4
- package/dist/strictness/processor.js +7 -10
- package/dist/strictness/types.js +1 -4
- package/dist/tokens/auto-fix.js +1 -4
- package/dist/tokens/cognitive-cost.js +6 -10
- package/dist/tokens/compliance.js +4 -8
- package/dist/tokens/confidence.js +6 -9
- package/dist/tokens/estimator.js +20 -26
- package/dist/tokens/improvements.js +12 -16
- package/dist/tokens/index.js +22 -40
- package/dist/tokens/parser.js +4 -7
- package/dist/tokens/patterns.js +2 -5
- package/dist/tokens/runtime-estimator.js +9 -12
- package/dist/tokens/smart-report.js +10 -14
- package/dist/tokens/spec-estimator.js +10 -15
- package/dist/tokens/types.js +1 -2
- package/dist/tokens/validator.js +3 -6
- package/dist/types.js +1 -2
- package/dist/validate/compliance.js +4 -8
- package/dist/validate/connection.js +5 -8
- package/dist/validate/types.js +1 -2
- package/dist/validate/validate.js +16 -19
- package/dist-cjs/__tests__/diagnostics.test.cjs +61 -0
- package/dist-cjs/__tests__/ofs.test.cjs +53 -0
- package/dist-cjs/__tests__/structural.test.cjs +30 -0
- package/dist-cjs/__tests__/validate.test.cjs +110 -0
- package/dist-cjs/cli/index.cjs +110 -0
- package/dist-cjs/detect/json/detectIntent.cjs +82 -0
- package/dist-cjs/detect/json/detectMarkdown.cjs +304 -0
- package/dist-cjs/detect/json/detectPresence.cjs +195 -0
- package/dist-cjs/detect/json/index.cjs +34 -0
- package/dist-cjs/detect/json/types.cjs +2 -0
- package/dist-cjs/extract/extract.cjs +72 -0
- package/dist-cjs/extract/types.cjs +2 -0
- package/dist-cjs/flex-md-loader.cjs +102 -0
- package/dist-cjs/index.cjs +79 -0
- package/dist-cjs/logger.cjs +22 -0
- package/dist-cjs/md/match.cjs +47 -0
- package/dist-cjs/md/normalize.cjs +13 -0
- package/dist-cjs/md/outline.cjs +49 -0
- package/dist-cjs/md/parse.cjs +199 -0
- package/dist-cjs/ofs/adapter.cjs +195 -0
- package/dist-cjs/ofs/enricher.cjs +151 -0
- package/dist-cjs/ofs/infer.cjs +63 -0
- package/dist-cjs/ofs/issuesEnvelope.cjs +76 -0
- package/dist-cjs/ofs/memory.cjs +26 -0
- package/dist-cjs/ofs/parser.cjs +373 -0
- package/dist-cjs/ofs/stringify.cjs +45 -0
- package/dist-cjs/pipeline/enforce.cjs +49 -0
- package/dist-cjs/pipeline/kind.cjs +30 -0
- package/dist-cjs/pipeline/repair.cjs +115 -0
- package/dist-cjs/strictness/container.cjs +49 -0
- package/dist-cjs/strictness/processor.cjs +32 -0
- package/dist-cjs/strictness/types.cjs +109 -0
- package/dist-cjs/tokens/auto-fix.cjs +59 -0
- package/dist-cjs/tokens/cognitive-cost.cjs +209 -0
- package/dist-cjs/tokens/compliance.cjs +74 -0
- package/dist-cjs/tokens/confidence.cjs +335 -0
- package/dist-cjs/tokens/estimator.cjs +157 -0
- package/dist-cjs/tokens/improvements.cjs +701 -0
- package/dist-cjs/tokens/index.cjs +74 -0
- package/dist-cjs/tokens/parser.cjs +100 -0
- package/dist-cjs/tokens/patterns.cjs +23 -0
- package/dist-cjs/tokens/runtime-estimator.cjs +74 -0
- package/dist-cjs/tokens/smart-report.cjs +191 -0
- package/dist-cjs/tokens/spec-estimator.cjs +125 -0
- package/dist-cjs/tokens/types.cjs +2 -0
- package/dist-cjs/tokens/validator.cjs +62 -0
- package/dist-cjs/types.cjs +2 -0
- package/dist-cjs/validate/compliance.cjs +103 -0
- package/dist-cjs/validate/connection.cjs +47 -0
- package/dist-cjs/validate/types.cjs +2 -0
- package/dist-cjs/validate/validate.cjs +319 -0
- package/docs/consumption.md +45 -0
- package/package.json +12 -8
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Helpers for "framed vs frameless" Markdown handling before Flex-MD.
|
|
4
3
|
*
|
|
@@ -9,29 +8,24 @@
|
|
|
9
8
|
* Notes:
|
|
10
9
|
* - This is heuristic by design; tune thresholds as you learn your data.
|
|
11
10
|
*/
|
|
12
|
-
|
|
13
|
-
exports.detectMarkdown = detectMarkdown;
|
|
14
|
-
exports.stripSingleFence = stripSingleFence;
|
|
15
|
-
exports.forceWrapAsMarkdown = forceWrapAsMarkdown;
|
|
16
|
-
exports.normalizeForFlexMd = normalizeForFlexMd;
|
|
17
|
-
const logger_js_1 = require("../../logger.js");
|
|
11
|
+
import { logger } from "../../logger.js";
|
|
18
12
|
const SINGLE_FENCE_BLOCK_RE = /^```([a-zA-Z0-9_-]+)?([^\n]*)\n([\s\S]*?)\n```$/;
|
|
19
13
|
const FENCE_OPEN_RE = /(^|\n)```/g;
|
|
20
|
-
function detectMarkdown(text) {
|
|
21
|
-
|
|
14
|
+
export function detectMarkdown(text) {
|
|
15
|
+
logger.debug("Starting markdown detection", {
|
|
22
16
|
inputType: typeof text,
|
|
23
17
|
inputLength: typeof text === "string" ? text.length : JSON.stringify(text ?? "").length
|
|
24
18
|
});
|
|
25
19
|
const reasons = [];
|
|
26
20
|
const raw = typeof text === "string" ? text : JSON.stringify(text ?? "");
|
|
27
21
|
const s = raw.replace(/\r\n/g, "\n");
|
|
28
|
-
|
|
22
|
+
logger.verbose("Input normalized for processing", {
|
|
29
23
|
originalType: typeof text,
|
|
30
24
|
normalizedLength: s.length,
|
|
31
25
|
hasNewlines: s.includes('\n')
|
|
32
26
|
});
|
|
33
27
|
const codeFences = [...s.matchAll(FENCE_OPEN_RE)].length;
|
|
34
|
-
|
|
28
|
+
logger.debug("Code fence analysis", {
|
|
35
29
|
totalFences: codeFences,
|
|
36
30
|
fenceRegex: FENCE_OPEN_RE.source
|
|
37
31
|
});
|
|
@@ -39,7 +33,7 @@ function detectMarkdown(text) {
|
|
|
39
33
|
const m = s.match(SINGLE_FENCE_BLOCK_RE);
|
|
40
34
|
const isFramed = !!m && codeFences === 2;
|
|
41
35
|
const frameLanguage = isFramed ? (m?.[1] ?? null) : null;
|
|
42
|
-
|
|
36
|
+
logger.debug("Framed markdown detection", {
|
|
43
37
|
regexMatch: !!m,
|
|
44
38
|
expectedFences: 2,
|
|
45
39
|
actualFences: codeFences,
|
|
@@ -53,24 +47,24 @@ function detectMarkdown(text) {
|
|
|
53
47
|
});
|
|
54
48
|
if (isFramed) {
|
|
55
49
|
reasons.push("Single fenced code block detected (framed payload).");
|
|
56
|
-
|
|
50
|
+
logger.info("Detected framed markdown", { language: frameLanguage });
|
|
57
51
|
}
|
|
58
52
|
else if (codeFences > 2) {
|
|
59
53
|
reasons.push("Multiple fenced code blocks detected.");
|
|
60
|
-
|
|
54
|
+
logger.debug("Multiple fences detected, not treating as single framed block", { fenceCount: codeFences });
|
|
61
55
|
}
|
|
62
56
|
else if (codeFences === 1) {
|
|
63
57
|
reasons.push("Single fence marker found but not properly framed.");
|
|
64
|
-
|
|
58
|
+
logger.debug("Single fence found but regex didn't match", {
|
|
65
59
|
regex: SINGLE_FENCE_BLOCK_RE.source,
|
|
66
60
|
hasMatch: !!m
|
|
67
61
|
});
|
|
68
62
|
}
|
|
69
63
|
else {
|
|
70
|
-
|
|
64
|
+
logger.debug("No fence markers detected");
|
|
71
65
|
}
|
|
72
66
|
const lines = s.split("\n");
|
|
73
|
-
|
|
67
|
+
logger.verbose("Line-by-line analysis started", { totalLines: lines.length });
|
|
74
68
|
const atxHeadings = lines.filter((l) => /^#{1,6}\s+\S/.test(l.trim())).length;
|
|
75
69
|
let setextHeadings = 0;
|
|
76
70
|
for (let i = 0; i < lines.length - 1; i++) {
|
|
@@ -95,7 +89,7 @@ function detectMarkdown(text) {
|
|
|
95
89
|
(s.match(/__[^_\n]+__/g) ?? []).length +
|
|
96
90
|
(s.match(/(^|[^*])\*[^*\n]+\*([^*]|$)/g) ?? []).length +
|
|
97
91
|
(s.match(/(^|[^_])_[^_\n]+_([^_]|$)/g) ?? []).length;
|
|
98
|
-
|
|
92
|
+
logger.debug("Markdown structure analysis", {
|
|
99
93
|
atxHeadings,
|
|
100
94
|
setextHeadings,
|
|
101
95
|
totalHeadings: headings,
|
|
@@ -110,7 +104,7 @@ function detectMarkdown(text) {
|
|
|
110
104
|
const hasList = unorderedListLines + orderedListLines >= 2;
|
|
111
105
|
const hasTable = tableRows >= 2;
|
|
112
106
|
const hasOtherSignals = inlineCodeSpans + mdLinks + emphasisTokens >= 2;
|
|
113
|
-
|
|
107
|
+
logger.debug("Heuristic analysis", {
|
|
114
108
|
hasList,
|
|
115
109
|
hasTable,
|
|
116
110
|
hasOtherSignals,
|
|
@@ -121,17 +115,17 @@ function detectMarkdown(text) {
|
|
|
121
115
|
let isMarkdownLikely = false;
|
|
122
116
|
if (isFramed) {
|
|
123
117
|
isMarkdownLikely = true;
|
|
124
|
-
|
|
118
|
+
logger.debug("Markdown likelihood determined: framed content is always considered markdown");
|
|
125
119
|
}
|
|
126
120
|
else if (headings >= 2) {
|
|
127
121
|
isMarkdownLikely = true;
|
|
128
122
|
reasons.push(`Detected ${headings} markdown heading(s) (>=2).`);
|
|
129
|
-
|
|
123
|
+
logger.debug("Markdown likelihood: sufficient headings detected", { headingCount: headings });
|
|
130
124
|
}
|
|
131
125
|
else if (headings >= 1 && (hasList || hasTable)) {
|
|
132
126
|
isMarkdownLikely = true;
|
|
133
127
|
reasons.push(`Detected heading(s) plus ${hasList ? "list" : "table"} structure.`);
|
|
134
|
-
|
|
128
|
+
logger.debug("Markdown likelihood: heading plus structural element", {
|
|
135
129
|
hasHeading: headings >= 1,
|
|
136
130
|
hasList,
|
|
137
131
|
hasTable
|
|
@@ -140,7 +134,7 @@ function detectMarkdown(text) {
|
|
|
140
134
|
else if ((hasList && hasTable) || (hasTable && hasOtherSignals) || (hasList && hasOtherSignals)) {
|
|
141
135
|
isMarkdownLikely = true;
|
|
142
136
|
reasons.push("Detected multiple markdown structural signals (lists/tables/links/code/emphasis).");
|
|
143
|
-
|
|
137
|
+
logger.debug("Markdown likelihood: multiple structural signals", {
|
|
144
138
|
listAndTable: hasList && hasTable,
|
|
145
139
|
tableAndOther: hasTable && hasOtherSignals,
|
|
146
140
|
listAndOther: hasList && hasOtherSignals
|
|
@@ -148,7 +142,7 @@ function detectMarkdown(text) {
|
|
|
148
142
|
}
|
|
149
143
|
else {
|
|
150
144
|
reasons.push("Insufficient markdown structure signals; treating as plain text.");
|
|
151
|
-
|
|
145
|
+
logger.debug("Markdown likelihood: insufficient signals, treating as plain text", {
|
|
152
146
|
headings,
|
|
153
147
|
hasList,
|
|
154
148
|
hasTable,
|
|
@@ -158,7 +152,7 @@ function detectMarkdown(text) {
|
|
|
158
152
|
if (/^\s*#{1,6}\s+\S/.test(lines[0] ?? "")) {
|
|
159
153
|
reasons.push("Text starts with an ATX heading (#...).");
|
|
160
154
|
isMarkdownLikely = true;
|
|
161
|
-
|
|
155
|
+
logger.debug("Additional check: starts with heading, upgrading to markdown");
|
|
162
156
|
}
|
|
163
157
|
return {
|
|
164
158
|
isMarkdownLikely,
|
|
@@ -185,7 +179,7 @@ function detectMarkdown(text) {
|
|
|
185
179
|
*
|
|
186
180
|
* - Also handles ```md / ```markdown / ```json etc.
|
|
187
181
|
*/
|
|
188
|
-
function stripSingleFence(input) {
|
|
182
|
+
export function stripSingleFence(input) {
|
|
189
183
|
const s = input.replace(/\r\n/g, "\n").trim();
|
|
190
184
|
const fenceCount = [...s.matchAll(FENCE_OPEN_RE)].length;
|
|
191
185
|
if (fenceCount !== 2) {
|
|
@@ -205,7 +199,7 @@ function stripSingleFence(input) {
|
|
|
205
199
|
* Choose a heading that exists in your OFS to maximize alignment.
|
|
206
200
|
* Default: "Full Answer" (common sink section).
|
|
207
201
|
*/
|
|
208
|
-
function forceWrapAsMarkdown(plainText, opts) {
|
|
202
|
+
export function forceWrapAsMarkdown(plainText, opts) {
|
|
209
203
|
const heading = opts?.heading ?? "Full Answer";
|
|
210
204
|
const level = opts?.level ?? 3;
|
|
211
205
|
const hashes = "#".repeat(level);
|
|
@@ -221,15 +215,15 @@ function forceWrapAsMarkdown(plainText, opts) {
|
|
|
221
215
|
* - Else: if markdown-likely: keep as-is
|
|
222
216
|
* - Else: wrap as markdown under a chosen heading
|
|
223
217
|
*/
|
|
224
|
-
function normalizeForFlexMd(input, opts) {
|
|
225
|
-
|
|
218
|
+
export function normalizeForFlexMd(input, opts) {
|
|
219
|
+
logger.info("Starting Flex-MD normalization", {
|
|
226
220
|
inputType: typeof input,
|
|
227
221
|
inputLength: typeof input === "string" ? input.length : JSON.stringify(input ?? "").length,
|
|
228
222
|
options: opts
|
|
229
223
|
});
|
|
230
224
|
const raw = typeof input === "string" ? input : JSON.stringify(input ?? "");
|
|
231
225
|
const detection = detectMarkdown(raw);
|
|
232
|
-
|
|
226
|
+
logger.debug("Detection completed", {
|
|
233
227
|
isFramed: detection.isFramed,
|
|
234
228
|
isMarkdownLikely: detection.isMarkdownLikely,
|
|
235
229
|
frameLanguage: detection.frameLanguage,
|
|
@@ -237,14 +231,14 @@ function normalizeForFlexMd(input, opts) {
|
|
|
237
231
|
});
|
|
238
232
|
// 1) Strip if framed
|
|
239
233
|
const { stripped, wasFramed, language } = stripSingleFence(raw);
|
|
240
|
-
|
|
234
|
+
logger.debug("Strip fence check", {
|
|
241
235
|
wasFramed,
|
|
242
236
|
language,
|
|
243
237
|
strippedLength: stripped.length,
|
|
244
238
|
originalLength: raw.length
|
|
245
239
|
});
|
|
246
240
|
if (wasFramed) {
|
|
247
|
-
|
|
241
|
+
logger.info("Normalization: stripped framed markdown", {
|
|
248
242
|
language,
|
|
249
243
|
contentLength: stripped.length
|
|
250
244
|
});
|
|
@@ -258,7 +252,7 @@ function normalizeForFlexMd(input, opts) {
|
|
|
258
252
|
}
|
|
259
253
|
// 2) Keep if markdown-likely
|
|
260
254
|
if (detection.isMarkdownLikely) {
|
|
261
|
-
|
|
255
|
+
logger.info("Normalization: keeping as-is (markdown-likely)", {
|
|
262
256
|
reasons: detection.reasons
|
|
263
257
|
});
|
|
264
258
|
return {
|
|
@@ -272,7 +266,7 @@ function normalizeForFlexMd(input, opts) {
|
|
|
272
266
|
// 3) Wrap if not markdown-likely
|
|
273
267
|
const fallbackHeading = opts?.fallbackHeading ?? "Full Answer";
|
|
274
268
|
const fallbackLevel = opts?.fallbackHeadingLevel ?? 3;
|
|
275
|
-
|
|
269
|
+
logger.info("Normalization: wrapping as markdown", {
|
|
276
270
|
fallbackHeading,
|
|
277
271
|
fallbackLevel,
|
|
278
272
|
reasons: detection.reasons
|
|
@@ -281,7 +275,7 @@ function normalizeForFlexMd(input, opts) {
|
|
|
281
275
|
heading: fallbackHeading,
|
|
282
276
|
level: fallbackLevel,
|
|
283
277
|
});
|
|
284
|
-
|
|
278
|
+
logger.debug("Wrapping completed", {
|
|
285
279
|
wrappedLength: wrapped.length,
|
|
286
280
|
originalLength: raw.length
|
|
287
281
|
});
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.detectJsonContainers = detectJsonContainers;
|
|
4
|
-
exports.detectJsonPresence = detectJsonPresence;
|
|
5
1
|
const RX_JSON_FENCE = /```json\s*\n([\s\S]*?)\n```/gi;
|
|
6
2
|
const RX_JSON_MARKER = /(BEGIN_JSON|BEGIN\s+JSON)\s*\n([\s\S]*?)\n(END_JSON|END\s+JSON)/gi;
|
|
7
3
|
// Very conservative raw JSON: must be only whitespace + object/array + whitespace
|
|
8
4
|
const RX_RAW_JSON = /^\s*(\{[\s\S]*\}|\[[\s\S]*\])\s*$/;
|
|
9
5
|
// Inline candidate finder
|
|
10
6
|
const RX_INLINE_CANDIDATE = /(\{|\[)/g;
|
|
11
|
-
function detectJsonContainers(md) {
|
|
7
|
+
export function detectJsonContainers(md) {
|
|
12
8
|
const fences = [];
|
|
13
9
|
const markers = [];
|
|
14
10
|
RX_JSON_FENCE.lastIndex = 0;
|
|
@@ -37,7 +33,7 @@ function detectJsonContainers(md) {
|
|
|
37
33
|
markers,
|
|
38
34
|
};
|
|
39
35
|
}
|
|
40
|
-
function detectJsonPresence(text, opts) {
|
|
36
|
+
export function detectJsonPresence(text, opts) {
|
|
41
37
|
const spans = [];
|
|
42
38
|
const kinds = new Set();
|
|
43
39
|
// 1) fenced json blocks
|
|
@@ -1,34 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.detectJsonPresence = exports.detectJsonContainers = exports.detectJsonIntent = void 0;
|
|
18
|
-
exports.detectJsonAll = detectJsonAll;
|
|
19
|
-
const detectIntent_js_1 = require("./detectIntent.js");
|
|
20
|
-
const detectPresence_js_1 = require("./detectPresence.js");
|
|
21
|
-
__exportStar(require("./types.js"), exports);
|
|
22
|
-
var detectIntent_js_2 = require("./detectIntent.js");
|
|
23
|
-
Object.defineProperty(exports, "detectJsonIntent", { enumerable: true, get: function () { return detectIntent_js_2.detectJsonIntent; } });
|
|
24
|
-
var detectPresence_js_2 = require("./detectPresence.js");
|
|
25
|
-
Object.defineProperty(exports, "detectJsonContainers", { enumerable: true, get: function () { return detectPresence_js_2.detectJsonContainers; } });
|
|
26
|
-
Object.defineProperty(exports, "detectJsonPresence", { enumerable: true, get: function () { return detectPresence_js_2.detectJsonPresence; } });
|
|
27
|
-
__exportStar(require("./detectMarkdown.js"), exports);
|
|
28
|
-
function detectJsonAll(textOrMd, opts) {
|
|
1
|
+
import { detectJsonIntent } from "./detectIntent.js";
|
|
2
|
+
import { detectJsonContainers, detectJsonPresence } from "./detectPresence.js";
|
|
3
|
+
export * from "./types.js";
|
|
4
|
+
export { detectJsonIntent } from "./detectIntent.js";
|
|
5
|
+
export { detectJsonContainers, detectJsonPresence } from "./detectPresence.js";
|
|
6
|
+
export * from "./detectMarkdown.js";
|
|
7
|
+
export function detectJsonAll(textOrMd, opts) {
|
|
29
8
|
return {
|
|
30
|
-
intent:
|
|
31
|
-
containers:
|
|
32
|
-
presence:
|
|
9
|
+
intent: detectJsonIntent(textOrMd),
|
|
10
|
+
containers: detectJsonContainers(textOrMd),
|
|
11
|
+
presence: detectJsonPresence(textOrMd, { parse: !!opts?.parseJson }),
|
|
33
12
|
};
|
|
34
13
|
}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/dist/extract/extract.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractFromMarkdown = extractFromMarkdown;
|
|
4
|
-
const parse_js_1 = require("../md/parse.js");
|
|
1
|
+
import { parseHeadingsAndSections, extractBullets, normalizeName } from "../md/parse.js";
|
|
5
2
|
/**
|
|
6
3
|
* Extracts sections, lists, and tables from Markdown based on the OFS.
|
|
7
4
|
*/
|
|
8
|
-
function extractFromMarkdown(md, spec) {
|
|
5
|
+
export function extractFromMarkdown(md, spec) {
|
|
9
6
|
// 0. Robustness: check for fenced block that might contain the target content
|
|
10
7
|
// Highly relevant for LLM responses where the model occasionally wraps everything in a container
|
|
11
8
|
// even if not strictly asked, or if the user provided unframed content but we have L2+ expectations elsewhere.
|
|
@@ -15,28 +12,28 @@ function extractFromMarkdown(md, spec) {
|
|
|
15
12
|
if (matches.length === 1) {
|
|
16
13
|
const content = matches[0][1];
|
|
17
14
|
// If the content inside the fence has more required sections than outside, use it
|
|
18
|
-
const parsedOutside =
|
|
19
|
-
const parsedInside =
|
|
20
|
-
const specNorms = new Set(spec.sections.map(s =>
|
|
21
|
-
const countOutside = parsedOutside.filter(p => specNorms.has(
|
|
22
|
-
const countInside = parsedInside.filter(p => specNorms.has(
|
|
15
|
+
const parsedOutside = parseHeadingsAndSections(md);
|
|
16
|
+
const parsedInside = parseHeadingsAndSections(content);
|
|
17
|
+
const specNorms = new Set(spec.sections.map(s => normalizeName(s.name)));
|
|
18
|
+
const countOutside = parsedOutside.filter(p => specNorms.has(normalizeName(p.heading.name))).length;
|
|
19
|
+
const countInside = parsedInside.filter(p => specNorms.has(normalizeName(p.heading.name))).length;
|
|
23
20
|
if (countInside >= countOutside && countInside > 0) {
|
|
24
21
|
workingContent = content;
|
|
25
22
|
}
|
|
26
23
|
}
|
|
27
24
|
const bulletNames = spec.sections.map(s => s.name);
|
|
28
|
-
const parsed =
|
|
25
|
+
const parsed = parseHeadingsAndSections(workingContent, { bulletNames });
|
|
29
26
|
const sectionsByName = {};
|
|
30
27
|
const tables = [];
|
|
31
|
-
const specMap = new Map(spec.sections.map(s => [
|
|
28
|
+
const specMap = new Map(spec.sections.map(s => [normalizeName(s.name), s]));
|
|
32
29
|
for (const p of parsed) {
|
|
33
|
-
const norm =
|
|
30
|
+
const norm = normalizeName(p.heading.name);
|
|
34
31
|
const sSpec = specMap.get(norm);
|
|
35
32
|
if (sSpec) {
|
|
36
33
|
const body = p.body.trim();
|
|
37
34
|
let list;
|
|
38
35
|
if (sSpec.kind === "list" || sSpec.kind === "ordered_list") {
|
|
39
|
-
const bullets =
|
|
36
|
+
const bullets = extractBullets(body);
|
|
40
37
|
if (bullets.length > 0) {
|
|
41
38
|
list = {
|
|
42
39
|
kind: "list",
|
package/dist/extract/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,79 +1,32 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.jsonToMarkdown = exports.Schema = exports.MarkdownParser = exports.JSONTransformer = exports.enforceFlexMd = exports.repairToMarkdownLevel = exports.detectResponseKind = exports.buildIssuesEnvelopeAuto = exports.buildIssuesEnvelope = exports.parseIssuesEnvelope = exports.processResponseMarkdown = exports.extractFromMarkdown = exports.checkConnection = exports.hasFlexMdContract = exports.checkCompliance = exports.validateMarkdownAgainstOfs = exports.enrichInstructionsWithFlexMd = exports.enrichInstructions = exports.buildMarkdownGuidance = exports.stringifyOutputFormatSpec = exports.recall = exports.remember = exports.transformWithOfs = exports.ofsToSchema = exports.validateFormat = exports.parseFormatSpecs = exports.parseInputFormatSpec = exports.parseOutputFormatSpec = exports.buildOutline = exports.logger = void 0;
|
|
18
1
|
// Core SFMD Types
|
|
19
|
-
|
|
20
|
-
|
|
2
|
+
export * from "./types.js";
|
|
3
|
+
export * from "./strictness/types.js";
|
|
21
4
|
// Logging
|
|
22
|
-
|
|
23
|
-
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_js_1.logger; } });
|
|
5
|
+
export { logger } from "./logger.js";
|
|
24
6
|
// Shared MD Parsing
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
Object.defineProperty(exports, "buildOutline", { enumerable: true, get: function () { return outline_js_1.buildOutline; } });
|
|
7
|
+
export * from "./md/parse.js";
|
|
8
|
+
export { buildOutline } from "./md/outline.js";
|
|
28
9
|
// Output Format Spec (OFS)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
var adapter_js_1 = require("./ofs/adapter.js");
|
|
35
|
-
Object.defineProperty(exports, "ofsToSchema", { enumerable: true, get: function () { return adapter_js_1.ofsToSchema; } });
|
|
36
|
-
Object.defineProperty(exports, "transformWithOfs", { enumerable: true, get: function () { return adapter_js_1.transformWithOfs; } });
|
|
37
|
-
var memory_js_1 = require("./ofs/memory.js");
|
|
38
|
-
Object.defineProperty(exports, "remember", { enumerable: true, get: function () { return memory_js_1.remember; } });
|
|
39
|
-
Object.defineProperty(exports, "recall", { enumerable: true, get: function () { return memory_js_1.recall; } });
|
|
40
|
-
var stringify_js_1 = require("./ofs/stringify.js");
|
|
41
|
-
Object.defineProperty(exports, "stringifyOutputFormatSpec", { enumerable: true, get: function () { return stringify_js_1.stringifyOutputFormatSpec; } });
|
|
42
|
-
var enricher_js_1 = require("./ofs/enricher.js");
|
|
43
|
-
Object.defineProperty(exports, "buildMarkdownGuidance", { enumerable: true, get: function () { return enricher_js_1.buildMarkdownGuidance; } });
|
|
44
|
-
Object.defineProperty(exports, "enrichInstructions", { enumerable: true, get: function () { return enricher_js_1.enrichInstructions; } });
|
|
45
|
-
Object.defineProperty(exports, "enrichInstructionsWithFlexMd", { enumerable: true, get: function () { return enricher_js_1.enrichInstructionsWithFlexMd; } });
|
|
10
|
+
export { parseOutputFormatSpec, parseInputFormatSpec, parseFormatSpecs, validateFormat } from "./ofs/parser.js";
|
|
11
|
+
export { ofsToSchema, transformWithOfs } from "./ofs/adapter.js";
|
|
12
|
+
export { remember, recall } from "./ofs/memory.js";
|
|
13
|
+
export { stringifyOutputFormatSpec } from "./ofs/stringify.js";
|
|
14
|
+
export { buildMarkdownGuidance, enrichInstructions, enrichInstructionsWithFlexMd } from "./ofs/enricher.js";
|
|
46
15
|
// Validation & Extraction
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
Object.defineProperty(exports, "hasFlexMdContract", { enumerable: true, get: function () { return compliance_js_1.hasFlexMdContract; } });
|
|
52
|
-
var connection_js_1 = require("./validate/connection.js");
|
|
53
|
-
Object.defineProperty(exports, "checkConnection", { enumerable: true, get: function () { return connection_js_1.checkConnection; } });
|
|
54
|
-
var extract_js_1 = require("./extract/extract.js");
|
|
55
|
-
Object.defineProperty(exports, "extractFromMarkdown", { enumerable: true, get: function () { return extract_js_1.extractFromMarkdown; } });
|
|
16
|
+
export { validateMarkdownAgainstOfs } from "./validate/validate.js";
|
|
17
|
+
export { checkCompliance, hasFlexMdContract } from "./validate/compliance.js";
|
|
18
|
+
export { checkConnection } from "./validate/connection.js";
|
|
19
|
+
export { extractFromMarkdown } from "./extract/extract.js";
|
|
56
20
|
// Processor & Fallback
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
var issuesEnvelope_js_1 = require("./ofs/issuesEnvelope.js");
|
|
60
|
-
Object.defineProperty(exports, "parseIssuesEnvelope", { enumerable: true, get: function () { return issuesEnvelope_js_1.parseIssuesEnvelope; } });
|
|
61
|
-
Object.defineProperty(exports, "buildIssuesEnvelope", { enumerable: true, get: function () { return issuesEnvelope_js_1.buildIssuesEnvelope; } });
|
|
62
|
-
Object.defineProperty(exports, "buildIssuesEnvelopeAuto", { enumerable: true, get: function () { return issuesEnvelope_js_1.buildIssuesEnvelopeAuto; } });
|
|
21
|
+
export { processResponseMarkdown } from "./strictness/processor.js";
|
|
22
|
+
export { parseIssuesEnvelope, buildIssuesEnvelope, buildIssuesEnvelopeAuto } from "./ofs/issuesEnvelope.js";
|
|
63
23
|
// Pipeline
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Object.defineProperty(exports, "repairToMarkdownLevel", { enumerable: true, get: function () { return repair_js_1.repairToMarkdownLevel; } });
|
|
68
|
-
var enforce_js_1 = require("./pipeline/enforce.js");
|
|
69
|
-
Object.defineProperty(exports, "enforceFlexMd", { enumerable: true, get: function () { return enforce_js_1.enforceFlexMd; } });
|
|
24
|
+
export { detectResponseKind } from "./pipeline/kind.js";
|
|
25
|
+
export { repairToMarkdownLevel } from "./pipeline/repair.js";
|
|
26
|
+
export { enforceFlexMd } from "./pipeline/enforce.js";
|
|
70
27
|
// JSON Detection
|
|
71
|
-
|
|
28
|
+
export * from "./detect/json/index.js";
|
|
72
29
|
// Token Estimation
|
|
73
|
-
|
|
30
|
+
export * from "./tokens/index.js";
|
|
74
31
|
// NX-MD-Parser Integration (Structured MD -> JSON)
|
|
75
|
-
|
|
76
|
-
Object.defineProperty(exports, "JSONTransformer", { enumerable: true, get: function () { return nx_md_parser_1.JSONTransformer; } });
|
|
77
|
-
Object.defineProperty(exports, "MarkdownParser", { enumerable: true, get: function () { return nx_md_parser_1.MarkdownParser; } });
|
|
78
|
-
Object.defineProperty(exports, "Schema", { enumerable: true, get: function () { return nx_md_parser_1.Schema; } });
|
|
79
|
-
Object.defineProperty(exports, "jsonToMarkdown", { enumerable: true, get: function () { return nx_md_parser_1.jsonToMarkdown; } });
|
|
32
|
+
export { JSONTransformer, MarkdownParser, Schema, jsonToMarkdown } from "nx-md-parser";
|
package/dist/logger.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.threshold = exports.logger = void 0;
|
|
4
|
-
const micro_logs_1 = require("micro-logs");
|
|
1
|
+
import { Logger } from 'micro-logs';
|
|
5
2
|
// Get DEBUG_LEVEL from environment, default to 'info'
|
|
6
3
|
const debugLevel = process.env.DEBUG_LEVEL || 'info';
|
|
7
4
|
// Map string levels to micro-logs levels
|
|
@@ -14,9 +11,9 @@ const levelMapping = {
|
|
|
14
11
|
};
|
|
15
12
|
// Default to 'info' if invalid level provided
|
|
16
13
|
const threshold = levelMapping[debugLevel.toLowerCase()] || 'info';
|
|
17
|
-
|
|
18
|
-
exports.logger = new micro_logs_1.Logger({
|
|
14
|
+
export const logger = new Logger({
|
|
19
15
|
packageName: 'flex-md',
|
|
20
16
|
envPrefix: 'FLEX_MD',
|
|
21
17
|
debugNamespace: 'flex-md:*'
|
|
22
18
|
});
|
|
19
|
+
export { threshold };
|
package/dist/md/match.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.matchSections = matchSections;
|
|
4
1
|
/**
|
|
5
2
|
* Matches sections from the outline against required section names.
|
|
6
3
|
* Supports merging multiple nodes of the same name and selecting highest-level matches.
|
|
7
4
|
*/
|
|
8
|
-
function matchSections(outline, sectionNames, strategy = "merge") {
|
|
5
|
+
export function matchSections(outline, sectionNames, strategy = "merge") {
|
|
9
6
|
const normalizedTargets = new Map(sectionNames.map(n => [norm(n), n]));
|
|
10
7
|
const found = new Map();
|
|
11
8
|
walk(outline.nodes, (node) => {
|
package/dist/md/normalize.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.normalizeMarkdownInput = normalizeMarkdownInput;
|
|
4
1
|
/**
|
|
5
2
|
* Centralized normalization for Markdown input.
|
|
6
3
|
* Handles common LLM output artifacts like literal \n.
|
|
7
4
|
*/
|
|
8
|
-
function normalizeMarkdownInput(md) {
|
|
5
|
+
export function normalizeMarkdownInput(md) {
|
|
9
6
|
if (!md)
|
|
10
7
|
return "";
|
|
11
8
|
// Handle literal \n common in LLM outputs delivered via JSON
|
package/dist/md/outline.js
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildOutline = buildOutline;
|
|
4
|
-
exports.slugify = slugify;
|
|
5
|
-
const parse_js_1 = require("./parse.js");
|
|
1
|
+
import { parseHeadingsAndSections } from "./parse.js";
|
|
6
2
|
/**
|
|
7
3
|
* Builds a nested tree of headings (outline) from Markdown text.
|
|
8
4
|
*/
|
|
9
|
-
function buildOutline(md) {
|
|
10
|
-
const sections =
|
|
5
|
+
export function buildOutline(md) {
|
|
6
|
+
const sections = parseHeadingsAndSections(md);
|
|
11
7
|
const roots = [];
|
|
12
8
|
const stack = [];
|
|
13
9
|
for (const s of sections) {
|
|
@@ -39,7 +35,7 @@ function buildOutline(md) {
|
|
|
39
35
|
/**
|
|
40
36
|
* Slugifies a string into an internal key.
|
|
41
37
|
*/
|
|
42
|
-
function slugify(text) {
|
|
38
|
+
export function slugify(text) {
|
|
43
39
|
return text
|
|
44
40
|
.toLowerCase()
|
|
45
41
|
.trim()
|
package/dist/md/parse.js
CHANGED
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
exports.extractFencedBlocks = extractFencedBlocks;
|
|
5
|
-
exports.parseHeadingsAndSections = parseHeadingsAndSections;
|
|
6
|
-
exports.extractBullets = extractBullets;
|
|
7
|
-
exports.parseMarkdownTable = parseMarkdownTable;
|
|
8
|
-
exports.isIssuesEnvelopeCheck = isIssuesEnvelopeCheck;
|
|
9
|
-
exports.markdownToJson = markdownToJson;
|
|
10
|
-
const nx_helpers_1 = require("nx-helpers");
|
|
11
|
-
const normalize_js_1 = require("./normalize.js");
|
|
12
|
-
function normalizeName(s) {
|
|
1
|
+
import { toCamelCase } from "nx-helpers";
|
|
2
|
+
import { normalizeMarkdownInput } from "./normalize.js";
|
|
3
|
+
export function normalizeName(s) {
|
|
13
4
|
return s.trim().replace(/\s+/g, " ").toLowerCase();
|
|
14
5
|
}
|
|
15
|
-
function extractFencedBlocks(text) {
|
|
6
|
+
export function extractFencedBlocks(text) {
|
|
16
7
|
const rx = /```(\w+)?\s*\n([\s\S]*?)\n```/g;
|
|
17
8
|
const blocks = [];
|
|
18
9
|
let m;
|
|
@@ -38,7 +29,7 @@ function extractFencedBlocks(text) {
|
|
|
38
29
|
}
|
|
39
30
|
return blocks;
|
|
40
31
|
}
|
|
41
|
-
function parseHeadingsAndSections(md, options = {}) {
|
|
32
|
+
export function parseHeadingsAndSections(md, options = {}) {
|
|
42
33
|
// Standard headings #... and alternative ===key.
|
|
43
34
|
// Also optionally allow "- Section" if specified in bulletNames.
|
|
44
35
|
const rx = /^((?:#{1,6})[ \t]+(.+?)[ \t]*|===(.+?)[ \t]*|([-*+])[ \t]+(.+?)[ \t]*)$/gm;
|
|
@@ -113,7 +104,7 @@ function nextLineIndex(text, idx) {
|
|
|
113
104
|
const n = text.indexOf("\n", idx);
|
|
114
105
|
return n === -1 ? text.length : n + 1;
|
|
115
106
|
}
|
|
116
|
-
function extractBullets(body) {
|
|
107
|
+
export function extractBullets(body) {
|
|
117
108
|
const lines = body.split(/\r?\n/);
|
|
118
109
|
const out = [];
|
|
119
110
|
for (const line of lines) {
|
|
@@ -123,7 +114,7 @@ function extractBullets(body) {
|
|
|
123
114
|
}
|
|
124
115
|
return out;
|
|
125
116
|
}
|
|
126
|
-
function parseMarkdownTable(body, columns) {
|
|
117
|
+
export function parseMarkdownTable(body, columns) {
|
|
127
118
|
const lines = body.split(/\r?\n/).map(l => l.trim()).filter(l => l.startsWith("|"));
|
|
128
119
|
if (lines.length < 2)
|
|
129
120
|
return [];
|
|
@@ -146,7 +137,7 @@ function parseMarkdownTable(body, columns) {
|
|
|
146
137
|
}
|
|
147
138
|
return results;
|
|
148
139
|
}
|
|
149
|
-
function isIssuesEnvelopeCheck(md) {
|
|
140
|
+
export function isIssuesEnvelopeCheck(md) {
|
|
150
141
|
const parsed = parseHeadingsAndSections(md);
|
|
151
142
|
const want = ["status", "issues", "expected", "found", "how to fix"].map(normalizeName);
|
|
152
143
|
const got = new Set(parsed.map(s => s.heading.norm));
|
|
@@ -165,9 +156,9 @@ function isIssuesEnvelopeCheck(md) {
|
|
|
165
156
|
}
|
|
166
157
|
return { isIssuesEnvelope: ok, sections };
|
|
167
158
|
}
|
|
168
|
-
function markdownToJson(md) {
|
|
159
|
+
export function markdownToJson(md) {
|
|
169
160
|
// Robustly handle both actual newlines and literal \n (common in LLM JSON outputs)
|
|
170
|
-
const normalizedMd =
|
|
161
|
+
const normalizedMd = normalizeMarkdownInput(md);
|
|
171
162
|
// Collect all bullet names that look like headers ("- Name")
|
|
172
163
|
// We look for patterns like "- Name\n" at the start of lines, ensuring it's not a sub-bullet.
|
|
173
164
|
const bulletNames = [];
|
|
@@ -180,7 +171,7 @@ function markdownToJson(md) {
|
|
|
180
171
|
const sections = parseHeadingsAndSections(normalizedMd, { bulletNames });
|
|
181
172
|
const result = {};
|
|
182
173
|
for (const sec of sections) {
|
|
183
|
-
const key =
|
|
174
|
+
const key = toCamelCase(sec.heading.name);
|
|
184
175
|
const body = sec.body.trim();
|
|
185
176
|
// 1. Try to detect list
|
|
186
177
|
const bullets = extractBullets(body);
|