@appaflytech/zeyrek-ai-mcp 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ export function registerAccessTools(server, platform) {
5
5
  const config = platform.config;
6
6
  server.registerTool('role_list', {
7
7
  title: 'Rolleri listele',
8
- description: "Projenin rollerini listeler. Uç YALNIZ id + name döner (backend RoleDto bu ikisini taşır) — SLUG BURADA YOKTUR ve iki anahtar farklıdır: page_create/page_update ve microservice_create'in roleIds alanı ID ister, buna karşılık Authorized(user.roles) ile middleware'in kurduğu user.roles SLUG karşılaştırır (platformun get-user sorgusu roles+user_roles join'inden slug dizisi üretir). Slug'ı built-in 'roles' entity'sinden okuyun (sabit id 01917ede-88a2-72ea-8397-2619e5d5dca0; row_list/microservice). ROL OLUŞTURAN BİR TOOL YOKTUR ve olmamalıdır: roller built-in datasource'taki sıradan bir entity'dir (kolonlar id · name UNIQUE · slug). Uygulamanın rol yönetmesi gerekiyorsa yol entity_get('roles') + kendi microservice ucun (uç + sayfa) ve rolü kullanıcıya bağlayan user_roles satırı — MCP'den doğrudan yazma değil; reçete platform_guide('entity') §'Hazır entity'ler'. Projeyle birlikte gelen roller çoğu senaryoya yeter; önce bu listeye bakın.",
8
+ description: "Projenin rollerini listeler. Uç YALNIZ id + name döner (backend RoleDto bu ikisini taşır) — SLUG BURADA YOKTUR ve iki anahtar farklıdır: page_create/page_update ve microservice_create'in roleIds alanı ID ister (microservice_patch'te aynı liste '/roles' yolundadır ve öğeleri { id, name } çiftidir — yamalanan belge okuma şeklidir), buna karşılık Authorized(user.roles) ile middleware'in kurduğu user.roles SLUG karşılaştırır (platformun get-user sorgusu roles+user_roles join'inden slug dizisi üretir). Slug'ı built-in 'roles' entity'sinden okuyun (sabit id 01917ede-88a2-72ea-8397-2619e5d5dca0; row_list/microservice). ROL OLUŞTURAN BİR TOOL YOKTUR ve olmamalıdır: roller built-in datasource'taki sıradan bir entity'dir (kolonlar id · name UNIQUE · slug). Uygulamanın rol yönetmesi gerekiyorsa yol entity_get('roles') + kendi microservice ucun (uç + sayfa) ve rolü kullanıcıya bağlayan user_roles satırı — MCP'den doğrudan yazma değil; reçete platform_guide('entity') §'Hazır entity'ler'. Projeyle birlikte gelen roller çoğu senaryoya yeter; önce bu listeye bakın.",
9
9
  inputSchema: { project: projectParam, environment: environmentParam },
10
10
  annotations: readOnly
11
11
  }, handle(config, async ({ project, environment }) => {
@@ -1,4 +1,4 @@
1
- import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, staleSetterWarnings, normalizeSchemaOps, validationNote, componentDefaultsNote, replacePropNote, flexSizeWarnings, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, verticalGapWarnings, withNormalization, FLEX_LAYOUT_PROP_NAMES } from '../knowledge/normalize.js';
1
+ import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, boundEventOps, stripGatewayEventFields, staleSetterWarnings, normalizeSchemaOps, validationNote, componentDefaultsNote, replacePropNote, flexSizeWarnings, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, verticalGapWarnings, withNormalization, FLEX_LAYOUT_PROP_NAMES } from '../knowledge/normalize.js';
2
2
  import { opsParam, writeViewParam, outlineWriteResponse, unknownEventOps, collectTypes, simulateLayoutOps, removeNodeFromTree, planEventRemovals, planResizes, planPropTypes, assertOpBodies } from './schemaOps.js';
3
3
  import { guid, projectParam, environmentParam, updates, microOps } from './common.js';
4
4
  import { fetchHost, hostPath } from './screens.js';
@@ -68,7 +68,10 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
68
68
  }
69
69
  const nodes = (record[spec.tree] ?? []);
70
70
  const events = host === 'layout' ? record.events : undefined;
71
- if (opRecords.some(entry => entry.op === 'set_event')) {
71
+ if (opRecords.some(entry => entry.op === 'set_event' || entry.op === 'add_event')) {
72
+ const bound = boundEventOps(nodes, opRecords);
73
+ if (bound.length > 0)
74
+ throw new PlatformApiError(`PAGE-034 — dolu olaya set_event (istek gönderilmedi): ${bound.join(' · ')}`, 400);
72
75
  const typesByElementId = new Map();
73
76
  collectTypes(nodes, typesByElementId);
74
77
  collectTypes(opRecords.map(entry => entry.component).filter(Boolean), typesByElementId);
@@ -77,6 +80,7 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
77
80
  if (unknown.length > 0)
78
81
  throw new PlatformApiError(`PAGE-008 — geçersiz olay adı (istek gönderilmedi): ${unknown.join(' · ')}`, 400);
79
82
  }
83
+ stripGatewayEventFields(opRecords);
80
84
  const deletedFlows = orphanedFlowPlan(nodes, events, [...opRecords, ...removeEventOps]);
81
85
  if (deletedFlows.length > 0 && allowFlowDeletion !== true)
82
86
  throw new PlatformApiError(orphanedFlowMessage(deletedFlows), 400);
@@ -113,7 +113,7 @@ export function registerEntityTools(server, platform) {
113
113
  }));
