@appaflytech/zeyrek-ai-mcp 0.0.7 → 0.0.8

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 (35) hide show
  1. package/dist/knowledge/backendConstraints.js +3 -0
  2. package/dist/knowledge/componentCatalog.js +59 -15
  3. package/dist/knowledge/normalize.js +459 -23
  4. package/dist/knowledge/propTypes.js +5 -4
  5. package/dist/knowledge/rules.js +110 -5
  6. package/dist/knowledge/styleResolve.js +6 -1
  7. package/dist/platform/http.js +10 -2
  8. package/dist/platform/screenshot.js +80 -8
  9. package/dist/platform/strictArguments.js +32 -0
  10. package/dist/platform/writeDiff.js +6 -3
  11. package/dist/resources/examples/page-sign-in.json +1 -1
  12. package/dist/resources/guides/component.md +1 -1
  13. package/dist/resources/guides/expressions.md +6 -0
  14. package/dist/resources/guides/getting-started.md +2 -0
  15. package/dist/resources/guides/layout.md +6 -0
  16. package/dist/resources/guides/microservice.md +105 -5
  17. package/dist/resources/guides/page.md +81 -18
  18. package/dist/resources/guides/translation.md +11 -10
  19. package/dist/resources/guides/workflow.md +50 -1
  20. package/dist/resources/schema-fingerprint.json +2 -2
  21. package/dist/resources/schemas/CreateMicroserviceCommand.json +4 -1
  22. package/dist/resources/schemas/CreateWorkflowCommand.json +4 -1
  23. package/dist/resources/schemas/PreviewMicroserviceCommand.json +4 -1
  24. package/dist/resources/schemas/PreviewWorkflowCommand.json +4 -1
  25. package/dist/resources/schemas/StepDto.json +4 -1
  26. package/dist/resources/schemas/UpdateMicroserviceCommand.json +4 -1
  27. package/dist/resources/schemas/UpdateWorkflowCommand.json +4 -1
  28. package/dist/server.js +2 -1
  29. package/dist/tools/flows.js +9 -3
  30. package/dist/tools/layouts.js +4 -4
  31. package/dist/tools/microservices.js +70 -6
  32. package/dist/tools/pages.js +127 -57
  33. package/dist/tools/queries.js +72 -6
  34. package/dist/tools/workflows.js +9 -5
  35. package/package.json +1 -1
@@ -6,10 +6,57 @@ import { unmappedMembers, withUnmappedMembers } from '../knowledge/schemaGuard.j
6
6
  import { handle } from '../platform/responses.js';
7
7
  import { z } from 'zod';
8
8
  import { evaluatePolicy, enforcePolicy, attachFindings } from '../knowledge/policy.js';
9
- import { policyRules } from '../knowledge/rules.js';
9
+ import { policyRules, rawQueryParameterNames } from '../knowledge/rules.js';
10
+ import { PlatformApiError } from '../platform/errors.js';
10
11
  import { constraintSummary } from '../knowledge/backendConstraints.js';
11
12
  const policyOverrideParam = z.boolean().optional()
12
13
  .describe('true: politika block bulgularını warn\'a indirir (bilinçli istisna; yanıtta işaretlenir)');
