@appaflytech/zeyrek-ai-mcp 0.0.5 → 0.0.7
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/.env.example +2 -2
- package/.env.production.example +9 -1
- package/README.md +14 -38
- package/dist/config.js +36 -3
- package/dist/knowledge/backendConstraints.js +982 -0
- package/dist/knowledge/componentCatalog.js +549 -92
- package/dist/knowledge/componentEvents.js +120 -25
- package/dist/knowledge/coverage.js +43 -0
- package/dist/knowledge/flowGuards.js +30 -0
- package/dist/knowledge/functionGuards.js +134 -0
- package/dist/knowledge/guideSections.js +49 -0
- package/dist/knowledge/hydrate.js +97 -0
- package/dist/knowledge/languageCodes.js +36 -0
- package/dist/knowledge/languages.js +105 -0
- package/dist/knowledge/layoutSummary.js +10 -0
- package/dist/knowledge/localization.js +51 -0
- package/dist/knowledge/normalize.js +500 -16
- package/dist/knowledge/outlines.js +167 -12
- package/dist/knowledge/policy.js +14 -5
- package/dist/knowledge/propTypes.js +80 -0
- package/dist/knowledge/rules.js +961 -44
- package/dist/knowledge/schemaGuard.js +199 -0
- package/dist/knowledge/styleResolve.js +63 -4
- package/dist/observability/trace.js +27 -3
- package/dist/platform/csv.js +123 -0
- package/dist/platform/errors.js +107 -6
- package/dist/platform/http.js +34 -4
- package/dist/platform/patch.js +27 -0
- package/dist/platform/refs.js +104 -0
- package/dist/platform/responses.js +25 -6
- package/dist/platform/screenshot.js +544 -16
- package/dist/platform/secrets.js +40 -0
- package/dist/platform/tokenVault.js +89 -0
- package/dist/platform/writeDiff.js +281 -0
- package/dist/resources/examples/flow-call-function.json +66 -0
- package/dist/resources/examples/function-total.json +70 -0
- package/dist/resources/examples/layout-app-shell.json +1 -1
- package/dist/resources/examples/microfunction-node-sum.json +56 -0
- package/dist/resources/examples/microservice-table-list.json +2 -4
- package/dist/resources/examples/page-dynamic-form.json +3 -3
- package/dist/resources/examples/page-flex-sections.json +99 -0
- package/dist/resources/examples/page-sign-in.json +4 -3
- package/dist/resources/guides/component.md +81 -8
- package/dist/resources/guides/entity.md +712 -20
- package/dist/resources/guides/expressions.md +47 -2
- package/dist/resources/guides/external-component.md +9 -0
- package/dist/resources/guides/functions.md +262 -0
- package/dist/resources/guides/getting-started.md +82 -7
- package/dist/resources/guides/layout.md +53 -10
- package/dist/resources/guides/merge.md +231 -0
- package/dist/resources/guides/microfunction.md +166 -0
- package/dist/resources/guides/microservice.md +287 -15
- package/dist/resources/guides/middleware.md +89 -1
- package/dist/resources/guides/modify-existing.md +23 -0
- package/dist/resources/guides/page.md +402 -49
- package/dist/resources/guides/translation.md +150 -8
- package/dist/resources/guides/view.md +16 -1
- package/dist/resources/guides/workflow.md +199 -28
- package/dist/resources/knowledge.js +5 -0
- package/dist/resources/rules.js +27 -0
- package/dist/resources/schema-fingerprint.json +8 -0
- package/dist/resources/schemas/AnalyzeImportQuery.json +51 -0
- package/dist/resources/schemas/ApplyMergePlanCommand.json +19 -0
- package/dist/resources/schemas/CreateBulkRowCommand.json +36 -0
- package/dist/resources/schemas/CreateDatasourceCommand.json +15 -6
- package/dist/resources/schemas/CreateDiscoveredEntitiesCommand.json +19 -8
- package/dist/resources/schemas/CreateEntityCommand.json +52 -12
- package/dist/resources/schemas/CreateEnvironmentCommand.json +31 -0
- package/dist/resources/schemas/CreateGlobalFunctionCommand.json +95 -0
- package/dist/resources/schemas/CreateImportPlanCommand.json +278 -0
- package/dist/resources/schemas/CreateMergePlanCommand.json +34 -0
- package/dist/resources/schemas/CreateMicrofunctionCommand.json +117 -0
- package/dist/resources/schemas/CreateMicrofunctionRuntimeCommand.json +51 -0
- package/dist/resources/schemas/CreateMicroserviceCommand.json +145 -3
- package/dist/resources/schemas/CreateQueryCommand.json +56 -3
- package/dist/resources/schemas/CreateRowCommand.json +38 -0
- package/dist/resources/schemas/CreateViewCommand.json +13 -10
- package/dist/resources/schemas/CreateWorkflowCommand.json +106 -14
- package/dist/resources/schemas/DataJobDto.json +267 -0
- package/dist/resources/schemas/ExportRowsCommand.json +172 -0
- package/dist/resources/schemas/Filter.json +3 -1
- package/dist/resources/schemas/GetRowsQuery.json +6 -1
- package/dist/resources/schemas/GlobalFunctionDto.json +89 -0
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +249 -0
- package/dist/resources/schemas/ImportAnalysisDto.json +401 -0
- package/dist/resources/schemas/ImportPlanDto.json +260 -0
- package/dist/resources/schemas/ImportSampleDto.json +90 -0
- package/dist/resources/schemas/InvokeMicrofunctionCommand.json +25 -0
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +135 -1
- package/dist/resources/schemas/PreviewQueryCommand.json +5 -2
- package/dist/resources/schemas/PreviewWorkflowCommand.json +45 -9
- package/dist/resources/schemas/ResolveMergeConflictsCommand.json +58 -0
- package/dist/resources/schemas/RevertMergePlanCommand.json +19 -0
- package/dist/resources/schemas/RunImportCommand.json +62 -0
- package/dist/resources/schemas/StepDto.json +34 -3
- package/dist/resources/schemas/UpdateBulkRowCommand.json +36 -0
- package/dist/resources/schemas/UpdateDatasourceCommand.json +15 -6
- package/dist/resources/schemas/UpdateEntityCommand.json +52 -11
- package/dist/resources/schemas/UpdateGlobalFunctionCommand.json +66 -0
- package/dist/resources/schemas/UpdateMicrofunctionCommand.json +121 -0
- package/dist/resources/schemas/UpdateMicrofunctionRuntimeCommand.json +54 -0
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +147 -4
- package/dist/resources/schemas/UpdateQueryCommand.json +13 -3
- package/dist/resources/schemas/UpdateRowCommand.json +40 -0
- package/dist/resources/schemas/UpdateViewCommand.json +15 -10
- package/dist/resources/schemas/UpdateWorkflowCommand.json +106 -14
- package/dist/server.js +17 -1
- package/dist/tools/access.js +3 -3
- package/dist/tools/activities.js +40 -0
- package/dist/tools/applications.js +1 -1
- package/dist/tools/automations.js +76 -34
- package/dist/tools/common.js +55 -0
- package/dist/tools/components.js +16 -7
- package/dist/tools/datasources.js +83 -21
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/deployments.js +34 -2
- package/dist/tools/dtos.js +25 -12
- package/dist/tools/entities.js +113 -28
- package/dist/tools/environments.js +52 -0
- package/dist/tools/externalComponents.js +9 -3
- package/dist/tools/files.js +57 -42
- package/dist/tools/flows.js +205 -13
- package/dist/tools/folders.js +7 -2
- package/dist/tools/functions.js +331 -0
- package/dist/tools/globalFunctions.js +63 -0
- package/dist/tools/importSchemas.js +79 -0
- package/dist/tools/imports.js +241 -0
- package/dist/tools/layouts.js +103 -29
- package/dist/tools/merges.js +113 -0
- package/dist/tools/microfunctions.js +155 -0
- package/dist/tools/microservices.js +270 -40
- package/dist/tools/organizations.js +5 -6
- package/dist/tools/pages.js +421 -104
- package/dist/tools/platformInfo.js +155 -11
- package/dist/tools/projects.js +183 -33
- package/dist/tools/queries.js +32 -10
- package/dist/tools/revisions.js +94 -0
- package/dist/tools/rows.js +484 -50
- package/dist/tools/screenWrite.js +68 -0
- package/dist/tools/screens.js +28 -0
- package/dist/tools/templates.js +32 -5
- package/dist/tools/translations.js +24 -8
- package/dist/tools/views.js +20 -10
- package/dist/tools/workflows.js +56 -21
- package/package.json +7 -2
package/dist/tools/flows.js
CHANGED
|
@@ -1,15 +1,37 @@
|
|
|
1
1
|
import { fetchHost, flowPath, hostParam, hostUpdateBody, unwrap } from './screens.js';
|
|
2
|
-
import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive } from './common.js';
|
|
2
|
+
import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive, microOps } from './common.js';
|
|
3
3
|
import { evaluatePolicy, enforcePolicy, attachFindings } from '../knowledge/policy.js';
|
|
4
|
-
import { normalizeFlowSteps, withNormalization } from '../knowledge/normalize.js';
|
|
4
|
+
import { normalizeFlowSteps, unknownSetterTargetWarnings, withNormalization } from '../knowledge/normalize.js';
|
|
5
5
|
import { flowBodyWarnings } from '../knowledge/coverage.js';
|
|
6
6
|
import { PlatformApiError } from '../platform/errors.js';
|
|
7
7
|
import { handle } from '../platform/responses.js';
|
|
8
|
-
import {
|
|
8
|
+
import { writeDiff, withWriteDiff } from '../platform/writeDiff.js';
|
|
9
|
+
import { resolvePatchOperations } from '../knowledge/outlines.js';
|
|
10
|
+
import { patchResult, baseVersionOf } from '../platform/patch.js';
|
|
11
|
+
import fastJsonPatch from 'fast-json-patch';
|
|
12
|
+
import { policyRules, flowExpressionSites } from '../knowledge/rules.js';
|
|
13
|
+
import { functionCallRefs } from '../knowledge/functionGuards.js';
|
|
9
14
|
import { randomUUID } from 'node:crypto';
|
|
10
15
|
import { z } from 'zod';
|
|
11
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Akış yazması yanıtında gövdeyi geri döndürmüyor, bu yüzden diff için akışı bir kez okuruz.
|
|
18
|
+
* ÖLÇÜLDÜ 2026-09-05 (Corecruiter koşusu, `S-19`): `code` adımının gövdesi kaydedilmedi,
|
|
19
|
+
* `flow_create` 200 döndü, `flow_get` adımı gösterdi ama `args` içinde kodu taşıyan alan yoktu —
|
|
20
|
+
* teşhis ~10 dakika sürdü ve tek belirti filtrenin hiçbir şey yapmamasıydı. Okuma başarısız
|
|
21
|
+
* olursa yazma yine başarılıdır: diff bir teşhis eklentisidir, yazmanın sonucu değil.
|
|
22
|
+
*/
|
|
23
|
+
async function flowWriteDrops(platform, host, project, environment, applicationId, hostId, flowId, sent) {
|
|
24
|
+
try {
|
|
25
|
+
const saved = unwrap(await platform.tenant('GET', project, flowPath(host, applicationId, hostId, flowId), { environment }));
|
|
26
|
+
return writeDiff(sent, saved);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return { dropped: [], normalized: [] };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const stepsParam = z.array(z.record(z.unknown())).describe("Adım listesi (StepManagementSchema: { stepId, name, type, kind, args, branches }). DİKKAT: branches[].nextStepId bir GUID değil, hedef adımın stepId STRING'idir; dal ADI motorun anahtarıdır ve start/setter/code/function adımlarında 'always' olmak zorundadır. Tam şablon: ngapps://examples/flow-load-table (ya da flow_get çıktısı); adım tipleri ve setter/parameters şekli platform_guide('page') Kural 1c. Kullanıcı fonksiyonu çağırmak için 'function' adımı: { type:'function', args:{ functionId:'<function_list id>', functionName:'<ad>', parameters:[{ name:'<bildirimdeki ad>', value:{ type:'static'|'property'|'storage'|'state'|'code', ref } }] } } → çıktı Steps.<adımAdı>.data (ngapps://examples/flow-call-function, platform_guide('functions')).");
|
|
12
33
|
const policyOverrideParam = z.boolean().optional();
|
|
34
|
+
const patchOperationsParam = z.array(z.record(z.unknown())).min(1).describe("RFC 6902 JSON Patch işlemleri; yolları flow_get çıktısıyla keşfedin. Dizi öğelerinde indeks yerine seçici kullanılabilir: '/steps[stepId=paint]/args/iteratees[element=tbl_recruiters]/mapping/source' — seçici gövde platforma gitmeden indekse çevrilir, çözülemezse istek hiç gönderilmez.");
|
|
13
35
|
const flowIdParam = guid.describe("Akış id'si; şemadaki events[].value bu id'dir");
|
|
14
36
|
function flowSummary(flow) {
|
|
15
37
|
return {
|
|
@@ -22,7 +44,15 @@ function flowSummary(flow) {
|
|
|
22
44
|
}
|
|
23
45
|
async function hostEnvelope(platform, host, project, environment, applicationId, hostId) {
|
|
24
46
|
const record = await fetchHost(platform, host, project, environment, applicationId, hostId);
|
|
25
|
-
return { [host]: hostUpdateBody(host, { ...record, applicationId }) };
|
|
47
|
+
return { record, envelope: { [host]: hostUpdateBody(host, { ...record, applicationId }) } };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* FLOW-024'ün arayacağı düğüm kümesi. Ham kaydın TAMAMI gezilmez: kayıt kendi `flows`'unu da
|
|
51
|
+
* taşıyabilir ve oradaki bayat element id'leri kümeyi kirletip aramayı sessizce boşa çıkarır.
|
|
52
|
+
* page/component düğümleri `schema`'da, layout'unkiler `views`'ta durur.
|
|
53
|
+
*/
|
|
54
|
+
function hostNodes(record) {
|
|
55
|
+
return record.schema ?? record.views ?? [];
|
|
26
56
|
}
|
|
27
57
|
async function requiredParameterWarnings(platform, project, environment, applicationId, steps) {
|
|
28
58
|
const warnings = [];
|
|
@@ -107,6 +137,95 @@ function rowsTargetsByStepName(steps) {
|
|
|
107
137
|
}
|
|
108
138
|
return targets;
|
|
109
139
|
}
|
|
140
|
+
const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
141
|
+
function toUiFunctionRecord(entry) {
|
|
142
|
+
return {
|
|
143
|
+
id: String(entry.id ?? ''),
|
|
144
|
+
name: String(entry.name ?? ''),
|
|
145
|
+
scope: String(entry.scope ?? 'application'),
|
|
146
|
+
pageId: typeof entry.pageId === 'string' ? entry.pageId : null,
|
|
147
|
+
isAsync: entry.isAsync === true,
|
|
148
|
+
parameters: (Array.isArray(entry.parameters) ? entry.parameters : [])
|
|
149
|
+
.filter(isRecord)
|
|
150
|
+
.map(parameter => ({ name: String(parameter.name ?? ''), required: parameter.required === true, defaultValue: parameter.defaultValue ?? null }))
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/** Uç okunamazsa (eski backend, yetki) `undefined`: uyarı üretilmez — lint yazmanın sonucu değil, eklentisidir. */
|
|
154
|
+
async function loadUiFunctions(platform, project, environment, applicationId) {
|
|
155
|
+
try {
|
|
156
|
+
const payload = await platform.tenant('GET', project, '/global-functions', { environment, query: { applicationId } });
|
|
157
|
+
return (Array.isArray(payload?.data) ? payload.data : []).filter(isRecord).map(toUiFunctionRecord);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* FLOW-024 / FLOW-025 (G-04 · G-05): `function` adımının bildirimle eşleşmesi ve ifadelerdeki
|
|
165
|
+
* `Functions.<ad>(…)` çağrılarının gerçek bir fonksiyona çözülmesi. Küme dinamiktir (uygulama
|
|
166
|
+
* fonksiyonları + barındırıcı SAYFANIN fonksiyonları, K2) — bu yüzden politika kuralı değil,
|
|
167
|
+
* ucu okuyan uyarıdır (`requiredParameterWarnings` deseni). docs/16 §5'in "lint yok" kararı
|
|
168
|
+
* fonksiyon kümesi dinamikleştiği için burada revize edildi (G-13).
|
|
169
|
+
*/
|
|
170
|
+
async function functionWarnings(platform, host, project, environment, applicationId, hostId, steps) {
|
|
171
|
+
const functionSteps = steps.filter(step => step.type === 'function');
|
|
172
|
+
const callSites = steps.flatMap(step => flowExpressionSites(step)
|
|
173
|
+
.flatMap(site => functionCallRefs(site.expression).map(ref => ({ step, origin: site.origin, ref }))));
|
|
174
|
+
if (functionSteps.length === 0 && callSites.length === 0)
|
|
175
|
+
return [];
|
|
176
|
+
const functions = await loadUiFunctions(platform, project, environment, applicationId);
|
|
177
|
+
if (functions === undefined)
|
|
178
|
+
return [];
|
|
179
|
+
const byId = new Map(functions.map(entry => [entry.id, entry]));
|
|
180
|
+
const byName = new Map(functions.map(entry => [entry.name, entry]));
|
|
181
|
+
const known = functions.map(entry => entry.name).sort().join(', ') || '(hiç fonksiyon yok)';
|
|
182
|
+
const visible = (entry) => entry.scope !== 'page' || (host === 'page' && entry.pageId === hostId);
|
|
183
|
+
const label = (step) => String(step.stepId ?? step.name ?? '?');
|
|
184
|
+
const warnings = new Set();
|
|
185
|
+
for (const step of functionSteps) {
|
|
186
|
+
const args = (step.args ?? {});
|
|
187
|
+
const id = typeof args.functionId === 'string' ? args.functionId : '';
|
|
188
|
+
const fn = byId.get(id);
|
|
189
|
+
if (fn === undefined) {
|
|
190
|
+
if (id !== '')
|
|
191
|
+
warnings.add(`FLOW-024: '${label(step)}' adımının functionId'si (${id}) uygulamada yok — platform 422 GlobalFunctionNotFound verir. Bilinen fonksiyonlar: ${known}. Gerçek id'yi function_list ile alın.`);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (typeof args.functionName === 'string' && args.functionName !== '' && args.functionName !== fn.name) {
|
|
195
|
+
warnings.add(`FLOW-024: '${label(step)}' adımının functionName'i '${args.functionName}' ama functionId '${fn.name}' fonksiyonuna ait — Studio özeti ve ad yedeği yanlış fonksiyonu gösterir; functionName: '${fn.name}' yazın.`);
|
|
196
|
+
}
|
|
197
|
+
if (!visible(fn)) {
|
|
198
|
+
warnings.add(`FLOW-024: '${label(step)}' adımı '${fn.name}' SAYFA fonksiyonunu çağırıyor ama fonksiyon başka bir sayfaya (${fn.pageId}) ait — bu ${host} bağlamının runtime paketi onu taşımaz, adım 'Functions.${fn.name} is not a function' ile düşer (K2). Fonksiyonu uygulama kapsamına alın ya da bu sayfada tanımlayın.`);
|
|
199
|
+
}
|
|
200
|
+
const given = (Array.isArray(args.parameters) ? args.parameters : []).filter(isRecord).map(parameter => String(parameter.name ?? ''));
|
|
201
|
+
const declared = fn.parameters.map(parameter => parameter.name);
|
|
202
|
+
const unknown = given.filter(name => name !== '' && !declared.includes(name));
|
|
203
|
+
if (unknown.length > 0) {
|
|
204
|
+
warnings.add(`FLOW-024: '${label(step)}' adımı '${fn.name}' fonksiyonunda olmayan parametre geçiyor: ${unknown.join(', ')} — bildirilenler: ${declared.join(', ') || '(parametresiz)'}. Eşleme ada göredir; tanınmayan parametre sessizce düşer.`);
|
|
205
|
+
}
|
|
206
|
+
const missing = fn.parameters.filter(parameter => parameter.required && !given.includes(parameter.name)).map(parameter => parameter.name);
|
|
207
|
+
if (missing.length > 0) {
|
|
208
|
+
warnings.add(`FLOW-024: '${label(step)}' adımında '${fn.name}' fonksiyonunun zorunlu parametresi eksik: ${missing.join(', ')} — çağrı 'Functions.${fn.name}: "${missing[0]}" is required' ile düşer, Steps.${String(step.name ?? label(step))}.error dolar ve akış hata gövdesiyle 'always' dalından devam eder.`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
for (const { step, origin, ref } of callSites) {
|
|
212
|
+
const fn = byName.get(ref.name);
|
|
213
|
+
if (fn === undefined) {
|
|
214
|
+
warnings.add(`FLOW-025: '${label(step)}' adımının ${origin} ifadesi Functions.${ref.name}(…) çağırıyor ama uygulamada bu adda fonksiyon yok — runtime 'Functions.${ref.name} is not a function' verir; runCode hatayı yutar, hedef prop yazılmaz. Bilinen fonksiyonlar: ${known}.`);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
if (!visible(fn)) {
|
|
218
|
+
warnings.add(`FLOW-025: '${label(step)}' adımının ${origin} ifadesi Functions.${ref.name}(…) çağırıyor ama bu bir SAYFA fonksiyonu ve başka sayfaya (${fn.pageId}) ait — bu ${host} bağlamında tanımsızdır (K2).`);
|
|
219
|
+
}
|
|
220
|
+
if (ref.argCount > fn.parameters.length) {
|
|
221
|
+
warnings.add(`FLOW-025: '${label(step)}' adımının ${origin} ifadesi Functions.${ref.name} için ${ref.argCount} argüman geçiyor, fonksiyon ${fn.parameters.length} parametre bildiriyor (${fn.parameters.map(parameter => parameter.name).join(', ') || 'parametresiz'}) — fazlası yok sayılır (konumsal eşleme, K5).`);
|
|
222
|
+
}
|
|
223
|
+
if (fn.isAsync && !(step.type === 'code' && origin === 'args.value')) {
|
|
224
|
+
warnings.add(`FLOW-025: '${label(step)}' adımının ${origin} ifadesi async fonksiyon Functions.${ref.name} çağırıyor — dönüş bir Promise'dir; setter/parametre/condition ifadesinde değer olarak '[object Promise]' kalır. async fonksiyonu code adımında 'await Functions.${ref.name}(…)' ile ya da function adımıyla çağırın.`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return [...warnings];
|
|
228
|
+
}
|
|
110
229
|
export function registerFlowTools(server, platform) {
|
|
111
230
|
const config = platform.config;
|
|
112
231
|
server.registerTool('flow_list', {
|
|
@@ -146,7 +265,7 @@ export function registerFlowTools(server, platform) {
|
|
|
146
265
|
},
|
|
147
266
|
annotations: writes
|
|
148
267
|
}, handle(config, async ({ project, environment, host, applicationId, hostId, name, slug, steps, errorSteps, flowId, policyOverride }) => {
|
|
149
|
-
const envelope = await hostEnvelope(platform, host, project, environment, applicationId, hostId);
|
|
268
|
+
const { record: hostRecord, envelope } = await hostEnvelope(platform, host, project, environment, applicationId, hostId);
|
|
150
269
|
const resolvedFlowId = flowId ?? randomUUID();
|
|
151
270
|
const flow = {
|
|
152
271
|
id: resolvedFlowId,
|
|
@@ -160,16 +279,21 @@ export function registerFlowTools(server, platform) {
|
|
|
160
279
|
const findings = enforcePolicy(evaluatePolicy(config, policyRules, 'flow', flow, { operation: 'create' }, policyOverride));
|
|
161
280
|
const parameterWarnings = [
|
|
162
281
|
...await requiredParameterWarnings(platform, project, environment, applicationId, steps),
|
|
163
|
-
...
|
|
282
|
+
...await functionWarnings(platform, host, project, environment, applicationId, hostId, steps),
|
|
283
|
+
...flowBodyWarnings(steps),
|
|
284
|
+
...unknownSetterTargetWarnings(steps, errorSteps ?? [], hostNodes(hostRecord))
|
|
164
285
|
];
|
|
165
286
|
await platform.tenant('POST', project, flowPath(host, applicationId, hostId), { environment, body: { flow, ...envelope } });
|
|
166
|
-
|
|
287
|
+
// Diff YALNIZ çağıranın yazdığı alanları kapsar; `id` ve barındırıcı bağı (`pageId` vb.)
|
|
288
|
+
// gövdeye gateway koyar, kullanıcının düzeltebileceği bir şey değildir.
|
|
289
|
+
const drops = await flowWriteDrops(platform, host, project, environment, applicationId, hostId, resolvedFlowId, { name: flow.name, slug: flow.slug, steps: flow.steps, errorSteps: flow.errorSteps });
|
|
290
|
+
return attachFindings(withWriteDiff(withNormalization({
|
|
167
291
|
host,
|
|
168
292
|
hostId,
|
|
169
293
|
flow: { id: resolvedFlowId, name, slug, steps: steps.length },
|
|
170
294
|
...(parameterWarnings.length > 0 ? { parameterWarnings } : {}),
|
|
171
295
|
hint: "Akışı bir olaya bağlamak için: page_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."
|
|
172
|
-
}, normalized), findings);
|
|
296
|
+
}, normalized), drops), findings);
|
|
173
297
|
}));
|
|
174
298
|
server.registerTool('flow_update', {
|
|
175
299
|
title: 'Akış güncelle',
|
|
@@ -192,7 +316,7 @@ export function registerFlowTools(server, platform) {
|
|
|
192
316
|
const current = unwrap(await platform.tenant('GET', project, flowPath(host, applicationId, hostId, flowId), { environment }));
|
|
193
317
|
if (!current.id)
|
|
194
318
|
throw new PlatformApiError(`'${flowId}' id'li akış bulunamadı; flow_list ile doğrulayın.`);
|
|
195
|
-
const envelope = await hostEnvelope(platform, host, project, environment, applicationId, hostId);
|
|
319
|
+
const { record: hostRecord, envelope } = await hostEnvelope(platform, host, project, environment, applicationId, hostId);
|
|
196
320
|
const flow = {
|
|
197
321
|
id: flowId,
|
|
198
322
|
name: name ?? current.name,
|
|
@@ -208,10 +332,78 @@ export function registerFlowTools(server, platform) {
|
|
|
208
332
|
: [];
|
|
209
333
|
const parameterWarnings = [
|
|
210
334
|
...await requiredParameterWarnings(platform, project, environment, applicationId, flow.steps),
|
|
211
|
-
...
|
|
335
|
+
...await functionWarnings(platform, host, project, environment, applicationId, hostId, flow.steps),
|
|
336
|
+
...flowBodyWarnings(flow.steps),
|
|
337
|
+
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord))
|
|
212
338
|
];
|
|
213
339
|
await platform.tenant('PUT', project, flowPath(host, applicationId, hostId, flowId), { environment, body: { flow, ...envelope } });
|
|
214
|
-
|
|
340
|
+
// Kısmi güncellemede yalnız GÖNDERİLEN alanlar karşılaştırılır; verilmeyen alan için
|
|
341
|
+
// "düştü" demek yanlış alarm olurdu.
|
|
342
|
+
const drops = await flowWriteDrops(platform, host, project, environment, applicationId, hostId, flowId, {
|
|
343
|
+
...(name === undefined ? {} : { name }),
|
|
344
|
+
...(slug === undefined ? {} : { slug }),
|
|
345
|
+
...(steps === undefined ? {} : { steps }),
|
|
346
|
+
...(errorSteps === undefined ? {} : { errorSteps })
|
|
347
|
+
});
|
|
348
|
+
return attachFindings(withWriteDiff(withNormalization({ host, hostId, flow: flowSummary(flow), ...(parameterWarnings.length > 0 ? { parameterWarnings } : {}) }, normalized), drops), findings);
|
|
349
|
+
}));
|
|
350
|
+
server.registerTool('flow_patch', {
|
|
351
|
+
title: "Akışa patch uygula",
|
|
352
|
+
description: "Tam gövdeyi bağlama almadan hedefli değişiklik: gateway akışı çeker, JSON Patch uygular, politika kontrolünden geçirip geri yazar. flow_update REPLACE olduğu için tek bir ifadeyi düzeltmek 10 adımlı gövdenin tamamını yeniden göndermek demekti (09-05 koşusunda aynı 11 KB'lik gövde beş kez gönderildi). Dizi öğelerinde indeks yerine SEÇİCİ kullanın — adım ve iteratee sırası platformda değişebilir: '/steps[stepId=paint]/args/iteratees[element=tbl_funnel]/mapping/mappings/share/ref' ya da '/steps[stepId=load_summary]/args/parameters[name=company]/value/ref'. Seçici çözülemezse istek HİÇ gönderilmez.",
|
|
353
|
+
inputSchema: {
|
|
354
|
+
project: projectParam,
|
|
355
|
+
environment: environmentParam,
|
|
356
|
+
host: hostParam,
|
|
357
|
+
applicationId: guid,
|
|
358
|
+
hostId: guid,
|
|
359
|
+
flowId: flowIdParam,
|
|
360
|
+
operations: patchOperationsParam.optional(),
|
|
361
|
+
ops: patchOperationsParam.optional().describe("'operations' ile aynı alan (eşanlamlı) — sayfa micro-op tool'larıyla aynı adı kullanabilmeniz için"),
|
|
362
|
+
policyOverride: policyOverrideParam
|
|
363
|
+
},
|
|
364
|
+
annotations: updates
|
|
365
|
+
}, handle(config, async ({ project, environment, host, applicationId, hostId, flowId, operations: givenOperations, ops, policyOverride }) => {
|
|
366
|
+
const operations = microOps('flow_patch', ops, givenOperations);
|
|
367
|
+
const current = unwrap(await platform.tenant('GET', project, flowPath(host, applicationId, hostId, flowId), { environment }));
|
|
368
|
+
if (!current.id)
|
|
369
|
+
throw new PlatformApiError(`'${flowId}' id'li akış bulunamadı; flow_list ile doğrulayın.`);
|
|
370
|
+
const document = structuredClone(current);
|
|
371
|
+
const resolved = resolvePatchOperations(document, operations, 'flow_get');
|
|
372
|
+
const patched = fastJsonPatch.applyPatch(document, resolved.operations, true, false).newDocument;
|
|
373
|
+
const { record: hostRecord } = await hostEnvelope(platform, host, project, environment, applicationId, hostId);
|
|
374
|
+
const flow = {
|
|
375
|
+
...patched,
|
|
376
|
+
id: flowId,
|
|
377
|
+
steps: patched.steps ?? [],
|
|
378
|
+
errorSteps: patched.errorSteps ?? [],
|
|
379
|
+
...(host === 'page' ? { pageId: hostId } : host === 'layout' ? { layoutId: hostId } : { componentId: hostId })
|
|
380
|
+
};
|
|
381
|
+
const normalized = [...normalizeFlowSteps(flow.steps), ...normalizeFlowSteps(flow.errorSteps)];
|
|
382
|
+
const findings = enforcePolicy(evaluatePolicy(config, policyRules, 'flow', flow, { operation: 'update' }, policyOverride));
|
|
383
|
+
const parameterWarnings = [
|
|
384
|
+
...await requiredParameterWarnings(platform, project, environment, applicationId, flow.steps),
|
|
385
|
+
...await functionWarnings(platform, host, project, environment, applicationId, hostId, flow.steps),
|
|
386
|
+
...flowBodyWarnings(flow.steps),
|
|
387
|
+
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord))
|
|
388
|
+
];
|
|
389
|
+
// Gövde değil FARK gönderilir: barındırıcı zarfı (envelope) yazma yolunda gerekmez, platform
|
|
390
|
+
// PATCH ucu akışı tek başına yazar. Net diff okunan kayıt ile son hâl arasından hesaplanır.
|
|
391
|
+
const netOps = fastJsonPatch.compare(current, flow);
|
|
392
|
+
const saved = await platform.tenant('PATCH', project, flowPath(host, applicationId, hostId, flowId), {
|
|
393
|
+
environment,
|
|
394
|
+
body: { baseVersion: baseVersionOf(current, 'flow_get'), ops: netOps }
|
|
395
|
+
});
|
|
396
|
+
const written = patchResult(saved, flow);
|
|
397
|
+
const drops = await flowWriteDrops(platform, host, project, environment, applicationId, hostId, flowId, { steps: flow.steps, errorSteps: flow.errorSteps });
|
|
398
|
+
return attachFindings(withWriteDiff(withNormalization({
|
|
399
|
+
host,
|
|
400
|
+
hostId,
|
|
401
|
+
applied: operations.length,
|
|
402
|
+
newVersion: written.newVersion,
|
|
403
|
+
patchTargets: resolved.targets,
|
|
404
|
+
flow: flowSummary(written.data),
|
|
405
|
+
...(parameterWarnings.length > 0 ? { parameterWarnings } : {})
|
|
406
|
+
}, [...normalized, ...resolved.notes.map(note => `patch yolu seçiciden indekse çözüldü: ${note}`)]), drops), findings);
|
|
215
407
|
}));
|
|
216
408
|
server.registerTool('flow_delete', {
|
|
217
409
|
title: 'Akış sil',
|
|
@@ -219,7 +411,7 @@ export function registerFlowTools(server, platform) {
|
|
|
219
411
|
inputSchema: { project: projectParam, environment: environmentParam, host: hostParam, applicationId: guid, hostId: guid, flowId: flowIdParam },
|
|
220
412
|
annotations: destructive
|
|
221
413
|
}, handle(config, async ({ project, environment, host, applicationId, hostId, flowId }) => {
|
|
222
|
-
const envelope = await hostEnvelope(platform, host, project, environment, applicationId, hostId);
|
|
414
|
+
const { envelope } = await hostEnvelope(platform, host, project, environment, applicationId, hostId);
|
|
223
415
|
await platform.tenant('DELETE', project, flowPath(host, applicationId, hostId, flowId), { environment, body: { id: flowId, ...envelope } });
|
|
224
416
|
return { deleted: flowId, host, hostId };
|
|
225
417
|
}));
|
package/dist/tools/folders.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { guid, projectParam, environmentParam, definitionParam, pagingParams, readOnly, writes, updates, destructive } from './common.js';
|
|
2
2
|
import { handle } from '../platform/responses.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
+
import { evaluatePolicy, enforcePolicy, attachFindings } from '../knowledge/policy.js';
|
|
5
|
+
import { policyRules } from '../knowledge/rules.js';
|
|
4
6
|
export function registerFolderTools(server, platform) {
|
|
5
7
|
const config = platform.config;
|
|
6
8
|
server.registerTool('folder_list', {
|
|
@@ -17,10 +19,13 @@ export function registerFolderTools(server, platform) {
|
|
|
17
19
|
}, handle(config, ({ project, environment, id, breadcrumb }) => platform.tenant('GET', project, breadcrumb ? `/folders/${id}/breadcrumb` : `/folders/${id}`, { environment })));
|
|
18
20
|
server.registerTool('folder_create', {
|
|
19
21
|
title: 'Klasör oluştur',
|
|
20
|
-
description: "Yeni klasör oluşturur (definition = CreateFolderCommand: { name, parentId? }). DİKKAT: fiziksel klasör adı ve depolama yolu ASCII'ye katlanır ('Donanım' → 'Donanim') ve aynı üst klasörde çakışırsa sonuna ' (1)' eklenir — kullanıcıya gösterilen displayName ham adı korur. Yanıttaki name/path katlanmış hâldir, dosya yollarını oradan okuyun.",
|
|
22
|
+
description: "Yeni klasör oluşturur (definition = CreateFolderCommand: { name, parentId? }). DİKKAT: fiziksel klasör adı ve depolama yolu ASCII'ye katlanır ('Donanım' → 'Donanim') ve aynı üst klasörde çakışırsa sonuna ' (1)' eklenir — kullanıcıya gösterilen displayName ham adı korur. Yanıttaki name/path katlanmış hâldir, dosya yollarını oradan okuyun. Backend ön kontrolü (FLD-001, block): name zorunlu ve \\|!#~$%&/=?»«@£§€{};'<>, karakterlerini içeremez.",
|
|
21
23
|
inputSchema: { project: projectParam, environment: environmentParam, definition: definitionParam },
|
|
22
24
|
annotations: writes
|
|
23
|
-
}, handle(config, ({ project, environment, definition }) =>
|
|
25
|
+
}, handle(config, async ({ project, environment, definition }) => {
|
|
26
|
+
const findings = enforcePolicy(evaluatePolicy(config, policyRules, 'folder', definition, { operation: 'create' }));
|
|
27
|
+
return attachFindings(await platform.tenant('POST', project, '/folders', { environment, body: definition }), findings);
|
|
28
|
+
}));
|
|
24
29
|
server.registerTool('folder_update', {
|
|
25
30
|
title: 'Klasör yetkilerini güncelle',
|
|
26
31
|
description: "Klasörün YETKİLENDİRMESİNİ günceller — `UpdateFolderCommand`'ın alanları yalnız `middlewareIds` ve `roleIds`'tir. Ad değiştirmek için folder_rename kullanın; **klasör TAŞIMA (parentId değiştirme) platformda desteklenmiyor** — gövdeye parentId/name koyarsanız sessizce yok sayılır ve istek yine 200 döner (etkinlik turu Ç3).",
|