@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/AUTHORING.md +7 -0
- package/CHANGELOG.md +20 -0
- package/dist/cli.js +120 -19
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +120 -19
- package/dist/cli.mjs.map +1 -1
- package/package.json +2 -2
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
13085
|
-
|
|
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[
|
|
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) => ({
|
|
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.
|
|
18254
|
-
sdk: true ? "0.
|
|
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() {
|