@vectros-ai/cli 0.10.0 → 0.11.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.mjs CHANGED
@@ -1619,7 +1619,7 @@ var require_proper_lockfile = __commonJS({
1619
1619
  // src/cli-bootstrap.ts
1620
1620
  import * as readline from "readline/promises";
1621
1621
 
1622
- // node_modules/@vectros-ai/sdk/dist/index.mjs
1622
+ // ../../node_modules/@vectros-ai/sdk/dist/index.mjs
1623
1623
  var __defProp2 = Object.defineProperty;
1624
1624
  var __export = (target, all) => {
1625
1625
  for (var name in all)
@@ -1654,6 +1654,7 @@ __export(api_exports, {
1654
1654
  FileUploadRequest: () => FileUploadRequest,
1655
1655
  ForbiddenError: () => ForbiddenError,
1656
1656
  IdentityLookupRequest: () => IdentityLookupRequest,
1657
+ IndexFailure: () => IndexFailure,
1657
1658
  InternalServerError: () => InternalServerError,
1658
1659
  ListEntitiesRequestOrder: () => ListEntitiesRequestOrder,
1659
1660
  ListUsersRequestOrder: () => ListUsersRequestOrder,
@@ -2175,6 +2176,17 @@ var IdentityLookupRequest;
2175
2176
  Desc: "desc"
2176
2177
  };
2177
2178
  })(IdentityLookupRequest || (IdentityLookupRequest = {}));
2179
+ var IndexFailure;
2180
+ ((IndexFailure2) => {
2181
+ IndexFailure2.Code = {
2182
+ SourceUnavailable: "SOURCE_UNAVAILABLE",
2183
+ TextIndexFailed: "TEXT_INDEX_FAILED",
2184
+ EmbeddingFailed: "EMBEDDING_FAILED",
2185
+ IndexingFailed: "INDEXING_FAILED",
2186
+ VectorLimitExceeded: "VECTOR_LIMIT_EXCEEDED",
2187
+ Internal: "INTERNAL"
2188
+ };
2189
+ })(IndexFailure || (IndexFailure = {}));
2178
2190
  var ModelDataVersionResponse;
2179
2191
  ((ModelDataVersionResponse2) => {
2180
2192
  ModelDataVersionResponse2.ChangeType = {
@@ -5691,7 +5703,7 @@ var AuthClient = class {
5691
5703
  );
5692
5704
  }
5693
5705
  /**
5694
- * Creates a short-lived JWT bearer token restricted to specific actions and, optionally, to a particular user, organization, or client. Use this to hand a narrowly-scoped credential to a browser or downstream service so it never sees your root API key. Only callable with a root API key (`sk_*`).
5706
+ * Creates a short-lived JWT bearer token restricted to specific actions and, optionally, to a particular user or identity entity (in any namespace). Use this to hand a narrowly-scoped credential to a browser or downstream service so it never sees your root API key. Only callable with a root API key (`sk_*`).
5695
5707
  *
5696
5708
  * @param {Vectros.TokenRequest} request
5697
5709
  * @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -5908,7 +5920,7 @@ var ComplianceClient = class {
5908
5920
  this._options = normalizeClientOptionsWithAuth(options);
5909
5921
  }
5910
5922
  /**
5911
- * Submits a right-to-erasure request for a single end-subject (a user, client, or organization). Erasure removes exactly the data the subject solely owns across the declared contexts, plus the subject's identity and lookup rows. It never touches another account's data and never cascades into another subject's data. The request is asynchronous: it returns 202 with a `requestId`; poll `GET /v1/erasure-requests/{id}` until the job completes to obtain the completion certificate. Requires a root API key — a scoped credential is rejected with 403.
5923
+ * Submits a right-to-erasure request for a single end-subject (a user, or an identity entity in any namespace). Erasure removes exactly the data the subject solely owns across the declared contexts, plus the subject's identity and lookup rows. It never touches another account's data and never cascades into another subject's data. The request is asynchronous: it returns 202 with a `requestId`; poll `GET /v1/erasure-requests/{id}` until the job completes to obtain the completion certificate. Requires a root API key — a scoped credential is rejected with 403.
5912
5924
  *
5913
5925
  * @param {Vectros.ErasureRequest} request
5914
5926
  * @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -12485,19 +12497,21 @@ function extractServerError(err) {
12485
12497
  const statusCode = typeof e.statusCode === "number" ? e.statusCode : void 0;
12486
12498
  let serverMessage;
12487
12499
  let requestId;
12500
+ let errorCode;
12488
12501
  if (e.body && typeof e.body === "object") {
12489
12502
  const b = e.body;
12490
12503
  if (typeof b.message === "string" && b.message.trim()) serverMessage = b.message.trim();
12491
12504
  if (typeof b.requestId === "string" && b.requestId.trim()) requestId = b.requestId.trim();
12505
+ if (typeof b.errorCode === "string" && b.errorCode.trim()) errorCode = b.errorCode.trim();
12492
12506
  } else if (typeof e.body === "string" && e.body.trim()) {
12493
12507
  serverMessage = e.body.trim();
12494
12508
  }
12495
- if (serverMessage) return { statusCode, message: serverMessage, requestId };
12509
+ if (serverMessage) return { statusCode, message: serverMessage, requestId, errorCode };
12496
12510
  const message = typeof e.message === "string" ? e.message : "";
12497
12511
  const isSdkEnvelope = /\nStatus code:/.test(message);
12498
- if (message && !isSdkEnvelope) return { statusCode, message, requestId };
12499
- if (statusCode) return { statusCode, message: `HTTP ${statusCode}`, requestId };
12500
- if (message) return { statusCode, message, requestId };
12512
+ if (message && !isSdkEnvelope) return { statusCode, message, requestId, errorCode };
12513
+ if (statusCode) return { statusCode, message: `HTTP ${statusCode}`, requestId, errorCode };
12514
+ if (message) return { statusCode, message, requestId, errorCode };
12501
12515
  }
12502
12516
  return { message: String(err) };
12503
12517
  }
@@ -12508,15 +12522,17 @@ async function devRouteError(res, action) {
12508
12522
  const raw = await res.text().catch(() => "");
12509
12523
  let message;
12510
12524
  let requestId;
12525
+ let errorCode;
12511
12526
  try {
12512
12527
  const parsed = JSON.parse(raw);
12513
12528
  if (typeof parsed.message === "string" && parsed.message.trim()) message = parsed.message.trim();
12514
12529
  if (typeof parsed.requestId === "string" && parsed.requestId.trim()) requestId = parsed.requestId.trim();
12530
+ if (typeof parsed.errorCode === "string" && parsed.errorCode.trim()) errorCode = parsed.errorCode.trim();
12515
12531
  } catch {
12516
12532
  }
12517
12533
  const err = new Error(`${action}: HTTP ${res.status}`);
12518
12534
  err.statusCode = res.status;
12519
- err.body = { message: message ?? `HTTP ${res.status}`, requestId };
12535
+ err.body = { message: message ?? `HTTP ${res.status}`, requestId, errorCode };
12520
12536
  return err;
12521
12537
  }
12522
12538
  function formatCliError(err, opts) {
@@ -12525,14 +12541,28 @@ function formatCliError(err, opts) {
12525
12541
  const block = actionable ?? ` \u2716 ${opts.action}: ${info.message}
12526
12542
  `;
12527
12543
  const debug = opts.debug ?? Boolean(process.env.VECTROS_MCP_DEBUG);
12528
- if (debug && info.requestId) {
12529
- return `${block} (requestId: ${info.requestId} \u2014 quote this to support)
12544
+ if (debug && (info.requestId || info.errorCode)) {
12545
+ const parts = [
12546
+ info.errorCode ? `errorCode: ${info.errorCode}` : null,
12547
+ info.requestId ? `requestId: ${info.requestId}` : null
12548
+ ].filter(Boolean);
12549
+ return `${block} (${parts.join(", ")} \u2014 quote this to support)
12530
12550
  `;
12531
12551
  }
12532
12552
  return block;
12533
12553
  }
12534
12554
  function renderActionableError(info) {
12535
12555
  const msg = info.message;
12556
+ switch (info.errorCode) {
12557
+ case "SESSION_REFRESH_REQUIRED":
12558
+ return ` \u2716 Your session has expired.
12559
+ Run 'vectros login' to re-authenticate, then retry.
12560
+ `;
12561
+ case "RATE_LIMITED":
12562
+ return ` \u2716 ${msg}
12563
+ You're being rate-limited \u2014 wait a moment and retry.
12564
+ `;
12565
+ }
12536
12566
  if (/scoped-key limit reached/i.test(msg)) {
12537
12567
  const plan = /plan '([^']+)'/i.exec(msg)?.[1];
12538
12568
  const count = /\((\d+) active keys\)/i.exec(msg)?.[1];
@@ -13081,8 +13111,13 @@ var KNOWN_CONTROL_PLANE_RESOURCES = [
13081
13111
  "users",
13082
13112
  "billing",
13083
13113
  "admin",
13084
- "clients",
13085
- "orgs"
13114
+ // Identity/compartment provisioning. The flat `orgs`/`clients` resources were
13115
+ // folded into the generic `entities` (per-namespace) + `namespaces` surfaces,
13116
+ // which is what the API now scopes on — so those are the current spellings a
13117
+ // pack could name. (Cosmetic: any non-data-plane resource hard-rejects whether
13118
+ // or not it is listed here; this list only sharpens the error message.)
13119
+ "entities",
13120
+ "namespaces"
13086
13121
  ];
13087
13122
  var VALID_OPS = /* @__PURE__ */ new Set(["c", "r", "u", "d"]);
13088
13123
  var DATA_PLANE_SET = new Set(DATA_PLANE_ALLOWLIST);
@@ -13529,6 +13564,21 @@ async function runLoader(client, input) {
13529
13564
  let seededCount = 0;
13530
13565
  const seededRecordIds = [];
13531
13566
  const seededDocumentIds = [];
13567
+ const seedIndexFailures = [];
13568
+ const noteIfIndexFailed = (created, rec, surface) => {
13569
+ if (created.indexStatus !== "FAILED") return;
13570
+ seedIndexFailures.push({
13571
+ externalId: rec.externalId,
13572
+ typeName: rec.typeName,
13573
+ surface,
13574
+ code: created.indexFailure?.code,
13575
+ message: created.indexFailure?.message
13576
+ });
13577
+ log.warn(
13578
+ { component: "loader", typeName: rec.typeName, externalId: rec.externalId, code: created.indexFailure?.code },
13579
+ "seed stored but failed to index"
13580
+ );
13581
+ };
13532
13582
  for (const rec of skipSeed ? [] : blueprint.seed ?? []) {
13533
13583
  const schemaId = schemaIds[rec.typeName];
13534
13584
  if (!schemaId) {
@@ -13549,6 +13599,7 @@ async function runLoader(client, input) {
13549
13599
  }
13550
13600
  });
13551
13601
  if (created.id) seededDocumentIds.push(created.id);
13602
+ noteIfIndexFailed(created, rec, "document");
13552
13603
  } else {
13553
13604
  const created = await ctxClient.records.createRecord({
13554
13605
  body: {
@@ -13560,6 +13611,7 @@ async function runLoader(client, input) {
13560
13611
  }
13561
13612
  });
13562
13613
  if (created.id) seededRecordIds.push(created.id);
13614
+ noteIfIndexFailed(created, rec, "record");
13563
13615
  }
13564
13616
  seededCount++;
13565
13617
  }
@@ -13578,7 +13630,8 @@ async function runLoader(client, input) {
13578
13630
  roleIds,
13579
13631
  seededCount,
13580
13632
  seededRecordIds,
13581
- seededDocumentIds
13633
+ seededDocumentIds,
13634
+ seedIndexFailures
13582
13635
  };
13583
13636
  }
13584
13637
  function buildPlan(blueprint, opts = {}) {
@@ -13833,6 +13886,17 @@ function seedSummaryLine(opts) {
13833
13886
  return opts.seededCount ? ` \u2714 Seeded ${opts.seededCount} record(s)
13834
13887
  ` : "";
13835
13888
  }
13889
+ function seedIndexWarningBlock(failures) {
13890
+ if (failures.length === 0) return "";
13891
+ const lines = failures.map((f) => {
13892
+ const reason = f.message ?? f.code ?? "indexing failed";
13893
+ return ` \u2022 ${f.typeName}/${f.externalId} (${f.surface}): ${reason}
13894
+ `;
13895
+ });
13896
+ return ` \u26A0 ${failures.length} seed(s) stored but not fully searchable:
13897
+ ` + lines.join("") + ` They're stored and retrievable by id, but won't appear in search until the issue above is resolved.
13898
+ `;
13899
+ }
13836
13900
  function reconcileTally(items, noun) {
13837
13901
  if (items.length === 0) return null;
13838
13902
  const created = items.filter((i) => i.action === "created").length;
@@ -14089,7 +14153,7 @@ ${renderPlan(blueprint, planSteps)}
14089
14153
  noSeed,
14090
14154
  declinedInteractively: seedDeclinedInteractively,
14091
14155
  seededCount: result.seededCount
14092
- })
14156
+ }) + seedIndexWarningBlock(result.seedIndexFailures)
14093
14157
  );
