micro-models-agent 0.18.3 → 0.19.1

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.
@@ -1,170 +0,0 @@
1
- import { t } from "../../i18n/index";
2
- import { existsSync } from "fs";
3
- import { join } from "path";
4
- const FILE_EXTENSIONS = new Set([
5
- "ts",
6
- "tsx",
7
- "js",
8
- "jsx",
9
- "mjs",
10
- "cjs",
11
- "mts",
12
- "cts",
13
- "json",
14
- "md",
15
- "yaml",
16
- "yml",
17
- "py",
18
- "rs",
19
- "go",
20
- "java",
21
- "c",
22
- "cpp",
23
- "h",
24
- "hpp",
25
- "html",
26
- "css",
27
- "scss",
28
- "less",
29
- "vue",
30
- "svelte",
31
- "sh",
32
- "bash",
33
- "zsh",
34
- "ps1",
35
- "bat",
36
- "cmd",
37
- "txt",
38
- "env",
39
- "env.local",
40
- "env.production",
41
- "gitignore",
42
- "dockerignore",
43
- "dockerfile",
44
- "makefile",
45
- "cmake",
46
- "toml",
47
- "lock",
48
- "config",
49
- "log",
50
- "xml",
51
- "sql",
52
- "graphql",
53
- "proto",
54
- "wasm",
55
- ]);
56
- const VERSION_PATTERN = /^\d+(\.\d+)*$/;
57
- const COMMON_WORDS = new Set([
58
- "node.js", "Node.js",
59
- "console.log", "console.error", "console.warn", "console.info",
60
- "Math.floor", "Math.ceil", "Math.round", "Math.max", "Math.min",
61
- "JSON.parse", "JSON.stringify",
62
- "Object.keys", "Object.values", "Object.entries",
63
- "Array.from", "Array.isArray",
64
- "Date.now", "Date.parse",
65
- "RegExp", "Promise",
66
- ]);
67
- export class FactualCheck {
68
- knownPaths = new Set();
69
- createdPaths = new Set();
70
- readFiles = new Set();
71
- baseDir = process.cwd();
72
- setBaseDir(dir) {
73
- this.baseDir = dir;
74
- }
75
- trackReadPath(path) {
76
- this.knownPaths.add(path);
77
- const base = path.split(/[/\\]/).pop();
78
- if (base && base !== path)
79
- this.knownPaths.add(base);
80
- // Track that this file was actually read by the agent
81
- this.readFiles.add(base || path);
82
- }
83
- trackCreatedPath(path) {
84
- this.knownPaths.add(path);
85
- const base = path.split(/[/\\]/).pop();
86
- if (base && base !== path)
87
- this.knownPaths.add(base);
88
- this.createdPaths.add(path);
89
- }
90
- trackDeletedPath(path) {
91
- this.knownPaths.add(path);
92
- const base = path.split(/[/\\]/).pop();
93
- if (base && base !== path)
94
- this.knownPaths.add(base);
95
- this.createdPaths.delete(path);
96
- }
97
- /**
98
- * Register file paths found in a document (e.g. structure.md, README).
99
- * Files mentioned in project documentation are not hallucinations.
100
- */
101
- trackDocumentContent(content) {
102
- // Match common path patterns in documentation
103
- const pathPatterns = /(?:^|\s)([\w\-./]+\.\w{1,10})(?:\s|$|[,;)])/gm;
104
- let match;
105
- while ((match = pathPatterns.exec(content)) !== null) {
106
- const file = match[1];
107
- if (file.includes('/') || file.includes('\\')) {
108
- this.knownPaths.add(file);
109
- }
110
- const base = file.split(/[/\\]/).pop();
111
- if (base)
112
- this.knownPaths.add(base);
113
- }
114
- }
115
- pathExistsOnDisk(path) {
116
- try {
117
- // Skip absolute paths — they're either system paths or outside the project.
118
- // On Windows, existsSync('/...') can hang on certain paths.
119
- if (path.startsWith("/") || path.startsWith("~") || /^[A-Za-z]:/.test(path)) {
120
- return false;
121
- }
122
- return existsSync(join(this.baseDir, path));
123
- }
124
- catch {
125
- return false;
126
- }
127
- }
128
- validate(response) {
129
- const pathRegex = /[\w\-./]+\.\w+/g;
130
- const mentionedPaths = response.match(pathRegex) || [];
131
- const unknownPaths = mentionedPaths.filter((p) => {
132
- if (this.knownPaths.has(p))
133
- return false;
134
- if (VERSION_PATTERN.test(p))
135
- return false;
136
- if (COMMON_WORDS.has(p))
137
- return false;
138
- // Skip absolute paths — agent responses use relative paths; absolute
139
- // paths are either system paths or URLs, and existsSync can hang on
140
- // Windows for root-relative paths like "/page.html".
141
- if (p.startsWith("/") || p.startsWith("~") || /^[A-Za-z]:/.test(p))
142
- return false;
143
- if (this.pathExistsOnDisk(p))
144
- return false;
145
- const ext = p.split(".").pop()?.toLowerCase() || "";
146
- if (!FILE_EXTENSIONS.has(ext))
147
- return false;
148
- const basename = p
149
- .split("/")
150
- .pop()
151
- ?.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
152
- if (basename) {
153
- const urlPattern = new RegExp(`(https?|file)://[^\\s]*${basename}`);
154
- if (urlPattern.test(response))
155
- return false;
156
- }
157
- return true;
158
- });
159
- if (unknownPaths.length > 0) {
160
- const uniquePaths = [...new Set(unknownPaths)];
161
- return {
162
- status: "warn",
163
- reason: t("hall.unknown_paths", {
164
- paths: uniquePaths.slice(0, 3).join(", "),
165
- }),
166
- };
167
- }
168
- return { status: "pass" };
169
- }
170
- }