@futdevpro/nts-dynamo 1.15.58 → 1.15.60

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 (85) hide show
  1. package/.dynamo/logs/cicd-pipeline/output.log +1622 -1705
  2. package/.dynamo/logs/cicd-pipeline/status.json +30 -30
  3. package/build/_modules/ai/_modules/document-ai/_collections/dai-code-chunking.util.d.ts.map +1 -1
  4. package/build/_modules/ai/_modules/document-ai/_collections/dai-code-chunking.util.js +2 -2
  5. package/build/_modules/ai/_modules/document-ai/_collections/dai-code-chunking.util.js.map +1 -1
  6. package/build/_modules/ai/_services/ai-embedding-mock.service.d.ts +1 -1
  7. package/build/_modules/ai/_services/ai-embedding-mock.service.d.ts.map +1 -1
  8. package/build/_modules/ai/_services/ai-embedding-mock.service.js.map +1 -1
  9. package/build/_modules/ai/_services/ai-embedding-provider.registry.d.ts.map +1 -1
  10. package/build/_modules/ai/_services/ai-embedding-provider.registry.js.map +1 -1
  11. package/build/_modules/ai/_services/lmstudio-embedding.control-service.d.ts +1 -1
  12. package/build/_modules/ai/_services/lmstudio-embedding.control-service.d.ts.map +1 -1
  13. package/build/_modules/ai/_services/lmstudio-embedding.control-service.js +3 -3
  14. package/build/_modules/ai/_services/lmstudio-embedding.control-service.js.map +1 -1
  15. package/build/_modules/ai/index.d.ts +2 -0
  16. package/build/_modules/ai/index.d.ts.map +1 -1
  17. package/build/_modules/ai/index.js +4 -0
  18. package/build/_modules/ai/index.js.map +1 -1
  19. package/build/_modules/data-readers/_collections/dynts-sqlite-reader.util.d.ts +17 -17
  20. package/build/_modules/data-readers/_collections/dynts-sqlite-reader.util.d.ts.map +1 -1
  21. package/build/_modules/data-readers/_collections/dynts-sqlite-reader.util.js +21 -21
  22. package/build/_modules/data-readers/_collections/dynts-sqlite-reader.util.js.map +1 -1
  23. package/build/_modules/local-vector-search/_models/data-models/lvs-vector-persist.data-model.d.ts +4 -4
  24. package/build/_modules/local-vector-search/_models/data-models/lvs-vector-persist.data-model.d.ts.map +1 -1
  25. package/build/_modules/local-vector-search/_models/data-models/lvs-vector-persist.data-model.js +5 -5
  26. package/build/_modules/local-vector-search/_models/data-models/lvs-vector-persist.data-model.js.map +1 -1
  27. package/build/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.d.ts +4 -4
  28. package/build/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.d.ts.map +1 -1
  29. package/build/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.js +4 -4
  30. package/build/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.js.map +1 -1
  31. package/build/_modules/local-vector-search/_services/lvs-vector-persist.data-service.d.ts +6 -6
  32. package/build/_modules/local-vector-search/_services/lvs-vector-persist.data-service.d.ts.map +1 -1
  33. package/build/_modules/local-vector-search/_services/lvs-vector-persist.data-service.js +5 -5
  34. package/build/_modules/local-vector-search/_services/lvs-vector-persist.data-service.js.map +1 -1
  35. package/build/_modules/mcp/_models/interfaces/dynts-mcp.interface.d.ts +1 -1
  36. package/build/_modules/mcp/_models/interfaces/dynts-mcp.interface.js +1 -1
  37. package/build/_modules/mcp/_services/dynts-mcp-server.service-base.d.ts +4 -4
  38. package/build/_modules/mcp/_services/dynts-mcp-server.service-base.d.ts.map +1 -1
  39. package/build/_modules/mcp/_services/dynts-mcp-server.service-base.js +6 -6
  40. package/build/_modules/mcp/_services/dynts-mcp-server.service-base.js.map +1 -1
  41. package/build/_modules/mcp/_services/dynts-mcp.adapter.d.ts +11 -11
  42. package/build/_modules/mcp/_services/dynts-mcp.adapter.d.ts.map +1 -1
  43. package/build/_modules/mcp/_services/dynts-mcp.adapter.js +16 -11
  44. package/build/_modules/mcp/_services/dynts-mcp.adapter.js.map +1 -1
  45. package/build/_modules/mcp/index.js +1 -1
  46. package/build/_modules/mcp/index.js.map +1 -1
  47. package/build/_modules/scoped-config/_models/data-models/dynts-scoped-config.data-model.d.ts +3 -3
  48. package/build/_modules/scoped-config/_models/data-models/dynts-scoped-config.data-model.d.ts.map +1 -1
  49. package/build/_modules/scoped-config/_models/data-models/dynts-scoped-config.data-model.js +4 -4
  50. package/build/_modules/scoped-config/_models/data-models/dynts-scoped-config.data-model.js.map +1 -1
  51. package/build/_modules/scoped-config/_models/interfaces/dynts-scoped-config.interface.d.ts.map +1 -1
  52. package/build/_modules/scoped-config/_models/interfaces/dynts-scoped-config.interface.js +9 -0
  53. package/build/_modules/scoped-config/_models/interfaces/dynts-scoped-config.interface.js.map +1 -1
  54. package/build/_modules/scoped-config/_services/dynts-scoped-config.control-service.d.ts +3 -3
  55. package/build/_modules/scoped-config/_services/dynts-scoped-config.control-service.d.ts.map +1 -1
  56. package/build/_modules/scoped-config/_services/dynts-scoped-config.control-service.js +1 -1
  57. package/build/_modules/scoped-config/_services/dynts-scoped-config.control-service.js.map +1 -1
  58. package/build/_modules/scoped-config/_services/dynts-scoped-config.data-service.d.ts +7 -7
  59. package/build/_modules/scoped-config/_services/dynts-scoped-config.data-service.d.ts.map +1 -1
  60. package/build/_modules/scoped-config/_services/dynts-scoped-config.data-service.js +2 -2
  61. package/build/_modules/scoped-config/_services/dynts-scoped-config.data-service.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/_modules/ai/_modules/document-ai/_collections/dai-code-chunking.util.ts +39 -7
  64. package/src/_modules/ai/_services/ai-embedding-mock.service.ts +18 -4
  65. package/src/_modules/ai/_services/ai-embedding-provider.registry.ts +4 -0
  66. package/src/_modules/ai/_services/lmstudio-embedding.control-service.ts +26 -5
  67. package/src/_modules/ai/index.ts +5 -0
  68. package/src/_modules/data-readers/_collections/dynts-sqlite-reader.util.spec.ts +145 -130
  69. package/src/_modules/data-readers/_collections/dynts-sqlite-reader.util.ts +131 -120
  70. package/src/_modules/local-vector-search/_models/data-models/lvs-vector-persist.data-model.ts +6 -5
  71. package/src/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.spec.ts +35 -35
  72. package/src/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.ts +9 -5
  73. package/src/_modules/local-vector-search/_services/lvs-vector-persist.data-service.spec.ts +11 -11
  74. package/src/_modules/local-vector-search/_services/lvs-vector-persist.data-service.ts +19 -17
  75. package/src/_modules/mcp/_models/interfaces/dynts-mcp.interface.ts +1 -1
  76. package/src/_modules/mcp/_services/dynts-mcp-server.service-base.spec.ts +123 -114
  77. package/src/_modules/mcp/_services/dynts-mcp-server.service-base.ts +44 -39
  78. package/src/_modules/mcp/_services/dynts-mcp.adapter.ts +114 -103
  79. package/src/_modules/mcp/index.ts +1 -1
  80. package/src/_modules/scoped-config/_models/data-models/dynts-scoped-config.data-model.ts +5 -4
  81. package/src/_modules/scoped-config/_models/interfaces/dynts-scoped-config.interface.ts +0 -2
  82. package/src/_modules/scoped-config/_services/dynts-scoped-config.control-service.spec.ts +19 -13
  83. package/src/_modules/scoped-config/_services/dynts-scoped-config.control-service.ts +37 -21
  84. package/src/_modules/scoped-config/_services/dynts-scoped-config.data-service.spec.ts +11 -6
  85. package/src/_modules/scoped-config/_services/dynts-scoped-config.data-service.ts +17 -14
