@vectros-ai/mcp-server 0.11.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 +66 -0
- package/README.md +2 -2
- package/dist/cli-http.js +211 -65
- package/dist/cli-http.js.map +1 -1
- package/dist/cli-http.mjs +211 -65
- package/dist/cli-http.mjs.map +1 -1
- package/dist/cli.js +211 -65
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +211 -65
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +211 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +211 -65
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/server.ts
|
|
4
4
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// node_modules/@vectros-ai/sdk/dist/index.mjs
|
|
7
7
|
var __defProp = Object.defineProperty;
|
|
8
8
|
var __export = (target, all) => {
|
|
9
9
|
for (var name in all)
|
|
@@ -2432,7 +2432,7 @@ var AuthClient = class {
|
|
|
2432
2432
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/admin/access-log");
|
|
2433
2433
|
}
|
|
2434
2434
|
/**
|
|
2435
|
-
* Lists
|
|
2435
|
+
* 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.
|
|
2436
2436
|
*
|
|
2437
2437
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
2438
2438
|
*
|
|
@@ -2815,7 +2815,7 @@ var AuthClient = class {
|
|
|
2815
2815
|
);
|
|
2816
2816
|
}
|
|
2817
2817
|
/**
|
|
2818
|
-
* 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.
|
|
2818
|
+
* 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.
|
|
2819
2819
|
*
|
|
2820
2820
|
* @param {Vectros.CreateAccessProfileRequest} request
|
|
2821
2821
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -3233,7 +3233,7 @@ var AuthClient = class {
|
|
|
3233
3233
|
);
|
|
3234
3234
|
}
|
|
3235
3235
|
/**
|
|
3236
|
-
* 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
|
|
3236
|
+
* 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.
|
|
3237
3237
|
*
|
|
3238
3238
|
* @param {Vectros.UpdateAccessProfileRequest} request
|
|
3239
3239
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -3306,7 +3306,7 @@ var AuthClient = class {
|
|
|
3306
3306
|
);
|
|
3307
3307
|
}
|
|
3308
3308
|
/**
|
|
3309
|
-
* 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.
|
|
3309
|
+
* 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.
|
|
3310
3310
|
*
|
|
3311
3311
|
* @param {Vectros.DeleteAccessProfileRequest} request
|
|
3312
3312
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4160,7 +4160,7 @@ var AuthClient = class {
|
|
|
4160
4160
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/auth/token");
|
|
4161
4161
|
}
|
|
4162
4162
|
/**
|
|
4163
|
-
* 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 `
|
|
4163
|
+
* 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.
|
|
4164
4164
|
*
|
|
4165
4165
|
* @param {Vectros.CreateInviteRequest} request
|
|
4166
4166
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4231,7 +4231,7 @@ var AuthClient = class {
|
|
|
4231
4231
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/users/invite");
|
|
4232
4232
|
}
|
|
4233
4233
|
/**
|
|
4234
|
-
* 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.
|
|
4234
|
+
* 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.
|
|
4235
4235
|
*
|
|
4236
4236
|
* @param {Vectros.CreateInviteRequest} request
|
|
4237
4237
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4565,7 +4565,7 @@ var DocumentsClient = class {
|
|
|
4565
4565
|
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
4566
4566
|
* scope: "group:eng-team",
|
|
4567
4567
|
* folderId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
4568
|
-
* startFrom: "
|
|
4568
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
4569
4569
|
* })
|
|
4570
4570
|
*/
|
|
4571
4571
|
listDocuments(request = {}, requestOptions) {
|
|
@@ -4613,7 +4613,7 @@ var DocumentsClient = class {
|
|
|
4613
4613
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents");
|
|
4614
4614
|
}
|
|
4615
4615
|
/**
|
|
4616
|
-
* Creates a document from a raw text string and queues it for asynchronous indexing so it becomes searchable. Optionally supply an `externalId` to make the create idempotent — if a document with the same `externalId` already exists in your context, that existing document is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing document was returned) tells the two apart. To overwrite an existing document's content instead of returning it unchanged, set `?upsert=true` (this also requires the `documents:u` scope). Requires the `documents:c` scope.
|
|
4616
|
+
* Creates a document from a raw text string and queues it for asynchronous indexing so it becomes searchable. Optionally supply an `externalId` to make the create idempotent — if a document with the same `externalId` already exists in your context, that existing document is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing document was returned) tells the two apart. To overwrite an existing document's content instead of returning it unchanged, set `?upsert=true` (this also requires the `documents:u` scope). Requires the `documents:c` scope to create. Being returned the existing document on a collision is a read of that document's data and additionally requires the `documents:r` scope — a credential holding `documents:c` alone receives a `400` ("already exists") on collision instead of the document.
|
|
4617
4617
|
*
|
|
4618
4618
|
* @param {Vectros.IngestDocumentRequest} request
|
|
4619
4619
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -4875,6 +4875,7 @@ var DocumentsClient = class {
|
|
|
4875
4875
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
4876
4876
|
*
|
|
4877
4877
|
* @throws {@link Vectros.BadRequestError}
|
|
4878
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
4878
4879
|
* @throws {@link Vectros.NotFoundError}
|
|
4879
4880
|
* @throws {@link Vectros.ConflictError}
|
|
4880
4881
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
@@ -4922,6 +4923,8 @@ var DocumentsClient = class {
|
|
|
4922
4923
|
switch (_response.error.statusCode) {
|
|
4923
4924
|
case 400:
|
|
4924
4925
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
4926
|
+
case 403:
|
|
4927
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
4925
4928
|
case 404:
|
|
4926
4929
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
4927
4930
|
case 409:
|
|
@@ -4939,25 +4942,29 @@ var DocumentsClient = class {
|
|
|
4939
4942
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "PATCH", "/v1/documents/{id}");
|
|
4940
4943
|
}
|
|
4941
4944
|
/**
|
|
4942
|
-
* Finds documents of a given type by field value. Supported fields: `externalId` (the document's first-class external identifier — no schema declaration required) and any field declared as a lookup field on the bound schema. A lookup on a sensitive field is rejected here because the value would appear in the URL query string; use POST /v1/documents/lookup (the request-body variant) for a sensitive field instead. Results are paginated: set `limit` for the page size and feed the returned `nextCursor` back as `startFrom` to fetch the next page. The response is a `{data, nextCursor}` envelope. Requires the `documents:r` scope.
|
|
4945
|
+
* Finds documents of a given type by field value. Supported fields: `externalId` (the document's first-class external identifier — no schema declaration required) and any field declared as a lookup field on the bound schema. A lookup on a sensitive field is rejected here because the value would appear in the URL query string; use POST /v1/documents/lookup (the request-body variant) for a sensitive field instead. `type`'s schema resolves with basedOn-aware shadowing: your own `userId`- or `scope`-owned variant if you have one, otherwise the shared base — for a scoped credential the owner is always your own token identity; `userId`/`scope` here only apply as an explicit owner selector for a root API key. Results are paginated: set `limit` for the page size and feed the returned `nextCursor` back as `startFrom` to fetch the next page. The response is a `{data, nextCursor}` envelope. Requires the `documents:r` scope.
|
|
4943
4946
|
*
|
|
4944
4947
|
* @param {Vectros.LookupDocumentsRequest} request
|
|
4945
4948
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
4946
4949
|
*
|
|
4950
|
+
* @throws {@link Vectros.BadRequestError}
|
|
4951
|
+
*
|
|
4947
4952
|
* @example
|
|
4948
4953
|
* await client.documents.lookupDocuments({
|
|
4949
4954
|
* type: "invoice",
|
|
4950
4955
|
* field: "po_number",
|
|
4951
4956
|
* value: "PO-1001",
|
|
4952
4957
|
* prefix: "PO-2024",
|
|
4953
|
-
* startFrom: "
|
|
4958
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl",
|
|
4959
|
+
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
4960
|
+
* scope: "org:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
|
|
4954
4961
|
* })
|
|
4955
4962
|
*/
|
|
4956
4963
|
lookupDocuments(request, requestOptions) {
|
|
4957
4964
|
return HttpResponsePromise.fromPromise(this.__lookupDocuments(request, requestOptions));
|
|
4958
4965
|
}
|
|
4959
4966
|
async __lookupDocuments(request, requestOptions) {
|
|
4960
|
-
const { type: type_, field, value, from: from_, to, prefix, startFrom, limit, order } = request;
|
|
4967
|
+
const { type: type_, field, value, from: from_, to, prefix, startFrom, limit, order, userId, scope } = request;
|
|
4961
4968
|
const _queryParams = {
|
|
4962
4969
|
type: type_,
|
|
4963
4970
|
field,
|
|
@@ -4967,7 +4974,9 @@ var DocumentsClient = class {
|
|
|
4967
4974
|
prefix,
|
|
4968
4975
|
startFrom,
|
|
4969
4976
|
limit,
|
|
4970
|
-
order: order != null ? order : void 0
|
|
4977
|
+
order: order != null ? order : void 0,
|
|
4978
|
+
userId,
|
|
4979
|
+
scope
|
|
4971
4980
|
};
|
|
4972
4981
|
const _authRequest = await this._options.authProvider.getAuthRequest();
|
|
4973
4982
|
const _headers = mergeHeaders(
|
|
@@ -4993,11 +5002,16 @@ var DocumentsClient = class {
|
|
|
4993
5002
|
return { data: _response.body, rawResponse: _response.rawResponse };
|
|
4994
5003
|
}
|
|
4995
5004
|
if (_response.error.reason === "status-code") {
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5005
|
+
switch (_response.error.statusCode) {
|
|
5006
|
+
case 400:
|
|
5007
|
+
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
5008
|
+
default:
|
|
5009
|
+
throw new VectrosError({
|
|
5010
|
+
statusCode: _response.error.statusCode,
|
|
5011
|
+
body: _response.error.body,
|
|
5012
|
+
rawResponse: _response.rawResponse
|
|
5013
|
+
});
|
|
5014
|
+
}
|
|
5001
5015
|
}
|
|
5002
5016
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents/lookup");
|
|
5003
5017
|
}
|
|
@@ -5317,7 +5331,7 @@ var FoldersClient = class {
|
|
|
5317
5331
|
* parentFolderId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
5318
5332
|
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
5319
5333
|
* scope: "group:eng-team",
|
|
5320
|
-
* startFrom: "
|
|
5334
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
5321
5335
|
* })
|
|
5322
5336
|
*/
|
|
5323
5337
|
listFolders(request = {}, requestOptions) {
|
|
@@ -5365,7 +5379,7 @@ var FoldersClient = class {
|
|
|
5365
5379
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/folders");
|
|
5366
5380
|
}
|
|
5367
5381
|
/**
|
|
5368
|
-
* Creates a folder to organize your documents and records. If `parentFolderId` is omitted, the folder is created under your context's default root folder. Folder creation is idempotent by (slug + parent): if a folder with the same slug already exists under the same parent, that existing folder is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing folder was returned) tells the two apart. To overwrite an existing folder's mutable fields instead of returning it unchanged, set `?upsert=true` (this also requires the `folders:u` scope). Requires the `folders:c` scope.
|
|
5382
|
+
* Creates a folder to organize your documents and records. If `parentFolderId` is omitted, the folder is created under your context's default root folder. Folder creation is idempotent by (slug + parent): if a folder with the same slug already exists under the same parent, that existing folder is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing folder was returned) tells the two apart. To overwrite an existing folder's mutable fields instead of returning it unchanged, set `?upsert=true` (this also requires the `folders:u` scope). Requires the `folders:c` scope to create. Being returned the existing folder on a collision is a read of that folder's data and additionally requires the `folders:r` scope — a credential holding `folders:c` alone receives a `400` ("already exists") on collision instead of the folder.
|
|
5369
5383
|
*
|
|
5370
5384
|
* @param {Vectros.CreateFolderRequest} request
|
|
5371
5385
|
* @param {FoldersClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -5494,6 +5508,7 @@ var FoldersClient = class {
|
|
|
5494
5508
|
* @param {Vectros.UpdateFolderRequest} request
|
|
5495
5509
|
* @param {FoldersClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
5496
5510
|
*
|
|
5511
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
5497
5512
|
* @throws {@link Vectros.NotFoundError}
|
|
5498
5513
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
5499
5514
|
*
|
|
@@ -5538,6 +5553,8 @@ var FoldersClient = class {
|
|
|
5538
5553
|
}
|
|
5539
5554
|
if (_response.error.reason === "status-code") {
|
|
5540
5555
|
switch (_response.error.statusCode) {
|
|
5556
|
+
case 403:
|
|
5557
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
5541
5558
|
case 404:
|
|
5542
5559
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
5543
5560
|
case 429:
|
|
@@ -5620,6 +5637,7 @@ var FoldersClient = class {
|
|
|
5620
5637
|
* @param {FoldersClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
5621
5638
|
*
|
|
5622
5639
|
* @throws {@link Vectros.BadRequestError}
|
|
5640
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
5623
5641
|
* @throws {@link Vectros.NotFoundError}
|
|
5624
5642
|
* @throws {@link Vectros.ConflictError}
|
|
5625
5643
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
@@ -5667,6 +5685,8 @@ var FoldersClient = class {
|
|
|
5667
5685
|
switch (_response.error.statusCode) {
|
|
5668
5686
|
case 400:
|
|
5669
5687
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
5688
|
+
case 403:
|
|
5689
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
5670
5690
|
case 404:
|
|
5671
5691
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
5672
5692
|
case 409:
|
|
@@ -5754,7 +5774,8 @@ var IdentityClient = class {
|
|
|
5754
5774
|
*
|
|
5755
5775
|
* @example
|
|
5756
5776
|
* await client.identity.listEntities({
|
|
5757
|
-
* namespace: "team"
|
|
5777
|
+
* namespace: "team",
|
|
5778
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
5758
5779
|
* })
|
|
5759
5780
|
*/
|
|
5760
5781
|
listEntities(request, requestOptions) {
|
|
@@ -5823,7 +5844,7 @@ var IdentityClient = class {
|
|
|
5823
5844
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/entities/{namespace}");
|
|
5824
5845
|
}
|
|
5825
5846
|
/**
|
|
5826
|
-
* Creates a new entity in the given namespace. This call is idempotent on `externalId` within the namespace: if an entity with the same `externalId` already exists, the existing record is returned instead of creating a duplicate (`created: false`, HTTP 200). To overwrite an existing entity's content instead of returning it unchanged, set `?upsert=true` (also requires the `entities:u:<namespace>` scope). The namespace must be entity-backed (`org`/`client`, or registered via `POST /v1/namespaces`). Requires the `entities:c:<namespace>` scope.
|
|
5847
|
+
* Creates a new entity in the given namespace. This call is idempotent on `externalId` within the namespace: if an entity with the same `externalId` already exists, the existing record is returned instead of creating a duplicate (`created: false`, HTTP 200). To overwrite an existing entity's content instead of returning it unchanged, set `?upsert=true` (also requires the `entities:u:<namespace>` scope). The namespace must be entity-backed (`org`/`client`, or registered via `POST /v1/namespaces`). Requires the `entities:c:<namespace>` scope to create. Being returned the existing entity on a collision is a read of that entity's data and additionally requires the `entities:r:<namespace>` scope — a credential holding `entities:c:<namespace>` alone receives a `400` ("already in use") on collision instead of the entity.
|
|
5827
5848
|
*
|
|
5828
5849
|
* @param {Vectros.CreateEntityRequest} request
|
|
5829
5850
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -6267,7 +6288,7 @@ var IdentityClient = class {
|
|
|
6267
6288
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/namespaces/{namespace}");
|
|
6268
6289
|
}
|
|
6269
6290
|
/**
|
|
6270
|
-
* Updates the mutable fields (`entityBacked`, `defaultSchemaId`) of a registered namespace. The namespace name itself is immutable. Requires a root API key. The reserved built-ins cannot be updated.
|
|
6291
|
+
* Updates the mutable fields (`entityBacked`, `defaultSchemaId`, `specificityRank`) of a registered namespace. The namespace name itself is immutable. Requires a root API key. The reserved built-ins cannot be updated.
|
|
6271
6292
|
*
|
|
6272
6293
|
* @param {Vectros.UpdateNamespaceRequest} request
|
|
6273
6294
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -6280,7 +6301,8 @@ var IdentityClient = class {
|
|
|
6280
6301
|
* await client.identity.updateNamespace({
|
|
6281
6302
|
* namespace: "team",
|
|
6282
6303
|
* body: {
|
|
6283
|
-
* namespace: "team"
|
|
6304
|
+
* namespace: "team",
|
|
6305
|
+
* specificityRank: 1500
|
|
6284
6306
|
* }
|
|
6285
6307
|
* })
|
|
6286
6308
|
*/
|
|
@@ -6445,7 +6467,7 @@ var IdentityClient = class {
|
|
|
6445
6467
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/namespaces");
|
|
6446
6468
|
}
|
|
6447
6469
|
/**
|
|
6448
|
-
* Registers a new scope namespace and declares whether its values resolve to identity entities (`entityBacked`). Requires a root API key. The reserved names `org` and `client` are built in and cannot be registered.
|
|
6470
|
+
* Registers a new scope namespace and declares whether its values resolve to identity entities (`entityBacked`). Also requires `specificityRank`, an explicit, account-unique position in the specificity order used to break recordType schema-resolution ties. Requires a root API key. The reserved names `org` and `client` are built in and cannot be registered.
|
|
6449
6471
|
*
|
|
6450
6472
|
* @param {Vectros.NamespaceRequest} request
|
|
6451
6473
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -6456,7 +6478,8 @@ var IdentityClient = class {
|
|
|
6456
6478
|
*
|
|
6457
6479
|
* @example
|
|
6458
6480
|
* await client.identity.registerNamespace({
|
|
6459
|
-
* namespace: "team"
|
|
6481
|
+
* namespace: "team",
|
|
6482
|
+
* specificityRank: 1500
|
|
6460
6483
|
* })
|
|
6461
6484
|
*/
|
|
6462
6485
|
registerNamespace(request, requestOptions) {
|
|
@@ -6516,7 +6539,7 @@ var IdentityClient = class {
|
|
|
6516
6539
|
* @example
|
|
6517
6540
|
* await client.identity.listUsers({
|
|
6518
6541
|
* externalId: "usr_12345",
|
|
6519
|
-
* startFrom: "
|
|
6542
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl",
|
|
6520
6543
|
* type: "person_v1",
|
|
6521
6544
|
* field: "team",
|
|
6522
6545
|
* value: "engineering",
|
|
@@ -6573,7 +6596,7 @@ var IdentityClient = class {
|
|
|
6573
6596
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/users");
|
|
6574
6597
|
}
|
|
6575
6598
|
/**
|
|
6576
|
-
* Creates a user identity in your account. The operation is idempotent on `externalId`: if a user with the same `externalId` already exists, the existing record is returned instead of creating a duplicate. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing user was returned) tells the two apart. To overwrite an existing user's mutable fields (email, status, payload, schema binding) instead of returning it unchanged, set `?upsert=true` (this also requires the `users:u` scope). Requires the `users:c` scope.
|
|
6599
|
+
* Creates a user identity in your account. The operation is idempotent on `externalId`: if a user with the same `externalId` already exists, the existing record is returned instead of creating a duplicate. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing user was returned) tells the two apart. To overwrite an existing user's mutable fields (email, status, payload, schema binding) instead of returning it unchanged, set `?upsert=true` (this also requires the `users:u` scope). Requires the `users:c` scope to create. Being returned the existing user on a collision is a read of that user's data and additionally requires the `users:r` scope — a credential holding `users:c` alone receives a `400` ("already exists") on collision instead of the user.
|
|
6577
6600
|
*
|
|
6578
6601
|
* @param {Vectros.CreateUserRequest} request
|
|
6579
6602
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -6697,11 +6720,12 @@ var IdentityClient = class {
|
|
|
6697
6720
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/users/{id}");
|
|
6698
6721
|
}
|
|
6699
6722
|
/**
|
|
6700
|
-
* 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.
|
|
6723
|
+
* 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.
|
|
6701
6724
|
*
|
|
6702
6725
|
* @param {Vectros.UpdateUserRequest} request
|
|
6703
6726
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
6704
6727
|
*
|
|
6728
|
+
* @throws {@link Vectros.BadRequestError}
|
|
6705
6729
|
* @throws {@link Vectros.NotFoundError}
|
|
6706
6730
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
6707
6731
|
*
|
|
@@ -6746,6 +6770,8 @@ var IdentityClient = class {
|
|
|
6746
6770
|
}
|
|
6747
6771
|
if (_response.error.reason === "status-code") {
|
|
6748
6772
|
switch (_response.error.statusCode) {
|
|
6773
|
+
case 400:
|
|
6774
|
+
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
6749
6775
|
case 404:
|
|
6750
6776
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
6751
6777
|
case 429:
|
|
@@ -7393,7 +7419,7 @@ var RecordsClient = class {
|
|
|
7393
7419
|
* folderId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
7394
7420
|
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
7395
7421
|
* scope: "group:eng-team",
|
|
7396
|
-
* startFrom: "
|
|
7422
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
7397
7423
|
* })
|
|
7398
7424
|
*/
|
|
7399
7425
|
listRecords(request = {}, requestOptions) {
|
|
@@ -7444,7 +7470,7 @@ var RecordsClient = class {
|
|
|
7444
7470
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/records");
|
|
7445
7471
|
}
|
|
7446
7472
|
/**
|
|
7447
|
-
* Creates a new record of a given type. The `payload` is validated against that type's schema before the record is stored. Identify the type by sending `typeName`, `schemaId`, or both (they must agree); if you send only `schemaId`, the type is taken from that schema. Optionally supply an `externalId` to make the create idempotent — if a record with the same `externalId` already exists in your context, that existing record is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing record was returned) tells the two apart. To overwrite an existing record's content instead of returning it unchanged, set `?upsert=true` (this also requires the `records:u:<type>` scope). Requires the `records:c:<type>` scope.
|
|
7473
|
+
* Creates a new record of a given type. The `payload` is validated against that type's schema before the record is stored. Identify the type by sending `typeName`, `schemaId`, or both (they must agree); if you send only `schemaId`, the type is taken from that schema. Optionally supply an `externalId` to make the create idempotent — if a record with the same `externalId` already exists in your context, that existing record is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing record was returned) tells the two apart. To overwrite an existing record's content instead of returning it unchanged, set `?upsert=true` (this also requires the `records:u:<type>` scope). Requires the `records:c:<type>` scope to create. Being returned the existing record on a collision is a read of that record's data and additionally requires the `records:r:<type>` scope — a credential holding `records:c:<type>` alone receives a `400` ("already exists") on collision instead of the record.
|
|
7448
7474
|
*
|
|
7449
7475
|
* @param {Vectros.CreateRecordRequest} request
|
|
7450
7476
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -7581,6 +7607,7 @@ var RecordsClient = class {
|
|
|
7581
7607
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
7582
7608
|
*
|
|
7583
7609
|
* @throws {@link Vectros.BadRequestError}
|
|
7610
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
7584
7611
|
* @throws {@link Vectros.NotFoundError}
|
|
7585
7612
|
* @throws {@link Vectros.ConflictError}
|
|
7586
7613
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
@@ -7629,6 +7656,8 @@ var RecordsClient = class {
|
|
|
7629
7656
|
switch (_response.error.statusCode) {
|
|
7630
7657
|
case 400:
|
|
7631
7658
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
7659
|
+
case 403:
|
|
7660
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
7632
7661
|
case 404:
|
|
7633
7662
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
7634
7663
|
case 409:
|
|
@@ -7710,6 +7739,7 @@ var RecordsClient = class {
|
|
|
7710
7739
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
7711
7740
|
*
|
|
7712
7741
|
* @throws {@link Vectros.BadRequestError}
|
|
7742
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
7713
7743
|
* @throws {@link Vectros.NotFoundError}
|
|
7714
7744
|
* @throws {@link Vectros.ConflictError}
|
|
7715
7745
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
@@ -7760,6 +7790,8 @@ var RecordsClient = class {
|
|
|
7760
7790
|
switch (_response.error.statusCode) {
|
|
7761
7791
|
case 400:
|
|
7762
7792
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
7793
|
+
case 403:
|
|
7794
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
7763
7795
|
case 404:
|
|
7764
7796
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
7765
7797
|
case 409:
|
|
@@ -7777,7 +7809,15 @@ var RecordsClient = class {
|
|
|
7777
7809
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "PATCH", "/v1/records/{id}");
|
|
7778
7810
|
}
|
|
7779
7811
|
/**
|
|
7780
|
-
* 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.
|
|
7812
|
+
* 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.
|
|
7813
|
+
*
|
|
7814
|
+
* 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`.
|
|
7815
|
+
*
|
|
7816
|
+
* 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.
|
|
7817
|
+
*
|
|
7818
|
+
* 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.
|
|
7819
|
+
*
|
|
7820
|
+
* 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.
|
|
7781
7821
|
*
|
|
7782
7822
|
* @param {Vectros.LookupRecordsRequest} request
|
|
7783
7823
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -7789,22 +7829,40 @@ var RecordsClient = class {
|
|
|
7789
7829
|
* type: "intake_form",
|
|
7790
7830
|
* field: "email",
|
|
7791
7831
|
* value: "jane@example.com",
|
|
7832
|
+
* values: ["open"],
|
|
7792
7833
|
* prefix: "jane",
|
|
7793
|
-
* startFrom: "
|
|
7834
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
7794
7835
|
* })
|
|
7795
7836
|
*/
|
|
7796
7837
|
lookupRecords(request, requestOptions) {
|
|
7797
7838
|
return HttpResponsePromise.fromPromise(this.__lookupRecords(request, requestOptions));
|
|
7798
7839
|
}
|
|
7799
7840
|
async __lookupRecords(request, requestOptions) {
|
|
7800
|
-
const {
|
|
7841
|
+
const {
|
|
7842
|
+
type: type_,
|
|
7843
|
+
field,
|
|
7844
|
+
value,
|
|
7845
|
+
values,
|
|
7846
|
+
from: from_,
|
|
7847
|
+
to,
|
|
7848
|
+
prefix,
|
|
7849
|
+
sortFrom,
|
|
7850
|
+
sortTo,
|
|
7851
|
+
startFrom,
|
|
7852
|
+
limit,
|
|
7853
|
+
includePayload,
|
|
7854
|
+
order
|
|
7855
|
+
} = request;
|
|
7801
7856
|
const _queryParams = {
|
|
7802
7857
|
type: type_,
|
|
7803
7858
|
field,
|
|
7804
7859
|
value,
|
|
7860
|
+
values,
|
|
7805
7861
|
from: from_,
|
|
7806
7862
|
to,
|
|
7807
7863
|
prefix,
|
|
7864
|
+
sortFrom,
|
|
7865
|
+
sortTo,
|
|
7808
7866
|
startFrom,
|
|
7809
7867
|
limit,
|
|
7810
7868
|
includePayload,
|
|
@@ -7848,7 +7906,7 @@ var RecordsClient = class {
|
|
|
7848
7906
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/records/lookup");
|
|
7849
7907
|
}
|
|
7850
7908
|
/**
|
|
7851
|
-
* 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.
|
|
7909
|
+
* 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.
|
|
7852
7910
|
*
|
|
7853
7911
|
* @param {Vectros.RecordLookupRequest} request
|
|
7854
7912
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -8035,13 +8093,15 @@ var SchemasClient = class {
|
|
|
8035
8093
|
* @param {Vectros.ListSchemasRequest} request
|
|
8036
8094
|
* @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
8037
8095
|
*
|
|
8096
|
+
* @throws {@link Vectros.BadRequestError}
|
|
8097
|
+
*
|
|
8038
8098
|
* @example
|
|
8039
8099
|
* await client.schemas.listSchemas({
|
|
8040
8100
|
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
8041
8101
|
* scope: "org:6ba7b810-9dad-11d1-80b4-00c04fd430c8",
|
|
8042
8102
|
* surface: "document",
|
|
8043
8103
|
* recordType: "intake_form",
|
|
8044
|
-
* startFrom: "
|
|
8104
|
+
* startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
|
|
8045
8105
|
* })
|
|
8046
8106
|
*/
|
|
8047
8107
|
listSchemas(request = {}, requestOptions) {
|
|
@@ -8081,16 +8141,21 @@ var SchemasClient = class {
|
|
|
8081
8141
|
return { data: _response.body, rawResponse: _response.rawResponse };
|
|
8082
8142
|
}
|
|
8083
8143
|
if (_response.error.reason === "status-code") {
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8144
|
+
switch (_response.error.statusCode) {
|
|
8145
|
+
case 400:
|
|
8146
|
+
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
8147
|
+
default:
|
|
8148
|
+
throw new VectrosError({
|
|
8149
|
+
statusCode: _response.error.statusCode,
|
|
8150
|
+
body: _response.error.body,
|
|
8151
|
+
rawResponse: _response.rawResponse
|
|
8152
|
+
});
|
|
8153
|
+
}
|
|
8089
8154
|
}
|
|
8090
8155
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/schemas");
|
|
8091
8156
|
}
|
|
8092
8157
|
/**
|
|
8093
|
-
* Defines a new record type with optional field definitions, validation rules, and lookup indexes. Idempotent by `typeName` within the same ownership scope: re-creating an existing `typeName` returns the existing schema rather than failing. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing schema was returned) tells the two apart. To reconcile an existing schema to the submitted shape instead of returning it unchanged, set `?upsert=true` (this also requires the `schemas:
|
|
8158
|
+
* Defines a new record type with optional field definitions, validation rules, and lookup indexes. Idempotent by `typeName` within the same ownership scope: re-creating an existing `typeName` returns the existing schema rather than failing. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing schema was returned) tells the two apart. To reconcile an existing schema to the submitted shape instead of returning it unchanged, set `?upsert=true` (this also requires the `schemas:u` scope; only legal schema changes are applied — migration-locked changes are rejected). Requires the `schemas:c` scope to create. Being returned the existing schema on a collision is a read of that schema's data and additionally requires the `schemas:r` scope — a credential holding `schemas:c` alone receives a `400` ("already in use") on collision instead of the schema.
|
|
8094
8159
|
*
|
|
8095
8160
|
* @param {Vectros.CreateSchemaRequest} request
|
|
8096
8161
|
* @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -8234,12 +8299,13 @@ var SchemasClient = class {
|
|
|
8234
8299
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/schemas/{id}");
|
|
8235
8300
|
}
|
|
8236
8301
|
/**
|
|
8237
|
-
* Updates a record schema. Fields you omit are preserved; `typeName` is immutable and cannot be changed. Collection fields (`fields`, `lookupFields`, `renderHints`, `capabilities`) are replaced in full when supplied. Requires the `schemas:
|
|
8302
|
+
* Updates a record schema. Fields you omit are preserved; `typeName` is immutable and cannot be changed. Collection fields (`fields`, `lookupFields`, `renderHints`, `capabilities`) are replaced in full when supplied. Requires the `schemas:u` scope.
|
|
8238
8303
|
*
|
|
8239
8304
|
* @param {Vectros.UpdateSchemaRequest} request
|
|
8240
8305
|
* @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
8241
8306
|
*
|
|
8242
8307
|
* @throws {@link Vectros.BadRequestError}
|
|
8308
|
+
* @throws {@link Vectros.ForbiddenError}
|
|
8243
8309
|
* @throws {@link Vectros.NotFoundError}
|
|
8244
8310
|
* @throws {@link Vectros.TooManyRequestsError}
|
|
8245
8311
|
*
|
|
@@ -8288,6 +8354,8 @@ var SchemasClient = class {
|
|
|
8288
8354
|
switch (_response.error.statusCode) {
|
|
8289
8355
|
case 400:
|
|
8290
8356
|
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
8357
|
+
case 403:
|
|
8358
|
+
throw new ForbiddenError(_response.error.body, _response.rawResponse);
|
|
8291
8359
|
case 404:
|
|
8292
8360
|
throw new NotFoundError(_response.error.body, _response.rawResponse);
|
|
8293
8361
|
case 429:
|
|
@@ -8303,7 +8371,7 @@ var SchemasClient = class {
|
|
|
8303
8371
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "PUT", "/v1/schemas/{id}");
|
|
8304
8372
|
}
|
|
8305
8373
|
/**
|
|
8306
|
-
* Permanently deletes a record schema. The request is refused with 409 if records of this type still exist — delete those records first, since every record must reference a live schema. Requires the `schemas:
|
|
8374
|
+
* Permanently deletes a record schema. The request is refused with 409 if records of this type still exist — delete those records first, since every record must reference a live schema. A lineage base (a schema other schemas declare `basedOn`) also cannot be deleted while any such variant still exists — delete the variant schema(s) first. Requires the `schemas:d` scope.
|
|
8307
8375
|
*
|
|
8308
8376
|
* @param {Vectros.DeleteSchemaRequest} request
|
|
8309
8377
|
* @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -8605,8 +8673,8 @@ function warnOnSuboptimalKey(key, log) {
|
|
|
8605
8673
|
|
|
8606
8674
|
// src/build-info.ts
|
|
8607
8675
|
var BUILD_INFO = {
|
|
8608
|
-
mcpServer: true ? "0.
|
|
8609
|
-
sdk: true ? "0.
|
|
8676
|
+
mcpServer: true ? "0.13.0" : "dev",
|
|
8677
|
+
sdk: true ? "0.38.0" : "dev"
|
|
8610
8678
|
};
|
|
8611
8679
|
function formatBuildInfo() {
|
|
8612
8680
|
return `vectros-mcp-server ${BUILD_INFO.mcpServer} (sdk ${BUILD_INFO.sdk})`;
|
|
@@ -8649,7 +8717,9 @@ async function resolveIdentity({
|
|
|
8649
8717
|
const derived = {
|
|
8650
8718
|
status: "ok",
|
|
8651
8719
|
environment: deriveEnvironment(environment),
|
|
8652
|
-
principalType: derivePrincipalType(apiKey)
|
|
8720
|
+
principalType: derivePrincipalType(apiKey),
|
|
8721
|
+
mcpServerVersion: BUILD_INFO.mcpServer,
|
|
8722
|
+
sdkVersion: BUILD_INFO.sdk
|
|
8653
8723
|
};
|
|
8654
8724
|
if (!apiKey || !environment) {
|
|
8655
8725
|
log.debug({ component: "identity", mode: "derived-only" }, "identity derived (no fetch)");
|
|
@@ -8677,7 +8747,13 @@ async function resolveIdentity({
|
|
|
8677
8747
|
);
|
|
8678
8748
|
}
|
|
8679
8749
|
}
|
|
8680
|
-
const merged = {
|
|
8750
|
+
const merged = {
|
|
8751
|
+
...derived,
|
|
8752
|
+
...extended,
|
|
8753
|
+
status: "ok",
|
|
8754
|
+
mcpServerVersion: derived.mcpServerVersion,
|
|
8755
|
+
sdkVersion: derived.sdkVersion
|
|
8756
|
+
};
|
|
8681
8757
|
log.debug(
|
|
8682
8758
|
{
|
|
8683
8759
|
component: "identity",
|
|
@@ -8999,14 +9075,23 @@ import { z as z2 } from "zod";
|
|
|
8999
9075
|
function pageItems(page) {
|
|
9000
9076
|
return page.data ?? [];
|
|
9001
9077
|
}
|
|
9078
|
+
var MAX_PAGES = 100;
|
|
9079
|
+
var MAX_ROWS = 1e6;
|
|
9002
9080
|
async function drainPages(fetchPage) {
|
|
9003
9081
|
const all = [];
|
|
9004
9082
|
let startFrom;
|
|
9083
|
+
let pages = 0;
|
|
9005
9084
|
for (; ; ) {
|
|
9006
9085
|
const page = await fetchPage(startFrom);
|
|
9007
|
-
|
|
9086
|
+
pages++;
|
|
9087
|
+
if (page.data?.length) for (const item of page.data) all.push(item);
|
|
9008
9088
|
const next = page.nextCursor;
|
|
9009
9089
|
if (!next) break;
|
|
9090
|
+
if (pages > MAX_PAGES || all.length > MAX_ROWS) {
|
|
9091
|
+
throw new Error(
|
|
9092
|
+
`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.`
|
|
9093
|
+
);
|
|
9094
|
+
}
|
|
9010
9095
|
startFrom = next;
|
|
9011
9096
|
}
|
|
9012
9097
|
return all;
|
|
@@ -9017,14 +9102,23 @@ var MCP_DEFAULT_LIMIT2 = 3;
|
|
|
9017
9102
|
var MCP_MAX_LIMIT2 = 100;
|
|
9018
9103
|
var inputSchema2 = {
|
|
9019
9104
|
type: z2.string().min(1, "type (record type) is required").describe('Record type / schema name (e.g. "patient", "clinical_note").'),
|
|
9020
|
-
// Lookup-mode args — provide `field` plus EXACTLY ONE of: value | from+to | prefix.
|
|
9105
|
+
// Lookup-mode args — provide `field` plus EXACTLY ONE of: value | values | from+to | prefix.
|
|
9021
9106
|
field: z2.string().optional().describe(
|
|
9022
|
-
'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.)'
|
|
9107
|
+
'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.'
|
|
9108
|
+
),
|
|
9109
|
+
value: z2.string().optional().describe(
|
|
9110
|
+
"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)."
|
|
9111
|
+
),
|
|
9112
|
+
values: z2.array(z2.string()).min(1).max(3).optional().describe(
|
|
9113
|
+
'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).'
|
|
9023
9114
|
),
|
|
9024
|
-
value: z2.string().optional().describe("Lookup mode (equality): exact-match value for `field`."),
|
|
9025
9115
|
from: z2.string().optional().describe("Lookup mode (range): inclusive lower bound; requires `to`. Non-sensitive fields only."),
|
|
9026
9116
|
to: z2.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
|
|
9027
9117
|
prefix: z2.string().optional().describe("Lookup mode (prefix): match values starting with this. String, non-sensitive fields only."),
|
|
9118
|
+
sortFrom: z2.string().optional().describe(
|
|
9119
|
+
"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`."
|
|
9120
|
+
),
|
|
9121
|
+
sortTo: z2.string().optional().describe("Lookup mode (equality/composite only): inclusive upper bound on the sort key; pairs with `sortFrom`."),
|
|
9028
9122
|
order: z2.enum(["asc", "desc"]).optional().describe(
|
|
9029
9123
|
"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."
|
|
9030
9124
|
),
|
|
@@ -9041,54 +9135,106 @@ var inputSchema2 = {
|
|
|
9041
9135
|
var recordQuery = ({ client, log }) => ({
|
|
9042
9136
|
name: "record_query",
|
|
9043
9137
|
title: "Record query (list or lookup)",
|
|
9044
|
-
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
|
|
9138
|
+
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.",
|
|
9045
9139
|
inputSchema: inputSchema2,
|
|
9046
9140
|
handler: async (args) => {
|
|
9047
9141
|
const limit = args.limit ?? MCP_DEFAULT_LIMIT2;
|
|
9048
9142
|
const type = args.type;
|
|
9049
9143
|
const field = args.field;
|
|
9050
9144
|
const value = args.value;
|
|
9145
|
+
const values = args.values;
|
|
9051
9146
|
const from = args.from;
|
|
9052
9147
|
const to = args.to;
|
|
9053
9148
|
const prefix = args.prefix;
|
|
9149
|
+
const sortFrom = args.sortFrom;
|
|
9150
|
+
const sortTo = args.sortTo;
|
|
9054
9151
|
const startFrom = args.startFrom;
|
|
9152
|
+
if (!field && (value !== void 0 || values !== void 0 || from !== void 0 || to !== void 0 || prefix !== void 0 || sortFrom !== void 0 || sortTo !== void 0)) {
|
|
9153
|
+
return toolError(
|
|
9154
|
+
"record_query",
|
|
9155
|
+
new Error(
|
|
9156
|
+
"'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."
|
|
9157
|
+
)
|
|
9158
|
+
);
|
|
9159
|
+
}
|
|
9055
9160
|
try {
|
|
9056
9161
|
let page;
|
|
9057
9162
|
if (field) {
|
|
9163
|
+
const fieldNames = field.split(",").map((f) => f.trim()).filter(Boolean);
|
|
9164
|
+
const normalizedField = fieldNames.join(",");
|
|
9165
|
+
const isCompositeField = fieldNames.length > 1;
|
|
9058
9166
|
const hasEquality = value !== void 0;
|
|
9167
|
+
const hasComposite = values !== void 0;
|
|
9059
9168
|
const hasRange = from !== void 0 || to !== void 0;
|
|
9060
9169
|
const hasPrefix = prefix !== void 0;
|
|
9061
|
-
const modes = Number(hasEquality) + Number(hasRange) + Number(hasPrefix);
|
|
9170
|
+
const modes = Number(hasEquality) + Number(hasComposite) + Number(hasRange) + Number(hasPrefix);
|
|
9062
9171
|
if (modes === 0) {
|
|
9063
9172
|
return toolError(
|
|
9064
9173
|
"record_query",
|
|
9065
9174
|
new Error(
|
|
9066
|
-
`lookup on field '${field}' needs one of: 'value' (exact), 'from'+'to' (range), or 'prefix'.`
|
|
9175
|
+
`lookup on field '${field}' needs one of: 'value' (exact), 'values' (composite exact), 'from'+'to' (range), or 'prefix'.`
|
|
9067
9176
|
)
|
|
9068
9177
|
);
|
|
9069
9178
|
}
|
|
9070
9179
|
if (modes > 1) {
|
|
9071
9180
|
return toolError(
|
|
9072
9181
|
"record_query",
|
|
9073
|
-
new Error(
|
|
9182
|
+
new Error(
|
|
9183
|
+
"'value', 'values', 'from'/'to', and 'prefix' are mutually exclusive \u2014 provide exactly one."
|
|
9184
|
+
)
|
|
9074
9185
|
);
|
|
9075
9186
|
}
|
|
9076
9187
|
if (hasRange && !(from !== void 0 && to !== void 0)) {
|
|
9077
9188
|
return toolError("record_query", new Error("range lookup requires both 'from' and 'to'."));
|
|
9078
9189
|
}
|
|
9190
|
+
if (isCompositeField && (hasRange || hasPrefix)) {
|
|
9191
|
+
return toolError(
|
|
9192
|
+
"record_query",
|
|
9193
|
+
new Error(
|
|
9194
|
+
`'field' names ${fieldNames.length} fields ('${normalizedField}') \u2014 a composite lookup is exact-match only ('value' or 'values'), not 'from'/'to'/'prefix'.`
|
|
9195
|
+
)
|
|
9196
|
+
);
|
|
9197
|
+
}
|
|
9198
|
+
if (hasComposite && values.length > fieldNames.length) {
|
|
9199
|
+
return toolError(
|
|
9200
|
+
"record_query",
|
|
9201
|
+
new Error(
|
|
9202
|
+
`'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).`
|
|
9203
|
+
)
|
|
9204
|
+
);
|
|
9205
|
+
}
|
|
9206
|
+
if (sortFrom !== void 0 || sortTo !== void 0) {
|
|
9207
|
+
if (!(hasEquality || hasComposite)) {
|
|
9208
|
+
return toolError(
|
|
9209
|
+
"record_query",
|
|
9210
|
+
new Error("'sortFrom'/'sortTo' narrow a 'value' or 'values' match only \u2014 not 'from'/'to'/'prefix'.")
|
|
9211
|
+
);
|
|
9212
|
+
}
|
|
9213
|
+
if (hasComposite && values.length < fieldNames.length) {
|
|
9214
|
+
return toolError(
|
|
9215
|
+
"record_query",
|
|
9216
|
+
new Error(
|
|
9217
|
+
`'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.`
|
|
9218
|
+
)
|
|
9219
|
+
);
|
|
9220
|
+
}
|
|
9221
|
+
}
|
|
9079
9222
|
page = await client.records.lookupRecordsByBody({
|
|
9080
9223
|
type,
|
|
9081
|
-
field,
|
|
9224
|
+
field: normalizedField,
|
|
9082
9225
|
value,
|
|
9226
|
+
values,
|
|
9083
9227
|
from,
|
|
9084
9228
|
to,
|
|
9085
9229
|
prefix,
|
|
9230
|
+
sortFrom,
|
|
9231
|
+
sortTo,
|
|
9086
9232
|
order: args.order,
|
|
9087
9233
|
startFrom,
|
|
9088
9234
|
limit
|
|
9089
9235
|
});
|
|
9090
9236
|
log.debug(
|
|
9091
|
-
{ tool: "record_query", mode: "lookup", type, field, returned: pageItems(page).length },
|
|
9237
|
+
{ tool: "record_query", mode: "lookup", type, field: normalizedField, returned: pageItems(page).length },
|
|
9092
9238
|
"record_query lookup ok"
|
|
9093
9239
|
);
|
|
9094
9240
|
} else {
|
|
@@ -9121,14 +9267,14 @@ var record_query_default = recordQuery;
|
|
|
9121
9267
|
import { z as z3 } from "zod";
|
|
9122
9268
|
|
|
9123
9269
|
// src/tools/resolve-external-id.ts
|
|
9124
|
-
function validateSelector(sel, entity) {
|
|
9270
|
+
function validateSelector(sel, entity, fieldName) {
|
|
9125
9271
|
const hasId = sel.id !== void 0 && sel.id !== "";
|
|
9126
9272
|
const hasExt = sel.externalId !== void 0 && sel.externalId !== "";
|
|
9127
9273
|
if (hasId && hasExt) {
|
|
9128
|
-
return `Provide either
|
|
9274
|
+
return `Provide either ${fieldName} or externalId (not both) to identify the ${entity}.`;
|
|
9129
9275
|
}
|
|
9130
9276
|
if (!hasId && !hasExt) {
|
|
9131
|
-
return `Provide
|
|
9277
|
+
return `Provide ${fieldName}, or externalId + type, to identify the ${entity}.`;
|
|
9132
9278
|
}
|
|
9133
9279
|
if (hasExt && (sel.type === void 0 || sel.type === "")) {
|
|
9134
9280
|
return "type is required when selecting by externalId (externalId is unique within a type).";
|
|
@@ -9136,7 +9282,7 @@ function validateSelector(sel, entity) {
|
|
|
9136
9282
|
return void 0;
|
|
9137
9283
|
}
|
|
9138
9284
|
async function resolveRecordIdByExternalId(client, sel) {
|
|
9139
|
-
const err = validateSelector(sel, "record");
|
|
9285
|
+
const err = validateSelector(sel, "record", "id");
|
|
9140
9286
|
if (err) return { error: err };
|
|
9141
9287
|
if (sel.id) return { id: sel.id };
|
|
9142
9288
|
const page = await client.records.lookupRecordsByBody({
|
|
@@ -9152,7 +9298,7 @@ async function resolveRecordIdByExternalId(client, sel) {
|
|
|
9152
9298
|
return { id: items[0].id };
|
|
9153
9299
|
}
|
|
9154
9300
|
async function resolveDocumentIdByExternalId(client, sel) {
|
|
9155
|
-
const err = validateSelector(sel, "document");
|
|
9301
|
+
const err = validateSelector(sel, "document", "documentId");
|
|
9156
9302
|
if (err) return { error: err };
|
|
9157
9303
|
if (sel.id) return { id: sel.id };
|
|
9158
9304
|
const page = await client.documents.lookupDocumentsByBody({
|
|
@@ -10027,7 +10173,7 @@ var inputSchema18 = {
|
|
|
10027
10173
|
var currentIdentity = ({ log, apiKey, environment }) => ({
|
|
10028
10174
|
name: "current_identity",
|
|
10029
10175
|
title: "Current identity (tenant + principal scope)",
|
|
10030
|
-
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?'
|
|
10176
|
+
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.",
|
|
10031
10177
|
inputSchema: inputSchema18,
|
|
10032
10178
|
handler: async () => {
|
|
10033
10179
|
try {
|
|
@@ -10505,7 +10651,7 @@ var identityResource = ({ log, apiKey, environment }) => ({
|
|
|
10505
10651
|
name: "identity",
|
|
10506
10652
|
uri: "vectros://identity",
|
|
10507
10653
|
title: "Current identity (tenant + principal scope)",
|
|
10508
|
-
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,
|
|
10654
|
+
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.",
|
|
10509
10655
|
mimeType: "application/json",
|
|
10510
10656
|
read: async () => {
|
|
10511
10657
|
const identity = await resolveIdentity({ log, apiKey, environment });
|