@vectros-ai/mcp-server 0.12.0 → 0.13.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 +37 -0
- package/README.md +2 -2
- package/dist/cli-http.js +160 -34
- package/dist/cli-http.js.map +1 -1
- package/dist/cli-http.mjs +160 -34
- package/dist/cli-http.mjs.map +1 -1
- package/dist/cli.js +160 -34
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +160 -34
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +160 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +160 -34
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2455,7 +2455,7 @@ var AuthClient = class {
|
|
|
2455
2455
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/admin/access-log");
|
|
2456
2456
|
}
|
|
2457
2457
|
/**
|
|
2458
|
-
* Lists
|
|
2458
|
+
* Lists your scoped API keys (`ssk_*`) in your credential's own environment — a live key lists live keys, a test key lists test keys. Revoked keys are excluded. Requires the `keys:r` scope.
|
|
2459
2459
|
*
|
|
2460
2460
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
2461
2461
|
*
|
|
@@ -2838,7 +2838,7 @@ var AuthClient = class {
|
|
|
2838
2838
|
);
|
|
2839
2839
|
}
|
|
2840
2840
|
/**
|
|
2841
|
-
* Creates a new access profile under the given app context. This call is idempotent by `principalId`: if a profile with the same `principalId` already exists, the existing profile is returned (with status 200) instead of creating a duplicate. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing profile was returned) tells the two apart. To overwrite an existing profile's `scopes`/`roleId`, `identityOverrides`, and `status` instead of returning it unchanged, set `?upsert=true` (this also requires the `profiles:u` scope). You must provide exactly one of `scopes` (an inline list of scopes) or `roleId` (a reference to a role); supplying both, or neither, is rejected. `identityOverrides` is keyed by ownership namespace in `scope:<namespace>` form — `scope:org` and `scope:client` for the reserved namespaces, or any namespace you have registered — and may name at most two; any other key (including the account identifier or `userId`) is rejected. If you use a scoped credential, the profile's effective scopes may not exceed your own; a root API key (`sk_`) is exempt. Requires the `profiles:c` scope.
|
|
2841
|
+
* Creates a new access profile under the given app context. This call is idempotent by `principalId`: if a profile with the same `principalId` already exists, the existing profile is returned (with status 200) instead of creating a duplicate. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing profile was returned) tells the two apart. To overwrite an existing profile's `scopes`/`roleId`, `identityOverrides`, and `status` instead of returning it unchanged, set `?upsert=true` (this also requires the `profiles:u` scope, and applies the same `identityOverrides` bounds the update endpoint documents — a scoped credential may not repoint or clear an identity value it does not itself hold). You must provide exactly one of `scopes` (an inline list of scopes) or `roleId` (a reference to a role); supplying both, or neither, is rejected. `identityOverrides` is keyed by ownership namespace in `scope:<namespace>` form — `scope:org` and `scope:client` for the reserved namespaces, or any namespace you have registered — and may name at most two; any other key (including the account identifier or `userId`) is rejected. If you use a scoped credential, the profile's effective scopes may not exceed your own; a root API key (`sk_`) is exempt. Requires the `profiles:c` scope.
|
|
2842
2842
|
*
|
|
2843
2843
|
* @param {Vectros.CreateAccessProfileRequest} request
|
|
2844
2844
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -3256,7 +3256,7 @@ var AuthClient = class {
|
|
|
3256
3256
|
);
|
|
3257
3257
|
}
|
|
3258
3258
|
/**
|
|
3259
|
-
* Updates an access profile. This is a partial update: any field you omit (or send as null) keeps its existing value. A profile must reference either inline `scopes` or a `roleId`, never both — so setting `scopes` clears any `roleId`, and setting `roleId` clears any inline `scopes`. The `contextId` and `principalId` are immutable. Status changes (for example active to suspended) take effect within about five minutes. If you use a scoped credential, the profile's effective scopes may not exceed your own
|
|
3259
|
+
* Updates an access profile. This is a partial update: any field you omit (or send as null) keeps its existing value. A profile must reference either inline `scopes` or a `roleId`, never both — so setting `scopes` clears any `roleId`, and setting `roleId` clears any inline `scopes`. The `contextId` and `principalId` are immutable. Status changes (for example active to suspended) take effect within about five minutes. If you use a scoped credential, the profile's effective scopes may not exceed your own, and its `identityOverrides` are bounded twice: you may only set a value your own identity holds, and you may only change or clear a value the profile already holds if that value is yours as well. Repointing or clearing another principal's established identity therefore returns 403. A root API key (`sk_`) is exempt. Requires the `profiles:u` scope.
|
|
3260
3260
|
*
|
|
3261
3261
|
* @param {Vectros.UpdateAccessProfileRequest} request
|
|
3262
3262
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -3329,7 +3329,7 @@ var AuthClient = class {
|
|
|
3329
3329
|
);
|
|
3330
3330
|
}
|
|
3331
3331
|
/**
|
|
3332
|
-
* Deletes an access profile. Within about five minutes (the access-profile cache lifetime), token minting for this principal in this context will be denied. Requires the `profiles:d` scope.
|
|
3332
|
+
* Deletes an access profile. Within about five minutes (the access-profile cache lifetime), token minting for this principal in this context will be denied. If you use a scoped credential and the profile carries `identityOverrides`, you may only delete it when you hold those values yourself — deleting a profile removes its identity, so the same bound applies as when clearing it. A profile with no `identityOverrides` is unaffected, and a root API key (`sk_`) is exempt. Requires the `profiles:d` scope.
|
|
3333
3333
|
*
|
|
3334
3334
|
* @param {Vectros.DeleteAccessProfileRequest} request
|
|
3335
3335
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4183,7 +4183,7 @@ var AuthClient = class {
|
|
|
4183
4183
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/auth/token");
|
|
4184
4184
|
}
|
|
4185
4185
|
/**
|
|
4186
|
-
* Invite a new member to one of your app contexts by email. Creates a pending user with a pre-resolved access profile (their permissions on accept) and signs an invitation token. This call is idempotent on the combination of context and email: re-inviting the same email in the same context rotates the token and resends the invitation rather than creating a duplicate. Returns HTTP 201 on a new invite or a successful resend. Returns 409 if that email already belongs to an active or suspended member of the app context, or already has an identity elsewhere in your account (an email can currently belong to only one tenant per account, i.e. your test and live environments cannot share an email). When `sendEmail` is false, the response includes the raw token and a ready-to-use accept link so you can deliver the invitation through your own email provider. Requires the `
|
|
4186
|
+
* Invite a new member to one of your app contexts by email. Creates a pending user with a pre-resolved access profile (their permissions on accept) and signs an invitation token. This call is idempotent on the combination of context and email: re-inviting the same email in the same context rotates the token and resends the invitation rather than creating a duplicate — this requires the `users:r` and `users:u` scopes in addition to `users:c`, because resending rotates a credential on an existing invitation and invalidates any link already sent. Without them the collision returns 409 instead, with no invitation details and no change to the outstanding invitation. Returns HTTP 201 on a new invite or a successful resend. Returns 409 if that email already belongs to an active or suspended member of the app context, or already has an identity elsewhere in your account (an email can currently belong to only one tenant per account, i.e. your test and live environments cannot share an email). When `sendEmail` is false, the response includes the raw token and a ready-to-use accept link so you can deliver the invitation through your own email provider. Requires the `users:c` scope.
|
|
4187
4187
|
*
|
|
4188
4188
|
* @param {Vectros.CreateInviteRequest} request
|
|
4189
4189
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4254,7 +4254,7 @@ var AuthClient = class {
|
|
|
4254
4254
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/users/invite");
|
|
4255
4255
|
}
|
|
4256
4256
|
/**
|
|
4257
|
-
* Resend an outstanding invitation, identified by its email and app context. Rotates the invitation token and extends its expiry, then (when `sendEmail` is true) re-delivers the email. Rotating the token invalidates any previously issued link for this invitation, so only the newest link works. The invitee's pending permissions are left unchanged.
|
|
4257
|
+
* Resend an outstanding invitation, identified by its email and app context. Rotates the invitation token and extends its expiry, then (when `sendEmail` is true) re-delivers the email. Rotating the token invalidates any previously issued link for this invitation, so only the newest link works. The invitee's pending permissions are left unchanged. Because this rotates a credential on an existing invitation, it requires the `users:c`, `users:r` and `users:u` scopes.
|
|
4258
4258
|
*
|
|
4259
4259
|
* @param {Vectros.CreateInviteRequest} request
|
|
4260
4260
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4588,7 +4588,7 @@ var DocumentsClient = class {
|
|
|
4588
4588
|
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
4589
4589
|
* scope: "group:eng-team",
|
|
4590
4590
|
* folderId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
4591
|
-
* startFrom: "
|
|
4591
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
4592
4592
|
* })
|
|
4593
4593
|
*/
|
|
4594
4594
|
listDocuments(request = {}, requestOptions) {
|
|
@@ -4898,6 +4898,7 @@ var DocumentsClient = class {
|
|
|
4898
4898
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
4899
4899
|
*
|
|
4900
4900
|
* @throws {@link Vectros.BadRequestError}
|
|
4901
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
4901
4902
|
* @throws {@link Vectros.NotFoundError}
|
|
4902
4903
|
* @throws {@link Vectros.ConflictError}
|
|
4903
4904
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
@@ -4945,6 +4946,8 @@ var DocumentsClient = class {
|
|
|
4945
4946
|
switch (_response.error.statusCode) {
|
|
4946
4947
|
case 400:
|
|
4947
4948
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
4949
|
+
case 403:
|
|
4950
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
4948
4951
|
case 404:
|
|
4949
4952
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
4950
4953
|
case 409:
|
|
@@ -4975,7 +4978,7 @@ var DocumentsClient = class {
|
|
|
4975
4978
|
* field: "po_number",
|
|
4976
4979
|
* value: "PO-1001",
|
|
4977
4980
|
* prefix: "PO-2024",
|
|
4978
|
-
* startFrom: "
|
|
4981
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl",
|
|
4979
4982
|
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
4980
4983
|
* scope: "org:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
|
|
4981
4984
|
* })
|
|
@@ -5351,7 +5354,7 @@ var FoldersClient = class {
|
|
|
5351
5354
|
* parentFolderId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
5352
5355
|
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
5353
5356
|
* scope: "group:eng-team",
|
|
5354
|
-
* startFrom: "
|
|
5357
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
5355
5358
|
* })
|
|
5356
5359
|
*/
|
|
5357
5360
|
listFolders(request = {}, requestOptions) {
|
|
@@ -5528,6 +5531,7 @@ var FoldersClient = class {
|
|
|
5528
5531
|
* @param {Vectros.UpdateFolderRequest} request
|
|
5529
5532
|
* @param {FoldersClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
5530
5533
|
*
|
|
5534
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
5531
5535
|
* @throws {@link Vectros.NotFoundError}
|
|
5532
5536
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
5533
5537
|
*
|
|
@@ -5572,6 +5576,8 @@ var FoldersClient = class {
|
|
|
5572
5576
|
}
|
|
5573
5577
|
if (_response.error.reason === "status-code") {
|
|
5574
5578
|
switch (_response.error.statusCode) {
|
|
5579
|
+
case 403:
|
|
5580
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
5575
5581
|
case 404:
|
|
5576
5582
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
5577
5583
|
case 429:
|
|
@@ -5654,6 +5660,7 @@ var FoldersClient = class {
|
|
|
5654
5660
|
* @param {FoldersClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
5655
5661
|
*
|
|
5656
5662
|
* @throws {@link Vectros.BadRequestError}
|
|
5663
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
5657
5664
|
* @throws {@link Vectros.NotFoundError}
|
|
5658
5665
|
* @throws {@link Vectros.ConflictError}
|
|
5659
5666
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
@@ -5701,6 +5708,8 @@ var FoldersClient = class {
|
|
|
5701
5708
|
switch (_response.error.statusCode) {
|
|
5702
5709
|
case 400:
|
|
5703
5710
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
5711
|
+
case 403:
|
|
5712
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
5704
5713
|
case 404:
|
|
5705
5714
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
5706
5715
|
case 409:
|
|
@@ -5788,7 +5797,8 @@ var IdentityClient = class {
|
|
|
5788
5797
|
*
|
|
5789
5798
|
* @example
|
|
5790
5799
|
* await client.identity.listEntities({
|
|
5791
|
-
* namespace: "team"
|
|
5800
|
+
* namespace: "team",
|
|
5801
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
5792
5802
|
* })
|
|
5793
5803
|
*/
|
|
5794
5804
|
listEntities(request, requestOptions) {
|
|
@@ -6552,7 +6562,7 @@ var IdentityClient = class {
|
|
|
6552
6562
|
* @example
|
|
6553
6563
|
* await client.identity.listUsers({
|
|
6554
6564
|
* externalId: "usr_12345",
|
|
6555
|
-
* startFrom: "
|
|
6565
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl",
|
|
6556
6566
|
* type: "person_v1",
|
|
6557
6567
|
* field: "team",
|
|
6558
6568
|
* value: "engineering",
|
|
@@ -6733,11 +6743,12 @@ var IdentityClient = class {
|
|
|
6733
6743
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/users/{id}");
|
|
6734
6744
|
}
|
|
6735
6745
|
/**
|
|
6736
|
-
* Updates mutable fields on an existing user (such as email, status, payload, or schema binding). The `type` field is immutable after creation. This endpoint also activates an invited user: a PUT that moves a PENDING user to ACTIVE and carries `inviteToken`, `externalSubject`, and `emailVerifiedAttestation=true` completes the invitation. Requires the `users:u` scope.
|
|
6746
|
+
* Updates mutable fields on an existing user (such as email, status, payload, or schema binding). The `type` field is immutable after creation, and `email` cannot be changed while an invitation to that user is still outstanding — revoke the invitation, or invite the new address instead. This endpoint also activates an invited user: a PUT that moves a PENDING user to ACTIVE and carries `inviteToken`, `externalSubject`, and `emailVerifiedAttestation=true` completes the invitation. Requires the `users:u` scope.
|
|
6737
6747
|
*
|
|
6738
6748
|
* @param {Vectros.UpdateUserRequest} request
|
|
6739
6749
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
6740
6750
|
*
|
|
6751
|
+
* @throws {@link Vectros.BadRequestError}
|
|
6741
6752
|
* @throws {@link Vectros.NotFoundError}
|
|
6742
6753
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
6743
6754
|
*
|
|
@@ -6782,6 +6793,8 @@ var IdentityClient = class {
|
|
|
6782
6793
|
}
|
|
6783
6794
|
if (_response.error.reason === "status-code") {
|
|
6784
6795
|
switch (_response.error.statusCode) {
|
|
6796
|
+
case 400:
|
|
6797
|
+
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
6785
6798
|
case 404:
|
|
6786
6799
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
6787
6800
|
case 429:
|
|
@@ -7429,7 +7442,7 @@ var RecordsClient = class {
|
|
|
7429
7442
|
* folderId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
7430
7443
|
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
7431
7444
|
* scope: "group:eng-team",
|
|
7432
|
-
* startFrom: "
|
|
7445
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
7433
7446
|
* })
|
|
7434
7447
|
*/
|
|
7435
7448
|
listRecords(request = {}, requestOptions) {
|
|
@@ -7617,6 +7630,7 @@ var RecordsClient = class {
|
|
|
7617
7630
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
7618
7631
|
*
|
|
7619
7632
|
* @throws {@link Vectros.BadRequestError}
|
|
7633
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
7620
7634
|
* @throws {@link Vectros.NotFoundError}
|
|
7621
7635
|
* @throws {@link Vectros.ConflictError}
|
|
7622
7636
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
@@ -7665,6 +7679,8 @@ var RecordsClient = class {
|
|
|
7665
7679
|
switch (_response.error.statusCode) {
|
|
7666
7680
|
case 400:
|
|
7667
7681
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
7682
|
+
case 403:
|
|
7683
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
7668
7684
|
case 404:
|
|
7669
7685
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
7670
7686
|
case 409:
|
|
@@ -7746,6 +7762,7 @@ var RecordsClient = class {
|
|
|
7746
7762
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
7747
7763
|
*
|
|
7748
7764
|
* @throws {@link Vectros.BadRequestError}
|
|
7765
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
7749
7766
|
* @throws {@link Vectros.NotFoundError}
|
|
7750
7767
|
* @throws {@link Vectros.ConflictError}
|
|
7751
7768
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
@@ -7796,6 +7813,8 @@ var RecordsClient = class {
|
|
|
7796
7813
|
switch (_response.error.statusCode) {
|
|
7797
7814
|
case 400:
|
|
7798
7815
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
7816
|
+
case 403:
|
|
7817
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
7799
7818
|
case 404:
|
|
7800
7819
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
7801
7820
|
case 409:
|
|
@@ -7813,7 +7832,15 @@ var RecordsClient = class {
|
|
|
7813
7832
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "PATCH", "/v1/records/{id}");
|
|
7814
7833
|
}
|
|
7815
7834
|
/**
|
|
7816
|
-
* Finds records by the value of a lookup field declared on the type's schema. Provide exactly one lookup mode: `value` (exact match), `from`+`to` (inclusive range, ascending by value), or `prefix` (string fields only, ascending). Range and prefix lookups are not supported on a sensitive field, because its value is stored as a blind index and has no sortable order. An exact-`value` lookup on a sensitive field is also rejected on this GET endpoint — the value must not appear in the URL — so use the `POST /v1/records/lookup` body variant for sensitive fields.
|
|
7835
|
+
* Finds records by the value of a lookup field declared on the type's schema. Provide exactly one lookup mode: `value` (exact match), `from`+`to` (inclusive range, ascending by value), or `prefix` (string fields only, ascending). Range and prefix lookups are not supported on a sensitive field, because its value is stored as a blind index and has no sortable order. An exact-`value` lookup on a sensitive field is also rejected on this GET endpoint — the value must not appear in the URL — so use the `POST /v1/records/lookup` body variant for sensitive fields.
|
|
7836
|
+
*
|
|
7837
|
+
* A `value` lookup can additionally be narrowed to a window of the lookup field's **sort key** using `sortFrom` and/or `sortTo` (inclusive) — for example, one session's records created since a timestamp. The sort key is whatever the schema declares as that lookup's `sortBy` (`createdAt` by default, `lastUpdated`, or another field), and bounds are given in that field's own units — epoch milliseconds for the two timestamp options. **Records that have no value for the sorted field are never included in a bounded window** — they are ordered ahead of every record that does have one, and a `sortFrom`/`sortTo` window only ever selects from records carrying a value. The sorted field does not have to be `required`.
|
|
7838
|
+
*
|
|
7839
|
+
* Narrowing is available on any lookup field your schema declares for fast equality lookup, and on `externalId` — which is always ordered by creation time, so its bounds are epoch milliseconds whatever the schema says. It is rejected (`400`) for a field declared with `rangeEnabled`, for a field declared beyond the schema's fast-lookup budget, for a lookup whose `sortBy` names a sensitive field (a sensitive value is stored as a blind index and has no order), and for a window whose start is after its end. Ownership fields are not lookup fields on this endpoint at all — see the `field` parameter.
|
|
7840
|
+
*
|
|
7841
|
+
* While paging a narrowed lookup, keep every other parameter identical. The cursor is valid only for the exact query that returned it — changing `order`, `sortFrom`, `sortTo`, or dropping them altogether, is rejected rather than silently resumed at a position that means something different in the new query.
|
|
7842
|
+
*
|
|
7843
|
+
* Results are paginated: set `limit` for the page size and pass the returned `nextCursor` back as `startFrom` for the next page. **Keep paging until `nextCursor` is null** — a page can come back empty or shorter than `limit` while more results remain, so an empty page is not the end of the results. Requires the `records:r:<type>` scope.
|
|
7817
7844
|
*
|
|
7818
7845
|
* @param {Vectros.LookupRecordsRequest} request
|
|
7819
7846
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -7825,22 +7852,40 @@ var RecordsClient = class {
|
|
|
7825
7852
|
* type: "intake_form",
|
|
7826
7853
|
* field: "email",
|
|
7827
7854
|
* value: "jane@example.com",
|
|
7855
|
+
* values: ["open"],
|
|
7828
7856
|
* prefix: "jane",
|
|
7829
|
-
* startFrom: "
|
|
7857
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
7830
7858
|
* })
|
|
7831
7859
|
*/
|
|
7832
7860
|
lookupRecords(request, requestOptions) {
|
|
7833
7861
|
return HttpResponsePromise.fromPromise(this.__lookupRecords(request, requestOptions));
|
|
7834
7862
|
}
|
|
7835
7863
|
async __lookupRecords(request, requestOptions) {
|
|
7836
|
-
const {
|
|
7864
|
+
const {
|
|
7865
|
+
type: type_,
|
|
7866
|
+
field,
|
|
7867
|
+
value,
|
|
7868
|
+
values,
|
|
7869
|
+
from: from_,
|
|
7870
|
+
to,
|
|
7871
|
+
prefix,
|
|
7872
|
+
sortFrom,
|
|
7873
|
+
sortTo,
|
|
7874
|
+
startFrom,
|
|
7875
|
+
limit,
|
|
7876
|
+
includePayload,
|
|
7877
|
+
order
|
|
7878
|
+
} = request;
|
|
7837
7879
|
const _queryParams = {
|
|
7838
7880
|
type: type_,
|
|
7839
7881
|
field,
|
|
7840
7882
|
value,
|
|
7883
|
+
values,
|
|
7841
7884
|
from: from_,
|
|
7842
7885
|
to,
|
|
7843
7886
|
prefix,
|
|
7887
|
+
sortFrom,
|
|
7888
|
+
sortTo,
|
|
7844
7889
|
startFrom,
|
|
7845
7890
|
limit,
|
|
7846
7891
|
includePayload,
|
|
@@ -7884,7 +7929,7 @@ var RecordsClient = class {
|
|
|
7884
7929
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/records/lookup");
|
|
7885
7930
|
}
|
|
7886
7931
|
/**
|
|
7887
|
-
* Body-based equivalent of `GET /v1/records/lookup`. Use this when looking up by a sensitive field: the value travels in the request body (and is blind-indexed server-side) instead of in the URL query string, so it never lands in access, CDN, or proxy logs. The GET variant rejects an exact-value lookup on a sensitive field and directs you here. Non-sensitive exact-value, range (`from`+`to`), and prefix lookups also work here. Returns the same `{data, nextCursor}` envelope and uses the same pagination as the GET variant. Requires the `records:r:<type>` scope.
|
|
7932
|
+
* Body-based equivalent of `GET /v1/records/lookup`. Use this when looking up by a sensitive field: the value travels in the request body (and is blind-indexed server-side) instead of in the URL query string, so it never lands in access, CDN, or proxy logs. The GET variant rejects an exact-value lookup on a sensitive field and directs you here. Non-sensitive exact-value, range (`from`+`to`), and prefix lookups also work here, as does narrowing a `value` lookup by the field's sort key with `sortFrom`/`sortTo` — see the GET variant for what the sort key is and when narrowing by it is available. Returns the same `{data, nextCursor}` envelope and uses the same pagination as the GET variant; keep paging until `nextCursor` is null rather than stopping on an empty page. Requires the `records:r:<type>` scope.
|
|
7888
7933
|
*
|
|
7889
7934
|
* @param {Vectros.RecordLookupRequest} request
|
|
7890
7935
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -8079,7 +8124,7 @@ var SchemasClient = class {
|
|
|
8079
8124
|
* scope: "org:6ba7b810-9dad-11d1-80b4-00c04fd430c8",
|
|
8080
8125
|
* surface: "document",
|
|
8081
8126
|
* recordType: "intake_form",
|
|
8082
|
-
* startFrom: "
|
|
8127
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
8083
8128
|
* })
|
|
8084
8129
|
*/
|
|
8085
8130
|
listSchemas(request = {}, requestOptions) {
|
|
@@ -8283,6 +8328,7 @@ var SchemasClient = class {
|
|
|
8283
8328
|
* @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
8284
8329
|
*
|
|
8285
8330
|
* @throws {@link Vectros.BadRequestError}
|
|
8331
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
8286
8332
|
* @throws {@link Vectros.NotFoundError}
|
|
8287
8333
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
8288
8334
|
*
|
|
@@ -8331,6 +8377,8 @@ var SchemasClient = class {
|
|
|
8331
8377
|
switch (_response.error.statusCode) {
|
|
8332
8378
|
case 400:
|
|
8333
8379
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
8380
|
+
case 403:
|
|
8381
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
8334
8382
|
case 404:
|
|
8335
8383
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
8336
8384
|
case 429:
|
|
@@ -8643,8 +8691,8 @@ function warnOnSuboptimalKey(key, log) {
|
|
|
8643
8691
|
|
|
8644
8692
|
// src/build-info.ts
|
|
8645
8693
|
var BUILD_INFO = {
|
|
8646
|
-
mcpServer: true ? "0.
|
|
8647
|
-
sdk: true ? "0.
|
|
8694
|
+
mcpServer: true ? "0.13.0" : "dev",
|
|
8695
|
+
sdk: true ? "0.38.0" : "dev"
|
|
8648
8696
|
};
|
|
8649
8697
|
function formatBuildInfo() {
|
|
8650
8698
|
return `vectros-mcp-server ${BUILD_INFO.mcpServer} (sdk ${BUILD_INFO.sdk})`;
|
|
@@ -8687,7 +8735,9 @@ async function resolveIdentity({
|
|
|
8687
8735
|
const derived = {
|
|
8688
8736
|
status: "ok",
|
|
8689
8737
|
environment: deriveEnvironment(environment),
|
|
8690
|
-
principalType: derivePrincipalType(apiKey)
|
|
8738
|
+
principalType: derivePrincipalType(apiKey),
|
|
8739
|
+
mcpServerVersion: BUILD_INFO.mcpServer,
|
|
8740
|
+
sdkVersion: BUILD_INFO.sdk
|
|
8691
8741
|
};
|
|
8692
8742
|
if (!apiKey || !environment) {
|
|
8693
8743
|
log.debug({ component: "identity", mode: "derived-only" }, "identity derived (no fetch)");
|
|
@@ -8715,7 +8765,13 @@ async function resolveIdentity({
|
|
|
8715
8765
|
);
|
|
8716
8766
|
}
|
|
8717
8767
|
}
|
|
8718
|
-
const merged = {
|
|
8768
|
+
const merged = {
|
|
8769
|
+
...derived,
|
|
8770
|
+
...extended,
|
|
8771
|
+
status: "ok",
|
|
8772
|
+
mcpServerVersion: derived.mcpServerVersion,
|
|
8773
|
+
sdkVersion: derived.sdkVersion
|
|
8774
|
+
};
|
|
8719
8775
|
log.debug(
|
|
8720
8776
|
{
|
|
8721
8777
|
component: "identity",
|
|
@@ -9037,14 +9093,23 @@ var import_zod2 = require("zod");
|
|
|
9037
9093
|
function pageItems(page) {
|
|
9038
9094
|
return page.data ?? [];
|
|
9039
9095
|
}
|
|
9096
|
+
var MAX_PAGES = 100;
|
|
9097
|
+
var MAX_ROWS = 1e6;
|
|
9040
9098
|
async function drainPages(fetchPage) {
|
|
9041
9099
|
const all = [];
|
|
9042
9100
|
let startFrom;
|
|
9101
|
+
let pages = 0;
|
|
9043
9102
|
for (; ; ) {
|
|
9044
9103
|
const page = await fetchPage(startFrom);
|
|
9045
|
-
|
|
9104
|
+
pages++;
|
|
9105
|
+
if (page.data?.length) for (const item of page.data) all.push(item);
|
|
9046
9106
|
const next = page.nextCursor;
|
|
9047
9107
|
if (!next) break;
|
|
9108
|
+
if (pages > MAX_PAGES || all.length > MAX_ROWS) {
|
|
9109
|
+
throw new Error(
|
|
9110
|
+
`drainPages: exceeded the runaway guard (${all.length} rows over ${pages} pages, limits ${MAX_ROWS}/${MAX_PAGES}) without the cursor going null. Refusing to return a partial result \u2014 the backend may be returning empty pages with a live cursor.`
|
|
9111
|
+
);
|
|
9112
|
+
}
|
|
9048
9113
|
startFrom = next;
|
|
9049
9114
|
}
|
|
9050
9115
|
return all;
|
|
@@ -9055,14 +9120,23 @@ var MCP_DEFAULT_LIMIT2 = 3;
|
|
|
9055
9120
|
var MCP_MAX_LIMIT2 = 100;
|
|
9056
9121
|
var inputSchema2 = {
|
|
9057
9122
|
type: import_zod2.z.string().min(1, "type (record type) is required").describe('Record type / schema name (e.g. "patient", "clinical_note").'),
|
|
9058
|
-
// Lookup-mode args — provide `field` plus EXACTLY ONE of: value | from+to | prefix.
|
|
9123
|
+
// Lookup-mode args — provide `field` plus EXACTLY ONE of: value | values | from+to | prefix.
|
|
9059
9124
|
field: import_zod2.z.string().optional().describe(
|
|
9060
|
-
'Lookup mode: name of the lookup-indexed field to query by. `externalId` is always queryable \u2014 e.g. `{type:"control", field:"externalId", value:"ctrl-scoped-key"}` finds the record you created under that externalId. (record_get / record_update also accept externalId directly.)'
|
|
9125
|
+
'Lookup mode: name of the lookup-indexed field to query by. `externalId` is always queryable \u2014 e.g. `{type:"control", field:"externalId", value:"ctrl-scoped-key"}` finds the record you created under that externalId. (record_get / record_update also accept externalId directly.) For a SCHEMA-declared composite lookup \u2014 check list_schemas\' lookupFields for a fieldNames entry, not any two fields you pick \u2014 give those field names comma-joined in the declared order (e.g. "status,area"). Use `values` to match on several of those fields at once, or `value` to match on just the FIRST field named (equivalent to a one-element `values`); range/prefix are not valid on a composite field.'
|
|
9126
|
+
),
|
|
9127
|
+
value: import_zod2.z.string().optional().describe(
|
|
9128
|
+
"Lookup mode (equality): exact-match value for `field`. Also valid when `field` names a SCHEMA-declared composite lookup \u2014 matches just the first named field, grouping by the rest (equivalent to `values` with one entry)."
|
|
9129
|
+
),
|
|
9130
|
+
values: import_zod2.z.array(import_zod2.z.string()).min(1).max(3).optional().describe(
|
|
9131
|
+
'Lookup mode (composite equality): only valid against a lookup the SCHEMA declares over several fields together (a fieldNames entry in list_schemas \u2014 you cannot combine two ordinary single-field lookups this way). One value per field, in the order the schema declares them (e.g. field="status,area", values=["open","billing"]). Mutually exclusive with `value`; a single-element array is exactly `value` written uniformly. Supplying FEWER values than the lookup declares is allowed \u2014 as long as they\'re a leading run of its fields \u2014 and returns records grouped by the fields left unspecified; `order` then sorts within each group, not across them. Record lookups only (not documents/users/entities).'
|
|
9061
9132
|
),
|
|
9062
|
-
value: import_zod2.z.string().optional().describe("Lookup mode (equality): exact-match value for `field`."),
|
|
9063
9133
|
from: import_zod2.z.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Non-sensitive fields only."),
|
|
9064
9134
|
to: import_zod2.z.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
|
|
9065
9135
|
prefix: import_zod2.z.string().optional().describe("Lookup mode (prefix): match values starting with this. String, non-sensitive fields only."),
|
|
9136
|
+
sortFrom: import_zod2.z.string().optional().describe(
|
|
9137
|
+
"Lookup mode (equality/composite only): inclusive lower bound on the lookup field's sort key, narrowing a `value`/`values` match to a window instead of paging the whole match. Give the bound in the sort field's own units (epoch milliseconds for `createdAt`/`lastUpdated`). With `values`, requires every value be supplied (no grouping) for one continuous ordering. Not valid with `from`/`to`/`prefix`."
|
|
9138
|
+
),
|
|
9139
|
+
sortTo: import_zod2.z.string().optional().describe("Lookup mode (equality/composite only): inclusive upper bound on the sort key; pairs with `sortFrom`."),
|
|
9066
9140
|
order: import_zod2.z.enum(["asc", "desc"]).optional().describe(
|
|
9067
9141
|
"Lookup mode: sort direction by the looked-up field. `asc` (default) or `desc` \u2014 use `desc` with a range/prefix lookup to get the most-recent / highest values first (e.g. latest-N). Ignored in list mode."
|
|
9068
9142
|
),
|
|
@@ -9079,54 +9153,106 @@ var inputSchema2 = {
|
|
|
9079
9153
|
var recordQuery = ({ client, log }) => ({
|
|
9080
9154
|
name: "record_query",
|
|
9081
9155
|
title: "Record query (list or lookup)",
|
|
9082
|
-
description: "Query structured records of a given type. Two modes:\n \u2022 Lookup on a lookup-indexed field: pass `field` plus exactly one of `value` (exact), `from`+`to` (range), or `prefix`. Works on sensitive fields too
|
|
9156
|
+
description: "Query structured records of a given type. Two modes:\n \u2022 Lookup on a lookup-indexed field: pass `field` plus exactly one of `value` (exact), `values` (exact, composite \u2014 one value per field; a single-element array is the same as `value`), `from`+`to` (range), or `prefix`. `values` with more than one entry, or a comma-joined `field`, ONLY works for a lookup the schema itself declared over several fields together \u2014 check list_schemas' lookupFields for a fieldNames entry, then pass those field names comma-joined as `field`; `from`/`to`/`prefix` are not valid there. Works on sensitive fields too. Optionally narrow an exact match to a window with `sortFrom`/`sortTo`.\n \u2022 List by type: omit `field`; optionally filter by `userId` or `scope` (`namespace:value`).\nReturns a `{ data, nextCursor }` page: `data` holds up to `limit` records (default 3, max 100 \u2014 raise it in one call when you can accept the payload), and a non-null `nextCursor` means more remain \u2014 pass it back as `startFrom` to page. A composite lookup given fewer than its full field count returns records grouped by the unspecified fields, ordered within each group. Mode is auto-detected from the arguments present.",
|
|
9083
9157
|
inputSchema: inputSchema2,
|
|
9084
9158
|
handler: async (args) => {
|
|
9085
9159
|
const limit = args.limit ?? MCP_DEFAULT_LIMIT2;
|
|
9086
9160
|
const type = args.type;
|
|
9087
9161
|
const field = args.field;
|
|
9088
9162
|
const value = args.value;
|
|
9163
|
+
const values = args.values;
|
|
9089
9164
|
const from = args.from;
|
|
9090
9165
|
const to = args.to;
|
|
9091
9166
|
const prefix = args.prefix;
|
|
9167
|
+
const sortFrom = args.sortFrom;
|
|
9168
|
+
const sortTo = args.sortTo;
|
|
9092
9169
|
const startFrom = args.startFrom;
|
|
9170
|
+
if (!field && (value !== void 0 || values !== void 0 || from !== void 0 || to !== void 0 || prefix !== void 0 || sortFrom !== void 0 || sortTo !== void 0)) {
|
|
9171
|
+
return toolError(
|
|
9172
|
+
"record_query",
|
|
9173
|
+
new Error(
|
|
9174
|
+
"'value'/'values'/'from'/'to'/'prefix'/'sortFrom'/'sortTo' require 'field' \u2014 without it, list mode runs and silently ignores them. Pass 'field' to run a lookup, or drop these to list by type."
|
|
9175
|
+
)
|
|
9176
|
+
);
|
|
9177
|
+
}
|
|
9093
9178
|
try {
|
|
9094
9179
|
let page;
|
|
9095
9180
|
if (field) {
|
|
9181
|
+
const fieldNames = field.split(",").map((f) => f.trim()).filter(Boolean);
|
|
9182
|
+
const normalizedField = fieldNames.join(",");
|
|
9183
|
+
const isCompositeField = fieldNames.length > 1;
|
|
9096
9184
|
const hasEquality = value !== void 0;
|
|
9185
|
+
const hasComposite = values !== void 0;
|
|
9097
9186
|
const hasRange = from !== void 0 || to !== void 0;
|
|
9098
9187
|
const hasPrefix = prefix !== void 0;
|
|
9099
|
-
const modes = Number(hasEquality) + Number(hasRange) + Number(hasPrefix);
|
|
9188
|
+
const modes = Number(hasEquality) + Number(hasComposite) + Number(hasRange) + Number(hasPrefix);
|
|
9100
9189
|
if (modes === 0) {
|
|
9101
9190
|
return toolError(
|
|
9102
9191
|
"record_query",
|
|
9103
9192
|
new Error(
|
|
9104
|
-
`lookup on field '${field}' needs one of: 'value' (exact), 'from'+'to' (range), or 'prefix'.`
|
|
9193
|
+
`lookup on field '${field}' needs one of: 'value' (exact), 'values' (composite exact), 'from'+'to' (range), or 'prefix'.`
|
|
9105
9194
|
)
|
|
9106
9195
|
);
|
|
9107
9196
|
}
|
|
9108
9197
|
if (modes > 1) {
|
|
9109
9198
|
return toolError(
|
|
9110
9199
|
"record_query",
|
|
9111
|
-
new Error(
|
|
9200
|
+
new Error(
|
|
9201
|
+
"'value', 'values', 'from'/'to', and 'prefix' are mutually exclusive \u2014 provide exactly one."
|
|
9202
|
+
)
|
|
9112
9203
|
);
|
|
9113
9204
|
}
|
|
9114
9205
|
if (hasRange && !(from !== void 0 && to !== void 0)) {
|
|
9115
9206
|
return toolError("record_query", new Error("range lookup requires both 'from' and 'to'."));
|
|
9116
9207
|
}
|
|
9208
|
+
if (isCompositeField && (hasRange || hasPrefix)) {
|
|
9209
|
+
return toolError(
|
|
9210
|
+
"record_query",
|
|
9211
|
+
new Error(
|
|
9212
|
+
`'field' names ${fieldNames.length} fields ('${normalizedField}') \u2014 a composite lookup is exact-match only ('value' or 'values'), not 'from'/'to'/'prefix'.`
|
|
9213
|
+
)
|
|
9214
|
+
);
|
|
9215
|
+
}
|
|
9216
|
+
if (hasComposite && values.length > fieldNames.length) {
|
|
9217
|
+
return toolError(
|
|
9218
|
+
"record_query",
|
|
9219
|
+
new Error(
|
|
9220
|
+
`'values' has ${values.length} entries but 'field' names only ${fieldNames.length} field(s) ('${normalizedField}') \u2014 supply at most one value per field, in order (fewer only as a leading run).`
|
|
9221
|
+
)
|
|
9222
|
+
);
|
|
9223
|
+
}
|
|
9224
|
+
if (sortFrom !== void 0 || sortTo !== void 0) {
|
|
9225
|
+
if (!(hasEquality || hasComposite)) {
|
|
9226
|
+
return toolError(
|
|
9227
|
+
"record_query",
|
|
9228
|
+
new Error("'sortFrom'/'sortTo' narrow a 'value' or 'values' match only \u2014 not 'from'/'to'/'prefix'.")
|
|
9229
|
+
);
|
|
9230
|
+
}
|
|
9231
|
+
if (hasComposite && values.length < fieldNames.length) {
|
|
9232
|
+
return toolError(
|
|
9233
|
+
"record_query",
|
|
9234
|
+
new Error(
|
|
9235
|
+
`'sortFrom'/'sortTo' with 'values' requires a value for every field named in 'field' (got ${values.length} of ${fieldNames.length}) \u2014 a partial/grouped match has no single continuous ordering to window.`
|
|
9236
|
+
)
|
|
9237
|
+
);
|
|
9238
|
+
}
|
|
9239
|
+
}
|
|
9117
9240
|
page = await client.records.lookupRecordsByBody({
|
|
9118
9241
|
type,
|
|
9119
|
-
field,
|
|
9242
|
+
field: normalizedField,
|
|
9120
9243
|
value,
|
|
9244
|
+
values,
|
|
9121
9245
|
from,
|
|
9122
9246
|
to,
|
|
9123
9247
|
prefix,
|
|
9248
|
+
sortFrom,
|
|
9249
|
+
sortTo,
|
|
9124
9250
|
order: args.order,
|
|
9125
9251
|
startFrom,
|
|
9126
9252
|
limit
|
|
9127
9253
|
});
|
|
9128
9254
|
log.debug(
|
|
9129
|
-
{ tool: "record_query", mode: "lookup", type, field, returned: pageItems(page).length },
|
|
9255
|
+
{ tool: "record_query", mode: "lookup", type, field: normalizedField, returned: pageItems(page).length },
|
|
9130
9256
|
"record_query lookup ok"
|
|
9131
9257
|
);
|
|
9132
9258
|
} else {
|
|
@@ -10065,7 +10191,7 @@ var inputSchema18 = {
|
|
|
10065
10191
|
var currentIdentity = ({ log, apiKey, environment }) => ({
|
|
10066
10192
|
name: "current_identity",
|
|
10067
10193
|
title: "Current identity (tenant + principal scope)",
|
|
10068
|
-
description: "Describe the credential the MCP server is operating under. Returns tenantId, environment (staging|production), principalType (root_key|scoped_key|token), principalKeyId, principalLabel, and (for scoped credentials) allowedActions plus dataScope \u2014 the credential's reach as { userId, scopes[] }, where each scope is a `namespace:value` string (e.g. \"org:<uuid>\"). Use this when the user asks 'what can you do here?'
|
|
10194
|
+
description: "Describe the credential the MCP server is operating under. Returns tenantId, environment (staging|production), principalType (root_key|scoped_key|token), principalKeyId, principalLabel, and (for scoped credentials) allowedActions plus dataScope \u2014 the credential's reach as { userId, scopes[] }, where each scope is a `namespace:value` string (e.g. \"org:<uuid>\"). Also reports mcpServerVersion (this server's own package version) and sdkVersion (the bundled @vectros-ai/sdk version) so a caller can tell what build it's talking to. Use this when the user asks 'what can you do here?', 'what tenant am I in?', or 'what version is this?'. Calls GET /v1/ping under the hood.",
|
|
10069
10195
|
inputSchema: inputSchema18,
|
|
10070
10196
|
handler: async () => {
|
|
10071
10197
|
try {
|
|
@@ -10543,7 +10669,7 @@ var identityResource = ({ log, apiKey, environment }) => ({
|
|
|
10543
10669
|
name: "identity",
|
|
10544
10670
|
uri: "vectros://identity",
|
|
10545
10671
|
title: "Current identity (tenant + principal scope)",
|
|
10546
|
-
description: "The tenant + principal scope the MCP server is authenticated as. Returns the same payload as the `current_identity` tool: status, tenantId, environment, principalType, principalKeyId, principalLabel,
|
|
10672
|
+
description: "The tenant + principal scope the MCP server is authenticated as. Returns the same payload as the `current_identity` tool: status, tenantId, environment, principalType, principalKeyId, principalLabel, (for scoped credentials) allowedActions + dataScope ({ userId, scopes[] }), plus mcpServerVersion and sdkVersion (this build's own version and the bundled @vectros-ai/sdk version). The /v1/ping backing call ships the extended shape today; the version fields are always client-derived.",
|
|
10547
10673
|
mimeType: "application/json",
|
|
10548
10674
|
read: async () => {
|
|
10549
10675
|
const identity = await resolveIdentity({ log, apiKey, environment });
|