@@ -3,7 +3,7 @@ import { DyFM_EnvironmentFlag } from '@futdevpro/fsm-dynamo';
3
3
 
4
4
  import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
5
5
  import { DyNTS_GlobalService } from '../../../_services/core/global.service';
6
- import { DyNTS_LVS_VectorPersist_DataModel } from '../_models/data-models/lvs-vector-persist.data-model';
6
+ import { DyNTS_LVS_VectorPersist } from '../_models/data-models/lvs-vector-persist.data-model';
7
7
  import { DyNTS_LVS_VectorPersist_DataService } from './lvs-vector-persist.data-service';
8
8
 
9
9
  /**
@@ -36,7 +36,7 @@ describe('| DyNTS_LVS_VectorPersist_DataService', () => {
36
36
  describe('| constructor', () => {
37
37
 
38
38
  it('| should create the service with a data model', () => {
39
- const data: DyNTS_LVS_VectorPersist_DataModel = new DyNTS_LVS_VectorPersist_DataModel({
39
+ const data: DyNTS_LVS_VectorPersist = new DyNTS_LVS_VectorPersist({
40
40
  collectionKey: 'pool-a',
41
41
  vectorId: 'v1',
42
42
  embedding: [1, 2, 3],
@@ -56,7 +56,7 @@ describe('| DyNTS_LVS_VectorPersist_DataService', () => {
56
56
  new DyNTS_LVS_VectorPersist_DataService({ issuer: 'issuer-123' });
57
57
 
58
58
  expect(service).toBeInstanceOf(DyNTS_LVS_VectorPersist_DataService);
59
- expect(service.data).toBeInstanceOf(DyNTS_LVS_VectorPersist_DataModel);
59
+ expect(service.data).toBeInstanceOf(DyNTS_LVS_VectorPersist);
60
60
  });
61
61
  });
62
62
 
@@ -66,12 +66,12 @@ describe('| DyNTS_LVS_VectorPersist_DataService', () => {
66
66
  const service: DyNTS_LVS_VectorPersist_DataService =
67
67
  new DyNTS_LVS_VectorPersist_DataService({ issuer: 'issuer-123' });
68
68
 
69
- const records: DyNTS_LVS_VectorPersist_DataModel[] = [
70
- new DyNTS_LVS_VectorPersist_DataModel({ collectionKey: 'pool-a', vectorId: 'v1', embedding: [1, 0] }),
69
+ const records: DyNTS_LVS_VectorPersist[] = [
70
+ new DyNTS_LVS_VectorPersist({ collectionKey: 'pool-a', vectorId: 'v1', embedding: [1, 0] }),
71
71
  ];
72
72
  const findSpy = spyOn(service, 'findDataList').and.returnValue(Promise.resolve(records));
73
73
 
74
- const result: DyNTS_LVS_VectorPersist_DataModel[] = await service.findByCollectionKey('pool-a');
74
+ const result: DyNTS_LVS_VectorPersist[] = await service.findByCollectionKey('pool-a');
75
75
 
76
76
  expect(findSpy).toHaveBeenCalledTimes(1);
77
77
  const filterArg = findSpy.calls.mostRecent().args[0] as { collectionKey: string };
@@ -86,7 +86,7 @@ describe('| DyNTS_LVS_VectorPersist_DataService', () => {
86
86
  const service: DyNTS_LVS_VectorPersist_DataService =
87
87
  new DyNTS_LVS_VectorPersist_DataService({ issuer: 'issuer-123' });
88
88
 
89
- const existing: DyNTS_LVS_VectorPersist_DataModel = new DyNTS_LVS_VectorPersist_DataModel({
89
+ const existing: DyNTS_LVS_VectorPersist = new DyNTS_LVS_VectorPersist({
90
90
  collectionKey: 'pool-a', vectorId: 'v1', embedding: [1, 2, 3],
91
91
  });
92
92
  existing._id = 'rec-1';
@@ -118,14 +118,14 @@ describe('| DyNTS_LVS_VectorPersist_DataService', () => {
118
118
  spyOn(service, 'findData').and.returnValue(Promise.resolve(null));
119
119
  const updateSpy = spyOn(service, 'updateData').and.returnValue(Promise.resolve());
120
120
  const saveSpy = spyOn(service, 'saveData')
121
- .and.callFake((data?: DyNTS_LVS_VectorPersist_DataModel) =>
122
- Promise.resolve(data as DyNTS_LVS_VectorPersist_DataModel));
121
+ .and.callFake((data?: DyNTS_LVS_VectorPersist) =>
122
+ Promise.resolve(data as DyNTS_LVS_VectorPersist));
123
123
 
124
124
  await service.upsertVector({ collectionKey: 'pool-a', vectorId: 'v2', embedding: [0.1, 0.2] });
125
125
 
126
126
  expect(updateSpy).not.toHaveBeenCalled();
127
127
  expect(saveSpy).toHaveBeenCalledTimes(1);
128
- const written = saveSpy.calls.mostRecent().args[0] as DyNTS_LVS_VectorPersist_DataModel;
128
+ const written = saveSpy.calls.mostRecent().args[0] as DyNTS_LVS_VectorPersist;
129
129
  expect(written.vectorId).toBe('v2');
130
130
  expect(written.collectionKey).toBe('pool-a');
131
131
  expect(written.embedding).toEqual([0.1, 0.2]);
@@ -139,7 +139,7 @@ describe('| DyNTS_LVS_VectorPersist_DataService', () => {
139
139
  const service: DyNTS_LVS_VectorPersist_DataService =
140
140
  new DyNTS_LVS_VectorPersist_DataService({ issuer: 'issuer-123' });
141
141
 
142
- const existing: DyNTS_LVS_VectorPersist_DataModel = new DyNTS_LVS_VectorPersist_DataModel({
142
+ const existing: DyNTS_LVS_VectorPersist = new DyNTS_LVS_VectorPersist({
143
143
  collectionKey: 'pool-a', vectorId: 'v1', embedding: [1, 0],
144
144
  });
145
145
  existing._id = 'rec-1';
@@ -3,8 +3,8 @@ import { DyFM_DBFilter, DyFM_DBFilterSimple } from '@futdevpro/fsm-dynamo';
3
3
 
4
4
  import { DyNTS_DataService } from '../../../_services/base/data.service';
5
5
  import {
6
- DyNTS_LVS_VectorPersist_DataModel,
7
- dyNTS_lvsVectorPersist_dataParams,
6
+ DyNTS_LVS_VectorPersist,
7
+ DyNTS_lvsVectorPersist_dataParams
8
8
  } from '../_models/data-models/lvs-vector-persist.data-model';
9
9
 
10
10
  /**
@@ -14,36 +14,36 @@ import {
14
14
  *
15
15
  * **FIGYELEM (memory: dynts_dataservice_eager_resolve):** a `DyNTS_DataService` base-ctor EAGER
16
16
  * `getDBService`-t hív → a hívó NEM tarthat élő data-service-példányt mezőként; minden művelet előtt
17
- * lazy `new DyNTS_LVS_VectorPersist_DataService(...)` kell (a `DyNTS_LVS_PersistentVectorPool` így jár el).
17
+ * lazy `new DyNTS_LVS_VectorPersist_DataService(...)` kell (a `DyNTS_LVS_PersistentVectorPool_ControlService` így jár el).
18
18
  *
19
19
  * **Atomikus írás (memory: mongoose_mixed_atomic_write):** az upsert a `(collectionKey, vectorId)`
20
20
  * logikai-kulcson MEGLÉVŐ rekordot `updateOne({...},{$set:{embedding,dimensions,metadata}})`-tel
21
21
  * frissíti (a Mixed `metadata` `findOne→mutate→save` SILENT-DROP-ja ellen); ÚJ rekordot `saveData`-val ír.
22
22
  */
