@appaflytech/zeyrek-ai-mcp 0.0.24 → 0.0.26
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 +0 -15
- package/dist/config.js +0 -11
- package/dist/index.js +0 -2
- package/dist/knowledge/componentCatalog.js +25 -13
- package/dist/knowledge/componentEvents.js +6 -13
- package/dist/knowledge/normalize.js +17 -68
- package/dist/knowledge/rules.js +49 -137
- package/dist/knowledge/styleResolve.js +4 -50
- package/dist/knowledge/themeResolve.js +3 -3
- package/dist/observability/trace.js +1 -1
- package/dist/platform/diagnostics.js +4 -10
- package/dist/platform/domSummary.js +1 -1
- package/dist/platform/http.js +7 -23
- package/dist/platform/responses.js +2 -6
- package/dist/platform/{capture/capture.js → screenshot.js} +514 -52
- package/dist/platform/secrets.js +0 -9
- package/dist/platform/strictArguments.js +12 -68
- package/dist/platform/tokenVault.js +4 -187
- package/dist/resources/examples/workflow-http-step.json +2 -2
- package/dist/resources/guides/component.md +1 -6
- package/dist/resources/guides/expressions.md +2 -2
- package/dist/resources/guides/functions.md +1 -1
- package/dist/resources/guides/layout.md +7 -11
- package/dist/resources/guides/microfunction.md +28 -0
- package/dist/resources/guides/microservice.md +4 -10
- package/dist/resources/guides/middleware.md +1 -5
- package/dist/resources/guides/page.md +55 -215
- package/dist/resources/guides/theme.md +1 -4
- package/dist/resources/guides/translation.md +1 -1
- package/dist/resources/guides/workflow.md +9 -12
- package/dist/resources/schema-fingerprint.json +2 -2
- package/dist/resources/schemas/CreateWorkflowCommand.json +3 -0
- package/dist/resources/schemas/PreviewWorkflowCommand.json +3 -0
- package/dist/resources/schemas/StepDto.json +12 -9
- package/dist/resources/schemas/UpdateWorkflowCommand.json +3 -0
- package/dist/server.js +1 -3
- package/dist/tools/applications.js +3 -60
- package/dist/tools/components.js +10 -50
- package/dist/tools/datasources.js +1 -1
- package/dist/tools/designSchemaPatch.js +6 -16
- package/dist/tools/externalComponents.js +4 -25
- package/dist/tools/flows.js +6 -79
- package/dist/tools/layouts.js +12 -44
- package/dist/tools/microservices.js +10 -26
- package/dist/tools/pages.js +67 -303
- package/dist/tools/platformInfo.js +2 -6
- package/dist/tools/rows.js +1 -7
- package/dist/tools/schemaOps.js +1 -1
- package/dist/tools/screenWrite.js +5 -6
- package/dist/tools/screens.js +3 -90
- package/dist/tools/workflows.js +1 -1
- package/package.json +1 -1
- package/dist/knowledge/mobileComponentCatalog.js +0 -801
- package/dist/knowledge/mobileComponentEvents.js +0 -225
- package/dist/knowledge/platform/lint.js +0 -312
- package/dist/knowledge/platform/mobile.js +0 -78
- package/dist/knowledge/platform/mobileRules.js +0 -182
- package/dist/knowledge/platform/mobileTabs.js +0 -108
- package/dist/knowledge/platform/profile.js +0 -20
- package/dist/knowledge/platform/resolve.js +0 -122
- package/dist/knowledge/platform/web.js +0 -38
- package/dist/knowledge/styleResolveNative.js +0 -510
- package/dist/platform/argumentAliases.js +0 -128
- package/dist/platform/bodyFile.js +0 -103
- package/dist/platform/capture/actions.js +0 -333
- package/dist/platform/capture/browser.js +0 -1
- package/dist/platform/capture/console-log.js +0 -80
- package/dist/platform/capture/index.js +0 -11
- package/dist/platform/capture/readiness.js +0 -103
- package/dist/platform/capture/summary.js +0 -77
- package/dist/platform/capture/target.js +0 -5
- package/dist/platform/capture/targets/studio-mobile.js +0 -15
- package/dist/platform/capture/targets/studio-web.js +0 -5
- package/dist/platform/schemaReadMemory.js +0 -60
- package/dist/resources/examples/mobile-app-shell-drawer.json +0 -209
- package/dist/resources/examples/mobile-app-shell-stack.json +0 -123
- package/dist/resources/examples/mobile-app-shell-tab.json +0 -174
- package/dist/resources/examples/mobile-list-detail-form.json +0 -656
- package/dist/resources/guides/mobile.md +0 -419
- package/dist/tools/mobile.js +0 -203
- package/dist/tools/profileWrite.js +0 -45
package/dist/server.js
CHANGED
|
@@ -39,7 +39,6 @@ import { registerMergeTools } from "./tools/merges.js";
|
|
|
39
39
|
import { registerRevisionTools } from "./tools/revisions.js";
|
|
40
40
|
import { registerActivityTools } from "./tools/activities.js";
|
|
41
41
|
import { registerDtoTools } from "./tools/dtos.js";
|
|
42
|
-
import { registerMobileTools } from "./tools/mobile.js";
|
|
43
42
|
const moduleRegistrations = {
|
|
44
43
|
platform: registerPlatformTools,
|
|
45
44
|
project: registerProjectTools,
|
|
@@ -81,10 +80,9 @@ const moduleRegistrations = {
|
|
|
81
80
|
merge: registerMergeTools,
|
|
82
81
|
activity: registerActivityTools,
|
|
83
82
|
revision: registerRevisionTools,
|
|
84
|
-
mobile: registerMobileTools,
|
|
85
83
|
};
|
|
86
84
|
export function createGatewayServer(platform) {
|
|
87
|
-
const server = rejectUnknownArguments(instrumentServer(new McpServer({ name: "ngapps", version: "0.1.0" }), platform.config)
|
|
85
|
+
const server = rejectUnknownArguments(instrumentServer(new McpServer({ name: "ngapps", version: "0.1.0" }), platform.config));
|
|
88
86
|
for (const moduleName of platform.config.modules) {
|
|
89
87
|
moduleRegistrations[moduleName](server, platform);
|
|
90
88
|
}
|
|
@@ -1,44 +1,6 @@
|
|
|
1
1
|
import { guid, pagingParams, readOnly, writes, updates, destructive } from './common.js';
|
|
2
2
|
import { handle } from '../platform/responses.js';
|
|
3
|
-
import { forgetApplication, readApplicationPlatform, resolveApplication } from '../knowledge/platform/resolve.js';
|
|
4
|
-
import { mobileTabsProblems, readMobileTabs } from '../knowledge/platform/mobileTabs.js';
|
|
5
|
-
import { findingLine } from '../knowledge/platform/profile.js';
|
|
6
3
|
import { z } from 'zod';
|
|
7
|
-
/**
|
|
8
|
-
* MOB-007 (sekme ayarı) — `properties.mobile.tabs` yazan mobil uygulama çağrısının denetimi. Yazım
|
|
9
|
-
* platforma YİNE gider (D3; backend `properties`'i doğrulamaz): bulgu `platformWarnings`'e düşer.
|
|
10
|
-
* Sayfa ve widget listesi okunamazsa o denetimler atlanır, biçim denetimi yine koşar.
|
|
11
|
-
*/
|
|
12
|
-
export async function mobileTabsWarnings(platform, applicationId, projectSlug, homepageId, properties) {
|
|
13
|
-
const tabs = readMobileTabs(properties);
|
|
14
|
-
if (tabs === undefined)
|
|
15
|
-
return [];
|
|
16
|
-
const pages = applicationId && projectSlug
|
|
17
|
-
? await platform.tenant('GET', projectSlug, `/pages/${applicationId}`, { query: { pageIndex: 0, pageLength: 200 } })
|
|
18
|
-
.then(response => (response?.data ?? []).map(page => ({ id: String(page.id ?? '') })))
|
|
19
|
-
.catch(() => undefined)
|
|
20
|
-
: undefined;
|
|
21
|
-
const widgetIds = applicationId && projectSlug
|
|
22
|
-
? await platform.tenant('GET', projectSlug, `/components/${applicationId}`, { query: { pageIndex: 0, pageLength: 999 } })
|
|
23
|
-
.then(response => new Set((response?.data ?? []).filter(entry => entry.kind === 'widget').map(entry => String(entry.id ?? ''))))
|
|
24
|
-
.catch(() => undefined)
|
|
25
|
-
: undefined;
|
|
26
|
-
return mobileTabsProblems(tabs, {
|
|
27
|
-
...(pages ? { pages } : {}),
|
|
28
|
-
...(homepageId ? { homepageId } : {}),
|
|
29
|
-
...(widgetIds ? { widgetIds } : {})
|
|
30
|
-
}).map(message => findingLine({
|
|
31
|
-
code: 'MOB-007',
|
|
32
|
-
severity: 'warn',
|
|
33
|
-
message,
|
|
34
|
-
guide: "platform_guide('mobile') §Gezinme"
|
|
35
|
-
}));
|
|
36
|
-
}
|
|
37
|
-
function withPlatformWarnings(response, warnings) {
|
|
38
|
-
if (warnings.length === 0 || !response || typeof response !== 'object' || Array.isArray(response))
|
|
39
|
-
return response;
|
|
40
|
-
return { ...response, platformWarnings: warnings };
|
|
41
|
-
}
|
|
42
4
|
export function registerApplicationTools(server, platform) {
|
|
43
5
|
const config = platform.config;
|
|
44
6
|
server.registerTool('application_list', {
|
|
@@ -72,14 +34,7 @@ export function registerApplicationTools(server, platform) {
|
|
|
72
34
|
notFoundPageId: guid.optional()
|
|
73
35
|
},
|
|
74
36
|
annotations: writes
|
|
75
|
-
}, handle(config,
|
|
76
|
-
const warnings = readApplicationPlatform(body.type) === 'mobile'
|
|
77
|
-
? await mobileTabsWarnings(platform, undefined, undefined, undefined, body.properties)
|
|
78
|
-
: [];
|
|
79
|
-
const response = await platform.org('POST', `/applications/${projectId}`, { body });
|
|
80
|
-
forgetApplication(platform);
|
|
81
|
-
return withPlatformWarnings(response, warnings);
|
|
82
|
-
}));
|
|
37
|
+
}, handle(config, ({ projectId, ...body }) => platform.org('POST', `/applications/${projectId}`, { body })));
|
|
83
38
|
server.registerTool('application_update', {
|
|
84
39
|
title: 'Application güncelle',
|
|
85
40
|
description: 'Application bilgilerini günceller; homepageId zorunludur (mevcut değeri application_get ile alın).',
|
|
@@ -94,23 +49,11 @@ export function registerApplicationTools(server, platform) {
|
|
|
94
49
|
notFoundPageId: guid.optional()
|
|
95
50
|
},
|
|
96
51
|
annotations: updates
|
|
97
|
-
}, handle(config,
|
|
98
|
-
const current = await resolveApplication(platform, id);
|
|
99
|
-
const warnings = current?.platform === 'mobile'
|
|
100
|
-
? await mobileTabsWarnings(platform, id, current.projectSlug, body.homepageId, body.properties)
|
|
101
|
-
: [];
|
|
102
|
-
const response = await platform.org('PUT', `/applications/${id}`, { body });
|
|
103
|
-
forgetApplication(platform, id);
|
|
104
|
-
return withPlatformWarnings(response, warnings);
|
|
105
|
-
}));
|
|
52
|
+
}, handle(config, ({ id, ...body }) => platform.org('PUT', `/applications/${id}`, { body })));
|
|
106
53
|
server.registerTool('application_delete', {
|
|
107
54
|
title: 'Application sil',
|
|
108
55
|
description: 'Application\'ı kalıcı olarak siler.',
|
|
109
56
|
inputSchema: { id: guid },
|
|
110
57
|
annotations: destructive
|
|
111
|
-
}, handle(config,
|
|
112
|
-
const response = await platform.org('DELETE', `/applications/${args.id}`);
|
|
113
|
-
forgetApplication(platform, args.id);
|
|
114
|
-
return response;
|
|
115
|
-
}));
|
|
58
|
+
}, handle(config, args => platform.org('DELETE', `/applications/${args.id}`)));
|
|
116
59
|
}
|
package/dist/tools/components.js
CHANGED
|
@@ -1,40 +1,25 @@
|
|
|
1
1
|
import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive } from './common.js';
|
|
2
|
-
import { normalizeComponentDefaults, componentDefaultsNote, clampBlockSizes, blockSizeNote, normalizeHeightTypes, heightTypeNote, normalizeSizeStrings, sizeStringNote,
|
|
2
|
+
import { normalizeComponentDefaults, componentDefaultsNote, clampBlockSizes, blockSizeNote, normalizeHeightTypes, heightTypeNote, normalizeSizeStrings, sizeStringNote, withNormalization } from '../knowledge/normalize.js';
|
|
3
3
|
import { eventContractsFor, eventPayloadNote } from '../knowledge/componentEvents.js';
|
|
4
4
|
import { componentPresetDefaults, readProjectTheme } from '../knowledge/themeSchema.js';
|
|
5
5
|
import { knowledgeFor, knowledgeNote, APPEARANCE_TOKEN_SETS, STATE_FLAG_NOTES, INTERNAL_ROLES_BY_TYPE } from '../knowledge/componentCatalog.js';
|
|
6
|
-
import { MOBILE_STATE_FLAG_NOTES, mobileComponentKnowledge } from '../knowledge/mobileComponentCatalog.js';
|
|
7
|
-
import { mobileComponentEventContracts } from '../knowledge/mobileComponentEvents.js';
|
|
8
6
|
import { componentUpdateBody, fetchHost, schemaParam, unwrap } from './screens.js';
|
|
9
7
|
import { PlatformApiError } from '../platform/errors.js';
|
|
10
8
|
import { handle } from '../platform/responses.js';
|
|
11
|
-
import { applicationTypeField, resolveProfile } from '../knowledge/platform/resolve.js';
|
|
12
|
-
import { mobileComponentNotes } from '../knowledge/platform/mobileRules.js';
|
|
13
9
|
import { z } from 'zod';
|
|
14
|
-
const typeParam = z.enum(['web', 'mobile']).optional().describe('Hedef platform
|
|
10
|
+
const typeParam = z.enum(['web', 'mobile']).optional().describe('Hedef platform; varsayılan web');
|
|
15
11
|
const kindParam = z.enum(['component', 'widget']).optional()
|
|
16
12
|
.describe("component: sayfaya konan tekil eleman. widget: kendi şeması olan kapsayıcı (container/modal/drawer)");
|
|
17
13
|
const widgetTypeParam = z.enum(['container', 'modal', 'drawer']).optional()
|
|
18
14
|
.describe("kind:'widget' iken zorunlu");
|
|
19
|
-
/**
|
|
20
|
-
* Uç `type` verilmezse WEB kataloğunu döner (`GetComponentsQuery` `Type ?? Web`); mobil uygulamanın
|
|
21
|
-
* paleti, doğrulayıcısı ve widget'ları `type=mobile` satırlarıdır. Profil mobil derse sorgu tipi
|
|
22
|
-
* taşır; web'de sorgu profil öncesiyle aynıdır (G1 kilidi).
|
|
23
|
-
*/
|
|
24
15
|
async function listComponents(platform, project, environment, applicationId, scope) {
|
|
25
16
|
const path = scope === 'all' ? `/components/${applicationId}/all` : `/components/${applicationId}`;
|
|
26
|
-
const catalogType = scope === 'all' ? 'web' : (await resolveProfile(platform, applicationId)).profile.catalogType;
|
|
27
17
|
const response = await platform.tenant('GET', project, path, {
|
|
28
18
|
environment,
|
|
29
|
-
query: scope === 'all' ? undefined : { pageIndex: 0, pageLength: 999
|
|
19
|
+
query: scope === 'all' ? undefined : { pageIndex: 0, pageLength: 999 }
|
|
30
20
|
});
|
|
31
21
|
return response?.data ?? [];
|
|
32
22
|
}
|
|
33
|
-
/** Uygulamanın kayıtlı bileşen slug'ları (mobil profilin MOB-003 denetimi). */
|
|
34
|
-
export async function fetchCatalogSlugs(platform, project, environment, applicationId) {
|
|
35
|
-
const components = await listComponents(platform, project, environment, applicationId);
|
|
36
|
-
return new Set(components.map(component => String(component.slug ?? '')).filter(slug => slug.length > 0));
|
|
37
|
-
}
|
|
38
23
|
/**
|
|
39
24
|
* Yerleşim normalizasyonlarının ikisi de aynı katalog listesinden beslenir; tek okumada
|
|
40
25
|
* çıkarılır ki yazma yolları fazladan istek atmasın. Uygulamanın kendi sözlüğü okunur
|
|
@@ -53,17 +38,12 @@ export async function fetchComponentLayoutRules(platform, project, environment,
|
|
|
53
38
|
export function componentLayoutRules(components) {
|
|
54
39
|
const maxSizes = new Map();
|
|
55
40
|
const autoHeights = new Map();
|
|
56
|
-
const droppable = new Map();
|
|
57
41
|
for (const component of components) {
|
|
58
42
|
const slug = typeof component.slug === 'string' ? component.slug : undefined;
|
|
59
43
|
if (!slug)
|
|
60
44
|
continue;
|
|
61
45
|
if (typeof component.isDefaultAutoHeight === 'boolean')
|
|
62
46
|
autoHeights.set(slug, component.isDefaultAutoHeight);
|
|
63
|
-
// Kap bilgisi sözlükten gelir; düğümün `states.isDroppable`ı onu izler (Studio paleti de
|
|
64
|
-
// aynı alanı katalogdan yazar). `true` gören tip kap sayılır.
|
|
65
|
-
if (typeof component.isDroppable === 'boolean')
|
|
66
|
-
droppable.set(slug, component.isDroppable);
|
|
67
47
|
const blocks = (component.definition ?? {}).blocks;
|
|
68
48
|
if (!Array.isArray(blocks))
|
|
69
49
|
continue;
|
|
@@ -78,7 +58,7 @@ export function componentLayoutRules(components) {
|
|
|
78
58
|
});
|
|
79
59
|
}
|
|
80
60
|
}
|
|
81
|
-
return { maxSizes, autoHeights
|
|
61
|
+
return { maxSizes, autoHeights };
|
|
82
62
|
}
|
|
83
63
|
/**
|
|
84
64
|
* Katalog okuması başarısız olsa da yazma isteği gitmeli, ama iki normalizasyonun düşüş davranışı
|
|
@@ -89,21 +69,14 @@ export function componentLayoutRules(components) {
|
|
|
89
69
|
* varsayılanını (`fixed`, `DesignComponentManagementSchema.cs:24`) kabul etmek demektir; en fazla
|
|
90
70
|
* sekiz tipte (auth-layout/html/image/layout/qrcode/table/text-editor/video) fazladan yükseklik
|
|
91
71
|
* üretir, atlamak ise her tipte içerik kırpar.
|
|
92
|
-
* - `states.isDroppable` atlanır — katalog okunamadığında hangi tipin kap olduğu bilinmez ve
|
|
93
|
-
* uydurulmaz; düğüm bugünkü hâliyle yazılır.
|
|
94
72
|
*/
|
|
95
73
|
export async function applyCatalogLayoutRules(platform, project, environment, applicationId, nodes) {
|
|
96
74
|
try {
|
|
97
75
|
const rules = await fetchComponentLayoutRules(platform, project, environment, applicationId);
|
|
98
|
-
return {
|
|
99
|
-
clamped: clampBlockSizes(nodes, rules.maxSizes),
|
|
100
|
-
heights: normalizeHeightTypes(nodes, rules.autoHeights),
|
|
101
|
-
sizes: normalizeSizeStrings(nodes),
|
|
102
|
-
states: normalizeDroppableStates(nodes, rules.droppable)
|
|
103
|
-
};
|
|
76
|
+
return { clamped: clampBlockSizes(nodes, rules.maxSizes), heights: normalizeHeightTypes(nodes, rules.autoHeights), sizes: normalizeSizeStrings(nodes) };
|
|
104
77
|
}
|
|
105
78
|
catch {
|
|
106
|
-
return { clamped: [], heights: normalizeHeightTypes(nodes, new Map()), sizes: normalizeSizeStrings(nodes)
|
|
79
|
+
return { clamped: [], heights: normalizeHeightTypes(nodes, new Map()), sizes: normalizeSizeStrings(nodes) };
|
|
107
80
|
}
|
|
108
81
|
}
|
|
109
82
|
/**
|
|
@@ -143,7 +116,6 @@ export function registerComponentTools(server, platform) {
|
|
|
143
116
|
}, handle(config, async ({ project, environment, applicationId, scope, includeHidden }) => {
|
|
144
117
|
const components = await listComponents(platform, project, environment, applicationId, scope);
|
|
145
118
|
return {
|
|
146
|
-
...applicationTypeField(await resolveProfile(platform, applicationId)),
|
|
147
119
|
components: components
|
|
148
120
|
.filter(component => includeHidden === true || component.isHide !== true)
|
|
149
121
|
.map(component => ({
|
|
@@ -189,15 +161,6 @@ export function registerComponentTools(server, platform) {
|
|
|
189
161
|
: [];
|
|
190
162
|
const componentSlug = typeof component.slug === 'string' ? component.slug : undefined;
|
|
191
163
|
const knowledge = knowledgeFor(componentSlug);
|
|
192
|
-
// Mobil uygulamada kayıt mobil kataloğun satırıdır (`listComponents` type=mobile); davranış
|
|
193
|
-
// notları web runtime'ından gelir (`knowledge` — mobil şema web sınıfını genişletir), bileşenin
|
|
194
|
-
// mobil farkları `mobileKnowledge`'ta, bütün mobil bileşenlere geçen notlar `mobileNotes`'ta (G4).
|
|
195
|
-
// Web ikizi olmayan bileşende (`app-bar`, `tooltip`…) bilgi yalnız `mobileKnowledge`'tadır; olay
|
|
196
|
-
// yükleri de önce mobil sözlükten okunur (`mobileComponentEvents.ts`).
|
|
197
|
-
const mobile = (await resolveProfile(platform, applicationId)).profile.platform === 'mobile';
|
|
198
|
-
const mobileKnowledge = mobile && componentSlug !== undefined && Object.hasOwn(mobileComponentKnowledge, componentSlug)
|
|
199
|
-
? mobileComponentKnowledge[componentSlug]
|
|
200
|
-
: undefined;
|
|
201
164
|
// S-3 — `defaults` HAM katalogdur; Studio'da bırakılan düğüm ise temanın bileşen preseti
|
|
202
165
|
// kaplanmış katalogdan kurulur (`withThemeComponentDefaults`). Tema okunamazsa (uç düşer,
|
|
203
166
|
// yetki yoksa) alan yanıta HİÇ girmez: uydurulmuş bir varsayılan yanlış bilgidir.
|
|
@@ -214,7 +177,7 @@ export function registerComponentTools(server, platform) {
|
|
|
214
177
|
isDroppable: component.isDroppable,
|
|
215
178
|
props: definition.props,
|
|
216
179
|
defaults: definition.defaults,
|
|
217
|
-
events: eventContractsFor(componentSlug, eventNames
|
|
180
|
+
events: eventContractsFor(componentSlug, eventNames),
|
|
218
181
|
eventPayloadNote,
|
|
219
182
|
...(knowledge
|
|
220
183
|
? {
|
|
@@ -225,7 +188,7 @@ export function registerComponentTools(server, platform) {
|
|
|
225
188
|
},
|
|
226
189
|
...(knowledge.guide ? { guide: knowledge.guide } : {})
|
|
227
190
|
}
|
|
228
|
-
:
|
|
191
|
+
: { knowledgeNote }),
|
|
229
192
|
...(componentSlug && INTERNAL_ROLES_BY_TYPE[componentSlug]
|
|
230
193
|
? {
|
|
231
194
|
internalRoles: INTERNAL_ROLES_BY_TYPE[componentSlug],
|
|
@@ -233,9 +196,8 @@ export function registerComponentTools(server, platform) {
|
|
|
233
196
|
}
|
|
234
197
|
: {}),
|
|
235
198
|
...(themeDefaults ? { themeDefaults } : {}),
|
|
236
|
-
...(mobile ? { platform: 'mobile', ...(mobileKnowledge ? { mobileKnowledge } : {}), mobileNotes: mobileComponentNotes(componentSlug) } : {}),
|
|
237
199
|
appearanceValues: APPEARANCE_TOKEN_SETS,
|
|
238
|
-
stateFlags:
|
|
200
|
+
stateFlags: STATE_FLAG_NOTES,
|
|
239
201
|
validations: definition.validations,
|
|
240
202
|
sizes: definition.blocks
|
|
241
203
|
};
|
|
@@ -272,13 +234,11 @@ export function registerComponentTools(server, platform) {
|
|
|
272
234
|
const catalog = (body.schema ?? []).length > 0
|
|
273
235
|
? await applyCatalogLayoutRules(platform, project, environment, applicationId, body.schema)
|
|
274
236
|
: { clamped: [], heights: [], sizes: [] };
|
|
275
|
-
// Mobil uygulamanın widget'ı mobil katalog satırıdır; tip verilmezse uygulamanın tipi.
|
|
276
|
-
const defaultType = body.type ?? (await resolveProfile(platform, applicationId)).profile.catalogType;
|
|
277
237
|
return platform.tenant('POST', project, `/components/${applicationId}`, {
|
|
278
238
|
environment,
|
|
279
239
|
body: {
|
|
280
240
|
kind: 'component',
|
|
281
|
-
type:
|
|
241
|
+
type: 'web',
|
|
282
242
|
categories: [],
|
|
283
243
|
definition: {},
|
|
284
244
|
schema: [],
|
|
@@ -118,7 +118,7 @@ export function registerDatasourceTools(server, platform) {
|
|
|
118
118
|
}, handle(config, ({ project, environment }) => platform.tenant('GET', project, '/datasources/resources', { environment })));
|
|
119
119
|
server.registerTool('datasource_configuration_options', {
|
|
120
120
|
title: 'Yapılandırma seçenekleri',
|
|
121
|
-
description: "Datasource'un alan tipi kataloğunu döner: commonType başına dbType listesi, varsayılan tip, tipin kabul ettiği seçenek anahtarları (length/precision/collation/...) ve dönüştürülebilir tipler; ayrıca ilişki kuralları (onUpdate/onDelete) ve identity generation tipleri.
|
|
121
|
+
description: "Datasource'un alan tipi kataloğunu döner: commonType başına dbType listesi, varsayılan tip, tipin kabul ettiği seçenek anahtarları (length/precision/collation/...) ve dönüştürülebilir tipler; ayrıca ilişki kuralları (onUpdate/onDelete) ve identity generation tipleri. VARSAYILAN YANIT ÖZETTİR (~5 KB): collation DEĞER listesi (816 kayıt, tam yanıtın %79'u) dışarıdadır — tipin collation kabul edip etmediği zaten options'ta yazar. Collation değerleri gerçekten gerekiyorsa includeCollations: true ile tam yanıtı isteyin (~45 KB).",
|
|
122
122
|
inputSchema: {
|
|
123
123
|
project: projectParam,
|
|
124
124
|
environment: environmentParam,
|
|
@@ -8,8 +8,6 @@ import { fetchComponentEventNames } from './components.js';
|
|
|
8
8
|
import { PlatformApiError } from '../platform/errors.js';
|
|
9
9
|
import { handle } from '../platform/responses.js';
|
|
10
10
|
import { slotWarning } from './layouts.js';
|
|
11
|
-
import { applicationTypeField, resolveProfile } from '../knowledge/platform/resolve.js';
|
|
12
|
-
import { boundFlowSteps, screenProfileWarnings } from './profileWrite.js';
|
|
13
11
|
import { z } from 'zod';
|
|
14
12
|
const HOSTS = {
|
|
15
13
|
layout: {
|
|
@@ -87,8 +85,7 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
|
|
|
87
85
|
if (deletedFlows.length > 0 && allowFlowDeletion !== true)
|
|
88
86
|
throw new PlatformApiError(orphanedFlowMessage(deletedFlows), 400);
|
|
89
87
|
const added = opRecords.filter(entry => entry.op === 'add_component').map(entry => entry.component);
|
|
90
|
-
|
|
91
|
-
assertScreenWriteGuards(spec.kind, { schema: added }, resolved.profile.platform);
|
|
88
|
+
assertScreenWriteGuards(spec.kind, { schema: added });
|
|
92
89
|
const catalogNotes = await screenCatalogNotes(platform, project, environment, applicationId, added);
|
|
93
90
|
const flowWarnings = opRecords.some(entry => entry.op === 'remove_component')
|
|
94
91
|
? [...orphanedFlowWarnings(nodes, events, opRecords), ...staleSetterWarnings(Array.isArray(record.flows) ? record.flows : [], opRecords, nodes)]
|
|
@@ -103,19 +100,13 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
|
|
|
103
100
|
|| (entry.op === 'replace_prop' && FLEX_LAYOUT_PROP_NAMES.has(String(entry.prop ?? ''))));
|
|
104
101
|
const nested = simulatable ? nestedRepeaterNodes(simulated) : [];
|
|
105
102
|
if (nested.length > 0)
|
|
106
|
-
throw new PlatformApiError(nestedRepeaterMessage(nested
|
|
103
|
+
throw new PlatformApiError(nestedRepeaterMessage(nested), 400);
|
|
107
104
|
const reshaped = simulatable || opRecords.some(entry => entry.op === 'remove_component');
|
|
108
|
-
const profileWarnings = await screenProfileWarnings(platform, resolved, project, environment, applicationId, {
|
|
109
|
-
kind: spec.kind,
|
|
110
|
-
ops: [...opRecords, ...propTypeOps],
|
|
111
|
-
savedNodes: nodes,
|
|
112
|
-
steps: await boundFlowSteps(platform, resolved, project, environment, host, applicationId, id, opRecords)
|
|
113
|
-
});
|
|
114
105
|
const layoutWarnings = reshaped
|
|
115
106
|
? [
|
|
116
|
-
...
|
|
107
|
+
...verticalGapWarnings(simulated, spec.codes.gap, touched),
|
|
117
108
|
...stringStyleWarning(stringStyleNodes(simulated)),
|
|
118
|
-
...
|
|
109
|
+
...inertFlexPropWarning(inertFlexPropNodes(simulated)),
|
|
119
110
|
...flexSizeWarnings(simulated, spec.codes.flexMismatch, spec.codes.flexInvalid),
|
|
120
111
|
...(host === 'layout' ? slotWarning(simulated) : [])
|
|
121
112
|
]
|
|
@@ -142,9 +133,8 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
|
|
|
142
133
|
response.deletedFlows = deletedFlows;
|
|
143
134
|
if (flowWarnings.length > 0)
|
|
144
135
|
response.flowWarnings = flowWarnings;
|
|
145
|
-
if (layoutWarnings.length > 0
|
|
146
|
-
response.layoutWarnings =
|
|
147
|
-
Object.assign(response, applicationTypeField(resolved));
|
|
136
|
+
if (layoutWarnings.length > 0)
|
|
137
|
+
response.layoutWarnings = layoutWarnings;
|
|
148
138
|
const contentOps = opRecords.filter(entry => entry.op === 'add_component' || entry.op === 'replace_prop');
|
|
149
139
|
let opDrops = emptyWriteDiff();
|
|
150
140
|
if (contentOps.length > 0) {
|
|
@@ -7,23 +7,6 @@ import { z } from 'zod';
|
|
|
7
7
|
import { evaluatePolicy, enforcePolicy } from '../knowledge/policy.js';
|
|
8
8
|
import { policyRules } from '../knowledge/rules.js';
|
|
9
9
|
import { EXTERNAL_COMPONENT_PROTOCOL_VERSION } from '../knowledge/backendConstraints.js';
|
|
10
|
-
import { resolveProfile } from '../knowledge/platform/resolve.js';
|
|
11
|
-
import { findingLine } from '../knowledge/platform/profile.js';
|
|
12
|
-
/**
|
|
13
|
-
* MOB-006 — harici bileşen protokolü v1 tarayıcıda koşan `.mjs` custom element'tir; mobil
|
|
14
|
-
* uygulamanın native çizeri onu yükleyemez (mobil protokol v2 Faz 3). Profil kapalı derse çağrı
|
|
15
|
-
* platforma GİTMEZ: yüklenen paket hiçbir ekranda çizilmeyecekti.
|
|
16
|
-
*/
|
|
17
|
-
async function assertExternalComponentsAllowed(platform, applicationId, tool) {
|
|
18
|
-
const resolved = await resolveProfile(platform, applicationId);
|
|
19
|
-
if (resolved.profile.externalComponents)
|
|
20
|
-
return;
|
|
21
|
-
throw new PlatformApiError(`${tool}: ${findingLine({
|
|
22
|
-
code: 'MOB-006',
|
|
23
|
-
severity: 'warn',
|
|
24
|
-
message: "harici bileşen mobil uygulamada desteklenmiyor — protokol v1 tarayıcıda koşan .mjs custom element'tir, native çizer onu yükleyemez (mobil protokol v2 Faz 3). Çağrı platforma gönderilmedi; mobil ekranı katalog bileşenleriyle kurun (component_list). Katalogda karşılığı olmayan küçük görünüm için geçici yol 'html' bileşenidir: içerik korumalı belgede tema değişkenleriyle çizilir, fireEvent/ngApps.emit ile akışa bağlanır (component_get('html'))."
|
|
25
|
-
})}`, 400);
|
|
26
|
-
}
|
|
27
10
|
/** Platformun köprü protokolü; scaffold ve publish bu sürüme göre üretir/doğrular (backend ExternalComponentRules.CurrentProtocolVersion) */
|
|
28
11
|
const PROTOCOL_VERSION = EXTERNAL_COMPONENT_PROTOCOL_VERSION;
|
|
29
12
|
/** Backend `ExternalComponentRules.MaxBundleSizeBytes` ile aynı sınır */
|
|
@@ -216,7 +199,6 @@ export function registerExternalComponentTools(server, platform) {
|
|
|
216
199
|
},
|
|
217
200
|
annotations: writes
|
|
218
201
|
}, handle(config, async ({ project, environment, applicationId, bundlePath, manifestPath, version }) => {
|
|
219
|
-
await assertExternalComponentsAllowed(platform, applicationId, 'external_component_publish');
|
|
220
202
|
const manifestFile = resolve(manifestPath);
|
|
221
203
|
const bundleFile = resolve(bundlePath);
|
|
222
204
|
let manifest;
|
|
@@ -280,13 +262,10 @@ export function registerExternalComponentTools(server, platform) {
|
|
|
280
262
|
acknowledgeWarnings: z.boolean().optional().describe('Doğrulama uyarılarını okuyup kabul ettiğinizi bildirir; uyarısı olan sürümlerde zorunlu')
|
|
281
263
|
},
|
|
282
264
|
annotations: updates
|
|
283
|
-
}, handle(config,
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
body: { version, acknowledgeWarnings: acknowledgeWarnings === true }
|
|
288
|
-
});
|
|
289
|
-
}));
|
|
265
|
+
}, handle(config, ({ project, environment, applicationId, slug, version, acknowledgeWarnings }) => platform.tenant('POST', project, `/components/${applicationId}/external/${slug}/activate`, {
|
|
266
|
+
environment,
|
|
267
|
+
body: { version, acknowledgeWarnings: acknowledgeWarnings === true }
|
|
268
|
+
})));
|
|
290
269
|
server.registerTool('external_component_versions', {
|
|
291
270
|
title: 'Paket sürümlerini listele',
|
|
292
271
|
description: 'Bir harici komponentin yayınlanmış paket sürümlerini, hangisinin aktif olduğunu ve her sürümün doğrulama raporunu listeler. Geri alınacak sürümü buradan seçin.',
|
package/dist/tools/flows.js
CHANGED
|
@@ -13,7 +13,6 @@ import { policyRules, flowExpressionSites } from '../knowledge/rules.js';
|
|
|
13
13
|
import { functionCallRefs } from '../knowledge/functionGuards.js';
|
|
14
14
|
import { existingMatch, ifExistsParam, platformRename, withRename } from '../platform/ifExists.js';
|
|
15
15
|
import { randomUUID } from 'node:crypto';
|
|
16
|
-
import { flowProfileWarnings } from './profileWrite.js';
|
|
17
16
|
import { z } from 'zod';
|
|
18
17
|
/**
|
|
19
18
|
* Akış yazması yanıtında gövdeyi geri döndürmüyor, bu yüzden diff için akışı bir kez okuruz.
|
|
@@ -275,7 +274,7 @@ async function functionWarnings(platform, host, project, environment, applicatio
|
|
|
275
274
|
}
|
|
276
275
|
const missing = fn.parameters.filter(parameter => parameter.required && !given.includes(parameter.name)).map(parameter => parameter.name);
|
|
277
276
|
if (missing.length > 0) {
|
|
278
|
-
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
|
|
277
|
+
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.`);
|
|
279
278
|
}
|
|
280
279
|
}
|
|
281
280
|
for (const { step, origin, ref } of callSites) {
|
|
@@ -296,60 +295,6 @@ async function functionWarnings(platform, host, project, environment, applicatio
|
|
|
296
295
|
}
|
|
297
296
|
return [...warnings];
|
|
298
297
|
}
|
|
299
|
-
/**
|
|
300
|
-
* FLOW-028 (g-02, ADR 0004 — ZM-07). `microservice.ts` `.finally` üç yoldan birini dener: adımın
|
|
301
|
-
* kendi `error` dalı bağlıysa oradan sürer, yoksa flow `errorSteps`'i (`engine.onError`) devralır,
|
|
302
|
-
* ikisi de yoksa `always` koşar ve storage artık `{ data: null, headers: null, error }`'dır — hata
|
|
303
|
-
* gövdesi ARTIK `data`'da DEĞİL. İkisi de bağlı değilken bu adımın `.data`'sını okuyan bir
|
|
304
|
-
* setter/condition varsa hata anında NULL üzerinden koşar ve yazar hiç fark etmez. Aynı yürüyüş
|
|
305
|
-
* FLOW-024/025'in kullandığı `flowExpressionSites` taramasıdır; setter'ın STORAGE (kod olmayan)
|
|
306
|
-
* referansı ayrıca kendi düz alanından okunur (FLOW-008/009 deseni, `rowsTargetsByStepName`).
|
|
307
|
-
*/
|
|
308
|
-
function microserviceAlwaysDataWarnings(steps, errorSteps) {
|
|
309
|
-
const mainSteps = (Array.isArray(steps) ? steps : []).filter(isRecord);
|
|
310
|
-
const hasErrorFlow = (Array.isArray(errorSteps) ? errorSteps : []).filter(isRecord).some(step => String(step.type ?? '') !== 'start');
|
|
311
|
-
const label = (step) => String(step.stepId ?? step.name ?? '?');
|
|
312
|
-
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
313
|
-
const warnings = new Set();
|
|
314
|
-
for (const step of mainSteps) {
|
|
315
|
-
if (String(step.type ?? '') !== 'microservice')
|
|
316
|
-
continue;
|
|
317
|
-
const name = String(step.name ?? step.stepId ?? '');
|
|
318
|
-
if (name === '')
|
|
319
|
-
continue;
|
|
320
|
-
const hasErrorBranch = (Array.isArray(step.branches) ? step.branches : [])
|
|
321
|
-
.filter(isRecord)
|
|
322
|
-
.some(branch => String(branch.name ?? '') === 'error' && Boolean(branch.nextStepId));
|
|
323
|
-
if (hasErrorBranch || hasErrorFlow)
|
|
324
|
-
continue;
|
|
325
|
-
const pattern = new RegExp(`Steps\\s*(?:\\.\\s*${escapeRegExp(name)}\\b|\\[\\s*['"]${escapeRegExp(name)}['"]\\s*\\])\\s*\\??\\.\\s*data\\b`);
|
|
326
|
-
const message = (other) => `FLOW-028: '${label(other)}' adımı 'always' dalında '${name}.data' okuyor ama '${name}' adımının ne bağlı bir 'error' dalı ne akışın 'errorSteps'i var — uç hata dönerse bu adımın 'data'sı NULL olur (eskiden hata gövdesiydi, ADR 0004) ve '${label(other)}' boş/null veriyle koşar. '${name}' adımına 'error' dalı bağlayın ya da flow'a errorSteps verin.`;
|
|
327
|
-
for (const other of mainSteps) {
|
|
328
|
-
if (other === step)
|
|
329
|
-
continue;
|
|
330
|
-
if (String(other.type ?? '') === 'setter') {
|
|
331
|
-
const iteratees = Array.isArray(other.args?.iteratees)
|
|
332
|
-
? other.args.iteratees.filter(isRecord)
|
|
333
|
-
: [];
|
|
334
|
-
for (const iteratee of iteratees) {
|
|
335
|
-
const mapping = (iteratee.mapping ?? {});
|
|
336
|
-
const value = (iteratee.value ?? {});
|
|
337
|
-
const reference = typeof mapping.source === 'string' && mapping.source.length > 0
|
|
338
|
-
? mapping.source
|
|
339
|
-
: typeof value.ref === 'string' ? value.ref : '';
|
|
340
|
-
if (value.type === 'storage' && (reference === `${name}.data` || reference.startsWith(`${name}.data.`) || reference.startsWith(`${name}.data[`))) {
|
|
341
|
-
warnings.add(message(other));
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
for (const site of flowExpressionSites(other)) {
|
|
346
|
-
if (pattern.test(site.expression))
|
|
347
|
-
warnings.add(message(other));
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
return [...warnings];
|
|
352
|
-
}
|
|
353
298
|
export function registerFlowTools(server, platform) {
|
|
354
299
|
const config = platform.config;
|
|
355
300
|
server.registerTool('flow_list', {
|
|
@@ -423,8 +368,7 @@ export function registerFlowTools(server, platform) {
|
|
|
423
368
|
...await requiredParameterWarnings(platform, project, environment, applicationId, steps),
|
|
424
369
|
...await functionWarnings(platform, host, project, environment, applicationId, hostId, steps),
|
|
425
370
|
...flowBodyWarnings(steps),
|
|
426
|
-
...unknownSetterTargetWarnings(steps, errorSteps ?? [], hostNodes(hostRecord))
|
|
427
|
-
...microserviceAlwaysDataWarnings(steps, errorSteps ?? [])
|
|
371
|
+
...unknownSetterTargetWarnings(steps, errorSteps ?? [], hostNodes(hostRecord))
|
|
428
372
|
];
|
|
429
373
|
// Gövde yalnız akıştır (designer-partial-update K1): barındırıcı zarfı platformda hâlâ isteğe bağlı
|
|
430
374
|
// ama gönderilirse okunan tam kaydı yeniden yazar, açık Studio designer'ının kayıtlı tabanını
|
|
@@ -438,7 +382,6 @@ export function registerFlowTools(server, platform) {
|
|
|
438
382
|
// Diff YALNIZ çağıranın yazdığı alanları kapsar; `id` ve barındırıcı bağı (`pageId` vb.)
|
|
439
383
|
// gövdeye gateway koyar, kullanıcının düzeltebileceği bir şey değildir.
|
|
440
384
|
const drops = await flowWriteDrops(platform, host, project, environment, applicationId, hostId, writtenFlowId, { name: flow.name, slug: flow.slug, steps: flow.steps, errorSteps: flow.errorSteps }, ifExists === 'duplicate');
|
|
441
|
-
const platformWarnings = await flowProfileWarnings(platform, applicationId, [...(flow.steps ?? []), ...(flow.errorSteps ?? [])]);
|
|
442
385
|
return attachFindings(withWriteDiff(withRename(withNormalization({
|
|
443
386
|
host,
|
|
444
387
|
hostId,
|
|
@@ -450,7 +393,6 @@ export function registerFlowTools(server, platform) {
|
|
|
450
393
|
steps: steps.length
|
|
451
394
|
},
|
|
452
395
|
...(parameterWarnings.length > 0 ? { parameterWarnings } : {}),
|
|
453
|
-
...(platformWarnings.length > 0 ? { platformWarnings } : {}),
|
|
454
396
|
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."
|
|
455
397
|
}, normalized), drops.renamed), drops), findings);
|
|
456
398
|
}));
|
|
@@ -493,8 +435,7 @@ export function registerFlowTools(server, platform) {
|
|
|
493
435
|
...await requiredParameterWarnings(platform, project, environment, applicationId, flow.steps),
|
|
494
436
|
...await functionWarnings(platform, host, project, environment, applicationId, hostId, flow.steps),
|
|
495
437
|
...flowBodyWarnings(flow.steps),
|
|
496
|
-
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord))
|
|
497
|
-
...microserviceAlwaysDataWarnings(flow.steps, flow.errorSteps)
|
|
438
|
+
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord))
|
|
498
439
|
];
|
|
499
440
|
await platform.tenant('PUT', project, flowPath(host, applicationId, hostId, flowId), { environment, body: { flow } });
|
|
500
441
|
// Kısmi güncellemede yalnız GÖNDERİLEN alanlar karşılaştırılır; verilmeyen alan için
|
|
@@ -505,9 +446,7 @@ export function registerFlowTools(server, platform) {
|
|
|
505
446
|
...(steps === undefined ? {} : { steps }),
|
|
506
447
|
...(errorSteps === undefined ? {} : { errorSteps })
|
|
507
448
|
});
|
|
508
|
-
|
|
509
|
-
return attachFindings(withWriteDiff(withNormalization({ host, hostId, flow: flowSummary(flow), ...(parameterWarnings.length > 0 ? { parameterWarnings } : {}),
|
|
510
|
-
...(platformWarnings.length > 0 ? { platformWarnings } : {}) }, normalized), drops), findings);
|
|
449
|
+
return attachFindings(withWriteDiff(withNormalization({ host, hostId, flow: flowSummary(flow), ...(parameterWarnings.length > 0 ? { parameterWarnings } : {}) }, normalized), drops), findings);
|
|
511
450
|
}));
|
|
512
451
|
server.registerTool('flow_patch', {
|
|
513
452
|
title: "Akışa patch uygula",
|
|
@@ -546,8 +485,7 @@ export function registerFlowTools(server, platform) {
|
|
|
546
485
|
...await requiredParameterWarnings(platform, project, environment, applicationId, flow.steps),
|
|
547
486
|
...await functionWarnings(platform, host, project, environment, applicationId, hostId, flow.steps),
|
|
548
487
|
...flowBodyWarnings(flow.steps),
|
|
549
|
-
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord))
|
|
550
|
-
...microserviceAlwaysDataWarnings(flow.steps, flow.errorSteps)
|
|
488
|
+
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord))
|
|
551
489
|
];
|
|
552
490
|
// Gövde değil FARK gönderilir; platform PATCH ucu akışı tek başına yazar. Net diff okunan kayıt ile son hâl arasından hesaplanır.
|
|
553
491
|
const netOps = fastJsonPatch.compare(current, flow);
|
|
@@ -557,7 +495,6 @@ export function registerFlowTools(server, platform) {
|
|
|
557
495
|
});
|
|
558
496
|
const written = patchResult(saved, flow);
|
|
559
497
|
const drops = await flowWriteDrops(platform, host, project, environment, applicationId, hostId, flowId, { steps: flow.steps, errorSteps: flow.errorSteps });
|
|
560
|
-
const platformWarnings = await flowProfileWarnings(platform, applicationId, [...(flow.steps ?? []), ...(flow.errorSteps ?? [])]);
|
|
561
498
|
return attachFindings(withWriteDiff(withNormalization({
|
|
562
499
|
host,
|
|
563
500
|
hostId,
|
|
@@ -565,8 +502,7 @@ export function registerFlowTools(server, platform) {
|
|
|
565
502
|
newVersion: written.newVersion,
|
|
566
503
|
patchTargets: resolved.targets,
|
|
567
504
|
flow: flowSummary(written.data),
|
|
568
|
-
...(parameterWarnings.length > 0 ? { parameterWarnings } : {})
|
|
569
|
-
...(platformWarnings.length > 0 ? { platformWarnings } : {})
|
|
505
|
+
...(parameterWarnings.length > 0 ? { parameterWarnings } : {})
|
|
570
506
|
}, [...normalized, ...resolved.notes.map(note => `patch yolu seçiciden indekse çözüldü: ${note}`)]), drops), findings);
|
|
571
507
|
}));
|
|
572
508
|
server.registerTool('flow_delete', {
|
|
@@ -578,13 +514,4 @@ export function registerFlowTools(server, platform) {
|
|
|
578
514
|
await platform.tenant('DELETE', project, flowPath(host, applicationId, hostId, flowId), { environment, body: { id: flowId } });
|
|
579
515
|
return { deleted: flowId, host, hostId };
|
|
580
516
|
}));
|
|
581
|
-
server.registerTool('flow_restore', {
|
|
582
|
-
title: 'Silinen akışı geri yükle',
|
|
583
|
-
description: "Silinmiş bir akışı revizyon defterindeki son içeriğiyle (ad, slug, adımlar, barındırıcı) AYNI id ile yeniden kurar. Sayfa kaydı bağı kalmayan akışı kalıcı siler (FLOW-002, allowFlowDeletion) — Studio'nun eski sekmesi boş şema kaydettiğinde de (ZM-27). Akışı olaya YENİDEN BAĞLAMAZ: geri geldikten sonra set_event ile bağlayın. SINIR: adımları sayfanın bir komponentini hedefliyorsa (tetikleyen element, iterate/parametre komponenti) o komponent de şemada olmalıdır, yoksa geri yükleme reddedilir — sayfa boşaldıysa (ZM-27) page_restore kullanın: sayfayı ve akışlarını birlikte geri kurar. Akış hâlâ varsa 409, saklama süresi dolup revizyonu budanmışsa 404 döner. Silinen akışı revision_list(module: 'flow') satırlarında operation: delete olarak bulun; recordId akış id'sidir.",
|
|
584
|
-
inputSchema: { project: projectParam, environment: environmentParam, flowId: flowIdParam },
|
|
585
|
-
annotations: writes
|
|
586
|
-
}, handle(config, async ({ project, environment, flowId }) => {
|
|
587
|
-
const restored = unwrap(await platform.tenant('POST', project, `/flows/${flowId}/restore`, { environment }));
|
|
588
|
-
return { restored: flowId, flow: restored };
|
|
589
|
-
}));
|
|
590
517
|
}
|