@softacus-software/elwis-data-mcp 0.1.0
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/CHANGELOG.md +15 -0
- package/LICENSE +6 -0
- package/README.md +183 -0
- package/dist/app-scope.js +92 -0
- package/dist/app-scope.js.map +1 -0
- package/dist/artifact-read.js +114 -0
- package/dist/artifact-read.js.map +1 -0
- package/dist/audit.js +36 -0
- package/dist/audit.js.map +1 -0
- package/dist/builders/artifact-type-execute.js +100 -0
- package/dist/builders/artifact-type-execute.js.map +1 -0
- package/dist/builders/artifact-type-plan.js +139 -0
- package/dist/builders/artifact-type-plan.js.map +1 -0
- package/dist/builders/design-interview.js +246 -0
- package/dist/builders/design-interview.js.map +1 -0
- package/dist/builders/entity-lifecycle-execute.js +12 -0
- package/dist/builders/entity-lifecycle-execute.js.map +1 -0
- package/dist/builders/entity-lifecycle-plan.js +345 -0
- package/dist/builders/entity-lifecycle-plan.js.map +1 -0
- package/dist/builders/links-execute.js +50 -0
- package/dist/builders/links-execute.js.map +1 -0
- package/dist/builders/links-plan.js +62 -0
- package/dist/builders/links-plan.js.map +1 -0
- package/dist/builders/page-execute.js +38 -0
- package/dist/builders/page-execute.js.map +1 -0
- package/dist/builders/page-plan.js +148 -0
- package/dist/builders/page-plan.js.map +1 -0
- package/dist/builders/records-execute.js +24 -0
- package/dist/builders/records-execute.js.map +1 -0
- package/dist/builders/records-lifecycle-execute.js +30 -0
- package/dist/builders/records-lifecycle-execute.js.map +1 -0
- package/dist/builders/records-lifecycle-plan.js +199 -0
- package/dist/builders/records-lifecycle-plan.js.map +1 -0
- package/dist/builders/records-plan.js +74 -0
- package/dist/builders/records-plan.js.map +1 -0
- package/dist/builders/update-page-execute.js +38 -0
- package/dist/builders/update-page-execute.js.map +1 -0
- package/dist/builders/update-page-plan.js +137 -0
- package/dist/builders/update-page-plan.js.map +1 -0
- package/dist/builders/workflow-execute.js +11 -0
- package/dist/builders/workflow-execute.js.map +1 -0
- package/dist/builders/workflow-plan.js +115 -0
- package/dist/builders/workflow-plan.js.map +1 -0
- package/dist/cli/client-configs.js +98 -0
- package/dist/cli/client-configs.js.map +1 -0
- package/dist/cli/login.js +64 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/prompter.js +77 -0
- package/dist/cli/prompter.js.map +1 -0
- package/dist/cli/setup.js +214 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/confirm.js +22 -0
- package/dist/confirm.js.map +1 -0
- package/dist/elwis-api.js +96 -0
- package/dist/elwis-api.js.map +1 -0
- package/dist/http-client.js +142 -0
- package/dist/http-client.js.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt.js +18 -0
- package/dist/jwt.js.map +1 -0
- package/dist/prune.js +9 -0
- package/dist/prune.js.map +1 -0
- package/dist/resolve.js +71 -0
- package/dist/resolve.js.map +1 -0
- package/dist/result.js +16 -0
- package/dist/result.js.map +1 -0
- package/dist/server.js +82 -0
- package/dist/server.js.map +1 -0
- package/dist/session-store.js +51 -0
- package/dist/session-store.js.map +1 -0
- package/dist/tools/build-artifact-type.js +36 -0
- package/dist/tools/build-artifact-type.js.map +1 -0
- package/dist/tools/build-links.js +33 -0
- package/dist/tools/build-links.js.map +1 -0
- package/dist/tools/build-page.js +40 -0
- package/dist/tools/build-page.js.map +1 -0
- package/dist/tools/build-workflow.js +36 -0
- package/dist/tools/build-workflow.js.map +1 -0
- package/dist/tools/create-application.js +44 -0
- package/dist/tools/create-application.js.map +1 -0
- package/dist/tools/create-artifacts.js +33 -0
- package/dist/tools/create-artifacts.js.map +1 -0
- package/dist/tools/create-folder.js +55 -0
- package/dist/tools/create-folder.js.map +1 -0
- package/dist/tools/delete-artifacts.js +33 -0
- package/dist/tools/delete-artifacts.js.map +1 -0
- package/dist/tools/delete-entity.js +35 -0
- package/dist/tools/delete-entity.js.map +1 -0
- package/dist/tools/explain-access.js +40 -0
- package/dist/tools/explain-access.js.map +1 -0
- package/dist/tools/get-entity.js +36 -0
- package/dist/tools/get-entity.js.map +1 -0
- package/dist/tools/get-page.js +75 -0
- package/dist/tools/get-page.js.map +1 -0
- package/dist/tools/list-apps.js +22 -0
- package/dist/tools/list-apps.js.map +1 -0
- package/dist/tools/list-entities.js +43 -0
- package/dist/tools/list-entities.js.map +1 -0
- package/dist/tools/propose-page-design.js +17 -0
- package/dist/tools/propose-page-design.js.map +1 -0
- package/dist/tools/raw-api.js +132 -0
- package/dist/tools/raw-api.js.map +1 -0
- package/dist/tools/read-artifacts.js +197 -0
- package/dist/tools/read-artifacts.js.map +1 -0
- package/dist/tools/resolve-entity.js +22 -0
- package/dist/tools/resolve-entity.js.map +1 -0
- package/dist/tools/update-artifacts.js +33 -0
- package/dist/tools/update-artifacts.js.map +1 -0
- package/dist/tools/update-entity.js +41 -0
- package/dist/tools/update-entity.js.map +1 -0
- package/dist/tools/update-page.js +40 -0
- package/dist/tools/update-page.js.map +1 -0
- package/dist/write-gate.js +25 -0
- package/dist/write-gate.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DeleteArtifactsInput, BuildDeletePlan } from '../builders/records-lifecycle-plan.js';
|
|
2
|
+
import { ExecuteDeletePlan } from '../builders/records-lifecycle-execute.js';
|
|
3
|
+
import { AssertWriteEnabled, CheckConfirmation, CONFIRMATION_MESSAGE, DRY_RUN_MESSAGE } from '../write-gate.js';
|
|
4
|
+
import { PlanToken } from '../confirm.js';
|
|
5
|
+
import { AuditedExecute } from '../audit.js';
|
|
6
|
+
import { RequireApplicationId } from '../resolve.js';
|
|
7
|
+
import { Text, ErrorResult } from '../result.js';
|
|
8
|
+
export function RegisterDeleteArtifacts(server, api, cfg, scope) {
|
|
9
|
+
server.registerTool('delete_elwis_artifacts', {
|
|
10
|
+
description: 'Delete data records (artifacts) in one batch call (up to 50), for requests like "remove the test orders" or "delete the RTX 4090 product". Records are addressed by name (scoped by artifactType when names repeat; one artifactType scope per call, split mixed-type batches) or by id. Deletion is soft: records disappear from the application but remain recoverable by an administrator. Links FROM a deleted record are deleted with it; links pointing TO it remain and dangle, warn the user when the record is linked. A name that does not resolve is a clean error and nothing else is deleted in its place; an ambiguous name is an error listing candidates instead of picking one. Before deleting on a user\'s behalf: run with dryRun first, show the user the resolved record names, and after they agree call again passing the ids from the dry-run plan (not the names) so exactly the confirmed records are deleted.',
|
|
11
|
+
inputSchema: DeleteArtifactsInput.shape,
|
|
12
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
13
|
+
}, async (raw) => {
|
|
14
|
+
try {
|
|
15
|
+
const applicationId = await RequireApplicationId(api, raw);
|
|
16
|
+
await scope.assertAllowed(applicationId);
|
|
17
|
+
const plan = await BuildDeletePlan(api, raw, applicationId);
|
|
18
|
+
const token = PlanToken(cfg, 'delete_elwis_artifacts', plan);
|
|
19
|
+
if (raw.dryRun)
|
|
20
|
+
return Text({ status: 'dry-run', dryRun: true, confirmationToken: token, message: DRY_RUN_MESSAGE, plan });
|
|
21
|
+
AssertWriteEnabled(cfg);
|
|
22
|
+
if (CheckConfirmation(cfg, token, raw.confirm) === 'pending') {
|
|
23
|
+
return Text({ status: 'confirmation-required', confirmationToken: token, plan, message: CONFIRMATION_MESSAGE });
|
|
24
|
+
}
|
|
25
|
+
const report = await AuditedExecute(cfg, scope, 'delete_elwis_artifacts', token, () => ExecuteDeletePlan(api, plan), (r) => ({ deleted: r.deleted }));
|
|
26
|
+
return Text({ status: 'ok', ...report });
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
return ErrorResult(e);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=delete-artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-artifacts.js","sourceRoot":"","sources":["../../src/tools/delete-artifacts.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAChH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,UAAU,uBAAuB,CAAC,MAAiB,EAAE,GAAa,EAAE,GAAgB,EAAE,KAAe;IACzG,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;QACE,WAAW,EAAE,24BAA24B;QACx5B,WAAW,EAAE,oBAAoB,CAAC,KAAK;QACvC,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE;KACxG,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC3D,MAAM,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;YAC5D,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE,wBAAwB,EAAE,IAAI,CAAC,CAAC;YAC7D,IAAI,GAAG,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3H,kBAAkB,CAAC,GAAG,CAAC,CAAC;YACxB,IAAI,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC7D,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC;YAClH,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,wBAAwB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACtJ,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { DeleteEntityInput, BuildEntityDeletePlan } from '../builders/entity-lifecycle-plan.js';
|
|
2
|
+
import { ExecuteEntityDeletePlan } from '../builders/entity-lifecycle-execute.js';
|
|
3
|
+
import { AssertWriteEnabled, CheckConfirmation, CONFIRMATION_MESSAGE, DRY_RUN_MESSAGE } from '../write-gate.js';
|
|
4
|
+
import { PlanToken } from '../confirm.js';
|
|
5
|
+
import { AuditedExecute } from '../audit.js';
|
|
6
|
+
import { RequireApplicationId, ResolveApplicationId } from '../resolve.js';
|
|
7
|
+
import { Text, ErrorResult } from '../result.js';
|
|
8
|
+
export function RegisterDeleteEntity(server, api, cfg, scope) {
|
|
9
|
+
server.registerTool('delete_elwis_entity', {
|
|
10
|
+
description: 'Delete one configuration entity: an application, data type, attribute, artifact type, link type, workflow, page, folder (addressed by name, full path like "Projects/2026", or id; the dry-run reports subfolders and records inside), or a single link between two records, for requests like "remove the old Priority attribute" or "delete the test page". For entity "application", target IS the application, and the backend deletes it even when it still has content, the dry-run reports its artifact types, pages, and record count; never confirm an application delete without walking the user through that list. Addressed by name, alias, or id within an application (workflows tenant-wide by name; links by id only). Deletion is soft: an administrator can recover it. The dry-run reports what still references the entity, attributes on a data type, artifact types assigning an attribute, record counts on an artifact type, link counts on a link type; show that to the user before going ahead, and expect the backend to refuse deletes that would orphan required structure. Always run with dryRun first, confirm the resolved name with the user, then call again with the confirmation token.',
|
|
11
|
+
inputSchema: DeleteEntityInput.shape,
|
|
12
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
13
|
+
}, async (raw) => {
|
|
14
|
+
try {
|
|
15
|
+
const applicationId = raw.entity === 'application'
|
|
16
|
+
? await ResolveApplicationId(api, raw.target)
|
|
17
|
+
: await RequireApplicationId(api, raw);
|
|
18
|
+
await scope.assertAllowed(applicationId);
|
|
19
|
+
const plan = await BuildEntityDeletePlan(api, raw, { applicationId, restricted: scope.restricted });
|
|
20
|
+
const token = PlanToken(cfg, 'delete_elwis_entity', plan);
|
|
21
|
+
if (raw.dryRun)
|
|
22
|
+
return Text({ status: 'dry-run', dryRun: true, confirmationToken: token, message: DRY_RUN_MESSAGE, plan });
|
|
23
|
+
AssertWriteEnabled(cfg);
|
|
24
|
+
if (CheckConfirmation(cfg, token, raw.confirm) === 'pending') {
|
|
25
|
+
return Text({ status: 'confirmation-required', confirmationToken: token, plan, message: CONFIRMATION_MESSAGE });
|
|
26
|
+
}
|
|
27
|
+
const report = await AuditedExecute(cfg, scope, 'delete_elwis_entity', token, () => ExecuteEntityDeletePlan(api, plan), (r) => r.deleted);
|
|
28
|
+
return Text({ status: 'ok', ...report });
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
return ErrorResult(e);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=delete-entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-entity.js","sourceRoot":"","sources":["../../src/tools/delete-entity.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAChH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,GAAa,EAAE,GAAgB,EAAE,KAAe;IACtG,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,WAAW,EAAE,gqCAAgqC;QAC7qC,WAAW,EAAE,iBAAiB,CAAC,KAAK;QACpC,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE;KACxG,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,KAAK,aAAa;gBAChD,CAAC,CAAC,MAAM,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC;gBAC7C,CAAC,CAAC,MAAM,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACzC,MAAM,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;YACpG,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE,qBAAqB,EAAE,IAAI,CAAC,CAAC;YAC1D,IAAI,GAAG,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3H,kBAAkB,CAAC,GAAG,CAAC,CAAC;YACxB,IAAI,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC7D,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC;YAClH,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC1I,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { DecodeJwtClaims } from '../jwt.js';
|
|
2
|
+
import { Text } from '../result.js';
|
|
3
|
+
export function RegisterExplainAccess(server, cfg, api, scope) {
|
|
4
|
+
server.registerTool('explain_elwis_access', {
|
|
5
|
+
description: 'Report who the configured token acts as (verified against the backend), the tenant and whether it matches the tenant this connection is pinned to, whether writes are enabled and require per-plan confirmation, the application allowlist, the audit log location, token expiry, and the tenant system attribute ids (Name, Sequence, Primary Text, needed as column keys for data-bound list widgets). Never returns the token itself. Call this first to check connectivity.',
|
|
6
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
7
|
+
}, async () => {
|
|
8
|
+
const c = DecodeJwtClaims(cfg.token);
|
|
9
|
+
let identity;
|
|
10
|
+
let connected = true;
|
|
11
|
+
try {
|
|
12
|
+
identity = await api.whoAmI();
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
connected = false;
|
|
16
|
+
identity = { userId: c.sub ?? null, email: null, tenantId: c.tenant ?? null, tenantAdmin: null };
|
|
17
|
+
}
|
|
18
|
+
const systemAttributes = connected ? await api.systemAttributes().catch(() => null) : null;
|
|
19
|
+
return Text({
|
|
20
|
+
systemAttributes,
|
|
21
|
+
connected,
|
|
22
|
+
host: cfg.baseUrl,
|
|
23
|
+
user: identity.userId,
|
|
24
|
+
email: identity.email,
|
|
25
|
+
tenant: identity.tenantId,
|
|
26
|
+
tenantBinding: cfg.expectedTenant
|
|
27
|
+
? { pinned: true, expected: cfg.expectedTenant, matches: identity.tenantId === cfg.expectedTenant }
|
|
28
|
+
: { pinned: false, note: `No tenant is set, so all data tools are disabled, I cannot tell which ELWIS environment to act in. Set ELWIS_TENANT to ${identity.tenantId ?? 'the tenant this login belongs to'} (that is the tenant of the account you signed in with), or re-run the setup wizard, which fills it in automatically.` },
|
|
29
|
+
rights: identity.tenantAdmin === null ? 'unknown' : identity.tenantAdmin ? 'tenant-admin' : 'user',
|
|
30
|
+
writeEnabled: cfg.writeEnabled,
|
|
31
|
+
writeConfirmation: cfg.requireConfirmation
|
|
32
|
+
? 'every write needs a user-confirmed plan token'
|
|
33
|
+
: 'OFF, writes execute immediately without user approval (ELWIS_REQUIRE_CONFIRMATION=false). If this is an interactive session with a person, warn them and suggest turning it back on.',
|
|
34
|
+
auditLog: cfg.auditLog,
|
|
35
|
+
appScope: scope.describe(),
|
|
36
|
+
tokenExpiry: c.exp ? new Date(c.exp * 1000).toISOString() : 'never',
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=explain-access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explain-access.js","sourceRoot":"","sources":["../../src/tools/explain-access.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,GAAgB,EAAE,GAAa,EAAE,KAAe;IACvG,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;QACE,WAAW,EAAE,idAAid;QAC9d,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;KAC/E,EACD,KAAK,IAAI,EAAE;QACT,MAAM,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,QAA+G,CAAC;QACpH,IAAI,SAAS,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,GAAG,KAAK,CAAC;YAClB,QAAQ,GAAG,EAAE,MAAM,EAAG,CAAC,CAAC,GAAc,IAAI,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAG,CAAC,CAAC,MAAiB,IAAI,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAC3H,CAAC;QACD,MAAM,gBAAgB,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC3F,OAAO,IAAI,CAAC;YACV,gBAAgB;YAChB,SAAS;YACT,IAAI,EAAE,GAAG,CAAC,OAAO;YACjB,IAAI,EAAE,QAAQ,CAAC,MAAM;YACrB,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,MAAM,EAAE,QAAQ,CAAC,QAAQ;YACzB,aAAa,EAAE,GAAG,CAAC,cAAc;gBAC/B,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,QAAQ,KAAK,GAAG,CAAC,cAAc,EAAE;gBACnG,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,0HAA0H,QAAQ,CAAC,QAAQ,IAAI,kCAAkC,uHAAuH,EAAE;YACrU,MAAM,EAAE,QAAQ,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM;YAClG,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,iBAAiB,EAAE,GAAG,CAAC,mBAAmB;gBACxC,CAAC,CAAC,+CAA+C;gBACjD,CAAC,CAAC,sLAAsL;YAC1L,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE;YAC1B,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO;SACpE,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { DELETE_ENTITY_KINDS, ResolveDocument } from '../builders/entity-lifecycle-plan.js';
|
|
3
|
+
import { RequireApplicationId, ResolveApplicationId } from '../resolve.js';
|
|
4
|
+
import { Text, ErrorResult } from '../result.js';
|
|
5
|
+
const GetEntityInput = z.object({
|
|
6
|
+
entity: z.enum(DELETE_ENTITY_KINDS),
|
|
7
|
+
applicationId: z.string().optional(),
|
|
8
|
+
applicationName: z.string().optional(),
|
|
9
|
+
target: z.string().min(1).describe('Entity name, alias, or 24-char hex id (links by id only)'),
|
|
10
|
+
});
|
|
11
|
+
const OMITTED_FIELDS = ['acl'];
|
|
12
|
+
export function RegisterGetEntity(server, api, scope) {
|
|
13
|
+
server.registerTool('get_elwis_entity', {
|
|
14
|
+
description: 'Read the full body of one configuration entity: an application, data type, attribute, artifact type, link type, workflow, page, or link. Use it before structured edits, to see a data type\'s current enum values, an artifact type\'s attribute assignments, a workflow\'s triggers and actions, then send the whole corrected field via update_elwis_entity. For entity "application", target IS the application. Access control lists are omitted.',
|
|
15
|
+
inputSchema: GetEntityInput.shape,
|
|
16
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
17
|
+
}, async (raw) => {
|
|
18
|
+
try {
|
|
19
|
+
const applicationId = raw.entity === 'application'
|
|
20
|
+
? await ResolveApplicationId(api, raw.target)
|
|
21
|
+
: await RequireApplicationId(api, raw);
|
|
22
|
+
await scope.assertAllowed(applicationId);
|
|
23
|
+
const doc = await ResolveDocument(api, raw.entity, { applicationId, restricted: scope.restricted }, raw.target);
|
|
24
|
+
const body = {};
|
|
25
|
+
for (const [key, value] of Object.entries(doc)) {
|
|
26
|
+
if (!OMITTED_FIELDS.includes(key))
|
|
27
|
+
body[key] = value;
|
|
28
|
+
}
|
|
29
|
+
return Text({ status: 'ok', entity: raw.entity, body });
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
return ErrorResult(e);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=get-entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-entity.js","sourceRoot":"","sources":["../../src/tools/get-entity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC;IACnC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,0DAA0D,CAAC;CAC/F,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,CAAC,KAAK,CAAC,CAAC;AAE/B,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,GAAa,EAAE,KAAe;IACjF,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;QACE,WAAW,EAAE,wbAAwb;QACrc,WAAW,EAAE,cAAc,CAAC,KAAK;QACjC,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;KACvG,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,KAAK,aAAa;gBAChD,CAAC,CAAC,MAAM,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC;gBAC7C,CAAC,CAAC,MAAM,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACzC,MAAM,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;YAChH,MAAM,IAAI,GAA4B,EAAE,CAAC;YACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACvD,CAAC;YACD,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { RequireApplicationId } from '../resolve.js';
|
|
3
|
+
import { FindPage } from '../builders/update-page-plan.js';
|
|
4
|
+
import { Text, ErrorResult } from '../result.js';
|
|
5
|
+
const EXCERPT_LIMIT = 160;
|
|
6
|
+
function Excerpt(value) {
|
|
7
|
+
const text = value?.model?.text;
|
|
8
|
+
if (typeof text !== 'string')
|
|
9
|
+
return null;
|
|
10
|
+
const plain = text.replace(/<style[\s\S]*?<\/style>/gi, '').replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
|
|
11
|
+
return plain.length > EXCERPT_LIMIT ? `${plain.slice(0, EXCERPT_LIMIT)}…` : plain;
|
|
12
|
+
}
|
|
13
|
+
function FullText(value) {
|
|
14
|
+
const text = value?.model?.text;
|
|
15
|
+
return typeof text === 'string' ? text : null;
|
|
16
|
+
}
|
|
17
|
+
export function RegisterGetPage(server, api, scope) {
|
|
18
|
+
server.registerTool('get_elwis_page', {
|
|
19
|
+
title: 'Get one ELWIS page structure',
|
|
20
|
+
description: 'Get the structure of one page: sections with their styles, rows with column layouts, and every widget with its id, code, and a short text excerpt. Section, row, and column numbers are 1-based counted from the top. Use this BEFORE update_elwis_page to find which section or widget the user means ("the header" is usually section 1, "the footer" the last section) and to get the widget ids that widgetTexts requires. The excerpt identifies a widget but is NOT its content: before editing a widget\'s text, call again with fullTextWidgets set to that widget id and modify the returned fullText, never regenerate a widget from the excerpt.',
|
|
21
|
+
inputSchema: {
|
|
22
|
+
applicationId: z.string().optional(),
|
|
23
|
+
applicationName: z.string().optional(),
|
|
24
|
+
page: z.string().describe('Page name, alias, or 24-char hex id'),
|
|
25
|
+
fullTextWidgets: z.array(z.string()).max(10).optional().describe('Widget ids whose complete HTML content to return as fullText (TEXT widgets only)'),
|
|
26
|
+
},
|
|
27
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
28
|
+
}, async (raw) => {
|
|
29
|
+
try {
|
|
30
|
+
const applicationId = await RequireApplicationId(api, raw);
|
|
31
|
+
await scope.assertAllowed(applicationId);
|
|
32
|
+
const page = await FindPage(api, applicationId, raw.page);
|
|
33
|
+
const widgetIds = [];
|
|
34
|
+
const sections = (page.sections ?? []).map((s, si) => ({
|
|
35
|
+
section: si + 1,
|
|
36
|
+
styles: s.styles ?? {},
|
|
37
|
+
rows: (s.rows ?? []).map((r, ri) => ({
|
|
38
|
+
row: ri + 1,
|
|
39
|
+
layout: r.layout,
|
|
40
|
+
columns: (r.blocks ?? []).map((b, bi) => ({
|
|
41
|
+
column: bi + 1,
|
|
42
|
+
widgets: (b.parts ?? [])
|
|
43
|
+
.filter((p) => typeof p.widget?.widgetId === 'string' && p.widget.widgetId.length > 0)
|
|
44
|
+
.map((p) => {
|
|
45
|
+
widgetIds.push(p.widget.widgetId);
|
|
46
|
+
return { widgetId: p.widget.widgetId };
|
|
47
|
+
}),
|
|
48
|
+
})),
|
|
49
|
+
})),
|
|
50
|
+
}));
|
|
51
|
+
const unique = [...new Set(widgetIds)];
|
|
52
|
+
const wantFull = new Set(raw.fullTextWidgets ?? []);
|
|
53
|
+
const docs = new Map();
|
|
54
|
+
const rows = unique.length ? await api.list('widget', { _id: { $in: unique.map(id => ({ $oid: id })) } }, unique.length + 1) : [];
|
|
55
|
+
for (const w of rows) {
|
|
56
|
+
docs.set(String(w.id), {
|
|
57
|
+
code: w.code,
|
|
58
|
+
excerpt: Excerpt(w.value),
|
|
59
|
+
...(wantFull.has(String(w.id)) ? { fullText: FullText(w.value) } : {}),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
for (const s of sections)
|
|
63
|
+
for (const r of s.rows)
|
|
64
|
+
for (const c of r.columns)
|
|
65
|
+
for (const w of c.widgets) {
|
|
66
|
+
Object.assign(w, docs.get(String(w.widgetId)) ?? { code: 'UNKNOWN', excerpt: null });
|
|
67
|
+
}
|
|
68
|
+
return Text({ status: 'ok', id: page.id, name: page.name, alias: page.alias ?? null, isPublic: page.isPublic ?? false, sections });
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
return ErrorResult(e);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=get-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-page.js","sourceRoot":"","sources":["../../src/tools/get-page.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,SAAS,OAAO,CAAC,KAAc;IAC7B,MAAM,IAAI,GAAI,KAA6B,EAAE,KAAK,EAAE,IAAI,CAAC;IACzD,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACjH,OAAO,KAAK,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AACpF,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,MAAM,IAAI,GAAI,KAA6B,EAAE,KAAK,EAAE,IAAI,CAAC;IACzD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAiB,EAAE,GAAa,EAAE,KAAe;IAC/E,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;QACE,KAAK,EAAE,8BAA8B;QACrC,WAAW,EAAE,6nBAA6nB;QAC1oB,WAAW,EAAE;YACX,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACpC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACtC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;YAChE,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kFAAkF,CAAC;SACrJ;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;KACvG,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC3D,MAAM,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1D,MAAM,SAAS,GAAa,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAsB,EAAE,EAAU,EAAE,EAAE,CAAC,CAAC;gBAClF,OAAO,EAAE,EAAE,GAAG,CAAC;gBACf,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;gBACtB,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAsB,EAAE,EAAU,EAAE,EAAE,CAAC,CAAC;oBAChE,GAAG,EAAE,EAAE,GAAG,CAAC;oBACX,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAsB,EAAE,EAAU,EAAE,EAAE,CAAC,CAAC;wBACrE,MAAM,EAAE,EAAE,GAAG,CAAC;wBACd,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;6BACrB,MAAM,CAAC,CAAC,CAAsB,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;6BAC1G,GAAG,CAAC,CAAC,CAAsB,EAAE,EAAE;4BAC9B,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;4BAClC,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,QAAkB,EAAE,CAAC;wBACnD,CAAC,CAAC;qBACL,CAAC,CAAC;iBACJ,CAAC,CAAC;aACJ,CAAC,CAAC,CAAC;YACJ,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;YACvC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,IAAI,GAAG,EAA8E,CAAC;YACnG,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAClI,KAAK,MAAM,CAAC,IAAI,IAAkC,EAAE,CAAC;gBACnD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;oBACrB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;oBACzB,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvE,CAAC,CAAC;YACL,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,QAAQ;gBAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI;oBAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO;wBAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAyC,EAAE,CAAC;4BACzI,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;wBACvF,CAAC;YACD,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrI,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Text, ErrorResult } from '../result.js';
|
|
3
|
+
export function RegisterListApps(server, api, scope) {
|
|
4
|
+
server.registerTool('list_elwis_apps', {
|
|
5
|
+
description: 'List ELWIS applications visible to the configured user. Optional name substring filter. When the server is configured with an application allowlist, only allowlisted applications are returned.',
|
|
6
|
+
inputSchema: { nameContains: z.string().optional(), limit: z.number().int().positive().max(100).optional() },
|
|
7
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
8
|
+
}, async ({ nameContains, limit }) => {
|
|
9
|
+
try {
|
|
10
|
+
await scope.assertTenant();
|
|
11
|
+
const filter = nameContains ? { name: { $regex: nameContains, $options: 'i' } } : {};
|
|
12
|
+
const rows = await api.list('application', filter, limit ?? 25);
|
|
13
|
+
const allowed = await scope.allowedIds();
|
|
14
|
+
const visible = allowed ? rows.filter(r => allowed.has(r.id)) : rows;
|
|
15
|
+
return Text(visible.map(r => ({ id: r.id, name: r.name, alias: r.alias, isActive: r.isActive ?? true })));
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
return ErrorResult(e);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=list-apps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-apps.js","sourceRoot":"","sources":["../../src/tools/list-apps.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,UAAU,gBAAgB,CAAC,MAAiB,EAAE,GAAa,EAAE,KAAe;IAChF,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EAAE,kMAAkM;QAC/M,WAAW,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAC5G,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;KAC/E,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE;QAChC,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,YAAY,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YAChE,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACrE,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5G,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { RequireApplicationId } from '../resolve.js';
|
|
3
|
+
import { EscapeRegex } from '../artifact-read.js';
|
|
4
|
+
import { Text, ErrorResult } from '../result.js';
|
|
5
|
+
const KIND = z.enum(['dataType', 'attribute', 'artifactType', 'linkType', 'folder', 'page', 'widget', 'workflow']);
|
|
6
|
+
const MAP = { dataType: 'data-type', attribute: 'attribute', artifactType: 'artifact-type', linkType: 'link-type', folder: 'folder', page: 'page', widget: 'widget', workflow: 'workflow' };
|
|
7
|
+
export function RegisterListEntities(server, api, scope) {
|
|
8
|
+
server.registerTool('list_elwis_entities', {
|
|
9
|
+
title: 'List ELWIS configuration entities',
|
|
10
|
+
description: 'Enumerate the configuration of an application: data types, attributes, artifact types, link types, folders, pages, widgets, or workflows (workflows are owner-scoped, not application-scoped, and are listed tenant-wide by name). Optional name substring filter. Returns compact {id, name, alias} rows with hasMore metadata; use resolve_elwis_entity when you already know the exact name.',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
kind: KIND,
|
|
13
|
+
applicationId: z.string().optional(),
|
|
14
|
+
applicationName: z.string().optional(),
|
|
15
|
+
nameContains: z.string().optional().describe('Case-insensitive substring match on the name'),
|
|
16
|
+
limit: z.number().int().positive().max(200).optional().describe('Maximum rows (default 50)'),
|
|
17
|
+
},
|
|
18
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
19
|
+
}, async ({ kind, applicationId, applicationName, nameContains, limit }) => {
|
|
20
|
+
try {
|
|
21
|
+
const appId = await RequireApplicationId(api, { applicationId, applicationName });
|
|
22
|
+
await scope.assertAllowed(appId);
|
|
23
|
+
const filter = kind === 'workflow' ? {} : { applicationId: { $oid: appId } };
|
|
24
|
+
if (nameContains)
|
|
25
|
+
filter.name = { $regex: EscapeRegex(nameContains), $options: 'i' };
|
|
26
|
+
const max = limit ?? 50;
|
|
27
|
+
let rows;
|
|
28
|
+
try {
|
|
29
|
+
rows = await api.list(MAP[kind], filter, max + 1);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
const loose = await api.list(MAP[kind], nameContains ? { name: { $regex: EscapeRegex(nameContains), $options: 'i' } } : {}, 200);
|
|
33
|
+
rows = loose.filter(r => String(r.applicationId) === appId).slice(0, max + 1);
|
|
34
|
+
}
|
|
35
|
+
const results = rows.slice(0, max).map(r => ({ id: r.id, name: r.name, alias: r.alias }));
|
|
36
|
+
return Text({ status: 'ok', returned: results.length, hasMore: rows.length > max, results });
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
return ErrorResult(e);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=list-entities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-entities.js","sourceRoot":"","sources":["../../src/tools/list-entities.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AACnH,MAAM,GAAG,GAA+B,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AAExN,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,GAAa,EAAE,KAAe;IACpF,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,KAAK,EAAE,mCAAmC;QAC1C,WAAW,EAAE,iYAAiY;QAC9Y,WAAW,EAAE;YACX,IAAI,EAAE,IAAI;YACV,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACpC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACtC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;YAC5F,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;SAC7F;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;KACvG,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE;QACtE,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC,CAAC;YAClF,MAAM,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,MAAM,GAA4B,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACtG,IAAI,YAAY;gBAAE,MAAM,CAAC,IAAI,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;YACrF,MAAM,GAAG,GAAG,KAAK,IAAI,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC;YACT,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;YACpD,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;gBACjI,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAE,CAA6B,CAAC,aAAa,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;YAC7G,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC1F,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ProposePageDesignInput, NextInterviewStep } from '../builders/design-interview.js';
|
|
2
|
+
import { Text, ErrorResult } from '../result.js';
|
|
3
|
+
export function RegisterProposePageDesign(server) {
|
|
4
|
+
server.registerTool('propose_page_design', {
|
|
5
|
+
description: 'The design interview for new pages. THE RULE: until you are 100% sure what the user wants, build nothing, be a curious child who asks how this should look, what goes here, which of these exactly. Call this tool FIRST for any new-page request; it returns the next questions to relay to the user (each with pickable suggestions) and the assumptions to state out loud ("I\'m assuming a one-line subtitle, correct me if that\'s wrong"). Feed the user\'s replies back via answers{} (question id -> their words) and set assumptionsConfirmed:true once they agree, then call again; repeat until status is "ready" and only then build from the returned brief with build_page, dryRun first. Ambiguity is resolved here mechanically: a bare color like "yellow" comes back as "which yellow exactly?" with named shades and hex codes; an unknown genre or a site reference you are not certain about ("like Notion") means research real examples with your web search and present 2-3 concrete interpretations. This tool writes nothing and is safe to call any number of times.',
|
|
6
|
+
inputSchema: ProposePageDesignInput.shape,
|
|
7
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
8
|
+
}, (raw) => {
|
|
9
|
+
try {
|
|
10
|
+
return Text(NextInterviewStep(ProposePageDesignInput.parse(raw)));
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
return ErrorResult(e);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=propose-page-design.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propose-page-design.js","sourceRoot":"","sources":["../../src/tools/propose-page-design.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAC5F,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,UAAU,yBAAyB,CAAC,MAAiB;IACzD,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,WAAW,EAAE,iiCAAiiC;QAC9iC,WAAW,EAAE,sBAAsB,CAAC,KAAK;QACzC,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACxG,EACD,CAAC,GAAG,EAAE,EAAE;QACN,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,iBAAiB,CAAC,sBAAsB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { AssertWriteEnabled, CheckConfirmation, CONFIRMATION_MESSAGE, DRY_RUN_MESSAGE } from '../write-gate.js';
|
|
3
|
+
import { PlanToken } from '../confirm.js';
|
|
4
|
+
import { AuditedExecute } from '../audit.js';
|
|
5
|
+
import { AppScopeError, FilterApplicationId } from '../app-scope.js';
|
|
6
|
+
import { Text, ErrorResult } from '../result.js';
|
|
7
|
+
const KIND = z.enum(['application', 'data-type', 'attribute', 'artifact-type', 'link-type', 'folder', 'page', 'widget', 'workflow']);
|
|
8
|
+
const WRITE_KIND = z.enum(['application', 'data-type', 'attribute', 'artifact-type', 'link-type', 'folder', 'page', 'widget', 'workflow', 'artifact', 'link']);
|
|
9
|
+
const CONFIRM_FIELD = z.string().optional().describe('Confirmation token from the previous preview of this exact call; required to execute when confirmation mode is on');
|
|
10
|
+
export function RegisterRawApi(server, api, cfg, scope) {
|
|
11
|
+
server.registerTool('elwis_context', {
|
|
12
|
+
description: 'Return tenant system attribute ids (nameAttributeId, sequenceAttributeId, primaryTextAttributeId) and fileArtifactTypeId. Needed to assemble artifact types by hand: an artifact type must merge the system attributes into its attributes map.',
|
|
13
|
+
inputSchema: {},
|
|
14
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
15
|
+
}, async () => {
|
|
16
|
+
try {
|
|
17
|
+
await scope.assertTenant();
|
|
18
|
+
return Text({ status: 'ok', systemAttributes: await api.systemAttributes() });
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
return ErrorResult(e);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
server.registerTool('elwis_list', {
|
|
25
|
+
description: 'List ELWIS entities of a given kind with a raw Mongo filter. Active records only (deleted:null is always applied). Use to discover ids, check whether something already exists before creating, and read back created records.',
|
|
26
|
+
inputSchema: { kind: KIND, filter: z.record(z.string(), z.any()).optional(), limit: z.number().int().positive().max(200).optional() },
|
|
27
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
28
|
+
}, async ({ kind, filter, limit }) => {
|
|
29
|
+
try {
|
|
30
|
+
await scope.assertListAllowed(kind, filter ?? {});
|
|
31
|
+
const rows = await api.list(kind, filter ?? {}, limit ?? 50);
|
|
32
|
+
const allowed = kind === 'application' ? await scope.allowedIds() : null;
|
|
33
|
+
return Text({ status: 'ok', data: allowed ? rows.filter(r => allowed.has(r.id)) : rows });
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
return ErrorResult(e);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
server.registerTool('elwis_create', {
|
|
40
|
+
description: 'Create one ELWIS entity by POSTing a body straight to /api/tenant/<kind>. The backend validates the full payload, you supply every required field yourself. No name resolution, ordering, reuse, or rollback is done for you: resolve ids with elwis_list / resolve_elwis_entity first, and create dependencies (data-type before attribute before artifact-type) in order. Set dryRun to preview without writing.',
|
|
41
|
+
inputSchema: { kind: WRITE_KIND, body: z.record(z.string(), z.any()), dryRun: z.boolean().optional(), confirm: CONFIRM_FIELD },
|
|
42
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
43
|
+
}, async ({ kind, body, dryRun, confirm }) => {
|
|
44
|
+
try {
|
|
45
|
+
await scope.assertTenant();
|
|
46
|
+
if (scope.restricted) {
|
|
47
|
+
const applicationId = FilterApplicationId(body);
|
|
48
|
+
if (!applicationId)
|
|
49
|
+
throw new AppScopeError('unspecified, when ELWIS_ALLOWED_APPS is set, create bodies must carry the applicationId of an allowlisted application');
|
|
50
|
+
await scope.assertAllowed(applicationId);
|
|
51
|
+
}
|
|
52
|
+
const token = PlanToken(cfg, 'elwis_create', { kind, body });
|
|
53
|
+
if (dryRun)
|
|
54
|
+
return Text({ status: 'dry-run', dryRun: true, confirmationToken: token, message: DRY_RUN_MESSAGE, kind, body });
|
|
55
|
+
AssertWriteEnabled(cfg);
|
|
56
|
+
if (CheckConfirmation(cfg, token, confirm) === 'pending') {
|
|
57
|
+
return Text({ status: 'confirmation-required', confirmationToken: token, kind, body, message: CONFIRMATION_MESSAGE });
|
|
58
|
+
}
|
|
59
|
+
const created = await AuditedExecute(cfg, scope, 'elwis_create', token, () => api.create(kind, body), (r) => ({ kind, created: r.id ?? r }));
|
|
60
|
+
return Text({ status: 'ok', created });
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
return ErrorResult(e);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
server.registerTool('elwis_update', {
|
|
67
|
+
title: 'Update one ELWIS entity',
|
|
68
|
+
description: 'Update one ELWIS entity by PUTting a body (which must include its id) to /api/tenant/<kind>. The backend validates the full payload; read the entity first with elwis_list and send the complete updated document. Set dryRun to preview without writing.',
|
|
69
|
+
inputSchema: { kind: WRITE_KIND, body: z.record(z.string(), z.any()), dryRun: z.boolean().optional(), confirm: CONFIRM_FIELD },
|
|
70
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
71
|
+
}, async ({ kind, body, dryRun, confirm }) => {
|
|
72
|
+
try {
|
|
73
|
+
await scope.assertTenant();
|
|
74
|
+
if (scope.restricted) {
|
|
75
|
+
const applicationId = FilterApplicationId(body);
|
|
76
|
+
if (!applicationId)
|
|
77
|
+
throw new AppScopeError('unspecified, when ELWIS_ALLOWED_APPS is set, update bodies must carry the applicationId of an allowlisted application');
|
|
78
|
+
await scope.assertAllowed(applicationId);
|
|
79
|
+
}
|
|
80
|
+
const { created, updated, deleted, etag, owner, isProtected, importStamp, ...clean } = body;
|
|
81
|
+
void created;
|
|
82
|
+
void updated;
|
|
83
|
+
void deleted;
|
|
84
|
+
void etag;
|
|
85
|
+
void owner;
|
|
86
|
+
void isProtected;
|
|
87
|
+
void importStamp;
|
|
88
|
+
const token = PlanToken(cfg, 'elwis_update', { kind, body: clean });
|
|
89
|
+
if (dryRun)
|
|
90
|
+
return Text({ status: 'dry-run', dryRun: true, confirmationToken: token, message: DRY_RUN_MESSAGE, kind, body: clean });
|
|
91
|
+
AssertWriteEnabled(cfg);
|
|
92
|
+
if (CheckConfirmation(cfg, token, confirm) === 'pending') {
|
|
93
|
+
return Text({ status: 'confirmation-required', confirmationToken: token, kind, body: clean, message: CONFIRMATION_MESSAGE });
|
|
94
|
+
}
|
|
95
|
+
const result = await AuditedExecute(cfg, scope, 'elwis_update', token, () => api.update(kind, clean), (r) => ({ kind, updated: r.id ?? r }));
|
|
96
|
+
return Text({ status: 'ok', updated: result });
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
return ErrorResult(e);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
server.registerTool('elwis_delete', {
|
|
103
|
+
title: 'Soft-delete one ELWIS entity',
|
|
104
|
+
description: 'Soft-delete one ELWIS entity by id. Destructive: requires both ELWIS_WRITE_ENABLED=true and ELWIS_DELETE_ENABLED=true on the server, and confirmName must match the entity name exactly, confirm the exact name with the user before calling; matching it is this tool\'s confirmation mechanism.',
|
|
105
|
+
inputSchema: { kind: WRITE_KIND, id: z.string(), confirmName: z.string().describe('The exact current name of the entity, as a deliberate confirmation the user has approved') },
|
|
106
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
|
|
107
|
+
}, async ({ kind, id, confirmName }) => {
|
|
108
|
+
try {
|
|
109
|
+
await scope.assertTenant();
|
|
110
|
+
AssertWriteEnabled(cfg);
|
|
111
|
+
if (!cfg.deleteEnabled)
|
|
112
|
+
throw new Error('Deletes are disabled. Set ELWIS_DELETE_ENABLED=true to allow soft deletes.');
|
|
113
|
+
const doc = await api.getOne(kind, id);
|
|
114
|
+
if (scope.restricted) {
|
|
115
|
+
const applicationId = doc.applicationId;
|
|
116
|
+
if (!applicationId)
|
|
117
|
+
throw new AppScopeError('unspecified, the entity has no owning application');
|
|
118
|
+
await scope.assertAllowed(String(applicationId));
|
|
119
|
+
}
|
|
120
|
+
const expected = doc.name ?? doc.id;
|
|
121
|
+
if (expected !== confirmName)
|
|
122
|
+
throw new Error('confirmName does not match the entity name (or its id when nameless); refusing to delete');
|
|
123
|
+
const token = PlanToken(cfg, 'elwis_delete', { kind, id, confirmName });
|
|
124
|
+
const deleted = await AuditedExecute(cfg, scope, 'elwis_delete', token, () => api.softDelete(kind, id), () => ({ kind, id, name: confirmName }));
|
|
125
|
+
return Text({ status: 'ok', deleted });
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
return ErrorResult(e);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=raw-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-api.js","sourceRoot":"","sources":["../../src/tools/raw-api.ts"],"names":[],"mappings":"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"}
|