@futdevpro/fdp-agent-memory 0.1.0 → 1.1.14

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 (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -7
  3. package/build/package.json +6 -5
  4. package/build/src/_cli/_collections/fam-arg.util.js +48 -0
  5. package/build/src/_cli/_collections/fam-cli.const.js +40 -0
  6. package/build/src/_cli/_collections/fam-output.util.js +86 -0
  7. package/build/src/_cli/_collections/fam-project-discovery.util.js +98 -0
  8. package/build/src/_cli/_commands/capture.command.js +73 -0
  9. package/build/src/_cli/_commands/config.command.js +93 -0
  10. package/build/src/_cli/_commands/doctor.command.js +124 -0
  11. package/build/src/_cli/_commands/errors.command.js +66 -0
  12. package/build/src/_cli/_commands/export.command.js +65 -0
  13. package/build/src/_cli/_commands/find-duplicates.command.js +97 -0
  14. package/build/src/_cli/_commands/import.command.js +136 -0
  15. package/build/src/_cli/_commands/init.command.js +147 -0
  16. package/build/src/_cli/_commands/read.command.js +109 -0
  17. package/build/src/_cli/_commands/scan-projects.command.js +138 -0
  18. package/build/src/_cli/_commands/scan.command.js +98 -0
  19. package/build/src/_cli/_commands/seed.command.js +40 -0
  20. package/build/src/_cli/_commands/serve.command.js +373 -0
  21. package/build/src/_cli/_commands/start.command.js +134 -0
  22. package/build/src/_cli/_commands/stats.command.js +54 -0
  23. package/build/src/_cli/_commands/write.command.js +103 -0
  24. package/build/src/_cli/_models/interfaces/fam-cli-global-options.interface.js +2 -0
  25. package/build/src/_cli/_models/interfaces/fam-cli-output.interface.js +9 -0
  26. package/build/src/_cli/_models/interfaces/fam-client-result.interface.js +2 -0
  27. package/build/src/_cli/_services/fam-client.service.js +140 -0
  28. package/build/src/_cli/register-commands.js +86 -0
  29. package/build/src/_collections/config-catalog.const.js +67 -1
  30. package/build/src/_collections/fam-console.util.js +367 -0
  31. package/build/src/_collections/fam-entry-bootstrap.util.js +158 -4
  32. package/build/src/_collections/fam-error-factory.util.js +0 -9
  33. package/build/src/_collections/fam-mcp-bridge.util.js +49 -0
  34. package/build/src/_collections/fam-reference-code.util.js +105 -0
  35. package/build/src/_collections/fam-version.const.js +10 -0
  36. package/build/src/_models/data-models/fam-entry-base-properties.const.js +1 -0
  37. package/build/src/_models/data-models/fam-entry.data-model.js +6 -0
  38. package/build/src/_models/data-models/fam-ingest-run.data-model.js +3 -1
  39. package/build/src/_models/data-models/fam-reference.data-model.js +7 -0
  40. package/build/src/_modules/capture/_collections/fam-capture.const.js +11 -0
  41. package/build/src/_modules/capture/_services/fam-auto-capture.control-service.js +87 -0
  42. package/build/src/_modules/capture/index.js +8 -0
  43. package/build/src/_modules/embedding/_collections/fam-embedding-prefix.util.js +77 -0
  44. package/build/src/_modules/embedding/_services/fam-duplicate-scan.control-service.js +202 -0
  45. package/build/src/_modules/embedding/_services/fam-embedding-pipeline.control-service.js +33 -9
  46. package/build/src/_modules/embedding/_services/fam-embedding.control-service.js +21 -2
  47. package/build/src/_modules/embedding/_services/fam-entry.data-service.js +135 -0
  48. package/build/src/_modules/embedding/_services/fam-vector-search.control-service.js +42 -32
  49. package/build/src/_modules/embedding/index.js +4 -1
  50. package/build/src/_modules/export/_collections/fam-export.const.js +22 -0
  51. package/build/src/_modules/export/_services/fam-export.control-service.js +64 -0
  52. package/build/src/_modules/export/index.js +8 -0
  53. package/build/src/_modules/ingest/_collections/fam-famignore.util.js +83 -0
  54. package/build/src/_modules/ingest/_collections/fam-file-routing.util.js +59 -48
  55. package/build/src/_modules/ingest/_collections/fam-git-repo.util.js +193 -0
  56. package/build/src/_modules/ingest/_collections/fam-project-identity.util.js +134 -0
  57. package/build/src/_modules/ingest/_collections/fam-scan-progress.util.js +57 -0
  58. package/build/src/_modules/ingest/_collections/fam-scan-summary.util.js +60 -0
  59. package/build/src/_modules/ingest/_collections/fam-scan-weight.util.js +53 -0
  60. package/build/src/_modules/ingest/_collections/fam-secret-exclude.util.js +37 -14
  61. package/build/src/_modules/ingest/_collections/fam-sliding-chunker.util.js +34 -0
  62. package/build/src/_modules/ingest/_collections/fam-ts-chunker.util.js +200 -14
  63. package/build/src/_modules/ingest/_services/fam-delta-compare.util.js +4 -1
  64. package/build/src/_modules/ingest/_services/fam-ingest-run.data-service.js +7 -4
  65. package/build/src/_modules/ingest/_services/fam-ingest.control-service.js +349 -17
  66. package/build/src/_modules/ingest/_services/fam-scan.control-service.js +25 -2
  67. package/build/src/_modules/ingest/index.js +3 -1
  68. package/build/src/_modules/mcp/_collections/fam-active-rules.util.js +56 -0
  69. package/build/src/_modules/mcp/_collections/fam-core-tools.const.js +47 -6
  70. package/build/src/_modules/mcp/_services/fam-capabilities-tool.service.js +4 -4
  71. package/build/src/_modules/mcp/_services/fam-capability-registry.service.js +224 -18
  72. package/build/src/_modules/mcp/_services/fam-mcp-adapter.service.js +4 -4
  73. package/build/src/_modules/mcp/_services/fam-mcp-server.service.js +4 -4
  74. package/build/src/_modules/mcp/_services/fam-read-tool.service.js +53 -1
  75. package/build/src/_modules/mcp/_services/fam-write-tool.service.js +104 -8
  76. package/build/src/_modules/mcp/index.js +4 -4
  77. package/build/src/_modules/migration/_collections/fam-claude-mem-normalize.util.js +66 -3
  78. package/build/src/_modules/migration/_collections/fam-prompt-aggregate.util.js +143 -0
  79. package/build/src/_modules/migration/_collections/fam-target-mapping.util.js +19 -0
  80. package/build/src/_modules/migration/_enums/fam-claude-mem-source.type-enum.js +6 -0
  81. package/build/src/_modules/migration/_models/interfaces/fam-claude-mem.interface.js +5 -0
  82. package/build/src/_modules/migration/_services/fam-agent-memory-reader.service.js +125 -0
  83. package/build/src/_modules/migration/_services/fam-claude-mem-import.control-service.js +101 -18
  84. package/build/src/_modules/migration/_services/fam-import-dedup.data-service.js +53 -0
  85. package/build/src/_modules/migration/index.js +3 -1
  86. package/build/src/_modules/retrieval/_services/fam-retrieval-candidate.data-service.js +78 -4
  87. package/build/src/_modules/retrieval/_services/fam-retrieval.control-service.js +293 -50
  88. package/build/src/_modules/scope-reference/_collections/fam-scope-normalize.util.js +6 -3
  89. package/build/src/_modules/scope-reference/_services/fam-reference.data-service.js +18 -0
  90. package/build/src/_modules/scope-reference/_services/fam-scope-resolver.control-service.js +79 -20
  91. package/build/src/_routes/server/api/api.controller.js +34 -2
  92. package/build/src/_routes/server/client-app/client-app.control-service.js +1 -1
  93. package/build/src/_routes/server/server-status/server-status.controller.js +2 -1
  94. package/build/src/app.server.js +13 -1
  95. package/build/src/environments/environment.js +1 -1
  96. package/build/src/index.js +1 -1
  97. package/client-dist/{chunk-GHKRM4SM.js → chunk-I77GXVAQ.js} +1 -1
  98. package/client-dist/{chunk-LMTL7GA3.js → chunk-YXHWCJ5O.js} +1 -1
  99. package/client-dist/index.html +1 -1
  100. package/client-dist/{main-2KWB3QYK.js → main-PJPEDVJT.js} +1 -1
  101. package/package.json +6 -5
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FAM_ReadTool_Service = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const path = tslib_1.__importStar(require("path"));
6
+ const fsm_dynamo_1 = require("@futdevpro/fsm-dynamo");
4
7
  const fam_table_type_enum_1 = require("../../../_enums/fam-table.type-enum");
5
8
  const error_codes_const_1 = require("../../../_collections/error-codes.const");
6
9
  const fam_error_factory_util_1 = require("../../../_collections/fam-error-factory.util");
@@ -36,7 +39,54 @@ class FAM_ReadTool_Service {
36
39
  async handle(input) {
37
40
  this.validate(input);
38
41
  const request = this.toRetrievalRequest(input);
39
- return retrieval_1.FAM_Retrieval_ControlService.getInstance().read(request);
42
+ const response = await retrieval_1.FAM_Retrieval_ControlService.getInstance().read(request);
43
+ this.rebaseToBasePath(response, input.basePath);
44
+ this.logReadActivity(input, response);
45
+ return response;
46
+ }
47
+ /**
48
+ * Ha a kérés `basePath`-et ad, a hit-ek `sourceFilePath`-ját a KANONIKUS `absolutePath`-ból a `basePath`-hez
49
+ * RELATÍVAN írjuk át (a hívó saját workspace-kontextusa — FAM-REV-050), `/`-normalizálva. `absolutePath` nélküli
50
+ * hit (nem-scan, pl. agent-write) érintetlen. basePath nélkül no-op (a `sourceFilePath` a scan-gyökérhez relatív marad).
51
+ */
52
+ rebaseToBasePath(response, basePath) {
53
+ if (!basePath) {
54
+ return;
55
+ }
56
+ for (const block of response.results ?? []) {
57
+ for (const hit of block.hits ?? []) {
58
+ if (hit.absolutePath) {
59
+ hit.sourceFilePath = path.relative(basePath, hit.absolutePath).replace(/\\/g, '/');
60
+ }
61
+ }
62
+ }
63
+ }
64
+ /**
65
+ * Egy-soros activity-log a read-műveletről (FEAT-001 console). A `[famRead]` prefix konzisztens a
66
+ * `[famIngest]`/`[famImport]` MON-eseményekkel. Diagnosztika — NEM befolyásolja a választ.
67
+ */
68
+ logReadActivity(input, response) {
69
+ let totalHits = 0;
70
+ let topScore = 0;
71
+ for (const block of response.results ?? []) {
72
+ for (const hit of block.hits ?? []) {
73
+ totalHits++;
74
+ const score = hit.finalScore ?? hit.score ?? 0;
75
+ if (score > topScore) {
76
+ topScore = score;
77
+ }
78
+ }
79
+ }
80
+ const tables = Array.from(new Set(input.queries.flatMap((query) => query.tables ?? []))).join(',');
81
+ const firstQuery = FAM_ReadTool_Service.truncate(input.queries[0]?.query ?? '');
82
+ const more = input.queries.length > 1 ? ` (+${input.queries.length - 1} query)` : '';
83
+ const top = totalHits ? `, top ${topScore.toFixed(3)}` : '';
84
+ fsm_dynamo_1.DyFM_Log.info(`[famRead] "${firstQuery}"${more} [${tables}] → ${totalHits} találat${top}`);
85
+ }
86
+ /** Egy keresési phrase rövidítése a log-sorhoz (whitespace-collapse + max 60 karakter). */
87
+ static truncate(text) {
88
+ const clean = text.replace(/\s+/g, ' ').trim();
89
+ return clean.length > 60 ? `${clean.slice(0, 57)}…` : clean;
40
90
  }
41
91
  /**
42
92
  * A `read` input validációja (dsgn-003 §2.1). Üres `queries` / üres `tables` / `reference` a
@@ -93,6 +143,8 @@ class FAM_ReadTool_Service {
93
143
  scopeFilter: query.scopeFilter,
94
144
  tagFilter: query.tagFilter,
95
145
  kindFilter: query.kindFilter,
146
+ excludeIds: query.excludeIds,
147
+ depth: query.depth,
96
148
  };
97
149
  }
98
150
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FAM_WriteTool_Service = void 0;
4
+ const fsm_dynamo_1 = require("@futdevpro/fsm-dynamo");
4
5
  const error_codes_const_1 = require("../../../_collections/error-codes.const");
5
6
  const fam_error_factory_util_1 = require("../../../_collections/fam-error-factory.util");
6
7
  const fam_entry_data_model_1 = require("../../../_models/data-models/fam-entry.data-model");
@@ -42,6 +43,12 @@ class FAM_WriteTool_Service {
42
43
  */
43
44
  async handle(input) {
44
45
  this.validate(input);
46
+ const output = await this.dispatch(input);
47
+ this.logWriteActivity(input, output);
48
+ return output;
49
+ }
50
+ /** Az operation-router (a `handle` validáció + activity-log közé ékelve, dsgn-003 §3). */
51
+ async dispatch(input) {
45
52
  switch (input.operation) {
46
53
  case fam_mcp_interface_1.FAM_WriteOperation.create:
47
54
  return this.handleCreate(input);
@@ -67,6 +74,34 @@ class FAM_WriteTool_Service {
67
74
  });
68
75
  }
69
76
  }
77
+ /**
78
+ * Egy-soros activity-log egy write-műveletről (FEAT-001 console). A `scan-*` a `[famIngest]`, az
79
+ * `import` a `[famImport]` strukturált MON-eseményén logol — itt a create/update/delete/re-embed humán
80
+ * egy-sorosa (`[famWrite]`, konzisztens a többi MON-prefixszel). Diagnosztika — NEM befolyásolja a választ.
81
+ */
82
+ logWriteActivity(input, output) {
83
+ if (input.operation === fam_mcp_interface_1.FAM_WriteOperation.import || output.scan) {
84
+ return;
85
+ }
86
+ let summary;
87
+ if (output.reEmbed) {
88
+ summary = `${output.reEmbed.reembedded}/${output.reEmbed.total} re-embed`;
89
+ }
90
+ else {
91
+ const parts = [];
92
+ if (output.created.length) {
93
+ parts.push(`+${output.created.length}`);
94
+ }
95
+ if (output.updated.length) {
96
+ parts.push(`~${output.updated.length}`);
97
+ }
98
+ if (output.deleted.length) {
99
+ parts.push(`-${output.deleted.length}`);
100
+ }
101
+ summary = parts.length ? parts.join(' ') : '∅';
102
+ }
103
+ fsm_dynamo_1.DyFM_Log.info(`[famWrite] ${input.operation} ${input.table} → ${summary}`);
104
+ }
70
105
  // =========================================================================
71
106
  // Validáció (dsgn-003 §3.1 / §6.3)
72
107
  // =========================================================================
@@ -203,16 +238,26 @@ class FAM_WriteTool_Service {
203
238
  async handleDelete(input) {
204
239
  const registryEntry = this.requireRegistryEntry(input.table, 'write-delete');
205
240
  const dataService = new embedding_1.FAM_Entry_DataService({ dataParams: registryEntry.dataParams, issuer: this.issuer });
206
- const targetEntry = await this.resolveTarget(input, dataService, 'write-delete');
207
- const deletedId = targetEntry._id ?? '';
208
- if (deletedId) {
209
- // absolute=false → soft-delete (a Dynamo-konvenció: a _deleted marker, archív collection).
210
- await dataService.deleteData(deletedId, false);
241
+ // FAM-REV-051 bulk: `sourceFilePath`/`absolutePath` egy fájl ÖSSZES chunkja; `id`/`query` → egyetlen.
242
+ const targets = await this.resolveDeleteTargets(input, dataService, 'write-delete');
243
+ const deletedIds = [];
244
+ for (const entry of targets) {
245
+ if (!entry._id) {
246
+ continue;
247
+ }
248
+ // absolute=false → soft-delete (Dynamo-konvenció: `_deleted` marker, archív collection).
249
+ await dataService.deleteData(entry._id, false);
250
+ // Pool-coherence (FAM-REV-046): a törölt vektort a hívó-process in-memory LVS-pool-jából is kivesszük.
251
+ embedding_1.FAM_VectorSearch_ControlService.getInstance().removeVector(input.table, entry._id);
252
+ deletedIds.push(entry._id);
211
253
  }
254
+ const warnings = deletedIds.length > 1
255
+ ? [`Bulk file-delete: ${deletedIds.length} chunk soft-delete-elve (cél: ${input.target?.by}='${input.target?.value}').`]
256
+ : [];
212
257
  return this.baseOutput({
213
258
  operation: input.operation, table: input.table,
214
- scopePath: (targetEntry.scopePath ?? []),
215
- uncertaintyNotes: [], deleted: deletedId ? [deletedId] : [], warnings: [],
259
+ scopePath: (targets[0]?.scopePath ?? []),
260
+ uncertaintyNotes: [], deleted: deletedIds, warnings: warnings,
216
261
  });
217
262
  }
218
263
  // =========================================================================
@@ -232,6 +277,7 @@ class FAM_WriteTool_Service {
232
277
  include: scan.include,
233
278
  exclude: scan.exclude,
234
279
  dryRun: scan.dryRun,
280
+ weights: scan.weights,
235
281
  issuer: this.issuer,
236
282
  };
237
283
  let summary;
@@ -254,7 +300,7 @@ class FAM_WriteTool_Service {
254
300
  created: [], updated: [], deleted: [], scopePath: summary.scopePath,
255
301
  scan: {
256
302
  filesProcessed: summary.filesProcessed, chunks: summary.chunkCount,
257
- verdicts: summary.verdicts, status: summary.status,
303
+ verdicts: summary.verdicts, status: summary.status, estimate: summary.estimate,
258
304
  },
259
305
  ingestRunId: summary.ingestRunId, uncertaintyNotes: [], warnings: warnings,
260
306
  };
@@ -420,6 +466,56 @@ class FAM_WriteTool_Service {
420
466
  }
421
467
  return matches[0];
422
468
  }
469
+ /**
470
+ * A DELETE cél-entry-k feloldása — BULK (FAM-REV-051). `by:id` → 1 entry; `by:sourceFilePath` /
471
+ * `by:absolutePath` → a fájl ÖSSZES chunkja (egy szkennelt fájl mindig több chunk → így törölhető egy
472
+ * lépésben); `by:query` → a `content`-substring match, de a véletlen tömeges törlés ellen TÖBB-matchnél
473
+ * megtagad (egyértelmű cél kell). Nincs match → `FAM-VAL-WRITE-003`. Az `absolutePath` a kanonikus,
474
+ * scan-root-független azonosító (FAM-REV-050) — ajánlott egész-fájl törléshez.
475
+ */
476
+ async resolveDeleteTargets(input, dataService, operation) {
477
+ const target = input.target;
478
+ if (!target || !target.by || !target.value) {
479
+ throw fam_error_factory_util_1.FAM_Error_Util.create({
480
+ errorCode: error_codes_const_1.FAM_ERROR_CODES.valWriteTargetAmbiguous,
481
+ message: 'A `delete` művelethez `target` kötelező ({ by: id|sourceFilePath|absolutePath|query, value }).',
482
+ issuer: this.issuer,
483
+ context: { operation: operation, table: input.table },
484
+ });
485
+ }
486
+ if (target.by === 'id') {
487
+ const byId = await dataService.findData({ _id: target.value }, true);
488
+ if (!byId || !byId._id) {
489
+ throw this.targetNotFound(input, target, operation);
490
+ }
491
+ return [byId];
492
+ }
493
+ const filter = {};
494
+ if (target.by === 'sourceFilePath') {
495
+ filter.sourceFilePath = target.value;
496
+ }
497
+ else if (target.by === 'absolutePath') {
498
+ filter['source.absolutePath'] = target.value;
499
+ }
500
+ else {
501
+ filter.content = target.value; // query
502
+ }
503
+ const matches = await dataService.findDataList(filter);
504
+ if (!matches.length) {
505
+ throw this.targetNotFound(input, target, operation);
506
+ }
507
+ // `query`-mód: a véletlen tömeges törlés ellen egyértelműséget követelünk (a fájl-módok BULK-ok).
508
+ if (target.by === 'query' && matches.length > 1) {
509
+ throw fam_error_factory_util_1.FAM_Error_Util.create({
510
+ errorCode: error_codes_const_1.FAM_ERROR_CODES.valWriteTargetAmbiguous,
511
+ message: `A 'query'='${target.value}' cél több (${matches.length}) entry-re illeszkedik — `
512
+ + 'pontosíts (`by:id`), vagy egész fájlhoz használj `by:sourceFilePath`/`by:absolutePath`-t (BULK).',
513
+ issuer: this.issuer,
514
+ context: { operation: operation, table: input.table },
515
+ });
516
+ }
517
+ return matches;
518
+ }
423
519
  /** A cél nem található → `FAM-VAL-WRITE-003` (deskriptív). */
424
520
  targetNotFound(input, target, operation) {
425
521
  return fam_error_factory_util_1.FAM_Error_Util.create({
@@ -5,15 +5,15 @@
5
5
  * a REST-réteg (`_routes/server/api`, SP-6.5: a transport-agnosztikus core `FAM_*Tool_Service`-ek a
6
6
  * REST-mirrorhoz), és a contract-tesztek (advertised-tool + diszjunkció).
7
7
  *
8
- * Boundary (dsgn-003 §5, BFR-AM-003): a `FAM_Mcp_Adapter` az EGYETLEN choke-pont a hivatalos
8
+ * Boundary (dsgn-003 §5, BFR-AM-003): a `FAM_Mcp_Adapter_Service` az EGYETLEN choke-pont a hivatalos
9
9
  * `@modelcontextprotocol/sdk` köré — a bedrock `DyNTS_Mcp_*` (MP-15) csere itt non-breaking. A 3
10
10
  * core-tool + a capability-registry transport-agnosztikus (MCP stdio + REST UGYANEZT hívja).
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.FAM_WriteOperation = exports.FAM_CapabilityCategory = exports.FAM_CapabilityRegistry = exports.FAM_CapabilitiesTool_Service = exports.FAM_WriteTool_Service = exports.FAM_ReadTool_Service = exports.FAM_CORE_TOOLS = exports.FAM_McpServer_Service = exports.FAM_Mcp_Adapter = void 0;
13
+ exports.FAM_WriteOperation = exports.FAM_CapabilityCategory = exports.FAM_CapabilityRegistry_Service = exports.FAM_CapabilitiesTool_Service = exports.FAM_WriteTool_Service = exports.FAM_ReadTool_Service = exports.FAM_CORE_TOOLS = exports.FAM_McpServer_Service = exports.FAM_Mcp_Adapter_Service = void 0;
14
14
  // SP-6.1 — MCP infra (adaptor + szerver-orchestrátor)
15
15
  var fam_mcp_adapter_service_1 = require("./_services/fam-mcp-adapter.service");
16
- Object.defineProperty(exports, "FAM_Mcp_Adapter", { enumerable: true, get: function () { return fam_mcp_adapter_service_1.FAM_Mcp_Adapter; } });
16
+ Object.defineProperty(exports, "FAM_Mcp_Adapter_Service", { enumerable: true, get: function () { return fam_mcp_adapter_service_1.FAM_Mcp_Adapter_Service; } });
17
17
  var fam_mcp_server_service_1 = require("./_services/fam-mcp-server.service");
18
18
  Object.defineProperty(exports, "FAM_McpServer_Service", { enumerable: true, get: function () { return fam_mcp_server_service_1.FAM_McpServer_Service; } });
19
19
  var fam_core_tools_const_1 = require("./_collections/fam-core-tools.const");
@@ -28,7 +28,7 @@ Object.defineProperty(exports, "FAM_WriteTool_Service", { enumerable: true, get:
28
28
  var fam_capabilities_tool_service_1 = require("./_services/fam-capabilities-tool.service");
29
29
  Object.defineProperty(exports, "FAM_CapabilitiesTool_Service", { enumerable: true, get: function () { return fam_capabilities_tool_service_1.FAM_CapabilitiesTool_Service; } });
30
30
  var fam_capability_registry_service_1 = require("./_services/fam-capability-registry.service");
31
- Object.defineProperty(exports, "FAM_CapabilityRegistry", { enumerable: true, get: function () { return fam_capability_registry_service_1.FAM_CapabilityRegistry; } });
31
+ Object.defineProperty(exports, "FAM_CapabilityRegistry_Service", { enumerable: true, get: function () { return fam_capability_registry_service_1.FAM_CapabilityRegistry_Service; } });
32
32
  // shared vokabulár (a REST-réteg + a contract-tesztek fogyasztják)
33
33
  var fam_mcp_interface_1 = require("./_models/interfaces/fam-mcp.interface");
34
34
  Object.defineProperty(exports, "FAM_CapabilityCategory", { enumerable: true, get: function () { return fam_mcp_interface_1.FAM_CapabilityCategory; } });
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FAM_ClaudeMemNormalize_Util = void 0;
4
4
  const fam_claude_mem_interface_1 = require("../_models/interfaces/fam-claude-mem.interface");
5
+ const fam_prompt_aggregate_util_1 = require("./fam-prompt-aggregate.util");
5
6
  /**
6
7
  * `FAM_ClaudeMemNormalize_Util` (SP-11.1) — a nyers forrás-rekordokat (observations / summaries /
7
8
  * prompts / sessions) a KÖZÖS `FAM_ClaudeMemRecord` köztes shape-re normalizálja. MINDEN reader
@@ -33,10 +34,13 @@ class FAM_ClaudeMemNormalize_Util {
33
34
  records.push(record);
34
35
  }
35
36
  }
36
- // user_prompts CSAK includePrompts:true esetén (default OFF — dsgn-009 §2 / §9.7).
37
+ // user_prompts CSAK includePrompts:true esetén (default OFF — dsgn-009 §2 / §9.7). L3 §3: a promptokat
38
+ // ELŐBB AGGREGÁLJUK (signature-dedup) — az ismétlődő sablonok (pl. automata-trigger üzenetek) EGY
39
+ // kanonikus bejegyzésbe vonva (+ repeatCount/projects/dateRange metaadat), az egyediek megmaradnak.
37
40
  if (set.includePrompts) {
38
- for (const prompt of set.prompts) {
39
- const record = FAM_ClaudeMemNormalize_Util.normalizePrompt(prompt, warnings);
41
+ const aggregated = fam_prompt_aggregate_util_1.FAM_PromptAggregate_Util.aggregate(set.prompts, set.sessions);
42
+ for (const item of aggregated) {
43
+ const record = FAM_ClaudeMemNormalize_Util.normalizeAggregatedPrompt(item, warnings);
40
44
  if (record) {
41
45
  records.push(record);
42
46
  }
@@ -143,6 +147,65 @@ class FAM_ClaudeMemNormalize_Util {
143
147
  createdAtEpoch: typeof raw.created_at_epoch === 'number' ? raw.created_at_epoch : undefined,
144
148
  };
145
149
  }
150
+ /**
151
+ * Egy AGGREGÁLT prompt-csoport → record (L3 §3). Egyedi prompt (`repeatCount:1`) → normál prompt-record; az
152
+ * ismétlődő sablon (`repeatCount>1`) → EGY kanonikus record + aggregátum-metaadat: a stats a `title`-ben (a
153
+ * `composeContent` bekomponálja → kereshető), az `aggregated-prompt`/`automation-trigger` a `concepts`-ben
154
+ * (→ tag). A content-hash dedup így a kanonikuson dolgozik (nulla duplikáció). A VALÓS sqlite-oszlopokat is
155
+ * olvassa (`prompt_text`/`content_session_id` — a `normalizePrompt` látens drift-fixe is).
156
+ */
157
+ static normalizeAggregatedPrompt(item, warnings) {
158
+ const raw = item.representative;
159
+ const sessionId = FAM_ClaudeMemNormalize_Util.cleanString(raw.claude_session_id ?? raw.content_session_id);
160
+ const promptNumber = typeof raw.prompt_number === 'number' ? raw.prompt_number : undefined;
161
+ const sourceRowId = sessionId !== undefined && promptNumber !== undefined
162
+ ? `${sessionId}:${promptNumber}`
163
+ : FAM_ClaudeMemNormalize_Util.toStringId(raw.id);
164
+ if (!sourceRowId) {
165
+ warnings.push('Egy aggregált user_prompt azonosító nélkül érkezett — kihagyva.');
166
+ return null;
167
+ }
168
+ if (!item.text) {
169
+ warnings.push('Egy aggregált user_prompt szöveg nélkül érkezett — kihagyva.');
170
+ return null;
171
+ }
172
+ const concepts = [];
173
+ let title = undefined;
174
+ if (item.repeatCount > 1) {
175
+ concepts.push('aggregated-prompt');
176
+ if (item.isAutomationTrigger) {
177
+ concepts.push('automation-trigger');
178
+ }
179
+ title = FAM_ClaudeMemNormalize_Util.aggregateTitle(item);
180
+ }
181
+ return {
182
+ entity: fam_claude_mem_interface_1.FAM_ClaudeMemEntity_Type.userPrompt,
183
+ sourceRowId: sourceRowId,
184
+ sdkSessionId: FAM_ClaudeMemNormalize_Util.cleanString(raw.sdk_session_id),
185
+ claudeSessionId: sessionId,
186
+ project: item.projects.length ? item.projects[0] : FAM_ClaudeMemNormalize_Util.cleanString(raw.project),
187
+ promptNumber: promptNumber,
188
+ title: title,
189
+ text: item.text,
190
+ concepts: concepts,
191
+ filesRead: [],
192
+ filesModified: [],
193
+ createdAtEpoch: item.dateRange ? item.dateRange.fromEpoch
194
+ : (typeof raw.created_at_epoch === 'number' ? raw.created_at_epoch : undefined),
195
+ };
196
+ }
197
+ /** Az ismétlődő prompt-sablon ember-olvasható aggregátum-címe (a `composeContent` ezt is bekomponálja). */
198
+ static aggregateTitle(item) {
199
+ const projectPart = item.projects.length
200
+ ? ` · ${item.projects.length} projekt (${item.projects.join(', ')})`
201
+ : '';
202
+ const dayPart = item.dateRange
203
+ ? ` · ${item.distinctDays} nap (${new Date(item.dateRange.fromEpoch).toISOString().slice(0, 10)}…`
204
+ + `${new Date(item.dateRange.toEpoch).toISOString().slice(0, 10)})`
205
+ : '';
206
+ const autoPart = item.isAutomationTrigger ? ' [automata-trigger]' : '';
207
+ return `Ismétlődő prompt-sablon — ${item.repeatCount}×${projectPart}${dayPart}${autoPart}`;
208
+ }
146
209
  /** Egy id (string vagy number) string-re — üres/undefined → ''. */
147
210
  static toStringId(id) {
148
211
  if (id === undefined || id === null) {
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FAM_PromptAggregate_Util = void 0;
4
+ /**
5
+ * `FAM_PromptAggregate_Util` (L3 §3) — a 11 975 claude-mem `user_prompt` **okos dedup-ja** import előtt. A
6
+ * promptokat **normalizált signature** szerint csoportosítja (számok → `#`, lowercase, whitespace-collapse), és:
7
+ * - **n=1** (egyedi, valódi info) → marad;
8
+ * - **ismétlődő sablon (n>1)** → EGY kanonikus bejegyzés + aggregátum-metaadat (`repeatCount`/`projects`/
9
+ * `distinctDays`/`dateRange` + `automation-trigger` jelölés) → **nulla duplikáció, de a minta megőrizve**.
10
+ *
11
+ * A `projects[]` az `sdk_sessions.project`-ből a `content_session_id`-join-on (a `user_prompts`-ban nincs
12
+ * közvetlen project). Determinista (azonos input → azonos output): a csoport-reprezentáns az ELSŐ (read-order)
13
+ * prompt, a projektek/napok rendezettek. Tisztán statikus (nincs DB/async).
14
+ */
15
+ class FAM_PromptAggregate_Util {
16
+ /** E küszöb FELETT egy sablon `automation-trigger` jelölést kap (a genuinely automatizált üzenetek). */
17
+ static AUTOMATION_THRESHOLD = 5;
18
+ /**
19
+ * **Triviális (noise) flow-control promptok** — önmagukban NULLA információ (user-direktíva: „`continue`/
20
+ * `Continue`/`Continue.` stb. kiszűrése"). Ezeket NEM importáljuk (még aggregálva sem): tiszta vezérlő-zaj.
21
+ * A bázis-formák (írásjel/whitespace nélkül, lowercase); az `isTrivialPrompt` strip-eli a körülvevő írásjelet,
22
+ * így a `Continue.` / `go!` / ` ok ` variánsok mind ide esnek.
23
+ */
24
+ static TRIVIAL_PROMPTS = new Set([
25
+ 'continue', 'continue working', 'continue please', 'please continue', 'pls continue',
26
+ 'go', 'go on', 'go ahead', 'keep going', 'carry on', 'proceed', 'proceed please',
27
+ 'next', 'more', 'resume', 'do it', 'do it.', 'continue from where you left off',
28
+ 'yes', 'yep', 'yeah', 'yup', 'ok', 'okay', 'k', 'kk', 'sure', 'y', 'fine',
29
+ 'continue towards the hyper plan', 'continue the hyper plan', 'continue hyperplan',
30
+ ]);
31
+ /**
32
+ * Triviális (noise) flow-control prompt-e (`continue`/`go`/`yes`/`ok`/… írásjel-/whitespace-variánsokkal)?
33
+ * A körülvevő írásjelet (`. ! , ; : -`) + whitespace-et strip-eljük, lowercase + collapse, majd a
34
+ * `TRIVIAL_PROMPTS` bázis-halmaz ellen vetjük. Az ilyen prompt önmagában értéktelen → kihagyjuk az importból.
35
+ */
36
+ static isTrivialPrompt(text) {
37
+ const normalized = text
38
+ .toLowerCase()
39
+ .replace(/[\s.!,;:\-–—]+$/u, '')
40
+ .replace(/^[\s.!,;:\-–—]+/u, '')
41
+ .replace(/\s+/g, ' ')
42
+ .trim();
43
+ return normalized.length > 0 && FAM_PromptAggregate_Util.TRIVIAL_PROMPTS.has(normalized);
44
+ }
45
+ /** A nyers promptok aggregálása signature szerint (a `sessions` a project-join forrása). */
46
+ static aggregate(prompts, sessions) {
47
+ const projectBySession = FAM_PromptAggregate_Util.buildProjectIndex(sessions);
48
+ // Signature → a csoport promptjai (read-order megőrizve a determinisztikus reprezentánshoz).
49
+ const groups = new Map();
50
+ for (const prompt of prompts) {
51
+ const text = FAM_PromptAggregate_Util.promptText(prompt);
52
+ if (!text || FAM_PromptAggregate_Util.isTrivialPrompt(text)) {
53
+ // Üres VAGY triviális (noise) flow-control prompt → kihagyjuk (nem aggregáljuk, nem importáljuk).
54
+ continue;
55
+ }
56
+ const signature = FAM_PromptAggregate_Util.signature(text);
57
+ const bucket = groups.get(signature);
58
+ if (bucket) {
59
+ bucket.push(prompt);
60
+ }
61
+ else {
62
+ groups.set(signature, [prompt]);
63
+ }
64
+ }
65
+ const items = [];
66
+ for (const group of groups.values()) {
67
+ items.push(FAM_PromptAggregate_Util.toAggregated(group, projectBySession));
68
+ }
69
+ return items;
70
+ }
71
+ /**
72
+ * Egy prompt-szöveg normalizált **signature**-je a sablon-egyezéshez: a számok `#`-re (a sorszámozott
73
+ * variánsok — `(1/5)` / `step 3` — egy sablonba essenek), lowercase, és a whitespace egyetlen szóközre.
74
+ */
75
+ static signature(text) {
76
+ return text.toLowerCase().replace(/\d+/g, '#').replace(/\s+/g, ' ').trim();
77
+ }
78
+ /** Egy prompt szövege (`prompt_text` — tényleges sqlite-oszlop — VAGY `text` — export-json). */
79
+ static promptText(prompt) {
80
+ const text = prompt.prompt_text ?? prompt.text;
81
+ return typeof text === 'string' ? text.trim() : '';
82
+ }
83
+ /** A `content_session_id` → `project` index a `sdk_sessions`-ből (a `claude_session_id` fallback). */
84
+ static buildProjectIndex(sessions) {
85
+ const index = new Map();
86
+ for (const session of sessions) {
87
+ const key = session.content_session_id ?? session.claude_session_id;
88
+ const project = typeof session.project === 'string' ? session.project.trim() : undefined;
89
+ if (key && project) {
90
+ index.set(key, project);
91
+ }
92
+ }
93
+ return index;
94
+ }
95
+ /** Egy signature-csoport → aggregált elem (reprezentáns + project/nap/dátum-aggregátum + automata-jelölés). */
96
+ static toAggregated(group, projectBySession) {
97
+ const projects = new Set();
98
+ const days = new Set();
99
+ let fromEpoch = Number.POSITIVE_INFINITY;
100
+ let toEpoch = Number.NEGATIVE_INFINITY;
101
+ for (const prompt of group) {
102
+ const project = FAM_PromptAggregate_Util.promptProject(prompt, projectBySession);
103
+ if (project) {
104
+ projects.add(project);
105
+ }
106
+ const epoch = FAM_PromptAggregate_Util.promptEpoch(prompt);
107
+ if (epoch !== null) {
108
+ fromEpoch = Math.min(fromEpoch, epoch);
109
+ toEpoch = Math.max(toEpoch, epoch);
110
+ days.add(new Date(epoch).toISOString().slice(0, 10));
111
+ }
112
+ }
113
+ return {
114
+ representative: group[0],
115
+ text: FAM_PromptAggregate_Util.promptText(group[0]),
116
+ repeatCount: group.length,
117
+ projects: [...projects].sort(),
118
+ distinctDays: days.size,
119
+ dateRange: toEpoch >= fromEpoch ? { fromEpoch: fromEpoch, toEpoch: toEpoch } : null,
120
+ isAutomationTrigger: group.length >= FAM_PromptAggregate_Util.AUTOMATION_THRESHOLD,
121
+ };
122
+ }
123
+ /** Egy prompt projektje: közvetlen `project`, VAGY a session-join (`content_session_id`/`claude_session_id`). */
124
+ static promptProject(prompt, projectBySession) {
125
+ if (typeof prompt.project === 'string' && prompt.project.trim()) {
126
+ return prompt.project.trim();
127
+ }
128
+ const key = prompt.content_session_id ?? prompt.claude_session_id;
129
+ return key ? projectBySession.get(key) : undefined;
130
+ }
131
+ /** Egy prompt időbélyege epoch-ms-ben (`created_at_epoch`, VAGY `created_at` ISO parse) — vagy `null`. */
132
+ static promptEpoch(prompt) {
133
+ if (typeof prompt.created_at_epoch === 'number' && isFinite(prompt.created_at_epoch)) {
134
+ return prompt.created_at_epoch;
135
+ }
136
+ if (typeof prompt.created_at === 'string') {
137
+ const parsed = Date.parse(prompt.created_at);
138
+ return isFinite(parsed) ? parsed : null;
139
+ }
140
+ return null;
141
+ }
142
+ }
143
+ exports.FAM_PromptAggregate_Util = FAM_PromptAggregate_Util;
@@ -16,10 +16,22 @@ const OBSERVATION_TYPE_DEFAULTS = {
16
16
  discovery: { table: fam_table_type_enum_1.FAM_Table.knowledge, kind: 'knowledge', tags: ['fact', 'discovery'] },
17
17
  change: { table: fam_table_type_enum_1.FAM_Table.memory, kind: 'memory_entry', tags: ['development_history', 'change'] },
18
18
  };
19
+ /**
20
+ * Az **agent-memory** (`.claude/.../memory/*.md`) frontmatter-`type` → cél-leképezése: `reference`→knowledge,
21
+ * `feedback`→**rules** (az agent viselkedési direktívái = aktív szabályok, a read-injekt is innen húz),
22
+ * `project`→memory, `user`→knowledge. Ismeretlen/hiányzó → az entitás-fallback (memory).
23
+ */
24
+ const AGENT_MEMORY_TYPE_DEFAULTS = {
25
+ reference: { table: fam_table_type_enum_1.FAM_Table.knowledge, kind: 'knowledge', tags: ['agent_memory', 'reference'] },
26
+ feedback: { table: fam_table_type_enum_1.FAM_Table.rules, kind: 'rule', tags: ['agent_memory', 'feedback'] },
27
+ project: { table: fam_table_type_enum_1.FAM_Table.memory, kind: 'memory_entry', tags: ['agent_memory', 'project'] },
28
+ user: { table: fam_table_type_enum_1.FAM_Table.knowledge, kind: 'knowledge', tags: ['agent_memory', 'user'] },
29
+ };
19
30
  /** A nem-observation entitások default-leképezése (dsgn-009 §4). */
20
31
  const ENTITY_DEFAULTS = {
21
32
  [fam_claude_mem_interface_1.FAM_ClaudeMemEntity_Type.sessionSummary]: { table: fam_table_type_enum_1.FAM_Table.memory, kind: 'summary', tags: ['session_history'] },
22
33
  [fam_claude_mem_interface_1.FAM_ClaudeMemEntity_Type.userPrompt]: { table: fam_table_type_enum_1.FAM_Table.memory, kind: 'user_prompt', tags: ['temporary_context'] },
34
+ [fam_claude_mem_interface_1.FAM_ClaudeMemEntity_Type.agentMemory]: { table: fam_table_type_enum_1.FAM_Table.memory, kind: 'agent_memory', tags: ['agent_memory'] },
23
35
  };
24
36
  /**
25
37
  * `FAM_TargetMapping_Util` (SP-11.2, dsgn-009 §4) — egy normalizált claude-mem rekord → cél-leképezés
@@ -71,6 +83,13 @@ class FAM_TargetMapping_Util {
71
83
  const type = record.type ?? 'change';
72
84
  return OBSERVATION_TYPE_DEFAULTS[type] ?? OBSERVATION_TYPE_DEFAULTS.change;
73
85
  }
86
+ if (record.entity === fam_claude_mem_interface_1.FAM_ClaudeMemEntity_Type.agentMemory) {
87
+ // Az agent-memory a frontmatter-`type`-ról képződik (reference/feedback/project/user); ismeretlen → memory.
88
+ const type = record.type ?? '';
89
+ return AGENT_MEMORY_TYPE_DEFAULTS[type]
90
+ ?? ENTITY_DEFAULTS[fam_claude_mem_interface_1.FAM_ClaudeMemEntity_Type.agentMemory]
91
+ ?? { table: fam_table_type_enum_1.FAM_Table.memory, kind: 'agent_memory', tags: ['agent_memory'] };
92
+ }
74
93
  return ENTITY_DEFAULTS[record.entity] ?? { table: fam_table_type_enum_1.FAM_Table.memory, kind: 'memory_entry', tags: [] };
75
94
  }
76
95
  /** A base-tag-ek + a concept-tag-ek egyesítése (rendezett dedup, üres kiszűrve). */
@@ -17,4 +17,10 @@ var FAM_ClaudeMemSource_Type;
17
17
  FAM_ClaudeMemSource_Type["sqlite"] = "sqlite";
18
18
  /** Live worker-api (`http://localhost:<port>`) — opcionális, csak ha a worker fut. */
19
19
  FAM_ClaudeMemSource_Type["workerApi"] = "worker-api";
20
+ /**
21
+ * **Agent-memory markdown-mappa** (`.claude/.../memory/*.md`) — az agent (Claude) tartós memóriája.
22
+ * Függőség-mentes (fs + egyszerű frontmatter-parse). UGYANAZ az engine (preview/run/rollback/dedup/embed),
23
+ * mint a claude-mem-en — csak a reader + a target-mapping (frontmatter-`type`→tár) különbözik.
24
+ */
25
+ FAM_ClaudeMemSource_Type["agentMemory"] = "agent-memory";
20
26
  })(FAM_ClaudeMemSource_Type || (exports.FAM_ClaudeMemSource_Type = FAM_ClaudeMemSource_Type = {}));
@@ -23,4 +23,9 @@ var FAM_ClaudeMemEntity_Type;
23
23
  FAM_ClaudeMemEntity_Type["sessionSummary"] = "session_summaries";
24
24
  /** user_prompts — opcionális (`memory`, `kind=user_prompt`); default OFF. */
25
25
  FAM_ClaudeMemEntity_Type["userPrompt"] = "user_prompts";
26
+ /**
27
+ * **agent-memory markdown** (`.claude/.../memory/*.md`) — az agent tartós memória-bejegyzései. A cél-tár a
28
+ * frontmatter-`type`-tól függ (reference→knowledge, feedback→rules, project→memory, user→knowledge).
29
+ */
30
+ FAM_ClaudeMemEntity_Type["agentMemory"] = "agent_memory";
26
31
  })(FAM_ClaudeMemEntity_Type || (exports.FAM_ClaudeMemEntity_Type = FAM_ClaudeMemEntity_Type = {}));