114
114
  server.registerTool('entity_create', {
115
115
  title: 'Entity oluştur',
116
- description: "Datasource altında yeni entity oluşturur (definition = CreateEntityCommand: name, fields[], applicationIds, ...). İlişkiler ve alan tipi kararı için platform_guide('entity') okuyun. Gövde politika kontrolünden geçer. applicationIds create'te platformca bağlanır (CreateEntityCommandHandler entityApplications'ı Entity ctor'una geçirir); satır uçları bu bağa İHTİYAÇ DUYMAZ — bağ yalnız Studio'nun application'a göre entity listesini ve bağımlılık sorgularını etkiler. `fields[].isLocalized: true` alanı ana tablodan çıkarıp companion `<slug>_localization` entity'sine taşır (yalnız düz METİN alanı; anahtar/unique/ilişki olamaz) — platform_guide('entity') §'Çoklu dilli alan'.",
116
+ description: "Datasource altında yeni entity oluşturur (definition = CreateEntityCommand: name, fields[], applicationIds, ...). İlişkiler ve alan tipi kararı için platform_guide('entity') okuyun. Gövde politika kontrolünden geçer. applicationIds create'te platformca bağlanır (CreateEntityCommandHandler entityApplications'ı Entity ctor'una geçirir); satır uçları bu bağa İHTİYAÇ DUYMAZ — bağ yalnız Studio'nun application'a göre entity listesini ve bağımlılık sorgularını etkiler. `fields[].isLocalized: true` alanı ana tablodan çıkarıp companion `<slug>_localization` entity'sine taşır (yalnız düz METİN alanı; anahtar/unique/ilişki olamaz) — platform_guide('entity') §'Çoklu dilli alan'. SEÇİM LİSTESİNE (enum) TEK DEĞER: listeyi yeniden göndermeyin — ekleme `{op:'add', path:'/fields[slug=status]/valueOptions/-', value:{value:'Onayda', order:4}}`, silme `{op:'remove', path:'/fields[slug=status]/valueOptions[value=Eski]'}`, yeniden adlandırma `{op:'replace', path:'/fields[slug=status]/valueOptions[value=Eski]/value', value:'Yeni'}`; `isEnum` türetilmiştir, ayrıca yazılmaz. Silme/yeniden adlandırmadan ÖNCE o değeri taşıyan satırları taşıyın — yoksa istek reddedilir ve hiçbir şey yazılmaz ('check constraint … is violated by some row') (platform_guide('entity') §'Alan tipine karar verme').",
117
117
  inputSchema: { project: projectParam, environment: environmentParam, datasourceId: guid, definition: definitionParam, policyOverride: policyOverrideParam },
118
118
  annotations: writes
119
119
  }, handle(config, async ({ project, environment, datasourceId, definition, policyOverride }) => {
@@ -399,7 +399,7 @@ export function registerFlowTools(server, platform) {
399
399
  outcome: existing === undefined ? 'created' : 'updated',
400
400
  flow: { id: writtenFlowId, name, slug, steps: steps.length },
401
401
  ...(parameterWarnings.length > 0 ? { parameterWarnings } : {}),
402
- hint: "Akışı bir olaya bağlamak için: page_schema_patch (layout'ta layout_schema_patch, widget'ta component_schema_patch) ops:[{op:'set_event', target:<elementId>, event:'<component_get events listesindeki ad>', eventValue:<flow id>}]. Olay adları komponente özeldir ve 'on' ÖNEKİ ALMAZ (button → 'click', form → 'submit', table → 'mount'/'select'/'sort'…); uydurma ad 200 döner ama bağ sessizce ölü kalır — gateway PAGE-008 ile yakalar."
402
+ hint: "Akışı bir olaya bağlamak için: page_schema_patch (layout'ta layout_schema_patch, widget'ta component_schema_patch) ops:[{op:'set_event', target:<elementId>, event:'<component_get events listesindeki ad>', eventValue:<flow id>}]; olayda zaten akış bağlıysa ikinciyi add_event ile ekleyin (set_event bağlı akışı değiştirir, PAGE-034). Olay adları komponente özeldir ve 'on' ÖNEKİ ALMAZ (button → 'click', form → 'submit', table → 'mount'/'select'/'sort'…); uydurma ad 200 döner ama bağ sessizce ölü kalır — gateway PAGE-008 ile yakalar."
403
403
  }, normalized), drops), findings);