14
+ function inferredParameterType(value) {
15
+ if (typeof value === 'number')
16
+ return Number.isInteger(value) ? 'number' : 'float';
17
+ if (typeof value === 'boolean')
18
+ return 'bool';
19
+ if (Array.isArray(value))
20
+ return 'array';
21
+ if (value !== null && typeof value === 'object')
22
+ return 'object';
23
+ return 'text';
24
+ }
25
+ /**
26
+ * G-13 — `PreviewQueryCommand` değeri yalnız `parameters[].value`'dan okur; üst düzey `parameters`
27
+ * argümanı şemada yokken SDK tarafından hata vermeden atılıyordu ve sorgu NULL'la koşuyordu.
28
+ * Argüman artık komutun kendi alanına bağlanır.
29
+ */
30
+ function bindPreviewParameters(definition, parameters, notes) {
31
+ const names = Object.keys(parameters ?? {});
32
+ if (parameters === undefined || names.length === 0)
33
+ return definition;
34
+ const rows = (Array.isArray(definition.parameters) ? definition.parameters : []);
35
+ const conflicts = names.filter(name => {
36
+ const row = rows.find(entry => entry?.name === name);
37
+ return row !== undefined && row.value !== undefined && JSON.stringify(row.value) !== JSON.stringify(parameters[name]);
38
+ });
39
+ if (conflicts.length > 0) {
40
+ throw new PlatformApiError(`parameters ile definition.parameters aynı adı farklı değerle taşıyor: ${conflicts.map(name => `'${name}'`).join(', ')}. Değeri tek yerde verin.`, 400);
41
+ }
42
+ const bound = rows.map(row => typeof row?.name === 'string' && row.name in parameters ? { ...row, value: parameters[row.name] } : row);
43
+ const added = names.filter(name => !rows.some(row => row?.name === name));
44
+ notes.push(`parameters definition.parameters[].value'ya bağlandı: ${names.join(', ')}${added.length > 0 ? ` (tipi değerden çıkarılıp eklenen satır: ${added.join(', ')})` : ''}`);
45
+ return {
46
+ ...definition,
47
+ parameters: [...bound, ...added.map(name => ({ name, type: inferredParameterType(parameters[name]), value: parameters[name] }))]
48
+ };
49
+ }
50
+ /** `language` sayılmaz: platform `{{language}}` kullanan sorguya değeri kendisi ekler (`PreviewQueryCommand.cs`). */
51
+ function unboundPreviewParameters(definition) {
52
+ const rows = (Array.isArray(definition.parameters) ? definition.parameters : []);
53
+ return rawQueryParameterNames(definition.rawQuery)
54
+ .filter(name => name.toLowerCase() !== 'language')
55
+ .filter(name => {
56
+ const value = rows.find(row => row?.name === name)?.value;
57
+ return value === undefined || value === null || (typeof value === 'string' && value.trim() === '');
58
+ });
59
+ }
13
60
  export function registerQueryTools(server, platform) {
14
61
  const config = platform.config;
15
62
  server.registerTool('query_list', {
@@ -26,7 +73,7 @@ export function registerQueryTools(server, platform) {
26
73
  }, handle(config, ({ project, environment, id }) => platform.tenant('GET', project, `/queries/${id}`, { environment })));
27
74
  server.registerTool('query_create', {
28
75
  title: 'Query oluştur',
29
- description: "Yeni query tanımlar (ham SQL). definition = CreateQueryCommand gövdesi. AGREGASYON VE RAPORLAMANIN YOLU BUDUR (SUM/COUNT/AVG/GROUP BY, dönemsel özet, KPI) — view_* bir TAM METİN ARAMA indeksidir, özet üretmez (09-02 M-3). VAR OLAN SATIRLARDAN TÜRETİLEN SATIR YAZMANIN DA YOLU BUDUR: 'INSERT … SELECT' kaydedip query kaynaklı bir uçtan çalıştırmak, geçmiş/hareket/junction tablosunu TEK çağrıda doldurur ve hiçbir id elle taşınmaz (ölçüldü 2026-09-07; reçete platform_guide('entity') §'Toplu ve türetilmiş satır'). Kayıt sırasında gövde bir kez ÇALIŞTIRILIR ama geri alınır — yazan sorguyu kaydetmek satır bırakmaz ve 'returnScheme' boş döner. Kayıtlı query'nin parametreleri parameterScheme ile tanımlanır ve runtime'da bağlanır; tüketimi source:'query' microservice'idir. PARAMETRENİN DEĞERİ HER ZAMAN ÇAĞRIDAN GELİR (body → query-string → header): parametreye ifade kaynağı verilemez (parameters[].source komut şemasında yoktur, platform sessizce atar) ve middleware'in kurduğu user bu yola girmez. Kimlik/tenant kapsamı sunucu tarafında zorlanacaksa sorguyu bir workflow query adımından çağırın — reçete platform_guide('microservice') §'Kimlik kapsaması × uç kaynağı'. BOŞ STRING parametre NULL'a çevrilir: '= @p' koşulu hiçbir satırla eşleşmez ve sorgu sessizce 0 satır döner — 'filtre yok' için (@p IS NULL OR ...) yazın ya da sentinel kullanın. Yorum içindeki belirteç parametre sayılmaz. SQL çalıştırılamazsa kayıt YİNE de oluşur: returnScheme boş kalır ve yanıttaki message nedeni söyler — SQL'i düzeltip query_update ile kaydedin. SORGUNUN KENDİ AÇIKLAMASI VAR: `description` alanını doldurun — sorgu listesinde ad ve slug dışında ipucu yoktur ve ucun açıklaması (MS-014) bunun yerine geçmez, çünkü bir sorgu birden çok uçtan tüketilir; boş bırakılırsa gateway `QRY-006` uyarısı düşürür (yazmayı durdurmaz). " + constraintSummary('CreateQueryCommand'),
76
+ description: "Yeni query tanımlar (ham SQL). definition = CreateQueryCommand gövdesi. AGREGASYON VE RAPORLAMANIN YOLU BUDUR (SUM/COUNT/AVG/GROUP BY, dönemsel özet, KPI) — view_* bir TAM METİN ARAMA indeksidir, özet üretmez (09-02 M-3). VAR OLAN SATIRLARDAN TÜRETİLEN SATIR YAZMANIN DA YOLU BUDUR: 'INSERT … SELECT' kaydedip query kaynaklı bir uçtan çalıştırmak, geçmiş/hareket/junction tablosunu TEK çağrıda doldurur ve hiçbir id elle taşınmaz (ölçüldü 2026-09-07; reçete platform_guide('entity') §'Toplu ve türetilmiş satır'). Kayıt sırasında gövde bir kez ÇALIŞTIRILIR ama geri alınır — yazan sorguyu kaydetmek satır bırakmaz ve 'returnScheme' boş döner. Kayıtlı query'nin parametreleri parameterScheme ile tanımlanır ve runtime'da bağlanır; tüketimi source:'query' microservice'idir. PARAMETRENİN DEĞERİ HER ZAMAN ÇAĞRIDAN GELİR (body → query-string → header): parametreye ifade kaynağı verilemez (parameters[].source komut şemasında yoktur, platform sessizce atar) ve middleware'in kurduğu user bu yola girmez. Kimlik/tenant kapsamı sunucu tarafında zorlanacaksa sorguyu bir workflow query adımından çağırın — reçete platform_guide('microservice') §'Kimlik kapsaması × uç kaynağı'. BOŞ STRING parametre NULL'a çevrilir: '= @p' koşulu hiçbir satırla eşleşmez ve sorgu sessizce 0 satır döner — 'filtre yok' için (@p IS NULL OR ...) yazın ya da sentinel kullanın; (@p = '' OR ...) kalıbı hiçbir zaman eşleşmez ve gateway `QRY-007` uyarısı düşürür. Yorum içindeki belirteç parametre sayılmaz. SQL çalıştırılamazsa kayıt YİNE de oluşur: returnScheme boş kalır ve yanıttaki message nedeni söyler — SQL'i düzeltip query_update ile kaydedin. SORGUNUN KENDİ AÇIKLAMASI VAR: `description` alanını doldurun — sorgu listesinde ad ve slug dışında ipucu yoktur ve ucun açıklaması (MS-014) bunun yerine geçmez, çünkü bir sorgu birden çok uçtan tüketilir; boş bırakılırsa gateway `QRY-006` uyarısı düşürür (yazmayı durdurmaz). " + constraintSummary('CreateQueryCommand'),
30
77
  inputSchema: { project: projectParam, environment: environmentParam, definition: definitionParam, policyOverride: policyOverrideParam },
31
78
  annotations: writes
32
79
  }, handle(config, async ({ project, environment, definition, policyOverride }) => {
@@ -59,12 +106,31 @@ export function registerQueryTools(server, platform) {
59
106
  server.registerTool('query_preview', {
60
107
  title: 'Query önizle',
61
108
  description: "Kaydedilmemiş query tanımını datasource üzerinde çalıştırır. definition = PreviewQueryCommand gövdesi. Preview ROLLBACK edilir: yazan bir sorgu (INSERT/UPDATE/DELETE) çalışır, affectedRowCount gerçek sayıyı döner ama SATIR KALMAZ (ölçüldü, 09-04 Y-19) — yazmayı doğrulamak için sorguyu kaydedip microservice/workflow üzerinden çalıştırın. YANITTA ROLLBACK İŞARETİ YOKTUR: 2026-09-07'de ölçüldü, yazan sorgunun yanıtı yalnız { affectedRowCount, elapsedMilliseconds } taşıyor — sayı başarı gibi görünür, tek kanıt sonradan row_list çekmektir. BOŞ STRING parametre NULL'a çevrilir (üç koşuda ölçüldü): '= @p' hiçbir satırla eşleşmez, 0 satır döner ve hata yoktur. Davranış kuralları: platform_guide('microservice'). " + constraintSummary('PreviewQueryCommand'),
62
- inputSchema: { project: projectParam, environment: environmentParam, datasourceId: guid, definition: definitionParam, language: languageParam, policyOverride: policyOverrideParam },
109
+ inputSchema: {
110
+ project: projectParam,
111
+ environment: environmentParam,
112
+ datasourceId: guid,
113
+ definition: definitionParam,
114
+ parameters: z.record(z.unknown()).optional()
115
+ .describe("Önizleme değerleri (ad → değer). definition.parameters[] içindeki aynı adlı satırın value'suna yazılır; satır yoksa tipi değerden çıkarılarak eklenir (tam sayı → number, ondalık → float, true/false → bool, diğerleri → text). Aynı ad definition.parameters'ta FARKLI bir value ile de varsa çağrı gönderilmez."),
116
+ language: languageParam,
117
+ policyOverride: policyOverrideParam
118
+ },
63
119
  annotations: writes
64
- }, handle(config, async ({ project, environment, datasourceId, definition, language, policyOverride }) => {
65
- const findings = enforcePolicy(evaluatePolicy(config, policyRules, 'query', definition, { operation: 'preview' }, policyOverride));
120
+ }, handle(config, async ({ project, environment, datasourceId, definition: given, parameters, language, policyOverride }) => {
66
121
  const notes = [];
122
+ const definition = bindPreviewParameters(given, parameters, notes);
123
+ const findings = enforcePolicy(evaluatePolicy(config, policyRules, 'query', definition, { operation: 'preview' }, policyOverride));
67
124
  const headers = languageHeader(language, notes);
68
- return attachFindings(withNormalization(await platform.tenant('POST', project, `/queries/${datasourceId}/preview`, { environment, body: definition, headers }), notes), findings);
125
+ const payload = await platform.tenant('POST', project, `/queries/${datasourceId}/preview`, { environment, body: definition, headers });
126
+ const unbound = unboundPreviewParameters(definition);
127
+ const withUnbound = unbound.length > 0 && payload && typeof payload === 'object' && !Array.isArray(payload)
128
+ ? {
129
+ ...payload,
130
+ unboundParameters: unbound,
131
+ unboundParametersNote: "rawQuery bu parametrelere başvuruyor ama değerleri yok ya da boş string (platform boş string'i NULL'a çevirir) — sorgu onları NULL ile koştu. Değeri üst düzey 'parameters' ya da definition.parameters[].value ile verin."
132
+ }
133
+ : payload;
134
+ return attachFindings(withNormalization(withUnbound, notes), findings);
69
135
  }));
70
136
  }
@@ -4,7 +4,7 @@ import { evaluatePolicy, enforcePolicy, attachFindings } from '../knowledge/poli
4
4
  import { workflowOutline, resolvePart, resolvePatchOperations } from '../knowledge/outlines.js';
5
5
  import { patchResult, baseVersionOf } from '../platform/patch.js';
6
6
  import { writeDiff, withWriteDiff } from '../platform/writeDiff.js';
7
- import { policyRules, microfunctionStepFindings } from '../knowledge/rules.js';
7
+ import { policyRules, microfunctionStepFindings, undefinedInputFieldFindings } from '../knowledge/rules.js';
8
8
  import { languageHeader } from '../knowledge/languageCodes.js';
9
9
  import { handle } from '../platform/responses.js';
10
10
  import fastJsonPatch from 'fast-json-patch';
@@ -118,7 +118,8 @@ export function registerWorkflowTools(server, platform) {
118
118
  const normalized = normalizeWorkflowDefinition(definition);
119
119
  const findings = enforcePolicy([
120
120
  ...evaluatePolicy(config, policyRules, 'workflow', definition, { operation: 'create', workflowKind: definition.type }, policyOverride),
121
- ...await microfunctionStepFindings(platform, project, environment, definition, definition.type, policyOverride)
121
+ ...await microfunctionStepFindings(platform, project, environment, definition, definition.type, policyOverride),
122
+ ...await undefinedInputFieldFindings(platform, project, environment, definition, definition.type, policyOverride)
122
123
  ]);
123
124
  const drift = unmappedMembers('CreateWorkflowCommand', definition);
124
125
  const payload = await platform.tenant('POST', project, `/workflows/${applicationId}`, { environment, body: definition });
@@ -133,7 +134,8 @@ export function registerWorkflowTools(server, platform) {
133
134
  const normalized = normalizeWorkflowDefinition(definition);
134
135
  const findings = enforcePolicy([
135
136
  ...evaluatePolicy(config, policyRules, 'workflow', definition, { operation: 'update', workflowKind: definition.type }, policyOverride),
136
- ...await microfunctionStepFindings(platform, project, environment, definition, definition.type, policyOverride)
137
+ ...await microfunctionStepFindings(platform, project, environment, definition, definition.type, policyOverride),
138
+ ...await undefinedInputFieldFindings(platform, project, environment, definition, definition.type, policyOverride)
137
139
  ]);
138
140
  const drift = unmappedMembers('UpdateWorkflowCommand', definition);
139
141
  const payload = await platform.tenant('PUT', project, `/workflows/${applicationId}/${id}`, { environment, body: definition });
@@ -153,7 +155,8 @@ export function registerWorkflowTools(server, platform) {
153
155
  const normalized = normalizeWorkflowDefinition(patched);
154
156
  const findings = enforcePolicy([
155
157
  ...evaluatePolicy(config, policyRules, 'workflow', patched, { operation: 'update', workflowKind: patched.type }, policyOverride),
156
- ...await microfunctionStepFindings(platform, project, environment, patched, patched.type, policyOverride)
158
+ ...await microfunctionStepFindings(platform, project, environment, patched, patched.type, policyOverride),
159
+ ...await undefinedInputFieldFindings(platform, project, environment, patched, patched.type, policyOverride)
157
160
  ]);
158
161
  const drift = introducedUnmappedMembers('UpdateWorkflowCommand', (current?.data ?? current), patched);
159
162
  // Gövde değil FARK gönderilir: gateway normalizasyonları da op'a çevrilsin diye net diff
@@ -198,7 +201,8 @@ export function registerWorkflowTools(server, platform) {
198
201
  }
199
202
  const findings = enforcePolicy([
200
203
  ...evaluatePolicy(config, policyRules, 'workflow', definition, { operation: 'preview', workflowKind: definition.type }, policyOverride),
201
- ...await microfunctionStepFindings(platform, project, environment, definition, definition.type, policyOverride)
204
+ ...await microfunctionStepFindings(platform, project, environment, definition, definition.type, policyOverride),
205
+ ...await undefinedInputFieldFindings(platform, project, environment, definition, definition.type, policyOverride)
202
206
  ]);
203
207
  const payload = await platform.tenant('POST', project, `/workflows/${applicationId}/preview`, { environment, body: definition, headers: languageHeader(language, normalized) });
204
208
  return attachFindings(withNormalization(payload, normalized), findings);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appaflytech/zeyrek-ai-mcp",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "type": "module",
5
5
  "description": "Zeyrek (NgApps) platform APIs as MCP tools — data, logic and Studio design surface in one gateway",
6
6
  "license": "UNLICENSED",