@caplets/core 0.25.0 → 0.26.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/dist/caplet-source.js +26 -23
- package/dist/cli/auth.d.ts +1 -0
- package/dist/cli/commands.d.ts +6 -1
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/vault.d.ts +7 -0
- package/dist/cloud/client.d.ts +59 -0
- package/dist/code-mode/platform-runtime.generated.d.ts +1 -1
- package/dist/code-mode.js +6 -6
- package/dist/{completion-DrPr2vYw.js → completion-DaYL-XQN.js} +28 -12
- package/dist/config-runtime.js +2 -2
- package/dist/config.d.ts +39 -6
- package/dist/daemon/validation.d.ts +1 -0
- package/dist/engine.d.ts +6 -2
- package/dist/generated-tool-input-schema.js +1 -1
- package/dist/index.js +517 -58
- package/dist/native.js +1 -1
- package/dist/observed-output-shapes/pure.js +1 -1
- package/dist/{observed-output-shapes-D2k2-q8K.js → observed-output-shapes-DuP7mJQf.js} +1 -1
- package/dist/observed-output-shapes.js +1 -1
- package/dist/remote-control/types.d.ts +1 -1
- package/dist/{schemas-C0PNPwjS.js → schemas-BoqMu4MG.js} +11 -8
- package/dist/{service-DjwB8aiW.js → service-rvZ7z6FI.js} +790 -110
- package/dist/{validation-DgxCzt-A.js → validation-C4tYXw6G.js} +1 -1
- package/dist/vault/access.d.ts +5 -0
- package/dist/vault/crypto.d.ts +19 -0
- package/dist/vault/index.d.ts +40 -0
- package/dist/vault/keys.d.ts +15 -0
- package/dist/vault/store.d.ts +4 -0
- package/dist/vault/types.d.ts +68 -0
- package/package.json +1 -1
package/dist/caplet-source.js
CHANGED
|
@@ -770,7 +770,7 @@ function collectionFromPath(schema, path, value) {
|
|
|
770
770
|
const a = [];
|
|
771
771
|
a[k] = v;
|
|
772
772
|
v = a;
|
|
773
|
-
} else v = new Map([[k, v]]);
|
|
773
|
+
} else v = /* @__PURE__ */ new Map([[k, v]]);
|
|
774
774
|
}
|
|
775
775
|
return createNode(v, void 0, {
|
|
776
776
|
aliasDuplicateObjects: false,
|
|
@@ -1304,7 +1304,7 @@ function stringify(item, ctx, onComment, onChompKeep) {
|
|
|
1304
1304
|
if (ctx.resolvedAliases?.has(item)) throw new TypeError(`Cannot stringify circular structure without alias nodes`);
|
|
1305
1305
|
else {
|
|
1306
1306
|
if (ctx.resolvedAliases) ctx.resolvedAliases.add(item);
|
|
1307
|
-
else ctx.resolvedAliases = new Set([item]);
|
|
1307
|
+
else ctx.resolvedAliases = /* @__PURE__ */ new Set([item]);
|
|
1308
1308
|
item = item.resolve(ctx.doc);
|
|
1309
1309
|
}
|
|
1310
1310
|
}
|
|
@@ -2494,7 +2494,7 @@ const schema = [
|
|
|
2494
2494
|
];
|
|
2495
2495
|
//#endregion
|
|
2496
2496
|
//#region ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/browser/dist/schema/tags.js
|
|
2497
|
-
const schemas = new Map([
|
|
2497
|
+
const schemas = /* @__PURE__ */ new Map([
|
|
2498
2498
|
["core", schema$2],
|
|
2499
2499
|
["failsafe", [
|
|
2500
2500
|
map,
|
|
@@ -5878,7 +5878,10 @@ function assignProp(target, prop, value) {
|
|
|
5878
5878
|
}
|
|
5879
5879
|
function mergeDefs(...defs) {
|
|
5880
5880
|
const mergedDescriptors = {};
|
|
5881
|
-
for (const def of defs)
|
|
5881
|
+
for (const def of defs) {
|
|
5882
|
+
const descriptors = Object.getOwnPropertyDescriptors(def);
|
|
5883
|
+
Object.assign(mergedDescriptors, descriptors);
|
|
5884
|
+
}
|
|
5882
5885
|
return Object.defineProperties({}, mergedDescriptors);
|
|
5883
5886
|
}
|
|
5884
5887
|
function esc(str) {
|
|
@@ -7309,13 +7312,13 @@ const $ZodObject = /*@__PURE__*/ $constructor("$ZodObject", (inst, def) => {
|
|
|
7309
7312
|
}
|
|
7310
7313
|
return propValues;
|
|
7311
7314
|
});
|
|
7312
|
-
const isObject$
|
|
7315
|
+
const isObject$2 = isObject;
|
|
7313
7316
|
const catchall = def.catchall;
|
|
7314
7317
|
let value;
|
|
7315
7318
|
inst._zod.parse = (payload, ctx) => {
|
|
7316
7319
|
value ?? (value = _normalized.value);
|
|
7317
7320
|
const input = payload.value;
|
|
7318
|
-
if (!isObject$
|
|
7321
|
+
if (!isObject$2(input)) {
|
|
7319
7322
|
payload.issues.push({
|
|
7320
7323
|
expected: "object",
|
|
7321
7324
|
code: "invalid_type",
|
|
@@ -7438,7 +7441,7 @@ const $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
7438
7441
|
return (payload, ctx) => fn(shape, payload, ctx);
|
|
7439
7442
|
};
|
|
7440
7443
|
let fastpass;
|
|
7441
|
-
const isObject$
|
|
7444
|
+
const isObject$1 = isObject;
|
|
7442
7445
|
const jit = !globalConfig.jitless;
|
|
7443
7446
|
const fastEnabled = jit && allowsEval.value;
|
|
7444
7447
|
const catchall = def.catchall;
|
|
@@ -7446,7 +7449,7 @@ const $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
7446
7449
|
inst._zod.parse = (payload, ctx) => {
|
|
7447
7450
|
value ?? (value = _normalized.value);
|
|
7448
7451
|
const input = payload.value;
|
|
7449
|
-
if (!isObject$
|
|
7452
|
+
if (!isObject$1(input)) {
|
|
7450
7453
|
payload.issues.push({
|
|
7451
7454
|
expected: "object",
|
|
7452
7455
|
code: "invalid_type",
|
|
@@ -7848,7 +7851,7 @@ const $ZodOptional = /*@__PURE__*/ $constructor("$ZodOptional", (inst, def) => {
|
|
|
7848
7851
|
inst._zod.optin = "optional";
|
|
7849
7852
|
inst._zod.optout = "optional";
|
|
7850
7853
|
defineLazy(inst._zod, "values", () => {
|
|
7851
|
-
return def.innerType._zod.values ? new Set([...def.innerType._zod.values, void 0]) : void 0;
|
|
7854
|
+
return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, void 0]) : void 0;
|
|
7852
7855
|
});
|
|
7853
7856
|
defineLazy(inst._zod, "pattern", () => {
|
|
7854
7857
|
const pattern = def.innerType._zod.pattern;
|
|
@@ -7882,7 +7885,7 @@ const $ZodNullable = /*@__PURE__*/ $constructor("$ZodNullable", (inst, def) => {
|
|
|
7882
7885
|
return pattern ? new RegExp(`^(${cleanRegex(pattern.source)}|null)$`) : void 0;
|
|
7883
7886
|
});
|
|
7884
7887
|
defineLazy(inst._zod, "values", () => {
|
|
7885
|
-
return def.innerType._zod.values ? new Set([...def.innerType._zod.values, null]) : void 0;
|
|
7888
|
+
return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, null]) : void 0;
|
|
7886
7889
|
});
|
|
7887
7890
|
inst._zod.parse = (payload, ctx) => {
|
|
7888
7891
|
if (payload.value === null) return payload;
|
|
@@ -10030,7 +10033,7 @@ function superRefine(fn, params) {
|
|
|
10030
10033
|
const SERVER_ID_PATTERN = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
10031
10034
|
const HEADER_NAME_PATTERN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
10032
10035
|
const HTTP_BASE_URL_PATTERN = /^(?![a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^/?#]*@)[^?#]*$/;
|
|
10033
|
-
const FORBIDDEN_HEADERS = new Set([
|
|
10036
|
+
const FORBIDDEN_HEADERS = /* @__PURE__ */ new Set([
|
|
10034
10037
|
"accept",
|
|
10035
10038
|
"authorization",
|
|
10036
10039
|
"connection",
|
|
@@ -10240,7 +10243,7 @@ const capletMcpServerSchema = object({
|
|
|
10240
10243
|
path: ["url"],
|
|
10241
10244
|
message: "remote servers require url"
|
|
10242
10245
|
});
|
|
10243
|
-
if (server.url && !
|
|
10246
|
+
if (server.url && !hasInterpolationReference(server.url) && !isAllowedRemoteUrl(server.url)) ctx.addIssue({
|
|
10244
10247
|
code: "custom",
|
|
10245
10248
|
path: ["url"],
|
|
10246
10249
|
message: "remote url must use https except loopback development urls"
|
|
@@ -10253,7 +10256,7 @@ const capletMcpServerSchema = object({
|
|
|
10253
10256
|
"redirectUri"
|
|
10254
10257
|
]) {
|
|
10255
10258
|
const value = server.auth[field];
|
|
10256
|
-
if (value && !
|
|
10259
|
+
if (value && !hasInterpolationReference(value) && !isUrl(value)) ctx.addIssue({
|
|
10257
10260
|
code: "custom",
|
|
10258
10261
|
path: ["auth", field],
|
|
10259
10262
|
message: `${field} must be a URL or environment reference`
|
|
@@ -10287,12 +10290,12 @@ const capletOpenApiEndpointSchema = object({
|
|
|
10287
10290
|
code: "custom",
|
|
10288
10291
|
message: "openapiEndpoint must define exactly one spec source: specPath or specUrl"
|
|
10289
10292
|
});
|
|
10290
|
-
if (endpoint.specUrl && !
|
|
10293
|
+
if (endpoint.specUrl && !hasInterpolationReference(endpoint.specUrl) && !isAllowedRemoteUrl(endpoint.specUrl)) ctx.addIssue({
|
|
10291
10294
|
code: "custom",
|
|
10292
10295
|
path: ["specUrl"],
|
|
10293
10296
|
message: "OpenAPI specUrl must use https except loopback development urls"
|
|
10294
10297
|
});
|
|
10295
|
-
if (endpoint.baseUrl && !
|
|
10298
|
+
if (endpoint.baseUrl && !hasInterpolationReference(endpoint.baseUrl) && !isAllowedRemoteUrl(endpoint.baseUrl)) ctx.addIssue({
|
|
10296
10299
|
code: "custom",
|
|
10297
10300
|
path: ["baseUrl"],
|
|
10298
10301
|
message: "OpenAPI baseUrl must use https except loopback development urls"
|
|
@@ -10317,12 +10320,12 @@ const capletGoogleDiscoveryApiSchema = object({
|
|
|
10317
10320
|
code: "custom",
|
|
10318
10321
|
message: "googleDiscoveryApi must define exactly one discovery source: discoveryPath or discoveryUrl"
|
|
10319
10322
|
});
|
|
10320
|
-
if (api.discoveryUrl && !
|
|
10323
|
+
if (api.discoveryUrl && !hasInterpolationReference(api.discoveryUrl) && !isAllowedRemoteUrl(api.discoveryUrl)) ctx.addIssue({
|
|
10321
10324
|
code: "custom",
|
|
10322
10325
|
path: ["discoveryUrl"],
|
|
10323
10326
|
message: "Google Discovery discoveryUrl must use https except loopback development urls"
|
|
10324
10327
|
});
|
|
10325
|
-
if (api.baseUrl && !
|
|
10328
|
+
if (api.baseUrl && !hasInterpolationReference(api.baseUrl) && !isAllowedHttpBaseUrl(api.baseUrl)) ctx.addIssue({
|
|
10326
10329
|
code: "custom",
|
|
10327
10330
|
path: ["baseUrl"],
|
|
10328
10331
|
message: "Google Discovery baseUrl must use https except loopback development urls and must not include credentials, query, or fragment"
|
|
@@ -10359,12 +10362,12 @@ const capletGraphQlEndpointSchema = object({
|
|
|
10359
10362
|
code: "custom",
|
|
10360
10363
|
message: "graphqlEndpoint must define exactly one schema source: schemaPath, schemaUrl, or introspection"
|
|
10361
10364
|
});
|
|
10362
|
-
if (endpoint.endpointUrl && !
|
|
10365
|
+
if (endpoint.endpointUrl && !hasInterpolationReference(endpoint.endpointUrl) && !isAllowedRemoteUrl(endpoint.endpointUrl)) ctx.addIssue({
|
|
10363
10366
|
code: "custom",
|
|
10364
10367
|
path: ["endpointUrl"],
|
|
10365
10368
|
message: "GraphQL endpointUrl must use https except loopback development urls"
|
|
10366
10369
|
});
|
|
10367
|
-
if (endpoint.schemaUrl && !
|
|
10370
|
+
if (endpoint.schemaUrl && !hasInterpolationReference(endpoint.schemaUrl) && !isAllowedRemoteUrl(endpoint.schemaUrl)) ctx.addIssue({
|
|
10368
10371
|
code: "custom",
|
|
10369
10372
|
path: ["schemaUrl"],
|
|
10370
10373
|
message: "GraphQL schemaUrl must use https except loopback development urls"
|
|
@@ -10408,7 +10411,7 @@ const capletHttpApiSchema = object({
|
|
|
10408
10411
|
projectBinding: capletProjectBindingSchema.optional(),
|
|
10409
10412
|
runtime: capletRuntimeRequirementsSchema.optional()
|
|
10410
10413
|
}).strict().superRefine((api, ctx) => {
|
|
10411
|
-
if (api.baseUrl && !
|
|
10414
|
+
if (api.baseUrl && !hasInterpolationReference(api.baseUrl) && !isAllowedHttpBaseUrl(api.baseUrl)) ctx.addIssue({
|
|
10412
10415
|
code: "custom",
|
|
10413
10416
|
path: ["baseUrl"],
|
|
10414
10417
|
message: "HTTP API baseUrl must use https except loopback development urls and must not include credentials, query, or fragment"
|
|
@@ -10713,7 +10716,7 @@ function normalizeGraphQlOperations(operations, baseDir, normalizePath) {
|
|
|
10713
10716
|
}]));
|
|
10714
10717
|
}
|
|
10715
10718
|
function normalizeBundleLocalPath(value, baseDir) {
|
|
10716
|
-
if (!value || isMapAbsolutePath(value) ||
|
|
10719
|
+
if (!value || isMapAbsolutePath(value) || hasInterpolationReference(value)) return value;
|
|
10717
10720
|
const parts = [...baseDir ? baseDir.split("/") : [], ...value.split("/")];
|
|
10718
10721
|
const normalized = [];
|
|
10719
10722
|
for (const part of parts) {
|
|
@@ -10793,8 +10796,8 @@ function validateCapletId(id, path) {
|
|
|
10793
10796
|
function errorMessage$1(error) {
|
|
10794
10797
|
return error instanceof Error ? error.message : String(error);
|
|
10795
10798
|
}
|
|
10796
|
-
function
|
|
10797
|
-
return /\$\{[A-Za-z_][A-Za-z0-9_]*\}|\$env:[A-Za-z_][A-Za-z0-9_]
|
|
10799
|
+
function hasInterpolationReference(value) {
|
|
10800
|
+
return /\$\{[A-Za-z_][A-Za-z0-9_]*\}|\$env:[A-Za-z_][A-Za-z0-9_]*|\$\{vault:[^}]+\}|\$vault:[A-Za-z0-9_-]+/.test(value);
|
|
10798
10801
|
}
|
|
10799
10802
|
//#endregion
|
|
10800
10803
|
//#region src/config-runtime.ts
|
package/dist/cli/auth.d.ts
CHANGED
|
@@ -70,6 +70,7 @@ export declare function localAuthTargets(options: {
|
|
|
70
70
|
})[];
|
|
71
71
|
export declare function localAuthConfigForTarget(options: {
|
|
72
72
|
serverId: string;
|
|
73
|
+
authDir?: string | undefined;
|
|
73
74
|
configPath?: string;
|
|
74
75
|
projectConfigPath?: string;
|
|
75
76
|
source: Exclude<AuthSource, "remote">;
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -31,8 +31,9 @@ export declare const cliCommands: {
|
|
|
31
31
|
readonly complete: "complete";
|
|
32
32
|
readonly config: "config";
|
|
33
33
|
readonly auth: "auth";
|
|
34
|
+
readonly vault: "vault";
|
|
34
35
|
};
|
|
35
|
-
export declare const topLevelCommandNames: readonly ["serve", "daemon", "code-mode", "attach", "remote", "cloud", "init", "setup", "doctor", "list", "install", "add", "inspect", "check-backend", "list-tools", "search-tools", "get-tool", "call-tool", "list-resources", "search-resources", "list-resource-templates", "read-resource", "list-prompts", "search-prompts", "get-prompt", "complete", "config", "auth", "completion"];
|
|
36
|
+
export declare const topLevelCommandNames: readonly ["serve", "daemon", "code-mode", "attach", "remote", "cloud", "init", "setup", "doctor", "list", "install", "add", "inspect", "check-backend", "list-tools", "search-tools", "get-tool", "call-tool", "list-resources", "search-resources", "list-resource-templates", "read-resource", "list-prompts", "search-prompts", "get-prompt", "complete", "config", "auth", "vault", "completion"];
|
|
36
37
|
export declare const cliSubcommands: {
|
|
37
38
|
readonly add: readonly ["cli", "mcp", "openapi", "google-discovery", "graphql", "http"];
|
|
38
39
|
readonly auth: readonly ["login", "logout", "list", "refresh"];
|
|
@@ -43,11 +44,15 @@ export declare const cliSubcommands: {
|
|
|
43
44
|
readonly config: readonly ["path", "paths"];
|
|
44
45
|
readonly daemon: readonly ["install", "uninstall", "start", "restart", "stop", "status", "logs"];
|
|
45
46
|
readonly setup: readonly ["codex", "claude-code", "opencode", "pi", "mcp-client"];
|
|
47
|
+
readonly vault: readonly ["set", "get", "list", "delete", "access"];
|
|
46
48
|
};
|
|
47
49
|
export declare const cliNestedSubcommands: {
|
|
48
50
|
readonly remote: {
|
|
49
51
|
readonly host: readonly ["pair", "clients", "revoke"];
|
|
50
52
|
};
|
|
53
|
+
readonly vault: {
|
|
54
|
+
readonly access: readonly ["grant", "list", "revoke"];
|
|
55
|
+
};
|
|
51
56
|
};
|
|
52
57
|
export declare const capletIdCommands: Set<string>;
|
|
53
58
|
export declare const qualifiedToolCommands: Set<string>;
|
package/dist/cli/doctor.d.ts
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { VaultAccessGrant, VaultDeleteStatus, VaultValueStatus } from "../vault";
|
|
2
|
+
export declare function formatVaultValueStatus(status: VaultValueStatus, json?: boolean): string;
|
|
3
|
+
export declare function formatVaultValueList(statuses: VaultValueStatus[], json?: boolean): string;
|
|
4
|
+
export declare function formatVaultDeleteStatus(status: VaultDeleteStatus, json?: boolean): string;
|
|
5
|
+
export declare function formatVaultAccessGrant(grant: VaultAccessGrant, json?: boolean): string;
|
|
6
|
+
export declare function formatVaultAccessList(grants: VaultAccessGrant[], json?: boolean): string;
|
|
7
|
+
export declare function formatVaultAccessRevoke(count: number, json?: boolean): string;
|
package/dist/cloud/client.d.ts
CHANGED
|
@@ -17,6 +17,49 @@ export type RegisterPresenceResult = {
|
|
|
17
17
|
expiresAt: string;
|
|
18
18
|
};
|
|
19
19
|
export type HeartbeatPresenceResult = RegisterPresenceResult;
|
|
20
|
+
export type CloudVaultValueStatus = {
|
|
21
|
+
key: string;
|
|
22
|
+
present: boolean;
|
|
23
|
+
valueBytes?: number | undefined;
|
|
24
|
+
createdAt?: string | undefined;
|
|
25
|
+
updatedAt?: string | undefined;
|
|
26
|
+
};
|
|
27
|
+
export type CloudVaultAccessGrant = {
|
|
28
|
+
storedKey: string;
|
|
29
|
+
referenceName: string;
|
|
30
|
+
capletId: string;
|
|
31
|
+
origin?: {
|
|
32
|
+
kind: string;
|
|
33
|
+
path: string;
|
|
34
|
+
} | undefined;
|
|
35
|
+
createdAt?: string | undefined;
|
|
36
|
+
updatedAt?: string | undefined;
|
|
37
|
+
};
|
|
38
|
+
export type CloudVaultSetInput = {
|
|
39
|
+
workspace: string;
|
|
40
|
+
name: string;
|
|
41
|
+
value: string;
|
|
42
|
+
force?: boolean | undefined;
|
|
43
|
+
grant?: string | undefined;
|
|
44
|
+
referenceName?: string | undefined;
|
|
45
|
+
};
|
|
46
|
+
export type CloudVaultNameInput = {
|
|
47
|
+
workspace: string;
|
|
48
|
+
name: string;
|
|
49
|
+
};
|
|
50
|
+
export type CloudVaultGetInput = CloudVaultNameInput & {
|
|
51
|
+
reveal?: boolean | undefined;
|
|
52
|
+
revealContext?: "human-cli" | undefined;
|
|
53
|
+
};
|
|
54
|
+
export type CloudVaultAccessGrantInput = CloudVaultNameInput & {
|
|
55
|
+
capletId: string;
|
|
56
|
+
referenceName?: string | undefined;
|
|
57
|
+
};
|
|
58
|
+
export type CloudVaultAccessListInput = {
|
|
59
|
+
workspace: string;
|
|
60
|
+
name?: string | undefined;
|
|
61
|
+
capletId?: string | undefined;
|
|
62
|
+
};
|
|
20
63
|
export declare class CapletsCloudClient {
|
|
21
64
|
private readonly options;
|
|
22
65
|
private readonly fetchImpl;
|
|
@@ -25,6 +68,22 @@ export declare class CapletsCloudClient {
|
|
|
25
68
|
stopPresence(presenceId: string): Promise<void>;
|
|
26
69
|
heartbeatPresence(presenceId: string): Promise<HeartbeatPresenceResult>;
|
|
27
70
|
updatePresenceCaplets(presenceId: string, allowedCapletIds: string[]): Promise<void>;
|
|
71
|
+
setVaultValue(input: CloudVaultSetInput): Promise<CloudVaultValueStatus>;
|
|
72
|
+
getVaultValue(input: CloudVaultGetInput): Promise<CloudVaultValueStatus | {
|
|
73
|
+
key: string;
|
|
74
|
+
value: string;
|
|
75
|
+
}>;
|
|
76
|
+
listVaultValues(input: {
|
|
77
|
+
workspace: string;
|
|
78
|
+
}): Promise<CloudVaultValueStatus[]>;
|
|
79
|
+
deleteVaultValue(input: CloudVaultNameInput): Promise<{
|
|
80
|
+
key: string;
|
|
81
|
+
deleted: boolean;
|
|
82
|
+
grantsRetained?: number | undefined;
|
|
83
|
+
}>;
|
|
84
|
+
grantVaultAccess(input: CloudVaultAccessGrantInput): Promise<CloudVaultAccessGrant>;
|
|
85
|
+
listVaultAccess(input: CloudVaultAccessListInput): Promise<CloudVaultAccessGrant[]>;
|
|
86
|
+
revokeVaultAccess(input: CloudVaultAccessGrantInput): Promise<CloudVaultAccessGrant[]>;
|
|
28
87
|
private headers;
|
|
29
88
|
private endpoint;
|
|
30
89
|
}
|