@appaflytech/zeyrek-ai-mcp 0.0.4 → 0.0.6

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/.env.example +8 -3
  2. package/.env.production.example +2 -0
  3. package/README.md +229 -193
  4. package/dist/config.js +20 -2
  5. package/dist/knowledge/backendConstraints.js +897 -0
  6. package/dist/knowledge/componentCatalog.js +196 -42
  7. package/dist/knowledge/coverage.js +43 -0
  8. package/dist/knowledge/flowGuards.js +30 -0
  9. package/dist/knowledge/guideSections.js +49 -0
  10. package/dist/knowledge/hydrate.js +97 -0
  11. package/dist/knowledge/languageCodes.js +36 -0
  12. package/dist/knowledge/languages.js +105 -0
  13. package/dist/knowledge/layoutSummary.js +10 -0
  14. package/dist/knowledge/localization.js +51 -0
  15. package/dist/knowledge/normalize.js +449 -16
  16. package/dist/knowledge/outlines.js +136 -12
  17. package/dist/knowledge/propTypes.js +80 -0
  18. package/dist/knowledge/rules.js +618 -43
  19. package/dist/knowledge/schemaGuard.js +199 -0
  20. package/dist/knowledge/styleResolve.js +63 -4
  21. package/dist/observability/trace.js +27 -3
  22. package/dist/platform/errors.js +46 -4
  23. package/dist/platform/http.js +33 -4
  24. package/dist/platform/patch.js +27 -0
  25. package/dist/platform/refs.js +104 -0
  26. package/dist/platform/responses.js +9 -2
  27. package/dist/platform/screenshot.js +527 -16
  28. package/dist/platform/secrets.js +40 -0
  29. package/dist/platform/tokenVault.js +89 -0
  30. package/dist/platform/writeDiff.js +281 -0
  31. package/dist/resources/examples/layout-app-shell.json +1 -1
  32. package/dist/resources/examples/microservice-table-list.json +2 -4
  33. package/dist/resources/examples/page-dynamic-form.json +2 -2
  34. package/dist/resources/examples/page-flex-sections.json +99 -0
  35. package/dist/resources/examples/page-sign-in.json +3 -2
  36. package/dist/resources/guides/component.md +69 -8
  37. package/dist/resources/guides/entity.md +404 -16
  38. package/dist/resources/guides/expressions.md +44 -2
  39. package/dist/resources/guides/external-component.md +9 -0
  40. package/dist/resources/guides/getting-started.md +77 -7
  41. package/dist/resources/guides/layout.md +53 -10
  42. package/dist/resources/guides/microservice.md +226 -13
  43. package/dist/resources/guides/middleware.md +89 -1
  44. package/dist/resources/guides/page.md +383 -46
  45. package/dist/resources/guides/translation.md +126 -8
  46. package/dist/resources/guides/view.md +16 -1
  47. package/dist/resources/guides/workflow.md +198 -27
  48. package/dist/resources/knowledge.js +5 -0
  49. package/dist/resources/rules.js +27 -0
  50. package/dist/resources/schema-fingerprint.json +8 -0
  51. package/dist/resources/schemas/CreateBulkRowCommand.json +33 -0
  52. package/dist/resources/schemas/CreateDatasourceCommand.json +15 -6
  53. package/dist/resources/schemas/CreateDiscoveredEntitiesCommand.json +19 -8
  54. package/dist/resources/schemas/CreateEntityCommand.json +52 -12
  55. package/dist/resources/schemas/CreateMicroserviceCommand.json +26 -2
  56. package/dist/resources/schemas/CreateQueryCommand.json +56 -3
  57. package/dist/resources/schemas/CreateRowCommand.json +38 -0
  58. package/dist/resources/schemas/CreateViewCommand.json +13 -10
  59. package/dist/resources/schemas/CreateWorkflowCommand.json +95 -14
  60. package/dist/resources/schemas/GetRowsQuery.json +3 -0
  61. package/dist/resources/schemas/PreviewMicroserviceCommand.json +16 -0
  62. package/dist/resources/schemas/PreviewQueryCommand.json +5 -2
  63. package/dist/resources/schemas/PreviewWorkflowCommand.json +34 -9
  64. package/dist/resources/schemas/StepDto.json +23 -3
  65. package/dist/resources/schemas/UpdateBulkRowCommand.json +33 -0
  66. package/dist/resources/schemas/UpdateDatasourceCommand.json +15 -6
  67. package/dist/resources/schemas/UpdateEntityCommand.json +49 -10
  68. package/dist/resources/schemas/UpdateMicroserviceCommand.json +28 -3
  69. package/dist/resources/schemas/UpdateQueryCommand.json +13 -3
  70. package/dist/resources/schemas/UpdateRowCommand.json +40 -0
  71. package/dist/resources/schemas/UpdateViewCommand.json +15 -10
  72. package/dist/resources/schemas/UpdateWorkflowCommand.json +95 -14
  73. package/dist/server.js +4 -0
  74. package/dist/tools/access.js +3 -3
  75. package/dist/tools/applications.js +1 -1
  76. package/dist/tools/automations.js +63 -30
  77. package/dist/tools/common.js +39 -0
  78. package/dist/tools/components.js +16 -7
  79. package/dist/tools/datasources.js +83 -21
  80. package/dist/tools/deployments.js +34 -2
  81. package/dist/tools/dtos.js +25 -12
  82. package/dist/tools/entities.js +113 -28
  83. package/dist/tools/externalComponents.js +9 -3
  84. package/dist/tools/files.js +20 -6
  85. package/dist/tools/flows.js +110 -11
  86. package/dist/tools/folders.js +7 -2
  87. package/dist/tools/globalFunctions.js +63 -0
  88. package/dist/tools/layouts.js +103 -29
  89. package/dist/tools/microservices.js +229 -38
  90. package/dist/tools/organizations.js +5 -6
  91. package/dist/tools/pages.js +365 -100
  92. package/dist/tools/platformInfo.js +152 -11
  93. package/dist/tools/projects.js +183 -33
  94. package/dist/tools/queries.js +32 -10
  95. package/dist/tools/rows.js +159 -45
  96. package/dist/tools/screenWrite.js +59 -0
  97. package/dist/tools/screens.js +28 -0
  98. package/dist/tools/translations.js +24 -8
  99. package/dist/tools/views.js +20 -10
  100. package/dist/tools/workflows.js +33 -16
  101. package/package.json +6 -3
