@appaflytech/zeyrek-ai-mcp 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +8 -3
- package/.env.production.example +2 -0
- package/README.md +229 -193
- package/dist/config.js +20 -2
- package/dist/knowledge/backendConstraints.js +897 -0
- package/dist/knowledge/componentCatalog.js +196 -42
- package/dist/knowledge/coverage.js +43 -0
- package/dist/knowledge/flowGuards.js +30 -0
- package/dist/knowledge/guideSections.js +49 -0
- package/dist/knowledge/hydrate.js +97 -0
- package/dist/knowledge/languageCodes.js +36 -0
- package/dist/knowledge/languages.js +105 -0
- package/dist/knowledge/layoutSummary.js +10 -0
- package/dist/knowledge/localization.js +51 -0
- package/dist/knowledge/normalize.js +449 -16
- package/dist/knowledge/outlines.js +136 -12
- package/dist/knowledge/propTypes.js +80 -0
- package/dist/knowledge/rules.js +618 -43
- package/dist/knowledge/schemaGuard.js +199 -0
- package/dist/knowledge/styleResolve.js +63 -4
- package/dist/observability/trace.js +27 -3
- package/dist/platform/errors.js +46 -4
- package/dist/platform/http.js +33 -4
- package/dist/platform/patch.js +27 -0
- package/dist/platform/refs.js +104 -0
- package/dist/platform/responses.js +9 -2
- package/dist/platform/screenshot.js +527 -16
- package/dist/platform/secrets.js +40 -0
- package/dist/platform/tokenVault.js +89 -0
- package/dist/platform/writeDiff.js +281 -0
- package/dist/resources/examples/layout-app-shell.json +1 -1
- package/dist/resources/examples/microservice-table-list.json +2 -4
- package/dist/resources/examples/page-dynamic-form.json +2 -2
- package/dist/resources/examples/page-flex-sections.json +99 -0
- package/dist/resources/examples/page-sign-in.json +3 -2
- package/dist/resources/guides/component.md +69 -8
- package/dist/resources/guides/entity.md +404 -16
- package/dist/resources/guides/expressions.md +44 -2
- package/dist/resources/guides/external-component.md +9 -0
- package/dist/resources/guides/getting-started.md +77 -7
- package/dist/resources/guides/layout.md +53 -10
- package/dist/resources/guides/microservice.md +226 -13
- package/dist/resources/guides/middleware.md +89 -1
- package/dist/resources/guides/page.md +383 -46
- package/dist/resources/guides/translation.md +126 -8
- package/dist/resources/guides/view.md +16 -1
- package/dist/resources/guides/workflow.md +198 -27
- package/dist/resources/knowledge.js +5 -0
- package/dist/resources/rules.js +27 -0
- package/dist/resources/schema-fingerprint.json +8 -0
- package/dist/resources/schemas/CreateBulkRowCommand.json +33 -0
- package/dist/resources/schemas/CreateDatasourceCommand.json +15 -6
- package/dist/resources/schemas/CreateDiscoveredEntitiesCommand.json +19 -8
- package/dist/resources/schemas/CreateEntityCommand.json +52 -12
- package/dist/resources/schemas/CreateMicroserviceCommand.json +26 -2
- package/dist/resources/schemas/CreateQueryCommand.json +56 -3
- package/dist/resources/schemas/CreateRowCommand.json +38 -0
- package/dist/resources/schemas/CreateViewCommand.json +13 -10
- package/dist/resources/schemas/CreateWorkflowCommand.json +95 -14
- package/dist/resources/schemas/GetRowsQuery.json +3 -0
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +16 -0
- package/dist/resources/schemas/PreviewQueryCommand.json +5 -2
- package/dist/resources/schemas/PreviewWorkflowCommand.json +34 -9
- package/dist/resources/schemas/StepDto.json +23 -3
- package/dist/resources/schemas/UpdateBulkRowCommand.json +33 -0
- package/dist/resources/schemas/UpdateDatasourceCommand.json +15 -6
- package/dist/resources/schemas/UpdateEntityCommand.json +49 -10
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +28 -3
- package/dist/resources/schemas/UpdateQueryCommand.json +13 -3
- package/dist/resources/schemas/UpdateRowCommand.json +40 -0
- package/dist/resources/schemas/UpdateViewCommand.json +15 -10
- package/dist/resources/schemas/UpdateWorkflowCommand.json +95 -14
- package/dist/server.js +4 -0
- package/dist/tools/access.js +3 -3
- package/dist/tools/applications.js +1 -1
- package/dist/tools/automations.js +63 -30
- package/dist/tools/common.js +39 -0
- package/dist/tools/components.js +16 -7
- package/dist/tools/datasources.js +83 -21
- package/dist/tools/deployments.js +34 -2
- package/dist/tools/dtos.js +25 -12
- package/dist/tools/entities.js +113 -28
- package/dist/tools/externalComponents.js +9 -3
- package/dist/tools/files.js +20 -6
- package/dist/tools/flows.js +110 -11
- package/dist/tools/folders.js +7 -2
- package/dist/tools/globalFunctions.js +63 -0
- package/dist/tools/layouts.js +103 -29
- package/dist/tools/microservices.js +229 -38
- package/dist/tools/organizations.js +5 -6
- package/dist/tools/pages.js +365 -100
- package/dist/tools/platformInfo.js +152 -11
- package/dist/tools/projects.js +183 -33
- package/dist/tools/queries.js +32 -10
- package/dist/tools/rows.js +159 -45
- package/dist/tools/screenWrite.js +59 -0
- package/dist/tools/screens.js +28 -0
- package/dist/tools/translations.js +24 -8
- package/dist/tools/views.js +20 -10
- package/dist/tools/workflows.js +33 -16
- package/package.json +6 -3
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { PlatformApiError } from './errors.js';
|
|
2
|
+
const guidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3
|
+
export function isGuid(value) {
|
|
4
|
+
return guidPattern.test(value);
|
|
5
|
+
}
|
|
6
|
+
export class RefResolveError extends PlatformApiError {
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Slug → id çözümü çağrı başına yapılır ve çağrılar arasında TAŞINMAZ: gateway stateless, N
|
|
10
|
+
* replika ile paylaşılan bir önbellek tutarsız olur. Belirsiz slug (aynı ad iki datasource'ta)
|
|
11
|
+
* sessizce "ilkini al" ile geçilmez — bu planın var oluş nedeni sessiz yanlışı azaltmaktı;
|
|
12
|
+
* adaylar listelenip `datasource/entity` biçimi istenir.
|
|
13
|
+
*/
|
|
14
|
+
export class RefResolver {
|
|
15
|
+
platform;
|
|
16
|
+
project;
|
|
17
|
+
environment;
|
|
18
|
+
resolved = [];
|
|
19
|
+
tree;
|
|
20
|
+
fieldsByEntity = new Map();
|
|
21
|
+
constructor(platform, project, environment) {
|
|
22
|
+
this.platform = platform;
|
|
23
|
+
this.project = project;
|
|
24
|
+
this.environment = environment;
|
|
25
|
+
}
|
|
26
|
+
async applicationId(ref) {
|
|
27
|
+
if (isGuid(ref))
|
|
28
|
+
return ref;
|
|
29
|
+
const projectPayload = await this.platform.org('GET', `/p/${this.platform.resolveProject(this.project)}`);
|
|
30
|
+
const applicationsPayload = await this.platform.org('GET', '/applications', { query: { projectId: String(projectPayload.data?.id ?? ''), pageLength: 100 } });
|
|
31
|
+
const applications = applicationsPayload.data ?? [];
|
|
32
|
+
const found = applications.find(application => application.slug === ref);
|
|
33
|
+
if (!found) {
|
|
34
|
+
throw new RefResolveError(`'${ref}' diye bir application yok. Mevcut slug'lar: ${applications.map(application => application.slug).join(', ') || '(yok)'}`);
|
|
35
|
+
}
|
|
36
|
+
this.resolved.push(`applicationId '${ref}' → ${found.id}`);
|
|
37
|
+
return found.id;
|
|
38
|
+
}
|
|
39
|
+
async entity(ref) {
|
|
40
|
+
const tree = await this.loadTree();
|
|
41
|
+
const flat = tree
|
|
42
|
+
.filter((datasource) => Boolean(datasource) && typeof datasource === 'object')
|
|
43
|
+
.flatMap(datasource => (Array.isArray(datasource.entities) ? datasource.entities : [])
|
|
44
|
+
.filter((entity) => Boolean(entity) && typeof entity === 'object' && typeof entity.id === 'string')
|
|
45
|
+
.map(entity => ({ datasource, entity })));
|
|
46
|
+
if (isGuid(ref)) {
|
|
47
|
+
const byId = flat.find(({ entity }) => entity.id.toLowerCase() === ref.toLowerCase());
|
|
48
|
+
if (!byId)
|
|
49
|
+
throw new RefResolveError(`'${ref}' id'li entity ağaçta yok.`);
|
|
50
|
+
return { entityId: byId.entity.id, datasourceId: byId.datasource.id, slug: byId.entity.slug };
|
|
51
|
+
}
|
|
52
|
+
const separator = ref.indexOf('/');
|
|
53
|
+
const [datasourcePart, entityPart] = separator === -1 ? [undefined, ref] : [ref.slice(0, separator), ref.slice(separator + 1)];
|
|
54
|
+
const matches = flat.filter(({ datasource, entity }) => entity.slug === entityPart && (datasourcePart === undefined || datasource.slug === datasourcePart || datasource.name === datasourcePart));
|
|
55
|
+
if (matches.length === 0) {
|
|
56
|
+
throw new RefResolveError(`'${ref}' diye bir entity yok. Mevcut slug'lar: ${flat.map(({ entity }) => entity.slug).join(', ') || '(yok)'}`);
|
|
57
|
+
}
|
|
58
|
+
if (matches.length > 1) {
|
|
59
|
+
throw new RefResolveError(`'${ref}' birden çok datasource'ta var: ${matches.map(({ datasource, entity }) => `${datasource.slug}/${entity.slug}`).join(', ')}. 'datasource/entity' biçimiyle verin.`);
|
|
60
|
+
}
|
|
61
|
+
const [{ datasource, entity }] = matches;
|
|
62
|
+
this.resolved.push(`entityId '${ref}' → ${entity.id}`);
|
|
63
|
+
return { entityId: entity.id, datasourceId: datasource.id, slug: entity.slug };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Entity'nin ham kaydı (alan listesi DIŞINDAKİ kök alanlar için: `localizationEntityId`,
|
|
67
|
+
* `localizationParentId`, `type`). `entityFields` ile aynı ucu çağırır ve aynı önbelleği
|
|
68
|
+
* kullanır — iki tur atmaz.
|
|
69
|
+
*/
|
|
70
|
+
async entityRecord(ref) {
|
|
71
|
+
const cached = this.recordByEntity.get(ref.entityId);
|
|
72
|
+
if (cached)
|
|
73
|
+
return cached;
|
|
74
|
+
const payload = await this.platform.tenant('GET', this.project, `/entities/${ref.datasourceId}/${ref.entityId}`, { environment: this.environment });
|
|
75
|
+
const record = payload.data ?? {};
|
|
76
|
+
this.recordByEntity.set(ref.entityId, record);
|
|
77
|
+
return record;
|
|
78
|
+
}
|
|
79
|
+
async entityFields(ref) {
|
|
80
|
+
const cached = this.fieldsByEntity.get(ref.entityId);
|
|
81
|
+
if (cached)
|
|
82
|
+
return cached;
|
|
83
|
+
const payload = await this.platform.tenant('GET', this.project, `/entities/${ref.datasourceId}/${ref.entityId}`, { environment: this.environment });
|
|
84
|
+
const fields = (payload.data?.fields ?? [])
|
|
85
|
+
.filter(field => typeof field?.id === 'string' && field.id !== '' && typeof field.slug === 'string' && field.slug !== '')
|
|
86
|
+
.map(field => ({
|
|
87
|
+
id: String(field.id),
|
|
88
|
+
slug: String(field.slug),
|
|
89
|
+
relationType: String(field.relationType ?? 'none'),
|
|
90
|
+
relationId: field.relationId ?? null,
|
|
91
|
+
primaryKey: field.primaryKey === true
|
|
92
|
+
}));
|
|
93
|
+
this.fieldsByEntity.set(ref.entityId, fields);
|
|
94
|
+
return fields;
|
|
95
|
+
}
|
|
96
|
+
recordByEntity = new Map();
|
|
97
|
+
async loadTree() {
|
|
98
|
+
if (this.tree)
|
|
99
|
+
return this.tree;
|
|
100
|
+
const payload = await this.platform.tenant('GET', this.project, '/datasources/tree', { environment: this.environment });
|
|
101
|
+
this.tree = Array.isArray(payload) ? payload : (payload?.data ?? []);
|
|
102
|
+
return this.tree;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { logError, logStep } from '../observability/trace.js';
|
|
2
2
|
import { PlatformApiError } from './errors.js';
|
|
3
|
+
import { maskSecrets } from './secrets.js';
|
|
3
4
|
export function prune(value) {
|
|
4
5
|
if (Array.isArray(value))
|
|
5
6
|
return value.map(prune);
|
|
@@ -127,11 +128,15 @@ function asStructured(payload) {
|
|
|
127
128
|
}
|
|
128
129
|
export function toolResult(payload, config) {
|
|
129
130
|
const pruned = prune(payload);
|
|
130
|
-
const
|
|
131
|
+
const { payload: safe, masked, tokenRefs } = maskSecrets(pruned);
|
|
132
|
+
const runtimeErrors = runtimeErrorSummary(safe);
|
|
131
133
|
if (runtimeErrors.length > 0) {
|
|
132
134
|
logStep('akış hatası ✕', `${runtimeErrors.length} adım hata ile bitti — platform HTTP 200 döndürdüğü için çağrı başarılı görünüyordu`, runtimeErrors);
|
|
133
135
|
}
|
|
134
|
-
|
|
136
|
+
if (masked.length > 0) {
|
|
137
|
+
logStep('maskeleme', `${masked.length} gizli alan yanıttan çıkarıldı — değer *** ile değiştirildi, yolu gatewayMasked'de`, masked);
|
|
138
|
+
}
|
|
139
|
+
const { payload: bounded, truncated } = shrink(safe, config.maxResponseBytes);
|
|
135
140
|
const structured = asStructured(bounded);
|
|
136
141
|
if (truncated) {
|
|
137
142
|
logStep('kırpma ✂', `yanıt ${config.maxResponseBytes} bayt sınırını aştı — en uzun liste yarıya indirilerek küçültüldü (MAX_RESPONSE_BYTES)`);
|
|
@@ -139,6 +144,8 @@ export function toolResult(payload, config) {
|
|
|
139
144
|
const enriched = {
|
|
140
145
|
...structured,
|
|
141
146
|
...(runtimeErrors.length > 0 ? { runtimeErrors } : {}),
|
|
147
|
+
...(masked.length > 0 ? { gatewayMasked: masked } : {}),
|
|
148
|
+
...(Object.keys(tokenRefs).length > 0 ? { tokenRefs, tokenRefNote: "Maskelenen JWT'ler gateway içinde tutuldu; bu referansları page_screenshot / page_runtime_get 'asUser' alanına verebilirsiniz (15 dk geçerli). Jetonun kendisi yanıta ve günlüğe hiç girmez." } : {}),
|
|
142
149
|
...(truncated ? { truncated: true, truncationNote: 'Liste, yanıt boyutu sınırı nedeniyle kırpıldı; sayfalama ya da daha dar filtre kullanın.' } : {})
|
|
143
150
|
};
|
|
144
151
|
return {
|