@appaflytech/zeyrek-ai-mcp 0.0.30 → 0.0.32
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/README.md +5 -5
- package/dist/config.js +0 -37
- package/dist/index.js +0 -2
- package/dist/knowledge/backendConstraints.js +1 -18
- package/dist/knowledge/boxSections.js +184 -0
- package/dist/knowledge/componentCatalog.js +232 -562
- package/dist/knowledge/componentEvents.js +21 -141
- package/dist/knowledge/layoutSummary.js +2 -140
- package/dist/knowledge/normalize.js +67 -236
- package/dist/knowledge/outlines.js +0 -36
- package/dist/knowledge/policy.js +4 -18
- package/dist/knowledge/reservedTables.js +0 -79
- package/dist/knowledge/rules.js +21 -319
- package/dist/knowledge/schemaGuard.js +0 -11
- package/dist/knowledge/styleResolve.js +38 -55
- package/dist/knowledge/themeResolve.js +3 -3
- package/dist/observability/trace.js +3 -6
- package/dist/platform/diagnostics.js +4 -10
- package/dist/platform/domSummary.js +1 -1
- package/dist/platform/errors.js +10 -162
- package/dist/platform/http.js +8 -29
- package/dist/platform/responses.js +5 -39
- package/dist/platform/{capture/capture.js → screenshot.js} +519 -105
- package/dist/platform/secrets.js +1 -17
- package/dist/platform/strictArguments.js +12 -68
- package/dist/platform/tokenVault.js +4 -187
- package/dist/resources/examples/layout-app-shell.json +707 -229
- package/dist/resources/examples/page-detail-profile.json +1 -2
- package/dist/resources/examples/page-dynamic-form.json +2 -3
- package/dist/resources/examples/page-flex-sections.json +1 -1
- package/dist/resources/examples/page-html-embed.json +1 -1
- package/dist/resources/examples/workflow-basic.json +2 -8
- package/dist/resources/guides/component.md +4 -91
- package/dist/resources/guides/entity.md +8 -50
- package/dist/resources/guides/expressions.md +5 -14
- package/dist/resources/guides/functions.md +1 -1
- package/dist/resources/guides/getting-started.md +1 -38
- package/dist/resources/guides/layout.md +58 -55
- package/dist/resources/guides/microservice.md +2 -81
- package/dist/resources/guides/middleware.md +2 -44
- package/dist/resources/guides/page.md +75 -454
- package/dist/resources/guides/theme.md +2 -8
- package/dist/resources/guides/translation.md +1 -1
- package/dist/resources/guides/workflow.md +1 -58
- package/dist/resources/rules.js +5 -11
- package/dist/resources/schema-fingerprint.json +5 -7
- package/dist/resources/schemas/CreateEntityCommand.json +0 -118
- package/dist/resources/schemas/CreateMicroserviceCommand.json +1 -13
- package/dist/resources/schemas/CreateQueryCommand.json +0 -4
- package/dist/resources/schemas/CreateWorkflowCommand.json +1 -143
- package/dist/resources/schemas/DataJobDto.json +1 -6
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +1 -21
- package/dist/resources/schemas/MicroserviceDto.json +3 -15
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +1 -10
- package/dist/resources/schemas/PreviewWorkflowCommand.json +1 -22
- package/dist/resources/schemas/StepDto.json +1 -22
- package/dist/resources/schemas/UpdateEntityCommand.json +0 -118
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +1 -13
- package/dist/resources/schemas/UpdateQueryCommand.json +0 -4
- package/dist/resources/schemas/UpdateViewCommand.json +2 -0
- package/dist/resources/schemas/UpdateWorkflowCommand.json +1 -143
- package/dist/server.js +1 -27
- package/dist/tools/access.js +2 -369
- package/dist/tools/applications.js +3 -60
- package/dist/tools/common.js +0 -7
- package/dist/tools/components.js +14 -118
- package/dist/tools/datasources.js +3 -3
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/deployments.js +2 -2
- package/dist/tools/designSchemaPatch.js +18 -34
- package/dist/tools/dtos.js +5 -36
- package/dist/tools/entities.js +12 -79
- package/dist/tools/externalComponents.js +5 -26
- package/dist/tools/flows.js +14 -122
- package/dist/tools/folders.js +1 -1
- package/dist/tools/imports.js +2 -5
- package/dist/tools/layouts.js +17 -50
- package/dist/tools/merges.js +1 -1
- package/dist/tools/microservices.js +25 -77
- package/dist/tools/pages.js +112 -465
- package/dist/tools/platformInfo.js +8 -27
- package/dist/tools/projects.js +9 -71
- package/dist/tools/rows.js +13 -69
- package/dist/tools/schemaOps.js +1 -61
- package/dist/tools/screenWrite.js +8 -37
- package/dist/tools/screens.js +5 -95
- package/dist/tools/templates.js +1 -26
- package/dist/tools/translations.js +1 -1
- package/dist/tools/variables.js +5 -11
- package/dist/tools/workflows.js +5 -10
- package/package.json +2 -2
- package/dist/knowledge/access.js +0 -802
- package/dist/knowledge/case.js +0 -41
- package/dist/knowledge/connectDataBind.js +0 -819
- package/dist/knowledge/connectDataDefinition.js +0 -341
- package/dist/knowledge/connectDataExecute.js +0 -93
- package/dist/knowledge/connectDataRules.js +0 -128
- package/dist/knowledge/decision.js +0 -121
- package/dist/knowledge/expressionPrelude.js +0 -59
- package/dist/knowledge/microserviceParameters.js +0 -58
- package/dist/knowledge/mining.js +0 -94
- package/dist/knowledge/mobileComponentCatalog.js +0 -859
- package/dist/knowledge/mobileComponentEvents.js +0 -239
- package/dist/knowledge/platform/lint.js +0 -385
- package/dist/knowledge/platform/mobile.js +0 -142
- package/dist/knowledge/platform/mobileLayoutLint.js +0 -324
- package/dist/knowledge/platform/mobileRules.js +0 -231
- package/dist/knowledge/platform/mobileSpacing.js +0 -82
- package/dist/knowledge/platform/mobileTabs.js +0 -108
- package/dist/knowledge/platform/nativeBoxModel.js +0 -44
- package/dist/knowledge/platform/profile.js +0 -25
- package/dist/knowledge/platform/resolve.js +0 -122
- package/dist/knowledge/platform/web.js +0 -39
- package/dist/knowledge/process.js +0 -510
- package/dist/knowledge/rowFilter.js +0 -43
- package/dist/knowledge/styleResolveNative.js +0 -527
- 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 -122
- 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/impersonation.js +0 -45
- package/dist/platform/jsonArray.js +0 -24
- package/dist/platform/schemaReadMemory.js +0 -60
- package/dist/resources/examples/bpm-gorev-kontrol.json +0 -294
- package/dist/resources/examples/bpm-iso-dokuman.json +0 -228
- package/dist/resources/examples/bpm-satinalma.json +0 -376
- package/dist/resources/examples/connect-data-convert-verify.json +0 -107
- package/dist/resources/examples/connect-data-dropdown-roles.json +0 -66
- package/dist/resources/examples/connect-data-edit-m2m.json +0 -73
- package/dist/resources/examples/connect-data-query-params.json +0 -50
- package/dist/resources/examples/connect-data-table-entity.json +0 -147
- package/dist/resources/examples/connect-data-workflow-microservice.json +0 -65
- package/dist/resources/examples/mobile-app-shell-drawer.json +0 -243
- package/dist/resources/examples/mobile-app-shell-stack.json +0 -157
- package/dist/resources/examples/mobile-app-shell-tab.json +0 -208
- package/dist/resources/examples/mobile-form-screen.json +0 -365
- package/dist/resources/examples/mobile-list-detail-form.json +0 -672
- package/dist/resources/guides/access.md +0 -796
- package/dist/resources/guides/bpm.md +0 -686
- package/dist/resources/guides/case.md +0 -153
- package/dist/resources/guides/decision.md +0 -185
- package/dist/resources/guides/mobile-layout.md +0 -193
- package/dist/resources/guides/mobile.md +0 -495
- package/dist/resources/read.js +0 -41
- package/dist/resources/schemas/AccessExplanationDto.json +0 -144
- package/dist/resources/schemas/AccessMatrixDto.json +0 -170
- package/dist/resources/schemas/AccessPermissionDto.json +0 -57
- package/dist/resources/schemas/AccessPolicyDto.json +0 -223
- package/dist/resources/schemas/AccessResourceDto.json +0 -86
- package/dist/resources/schemas/AppSessionDto.json +0 -53
- package/dist/resources/schemas/ConnectDataDescribeDto.json +0 -344
- package/dist/resources/schemas/ConnectDataRequestModel.json +0 -202
- package/dist/resources/schemas/ConnectDataResultDto.json +0 -421
- package/dist/resources/schemas/ConnectorCredentialDto.json +0 -70
- package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +0 -37
- package/dist/resources/schemas/CreateAccessPolicyCommand.json +0 -209
- package/dist/resources/schemas/CreateDecisionCommand.json +0 -221
- package/dist/resources/schemas/CreateProcessDefinitionCommand.json +0 -1337
- package/dist/resources/schemas/DecisionDto.json +0 -302
- package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +0 -28
- package/dist/resources/schemas/ExplainAccessQuery.json +0 -33
- package/dist/resources/schemas/GenerateProcessDocumentCommand.json +0 -116
- package/dist/resources/schemas/OrganizationProjectDto.json +0 -335
- package/dist/resources/schemas/OrganizationSchemaDto.json +0 -196
- package/dist/resources/schemas/OrganizationSchemaVersionDto.json +0 -207
- package/dist/resources/schemas/PatchProcessDefinitionCommand.json +0 -76
- package/dist/resources/schemas/ProcessDefinitionDto.json +0 -1480
- package/dist/resources/schemas/ProcessSimulationDto.json +0 -96
- package/dist/resources/schemas/SaveConnectorCredentialCommand.json +0 -90
- package/dist/resources/schemas/SaveProcessEventSourceCommand.json +0 -61
- package/dist/resources/schemas/SaveProcessMailSourceCommand.json +0 -89
- package/dist/resources/schemas/SignProcessTaskCommand.json +0 -73
- package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +0 -92
- package/dist/resources/schemas/UpdateAccessPolicyCommand.json +0 -209
- package/dist/resources/schemas/UpdateDecisionCommand.json +0 -216
- package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +0 -1357
- package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +0 -1339
- package/dist/tools/accessOperations.js +0 -135
- package/dist/tools/accessPolicies.js +0 -170
- package/dist/tools/accessRuntime.js +0 -203
- package/dist/tools/bpm.js +0 -343
- package/dist/tools/bpmGovernance.js +0 -266
- package/dist/tools/bpmOperations.js +0 -230
- package/dist/tools/bpmReporting.js +0 -154
- package/dist/tools/bpmRouting.js +0 -150
- package/dist/tools/bpmRuntime.js +0 -396
- package/dist/tools/case.js +0 -178
- package/dist/tools/caseRuntime.js +0 -89
- package/dist/tools/connectData.js +0 -449
- package/dist/tools/connectors.js +0 -193
- package/dist/tools/decisions.js +0 -206
- package/dist/tools/mobile.js +0 -221
- package/dist/tools/modules.js +0 -48
- package/dist/tools/organizationStructure.js +0 -137
- package/dist/tools/profileWrite.js +0 -92
package/dist/tools/connectors.js
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive } from './common.js';
|
|
2
|
-
import { PlatformApiError } from '../platform/errors.js';
|
|
3
|
-
import { handle } from '../platform/responses.js';
|
|
4
|
-
import { assertProcessNotProduction } from './bpm.js';
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
const credentialKinds = ['api-key', 'basic', 'bearer', 'oauth2-client', 'oauth2-auth-code', 'webhook'];
|
|
7
|
-
const eventSourceKinds = ['http', 'rabbitmq', 'kafka', 'service-bus'];
|
|
8
|
-
const mailSourceKinds = ['imap', 'graph'];
|
|
9
|
-
const credentialFields = {
|
|
10
|
-
name: z.string().min(1).max(100).describe("kasa adı (tekil); düğümde credentialRef, kanal kimliklerinde sabit ad: notification-sms · notification-teams · notification-slack"),
|
|
11
|
-
connectorName: z.string().min(1).max(50).describe('connector_list adı; kaydedildikten sonra değişmez'),
|
|
12
|
-
kind: z.enum(credentialKinds),
|
|
13
|
-
baseUrl: z.string().max(500).optional().describe('instance/taban URL (Salesforce instance, Jira site, Camunda REST kökü)'),
|
|
14
|
-
tokenUrl: z.string().max(500).optional().describe('oauth2 belirteç ucu'),
|
|
15
|
-
clientId: z.string().max(200).optional(),
|
|
16
|
-
username: z.string().max(200).optional(),
|
|
17
|
-
scopes: z.array(z.string().max(200)).max(50).optional(),
|
|
18
|
-
apiKeyHeader: z.string().max(100).optional().describe("api-key başlığı; yoksa Authorization"),
|
|
19
|
-
clientSecret: z.string().max(4000).optional(),
|
|
20
|
-
password: z.string().max(4000).optional(),
|
|
21
|
-
apiKey: z.string().max(4000).optional().describe('webhook türünde webhook URL\'si buraya yazılır'),
|
|
22
|
-
refreshToken: z.string().max(4000).optional(),
|
|
23
|
-
accessToken: z.string().max(4000).optional()
|
|
24
|
-
};
|
|
25
|
-
function catalogOf(payload) {
|
|
26
|
-
const data = payload?.data ?? payload;
|
|
27
|
-
return Array.isArray(data) ? data : [];
|
|
28
|
-
}
|
|
29
|
-
export function registerConnectorTools(server, platform) {
|
|
30
|
-
const config = platform.config;
|
|
31
|
-
server.registerTool('connector_list', {
|
|
32
|
-
title: 'Bağlayıcı kataloğu',
|
|
33
|
-
description: "Kayıtlı bağlayıcıları listeler (GET bpm/connectors): ad, kategori (ai | process-engine | productivity | messaging | business-app | rpa), başlık, sürüm, desteklenen kimlik türleri ve işlem adları. category verilirse yalnız o kategori döner (süzme gateway'de). İşlem girdi/çıktı şemaları için connector_get. Süreçte kullanım: service düğümü connector { name, operation, credentialRef, input } ya da dış motor için externalEngine { engine: camunda8 | camunda7 | flowable, processKey, credentialRef, input }.",
|
|
34
|
-
inputSchema: {
|
|
35
|
-
project: projectParam,
|
|
36
|
-
environment: environmentParam,
|
|
37
|
-
category: z.enum(['ai', 'process-engine', 'productivity', 'messaging', 'business-app', 'rpa']).optional().describe('yalnız bu kategorideki bağlayıcılar')
|
|
38
|
-
},
|
|
39
|
-
annotations: readOnly
|
|
40
|
-
}, handle(config, async ({ project, environment, category }) => catalogOf(await platform.tenant('GET', project, '/bpm/connectors', { environment }))
|
|
41
|
-
.filter(connector => !category || connector.category === category)
|
|
42
|
-
.map(connector => ({
|
|
43
|
-
name: connector.name,
|
|
44
|
-
category: connector.category,
|
|
45
|
-
title: connector.title,
|
|
46
|
-
version: connector.version,
|
|
47
|
-
credentialKinds: connector.credentialKinds,
|
|
48
|
-
operations: (Array.isArray(connector.operations) ? connector.operations : []).map(operation => operation.name)
|
|
49
|
-
}))));
|
|
50
|
-
server.registerTool('connector_get', {
|
|
51
|
-
title: 'Bağlayıcıyı getir',
|
|
52
|
-
description: 'Bağlayıcının işlemlerini girdi ve çıktı şemalarıyla döner (katalogdan adla). Girdi doğrulaması zorunlu alanlar ve temel türlerle sınırlıdır; düğümde input değerleri Jint ifadesidir.',
|
|
53
|
-
inputSchema: { project: projectParam, environment: environmentParam, name: z.string().min(1).max(50) },
|
|
54
|
-
annotations: readOnly
|
|
55
|
-
}, handle(config, async ({ project, environment, name }) => {
|
|
56
|
-
const catalog = catalogOf(await platform.tenant('GET', project, '/bpm/connectors', { environment }));
|
|
57
|
-
const connector = catalog.find(candidate => candidate.name === name);
|
|
58
|
-
if (!connector)
|
|
59
|
-
throw new PlatformApiError(`connector_get: '${name}' diye bağlayıcı yok. Mevcutlar: ${catalog.map(candidate => String(candidate.name)).join(', ')}.`, 404);
|
|
60
|
-
return connector;
|
|
61
|
-
}));
|
|
62
|
-
server.registerTool('connector_credential_list', {
|
|
63
|
-
title: 'Kimlik kasasını listele',
|
|
64
|
-
description: "Kasa kayıtlarını listeler (GET bpm/connector-credentials): ad, bağlayıcı, tür, taban/belirteç URL'si, istemci kimliği, kapsamlar, secretFields (yalnız saklı sırların ADLARI) ve anahtar sürümü. Platform sırrı hiç döndürmez; gateway sır ya da belirteç adlı alanları ayrıca *** ile maskeler (BPM-017). Yetki process.manage.",
|
|
65
|
-
inputSchema: { project: projectParam, environment: environmentParam },
|
|
66
|
-
annotations: readOnly
|
|
67
|
-
}, handle(config, ({ project, environment }) => platform.tenant('GET', project, '/bpm/connector-credentials', { environment })));
|
|
68
|
-
server.registerTool('connector_credential_create', {
|
|
69
|
-
title: 'Kasaya kimlik yaz',
|
|
70
|
-
description: "Bağlayıcı kimliği oluşturur (POST bpm/connector-credentials). Sırlar (clientSecret, password, apiKey, refreshToken, accessToken) proje veri anahtarıyla şifrelenir; yanıtta ve gateway günlüğünde görünmez (BPM-017). Türler: basic · api-key (apiKeyHeader) · bearer · oauth2-client (tokenUrl, clientId, clientSecret, scopes) · oauth2-auth-code (refreshToken elle) · webhook (URL apiKey'de; teams-webhook, slack). Yazdıktan sonra connector_credential_update { operation: 'test' }.",
|
|
71
|
-
inputSchema: { project: projectParam, environment: environmentParam, ...credentialFields },
|
|
72
|
-
annotations: writes
|
|
73
|
-
}, handle(config, async ({ project, environment, ...credential }) => {
|
|
74
|
-
assertProcessNotProduction('connector_credential_create', environment, config);
|
|
75
|
-
return platform.tenant('POST', project, '/bpm/connector-credentials', { environment, body: credential });
|
|
76
|
-
}));
|
|
77
|
-
server.registerTool('connector_credential_update', {
|
|
78
|
-
title: 'Kasa kimliğini güncelle / test et / döndür',
|
|
79
|
-
description: "operation save (varsayılan; PUT bpm/connector-credentials/{id}, tam gövde — bütün sır alanları boşsa saklı sırlar korunur; TEK bir sır alanı bile gönderilirse saklı sırların tamamı gönderilenle değişir, o türün bütün sırlarını birlikte verin: oauth2-client clientSecret · oauth2-auth-code clientSecret + refreshToken · basic password · api-key/webhook apiKey · bearer accessToken) · test (POST …/{id}/test-connection; bağlayıcının bağlantı denemesi, hata 502 ConnectorFailed) · rotate (POST …/rotate; bütün sırları en yeni proje anahtar sürümüyle yeniden şifreler, id almaz, değişen sayısını döner; şifreleme anahtarı yapılandırılmamışsa kasa boş olsa bile ProtectionKeyUnavailable hatası döner — 0 başarı değildir).",
|
|
80
|
-
inputSchema: {
|
|
81
|
-
project: projectParam,
|
|
82
|
-
environment: environmentParam,
|
|
83
|
-
id: guid.optional().describe('save ve test için zorunlu'),
|
|
84
|
-
operation: z.enum(['save', 'test', 'rotate']).optional(),
|
|
85
|
-
...z.object(credentialFields).partial().shape
|
|
86
|
-
},
|
|
87
|
-
annotations: updates
|
|
88
|
-
}, handle(config, async ({ project, environment, id, operation, ...credential }) => {
|
|
89
|
-
assertProcessNotProduction('connector_credential_update', environment, config);
|
|
90
|
-
const resolvedOperation = operation ?? 'save';
|
|
91
|
-
if (resolvedOperation === 'rotate')
|
|
92
|
-
return platform.tenant('POST', project, '/bpm/connector-credentials/rotate', { environment });
|
|
93
|
-
if (!id)
|
|
94
|
-
throw new PlatformApiError(`connector_credential_update: operation '${resolvedOperation}' id ister (istek gönderilmedi).`, 400);
|
|
95
|
-
if (resolvedOperation === 'test')
|
|
96
|
-
return platform.tenant('POST', project, `/bpm/connector-credentials/${id}/test-connection`, { environment });
|
|
97
|
-
if (!credential.name || !credential.connectorName || !credential.kind)
|
|
98
|
-
throw new PlatformApiError("connector_credential_update: save tam gövde ister — name, connectorName, kind (connector_credential_list çıktısından) (istek gönderilmedi).", 400);
|
|
99
|
-
return platform.tenant('PUT', project, `/bpm/connector-credentials/${id}`, { environment, body: credential });
|
|
100
|
-
}));
|
|
101
|
-
server.registerTool('connector_credential_delete', {
|
|
102
|
-
title: 'Kasa kimliğini sil',
|
|
103
|
-
description: 'Kimliği siler (DELETE bpm/connector-credentials/{id}). Bir süreç düğümü kullanıyorsa 422 ReferencedByProcess, bir olay ya da e-posta kaynağı kullanıyorsa 400 RowHasExistingRelation döner; önce başvuruları değiştirin.',
|
|
104
|
-
inputSchema: { project: projectParam, environment: environmentParam, id: guid },
|
|
105
|
-
annotations: destructive
|
|
106
|
-
}, handle(config, async ({ project, environment, id }) => {
|
|
107
|
-
assertProcessNotProduction('connector_credential_delete', environment, config);
|
|
108
|
-
return platform.tenant('DELETE', project, `/bpm/connector-credentials/${id}`, { environment });
|
|
109
|
-
}));
|
|
110
|
-
server.registerTool('process_event_source_list', {
|
|
111
|
-
title: 'Olay kaynaklarını listele',
|
|
112
|
-
description: 'Olay kaynaklarını listeler (GET bpm/event-sources): ad, tür, adres, mesaj adı, korelasyon anahtarı ifadesi, tampon süresi, etkinlik ve son olay zamanı.',
|
|
113
|
-
inputSchema: { project: projectParam, environment: environmentParam },
|
|
114
|
-
annotations: readOnly
|
|
115
|
-
}, handle(config, ({ project, environment }) => platform.tenant('GET', project, '/bpm/event-sources', { environment })));
|
|
116
|
-
server.registerTool('process_event_source_create', {
|
|
117
|
-
title: 'Olay kaynağı yaz',
|
|
118
|
-
description: "Dış olayı BPM mesajına çeviren kaynak oluşturur (POST bpm/event-sources) ya da id verilirse tam gövdeyle günceller (PUT …/{id}). Olay girişi process_trigger { kind: 'event-source', name, eventId, payload }: payload korelasyon anahtarı Jint ifadesiyle (ör. 'payload.siparisNo') mesaja dönüşür, aynı eventId ikinci kez işlenmez. kind http taşımadan bağımsızdır; kafka/service-bus tüketicisi henüz yok (NuGet), rabbitmq dinleyicisi borç.",
|
|
119
|
-
inputSchema: {
|
|
120
|
-
project: projectParam,
|
|
121
|
-
environment: environmentParam,
|
|
122
|
-
id: guid.optional().describe('verilirse güncelleme'),
|
|
123
|
-
name: z.string().min(1).max(100),
|
|
124
|
-
kind: z.enum(eventSourceKinds),
|
|
125
|
-
address: z.string().max(500).optional().describe('konu/kuyruk adresi'),
|
|
126
|
-
credentialRef: z.string().max(100).optional().describe('kasadaki kaydın adı (connector_credential_list); olmayan ad 404'),
|
|
127
|
-
messageName: z.string().min(1).max(100),
|
|
128
|
-
correlationKey: z.string().max(500).optional().describe("Jint ifadesi, ör. 'payload.siparisNo'"),
|
|
129
|
-
bufferSeconds: z.number().int().min(0).max(86400).optional(),
|
|
130
|
-
isActive: z.boolean().optional()
|
|
131
|
-
},
|
|
132
|
-
annotations: writes
|
|
133
|
-
}, handle(config, async ({ project, environment, id, ...source }) => {
|
|
134
|
-
assertProcessNotProduction('process_event_source_create', environment, config);
|
|
135
|
-
return id
|
|
136
|
-
? platform.tenant('PUT', project, `/bpm/event-sources/${id}`, { environment, body: source })
|
|
137
|
-
: platform.tenant('POST', project, '/bpm/event-sources', { environment, body: source });
|
|
138
|
-
}));
|
|
139
|
-
server.registerTool('process_event_source_delete', {
|
|
140
|
-
title: 'Olay kaynağını sil',
|
|
141
|
-
description: 'Olay kaynağını siler (DELETE bpm/event-sources/{id}); o ada gelen olaylar 404 alır.',
|
|
142
|
-
inputSchema: { project: projectParam, environment: environmentParam, id: guid },
|
|
143
|
-
annotations: destructive
|
|
144
|
-
}, handle(config, async ({ project, environment, id }) => {
|
|
145
|
-
assertProcessNotProduction('process_event_source_delete', environment, config);
|
|
146
|
-
return platform.tenant('DELETE', project, `/bpm/event-sources/${id}`, { environment });
|
|
147
|
-
}));
|
|
148
|
-
server.registerTool('process_mail_source_list', {
|
|
149
|
-
title: 'E-posta kaynaklarını listele',
|
|
150
|
-
description: 'E-posta kaynaklarını listeler (GET bpm/mail-sources): tür (imap | graph), sunucu, posta kutusu, klasör, kurallar, son UID ve son yoklama zamanı.',
|
|
151
|
-
inputSchema: { project: projectParam, environment: environmentParam },
|
|
152
|
-
annotations: readOnly
|
|
153
|
-
}, handle(config, ({ project, environment }) => platform.tenant('GET', project, '/bpm/mail-sources', { environment })));
|
|
154
|
-
server.registerTool('process_mail_source_create', {
|
|
155
|
-
title: 'E-posta kaynağı yaz',
|
|
156
|
-
description: "Gelen e-postayı kurallarla BPM mesajına çeviren kaynak oluşturur (POST bpm/mail-sources) ya da id verilirse günceller (PUT …/{id}). Kural { subjectPattern, fromPattern (regex), messageName, correlationKey (Jint; mail.subject, mail.from, match.groups) }; ekler files'a yazılır, aynı Message-ID ikinci kez işlenmez. credentialRef kasadaki bir kaydın adıdır (connector_credential_list): kayıtta kimliğe çözülür, olmayan ad 404 (connector-credential: <ad>) döner; kasa kaydının adı sonradan değişirse kaynak yeni adı gösterir. imap kimliği 'imap' bağlayıcısının kasa kaydıdır (basic), graph kimliği 'microsoft-graph' (oauth2-client). Zamanlanmış yoklama yok: process_trigger { kind: 'mail-source', sourceId }.",
|
|
157
|
-
inputSchema: {
|
|
158
|
-
project: projectParam,
|
|
159
|
-
environment: environmentParam,
|
|
160
|
-
id: guid.optional().describe('verilirse güncelleme'),
|
|
161
|
-
name: z.string().min(1).max(100),
|
|
162
|
-
kind: z.enum(mailSourceKinds),
|
|
163
|
-
host: z.string().max(200).optional(),
|
|
164
|
-
port: z.number().int().min(1).max(65535).optional(),
|
|
165
|
-
useSsl: z.boolean().optional(),
|
|
166
|
-
mailbox: z.string().max(200).optional(),
|
|
167
|
-
folder: z.string().max(200).optional(),
|
|
168
|
-
credentialRef: z.string().min(1).max(100).describe('kasadaki kaydın adı (connector_credential_list); olmayan ad 404'),
|
|
169
|
-
rules: z.array(z.object({
|
|
170
|
-
subjectPattern: z.string().max(500).optional(),
|
|
171
|
-
fromPattern: z.string().max(500).optional(),
|
|
172
|
-
messageName: z.string().min(1).max(100),
|
|
173
|
-
correlationKey: z.string().max(500).optional()
|
|
174
|
-
})).min(1).max(50),
|
|
175
|
-
isActive: z.boolean().optional()
|
|
176
|
-
},
|
|
177
|
-
annotations: writes
|
|
178
|
-
}, handle(config, async ({ project, environment, id, ...source }) => {
|
|
179
|
-
assertProcessNotProduction('process_mail_source_create', environment, config);
|
|
180
|
-
return id
|
|
181
|
-
? platform.tenant('PUT', project, `/bpm/mail-sources/${id}`, { environment, body: source })
|
|
182
|
-
: platform.tenant('POST', project, '/bpm/mail-sources', { environment, body: source });
|
|
183
|
-
}));
|
|
184
|
-
server.registerTool('process_mail_source_delete', {
|
|
185
|
-
title: 'E-posta kaynağını sil',
|
|
186
|
-
description: 'E-posta kaynağını siler (DELETE bpm/mail-sources/{id}).',
|
|
187
|
-
inputSchema: { project: projectParam, environment: environmentParam, id: guid },
|
|
188
|
-
annotations: destructive
|
|
189
|
-
}, handle(config, async ({ project, environment, id }) => {
|
|
190
|
-
assertProcessNotProduction('process_mail_source_delete', environment, config);
|
|
191
|
-
return platform.tenant('DELETE', project, `/bpm/mail-sources/${id}`, { environment });
|
|
192
|
-
}));
|
|
193
|
-
}
|
package/dist/tools/decisions.js
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
import { guid, projectParam, environmentParam, pagingParams, readOnly, writes, updates, destructive, microOps } from './common.js';
|
|
2
|
-
import { applyPolicyMode, attachFindings, PolicyBlockError } from '../knowledge/policy.js';
|
|
3
|
-
import { assertInline, writeLocalFile } from './bpmGovernance.js';
|
|
4
|
-
import { assertProcessNotProduction, dataOf } from './bpm.js';
|
|
5
|
-
import { unmappedMembers, withUnmappedMembers } from '../knowledge/schemaGuard.js';
|
|
6
|
-
import { resolvePatchOperations } from '../knowledge/outlines.js';
|
|
7
|
-
import { decisionFindings } from '../knowledge/decision.js';
|
|
8
|
-
import { withNormalization } from '../knowledge/normalize.js';
|
|
9
|
-
import { PlatformApiError } from '../platform/errors.js';
|
|
10
|
-
import { handle } from '../platform/responses.js';
|
|
11
|
-
import { readFile } from 'node:fs/promises';
|
|
12
|
-
import fastJsonPatch from 'fast-json-patch';
|
|
13
|
-
import { resolve } from 'node:path';
|
|
14
|
-
import { z } from 'zod';
|
|
15
|
-
const maxInlineXmlBytes = 256_000;
|
|
16
|
-
const maxDmnBytes = 5_000_000;
|
|
17
|
-
const decisionParam = z.record(z.unknown())
|
|
18
|
-
.describe("Karar modeli: { slug, name, kind: table | literal, hitPolicy: unique | any | first | priority | collect | rule-order | output-order, aggregation?, inputs[{ id, label, expression, typeRef, allowedValues }], outputs[{ id, name, typeRef, allowedValues, defaultOutputEntry }], rules[{ id, description, inputEntries[], outputEntries[] }], requires[], inputData[], literalExpression?, typeRef? }. Hücreler FEEL; '-' joker. Ayrıntı platform_guide('decision').");
|
|
19
|
-
const policyOverrideParam = z.boolean().optional()
|
|
20
|
-
.describe("true: politika block bulgularını warn'a indirir (bilinçli istisna; yanıtta işaretlenir)");
|
|
21
|
-
const patchOperationsParam = z.array(z.record(z.unknown())).min(1)
|
|
22
|
-
.describe("RFC 6902 JSON Patch işlemleri, yollar karar modeline göre. Kural ve sütun hedeflerken İNDEKS YERİNE SEÇİCİ: { op: 'replace', path: '/rules[id=buyuk]/outputEntries/0', value: '3' }; yeni kural '/rules/-'.");
|
|
23
|
-
function lintDecision(config, decision, policyOverride) {
|
|
24
|
-
if (config.policyMode === 'off')
|
|
25
|
-
return [];
|
|
26
|
-
const findings = applyPolicyMode(config, decisionFindings(decision), policyOverride === true);
|
|
27
|
-
const blocking = findings.filter(finding => finding.severity === 'block');
|
|
28
|
-
if (blocking.length > 0)
|
|
29
|
-
throw new PolicyBlockError(blocking);
|
|
30
|
-
return findings;
|
|
31
|
-
}
|
|
32
|
-
export function registerDecisionTools(server, platform) {
|
|
33
|
-
const config = platform.config;
|
|
34
|
-
server.registerTool('decision_list', {
|
|
35
|
-
title: 'Kararları listele',
|
|
36
|
-
description: "DMN karar tablolarını ve literal kararları listeler (GET bpm/decisions): slug, ad, kind, hitPolicy, aktif ve taslak sürüm numarası. Süreçte 'decision' düğümü decisionSlug ile başvurur.",
|
|
37
|
-
inputSchema: { project: projectParam, environment: environmentParam, searchTerm: z.string().max(200).optional(), applicationId: guid.optional(), ...pagingParams },
|
|
38
|
-
annotations: readOnly
|
|
39
|
-
}, handle(config, ({ project, environment, ...query }) => platform.tenant('GET', project, '/bpm/decisions', { environment, query })));
|
|
40
|
-
server.registerTool('decision_get', {
|
|
41
|
-
title: 'Kararı getir',
|
|
42
|
-
description: "Kararı getirir (GET bpm/decisions/{id}): decision güncel model (taslak varsa taslak), activeDecision yayındaki model, versions[] (draft → active → retiring → retired). Değerlendirme için decision_preview.",
|
|
43
|
-
inputSchema: { project: projectParam, environment: environmentParam, id: guid },
|
|
44
|
-
annotations: readOnly
|
|
45
|
-
}, handle(config, ({ project, environment, id }) => platform.tenant('GET', project, `/bpm/decisions/${id}`, { environment })));
|
|
46
|
-
server.registerTool('decision_create', {
|
|
47
|
-
title: 'Karar oluştur',
|
|
48
|
-
description: "Yeni karar yazar (POST bpm/decisions; taslak sürüm). İlk kullanımdan önce platform_guide('decision') okuyun. Gateway yazmadan önce denetler: DMN-001 (unique tabloda aynı girdiyi eşleyen iki kural, block) ve DMN-002 (FEEL alt kümesinde olmayan işlev, warn — backend yine de yazımı 422 ile reddeder). Yayın decision_publish; süreçte kullanım 'decision' düğümü { decisionSlug, input, output }.",
|
|
49
|
-
inputSchema: { project: projectParam, environment: environmentParam, applicationId: guid.optional(), decision: decisionParam, policyOverride: policyOverrideParam },
|
|
50
|
-
annotations: writes
|
|
51
|
-
}, handle(config, async ({ project, environment, applicationId, decision, policyOverride }) => {
|
|
52
|
-
assertProcessNotProduction('decision_create', environment, config);
|
|
53
|
-
const findings = lintDecision(config, decision, policyOverride);
|
|
54
|
-
const saved = await platform.tenant('POST', project, '/bpm/decisions', { environment, body: { applicationId, decision } });
|
|
55
|
-
return withUnmappedMembers(attachFindings(dataOf(saved), findings), unmappedMembers('CreateDecisionCommand', { applicationId, decision }));
|
|
56
|
-
}));
|
|
57
|
-
server.registerTool('decision_update', {
|
|
58
|
-
title: 'Kararı güncelle',
|
|
59
|
-
description: "Kararın taslağını tam modelle yazar (PUT bpm/decisions/{id}; taslak yoksa açılır) ya da retireVersion ile aktif/emekliye ayrılan sürümü emekliye ayırır (POST …/versions/{n}/retire). İkisinden biri. Backend sürüm denetimi yapmaz: aynı kararı iki ajan yazıyorsa son yazan kazanır; hedefli değişiklik için decision_patch. Yayından sonra slug değişmez. DMN-001/002 denetimi decision_create ile aynı.",
|
|
60
|
-
inputSchema: {
|
|
61
|
-
project: projectParam,
|
|
62
|
-
environment: environmentParam,
|
|
63
|
-
id: guid,
|
|
64
|
-
decision: decisionParam.optional(),
|
|
65
|
-
retireVersion: z.number().int().min(1).optional().describe('emekliye ayrılacak sürüm numarası (decision yerine)'),
|
|
66
|
-
policyOverride: policyOverrideParam
|
|
67
|
-
},
|
|
68
|
-
annotations: updates
|
|
69
|
-
}, handle(config, async ({ project, environment, id, decision, retireVersion, policyOverride }) => {
|
|
70
|
-
assertProcessNotProduction('decision_update', environment, config);
|
|
71
|
-
if (Boolean(decision) === (retireVersion !== undefined))
|
|
72
|
-
throw new PlatformApiError("decision_update: 'decision' ya da 'retireVersion' — yalnız biri (istek gönderilmedi).", 400);
|
|
73
|
-
if (retireVersion !== undefined)
|
|
74
|
-
return dataOf(await platform.tenant('POST', project, `/bpm/decisions/${id}/versions/${retireVersion}/retire`, { environment }));
|
|
75
|
-
const findings = lintDecision(config, decision, policyOverride);
|
|
76
|
-
return withUnmappedMembers(attachFindings(dataOf(await platform.tenant('PUT', project, `/bpm/decisions/${id}`, { environment, body: { decision } })), findings), unmappedMembers('UpdateDecisionCommand', { decision }));
|
|
77
|
-
}));
|
|
78
|
-
server.registerTool('decision_patch', {
|
|
79
|
-
title: 'Karara patch uygula',
|
|
80
|
-
description: "Tam modeli bağlama almadan hedefli değişiklik: gateway güncel modeli okur (GET), seçicileri (/rules[id=x], /inputs[id=x]) çözer, yamayı yerelde uygular, DMN-001/002 denetiminden geçirir ve tam modeli taslağa yazar (PUT). Backend sürüm denetimi yok: okuma ile yazma arasında başka yazan olursa değişikliği ezilir. Yanıt { patchTargets, decision }.",
|
|
81
|
-
inputSchema: {
|
|
82
|
-
project: projectParam,
|
|
83
|
-
environment: environmentParam,
|
|
84
|
-
id: guid,
|
|
85
|
-
operations: patchOperationsParam.optional(),
|
|
86
|
-
ops: patchOperationsParam.optional().describe("'operations' ile aynı alan (eşanlamlı)"),
|
|
87
|
-
policyOverride: policyOverrideParam
|
|
88
|
-
},
|
|
89
|
-
annotations: updates
|
|
90
|
-
}, handle(config, async ({ project, environment, id, operations: givenOperations, ops, policyOverride }) => {
|
|
91
|
-
assertProcessNotProduction('decision_patch', environment, config);
|
|
92
|
-
const operations = microOps('decision_patch', ops, givenOperations);
|
|
93
|
-
const current = dataOf(await platform.tenant('GET', project, `/bpm/decisions/${id}`, { environment }));
|
|
94
|
-
const model = structuredClone((current.decision ?? {}));
|
|
95
|
-
const resolved = resolvePatchOperations(model, operations, 'decision_get');
|
|
96
|
-
let patched;
|
|
97
|
-
try {
|
|
98
|
-
patched = fastJsonPatch.applyPatch(model, resolved.operations, true, false).newDocument;
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
101
|
-
throw new PlatformApiError(`decision_patch: yama uygulanamadı — ${error instanceof Error ? error.message : String(error)} (istek gönderilmedi). Yolları decision_get çıktısına göre kurun.`, 400);
|
|
102
|
-
}
|
|
103
|
-
const findings = lintDecision(config, patched, policyOverride);
|
|
104
|
-
const saved = dataOf(await platform.tenant('PUT', project, `/bpm/decisions/${id}`, { environment, body: { decision: patched } }));
|
|
105
|
-
return withNormalization(attachFindings({ patchTargets: resolved.targets, decision: saved.decision ?? patched }, findings), resolved.notes);
|
|
106
|
-
}));
|
|
107
|
-
server.registerTool('decision_delete', {
|
|
108
|
-
title: 'Kararı sil',
|
|
109
|
-
description: "Kararı ve bütün sürümlerini siler (DELETE bpm/decisions/{id}). Bir süreç tanımı decisionSlug ile başvuruyorsa 422 ReferencedByProcess, başka karar requires ile başvuruyorsa 422 DecisionInvalid.",
|
|
110
|
-
inputSchema: { project: projectParam, environment: environmentParam, id: guid },
|
|
111
|
-
annotations: destructive
|
|
112
|
-
}, handle(config, async ({ project, environment, id }) => {
|
|
113
|
-
assertProcessNotProduction('decision_delete', environment, config);
|
|
114
|
-
return platform.tenant('DELETE', project, `/bpm/decisions/${id}`, { environment });
|
|
115
|
-
}));
|
|
116
|
-
server.registerTool('decision_clone', {
|
|
117
|
-
title: 'Kararı klonla',
|
|
118
|
-
description: 'Kararın güncel modelinden yeni slug ile taslak kopya oluşturur (GET + POST bpm/decisions). variable verilmemişse slug\'dan türetildiği için üst kararlar yeni adı görür; requires başvuruları kopyalanır.',
|
|
119
|
-
inputSchema: { project: projectParam, environment: environmentParam, id: guid, slug: z.string().min(1).max(100) },
|
|
120
|
-
annotations: writes
|
|
121
|
-
}, handle(config, async ({ project, environment, id, slug }) => {
|
|
122
|
-
assertProcessNotProduction('decision_clone', environment, config);
|
|
123
|
-
const current = dataOf(await platform.tenant('GET', project, `/bpm/decisions/${id}`, { environment }));
|
|
124
|
-
const decision = { ...structuredClone((current.decision ?? {})), slug };
|
|
125
|
-
return dataOf(await platform.tenant('POST', project, '/bpm/decisions', { environment, body: { applicationId: current.applicationId ?? undefined, decision } }));
|
|
126
|
-
}));
|
|
127
|
-
server.registerTool('decision_preview', {
|
|
128
|
-
title: 'Kararı değerlendir (kuru)',
|
|
129
|
-
description: "Kararı verilen girdilerle YAN ETKİSİZ değerlendirir (POST bpm/decisions/{id}/evaluate; transaction açmaz, defter yazmaz — tablo tasarımını denemenin yolu, platform_guide('decision') §Deneme): version verilmezse taslak (yoksa aktif). DRD'deki alt kararlar (requires) önce değerlendirilir. Yanıt { value, outputs, matchedRules, decisions[] (her karar için inputs, value, matchedRules) }. unique'te birden çok kural eşleşirse 422 DecisionHitPolicyViolated (eşleşen kural kimlikleriyle); hiçbiri eşleşmezse defaultOutputEntry ya da null.",
|
|
130
|
-
inputSchema: {
|
|
131
|
-
project: projectParam,
|
|
132
|
-
environment: environmentParam,
|
|
133
|
-
id: guid,
|
|
134
|
-
inputs: z.record(z.unknown()).describe("girdi adları → değerler, ör. { tutar: 180000, kategori: 'makine' }; tarih '2026-09-17', süre 'P3D'"),
|
|
135
|
-
version: z.number().int().min(1).optional()
|
|
136
|
-
},
|
|
137
|
-
annotations: readOnly
|
|
138
|
-
}, handle(config, ({ project, environment, id, inputs, version }) => platform.tenant('POST', project, `/bpm/decisions/${id}/evaluate`, { environment, query: { version }, body: { inputs } })));
|
|
139
|
-
server.registerTool('decision_publish', {
|
|
140
|
-
title: 'Kararı yayınla',
|
|
141
|
-
description: "Taslağı aktif sürüm yapar (POST bpm/decisions/{id}/publish); önceki aktif sürüm retiring olur. requires içindeki her kararın aktif sürümü olmalı (422 DecisionUnknown) ve döngü olmamalı (422 DecisionInvalid). Gateway yayından önce taslağı DMN-001/002 ile denetler. production hedefi durur (BPM-001).",
|
|
142
|
-
inputSchema: { project: projectParam, environment: environmentParam, id: guid, policyOverride: policyOverrideParam },
|
|
143
|
-
annotations: writes
|
|
144
|
-
}, handle(config, async ({ project, environment, id, policyOverride }) => {
|
|
145
|
-
assertProcessNotProduction('decision_publish', environment, config);
|
|
146
|
-
const current = dataOf(await platform.tenant('GET', project, `/bpm/decisions/${id}`, { environment }));
|
|
147
|
-
const findings = lintDecision(config, (current.decision ?? {}), policyOverride);
|
|
148
|
-
return attachFindings(dataOf(await platform.tenant('POST', project, `/bpm/decisions/${id}/publish`, { environment })), findings);
|
|
149
|
-
}));
|
|
150
|
-
server.registerTool('decision_dmn_get', {
|
|
151
|
-
title: 'Kararı DMN 1.3 XML olarak dışa aktar',
|
|
152
|
-
description: "Kararı ve requires ile bağlı alt kararlarını DMN 1.3 XML'e çevirir (GET bpm/decisions/{id}/dmn; zeyrek: uzantısı kaynak ve kategori bilgisini taşır). version verilmezse taslak (yoksa aktif). Yanıt { decisionId, versionNumber, state, sizeBytes, xml }; 256 KB üstü için outPath verin.",
|
|
153
|
-
inputSchema: {
|
|
154
|
-
project: projectParam,
|
|
155
|
-
environment: environmentParam,
|
|
156
|
-
id: guid,
|
|
157
|
-
version: z.number().int().min(1).optional(),
|
|
158
|
-
outPath: z.string().min(1).optional().describe('verilirse XML bu yerel yola yazılır ve yanıt yalnız özet döner')
|
|
159
|
-
},
|
|
160
|
-
annotations: readOnly
|
|
161
|
-
}, handle(config, async ({ project, environment, id, version, outPath }) => {
|
|
162
|
-
const response = await platform.tenantWithHeaders('GET', project, `/bpm/decisions/${id}/dmn`, { environment, query: { version }, expectBinary: true });
|
|
163
|
-
const payload = response.body;
|
|
164
|
-
const xml = payload.bytes.toString('utf8').replace(/^\uFEFF/, '');
|
|
165
|
-
const summary = {
|
|
166
|
-
decisionId: id,
|
|
167
|
-
versionNumber: Number(response.headers['x-decision-version']) || null,
|
|
168
|
-
state: response.headers['x-decision-version-state'] ?? null,
|
|
169
|
-
sizeBytes: payload.bytes.byteLength
|
|
170
|
-
};
|
|
171
|
-
if (outPath)
|
|
172
|
-
return { ...summary, path: await writeLocalFile('decision_dmn_get', outPath, xml) };
|
|
173
|
-
const inline = { ...summary, xml };
|
|
174
|
-
assertInline('decision_dmn_get', config, inline);
|
|
175
|
-
return inline;
|
|
176
|
-
}));
|
|
177
|
-
server.registerTool('decision_dmn_update', {
|
|
178
|
-
title: 'DMN 1.3 XML içe aktar',
|
|
179
|
-
description: "DMN 1.3 XML'deki kararları içe aktarır (POST bpm/decisions/import-dmn): slug'ı (decision id) mevcut karar taslağına yazılır, yoksa yeni karar oluşur; DRD bilgi gereksinimleri requires olur. xml (≤ 256 KB) ya da filePath (≤ 5 MB) — biri. Camunda/Trisotech tablolarında desteklenmeyen FEEL işlevi değerlendirmede 422 ExpressionInvalid döner; içe aktardıktan sonra decision_preview ile deneyin. DTD/dış varlık içeren XML 400.",
|
|
180
|
-
inputSchema: {
|
|
181
|
-
project: projectParam,
|
|
182
|
-
environment: environmentParam,
|
|
183
|
-
applicationId: guid.optional(),
|
|
184
|
-
xml: z.string().min(1).max(maxInlineXmlBytes).optional(),
|
|
185
|
-
filePath: z.string().min(1).optional().describe('yerel .dmn dosyası')
|
|
186
|
-
},
|
|
187
|
-
annotations: updates
|
|
188
|
-
}, handle(config, async ({ project, environment, applicationId, xml, filePath }) => {
|
|
189
|
-
assertProcessNotProduction('decision_dmn_update', environment, config);
|
|
190
|
-
if (Boolean(xml) === Boolean(filePath))
|
|
191
|
-
throw new PlatformApiError("decision_dmn_update: 'xml' ya da 'filePath' — yalnız biri (istek gönderilmedi).", 400);
|
|
192
|
-
let content = xml ?? '';
|
|
193
|
-
if (filePath) {
|
|
194
|
-
try {
|
|
195
|
-
content = await readFile(resolve(filePath), 'utf8');
|
|
196
|
-
}
|
|
197
|
-
catch (error) {
|
|
198
|
-
throw new PlatformApiError(`decision_dmn_update: dosya okunamadı — ${resolve(filePath)} (${error instanceof Error ? error.message : String(error)}). Yol gateway sürecinin çalıştığı makineye göre çözülür (istek gönderilmedi).`, 400);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
content = content.replace(/^/, '');
|
|
202
|
-
if (Buffer.byteLength(content, 'utf8') > maxDmnBytes)
|
|
203
|
-
throw new PlatformApiError(`decision_dmn_update: XML en çok ${maxDmnBytes} B (istek gönderilmedi).`, 413);
|
|
204
|
-
return platform.tenant('POST', project, '/bpm/decisions/import-dmn', { environment, body: { applicationId, xml: content } });
|
|
205
|
-
}));
|
|
206
|
-
}
|
package/dist/tools/mobile.js
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { environmentParam, guid, projectParam, writes } from './common.js';
|
|
3
|
-
import { fetchHost, pageUpdateBody, unwrap } from './screens.js';
|
|
4
|
-
import { fetchCatalogSlugs } from './components.js';
|
|
5
|
-
import { mobileTabsWarnings } from './applications.js';
|
|
6
|
-
import { PlatformApiError } from '../platform/errors.js';
|
|
7
|
-
import { handle } from '../platform/responses.js';
|
|
8
|
-
import { PAGE_CONTAINER_ELEMENT_ID, ensurePageContainer } from '../knowledge/normalize.js';
|
|
9
|
-
import { mobileProfile, shellLessPageSkeleton } from '../knowledge/platform/mobile.js';
|
|
10
|
-
import { MAX_MOBILE_TABS } from '../knowledge/platform/mobileTabs.js';
|
|
11
|
-
import { forgetApplication } from '../knowledge/platform/resolve.js';
|
|
12
|
-
import { readKnowledgeFile } from '../resources/knowledge.js';
|
|
13
|
-
/** Ana sayfa: açıkça verilen, yoksa ilk sekme, yoksa ilk sayfa. */
|
|
14
|
-
function homepageSlug(input) {
|
|
15
|
-
return input.homepage ?? input.tabs?.[0]?.pageSlug ?? input.pages[0].pageSlug;
|
|
16
|
-
}
|
|
17
|
-
export function mobileAppInputErrors(input) {
|
|
18
|
-
const errors = [];
|
|
19
|
-
const slugs = input.pages.map(page => page.pageSlug);
|
|
20
|
-
const repeated = slugs.filter((slug, index) => slugs.indexOf(slug) !== index);
|
|
21
|
-
if (input.pages.length === 0)
|
|
22
|
-
errors.push('pages en az bir sayfa ister');
|
|
23
|
-
if (repeated.length > 0)
|
|
24
|
-
errors.push(`pages içinde tekrar eden slug var: ${[...new Set(repeated)].join(', ')}`);
|
|
25
|
-
if (input.tabs !== undefined) {
|
|
26
|
-
const tabSlugs = input.tabs.map(tab => tab.pageSlug);
|
|
27
|
-
if (input.tabs.length === 0)
|
|
28
|
-
errors.push("tabs verildiyse en az bir öğe taşır; sekme istemiyorsan alanı hiç gönderme (yığın)");
|
|
29
|
-
if (input.tabs.length > MAX_MOBILE_TABS)
|
|
30
|
-
errors.push(`tabs en fazla ${MAX_MOBILE_TABS} öğe taşır (${input.tabs.length} verildi) — fazlası yığına açılan sayfa olarak kalmalı`);
|
|
31
|
-
for (const slug of tabSlugs.filter(slug => !slugs.includes(slug)))
|
|
32
|
-
errors.push(`tabs '${slug}' pages içinde yok — sekme yalnız kurulan bir sayfayı gösterebilir`);
|
|
33
|
-
if (tabSlugs.some((slug, index) => tabSlugs.indexOf(slug) !== index))
|
|
34
|
-
errors.push('tabs içinde tekrar eden sayfa var');
|
|
35
|
-
}
|
|
36
|
-
if (input.homepage !== undefined && !slugs.includes(input.homepage))
|
|
37
|
-
errors.push(`homepage '${input.homepage}' pages içinde yok`);
|
|
38
|
-
return errors;
|
|
39
|
-
}
|
|
40
|
-
export function buildMobileAppPlan(input) {
|
|
41
|
-
const home = homepageSlug(input);
|
|
42
|
-
const others = input.pages.filter(page => page.pageSlug !== home);
|
|
43
|
-
return [
|
|
44
|
-
{ step: 'application_create', tool: 'application_create', summary: "type:'mobile' uygulama; backend ana sayfayı kendisi açar" },
|
|
45
|
-
{ step: 'layout_create', tool: 'layout_create', summary: `kabuk: app-bar + slot${input.drawer ? ' + drawer widget (app-bar.menuTarget)' : ''}` },
|
|
46
|
-
...others.map((page, index) => ({ step: `page_create#${index + 1}`, tool: 'page_create', summary: `'${page.pageSlug}' (${page.pageName}), layoutId ile` })),
|
|
47
|
-
{ step: 'page_update#homepage', tool: 'page_update', summary: `backend'in ana sayfası → '${home}' (ad, slug, layoutId)` },
|
|
48
|
-
...(input.tabs ? [{ step: 'application_update', tool: 'application_update', summary: `properties.mobile.tabs: ${input.tabs.map(tab => tab.pageSlug).join(' · ')}` }] : [])
|
|
49
|
-
];
|
|
50
|
-
}
|
|
51
|
-
/** Kabuk ağacı örnek dosyasından okunur — örnek ile aracın kurduğu layout tek kaynaktır. */
|
|
52
|
-
function shellViews(input) {
|
|
53
|
-
const example = JSON.parse(readKnowledgeFile('examples', input.drawer ? 'mobile-app-shell-drawer.json' : 'mobile-app-shell-stack.json'));
|
|
54
|
-
const views = structuredClone(example.layoutCreate.views);
|
|
55
|
-
// app-bar kabukta üst güvenli alanın içindedir (mizanpaj S1); ağaçta derinlikten bağımsız aranır.
|
|
56
|
-
const findAppBar = (nodes) => nodes.find(node => node.type === 'app-bar') ?? nodes.map(node => findAppBar(node.children ?? [])).find(Boolean);
|
|
57
|
-
const appBar = findAppBar(views);
|
|
58
|
-
if (appBar && input.title)
|
|
59
|
-
appBar.props.title = { type: 'static', ref: null, data: input.title };
|
|
60
|
-
return views;
|
|
61
|
-
}
|
|
62
|
-
const SHELL_TYPES = ['app-bar', 'slot'];
|
|
63
|
-
/** Boş sayfanın şeması: kabuklu sayfada kök şablonu, kabuksuzda iskeletiyle (üst pay + kenar boşluğu). */
|
|
64
|
-
function mobilePageSchema(shell) {
|
|
65
|
-
const schema = ensurePageContainer([], mobileProfile.layout.rootContainer).schema;
|
|
66
|
-
if (!shell && schema[0])
|
|
67
|
-
shellLessPageSkeleton(schema[0]);
|
|
68
|
-
return schema;
|
|
69
|
-
}
|
|
70
|
-
export function registerMobileTools(server, platform) {
|
|
71
|
-
const config = platform.config;
|
|
72
|
-
server.registerTool('mobile_app_create', {
|
|
73
|
-
title: 'Mobil uygulamayı kabuğuyla kur',
|
|
74
|
-
description: "Mobil uygulamayı (type:'mobile'), kabuk layout'unu (app-bar + slot; drawer:true ise çekmece widget'ı), sayfalarını ve isteğe bağlı sekme ayarını (properties.mobile.tabs) TEK çağrıda kurar. Sıra: application_create → layout_create → page_create (sayfalar layoutId ile doğar) → backend'in açtığı ana sayfa seçilen ana sayfaya dönüştürülür (yetim sayfa kalmaz) → application_update (yalnız tabs verildiyse). tabs yoksa gezinme yığındır. dryRun:true planı döner, hiçbir şey yazmaz. Platformda işlem yoktur: hata olursa yanıt completed (kurulanlar), failed (düşen adım) ve remaining (kalanlar) taşır — kalanları tekil araçlarla tamamlayın. Kabuk bileşenleri (app-bar, slot) mobil katalogda yoksa layout atlanır ve uyarı döner. Rehber: platform_guide('mobile').",
|
|
75
|
-
inputSchema: {
|
|
76
|
-
project: projectParam,
|
|
77
|
-
environment: environmentParam,
|
|
78
|
-
projectId: guid,
|
|
79
|
-
slug: z.string().min(1),
|
|
80
|
-
name: z.string().min(1),
|
|
81
|
-
color: z.string().optional(),
|
|
82
|
-
pages: z.array(z.object({ pageSlug: z.string().min(1), pageName: z.string().min(1) })).min(1),
|
|
83
|
-
tabs: z.array(z.object({ pageSlug: z.string().min(1), label: z.string().optional(), icon: z.string().optional() })).optional()
|
|
84
|
-
.describe(`1-${MAX_MOBILE_TABS} sekme; her pageSlug pages içinden. Verilmezse sekme çubuğu yok (yığın). label 't:<anahtar>' ile yazılırsa çeviri sözlüğünden çözülür (platform_guide('mobile') §Çok dil).`),
|
|
85
|
-
drawer: z.boolean().optional().describe("true: layout'a drawer widget'ı + app-bar.menuTarget (çekmece)"),
|
|
86
|
-
title: z.string().optional().describe('app-bar başlığı (bütün sayfalar için sabit metin). Boşsa çubuk başlıksız çizilir — sayfa adına düşen bir yedek YOKTUR; sayfaya göre değişen başlık için title\'ı bir değişkene bağlayın ya da başlığı sayfanın içine text olarak koyun'),
|
|
87
|
-
homepage: z.string().optional().describe('Ana sayfanın pageSlug\'ı; varsayılan ilk sekme, sekme yoksa ilk sayfa'),
|
|
88
|
-
dryRun: z.boolean().optional()
|
|
89
|
-
},
|
|
90
|
-
annotations: writes
|
|
91
|
-
}, handle(config, async ({ project, environment, projectId, slug, name, color, pages, tabs, drawer, title, homepage, dryRun }) => {
|
|
92
|
-
const input = { pages, ...(tabs ? { tabs } : {}), ...(drawer ? { drawer } : {}), ...(homepage ? { homepage } : {}), ...(title ? { title } : {}) };
|
|
93
|
-
const errors = mobileAppInputErrors(input);
|
|
94
|
-
if (errors.length > 0)
|
|
95
|
-
throw new PlatformApiError(`mobile_app_create: ${errors.join(' · ')}. Hiçbir şey yazılmadı.`, 400);
|
|
96
|
-
const plan = buildMobileAppPlan(input);
|
|
97
|
-
if (dryRun)
|
|
98
|
-
return { dryRun: true, plan };
|
|
99
|
-
const completed = [];
|
|
100
|
-
const skipped = new Set();
|
|
101
|
-
const warnings = [];
|
|
102
|
-
const home = homepageSlug(input);
|
|
103
|
-
const pageIds = new Map();
|
|
104
|
-
let applicationId;
|
|
105
|
-
let homepageId;
|
|
106
|
-
let layoutId;
|
|
107
|
-
let current = 'application_create';
|
|
108
|
-
try {
|
|
109
|
-
const created = unwrap(await platform.org('POST', `/applications/${projectId}`, {
|
|
110
|
-
environment,
|
|
111
|
-
body: { slug, name, type: 'mobile', ...(color ? { color } : {}) }
|
|
112
|
-
}));
|
|
113
|
-
applicationId = String(created.id ?? '');
|
|
114
|
-
homepageId = typeof created.homepageId === 'string'
|
|
115
|
-
? created.homepageId
|
|
116
|
-
: String(created.homepage?.id ?? '');
|
|
117
|
-
forgetApplication(platform);
|
|
118
|
-
if (!applicationId || !homepageId)
|
|
119
|
-
throw new PlatformApiError('application_create yanıtı uygulama ya da ana sayfa kimliği taşımıyor — application_get ile kontrol edin.');
|
|
120
|
-
completed.push({ step: 'application_create', id: applicationId });
|
|
121
|
-
current = 'layout_create';
|
|
122
|
-
const catalog = await fetchCatalogSlugs(platform, project, environment, applicationId);
|
|
123
|
-
const missing = SHELL_TYPES.filter(type => !catalog.has(type));
|
|
124
|
-
if (missing.length > 0) {
|
|
125
|
-
skipped.add('layout_create');
|
|
126
|
-
warnings.push(`MOB-003 (uyarı) — kabuk bileşenleri mobil katalogda yok (${missing.join(', ')}): layout KURULMADI, sayfalar layout'suz açıldı. Katalog yazıldıktan sonra kabuğu ngapps://examples/mobile-app-shell-${input.drawer ? 'drawer' : input.tabs ? 'tab' : 'stack'} ile layout_create + page_update(layoutId) olarak kurun.`);
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
const layout = unwrap(await platform.tenant('POST', project, `/layouts/${applicationId}`, {
|
|
130
|
-
environment,
|
|
131
|
-
body: { name: `${name} kabuğu`, views: shellViews(input), events: [], parameters: null }
|
|
132
|
-
}));
|
|
133
|
-
layoutId = String(layout.id ?? '');
|
|
134
|
-
completed.push({ step: 'layout_create', id: layoutId });
|
|
135
|
-
}
|
|
136
|
-
const others = pages.filter(page => page.pageSlug !== home);
|
|
137
|
-
for (const [index, page] of others.entries()) {
|
|
138
|
-
current = `page_create#${index + 1}`;
|
|
139
|
-
const saved = unwrap(await platform.tenant('POST', project, `/pages/${applicationId}`, {
|
|
140
|
-
environment,
|
|
141
|
-
body: {
|
|
142
|
-
name: page.pageName,
|
|
143
|
-
slug: page.pageSlug,
|
|
144
|
-
browserTitle: '',
|
|
145
|
-
browserTitleKey: '',
|
|
146
|
-
layoutId: layoutId ?? null,
|
|
147
|
-
roleIds: [],
|
|
148
|
-
middlewareIds: [],
|
|
149
|
-
events: [],
|
|
150
|
-
schema: mobilePageSchema(layoutId !== undefined)
|
|
151
|
-
}
|
|
152
|
-
}));
|
|
153
|
-
pageIds.set(page.pageSlug, String(saved.id ?? ''));
|
|
154
|
-
completed.push({ step: current, id: String(saved.id ?? '') });
|
|
155
|
-
}
|
|
156
|
-
current = 'page_update#homepage';
|
|
157
|
-
const homePage = pages.find(page => page.pageSlug === home);
|
|
158
|
-
const existing = await fetchHost(platform, 'page', project, environment, applicationId, homepageId);
|
|
159
|
-
// Backend'in açtığı ana sayfanın kökü sözleşme dışıdır (`size: grow`, S-16). Sayfa henüz boşsa kök
|
|
160
|
-
// öteki sayfalarla aynı şablonla yeniden yazılır; içerik varsa dokunulmaz.
|
|
161
|
-
const homeSchema = existing.schema;
|
|
162
|
-
const blankHome = Array.isArray(homeSchema) && homeSchema.length === 1 && homeSchema[0]?.elementId === PAGE_CONTAINER_ELEMENT_ID && (homeSchema[0].children ?? []).length === 0;
|
|
163
|
-
await platform.tenant('PUT', project, `/pages/${applicationId}/${homepageId}`, {
|
|
164
|
-
environment,
|
|
165
|
-
body: pageUpdateBody(existing, {
|
|
166
|
-
name: homePage.pageName,
|
|
167
|
-
slug: homePage.pageSlug,
|
|
168
|
-
layoutId: layoutId ?? null,
|
|
169
|
-
...(blankHome ? { schema: mobilePageSchema(layoutId !== undefined) } : {})
|
|
170
|
-
})
|
|
171
|
-
});
|
|
172
|
-
pageIds.set(home, homepageId);
|
|
173
|
-
completed.push({ step: current, id: homepageId });
|
|
174
|
-
if (tabs) {
|
|
175
|
-
current = 'application_update';
|
|
176
|
-
const properties = {
|
|
177
|
-
mobile: {
|
|
178
|
-
tabs: {
|
|
179
|
-
enabled: true,
|
|
180
|
-
style: 'default',
|
|
181
|
-
showLabels: true,
|
|
182
|
-
items: tabs.map(tab => ({ page: pageIds.get(tab.pageSlug), ...(tab.label ? { label: tab.label } : {}), ...(tab.icon ? { icon: tab.icon } : {}) }))
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
warnings.push(...await mobileTabsWarnings(platform, applicationId, platform.resolveProject(project), homepageId, properties));
|
|
187
|
-
await platform.org('PUT', `/applications/${applicationId}`, {
|
|
188
|
-
environment,
|
|
189
|
-
body: { slug, name, homepageId, ...(color ? { color } : {}), properties }
|
|
190
|
-
});
|
|
191
|
-
forgetApplication(platform, applicationId);
|
|
192
|
-
completed.push({ step: current });
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
catch (error) {
|
|
196
|
-
if (completed.length === 0)
|
|
197
|
-
throw error;
|
|
198
|
-
const done = new Set(completed.map(entry => entry.step));
|
|
199
|
-
return {
|
|
200
|
-
applicationId,
|
|
201
|
-
...(layoutId ? { layoutId } : {}),
|
|
202
|
-
completed,
|
|
203
|
-
failed: { step: current, error: error instanceof Error ? error.message : String(error) },
|
|
204
|
-
remaining: plan.map(step => step.step).filter(step => !done.has(step) && !skipped.has(step) && step !== current),
|
|
205
|
-
...(warnings.length > 0 ? { warnings } : {}),
|
|
206
|
-
note: 'Kurulum yarıda kaldı: completed kurulanları, remaining eksik adımları söyler. Kalanları tekil araçlarla tamamlayın (page_create, page_update, application_update) — mobile_app_create aynı slug ile tekrar çağrılırsa uygulamayı ikinci kez açmaya çalışır.'
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
return {
|
|
210
|
-
applicationId,
|
|
211
|
-
homepageId,
|
|
212
|
-
...(layoutId ? { layoutId } : {}),
|
|
213
|
-
applicationType: 'mobile',
|
|
214
|
-
pages: pages.map(page => ({ slug: page.pageSlug, name: page.pageName, id: pageIds.get(page.pageSlug), ...(page.pageSlug === home ? { homepage: true } : {}) })),
|
|
215
|
-
...(tabs ? { tabs: tabs.map(tab => tab.pageSlug) } : {}),
|
|
216
|
-
completed,
|
|
217
|
-
...(warnings.length > 0 ? { warnings } : {}),
|
|
218
|
-
next: "Ekranları page_schema_patch ile doldurun; doğrulama page_screenshot (mobilde varsayılan device: 'phone'). platform_guide('mobile')."
|
|
219
|
-
};
|
|
220
|
-
}));
|
|
221
|
-
}
|