@@ -62,6 +62,8 @@ export function entityOutline(definition) {
62
62
  slug: definition.slug,
63
63
  name: definition.name,
64
64
  datasourceId: definition.datasourceId,
65
+ localizationEntityId: definition.localizationEntityId ?? null,
66
+ localizationParentId: definition.localizationParentId ?? null,
65
67
  fieldCount: asArray(definition.fields).length,
66
68
  fields: asArray(definition.fields).map(field => ({
67
69
  id: field.id,
@@ -73,10 +75,116 @@ export function entityOutline(definition) {
73
75
  relationId: field.relationId ?? null,
74
76
  isLocalized: Boolean(field.isLocalized)
75
77
  })),
78
+ indexCount: asArray(definition.indexes).length,
79
+ // Index'ler alanlardan çok daha az sayıdadır; tam projeksiyon outline'ı şişirmez ve yazılan
80
+ // index'in kanıtı ayrı bir tur istemez (B-45'in `entity_get`/`entity_create` ayağı).
81
+ ...(asArray(definition.indexes).length > 0
82
+ ? {
83
+ indexes: asArray(definition.indexes).map(index => ({
84
+ id: index.id,
85
+ name: index.name,
86
+ unique: Boolean(index.unique),
87
+ fieldIds: Array.isArray(index.fieldIds) ? index.fieldIds : []
88
+ }))
89
+ }
90
+ : {}),
76
91
  view: 'outline',
77
92
  hint: "Bir alanın tam gövdesi için view:'part', part:'fields[slug=<slug>]'; değişiklik için entity_patch. isLocalized alanlar için platform_guide('entity') §'Çoklu dilli alan'."
78
93
  };
79
94
  }
