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
package/README.md
CHANGED
|
@@ -34,6 +34,11 @@ Flex-MD is a TypeScript library for building and enforcing **Markdown Output Con
|
|
|
34
34
|
npm install flex-md
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
## Runtime Compatibility
|
|
38
|
+
|
|
39
|
+
- Node LTS baseline: `>=18` (see `engines` in `package.json`).
|
|
40
|
+
- Dual-surface consumption guidance for library authors is documented in [docs/consumption.md](./docs/consumption.md).
|
|
41
|
+
|
|
37
42
|
## Quick Start
|
|
38
43
|
|
|
39
44
|
### 1. Define your Output Format Spec (OFS) with System Parts
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# athenices ai-gateway coordination
|
|
2
|
+
|
|
3
|
+
## Primary signal
|
|
4
|
+
|
|
5
|
+
The primary consumer bug report in this ecosystem was observed through `@athenices/ai-gateway` in the `extractJsonFromFlexMd` path.
|
|
6
|
+
|
|
7
|
+
## Coordination policy
|
|
8
|
+
|
|
9
|
+
1. Prefer fixing the gateway loader behavior first.
|
|
10
|
+
2. Keep `flex-md` package-level behavior documented and smoke-tested.
|
|
11
|
+
3. Only change `flex-md` runtime format outputs (for example, introducing a true ESM build) if gateway-side fixes still leave reproducible runtime failures.
|
|
12
|
+
|
|
13
|
+
## flex-md package notes
|
|
14
|
+
|
|
15
|
+
- `flex-md` currently exposes `import` and `require` export conditions.
|
|
16
|
+
- Both resolved runtime files are currently CommonJS output.
|
|
17
|
+
- Package-level smoke coverage includes:
|
|
18
|
+
- direct `require` and `import` checks from local build artifacts,
|
|
19
|
+
- package-name resolution checks via tarball install in a temp consumer.
|
|
20
|
+
|
|
21
|
+
## woroces ai-skills interaction
|
|
22
|
+
|
|
23
|
+
`@woroces/ai-skills` uses dynamic `import("flex-md")` in `parseFlexMd` when the gateway does not provide parsed payloads.
|
|
24
|
+
|
|
25
|
+
Improving gateway payload behavior reduces reliance on this fallback import path.
|
|
@@ -1,61 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const ok = await (0, index_js_1.hasFlexMdContract)("Hello", "L0");
|
|
19
|
-
(0, vitest_1.expect)(ok).toBe(false);
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { checkCompliance, hasFlexMdContract, enrichInstructionsWithFlexMd, validateFormat } from "../index.js";
|
|
3
|
+
describe("Diagnostics", () => {
|
|
4
|
+
describe("checkCompliance", () => {
|
|
5
|
+
it("should return meetsCompliance: true for L0 if Markdown is mentioned", async () => {
|
|
6
|
+
const res = await checkCompliance("Reply in Markdown.", "L0");
|
|
7
|
+
expect(res.meetsCompliance).toBe(true);
|
|
8
|
+
expect(res.issues).toHaveLength(0);
|
|
9
|
+
});
|
|
10
|
+
it("should return issues for L2 if container is missing", async () => {
|
|
11
|
+
const res = await checkCompliance("Reply in Markdown. Include headings.", "L2");
|
|
12
|
+
expect(res.meetsCompliance).toBe(false);
|
|
13
|
+
expect(res.issues.some(i => i.type === "missing-container")).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
it("should return false for hasFlexMdContract if requirements not met", async () => {
|
|
16
|
+
const ok = await hasFlexMdContract("Hello", "L0");
|
|
17
|
+
expect(ok).toBe(false);
|
|
20
18
|
});
|
|
21
19
|
});
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const res = await
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const res = await
|
|
32
|
-
|
|
33
|
-
|
|
20
|
+
describe("enrichInstructionsWithFlexMd", () => {
|
|
21
|
+
it("should append guidance to existing instructions", async () => {
|
|
22
|
+
const res = await enrichInstructionsWithFlexMd("Do a good job.", "L0");
|
|
23
|
+
expect(res.enriched).toContain("Do a good job.");
|
|
24
|
+
expect(res.enriched).toContain("Reply in Markdown.");
|
|
25
|
+
expect(res.changes).toHaveLength(1);
|
|
26
|
+
expect(res.metadata?.guidanceAdded).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
it("should track container addition for L2", async () => {
|
|
29
|
+
const res = await enrichInstructionsWithFlexMd("Do a good job.", "L2");
|
|
30
|
+
expect(res.changes.some(c => c.type === "added-container")).toBe(true);
|
|
31
|
+
expect(res.metadata?.containerAdded).toBe(true);
|
|
34
32
|
});
|
|
35
33
|
});
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
describe("validateFormat", () => {
|
|
35
|
+
it("should validate a correct flex-md OFS", async () => {
|
|
38
36
|
const ofs = `## Output format\n- Summary — prose\n- Actions — list`;
|
|
39
|
-
const res = await
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
const res = await validateFormat(ofs);
|
|
38
|
+
expect(res.valid).toBe(true);
|
|
39
|
+
expect(res.metadata?.sectionCount).toBe(2);
|
|
42
40
|
});
|
|
43
|
-
|
|
41
|
+
it("should return errors for missing heading", async () => {
|
|
44
42
|
const ofs = `- Summary — prose`;
|
|
45
|
-
const res = await
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
const res = await validateFormat(ofs);
|
|
44
|
+
expect(res.valid).toBe(false);
|
|
45
|
+
expect(res.issues.some(i => i.type === "missing-heading")).toBe(true);
|
|
48
46
|
});
|
|
49
|
-
|
|
47
|
+
it("should validate JSON schema", async () => {
|
|
50
48
|
const schema = `{"type": "object"}`;
|
|
51
|
-
const res = await
|
|
52
|
-
|
|
49
|
+
const res = await validateFormat(schema, "json-schema");
|
|
50
|
+
expect(res.valid).toBe(true);
|
|
53
51
|
});
|
|
54
|
-
|
|
52
|
+
it("should fail on invalid JSON schema", async () => {
|
|
55
53
|
const schema = `{"type": "object"`;
|
|
56
|
-
const res = await
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
const res = await validateFormat(schema, "json-schema");
|
|
55
|
+
expect(res.valid).toBe(false);
|
|
56
|
+
expect(res.issues[0].type).toBe("syntax-error");
|
|
59
57
|
});
|
|
60
58
|
});
|
|
61
59
|
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const enricher_js_1 = require("../ofs/enricher.js");
|
|
6
|
-
(0, vitest_1.describe)("Instructions Output Format Block Generation", () => {
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { stringifyOutputFormatSpec } from "../ofs/stringify.js";
|
|
3
|
+
import { buildMarkdownGuidance } from "../ofs/enricher.js";
|
|
4
|
+
describe("Instructions Output Format Block Generation", () => {
|
|
7
5
|
const spec = {
|
|
8
6
|
description: "Standard report format for technical analysis.",
|
|
9
7
|
sections: [
|
|
@@ -23,31 +21,31 @@ const enricher_js_1 = require("../ofs/enricher.js");
|
|
|
23
21
|
],
|
|
24
22
|
emptySectionValue: "N/A"
|
|
25
23
|
};
|
|
26
|
-
|
|
27
|
-
const md =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
it("should stringify an OFS object correctly", () => {
|
|
25
|
+
const md = stringifyOutputFormatSpec(spec);
|
|
26
|
+
expect(md).toContain("## Output format (Markdown)");
|
|
27
|
+
expect(md).toContain("Standard report format for technical analysis.");
|
|
28
|
+
expect(md).toContain("- Summary — text (required)");
|
|
29
|
+
expect(md).toContain("Description: A brief summary of the topic.");
|
|
30
|
+
expect(md).toContain("Instruction: Keep it under 3 sentences.");
|
|
31
|
+
expect(md).toContain("- Key Points — list (optional)");
|
|
32
|
+
expect(md).toContain("Description: Important takeaways.");
|
|
33
|
+
expect(md).toContain("If a section is empty, write `N/A`.");
|
|
36
34
|
});
|
|
37
|
-
|
|
38
|
-
const guidance =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
it("should build markdown guidance (L1) correctly", () => {
|
|
36
|
+
const guidance = buildMarkdownGuidance(spec, { level: 1 });
|
|
37
|
+
expect(guidance).toContain("Include these section headings somewhere");
|
|
38
|
+
expect(guidance).toContain("- Summary");
|
|
39
|
+
expect(guidance).toContain("Description: A brief summary of the topic.");
|
|
40
|
+
expect(guidance).toContain("Instruction: Keep it under 3 sentences.");
|
|
41
|
+
expect(guidance).toContain("- Key Points");
|
|
42
|
+
expect(guidance).toContain("Description: Important takeaways.");
|
|
45
43
|
});
|
|
46
|
-
|
|
47
|
-
const guidance =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
it("should build markdown guidance (L3) correctly", () => {
|
|
45
|
+
const guidance = buildMarkdownGuidance(spec, { level: 3 });
|
|
46
|
+
expect(guidance).toContain("Return your entire answer inside a single ```markdown fenced block");
|
|
47
|
+
expect(guidance).toContain("- Summary");
|
|
48
|
+
expect(guidance).toContain("- Key Points (list)");
|
|
49
|
+
expect(guidance).toContain("Do not return JSON");
|
|
52
50
|
});
|
|
53
51
|
});
|
|
@@ -1,30 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
(
|
|
6
|
-
(0, vitest_1.describe)("===key support", () => {
|
|
7
|
-
(0, vitest_1.it)("should parse ===key as a top-level section", () => {
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { buildOutline, checkConnection } from "../index.js";
|
|
3
|
+
describe("Structural Diagnostics", () => {
|
|
4
|
+
describe("===key support", () => {
|
|
5
|
+
it("should parse ===key as a top-level section", () => {
|
|
8
6
|
const md = `===skills\nThis is the skills section.\n\n## Subskill\nDetails.`;
|
|
9
|
-
const outline =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
const outline = buildOutline(md);
|
|
8
|
+
expect(outline.nodes).toHaveLength(1);
|
|
9
|
+
expect(outline.nodes[0].title).toBe("skills");
|
|
10
|
+
expect(outline.nodes[0].children).toHaveLength(1);
|
|
11
|
+
expect(outline.nodes[0].children[0].title).toBe("Subskill");
|
|
14
12
|
});
|
|
15
13
|
});
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
describe("checkConnection", () => {
|
|
15
|
+
it("should find a section by name", () => {
|
|
18
16
|
const md = `# Overview\n## Details\n===skills\nContent.`;
|
|
19
|
-
const res =
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
const res = checkConnection(md, "skills");
|
|
18
|
+
expect(res.connected).toBe(true);
|
|
19
|
+
expect(res.path).toContain("skills");
|
|
22
20
|
});
|
|
23
|
-
|
|
21
|
+
it("should fail gracefully for missing sections", () => {
|
|
24
22
|
const md = `# Overview`;
|
|
25
|
-
const res =
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
const res = checkConnection(md, "missing");
|
|
24
|
+
expect(res.connected).toBe(false);
|
|
25
|
+
expect(res.suggestion).toContain("Overview");
|
|
28
26
|
});
|
|
29
27
|
});
|
|
30
28
|
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const validate_js_1 = require("../validate/validate.js");
|
|
5
|
-
const issuesEnvelope_js_1 = require("../ofs/issuesEnvelope.js");
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { validateMarkdownAgainstOfs } from "../validate/validate.js";
|
|
3
|
+
import { parseIssuesEnvelope } from "../ofs/issuesEnvelope.js";
|
|
6
4
|
const SPEC = {
|
|
7
5
|
emptySectionValue: "None",
|
|
8
6
|
sections: [
|
|
@@ -32,8 +30,8 @@ function mdL1Good() {
|
|
|
32
30
|
"- U",
|
|
33
31
|
].join("\n");
|
|
34
32
|
}
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
describe("parseIssuesEnvelope()", () => {
|
|
34
|
+
it("detects envelope and extracts bullets", () => {
|
|
37
35
|
const env = [
|
|
38
36
|
"## Status",
|
|
39
37
|
"Non-compliant output (cannot be repaired to the required format).",
|
|
@@ -50,17 +48,17 @@ function mdL1Good() {
|
|
|
50
48
|
"## How to fix",
|
|
51
49
|
"- Do X",
|
|
52
50
|
].join("\n");
|
|
53
|
-
const parsed =
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
const parsed = parseIssuesEnvelope(env);
|
|
52
|
+
expect(parsed.isIssuesEnvelope).toBe(true);
|
|
53
|
+
expect(parsed.sections["issues"].bullets[0]).toContain("Missing required section");
|
|
56
54
|
});
|
|
57
55
|
});
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const r =
|
|
61
|
-
|
|
56
|
+
describe("validateMarkdownAgainstOfs()", () => {
|
|
57
|
+
it("L0 accepts anything", () => {
|
|
58
|
+
const r = validateMarkdownAgainstOfs("whatever", SPEC, 0);
|
|
59
|
+
expect(r.ok).toBe(true);
|
|
62
60
|
});
|
|
63
|
-
|
|
61
|
+
it("L1 fails when required section missing", () => {
|
|
64
62
|
const md = [
|
|
65
63
|
"## Short answer",
|
|
66
64
|
"Yes.",
|
|
@@ -68,21 +66,21 @@ function mdL1Good() {
|
|
|
68
66
|
"## Reasoning",
|
|
69
67
|
"1. A",
|
|
70
68
|
].join("\n");
|
|
71
|
-
const r =
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
const r = validateMarkdownAgainstOfs(md, SPEC, 1);
|
|
70
|
+
expect(r.ok).toBe(false);
|
|
71
|
+
expect(r.issues.some(i => i.code === "MISSING_SECTION")).toBe(true);
|
|
74
72
|
});
|
|
75
|
-
|
|
76
|
-
const r =
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
it("L2 requires a single fenced markdown block", () => {
|
|
74
|
+
const r = validateMarkdownAgainstOfs(mdL1Good(), SPEC, 2);
|
|
75
|
+
expect(r.ok).toBe(false);
|
|
76
|
+
expect(r.issues.some(i => i.code === "CONTAINER_MISSING")).toBe(true);
|
|
79
77
|
});
|
|
80
|
-
|
|
78
|
+
it("L2 passes with one fence containing valid L1", () => {
|
|
81
79
|
const md = ["```markdown", mdL1Good(), "```"].join("\n");
|
|
82
|
-
const r =
|
|
83
|
-
|
|
80
|
+
const r = validateMarkdownAgainstOfs(md, SPEC, 2);
|
|
81
|
+
expect(r.ok).toBe(true);
|
|
84
82
|
});
|
|
85
|
-
|
|
83
|
+
it("L3 enforces section kinds (Reasoning must be ordered list)", () => {
|
|
86
84
|
const bad = [
|
|
87
85
|
"```markdown",
|
|
88
86
|
[
|
|
@@ -103,8 +101,8 @@ function mdL1Good() {
|
|
|
103
101
|
].join("\n"),
|
|
104
102
|
"```",
|
|
105
103
|
].join("\n");
|
|
106
|
-
const r =
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
const r = validateMarkdownAgainstOfs(bad, SPEC, 3);
|
|
105
|
+
expect(r.ok).toBe(false);
|
|
106
|
+
expect(r.issues.some(i => i.code === "WRONG_SECTION_KIND")).toBe(true);
|
|
109
107
|
});
|
|
110
108
|
});
|
package/dist/cli/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const path_1 = require("path");
|
|
6
|
-
const index_js_1 = require("../index.js");
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
import { checkCompliance, checkConnection } from "../index.js";
|
|
7
5
|
const [, , command, ...args] = process.argv;
|
|
8
6
|
async function main() {
|
|
9
7
|
if (!command || command === "--help" || command === "-h") {
|
|
@@ -57,8 +55,8 @@ async function handleCheck(args) {
|
|
|
57
55
|
if (!file)
|
|
58
56
|
throw new Error("Missing file argument.");
|
|
59
57
|
const level = (args.includes("--level") ? args[args.indexOf("--level") + 1] : "L2");
|
|
60
|
-
const content =
|
|
61
|
-
const result = await
|
|
58
|
+
const content = readFileSync(resolve(file), "utf-8");
|
|
59
|
+
const result = await checkCompliance(content, level);
|
|
62
60
|
if (result.meetsCompliance) {
|
|
63
61
|
console.log("✅ Content meets compliance.");
|
|
64
62
|
}
|
|
@@ -74,10 +72,10 @@ async function handleDiagnose(args) {
|
|
|
74
72
|
const key = args[1];
|
|
75
73
|
if (!file || !key)
|
|
76
74
|
throw new Error("Usage: flex-md diagnose <file> <key>");
|
|
77
|
-
if (!
|
|
75
|
+
if (!existsSync(file))
|
|
78
76
|
throw new Error(`File not found: ${file}`);
|
|
79
|
-
const content =
|
|
80
|
-
const result =
|
|
77
|
+
const content = readFileSync(resolve(file), "utf-8");
|
|
78
|
+
const result = checkConnection(content, key);
|
|
81
79
|
if (result.connected) {
|
|
82
80
|
console.log(`✅ Key "${key}" found at path: ${result.path?.join(" -> ")}`);
|
|
83
81
|
}
|
|
@@ -91,9 +89,9 @@ async function handleCreate(args) {
|
|
|
91
89
|
const key = args[1];
|
|
92
90
|
if (!file || !key)
|
|
93
91
|
throw new Error("Usage: flex-md create <file> <key>");
|
|
94
|
-
const content =
|
|
92
|
+
const content = existsSync(file) ? readFileSync(file, "utf-8") : "";
|
|
95
93
|
const newContent = content + `\n\n## ${key}\n\n[Content for ${key}]\n`;
|
|
96
|
-
|
|
94
|
+
writeFileSync(file, newContent);
|
|
97
95
|
console.log(`✅ Section "${key}" created in ${file}`);
|
|
98
96
|
}
|
|
99
97
|
async function handleSync(args) {
|
|
@@ -101,10 +99,10 @@ async function handleSync(args) {
|
|
|
101
99
|
const target = args[1];
|
|
102
100
|
if (!source || !target)
|
|
103
101
|
throw new Error("Usage: flex-md sync <source> <target>");
|
|
104
|
-
if (!
|
|
102
|
+
if (!existsSync(source))
|
|
105
103
|
throw new Error(`Source file not found: ${source}`);
|
|
106
|
-
const content =
|
|
107
|
-
|
|
104
|
+
const content = readFileSync(source, "utf-8");
|
|
105
|
+
writeFileSync(target, content);
|
|
108
106
|
console.log(`✅ Content synced from ${source} to ${target}`);
|
|
109
107
|
}
|
|
110
108
|
main();
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.detectJsonIntent = detectJsonIntent;
|
|
4
1
|
const HARD_PATTERNS = [
|
|
5
2
|
/\breturn\s+only\s+json\b/i,
|
|
6
3
|
/\boutput\s+only\s+json\b/i,
|
|
@@ -28,7 +25,7 @@ const TOOLING_PATTERNS = [
|
|
|
28
25
|
/\btool\s+call\b/i,
|
|
29
26
|
/\barguments\b.*\bjson\b/i,
|
|
30
27
|
];
|
|
31
|
-
function detectJsonIntent(text) {
|
|
28
|
+
export function detectJsonIntent(text) {
|
|
32
29
|
const signals = [];
|
|
33
30
|
const add = (rx, strength, idx, len) => {
|
|
34
31
|
signals.push({
|