@futdevpro/fdp-agent-memory 0.1.0

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.
Files changed (117) hide show
  1. package/README.md +345 -0
  2. package/build/package.json +96 -0
  3. package/build/src/_assets/mcp-client-config/README.md +29 -0
  4. package/build/src/_assets/mcp-client-config/claude_desktop_config.json +15 -0
  5. package/build/src/_assets/mcp-client-config/mcp.json +15 -0
  6. package/build/src/_collections/config-catalog.const.js +180 -0
  7. package/build/src/_collections/config-error-codes.const.js +30 -0
  8. package/build/src/_collections/config-presets.const.js +25 -0
  9. package/build/src/_collections/error-banners.const.js +100 -0
  10. package/build/src/_collections/error-codes.const.js +150 -0
  11. package/build/src/_collections/fam-db-models.const.js +37 -0
  12. package/build/src/_collections/fam-entry-bootstrap.util.js +80 -0
  13. package/build/src/_collections/fam-error-context.util.js +90 -0
  14. package/build/src/_collections/fam-error-factory.util.js +64 -0
  15. package/build/src/_enums/fam-config-level.type-enum.js +15 -0
  16. package/build/src/_enums/fam-table.type-enum.js +20 -0
  17. package/build/src/_integration-tests/_helpers/fam-integration-test-setup.util.js +105 -0
  18. package/build/src/_models/data-models/fam-codebase.data-model.js +51 -0
  19. package/build/src/_models/data-models/fam-coding-patterns.data-model.js +58 -0
  20. package/build/src/_models/data-models/fam-config.data-model.js +68 -0
  21. package/build/src/_models/data-models/fam-documents.data-model.js +53 -0
  22. package/build/src/_models/data-models/fam-entry-base-properties.const.js +43 -0
  23. package/build/src/_models/data-models/fam-entry.data-model.js +81 -0
  24. package/build/src/_models/data-models/fam-error.data-model.js +88 -0
  25. package/build/src/_models/data-models/fam-ingest-run.data-model.js +74 -0
  26. package/build/src/_models/data-models/fam-knowledge.data-model.js +48 -0
  27. package/build/src/_models/data-models/fam-memory.data-model.js +55 -0
  28. package/build/src/_models/data-models/fam-reference.data-model.js +67 -0
  29. package/build/src/_models/data-models/fam-rules.data-model.js +51 -0
  30. package/build/src/_models/data-models/fam-scope.data-model.js +52 -0
  31. package/build/src/_models/interfaces/fam-common.interface.js +23 -0
  32. package/build/src/_models/interfaces/fam-config.interface.js +2 -0
  33. package/build/src/_models/interfaces/fam-error.interface.js +2 -0
  34. package/build/src/_modules/embedding/_collections/fam-embedding-pricing.const.js +22 -0
  35. package/build/src/_modules/embedding/_collections/fam-store-registry.const.js +63 -0
  36. package/build/src/_modules/embedding/_models/interfaces/fam-embedding-cost.interface.js +10 -0
  37. package/build/src/_modules/embedding/_models/interfaces/fam-embedding-provider.interface.js +2 -0
  38. package/build/src/_modules/embedding/_models/interfaces/fam-resolved-provider.interface.js +2 -0
  39. package/build/src/_modules/embedding/_services/fam-embedding-bootstrap.control-service.js +52 -0
  40. package/build/src/_modules/embedding/_services/fam-embedding-cost.control-service.js +175 -0
  41. package/build/src/_modules/embedding/_services/fam-embedding-pipeline.control-service.js +202 -0
  42. package/build/src/_modules/embedding/_services/fam-embedding-preset.control-service.js +66 -0
  43. package/build/src/_modules/embedding/_services/fam-embedding.control-service.js +253 -0
  44. package/build/src/_modules/embedding/_services/fam-entry.data-service.js +64 -0
  45. package/build/src/_modules/embedding/_services/fam-lmstudio-embedding.provider.js +112 -0
  46. package/build/src/_modules/embedding/_services/fam-mock-embedding.provider.js +64 -0
  47. package/build/src/_modules/embedding/_services/fam-openai-embedding.provider.js +64 -0
  48. package/build/src/_modules/embedding/_services/fam-vector-search.control-service.js +244 -0
  49. package/build/src/_modules/embedding/index.js +40 -0
  50. package/build/src/_modules/ingest/_collections/fam-content-hash.util.js +35 -0
  51. package/build/src/_modules/ingest/_collections/fam-file-routing.util.js +95 -0
  52. package/build/src/_modules/ingest/_collections/fam-glob-match.util.js +84 -0
  53. package/build/src/_modules/ingest/_collections/fam-md-chunker.util.js +164 -0
  54. package/build/src/_modules/ingest/_collections/fam-scan-path.util.js +91 -0
  55. package/build/src/_modules/ingest/_collections/fam-secret-exclude.util.js +54 -0
  56. package/build/src/_modules/ingest/_collections/fam-sliding-chunker.util.js +76 -0
  57. package/build/src/_modules/ingest/_collections/fam-ts-chunker.util.js +316 -0
  58. package/build/src/_modules/ingest/_models/interfaces/fam-ingest.interface.js +2 -0
  59. package/build/src/_modules/ingest/_services/fam-chunker.control-service.js +114 -0
  60. package/build/src/_modules/ingest/_services/fam-delta-compare.util.js +74 -0
  61. package/build/src/_modules/ingest/_services/fam-ingest-run.data-service.js +85 -0
  62. package/build/src/_modules/ingest/_services/fam-ingest.control-service.js +384 -0
  63. package/build/src/_modules/ingest/_services/fam-scan.control-service.js +211 -0
  64. package/build/src/_modules/ingest/index.js +46 -0
  65. package/build/src/_modules/mcp/_collections/fam-core-tools.const.js +186 -0
  66. package/build/src/_modules/mcp/_models/interfaces/fam-mcp.interface.js +31 -0
  67. package/build/src/_modules/mcp/_services/fam-capabilities-tool.service.js +111 -0
  68. package/build/src/_modules/mcp/_services/fam-capability-registry.service.js +1180 -0
  69. package/build/src/_modules/mcp/_services/fam-mcp-adapter.service.js +123 -0
  70. package/build/src/_modules/mcp/_services/fam-mcp-server.service.js +69 -0
  71. package/build/src/_modules/mcp/_services/fam-read-tool.service.js +99 -0
  72. package/build/src/_modules/mcp/_services/fam-write-tool.service.js +460 -0
  73. package/build/src/_modules/mcp/index.js +35 -0
  74. package/build/src/_modules/migration/_collections/fam-claude-mem-normalize.util.js +166 -0
  75. package/build/src/_modules/migration/_collections/fam-import-content-hash.util.js +38 -0
  76. package/build/src/_modules/migration/_collections/fam-target-mapping.util.js +90 -0
  77. package/build/src/_modules/migration/_enums/fam-claude-mem-source.type-enum.js +20 -0
  78. package/build/src/_modules/migration/_models/interfaces/fam-claude-mem.interface.js +26 -0
  79. package/build/src/_modules/migration/_services/fam-claude-mem-export-reader.service.js +134 -0
  80. package/build/src/_modules/migration/_services/fam-claude-mem-import.control-service.js +533 -0
  81. package/build/src/_modules/migration/_services/fam-claude-mem-sqlite-reader.service.js +144 -0
  82. package/build/src/_modules/migration/_services/fam-claude-mem-worker-reader.service.js +115 -0
  83. package/build/src/_modules/migration/_services/fam-import-dedup.data-service.js +102 -0
  84. package/build/src/_modules/migration/index.js +38 -0
  85. package/build/src/_modules/retrieval/_models/interfaces/fam-retrieval.interface.js +2 -0
  86. package/build/src/_modules/retrieval/_services/fam-retrieval-candidate.data-service.js +67 -0
  87. package/build/src/_modules/retrieval/_services/fam-retrieval-suggestions.util.js +182 -0
  88. package/build/src/_modules/retrieval/_services/fam-retrieval.control-service.js +282 -0
  89. package/build/src/_modules/retrieval/index.js +22 -0
  90. package/build/src/_modules/scope-reference/_collections/fam-fuzzy-match.util.js +86 -0
  91. package/build/src/_modules/scope-reference/_collections/fam-scope-normalize.util.js +47 -0
  92. package/build/src/_modules/scope-reference/_models/interfaces/fam-reference-resolution.interface.js +2 -0
  93. package/build/src/_modules/scope-reference/_models/interfaces/fam-resolution-trace.interface.js +2 -0
  94. package/build/src/_modules/scope-reference/_services/fam-reference.data-service.js +179 -0
  95. package/build/src/_modules/scope-reference/_services/fam-scope-resolver.control-service.js +473 -0
  96. package/build/src/_modules/scope-reference/_services/fam-scope.data-service.js +215 -0
  97. package/build/src/_modules/scope-reference/index.js +26 -0
  98. package/build/src/_routes/server/api/api.controller.js +400 -0
  99. package/build/src/_routes/server/client-app/client-app.control-service.js +132 -0
  100. package/build/src/_routes/server/client-app/client-app.controller.js +35 -0
  101. package/build/src/_routes/server/config/config.control-service.js +476 -0
  102. package/build/src/_routes/server/config/config.data-service.js +49 -0
  103. package/build/src/_routes/server/errors/errors.control-service.js +123 -0
  104. package/build/src/_routes/server/errors/errors.controller.js +65 -0
  105. package/build/src/_routes/server/errors/errors.data-service.js +80 -0
  106. package/build/src/_routes/server/server-status/server-status.control-service.js +19 -0
  107. package/build/src/_routes/server/server-status/server-status.controller.js +39 -0
  108. package/build/src/app.server.js +122 -0
  109. package/build/src/environments/environment.js +20 -0
  110. package/build/src/index.js +18 -0
  111. package/client-dist/chunk-GHKRM4SM.js +1 -0
  112. package/client-dist/chunk-LMTL7GA3.js +575 -0
  113. package/client-dist/index.html +17 -0
  114. package/client-dist/main-2KWB3QYK.js +2 -0
  115. package/client-dist/polyfills-HGDOEU5L.js +2 -0
  116. package/client-dist/styles-3J7JD5YE.css +1 -0
  117. package/package.json +96 -0
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FAM_ClaudeMemWorkerReader_Service = void 0;
4
+ const error_codes_const_1 = require("../../../_collections/error-codes.const");
5
+ const fam_error_factory_util_1 = require("../../../_collections/fam-error-factory.util");
6
+ const fam_claude_mem_source_type_enum_1 = require("../_enums/fam-claude-mem-source.type-enum");
7
+ const fam_claude_mem_normalize_util_1 = require("../_collections/fam-claude-mem-normalize.util");
8
+ /** A worker-api lekérdezés timeout-ja (ms) — fail-soft a worker-down ellen (NEM hang). */
9
+ const WORKER_API_TIMEOUT_MS = 8000;
10
+ /**
11
+ * `FAM_ClaudeMemWorkerReader_Service` (SP-11.1) — a **live worker-api reader** (`from=worker-api`,
12
+ * OPCIONÁLIS — csak ha a claude-mem worker fut). A worker REST-végpontjait (`GET /api/observations`,
13
+ * `GET /api/summaries`, `GET /api/prompts`, `GET /api/sessions`) olvassa Node 20 global `fetch`-csel
14
+ * (függőség-mentes), timeout-tal — worker-down → tiszta strukturált hiba (`FAM-IMP-SOURCE-001`), NEM
15
+ * hang. A reader UGYANAZT a normalizált halmazt adja, mint az export-JSON ugyanarra a tartalomra.
16
+ *
17
+ * **NEM az LLM-facing MCP-toolokon megy át** (search/timeline/get_observations — azok token-optimalizált
18
+ * lapozott eszközök): a worker-api bulk read-végpontjait használja közvetlenül (dsgn-009 §1).
19
+ */
20
+ class FAM_ClaudeMemWorkerReader_Service {
21
+ static _instance;
22
+ /** Default issuer (a forrás-hibák issuer-éhez; dsgn-008). */
23
+ issuer = 'FAM_ClaudeMemWorkerReader_Service';
24
+ static getInstance() {
25
+ if (!FAM_ClaudeMemWorkerReader_Service._instance) {
26
+ FAM_ClaudeMemWorkerReader_Service._instance = new FAM_ClaudeMemWorkerReader_Service();
27
+ }
28
+ return FAM_ClaudeMemWorkerReader_Service._instance;
29
+ }
30
+ /**
31
+ * A worker-api 4 végpontjának olvasása + normalizálás (SP-11.1). A `baseUrl` a worker base-URL-je
32
+ * (pl. `http://localhost:3000`). A `prompts` lekérése CSAK `includePrompts:true` esetén (a default
33
+ * OFF — fölösleges hálózati kör elkerülése). Worker-down / nem-2xx / nem-JSON → `FAM-IMP-SOURCE-001`.
34
+ */
35
+ async read(set) {
36
+ if (!set.baseUrl || !set.baseUrl.trim().length) {
37
+ throw fam_error_factory_util_1.FAM_Error_Util.create({
38
+ errorCode: error_codes_const_1.FAM_ERROR_CODES.impSource,
39
+ message: 'A worker-api importhoz `path` (a worker base-URL) kötelező, pl. `http://localhost:3000`.',
40
+ issuer: this.issuer,
41
+ context: { operation: 'import-read-worker-api' },
42
+ });
43
+ }
44
+ const base = set.baseUrl.replace(/\/+$/, '');
45
+ const observations = await this.fetchArray(`${base}/api/observations`);
46
+ const summaries = await this.fetchArray(`${base}/api/summaries`);
47
+ const sessions = await this.fetchArray(`${base}/api/sessions`);
48
+ const prompts = set.includePrompts
49
+ ? await this.fetchArray(`${base}/api/prompts`)
50
+ : [];
51
+ return fam_claude_mem_normalize_util_1.FAM_ClaudeMemNormalize_Util.normalizeAll({
52
+ from: fam_claude_mem_source_type_enum_1.FAM_ClaudeMemSource_Type.workerApi,
53
+ observations: observations, summaries: summaries, prompts: prompts, sessions: sessions,
54
+ includePrompts: set.includePrompts,
55
+ });
56
+ }
57
+ /**
58
+ * Egy worker-végpont GET-je timeout-tal, a választ tömbre normalizálva. A worker `{ data: [...] }`
59
+ * vagy nyers `[...]` formát is adhat — mindkettőt kezeljük. Worker-down (abort/timeout) / nem-2xx /
60
+ * nem-JSON → `FAM-IMP-SOURCE-001` (deskriptív, NEM hang).
61
+ */
62
+ async fetchArray(url) {
63
+ const controller = new AbortController();
64
+ const timer = setTimeout(() => controller.abort(), WORKER_API_TIMEOUT_MS);
65
+ try {
66
+ const response = await fetch(url, { method: 'GET', signal: controller.signal });
67
+ if (!response.ok) {
68
+ throw fam_error_factory_util_1.FAM_Error_Util.create({
69
+ errorCode: error_codes_const_1.FAM_ERROR_CODES.impSource,
70
+ message: `A claude-mem worker-api nem-2xx választ adott (HTTP ${response.status}): '${url}'. `
71
+ + 'Fut a worker? (a worker-api út opcionális — használd a `export-json` forrást.)',
72
+ issuer: this.issuer,
73
+ context: { operation: 'import-read-worker-api' },
74
+ });
75
+ }
76
+ const parsed = await response.json();
77
+ return this.unwrapArray(parsed);
78
+ }
79
+ catch (error) {
80
+ if (error && typeof error === 'object' && 'errorCode' in error) {
81
+ throw error;
82
+ }
83
+ throw fam_error_factory_util_1.FAM_Error_Util.create({
84
+ errorCode: error_codes_const_1.FAM_ERROR_CODES.impSource,
85
+ message: `A claude-mem worker-api elérhetetlen (timeout/abort/hálózati hiba): '${url}'. `
86
+ + 'A worker valószínűleg nem fut — használd a `export-json` (default) forrást.',
87
+ issuer: this.issuer,
88
+ context: { operation: 'import-read-worker-api' },
89
+ cause: error,
90
+ });
91
+ }
92
+ finally {
93
+ clearTimeout(timer);
94
+ }
95
+ }
96
+ /** A worker-válasz tömbre fejtése: nyers `[...]` VAGY `{ data: [...] }` VAGY `{ <kulcs>: [...] }`. */
97
+ unwrapArray(parsed) {
98
+ if (Array.isArray(parsed)) {
99
+ return parsed;
100
+ }
101
+ if (parsed && typeof parsed === 'object') {
102
+ const container = parsed;
103
+ if (Array.isArray(container.data)) {
104
+ return container.data;
105
+ }
106
+ for (const value of Object.values(container)) {
107
+ if (Array.isArray(value)) {
108
+ return value;
109
+ }
110
+ }
111
+ }
112
+ return [];
113
+ }
114
+ }
115
+ exports.FAM_ClaudeMemWorkerReader_Service = FAM_ClaudeMemWorkerReader_Service;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FAM_ImportDedup_DataService = void 0;
4
+ const embedding_1 = require("../../embedding");
5
+ const fam_target_mapping_util_1 = require("../_collections/fam-target-mapping.util");
6
+ /**
7
+ * `FAM_ImportDedup_DataService` (SP-11.2, dsgn-009 §3) — a claude-mem import **idempotens 3-lépcsős
8
+ * dedup** lookup-ja. Statikus-szerű service (singleton); a `FAM_Entry_DataService`-en át kérdezi a
9
+ * cél-tárakat. **NEM tartunk élő DataService mezőt** (memory: dynts_dataservice_eager_resolve) —
10
+ * minden lookup előtt lazy `new FAM_Entry_DataService`.
11
+ *
12
+ * A 3 lépcső EGYMÁS UTÁN (dsgn-009 §3):
13
+ * 1. ELSŐDLEGES kulcs: `(importSource='claude-mem', importSourceId)` egyezés → SKIP-existing.
14
+ * 2. ha nincs id-egyezés: `contentHash` a cél-táron → egyezés → SKIP-duplicate-content.
15
+ * 3. ha még mindig nincs: KÜLÖN tartalom-ekvivalencia fallback — `sdk_session_id + title +
16
+ * created_at_epoch` kompozit → egyezés → SKIP-duplicate-content. A kompozit NEM
17
+ * `importSourceId`-alternatíva, csak ez a (3) lépcső.
18
+ *
19
+ * **BFR-AM-006 workaround:** a generic `DataService.compareData()` még nincs bedrock-szinten — ez a
20
+ * FAM-lokális helper. Kódolva úgy, hogy a bedrock `compareData()` landolásakor a lookup-belső
21
+ * cserélhető legyen, a `verdictFor` szerződés változatlanul.
22
+ */
23
+ class FAM_ImportDedup_DataService {
24
+ static _instance;
25
+ /** A claude-mem import-forrás jelölője (a `importSource` mezőhöz; dsgn-009 §3). */
26
+ static IMPORT_SOURCE = 'claude-mem';
27
+ /** Default issuer a dedup-lookup-okhoz. */
28
+ issuer = 'FAM_ImportDedup_DataService';
29
+ static getInstance() {
30
+ if (!FAM_ImportDedup_DataService._instance) {
31
+ FAM_ImportDedup_DataService._instance = new FAM_ImportDedup_DataService();
32
+ }
33
+ return FAM_ImportDedup_DataService._instance;
34
+ }
35
+ /**
36
+ * A 3-lépcsős dedup-verdikt egy rekordra a cél-táron (dsgn-009 §3). A lépcsők EGYMÁS UTÁN
37
+ * értékelődnek; az első egyezés dönt. `import` → új (nincs egyezés); `skip-existing` → (1)
38
+ * importSourceId; `skip-duplicate-content` → (2) contentHash VAGY (3) fallback-kompozit.
39
+ */
40
+ async verdictFor(set) {
41
+ const dataService = this.dataServiceFor(set.table);
42
+ if (!dataService) {
43
+ // Nem-vektorizált / ismeretlen tár → nincs mivel dedup-olni: kezeljük új-ként (a mapping
44
+ // a 6 fő tár egyikére old fel, ez gyakorlatilag nem fordul elő — defenzív ág).
45
+ return 'import';
46
+ }
47
+ // (1) ELSŐDLEGES kulcs: importSource + importSourceId.
48
+ const byId = await dataService.findHydratableList({
49
+ importSource: FAM_ImportDedup_DataService.IMPORT_SOURCE,
50
+ importSourceId: set.importSourceId,
51
+ });
52
+ if (byId.length) {
53
+ return 'skip-existing';
54
+ }
55
+ // (2) contentHash a cél-táron (a claude-mem import-forrásra szűkítve a fals-pozitív ellen).
56
+ const byHash = await dataService.findHydratableList({
57
+ importSource: FAM_ImportDedup_DataService.IMPORT_SOURCE,
58
+ contentHash: set.contentHash,
59
+ });
60
+ if (byHash.length) {
61
+ return 'skip-duplicate-content';
62
+ }
63
+ // (3) KÜLÖN fallback: sdk_session_id + title + created_at_epoch kompozit (claude-mem natív
64
+ // observation-dedup). Csak akkor, ha mindhárom kulcs-tag jelen van (egyébként a kompozit
65
+ // megbízhatatlan — nincs fallback-egyezés, a rekord új).
66
+ if (this.hasCompositeKey(set.record)) {
67
+ const byComposite = await dataService.findHydratableList(this.compositeFilter(set.record));
68
+ if (byComposite.length) {
69
+ return 'skip-duplicate-content';
70
+ }
71
+ }
72
+ return 'import';
73
+ }
74
+ /** A (3) fallback kompozit-kulcs jelenléte: sdk_session_id + title + created_at_epoch mind kell. */
75
+ hasCompositeKey(record) {
76
+ return Boolean(record.sdkSessionId && record.title && typeof record.createdAtEpoch === 'number');
77
+ }
78
+ /**
79
+ * A (3) fallback content-ekvivalencia szűrő. A claude-mem natív `sdk_session_id + title +
80
+ * created_at_epoch` kompozit a FORRÁS-natív observation-dedup kulcsa — ugyanaz a session+cím+idő
81
+ * páros ugyanazt a tartalmat jelöli. A FAM-oldalon a tartalom-ekvivalenciát a TELJES vektorizált
82
+ * `content` exact-egyezésével érvényesítjük (a `composeContent` a title-lel KEZD, a join determinista),
83
+ * a claude-mem import-forrásra szűkítve. Így a kompozit-egyezés (azonos session-tartalom más row-id
84
+ * alatt) a content-azonosságon át kiderül — type-tiszta, `$regex` nélkül.
85
+ */
86
+ compositeFilter(record) {
87
+ const filter = {
88
+ importSource: FAM_ImportDedup_DataService.IMPORT_SOURCE,
89
+ content: fam_target_mapping_util_1.FAM_TargetMapping_Util.composeContent(record),
90
+ };
91
+ return filter;
92
+ }
93
+ /** Lazy `FAM_Entry_DataService` a tárhoz (a 6 fő tár); nem-vektorizált tár → undefined. */
94
+ dataServiceFor(table) {
95
+ const registryEntry = embedding_1.FAM_StoreRegistry_Util.getEntry(table);
96
+ if (!registryEntry) {
97
+ return undefined;
98
+ }
99
+ return new embedding_1.FAM_Entry_DataService({ dataParams: registryEntry.dataParams, issuer: this.issuer });
100
+ }
101
+ }
102
+ exports.FAM_ImportDedup_DataService = FAM_ImportDedup_DataService;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ /**
3
+ * `migration` modul barrel (MP-11, dsgn-009) — a claude-mem → FAM **egyirányú** migrációs engine
4
+ * publikus felülete. A fogyasztó-MP-k innen importálnak: a MP-6 `write.operation=import` thin-wrapper
5
+ * + a 5 import/migration capability (`preview_claude_mem_import` / `map_claude_mem_entries` /
6
+ * `import_claude_mem` / `run_import` / `rollback_import`), valamint a MP-9 `fam import claude-mem` CLI
7
+ * (downstream FOGYASZTÓ — vékony wrapper, NEM duplikál logikát).
8
+ *
9
+ * Boundary (dsgn-009 §7 HARD egyirányúság): NINCS reverse/export-adapter (FDP→claude-mem); az
10
+ * `importSource`/`importSourceId` csak provenance (audit/dedup). A SQLite-reader IZOLÁLT build-only
11
+ * függőség (BFR-AM-009 fallback) — a bedrock-reader landolásakor (MP-15) CSAK a reader-impl cserélődik.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.FAM_ClaudeMemEntity_Type = exports.FAM_ClaudeMemSource_Type = exports.FAM_ImportContentHash_Util = exports.FAM_TargetMapping_Util = exports.FAM_ImportDedup_DataService = exports.FAM_ClaudeMemNormalize_Util = exports.FAM_ClaudeMemWorkerReader_Service = exports.FAM_ClaudeMemSqliteReader_Service = exports.FAM_ClaudeMemExportReader_Service = exports.FAM_ClaudeMemImport_ControlService = void 0;
15
+ // SP-11.3 — a migrációs engine (preview → map → run → rollback)
16
+ var fam_claude_mem_import_control_service_1 = require("./_services/fam-claude-mem-import.control-service");
17
+ Object.defineProperty(exports, "FAM_ClaudeMemImport_ControlService", { enumerable: true, get: function () { return fam_claude_mem_import_control_service_1.FAM_ClaudeMemImport_ControlService; } });
18
+ // SP-11.1 — forrás-readerek (export-JSON default / SQLite build-only / live worker-api)
19
+ var fam_claude_mem_export_reader_service_1 = require("./_services/fam-claude-mem-export-reader.service");
20
+ Object.defineProperty(exports, "FAM_ClaudeMemExportReader_Service", { enumerable: true, get: function () { return fam_claude_mem_export_reader_service_1.FAM_ClaudeMemExportReader_Service; } });
21
+ var fam_claude_mem_sqlite_reader_service_1 = require("./_services/fam-claude-mem-sqlite-reader.service");
22
+ Object.defineProperty(exports, "FAM_ClaudeMemSqliteReader_Service", { enumerable: true, get: function () { return fam_claude_mem_sqlite_reader_service_1.FAM_ClaudeMemSqliteReader_Service; } });
23
+ var fam_claude_mem_worker_reader_service_1 = require("./_services/fam-claude-mem-worker-reader.service");
24
+ Object.defineProperty(exports, "FAM_ClaudeMemWorkerReader_Service", { enumerable: true, get: function () { return fam_claude_mem_worker_reader_service_1.FAM_ClaudeMemWorkerReader_Service; } });
25
+ var fam_claude_mem_normalize_util_1 = require("./_collections/fam-claude-mem-normalize.util");
26
+ Object.defineProperty(exports, "FAM_ClaudeMemNormalize_Util", { enumerable: true, get: function () { return fam_claude_mem_normalize_util_1.FAM_ClaudeMemNormalize_Util; } });
27
+ // SP-11.2 — dedup + target-mapping + content-hash
28
+ var fam_import_dedup_data_service_1 = require("./_services/fam-import-dedup.data-service");
29
+ Object.defineProperty(exports, "FAM_ImportDedup_DataService", { enumerable: true, get: function () { return fam_import_dedup_data_service_1.FAM_ImportDedup_DataService; } });
30
+ var fam_target_mapping_util_1 = require("./_collections/fam-target-mapping.util");
31
+ Object.defineProperty(exports, "FAM_TargetMapping_Util", { enumerable: true, get: function () { return fam_target_mapping_util_1.FAM_TargetMapping_Util; } });
32
+ var fam_import_content_hash_util_1 = require("./_collections/fam-import-content-hash.util");
33
+ Object.defineProperty(exports, "FAM_ImportContentHash_Util", { enumerable: true, get: function () { return fam_import_content_hash_util_1.FAM_ImportContentHash_Util; } });
34
+ // enums + shared vokabulár (a MP-6 wiring + a CLI fogyasztja)
35
+ var fam_claude_mem_source_type_enum_1 = require("./_enums/fam-claude-mem-source.type-enum");
36
+ Object.defineProperty(exports, "FAM_ClaudeMemSource_Type", { enumerable: true, get: function () { return fam_claude_mem_source_type_enum_1.FAM_ClaudeMemSource_Type; } });
37
+ var fam_claude_mem_interface_1 = require("./_models/interfaces/fam-claude-mem.interface");
38
+ Object.defineProperty(exports, "FAM_ClaudeMemEntity_Type", { enumerable: true, get: function () { return fam_claude_mem_interface_1.FAM_ClaudeMemEntity_Type; } });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FAM_RetrievalCandidate_DataService = void 0;
4
+ const fam_table_type_enum_1 = require("../../../_enums/fam-table.type-enum");
5
+ const embedding_1 = require("../../embedding");
6
+ /**
7
+ * `FAM_RetrievalCandidate_DataService` (SP-5.1) — a read-pipeline ① scope + ② tag/kind **Mongo-szintű
8
+ * prefilter**-e: a vektor-keresés ELŐTT (dsgn-005 §2.1/§2.2) szűkíti a jelölt-halmazt egy tárra.
9
+ *
10
+ * A `FAM_Entry_DataService`-t (MP-2) használja a per-tár `dataParams`-szal (a registry-ből), így a 6
11
+ * fő tár mindegyikére a közös `FAM_Entry` bázis-mezőkre szűr. A `findDataList` (a `DyNTS_DataService`
12
+ * alap-query-je) az aktív (nem soft-delete-elt) rekordokat adja — a `_deleted` guard így beépített.
13
+ * A `rules.isActive:false` szabály (dsgn-001 §4) explicit kizárásra kerül (a `findDataList` filterén).
14
+ *
15
+ * **A prefilter bizonyíthatóan a vektor-keresés ELŐTT szűkít (acceptance dsgn-005 §9.3):** a candidate-ID
16
+ * halmazt adja a `FAM_VectorSearch_ControlService.search({ candidateIds })`-nek (prefilter→vektor,
17
+ * dsgn-006 §4.3), így a koszinusz csak a szűkített halmazon fut.
18
+ *
19
+ * **FIGYELEM (memory: dynts_dataservice_eager_resolve):** NEM tartunk élő DataService mezőt; minden
20
+ * művelet előtt lazy `new FAM_Entry_DataService`.
21
+ */
22
+ class FAM_RetrievalCandidate_DataService {
23
+ issuer = 'FAM_RetrievalCandidate_DataService';
24
+ /**
25
+ * A prefilter-feltételeknek megfelelő jelölt-entry-k egy tárból (dsgn-005 §2.1/§2.2). A
26
+ * `findDataList` az AKTÍV (nem-`_deleted`) rekordokat adja; a `rules` táron az `isActive:true`
27
+ * szűrés is rákerül. A scope subtree (`scopePath.scopeId $in scopeIdSet`), a tag (OR, `tags $in`)
28
+ * és a kind a Mongo-filterben. Nem-vektorizált / ismeretlen tár → üres lista (a registry dönt).
29
+ */
30
+ async loadCandidates(input) {
31
+ const registryEntry = embedding_1.FAM_StoreRegistry_Util.getEntry(input.table);
32
+ if (!registryEntry) {
33
+ return [];
34
+ }
35
+ const filter = this.buildFilter(input, registryEntry);
36
+ const dataService = new embedding_1.FAM_Entry_DataService({ dataParams: registryEntry.dataParams, issuer: this.issuer });
37
+ return dataService.findDataList(filter);
38
+ }
39
+ /**
40
+ * A Mongo-prefilter összeállítása (dsgn-005 §2.1/§2.2). A `scopePath.scopeId $in scopeIdSet`
41
+ * subtree-szemantika (a `scopeIdSet` MÁR a subtree-uniót tartalmazza, MP-3 `expandForRead`); a
42
+ * `tags $in tagFilter` OR-szemantika; a `kind` egyezés; a `rules` táron `isActive:true`. A
43
+ * `_deleted`-kizárás a `findDataList` alap-konvenciójában (aktív-only) van.
44
+ */
45
+ buildFilter(input, registryEntry) {
46
+ const filter = {};
47
+ // ① scope-prefilter (subtree scopeId-halmaz). null → nincs scope-szűrés (teljes tár).
48
+ if (input.scopeIdSet) {
49
+ // A scopePath denormalizált scope-ref tömb; a scopeId-ra szűrünk (dot-path a Mixed tömbön).
50
+ filter['scopePath.scopeId'] = { $in: input.scopeIdSet };
51
+ }
52
+ // ② tag-prefilter (OR a tagek között): bármely tag-match bekerül.
53
+ if (input.tagFilter && input.tagFilter.length) {
54
+ filter.tags = { $in: input.tagFilter };
55
+ }
56
+ // ② kind-prefilter (egyetlen kind).
57
+ if (input.kindFilter) {
58
+ filter.kind = input.kindFilter;
59
+ }
60
+ // Soft-delete/aktív guard a `rules` táron (dsgn-001 §4): inaktív szabály SOHA nem jelölt.
61
+ if (registryEntry.table === fam_table_type_enum_1.FAM_Table.rules) {
62
+ filter.isActive = true;
63
+ }
64
+ return filter;
65
+ }
66
+ }
67
+ exports.FAM_RetrievalCandidate_DataService = FAM_RetrievalCandidate_DataService;
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FAM_RetrievalSuggestions_Util = void 0;
4
+ /** A scope-javaslat domináns-küszöbe (>50% a relevantSet-ben; dsgn-005 §4.4). */
5
+ const SCOPE_DOMINANCE_RATIO = 0.5;
6
+ /** A tag-javaslat előfordulási küszöbe (>40% a relevantSet-ben; dsgn-005 §4.4). */
7
+ const TAG_FREQUENCY_RATIO = 0.4;
8
+ /**
9
+ * `FAM_RetrievalSuggestions_Util` (SP-5.3, dsgn-005 §4.4) — a **konkrét, gépelhető** szűkítési
10
+ * javaslatok generátora a `relevantSet` valós statisztikáiból + a query tényleges paramétereiből.
11
+ * Statikus util (nincs függőség). A javaslatok rendezettek: scope → tag → minScore → topK → kind.
12
+ *
13
+ * Üres `relevantSet` → üres javaslat-lista (dsgn-005 §4.4 vége). Minden javaslat-típus külön
14
+ * feltételhez kötött (graceful: a hiányzó statisztikájú javaslat KIMARAD, nem hiba — dsgn-005 §kockázat).
15
+ */
16
+ class FAM_RetrievalSuggestions_Util {
17
+ /**
18
+ * A teljes, rendezett javaslat-lista (dsgn-005 §4.4). A sorrend kötött (scope → tag → minScore →
19
+ * topK → kind). Üres relevantSet → `[]`. A scope/tag/kind a relevantSet eloszlásából; a minScore a
20
+ * returnedHits-határ és az első levágott elem közti érték; a topK a teljes releváns halmazhoz.
21
+ */
22
+ static generate(input) {
23
+ if (!input.relevantSet.length) {
24
+ return [];
25
+ }
26
+ const suggestions = [];
27
+ const scopeSuggestion = FAM_RetrievalSuggestions_Util.scopeSuggestion(input);
28
+ if (scopeSuggestion) {
29
+ suggestions.push(scopeSuggestion);
30
+ }
31
+ const tagSuggestion = FAM_RetrievalSuggestions_Util.tagSuggestion(input);
32
+ if (tagSuggestion) {
33
+ suggestions.push(tagSuggestion);
34
+ }
35
+ const minScoreSuggestion = FAM_RetrievalSuggestions_Util.minScoreSuggestion(input);
36
+ if (minScoreSuggestion) {
37
+ suggestions.push(minScoreSuggestion);
38
+ }
39
+ const topKSuggestion = FAM_RetrievalSuggestions_Util.topKSuggestion(input);
40
+ if (topKSuggestion) {
41
+ suggestions.push(topKSuggestion);
42
+ }
43
+ const kindSuggestion = FAM_RetrievalSuggestions_Util.kindSuggestion(input);
44
+ if (kindSuggestion) {
45
+ suggestions.push(kindSuggestion);
46
+ }
47
+ return suggestions;
48
+ }
49
+ /**
50
+ * Scope-javaslat (dsgn-005 §4.4 #1): csak ha a query NEM adott scope-filtert ÉS a relevantSet-ben
51
+ * van domináns mélyebb (a legmélyebb layer) scope-entitás (>50%). A javaslat a domináns scope
52
+ * canonical nevét + layerét + arányt írja ki.
53
+ */
54
+ static scopeSuggestion(input) {
55
+ // Csak ha a query nem adott scope-filtert (a már-szűkítettet nem javasoljuk újra).
56
+ if (input.query.scopeFilter && input.query.scopeFilter.length) {
57
+ return undefined;
58
+ }
59
+ // A legmélyebb layer scope-entitás-eloszlása a relevantSet hit-jeiben (a leaf a legspecifikusabb).
60
+ const countByScope = new Map();
61
+ for (const hit of input.relevantSet) {
62
+ if (!hit.scopePath.length) {
63
+ continue;
64
+ }
65
+ const leaf = hit.scopePath[hit.scopePath.length - 1];
66
+ const key = leaf.scopeId;
67
+ const existing = countByScope.get(key);
68
+ if (existing) {
69
+ existing.count++;
70
+ }
71
+ else {
72
+ countByScope.set(key, { layer: leaf.layer, canonicalName: leaf.canonicalName, count: 1 });
73
+ }
74
+ }
75
+ let dominant = undefined;
76
+ for (const entry of countByScope.values()) {
77
+ if (!dominant || entry.count > dominant.count) {
78
+ dominant = entry;
79
+ }
80
+ }
81
+ if (!dominant) {
82
+ return undefined;
83
+ }
84
+ const ratio = dominant.count / input.relevantSet.length;
85
+ if (ratio <= SCOPE_DOMINANCE_RATIO) {
86
+ return undefined;
87
+ }
88
+ const percent = Math.round(ratio * 100);
89
+ return `szűkíts scope-ra: ${dominant.layer}=${dominant.canonicalName} (a találatok ${percent}%-a ehhez tartozik)`;
90
+ }
91
+ /**
92
+ * Tag-javaslat (dsgn-005 §4.4 #2): a relevantSet leggyakoribb, a `tagFilter`-ben még nem szereplő
93
+ * tagje (>40% előfordulás). A már aktív tag-filtereket kizárjuk.
94
+ */
95
+ static tagSuggestion(input) {
96
+ const activeTags = new Set(input.query.tagFilter ?? []);
97
+ const countByTag = new Map();
98
+ for (const hit of input.relevantSet) {
99
+ for (const tag of hit.tags) {
100
+ if (activeTags.has(tag)) {
101
+ continue;
102
+ }
103
+ countByTag.set(tag, (countByTag.get(tag) ?? 0) + 1);
104
+ }
105
+ }
106
+ let bestTag = undefined;
107
+ let bestCount = 0;
108
+ for (const [tag, count] of countByTag.entries()) {
109
+ if (count > bestCount) {
110
+ bestTag = tag;
111
+ bestCount = count;
112
+ }
113
+ }
114
+ if (!bestTag) {
115
+ return undefined;
116
+ }
117
+ const ratio = bestCount / input.relevantSet.length;
118
+ if (ratio <= TAG_FREQUENCY_RATIO) {
119
+ return undefined;
120
+ }
121
+ const percent = Math.round(ratio * 100);
122
+ return `adj tagFilter-t: ['${bestTag}'] (a releváns találatok ${percent}%-án jelen van)`;
123
+ }
124
+ /**
125
+ * minScore-javaslat (dsgn-005 §4.4 #3): a returnedHits utolsó eleme és a (topK+1.) levágott elem
126
+ * `finalScore`-jának számtani közepe (2 tizedes) + a becsült megmaradó találat-szám. Csak akkor,
127
+ * ha van levágott elem (topK+1 létezik).
128
+ */
129
+ static minScoreSuggestion(input) {
130
+ if (input.relevantSet.length <= input.effectiveTopK) {
131
+ return undefined;
132
+ }
133
+ const lastReturned = input.relevantSet[input.effectiveTopK - 1];
134
+ const firstCut = input.relevantSet[input.effectiveTopK];
135
+ const suggested = Math.round(((lastReturned.finalScore + firstCut.finalScore) / 2) * 100) / 100;
136
+ // A becsült megmaradó: hány relevantSet-elem finalScore-ja >= a javasolt küszöb.
137
+ const remaining = input.relevantSet.filter((hit) => hit.finalScore >= suggested).length;
138
+ const current = input.query.minScore ?? 0;
139
+ return `emeld a minScore-t ${suggested.toFixed(2)}-re (jelenleg ${current}; ez ~${remaining} találatra szűkít)`;
140
+ }
141
+ /**
142
+ * topK-javaslat (dsgn-005 §4.4 #4): csak `truncated:true`-nál; javasolt érték
143
+ * `min(totalRelevant, MAX_PAGE_SIZE)`, a teljes releváns halmazért.
144
+ */
145
+ static topKSuggestion(input) {
146
+ if (!input.truncated) {
147
+ return undefined;
148
+ }
149
+ const totalRelevant = input.relevantSet.length;
150
+ const suggested = Math.min(totalRelevant, input.maxPageSize);
151
+ return `emeld a topK-t ${suggested}-re a teljes releváns halmazért (totalRelevant=${totalRelevant})`;
152
+ }
153
+ /**
154
+ * kindFilter-javaslat (dsgn-005 §4.4 #5): csak ha a relevantSet ≥2 különböző `kind`-ot tartalmaz
155
+ * ÉS nincs aktív `kindFilter`. A javaslat a leggyakoribb kind-ot ajánlja.
156
+ */
157
+ static kindSuggestion(input) {
158
+ if (input.query.kindFilter) {
159
+ return undefined;
160
+ }
161
+ const countByKind = new Map();
162
+ for (const hit of input.relevantSet) {
163
+ if (!hit.kind) {
164
+ continue;
165
+ }
166
+ countByKind.set(hit.kind, (countByKind.get(hit.kind) ?? 0) + 1);
167
+ }
168
+ if (countByKind.size < 2) {
169
+ return undefined;
170
+ }
171
+ let bestKind = undefined;
172
+ let bestCount = 0;
173
+ for (const [kind, count] of countByKind.entries()) {
174
+ if (count > bestCount) {
175
+ bestKind = kind;
176
+ bestCount = count;
177
+ }
178
+ }
179
+ return `adj kindFilter-t: '${bestKind}' (a releváns találatok kindjai vegyesek)`;
180
+ }
181
+ }
182
+ exports.FAM_RetrievalSuggestions_Util = FAM_RetrievalSuggestions_Util;