95
+ const identityKeys = ['id', 'slug', 'name', 'elementId', 'stepId'];
96
+ /**
97
+ * Eklenen öğeyi FİNAL gövdede kimliğinden bulur. Konumsal ("dizinin son elemanı") arama
98
+ * platform diziye kendi öğesini eklediğinde yanlış kaydı gösterir: audit trail açık bir
99
+ * entity'ye alan eklendiğinde platform `fields`in sonuna dört `sys_*` alanı ekler ve rapor
100
+ * eklenen alan yerine `sys_updated_user_id`'yi gösteriyordu (ölçüldü 2026-09-08).
101
+ */
102
+ function appendedPosition(section, value) {
103
+ if (!value || typeof value !== 'object')
104
+ return -1;
105
+ const source = value;
106
+ for (const key of identityKeys) {
107
+ const wanted = source[key];
108
+ if (wanted === undefined || wanted === null || wanted === '')
109
+ continue;
110
+ const position = section.findIndex(item => Boolean(item) && typeof item === 'object' && item[key] === wanted);
111
+ if (position >= 0)
112
+ return position;
113
+ }
114
+ return -1;
115
+ }
116
+ /**
117
+ * Patch'in DOKUNDUĞU bölümleri kayıttan çıkarır (S-8 · P2-1).
118
+ *
119
+ * `entity_patch` yanıtı bir outline'dır ve outline `indexes` taşımıyordu: 2026-09-06 koşusunda
120
+ * iki index yazıldı, "yazdım" demenin kanıtı yanıtta olmadığı için her entity için ayrı bir
121
+ * `entity_get(view:'part', part:'indexes[0]')` turu atıldı. Keşif çağrısı oranı o koşuda %30.1'di.
122
+ *
123
+ * Outline'ın kısa kalma amacı korunur: TAM gövde değil, yalnız yamanın adreslediği bölüm döner —
124
+ * dizide de yalnız dokunulan eleman. Yollar `resolvePatchOperations`'tan geçmiş, yani indekse
125
+ * çevrilmiş olmalıdır; `-` (dizi sonu) eklenen son elemana çözülür.
126
+ */
127
+ export function patchedSections(document, operations) {
128
+ const explicit = new Map();
129
+ const appends = new Map();
130
+ const whole = new Set();
131
+ for (const operation of operations) {
132
+ const path = typeof operation.path === 'string' ? operation.path : '';
133
+ if (!path.startsWith('/'))
134
+ continue;
135
+ const [key, index] = path.split('/').slice(1);
136
+ if (!key || !Object.hasOwn(document, key))
137
+ continue;
138
+ if (!Array.isArray(document[key]) || index === undefined) {
139
+ whole.add(key);
140
+ continue;
141
+ }
142
+ // Dizi sonu (`-`) yolu FİNAL gövdede tek bir indekse çözülemez: aynı çağrıda iki `add`
143
+ // varsa ikisi de son elemanı gösterir ve rapor bir tanesini yutardı (ölçüldü 2026-09-06,
144
+ // gerçek uçta: iki index eklendi, yanıt birini gösterdi). Eklenen gövde saklanır ve önce
145
+ // KİMLİKTEN aranır; kimlik tutmazsa son N eleman alınır.
146
+ if (index === '-') {
147
+ appends.set(key, [...(appends.get(key) ?? []), operation.value]);
148
+ continue;
149
+ }
150
+ const position = Number(index);
151
+ if (!Number.isInteger(position) || position < 0)
152
+ continue;
153
+ const positions = explicit.get(key) ?? new Set();
154
+ positions.add(position);
155
+ explicit.set(key, positions);
156
+ }
157
+ const touched = {};
158
+ for (const key of whole)
159
+ touched[key] = document[key];
160
+ for (const key of new Set([...explicit.keys(), ...appends.keys()])) {
161
+ if (whole.has(key))
162
+ continue;
163
+ const section = document[key];
164
+ const wanted = new Set();
165
+ for (const position of explicit.get(key) ?? []) {
166
+ if (position < section.length)
167
+ wanted.add(position);
168
+ }
169
+ let unresolved = 0;
170
+ for (const value of appends.get(key) ?? []) {
171
+ const position = appendedPosition(section, value);
172
+ if (position >= 0)
173
+ wanted.add(position);
174
+ else
175
+ unresolved++;
176
+ }
177
+ for (let step = 0; step < unresolved; step++) {
178
+ const position = section.length - 1 - step;
179
+ if (position >= 0)
180
+ wanted.add(position);
181
+ }
182
+ if (wanted.size === 0)
183
+ continue;
184
+ touched[key] = [...wanted].sort((left, right) => left - right).map(position => section[position]);
185
+ }
186
+ return touched;
187
+ }
80
188
  const segmentPattern = /^(\w+)(?:\[(?:(\d+)|(\w+)=([^\]]+))\])?$/;