14094
14158
  const entry = buildVectrosServerEntry({ apiKey: result.rawKey, apiBaseUrl: baseUrl });
14095
14159
  const isCode = args.client === "code";
@@ -15370,6 +15434,25 @@ function canonicalDim(key) {
15370
15434
  if (key === "userId" || key === "partnerUserId") return "user";
15371
15435
  return key;
15372
15436
  }
15437
+ var FORBIDDEN_SCOPE_NAMESPACES = /* @__PURE__ */ new Set([
15438
+ "user",
15439
+ "record",
15440
+ "document",
15441
+ "entity",
15442
+ "self",
15443
+ "tenant",
15444
+ "context",
15445
+ "scope",
15446
+ "versions",
15447
+ "lookup"
15448
+ ]);
15449
+ var SCOPE_NAMESPACE_RE = /^[a-z][a-z0-9_-]{1,31}$/;
15450
+ function isRecognizedOwnershipKey(key) {
15451
+ if (key === "userId" || key === "partnerUserId") return true;
15452
+ if (!key.startsWith("scope:")) return false;
15453
+ const ns = key.slice("scope:".length);
15454
+ return !FORBIDDEN_SCOPE_NAMESPACES.has(ns) && SCOPE_NAMESPACE_RE.test(ns);
15455
+ }
15373
15456
  var SELF_TOKEN_RE2 = /^\$\{\{\s*self\.[a-zA-Z.]+\s*\}\}$/;
