@vectros-ai/mcp-server 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli-http.js CHANGED
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  // src/server.ts
27
27
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
28
28
 
29
- // ../../node_modules/@vectros-ai/sdk/dist/index.mjs
29
+ // node_modules/@vectros-ai/sdk/dist/index.mjs
30
30
  var __defProp2 = Object.defineProperty;
31
31
  var __export = (target, all) => {
32
32
  for (var name in all)
@@ -41,10 +41,13 @@ __export(api_exports, {
41
41
  BatchWriteRequest: () => BatchWriteRequest,
42
42
  BatchWriteResult: () => BatchWriteResult,
43
43
  ChatMessage: () => ChatMessage,
44
+ ChatRequest: () => ChatRequest,
44
45
  ConflictError: () => ConflictError,
45
46
  ContentDeltaEvent: () => ContentDeltaEvent,
46
47
  ContentTooLargeError: () => ContentTooLargeError,
48
+ DocumentAskRequest: () => DocumentAskRequest,
47
49
  DocumentContextEvent: () => DocumentContextEvent,
50
+ DocumentExtraction: () => DocumentExtraction,
48
51
  DocumentLookupRequest: () => DocumentLookupRequest,
49
52
  DocumentPatchRequest: () => DocumentPatchRequest,
50
53
  DocumentRequest: () => DocumentRequest,
@@ -74,8 +77,10 @@ __export(api_exports, {
74
77
  NotImplementedError: () => NotImplementedError,
75
78
  PaymentRequiredError: () => PaymentRequiredError,
76
79
  PingResponse: () => PingResponse,
80
+ RagRequest: () => RagRequest,
77
81
  RagSearch: () => RagSearch,
78
82
  ReadAccessLogResponse: () => ReadAccessLogResponse,
83
+ ReasoningDeltaEvent: () => ReasoningDeltaEvent,
79
84
  RecordLookupRequest: () => RecordLookupRequest,
80
85
  RecordRequest: () => RecordRequest,
81
86
  RecordResponse: () => RecordResponse,
@@ -95,6 +100,7 @@ __export(api_exports, {
95
100
  UserExistsResponse: () => UserExistsResponse,
96
101
  UserRequest: () => UserRequest,
97
102
  UserResponse: () => UserResponse,
103
+ agents: () => agents_exports,
98
104
  auth: () => auth_exports,
99
105
  compliance: () => compliance_exports,
100
106
  documents: () => documents_exports,
@@ -360,6 +366,7 @@ var UnprocessableEntityError = class extends VectrosError {
360
366
  this.name = this.constructor.name;
361
367
  }
362
368
  };
369
+ var agents_exports = {};
363
370
  var auth_exports = {};
364
371
  var ErasureRequest;
365
372
  ((ErasureRequest2) => {
@@ -431,7 +438,33 @@ var ListUsersRequestOrder = {
431
438
  Asc: "asc",
432
439
  Desc: "desc"
433
440
  };
441
+ var ChatRequest;
442
+ ((ChatRequest2) => {
443
+ ChatRequest2.Reasoning = {
444
+ Omit: "omit",
445
+ Stream: "stream"
446
+ };
447
+ })(ChatRequest || (ChatRequest = {}));
448
+ var DocumentAskRequest;
449
+ ((DocumentAskRequest2) => {
450
+ DocumentAskRequest2.Reasoning = {
451
+ Omit: "omit",
452
+ Stream: "stream"
453
+ };
454
+ })(DocumentAskRequest || (DocumentAskRequest = {}));
455
+ var RagRequest;
456
+ ((RagRequest2) => {
457
+ RagRequest2.Reasoning = {
458
+ Omit: "omit",
459
+ Stream: "stream"
460
+ };
461
+ })(RagRequest || (RagRequest = {}));
434
462
  var inference_exports = {};
463
+ __export(inference_exports, {
464
+ ChatRequest: () => ChatRequest,
465
+ DocumentAskRequest: () => DocumentAskRequest,
466
+ RagRequest: () => RagRequest
467
+ });
435
468
  var BatchWriteRequest;
436
469
  ((BatchWriteRequest2) => {
437
470
  BatchWriteRequest2.Atomicity = {
@@ -538,6 +571,18 @@ var DocumentContextEvent;
538
571
  DocumentContext: "document_context"
539
572
  };
540
573
  })(DocumentContextEvent || (DocumentContextEvent = {}));
574
+ var DocumentExtraction;
575
+ ((DocumentExtraction2) => {
576
+ DocumentExtraction2.Outcome = {
577
+ Ok: "OK",
578
+ Truncated: "TRUNCATED",
579
+ NoText: "NO_TEXT",
580
+ Encrypted: "ENCRYPTED",
581
+ Unsupported: "UNSUPPORTED",
582
+ TooLarge: "TOO_LARGE",
583
+ Unreadable: "UNREADABLE"
584
+ };
585
+ })(DocumentExtraction || (DocumentExtraction = {}));
541
586
  var DocumentRequest;
542
587
  ((DocumentRequest2) => {
543
588
  DocumentRequest2.IndexMode = {
@@ -704,6 +749,12 @@ var ReadAccessLogResponse;
704
749
  Rag: "rag"
705
750
  };
706
751
  })(ReadAccessLogResponse || (ReadAccessLogResponse = {}));
752
+ var ReasoningDeltaEvent;
753
+ ((ReasoningDeltaEvent2) => {
754
+ ReasoningDeltaEvent2.Event = {
755
+ ReasoningDelta: "reasoning_delta"
756
+ };
757
+ })(ReasoningDeltaEvent || (ReasoningDeltaEvent = {}));
707
758
  var RecordRequest;
708
759
  ((RecordRequest2) => {
709
760
  RecordRequest2.Status = {
@@ -1837,13 +1888,13 @@ function joinPathSegments(left, right) {
1837
1888
  }
1838
1889
  return `${left}/${right}`;
1839
1890
  }
1840
- function trimSlashes(str) {
1841
- if (!str) return str;
1891
+ function trimSlashes(str2) {
1892
+ if (!str2) return str2;
1842
1893
  let start = 0;
1843
- let end = str.length;
1844
- if (str.startsWith("/")) start = 1;
1845
- if (str.endsWith("/")) end = str.length - 1;
1846
- return start === 0 && end === str.length ? str : str.slice(start, end);
1894
+ let end = str2.length;
1895
+ if (str2.startsWith("/")) start = 1;
1896
+ if (str2.endsWith("/")) end = str2.length - 1;
1897
+ return start === 0 && end === str2.length ? str2 : str2.slice(start, end);
1847
1898
  }
1848
1899
  var Supplier = {
1849
1900
  get: async (supplier) => {
@@ -2266,140 +2317,767 @@ var QueryStringBuilder = class {
2266
2317
  }
2267
2318
  }
2268
2319
  }
2269
- return this;
2320
+ return this;
2321
+ }
2322
+ /**
2323
+ * Returns the assembled query string (without the leading `?`).
2324
+ * Returns an empty string when no parameters were added.
2325
+ */
2326
+ build() {
2327
+ return [...this.parts.values()].join("&");
2328
+ }
2329
+ };
2330
+ var TOKEN_PARAM = "token";
2331
+ var BearerAuthProvider = class _BearerAuthProvider {
2332
+ constructor(options) {
2333
+ this.options = options;
2334
+ }
2335
+ static canCreate(options) {
2336
+ return options?.[TOKEN_PARAM] != null;
2337
+ }
2338
+ async getAuthRequest({
2339
+ endpointMetadata
2340
+ } = {}) {
2341
+ const token = await Supplier.get(this.options[TOKEN_PARAM]);
2342
+ if (token == null) {
2343
+ throw new VectrosError({
2344
+ message: _BearerAuthProvider.AUTH_CONFIG_ERROR_MESSAGE
2345
+ });
2346
+ }
2347
+ return {
2348
+ headers: { Authorization: `Bearer ${token}` }
2349
+ };
2350
+ }
2351
+ };
2352
+ ((BearerAuthProvider2) => {
2353
+ BearerAuthProvider2.AUTH_SCHEME = "BearerAuth";
2354
+ BearerAuthProvider2.AUTH_CONFIG_ERROR_MESSAGE = `Please provide '${TOKEN_PARAM}' when initializing the client`;
2355
+ function createInstance(options) {
2356
+ return new BearerAuthProvider2(options);
2357
+ }
2358
+ BearerAuthProvider2.createInstance = createInstance;
2359
+ })(BearerAuthProvider || (BearerAuthProvider = {}));
2360
+ function mergeHeaders(...headersArray) {
2361
+ const result = {};
2362
+ for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
2363
+ const insensitiveKey = key.toLowerCase();
2364
+ if (value != null) {
2365
+ result[insensitiveKey] = value;
2366
+ } else if (insensitiveKey in result) {
2367
+ delete result[insensitiveKey];
2368
+ }
2369
+ }
2370
+ return result;
2371
+ }
2372
+ function mergeOnlyDefinedHeaders(...headersArray) {
2373
+ const result = {};
2374
+ for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
2375
+ const insensitiveKey = key.toLowerCase();
2376
+ if (value != null) {
2377
+ result[insensitiveKey] = value;
2378
+ }
2379
+ }
2380
+ return result;
2381
+ }
2382
+ function normalizeClientOptions(options) {
2383
+ const headers = mergeHeaders(
2384
+ {
2385
+ "X-Fern-Language": "JavaScript",
2386
+ "X-Fern-Runtime": RUNTIME.type,
2387
+ "X-Fern-Runtime-Version": RUNTIME.version
2388
+ },
2389
+ options?.headers
2390
+ );
2391
+ return {
2392
+ ...options,
2393
+ logging: logging_exports.createLogger(options?.logging),
2394
+ headers
2395
+ };
2396
+ }
2397
+ function normalizeClientOptionsWithAuth(options) {
2398
+ const normalized = normalizeClientOptions(options);
2399
+ if (options.auth === false) {
2400
+ normalized.authProvider = new NoOpAuthProvider();
2401
+ return normalized;
2402
+ }
2403
+ if (options.auth != null) {
2404
+ if (typeof options.auth === "function") {
2405
+ normalized.authProvider = { getAuthRequest: options.auth };
2406
+ return normalized;
2407
+ }
2408
+ if (isAuthProvider(options.auth)) {
2409
+ normalized.authProvider = options.auth;
2410
+ return normalized;
2411
+ }
2412
+ Object.assign(normalized, options.auth);
2413
+ }
2414
+ const normalizedWithNoOpAuthProvider = withNoOpAuthProvider(normalized);
2415
+ normalized.authProvider ?? (normalized.authProvider = new BearerAuthProvider(normalizedWithNoOpAuthProvider));
2416
+ return normalized;
2417
+ }
2418
+ function withNoOpAuthProvider(options) {
2419
+ return {
2420
+ ...options,
2421
+ authProvider: new NoOpAuthProvider()
2422
+ };
2423
+ }
2424
+ function handleNonStatusCodeError(error, rawResponse, method, path2) {
2425
+ switch (error.reason) {
2426
+ case "non-json":
2427
+ throw new VectrosError({
2428
+ statusCode: error.statusCode,
2429
+ body: error.rawBody,
2430
+ rawResponse
2431
+ });
2432
+ case "body-is-null":
2433
+ throw new VectrosError({
2434
+ statusCode: error.statusCode,
2435
+ rawResponse
2436
+ });
2437
+ case "timeout":
2438
+ throw new VectrosTimeoutError(`Timeout exceeded when calling ${method} ${path2}.`, {
2439
+ cause: error.cause
2440
+ });
2441
+ case "unknown":
2442
+ throw new VectrosError({
2443
+ message: error.errorMessage,
2444
+ rawResponse,
2445
+ cause: error.cause
2446
+ });
2447
+ default:
2448
+ throw new VectrosError({
2449
+ message: "Unknown error",
2450
+ rawResponse
2451
+ });
2452
+ }
2453
+ }
2454
+ var AgentsClient = class {
2455
+ constructor(options) {
2456
+ this._options = normalizeClientOptionsWithAuth(options);
2457
+ }
2458
+ /**
2459
+ * Returns a page of the agents in the app context, newest first, each at its latest version. A caller holding `runs:c` but not `agents:r` gets only each agent's `id`, `name`, `description`, `latestVersion` and `status`. Retired and purged agents are left out unless `includeRetired=true`. Requires `agents:r` or `runs:c`.
2460
+ *
2461
+ * @param {Vectros.ListAgentsRequest} request
2462
+ * @param {AgentsClient.RequestOptions} requestOptions - Request-specific configuration.
2463
+ *
2464
+ * @throws {@link Vectros.ForbiddenError}
2465
+ *
2466
+ * @example
2467
+ * await client.agents.listAgents()
2468
+ */
2469
+ listAgents(request = {}, requestOptions) {
2470
+ return HttpResponsePromise.fromPromise(this.__listAgents(request, requestOptions));
2471
+ }
2472
+ async __listAgents(request = {}, requestOptions) {
2473
+ const { contextId, includeRetired, startFrom, limit } = request;
2474
+ const _queryParams = {
2475
+ contextId,
2476
+ includeRetired,
2477
+ startFrom,
2478
+ limit
2479
+ };
2480
+ const _authRequest = await this._options.authProvider.getAuthRequest();
2481
+ const _headers = mergeHeaders(
2482
+ _authRequest.headers,
2483
+ this._options?.headers,
2484
+ requestOptions?.headers
2485
+ );
2486
+ const _response = await fetcher({
2487
+ url: url_exports.join(
2488
+ await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
2489
+ "v1/agents"
2490
+ ),
2491
+ method: "GET",
2492
+ headers: _headers,
2493
+ queryString: url_exports.queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
2494
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
2495
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
2496
+ abortSignal: requestOptions?.abortSignal,
2497
+ fetchFn: this._options?.fetch,
2498
+ logging: this._options.logging
2499
+ });
2500
+ if (_response.ok) {
2501
+ return { data: _response.body, rawResponse: _response.rawResponse };
2502
+ }
2503
+ if (_response.error.reason === "status-code") {
2504
+ switch (_response.error.statusCode) {
2505
+ case 403:
2506
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
2507
+ default:
2508
+ throw new VectrosError({
2509
+ statusCode: _response.error.statusCode,
2510
+ body: _response.error.body,
2511
+ rawResponse: _response.rawResponse
2512
+ });
2513
+ }
2514
+ }
2515
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/agents");
2516
+ }
2517
+ /**
2518
+ * Stores a new agent at version 1, or returns the existing agent of this name unchanged. With `?upsert=true` an existing agent whose definition differs gets a new version instead. Requires the `agents:c` scope (also `agents:u` with `?upsert=true`).
2519
+ *
2520
+ * @param {Vectros.CreateAgentRequest} request
2521
+ * @param {AgentsClient.RequestOptions} requestOptions - Request-specific configuration.
2522
+ *
2523
+ * @throws {@link Vectros.BadRequestError}
2524
+ * @throws {@link Vectros.ForbiddenError}
2525
+ * @throws {@link Vectros.ConflictError}
2526
+ * @throws {@link Vectros.TooManyRequestsError}
2527
+ *
2528
+ * @example
2529
+ * await client.agents.createAgent({
2530
+ * body: {
2531
+ * model: "claude-sonnet-5-5"
2532
+ * }
2533
+ * })
2534
+ */
2535
+ createAgent(request, requestOptions) {
2536
+ return HttpResponsePromise.fromPromise(this.__createAgent(request, requestOptions));
2537
+ }
2538
+ async __createAgent(request, requestOptions) {
2539
+ const { upsert, contextId, body: _body } = request;
2540
+ const _queryParams = {
2541
+ upsert,
2542
+ contextId
2543
+ };
2544
+ const _authRequest = await this._options.authProvider.getAuthRequest();
2545
+ const _headers = mergeHeaders(
2546
+ _authRequest.headers,
2547
+ this._options?.headers,
2548
+ requestOptions?.headers
2549
+ );
2550
+ const _response = await fetcher({
2551
+ url: url_exports.join(
2552
+ await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
2553
+ "v1/agents"
2554
+ ),
2555
+ method: "POST",
2556
+ headers: _headers,
2557
+ contentType: "application/json",
2558
+ queryString: url_exports.queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
2559
+ requestType: "json",
2560
+ body: _body,
2561
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
2562
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
2563
+ abortSignal: requestOptions?.abortSignal,
2564
+ fetchFn: this._options?.fetch,
2565
+ logging: this._options.logging
2566
+ });
2567
+ if (_response.ok) {
2568
+ return { data: _response.body, rawResponse: _response.rawResponse };
2569
+ }
2570
+ if (_response.error.reason === "status-code") {
2571
+ switch (_response.error.statusCode) {
2572
+ case 400:
2573
+ throw new BadRequestError(_response.error.body, _response.rawResponse);
2574
+ case 403:
2575
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
2576
+ case 409:
2577
+ throw new ConflictError(_response.error.body, _response.rawResponse);
2578
+ case 429:
2579
+ throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
2580
+ default:
2581
+ throw new VectrosError({
2582
+ statusCode: _response.error.statusCode,
2583
+ body: _response.error.body,
2584
+ rawResponse: _response.rawResponse
2585
+ });
2586
+ }
2587
+ }
2588
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/agents");
2589
+ }
2590
+ /**
2591
+ * Returns the agent at its latest version, or at `version`. Requires the `agents:r` scope.
2592
+ *
2593
+ * @param {Vectros.GetAgentRequest} request
2594
+ * @param {AgentsClient.RequestOptions} requestOptions - Request-specific configuration.
2595
+ *
2596
+ * @throws {@link Vectros.ForbiddenError}
2597
+ * @throws {@link Vectros.NotFoundError}
2598
+ *
2599
+ * @example
2600
+ * await client.agents.getAgent({
2601
+ * id: "id"
2602
+ * })
2603
+ */
2604
+ getAgent(request, requestOptions) {
2605
+ return HttpResponsePromise.fromPromise(this.__getAgent(request, requestOptions));
2606
+ }
2607
+ async __getAgent(request, requestOptions) {
2608
+ const { id, contextId, version } = request;
2609
+ const _queryParams = {
2610
+ contextId,
2611
+ version
2612
+ };
2613
+ const _authRequest = await this._options.authProvider.getAuthRequest();
2614
+ const _headers = mergeHeaders(
2615
+ _authRequest.headers,
2616
+ this._options?.headers,
2617
+ requestOptions?.headers
2618
+ );
2619
+ const _response = await fetcher({
2620
+ url: url_exports.join(
2621
+ await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
2622
+ `v1/agents/${url_exports.encodePathParam(id)}`
2623
+ ),
2624
+ method: "GET",
2625
+ headers: _headers,
2626
+ queryString: url_exports.queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
2627
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
2628
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
2629
+ abortSignal: requestOptions?.abortSignal,
2630
+ fetchFn: this._options?.fetch,
2631
+ logging: this._options.logging
2632
+ });
2633
+ if (_response.ok) {
2634
+ return { data: _response.body, rawResponse: _response.rawResponse };
2635
+ }
2636
+ if (_response.error.reason === "status-code") {
2637
+ switch (_response.error.statusCode) {
2638
+ case 403:
2639
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
2640
+ case 404:
2641
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
2642
+ default:
2643
+ throw new VectrosError({
2644
+ statusCode: _response.error.statusCode,
2645
+ body: _response.error.body,
2646
+ rawResponse: _response.rawResponse
2647
+ });
2648
+ }
2649
+ }
2650
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/agents/{id}");
2651
+ }
2652
+ /**
2653
+ * Stores the body as the agent's next version. Earlier versions never change. Every optional field you leave out takes its default; `model` is required. With `?restore=true` a retired agent becomes active again with this version. Requires the `agents:u` scope.
2654
+ *
2655
+ * @param {Vectros.UpdateAgentRequest} request
2656
+ * @param {AgentsClient.RequestOptions} requestOptions - Request-specific configuration.
2657
+ *
2658
+ * @throws {@link Vectros.BadRequestError}
2659
+ * @throws {@link Vectros.ForbiddenError}
2660
+ * @throws {@link Vectros.NotFoundError}
2661
+ * @throws {@link Vectros.ConflictError}
2662
+ * @throws {@link Vectros.TooManyRequestsError}
2663
+ *
2664
+ * @example
2665
+ * await client.agents.updateAgent({
2666
+ * id: "id",
2667
+ * body: {
2668
+ * model: "claude-sonnet-5-5"
2669
+ * }
2670
+ * })
2671
+ */
2672
+ updateAgent(request, requestOptions) {
2673
+ return HttpResponsePromise.fromPromise(this.__updateAgent(request, requestOptions));
2674
+ }
2675
+ async __updateAgent(request, requestOptions) {
2676
+ const { id, restore, contextId, body: _body } = request;
2677
+ const _queryParams = {
2678
+ restore,
2679
+ contextId
2680
+ };
2681
+ const _authRequest = await this._options.authProvider.getAuthRequest();
2682
+ const _headers = mergeHeaders(
2683
+ _authRequest.headers,
2684
+ this._options?.headers,
2685
+ requestOptions?.headers
2686
+ );
2687
+ const _response = await fetcher({
2688
+ url: url_exports.join(
2689
+ await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
2690
+ `v1/agents/${url_exports.encodePathParam(id)}`
2691
+ ),
2692
+ method: "PUT",
2693
+ headers: _headers,
2694
+ contentType: "application/json",
2695
+ queryString: url_exports.queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
2696
+ requestType: "json",
2697
+ body: _body,
2698
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
2699
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
2700
+ abortSignal: requestOptions?.abortSignal,
2701
+ fetchFn: this._options?.fetch,
2702
+ logging: this._options.logging
2703
+ });
2704
+ if (_response.ok) {
2705
+ return { data: _response.body, rawResponse: _response.rawResponse };
2706
+ }
2707
+ if (_response.error.reason === "status-code") {
2708
+ switch (_response.error.statusCode) {
2709
+ case 400:
2710
+ throw new BadRequestError(_response.error.body, _response.rawResponse);
2711
+ case 403:
2712
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
2713
+ case 404:
2714
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
2715
+ case 409:
2716
+ throw new ConflictError(_response.error.body, _response.rawResponse);
2717
+ case 429:
2718
+ throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
2719
+ default:
2720
+ throw new VectrosError({
2721
+ statusCode: _response.error.statusCode,
2722
+ body: _response.error.body,
2723
+ rawResponse: _response.rawResponse
2724
+ });
2725
+ }
2726
+ }
2727
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "PUT", "/v1/agents/{id}");
2728
+ }
2729
+ /**
2730
+ * Retires the agent: its versions stay readable, it leaves the default listing, and it can be restored. With `?purge=true` a retired agent's content (every version's prompt, description, tools, model, limits and budget) is erased, leaving its id, name, version numbers and timestamps; its change history keeps only a one-way hash of the prompt, description and tools. If the agent is restored while a purge is running, the purge stops (409) and versions it already erased stay erased; purge it again after retiring it. With `?purge=true&version=N` one version that is not the latest is erased. The name of a purged agent stays reserved. Requires the `agents:d` scope.
2731
+ *
2732
+ * @param {Vectros.DeleteAgentRequest} request
2733
+ * @param {AgentsClient.RequestOptions} requestOptions - Request-specific configuration.
2734
+ *
2735
+ * @throws {@link Vectros.BadRequestError}
2736
+ * @throws {@link Vectros.ForbiddenError}
2737
+ * @throws {@link Vectros.NotFoundError}
2738
+ * @throws {@link Vectros.ConflictError}
2739
+ * @throws {@link Vectros.TooManyRequestsError}
2740
+ *
2741
+ * @example
2742
+ * await client.agents.deleteAgent({
2743
+ * id: "id"
2744
+ * })
2745
+ */
2746
+ deleteAgent(request, requestOptions) {
2747
+ return HttpResponsePromise.fromPromise(this.__deleteAgent(request, requestOptions));
2748
+ }
2749
+ async __deleteAgent(request, requestOptions) {
2750
+ const { id, purge, version, contextId } = request;
2751
+ const _queryParams = {
2752
+ purge,
2753
+ version,
2754
+ contextId
2755
+ };
2756
+ const _authRequest = await this._options.authProvider.getAuthRequest();
2757
+ const _headers = mergeHeaders(
2758
+ _authRequest.headers,
2759
+ this._options?.headers,
2760
+ requestOptions?.headers
2761
+ );
2762
+ const _response = await fetcher({
2763
+ url: url_exports.join(
2764
+ await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
2765
+ `v1/agents/${url_exports.encodePathParam(id)}`
2766
+ ),
2767
+ method: "DELETE",
2768
+ headers: _headers,
2769
+ queryString: url_exports.queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
2770
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
2771
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
2772
+ abortSignal: requestOptions?.abortSignal,
2773
+ fetchFn: this._options?.fetch,
2774
+ logging: this._options.logging
2775
+ });
2776
+ if (_response.ok) {
2777
+ return { data: _response.body, rawResponse: _response.rawResponse };
2778
+ }
2779
+ if (_response.error.reason === "status-code") {
2780
+ switch (_response.error.statusCode) {
2781
+ case 400:
2782
+ throw new BadRequestError(_response.error.body, _response.rawResponse);
2783
+ case 403:
2784
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
2785
+ case 404:
2786
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
2787
+ case 409:
2788
+ throw new ConflictError(_response.error.body, _response.rawResponse);
2789
+ case 429:
2790
+ throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
2791
+ default:
2792
+ throw new VectrosError({
2793
+ statusCode: _response.error.statusCode,
2794
+ body: _response.error.body,
2795
+ rawResponse: _response.rawResponse
2796
+ });
2797
+ }
2798
+ }
2799
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "DELETE", "/v1/agents/{id}");
2800
+ }
2801
+ /**
2802
+ * Returns a page of the agent's versions, newest first: who wrote each and when, and whether it was purged. With `includeContent=true` each entry carries its full definition. Requires the `agents:r` scope.
2803
+ *
2804
+ * @param {Vectros.ListAgentVersionsRequest} request
2805
+ * @param {AgentsClient.RequestOptions} requestOptions - Request-specific configuration.
2806
+ *
2807
+ * @throws {@link Vectros.ForbiddenError}
2808
+ * @throws {@link Vectros.NotFoundError}
2809
+ *
2810
+ * @example
2811
+ * await client.agents.listAgentVersions({
2812
+ * id: "id"
2813
+ * })
2814
+ */
2815
+ listAgentVersions(request, requestOptions) {
2816
+ return HttpResponsePromise.fromPromise(this.__listAgentVersions(request, requestOptions));
2817
+ }
2818
+ async __listAgentVersions(request, requestOptions) {
2819
+ const { id, contextId, includeContent, startFrom, limit } = request;
2820
+ const _queryParams = {
2821
+ contextId,
2822
+ includeContent,
2823
+ startFrom,
2824
+ limit
2825
+ };
2826
+ const _authRequest = await this._options.authProvider.getAuthRequest();
2827
+ const _headers = mergeHeaders(
2828
+ _authRequest.headers,
2829
+ this._options?.headers,
2830
+ requestOptions?.headers
2831
+ );
2832
+ const _response = await fetcher({
2833
+ url: url_exports.join(
2834
+ await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
2835
+ `v1/agents/${url_exports.encodePathParam(id)}/versions`
2836
+ ),
2837
+ method: "GET",
2838
+ headers: _headers,
2839
+ queryString: url_exports.queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
2840
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
2841
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
2842
+ abortSignal: requestOptions?.abortSignal,
2843
+ fetchFn: this._options?.fetch,
2844
+ logging: this._options.logging
2845
+ });
2846
+ if (_response.ok) {
2847
+ return { data: _response.body, rawResponse: _response.rawResponse };
2848
+ }
2849
+ if (_response.error.reason === "status-code") {
2850
+ switch (_response.error.statusCode) {
2851
+ case 403:
2852
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
2853
+ case 404:
2854
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
2855
+ default:
2856
+ throw new VectrosError({
2857
+ statusCode: _response.error.statusCode,
2858
+ body: _response.error.body,
2859
+ rawResponse: _response.rawResponse
2860
+ });
2861
+ }
2862
+ }
2863
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/agents/{id}/versions");
2864
+ }
2865
+ /**
2866
+ * Stops a run. The answer is `202` with the run still `RUNNING`: read it with `GET /v1/runs/{id}` to see it end. A model call in progress is cut within a few seconds; a tool call in progress is first allowed to finish, for up to about 30 seconds, so its change is recorded and billed, and the run stops as soon as it has. The run then ends `CANCELLED` with `errorCode` `CANCELLED_BY_CALLER`, unless it had already completed, in which case it stays `COMPLETED`. Its reservation is settled once, like any run's: a model call in progress when it stopped is charged up to its maximum. A run that has ended (or that had not started, which this cancel ends) answers `200` with its final state, so a cancel can always be retried. A run can be cancelled by the credential that started it (for a token bound to a user, by that user) and by your root key. Requires the `runs:c` scope; with `runs:r` as well the answer is the whole run, otherwise only its `id`, `status`, `terminal`, `reason` and `errorCode`. Takes no body.
2867
+ *
2868
+ * @param {Vectros.CancelRunRequest} request
2869
+ * @param {AgentsClient.RequestOptions} requestOptions - Request-specific configuration.
2870
+ *
2871
+ * @throws {@link Vectros.BadRequestError}
2872
+ * @throws {@link Vectros.UnauthorizedError}
2873
+ * @throws {@link Vectros.ForbiddenError}
2874
+ * @throws {@link Vectros.NotFoundError}
2875
+ * @throws {@link Vectros.TooManyRequestsError}
2876
+ *
2877
+ * @example
2878
+ * await client.agents.cancelRun({
2879
+ * id: "id"
2880
+ * })
2881
+ */
2882
+ cancelRun(request, requestOptions) {
2883
+ return HttpResponsePromise.fromPromise(this.__cancelRun(request, requestOptions));
2884
+ }
2885
+ async __cancelRun(request, requestOptions) {
2886
+ const { id, contextId } = request;
2887
+ const _queryParams = {
2888
+ contextId
2889
+ };
2890
+ const _authRequest = await this._options.authProvider.getAuthRequest();
2891
+ const _headers = mergeHeaders(
2892
+ _authRequest.headers,
2893
+ this._options?.headers,
2894
+ requestOptions?.headers
2895
+ );
2896
+ const _response = await fetcher({
2897
+ url: url_exports.join(
2898
+ await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
2899
+ `v1/runs/${url_exports.encodePathParam(id)}/cancel`
2900
+ ),
2901
+ method: "POST",
2902
+ headers: _headers,
2903
+ queryString: url_exports.queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
2904
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
2905
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
2906
+ abortSignal: requestOptions?.abortSignal,
2907
+ fetchFn: this._options?.fetch,
2908
+ logging: this._options.logging
2909
+ });
2910
+ if (_response.ok) {
2911
+ return { data: _response.body, rawResponse: _response.rawResponse };
2912
+ }
2913
+ if (_response.error.reason === "status-code") {
2914
+ switch (_response.error.statusCode) {
2915
+ case 400:
2916
+ throw new BadRequestError(_response.error.body, _response.rawResponse);
2917
+ case 401:
2918
+ throw new UnauthorizedError(_response.error.body, _response.rawResponse);
2919
+ case 403:
2920
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
2921
+ case 404:
2922
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
2923
+ case 429:
2924
+ throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
2925
+ default:
2926
+ throw new VectrosError({
2927
+ statusCode: _response.error.statusCode,
2928
+ body: _response.error.body,
2929
+ rawResponse: _response.rawResponse
2930
+ });
2931
+ }
2932
+ }
2933
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/runs/{id}/cancel");
2934
+ }
2935
+ /**
2936
+ * Returns the status and metadata of one run: the agent version that ran, how it ended, its tool calls (never their arguments or results) and what it was charged. It never returns text: the answer is delivered only in the run's stream. A run is visible to the credential that started it (for a token bound to a user, to that user) and to your root key, and is kept for 30 days after it ends. Requires the `runs:r` scope.
2937
+ *
2938
+ * @param {Vectros.GetRunRequest} request
2939
+ * @param {AgentsClient.RequestOptions} requestOptions - Request-specific configuration.
2940
+ *
2941
+ * @throws {@link Vectros.BadRequestError}
2942
+ * @throws {@link Vectros.UnauthorizedError}
2943
+ * @throws {@link Vectros.ForbiddenError}
2944
+ * @throws {@link Vectros.NotFoundError}
2945
+ *
2946
+ * @example
2947
+ * await client.agents.getRun({
2948
+ * id: "id"
2949
+ * })
2950
+ */
2951
+ getRun(request, requestOptions) {
2952
+ return HttpResponsePromise.fromPromise(this.__getRun(request, requestOptions));
2953
+ }
2954
+ async __getRun(request, requestOptions) {
2955
+ const { id, contextId } = request;
2956
+ const _queryParams = {
2957
+ contextId
2958
+ };
2959
+ const _authRequest = await this._options.authProvider.getAuthRequest();
2960
+ const _headers = mergeHeaders(
2961
+ _authRequest.headers,
2962
+ this._options?.headers,
2963
+ requestOptions?.headers
2964
+ );
2965
+ const _response = await fetcher({
2966
+ url: url_exports.join(
2967
+ await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
2968
+ `v1/runs/${url_exports.encodePathParam(id)}`
2969
+ ),
2970
+ method: "GET",
2971
+ headers: _headers,
2972
+ queryString: url_exports.queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
2973
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
2974
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
2975
+ abortSignal: requestOptions?.abortSignal,
2976
+ fetchFn: this._options?.fetch,
2977
+ logging: this._options.logging
2978
+ });
2979
+ if (_response.ok) {
2980
+ return { data: _response.body, rawResponse: _response.rawResponse };
2981
+ }
2982
+ if (_response.error.reason === "status-code") {
2983
+ switch (_response.error.statusCode) {
2984
+ case 400:
2985
+ throw new BadRequestError(_response.error.body, _response.rawResponse);
2986
+ case 401:
2987
+ throw new UnauthorizedError(_response.error.body, _response.rawResponse);
2988
+ case 403:
2989
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
2990
+ case 404:
2991
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
2992
+ default:
2993
+ throw new VectrosError({
2994
+ statusCode: _response.error.statusCode,
2995
+ body: _response.error.body,
2996
+ rawResponse: _response.rawResponse
2997
+ });
2998
+ }
2999
+ }
3000
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/runs/{id}");
2270
3001
  }
2271
3002
  /**
2272
- * Returns the assembled query string (without the leading `?`).
2273
- * Returns an empty string when no parameters were added.
3003
+ * Starts a run of a stored agent and streams what it does as Server-Sent Events. The response is always `text/event-stream`, whatever `Accept` you send; its `X-Vectros-Run-Id` header names the run. The run's tool calls act as you, with your own permissions, and only through the tools the agent lists. On a prepaid account the run reserves its budget from your inference balance when it starts and returns what its model calls did not use when it ends; a fixed fee per run, tool calls and run time are billed separately, against your plan. Read each event's `type`; ignore types and fields you do not know; stop at the event with `terminal: true`. A stream that ends without one: read the run with `GET /v1/runs/{id}`. Closing the stream stops the run only on a best-effort basis. Requires the `runs:c` scope, and agent runs switched on for your tenant by an account owner.
2274
3004
  */
2275
- build() {
2276
- return [...this.parts.values()].join("&");
2277
- }
2278
- };
2279
- var TOKEN_PARAM = "token";
2280
- var BearerAuthProvider = class _BearerAuthProvider {
2281
- constructor(options) {
2282
- this.options = options;
2283
- }
2284
- static canCreate(options) {
2285
- return options?.[TOKEN_PARAM] != null;
2286
- }
2287
- async getAuthRequest({
2288
- endpointMetadata
2289
- } = {}) {
2290
- const token = await Supplier.get(this.options[TOKEN_PARAM]);
2291
- if (token == null) {
2292
- throw new VectrosError({
2293
- message: _BearerAuthProvider.AUTH_CONFIG_ERROR_MESSAGE
2294
- });
2295
- }
2296
- return {
2297
- headers: { Authorization: `Bearer ${token}` }
2298
- };
2299
- }
2300
- };
2301
- ((BearerAuthProvider2) => {
2302
- BearerAuthProvider2.AUTH_SCHEME = "BearerAuth";
2303
- BearerAuthProvider2.AUTH_CONFIG_ERROR_MESSAGE = `Please provide '${TOKEN_PARAM}' when initializing the client`;
2304
- function createInstance(options) {
2305
- return new BearerAuthProvider2(options);
2306
- }
2307
- BearerAuthProvider2.createInstance = createInstance;
2308
- })(BearerAuthProvider || (BearerAuthProvider = {}));
2309
- function mergeHeaders(...headersArray) {
2310
- const result = {};
2311
- for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
2312
- const insensitiveKey = key.toLowerCase();
2313
- if (value != null) {
2314
- result[insensitiveKey] = value;
2315
- } else if (insensitiveKey in result) {
2316
- delete result[insensitiveKey];
2317
- }
2318
- }
2319
- return result;
2320
- }
2321
- function mergeOnlyDefinedHeaders(...headersArray) {
2322
- const result = {};
2323
- for (const [key, value] of headersArray.filter((headers) => headers != null).flatMap((headers) => Object.entries(headers))) {
2324
- const insensitiveKey = key.toLowerCase();
2325
- if (value != null) {
2326
- result[insensitiveKey] = value;
2327
- }
3005
+ createRun(request, requestOptions) {
3006
+ return HttpResponsePromise.fromPromise(this.__createRun(request, requestOptions));
2328
3007
  }
2329
- return result;
2330
- }
2331
- function normalizeClientOptions(options) {
2332
- const headers = mergeHeaders(
2333
- {
2334
- "X-Fern-Language": "JavaScript",
2335
- "X-Fern-Runtime": RUNTIME.type,
2336
- "X-Fern-Runtime-Version": RUNTIME.version
2337
- },
2338
- options?.headers
2339
- );
2340
- return {
2341
- ...options,
2342
- logging: logging_exports.createLogger(options?.logging),
2343
- headers
2344
- };
2345
- }
2346
- function normalizeClientOptionsWithAuth(options) {
2347
- const normalized = normalizeClientOptions(options);
2348
- if (options.auth === false) {
2349
- normalized.authProvider = new NoOpAuthProvider();
2350
- return normalized;
2351
- }
2352
- if (options.auth != null) {
2353
- if (typeof options.auth === "function") {
2354
- normalized.authProvider = { getAuthRequest: options.auth };
2355
- return normalized;
3008
+ async __createRun(request, requestOptions) {
3009
+ const { "Idempotency-Key": idempotencyKey, ..._body } = request;
3010
+ const _authRequest = await this._options.authProvider.getAuthRequest();
3011
+ const _headers = mergeHeaders(
3012
+ _authRequest.headers,
3013
+ this._options?.headers,
3014
+ mergeOnlyDefinedHeaders({ "Idempotency-Key": idempotencyKey }),
3015
+ requestOptions?.headers
3016
+ );
3017
+ const _response = await fetcher({
3018
+ url: url_exports.join(
3019
+ await Supplier.get(this._options.baseUrl) ?? await Supplier.get(this._options.environment),
3020
+ "v1/runs"
3021
+ ),
3022
+ method: "POST",
3023
+ headers: _headers,
3024
+ contentType: "application/json",
3025
+ queryString: url_exports.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
3026
+ requestType: "json",
3027
+ body: _body,
3028
+ responseType: "sse",
3029
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
3030
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
3031
+ abortSignal: requestOptions?.abortSignal,
3032
+ fetchFn: this._options?.fetch,
3033
+ logging: this._options.logging
3034
+ });
3035
+ if (_response.ok) {
3036
+ return {
3037
+ data: new Stream({
3038
+ stream: _response.body,
3039
+ parse: (data) => data,
3040
+ signal: requestOptions?.abortSignal,
3041
+ eventShape: {
3042
+ type: "sse"
3043
+ }
3044
+ }),
3045
+ rawResponse: _response.rawResponse
3046
+ };
2356
3047
  }
2357
- if (isAuthProvider(options.auth)) {
2358
- normalized.authProvider = options.auth;
2359
- return normalized;
3048
+ if (_response.error.reason === "status-code") {
3049
+ switch (_response.error.statusCode) {
3050
+ case 400:
3051
+ throw new BadRequestError(_response.error.body, _response.rawResponse);
3052
+ case 401:
3053
+ throw new UnauthorizedError(_response.error.body, _response.rawResponse);
3054
+ case 402:
3055
+ throw new PaymentRequiredError(_response.error.body, _response.rawResponse);
3056
+ case 403:
3057
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
3058
+ case 404:
3059
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
3060
+ case 409:
3061
+ throw new ConflictError(_response.error.body, _response.rawResponse);
3062
+ case 413:
3063
+ throw new ContentTooLargeError(_response.error.body, _response.rawResponse);
3064
+ case 422:
3065
+ throw new UnprocessableEntityError(_response.error.body, _response.rawResponse);
3066
+ case 429:
3067
+ throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
3068
+ case 503:
3069
+ throw new ServiceUnavailableError(_response.error.body, _response.rawResponse);
3070
+ default:
3071
+ throw new VectrosError({
3072
+ statusCode: _response.error.statusCode,
3073
+ body: _response.error.body,
3074
+ rawResponse: _response.rawResponse
3075
+ });
3076
+ }
2360
3077
  }
2361
- Object.assign(normalized, options.auth);
2362
- }
2363
- const normalizedWithNoOpAuthProvider = withNoOpAuthProvider(normalized);
2364
- normalized.authProvider ?? (normalized.authProvider = new BearerAuthProvider(normalizedWithNoOpAuthProvider));
2365
- return normalized;
2366
- }
2367
- function withNoOpAuthProvider(options) {
2368
- return {
2369
- ...options,
2370
- authProvider: new NoOpAuthProvider()
2371
- };
2372
- }
2373
- function handleNonStatusCodeError(error, rawResponse, method, path2) {
2374
- switch (error.reason) {
2375
- case "non-json":
2376
- throw new VectrosError({
2377
- statusCode: error.statusCode,
2378
- body: error.rawBody,
2379
- rawResponse
2380
- });
2381
- case "body-is-null":
2382
- throw new VectrosError({
2383
- statusCode: error.statusCode,
2384
- rawResponse
2385
- });
2386
- case "timeout":
2387
- throw new VectrosTimeoutError(`Timeout exceeded when calling ${method} ${path2}.`, {
2388
- cause: error.cause
2389
- });
2390
- case "unknown":
2391
- throw new VectrosError({
2392
- message: error.errorMessage,
2393
- rawResponse,
2394
- cause: error.cause
2395
- });
2396
- default:
2397
- throw new VectrosError({
2398
- message: "Unknown error",
2399
- rawResponse
2400
- });
3078
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/runs");
2401
3079
  }
2402
- }
3080
+ };
2403
3081
  var AuthClient = class {
2404
3082
  constructor(options) {
2405
3083
  this._options = normalizeClientOptionsWithAuth(options);
@@ -2598,7 +3276,7 @@ var AuthClient = class {
2598
3276
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/admin/keys/scoped");
2599
3277
  }
2600
3278
  /**
2601
- * Creates a scoped API key (an `ssk_*` secret) that inherits its permissions from an existing access profile in your account. The call is idempotent on the combination of tenant, context, user, and key name: re-issuing the same request returns the existing key WITHOUT re-disclosing its raw secret. The raw key is returned ONLY in this response — store it securely, as it cannot be retrieved again. Requires the `keys:c` scope. If you use a scoped credential, `keys:c` alone is not sufficient: because the minted key is durably bound to the profile you name, the profile's effective scopes may not exceed your own, and you may only mint against a profile whose `identityOverrides` values your own identity holds. Minting a key bound to your OWN principal needs nothing further; minting one bound to a DIFFERENT principal additionally requires the `delegate-mint` capability (`granted_capabilities`) on your credential — without it the request is refused. A root API key (`sk_`) is exempt from all three bounds. The profile you name must be `active` AND the user you name must not be `SUSPENDED`: either is refused with `409`, and no root exemption applies to that. Both refusals stop ISSUANCE only. Suspending the profile additionally stops credentials already bound to it, within about five minutes; suspending the user does not stop their existing keys at all. A `PENDING` user is fine.
3279
+ * Creates a scoped API key (an `ssk_*` secret) that inherits its permissions from an existing access profile in your account. The call is idempotent on the combination of tenant, context, user, and key name: re-issuing the same request returns the existing key WITHOUT re-disclosing its raw secret. The raw key is returned ONLY in this response — store it securely, as it cannot be retrieved again. Requires the `keys:c` scope. If you use a scoped credential, `keys:c` alone is not sufficient: because the minted key is durably bound to the profile you name, the profile's effective scopes may not exceed your own, and you may only mint against a profile whose `identityOverrides` values your own identity holds. Minting a key bound to your OWN principal needs nothing further; minting one bound to a DIFFERENT principal additionally requires the `delegate-mint` capability (`granted_capabilities`) on your credential — without it the request is refused. A root API key (`sk_`) is exempt from all three bounds. The profile you name must be `active` AND the user you name must not be `SUSPENDED`: either is refused with `409`, and no root exemption applies to that. Both refusals stop ISSUANCE only. Suspending the profile or the user additionally stops credentials already bound to it, within about five minutes. A `PENDING` user is fine.
2602
3280
  *
2603
3281
  * @param {Vectros.CreateScopedKeyRequest} request
2604
3282
  * @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -2941,14 +3619,13 @@ var AuthClient = class {
2941
3619
  * @throws {@link Vectros.BadRequestError}
2942
3620
  * @throws {@link Vectros.ForbiddenError}
2943
3621
  * @throws {@link Vectros.NotFoundError}
3622
+ * @throws {@link Vectros.ConflictError}
2944
3623
  * @throws {@link Vectros.TooManyRequestsError}
2945
3624
  *
2946
3625
  * @example
2947
3626
  * await client.auth.createAccessProfile({
2948
3627
  * contextId: "contextId",
2949
- * body: {
2950
- * principalId: "usr_6ba7b810-9dad-11d1-80b4-00c04fd430c8"
2951
- * }
3628
+ * body: {}
2952
3629
  * })
2953
3630
  */
2954
3631
  createAccessProfile(request, requestOptions) {
@@ -2993,6 +3670,8 @@ var AuthClient = class {
2993
3670
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
2994
3671
  case 404:
2995
3672
  throw new NotFoundError(_response.error.body, _response.rawResponse);
3673
+ case 409:
3674
+ throw new ConflictError(_response.error.body, _response.rawResponse);
2996
3675
  case 429:
2997
3676
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
2998
3677
  default:
@@ -3076,14 +3755,13 @@ var AuthClient = class {
3076
3755
  * @throws {@link Vectros.BadRequestError}
3077
3756
  * @throws {@link Vectros.PaymentRequiredError}
3078
3757
  * @throws {@link Vectros.ForbiddenError}
3758
+ * @throws {@link Vectros.NotFoundError}
3759
+ * @throws {@link Vectros.ConflictError}
3079
3760
  * @throws {@link Vectros.TooManyRequestsError}
3080
3761
  *
3081
3762
  * @example
3082
3763
  * await client.auth.createAppContext({
3083
- * body: {
3084
- * contextId: "myapp",
3085
- * name: "My Internal App"
3086
- * }
3764
+ * body: {}
3087
3765
  * })
3088
3766
  */
3089
3767
  createAppContext(request, requestOptions) {
@@ -3128,6 +3806,10 @@ var AuthClient = class {
3128
3806
  throw new PaymentRequiredError(_response.error.body, _response.rawResponse);
3129
3807
  case 403:
3130
3808
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
3809
+ case 404:
3810
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
3811
+ case 409:
3812
+ throw new ConflictError(_response.error.body, _response.rawResponse);
3131
3813
  case 429:
3132
3814
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
3133
3815
  default:
@@ -3216,18 +3898,13 @@ var AuthClient = class {
3216
3898
  * @throws {@link Vectros.BadRequestError}
3217
3899
  * @throws {@link Vectros.ForbiddenError}
3218
3900
  * @throws {@link Vectros.NotFoundError}
3901
+ * @throws {@link Vectros.ConflictError}
3219
3902
  * @throws {@link Vectros.TooManyRequestsError}
3220
3903
  *
3221
3904
  * @example
3222
3905
  * await client.auth.createRole({
3223
3906
  * contextId: "contextId",
3224
- * body: {
3225
- * roleId: "engineering-member",
3226
- * name: "Engineering Team Member",
3227
- * scopes: [{
3228
- * allowed_actions: ["records:cru", "search:r"]
3229
- * }]
3230
- * }
3907
+ * body: {}
3231
3908
  * })
3232
3909
  */
3233
3910
  createRole(request, requestOptions) {
@@ -3272,6 +3949,8 @@ var AuthClient = class {
3272
3949
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
3273
3950
  case 404:
3274
3951
  throw new NotFoundError(_response.error.body, _response.rawResponse);
3952
+ case 409:
3953
+ throw new ConflictError(_response.error.body, _response.rawResponse);
3275
3954
  case 429:
3276
3955
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
3277
3956
  default:
@@ -3362,15 +4041,14 @@ var AuthClient = class {
3362
4041
  * @throws {@link Vectros.BadRequestError}
3363
4042
  * @throws {@link Vectros.ForbiddenError}
3364
4043
  * @throws {@link Vectros.NotFoundError}
4044
+ * @throws {@link Vectros.ConflictError}
3365
4045
  * @throws {@link Vectros.TooManyRequestsError}
3366
4046
  *
3367
4047
  * @example
3368
4048
  * await client.auth.updateAccessProfile({
3369
4049
  * contextId: "contextId",
3370
4050
  * principalId: "principalId",
3371
- * body: {
3372
- * principalId: "usr_6ba7b810-9dad-11d1-80b4-00c04fd430c8"
3373
- * }
4051
+ * body: {}
3374
4052
  * })
3375
4053
  */
3376
4054
  updateAccessProfile(request, requestOptions) {
@@ -3412,6 +4090,8 @@ var AuthClient = class {
3412
4090
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
3413
4091
  case 404:
3414
4092
  throw new NotFoundError(_response.error.body, _response.rawResponse);
4093
+ case 409:
4094
+ throw new ConflictError(_response.error.body, _response.rawResponse);
3415
4095
  case 429:
3416
4096
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
3417
4097
  default:
@@ -3558,22 +4238,20 @@ var AuthClient = class {
3558
4238
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/app-contexts/{contextId}");
3559
4239
  }
3560
4240
  /**
3561
- * Updates an app context. This is a partial update: any field you omit (or send as null) keeps its existing value. The `contextId` is immutable and is taken from the URL path, so any `contextId` in the request body is ignored. Patchable fields: `name`, `description`, `companyName`; the per-principal metering trio (`meteringAxis`, `principalBurstLimit`, `principalUsageCap` — only takes effect for a partner with the corresponding account-level feature enabled); `readAccessLogDefault` (the PHI read-access-logging context default); and `identityProjectionClaims` (requires the platform provisioning capability on top of the ordinary scope below — see its own field description). Requires the `app-contexts:u` scope.
4241
+ * Updates an app context. This is a partial update: any field you omit (or send as null) keeps its existing value. The `contextId` is immutable and is taken from the URL path, so any `contextId` in the request body is ignored. Patchable fields: `name`, `description`, `companyName`; the per-principal metering trio (`meteringAxis`, `principalBurstLimit`, `principalUsageCap` — only takes effect for an account with the corresponding feature enabled); `readAccessLogDefault` (the PHI read-access-logging context default); and `identityProjectionClaims` (requires the platform provisioning capability on top of the ordinary scope below — see its own field description). Requires the `app-contexts:u` scope.
3562
4242
  *
3563
4243
  * @param {Vectros.UpdateAppContextRequest} request
3564
4244
  * @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
3565
4245
  *
3566
4246
  * @throws {@link Vectros.ForbiddenError}
3567
4247
  * @throws {@link Vectros.NotFoundError}
4248
+ * @throws {@link Vectros.ConflictError}
3568
4249
  * @throws {@link Vectros.TooManyRequestsError}
3569
4250
  *
3570
4251
  * @example
3571
4252
  * await client.auth.updateAppContext({
3572
4253
  * contextId: "contextId",
3573
- * body: {
3574
- * contextId: "myapp",
3575
- * name: "My Internal App"
3576
- * }
4254
+ * body: {}
3577
4255
  * })
3578
4256
  */
3579
4257
  updateAppContext(request, requestOptions) {
@@ -3613,6 +4291,8 @@ var AuthClient = class {
3613
4291
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
3614
4292
  case 404:
3615
4293
  throw new NotFoundError(_response.error.body, _response.rawResponse);
4294
+ case 409:
4295
+ throw new ConflictError(_response.error.body, _response.rawResponse);
3616
4296
  case 429:
3617
4297
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
3618
4298
  default:
@@ -3769,19 +4449,14 @@ var AuthClient = class {
3769
4449
  *
3770
4450
  * @throws {@link Vectros.ForbiddenError}
3771
4451
  * @throws {@link Vectros.NotFoundError}
4452
+ * @throws {@link Vectros.ConflictError}
3772
4453
  * @throws {@link Vectros.TooManyRequestsError}
3773
4454
  *
3774
4455
  * @example
3775
4456
  * await client.auth.updateRole({
3776
4457
  * contextId: "contextId",
3777
4458
  * roleId: "roleId",
3778
- * body: {
3779
- * roleId: "engineering-member",
3780
- * name: "Engineering Team Member",
3781
- * scopes: [{
3782
- * allowed_actions: ["records:cru", "search:r"]
3783
- * }]
3784
- * }
4459
+ * body: {}
3785
4460
  * })
3786
4461
  */
3787
4462
  updateRole(request, requestOptions) {
@@ -3821,6 +4496,8 @@ var AuthClient = class {
3821
4496
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
3822
4497
  case 404:
3823
4498
  throw new NotFoundError(_response.error.body, _response.rawResponse);
4499
+ case 409:
4500
+ throw new ConflictError(_response.error.body, _response.rawResponse);
3824
4501
  case 429:
3825
4502
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
3826
4503
  default:
@@ -3846,6 +4523,7 @@ var AuthClient = class {
3846
4523
  *
3847
4524
  * @throws {@link Vectros.ForbiddenError}
3848
4525
  * @throws {@link Vectros.NotFoundError}
4526
+ * @throws {@link Vectros.ConflictError}
3849
4527
  * @throws {@link Vectros.TooManyRequestsError}
3850
4528
  *
3851
4529
  * @example
@@ -3888,6 +4566,8 @@ var AuthClient = class {
3888
4566
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
3889
4567
  case 404:
3890
4568
  throw new NotFoundError(_response.error.body, _response.rawResponse);
4569
+ case 409:
4570
+ throw new ConflictError(_response.error.body, _response.rawResponse);
3891
4571
  case 429:
3892
4572
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
3893
4573
  default:
@@ -4169,6 +4849,7 @@ var AuthClient = class {
4169
4849
  * @throws {@link Vectros.BadRequestError}
4170
4850
  * @throws {@link Vectros.ForbiddenError}
4171
4851
  * @throws {@link Vectros.NotFoundError}
4852
+ * @throws {@link Vectros.ConflictError}
4172
4853
  * @throws {@link Vectros.TooManyRequestsError}
4173
4854
  *
4174
4855
  * @example
@@ -4215,6 +4896,8 @@ var AuthClient = class {
4215
4896
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
4216
4897
  case 404:
4217
4898
  throw new NotFoundError(_response.error.body, _response.rawResponse);
4899
+ case 409:
4900
+ throw new ConflictError(_response.error.body, _response.rawResponse);
4218
4901
  case 429:
4219
4902
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
4220
4903
  default:
@@ -4228,7 +4911,7 @@ var AuthClient = class {
4228
4911
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "PUT", "/v1/auth/issuers/{issuerId}");
4229
4912
  }
4230
4913
  /**
4231
- * Deregisters a trusted third-party IdP issuer. Requires a root API key or the bootstrap's provisioning capability. A credential confined to one app context may only deregister an issuer registered in that context; naming one registered in another context returns 404, identically to a nonexistent issuerId. A root API key may deregister any issuer. Refused if any user account was ever created or matched via this issuer (by a prior self-signup or accepted invite, through `POST /v1/auth/token/exchange`) — that access cannot be silently orphaned. This is unconditional on the affected users' `status`: suspending them first does not lift the refusal. **A bound registration cannot be replaced, self-service, within its own app context**: registering a replacement issuer under a different issuerId in the SAME context also fails, because the context's one-active-issuer claim is released only when THIS registration is deleted. Two real options: suspend this issuer (stops new exchanges immediately) and register a replacement under a DIFFERENT app context — note that targets a different context, so this context's existing users/roles/access profiles are not carried over; or contact your platform operator, who can force-release this registration so a replacement may be registered in the SAME context under a new issuerId. **The operator path is not a lighter-weight alternative to the first — it PERMANENTLY RETIRES this issuerId and leaves every bound user unable to ever exchange through it again; it does not preserve continuity for them any better than registering under a different context does.** An issuer that has never been used for an exchange (no bound users yet) can always be deregistered.
4914
+ * Deregisters a trusted third-party IdP issuer. Requires a root API key or the bootstrap's provisioning capability. A credential confined to one app context may only deregister an issuer registered in that context; naming one registered in another context returns 404, identically to a nonexistent issuerId. A root API key may deregister any issuer. Refused if any user account was ever created or matched via this issuer (by a prior self-signup or accepted invite, through `POST /v1/auth/token/exchange`) — that access cannot be silently orphaned. This is unconditional on the affected users' `status`: suspending them first does not lift the refusal. **A bound registration cannot be replaced, self-service, within its own app context**: registering a replacement issuer under a different issuerId in the SAME context also fails, because the context's one-active-issuer claim is released only when THIS registration is deleted. Two real options: suspend this issuer (stops new exchanges immediately) and register a replacement under a DIFFERENT app context — note that targets a different context, so this context's existing users/roles/access profiles are not carried over; or contact support, who can force-release this registration so a replacement may be registered in the SAME context under a new issuerId. **The support path is not a lighter-weight alternative to the first — it PERMANENTLY RETIRES this issuerId and leaves every bound user unable to ever exchange through it again; it does not preserve continuity for them any better than registering under a different context does.** An issuer that has never been used for an exchange (no bound users yet) can always be deregistered.
4232
4915
  *
4233
4916
  * @param {Vectros.DeleteIssuerRequest} request
4234
4917
  * @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -4354,7 +5037,7 @@ var AuthClient = class {
4354
5037
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/auth/issuers");
4355
5038
  }
4356
5039
  /**
4357
- * Registers a trusted third-party IdP issuer that BYO-IdP token exchange (`POST /v1/auth/token/exchange`) may accept a `subject_token` from. Requires a root API key or the CLI bootstrap's provisioning capability — never an ordinary partner-grantable scope. A credential authorized only via the provisioning capability may register only against the app context it is bound to; naming a different one returns 403. A root API key is unaffected and may register against any of its contexts. A registration without `restrictedToDomain` is created `pending_verification` with a one-time challenge (`verificationClaim`, `verificationNonce`, `verificationExpiresAt`) and accepts no token until you prove you control the issuer with `POST /v1/auth/issuers/{issuerId}/verify`; it claims no `(issuer, audience)` pair until then, so registering never reveals whether another tenant holds one. A registration scoped to an already-verified domain with `restrictedToDomain` is `active` at once. Idempotent by `issuerId` within your tenant. If `issuerId` collides with a registration owned by a different app context than the one you're confined to, the request fails with 400 rather than returning that context's configuration. An app context may have at most one active issuer — deregister the existing one first if you need to replace it. One issuer MAY serve several contexts today, each via its own registration row with a distinct `audience`. Optionally name `restrictedToDomain` to scope this registration's (issuer, audience) uniqueness to a specific VERIFIED domain rather than the bare pair — see that field's own description. A domain-scoped registration proves control of the DOMAIN, not of the issuer itself: it routes only tokens carrying that domain's `hd` claim.
5040
+ * Registers a trusted third-party IdP issuer that BYO-IdP token exchange (`POST /v1/auth/token/exchange`) may accept a `subject_token` from. Requires a root API key or the CLI bootstrap's provisioning capability — never an ordinary grantable scope. A credential authorized only via the provisioning capability may register only against the app context it is bound to; naming a different one returns 403. A root API key is unaffected and may register against any of its contexts. A registration without `restrictedToDomain` is created `pending_verification` with a one-time challenge (`verificationClaim`, `verificationNonce`, `verificationExpiresAt`) and accepts no token until you prove you control the issuer with `POST /v1/auth/issuers/{issuerId}/verify`; it claims no `(issuer, audience)` pair until then, so registering never reveals whether another tenant holds one. A registration scoped to an already-verified domain with `restrictedToDomain` is `active` at once. Idempotent by `issuerId` within your tenant. If `issuerId` collides with a registration owned by a different app context than the one you're confined to, the request fails with 400 rather than returning that context's configuration. An app context may have at most one active issuer — deregister the existing one first if you need to replace it. One issuer MAY serve several contexts, each via its own registration row with a distinct `audience`. Optionally name `restrictedToDomain` to scope this registration's (issuer, audience) uniqueness to a specific VERIFIED domain rather than the bare pair — see that field's own description. A domain-scoped registration proves control of the DOMAIN, not of the issuer itself: it routes only tokens carrying that domain's `hd` claim.
4358
5041
  *
4359
5042
  * @param {Vectros.IssuerRequest} request
4360
5043
  * @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -4763,6 +5446,7 @@ var AuthClient = class {
4763
5446
  * @throws {@link Vectros.BadRequestError}
4764
5447
  * @throws {@link Vectros.ForbiddenError}
4765
5448
  * @throws {@link Vectros.NotFoundError}
5449
+ * @throws {@link Vectros.ConflictError}
4766
5450
  * @throws {@link Vectros.TooManyRequestsError}
4767
5451
  *
4768
5452
  * @example
@@ -4810,6 +5494,8 @@ var AuthClient = class {
4810
5494
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
4811
5495
  case 404:
4812
5496
  throw new NotFoundError(_response.error.body, _response.rawResponse);
5497
+ case 409:
5498
+ throw new ConflictError(_response.error.body, _response.rawResponse);
4813
5499
  case 429:
4814
5500
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
4815
5501
  default:
@@ -4909,6 +5595,7 @@ var AuthClient = class {
4909
5595
  * @throws {@link Vectros.UnauthorizedError}
4910
5596
  * @throws {@link Vectros.ForbiddenError}
4911
5597
  * @throws {@link Vectros.NotFoundError}
5598
+ * @throws {@link Vectros.ContentTooLargeError}
4912
5599
  * @throws {@link Vectros.TooManyRequestsError}
4913
5600
  *
4914
5601
  * @example
@@ -4953,6 +5640,8 @@ var AuthClient = class {
4953
5640
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
4954
5641
  case 404:
4955
5642
  throw new NotFoundError(_response.error.body, _response.rawResponse);
5643
+ case 413:
5644
+ throw new ContentTooLargeError(_response.error.body, _response.rawResponse);
4956
5645
  case 429:
4957
5646
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
4958
5647
  default:
@@ -5092,7 +5781,7 @@ var ComplianceClient = class {
5092
5781
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/erasure-requests/{id}");
5093
5782
  }
5094
5783
  /**
5095
- * Submits an asynchronous job to export your account's data, or a single end-subject's data, across the requested contexts. The request returns 202 with an `exportJobId`; poll `GET /v1/admin/export/{id}` until the job completes to obtain a short-lived presigned download URL and a manifest describing the payload. Requires a root API key — a scoped credential is rejected with 403.
5784
+ * Reserved: with a root API key this operation answers `501` and starts no job. The request and response shapes are published so that integrations can be written against them: a request names the contexts, or a single end-subject, to export, and the response carries an `exportJobId` that `GET /v1/admin/export/{id}` reports on. Requires a root API key — a scoped credential is rejected with 403.
5096
5785
  *
5097
5786
  * @param {Vectros.ExportRequest} request
5098
5787
  * @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -5153,7 +5842,7 @@ var ComplianceClient = class {
5153
5842
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/admin/export");
5154
5843
  }
5155
5844
  /**
5156
- * Polls an export job by id. While the job is still running this returns its status only; once it completes, the response also includes a short-lived presigned download URL and a manifest (format version and per-context counts). Requires a root API key.
5845
+ * Reserved: with a root API key this operation answers `501`. Its response shape is the one the export operation above refers to: the job status, and a short-lived presigned download URL and a manifest (format version and per-context counts) for a completed job. Requires a root API key.
5157
5846
  *
5158
5847
  * @param {Vectros.GetExportRequest} request
5159
5848
  * @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -5219,7 +5908,7 @@ var DocumentsClient = class {
5219
5908
  this._options = normalizeClientOptionsWithAuth(options);
5220
5909
  }
5221
5910
  /**
5222
- * Returns a paginated list of your documents, optionally filtered by folder (`folderId`) and/or owner (`userId` or `scope`). The response is a `{data, nextCursor}` envelope; pass `nextCursor` back as `startFrom` to fetch the next page. Requires the `documents:r` scope.
5911
+ * Returns a paginated list of your documents, optionally filtered by folder (`folderId`), owner (`userId` or `scope`) and/or type (`type`). The response is a `{data, nextCursor}` envelope; pass `nextCursor` back as `startFrom` to fetch the next page. A page can hold fewer documents than `limit`, or none, while `nextCursor` is still set: keep paging until `nextCursor` is null. Requires the `documents:r` scope.
5223
5912
  *
5224
5913
  * @param {Vectros.ListDocumentsRequest} request
5225
5914
  * @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -5229,6 +5918,7 @@ var DocumentsClient = class {
5229
5918
  * userId: "550e8400-e29b-41d4-a716-446655440000",
5230
5919
  * scope: "group:eng-team",
5231
5920
  * folderId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
5921
+ * type: "investigation_report",
5232
5922
  * startFrom: "b3BhcXVlLWN1cnNvci1mcm9tLXRoZS1wcmV2aW91cy1wYWdl"
5233
5923
  * })
5234
5924
  */
@@ -5236,11 +5926,12 @@ var DocumentsClient = class {
5236
5926
  return HttpResponsePromise.fromPromise(this.__listDocuments(request, requestOptions));
5237
5927
  }
5238
5928
  async __listDocuments(request = {}, requestOptions) {
5239
- const { userId, scope, folderId, startFrom, limit } = request;
5929
+ const { userId, scope, folderId, type: type_, startFrom, limit } = request;
5240
5930
  const _queryParams = {
5241
5931
  userId,
5242
5932
  scope,
5243
5933
  folderId,
5934
+ type: type_,
5244
5935
  startFrom,
5245
5936
  limit
5246
5937
  };
@@ -5284,13 +5975,13 @@ var DocumentsClient = class {
5284
5975
  *
5285
5976
  * @throws {@link Vectros.BadRequestError}
5286
5977
  * @throws {@link Vectros.ForbiddenError}
5978
+ * @throws {@link Vectros.NotFoundError}
5979
+ * @throws {@link Vectros.ConflictError}
5287
5980
  * @throws {@link Vectros.TooManyRequestsError}
5288
5981
  *
5289
5982
  * @example
5290
5983
  * await client.documents.ingestDocument({
5291
- * body: {
5292
- * title: "Patient Intake Form \u2014 Jane Doe"
5293
- * }
5984
+ * body: {}
5294
5985
  * })
5295
5986
  */
5296
5987
  ingestDocument(request, requestOptions) {
@@ -5335,6 +6026,10 @@ var DocumentsClient = class {
5335
6026
  throw new BadRequestError(_response.error.body, _response.rawResponse);
5336
6027
  case 403:
5337
6028
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
6029
+ case 404:
6030
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
6031
+ case 409:
6032
+ throw new ConflictError(_response.error.body, _response.rawResponse);
5338
6033
  case 429:
5339
6034
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
5340
6035
  default:
@@ -5416,9 +6111,7 @@ var DocumentsClient = class {
5416
6111
  * @example
5417
6112
  * await client.documents.updateDocument({
5418
6113
  * id: "id",
5419
- * body: {
5420
- * title: "Patient Intake Form \u2014 Jane Doe"
5421
- * }
6114
+ * body: {}
5422
6115
  * })
5423
6116
  */
5424
6117
  updateDocument(request, requestOptions) {
@@ -5482,6 +6175,7 @@ var DocumentsClient = class {
5482
6175
  * @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
5483
6176
  *
5484
6177
  * @throws {@link Vectros.NotFoundError}
6178
+ * @throws {@link Vectros.ConflictError}
5485
6179
  * @throws {@link Vectros.TooManyRequestsError}
5486
6180
  *
5487
6181
  * @example
@@ -5521,6 +6215,8 @@ var DocumentsClient = class {
5521
6215
  switch (_response.error.statusCode) {
5522
6216
  case 404:
5523
6217
  throw new NotFoundError(_response.error.body, _response.rawResponse);
6218
+ case 409:
6219
+ throw new ConflictError(_response.error.body, _response.rawResponse);
5524
6220
  case 429:
5525
6221
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
5526
6222
  default:
@@ -5813,11 +6509,12 @@ var DocumentsClient = class {
5813
6509
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents/{id}/download");
5814
6510
  }
5815
6511
  /**
5816
- * Returns the document's full text body when it is retained: always available for text-ingested documents, and for file-uploaded documents unless they were uploaded with `storeText=false` (which discards the extracted text once indexing completes — the original file remains available via `GET /{id}/download`). Returns 404 when the document does not exist, its text was not retained, or extraction has not yet completed. Requires the `documents:r` scope.
6512
+ * Returns the document's full text body when it is retained: retained for text-ingested documents, and for file-uploaded documents unless they were uploaded with `storeText=false` (which discards the extracted text once indexing completes — the original file remains available via `GET /v1/documents/{id}/download`). Returns 404 when the document does not exist, its text was not retained, extraction has not yet completed, or no text could be extracted from its file (see the document's `extraction`). To read a long text in parts, pass `limit` (and `offset` from the second part on): offsets and lengths count Unicode characters (code points), `totalLength` is the length of the whole text, and `nextOffset` is where the next part starts, absent once the end is reached. Requires the `documents:r` scope.
5817
6513
  *
5818
6514
  * @param {Vectros.GetDocumentTextRequest} request
5819
6515
  * @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
5820
6516
  *
6517
+ * @throws {@link Vectros.BadRequestError}
5821
6518
  * @throws {@link Vectros.NotFoundError}
5822
6519
  *
5823
6520
  * @example
@@ -5829,7 +6526,11 @@ var DocumentsClient = class {
5829
6526
  return HttpResponsePromise.fromPromise(this.__getDocumentText(request, requestOptions));
5830
6527
  }
5831
6528
  async __getDocumentText(request, requestOptions) {
5832
- const { id } = request;
6529
+ const { id, offset, limit } = request;
6530
+ const _queryParams = {
6531
+ offset,
6532
+ limit
6533
+ };
5833
6534
  const _authRequest = await this._options.authProvider.getAuthRequest();
5834
6535
  const _headers = mergeHeaders(
5835
6536
  _authRequest.headers,
@@ -5843,7 +6544,7 @@ var DocumentsClient = class {
5843
6544
  ),
5844
6545
  method: "GET",
5845
6546
  headers: _headers,
5846
- queryString: url_exports.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
6547
+ queryString: url_exports.queryBuilder().addMany(_queryParams).mergeAdditional(requestOptions?.queryParams).build(),
5847
6548
  timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1e3,
5848
6549
  maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
5849
6550
  abortSignal: requestOptions?.abortSignal,
@@ -5855,6 +6556,8 @@ var DocumentsClient = class {
5855
6556
  }
5856
6557
  if (_response.error.reason === "status-code") {
5857
6558
  switch (_response.error.statusCode) {
6559
+ case 400:
6560
+ throw new BadRequestError(_response.error.body, _response.rawResponse);
5858
6561
  case 404:
5859
6562
  throw new NotFoundError(_response.error.body, _response.rawResponse);
5860
6563
  default:
@@ -5933,6 +6636,7 @@ var DocumentsClient = class {
5933
6636
  *
5934
6637
  * @throws {@link Vectros.BadRequestError}
5935
6638
  * @throws {@link Vectros.ForbiddenError}
6639
+ * @throws {@link Vectros.ConflictError}
5936
6640
  * @throws {@link Vectros.TooManyRequestsError}
5937
6641
  *
5938
6642
  * @example
@@ -5982,6 +6686,8 @@ var DocumentsClient = class {
5982
6686
  throw new BadRequestError(_response.error.body, _response.rawResponse);
5983
6687
  case 403:
5984
6688
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
6689
+ case 409:
6690
+ throw new ConflictError(_response.error.body, _response.rawResponse);
5985
6691
  case 429:
5986
6692
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
5987
6693
  default:
@@ -6065,13 +6771,13 @@ var FoldersClient = class {
6065
6771
  *
6066
6772
  * @throws {@link Vectros.BadRequestError}
6067
6773
  * @throws {@link Vectros.ForbiddenError}
6774
+ * @throws {@link Vectros.NotFoundError}
6775
+ * @throws {@link Vectros.ConflictError}
6068
6776
  * @throws {@link Vectros.TooManyRequestsError}
6069
6777
  *
6070
6778
  * @example
6071
6779
  * await client.folders.createFolder({
6072
- * body: {
6073
- * name: "Patient Records 2024"
6074
- * }
6780
+ * body: {}
6075
6781
  * })
6076
6782
  */
6077
6783
  createFolder(request, requestOptions) {
@@ -6114,6 +6820,10 @@ var FoldersClient = class {
6114
6820
  throw new BadRequestError(_response.error.body, _response.rawResponse);
6115
6821
  case 403:
6116
6822
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
6823
+ case 404:
6824
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
6825
+ case 409:
6826
+ throw new ConflictError(_response.error.body, _response.rawResponse);
6117
6827
  case 429:
6118
6828
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
6119
6829
  default:
@@ -6189,14 +6899,13 @@ var FoldersClient = class {
6189
6899
  *
6190
6900
  * @throws {@link Vectros.ForbiddenError}
6191
6901
  * @throws {@link Vectros.NotFoundError}
6902
+ * @throws {@link Vectros.ConflictError}
6192
6903
  * @throws {@link Vectros.TooManyRequestsError}
6193
6904
  *
6194
6905
  * @example
6195
6906
  * await client.folders.updateFolder({
6196
6907
  * id: "id",
6197
- * body: {
6198
- * name: "Patient Records 2024"
6199
- * }
6908
+ * body: {}
6200
6909
  * })
6201
6910
  */
6202
6911
  updateFolder(request, requestOptions) {
@@ -6236,6 +6945,8 @@ var FoldersClient = class {
6236
6945
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
6237
6946
  case 404:
6238
6947
  throw new NotFoundError(_response.error.body, _response.rawResponse);
6948
+ case 409:
6949
+ throw new ConflictError(_response.error.body, _response.rawResponse);
6239
6950
  case 429:
6240
6951
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
6241
6952
  default:
@@ -6256,6 +6967,7 @@ var FoldersClient = class {
6256
6967
  *
6257
6968
  * @throws {@link Vectros.BadRequestError}
6258
6969
  * @throws {@link Vectros.NotFoundError}
6970
+ * @throws {@link Vectros.ConflictError}
6259
6971
  * @throws {@link Vectros.TooManyRequestsError}
6260
6972
  *
6261
6973
  * @example
@@ -6297,6 +7009,8 @@ var FoldersClient = class {
6297
7009
  throw new BadRequestError(_response.error.body, _response.rawResponse);
6298
7010
  case 404:
6299
7011
  throw new NotFoundError(_response.error.body, _response.rawResponse);
7012
+ case 409:
7013
+ throw new ConflictError(_response.error.body, _response.rawResponse);
6300
7014
  case 429:
6301
7015
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
6302
7016
  default:
@@ -6310,7 +7024,7 @@ var FoldersClient = class {
6310
7024
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "DELETE", "/v1/folders/{id}");
6311
7025
  }
6312
7026
  /**
6313
- * Partially updates a folder using an RFC 7386 JSON Merge Patch. The `name`, `description`, and ownership fields (`userId`, `scopes`) are applied when present and left unchanged when omitted; sending any of these as null is rejected, because clearing a field is not supported in this release (omit it instead). `slug` and `parentFolderId` are immutable — a folder cannot be re-slugged or moved via the API — and the request is rejected if either is present. Pass `expectedVersion` for optimistic concurrency (you get a 409 if the folder changed since you last read it). Requires the `folders:u` scope.
7027
+ * Partially updates a folder using an RFC 7386 JSON Merge Patch. The `name`, `description`, and ownership fields (`userId`, `scopes`) are applied when present and left unchanged when omitted; sending any of these as null is rejected, because clearing a field is not supported (omit it instead). `slug` and `parentFolderId` are immutable — a folder cannot be re-slugged or moved via the API — and the request is rejected if either is present. Pass `expectedVersion` for optimistic concurrency (you get a 409 if the folder changed since you last read it). Requires the `folders:u` scope.
6314
7028
  *
6315
7029
  * @param {Vectros.PatchFolderRequest} request
6316
7030
  * @param {FoldersClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -6324,9 +7038,7 @@ var FoldersClient = class {
6324
7038
  * @example
6325
7039
  * await client.folders.patchFolder({
6326
7040
  * id: "id",
6327
- * body: {
6328
- * name: "Patient Records 2024"
6329
- * }
7041
+ * body: {}
6330
7042
  * })
6331
7043
  */
6332
7044
  patchFolder(request, requestOptions) {
@@ -6533,15 +7245,15 @@ var IdentityClient = class {
6533
7245
  *
6534
7246
  * @throws {@link Vectros.BadRequestError}
6535
7247
  * @throws {@link Vectros.ForbiddenError}
7248
+ * @throws {@link Vectros.NotFoundError}
7249
+ * @throws {@link Vectros.ConflictError}
6536
7250
  * @throws {@link Vectros.TooManyRequestsError}
6537
7251
  *
6538
7252
  * @example
6539
7253
  * await client.identity.createEntity({
6540
7254
  * namespace: "team",
6541
7255
  * contextId: "myapp",
6542
- * body: {
6543
- * externalId: "team_eng_platform"
6544
- * }
7256
+ * body: {}
6545
7257
  * })
6546
7258
  */
6547
7259
  createEntity(request, requestOptions) {
@@ -6585,6 +7297,10 @@ var IdentityClient = class {
6585
7297
  throw new BadRequestError(_response.error.body, _response.rawResponse);
6586
7298
  case 403:
6587
7299
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
7300
+ case 404:
7301
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
7302
+ case 409:
7303
+ throw new ConflictError(_response.error.body, _response.rawResponse);
6588
7304
  case 429:
6589
7305
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
6590
7306
  default:
@@ -6665,6 +7381,7 @@ var IdentityClient = class {
6665
7381
  *
6666
7382
  * @throws {@link Vectros.BadRequestError}
6667
7383
  * @throws {@link Vectros.NotFoundError}
7384
+ * @throws {@link Vectros.ConflictError}
6668
7385
  * @throws {@link Vectros.TooManyRequestsError}
6669
7386
  *
6670
7387
  * @example
@@ -6672,9 +7389,7 @@ var IdentityClient = class {
6672
7389
  * namespace: "team",
6673
7390
  * id: "id",
6674
7391
  * contextId: "myapp",
6675
- * body: {
6676
- * externalId: "team_eng_platform"
6677
- * }
7392
+ * body: {}
6678
7393
  * })
6679
7394
  */
6680
7395
  updateEntity(request, requestOptions) {
@@ -6717,6 +7432,8 @@ var IdentityClient = class {
6717
7432
  throw new BadRequestError(_response.error.body, _response.rawResponse);
6718
7433
  case 404:
6719
7434
  throw new NotFoundError(_response.error.body, _response.rawResponse);
7435
+ case 409:
7436
+ throw new ConflictError(_response.error.body, _response.rawResponse);
6720
7437
  case 429:
6721
7438
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
6722
7439
  default:
@@ -6736,6 +7453,7 @@ var IdentityClient = class {
6736
7453
  * @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
6737
7454
  *
6738
7455
  * @throws {@link Vectros.NotFoundError}
7456
+ * @throws {@link Vectros.ConflictError}
6739
7457
  * @throws {@link Vectros.TooManyRequestsError}
6740
7458
  *
6741
7459
  * @example
@@ -6780,6 +7498,8 @@ var IdentityClient = class {
6780
7498
  switch (_response.error.statusCode) {
6781
7499
  case 404:
6782
7500
  throw new NotFoundError(_response.error.body, _response.rawResponse);
7501
+ case 409:
7502
+ throw new ConflictError(_response.error.body, _response.rawResponse);
6783
7503
  case 429:
6784
7504
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
6785
7505
  default:
@@ -7003,15 +7723,13 @@ var IdentityClient = class {
7003
7723
  *
7004
7724
  * @throws {@link Vectros.ForbiddenError}
7005
7725
  * @throws {@link Vectros.NotFoundError}
7726
+ * @throws {@link Vectros.ConflictError}
7006
7727
  * @throws {@link Vectros.TooManyRequestsError}
7007
7728
  *
7008
7729
  * @example
7009
7730
  * await client.identity.updateNamespace({
7010
7731
  * namespace: "team",
7011
- * body: {
7012
- * namespace: "team",
7013
- * specificityRank: 1500
7014
- * }
7732
+ * body: {}
7015
7733
  * })
7016
7734
  */
7017
7735
  updateNamespace(request, requestOptions) {
@@ -7054,6 +7772,8 @@ var IdentityClient = class {
7054
7772
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
7055
7773
  case 404:
7056
7774
  throw new NotFoundError(_response.error.body, _response.rawResponse);
7775
+ case 409:
7776
+ throw new ConflictError(_response.error.body, _response.rawResponse);
7057
7777
  case 429:
7058
7778
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
7059
7779
  default:
@@ -7074,6 +7794,7 @@ var IdentityClient = class {
7074
7794
  *
7075
7795
  * @throws {@link Vectros.ForbiddenError}
7076
7796
  * @throws {@link Vectros.NotFoundError}
7797
+ * @throws {@link Vectros.ConflictError}
7077
7798
  * @throws {@link Vectros.TooManyRequestsError}
7078
7799
  *
7079
7800
  * @example
@@ -7118,6 +7839,8 @@ var IdentityClient = class {
7118
7839
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
7119
7840
  case 404:
7120
7841
  throw new NotFoundError(_response.error.body, _response.rawResponse);
7842
+ case 409:
7843
+ throw new ConflictError(_response.error.body, _response.rawResponse);
7121
7844
  case 429:
7122
7845
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
7123
7846
  default:
@@ -7182,7 +7905,7 @@ var IdentityClient = class {
7182
7905
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/namespaces");
7183
7906
  }
7184
7907
  /**
7185
- * 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 or one of the CLI bootstrap's two provisioning capabilities — never an ordinary partner-grantable scope. A bootstrap credential's registration is confined to its own app context UNLESS it additionally holds the tenant-wide namespace-provisioning capability and `contextId` is omitted, in which case it may register a TENANT-WIDE namespace (visible to every context). `org` and `client` are reserved names, registered the same way as any other namespace.
7908
+ * 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 or one of the CLI bootstrap's two provisioning capabilities — never an ordinary grantable scope. A bootstrap credential's registration is confined to its own app context UNLESS it additionally holds the tenant-wide namespace-provisioning capability and `contextId` is omitted, in which case it may register a TENANT-WIDE namespace (visible to every context). `org` and `client` are reserved names, registered the same way as any other namespace.
7186
7909
  *
7187
7910
  * @param {Vectros.RegisterNamespaceRequest} request
7188
7911
  * @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -7193,10 +7916,7 @@ var IdentityClient = class {
7193
7916
  *
7194
7917
  * @example
7195
7918
  * await client.identity.registerNamespace({
7196
- * body: {
7197
- * namespace: "team",
7198
- * specificityRank: 1500
7199
- * }
7919
+ * body: {}
7200
7920
  * })
7201
7921
  */
7202
7922
  registerNamespace(request, requestOptions) {
@@ -7324,13 +8044,12 @@ var IdentityClient = class {
7324
8044
  *
7325
8045
  * @throws {@link Vectros.BadRequestError}
7326
8046
  * @throws {@link Vectros.ForbiddenError}
8047
+ * @throws {@link Vectros.ConflictError}
7327
8048
  * @throws {@link Vectros.TooManyRequestsError}
7328
8049
  *
7329
8050
  * @example
7330
8051
  * await client.identity.createUser({
7331
- * body: {
7332
- * externalId: "usr_12345"
7333
- * }
8052
+ * body: {}
7334
8053
  * })
7335
8054
  */
7336
8055
  createUser(request, requestOptions) {
@@ -7373,6 +8092,8 @@ var IdentityClient = class {
7373
8092
  throw new BadRequestError(_response.error.body, _response.rawResponse);
7374
8093
  case 403:
7375
8094
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
8095
+ case 409:
8096
+ throw new ConflictError(_response.error.body, _response.rawResponse);
7376
8097
  case 429:
7377
8098
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
7378
8099
  default:
@@ -7441,21 +8162,21 @@ var IdentityClient = class {
7441
8162
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/users/{id}");
7442
8163
  }
7443
8164
  /**
7444
- * 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. **`externalSubject` set this way is NOT an authentication binding and does not enable sign-in anywhere** — not the Vectros DevPortal/Admin App/web apps, and not `/v1/auth/token/exchange` either; both are granted only by the invitee authenticating themselves. If the invitee needs dev-portal/web-app access, send them the invitation link and let them accept it directly. If the invitee needs to sign in via token exchange, have them redeem `inviteToken` themselves at `/v1/auth/token/exchange` with their own credential — Vectros verifies it there and computes its own value for this field from the verified credential. The value you send here is stored exactly as-is, with no normalization, and does NOT automatically match or deduplicate against what a later token-exchange sign-in computes for the same real-world identity. Call this endpoint directly only if you run your own backend and want Vectros to record which of your own users a given account corresponds to — treat this field as informational for that purpose, not as a way to pre-authorize sign-in. Requires the `users:u` scope.
8165
+ * 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. **`externalSubject` set this way is NOT an authentication binding and does not enable sign-in anywhere** — not the Vectros DevPortal/Admin App/web apps, and not `/v1/auth/token/exchange` either; both are granted only by the invitee authenticating themselves. A subject stored through `PUT /v1/users/{id}` does not make the person a member of your account: it is ignored for the tenant claims in sign-in tokens, the developer portal's memberships list and tenant switching, and an ownership transfer. To give such a person access, delete the user and invite them again; accepting the invitation binds the subject and counts it. If the invitee needs dev-portal/web-app access, send them the invitation link and let them accept it directly. If the invitee needs to sign in via token exchange, have them redeem `inviteToken` themselves at `/v1/auth/token/exchange` with their own credential — Vectros verifies it there and computes its own value for this field from the verified credential. The value you send here is stored exactly as-is, with no normalization, and does NOT automatically match or deduplicate against what a later token-exchange sign-in computes for the same real-world identity. Call this endpoint directly only if you run your own backend and want Vectros to record which of your own users a given account corresponds to — treat this field as informational for that purpose, not as a way to pre-authorize sign-in. Requires the `users:u` scope.
7445
8166
  *
7446
8167
  * @param {Vectros.UpdateUserRequest} request
7447
8168
  * @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
7448
8169
  *
7449
8170
  * @throws {@link Vectros.BadRequestError}
8171
+ * @throws {@link Vectros.ForbiddenError}
7450
8172
  * @throws {@link Vectros.NotFoundError}
8173
+ * @throws {@link Vectros.ConflictError}
7451
8174
  * @throws {@link Vectros.TooManyRequestsError}
7452
8175
  *
7453
8176
  * @example
7454
8177
  * await client.identity.updateUser({
7455
8178
  * id: "550e8400-e29b-41d4-a716-446655440000",
7456
- * body: {
7457
- * externalId: "usr_12345"
7458
- * }
8179
+ * body: {}
7459
8180
  * })
7460
8181
  */
7461
8182
  updateUser(request, requestOptions) {
@@ -7493,8 +8214,12 @@ var IdentityClient = class {
7493
8214
  switch (_response.error.statusCode) {
7494
8215
  case 400:
7495
8216
  throw new BadRequestError(_response.error.body, _response.rawResponse);
8217
+ case 403:
8218
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
7496
8219
  case 404:
7497
8220
  throw new NotFoundError(_response.error.body, _response.rawResponse);
8221
+ case 409:
8222
+ throw new ConflictError(_response.error.body, _response.rawResponse);
7498
8223
  case 429:
7499
8224
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
7500
8225
  default:
@@ -7513,6 +8238,7 @@ var IdentityClient = class {
7513
8238
  * @param {Vectros.DeleteUserRequest} request
7514
8239
  * @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
7515
8240
  *
8241
+ * @throws {@link Vectros.ForbiddenError}
7516
8242
  * @throws {@link Vectros.NotFoundError}
7517
8243
  * @throws {@link Vectros.ConflictError}
7518
8244
  * @throws {@link Vectros.TooManyRequestsError}
@@ -7552,6 +8278,8 @@ var IdentityClient = class {
7552
8278
  }
7553
8279
  if (_response.error.reason === "status-code") {
7554
8280
  switch (_response.error.statusCode) {
8281
+ case 403:
8282
+ throw new ForbiddenError(_response.error.body, _response.rawResponse);
7555
8283
  case 404:
7556
8284
  throw new NotFoundError(_response.error.body, _response.rawResponse);
7557
8285
  case 409:
@@ -7756,7 +8484,7 @@ var InferenceClient = class {
7756
8484
  this._options = normalizeClientOptionsWithAuth(options);
7757
8485
  }
7758
8486
  /**
7759
- * Returns every inference model available to you, including each model's context window, the plan tiers it's available on, and the exact credit rates charged per 1K input and output tokens. Use this to populate model pickers and to validate a request before calling `/v1/chat`, `/v1/rag`, or `/v1/documents/{id}/ask`.
8487
+ * Returns the whole platform model catalog, whatever your plan: `availableOn` names each model's plan tiers. Each entry also carries the context window and the credit rates per 1K input and output tokens: `regionPricing.base` for global-region requests, `regionPricing.us` for default requests, `longContext` for prompts over its threshold, and `cachePricing` for prompt-cache tokens on a model that has cache prices. A model reached through a `providerAlias` is not listed. Use this to populate model pickers and to validate a request before calling `/v1/chat`, `/v1/rag`, or `/v1/documents/{id}/ask`.
7760
8488
  *
7761
8489
  * @param {InferenceClient.RequestOptions} requestOptions - Request-specific configuration.
7762
8490
  *
@@ -7800,7 +8528,7 @@ var InferenceClient = class {
7800
8528
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/models");
7801
8529
  }
7802
8530
  /**
7803
- * Streams a model response as Server-Sent Events (SSE). Send the full conversation history in the `messages` array; a message with role `system` is extracted and used as the system prompt. Token cost is debited from your pre-paid inference balance (in cents), and a small per-call flat fee is debited from your monthly platform credit allowance. Requires the `inference:r` scope.
8531
+ * Streams a model response as Server-Sent Events (SSE). Send the full conversation history in the `messages` array; a message with role `system` is extracted and used as the system prompt. On a pre-paid account, token cost is debited from your inference balance; usage-billed accounts accrue it for post-billing. A request routed through your own `providerAlias` incurs no Vectros token cost. A per-call platform fee is charged to your monthly credit allowance, except when the call fails on the server side: 0.2 credits for a call of up to 60 seconds, then 1 credit per 5 minutes of the call's duration. Requires the `inference:r` scope.
7804
8532
  */
7805
8533
  chatInference(request, requestOptions) {
7806
8534
  return HttpResponsePromise.fromPromise(this.__chatInference(request, requestOptions));
@@ -7853,10 +8581,14 @@ var InferenceClient = class {
7853
8581
  throw new PaymentRequiredError(_response.error.body, _response.rawResponse);
7854
8582
  case 403:
7855
8583
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
8584
+ case 404:
8585
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
7856
8586
  case 413:
7857
8587
  throw new ContentTooLargeError(_response.error.body, _response.rawResponse);
7858
8588
  case 429:
7859
8589
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
8590
+ case 503:
8591
+ throw new ServiceUnavailableError(_response.error.body, _response.rawResponse);
7860
8592
  default:
7861
8593
  throw new VectrosError({
7862
8594
  statusCode: _response.error.statusCode,
@@ -7868,7 +8600,7 @@ var InferenceClient = class {
7868
8600
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/chat");
7869
8601
  }
7870
8602
  /**
7871
- * Loads a single document's extracted text, supplies it as context, and streams a model answer about it. The document must be fully indexed. If the document exceeds the 32K-token cap, the call returns 413 with no credits charged — use `POST /v1/rag` instead to answer over larger or multi-document collections. Requires the `inference:r` scope.
8603
+ * Loads a single document's extracted text, supplies it as context, and streams a model answer about it. The document must have finished processing and have text. If the document exceeds the 32K-token cap, the call returns 413 with no credits charged — use `POST /v1/rag` instead to answer over larger or multi-document collections. Requires the `inference:r` scope.
7872
8604
  */
7873
8605
  documentAsk(request, requestOptions) {
7874
8606
  return HttpResponsePromise.fromPromise(this.__documentAsk(request, requestOptions));
@@ -7930,6 +8662,8 @@ var InferenceClient = class {
7930
8662
  throw new ContentTooLargeError(_response.error.body, _response.rawResponse);
7931
8663
  case 429:
7932
8664
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
8665
+ case 503:
8666
+ throw new ServiceUnavailableError(_response.error.body, _response.rawResponse);
7933
8667
  default:
7934
8668
  throw new VectrosError({
7935
8669
  statusCode: _response.error.statusCode,
@@ -7994,12 +8728,16 @@ var InferenceClient = class {
7994
8728
  throw new PaymentRequiredError(_response.error.body, _response.rawResponse);
7995
8729
  case 403:
7996
8730
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
8731
+ case 404:
8732
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
7997
8733
  case 413:
7998
8734
  throw new ContentTooLargeError(_response.error.body, _response.rawResponse);
7999
8735
  case 429:
8000
8736
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
8001
8737
  case 500:
8002
8738
  throw new InternalServerError(_response.error.body, _response.rawResponse);
8739
+ case 503:
8740
+ throw new ServiceUnavailableError(_response.error.body, _response.rawResponse);
8003
8741
  default:
8004
8742
  throw new VectrosError({
8005
8743
  statusCode: _response.error.statusCode,
@@ -8077,7 +8815,7 @@ var RecordsClient = class {
8077
8815
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/records/batch-get");
8078
8816
  }
8079
8817
  /**
8080
- * Reserved endpoint for batch lookup and reference resolution. The published response shape correlates results to each input and carries a per-item status envelope. It currently returns 501 (not implemented). The documented 200 response schema is the stable shape this endpoint will use once available. Requires the `records:r` scope.
8818
+ * Reserved endpoint for batch lookup and reference resolution. With the `records:r` scope it answers 501 (not implemented). The published response shape correlates results to each input and carries a per-item status envelope. Requires the `records:r` scope.
8081
8819
  *
8082
8820
  * @param {Vectros.BatchLookupRequest} request
8083
8821
  * @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -8138,7 +8876,7 @@ var RecordsClient = class {
8138
8876
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/v1/records/lookup/batch");
8139
8877
  }
8140
8878
  /**
8141
- * Writes up to 50 records (or 50 with `atomicity: all_or_nothing`) in a single request. Each item in `items` has exactly the same shape, and goes through exactly the same validation, authorization and idempotency rules, as the body of a single `POST /v1/records` — including schema validation, `externalId` idempotency, unique-field enforcement, and the `records:c:<type>` scope check, which is applied per item against that item's own record type. A batch is not a way to write a type your credential could not write one at a time.
8879
+ * Writes up to 50 records per request in `best_effort` mode and up to 50 with `atomicity: all_or_nothing`, in a single request. Each item in `items` has exactly the same shape, and goes through exactly the same validation, authorization and idempotency rules, as the body of a single `POST /v1/records` — including schema validation, `externalId` idempotency, unique-field enforcement, and the `records:c:<type>` scope check, which is applied per item against that item's own record type. A batch is not a way to write a type your credential could not write one at a time.
8142
8880
  *
8143
8881
  * `atomicity` selects how the batch commits. `best_effort` (the default) writes each item independently: some can succeed while others fail, and each item's own outcome is reported. `all_or_nothing` commits every item in one transaction — if any item fails, no record is created or updated at all, and every item that was itself fine reports `not_committed` while the ones that failed report why. Because the transaction is bounded by the number of underlying storage rows rather than by the number of records, a large `all_or_nothing` batch can be refused as too large to commit atomically even when it is within the item limit; the error says so, and nothing is written when it happens.
8144
8882
  *
@@ -8277,6 +9015,8 @@ var RecordsClient = class {
8277
9015
  *
8278
9016
  * @throws {@link Vectros.BadRequestError}
8279
9017
  * @throws {@link Vectros.ForbiddenError}
9018
+ * @throws {@link Vectros.NotFoundError}
9019
+ * @throws {@link Vectros.ConflictError}
8280
9020
  * @throws {@link Vectros.TooManyRequestsError}
8281
9021
  *
8282
9022
  * @example
@@ -8333,6 +9073,10 @@ var RecordsClient = class {
8333
9073
  throw new BadRequestError(_response.error.body, _response.rawResponse);
8334
9074
  case 403:
8335
9075
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
9076
+ case 404:
9077
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
9078
+ case 409:
9079
+ throw new ConflictError(_response.error.body, _response.rawResponse);
8336
9080
  case 429:
8337
9081
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
8338
9082
  default:
@@ -8481,6 +9225,7 @@ var RecordsClient = class {
8481
9225
  * @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
8482
9226
  *
8483
9227
  * @throws {@link Vectros.NotFoundError}
9228
+ * @throws {@link Vectros.ConflictError}
8484
9229
  * @throws {@link Vectros.TooManyRequestsError}
8485
9230
  *
8486
9231
  * @example
@@ -8520,6 +9265,8 @@ var RecordsClient = class {
8520
9265
  switch (_response.error.statusCode) {
8521
9266
  case 404:
8522
9267
  throw new NotFoundError(_response.error.body, _response.rawResponse);
9268
+ case 409:
9269
+ throw new ConflictError(_response.error.body, _response.rawResponse);
8523
9270
  case 429:
8524
9271
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
8525
9272
  default:
@@ -8533,7 +9280,7 @@ var RecordsClient = class {
8533
9280
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "DELETE", "/v1/records/{id}");
8534
9281
  }
8535
9282
  /**
8536
- * Partially updates a record using an RFC 7386 JSON Merge Patch. The `payload` object is deep-merged into the existing payload: keys you send overwrite (recursing into nested objects), a key set to null is deleted, and keys you omit are left unchanged — so you can change a single field without re-sending the rest (unlike the full-replacement PUT). Top-level fields (`status`, `folderId`, `userId`, `scopes`) are set when present and left unchanged when omitted; sending a top-level field as null is rejected (clearing a top-level field is not supported in this release — omit it instead). `typeName`, `schemaId`, `externalId`, and `indexMode` are immutable and rejected if present. The merged result is validated against the schema. Pass `expectedVersion` to make the patch conditional (optimistic concurrency, 409 on conflict). Requires the `records:u:<type>` scope.
9283
+ * Partially updates a record using an RFC 7386 JSON Merge Patch. The `payload` object is deep-merged into the existing payload: keys you send overwrite (recursing into nested objects), a key set to null is deleted, and keys you omit are left unchanged — so you can change a single field without re-sending the rest (unlike the full-replacement PUT). Top-level fields (`status`, `folderId`, `userId`, `scopes`) are set when present and left unchanged when omitted; sending a top-level field as null is rejected (clearing a top-level field is not supported — omit it instead). `typeName`, `schemaId`, `externalId`, and `indexMode` are immutable and rejected if present. The merged result is validated against the schema. Pass `expectedVersion` to make the patch conditional (optimistic concurrency, 409 on conflict). Requires the `records:u:<type>` scope.
8537
9284
  *
8538
9285
  * @param {Vectros.PatchRecordRequest} request
8539
9286
  * @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -8962,6 +9709,8 @@ var SchemasClient = class {
8962
9709
  *
8963
9710
  * @throws {@link Vectros.BadRequestError}
8964
9711
  * @throws {@link Vectros.ForbiddenError}
9712
+ * @throws {@link Vectros.NotFoundError}
9713
+ * @throws {@link Vectros.ConflictError}
8965
9714
  * @throws {@link Vectros.TooManyRequestsError}
8966
9715
  *
8967
9716
  * @example
@@ -8986,8 +9735,7 @@ var SchemasClient = class {
8986
9735
  * }],
8987
9736
  * capabilities: {
8988
9737
  * "auditHistory": true
8989
- * },
8990
- * allowedSurfaces: ["record"]
9738
+ * }
8991
9739
  * }
8992
9740
  * })
8993
9741
  */
@@ -9031,6 +9779,10 @@ var SchemasClient = class {
9031
9779
  throw new BadRequestError(_response.error.body, _response.rawResponse);
9032
9780
  case 403:
9033
9781
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
9782
+ case 404:
9783
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
9784
+ case 409:
9785
+ throw new ConflictError(_response.error.body, _response.rawResponse);
9034
9786
  case 429:
9035
9787
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
9036
9788
  default:
@@ -9113,11 +9865,7 @@ var SchemasClient = class {
9113
9865
  * @example
9114
9866
  * await client.schemas.updateSchema({
9115
9867
  * id: "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
9116
- * body: {
9117
- * typeName: "intake_form",
9118
- * displayName: "Client Intake Form",
9119
- * allowedSurfaces: ["record"]
9120
- * }
9868
+ * body: {}
9121
9869
  * })
9122
9870
  */
9123
9871
  updateSchema(request, requestOptions) {
@@ -9174,7 +9922,7 @@ var SchemasClient = class {
9174
9922
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "PUT", "/v1/schemas/{id}");
9175
9923
  }
9176
9924
  /**
9177
- * 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. The same applies to documents bound to this schema (for a schema declaring the `document` surface) — delete those documents first. 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. It is likewise refused while any trigger rule fires off this schema — delete those trigger rules first. Requires the `schemas:d` scope.
9925
+ * 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. The same applies to documents bound to this schema (for a schema declaring the `document` surface) — delete those documents first. 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. It is likewise refused while any trigger rule fires off this schema — delete those trigger rules first — and, for a schema declaring the `user` or `entity` surface, while any user or entity bound to it still exists. Requires the `schemas:d` scope.
9178
9926
  *
9179
9927
  * @param {Vectros.DeleteSchemaRequest} request
9180
9928
  * @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -9301,7 +10049,7 @@ var ScriptsClient = class {
9301
10049
  this._options = normalizeClientOptionsWithAuth(options);
9302
10050
  }
9303
10051
  /**
9304
- * Runs a script you previously pushed to `POST /v1/scripts`, under your own credential, and returns what it returned. Every write the script makes is buffered and committed as ONE transaction after the script finishes: either all of them land or none do, and the response is sent only after they have committed — so everything in `result` is committed state or the script's own computation over it. On any failure the body is the standard error envelope and nothing the script staged is committed: its rows are written only when the transaction commits, and a document body or a large payload is DECIDED at that point and WRITTEN to storage only after the commit, so an aborted execution leaves nothing behind. The one residual sits after a successful commit, outside this response: if storing a body fails then, the row exists and the body does not until the platform's repair lands — so a `200` guarantees the rows, and a document's text should be read before it is relied on.
10052
+ * Runs a script you previously pushed to `POST /v1/scripts`, under your own credential, and returns what it returned. Every write the script makes is buffered and committed as ONE transaction after the script finishes: either all of them land or none do, and the response is sent only after they have committed — so everything in `result` is committed state or the script's own computation over it. On any failure the body is the standard error envelope and nothing the script staged is committed: its rows are written only when the transaction commits, and a document body or a large payload is DECIDED at that point and WRITTEN to storage only after the commit, so an aborted execution leaves nothing behind. The one residual sits after a successful commit, outside this response: if storing a body fails then, the row exists and the body may not — so a `200` guarantees the rows, and a document's text should be read before it is relied on.
9305
10053
  *
9306
10054
  * **Permission.** Requires the `scripts:x` scope — the permission to *execute* — separate from the `scripts:c` permission to push scripts. Bare `scripts:x` grants every script in the context; `scripts:x:<name>` grants exactly that script name, every version of it. Execution discloses no source, so `scripts:r` is not needed. Inside the script, every read and write is enforced by your credential's data scopes exactly as the equivalent REST call would be — `scripts:x` alone can read and write nothing.
9307
10055
  *
@@ -9657,7 +10405,7 @@ var ScriptsClient = class {
9657
10405
  return handleNonStatusCodeError(_response.error, _response.rawResponse, "PUT", "/v1/scripts/{id}");
9658
10406
  }
9659
10407
  /**
9660
- * Permanently deletes one script version by ID. Deleting one version does not affect any other version of the same name. Requires the `scripts:d` scope. Refused with 409 if a live trigger rule still references this version — either directly (a pinned `scriptRef`), or via `"latest"` when this IS the newest version of its name. Delete or re-point those rules first.
10408
+ * Permanently deletes one script version by ID. Deleting one version does not affect any other version of the same name. Requires the `scripts:d` scope. Refused with 409 if a live trigger rule still references this version — either directly (a pinned `scriptRef`), or via `"latest"` when this IS the newest version of its name. Delete or re-point those rules first. Also refused with a retryable 409, deleting nothing, when it cannot be told yet whether this is the newest version (for example just after several of this name's newest versions were deleted, or while its first version is gone and the listing has not caught up) and a `"latest"` rule depends on the script: try again shortly.
9661
10409
  *
9662
10410
  * @param {Vectros.DeleteScriptRequest} request
9663
10411
  * @param {ScriptsClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -9915,21 +10663,13 @@ var TriggersClient = class {
9915
10663
  *
9916
10664
  * @throws {@link Vectros.BadRequestError}
9917
10665
  * @throws {@link Vectros.ForbiddenError}
10666
+ * @throws {@link Vectros.NotFoundError}
10667
+ * @throws {@link Vectros.ConflictError}
9918
10668
  * @throws {@link Vectros.TooManyRequestsError}
9919
10669
  *
9920
10670
  * @example
9921
10671
  * await client.triggers.createTrigger({
9922
- * body: {
9923
- * name: "on-intake-create",
9924
- * firingSource: {
9925
- * schemaId: "sch_9f8e7d6c",
9926
- * event: "CREATE"
9927
- * },
9928
- * scriptRef: {
9929
- * name: "notify-assignee",
9930
- * version: "3"
9931
- * }
9932
- * }
10672
+ * body: {}
9933
10673
  * })
9934
10674
  */
9935
10675
  createTrigger(request, requestOptions) {
@@ -9972,6 +10712,10 @@ var TriggersClient = class {
9972
10712
  throw new BadRequestError(_response.error.body, _response.rawResponse);
9973
10713
  case 403:
9974
10714
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
10715
+ case 404:
10716
+ throw new NotFoundError(_response.error.body, _response.rawResponse);
10717
+ case 409:
10718
+ throw new ConflictError(_response.error.body, _response.rawResponse);
9975
10719
  case 429:
9976
10720
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
9977
10721
  default:
@@ -10048,22 +10792,13 @@ var TriggersClient = class {
10048
10792
  * @throws {@link Vectros.BadRequestError}
10049
10793
  * @throws {@link Vectros.ForbiddenError}
10050
10794
  * @throws {@link Vectros.NotFoundError}
10795
+ * @throws {@link Vectros.ConflictError}
10051
10796
  * @throws {@link Vectros.TooManyRequestsError}
10052
10797
  *
10053
10798
  * @example
10054
10799
  * await client.triggers.updateTrigger({
10055
10800
  * id: "id",
10056
- * body: {
10057
- * name: "on-intake-create",
10058
- * firingSource: {
10059
- * schemaId: "sch_9f8e7d6c",
10060
- * event: "CREATE"
10061
- * },
10062
- * scriptRef: {
10063
- * name: "notify-assignee",
10064
- * version: "3"
10065
- * }
10066
- * }
10801
+ * body: {}
10067
10802
  * })
10068
10803
  */
10069
10804
  updateTrigger(request, requestOptions) {
@@ -10105,6 +10840,8 @@ var TriggersClient = class {
10105
10840
  throw new ForbiddenError(_response.error.body, _response.rawResponse);
10106
10841
  case 404:
10107
10842
  throw new NotFoundError(_response.error.body, _response.rawResponse);
10843
+ case 409:
10844
+ throw new ConflictError(_response.error.body, _response.rawResponse);
10108
10845
  case 429:
10109
10846
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
10110
10847
  default:
@@ -10124,6 +10861,7 @@ var TriggersClient = class {
10124
10861
  * @param {TriggersClient.RequestOptions} requestOptions - Request-specific configuration.
10125
10862
  *
10126
10863
  * @throws {@link Vectros.NotFoundError}
10864
+ * @throws {@link Vectros.ConflictError}
10127
10865
  * @throws {@link Vectros.TooManyRequestsError}
10128
10866
  *
10129
10867
  * @example
@@ -10163,6 +10901,8 @@ var TriggersClient = class {
10163
10901
  switch (_response.error.statusCode) {
10164
10902
  case 404:
10165
10903
  throw new NotFoundError(_response.error.body, _response.rawResponse);
10904
+ case 409:
10905
+ throw new ConflictError(_response.error.body, _response.rawResponse);
10166
10906
  case 429:
10167
10907
  throw new TooManyRequestsError(_response.error.body, _response.rawResponse);
10168
10908
  default:
@@ -10183,6 +10923,9 @@ var VectrosClient = class {
10183
10923
  get auth() {
10184
10924
  return this._auth ?? (this._auth = new AuthClient(this._options));
10185
10925
  }
10926
+ get agents() {
10927
+ return this._agents ?? (this._agents = new AgentsClient(this._options));
10928
+ }
10186
10929
  get documents() {
10187
10930
  return this._documents ?? (this._documents = new DocumentsClient(this._options));
10188
10931
  }
@@ -10248,7 +10991,7 @@ var logging;
10248
10991
 
10249
10992
  // src/server.ts
10250
10993
  var import_types3 = require("@modelcontextprotocol/sdk/types.js");
10251
- var import_zod25 = require("zod");
10994
+ var import_zod28 = require("zod");
10252
10995
 
10253
10996
  // src/auth.ts
10254
10997
  var KEY_RE = /^(sk|ssk|st)_(live|test)_/;
@@ -10292,8 +11035,8 @@ function warnOnSuboptimalKey(key, log) {
10292
11035
 
10293
11036
  // src/build-info.ts
10294
11037
  var BUILD_INFO = {
10295
- mcpServer: true ? "0.18.1" : "dev",
10296
- sdk: true ? "0.47.0" : "dev"
11038
+ mcpServer: true ? "0.19.0" : "dev",
11039
+ sdk: true ? "0.49.0" : "dev"
10297
11040
  };
10298
11041
 
10299
11042
  // src/log.ts
@@ -10549,6 +11292,11 @@ ${detail}${trailer}`
10549
11292
  };
10550
11293
  }
10551
11294
 
11295
+ // src/tools/limits.ts
11296
+ var MAX_OWNERSHIP_SCOPES = 2;
11297
+ var MAX_SCOPE_FILTERS = 16;
11298
+ var MAX_CONTENT_TYPES = 2;
11299
+
10552
11300
  // src/tools/hybrid_search.ts
10553
11301
  var MCP_DEFAULT_LIMIT = 3;
10554
11302
  var MCP_MAX_LIMIT = 50;
@@ -10591,11 +11339,11 @@ var inputSchema = {
10591
11339
  folderId: import_zod.z.string().optional().describe("Scope to content in this EXACT folder (Vectros folder id)."),
10592
11340
  rootFolderId: import_zod.z.string().optional().describe("Scope to content under this folder AND all its descendants (subtree-root folder id)."),
10593
11341
  // Content narrowing.
10594
- contentTypes: import_zod.z.array(import_zod.z.enum(["documents", "records"])).optional().describe('Narrow to content types. ["documents"] or ["records"]; omit for unified (both).'),
11342
+ contentTypes: import_zod.z.array(import_zod.z.enum(["documents", "records"])).max(MAX_CONTENT_TYPES, `contentTypes accepts at most ${MAX_CONTENT_TYPES} entries`).optional().describe('Narrow to content types. ["documents"] or ["records"]; omit for unified (both).'),
10595
11343
  typeName: import_zod.z.string().optional().describe(
10596
11344
  'Restrict hits to this schema type (e.g. "patient", "runbook"). Applies to BOTH documents and records \u2014 combine with contentTypes to scope within one content type. Untyped content never matches.'
10597
11345
  ),
10598
- filters: import_zod.z.record(import_zod.z.unknown()).optional().describe(
11346
+ filters: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional().describe(
10599
11347
  'Field-level metadata filters (AND-combined). Value = scalar (equality), array (OR-set), or operator map: $eq/$ne/$gt/$gte/$lt/$lte (scalar) or $in/$nin (array). e.g. {"status":"open"} or {"price":{"$gte":100,"$lte":500}}.'
10600
11348
  ),
10601
11349
  // Ownership.
@@ -10603,7 +11351,7 @@ var inputSchema = {
10603
11351
  scope: import_zod.z.string().optional().describe(
10604
11352
  'Restrict to content carrying this scope value, in `namespace:value` form (e.g. "org:<uuid>", "client:<uuid>", "group:eng-team"). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself. Mutually exclusive with `scopeFilters` \u2014 use this for ONE dimension.'
10605
11353
  ),
10606
- scopeFilters: import_zod.z.array(import_zod.z.string()).min(1, "scopeFilters must name at least one dimension when supplied").optional().describe(
11354
+ scopeFilters: import_zod.z.array(import_zod.z.string()).min(1, "scopeFilters must name at least one dimension when supplied").max(MAX_SCOPE_FILTERS, `scopeFilters accepts at most ${MAX_SCOPE_FILTERS} entries`).optional().describe(
10607
11355
  'Restrict to content matching ALL of these scope values \u2014 one per namespace \u2014 for a credential whose access spans more than one ownership dimension. e.g. ["org:<uuid>", "client:<uuid>"] narrows to one specific client WITHIN one specific org, which `scope` alone cannot express. Same `namespace:value` form as `scope`; naming the same namespace twice is rejected. Mutually exclusive with `scope` \u2014 use `scope` for a single dimension.'
10608
11356
  ),
10609
11357
  // Date window.
@@ -11124,7 +11872,7 @@ var inputSchema5 = {
11124
11872
  status: import_zod5.z.string().optional().describe("Record lifecycle status. Defaults to ACTIVE server-side."),
11125
11873
  folderId: import_zod5.z.string().optional().describe("Group this record into a folder."),
11126
11874
  userId: import_zod5.z.string().optional().describe("Owning user id."),
11127
- scopes: import_zod5.z.array(import_zod5.z.string()).optional().describe(
11875
+ scopes: import_zod5.z.array(import_zod5.z.string()).max(MAX_OWNERSHIP_SCOPES, `scopes accepts at most ${MAX_OWNERSHIP_SCOPES} entries`).optional().describe(
11128
11876
  'Scope ownership as `namespace:value` entries, at most 2 (e.g. ["org:<uuid>", "group:eng-team"]). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself. This is the record\'s COMPLETE scope declaration, and each entry must fall inside the `data_scope` of a single clause of your credential that also grants this write \u2014 your identity supplies the DEFAULT when you state none, it does not limit which value you may state. An empty array `[]` creates a PRIVATE record owned by the calling user alone. Omit to stamp the credential\'s full identity \u2014 the default.'
11129
11877
  )
11130
11878
  };
@@ -11182,7 +11930,7 @@ var itemSchema = import_zod6.z.strictObject({
11182
11930
  status: import_zod6.z.string().optional().describe("Record lifecycle status. Defaults to ACTIVE server-side."),
11183
11931
  folderId: import_zod6.z.string().optional().describe("Group this record into a folder."),
11184
11932
  userId: import_zod6.z.string().optional().describe("Owning user id."),
11185
- scopes: import_zod6.z.array(import_zod6.z.string()).optional().describe(
11933
+ scopes: import_zod6.z.array(import_zod6.z.string()).max(MAX_OWNERSHIP_SCOPES, `scopes accepts at most ${MAX_OWNERSHIP_SCOPES} entries`).optional().describe(
11186
11934
  "Scope ownership as `namespace:value` entries, at most 2 namespaces. When supplied this is the record's COMPLETE scope declaration, and each entry must fall inside the `data_scope` of a single clause of your credential that also grants this write \u2014 your identity supplies the DEFAULT when you state none, it does not limit which value you may state. `[]` creates a PRIVATE record owned by the calling user alone. Omit to inherit the credential's full identity."
11187
11935
  )
11188
11936
  });
@@ -11269,7 +12017,7 @@ var inputSchema7 = {
11269
12017
  ),
11270
12018
  status: import_zod7.z.string().optional().describe("Set the record lifecycle status (e.g. ARCHIVED) \u2014 archive/workflow without physical deletion."),
11271
12019
  expectedVersion: import_zod7.z.number().int().optional().describe(
11272
- "Optimistic concurrency: the version you last read. If the record changed since, the update is refused as a conflict (re-read and retry). Omit for last-write-wins."
12020
+ "Optimistic concurrency: the version you last read. If the record changed since, the update is refused as a conflict (re-read and retry). Omit it to update whatever version is current: an update that meets another change to the same record at the same moment is still refused as a conflict."
11273
12021
  )
11274
12022
  };
11275
12023
  var recordUpdate = ({ client, log }) => ({
@@ -11339,7 +12087,7 @@ var import_zod10 = require("zod");
11339
12087
  // src/tools/provider-alias.ts
11340
12088
  var import_zod9 = require("zod");
11341
12089
  var providerAliasInput = import_zod9.z.string().min(1, "providerAlias must be non-empty when supplied").optional().describe(
11342
- "Route THIS call through your own model provider instead of the platform-hosted default, by the alias of a provider config your account has activated. It works only after your account has set up that provider and signed the platform's risk-acceptance waiver; without both, the platform refuses the call with a 403, which is returned to you as written. If your account has accepted the Business Associate Agreement with Vectros in the developer portal, an account owner must also have attested that provider config in the developer portal (Model Providers); until then the platform refuses the call with a 403 that says it needs a BAA-holder attestation. A call served by your own provider leaves the Vectros perimeter. Omit it (the default) to use the platform-hosted path. When set, `model` names the model on your provider's own id space, and falls back to that provider config's default model when omitted."
12090
+ "Route THIS call through your own model provider instead of the platform-hosted default, by the alias of a provider config your account has activated. It works only after your account has set up that provider and signed the platform's risk-acceptance waiver; without both, the platform refuses the call with a 403, which is returned to you as written. When the waiver is the cause, the 403 carries an `errorCode` that says which case it is: `WAIVER_NOT_SIGNED` (the waiver has not been signed), `WAIVER_TEXT_CHANGED` (Vectros now requires a newer version of the waiver than the one in force for your account), or `WAIVER_REVOKED` (an owner revoked it). An account owner resolves each in the developer portal (Model Providers); retrying the call does not help. If your account has accepted the Business Associate Agreement with Vectros in the developer portal, an account owner must also have attested that provider config in the developer portal (Model Providers); until then the platform refuses the call with a 403 that says it needs a BAA-holder attestation. A call served by your own provider leaves the Vectros perimeter. Omit it (the default) to use the platform-hosted path. When set, `model` names the model on your provider's own id space, and falls back to that provider config's default model when omitted."
11343
12091
  );
11344
12092
 
11345
12093
  // src/tools/rag_ask.ts
@@ -11366,14 +12114,14 @@ var inputSchema9 = {
11366
12114
  scope: import_zod10.z.string().optional().describe(
11367
12115
  'Restrict retrieval to content carrying this scope value, in `namespace:value` form (e.g. "org:<uuid>", "client:<uuid>", "group:eng-team"). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself. Mutually exclusive with `scopeFilters` \u2014 use this for ONE dimension.'
11368
12116
  ),
11369
- scopeFilters: import_zod10.z.array(import_zod10.z.string()).min(1, "scopeFilters must name at least one dimension when supplied").optional().describe(
12117
+ scopeFilters: import_zod10.z.array(import_zod10.z.string()).min(1, "scopeFilters must name at least one dimension when supplied").max(MAX_SCOPE_FILTERS, `scopeFilters accepts at most ${MAX_SCOPE_FILTERS} entries`).optional().describe(
11370
12118
  'Restrict retrieval to content matching ALL of these scope values \u2014 one per namespace \u2014 for a credential whose access spans more than one ownership dimension. e.g. ["org:<uuid>", "client:<uuid>"] grounds the answer on one specific client WITHIN one specific org, which `scope` alone cannot express. Naming the same namespace twice is rejected. Mutually exclusive with `scope`.'
11371
12119
  ),
11372
12120
  folderId: import_zod10.z.string().optional().describe("Restrict retrieval to this exact folder."),
11373
12121
  rootFolderId: import_zod10.z.string().optional().describe("Restrict retrieval to this folder and all its descendants."),
11374
12122
  typeName: import_zod10.z.string().optional().describe("Restrict record retrieval to this schema type."),
11375
- contentTypes: import_zod10.z.array(import_zod10.z.enum(["documents", "records"])).optional().describe('Narrow retrieval to content types. ["documents"] or ["records"]; omit for both.'),
11376
- filters: import_zod10.z.record(import_zod10.z.unknown()).optional().describe(
12123
+ contentTypes: import_zod10.z.array(import_zod10.z.enum(["documents", "records"])).max(MAX_CONTENT_TYPES, `contentTypes accepts at most ${MAX_CONTENT_TYPES} entries`).optional().describe('Narrow retrieval to content types. ["documents"] or ["records"]; omit for both.'),
12124
+ filters: import_zod10.z.record(import_zod10.z.string(), import_zod10.z.unknown()).optional().describe(
11377
12125
  'Field-level metadata filters (AND-combined). Value = scalar (equality), array (OR-set), or operator map ($eq/$ne/$gt/$gte/$lt/$lte, $in/$nin). e.g. {"status":"open"}.'
11378
12126
  ),
11379
12127
  createdAfter: import_zod10.z.string().optional().describe(
@@ -11648,7 +12396,7 @@ function isNotAvailable(err) {
11648
12396
  var documentGet = ({ client, log }) => ({
11649
12397
  name: "document_get",
11650
12398
  title: "Get document metadata (and optionally text)",
11651
- description: "Fetch metadata for a single document \u2014 select it by its Vectros `documentId` OR by your own `externalId` + `type` (resolved for you). Pass `includeText: true` to also fetch the text body (capped at ~8K tokens; `truncated: true` flag if cut). Text is available for every text-ingested document and for file-ingested documents unless they were uploaded with `storeText: false` (extracted text discarded after indexing) \u2014 then `textAvailable: false` is set; the original file is still retrievable via `includeDownloadUrl`. Pass `includeDownloadUrl: true` to also get a short-lived presigned `downloadUrl` for the original file (file-backed documents only). Returns the full document metadata, including its lifecycle `status` (ACTIVE, or ARCHIVED when soft-retracted from search \u2014 restorable via document_update) and its processing `indexStatus`. When `indexStatus` is FAILED the response also carries `indexFailure` with a machine-readable `code` telling you whether the content is still findable \u2014 e.g. TEXT_INDEX_FAILED / VECTOR_LIMIT_EXCEEDED (one leg still serves it) vs INDEXING_FAILED (not findable by search at all). Branch on `code`, not on the message.",
12399
+ description: "Fetch metadata for a single document \u2014 select it by its Vectros `documentId` OR by your own `externalId` + `type` (resolved for you). Pass `includeText: true` to also fetch the text body (capped at ~8K tokens; `truncated: true` flag if cut). Text is available for every text-ingested document and for file-ingested documents unless they were uploaded with `storeText: false` (extracted text discarded after indexing) or no text could be extracted from the file (`extraction.outcome` other than OK/TRUNCATED, e.g. an image or a scanned page) \u2014 then `textAvailable: false` is set; the original file is still retrievable via `includeDownloadUrl`. Pass `includeDownloadUrl: true` to also get a short-lived presigned `downloadUrl` for the original file (file-backed documents only). Returns the full document metadata, including its lifecycle `status` (ACTIVE, or ARCHIVED when soft-retracted from search \u2014 restorable via document_update) and its processing `indexStatus`. When `indexStatus` is FAILED the response also carries `indexFailure` with a machine-readable `code` telling you whether the content is still findable \u2014 e.g. TEXT_INDEX_FAILED / VECTOR_LIMIT_EXCEEDED (one leg still serves it) vs INDEXING_FAILED (not findable by search at all). Branch on `code`, not on the message.",
11652
12400
  inputSchema: inputSchema12,
11653
12401
  // A pure read — never creates, modifies, or deletes anything server-side.
11654
12402
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
@@ -11674,7 +12422,7 @@ var documentGet = ({ client, log }) => ({
11674
12422
  if (isNotAvailable(textErr)) {
11675
12423
  log.debug(
11676
12424
  { tool: "document_get", id },
11677
- "document_get text unavailable (not retained \u2014 storeText:false upload)"
12425
+ "document_get text unavailable (not retained, or no text could be extracted from the file)"
11678
12426
  );
11679
12427
  extra = { ...extra, textAvailable: false };
11680
12428
  } else {
@@ -11727,10 +12475,12 @@ var inputSchema13 = {
11727
12475
  to: import_zod14.z.string().optional().describe("Lookup mode (range): inclusive upper bound; requires `from`."),
11728
12476
  prefix: import_zod14.z.string().optional().describe("Lookup mode (prefix): match values starting with this. Range-enabled string fields only."),
11729
12477
  order: import_zod14.z.enum(["asc", "desc"]).optional().describe(
11730
- "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."
12478
+ "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). Refused without `field`."
11731
12479
  ),
11732
- type: import_zod14.z.string().optional().describe("Lookup mode: the document type (the bound schema's type). Required with `field`."),
11733
- // List-mode args:
12480
+ type: import_zod14.z.string().min(1, "type must be non-empty: omit it to list every type").optional().describe(
12481
+ "The document type (the bound schema's type). Required with `field` (lookup mode); in list mode it narrows the list to documents of this type. The list filter applies page by page: a page can hold fewer documents than `limit`, or none, while `nextCursor` is set, so keep paging until `nextCursor` is null before concluding there are none. For a large collection, hybrid_search with `typeName` finds documents of one type directly."
12482
+ ),
12483
+ // List-mode args (`type` above applies to both modes):
11734
12484
  folderId: import_zod14.z.string().optional().describe("List mode: only documents in this folder (Vectros folder id)."),
11735
12485
  userId: import_zod14.z.string().optional().describe("List mode: scope to documents owned by this user."),
11736
12486
  scope: import_zod14.z.string().optional().describe(
@@ -11744,7 +12494,7 @@ var inputSchema13 = {
11744
12494
  var documentQuery = ({ client, log }) => ({
11745
12495
  name: "document_query",
11746
12496
  title: "Document query (list or lookup)",
11747
- description: "Query document metadata. Two modes:\n \u2022 Lookup on a lookup-indexed field: pass `type` and `field` plus exactly one of `value` (exact), `from`+`to` (range), or `prefix`. Works on sensitive fields (equality only there); range/prefix need a range-enabled field.\n \u2022 List: omit `field`; optionally filter by `folderId`/`userId`/`scope` (`namespace:value`).\nReturns a `{ data, nextCursor }` page: `data` holds up to `limit` documents (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. Mode is auto-detected. Use document_get for the full text/download URL of one document.",
12497
+ description: "Query document metadata. Two modes:\n \u2022 Lookup on a lookup-indexed field: pass `type` and `field` plus exactly one of `value` (exact), `from`+`to` (range), or `prefix`. Works on sensitive fields (equality only there); range/prefix need a range-enabled field.\n \u2022 List: omit `field`; optionally filter by `type`/`folderId`/`userId`/`scope` (`namespace:value`). The `type` filter is applied page by page, so a page can be short or empty while `nextCursor` is set: keep paging before concluding there are none.\nReturns a `{ data, nextCursor }` page: `data` holds up to `limit` documents (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. Mode is auto-detected. Use document_get for the full text/download URL of one document.",
11748
12498
  inputSchema: inputSchema13,
11749
12499
  // A pure read — never creates, modifies, or deletes anything server-side.
11750
12500
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
@@ -11803,7 +12553,19 @@ var documentQuery = ({ client, log }) => ({
11803
12553
  "document_query lookup ok"
11804
12554
  );
11805
12555
  } else {
12556
+ const strayLookupArgs = ["value", "from", "to", "prefix", "order"].filter(
12557
+ (k) => args[k] !== void 0
12558
+ );
12559
+ if (strayLookupArgs.length > 0) {
12560
+ return toolError(
12561
+ "document_query",
12562
+ new Error(
12563
+ `Lookup arguments need 'field' (and 'type'): ${strayLookupArgs.map((k) => `'${k}'`).join(", ")}. Without 'field' the call lists documents: filter the list with 'type', 'folderId', 'userId' or 'scope'.`
12564
+ )
12565
+ );
12566
+ }
11806
12567
  page = await client.documents.listDocuments({
12568
+ type,
11807
12569
  folderId: args.folderId,
11808
12570
  userId: args.userId,
11809
12571
  scope: args.scope,
@@ -11811,7 +12573,7 @@ var documentQuery = ({ client, log }) => ({
11811
12573
  limit
11812
12574
  });
11813
12575
  log.debug(
11814
- { tool: "document_query", mode: "list", limit, returned: pageItems(page).length },
12576
+ { tool: "document_query", mode: "list", type, limit, returned: pageItems(page).length },
11815
12577
  "document_query list ok"
11816
12578
  );
11817
12579
  }
@@ -11846,11 +12608,11 @@ var inputSchema14 = {
11846
12608
  "Lifecycle status. `ARCHIVED` soft-retracts the document \u2014 it is pulled from search and recall but kept and recoverable; set it back to `ACTIVE` to re-index and restore it. The way to retire superseded content when the credential has no delete authority. Omit to leave unchanged."
11847
12609
  ),
11848
12610
  userId: import_zod15.z.string().optional().describe("Reassign the owning user (Vectros UUID)."),
11849
- scopes: import_zod15.z.array(import_zod15.z.string()).optional().describe(
12611
+ scopes: import_zod15.z.array(import_zod15.z.string()).max(MAX_OWNERSHIP_SCOPES, `scopes accepts at most ${MAX_OWNERSHIP_SCOPES} entries`).optional().describe(
11850
12612
  'Reassign scope ownership as `namespace:value` entries, at most 2 (e.g. ["org:<uuid>", "group:eng-team"]) \u2014 the COMPLETE new parent set. `org`/`client` are reserved namespace names, registered like any other. Omit to leave ownership unchanged; `[]` clears it (private to the owning user).'
11851
12613
  ),
11852
12614
  expectedVersion: import_zod15.z.number().int().optional().describe(
11853
- "Optimistic concurrency: the version you last read. If the document changed since, the update is refused as a conflict (re-read and retry). Omit for last-write-wins."
12615
+ "Optimistic concurrency: the version you last read. If the document changed since, the update is refused as a conflict (re-read and retry). Omit it to update whatever version is current: an update that meets another change to the same document at the same moment is still refused as a conflict."
11854
12616
  )
11855
12617
  };
11856
12618
  var documentUpdate = ({ client, log }) => ({
@@ -11990,7 +12752,7 @@ var inputSchema17 = {
11990
12752
  "Optional stable slug (sibling-unique; idempotency key). Lowercase letters/digits/hyphens. SUPPLY THIS to make a retry safe \u2014 if omitted, a derived slug is only ever a freshly-proved-free one, so a redelivered call creates a new sibling folder every time rather than matching the first."
11991
12753
  ),
11992
12754
  userId: import_zod18.z.string().optional().describe("Owning user (Vectros UUID)."),
11993
- scopes: import_zod18.z.array(import_zod18.z.string()).optional().describe(
12755
+ scopes: import_zod18.z.array(import_zod18.z.string()).max(MAX_OWNERSHIP_SCOPES, `scopes accepts at most ${MAX_OWNERSHIP_SCOPES} entries`).optional().describe(
11994
12756
  'Scope ownership as `namespace:value` entries, at most 2 (e.g. ["org:<uuid>", "group:eng-team"]). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself. This is the folder\'s COMPLETE scope declaration and values must come from the credential\'s own identity. An empty array `[]` creates a PRIVATE folder owned by the calling user alone. Omit to stamp the credential\'s full identity \u2014 the default.'
11995
12757
  )
11996
12758
  };
@@ -12004,10 +12766,8 @@ var folderCreate = ({ client, log }) => ({
12004
12766
  // freshly-proved-free value, so the idempotency check running after that derivation can never
12005
12767
  // match on the default path. `slug` is optional, so this is annotated for the less-safe default —
12006
12768
  // the same standard applied to record_create/document_ingest/record_batch_write's identical
12007
- // optional-dedupe-key shape. (A prior version of this annotation claimed unconditional
12008
- // idempotency, reasoning that the derived slug made this tool "genuinely structurally different"
12009
- // from the optional-externalId tools — that reasoning was wrong: the derivation is unconditional,
12010
- // but it is unconditionally NON-colliding by construction, which is the opposite property.)
12769
+ // optional-dedupe-key shape. (The slug derivation being unconditional does not make the tool
12770
+ // idempotent: it is unconditionally NON-colliding by construction, which is the opposite property.)
12011
12771
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false },
12012
12772
  handler: async (args) => {
12013
12773
  try {
@@ -12038,11 +12798,11 @@ var inputSchema18 = {
12038
12798
  name: import_zod19.z.string().optional().describe("New folder name. Omit to keep the current name."),
12039
12799
  description: import_zod19.z.string().optional().describe("New description. Omit to leave unchanged."),
12040
12800
  userId: import_zod19.z.string().optional().describe("Reassign the owning user (Vectros UUID)."),
12041
- scopes: import_zod19.z.array(import_zod19.z.string()).optional().describe(
12801
+ scopes: import_zod19.z.array(import_zod19.z.string()).max(MAX_OWNERSHIP_SCOPES, `scopes accepts at most ${MAX_OWNERSHIP_SCOPES} entries`).optional().describe(
12042
12802
  'Reassign scope ownership as `namespace:value` entries, at most 2 (e.g. ["org:<uuid>", "group:eng-team"]) \u2014 the COMPLETE new parent set. `org`/`client` are reserved namespace names, registered like any other. Omit to leave ownership unchanged; `[]` clears it (private to the owning user).'
12043
12803
  ),
12044
12804
  expectedVersion: import_zod19.z.number().int().optional().describe(
12045
- "Optimistic concurrency: the version you last read. If the folder changed since, the update is refused as a conflict (re-read and retry). Omit for last-write-wins."
12805
+ "Optimistic concurrency: the version you last read. If the folder changed since, the update is refused as a conflict (re-read and retry). Omit it to update whatever version is current: an update that meets another change to the same folder at the same moment is still refused as a conflict."
12046
12806
  )
12047
12807
  };
12048
12808
  var folderUpdate = ({ client, log }) => ({
@@ -12087,7 +12847,7 @@ var inputSchema19 = {
12087
12847
  var folderDelete = ({ client, log }) => ({
12088
12848
  name: "folder_delete",
12089
12849
  title: "Delete a folder",
12090
- description: 'Permanently delete a folder by id. The folder must be EMPTY first \u2014 it must contain no documents, no records, and no sub-folders \u2014 and a non-empty folder is refused, which is the most common way this call fails. Use record_query with this folderId, and document_query, to see what is in it. Clearing it differs by content type: a document can be moved out (document_update with a different folderId) or deleted. A RECORD can also be re-filed into another folder \u2014 the API supports it \u2014 but THIS SERVER does not expose that yet: record_update has no folderId argument, so from here your only option is record_delete (needs records:d). Do NOT read that as "the record cannot be moved" and delete the record on that basis: if the record should be kept, tell the user to move it with the Vectros API/SDK directly rather than deleting it here. A sub-folder cannot be re-parented at all, so nested folders have to be emptied and deleted innermost-first. Note the emptiness check counts everything in the folder, INCLUDING items your credential cannot read \u2014 so a refusal you cannot account for from what you can list is expected behaviour, not a bug, and retrying will not clear it. Requires the key to allow folders:d \u2014 a key without it gets a permission error. Protected folders (e.g. a context root) cannot be deleted at all, however empty.',
12850
+ description: 'Permanently delete a folder by id. The folder must be EMPTY first \u2014 it must contain no documents, no records, and no sub-folders \u2014 and a non-empty folder is refused, which is the most common way this call fails. Use record_query with this folderId, and document_query, to see what is in it. Clearing it differs by content type: a document can be moved out (document_update with a different folderId) or deleted. A RECORD can also be re-filed into another folder \u2014 the API supports it \u2014 but THIS SERVER does not expose that: record_update has no folderId argument, so from here your only option is record_delete (needs records:d). Do NOT read that as "the record cannot be moved" and delete the record on that basis: if the record should be kept, tell the user to move it with the Vectros API/SDK directly rather than deleting it here. A sub-folder cannot be re-parented at all, so nested folders have to be emptied and deleted innermost-first. Note the emptiness check counts everything in the folder, INCLUDING items your credential cannot read \u2014 so a refusal you cannot account for from what you can list is expected behaviour, not a bug, and retrying will not clear it. Requires the key to allow folders:d \u2014 a key without it gets a permission error. Protected folders (e.g. a context root) cannot be deleted at all, however empty.',
12091
12851
  inputSchema: inputSchema19,
12092
12852
  // Deletes. Idempotent in the standard REST sense: the end state ("this id no longer
12093
12853
  // resolves") is the same whether this is the first delete or a repeat of one.
@@ -12113,7 +12873,7 @@ var inputSchema20 = {
12113
12873
  var currentIdentity = ({ log, apiKey, environment }) => ({
12114
12874
  name: "current_identity",
12115
12875
  title: "Current identity (tenant + principal scope)",
12116
- 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 verb+ownership reach as { userId, scopes[] }, where each scope is a `namespace:value` string (e.g. \"org:<uuid>\"). Note: this does not yet include granted_capabilities (member-lifecycle / forensic-read / context-directory-read / delegate-mint, as of API 0.40.0, joined by delegate-principal-stamp in 0.42.0) \u2014 a separate reach dimension a scope clause can carry that /v1/ping does not report yet, so allowedActions+dataScope may understate a credential's true reach. 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.",
12876
+ 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 verb+ownership reach as { userId, scopes[] }, where each scope is a `namespace:value` string (e.g. \"org:<uuid>\"). Note: this does not include granted_capabilities (member-lifecycle / forensic-read / context-directory-read / delegate-mint, as of API 0.40.0, joined by delegate-principal-stamp in 0.42.0 and trigger-control-plane-grant in 0.44.0) \u2014 a separate reach dimension a scope clause can carry that /v1/ping does not report, so allowedActions+dataScope may understate a credential's true reach. 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.",
12117
12877
  inputSchema: inputSchema20,
12118
12878
  // A pure read (/v1/ping) — never creates, modifies, or deletes anything server-side.
12119
12879
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
@@ -12240,14 +13000,14 @@ var inputSchema21 = {
12240
13000
  // Common (both modes):
12241
13001
  folderId: import_zod21.z.string().optional().describe("Optional folder to ingest into. Default: tenant root."),
12242
13002
  userId: import_zod21.z.string().optional().describe("Owning user ID. Optional."),
12243
- scopes: import_zod21.z.array(import_zod21.z.string()).optional().describe(
13003
+ scopes: import_zod21.z.array(import_zod21.z.string()).max(MAX_OWNERSHIP_SCOPES, `scopes accepts at most ${MAX_OWNERSHIP_SCOPES} entries`).optional().describe(
12244
13004
  "TEXT MODE ONLY. Scope ownership as `namespace:value` entries, at most 2 (e.g. [\"org:<uuid>\", \"group:eng-team\"]). `org` and `client` are reserved namespace names, registered like any other; others are namespaces you registered yourself. This is the document's COMPLETE scope declaration and values must come from the credential's own identity. An empty array `[]` creates a PRIVATE document owned by the calling user alone. Omit to stamp the credential's full identity \u2014 the default. Rejected with `filePath` (file uploads do not accept a scope declaration): a file-uploaded document is stamped with the credential's full identity."
12245
13005
  )
12246
13006
  };
12247
13007
  var documentIngest = ({ client, log, transport, ingestRoot }) => ({
12248
13008
  name: "document_ingest",
12249
13009
  title: "Ingest a new document (text body or file upload)",
12250
- description: "Create a new document in your Vectros tenant. Two modes:\n \u2022 Text mode: pass `text` (string body). Single-call. Use for crawled content, notes, generated text.\n \u2022 File mode: pass `filePath` (local path on the MCP server's host machine). STDIO-TRANSPORT ONLY \u2014 rejected on HTTP transport. MCP server reads the bytes, requests a presigned upload URL, and PUTs them. Returns when the upload is accepted (indexStatus: PENDING_INDEX); poll `document_get` until indexStatus is INDEXED. EXCEPTION \u2014 re-ingesting file mode against an externalId that already has a document (response `created:false`): the file body is replaced by ANY such re-ingest, whether or not `upsert` was set (`upsert` there only additionally applies `payload`/`title` to the matched document). The document keeps serving the OLD file's bytes until the new one is adopted, and indexStatus already reads INDEXED left over from that old file, so polling it returns immediately without waiting for the new content. Poll `document_get` and watch `fileItemId` instead \u2014 once it differs from the value it held before this call, the new file has been adopted. Re-request any download URL after that: one minted before adoption can stop working even within its stated `downloadExpires`.\nEither `text` or `filePath` must be present; both is an error. Idempotent by `externalId` (re-ingest returns the existing document, not a duplicate \u2014 requires documents:r in addition to documents:c, since being handed the existing document is a read of it; in FILE MODE a re-ingest against an existing externalId needs documents:u). TEXT MODE: without `upsert`, the existing document's content is genuinely unchanged. FILE MODE: as noted above, a re-ingest against an existing externalId always replaces the file body regardless of `upsert` \u2014 only the `payload`/`title` metadata overwrite is gated by it. To UPDATE an existing document instead \u2014 re-index an edited body \u2014 pass `upsert:true` with the same `externalId` (and the same `schemaId`); this is the re-sync primitive for keeping a knowledge base current. Pass `schemaId` + `payload` for a typed, lookup-queryable document (records parity). An `externalId` with no `schemaId` is refused (400) unless you also pass `confirmUntyped:true` to confirm that an untyped document is intended. indexMode defaults to HYBRID for untyped documents (omit to inherit a bound schema's default). storeText is a FILE-MODE knob (default true): false discards the uploaded file's extracted text after indexing (search + file download keep working; text retrieval and document_ask do not). Text-mode bodies are always retained, so storeText is not accepted with `text`.",
13010
+ description: "Create a new document in your Vectros tenant. Two modes:\n \u2022 Text mode: pass `text` (string body). Single-call. Use for crawled content, notes, generated text.\n \u2022 File mode: pass `filePath` (local path on the MCP server's host machine). STDIO-TRANSPORT ONLY \u2014 rejected on HTTP transport. MCP server reads the bytes, requests a presigned upload URL, and PUTs them. Returns when the upload is accepted (indexStatus: PENDING_INDEX); poll `document_get` until indexStatus is terminal: INDEXED, SKIPPED (no indexable text: `extraction.outcome` says why, e.g. NO_TEXT for an image or a scanned page), STORED (indexMode NONE) or FAILED. EXCEPTION \u2014 re-ingesting file mode against an externalId that already has a document (response `created:false`): the file body is replaced by ANY such re-ingest, whether or not `upsert` was set (`upsert` there only additionally applies `payload`/`title` to the matched document). The document keeps serving the OLD file's bytes until the new one is adopted, and indexStatus already reads INDEXED left over from that old file, so polling it returns immediately without waiting for the new content. Poll `document_get` and watch `fileItemId` instead \u2014 once it differs from the value it held before this call, the new file has been adopted. Re-request any download URL after that: one minted before adoption can stop working even within its stated `downloadExpires`.\nEither `text` or `filePath` must be present; both is an error. Idempotent by `externalId` (re-ingest returns the existing document, not a duplicate \u2014 requires documents:r in addition to documents:c, since being handed the existing document is a read of it; in FILE MODE a re-ingest against an existing externalId needs documents:u). TEXT MODE: without `upsert`, the existing document's content is genuinely unchanged. FILE MODE: as noted above, a re-ingest against an existing externalId always replaces the file body regardless of `upsert` \u2014 only the `payload`/`title` metadata overwrite is gated by it. To UPDATE an existing document instead \u2014 re-index an edited body \u2014 pass `upsert:true` with the same `externalId` (and the same `schemaId`); this is the re-sync primitive for keeping a knowledge base current. Pass `schemaId` + `payload` for a typed, lookup-queryable document (records parity). An `externalId` with no `schemaId` is refused (400) unless you also pass `confirmUntyped:true` to confirm that an untyped document is intended. indexMode defaults to HYBRID for untyped documents (omit to inherit a bound schema's default). storeText is a FILE-MODE knob (default true): false discards the uploaded file's extracted text after indexing (search + file download keep working; text retrieval and document_ask do not). Text-mode bodies are always retained, so storeText is not accepted with `text`.",
12251
13011
  inputSchema: inputSchema21,
12252
13012
  // Creates by default, idempotent ONLY when the caller supplies `externalId` (optional,
12253
13013
  // per the doc comment above) — re-ingest then returns the existing document rather than
@@ -12389,7 +13149,7 @@ var documentIngest = ({ client, log, transport, ingestRoot }) => ({
12389
13149
  "document_ingest file ok"
12390
13150
  );
12391
13151
  const uploadCreated = upload?.created;
12392
- const note = uploadCreated === false ? "File replaced: this re-ingest matched an existing externalId, which always replaces that document's file body (upsert or not \u2014 upsert only additionally applies payload/title to it). The next document_get call may already show indexStatus: INDEXED \u2014 that is left over from the PREVIOUS file, not confirmation the new one is ready, and the document keeps serving the old file's bytes until adoption completes. Poll document_get(id) and watch fileItemId instead: once it differs from the value it held before this call, the new file has been adopted. Any download URL already held for this document was minted for the old file and can stop working before its stated downloadExpires once adoption happens \u2014 request a fresh one after fileItemId changes." : "File uploaded; indexing is asynchronous. Poll document_get(id) until indexStatus is INDEXED.";
13152
+ const note = uploadCreated === false ? "File replaced: this re-ingest matched an existing externalId, which always replaces that document's file body (upsert or not \u2014 upsert only additionally applies payload/title to it). The next document_get call may already show indexStatus: INDEXED \u2014 that is left over from the PREVIOUS file, not confirmation the new one is ready, and the document keeps serving the old file's bytes until adoption completes. Poll document_get(id) and watch fileItemId instead: once it differs from the value it held before this call, the new file has been adopted. Any download URL already held for this document was minted for the old file and can stop working before its stated downloadExpires once adoption happens \u2014 request a fresh one after fileItemId changes." : "File uploaded; indexing is asynchronous. Poll document_get(id) until indexStatus is INDEXED, SKIPPED (no indexable text; see extraction.outcome), STORED or FAILED.";
12393
13153
  return {
12394
13154
  content: [
12395
13155
  {
@@ -12562,6 +13322,365 @@ var versionHistory = ({ client, log }) => ({
12562
13322
  });
12563
13323
  var version_history_default = versionHistory;
12564
13324
 
13325
+ // src/tools/agent_list.ts
13326
+ var import_zod24 = require("zod");
13327
+ var MCP_DEFAULT_LIMIT6 = 10;
13328
+ var MCP_MAX_LIMIT6 = 100;
13329
+ function toAgentSummary(agent) {
13330
+ return {
13331
+ id: agent.id,
13332
+ name: agent.name,
13333
+ description: agent.description,
13334
+ latestVersion: agent.latestVersion,
13335
+ status: agent.status
13336
+ };
13337
+ }
13338
+ var inputSchema24 = {
13339
+ includeRetired: import_zod24.z.boolean().optional().describe("Also list retired and purged agents (neither can be run). Default false."),
13340
+ startFrom: import_zod24.z.string().optional().describe("Pagination cursor: pass the `nextCursor` from the previous page to fetch the next."),
13341
+ limit: import_zod24.z.number().int().min(1).max(MCP_MAX_LIMIT6).optional().describe(`Max agents per page. Default ${MCP_DEFAULT_LIMIT6}, max ${MCP_MAX_LIMIT6}.`)
13342
+ };
13343
+ var agentList = ({ client, log }) => ({
13344
+ name: "agent_list",
13345
+ title: "List agents",
13346
+ description: "List the stored agents you can run with agent_run, newest first. Each is returned as its `id`, `name`, `description`, `latestVersion` and `status`; only an `ACTIVE` agent can be run. Retired and purged agents are left out unless `includeRetired` is true. Returns a `{ data, nextCursor }` page: a non-null `nextCursor` means more remain, pass it back as `startFrom`. Needs the `runs:c` or `agents:r` scope; running a listed agent needs `runs:c`, so a credential with only `agents:r` can list agents but not run them.",
13347
+ inputSchema: inputSchema24,
13348
+ // A pure read: it lists definitions and changes nothing.
13349
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
13350
+ handler: async (args) => {
13351
+ const limit = args.limit ?? MCP_DEFAULT_LIMIT6;
13352
+ try {
13353
+ const page = await client.agents.listAgents({
13354
+ includeRetired: args.includeRetired,
13355
+ startFrom: args.startFrom,
13356
+ limit
13357
+ });
13358
+ const data = (page.data ?? []).map(toAgentSummary);
13359
+ const nextCursor = page.nextCursor ?? null;
13360
+ log.debug({ tool: "agent_list", limit, returned: data.length }, "agent_list ok");
13361
+ return { content: [{ type: "text", text: JSON.stringify({ data, nextCursor }, null, 2) }] };
13362
+ } catch (err) {
13363
+ log.warn({ tool: "agent_list", err: String(err) }, "agent_list failed");
13364
+ return toolError("agent_list", err);
13365
+ }
13366
+ }
13367
+ });
13368
+ var agent_list_default = agentList;
13369
+
13370
+ // src/tools/agent_run.ts
13371
+ var import_node_crypto = require("crypto");
13372
+ var import_zod25 = require("zod");
13373
+
13374
+ // src/run-stream.ts
13375
+ var TEXT_PROGRESS_CHARS = 256;
13376
+ var HEARTBEAT_MS = 15e3;
13377
+ var TERMINAL_STATUS = {
13378
+ "run.completed": "COMPLETED",
13379
+ "run.failed": "FAILED",
13380
+ "run.cancelled": "CANCELLED"
13381
+ };
13382
+ function str(v) {
13383
+ return typeof v === "string" && v.length > 0 ? v : void 0;
13384
+ }
13385
+ function num(v) {
13386
+ return typeof v === "number" && Number.isFinite(v) ? v : void 0;
13387
+ }
13388
+ async function consumeRunStream(stream, initialRunId, onProgress, heartbeatMs = HEARTBEAT_MS) {
13389
+ const result = {
13390
+ runId: initialRunId,
13391
+ terminal: false,
13392
+ status: "UNKNOWN",
13393
+ text: "",
13394
+ toolCalls: []
13395
+ };
13396
+ const blocks = [];
13397
+ let pending = "";
13398
+ let unsentChars = 0;
13399
+ const emit = async (message) => {
13400
+ if (!onProgress) return;
13401
+ try {
13402
+ await onProgress(message);
13403
+ } catch {
13404
+ }
13405
+ };
13406
+ let heartbeat;
13407
+ let lastEventAt = Date.now();
13408
+ if (onProgress) {
13409
+ heartbeat = setInterval(() => {
13410
+ if (Date.now() - lastEventAt >= heartbeatMs) {
13411
+ lastEventAt = Date.now();
13412
+ void emit("run still working");
13413
+ }
13414
+ }, Math.max(1, Math.floor(heartbeatMs / 3)));
13415
+ heartbeat.unref?.();
13416
+ }
13417
+ try {
13418
+ for await (const raw of stream) {
13419
+ lastEventAt = Date.now();
13420
+ if (!raw || typeof raw !== "object") continue;
13421
+ const ev = raw;
13422
+ result.runId ??= str(ev.runId);
13423
+ const type = typeof ev.type === "string" ? ev.type : "";
13424
+ switch (type) {
13425
+ case "run.started":
13426
+ result.agentId = str(ev.agentId) ?? result.agentId;
13427
+ result.agentVersion = num(ev.agentVersion) ?? result.agentVersion;
13428
+ await emit("run started");
13429
+ break;
13430
+ case "message.delta": {
13431
+ const piece = typeof ev.text === "string" ? ev.text : "";
13432
+ pending += piece;
13433
+ unsentChars += piece.length;
13434
+ if (unsentChars >= TEXT_PROGRESS_CHARS) {
13435
+ unsentChars = 0;
13436
+ await emit(`answer: ${blocks.join("\n\n").length + pending.length} characters so far`);
13437
+ }
13438
+ break;
13439
+ }
13440
+ case "message.completed": {
13441
+ const full = str(ev.text) ?? pending;
13442
+ if (full.length > 0) blocks.push(full);
13443
+ pending = "";
13444
+ unsentChars = 0;
13445
+ await emit("model call completed");
13446
+ break;
13447
+ }
13448
+ case "tool.completed": {
13449
+ const call = {
13450
+ tool: str(ev.tool),
13451
+ outcome: str(ev.outcome),
13452
+ code: str(ev.code)
13453
+ };
13454
+ result.toolCalls.push(call);
13455
+ await emit(`tool ${call.tool ?? "call"}: ${call.outcome ?? "ended"}`);
13456
+ break;
13457
+ }
13458
+ default:
13459
+ break;
13460
+ }
13461
+ if (ev.terminal === true || Object.hasOwn(TERMINAL_STATUS, type)) {
13462
+ result.terminal = true;
13463
+ result.status = str(ev.status) ?? TERMINAL_STATUS[type] ?? "ENDED";
13464
+ result.reason = str(ev.reason);
13465
+ result.errorCode = str(ev.errorCode);
13466
+ if (typeof ev.settled === "boolean" || ev.inferenceBalanceCentsChargedMilli !== void 0 || ev.inferenceBalanceCentsRefundedMilli !== void 0) {
13467
+ result.charged = {
13468
+ settled: typeof ev.settled === "boolean" ? ev.settled : void 0,
13469
+ inferenceBalanceCentsChargedMilli: num(ev.inferenceBalanceCentsChargedMilli),
13470
+ inferenceBalanceCentsRefundedMilli: num(ev.inferenceBalanceCentsRefundedMilli)
13471
+ };
13472
+ }
13473
+ break;
13474
+ }
13475
+ }
13476
+ } catch (err) {
13477
+ result.streamError = err instanceof Error ? err.message : String(err);
13478
+ } finally {
13479
+ if (heartbeat) clearInterval(heartbeat);
13480
+ }
13481
+ if (pending.length > 0) blocks.push(pending);
13482
+ result.text = blocks.join("\n\n");
13483
+ return result;
13484
+ }
13485
+
13486
+ // src/tools/agent_run.ts
13487
+ var RUN_ID_HEADER = "x-vectros-run-id";
13488
+ var MAX_INPUT_CHARS = 1e5;
13489
+ var MAX_INPUT_BYTES = 24e4;
13490
+ function encodedInputBytes(v) {
13491
+ return Buffer.byteLength(JSON.stringify(v), "utf8");
13492
+ }
13493
+ var TERMINAL_EVENT_TYPES = /* @__PURE__ */ new Set(["run.completed", "run.failed", "run.cancelled"]);
13494
+ var ENDED_STATUSES = /* @__PURE__ */ new Set(["COMPLETED", "FAILED", "CANCELLED", "EXPIRED"]);
13495
+ var inputSchema25 = {
13496
+ agentId: import_zod25.z.string().min(1, "agentId must be non-empty").describe("The agent to run: an `id` from agent_list."),
13497
+ input: import_zod25.z.string().min(1, "input must be non-empty").max(MAX_INPUT_CHARS, `input accepts at most ${MAX_INPUT_CHARS} characters`).refine(
13498
+ (v) => encodedInputBytes(v) <= MAX_INPUT_BYTES,
13499
+ `input accepts at most ${MAX_INPUT_BYTES} bytes as sent (a JSON string in UTF-8)`
13500
+ ).describe(
13501
+ `What the agent is asked, 1 to ${MAX_INPUT_CHARS} characters and at most ${MAX_INPUT_BYTES} bytes as sent (a JSON string in UTF-8; most control characters other than newline and tab count six bytes).`
13502
+ ),
13503
+ agentVersion: import_zod25.z.number().int().min(1).optional().describe("The agent version to run. Default: its latest version."),
13504
+ maxInferenceCents: import_zod25.z.number().int().min(1).optional().describe(
13505
+ "The most this run's model calls may cost, in US cents. It can only lower the agent's own budget (a higher value is refused); a value below the platform minimum is refused with errorCode `BUDGET_TOO_LOW`, whose message names the minimum. Default: the agent's budget. A run that reaches it ends `FAILED` with errorCode `BUDGET_EXCEEDED`."
13506
+ ),
13507
+ readOnly: import_zod25.z.boolean().optional().describe("When true, every tool call that would change data is refused in this run. Default false."),
13508
+ idempotencyKey: import_zod25.z.string().regex(/^[A-Za-z0-9._:-]{1,128}$/, "idempotencyKey is 1 to 128 letters, digits, `.`, `_`, `:` or `-`").optional().describe(
13509
+ "Makes a retried call safe: the same key with the same arguments never starts a second run; the retry returns that run's id and status (`alreadyStarted: true`) instead. Its answer text is not returned again; read how it ended with run_get. Default: a new key per call."
13510
+ )
13511
+ };
13512
+ var agentRun = ({ client, log }) => ({
13513
+ name: "agent_run",
13514
+ title: "Run an agent",
13515
+ description: "Run a stored agent (from agent_list) on one `input` and return its answer. The agent's tool calls act as you, with your own permissions, and only through the tools the agent lists; set `readOnly` to refuse every tool call that would change data. Cap the run's model cost with `maxInferenceCents` (it can only lower the agent's own budget). The run is billed: model calls against your inference balance, and a fee per run, tool calls and run time against your plan. An agent can search the web or fetch a page when its definition lists that web tool (web fetch also needs your tenant's owner to switch it on, and a run of an agent that lists `web_search` is refused while the platform has web search disabled). Returns `{ runId, agentId, agentVersion, status, terminal, reason, errorCode, text, toolCalls, charged }`; `charged` carries the run's charge and refund in milli-cents (1 cent = 1000). Progress notifications keep the call alive while the run works for a client that resets its timeout on progress; cancelling the call cancels the run once the run is named (almost at once). If `terminal` is false the result arrived before the run ended: read it with run_get, which needs `runs:r` as well. Calling again without `idempotencyKey` starts a new, billed run. Needs the `runs:c` scope.",
13516
+ inputSchema: inputSchema25,
13517
+ // Not a read: a run is billed, and its tool calls may create, change or delete data with the
13518
+ // caller's permissions, so a host should confirm it. Not idempotent: each call is a new paid run
13519
+ // unless the same idempotencyKey is passed again.
13520
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
13521
+ handler: async (args, extra) => {
13522
+ const agentId = args.agentId;
13523
+ const maxInferenceCents = args.maxInferenceCents;
13524
+ const idempotencyKey = args.idempotencyKey ?? (0, import_node_crypto.randomUUID)();
13525
+ const request = {
13526
+ "Idempotency-Key": idempotencyKey,
13527
+ agentId,
13528
+ agentVersion: args.agentVersion,
13529
+ input: { text: args.input },
13530
+ budget: maxInferenceCents !== void 0 ? { maxInferenceCents } : void 0,
13531
+ readOnly: args.readOnly
13532
+ };
13533
+ const progressToken = extra._meta?.progressToken;
13534
+ let progressCount = 0;
13535
+ const onProgress = progressToken !== void 0 && extra.sendNotification ? async (message) => {
13536
+ progressCount += 1;
13537
+ await extra.sendNotification({
13538
+ method: "notifications/progress",
13539
+ params: { progressToken, progress: progressCount, message }
13540
+ });
13541
+ } : void 0;
13542
+ const streamAbort = new AbortController();
13543
+ const callSignal = extra.signal;
13544
+ let knownRunId;
13545
+ let headersReceived = false;
13546
+ let cancelRequested = false;
13547
+ let cancelSent = false;
13548
+ let runEnded = false;
13549
+ const sendCancel = () => {
13550
+ if (!cancelRequested || cancelSent || !knownRunId || runEnded) return;
13551
+ cancelSent = true;
13552
+ const id = knownRunId;
13553
+ client.agents.cancelRun({ id }).then(
13554
+ () => log.info({ tool: "agent_run", runId: id }, "agent_run cancelled by the client"),
13555
+ (err) => log.warn({ tool: "agent_run", runId: id, err: String(err) }, "agent_run cancel failed")
13556
+ );
13557
+ };
13558
+ const cancelIfNamed = () => {
13559
+ if (!cancelRequested || !headersReceived || !knownRunId) return;
13560
+ sendCancel();
13561
+ streamAbort.abort();
13562
+ };
13563
+ const onCancel = () => {
13564
+ cancelRequested = true;
13565
+ cancelIfNamed();
13566
+ };
13567
+ if (callSignal?.aborted) {
13568
+ return toolError("agent_run", new Error("The call was cancelled before the run started."));
13569
+ }
13570
+ callSignal?.addEventListener("abort", onCancel, { once: true });
13571
+ try {
13572
+ const { data: stream, rawResponse } = await client.agents.createRun(request, { abortSignal: streamAbort.signal }).withRawResponse();
13573
+ headersReceived = true;
13574
+ knownRunId = rawResponse.headers.get(RUN_ID_HEADER) ?? void 0;
13575
+ cancelIfNamed();
13576
+ const naming = async function* () {
13577
+ for await (const ev of stream) {
13578
+ if (!knownRunId && ev && typeof ev === "object") {
13579
+ const id = ev.runId;
13580
+ if (typeof id === "string" && id.length > 0) {
13581
+ knownRunId = id;
13582
+ cancelIfNamed();
13583
+ }
13584
+ }
13585
+ if (ev && typeof ev === "object") {
13586
+ const e = ev;
13587
+ if (e.terminal === true || typeof e.type === "string" && TERMINAL_EVENT_TYPES.has(e.type)) runEnded = true;
13588
+ }
13589
+ yield ev;
13590
+ }
13591
+ };
13592
+ const run = await consumeRunStream(naming(), knownRunId, onProgress);
13593
+ knownRunId ??= run.runId;
13594
+ if (run.terminal) runEnded = true;
13595
+ sendCancel();
13596
+ log.debug(
13597
+ {
13598
+ tool: "agent_run",
13599
+ runId: run.runId,
13600
+ status: run.status,
13601
+ terminal: run.terminal,
13602
+ toolCalls: run.toolCalls.length,
13603
+ textLength: run.text.length
13604
+ },
13605
+ "agent_run ok"
13606
+ );
13607
+ const body = {
13608
+ runId: run.runId,
13609
+ agentId: run.agentId ?? agentId,
13610
+ agentVersion: run.agentVersion,
13611
+ status: run.status,
13612
+ terminal: run.terminal,
13613
+ reason: run.reason,
13614
+ errorCode: run.errorCode,
13615
+ text: run.text,
13616
+ toolCalls: run.toolCalls,
13617
+ charged: run.charged
13618
+ };
13619
+ if (!run.terminal) {
13620
+ body.note = cancelRequested ? "The call was cancelled and the run was asked to stop. Read it with run_get (needs the `runs:r` scope) to see how it ended." : "The stream ended before the run did" + (run.streamError ? ` (${run.streamError})` : "") + ". The run may still be working: read it with run_get until `terminal` is true (run_get needs the `runs:r` scope).";
13621
+ }
13622
+ return { content: [{ type: "text", text: JSON.stringify(body, null, 2) }] };
13623
+ } catch (err) {
13624
+ const e = err;
13625
+ if (e?.body?.errorCode === "IDEMPOTENCY_IN_PROGRESS") {
13626
+ const runId = (typeof e.body.runId === "string" ? e.body.runId : void 0) ?? e.rawResponse?.headers?.get?.(RUN_ID_HEADER) ?? void 0;
13627
+ if (runId) {
13628
+ const status = typeof e.body.status === "string" ? e.body.status : void 0;
13629
+ log.info({ tool: "agent_run", runId }, "agent_run: the idempotency key already started a run");
13630
+ const body = {
13631
+ runId,
13632
+ agentId,
13633
+ status,
13634
+ // The 409 names the run's status at the time; an ended status is final.
13635
+ terminal: status !== void 0 && ENDED_STATUSES.has(status),
13636
+ alreadyStarted: true,
13637
+ note: "This idempotency key already started this run, so no new run was started. Its answer text is not returned again and cannot be read back: run_get (needs the `runs:r` scope) shows how the run ended and what it was charged, never its text. To start another run, pass a new idempotencyKey."
13638
+ };
13639
+ return { content: [{ type: "text", text: JSON.stringify(body, null, 2) }] };
13640
+ }
13641
+ }
13642
+ log.warn({ tool: "agent_run", agentId, err: String(err) }, "agent_run failed");
13643
+ const result = toolError("agent_run", err);
13644
+ const statusCode = err?.statusCode;
13645
+ if (typeof statusCode !== "number" || statusCode === 408 || statusCode >= 500) {
13646
+ result.content[0].text += `
13647
+ idempotencyKey: ${idempotencyKey}
13648
+ A run may have started before this error. Call agent_run again with the same arguments and this idempotencyKey: if a run started, the call names it; if not, it starts one.` + (cancelRequested ? " (The call was cancelled; a run that started could not be cancelled.)" : "");
13649
+ }
13650
+ return result;
13651
+ } finally {
13652
+ callSignal?.removeEventListener("abort", onCancel);
13653
+ }
13654
+ }
13655
+ });
13656
+ var agent_run_default = agentRun;
13657
+
13658
+ // src/tools/run_get.ts
13659
+ var import_zod26 = require("zod");
13660
+ var inputSchema26 = {
13661
+ runId: import_zod26.z.string().min(1, "runId must be non-empty").describe("The run id agent_run returned (`runId`).")
13662
+ };
13663
+ var runGet = ({ client, log }) => ({
13664
+ name: "run_get",
13665
+ title: "Get an agent run",
13666
+ description: "Read one agent run by id: `status` (`RUNNING`, `COMPLETED`, `FAILED`, `CANCELLED` or `EXPIRED`), `terminal` (whether it has ended; poll until true), `reason`, `errorCode`, `steps`, its `toolCalls` (each tool and how it ended, never its arguments or result) and `usage` (what it was charged, in milli-cents). It does not return the answer text: agent_run returns that. Use it when agent_run returned `terminal: false`. Needs the `runs:r` scope, which starting a run (`runs:c`) does not include: a credential with only `runs:c` gets `403` here, and learns how its runs end only from agent_run's own result.",
13667
+ inputSchema: inputSchema26,
13668
+ // A pure read: polling a run does not change it.
13669
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
13670
+ handler: async (args) => {
13671
+ const runId = args.runId;
13672
+ try {
13673
+ const run = await client.agents.getRun({ id: runId });
13674
+ log.debug({ tool: "run_get", runId, status: run.status, terminal: run.terminal }, "run_get ok");
13675
+ return { content: [{ type: "text", text: JSON.stringify(run, null, 2) }] };
13676
+ } catch (err) {
13677
+ log.warn({ tool: "run_get", runId, err: String(err) }, "run_get failed");
13678
+ return toolError("run_get", err);
13679
+ }
13680
+ }
13681
+ });
13682
+ var run_get_default = runGet;
13683
+
12565
13684
  // src/tools/types.ts
12566
13685
  var TOOL_NAMES = [
12567
13686
  "hybrid_search",
@@ -12586,7 +13705,10 @@ var TOOL_NAMES = [
12586
13705
  "current_identity",
12587
13706
  "document_ingest",
12588
13707
  "lookup_principal",
12589
- "version_history"
13708
+ "version_history",
13709
+ "agent_list",
13710
+ "agent_run",
13711
+ "run_get"
12590
13712
  ];
12591
13713
 
12592
13714
  // src/tools/index.ts
@@ -12613,7 +13735,10 @@ var ALL_TOOL_FACTORIES = {
12613
13735
  current_identity: current_identity_default,
12614
13736
  document_ingest: document_ingest_default,
12615
13737
  lookup_principal: lookup_principal_default,
12616
- version_history: version_history_default
13738
+ version_history: version_history_default,
13739
+ agent_list: agent_list_default,
13740
+ agent_run: agent_run_default,
13741
+ run_get: run_get_default
12617
13742
  };
12618
13743
 
12619
13744
  // src/resources/schemas.ts
@@ -12637,7 +13762,7 @@ var identityResource = ({ log, apiKey, environment }) => ({
12637
13762
  name: "identity",
12638
13763
  uri: "vectros://identity",
12639
13764
  title: "Current identity (tenant + principal scope)",
12640
- 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[] }). Note: this does not yet include granted_capabilities (member-lifecycle / forensic-read / context-directory-read / delegate-mint, as of API 0.40.0, joined by delegate-principal-stamp in 0.42.0) \u2014 a separate reach dimension a scope clause can carry that /v1/ping does not report yet, so allowedActions+dataScope may understate a credential's true reach. Also reports 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.",
13765
+ 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[] }). Note: this does not include granted_capabilities (member-lifecycle / forensic-read / context-directory-read / delegate-mint, as of API 0.40.0, joined by delegate-principal-stamp in 0.42.0 and trigger-control-plane-grant in 0.44.0) \u2014 a separate reach dimension a scope clause can carry that /v1/ping does not report, so allowedActions+dataScope may understate a credential's true reach. Also reports 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.",
12641
13766
  mimeType: "application/json",
12642
13767
  read: async () => {
12643
13768
  const identity = await resolveIdentity({ log, apiKey, environment });
@@ -12656,11 +13781,12 @@ var ALL_RESOURCE_FACTORIES = {
12656
13781
  };
12657
13782
 
12658
13783
  // src/zod-to-json-schema.ts
12659
- var import_zod24 = require("zod");
13784
+ var import_zod27 = require("zod");
12660
13785
  function zodShapeToJsonSchema(shape) {
12661
13786
  const properties = {};
12662
13787
  const required = [];
12663
- for (const [name, schema] of Object.entries(shape)) {
13788
+ for (const [name, entry] of Object.entries(shape)) {
13789
+ const schema = entry;
12664
13790
  properties[name] = zodTypeToJsonSchema(schema);
12665
13791
  if (!schema.isOptional()) required.push(name);
12666
13792
  }
@@ -12669,43 +13795,45 @@ function zodShapeToJsonSchema(shape) {
12669
13795
  return out;
12670
13796
  }
12671
13797
  function zodTypeToJsonSchema(schema) {
12672
- const description = schema.description;
13798
+ const descriptionOf = (s) => s.description;
13799
+ let description = descriptionOf(schema);
12673
13800
  let current = schema;
12674
- while (current instanceof import_zod24.z.ZodOptional || current instanceof import_zod24.z.ZodDefault || current instanceof import_zod24.z.ZodNullable) {
13801
+ while (current instanceof import_zod27.z.ZodOptional || current instanceof import_zod27.z.ZodDefault || current instanceof import_zod27.z.ZodNullable) {
12675
13802
  current = current._def.innerType;
13803
+ description ??= descriptionOf(current);
12676
13804
  }
12677
13805
  const base = description ? { description } : {};
12678
- if (current instanceof import_zod24.z.ZodString) {
13806
+ if (current instanceof import_zod27.z.ZodString) {
12679
13807
  return { ...base, type: "string" };
12680
13808
  }
12681
- if (current instanceof import_zod24.z.ZodNumber) {
13809
+ if (current instanceof import_zod27.z.ZodNumber) {
12682
13810
  return { ...base, type: "number" };
12683
13811
  }
12684
- if (current instanceof import_zod24.z.ZodBoolean) {
13812
+ if (current instanceof import_zod27.z.ZodBoolean) {
12685
13813
  return { ...base, type: "boolean" };
12686
13814
  }
12687
- if (current instanceof import_zod24.z.ZodEnum) {
13815
+ if (current instanceof import_zod27.z.ZodEnum) {
12688
13816
  return {
12689
13817
  ...base,
12690
13818
  type: "string",
12691
13819
  enum: current.options
12692
13820
  };
12693
13821
  }
12694
- if (current instanceof import_zod24.z.ZodArray) {
13822
+ if (current instanceof import_zod27.z.ZodArray) {
12695
13823
  return {
12696
13824
  ...base,
12697
13825
  type: "array",
12698
13826
  items: zodTypeToJsonSchema(current.element)
12699
13827
  };
12700
13828
  }
12701
- if (current instanceof import_zod24.z.ZodObject) {
13829
+ if (current instanceof import_zod27.z.ZodObject) {
12702
13830
  return {
12703
13831
  ...base,
12704
13832
  ...zodShapeToJsonSchema(current.shape)
12705
13833
  };
12706
13834
  }
12707
- if (current instanceof import_zod24.z.ZodRecord) {
12708
- const valueType = current._def.valueType;
13835
+ if (current instanceof import_zod27.z.ZodRecord) {
13836
+ const valueType = current.valueType;
12709
13837
  return {
12710
13838
  ...base,
12711
13839
  type: "object",
@@ -12833,7 +13961,7 @@ var VectrosMCPServer = class {
12833
13961
  if (!tool) {
12834
13962
  result = toolError(req.params.name ?? "unknown", new Error("No such tool."));
12835
13963
  } else {
12836
- const parsed = import_zod25.z.object(tool.inputSchema).strict().safeParse(req.params.arguments ?? {});
13964
+ const parsed = import_zod28.z.object(tool.inputSchema).strict().safeParse(req.params.arguments ?? {});
12837
13965
  if (!parsed.success) {
12838
13966
  result = toolError(tool.name, new Error(formatArgError(tool, parsed.error)));
12839
13967
  } else {
@@ -12896,7 +14024,7 @@ var VectrosMCPServer = class {
12896
14024
  *
12897
14025
  * If `validateOnStart` (default true) is enabled, performs a
12898
14026
  * GET /v1/ping check BEFORE wiring the transport. On failure,
12899
- * throws — the partner's MCP client sees a startup error instead
14027
+ * throws — your MCP client sees a startup error instead
12900
14028
  * of a confusing "tools work but the first call 401s" experience.
12901
14029
  */
12902
14030
  async connect(transport) {
@@ -12957,7 +14085,7 @@ var VectrosMCPServer = class {
12957
14085
 
12958
14086
  // src/transport/http.ts
12959
14087
  var import_node_http = require("http");
12960
- var import_node_crypto = require("crypto");
14088
+ var import_node_crypto2 = require("crypto");
12961
14089
  var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
12962
14090
  function constantTimeEqual(a, b) {
12963
14091
  if (a.length !== b.length) return false;
@@ -13020,7 +14148,7 @@ async function startHttpTransport(opts) {
13020
14148
  let allowedHosts = /* @__PURE__ */ new Set();
13021
14149
  let allowedOrigins = /* @__PURE__ */ new Set();
13022
14150
  const mcpTransport = new import_streamableHttp.StreamableHTTPServerTransport({
13023
- sessionIdGenerator: () => (0, import_node_crypto.randomUUID)()
14151
+ sessionIdGenerator: () => (0, import_node_crypto2.randomUUID)()
13024
14152
  });
13025
14153
  await mcpServer.connect(mcpTransport);
13026
14154
  const httpServer = (0, import_node_http.createServer)(async (req, res) => {