@futdevpro/fdp-agent-memory 0.1.0 → 1.1.12
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/LICENSE +21 -0
- package/README.md +7 -7
- package/build/package.json +6 -5
- package/build/src/_cli/_collections/fam-arg.util.js +48 -0
- package/build/src/_cli/_collections/fam-cli.const.js +40 -0
- package/build/src/_cli/_collections/fam-output.util.js +86 -0
- package/build/src/_cli/_collections/fam-project-discovery.util.js +98 -0
- package/build/src/_cli/_commands/capture.command.js +73 -0
- package/build/src/_cli/_commands/config.command.js +93 -0
- package/build/src/_cli/_commands/doctor.command.js +124 -0
- package/build/src/_cli/_commands/errors.command.js +66 -0
- package/build/src/_cli/_commands/export.command.js +65 -0
- package/build/src/_cli/_commands/find-duplicates.command.js +97 -0
- package/build/src/_cli/_commands/import.command.js +136 -0
- package/build/src/_cli/_commands/init.command.js +147 -0
- package/build/src/_cli/_commands/read.command.js +109 -0
- package/build/src/_cli/_commands/scan-projects.command.js +138 -0
- package/build/src/_cli/_commands/scan.command.js +98 -0
- package/build/src/_cli/_commands/seed.command.js +40 -0
- package/build/src/_cli/_commands/serve.command.js +350 -0
- package/build/src/_cli/_commands/start.command.js +134 -0
- package/build/src/_cli/_commands/stats.command.js +54 -0
- package/build/src/_cli/_commands/write.command.js +103 -0
- package/build/src/_cli/_models/interfaces/fam-cli-global-options.interface.js +2 -0
- package/build/src/_cli/_models/interfaces/fam-cli-output.interface.js +9 -0
- package/build/src/_cli/_models/interfaces/fam-client-result.interface.js +2 -0
- package/build/src/_cli/_services/fam-client.service.js +140 -0
- package/build/src/_cli/register-commands.js +86 -0
- package/build/src/_collections/config-catalog.const.js +67 -1
- package/build/src/_collections/fam-console.util.js +367 -0
- package/build/src/_collections/fam-entry-bootstrap.util.js +158 -4
- package/build/src/_collections/fam-error-factory.util.js +0 -9
- package/build/src/_collections/fam-mcp-bridge.util.js +49 -0
- package/build/src/_collections/fam-reference-code.util.js +105 -0
- package/build/src/_collections/fam-version.const.js +10 -0
- package/build/src/_models/data-models/fam-entry-base-properties.const.js +1 -0
- package/build/src/_models/data-models/fam-entry.data-model.js +6 -0
- package/build/src/_models/data-models/fam-ingest-run.data-model.js +3 -1
- package/build/src/_models/data-models/fam-reference.data-model.js +7 -0
- package/build/src/_modules/capture/_collections/fam-capture.const.js +11 -0
- package/build/src/_modules/capture/_services/fam-auto-capture.control-service.js +87 -0
- package/build/src/_modules/capture/index.js +8 -0
- package/build/src/_modules/embedding/_collections/fam-embedding-prefix.util.js +77 -0
- package/build/src/_modules/embedding/_services/fam-duplicate-scan.control-service.js +202 -0
- package/build/src/_modules/embedding/_services/fam-embedding-pipeline.control-service.js +33 -9
- package/build/src/_modules/embedding/_services/fam-embedding.control-service.js +21 -2
- package/build/src/_modules/embedding/_services/fam-entry.data-service.js +135 -0
- package/build/src/_modules/embedding/_services/fam-vector-search.control-service.js +42 -32
- package/build/src/_modules/embedding/index.js +4 -1
- package/build/src/_modules/export/_collections/fam-export.const.js +22 -0
- package/build/src/_modules/export/_services/fam-export.control-service.js +64 -0
- package/build/src/_modules/export/index.js +8 -0
- package/build/src/_modules/ingest/_collections/fam-famignore.util.js +83 -0
- package/build/src/_modules/ingest/_collections/fam-file-routing.util.js +59 -48
- package/build/src/_modules/ingest/_collections/fam-project-identity.util.js +134 -0
- package/build/src/_modules/ingest/_collections/fam-scan-progress.util.js +57 -0
- package/build/src/_modules/ingest/_collections/fam-scan-summary.util.js +60 -0
- package/build/src/_modules/ingest/_collections/fam-scan-weight.util.js +53 -0
- package/build/src/_modules/ingest/_collections/fam-secret-exclude.util.js +37 -14
- package/build/src/_modules/ingest/_collections/fam-sliding-chunker.util.js +34 -0
- package/build/src/_modules/ingest/_collections/fam-ts-chunker.util.js +200 -14
- package/build/src/_modules/ingest/_services/fam-delta-compare.util.js +4 -1
- package/build/src/_modules/ingest/_services/fam-ingest-run.data-service.js +7 -4
- package/build/src/_modules/ingest/_services/fam-ingest.control-service.js +346 -17
- package/build/src/_modules/ingest/_services/fam-scan.control-service.js +25 -2
- package/build/src/_modules/ingest/index.js +3 -1
- package/build/src/_modules/mcp/_collections/fam-active-rules.util.js +56 -0
- package/build/src/_modules/mcp/_collections/fam-core-tools.const.js +47 -6
- package/build/src/_modules/mcp/_services/fam-capabilities-tool.service.js +4 -4
- package/build/src/_modules/mcp/_services/fam-capability-registry.service.js +224 -18
- package/build/src/_modules/mcp/_services/fam-mcp-adapter.service.js +4 -4
- package/build/src/_modules/mcp/_services/fam-mcp-server.service.js +4 -4
- package/build/src/_modules/mcp/_services/fam-read-tool.service.js +53 -1
- package/build/src/_modules/mcp/_services/fam-write-tool.service.js +104 -8
- package/build/src/_modules/mcp/index.js +4 -4
- package/build/src/_modules/migration/_collections/fam-claude-mem-normalize.util.js +66 -3
- package/build/src/_modules/migration/_collections/fam-prompt-aggregate.util.js +143 -0
- package/build/src/_modules/migration/_collections/fam-target-mapping.util.js +19 -0
- package/build/src/_modules/migration/_enums/fam-claude-mem-source.type-enum.js +6 -0
- package/build/src/_modules/migration/_models/interfaces/fam-claude-mem.interface.js +5 -0
- package/build/src/_modules/migration/_services/fam-agent-memory-reader.service.js +125 -0
- package/build/src/_modules/migration/_services/fam-claude-mem-import.control-service.js +101 -18
- package/build/src/_modules/migration/_services/fam-import-dedup.data-service.js +53 -0
- package/build/src/_modules/migration/index.js +3 -1
- package/build/src/_modules/retrieval/_services/fam-retrieval-candidate.data-service.js +78 -4
- package/build/src/_modules/retrieval/_services/fam-retrieval.control-service.js +293 -50
- package/build/src/_modules/scope-reference/_collections/fam-scope-normalize.util.js +6 -3
- package/build/src/_modules/scope-reference/_services/fam-reference.data-service.js +18 -0
- package/build/src/_modules/scope-reference/_services/fam-scope-resolver.control-service.js +79 -20
- package/build/src/_routes/server/api/api.controller.js +34 -2
- package/build/src/_routes/server/client-app/client-app.control-service.js +1 -1
- package/build/src/_routes/server/server-status/server-status.controller.js +2 -1
- package/build/src/app.server.js +13 -1
- package/build/src/environments/environment.js +1 -1
- package/build/src/index.js +1 -1
- package/client-dist/{chunk-GHKRM4SM.js → chunk-I77GXVAQ.js} +1 -1
- package/client-dist/{chunk-LMTL7GA3.js → chunk-YXHWCJ5O.js} +1 -1
- package/client-dist/index.html +1 -1
- package/client-dist/{main-2KWB3QYK.js → main-PJPEDVJT.js} +1 -1
- package/package.json +6 -5
|
@@ -9,77 +9,88 @@ const fam_table_type_enum_1 = require("../../../_enums/fam-table.type-enum");
|
|
|
9
9
|
* felderített fájlt a kiterjesztése / fájlnév-mintája alapján `documents` / `codebase` / `skip`
|
|
10
10
|
* cél-tárra route-ol. Statikus util (nincs DB-/service-függés).
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
* -
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - `
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* dokumentációt célozza (`.md`/`.mdx`/`.txt`/`.rst`), nem a markup-ot (dsgn-004 §2). A
|
|
21
|
-
* `chunkStrategyFor` a route + kiterjesztés alapján adja a chunker-stratégiát (SP-4.2 dispatch).
|
|
12
|
+
* **FAM-REV-064 — „semmi ne vesszen el" inverzió:** a korábbi szűk ALLOWLIST (csak ismert kiterjesztés
|
|
13
|
+
* → tár, MINDEN MÁS → skip) szöveges, info-hordozó fájlokat ejtett el (pl. `.mdc` Cursor-rules, `.sh`,
|
|
14
|
+
* `.ps1`, `.xml`, git-hookok, `LICENSE`). Az új logika DENYLIST-alapú: a **dokumentum-kiterjesztések** a
|
|
15
|
+
* `documents` táron; a **known-binary** (kép/font/archív/média/bináris/office) + a **generált zaj** (lock-
|
|
16
|
+
* fájlok, `.min.*`, source-map) `skip`; **MINDEN MÁS szöveges fájl** (ismert VAGY ismeretlen kiterjesztés,
|
|
17
|
+
* extension-nélküli `LICENSE`/`Dockerfile`/git-hook) → `codebase`. A bináris-tartalmú álcázott fájlokat a
|
|
18
|
+
* scanner null-byte tartalom-ellenőrzése szűri (`binary-content` skip), így nem kerül szemét a generic
|
|
19
|
+
* chunkerbe. Így minden valódi szöveg bekerül; a tényleges bináris + a generált zaj kimarad.
|
|
22
20
|
*/
|
|
23
21
|
class FAM_FileRouting_Util {
|
|
24
|
-
/** Dokumentum-kiterjesztések → `documents` (
|
|
25
|
-
static DOCUMENT_EXTENSIONS = ['.md', '.mdx', '.txt', '.rst'];
|
|
26
|
-
/**
|
|
27
|
-
static
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
static
|
|
22
|
+
/** Dokumentum-kiterjesztések → `documents` (a `.mdc` Cursor-rules + `.markdown` IDE, FAM-REV-064). */
|
|
23
|
+
static DOCUMENT_EXTENSIONS = ['.md', '.mdx', '.markdown', '.mdc', '.txt', '.text', '.rst', '.adoc'];
|
|
24
|
+
/** Markdown-kiterjesztések (a header-aware chunker célja; a `.mdc`/`.markdown` is, FAM-REV-064). */
|
|
25
|
+
static MARKDOWN_EXTENSIONS = ['.md', '.mdx', '.markdown', '.mdc'];
|
|
26
|
+
/** TS-szemantikus chunker kiterjesztései (dsgn-004 §3.1; `.cjs`/`.cts`/`.mjs` is JS/TS-variáns). */
|
|
27
|
+
static TS_EXTENSIONS = ['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.cjs', '.mjs'];
|
|
28
|
+
/**
|
|
29
|
+
* Known-binary kiterjesztések → `skip` (FAM-REV-064 denylist). Kép/font/archív/média/futtatható/
|
|
30
|
+
* lefordított/office/adatbázis + source-map (`.map`). Az office/PDF szöveg-kinyerés BACKLOG (dsgn BACKLOG),
|
|
31
|
+
* ezért egyelőre skip (nem néma — `filesSkipped` + `skipReason`). NEM tartalmazza a `.svg`-t? — DE: a
|
|
32
|
+
* `.svg` döntően generált path-grafika (alacsony szemantikai szöveg), ezért IDE soroljuk.
|
|
33
|
+
*/
|
|
34
|
+
static BINARY_EXTENSIONS = new Set([
|
|
35
|
+
// képek
|
|
36
|
+
'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.ico', '.webp', '.tiff', '.tif', '.svg', '.psd', '.ai',
|
|
37
|
+
// fontok
|
|
38
|
+
'.woff', '.woff2', '.ttf', '.eot', '.otf',
|
|
39
|
+
// archívok
|
|
40
|
+
'.zip', '.tgz', '.gz', '.tar', '.rar', '.7z', '.bz2', '.xz', '.jar', '.war', '.nupkg',
|
|
41
|
+
// média
|
|
42
|
+
'.mp3', '.mp4', '.wav', '.avi', '.mov', '.mkv', '.flac', '.ogg', '.webm', '.m4a', '.aac',
|
|
43
|
+
// futtatható / lefordított
|
|
44
|
+
'.exe', '.dll', '.so', '.dylib', '.bin', '.o', '.a', '.lib', '.node', '.wasm', '.class', '.pyc', '.pyo',
|
|
45
|
+
// office / PDF (szöveg-kinyerés BACKLOG)
|
|
46
|
+
'.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.odt', '.ods',
|
|
47
|
+
// adatbázis / egyéb bináris
|
|
48
|
+
'.db', '.sqlite', '.sqlite3', '.mdb', '.dat', '.map',
|
|
49
|
+
]);
|
|
37
50
|
/**
|
|
38
|
-
* Egy fájl route-verdiktje (
|
|
39
|
-
* (
|
|
40
|
-
* → `codebase
|
|
51
|
+
* Egy fájl route-verdiktje (FAM-REV-064 denylist-inverzió). Sorrend: (1) generált-zaj (lock/`.min.`/
|
|
52
|
+
* source-map) → skip; (2) dokumentum-kiterjesztés → `documents`; (3) known-binary → skip; (4) MINDEN MÁS
|
|
53
|
+
* (bármilyen szöveg, ismeretlen kiterjesztés, extension-nélküli) → `codebase`. Case-insensitive.
|
|
41
54
|
*/
|
|
42
55
|
static route(relativePath) {
|
|
43
56
|
const fileName = path.basename(relativePath).toLowerCase();
|
|
44
57
|
const extension = path.extname(fileName);
|
|
58
|
+
if (FAM_FileRouting_Util.isGeneratedNoise(fileName)) {
|
|
59
|
+
return 'skip';
|
|
60
|
+
}
|
|
45
61
|
if (FAM_FileRouting_Util.DOCUMENT_EXTENSIONS.includes(extension)) {
|
|
46
62
|
return fam_table_type_enum_1.FAM_Table.documents;
|
|
47
63
|
}
|
|
48
|
-
if (FAM_FileRouting_Util.
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
if (FAM_FileRouting_Util.isConfigFile(fileName)) {
|
|
52
|
-
return fam_table_type_enum_1.FAM_Table.codebase;
|
|
64
|
+
if (FAM_FileRouting_Util.BINARY_EXTENSIONS.has(extension)) {
|
|
65
|
+
return 'skip';
|
|
53
66
|
}
|
|
54
|
-
|
|
67
|
+
// Minden egyéb (ismert kód, ismeretlen-de-szöveges, extension-nélküli LICENSE/Dockerfile/git-hook) →
|
|
68
|
+
// codebase. A bináris-tartalmú álcázott fájlt a scanner null-byte tartalom-ellenőrzése szűri.
|
|
69
|
+
return fam_table_type_enum_1.FAM_Table.codebase;
|
|
55
70
|
}
|
|
56
71
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
72
|
+
* Generált / zaj fájl-e (FAM-REV-064): a lock-fájlok (pnpm-lock.yaml / package-lock.json / yarn.lock /
|
|
73
|
+
* `*.lock`), a minifikált bundle-k (`.min.js`/`.min.css`) — ezek hatalmasak + generáltak, NEM info-
|
|
74
|
+
* hordozó forrás, ezért `skip` (NEM vesztünk valódi információt; a forrás `.ts`/`.scss` megvan).
|
|
59
75
|
*/
|
|
60
|
-
static
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
if (fileName === 'package.json' || fileName === 'package-lock.json') {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
if (/^tsconfig.*\.json$/.test(fileName)) {
|
|
76
|
+
static isGeneratedNoise(fileName) {
|
|
77
|
+
if (fileName === 'pnpm-lock.yaml' || fileName === 'package-lock.json' || fileName === 'yarn.lock'
|
|
78
|
+
|| fileName === 'bun.lockb' || fileName === 'composer.lock') {
|
|
68
79
|
return true;
|
|
69
80
|
}
|
|
70
|
-
if (
|
|
81
|
+
if (fileName.endsWith('.lock')) {
|
|
71
82
|
return true;
|
|
72
83
|
}
|
|
73
|
-
if (
|
|
84
|
+
if (/\.min\.(js|css|mjs)$/.test(fileName)) {
|
|
74
85
|
return true;
|
|
75
86
|
}
|
|
76
87
|
return false;
|
|
77
88
|
}
|
|
78
89
|
/**
|
|
79
|
-
* A chunker-stratégia kulcsa egy fájlhoz (SP-4.2 dispatch, dsgn-004 §3). `ts` a TS-szemantikus
|
|
80
|
-
*
|
|
81
|
-
* `
|
|
82
|
-
* `skip` fájlra NEM hívandó.
|
|
90
|
+
* A chunker-stratégia kulcsa egy fájlhoz (SP-4.2 dispatch, dsgn-004 §3). `ts` a TS/JS-szemantikus,
|
|
91
|
+
* `md` a markdown-header-aware (`.md`/`.mdx`/`.markdown`/`.mdc`), `generic` minden más `documents`/
|
|
92
|
+
* `codebase` fájlra (config/JSON/HTML/`.txt`/`.sh`/`.ps1`/`.xml`/ismeretlen-szöveg). A `route`
|
|
93
|
+
* előfeltétel: `skip` fájlra NEM hívandó.
|
|
83
94
|
*/
|
|
84
95
|
static chunkStrategyFor(relativePath) {
|
|
85
96
|
const extension = path.extname(path.basename(relativePath).toLowerCase());
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_ProjectIdentity_Util = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
|
+
/**
|
|
8
|
+
* `FAM_ProjectIdentity_Util` — egy scan-gyökér **projekt-identitásának** felismerése (git + `package.json`).
|
|
9
|
+
* A scan ebből (a) egy kereshető `knowledge` „project-identity" entry-t készít (név/verzió/leírás/függőségek/
|
|
10
|
+
* git-repo), és (b) reference-aliasokat (a package-név + rövid alakok → a projekt scope-ja). A parse-rész PURE
|
|
11
|
+
* (önállóan tesztelhető), a `detect` az IO-wrapper (a `.git`/`package.json` olvasása — opt-in: hiányzó fájl no-op).
|
|
12
|
+
*/
|
|
13
|
+
class FAM_ProjectIdentity_Util {
|
|
14
|
+
/** A generált identity-entry `kind`-ja. */
|
|
15
|
+
static KIND = 'project-identity';
|
|
16
|
+
/** A `package.json`-ból kinyert mezők (PURE — érvénytelen JSON → üres). */
|
|
17
|
+
static parsePackageJson(content) {
|
|
18
|
+
try {
|
|
19
|
+
const parsed = JSON.parse(content);
|
|
20
|
+
const deps = [
|
|
21
|
+
...Object.keys(parsed.dependencies ?? {}),
|
|
22
|
+
...Object.keys(parsed.peerDependencies ?? {}),
|
|
23
|
+
];
|
|
24
|
+
return {
|
|
25
|
+
packageName: typeof parsed.name === 'string' ? parsed.name : undefined,
|
|
26
|
+
version: typeof parsed.version === 'string' ? parsed.version : undefined,
|
|
27
|
+
description: typeof parsed.description === 'string' ? parsed.description : undefined,
|
|
28
|
+
dependencies: Array.from(new Set(deps)).sort(),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return { dependencies: [] };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** A git `origin` remote URL-je a `.git/config` tartalmából (PURE; nincs origin → undefined). */
|
|
36
|
+
static parseGitRemote(gitConfigContent) {
|
|
37
|
+
const lines = gitConfigContent.split(/\r?\n/);
|
|
38
|
+
let inOrigin = false;
|
|
39
|
+
for (const rawLine of lines) {
|
|
40
|
+
const line = rawLine.trim();
|
|
41
|
+
if (line.startsWith('[remote ')) {
|
|
42
|
+
inOrigin = line.includes('"origin"');
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (inOrigin && line.startsWith('url')) {
|
|
46
|
+
const eq = line.indexOf('=');
|
|
47
|
+
if (eq >= 0) {
|
|
48
|
+
return line.slice(eq + 1).trim();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
/** Egy git-remote-URL → `org/repo` rövid alak (`.git` levágva; SSH/HTTPS egyaránt; PURE). Hiba → undefined. */
|
|
55
|
+
static shortRepo(remoteUrl) {
|
|
56
|
+
if (!remoteUrl) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
// git@host:org/repo.git VAGY https://host/org/repo.git
|
|
60
|
+
const afterHost = remoteUrl.includes(':') && !remoteUrl.startsWith('http')
|
|
61
|
+
? remoteUrl.slice(remoteUrl.lastIndexOf(':') + 1)
|
|
62
|
+
: remoteUrl.replace(/^https?:\/\/[^/]+\//, '');
|
|
63
|
+
const cleaned = afterHost.replace(/\.git$/, '').replace(/^\/+/, '');
|
|
64
|
+
const segments = cleaned.split('/').filter(Boolean);
|
|
65
|
+
return segments.length >= 2 ? segments.slice(-2).join('/') : (segments[0] || undefined);
|
|
66
|
+
}
|
|
67
|
+
/** A projekt-identitás felismerése egy scan-gyökérből (IO: `package.json` + `.git/config`). Hiányzó → részleges. */
|
|
68
|
+
static detect(rootAbsolutePath) {
|
|
69
|
+
const identity = { isGit: false, dependencies: [] };
|
|
70
|
+
try {
|
|
71
|
+
const pkgPath = path.join(rootAbsolutePath, 'package.json');
|
|
72
|
+
if (fs.existsSync(pkgPath)) {
|
|
73
|
+
const parsed = FAM_ProjectIdentity_Util.parsePackageJson(fs.readFileSync(pkgPath, 'utf-8'));
|
|
74
|
+
identity.packageName = parsed.packageName;
|
|
75
|
+
identity.version = parsed.version;
|
|
76
|
+
identity.description = parsed.description;
|
|
77
|
+
identity.dependencies = parsed.dependencies;
|
|
78
|
+
}
|
|
79
|
+
const gitDir = path.join(rootAbsolutePath, '.git');
|
|
80
|
+
if (fs.existsSync(gitDir)) {
|
|
81
|
+
identity.isGit = true;
|
|
82
|
+
const configPath = path.join(gitDir, 'config');
|
|
83
|
+
if (fs.existsSync(configPath)) {
|
|
84
|
+
identity.gitRemote = FAM_ProjectIdentity_Util.parseGitRemote(fs.readFileSync(configPath, 'utf-8'));
|
|
85
|
+
identity.gitRepo = FAM_ProjectIdentity_Util.shortRepo(identity.gitRemote);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// best-effort: az identitás-olvasás hibája NEM buktatja a scant (a részleges identity visszaadva).
|
|
91
|
+
}
|
|
92
|
+
return identity;
|
|
93
|
+
}
|
|
94
|
+
/** Van-e bármi érdemi identitás (package.json VAGY git) — különben nincs értelme entry-t generálni. */
|
|
95
|
+
static hasIdentity(identity) {
|
|
96
|
+
return Boolean(identity.packageName || identity.isGit);
|
|
97
|
+
}
|
|
98
|
+
/** A kereshető `knowledge` „project-identity" entry szövege (PURE). */
|
|
99
|
+
static buildContent(identity, scopeLabel, root) {
|
|
100
|
+
const lines = [];
|
|
101
|
+
lines.push(`Projekt-identitás — ${scopeLabel}`);
|
|
102
|
+
lines.push(`Gyökér: ${root}`);
|
|
103
|
+
if (identity.packageName) {
|
|
104
|
+
lines.push(`Csomag: ${identity.packageName}${identity.version ? ` v${identity.version}` : ''}`);
|
|
105
|
+
}
|
|
106
|
+
lines.push(`Git-projekt: ${identity.isGit ? 'igen' : 'nem'}${identity.gitRepo ? ` (repo: ${identity.gitRepo})` : ''}`);
|
|
107
|
+
if (identity.description) {
|
|
108
|
+
lines.push(`Leírás: ${identity.description}`);
|
|
109
|
+
}
|
|
110
|
+
if (identity.dependencies.length) {
|
|
111
|
+
lines.push(`Függőségek (${identity.dependencies.length}): ${identity.dependencies.join(', ')}`);
|
|
112
|
+
}
|
|
113
|
+
return lines.join('\n');
|
|
114
|
+
}
|
|
115
|
+
/** A reference-aliasok (a package-név + rövid alakok + repo + dir-név → a projekt scope-ja). Dedup, üresek nélkül (PURE). */
|
|
116
|
+
static buildAliases(identity, dirName, scopeCanonical) {
|
|
117
|
+
const aliases = [dirName, scopeCanonical];
|
|
118
|
+
if (identity.packageName) {
|
|
119
|
+
aliases.push(identity.packageName);
|
|
120
|
+
const bare = identity.packageName.replace(/^@[^/]+\//, ''); // @futdevpro/fsm-dynamo → fsm-dynamo
|
|
121
|
+
aliases.push(bare);
|
|
122
|
+
const firstSegment = bare.split('-')[0]; // fsm-dynamo → fsm
|
|
123
|
+
if (firstSegment && firstSegment !== bare) {
|
|
124
|
+
aliases.push(firstSegment);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (identity.gitRepo) {
|
|
128
|
+
aliases.push(identity.gitRepo);
|
|
129
|
+
aliases.push(identity.gitRepo.split('/').pop() ?? '');
|
|
130
|
+
}
|
|
131
|
+
return Array.from(new Set(aliases.map((alias) => alias.trim()).filter(Boolean)));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.FAM_ProjectIdentity_Util = FAM_ProjectIdentity_Util;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_ScanProgress_Util = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* `FAM_ScanProgress_Util` (descriptive user feedback) — a scan **pre-becslés** + **futás-közbeni progress** PURE
|
|
6
|
+
* (DB-/provider-mentes) magja. A nagy, workspace-szintű scanhez: a hívó ELŐRE lássa a becsült időt, és FUTÁS
|
|
7
|
+
* közben kövesse a haladást (X/N fájl, %, chunk, verdikt-bontás, eltelt + ETA). Statikus util — a control-service
|
|
8
|
+
* a delta-számokból + az óra-időből táplálja; a formázás/ETA-matek itt izoláltan tesztelhető.
|
|
9
|
+
*/
|
|
10
|
+
class FAM_ScanProgress_Util {
|
|
11
|
+
/**
|
|
12
|
+
* Pre-scan idő-becslés az embeddelendő chunk-számból + a per-chunk-ms-ből. `estimatedSeconds = chunks×ms/1000`.
|
|
13
|
+
* Durva (a tényleges sebesség gép-/modell-függő); a futó scan ETA-ja pontosítja.
|
|
14
|
+
*/
|
|
15
|
+
static estimate(set) {
|
|
16
|
+
const estimatedSeconds = Math.round((set.chunksToEmbed * set.msPerChunk) / 1000);
|
|
17
|
+
return {
|
|
18
|
+
chunksToEmbed: set.chunksToEmbed,
|
|
19
|
+
msPerChunk: set.msPerChunk,
|
|
20
|
+
estimatedSeconds: estimatedSeconds,
|
|
21
|
+
note: `~${FAM_ScanProgress_Util.formatDuration(estimatedSeconds)} embeddelés (${set.chunksToEmbed} chunk × `
|
|
22
|
+
+ `${set.msPerChunk}ms — DURVA becslés, gép-/modell-függő; a futó scan ETA-ja pontosítja)`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Másodperc → ember-olvasható (`45s` / `3m 20s` / `1h 5m`). Negatív/0 → `0s`. */
|
|
26
|
+
static formatDuration(totalSeconds) {
|
|
27
|
+
const s = Math.max(0, Math.round(totalSeconds));
|
|
28
|
+
if (s < 60) {
|
|
29
|
+
return `${s}s`;
|
|
30
|
+
}
|
|
31
|
+
const minutes = Math.floor(s / 60);
|
|
32
|
+
const remSec = s % 60;
|
|
33
|
+
if (minutes < 60) {
|
|
34
|
+
return remSec ? `${minutes}m ${remSec}s` : `${minutes}m`;
|
|
35
|
+
}
|
|
36
|
+
const hours = Math.floor(minutes / 60);
|
|
37
|
+
const remMin = minutes % 60;
|
|
38
|
+
return remMin ? `${hours}h ${remMin}m` : `${hours}h`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Egy futás-közbeni progress-sor: `processed/total` fájl + %, chunk-szám, verdikt-bontás, eltelt idő + ETA.
|
|
42
|
+
* Az ETA a MÉRT sebességből (`processed / elapsed`) → a hátralévő fájlok ideje (csak ha van haladás + maradék).
|
|
43
|
+
* `[famIngest]` prefix → az activity-monitor allowlistjén keresztül megjelenik a konzol-ablakban.
|
|
44
|
+
*/
|
|
45
|
+
static progressLine(set) {
|
|
46
|
+
const pct = set.total ? Math.round((set.processed / set.total) * 100) : 100;
|
|
47
|
+
const rate = set.processed / Math.max(set.elapsedSeconds, 0.001);
|
|
48
|
+
const remaining = set.total - set.processed;
|
|
49
|
+
const eta = rate > 0 && remaining > 0
|
|
50
|
+
? `, ETA ~${FAM_ScanProgress_Util.formatDuration(remaining / rate)}`
|
|
51
|
+
: '';
|
|
52
|
+
return `[famIngest] feldolgozás ${set.processed}/${set.total} fájl (${pct}%), ${set.chunkCount} chunk, `
|
|
53
|
+
+ `${set.verdicts.new} új / ${set.verdicts.modified} mód / ${set.verdicts.equal} vált., `
|
|
54
|
+
+ `eltelt ${FAM_ScanProgress_Util.formatDuration(set.elapsedSeconds)}${eta}`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.FAM_ScanProgress_Util = FAM_ScanProgress_Util;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_ScanSummary_Util = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* `FAM_ScanSummary_Util` (file-rendszer összefoglaló) — a scan által GENERÁLT, kereshető „mi van a projektben"
|
|
6
|
+
* összefoglaló PURE építője. A scan után egy `knowledge`-entry készül a mappastruktúrából (mappák + fájlok
|
|
7
|
+
* felsorolása), hogy az agent lekérdezhesse a projekt/mappa tartalmát (NEM kell végigscannelnie). Statikus util.
|
|
8
|
+
*
|
|
9
|
+
* **Méret-korlát:** a per-mappa fájllista a `MAX_FILES_PER_DIR`-nál levágódik (`+N további`), a teljes szöveg a
|
|
10
|
+
* `MAX_CHARS`-nál — így az összefoglaló egyetlen, embeddelhető chunk marad nagy fáknál is (minden MAPPA így is felsorolt).
|
|
11
|
+
*/
|
|
12
|
+
class FAM_ScanSummary_Util {
|
|
13
|
+
/** A generált összefoglaló-entry `kind`-ja. */
|
|
14
|
+
static KIND = 'fs-summary';
|
|
15
|
+
/** A generált összefoglaló-entry `source.type`-ja (a reconciliation `scan`-t szűr → ezt nem érinti). */
|
|
16
|
+
static SOURCE_TYPE = 'scan-summary';
|
|
17
|
+
/** Per-mappa felsorolt fájlok plafonja (felette `+N további`). */
|
|
18
|
+
static MAX_FILES_PER_DIR = 80;
|
|
19
|
+
/** A teljes összefoglaló-szöveg plafonja (egyetlen embeddelhető chunk). */
|
|
20
|
+
static MAX_CHARS = 40000;
|
|
21
|
+
/**
|
|
22
|
+
* A mappastruktúra-összefoglaló szövege: fejléc (scope / root / fájl-számok) + a mappánként csoportosított,
|
|
23
|
+
* rendezett fájllista. A relatív utak `/`-normalizáltak; a gyökér-szintű fájlok a `(gyökér)` alatt.
|
|
24
|
+
*/
|
|
25
|
+
static build(set) {
|
|
26
|
+
const byDir = new Map();
|
|
27
|
+
for (const rawPath of set.relativePaths) {
|
|
28
|
+
const normalized = rawPath.replace(/\\/g, '/');
|
|
29
|
+
const slashIndex = normalized.lastIndexOf('/');
|
|
30
|
+
const dir = slashIndex >= 0 ? normalized.slice(0, slashIndex) : '';
|
|
31
|
+
const name = slashIndex >= 0 ? normalized.slice(slashIndex + 1) : normalized;
|
|
32
|
+
if (!byDir.has(dir)) {
|
|
33
|
+
byDir.set(dir, []);
|
|
34
|
+
}
|
|
35
|
+
byDir.get(dir)?.push(name);
|
|
36
|
+
}
|
|
37
|
+
const lines = [];
|
|
38
|
+
lines.push(`File-rendszer összefoglaló — ${set.scopeLabel}`);
|
|
39
|
+
lines.push(`Gyökér: ${set.root}`);
|
|
40
|
+
lines.push(`${set.relativePaths.length} fájl ingestelve (${set.tables.join(', ') || '—'}), ${set.skippedCount} kihagyva.`);
|
|
41
|
+
lines.push('');
|
|
42
|
+
lines.push(`Mappák (${byDir.size}) + fájlok:`);
|
|
43
|
+
for (const dir of Array.from(byDir.keys()).sort()) {
|
|
44
|
+
const files = (byDir.get(dir) ?? []).sort();
|
|
45
|
+
const label = dir === '' ? '(gyökér)' : `${dir}/`;
|
|
46
|
+
const shown = files.length > FAM_ScanSummary_Util.MAX_FILES_PER_DIR
|
|
47
|
+
? files.slice(0, FAM_ScanSummary_Util.MAX_FILES_PER_DIR)
|
|
48
|
+
: files;
|
|
49
|
+
const more = files.length > FAM_ScanSummary_Util.MAX_FILES_PER_DIR
|
|
50
|
+
? ` (+${files.length - FAM_ScanSummary_Util.MAX_FILES_PER_DIR} további)`
|
|
51
|
+
: '';
|
|
52
|
+
lines.push(` ${label} — ${files.length} fájl: ${shown.join(', ')}${more}`);
|
|
53
|
+
}
|
|
54
|
+
const content = lines.join('\n');
|
|
55
|
+
return content.length > FAM_ScanSummary_Util.MAX_CHARS
|
|
56
|
+
? `${content.slice(0, FAM_ScanSummary_Util.MAX_CHARS)}\n… (összefoglaló levágva a méret-plafonnál)`
|
|
57
|
+
: content;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.FAM_ScanSummary_Util = FAM_ScanSummary_Util;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_ScanWeight_Util = void 0;
|
|
4
|
+
const fam_glob_match_util_1 = require("./fam-glob-match.util");
|
|
5
|
+
/**
|
|
6
|
+
* `FAM_ScanWeight_Util` (FAM-REV-055) — a scan-idejű **súly-kiemelés** pure magja. A hívó (agent) scankor
|
|
7
|
+
* megadhat `weights` szabályokat (glob → súly), hogy a FONTOSABB fájlok chunkjai NAGYOBB retrieval-súlyt
|
|
8
|
+
* kapjanak (a `finalScore = score × weight` → előrébb a rangsorban). **First-match-wins:** a `weights` sorrend
|
|
9
|
+
* SZÁMÍT (az első illeszkedő szabály nyer). Nincs match → `undefined` (→ a tár model-default súlya marad).
|
|
10
|
+
*/
|
|
11
|
+
class FAM_ScanWeight_Util {
|
|
12
|
+
/**
|
|
13
|
+
* Az adott (projekt-relatív) fájl súlya a `weights` szabályokból: az ELSŐ illeszkedő minta súlya, vagy
|
|
14
|
+
* `undefined` (nincs szabály / nincs match). Az illesztés a `FAM_GlobMatch_Util` (a scan ignore/include-pal
|
|
15
|
+
* azonos szemantika). A negatív / nem-véges súlyt kihagyja (defenzív — a 0/negatív weight retrieval-kizárást
|
|
16
|
+
* jelentene; ha szándékos, a `write`-on át explicit állítható).
|
|
17
|
+
*/
|
|
18
|
+
static resolve(relativePath, weights) {
|
|
19
|
+
if (!weights || !weights.length) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
for (const rule of weights) {
|
|
23
|
+
if (typeof rule.weight !== 'number' || !Number.isFinite(rule.weight) || rule.weight <= 0) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (fam_glob_match_util_1.FAM_GlobMatch_Util.matches(relativePath, rule.pattern)) {
|
|
27
|
+
return rule.weight;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
/** Teszt-/spec-fájl-e (`*.spec.*` / `*.test.*` a TS/JS-kiterjesztéseken). FAM-REV-058. */
|
|
33
|
+
static isTestFile(relativePath) {
|
|
34
|
+
return /\.(spec|test)\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/i.test(relativePath);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A fájl EFFEKTÍV súlya a DEFAULT teszt-súllyal (FAM-REV-058): az explicit scan-`weights` match NYER; különben
|
|
38
|
+
* egy teszt-/spec-fájl a `testFileWeight`-et kapja (a próza-nehéz specek különben az implementáció fölé
|
|
39
|
+
* rangsorolnak); különben `undefined` (→ a tár model-default súlya). A `testFileWeight===1` (nincs csökkentés)
|
|
40
|
+
* vagy hiánya → nincs default-súly.
|
|
41
|
+
*/
|
|
42
|
+
static resolveWithDefault(relativePath, weights, testFileWeight) {
|
|
43
|
+
const explicit = FAM_ScanWeight_Util.resolve(relativePath, weights);
|
|
44
|
+
if (explicit !== undefined) {
|
|
45
|
+
return explicit;
|
|
46
|
+
}
|
|
47
|
+
if (typeof testFileWeight === 'number' && testFileWeight !== 1 && FAM_ScanWeight_Util.isTestFile(relativePath)) {
|
|
48
|
+
return testFileWeight;
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.FAM_ScanWeight_Util = FAM_ScanWeight_Util;
|
|
@@ -3,9 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.FAM_SecretExclude_Util = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* `FAM_SecretExclude_Util` (SP-4.1, dsgn-004 §6.3) — a scan-réteg **fájlnév-/útvonal-alapú**
|
|
6
|
-
* secret-kizárása. A felsorolt minták (`.env*`, `*.key`, `*.pem`, `*.p12`, `id_rsa*`,
|
|
7
|
-
*
|
|
8
|
-
* routing **ELŐTT** fut, és a kizárt fájlok a `filesSkipped`-be számolódnak
|
|
6
|
+
* secret-kizárása. A felsorolt minták (`.env*`, `*.key`, `*.pem`, `*.p12`, `id_rsa*`, `*.crt`,
|
|
7
|
+
* `secrets/` mappa + a `secret`/`credential` névrész NEM-forrásfájlokon) **SOHA** nem ingestálódnak;
|
|
8
|
+
* a kizárás a file-típus-routing **ELŐTT** fut, és a kizárt fájlok a `filesSkipped`-be számolódnak
|
|
9
|
+
* (audit, NEM néma).
|
|
10
|
+
*
|
|
11
|
+
* **FALSE-POSITIVE FIX (2026-06-20 audit):** a korábbi `*secret*` / `*credential*` substring-minta
|
|
12
|
+
* **bármely** forrásfájlt is kizárt, aminek a neve tartalmazta ezeket (pl. maga a
|
|
13
|
+
* `fam-secret-exclude.util.ts`, vagy egy `secret-manager.service.ts`) → kód-RAG-lefedettség-rés. Ezért
|
|
14
|
+
* a `secret`/`credential` névrész-minta MOST CSAK **nem-forrás/doc-kiterjesztésekre** alkalmazódik
|
|
15
|
+
* (egy `.ts`/`.md` fájl, aminek a neve „secret", az KÓD a titokról, NEM titok-fájl). A valódi titok-
|
|
16
|
+
* fájlok (`.env`/`.key`/`.pem`/…) kiterjesztés-/névalapon továbbra is mindig kizártak.
|
|
9
17
|
*
|
|
10
18
|
* **HATÁR (dsgn-004 §6 megjegyzés + `MP-4-detailed` kockázat) — KIFEJEZETTEN BACKLOG:** ez CSAK
|
|
11
19
|
* fájlnév-/útvonal-alapú kizárás. A **tartalmi** PII/secret-detektálás (a fájlon BELÜLI titkok
|
|
@@ -15,12 +23,10 @@ exports.FAM_SecretExclude_Util = void 0;
|
|
|
15
23
|
*/
|
|
16
24
|
class FAM_SecretExclude_Util {
|
|
17
25
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* ettől FÜGGETLENÜL is alkalmazza őket (a config-override NEM kapcsolhatja ki a secret-védelmet).
|
|
21
|
-
* A vizsgálat a fájlnévre (regex) + az útvonal-szegmensekre (`secrets/`) megy.
|
|
26
|
+
* HARD secret-fájlnév-minták (dsgn-004 §6.3) — **MINDIG** kizárnak, kiterjesztéstől függetlenül:
|
|
27
|
+
* ezek a fájlok maguk a titkok (kulcs/cert/env). A config-override NEM kapcsolhatja ki őket.
|
|
22
28
|
*/
|
|
23
|
-
static
|
|
29
|
+
static HARD_SECRET_PATTERNS = [
|
|
24
30
|
/^\.env(\..*)?$/i, // .env, .env.local, .env.production, ...
|
|
25
31
|
/\.key$/i, // *.key
|
|
26
32
|
/\.pem$/i, // *.pem
|
|
@@ -29,14 +35,24 @@ class FAM_SecretExclude_Util {
|
|
|
29
35
|
/\.pfx$/i, // *.pfx (cert)
|
|
30
36
|
/^id_rsa.*$/i, // id_rsa, id_rsa.pub, ...
|
|
31
37
|
/^id_ed25519.*$/i, // id_ed25519, id_ed25519.pub
|
|
32
|
-
/secret/i, // *secret* (bárhol a fájlnévben)
|
|
33
|
-
/credential/i, // *credential* (bárhol a fájlnévben)
|
|
34
38
|
];
|
|
39
|
+
/**
|
|
40
|
+
* SOFT névrész-minták (`secret`/`credential` bárhol a fájlnévben) — CSAK NEM-forrás/doc-fájlokra
|
|
41
|
+
* (pl. `secrets.json`, `my-credential.txt`). Egy `.ts`/`.md` fájl, aminek a neve „secret", az KÓD/
|
|
42
|
+
* DOC a titokról (legit forrás), NEM titok → ingestálódik (false-positive fix, lásd osztály-jsdoc).
|
|
43
|
+
*/
|
|
44
|
+
static SOFT_SECRET_NAME_PATTERNS = [
|
|
45
|
+
/secret/i, // *secret* (csak nem-forrás kiterjesztésen)
|
|
46
|
+
/credential/i, // *credential* (csak nem-forrás kiterjesztésen)
|
|
47
|
+
];
|
|
48
|
+
/** Ismert FORRÁS-/DOC-kiterjesztések — ezeken a SOFT névrész-minta NEM zár ki (legit kód/doc). */
|
|
49
|
+
static SOURCE_DOC_EXTENSION = /\.(ts|tsx|mts|cts|js|jsx|mjs|cjs|md|markdown)$/i;
|
|
35
50
|
/** A secret-mappák (az útvonal BÁRMELY szegmense — pl. `secrets/`, `.ssh/`). */
|
|
36
51
|
static SECRET_DIR_SEGMENTS = ['secrets', '.ssh', '.gnupg'];
|
|
37
52
|
/**
|
|
38
|
-
* Secret-e a (projekt-relatív, `/`-normalizált) útvonal —
|
|
39
|
-
*
|
|
53
|
+
* Secret-e a (projekt-relatív, `/`-normalizált) útvonal — secret-mappa-szegmens VAGY HARD-minta
|
|
54
|
+
* VAGY (nem-forrásfájlon) SOFT névrész-minta alapján (dsgn-004 §6.3). `true` → SOHA nem ingestálódik
|
|
55
|
+
* (`filesSkipped`, audit).
|
|
40
56
|
*/
|
|
41
57
|
static isSecret(relativePath) {
|
|
42
58
|
const normalized = relativePath.replace(/\\/g, '/');
|
|
@@ -47,8 +63,15 @@ class FAM_SecretExclude_Util {
|
|
|
47
63
|
if (dirSegments.some((segment) => FAM_SecretExclude_Util.SECRET_DIR_SEGMENTS.includes(segment))) {
|
|
48
64
|
return true;
|
|
49
65
|
}
|
|
50
|
-
// (2)
|
|
51
|
-
|
|
66
|
+
// (2) HARD secret-fájlnév-minta (mindig).
|
|
67
|
+
if (FAM_SecretExclude_Util.HARD_SECRET_PATTERNS.some((pattern) => pattern.test(fileName))) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
// (3) SOFT névrész-minta — CSAK ha NEM ismert forrás-/doc-kiterjesztés (a "secret"-nevű .ts legit kód).
|
|
71
|
+
if (FAM_SecretExclude_Util.SOURCE_DOC_EXTENSION.test(fileName)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return FAM_SecretExclude_Util.SOFT_SECRET_NAME_PATTERNS.some((pattern) => pattern.test(fileName));
|
|
52
75
|
}
|
|
53
76
|
}
|
|
54
77
|
exports.FAM_SecretExclude_Util = FAM_SecretExclude_Util;
|
|
@@ -32,6 +32,19 @@ class FAM_SlidingChunker_Util {
|
|
|
32
32
|
if (paragraphStart >= 0) {
|
|
33
33
|
charCursor = paragraphStart;
|
|
34
34
|
}
|
|
35
|
+
// FAM-REV-065: egy paragrafus ÖNMAGÁBAN a maxSize felett (pl. sortörés-nélküli nagy JSON/blob) →
|
|
36
|
+
// flush + HARD-SPLIT (char-vágás maxSize-onként). KÜLÖNBEN egyetlen óriás-chunk lenne, ami az
|
|
37
|
+
// embedding-modell token-limitjét túllépi → `error` státusz → a tartalom NEM kereshető (info-veszteség).
|
|
38
|
+
if (paragraph.length > sizing.maxSize) {
|
|
39
|
+
if (currentText.trim().length) {
|
|
40
|
+
FAM_SlidingChunker_Util.emit(chunks, currentText.trim(), currentCharStart, sizing.minSize);
|
|
41
|
+
currentText = '';
|
|
42
|
+
}
|
|
43
|
+
FAM_SlidingChunker_Util.hardSplit(chunks, paragraph, charCursor, sizing);
|
|
44
|
+
charCursor = charCursor + paragraph.length;
|
|
45
|
+
currentCharStart = charCursor;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
35
48
|
if (currentText.length && currentText.length + paragraph.length + 2 > sizing.maxSize) {
|
|
36
49
|
FAM_SlidingChunker_Util.emit(chunks, currentText.trim(), currentCharStart, sizing.minSize);
|
|
37
50
|
if (currentText.length > sizing.overlap) {
|
|
@@ -60,6 +73,27 @@ class FAM_SlidingChunker_Util {
|
|
|
60
73
|
}
|
|
61
74
|
return chunks;
|
|
62
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Egy maxSize feletti, természetes törés-pont NÉLKÜLI szöveg HARD-SPLIT-je (FAM-REV-065): char-vágás
|
|
78
|
+
* `maxSize`-onként, `overlap`-pal lépve. A darabok a `minSize`-szűrés ALÓL MENTESEK (a tail-darab is kell
|
|
79
|
+
* — semmi ne vesszen el), és a `position` a forrás-offszetre mutat. Így a nagy JSON/blob is embeddelhető
|
|
80
|
+
* (modell-token-limit alatti darabok), nem ragad `error`-ba.
|
|
81
|
+
*/
|
|
82
|
+
static hardSplit(chunks, text, charStart, sizing) {
|
|
83
|
+
const step = Math.max(1, sizing.maxSize - sizing.overlap);
|
|
84
|
+
for (let i = 0; i < text.length; i += step) {
|
|
85
|
+
const piece = text.slice(i, i + sizing.maxSize);
|
|
86
|
+
chunks.push({
|
|
87
|
+
content: piece,
|
|
88
|
+
position: { charStart: charStart + i, charEnd: charStart + i + piece.length },
|
|
89
|
+
chunkType: 'generic',
|
|
90
|
+
headingPath: [],
|
|
91
|
+
});
|
|
92
|
+
if (i + sizing.maxSize >= text.length) {
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
63
97
|
/** Egy chunk hozzáadása `chunkType='generic'`-kel (zaj-szűrés a `minSize`-ra). */
|
|
64
98
|
static emit(chunks, content, charStart, minSize) {
|
|
65
99
|
if (content.length < minSize) {
|