15374
15457
  function normalizeClauses(raw) {
15375
15458
  const out = [];
@@ -15379,15 +15462,18 @@ function normalizeClauses(raw) {
15379
15462
  const actions = obj.allowed_actions ?? obj.allowedActions ?? [];
15380
15463
  const ds = obj.data_scope ?? obj.dataScope ?? {};
15381
15464
  const dataScope = {};
15465
+ const unrecognizedDims = [];
15382
15466
  for (const [k, v] of Object.entries(ds)) {
15467
+ const dim = canonicalDim(k);
15383
15468
  const values = Array.isArray(v) ? v : [v];
15384
- dataScope[canonicalDim(k)] = values.map((val) => {
15469
+ dataScope[dim] = values.map((val) => {
15385
15470
  if (val === null) return null;
15386
15471
  const s = String(val);
15387
15472
  return SELF_TOKEN_RE2.test(s) ? SELF : s;
15388
15473
  });
15474
+ if (!isRecognizedOwnershipKey(k)) unrecognizedDims.push(k);
15389
15475
  }
15390
- out.push({ actions: Array.isArray(actions) ? actions.map(String) : [], dataScope });
15476
+ out.push({ actions: Array.isArray(actions) ? actions.map(String) : [], dataScope, unrecognizedDims });
15391
15477
  }
15392
15478
  return out;
15393
15479
  }
@@ -15398,6 +15484,7 @@ function buildArchetypes(clauses) {
15398
15484
  ];
15399
15485
  const scopeDims = /* @__PURE__ */ new Map();
15400
15486
  for (const c of clauses) {
15487
+ if (c.unrecognizedDims.length > 0) continue;
15401
15488
  for (const [dim, values] of Object.entries(c.dataScope)) {
15402
15489
  if (dim === "user") continue;
15403
15490
  const set = scopeDims.get(dim) ?? /* @__PURE__ */ new Set();
@@ -15421,6 +15508,7 @@ function buildArchetypes(clauses) {
15421
15508
  return rows;
15422
15509
  }
15423
15510
  function clauseMatches(clause, arch) {
15511
+ if (clause.unrecognizedDims.length > 0) return false;
15424
15512
  for (const [dim, allowed] of Object.entries(clause.dataScope)) {
15425
15513
  const recordValue = arch.owners[dim];
15426
15514
  const ok = allowed.some((a) => {
@@ -15486,7 +15574,14 @@ async function runAccessExplain(opts, deps = {}) {
15486
15574
  context: opts.context,
15487
15575
  via,
15488
15576
  identityOverrides: profile.identityOverrides,
15489
- clauses: clauses.map((c, i) => ({ n: i + 1, actions: c.actions, dataScope: renderDataScope(c.dataScope) })),
15577
+ clauses: clauses.map((c, i) => ({
15578
+ n: i + 1,
15579
+ actions: c.actions,
15580
+ dataScope: renderDataScope(c.dataScope),
15581
+ // Present only on a dead clause — an unrecognized dim the platform
15582
+ // denies (a retired key or a bad scope:<ns>); the matrix omits it.
15583
+ ...c.unrecognizedDims.length > 0 ? { grantsNothing: true, unrecognizedDims: c.unrecognizedDims } : {}
15584
+ })),
15490
15585
  matrix: rows,
15491
15586
  note: "Ownership dimensions only: per-type action qualifiers narrow further, and search/RAG visibility is bounded per row by the same clause's typed read grants. Client-side preview; the platform decides at request time."
15492
15587
  })}
@@ -15505,6 +15600,12 @@ async function runAccessExplain(opts, deps = {}) {
15505
15600
  clauses.forEach((c, i) => {
15506
15601
  process.stdout.write(` ${i + 1}. [${c.actions.join(", ")}] where ${renderDataScope(c.dataScope)}
15507
15602
  `);
15603
+ if (c.unrecognizedDims.length > 0) {
15604
+ process.stdout.write(
15605
+ ` \u2716 grants nothing \u2014 unrecognized dimension${c.unrecognizedDims.length > 1 ? "s" : ""}: ${c.unrecognizedDims.join(", ")} (the platform denies a clause keyed on any dim that is not userId or a valid scope:<namespace>)
15606
+ `
15607
+ );
15608
+ }
15508
15609
  });
15509
15610
  process.stdout.write(
15510
15611
  "\n" + formatTable(rows, [
@@ -18250,8 +18351,8 @@ function emitJoined(alias, context, principalId, role, keyId, reused) {
18250
18351
 
18251
18352
  // src/build-info.ts
18252
18353
  var BUILD_INFO = {
18253
- cli: true ? "0.10.0" : "dev",
18254
- sdk: true ? "0.35.0" : "dev",
18354
+ cli: true ? "0.11.0" : "dev",
18355
+ sdk: true ? "0.36.0" : "dev",
18255
18356
  blueprints: true ? "0.8.0" : "dev"
18256
18357
  };
18257
18358
  function formatBuildInfo() {