@amerged/ohmyhost-mcp 0.1.32 → 0.1.34
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/README.md +1 -1
- package/dist/{chunk-B2W7NWLK.js → chunk-E3ZJXGBW.js} +9 -9
- package/dist/index.js +1 -1
- package/dist/stdio-main.js +35 -12
- package/package.json +1 -1
- package/src/apps/mcp/package.json +1 -1
- package/src/apps/mcp/src/local-server.ts +16 -4
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +1 -1
- package/src/apps/product-cli/src/runtime-contract.ts +26 -2
- package/src/packages/agent-skills/src/generated-skill-resources.ts +8 -8
- package/src/packages/contracts/src/framework-admission-corpus.ts +97 -0
- package/src/packages/contracts/src/framework-admission.ts +2 -2
- package/src/packages/contracts/src/framework-source-rules.ts +22 -5
- package/src/packages/sdk-ts/package.json +1 -1
- package/src/packages/sdk-ts/src/generated/sdk.gen.ts +1 -1
- package/src/packages/sdk-ts/src/generated/types.gen.ts +15 -1
package/dist/index.js
CHANGED
package/dist/stdio-main.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
serverIdentityOf,
|
|
31
31
|
setNegotiatedProtocolVersion,
|
|
32
32
|
validateEnvelopeMeta
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-E3ZJXGBW.js";
|
|
34
34
|
|
|
35
35
|
// node_modules/.pnpm/ignore@7.0.12/node_modules/ignore/index.js
|
|
36
36
|
var require_ignore = __commonJS({
|
|
@@ -20344,9 +20344,9 @@ var FRAMEWORK_CONVERSION_DETAILS = Object.freeze({
|
|
|
20344
20344
|
paths: ["framework_config"],
|
|
20345
20345
|
template: `"{{path}}" does not follow the TanStack Start plugin contract: import tanstackStart from "@tanstack/react-start/plugin/vite"; on runtime edge also import cloudflare from "@cloudflare/vite-plugin" and call cloudflare({ viteEnvironment: { name: "ssr" } }) before tanstackStart(); on runtime static do not import the Cloudflare plugin. ${PUSH_AND_PLAN}`
|
|
20346
20346
|
},
|
|
20347
|
-
|
|
20347
|
+
next_tailwind_turbopack_only: {
|
|
20348
20348
|
paths: ["framework_config"],
|
|
20349
|
-
template: `"{{path}}"
|
|
20349
|
+
template: `"{{path}}" loads Tailwind CSS through the Turbopack rule "@tailwindcss/turbopack", which the Webpack build on ohmyho.st ignores, and the application root has no PostCSS configuration that Webpack reads, so the site would deploy without its Tailwind classes. Add postcss.config.mjs to the application root with export default { plugins: { "@tailwindcss/postcss": {} } } and remove the Turbopack rule. Use the package manager to add @tailwindcss/postcss to devDependencies at the same version as tailwindcss and to remove @tailwindcss/turbopack, so the lockfile records both. ${PUSH_AND_PLAN}`
|
|
20350
20350
|
},
|
|
20351
20351
|
framework_version_unsupported: {
|
|
20352
20352
|
paths: ["manifest", "lockfile"],
|
|
@@ -22322,14 +22322,25 @@ var parseDevAccessTicket = (value) => {
|
|
|
22322
22322
|
return input;
|
|
22323
22323
|
};
|
|
22324
22324
|
var parseCurrentIdentity = (value) => {
|
|
22325
|
-
const input = exactRecord2(value, ["actor_id", "organization_ids"]);
|
|
22325
|
+
const input = exactRecord2(value, ["actor_id", "email", "organization_ids", "organizations"]);
|
|
22326
|
+
const email = input["email"];
|
|
22326
22327
|
const organizationIds = input["organization_ids"];
|
|
22328
|
+
const organizations = input["organizations"];
|
|
22327
22329
|
if (typeof input["actor_id"] !== "string" || input["actor_id"].length === 0 || input["actor_id"].length > 256 || [...input["actor_id"]].some((character) => {
|
|
22328
22330
|
const codePoint = character.codePointAt(0) ?? 0;
|
|
22329
22331
|
return codePoint <= 31 || codePoint === 127;
|
|
22330
|
-
}) || !Array.isArray(organizationIds) || organizationIds.some((organizationId) => !isUlid(organizationId)) || new Set(organizationIds).size !== organizationIds.length) {
|
|
22332
|
+
}) || email !== null && (!boundedString(email, 3, 254) || !/^[^\s@]+@[^\s@.]+(?:\.[^\s@.]+)+$/u.test(email) || /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(email)) || !Array.isArray(organizationIds) || organizationIds.some((organizationId) => !isUlid(organizationId)) || new Set(organizationIds).size !== organizationIds.length || !Array.isArray(organizations) || organizations.length !== organizationIds.length) {
|
|
22331
22333
|
throw new ResponseContractError();
|
|
22332
22334
|
}
|
|
22335
|
+
organizations.forEach((organization, index) => {
|
|
22336
|
+
const entry = exactRecord2(organization, ["id", "name"]);
|
|
22337
|
+
if (entry["id"] !== organizationIds[index] || !boundedString(entry["name"], 1, 128) || entry["name"].trim() !== entry["name"] || [...entry["name"]].some((character) => {
|
|
22338
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
22339
|
+
return codePoint <= 31 || codePoint === 127;
|
|
22340
|
+
})) {
|
|
22341
|
+
throw new ResponseContractError();
|
|
22342
|
+
}
|
|
22343
|
+
});
|
|
22333
22344
|
return input;
|
|
22334
22345
|
};
|
|
22335
22346
|
var parseAccountProfile = (value) => {
|
|
@@ -23221,7 +23232,7 @@ function exact3(v, keys) {
|
|
|
23221
23232
|
// apps/product-cli/package.json
|
|
23222
23233
|
var package_default2 = {
|
|
23223
23234
|
name: "@ohmyhost/product-cli",
|
|
23224
|
-
version: "0.1.
|
|
23235
|
+
version: "0.1.34",
|
|
23225
23236
|
private: true,
|
|
23226
23237
|
ohmyhost: {
|
|
23227
23238
|
deployment: "production",
|
|
@@ -24327,7 +24338,7 @@ var HELP_USAGE = Object.freeze({
|
|
|
24327
24338
|
"project flag set": "ohmyhost project flag set --project ULID --enabled true|false --idempotency-key KEY --json (shows the small Powered by ohmyho.st flag on the production site; while it shows, this project's custom domain uses no domain credits and also works on Free, and each Paid period bought through Stripe adds 250 credits to the workspace, however many projects show the flag)",
|
|
24328
24339
|
"project handle check": "ohmyhost project handle check --handle HANDLE --json (is this address free? answers with a reason and free alternatives; the address becomes HANDLE.check.omh.st)",
|
|
24329
24340
|
"project handle set": "ohmyhost project handle set --project ULID --handle HANDLE --if-match ETAG --idempotency-key KEY --json (moves the project to a free address; the old one stops working and anyone may claim it)",
|
|
24330
|
-
"database compute set": "ohmyhost database compute set --project ULID --environment dev|prod --profile standard|performance --idempotency-key KEY --yes [--wait] --json\n standard: Free 0.25 CU/1 GB
|
|
24341
|
+
"database compute set": "ohmyhost database compute set --project ULID --environment dev|prod --profile standard|performance --idempotency-key KEY --yes [--wait] --json\n standard: Free 0.25 CU/1 GB, Paid 0.5 CU/2 GB. performance: Paid 1 CU/4 GB, 2.5x database compute credits per equal active minute. All profiles use the provider-default idle suspension.",
|
|
24331
24342
|
"database compute get": "ohmyhost database compute get --project ULID [--environment dev|prod] --json",
|
|
24332
24343
|
"database write": "ohmyhost database write --project ULID --environment dev|prod --statement-file PATH --idempotency-key KEY [--parameters-json JSON] --yes --json",
|
|
24333
24344
|
"database query": "ohmyhost database query --project ULID --environment dev|prod --statement SQL [--parameters-json JSON] --json",
|
|
@@ -29147,7 +29158,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
29147
29158
|
});
|
|
29148
29159
|
registerManagedSourceTools(server, dependencies);
|
|
29149
29160
|
registerProductTool(server, dependencies, "database_compute_get", "Read current managed database size, memory, region and compute state without running SQL or waking the database. Shared Dev/Prod resolves to one physical database. A null database means no confirmed managed placement. suspend_timeout_seconds=0 uses the provider default; -1 disables scale to zero. A configured value is not proof that an in-progress resize finished. This read never resizes or changes billing.", external_exports.object({ project_id: identifier2, environment: external_exports.enum(["dev", "prod"]).default("dev") }), (client2, input) => client2.getDatabaseCompute({ projectId: input.project_id, environment: input.environment }));
|
|
29150
|
-
registerProductTool(server, dependencies, "database_compute_set", "Select standard or performance compute for an existing database: Free 0.25 CU/1 GB
|
|
29161
|
+
registerProductTool(server, dependencies, "database_compute_set", "Select standard or performance compute for an existing database: Free 0.25 CU/1 GB, Paid 0.5 CU/2 GB. All profiles use provider-default idle suspension (suspend_timeout_seconds=0). First read database_compute_get and explain actual size, metered compute cost, possible brief connection interruption and that shared data changes both Dev and Prod. Require the user's decision before confirm=true. SQL data is preserved. Poll the returned operation every 60 seconds; never submit a second change while it runs. Performance requires active Paid access and selects 1 CU/4 GB at 2.5x Paid-standard compute credits per equal active minute. This affects only database compute. Read organization_credits_get for the published rate and active meter first. A successful choice is remembered per physical database; automatic Free downgrades preserve it, and an explicit standard choice clears it. Mixed/uncertain transition hours waive the premium; never multiply raw CU usage again.", external_exports.object({
|
|
29151
29162
|
project_id: identifier2,
|
|
29152
29163
|
environment: external_exports.enum(["dev", "prod"]),
|
|
29153
29164
|
profile: external_exports.enum(["standard", "performance"]),
|
|
@@ -29411,7 +29422,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
29411
29422
|
});
|
|
29412
29423
|
return { revoked: true, key_id: input.key_id };
|
|
29413
29424
|
}, destructiveAnnotations());
|
|
29414
|
-
registerProductTool(server, dependencies, "identity_get", "Get the ohmyho.st customer/agent identity this call acts as: user, organization and, in context, the saved login or OHMYHOST_TOKEN that supplied it. Compare it with the user and organization the customer named before any change. This does not authenticate the hosted application's end users or provision a customer AuthKit tenant; application authentication is the customer's chosen integration.", external_exports.object({}), (client2, _input, signal) => client2.getCurrentIdentity(signal));
|
|
29425
|
+
registerProductTool(server, dependencies, "identity_get", "Get the ohmyho.st customer/agent identity this call acts as: user and account email, scoped organization IDs and names and, in context, the saved login or OHMYHOST_TOKEN that supplied it. Compare it with the user and organization the customer named before any change. This does not authenticate the hosted application's end users or provision a customer AuthKit tenant; application authentication is the customer's chosen integration.", external_exports.object({}), (client2, _input, signal) => client2.getCurrentIdentity(signal));
|
|
29415
29426
|
registerProductTool(server, dependencies, "project_handle_check", "Check whether a project address is free before offering it to the customer. A handle is one to five lowercase words of letters and digits joined by single hyphens, three to fifty-nine characters, and never a reserved word such as admin, api, dev or www; it becomes <handle>.check.omh.st for Prod and dev-<handle>.check.omh.st for Dev. The answer names why a handle cannot be used and returns free alternatives, so offer one of those instead of guessing again. Check the name here first, then move an existing project onto it with project_handle_set.", external_exports.object({ handle: external_exports.string().min(1).max(120) }), (client2, input) => client2.checkProjectHandle({ handle: input.handle }));
|
|
29416
29427
|
registerProductTool(server, dependencies, "project_handle_set", "Move a project to an address the customer chose, after project_handle_check said it is free. The Dev and Prod gateways are re-published at the new address and it is stored only once both serve it; the previous address stops answering and anyone may claim it, so a link already shared stops working. Needs the project's current ETag from project_status and one idempotency key; reuse the same key after an uncertain answer. Refused while another operation is running for the project, and refused for an address that is taken, unusable, or the one the project already has. Returns an operation to follow with operation_get.", external_exports.object({
|
|
29417
29428
|
project_id: identifier2,
|
|
@@ -29896,7 +29907,12 @@ function registerManagedSourceTools(server, dependencies) {
|
|
|
29896
29907
|
directory: input.directory,
|
|
29897
29908
|
metadataDirectory: resolveProductCliEnvironment(dependencies.environment).linkDirectory,
|
|
29898
29909
|
apiOrigin: client2.productApiOrigin ?? resolveProductCliEnvironment(dependencies.environment).apiOrigin,
|
|
29899
|
-
identity: {
|
|
29910
|
+
identity: {
|
|
29911
|
+
actor_id: current.actor_id,
|
|
29912
|
+
email: current.email,
|
|
29913
|
+
organization_ids: current.organization_ids,
|
|
29914
|
+
organizations: current.organizations
|
|
29915
|
+
},
|
|
29900
29916
|
projectId: input.project_id,
|
|
29901
29917
|
request,
|
|
29902
29918
|
explicitExpectedCommit: input.expected_commit_sha !== void 0,
|
|
@@ -29933,7 +29949,12 @@ function registerManagedSourceTools(server, dependencies) {
|
|
|
29933
29949
|
directory: input.directory,
|
|
29934
29950
|
metadataDirectory: resolveProductCliEnvironment(dependencies.environment).linkDirectory,
|
|
29935
29951
|
apiOrigin: client2.productApiOrigin ?? resolveProductCliEnvironment(dependencies.environment).apiOrigin,
|
|
29936
|
-
identity: {
|
|
29952
|
+
identity: {
|
|
29953
|
+
actor_id: current.actor_id,
|
|
29954
|
+
email: current.email,
|
|
29955
|
+
organization_ids: current.organization_ids,
|
|
29956
|
+
organizations: current.organizations
|
|
29957
|
+
},
|
|
29937
29958
|
projectId: input.project_id,
|
|
29938
29959
|
operationId: input.operation_id,
|
|
29939
29960
|
api: port(client2),
|
|
@@ -29993,7 +30014,9 @@ async function handoverAccount(client2, signal) {
|
|
|
29993
30014
|
const report = await client2.getCurrentIdentity(signal);
|
|
29994
30015
|
const identity = parseCurrentIdentity({
|
|
29995
30016
|
actor_id: report.actor_id,
|
|
29996
|
-
|
|
30017
|
+
email: report.email,
|
|
30018
|
+
organization_ids: report.organization_ids,
|
|
30019
|
+
organizations: report.organizations
|
|
29997
30020
|
});
|
|
29998
30021
|
const userId = identity.actor_id.startsWith("user:") ? identity.actor_id.slice(5) : "";
|
|
29999
30022
|
const [organizationId, ...others] = identity.organization_ids;
|
package/package.json
CHANGED
|
@@ -522,7 +522,7 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
|
|
|
522
522
|
server,
|
|
523
523
|
dependencies,
|
|
524
524
|
"database_compute_set",
|
|
525
|
-
"Select standard or performance compute for an existing database: Free 0.25 CU/1 GB
|
|
525
|
+
"Select standard or performance compute for an existing database: Free 0.25 CU/1 GB, Paid 0.5 CU/2 GB. All profiles use provider-default idle suspension (suspend_timeout_seconds=0). First read database_compute_get and explain actual size, metered compute cost, possible brief connection interruption and that shared data changes both Dev and Prod. Require the user's decision before confirm=true. SQL data is preserved. Poll the returned operation every 60 seconds; never submit a second change while it runs. Performance requires active Paid access and selects 1 CU/4 GB at 2.5x Paid-standard compute credits per equal active minute. This affects only database compute. Read organization_credits_get for the published rate and active meter first. A successful choice is remembered per physical database; automatic Free downgrades preserve it, and an explicit standard choice clears it. Mixed/uncertain transition hours waive the premium; never multiply raw CU usage again.",
|
|
526
526
|
z.object({
|
|
527
527
|
project_id: identifier,
|
|
528
528
|
environment: z.enum(["dev", "prod"]),
|
|
@@ -1119,7 +1119,7 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
|
|
|
1119
1119
|
server,
|
|
1120
1120
|
dependencies,
|
|
1121
1121
|
"identity_get",
|
|
1122
|
-
"Get the ohmyho.st customer/agent identity this call acts as: user, organization and, in context, the saved login or OHMYHOST_TOKEN that supplied it. Compare it with the user and organization the customer named before any change. This does not authenticate the hosted application's end users or provision a customer AuthKit tenant; application authentication is the customer's chosen integration.",
|
|
1122
|
+
"Get the ohmyho.st customer/agent identity this call acts as: user and account email, scoped organization IDs and names and, in context, the saved login or OHMYHOST_TOKEN that supplied it. Compare it with the user and organization the customer named before any change. This does not authenticate the hosted application's end users or provision a customer AuthKit tenant; application authentication is the customer's chosen integration.",
|
|
1123
1123
|
z.object({}),
|
|
1124
1124
|
(client, _input, signal) => client.getCurrentIdentity(signal),
|
|
1125
1125
|
);
|
|
@@ -2072,7 +2072,12 @@ function registerManagedSourceTools(
|
|
|
2072
2072
|
apiOrigin:
|
|
2073
2073
|
client.productApiOrigin ??
|
|
2074
2074
|
resolveProductCliEnvironment(dependencies.environment).apiOrigin,
|
|
2075
|
-
identity: {
|
|
2075
|
+
identity: {
|
|
2076
|
+
actor_id: current.actor_id,
|
|
2077
|
+
email: current.email,
|
|
2078
|
+
organization_ids: current.organization_ids,
|
|
2079
|
+
organizations: current.organizations,
|
|
2080
|
+
},
|
|
2076
2081
|
projectId: input.project_id,
|
|
2077
2082
|
request,
|
|
2078
2083
|
explicitExpectedCommit: input.expected_commit_sha !== undefined,
|
|
@@ -2120,7 +2125,12 @@ function registerManagedSourceTools(
|
|
|
2120
2125
|
apiOrigin:
|
|
2121
2126
|
client.productApiOrigin ??
|
|
2122
2127
|
resolveProductCliEnvironment(dependencies.environment).apiOrigin,
|
|
2123
|
-
identity: {
|
|
2128
|
+
identity: {
|
|
2129
|
+
actor_id: current.actor_id,
|
|
2130
|
+
email: current.email,
|
|
2131
|
+
organization_ids: current.organization_ids,
|
|
2132
|
+
organizations: current.organizations,
|
|
2133
|
+
},
|
|
2124
2134
|
projectId: input.project_id,
|
|
2125
2135
|
operationId: input.operation_id,
|
|
2126
2136
|
api: port(client),
|
|
@@ -2235,7 +2245,9 @@ async function handoverAccount(
|
|
|
2235
2245
|
const report = await client.getCurrentIdentity(signal);
|
|
2236
2246
|
const identity = parseCurrentIdentity({
|
|
2237
2247
|
actor_id: report.actor_id,
|
|
2248
|
+
email: report.email,
|
|
2238
2249
|
organization_ids: report.organization_ids,
|
|
2250
|
+
organizations: report.organizations,
|
|
2239
2251
|
});
|
|
2240
2252
|
const userId = identity.actor_id.startsWith("user:") ? identity.actor_id.slice(5) : "";
|
|
2241
2253
|
const [organizationId, ...others] = identity.organization_ids;
|
|
@@ -399,7 +399,7 @@ const HELP_USAGE = Object.freeze({
|
|
|
399
399
|
"ohmyhost project handle set --project ULID --handle HANDLE --if-match ETAG --idempotency-key KEY --json (moves the project to a free address; the old one stops working and anyone may claim it)",
|
|
400
400
|
"database compute set":
|
|
401
401
|
"ohmyhost database compute set --project ULID --environment dev|prod --profile standard|performance --idempotency-key KEY --yes [--wait] --json\n" +
|
|
402
|
-
" standard: Free 0.25 CU/1 GB
|
|
402
|
+
" standard: Free 0.25 CU/1 GB, Paid 0.5 CU/2 GB. performance: Paid 1 CU/4 GB, 2.5x database compute credits per equal active minute. All profiles use the provider-default idle suspension.",
|
|
403
403
|
"database compute get":
|
|
404
404
|
"ohmyhost database compute get --project ULID [--environment dev|prod] --json",
|
|
405
405
|
"database write":
|
|
@@ -63,7 +63,9 @@ export interface SafeProblem {
|
|
|
63
63
|
|
|
64
64
|
export interface PublicCurrentIdentity {
|
|
65
65
|
readonly actor_id: string;
|
|
66
|
+
readonly email: string | null;
|
|
66
67
|
readonly organization_ids: readonly string[];
|
|
68
|
+
readonly organizations: readonly { readonly id: string; readonly name: string }[];
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
/** One workspace the signed-in user belongs to, with the provider identity a selection needs. */
|
|
@@ -635,8 +637,10 @@ export function parseProjectCreditBudget(value: unknown): ProjectCreditBudget {
|
|
|
635
637
|
}
|
|
636
638
|
|
|
637
639
|
export const parseCurrentIdentity = (value: unknown): PublicCurrentIdentity => {
|
|
638
|
-
const input = exactRecord(value, ["actor_id", "organization_ids"]);
|
|
640
|
+
const input = exactRecord(value, ["actor_id", "email", "organization_ids", "organizations"]);
|
|
641
|
+
const email = input["email"];
|
|
639
642
|
const organizationIds = input["organization_ids"];
|
|
643
|
+
const organizations = input["organizations"];
|
|
640
644
|
if (
|
|
641
645
|
typeof input["actor_id"] !== "string" ||
|
|
642
646
|
input["actor_id"].length === 0 ||
|
|
@@ -645,12 +649,32 @@ export const parseCurrentIdentity = (value: unknown): PublicCurrentIdentity => {
|
|
|
645
649
|
const codePoint = character.codePointAt(0) ?? 0;
|
|
646
650
|
return codePoint <= 31 || codePoint === 127;
|
|
647
651
|
}) ||
|
|
652
|
+
(email !== null &&
|
|
653
|
+
(!boundedString(email, 3, 254) ||
|
|
654
|
+
!/^[^\s@]+@[^\s@.]+(?:\.[^\s@.]+)+$/u.test(email) ||
|
|
655
|
+
/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(email))) ||
|
|
648
656
|
!Array.isArray(organizationIds) ||
|
|
649
657
|
organizationIds.some((organizationId) => !isUlid(organizationId)) ||
|
|
650
|
-
new Set(organizationIds).size !== organizationIds.length
|
|
658
|
+
new Set(organizationIds).size !== organizationIds.length ||
|
|
659
|
+
!Array.isArray(organizations) ||
|
|
660
|
+
organizations.length !== organizationIds.length
|
|
651
661
|
) {
|
|
652
662
|
throw new ResponseContractError();
|
|
653
663
|
}
|
|
664
|
+
organizations.forEach((organization: unknown, index) => {
|
|
665
|
+
const entry = exactRecord(organization, ["id", "name"]);
|
|
666
|
+
if (
|
|
667
|
+
entry["id"] !== organizationIds[index] ||
|
|
668
|
+
!boundedString(entry["name"], 1, 128) ||
|
|
669
|
+
entry["name"].trim() !== entry["name"] ||
|
|
670
|
+
[...entry["name"]].some((character) => {
|
|
671
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
672
|
+
return codePoint <= 31 || codePoint === 127;
|
|
673
|
+
})
|
|
674
|
+
) {
|
|
675
|
+
throw new ResponseContractError();
|
|
676
|
+
}
|
|
677
|
+
});
|
|
654
678
|
return input as unknown as PublicCurrentIdentity;
|
|
655
679
|
};
|
|
656
680
|
|