@futdevpro/nts-dynamo 1.15.107 → 1.15.111
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dynamo/logs/cicd-pipeline/output.log +1836 -1821
- package/.dynamo/logs/cicd-pipeline/status.json +37 -23
- package/build/_modules/ai/_collections/ai-provider-error.util.d.ts +9 -0
- package/build/_modules/ai/_collections/ai-provider-error.util.d.ts.map +1 -1
- package/build/_modules/ai/_collections/ai-provider-error.util.js +42 -3
- package/build/_modules/ai/_collections/ai-provider-error.util.js.map +1 -1
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.d.ts +8 -0
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.d.ts.map +1 -1
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.js +2 -1
- package/build/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.js.map +1 -1
- package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.d.ts +13 -3
- package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.d.ts.map +1 -1
- package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.js +13 -3
- package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.js.map +1 -1
- package/build/_modules/server/server-status/server-status.control-service.d.ts +10 -0
- package/build/_modules/server/server-status/server-status.control-service.d.ts.map +1 -1
- package/build/_modules/server/server-status/server-status.control-service.js +21 -0
- package/build/_modules/server/server-status/server-status.control-service.js.map +1 -1
- package/package.json +2 -2
- package/scripts/_seed-out/aim-seed.fixtures.ts +161 -0
- package/scripts/_seed-out/seed-raw.json +153 -0
- package/scripts/ai-fixture-seed.js +126 -0
- package/src/_modules/ai/_collections/ai-provider-error.util.ts +49 -3
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.ts +11 -1
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.ts +13 -3
- package/src/_modules/server/server-status/server-status.control-service.spec.ts +40 -0
- package/src/_modules/server/server-status/server-status.control-service.ts +40 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { DyNTS_AIMock_Fixture } from '../_models/interfaces/aim-fixture.interface';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Valodi AI-generalasbol beegetve (live capture 2026-07-21). Kezzel NE szerkeszd.
|
|
5
|
+
*
|
|
6
|
+
* Determinisztikus sorrend (match-kulcs szerint) + rendezett objektum-kulcsok, hogy az ujra-generalas
|
|
7
|
+
* ne okozzon zajos diff-et. Forras: `DyNTS_AIMock_FixtureSerializer_Util`.
|
|
8
|
+
*/
|
|
9
|
+
export const DyNTS_AIMock_TextFixtures: DyNTS_AIMock_Fixture[] = [
|
|
10
|
+
{
|
|
11
|
+
"capturedAt": "2026-07-22T00:58:38.792Z",
|
|
12
|
+
"config": {
|
|
13
|
+
"temperature": 0
|
|
14
|
+
},
|
|
15
|
+
"input": "Reply with exactly: PONG",
|
|
16
|
+
"inputHash": "0fb5aed1b51b28b04409b7963b2453fe1597d198c3b8396fc8ebd072104511de",
|
|
17
|
+
"modality": "text",
|
|
18
|
+
"model": "gpt-4o-mini",
|
|
19
|
+
"output": {
|
|
20
|
+
"content": "PONG",
|
|
21
|
+
"finish_reason": "stop",
|
|
22
|
+
"usage": {
|
|
23
|
+
"completion_tokens": 2,
|
|
24
|
+
"completion_tokens_details": {
|
|
25
|
+
"accepted_prediction_tokens": 0,
|
|
26
|
+
"audio_tokens": 0,
|
|
27
|
+
"reasoning_tokens": 0,
|
|
28
|
+
"rejected_prediction_tokens": 0
|
|
29
|
+
},
|
|
30
|
+
"prompt_tokens": 13,
|
|
31
|
+
"prompt_tokens_details": {
|
|
32
|
+
"audio_tokens": 0,
|
|
33
|
+
"cached_tokens": 0
|
|
34
|
+
},
|
|
35
|
+
"total_tokens": 15
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"provider": "open-ai",
|
|
39
|
+
"sourceModel": "gpt-4o-mini"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"capturedAt": "2026-07-22T00:58:37.828Z",
|
|
43
|
+
"config": {
|
|
44
|
+
"temperature": 0
|
|
45
|
+
},
|
|
46
|
+
"input": "Reply with exactly: PONG",
|
|
47
|
+
"inputHash": "0fb5aed1b51b28b04409b7963b2453fe1597d198c3b8396fc8ebd072104511de",
|
|
48
|
+
"modality": "text",
|
|
49
|
+
"model": "gpt-5.4-nano",
|
|
50
|
+
"output": {
|
|
51
|
+
"content": "PONG",
|
|
52
|
+
"finish_reason": "stop",
|
|
53
|
+
"usage": {
|
|
54
|
+
"completion_tokens": 5,
|
|
55
|
+
"completion_tokens_details": {
|
|
56
|
+
"accepted_prediction_tokens": 0,
|
|
57
|
+
"audio_tokens": 0,
|
|
58
|
+
"reasoning_tokens": 0,
|
|
59
|
+
"rejected_prediction_tokens": 0
|
|
60
|
+
},
|
|
61
|
+
"prompt_tokens": 12,
|
|
62
|
+
"prompt_tokens_details": {
|
|
63
|
+
"audio_tokens": 0,
|
|
64
|
+
"cached_tokens": 0
|
|
65
|
+
},
|
|
66
|
+
"total_tokens": 17
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"provider": "open-ai",
|
|
70
|
+
"sourceModel": "gpt-5.4-nano"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"capturedAt": "2026-07-22T00:58:38.316Z",
|
|
74
|
+
"config": {
|
|
75
|
+
"temperature": 0
|
|
76
|
+
},
|
|
77
|
+
"input": "What is the capital of Hungary? One word.",
|
|
78
|
+
"inputHash": "85c5b3ea12c8e34d97a18cb75ae55936aeb2ef0af90eb2f395a44ace6ce997e8",
|
|
79
|
+
"modality": "text",
|
|
80
|
+
"model": "gpt-5.4-nano",
|
|
81
|
+
"output": {
|
|
82
|
+
"content": "Budapest",
|
|
83
|
+
"finish_reason": "stop",
|
|
84
|
+
"usage": {
|
|
85
|
+
"completion_tokens": 5,
|
|
86
|
+
"completion_tokens_details": {
|
|
87
|
+
"accepted_prediction_tokens": 0,
|
|
88
|
+
"audio_tokens": 0,
|
|
89
|
+
"reasoning_tokens": 0,
|
|
90
|
+
"rejected_prediction_tokens": 0
|
|
91
|
+
},
|
|
92
|
+
"prompt_tokens": 16,
|
|
93
|
+
"prompt_tokens_details": {
|
|
94
|
+
"audio_tokens": 0,
|
|
95
|
+
"cached_tokens": 0
|
|
96
|
+
},
|
|
97
|
+
"total_tokens": 21
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"provider": "open-ai",
|
|
101
|
+
"sourceModel": "gpt-5.4-nano"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"capturedAt": "2026-07-22T00:58:39.151Z",
|
|
105
|
+
"config": {},
|
|
106
|
+
"input": "artificial intelligence",
|
|
107
|
+
"inputHash": "803b3eb2b6af027151950019f2d5ede506a6636a9eafd262b27c23e3f834056f",
|
|
108
|
+
"modality": "embedding",
|
|
109
|
+
"model": "text-embedding-3-small",
|
|
110
|
+
"output": {
|
|
111
|
+
"dimensions": 1536,
|
|
112
|
+
"embeddingHead": [
|
|
113
|
+
0.0005774497985839844,
|
|
114
|
+
-0.012481689453125,
|
|
115
|
+
-0.01143646240234375,
|
|
116
|
+
-0.0247344970703125,
|
|
117
|
+
0.011383056640625,
|
|
118
|
+
-0.006069183349609375,
|
|
119
|
+
-0.0209503173828125,
|
|
120
|
+
0.03741455078125
|
|
121
|
+
],
|
|
122
|
+
"model": "text-embedding-3-small",
|
|
123
|
+
"object": "list",
|
|
124
|
+
"usage": {
|
|
125
|
+
"prompt_tokens": 3,
|
|
126
|
+
"total_tokens": 3
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"provider": "open-ai",
|
|
130
|
+
"sourceModel": "text-embedding-3-small"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"capturedAt": "2026-07-22T00:58:39.020Z",
|
|
134
|
+
"config": {},
|
|
135
|
+
"input": "the quick brown fox",
|
|
136
|
+
"inputHash": "9ecb36561341d18eb65484e833efea61edc74b84cf5e6ae1b81c63533e25fc8f",
|
|
137
|
+
"modality": "embedding",
|
|
138
|
+
"model": "text-embedding-3-small",
|
|
139
|
+
"output": {
|
|
140
|
+
"dimensions": 1536,
|
|
141
|
+
"embeddingHead": [
|
|
142
|
+
-0.033355712890625,
|
|
143
|
+
-0.00183868408203125,
|
|
144
|
+
0.005237579345703125,
|
|
145
|
+
-0.06304931640625,
|
|
146
|
+
-0.04779052734375,
|
|
147
|
+
0.0018625259399414062,
|
|
148
|
+
0.016876220703125,
|
|
149
|
+
0.034820556640625
|
|
150
|
+
],
|
|
151
|
+
"model": "text-embedding-3-small",
|
|
152
|
+
"object": "list",
|
|
153
|
+
"usage": {
|
|
154
|
+
"prompt_tokens": 4,
|
|
155
|
+
"total_tokens": 4
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"provider": "open-ai",
|
|
159
|
+
"sourceModel": "text-embedding-3-small"
|
|
160
|
+
}
|
|
161
|
+
];
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"provider": "open-ai",
|
|
4
|
+
"model": "gpt-5.4-nano",
|
|
5
|
+
"modality": "text",
|
|
6
|
+
"config": {
|
|
7
|
+
"temperature": 0
|
|
8
|
+
},
|
|
9
|
+
"input": "Reply with exactly: PONG",
|
|
10
|
+
"inputHash": "0fb5aed1b51b28b04409b7963b2453fe1597d198c3b8396fc8ebd072104511de",
|
|
11
|
+
"output": {
|
|
12
|
+
"content": "PONG",
|
|
13
|
+
"finish_reason": "stop",
|
|
14
|
+
"usage": {
|
|
15
|
+
"prompt_tokens": 12,
|
|
16
|
+
"completion_tokens": 5,
|
|
17
|
+
"total_tokens": 17,
|
|
18
|
+
"prompt_tokens_details": {
|
|
19
|
+
"cached_tokens": 0,
|
|
20
|
+
"audio_tokens": 0
|
|
21
|
+
},
|
|
22
|
+
"completion_tokens_details": {
|
|
23
|
+
"reasoning_tokens": 0,
|
|
24
|
+
"audio_tokens": 0,
|
|
25
|
+
"accepted_prediction_tokens": 0,
|
|
26
|
+
"rejected_prediction_tokens": 0
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"capturedAt": "2026-07-22T00:58:37.828Z",
|
|
31
|
+
"sourceModel": "gpt-5.4-nano"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"provider": "open-ai",
|
|
35
|
+
"model": "gpt-5.4-nano",
|
|
36
|
+
"modality": "text",
|
|
37
|
+
"config": {
|
|
38
|
+
"temperature": 0
|
|
39
|
+
},
|
|
40
|
+
"input": "What is the capital of Hungary? One word.",
|
|
41
|
+
"inputHash": "85c5b3ea12c8e34d97a18cb75ae55936aeb2ef0af90eb2f395a44ace6ce997e8",
|
|
42
|
+
"output": {
|
|
43
|
+
"content": "Budapest",
|
|
44
|
+
"finish_reason": "stop",
|
|
45
|
+
"usage": {
|
|
46
|
+
"prompt_tokens": 16,
|
|
47
|
+
"completion_tokens": 5,
|
|
48
|
+
"total_tokens": 21,
|
|
49
|
+
"prompt_tokens_details": {
|
|
50
|
+
"cached_tokens": 0,
|
|
51
|
+
"audio_tokens": 0
|
|
52
|
+
},
|
|
53
|
+
"completion_tokens_details": {
|
|
54
|
+
"reasoning_tokens": 0,
|
|
55
|
+
"audio_tokens": 0,
|
|
56
|
+
"accepted_prediction_tokens": 0,
|
|
57
|
+
"rejected_prediction_tokens": 0
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"capturedAt": "2026-07-22T00:58:38.316Z",
|
|
62
|
+
"sourceModel": "gpt-5.4-nano"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"provider": "open-ai",
|
|
66
|
+
"model": "gpt-4o-mini",
|
|
67
|
+
"modality": "text",
|
|
68
|
+
"config": {
|
|
69
|
+
"temperature": 0
|
|
70
|
+
},
|
|
71
|
+
"input": "Reply with exactly: PONG",
|
|
72
|
+
"inputHash": "0fb5aed1b51b28b04409b7963b2453fe1597d198c3b8396fc8ebd072104511de",
|
|
73
|
+
"output": {
|
|
74
|
+
"content": "PONG",
|
|
75
|
+
"finish_reason": "stop",
|
|
76
|
+
"usage": {
|
|
77
|
+
"prompt_tokens": 13,
|
|
78
|
+
"completion_tokens": 2,
|
|
79
|
+
"total_tokens": 15,
|
|
80
|
+
"prompt_tokens_details": {
|
|
81
|
+
"cached_tokens": 0,
|
|
82
|
+
"audio_tokens": 0
|
|
83
|
+
},
|
|
84
|
+
"completion_tokens_details": {
|
|
85
|
+
"reasoning_tokens": 0,
|
|
86
|
+
"audio_tokens": 0,
|
|
87
|
+
"accepted_prediction_tokens": 0,
|
|
88
|
+
"rejected_prediction_tokens": 0
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"capturedAt": "2026-07-22T00:58:38.792Z",
|
|
93
|
+
"sourceModel": "gpt-4o-mini"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"provider": "open-ai",
|
|
97
|
+
"model": "text-embedding-3-small",
|
|
98
|
+
"modality": "embedding",
|
|
99
|
+
"config": {},
|
|
100
|
+
"input": "the quick brown fox",
|
|
101
|
+
"inputHash": "9ecb36561341d18eb65484e833efea61edc74b84cf5e6ae1b81c63533e25fc8f",
|
|
102
|
+
"output": {
|
|
103
|
+
"object": "list",
|
|
104
|
+
"model": "text-embedding-3-small",
|
|
105
|
+
"dimensions": 1536,
|
|
106
|
+
"embeddingHead": [
|
|
107
|
+
-0.033355712890625,
|
|
108
|
+
-0.00183868408203125,
|
|
109
|
+
0.005237579345703125,
|
|
110
|
+
-0.06304931640625,
|
|
111
|
+
-0.04779052734375,
|
|
112
|
+
0.0018625259399414062,
|
|
113
|
+
0.016876220703125,
|
|
114
|
+
0.034820556640625
|
|
115
|
+
],
|
|
116
|
+
"usage": {
|
|
117
|
+
"prompt_tokens": 4,
|
|
118
|
+
"total_tokens": 4
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"capturedAt": "2026-07-22T00:58:39.020Z",
|
|
122
|
+
"sourceModel": "text-embedding-3-small"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"provider": "open-ai",
|
|
126
|
+
"model": "text-embedding-3-small",
|
|
127
|
+
"modality": "embedding",
|
|
128
|
+
"config": {},
|
|
129
|
+
"input": "artificial intelligence",
|
|
130
|
+
"inputHash": "803b3eb2b6af027151950019f2d5ede506a6636a9eafd262b27c23e3f834056f",
|
|
131
|
+
"output": {
|
|
132
|
+
"object": "list",
|
|
133
|
+
"model": "text-embedding-3-small",
|
|
134
|
+
"dimensions": 1536,
|
|
135
|
+
"embeddingHead": [
|
|
136
|
+
0.0005774497985839844,
|
|
137
|
+
-0.012481689453125,
|
|
138
|
+
-0.01143646240234375,
|
|
139
|
+
-0.0247344970703125,
|
|
140
|
+
0.011383056640625,
|
|
141
|
+
-0.006069183349609375,
|
|
142
|
+
-0.0209503173828125,
|
|
143
|
+
0.03741455078125
|
|
144
|
+
],
|
|
145
|
+
"usage": {
|
|
146
|
+
"prompt_tokens": 3,
|
|
147
|
+
"total_tokens": 3
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"capturedAt": "2026-07-22T00:58:39.151Z",
|
|
151
|
+
"sourceModel": "text-embedding-3-small"
|
|
152
|
+
}
|
|
153
|
+
]
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FIZETOS fixture-seed (MP-3 SP-3.3) — a VALODI `DyNTS_AIMock_FixtureHarness_Service`-en es a
|
|
3
|
+
* `DyNTS_AIMock_FixtureSerializer_Util`-on keresztul, hogy a sajat kodutunkat is bizonyitsa (dogfooding).
|
|
4
|
+
*
|
|
5
|
+
* ⚠️ EZ PENZT KOLT. Szandekosan KICSI es KORLATOZOTT:
|
|
6
|
+
* - csak a legolcsobb engedett modellek (`gpt-5.4-nano` text, `text-embedding-3-small` embedding)
|
|
7
|
+
* - rovid promptok + szuk `max_completion_tokens`
|
|
8
|
+
* - kep-generalas NINCS (kulon dontes targya)
|
|
9
|
+
* - MINDEN fixture AZONNAL lemezre irodik (runbook §2c) — kvota-kifogyas nem viszi el az addigi munkat
|
|
10
|
+
* - 429 eseten az adott provider leall, a tobbi megy tovabb
|
|
11
|
+
* - a futas vegen kiirja a TENYLEGES token-fogyast
|
|
12
|
+
*
|
|
13
|
+
* Futtatas: node scripts/ai-fixture-seed.js
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
|
|
19
|
+
const ENV_PATH = path.resolve(__dirname, '../../../fdp-devops/.env');
|
|
20
|
+
const AIMOCK = path.resolve(__dirname, '../build/_modules/ai/_modules/ai-mock');
|
|
21
|
+
const OUT_DIR = path.resolve(__dirname, '_seed-out');
|
|
22
|
+
const RAW_FILE = path.join(OUT_DIR, 'seed-raw.json');
|
|
23
|
+
|
|
24
|
+
const { DyNTS_AIMock_FixtureHarness_Service } = require(path.join(AIMOCK, '_services/aim-fixture-harness.service'));
|
|
25
|
+
const { DyNTS_AIMock_FixtureSerializer_Util } = require(path.join(AIMOCK, '_collections/aim-fixture-serializer.util'));
|
|
26
|
+
const { DyNTS_AIMock_Modality } = require(path.join(AIMOCK, '_enums/aim-modality.enum'));
|
|
27
|
+
const { DyFM_OAI_Models } = require('@futdevpro/fsm-dynamo/ai/open-ai');
|
|
28
|
+
|
|
29
|
+
function loadKey() {
|
|
30
|
+
for (const line of fs.readFileSync(ENV_PATH, 'utf8').split(/\r?\n/)) {
|
|
31
|
+
const m = line.match(/^OPENAI_API_KEY=(.*)$/);
|
|
32
|
+
if (m) { return m[1].trim().replace(/^["']|["']$/g, ''); }
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const usage = { prompt: 0, completion: 0, calls: 0 };
|
|
38
|
+
let quotaStop = false;
|
|
39
|
+
|
|
40
|
+
/** VALODI generator — ez az egyetlen pont, ahol penz folyik. */
|
|
41
|
+
function makeGenerator(key) {
|
|
42
|
+
return async (request) => {
|
|
43
|
+
if (request.modality === DyNTS_AIMock_Modality.embedding) {
|
|
44
|
+
const r = await fetch('https://api.openai.com/v1/embeddings', {
|
|
45
|
+
method: 'POST',
|
|
46
|
+
headers: { Authorization: `Bearer ${key}`, 'content-type': 'application/json' },
|
|
47
|
+
body: JSON.stringify({ model: request.model, input: request.input, ...(request.config || {}) }),
|
|
48
|
+
});
|
|
49
|
+
if (r.status === 429) { quotaStop = true; throw new Error('429 quota'); }
|
|
50
|
+
const j = await r.json();
|
|
51
|
+
if (j.error) { throw new Error(j.error.message); }
|
|
52
|
+
usage.prompt += j.usage?.prompt_tokens || 0;
|
|
53
|
+
usage.calls++;
|
|
54
|
+
// a teljes vektor helyett a dimenziot + az elso 8 erteket orizzuk (a fixture-fajl maradjon kezelheto)
|
|
55
|
+
return { object: j.object, model: j.model, dimensions: j.data[0].embedding.length,
|
|
56
|
+
embeddingHead: j.data[0].embedding.slice(0, 8), usage: j.usage };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const r = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: { Authorization: `Bearer ${key}`, 'content-type': 'application/json' },
|
|
62
|
+
body: JSON.stringify({ model: request.model, messages: [ { role: 'user', content: request.input } ],
|
|
63
|
+
max_completion_tokens: 64, ...(request.config || {}) }),
|
|
64
|
+
});
|
|
65
|
+
if (r.status === 429) { quotaStop = true; throw new Error('429 quota'); }
|
|
66
|
+
const j = await r.json();
|
|
67
|
+
if (j.error) { throw new Error(j.error.message); }
|
|
68
|
+
usage.prompt += j.usage?.prompt_tokens || 0;
|
|
69
|
+
usage.completion += j.usage?.completion_tokens || 0;
|
|
70
|
+
usage.calls++;
|
|
71
|
+
return { content: j.choices[0].message.content, finish_reason: j.choices[0].finish_reason, usage: j.usage };
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const SEED = [
|
|
76
|
+
{ model: 'gpt-5.4-nano', modality: DyNTS_AIMock_Modality.text, config: { temperature: 0 }, input: 'Reply with exactly: PONG' },
|
|
77
|
+
{ model: 'gpt-5.4-nano', modality: DyNTS_AIMock_Modality.text, config: { temperature: 0 }, input: 'What is the capital of Hungary? One word.' },
|
|
78
|
+
{ model: 'gpt-4o-mini', modality: DyNTS_AIMock_Modality.text, config: { temperature: 0 }, input: 'Reply with exactly: PONG' },
|
|
79
|
+
{ model: 'text-embedding-3-small', modality: DyNTS_AIMock_Modality.embedding, config: {}, input: 'the quick brown fox' },
|
|
80
|
+
{ model: 'text-embedding-3-small', modality: DyNTS_AIMock_Modality.embedding, config: {}, input: 'artificial intelligence' },
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
(async () => {
|
|
84
|
+
const key = loadKey();
|
|
85
|
+
if (!key) { console.error('OPENAI_API_KEY hianyzik'); process.exit(1); }
|
|
86
|
+
|
|
87
|
+
const harness = new DyNTS_AIMock_FixtureHarness_Service({
|
|
88
|
+
generator: makeGenerator(key),
|
|
89
|
+
registry: DyFM_OAI_Models,
|
|
90
|
+
allowRealSpend: true, // ⚠️ JOVAHAGYOTT futas (G1). Alapertelmezesben ez false.
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
fs.mkdirSync(OUT_DIR, { recursive: true });
|
|
94
|
+
const fixtures = [];
|
|
95
|
+
|
|
96
|
+
console.log('FIZETOS seed — kicsi es korlatozott, fixture-onkent lemezre irva\n');
|
|
97
|
+
|
|
98
|
+
for (const s of SEED) {
|
|
99
|
+
if (quotaStop) { console.log(` KIHAGYVA (kvota): ${s.model} / ${s.input.slice(0, 30)}`); continue; }
|
|
100
|
+
try {
|
|
101
|
+
const f = await harness.capture({ provider: 'open-ai', model: s.model, modality: s.modality,
|
|
102
|
+
config: s.config, input: s.input });
|
|
103
|
+
fixtures.push(f);
|
|
104
|
+
fs.writeFileSync(RAW_FILE, JSON.stringify(fixtures, null, 2)); // INKREMENTALIS
|
|
105
|
+
console.log(` ✅ ${s.model} [${s.modality}] "${s.input.slice(0, 32)}"`);
|
|
106
|
+
} catch (e) {
|
|
107
|
+
console.log(` ❌ ${s.model}: ${e.message.slice(0, 90)}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (fixtures.length) {
|
|
112
|
+
const src = DyNTS_AIMock_FixtureSerializer_Util.toConstantFile({
|
|
113
|
+
constName: 'DyNTS_AIMock_TextFixtures', fixtures, importPath: '../_models/interfaces/aim-fixture.interface',
|
|
114
|
+
headerNote: 'Valodi AI-generalasbol beegetve (live capture 2026-07-21). Kezzel NE szerkeszd.',
|
|
115
|
+
});
|
|
116
|
+
const again = DyNTS_AIMock_FixtureSerializer_Util.toConstantFile({
|
|
117
|
+
constName: 'DyNTS_AIMock_TextFixtures', fixtures, importPath: '../_models/interfaces/aim-fixture.interface',
|
|
118
|
+
headerNote: 'Valodi AI-generalasbol beegetve (live capture 2026-07-21). Kezzel NE szerkeszd.',
|
|
119
|
+
});
|
|
120
|
+
fs.writeFileSync(path.join(OUT_DIR, 'aim-seed.fixtures.ts'), src);
|
|
121
|
+
console.log(`\n determinizmus (ketszer szerializalva byte-azonos): ${src === again ? '✅ IGEN' : '❌ NEM'}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log(`\n📊 TENYLEGES fogyas: ${usage.calls} hivas · prompt ${usage.prompt} token · completion ${usage.completion} token`);
|
|
125
|
+
console.log(` ${fixtures.length} fixture → ${OUT_DIR}`);
|
|
126
|
+
})();
|
|
@@ -34,8 +34,14 @@ export class DyNTS_AI_ProviderError_Util {
|
|
|
34
34
|
type: 'error',
|
|
35
35
|
error: {
|
|
36
36
|
type: 'invalid_request_error',
|
|
37
|
-
|
|
37
|
+
// MERT (capture 2026-07-21, claude-opus-4-8 + temperature): a valodi uzenet ez, NEM a korabbi
|
|
38
|
+
// kozelitesem ("Extra inputs are not permitted").
|
|
39
|
+
message: `\`${set.param}\` is deprecated for this model.`,
|
|
38
40
|
},
|
|
41
|
+
// VERIFIED (capture 2026-07-21): a valodi Anthropic hiba-body TOP-LEVEL `request_id`-t is hoz —
|
|
42
|
+
// ez korabban hianyzott a sablonbol. Fixture-oknel a rogzitett valodi ertek szerepel; itt
|
|
43
|
+
// szintetikus placeholder, hogy az ALAK hu legyen.
|
|
44
|
+
request_id: 'req_mock',
|
|
39
45
|
},
|
|
40
46
|
reason: `invalid_request_error:${set.param}`,
|
|
41
47
|
};
|
|
@@ -82,17 +88,57 @@ export class DyNTS_AI_ProviderError_Util {
|
|
|
82
88
|
};
|
|
83
89
|
}
|
|
84
90
|
|
|
91
|
+
// MERT (capture 2026-07-21, gpt-4o-mini + temperature: 3): a valodi OpenAI range-hiba kodja
|
|
92
|
+
// `decimal_above_max_value`, NEM az altalam felteteleztt `invalid_value`, es a message formatuma ez:
|
|
93
|
+
// "Invalid 'temperature': decimal above maximum value. Expected a value <= 2, but got 3 instead."
|
|
85
94
|
return {
|
|
86
95
|
httpStatus: 400,
|
|
87
96
|
providerErrorBody: {
|
|
88
97
|
error: {
|
|
89
|
-
message: `Invalid
|
|
98
|
+
message: `Invalid '${set.param}': ${set.detail}.`,
|
|
90
99
|
type: 'invalid_request_error',
|
|
91
100
|
param: set.param,
|
|
92
|
-
code: '
|
|
101
|
+
code: 'decimal_above_max_value',
|
|
93
102
|
},
|
|
94
103
|
},
|
|
95
104
|
reason: `invalid_value:${set.param}`,
|
|
96
105
|
};
|
|
97
106
|
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Ismeretlen modell → **HTTP 404** (NEM 400), `code: 'model_not_found'`.
|
|
110
|
+
* MERT (capture 2026-07-21): `The model \`X\` does not exist or you do not have access to it.`
|
|
111
|
+
* @param set - provider + a nem letezo modell-azonosito
|
|
112
|
+
*/
|
|
113
|
+
static buildModelNotFoundError(
|
|
114
|
+
set: {
|
|
115
|
+
provider: string,
|
|
116
|
+
model: string,
|
|
117
|
+
}
|
|
118
|
+
): DyNTS_AI_ProviderError {
|
|
119
|
+
if (set.provider === this.anthropicProviderId) {
|
|
120
|
+
return {
|
|
121
|
+
httpStatus: 404,
|
|
122
|
+
providerErrorBody: {
|
|
123
|
+
type: 'error',
|
|
124
|
+
error: { type: 'not_found_error', message: `model: ${set.model}` },
|
|
125
|
+
request_id: 'req_mock',
|
|
126
|
+
},
|
|
127
|
+
reason: `not_found_error:${set.model}`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
httpStatus: 404,
|
|
133
|
+
providerErrorBody: {
|
|
134
|
+
error: {
|
|
135
|
+
message: `The model \`${set.model}\` does not exist or you do not have access to it.`,
|
|
136
|
+
type: 'invalid_request_error',
|
|
137
|
+
param: null,
|
|
138
|
+
code: 'model_not_found',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
reason: `model_not_found:${set.model}`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
98
144
|
}
|
|
@@ -22,6 +22,14 @@ export class DyNTS_AIMock_FixtureSerializer_Util {
|
|
|
22
22
|
constName: string,
|
|
23
23
|
fixtures: DyNTS_AIMock_Fixture[],
|
|
24
24
|
headerNote?: string,
|
|
25
|
+
/**
|
|
26
|
+
* A generalt fajl import-utvonala a `DyNTS_AIMock_Fixture` tipushoz.
|
|
27
|
+
*
|
|
28
|
+
* Default a publikus package-utvonal (KULSO consumer fixture-fajljaihoz). **A csomagon BELULRE**
|
|
29
|
+
* kerulo fixture-oknel relativ utat kell adni (pl. `'../_models/interfaces/aim-fixture.interface'`),
|
|
30
|
+
* kulonben a fajl onmagara hivatkozna a package-nevvel, ami build-kor nem oldodik fel.
|
|
31
|
+
*/
|
|
32
|
+
importPath?: string,
|
|
25
33
|
}
|
|
26
34
|
): string {
|
|
27
35
|
const sorted: DyNTS_AIMock_Fixture[] = this.sortFixtures(set.fixtures);
|
|
@@ -31,8 +39,10 @@ export class DyNTS_AIMock_FixtureSerializer_Util {
|
|
|
31
39
|
|
|
32
40
|
const note: string = set.headerNote ?? 'Auto-generalt fixture-keszlet — kezzel NE szerkeszd.';
|
|
33
41
|
|
|
42
|
+
const importPath: string = set.importPath ?? '@futdevpro/nts-dynamo/ai/ai-mock';
|
|
43
|
+
|
|
34
44
|
return [
|
|
35
|
-
`import { DyNTS_AIMock_Fixture } from '
|
|
45
|
+
`import { DyNTS_AIMock_Fixture } from '${importPath}';`,
|
|
36
46
|
'',
|
|
37
47
|
'/**',
|
|
38
48
|
` * ${note}`,
|
|
@@ -706,9 +706,19 @@ export class DyNTS_OAI_LLM_ServiceBase extends DyNTS_AI_LLM_ServiceBase {
|
|
|
706
706
|
}
|
|
707
707
|
|
|
708
708
|
/**
|
|
709
|
-
*
|
|
710
|
-
*
|
|
711
|
-
*
|
|
709
|
+
* ⚠️ **TUL TAG HEURISZTIKA — csak FALLBACK, ne ez legyen az igazsag forrasa.**
|
|
710
|
+
*
|
|
711
|
+
* Eredetileg (FR-047) azt felteteleztuk, hogy MINDEN `gpt-5.x` + o-series modell elutasitja a
|
|
712
|
+
* sampling-parametereket. **Live capture 2026-07-21 ezt MEGCAFOLTA:**
|
|
713
|
+
* - elutasit: `gpt-5.5`, `o3-mini`, `o4-mini`
|
|
714
|
+
* - **ELFOGADJA**: `gpt-5.4-mini`, `gpt-5.4-nano` (HTTP 200, `reasoning_tokens: 0`)
|
|
715
|
+
*
|
|
716
|
+
* Vagyis erre a ket modellre ez a regex **NEMAN kidobna ervenyes parametereket** — halkan rontva a
|
|
717
|
+
* kimenetet. Ezert az `applySamplingParams` a **registry `settingsSchema`-t reszesiti elonyben**, es ezt
|
|
718
|
+
* a heurisztikat CSAK akkor hasznalja, ha az adott modellhez nincs schema (regi fsm-verzio / ismeretlen
|
|
719
|
+
* modell). Amint a populalt schema mindenhol elerheto, ez a metodus elhagyhato.
|
|
720
|
+
*
|
|
721
|
+
* Reszletek: `documentations/plans/ai-mocking-system/CAPTURE-FINDINGS.md` §1.
|
|
712
722
|
*/
|
|
713
723
|
protected isReasoningModel(modelId: string): boolean {
|
|
714
724
|
return /^gpt-5/.test(modelId) || /^o[0-9]/.test(modelId);
|
|
@@ -529,6 +529,46 @@ describe('| DyNTS_ServerStatus_ControlService', () => {
|
|
|
529
529
|
expect(result.dbPingOk).toBe(false);
|
|
530
530
|
});
|
|
531
531
|
|
|
532
|
+
// DIAGNOSZTIKA (2026-07-22) — a "readiness 503, de az app kiszolgál" flotta-lelet miatt.
|
|
533
|
+
// A lényeg: a diag-mezők akkor is kitöltődnek, amikor a probe NEM-ready-t jelent — épp AKKOR
|
|
534
|
+
// kellenek, hogy a következő mérés eldöntse, a probe mér-e rosszul vagy a DB halott-e.
|
|
535
|
+
it('| should populate diagnostics fields EVEN when not ready (this is when they matter)', async () => {
|
|
536
|
+
const fakeConnection = {
|
|
537
|
+
readyState: 0,
|
|
538
|
+
db: undefined,
|
|
539
|
+
host: 'mongodb',
|
|
540
|
+
name: 'adventor',
|
|
541
|
+
models: { user: {}, preset: {} },
|
|
542
|
+
};
|
|
543
|
+
spyOn(service as any, 'getMongooseConnection').and.returnValue(fakeConnection);
|
|
544
|
+
|
|
545
|
+
const result = await service.checkDbReadiness();
|
|
546
|
+
|
|
547
|
+
expect(result.ready).toBe(false);
|
|
548
|
+
expect(result.dbHost).toBe('mongodb');
|
|
549
|
+
expect(result.dbName).toBe('adventor');
|
|
550
|
+
// 0 model a default connectionön = a data-layer NEM ezt a handle-t használja (a fő gyanú)
|
|
551
|
+
expect(result.dbModelCount).toBe(2);
|
|
552
|
+
expect(result.dbConnectionCount).toEqual(jasmine.any(Number));
|
|
553
|
+
expect(result.dbOtherReadyStates).toEqual(jasmine.any(Array));
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
it('| should stay ready even if diagnostics collection throws (probe must never fail)', async () => {
|
|
557
|
+
// a diag-gyűjtés SAJÁT try-ban van → a getter-robbanás nem ronthatja el a readiness-választ
|
|
558
|
+
const fakeConnection = {
|
|
559
|
+
readyState: 1,
|
|
560
|
+
db: { admin: () => ({ ping: async () => ({ ok: 1 }) }) },
|
|
561
|
+
get host(): string { throw new Error('diag boom'); },
|
|
562
|
+
};
|
|
563
|
+
spyOn(service as any, 'getMongooseConnection').and.returnValue(fakeConnection);
|
|
564
|
+
|
|
565
|
+
const result = await service.checkDbReadiness();
|
|
566
|
+
|
|
567
|
+
expect(result.ready).toBe(true);
|
|
568
|
+
expect(result.dbReadyState).toBe(1);
|
|
569
|
+
expect(result.dbPingOk).toBe(true);
|
|
570
|
+
});
|
|
571
|
+
|
|
532
572
|
it('| should NOT be ready when connected but ping fails (DB unresponsive)', async () => {
|
|
533
573
|
const fakeConnection = {
|
|
534
574
|
readyState: 1,
|
|
@@ -44,6 +44,24 @@ export interface DyNTS_DbReadiness {
|
|
|
44
44
|
serverVersion: string;
|
|
45
45
|
/** AZ APP saját verziója (`DyNTS_global_settings.systemVersion`) — deploy-verifikációhoz. */
|
|
46
46
|
appVersion?: string;
|
|
47
|
+
|
|
48
|
+
// --- DIAGNOSZTIKA (2026-07-22) — a flotta-szintű "readiness 503, de az app kiszolgál" lelet miatt ---
|
|
49
|
+
// Élesben mérve: az adventor / token-service / master-prompter MIND `dbReadyState:0`-t adott, miközben
|
|
50
|
+
// kiszolgáltak, a Mongo bizonyítottan élt, és a reconnect-guard (amely UGYANEZT a readyState-et olvassa)
|
|
51
|
+
// egyetlen warningot sem logolt. Öt hipotézist zártunk ki méréssel (több replika · két mongoose-példány ·
|
|
52
|
+
// esModule default-export · leszármazott-override · halott DB) — a gyökér-ok NEM dőlt el. Ezek a mezők
|
|
53
|
+
// teszik a KÖVETKEZŐ mérést döntővé, találgatás nélkül. Mind ADDITÍV + opcionális → nem törnek meg semmit.
|
|
54
|
+
|
|
55
|
+
/** Hány mongoose-connection létezik ebben a process-ben (`mongoose.connections.length`). >1 → nem a default-on megy a data-layer. */
|
|
56
|
+
dbConnectionCount?: number;
|
|
57
|
+
/** A default connection cél-hosztja (`connection.host`) — üres/undefined, ha a connect sosem futott le rajta. */
|
|
58
|
+
dbHost?: string;
|
|
59
|
+
/** A default connection adatbázis-neve (`connection.name`). */
|
|
60
|
+
dbName?: string;
|
|
61
|
+
/** Hány model van a default connectionre regisztrálva. 0 → a data-layer NEM ezt a connectiont használja. */
|
|
62
|
+
dbModelCount?: number;
|
|
63
|
+
/** A NEM-default connectionök readyState-jei — ha itt van 1-es, a probe rossz handle-t mér. */
|
|
64
|
+
dbOtherReadyStates?: number[];
|
|
47
65
|
}
|
|
48
66
|
|
|
49
67
|
export abstract class DyNTS_ServerStatus_ControlService<
|
|
@@ -232,6 +250,27 @@ export abstract class DyNTS_ServerStatus_ControlService<
|
|
|
232
250
|
dbPingOk = false;
|
|
233
251
|
}
|
|
234
252
|
|
|
253
|
+
// DIAGNOSZTIKA (2026-07-22): sosem dobhat — a probe-nak determinisztikusan kell válaszolnia,
|
|
254
|
+
// ezért a diag-gyűjtés SAJÁT try-ban van (ha bármelyik mező kiolvasása elszáll, a readiness
|
|
255
|
+
// válasz attól még ép marad).
|
|
256
|
+
let diagnostics: Partial<DyNTS_DbReadiness> = {};
|
|
257
|
+
try {
|
|
258
|
+
const conn: mongoose.Connection = this.getMongooseConnection();
|
|
259
|
+
const all: mongoose.Connection[] = mongoose.connections ?? [];
|
|
260
|
+
|
|
261
|
+
diagnostics = {
|
|
262
|
+
dbConnectionCount: all.length,
|
|
263
|
+
dbHost: conn?.host,
|
|
264
|
+
dbName: conn?.name,
|
|
265
|
+
dbModelCount: Object.keys(conn?.models ?? {}).length,
|
|
266
|
+
// a default connectiont kihagyjuk — csak a "van-e MÁSIK, élő handle" kérdés érdekes
|
|
267
|
+
dbOtherReadyStates: all.filter((c: mongoose.Connection): boolean => c !== conn)
|
|
268
|
+
.map((c: mongoose.Connection): number => c?.readyState ?? -1),
|
|
269
|
+
};
|
|
270
|
+
} catch (error) {
|
|
271
|
+
DyFM_Log.warn('(checkDbReadiness) diagnostics collection failed (non-fatal)', error);
|
|
272
|
+
}
|
|
273
|
+
|
|
235
274
|
return {
|
|
236
275
|
ready: dbReadyState === 1 && dbPingOk,
|
|
237
276
|
dbReadyState: dbReadyState,
|
|
@@ -239,6 +278,7 @@ export abstract class DyNTS_ServerStatus_ControlService<
|
|
|
239
278
|
uptime: +new Date() - +this.up,
|
|
240
279
|
serverVersion: this.serverVersion,
|
|
241
280
|
appVersion: this.appVersion,
|
|
281
|
+
...diagnostics,
|
|
242
282
|
};
|
|
243
283
|
}
|
|
244
284
|
|