404
404
  }));
405
405
  server.registerTool('flow_update', {
@@ -126,7 +126,7 @@ export function registerFunctionTools(server, platform) {
126
126
  const config = platform.config;
127
127
  server.registerTool('function_list', {
128
128
  title: 'Fonksiyonları listele',
129
- description: "Fonksiyonları imzalarıyla listeler; iki kaynak tek listede (source: 'workflow' sunucu, 'studio' tarayıcı). Süzgeçler birleşir: source · applicationId (studio kayıtları) · scope · pageId (yalnız o sayfanın sayfa kapsamlıları). Gövde listede YOKTUR (bodyLines sayılır) — function_get ile okuyun. Bir ifadeye Functions.x(…) ya da çıplak x(…) yazmadan önce adı, id'yi ve parametre SIRASINI buradan alın — platform_guide('functions').",
129
+ description: "Fonksiyonları imzalarıyla listeler; iki kaynak tek listede (source: 'workflow' sunucu, 'studio' tarayıcı). Süzgeçler birleşir: source · applicationId (studio kayıtları) · scope · pageId (yalnız o sayfanın sayfa kapsamlıları). Gövde listede YOKTUR (bodyLines sayılır) — function_get ile okuyun. Bir ifadeye Functions.x(…) ya da çıplak x(…) yazmadan önce adı, id'yi ve parametre SIRASINI buradan alın — platform_guide('functions'). Gövdeyi DEĞİŞTİRMEK için function_update { id, body }; fonksiyonda patch aracı yoktur.",
130
130
  inputSchema: {
131
131
  project: projectParam,
132
132
  environment: environmentParam,
@@ -2,7 +2,7 @@ import { guid, appRef, withResolved, projectParam, environmentParam, definitionP
2
2
  import { languageHeader } from '../knowledge/languageCodes.js';
3
3
  import { hydrateMicroserviceRefs } from '../knowledge/hydrate.js';
4
4
  import { RefResolver } from '../platform/refs.js';
5
- import { normalizeMicroserviceDefinition, withNormalization } from '../knowledge/normalize.js';
5
+ import { normalizeMicroserviceDefinition, normalizeMicroservicePatchOps, withNormalization } from '../knowledge/normalize.js';
6
6
  import { evaluatePolicy, enforcePolicy, attachFindings } from '../knowledge/policy.js';
7
7
  import { microserviceOutline, workflowOutline, resolvePart, resolvePatchOperations } from '../knowledge/outlines.js';
8
8
  import { patchResult, baseVersionOf } from '../platform/patch.js';
@@ -323,7 +323,7 @@ export function registerMicroserviceTools(server, platform) {
323
323
  }));
324
324
  server.registerTool('microservice_patch', {
325
325
  title: 'Microservice\'e patch uygula',
326
- description: 'Tam gövdeyi bağlama almadan hedefli değişiklik: gateway mevcut tanımı çeker, JSON Patch uygular, politika kontrolünden geçirir, geri yazar. Yanıt outline özetidir.',
326
+ description: "Tam gövdeyi bağlama almadan hedefli değişiklik: gateway mevcut tanımı çeker, JSON Patch uygular, politika kontrolünden geçirir, geri yazar. Yanıt outline özetidir. YAMALANAN BELGE microservice_get'in OKUMA ŞEKLİDİR, create/update gövdesi değil — ikisinin alan adları her yerde aynı DEĞİL: ROL LİSTESİ '/roles' yolundadır ve öğeleri { id: <role_list id>, name } çiftleridir ('roleIds' yalnız create/update gövdesinde vardır; verirseniz gateway '/roles'a çevirir ve gatewayNormalized ile söyler). Rolü değiştirmek için ucun tanımını yeniden göndermeyin: {op:'replace', path:'/roles', value:[{id:'<role_list id>'}]} yeter — 'name' isteğe bağlıdır, platform yalnız id okur. Tam dizi replace'i tercih edin: alan boş listede null serileşebilir ve '/roles/-' eklemesi o hâlde çözülemez (gateway katlar, notu yanıtta görürsünüz). Middleware listesi '/middlewareIds' ile iki yolda da aynı addır.",
327
327
  inputSchema: { project: projectParam, environment: environmentParam, applicationId: appRef, id: guid, operations: patchOperationsParam.optional(), ops: patchOperationsParam.optional().describe("'operations' ile aynı alan (eşanlamlı) — sayfa micro-op tool'larıyla aynı adı kullanabilmeniz için"), policyOverride: policyOverrideParam },
328
328
  annotations: updates
329
329
  }, handle(config, async ({ project, environment, applicationId, id, operations: givenOperations, ops, policyOverride }) => {
@@ -332,7 +332,11 @@ export function registerMicroserviceTools(server, platform) {
332
332
  const resolvedApplicationId = await resolver.applicationId(applicationId);
333
333
  const current = await platform.tenant('GET', project, `/microservices/${resolvedApplicationId}/${id}`, { environment });
334
334
  const definition = structuredClone((current?.data ?? current));
335
- const resolved = resolvePatchOperations(definition, operations);
335
+ // Rol yolu seçici çözümünden ÖNCE çevrilir: '/roleIds' patch belgesinde hiç yoktur, o hâliyle
336
+ // applyPatch'e giden replace OPERATION_PATH_UNRESOLVABLE ile düşerdi (S-2).
337
+ const roleOperations = structuredClone(operations);
338
+ const roleNotes = normalizeMicroservicePatchOps(roleOperations, definition);
339
+ const resolved = resolvePatchOperations(definition, roleOperations);
336
340
  const patched = fastJsonPatch.applyPatch(definition, resolved.operations, true, false).newDocument;
337
341
  // Patch gövdesi tam PUT olarak geri yazılır: okunan kayıtta olmayan alan yazmada da SİLİNİR.
338
342
  // 09-04 koşusunda gidiş-dönüş 'description'ı düşürdü ve MS-014 patch'i bloke etti; genel
@@ -354,7 +358,7 @@ export function registerMicroserviceTools(server, platform) {
354
358
  body: { baseVersion: baseVersionOf(definition, 'microservice_get'), ops: netOps }
355
359
  });
356
360
  const written = patchResult(saved, patched);
357
- return attachFindings(withUnmappedMembers(withWriteDiff(withResolved(withNormalization({ applied: operations.length, newVersion: written.newVersion, outline: microserviceOutline(written.data) }, [...normalized, ...resolved.notes.map(note => `patch yolu seçiciden indekse çözüldü: ${note}`)]), resolver.resolved), writeDiff(patched, written.data)), drift), findings);
361
+ return attachFindings(withUnmappedMembers(withWriteDiff(withResolved(withNormalization({ applied: operations.length, newVersion: written.newVersion, outline: microserviceOutline(written.data) }, [...roleNotes, ...normalized, ...resolved.notes.map(note => `patch yolu seçiciden indekse çözüldü: ${note}`)]), resolver.resolved), writeDiff(patched, written.data)), drift), findings);
358
362
  }));
359
363
  server.registerTool('microservice_delete', {
360
364
  title: 'Microservice sil',
@@ -1,5 +1,5 @@
1
1
  import { guid, projectParam, environmentParam, pagingParams, readOnly, writes, updates, destructive, microOps, isBranchName } from './common.js';
2
- import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, staleSetterWarnings, lostSetterTargets, normalizeComponentDefaults, normalizeSchemaOps, schemaOpValidationErrors, codePropTemplateErrors, validationNote, componentDefaultsNote, replacePropNote, ensurePageContainer, retargetRootAdds, rootAddsNote, flexSizeWarnings, spacingLayerWarnings, reorderSchemaBlocks, reorderNote, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, FLEX_LAYOUT_PROP_NAMES, resetPageContainerPosition, pageContainerPositionWarning, verticalGapWarnings, flexIndexOrder, flexIndexOrderNote, withNormalization, parseVariableEntries, PAGE_CONTAINER_ELEMENT_ID } from '../knowledge/normalize.js';
2
+ import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, boundEventOps, stripGatewayEventFields, staleSetterWarnings, lostSetterTargets, normalizeComponentDefaults, normalizeSchemaOps, schemaOpValidationErrors, codePropTemplateErrors, validationNote, componentDefaultsNote, replacePropNote, ensurePageContainer, retargetRootAdds, rootAddsNote, flexSizeWarnings, spacingLayerWarnings, reorderSchemaBlocks, reorderNote, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, FLEX_LAYOUT_PROP_NAMES, resetPageContainerPosition, pageContainerPositionWarning, verticalGapWarnings, flexIndexOrder, flexIndexOrderNote, withNormalization, parseVariableEntries, PAGE_CONTAINER_ELEMENT_ID } from '../knowledge/normalize.js';
3
3
  import { functionSignature } from '../knowledge/functionGuards.js';
4
4
  import { fetchHost, pageUpdateBody, schemaParam, eventsParam, unwrap, modeParam, summarize, findNode, flowPath } from './screens.js';
5
5
  import { fetchComponentEventNames } from './components.js';
@@ -67,7 +67,7 @@ async function fetchPage(platform, project, environment, applicationId, pageId)
67
67
  */
68
68
  export const SERVER_PAGE_OPS = [
69
69
  'replace_prop', 'set_binding', 'set_prop_type', 'add_component', 'remove_component', 'move_component', 'reorder', 'set_block',
70
- 'set_appearance', 'set_states', 'set_event', 'remove_event', 'set_validations', 'set_state_binding', 'remove_state_binding', 'batch'
70
+ 'set_appearance', 'set_states', 'set_event', 'add_event', 'remove_event', 'set_validations', 'set_state_binding', 'remove_state_binding', 'batch'
71
71
  ];
72
72
  export function registerPageTools(server, platform, injectedScreenshotter, injectedMemory) {
73
73
  const config = platform.config;
@@ -638,10 +638,13 @@ export function registerPageTools(server, platform, injectedScreenshotter, injec
638
638
  reject('PAGE-016', entry, schemaOpValidationErrors([entry]));
639
639
  for (const entry of opRecords)
640
640
  reject('PAGE-032', entry, codePropTemplateErrors([entry]));
641
- if (opRecords.some(entry => entry.op === 'set_event')) {
641
+ if (opRecords.some(entry => entry.op === 'set_event' || entry.op === 'add_event')) {
642
642
  const typesByElementId = new Map();
643
643
  try {
644
- collectTypes((await readPage()).schema, typesByElementId);
644
+ const page = await readPage();
645
+ collectTypes(page.schema, typesByElementId);
646
+ for (const entry of opRecords)
647
+ reject('PAGE-034', entry, boundEventOps(page.schema, [entry]));
645
648
  }
646
649
  catch {
647
650
  typesByElementId.clear();
@@ -653,6 +656,7 @@ export function registerPageTools(server, platform, injectedScreenshotter, injec
653
656
  }
654
657
  if (rejected.length > 0)
655
658
  throw new PlatformApiError(rejectedOpsMessage(rejected), 400);
659
+ stripGatewayEventFields(opRecords);
656
660
  const wantsRootAdd = opRecords.some(entry => entry.op === 'add_component' && (entry.parent === undefined || entry.parent === null || entry.parent === 'root'));
657
661
  let retargeted = [];
658
662
  if (wantsRootAdd) {
@@ -71,7 +71,7 @@ const guideRouting = {
71
71
  middleware: 'auth/oturum/yetki',
72
72
  view: 'tam metin arama indeksi',
73
73
  expressions: 'ifade fonksiyon/bağlam sözlüğü (system.*, file.*, Page.*, state.*, Steps…)',
74
- functions: "fonksiyonlar, iki kaynak tek biçim: source:'studio' tarayıcıda Functions.<ad>() (kapsam uygulama/sayfa, UI flow 'function' adımı), source:'workflow' sunucuda çıplak ad; parametre/varsayılan/required, tuzaklar",
74
+ functions: "fonksiyonlar, iki kaynak tek biçim: source:'studio' tarayıcıda Functions.<ad>() (kapsam uygulama/sayfa, UI flow 'function' adımı), source:'workflow' sunucuda çıplak ad; parametre/varsayılan/required, tuzaklar; GÖVDE GÜNCELLEME function_update (yalnız değişen alanı gönder, patch aracı yok)",
75
75
  translation: 'sayfa/içerik çevirileri (çoklu dil)',
76
76
  merge: "dal aç, dalda çalış, development'a merge et; çakışma çözümü ve apply kapıları"
77
77
  };
@@ -24,7 +24,7 @@ export function outlineWriteResponse(response) {
24
24
  if (Array.isArray(container.appliedPatch))
25
25
  container.appliedPatch = outlineAppliedPatch(container.appliedPatch);
26
26
  }
27
- export const opsParam = z.array(z.record(z.unknown())).describe("Micro-op listesi. Op sözlüğü: replace_prop {target, prop, value} (value ham değer, code sarmalı {type: 'code', ref: '{{ … }}'} ya da translation sarmalı {type: 'translation', ref: '<çeviri anahtarı>'} — prop tipini değiştirmek için komponenti silip yeniden EKLEMEYİN, ona yazan setter'ların hedefi silinir (FLOW-018); platform replace_prop'ta expression alanını OKUMAZ — gateway onu code sarmalına çevirir) | set_binding {target, prop, expression: '{{ Page.variables.x }}'} | add_component {parent (üst elementId ya da 'root'), index?, component} | remove_component {target} | move_component {target, parent, index?, position: {x, y}} (index ÇİZİM sırası değildir, runtime çocukları blocks.position'a göre (y, sonra x) çizer. page_schema_patch'te flex kapta gateway index'i görünen sıraya çevirir ve kardeş konumlarını yeniden yazar; ızgara kapta sırayı position.y verir, sona eklemeyen index PAGE-033 uyarısıdır. layout_schema_patch ve component_schema_patch bu çeviriyi YAPMAZ: orada sırayı position.y ile verin) | set_event {target, event, eventValue} | remove_event {target, event} (olayı diziden çıkarır; target: 'page' sayfa düzeyi olaylar. set_event ile eventValue: null olay SİLMEZ, değersiz ölü kayıt bırakır. Olmayan olay 422 missing-event) | set_validations {target, validations: [{type, message, value, isActive}]} (komponentin validation listesini TAMAMEN değiştirir; boş dizi hepsini siler) | set_appearance {target, appearance: {heightType?, widthType?, tooltip?, background?, …}} (kurulu düğümün appearance'ına YALNIZ verilen alanları yazar, gerisini korur; null alanı temizler; bilinmeyen alan unknown-appearance-field ile reddedilir. GÖRÜNÜRLÜK appearance'ta DEĞİLDİR: gizlemek için replace_prop {target, prop: 'isHidden', value: true}, koşul için set_binding {prop: 'isHidden'} — add_component gövdesindeki appearance.isHidden'ı gateway props.isHidden'a taşır) | resize_component {target, size?: {w,h}, appearance?: {widthType,widthString,heightType,heightString}, states?: {isWrapper,isScrollable,isSticky,isDroppable,isFloating,isQuickStack}, breakpoint?: 1024} (gateway adı: platforma set_block {target, breakpoint, size} + set_appearance {target, appearance} + set_states {target, states} olarak gider — o üç op'u doğrudan da gönderebilirsiniz. move_component'e konan size reddedilir. Izgarada blocks[].size, flex'te appearance geçerlidir; ebeveynin düzeni yazılanı etkisiz kılıyorsa PAGE-019 uyarısı çıkar. states bir PROP DEĞİL düğüm alanıdır ve replace_prop onu yazamaz — düğümü silmeden isWrapper bayrağını değiştirmenin yolu budur). set_prop_type {target, prop, propType: 'static'|'code'|'translation', ref?, data?} (replace_prop sarmalıyla aynı sonucu verir ve mevcut data'yı tasarım yedeği olarak taşır. Bu op prop'un TİPİNİ yerinde değiştirir. Taşıyıcı alan tipe göre: static → data, code ve translation → ref (runtime data'yı her turda ezer, anahtar yalnız ref'te yaşar). Eksik taşıyıcı istek gönderilmeden reddedilir; page_schema_validate aynı kararı verir) | reorder {parent ('root' ya da elementId), order: [çocuk elementId'lerinin TAMAMI, yeni sırada]} (yalnız DİZİ sırasını değiştirir; çizim sırası blocks.position'dır — görünen sırayı değiştirmek için konumları set_block/move_component ile de yazın) | set_state_binding {target, binding: {name, expression, targets}} (ada göre ekler/değiştirir) | remove_state_binding {target, name} | batch {gestureId?, label?, ops: [...]} (iç içe batch yok). target = elementId. İstek atomiktir: tek op reddedilirse hiçbiri yazılmaz.");
27
+ export const opsParam = z.array(z.record(z.unknown())).describe("Micro-op listesi. Op sözlüğü: replace_prop {target, prop, value} (value ham değer, code sarmalı {type: 'code', ref: '{{ … }}'} ya da translation sarmalı {type: 'translation', ref: '<çeviri anahtarı>'} — prop tipini değiştirmek için komponenti silip yeniden EKLEMEYİN, ona yazan setter'ların hedefi silinir (FLOW-018); platform replace_prop'ta expression alanını OKUMAZ — gateway onu code sarmalına çevirir) | set_binding {target, prop, expression: '{{ Page.variables.x }}'} | add_component {parent (üst elementId ya da 'root'), index?, component} | remove_component {target} | move_component {target, parent, index?, position: {x, y}} (index ÇİZİM sırası değildir, runtime çocukları blocks.position'a göre (y, sonra x) çizer. page_schema_patch'te flex kapta gateway index'i görünen sıraya çevirir ve kardeş konumlarını yeniden yazar; ızgara kapta sırayı position.y verir, sona eklemeyen index PAGE-033 uyarısıdır. layout_schema_patch ve component_schema_patch bu çeviriyi YAPMAZ: orada sırayı position.y ile verin) | set_event {target, event, eventValue, replaceBoundFlows?} (olayın BÜTÜN bağlarını bu tek akışa indirir; olayda başka akış bağlıysa gateway PAGE-034 ile reddeder — bilerek değiştirmek için replaceBoundFlows: true) | add_event {target, event, eventValue} (olaya bir akış DAHA bağlar; bağlı akışların hepsi paralel ve birbirinden bağımsız koşar, sıra garantisi yoktur — sıra gerekiyorsa flow-trigger. Aynı akış iki kez 422 duplicate-event. Mobil runtime yalnız İLK akışı koşar) | remove_event {target, event, eventValue?} (olayı diziden çıkarır; target: 'page' sayfa düzeyi olaylar. Olaya birden fazla akış bağlıysa eventValue ile hangisi olduğunu verin, yoksa 422 ambiguous-event. set_event ile eventValue: null olay SİLMEZ, değersiz ölü kayıt bırakır. Olmayan olay 422 missing-event) | set_validations {target, validations: [{type, message, value, isActive}]} (komponentin validation listesini TAMAMEN değiştirir; boş dizi hepsini siler) | set_appearance {target, appearance: {heightType?, widthType?, tooltip?, background?, …}} (kurulu düğümün appearance'ına YALNIZ verilen alanları yazar, gerisini korur; null alanı temizler; bilinmeyen alan unknown-appearance-field ile reddedilir. GÖRÜNÜRLÜK appearance'ta DEĞİLDİR: gizlemek için replace_prop {target, prop: 'isHidden', value: true}, koşul için set_binding {prop: 'isHidden'} — add_component gövdesindeki appearance.isHidden'ı gateway props.isHidden'a taşır) | resize_component {target, size?: {w,h}, appearance?: {widthType,widthString,heightType,heightString}, states?: {isWrapper,isScrollable,isSticky,isDroppable,isFloating,isQuickStack}, breakpoint?: 1024} (gateway adı: platforma set_block {target, breakpoint, size} + set_appearance {target, appearance} + set_states {target, states} olarak gider — o üç op'u doğrudan da gönderebilirsiniz. move_component'e konan size reddedilir. Izgarada blocks[].size, flex'te appearance geçerlidir; ebeveynin düzeni yazılanı etkisiz kılıyorsa PAGE-019 uyarısı çıkar. states bir PROP DEĞİL düğüm alanıdır ve replace_prop onu yazamaz — düğümü silmeden isWrapper bayrağını değiştirmenin yolu budur). set_prop_type {target, prop, propType: 'static'|'code'|'translation', ref?, data?} (replace_prop sarmalıyla aynı sonucu verir ve mevcut data'yı tasarım yedeği olarak taşır. Bu op prop'un TİPİNİ yerinde değiştirir. Taşıyıcı alan tipe göre: static → data, code ve translation → ref (runtime data'yı her turda ezer, anahtar yalnız ref'te yaşar). Eksik taşıyıcı istek gönderilmeden reddedilir; page_schema_validate aynı kararı verir) | reorder {parent ('root' ya da elementId), order: [çocuk elementId'lerinin TAMAMI, yeni sırada]} (yalnız DİZİ sırasını değiştirir; çizim sırası blocks.position'dır — görünen sırayı değiştirmek için konumları set_block/move_component ile de yazın) | set_state_binding {target, binding: {name, expression, targets}} (ada göre ekler/değiştirir) | remove_state_binding {target, name} | batch {gestureId?, label?, ops: [...]} (iç içe batch yok). target = elementId. İstek atomiktir: tek op reddedilirse hiçbiri yazılmaz.");
28
28
  /**
29
29
  * PAGE-008 — `set_event` uydurma bir olay adıyla 200 döner ve bağ SESSİZCE ölü kalır: motor olayı
30
30
  * komponentin yaydığı adla eşleştirir, eşleşme yoksa akış hiç çalışmaz. Kontrol yalnız hedefin
@@ -35,7 +35,7 @@ export const opsParam = z.array(z.record(z.unknown())).describe("Micro-op listes
35
35
  export function unknownEventOps(ops, typesByElementId, eventsBySlug) {
36
36
  return ops
37
37
  .map(op => op)
38
- .filter(op => op.op === 'set_event')
38
+ .filter(op => op.op === 'set_event' || op.op === 'add_event')
39
39
  .flatMap(op => {
40
40
  const target = String(op.target ?? '');
41
41
  const event = String(op.event ?? '');
@@ -213,7 +213,7 @@ export function registerWorkflowTools(server, platform) {
213
213
  }));
214
214
  server.registerTool('workflow_step_schema', {
215
215
  title: 'Step şeması üret',
216
- description: "Verilen step tanımı için girdi/çıktı şemasını üretir (parameterScheme / returnScheme); step yazarken definition'ı doğrulamanın en hızlı yolu. type:'workflow' adımında (rule.workflowId) çağrılan akışın parametre ve dönüş DTO'sunu döner — alt akışa girdi YALNIZ rule.expression ile geçer, nesne literalinin anahtarları bu parameterScheme'in alanlarıdır (WF-032; platform_guide('workflow') §Workflow adımı).",
216
+ description: "Verilen step tanımı için girdi/çıktı şemasını üretir (parameterScheme / returnScheme); step yazarken definition'ı doğrulamanın en hızlı yolu. type:'workflow' adımında (rule.workflowId) çağrılan akışın parametre ve dönüş DTO'sunu döner — alt akışa girdi YALNIZ rule.expression ile geçer, nesne literalinin anahtarları bu parameterScheme'in alanlarıdır (WF-032; platform_guide('workflow') §Workflow adımı). ŞEMA ALAN ADLARINI VERİR, HANGİ ALANIN ÇALIŞTIĞINI DEĞİL — üç ölçülmüş sapma (2026-09-16): (1) 'http' adımının returnScheme'i kök seviyede { httpStatusCode, data } der, koşumda ise adım { data, meta: { httpStatusCode }, error }'dır, yani <adım>.httpStatusCode UNDEFINED, doğrusu <adım>.meta.httpStatusCode; (2) 'workflow' adımında workflowId boşken parameterScheme/returnScheme boş döner ve şema girdinin rule.expression ile bağlandığını söylemez; (3) 'email' adımında şemanın gösterdiği alıcı adı çalışmaz (36/W-6). Sözleşmenin ölçülmüş hâli: ngapps://examples/workflow-http-step · workflow-call-workflow · workflow-loop-step ve platform_guide('workflow').",
217
217
  inputSchema: { project: projectParam, environment: environmentParam, applicationId: guid, id: guid, step: definitionParam },
218
218
  annotations: readOnly
219
219
  }, handle(config, ({ project, environment, applicationId, id, step }) => platform.tenant('POST', project, `/workflows/${applicationId}/${id}/steps/schema`, { environment, body: step })));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appaflytech/zeyrek-ai-mcp",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
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",