23
- export class DyNTS_LVS_VectorPersist_DataService extends DyNTS_DataService<DyNTS_LVS_VectorPersist_DataModel> {
23
+ export class DyNTS_LVS_VectorPersist_DataService extends DyNTS_DataService<DyNTS_LVS_VectorPersist> {
24
24
 
25
25
  constructor(
26
26
  set: {
27
- data?: DyNTS_LVS_VectorPersist_DataModel,
27
+ data?: DyNTS_LVS_VectorPersist,
28
28
  issuer: string,
29
29
  },
30
30
  ) {
31
31
  super(
32
- set.data instanceof DyNTS_LVS_VectorPersist_DataModel
32
+ set.data instanceof DyNTS_LVS_VectorPersist
33
33
  ? set.data
34
- : new DyNTS_LVS_VectorPersist_DataModel(set.data),
35
- dyNTS_lvsVectorPersist_dataParams,
34
+ : new DyNTS_LVS_VectorPersist(set.data),
35
+ DyNTS_lvsVectorPersist_dataParams,
36
36
  set.issuer,
37
37
  );
38
38
  }
39
39
 
40
40
  /**
41
41
  * Egy (logikai) pool ÖSSZES perzistált, nem-soft-delete-elt vektor-rekordja — a boot-hidratáláshoz
42
- * (a `DyNTS_LVS_PersistentVectorPool.hydrateFromMongo` ezt tölti az in-memory pool-ba).
42
+ * (a `DyNTS_LVS_PersistentVectorPool_ControlService.hydrateFromMongo` ezt tölti az in-memory pool-ba).
43
43
  */
44
- async findByCollectionKey(collectionKey: string): Promise<DyNTS_LVS_VectorPersist_DataModel[]> {
44
+ async findByCollectionKey(collectionKey: string): Promise<DyNTS_LVS_VectorPersist[]> {
45
45
  return this.findDataList(
46
- { collectionKey: collectionKey } as DyFM_DBFilterSimple<DyNTS_LVS_VectorPersist_DataModel>,
46
+ { collectionKey: collectionKey },
47
47
  true,
48
48
  );
49
49
  }
@@ -59,14 +59,14 @@ export class DyNTS_LVS_VectorPersist_DataService extends DyNTS_DataService<DyNTS
59
59
  embedding: number[],
60
60
  metadata?: unknown,
61
61
  }): Promise<void> {
62
- const existing: DyNTS_LVS_VectorPersist_DataModel = await this.findData(
63
- { collectionKey: set.collectionKey, vectorId: set.vectorId } as DyFM_DBFilter<DyNTS_LVS_VectorPersist_DataModel>,
62
+ const existing: DyNTS_LVS_VectorPersist = await this.findData(
63
+ { collectionKey: set.collectionKey, vectorId: set.vectorId },
64
64
  true,
65
65
  );
66
66
 
67
67
  if (existing?._id) {
68
68
  await this.updateData({
69
- filterBy: { _id: existing._id } as DyFM_DBFilterSimple<DyNTS_LVS_VectorPersist_DataModel>,
69
+ filterBy: { _id: existing._id },
70
70
  update: {
71
71
  $set: {
72
72
  embedding: set.embedding,
@@ -75,11 +75,12 @@ export class DyNTS_LVS_VectorPersist_DataService extends DyNTS_DataService<DyNTS
75
75
  },
76
76
  },
77
77
  });
78
+
78
79
  return;
79
80
  }
80
81
 
81
82
  await this.saveData(
82
- new DyNTS_LVS_VectorPersist_DataModel({
83
+ new DyNTS_LVS_VectorPersist({
83
84
  collectionKey: set.collectionKey,
84
85
  vectorId: set.vectorId,
85
86
  embedding: set.embedding,
@@ -95,10 +96,11 @@ export class DyNTS_LVS_VectorPersist_DataService extends DyNTS_DataService<DyNTS
95
96
  * `removeVector`-ja után — a tartós tár is törli). `addArchive` nincs → `absolute` true-val töröl.
96
97
  */
97
98
  async removeVector(collectionKey: string, vectorId: string): Promise<void> {
98
- const existing: DyNTS_LVS_VectorPersist_DataModel = await this.findData(
99
- { collectionKey: collectionKey, vectorId: vectorId } as DyFM_DBFilter<DyNTS_LVS_VectorPersist_DataModel>,
99
+ const existing: DyNTS_LVS_VectorPersist = await this.findData(
100
+ { collectionKey: collectionKey, vectorId: vectorId },
100
101
  true,
101
102
  );
103
+
102
104
  if (existing?._id) {
103
105
  await this.deleteData(existing._id, true);
104
106
  }
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Boundary: a `DyNTS_McpToolDefinition` + a `DyNTS_Mcp_Adapter` egyetlen `registerTool` choke-pontot
7
7
  * ad — a hivatalos `@modelcontextprotocol/sdk` KIZÁRÓLAG az adaptor mögött él, így egy jövőbeli
8
- * transport-/SDK-csere NEM-breaking (csak az adaptor cserélődik, a `DyNTS_Mcp_ServerBase` + a
8
+ * transport-/SDK-csere NEM-breaking (csak az adaptor cserélődik, a `DyNTS_Mcp_Server_ServiceBase` + a
9
9
  * consumer-tool-ok változatlanok). A consumer a SAJÁT tool-jait regisztrálja (a bedrock NEM definiál
10
10
  * domain-tool-okat — csak a server-base + a transport + a registry).
11
11
  */
@@ -1,12 +1,12 @@
1
- import { DyNTS_Mcp_ServerBase } from './dynts-mcp-server.service-base';
1
+ import { DyNTS_Mcp_Server_ServiceBase } from './dynts-mcp-server.service-base';
2
2
  import {
3
- DyNTS_Mcp_CallResult,
4
- DyNTS_Mcp_ServerInfo,
5
- DyNTS_Mcp_ToolDefinition,
3
+ DyNTS_Mcp_CallResult,
4
+ DyNTS_Mcp_ServerInfo,
5
+ DyNTS_Mcp_ToolDefinition
6
6
  } from '../_models/interfaces/dynts-mcp.interface';
7
7
 
8
8
  /**
9
- * CONTRACT — `DyNTS_Mcp_ServerBase` tool-registry + dispatch (BFR-AM-003). A transportot NEM nyitjuk
9
+ * CONTRACT — `DyNTS_Mcp_Server_ServiceBase` tool-registry + dispatch (BFR-AM-003). A transportot NEM nyitjuk
10
10
  * meg (nincs valódi stdio-szerver) — a `build()` + `callTool()` közvetlen dispatch-ét teszteljük,
11
11
  * ami UGYANAZ a logika, mint a SDK `tools/call`-ja:
12
12
  * - N tool regisztrálása → `getAdvertisedToolNames` PONTOSAN ezeket listázza,
@@ -15,128 +15,137 @@ import {
15
15
  * - handler-dobott hiba → `isError:true` fordítás (a payload tartalmazza a message-et),
16
16
  * - `isError:true` outcome → `isError:true` call-result.
17
17
  */
18
- describe('DyNTS_Mcp_ServerBase (tool-registry + dispatch, BFR-AM-003)', () => {
19
-
20
- /** A handler-hívások nyoma (melyik tool, milyen args) — a dispatch-helyesség igazolásához. */
21
- let calls: { name: string; args: unknown }[];
22
-
23
- /** Egy teszt-tool-definíció gyára (a handler `data`-ba teszi a tool-nevet + az args-ot). */
24
- const makeTool = (name: string): DyNTS_Mcp_ToolDefinition => ({
25
- name: name,
26
- description: `Test tool ${name}.`,
27
- inputSchema: { type: 'object', properties: { x: { type: 'string' } } },
28
- handler: async (args: unknown) => {
29
- calls.push({ name: name, args: args });
30
- return { data: { tool: name, echo: args } };
18
+ describe('| DyNTS_Mcp_Server_ServiceBase (tool-registry + dispatch, BFR-AM-003)', () => {
19
+
20
+ /** A handler-hívások nyoma (melyik tool, milyen args) — a dispatch-helyesség igazolásához. */
21
+ let calls: { name: string; args: unknown }[];
22
+
23
+ /** Egy teszt-tool-definíció gyára (a handler `data`-ba teszi a tool-nevet + az args-ot). */
24
+ const makeTool = (name: string): DyNTS_Mcp_ToolDefinition => ({
25
+ name: name,
26
+ description: `Test tool ${name}.`,
27
+ inputSchema: { type: 'object', properties: { x: { type: 'string' } } },
28
+ handler: async (args: unknown) => {
29
+ calls.push({ name: name, args: args });
30
+
31
+ return { data: { tool: name, echo: args } };
32
+ },
33
+ });
34
+
35
+ /** A teszt-szerver: 3 tool + egy szándékosan dobó tool. */
36
+ class TestServer extends DyNTS_Mcp_Server_ServiceBase {
37
+ protected getServerInfo(): DyNTS_Mcp_ServerInfo {
38
+ return { name: 'test-mcp', version: '0.0.1-spec' };
39
+ }
40
+ protected getTools(): DyNTS_Mcp_ToolDefinition[] {
41
+ return [
42
+ makeTool('alpha'),
43
+ makeTool('beta'),
44
+ {
45
+ name: 'boom',
46
+ description: 'Always throws.',
47
+ inputSchema: { type: 'object' },
48
+ handler: async () => {
49
+ throw new Error('kaboom from handler');
50
+ },
51
+ },
52
+ {
53
+ name: 'structuredError',
54
+ description: 'Returns a structured error outcome.',
55
+ inputSchema: { type: 'object' },
56
+ handler: async () => ({ data: { reason: 'nope' }, isError: true }),
31
57
  },
58
+ ];
59
+ }
60
+ }
61
+
62
+ let server: TestServer;
63
+
64
+ beforeEach(() => {
65
+ calls = [];
66
+ server = new TestServer();
67
+ });
68
+
69
+ /** A `content[0].text` JSON-payload kiparse-olása (a transport text-JSON shape-je). */
70
+ const payloadOf = (result: DyNTS_Mcp_CallResult): { [key: string]: unknown } =>
71
+ JSON.parse(result.content[0].text) as { [key: string]: unknown };
72
+
73
+ describe('| registry — getTools → advertised', () => {
74
+ it('| a deklarált tool-okat hirdeti build ELŐTT is (determinisztikus)', () => {
75
+ expect(server.getAdvertisedToolNames().sort())
76
+ .toEqual([ 'alpha', 'beta', 'boom', 'structuredError' ]);
32
77
  });
33
78
 
34
- /** A teszt-szerver: 3 tool + egy szándékosan dobó tool. */
35
- class TestServer extends DyNTS_Mcp_ServerBase {
36
- protected getServerInfo(): DyNTS_Mcp_ServerInfo {
37
- return { name: 'test-mcp', version: '0.0.1-spec' };
38
- }
39
- protected getTools(): DyNTS_Mcp_ToolDefinition[] {
40
- return [
41
- makeTool('alpha'),
42
- makeTool('beta'),
43
- {
44
- name: 'boom',
45
- description: 'Always throws.',
46
- inputSchema: { type: 'object' },
47
- handler: async () => {
48
- throw new Error('kaboom from handler');
49
- },
50
- },
51
- {
52
- name: 'structuredError',
53
- description: 'Returns a structured error outcome.',
54
- inputSchema: { type: 'object' },
55
- handler: async () => ({ data: { reason: 'nope' }, isError: true }),
56
- },
57
- ];
58
- }
59
- }
79
+ it('| build() után UGYANAZOK a hirdetett tool-ok (idempotens build)', () => {
80
+ const adapter1 = server.build();
81
+ const adapter2 = server.build();
82
+
83
+ expect(adapter1).toBe(adapter2);
84
+ expect(adapter1.getAdvertisedToolNames().sort())
85
+ .toEqual([ 'alpha', 'beta', 'boom', 'structuredError' ]);
86
+ });
87
+ });
60
88
 
61
- let server: TestServer;
89
+ describe('| dispatch — callTool a megfelelő handler-re route-ol', () => {
90
+ it('| alpha → az alpha handler fut (a data a tool-nevet + az args-ot adja)', async () => {
91
+ const result: DyNTS_Mcp_CallResult = await server.callTool({ name: 'alpha', arguments: { x: '1' } });
62
92
 
63
- beforeEach(() => {
64
- calls = [];
65
- server = new TestServer();
93
+ expect(result.isError).toBe(false);
94
+ expect(calls).toEqual([{ name: 'alpha', args: { x: '1' } }]);
95
+ expect(payloadOf(result)).toEqual({ tool: 'alpha', echo: { x: '1' } });
66
96
  });
67
97
 
68
- /** A `content[0].text` JSON-payload kiparse-olása (a transport text-JSON shape-je). */
69
- const payloadOf = (result: DyNTS_Mcp_CallResult): { [key: string]: unknown } =>
70
- JSON.parse(result.content[0].text) as { [key: string]: unknown };
98
+ it('| beta a beta handler fut (a dispatch a `name` szerint választ)', async () => {
99
+ await server.callTool({ name: 'beta', arguments: { x: '2' } });
100
+ expect(calls).toEqual([{ name: 'beta', args: { x: '2' } }]);
101
+ });
102
+ });
103
+
104
+ describe('| strukturált hiba (no-silent-failure)', () => {
105
+ it('| ismeretlen tool → isError:true + advertised-lista a message-ben (NEM néma/crash)', async () => {
106
+ const result: DyNTS_Mcp_CallResult = await server.callTool({ name: 'does_not_exist' });
71
107
 
72
- describe('registry — getTools → advertised', () => {
73
- it('a deklarált tool-okat hirdeti build ELŐTT is (determinisztikus)', () => {
74
- expect(server.getAdvertisedToolNames().sort())
75
- .toEqual(['alpha', 'beta', 'boom', 'structuredError']);
76
- });
77
-
78
- it('build() után UGYANAZOK a hirdetett tool-ok (idempotens build)', () => {
79
- const adapter1 = server.build();
80
- const adapter2 = server.build();
81
- expect(adapter1).toBe(adapter2);
82
- expect(adapter1.getAdvertisedToolNames().sort())
83
- .toEqual(['alpha', 'beta', 'boom', 'structuredError']);
84
- });
108
+ expect(result.isError).toBe(true);
109
+ const payload = payloadOf(result) as { ok: boolean; error: { message: string } };
110
+
111
+ expect(payload.ok).toBe(false);
112
+ expect(payload.error.message).toContain('does_not_exist');
113
+ expect(payload.error.message).toContain('alpha');
114
+ // egyetlen ismeretlen tool sem futtatott handlert.
115
+ expect(calls.length).toBe(0);
85
116
  });
86
117
 
87
- describe('dispatch callTool a megfelelő handler-re route-ol', () => {
88
- it('alpha az alpha handler fut (a data a tool-nevet + az args-ot adja)', async () => {
89
- const result: DyNTS_Mcp_CallResult = await server.callTool({ name: 'alpha', arguments: { x: '1' } });
90
- expect(result.isError).toBe(false);
91
- expect(calls).toEqual([{ name: 'alpha', args: { x: '1' } }]);
92
- expect(payloadOf(result)).toEqual({ tool: 'alpha', echo: { x: '1' } });
93
- });
94
-
95
- it('beta → a beta handler fut (a dispatch a `name` szerint választ)', async () => {
96
- await server.callTool({ name: 'beta', arguments: { x: '2' } });
97
- expect(calls).toEqual([{ name: 'beta', args: { x: '2' } }]);
98
- });
118
+ it('| handler-dobott hiba → isError:true + a hiba message-e a payload-ban (NEM crash)', async () => {
119
+ const result: DyNTS_Mcp_CallResult = await server.callTool({ name: 'boom' });
120
+
121
+ expect(result.isError).toBe(true);
122
+ const payload = payloadOf(result) as { ok: boolean; error: { message: string } };
123
+
124
+ expect(payload.ok).toBe(false);
125
+ expect(payload.error.message).toContain('kaboom from handler');
99
126
  });
100
127
 
101
- describe('strukturált hiba (no-silent-failure)', () => {
102
- it('ismeretlen tool → isError:true + advertised-lista a message-ben (NEM néma/crash)', async () => {
103
- const result: DyNTS_Mcp_CallResult = await server.callTool({ name: 'does_not_exist' });
104
- expect(result.isError).toBe(true);
105
- const payload = payloadOf(result) as { ok: boolean; error: { message: string } };
106
- expect(payload.ok).toBe(false);
107
- expect(payload.error.message).toContain('does_not_exist');
108
- expect(payload.error.message).toContain('alpha');
109
- // egyetlen ismeretlen tool sem futtatott handlert.
110
- expect(calls.length).toBe(0);
111
- });
112
-
113
- it('handler-dobott hiba → isError:true + a hiba message-e a payload-ban (NEM crash)', async () => {
114
- const result: DyNTS_Mcp_CallResult = await server.callTool({ name: 'boom' });
115
- expect(result.isError).toBe(true);
116
- const payload = payloadOf(result) as { ok: boolean; error: { message: string } };
117
- expect(payload.ok).toBe(false);
118
- expect(payload.error.message).toContain('kaboom from handler');
119
- });
120
-
121
- it('isError:true outcome → isError:true call-result (a strukturált hiba átmegy)', async () => {
122
- const result: DyNTS_Mcp_CallResult = await server.callTool({ name: 'structuredError' });
123
- expect(result.isError).toBe(true);
124
- expect(payloadOf(result)).toEqual({ reason: 'nope' });
125
- });
128
+ it('| isError:true outcome → isError:true call-result (a strukturált hiba átmegy)', async () => {
129
+ const result: DyNTS_Mcp_CallResult = await server.callTool({ name: 'structuredError' });
130
+
131
+ expect(result.isError).toBe(true);
132
+ expect(payloadOf(result)).toEqual({ reason: 'nope' });
126
133
  });
134
+ });
135
+
136
+ describe('| start — transport-választás', () => {
137
+ it('| ismeretlen transport → dob (exhaustiveness-guard); stdio nem nyílik a spec-ben', async () => {
138
+ let thrown: unknown;
127
139
 
128
- describe('start — transport-választás', () => {
129
- it('ismeretlen transport dob (exhaustiveness-guard); stdio nem nyílik a spec-ben', async () => {
130
- let thrown: unknown;
131
- try {
132
- // Szándékosan érvénytelen transport (a típus-szűkítés megkerülésével) — a guard-ágat teszteli,
133
- // valódi stdio-szervert NEM indítunk.
134
- await server.start({ transport: 'http' as never });
135
- } catch (error) {
136
- thrown = error;
137
- }
138
- expect(thrown).toBeDefined();
139
- expect((thrown as Error).message).toContain('Unsupported MCP transport');
140
- });
140
+ try {
141
+ // Szándékosan érvénytelen transport (a típus-szűkítés megkerülésével) a guard-ágat teszteli,
142
+ // valódi stdio-szervert NEM indítunk.
143
+ await server.start({ transport: 'http' as never });
144
+ } catch (error) {
145
+ thrown = error;
146
+ }
147
+ expect(thrown).toBeDefined();
148
+ expect((thrown as Error).message).toContain('Unsupported MCP transport');
141
149
  });
150
+ });
142
151
  });
@@ -1,26 +1,26 @@
1
1
  import { DyFM_Log } from '@futdevpro/fsm-dynamo';
2
2
 
3
3
  import {
4
- DyNTS_Mcp_CallResult,
5
- DyNTS_Mcp_ServerInfo,
6
- DyNTS_Mcp_StartOptions,
7
- DyNTS_Mcp_ToolDefinition,
4
+ DyNTS_Mcp_CallResult,
5
+ DyNTS_Mcp_ServerInfo,
6
+ DyNTS_Mcp_StartOptions,
7
+ DyNTS_Mcp_ToolDefinition
8
8
  } from '../_models/interfaces/dynts-mcp.interface';
9
9
  import { DyNTS_Mcp_Adapter } from './dynts-mcp.adapter';
10
10
 
11
11
  /**
12
- * `DyNTS_Mcp_ServerBase` (BFR-AM-003) — a **domain-agnosztikus** MCP-szerver-base. Egy bedrock-réteg
12
+ * `DyNTS_Mcp_Server_ServiceBase` (BFR-AM-003) — a **domain-agnosztikus** MCP-szerver-base. Egy bedrock-réteg
13
13
  * a hivatalos `@modelcontextprotocol/sdk` fölött: a server-base felel a tool-registry-ért, a
14
14
  * `tools/list`/`tools/call` dispatch-ért (az adaptoron át) + a transport-indításért — a SDK KIZÁRÓLAG
15
15
  * a `DyNTS_Mcp_Adapter` mögött él (egy jövőbeli transport-/SDK-csere NON-breaking).
16
16
  *
17
- * **Használat (consumer):** a consumer leszármazik (`extends DyNTS_Mcp_ServerBase`) + implementálja a
17
+ * **Használat (consumer):** a consumer leszármazik (`extends DyNTS_Mcp_Server_ServiceBase`) + implementálja a
18
18
  * `getServerInfo()` (név/verzió) és `getTools()` (a SAJÁT tool-jai) abstract metódusokat. A bedrock
19
19
  * SEMMILYEN domain-tool-t NEM definiál — csak a server-base + a transport + a registry. (Pl. a FAM a
20
20
  * `read`/`write`/`capabilities` tool-jait itt regisztrálja, a bedrock-on kívül.)
21
21
  *
22
22
  * ```ts
23
- * class My_McpServer extends DyNTS_Mcp_ServerBase {
23
+ * class My_McpServer extends DyNTS_Mcp_Server_ServiceBase {
24
24
  * protected getServerInfo() { return { name: 'my-app', version: '1.0.0' }; }
25
25
  * protected getTools() { return [readTool, writeTool]; }
26
26
  * }
@@ -30,10 +30,10 @@ import { DyNTS_Mcp_Adapter } from './dynts-mcp.adapter';
30
30
  * **stdio-konvenció:** a stdout a JSON-RPC csatorna — a boot-üzenet + minden log a stderr-re megy (a
31
31
  * hívó App a `DyFM_Log`-ot stdio-módban stderr-re konfigurálja).
32
32
  */
33
- export abstract class DyNTS_Mcp_ServerBase {
33
+ export abstract class DyNTS_Mcp_Server_ServiceBase {
34
34
 
35
- /** Az MCP-adaptor (a regisztrált tool-ok + a transport mögötti SDK-réteg). Lazy a `build()`-ben. */
36
- private adapter: DyNTS_Mcp_Adapter | null = null;
35
+ /** Az MCP-adaptor (a regisztrált tool-ok + a transport mögötti SDK-réteg). Lazy a `build()`-ben. */
36
+ private adapter: DyNTS_Mcp_Adapter | null = null;
37
37
 
38
38
  /**
39
39
  * A szerver identitása (név/verzió) — a consumer adja. A SDK `serverInfo`-jaként hirdetődik.
@@ -52,15 +52,17 @@ export abstract class DyNTS_Mcp_ServerBase {
52
52
  * hirdeti, transport nélkül). Idempotens: ismételt hívás ugyanazt az adaptort adja vissza.
53
53
  */
54
54
  public build(): DyNTS_Mcp_Adapter {
55
- if (this.adapter) {
56
- return this.adapter;
57
- }
58
- const adapter: DyNTS_Mcp_Adapter = new DyNTS_Mcp_Adapter(this.getServerInfo());
59
- for (const tool of this.getTools()) {
60
- adapter.registerTool(tool);
61
- }
62
- this.adapter = adapter;
63
- return adapter;
55
+ if (this.adapter) {
56
+ return this.adapter;
57
+ }
58
+ const adapter: DyNTS_Mcp_Adapter = new DyNTS_Mcp_Adapter(this.getServerInfo());
59
+
60
+ for (const tool of this.getTools()) {
61
+ adapter.registerTool(tool);
62
+ }
63
+ this.adapter = adapter;
64
+
65
+ return adapter;
64
66
  }
65
67
 
66
68
  /**
@@ -69,12 +71,13 @@ export abstract class DyNTS_Mcp_ServerBase {
69
71
  * a `tools/call` route-ol. A boot-üzenet a stderr-en.
70
72
  */
71
73
  public async start(options?: DyNTS_Mcp_StartOptions): Promise<void> {
72
- const transport: 'stdio' = options?.transport ?? 'stdio';
73
- const adapter: DyNTS_Mcp_Adapter = this.build();
74
- const info: DyNTS_Mcp_ServerInfo = this.getServerInfo();
75
- DyFM_Log.testInfo(`[DyNTS MCP] ${transport} server starting (${info.name} v${info.version}); `
74
+ const transport: 'stdio' = options?.transport ?? 'stdio';
75
+ const adapter: DyNTS_Mcp_Adapter = this.build();
76
+ const info: DyNTS_Mcp_ServerInfo = this.getServerInfo();
77
+
78
+ DyFM_Log.testInfo(`[DyNTS MCP] ${transport} server starting (${info.name} v${info.version}); `
76
79
  + `advertised tools: ${adapter.getAdvertisedToolNames().join(', ')}`);
77
- await this.startTransport(adapter, transport);
80
+ await this.startTransport(adapter, transport);
78
81
  }
79
82
 
80
83
  /**
@@ -82,9 +85,9 @@ export abstract class DyNTS_Mcp_ServerBase {
82
85
  * neveit adja (transport nélkül is determinisztikus).
83
86
  */
84
87
  public getAdvertisedToolNames(): string[] {
85
- return this.adapter
86
- ? this.adapter.getAdvertisedToolNames()
87
- : this.getTools().map((tool) => tool.name);
88
+ return this.adapter
89
+ ? this.adapter.getAdvertisedToolNames()
90
+ : this.getTools().map((tool) => tool.name);
88
91
  }
89
92
 
90
93
  /**
@@ -93,14 +96,14 @@ export abstract class DyNTS_Mcp_ServerBase {
93
96
  * tool → strukturált hiba; handler-hiba → `isError:true`).
94
97
  */
95
98
  public async callTool(set: { name: string; arguments?: unknown }): Promise<DyNTS_Mcp_CallResult> {
96
- return this.build().dispatchToolCall(set);
99
+ return this.build().dispatchToolCall(set);
97
100
  }
98
101
 
99
102
  /** A szerver leállítása (graceful close — teszt-/shutdown-úthoz). */
100
103
  public async close(): Promise<void> {
101
- if (this.adapter) {
102
- await this.adapter.close();
103
- }
104
+ if (this.adapter) {
105
+ await this.adapter.close();
106
+ }
104
107
  }
105
108
 
106
109
  /**
@@ -108,13 +111,15 @@ export abstract class DyNTS_Mcp_ServerBase {
108
111
  * módon bővíthető legyen (a `start()` + a registry változatlan). MVP: csak `stdio`.
109
112
  */
110
113
  private async startTransport(adapter: DyNTS_Mcp_Adapter, transport: 'stdio'): Promise<void> {
111
- switch (transport) {
112
- case 'stdio':
113
- await adapter.startStdio();
114
- return;
115
- default:
116
- // Exhaustiveness-guard: a `DyNTS_Mcp_TransportKind` bővülésekor itt fordítási hibát kapunk.
117
- throw new Error(`Unsupported MCP transport: '${transport as string}'.`);
118
- }
114
+ switch (transport) {
115
+ case 'stdio':
116
+ await adapter.startStdio();
117
+
118
+ return;
119
+
120
+ default:
121
+ // Exhaustiveness-guard: a `DyNTS_Mcp_TransportKind` bővülésekor itt fordítási hibát kapunk.
122
+ throw new Error(`Unsupported MCP transport: '${transport as string}'.`);
123
+ }
119
124
  }
120
125
  }