81
189
  export function resolvePart(definition, part) {
82
190
  let current = definition;
@@ -111,7 +219,7 @@ function unescapePointer(segment) {
111
219
  * `*_get`'in `part` sözdizimindeki seçiciyi (`steps[id=…]`, `fields[slug=…]`) patch yollarında da
112
220
  * kabul edip indekse çeviriyoruz; çözülemeyen seçici, gövde platforma GİTMEDEN hata verir.
113
221
  */
114
- export function resolvePatchPointer(document, path) {
222
+ export function resolvePatchPointer(document, path, readTool = 'workflow_get', op = '') {
115
223
  if (!path.startsWith('/'))
116
224
  throw new Error(`JSON Patch yolu '/' ile başlamalı: '${path}'`);
117
225
  const segments = path.split('/').slice(1);
@@ -131,11 +239,21 @@ export function resolvePatchPointer(document, path) {
131
239
  const [, key, field, value] = match;
132
240
  const collection = current && typeof current === 'object' ? current[key] : undefined;
133
241
  if (!Array.isArray(collection)) {
134
- throw new Error(`Patch yolu çözülemedi: '${path}' — '${key}' bir dizi değil. Mevcut yapıyı workflow_get view:'outline' ile okuyun.`);
242
+ throw new Error(`Patch yolu çözülemedi: '${path}' — '${key}' bir dizi değil. Mevcut yapıyı ${readTool} view:'outline' ile okuyun.`);
135
243
  }
136
244
  const index = collection.findIndex(entry => entry && typeof entry === 'object' && String(entry[field]) === value);
137
245
  if (index === -1) {
138
- throw new Error(`Patch yolu çözülemedi: '${path}' — '${key}' dizisinde ${field}='${value}' yok. Mevcut id/ad değerlerini workflow_get view:'outline' ile okuyun.`);
246
+ const available = collection
247
+ .map(entry => entry && typeof entry === 'object' ? entry[field] : undefined)
248
+ .filter(entry => entry !== undefined && entry !== null)
249
+ .map(entry => `'${String(entry)}'`);
250
+ // Seçici VAR OLAN bir öğeyi adresler; yeni öğe eklemenin yolu dizi sonu (`-`) segmentidir.
251
+ // 2026-09-06 koşusunda ajan eksik bir iteratee'yi `add` ile eklemeye çalıştı, mesaj yalnız
252
+ // "yok" dedi ve ajan diziyi 13 girdiyle baştan yazmak zorunda kaldı (S-5 · P0-2 Step 6).
253
+ const addHint = op === 'add'
254
+ ? ` EKLEMEK istiyorsanız seçici değil dizi sonu yolunu kullanın: '${path.slice(0, path.indexOf(`${key}[`) + key.length)}/-' — seçici yalnız VAR OLAN öğeyi adresler.`
255
+ : '';
256
+ throw new Error(`Patch yolu çözülemedi: '${path}' — '${key}' dizisinde ${field}='${value}' yok. Mevcut değerler: ${available.length > 0 ? available.join(', ') : '(hiç)'}.${addHint} Tam listeyi ${readTool} view:'outline' ile okuyun.`);
139
257
  }
140
258
  resolved.push(key, String(index));
141
259
  current = collection[index];
@@ -145,24 +263,30 @@ export function resolvePatchPointer(document, path) {
145
263
  return rewritten ? { path: resolvedPath, note: `${path} → ${resolvedPath}` } : { path: resolvedPath };
146
264
  }
147
265
  /**
148
- * Yanıtın `applied: N` demekle yetinmemesi için: her op'un hangi step'e indiğini adıyla söyler.
266
+ * Yanıtın `applied: N` demekle yetinmemesi için: her op'un hangi öğeye indiğini adıyla söyler.
267
+ * Seçiciyle yazılan yol indekse çevrildiği için, indeksin hangi kayda denk geldiğini görmek
268
+ * sessiz veri bozulmasını önleyen tek sinyaldir (entity'de alan sırası değişebilir).
149
269
  */
150
270
  export function describePatchTarget(document, path) {
151
- const match = /^\/steps\/(\d+)(\/.*)?$/.exec(path);
271
+ const match = /^\/(steps|fields|indexes)\/(\d+)(\/.*)?$/.exec(path);
152
272
  if (!match)
153
273
  return path;
154
- const step = asArray(document.steps)[Number(match[1])];
155
- return step
156
- ? `${path} → '${String(step.name ?? step.id ?? '?')}' (${String(step.type ?? '?')}, id ${String(step.id ?? '?')})`
157
- : `${path} → (dizide ${match[1]}. eleman YOK)`;
274
+ const collection = asArray(document[match[1]]);
275
+ const entry = collection[Number(match[2])];
276
+ if (!entry)
277
+ return `${path} → (dizide ${match[2]}. eleman YOK)`;
278
+ const label = String(entry.name ?? entry.slug ?? entry.id ?? '?');
279
+ const kind = entry.type ?? entry.dbType;
280
+ return `${path} → '${label}'${kind ? ` (${String(kind)}` + `, id ${String(entry.id ?? '?')})` : `, id ${String(entry.id ?? '?')}`}`;
158
281
  }
159
- export function resolvePatchOperations(document, operations) {
282
+ export function resolvePatchOperations(document, operations, readTool = 'workflow_get') {
160
283
  const notes = [];
161
284
  const targets = [];
162
285
  const resolved = operations.map(operation => {
163
286
  const path = typeof operation.path === 'string' ? operation.path : '';
164
- const outcome = resolvePatchPointer(document, path);
165
- const from = typeof operation.from === 'string' ? resolvePatchPointer(document, operation.from) : undefined;
287
+ const op = typeof operation.op === 'string' ? operation.op : '';
288
+ const outcome = resolvePatchPointer(document, path, readTool, op);
289
+ const from = typeof operation.from === 'string' ? resolvePatchPointer(document, operation.from, readTool, op) : undefined;
166
290
  if (outcome.note)
167
291
  notes.push(outcome.note);
168
292
  if (from?.note)
@@ -0,0 +1,80 @@
1
+ import { findNode } from '../tools/screens.js';
2
+ /**
3
+ * Prop değerinin `type` alanı üç değer alır ve her biri taşıyıcısı farklıdır.
4
+ *
5
+ * Platformun kendi micro-op applier'ı `replace_prop`'ta gönderilen ham değeri HER ZAMAN `Static`
6
+ * (ifade verilmişse `Code`) Prop'una sarar (`PageSchemaMicroOpApplier.cs:77`), yani kurulu bir
7
+ * etiketi çeviriye bağlamanın platform tarafında bir yolu yoktur. Bu op o boşluğu kapatır:
8
+ * şemayı okur, prop'un TİPİNİ yerinde değiştirir, gövdeyi tam yazar.
9
+ *
10
+ * Alternatifi `remove_component` + `add_component`'tı ve pahalıydı: 2026-09-06 koşusunda on bir
11
+ * etiket o yolla yeniden kuruldu, o düğümlere yazan DOKUZ setter iteratee'si platform tarafından
12
+ * sessizce silindi ve üç KPI kartı boş kaldı (S-5/G-2).
13
+ *
14
+ * Taşıyıcı: `static` değeri `data`'da; `code` ve `translation` ifadeyi/anahtarı `ref`'te taşır —
15
+ * runtime `data`'yı her turda çözümlenmiş değerle ezer, o yüzden anahtar yalnız `ref`'te yaşar
16
+ * (`platform_guide('translation')`).
17
+ */
18
+ export const PROP_TYPE_CARRIER = { static: 'data', code: 'ref', translation: 'ref' };
19
+ export const SET_PROP_TYPE_OP = 'set_prop_type';
20
+ export function isSetPropTypeOp(op) {
21
+ return Boolean(op) && typeof op === 'object' && String(op.op ?? '') === SET_PROP_TYPE_OP;
22
+ }
23
+ export function setPropTypeErrors(ops) {
24
+ const issues = [];
25
+ for (const op of ops) {
26
+ const target = String(op.target ?? '');
27
+ const prop = String(op.prop ?? '');
28
+ const propType = String(op.propType ?? '');
29
+ if (!target || !prop) {
30
+ issues.push("set_prop_type için 'target' (elementId) ve 'prop' (prop adı) zorunludur.");
31
+ continue;
32
+ }
33
+ const carrier = PROP_TYPE_CARRIER[propType];
34
+ if (!carrier) {
35
+ issues.push(`set_prop_type '${target}.${prop}': geçersiz propType '${propType || '(boş)'}'. Yazılabilir tipler: ${Object.keys(PROP_TYPE_CARRIER).join(' · ')}.`);
36
+ continue;
37
+ }
38
+ if (carrier === 'ref' && String(op.ref ?? '').trim().length === 0) {
39
+ issues.push(`set_prop_type '${target}.${prop}': propType '${propType}' değeri 'ref' alanında taşır ve 'ref' boş. ${propType === 'translation' ? "translation_list ile çeviri anahtarını bulun (ör. ref: 'dashboard.kpi.total')" : "ref: '<ifade>' verin (ör. 'Page.variables.total')"} — runtime 'data'yı her turda ezer, anahtar yalnız ref'te yaşar.`);
40
+ }
41
+ if (carrier === 'data' && op.data === undefined && op.value === undefined) {
42
+ issues.push(`set_prop_type '${target}.${prop}': propType 'static' değeri 'data' alanında taşır ve 'data' verilmedi. Mevcut değeri korumak istiyorsanız data'yı açıkça yazın.`);
43
+ }
44
+ }
45
+ return issues;
46
+ }
47
+ /**
48
+ * Op'ları verilen ağaca uygular. Ağacı YERİNDE değiştirir — çağıran kopyayı kendisi alır, çünkü
49
+ * sayfa ve layout hatları gövdeyi farklı biçimde geri yazıyor (`pageUpdateBody` / `layoutUpdateBody`).
50
+ * Bulunamayan hedefler atılmaz, `missingTargets` ile döner: çağıran kendi aracının adını içeren
51
+ * hata mesajını kurar.
52
+ */
53
+ export function applyPropTypesToSchema(schema, ops) {
54
+ const applied = [];
55
+ const missingTargets = [];
56
+ for (const op of ops) {
57
+ const target = String(op.target ?? '');
58
+ const prop = String(op.prop ?? '');
59
+ const propType = String(op.propType ?? '');
60
+ const node = findNode(schema, target);
61
+ if (!node) {
62
+ missingTargets.push(target);
63
+ continue;
64
+ }
65
+ const props = (node.props ?? {});
66
+ const existing = props[prop];
67
+ const current = existing && typeof existing === 'object' && !Array.isArray(existing)
68
+ ? existing
69
+ : undefined;
70
+ // `data` tasarım zamanı yedeğidir: `code`/`translation`'a geçerken mevcut metni koruyoruz ki
71
+ // Studio'da boş kutu görünmesin (runtime onu zaten çözümlenmiş değerle ezer).
72
+ const carried = op.data !== undefined ? op.data : op.value !== undefined ? op.value : current?.data ?? null;
73
+ props[prop] = propType === 'static'
74
+ ? { type: 'static', ref: null, data: carried }
75
+ : { type: propType, ref: String(op.ref), data: carried };
76
+ node.props = props;
77
+ applied.push(`${target}.${prop}: ${current?.type ?? '(yok)'} → ${propType}`);
78
+ }
79
+ return { applied, missingTargets };
80
+ }