@topolo/cli 0.12.12 → 0.12.14
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/index.js +40 -36
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { platform as platform2 } from "os";
|
|
|
9
9
|
import { createInterface } from "readline/promises";
|
|
10
10
|
import { stdin as input } from "process";
|
|
11
11
|
|
|
12
|
-
// node_modules
|
|
12
|
+
// node_modules/@topolo/sdk/dist/index.js
|
|
13
13
|
function applyAuthHeaders(headers, credential) {
|
|
14
14
|
if (credential.kind === "api_key") {
|
|
15
15
|
headers.set("X-Api-Key", credential.apiKey);
|
|
@@ -124,9 +124,9 @@ function canonicalTopoloServiceErrorCode(value) {
|
|
|
124
124
|
}
|
|
125
125
|
function sanitizeTopoloServiceMessage(value) {
|
|
126
126
|
if (typeof value !== "string") return void 0;
|
|
127
|
-
const
|
|
128
|
-
if (!
|
|
129
|
-
return
|
|
127
|
+
const text3 = value.replace(/[\u0000-\u001f\u007f-\u009f\u200b-\u200f\u2028-\u202e\u2066-\u2069\ufeff]/g, " ").replace(/\b[a-z][a-z0-9+.-]*:\/\/\S+/gi, "[url]").replace(/[^\s@<>()[\],;:"']+@[^\s@<>()[\],;:"']+\.[a-z]{2,}/gi, "[email]").replace(/[A-Za-z0-9_\-+/=.]{20,}/g, (run) => /[0-9]/.test(run) && /[A-Za-z]/.test(run) ? "[redacted]" : run).replace(/\s+/g, " ").trim();
|
|
128
|
+
if (!text3) return void 0;
|
|
129
|
+
return text3.length > SERVICE_MESSAGE_MAX_LENGTH ? `${text3.slice(0, SERVICE_MESSAGE_MAX_LENGTH - 1).trimEnd()}\u2026` : text3;
|
|
130
130
|
}
|
|
131
131
|
function canonicalTopoloRequestId(value) {
|
|
132
132
|
if (typeof value !== "string") return void 0;
|
|
@@ -194,10 +194,10 @@ var TopoloPermissionError = class extends TopoloSdkError {
|
|
|
194
194
|
};
|
|
195
195
|
function extractTopoloServiceErrorCode(body) {
|
|
196
196
|
if (!body || typeof body !== "object" || Array.isArray(body)) return null;
|
|
197
|
-
const
|
|
198
|
-
const topLevel = canonicalTopoloServiceErrorCode(
|
|
197
|
+
const record3 = body;
|
|
198
|
+
const topLevel = canonicalTopoloServiceErrorCode(record3.code);
|
|
199
199
|
if (topLevel) return topLevel;
|
|
200
|
-
const nested =
|
|
200
|
+
const nested = record3.error;
|
|
201
201
|
const nestedString = canonicalTopoloServiceErrorCode(nested);
|
|
202
202
|
if (nestedString) return nestedString;
|
|
203
203
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
@@ -209,13 +209,13 @@ function extractTopoloServiceErrorCode(body) {
|
|
|
209
209
|
}
|
|
210
210
|
function extractTopoloServiceErrorMessage(body) {
|
|
211
211
|
if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
|
|
212
|
-
const
|
|
213
|
-
const nested =
|
|
212
|
+
const record3 = body;
|
|
213
|
+
const nested = record3.error;
|
|
214
214
|
const candidates = [];
|
|
215
215
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
216
216
|
candidates.push(nested.message);
|
|
217
217
|
}
|
|
218
|
-
candidates.push(
|
|
218
|
+
candidates.push(record3.message, record3.error_description);
|
|
219
219
|
if (typeof nested === "string" && !canonicalTopoloServiceErrorCode(nested)) candidates.push(nested);
|
|
220
220
|
for (const candidate of candidates) {
|
|
221
221
|
const message2 = sanitizeTopoloServiceMessage(candidate);
|
|
@@ -228,14 +228,14 @@ function serviceErrorCode(body, fallback) {
|
|
|
228
228
|
}
|
|
229
229
|
function extractTopoloServiceErrorDetails(body) {
|
|
230
230
|
if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
|
|
231
|
-
const
|
|
232
|
-
let candidate =
|
|
233
|
-
const nested =
|
|
231
|
+
const record3 = body;
|
|
232
|
+
let candidate = record3.details;
|
|
233
|
+
const nested = record3.error;
|
|
234
234
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
235
235
|
const nestedRecord = nested;
|
|
236
236
|
if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
|
|
237
237
|
}
|
|
238
|
-
if (candidate === void 0) candidate =
|
|
238
|
+
if (candidate === void 0) candidate = record3;
|
|
239
239
|
if (Array.isArray(candidate)) return validationIssueDetails(canonicalTopoloValidationIssues(candidate)) ?? void 0;
|
|
240
240
|
if (!candidate || typeof candidate !== "object") return void 0;
|
|
241
241
|
const source = candidate;
|
|
@@ -294,18 +294,18 @@ function validationIssueDetails(issues) {
|
|
|
294
294
|
return paths.length ? { paths, issues } : { issues };
|
|
295
295
|
}
|
|
296
296
|
function issue(path, message2) {
|
|
297
|
-
const
|
|
298
|
-
if (!path && !
|
|
299
|
-
return { ...path ? { path } : {}, ...
|
|
297
|
+
const text3 = sanitizeTopoloServiceMessage(message2);
|
|
298
|
+
if (!path && !text3) return null;
|
|
299
|
+
return { ...path ? { path } : {}, ...text3 ? { message: text3 } : {} };
|
|
300
300
|
}
|
|
301
301
|
function canonicalTopoloValidationIssues(values) {
|
|
302
302
|
const issues = [];
|
|
303
303
|
for (const value of values) {
|
|
304
304
|
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
305
|
-
const
|
|
306
|
-
const path = canonicalTopoloValidationPath(
|
|
305
|
+
const record3 = value;
|
|
306
|
+
const path = canonicalTopoloValidationPath(record3.field) ?? canonicalTopoloValidationPath(record3.path);
|
|
307
307
|
if (!path) continue;
|
|
308
|
-
const projected = issue(path,
|
|
308
|
+
const projected = issue(path, record3.message);
|
|
309
309
|
if (projected) issues.push(projected);
|
|
310
310
|
if (issues.length === SERVICE_ISSUE_LIMIT) break;
|
|
311
311
|
}
|
|
@@ -437,10 +437,10 @@ function sensitive(key, value) {
|
|
|
437
437
|
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
438
438
|
if (normalized === "capability") {
|
|
439
439
|
if (typeof value !== "string") return value !== null && value !== void 0 && typeof value !== "boolean" && typeof value !== "number";
|
|
440
|
-
const
|
|
441
|
-
return Boolean(
|
|
440
|
+
const text3 = value.trim();
|
|
441
|
+
return Boolean(text3) && !/^[a-z][a-z0-9_-]{0,31}$/.test(text3);
|
|
442
442
|
}
|
|
443
|
-
return ["authorization", "cookie", "setcookie", "proxyauthorization"].includes(normalized) || /(token|secret|password|privatekey|apikey)$/.test(normalized);
|
|
443
|
+
return ["authorization", "cookie", "setcookie", "proxyauthorization"].includes(normalized) || /(token|secret|password|privatekey|apikey|backupcodes?|recoverycodes?)$/.test(normalized);
|
|
444
444
|
}
|
|
445
445
|
function maskActionSecrets(value, secrets) {
|
|
446
446
|
let masked = value;
|
|
@@ -467,6 +467,9 @@ async function protectActionResult(value, store) {
|
|
|
467
467
|
const secrets = /* @__PURE__ */ new Map();
|
|
468
468
|
async function protect(item, key = "") {
|
|
469
469
|
if (isActionSecretReference(item)) return item;
|
|
470
|
+
if (Array.isArray(item) && /(?:backup|recovery)codes$/.test(key.toLowerCase().replace(/[^a-z0-9]/g, ""))) {
|
|
471
|
+
return Promise.all(item.map((child) => protect(child, key)));
|
|
472
|
+
}
|
|
470
473
|
if (sensitive(key, item)) {
|
|
471
474
|
const reference = store ? await store.save(item) : "[REDACTED]";
|
|
472
475
|
if (typeof item === "string" && item) secrets.set(item, reference);
|
|
@@ -722,7 +725,7 @@ function inspectSchema(schema, path, root, depth) {
|
|
|
722
725
|
if (unsupportedKeyword) {
|
|
723
726
|
return { path, code: "unsupported_schema_keyword", message: `Action schema uses unsupported keyword ${unsupportedKeyword}.` };
|
|
724
727
|
}
|
|
725
|
-
if (typeof schema.format === "string" && !["uri", "email", "date-time"].includes(schema.format)) {
|
|
728
|
+
if (typeof schema.format === "string" && !["uri", "email", "date-time", "uuid"].includes(schema.format)) {
|
|
726
729
|
return { path, code: "unsupported_schema_format", message: `Action schema uses unsupported format ${schema.format}.` };
|
|
727
730
|
}
|
|
728
731
|
if (typeof schema.$ref === "string" && !resolveLocalReference(root, schema.$ref)) {
|
|
@@ -859,6 +862,7 @@ function validateString(schema, value, path, errors) {
|
|
|
859
862
|
if (schema.format === "uri" && !isUrl(value)) errors.push({ path, code: "format_uri", message: "Expected an absolute URL." });
|
|
860
863
|
if (schema.format === "email" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(value)) errors.push({ path, code: "format_email", message: "Expected an email address." });
|
|
861
864
|
if (schema.format === "date-time" && !isDateTime(value)) errors.push({ path, code: "format_date_time", message: "Expected an ISO-8601 date-time." });
|
|
865
|
+
if (schema.format === "uuid" && (value.length !== 36 || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value))) errors.push({ path, code: "format_uuid", message: "Expected a hyphenated UUID." });
|
|
862
866
|
}
|
|
863
867
|
function validateNumber(schema, value, path, errors) {
|
|
864
868
|
if (typeof schema.minimum === "number" && value < schema.minimum) errors.push({ path, code: "minimum", message: `Expected a value of at least ${schema.minimum}.` });
|
|
@@ -1916,14 +1920,14 @@ var TopoloClient = class _TopoloClient {
|
|
|
1916
1920
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
1917
1921
|
throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is unavailable.");
|
|
1918
1922
|
}
|
|
1919
|
-
const
|
|
1920
|
-
if (
|
|
1923
|
+
const record3 = raw;
|
|
1924
|
+
if (record3.algorithm !== "sha256-v1" || typeof record3.digest !== "string" || !/^[a-f0-9]{64}$/.test(record3.digest) || !Number.isSafeInteger(record3.actionCount) || Number(record3.actionCount) < 0) {
|
|
1921
1925
|
throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is invalid.");
|
|
1922
1926
|
}
|
|
1923
1927
|
return {
|
|
1924
1928
|
algorithm: "sha256-v1",
|
|
1925
|
-
digest:
|
|
1926
|
-
actionCount: Number(
|
|
1929
|
+
digest: record3.digest,
|
|
1930
|
+
actionCount: Number(record3.actionCount)
|
|
1927
1931
|
};
|
|
1928
1932
|
}
|
|
1929
1933
|
/** @deprecated Prefer searchActions() so callers retain the continuation cursor. */
|
|
@@ -2641,10 +2645,10 @@ function extractRequired(body) {
|
|
|
2641
2645
|
if (Array.isArray(maybe.required)) return canonicalTopoloRequired(maybe.required);
|
|
2642
2646
|
for (const nested of [maybe.details, maybe.error]) {
|
|
2643
2647
|
if (!nested || typeof nested !== "object" || Array.isArray(nested)) continue;
|
|
2644
|
-
const
|
|
2645
|
-
if (Array.isArray(
|
|
2646
|
-
if (
|
|
2647
|
-
const required =
|
|
2648
|
+
const record3 = nested;
|
|
2649
|
+
if (Array.isArray(record3.required)) return canonicalTopoloRequired(record3.required);
|
|
2650
|
+
if (record3.details && typeof record3.details === "object" && !Array.isArray(record3.details)) {
|
|
2651
|
+
const required = record3.details.required;
|
|
2648
2652
|
if (Array.isArray(required)) return canonicalTopoloRequired(required);
|
|
2649
2653
|
}
|
|
2650
2654
|
}
|
|
@@ -2719,8 +2723,8 @@ function compactResultValue(value, depth, budget) {
|
|
|
2719
2723
|
return value.length > ACTION_RESULT_MAX_ITEMS ? { count: value.length, items, omittedItems: value.length - ACTION_RESULT_MAX_ITEMS } : items;
|
|
2720
2724
|
}
|
|
2721
2725
|
if (typeof value === "object") {
|
|
2722
|
-
const
|
|
2723
|
-
const allKeys = Object.keys(
|
|
2726
|
+
const record3 = value;
|
|
2727
|
+
const allKeys = Object.keys(record3);
|
|
2724
2728
|
const ranked = allKeys.sort((left, right) => resultKeyPriority(left) - resultKeyPriority(right));
|
|
2725
2729
|
const prioritized = ranked.filter((key) => resultKeyPriority(key) < 2);
|
|
2726
2730
|
const ordinary = ranked.filter((key) => resultKeyPriority(key) === 2);
|
|
@@ -2729,7 +2733,7 @@ function compactResultValue(value, depth, budget) {
|
|
|
2729
2733
|
...prioritized,
|
|
2730
2734
|
...ordinary.slice(0, ordinaryLimit)
|
|
2731
2735
|
].slice(0, ACTION_RESULT_MAX_KEYS);
|
|
2732
|
-
const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(
|
|
2736
|
+
const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(record3[key], depth + 1, budget)]));
|
|
2733
2737
|
if (allKeys.length > keys.length) compact["_omittedKeys"] = allKeys.length - keys.length;
|
|
2734
2738
|
return compact;
|
|
2735
2739
|
}
|
|
@@ -3493,7 +3497,7 @@ function createTopolo(options) {
|
|
|
3493
3497
|
};
|
|
3494
3498
|
}
|
|
3495
3499
|
|
|
3496
|
-
// node_modules
|
|
3500
|
+
// node_modules/@topolo/sdk/dist/node/credential-store.js
|
|
3497
3501
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2, chmod as chmod2, rm as rm2, stat } from "fs/promises";
|
|
3498
3502
|
import { existsSync as existsSync2 } from "fs";
|
|
3499
3503
|
import { homedir as homedir2, platform } from "os";
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/cli",
|
|
3
3
|
"packageManager": "pnpm@10.17.1",
|
|
4
|
-
"version": "0.12.
|
|
5
|
-
"topoloPublishedVersion": "0.12.
|
|
4
|
+
"version": "0.12.14",
|
|
5
|
+
"topoloPublishedVersion": "0.12.14",
|
|
6
6
|
"description": "Public command-line interface for Topolo customer organizations, developers, and agents.",
|
|
7
7
|
"license": "UNLICENSED",
|
|
8
8
|
"author": "Topolo",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
31
|
-
"@topolo/mcp": "0.14.
|
|
32
|
-
"@topolo/sdk": "0.
|
|
31
|
+
"@topolo/mcp": "0.14.7",
|
|
32
|
+
"@topolo/sdk": "0.23.2",
|
|
33
33
|
"commander": "^12.1.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|