@topolo/mcp 0.11.11 → 0.12.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/dispatch.js +1 -1
- package/dist/http.js +2957 -1514
- package/dist/index.js +902 -45
- package/package.json +10 -5
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
|
|
6
|
-
// node_modules/@topolo/sdk/dist/index.js
|
|
6
|
+
// node_modules/.pnpm/@topolo+sdk@0.17.1/node_modules/@topolo/sdk/dist/index.js
|
|
7
7
|
function applyAuthHeaders(headers, credential) {
|
|
8
8
|
if (credential.kind === "api_key") {
|
|
9
9
|
headers.set("X-Api-Key", credential.apiKey);
|
|
@@ -80,6 +80,7 @@ var ERROR_CODE_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;
|
|
|
80
80
|
var TOPOLO_REQUEST_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
81
81
|
var CLOUDFLARE_RAY_ID_PATTERN = /^[0-9a-f]{16}-[A-Z]{3}$/;
|
|
82
82
|
var PERMISSION_PATTERN = /^[a-z][a-z0-9_-]{0,63}(?:\.[a-z][a-z0-9_-]{0,63})*:(?:[a-z][a-z0-9_-]{0,63}|\*)$/;
|
|
83
|
+
var PUBLIC_FIELD_PATH_PATTERN = /^[$.a-z0-9_[\]-]{1,160}$/i;
|
|
83
84
|
var RETRY_AFTER_DATE_PATTERN = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/;
|
|
84
85
|
var PUBLIC_DETAIL_SOURCES = /* @__PURE__ */ new Set([
|
|
85
86
|
"api_key_introspection",
|
|
@@ -166,10 +167,10 @@ var TopoloPermissionError = class extends TopoloSdkError {
|
|
|
166
167
|
};
|
|
167
168
|
function extractTopoloServiceErrorCode(body) {
|
|
168
169
|
if (!body || typeof body !== "object" || Array.isArray(body)) return null;
|
|
169
|
-
const
|
|
170
|
-
const topLevel = canonicalTopoloErrorCode(
|
|
170
|
+
const record2 = body;
|
|
171
|
+
const topLevel = canonicalTopoloErrorCode(record2.code);
|
|
171
172
|
if (topLevel) return topLevel;
|
|
172
|
-
const nested =
|
|
173
|
+
const nested = record2.error;
|
|
173
174
|
const nestedString = canonicalTopoloErrorCode(nested);
|
|
174
175
|
if (nestedString) return nestedString;
|
|
175
176
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
@@ -184,15 +185,19 @@ function serviceErrorCode(body, fallback) {
|
|
|
184
185
|
}
|
|
185
186
|
function extractTopoloServiceErrorDetails(body) {
|
|
186
187
|
if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
|
|
187
|
-
const
|
|
188
|
-
let candidate =
|
|
189
|
-
const nested =
|
|
188
|
+
const record2 = body;
|
|
189
|
+
let candidate = record2.details;
|
|
190
|
+
const nested = record2.error;
|
|
190
191
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
191
192
|
const nestedRecord = nested;
|
|
192
193
|
if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
|
|
193
194
|
}
|
|
194
|
-
if (candidate === void 0) candidate =
|
|
195
|
-
if (
|
|
195
|
+
if (candidate === void 0) candidate = record2;
|
|
196
|
+
if (Array.isArray(candidate)) {
|
|
197
|
+
const paths = canonicalTopoloValidationPaths(candidate);
|
|
198
|
+
return paths.length ? { paths } : void 0;
|
|
199
|
+
}
|
|
200
|
+
if (!candidate || typeof candidate !== "object") return void 0;
|
|
196
201
|
const source = candidate;
|
|
197
202
|
const safe = {};
|
|
198
203
|
for (const [key, value] of Object.entries(source)) {
|
|
@@ -229,12 +234,42 @@ function extractTopoloServiceErrorDetails(body) {
|
|
|
229
234
|
continue;
|
|
230
235
|
}
|
|
231
236
|
if (["missingFields", "fields", "paths"].includes(key) && Array.isArray(value)) {
|
|
232
|
-
const paths = value.filter((item) => typeof item === "string" &&
|
|
237
|
+
const paths = value.filter((item) => typeof item === "string" && PUBLIC_FIELD_PATH_PATTERN.test(item));
|
|
233
238
|
if (paths.length) safe[key] = paths;
|
|
234
239
|
}
|
|
235
240
|
}
|
|
236
241
|
return Object.keys(safe).length ? safe : void 0;
|
|
237
242
|
}
|
|
243
|
+
function canonicalTopoloValidationPaths(issues) {
|
|
244
|
+
const paths = [];
|
|
245
|
+
for (const issue of issues) {
|
|
246
|
+
if (!issue || typeof issue !== "object" || Array.isArray(issue)) continue;
|
|
247
|
+
const record2 = issue;
|
|
248
|
+
const path = canonicalTopoloValidationPath(record2.field) ?? canonicalTopoloValidationPath(record2.path);
|
|
249
|
+
if (path && !paths.includes(path)) paths.push(path);
|
|
250
|
+
if (paths.length === 32) break;
|
|
251
|
+
}
|
|
252
|
+
return paths;
|
|
253
|
+
}
|
|
254
|
+
function canonicalTopoloValidationPath(value) {
|
|
255
|
+
if (typeof value === "string") {
|
|
256
|
+
const path2 = value.trim();
|
|
257
|
+
return PUBLIC_FIELD_PATH_PATTERN.test(path2) ? path2 : void 0;
|
|
258
|
+
}
|
|
259
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > 32) return void 0;
|
|
260
|
+
const segments = value.map((segment) => {
|
|
261
|
+
if (typeof segment === "number" && Number.isSafeInteger(segment) && segment >= 0) {
|
|
262
|
+
return String(segment);
|
|
263
|
+
}
|
|
264
|
+
if (typeof segment === "string" && /^[a-z0-9_$-]{1,80}$/i.test(segment)) {
|
|
265
|
+
return segment;
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
});
|
|
269
|
+
if (segments.includes(null)) return void 0;
|
|
270
|
+
const path = segments.join(".");
|
|
271
|
+
return PUBLIC_FIELD_PATH_PATTERN.test(path) ? path : void 0;
|
|
272
|
+
}
|
|
238
273
|
function publicTopoloErrorMessage(error) {
|
|
239
274
|
const code = canonicalTopoloErrorCode(
|
|
240
275
|
typeof error === "string" ? error : error.code ?? extractTopoloServiceErrorCode(error.body)
|
|
@@ -677,6 +712,222 @@ function isMultipleOf(value, divisor) {
|
|
|
677
712
|
const quotient = value / divisor;
|
|
678
713
|
return Math.abs(quotient - Math.round(quotient)) < Number.EPSILON * Math.max(1, Math.abs(quotient)) * 4;
|
|
679
714
|
}
|
|
715
|
+
var ACTOR_ENVELOPE_VERSION = 1;
|
|
716
|
+
var TOPOLO_ACTOR_ENVELOPE_HEADER = "X-Topolo-Actor-Envelope";
|
|
717
|
+
var PRINCIPAL_TYPES = /* @__PURE__ */ new Set([
|
|
718
|
+
"human",
|
|
719
|
+
"managed_agent",
|
|
720
|
+
"external_agent",
|
|
721
|
+
"service",
|
|
722
|
+
"browser_automation"
|
|
723
|
+
]);
|
|
724
|
+
var ACCOUNTABLE_SUBJECT_TYPES = /* @__PURE__ */ new Set(["human", "organization"]);
|
|
725
|
+
var CHANNELS = /* @__PURE__ */ new Set(["web", "mobile", "cli", "mcp", "api", "workflow", "browser_automation"]);
|
|
726
|
+
var ASSURANCE_LEVELS = /* @__PURE__ */ new Set(["authenticated", "workload_identity", "user_verified"]);
|
|
727
|
+
var HASH_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
728
|
+
var ActorEnvelopeValidationError = class extends Error {
|
|
729
|
+
path;
|
|
730
|
+
constructor(path, message) {
|
|
731
|
+
super(`${path}: ${message}`);
|
|
732
|
+
this.name = "ActorEnvelopeValidationError";
|
|
733
|
+
this.path = path;
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
function parseActorEnvelope(value) {
|
|
737
|
+
const envelope = record(value, "actorEnvelope");
|
|
738
|
+
exactKeys(envelope, [
|
|
739
|
+
"schemaVersion",
|
|
740
|
+
"organizationId",
|
|
741
|
+
"accountableSubject",
|
|
742
|
+
"performer",
|
|
743
|
+
"delegation",
|
|
744
|
+
"channel",
|
|
745
|
+
"assurance",
|
|
746
|
+
"action",
|
|
747
|
+
"issuedAt",
|
|
748
|
+
"expiresAt"
|
|
749
|
+
], "actorEnvelope");
|
|
750
|
+
if (envelope.schemaVersion !== ACTOR_ENVELOPE_VERSION) {
|
|
751
|
+
fail("actorEnvelope.schemaVersion", `must equal ${ACTOR_ENVELOPE_VERSION}`);
|
|
752
|
+
}
|
|
753
|
+
const accountableSubject = parseAccountableSubject(envelope.accountableSubject);
|
|
754
|
+
const performer = parseIdentity(envelope.performer, "actorEnvelope.performer");
|
|
755
|
+
const organizationId = text(envelope.organizationId, "actorEnvelope.organizationId");
|
|
756
|
+
const channel = member(envelope.channel, CHANNELS, "actorEnvelope.channel");
|
|
757
|
+
const issuedAt = timestamp(envelope.issuedAt, "actorEnvelope.issuedAt");
|
|
758
|
+
const expiresAt = envelope.expiresAt === void 0 ? void 0 : timestamp(envelope.expiresAt, "actorEnvelope.expiresAt");
|
|
759
|
+
if (expiresAt && Date.parse(expiresAt) <= Date.parse(issuedAt)) {
|
|
760
|
+
fail("actorEnvelope.expiresAt", "must be later than issuedAt");
|
|
761
|
+
}
|
|
762
|
+
const assuranceValue = record(envelope.assurance, "actorEnvelope.assurance");
|
|
763
|
+
exactKeys(assuranceValue, ["level", "methods"], "actorEnvelope.assurance");
|
|
764
|
+
const assurance = {
|
|
765
|
+
level: member(assuranceValue.level, ASSURANCE_LEVELS, "actorEnvelope.assurance.level"),
|
|
766
|
+
methods: textArray(assuranceValue.methods, "actorEnvelope.assurance.methods")
|
|
767
|
+
};
|
|
768
|
+
const actionValue = record(envelope.action, "actorEnvelope.action");
|
|
769
|
+
exactKeys(actionValue, ["requestId", "actionId", "resourceType", "resourceId", "inputHash"], "actorEnvelope.action");
|
|
770
|
+
const inputHash = text(actionValue.inputHash, "actorEnvelope.action.inputHash");
|
|
771
|
+
if (!HASH_PATTERN.test(inputHash)) fail("actorEnvelope.action.inputHash", "must be a lowercase sha256 digest");
|
|
772
|
+
const action = {
|
|
773
|
+
requestId: text(actionValue.requestId, "actorEnvelope.action.requestId"),
|
|
774
|
+
actionId: text(actionValue.actionId, "actorEnvelope.action.actionId"),
|
|
775
|
+
...actionValue.resourceType === void 0 ? {} : { resourceType: text(actionValue.resourceType, "actorEnvelope.action.resourceType") },
|
|
776
|
+
...actionValue.resourceId === void 0 ? {} : { resourceId: text(actionValue.resourceId, "actorEnvelope.action.resourceId") },
|
|
777
|
+
inputHash
|
|
778
|
+
};
|
|
779
|
+
if (action.resourceType === void 0 !== (action.resourceId === void 0)) {
|
|
780
|
+
fail("actorEnvelope.action", "resourceType and resourceId must be provided together");
|
|
781
|
+
}
|
|
782
|
+
const delegation = parseDelegation(envelope.delegation);
|
|
783
|
+
const directHuman = performer.principalType === "human" && performer.principalId === accountableSubject.principalId;
|
|
784
|
+
if (directHuman && delegation !== null) fail("actorEnvelope.delegation", "must be null for direct human action");
|
|
785
|
+
if (!directHuman && delegation === null) fail("actorEnvelope.delegation", "is required when performer differs from accountable subject");
|
|
786
|
+
if (delegation) {
|
|
787
|
+
const finalHop = delegation.lineage.at(-1);
|
|
788
|
+
if (!finalHop || finalHop.principalId !== performer.principalId || finalHop.principalType !== performer.principalType) {
|
|
789
|
+
fail("actorEnvelope.delegation.lineage", "must end with the performer");
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
if (performer.principalType === "external_agent" && (!performer.installationId || !performer.provider)) {
|
|
793
|
+
fail("actorEnvelope.performer", "external_agent requires installationId and provider");
|
|
794
|
+
}
|
|
795
|
+
if (performer.principalType === "managed_agent" && !performer.agentInstanceId) {
|
|
796
|
+
fail("actorEnvelope.performer.agentInstanceId", "is required for managed_agent");
|
|
797
|
+
}
|
|
798
|
+
if (performer.principalType === "browser_automation" && (!performer.installationId || !performer.browserSessionId)) {
|
|
799
|
+
fail("actorEnvelope.performer", "browser_automation requires installationId and browserSessionId");
|
|
800
|
+
}
|
|
801
|
+
return {
|
|
802
|
+
schemaVersion: ACTOR_ENVELOPE_VERSION,
|
|
803
|
+
organizationId,
|
|
804
|
+
accountableSubject,
|
|
805
|
+
performer,
|
|
806
|
+
delegation,
|
|
807
|
+
channel,
|
|
808
|
+
assurance,
|
|
809
|
+
action,
|
|
810
|
+
issuedAt,
|
|
811
|
+
...expiresAt ? { expiresAt } : {}
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
function canonicalizeActorEnvelope(value) {
|
|
815
|
+
return canonicalJson(parseActorEnvelope(value));
|
|
816
|
+
}
|
|
817
|
+
function encodeActorEnvelopeHeader(value) {
|
|
818
|
+
const bytes = new TextEncoder().encode(canonicalizeActorEnvelope(value));
|
|
819
|
+
const binary = Array.from(bytes, (byte) => String.fromCharCode(byte)).join("");
|
|
820
|
+
return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
821
|
+
}
|
|
822
|
+
function canonicalJson(value) {
|
|
823
|
+
if (value === null) return "null";
|
|
824
|
+
if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
|
|
825
|
+
if (typeof value === "number") {
|
|
826
|
+
if (!Number.isFinite(value)) throw new TypeError("Canonical JSON accepts finite numbers only.");
|
|
827
|
+
return JSON.stringify(value);
|
|
828
|
+
}
|
|
829
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
830
|
+
if (typeof value !== "object" || !value || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) {
|
|
831
|
+
throw new TypeError("Canonical JSON accepts JSON objects, arrays, and primitives only.");
|
|
832
|
+
}
|
|
833
|
+
const entries = Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right));
|
|
834
|
+
return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
|
|
835
|
+
}
|
|
836
|
+
function parseAccountableSubject(value) {
|
|
837
|
+
const path = "actorEnvelope.accountableSubject";
|
|
838
|
+
const subject = record(value, path);
|
|
839
|
+
exactKeys(subject, ["principalType", "principalId", "displayName"], path);
|
|
840
|
+
return {
|
|
841
|
+
principalType: member(subject.principalType, ACCOUNTABLE_SUBJECT_TYPES, `${path}.principalType`),
|
|
842
|
+
principalId: text(subject.principalId, `${path}.principalId`),
|
|
843
|
+
...subject.displayName === void 0 ? {} : { displayName: text(subject.displayName, `${path}.displayName`) }
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
async function sha256CanonicalValue(value) {
|
|
847
|
+
const bytes = new TextEncoder().encode(canonicalJson(value));
|
|
848
|
+
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
849
|
+
return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
850
|
+
}
|
|
851
|
+
function parseIdentity(value, path) {
|
|
852
|
+
const identity = record(value, path);
|
|
853
|
+
exactKeys(identity, [
|
|
854
|
+
"principalType",
|
|
855
|
+
"principalId",
|
|
856
|
+
"displayName",
|
|
857
|
+
"installationId",
|
|
858
|
+
"agentInstanceId",
|
|
859
|
+
"browserSessionId",
|
|
860
|
+
"provider",
|
|
861
|
+
"model"
|
|
862
|
+
], path);
|
|
863
|
+
return {
|
|
864
|
+
principalType: member(identity.principalType, PRINCIPAL_TYPES, `${path}.principalType`),
|
|
865
|
+
principalId: text(identity.principalId, `${path}.principalId`),
|
|
866
|
+
...optionalTextFields(identity, path, [
|
|
867
|
+
"displayName",
|
|
868
|
+
"installationId",
|
|
869
|
+
"agentInstanceId",
|
|
870
|
+
"browserSessionId",
|
|
871
|
+
"provider",
|
|
872
|
+
"model"
|
|
873
|
+
])
|
|
874
|
+
};
|
|
875
|
+
}
|
|
876
|
+
function parseDelegation(value) {
|
|
877
|
+
if (value === null) return null;
|
|
878
|
+
const delegation = record(value, "actorEnvelope.delegation");
|
|
879
|
+
exactKeys(delegation, ["taskId", "runId", "lineage"], "actorEnvelope.delegation");
|
|
880
|
+
if (!Array.isArray(delegation.lineage) || delegation.lineage.length === 0 || delegation.lineage.length > 16) {
|
|
881
|
+
fail("actorEnvelope.delegation.lineage", "must contain between 1 and 16 hops");
|
|
882
|
+
}
|
|
883
|
+
return {
|
|
884
|
+
taskId: text(delegation.taskId, "actorEnvelope.delegation.taskId"),
|
|
885
|
+
runId: text(delegation.runId, "actorEnvelope.delegation.runId"),
|
|
886
|
+
lineage: delegation.lineage.map((value2, index) => {
|
|
887
|
+
const hop = record(value2, `actorEnvelope.delegation.lineage[${index}]`);
|
|
888
|
+
exactKeys(hop, ["principalType", "principalId"], `actorEnvelope.delegation.lineage[${index}]`);
|
|
889
|
+
return {
|
|
890
|
+
principalType: member(hop.principalType, PRINCIPAL_TYPES, `actorEnvelope.delegation.lineage[${index}].principalType`),
|
|
891
|
+
principalId: text(hop.principalId, `actorEnvelope.delegation.lineage[${index}].principalId`)
|
|
892
|
+
};
|
|
893
|
+
})
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
function record(value, path) {
|
|
897
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) fail(path, "must be an object");
|
|
898
|
+
return value;
|
|
899
|
+
}
|
|
900
|
+
function exactKeys(value, allowed, path) {
|
|
901
|
+
const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
|
|
902
|
+
if (unknown.length) fail(path, `contains unknown field ${unknown[0]}`);
|
|
903
|
+
}
|
|
904
|
+
function text(value, path) {
|
|
905
|
+
if (typeof value !== "string" || value.trim() !== value || value.length === 0 || value.length > 256) {
|
|
906
|
+
fail(path, "must be a non-empty trimmed string of at most 256 characters");
|
|
907
|
+
}
|
|
908
|
+
return value;
|
|
909
|
+
}
|
|
910
|
+
function timestamp(value, path) {
|
|
911
|
+
const result = text(value, path);
|
|
912
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(result) || Number.isNaN(Date.parse(result))) {
|
|
913
|
+
fail(path, "must be an RFC 3339 UTC timestamp");
|
|
914
|
+
}
|
|
915
|
+
return result;
|
|
916
|
+
}
|
|
917
|
+
function member(value, values, path) {
|
|
918
|
+
if (typeof value !== "string" || !values.has(value)) fail(path, "contains an unsupported value");
|
|
919
|
+
return value;
|
|
920
|
+
}
|
|
921
|
+
function textArray(value, path) {
|
|
922
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > 16) fail(path, "must contain between 1 and 16 values");
|
|
923
|
+
return value.map((item, index) => text(item, `${path}[${index}]`));
|
|
924
|
+
}
|
|
925
|
+
function optionalTextFields(value, path, keys) {
|
|
926
|
+
return Object.fromEntries(keys.flatMap((key) => value[key] === void 0 ? [] : [[key, text(value[key], `${path}.${key}`)]]));
|
|
927
|
+
}
|
|
928
|
+
function fail(path, message) {
|
|
929
|
+
throw new ActorEnvelopeValidationError(path, message);
|
|
930
|
+
}
|
|
680
931
|
function parseTopoloActionUploadContract(value) {
|
|
681
932
|
if (!isRecord2(value) || value.profile !== "inline-base64" && value.profile !== "url-session") {
|
|
682
933
|
throw new TopoloSdkError("upload_contract_unavailable", "This action does not publish a supported upload contract.");
|
|
@@ -881,6 +1132,7 @@ var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
|
881
1132
|
var TopoloClient = class _TopoloClient {
|
|
882
1133
|
credential;
|
|
883
1134
|
agent;
|
|
1135
|
+
actorContext;
|
|
884
1136
|
serviceUrls;
|
|
885
1137
|
environment;
|
|
886
1138
|
appIds;
|
|
@@ -911,6 +1163,11 @@ var TopoloClient = class _TopoloClient {
|
|
|
911
1163
|
if (!options.agent?.clientName) throw new TopoloAuthError("agent.clientName is required");
|
|
912
1164
|
this.credential = options.credential;
|
|
913
1165
|
this.agent = options.agent;
|
|
1166
|
+
this.actorContext = options.actorContext ? {
|
|
1167
|
+
channel: options.actorContext.channel,
|
|
1168
|
+
taskId: options.actorContext.taskId ?? `task_${generateRequestId()}`,
|
|
1169
|
+
runId: options.actorContext.runId ?? `run_${generateRequestId()}`
|
|
1170
|
+
} : void 0;
|
|
914
1171
|
this.environment = options.environment;
|
|
915
1172
|
this.serviceUrls = options.environment ? topoloServiceOrigins(options.serviceUrls, options.environment) : options.serviceUrls;
|
|
916
1173
|
this.appIds = options.appIds;
|
|
@@ -964,11 +1221,15 @@ var TopoloClient = class _TopoloClient {
|
|
|
964
1221
|
const platformAppId = resolveConfiguredAppId(resolvedService.serviceKey, this.appIds);
|
|
965
1222
|
if (platformAppId) headers.set("X-App-ID", platformAppId);
|
|
966
1223
|
applyAuthHeaders(headers, this.credential);
|
|
967
|
-
const
|
|
1224
|
+
const actorEnvelope = opts.actorEnvelope === void 0 ? void 0 : parseActorEnvelope(opts.actorEnvelope);
|
|
1225
|
+
const requestId = actorEnvelope?.action.requestId ?? generateRequestId();
|
|
968
1226
|
applyAuditHeaders(headers, this.agent, requestId);
|
|
969
1227
|
if (opts.headers) {
|
|
970
1228
|
for (const [k, v] of Object.entries(opts.headers)) headers.set(k, v);
|
|
971
1229
|
}
|
|
1230
|
+
if (actorEnvelope) {
|
|
1231
|
+
headers.set(TOPOLO_ACTOR_ENVELOPE_HEADER, encodeActorEnvelopeHeader(actorEnvelope));
|
|
1232
|
+
}
|
|
972
1233
|
if (opts.resource) {
|
|
973
1234
|
const resourceType = opts.resource.resourceType.trim();
|
|
974
1235
|
const resourceId = opts.resource.resourceId.trim();
|
|
@@ -1011,16 +1272,29 @@ var TopoloClient = class _TopoloClient {
|
|
|
1011
1272
|
clearTimeout(timeoutId);
|
|
1012
1273
|
}
|
|
1013
1274
|
};
|
|
1275
|
+
const fetchWithReadRetry = async () => {
|
|
1276
|
+
const maxAttempts = method === "GET" ? 2 : 1;
|
|
1277
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
1278
|
+
try {
|
|
1279
|
+
return await fetchOnce();
|
|
1280
|
+
} catch (error) {
|
|
1281
|
+
const transportFailure = !(error instanceof TopoloSdkError) && !opts.signal?.aborted;
|
|
1282
|
+
if (!transportFailure || attempt === maxAttempts) throw error;
|
|
1283
|
+
await new Promise((resolve2) => setTimeout(resolve2, 250));
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
throw new TopoloSdkError("network_error", "Topolo read retry loop exhausted.");
|
|
1287
|
+
};
|
|
1014
1288
|
let res;
|
|
1015
1289
|
try {
|
|
1016
1290
|
const attemptedCredential = this.credential;
|
|
1017
|
-
res = await
|
|
1291
|
+
res = await fetchWithReadRetry();
|
|
1018
1292
|
if (res.status === 401 && attemptedCredential.kind === "access_token" && this.refreshCredential) {
|
|
1019
1293
|
await res.body?.cancel().catch(() => void 0);
|
|
1020
1294
|
const refreshed = await this.refreshRejectedAccessToken(attemptedCredential.accessToken);
|
|
1021
1295
|
if (refreshed) {
|
|
1022
1296
|
applyAuthHeaders(headers, refreshed);
|
|
1023
|
-
res = await
|
|
1297
|
+
res = await fetchWithReadRetry();
|
|
1024
1298
|
}
|
|
1025
1299
|
}
|
|
1026
1300
|
} catch (err) {
|
|
@@ -1402,14 +1676,14 @@ var TopoloClient = class _TopoloClient {
|
|
|
1402
1676
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
1403
1677
|
throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is unavailable.");
|
|
1404
1678
|
}
|
|
1405
|
-
const
|
|
1406
|
-
if (
|
|
1679
|
+
const record2 = raw;
|
|
1680
|
+
if (record2.algorithm !== "sha256-v1" || typeof record2.digest !== "string" || !/^[a-f0-9]{64}$/.test(record2.digest) || !Number.isSafeInteger(record2.actionCount) || Number(record2.actionCount) < 0) {
|
|
1407
1681
|
throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is invalid.");
|
|
1408
1682
|
}
|
|
1409
1683
|
return {
|
|
1410
1684
|
algorithm: "sha256-v1",
|
|
1411
|
-
digest:
|
|
1412
|
-
actionCount: Number(
|
|
1685
|
+
digest: record2.digest,
|
|
1686
|
+
actionCount: Number(record2.actionCount)
|
|
1413
1687
|
};
|
|
1414
1688
|
}
|
|
1415
1689
|
/** @deprecated Prefer searchActions() so callers retain the continuation cursor. */
|
|
@@ -1609,6 +1883,20 @@ var TopoloClient = class _TopoloClient {
|
|
|
1609
1883
|
);
|
|
1610
1884
|
}
|
|
1611
1885
|
const mapped = mapActionInput(entry, input);
|
|
1886
|
+
const resolvedActorEnvelope = options.actorEnvelope ?? await this.buildVerifiedAgentActorEnvelope(entry.actionId, input, options.resource);
|
|
1887
|
+
if (resolvedActorEnvelope) {
|
|
1888
|
+
const actorEnvelope = parseActorEnvelope(resolvedActorEnvelope);
|
|
1889
|
+
if (actorEnvelope.action.actionId !== entry.actionId) {
|
|
1890
|
+
throw new TopoloSdkError("actor_envelope_action_mismatch", "Actor envelope actionId does not match the executed action.");
|
|
1891
|
+
}
|
|
1892
|
+
if (actorEnvelope.action.inputHash !== await sha256CanonicalValue(input)) {
|
|
1893
|
+
throw new TopoloSdkError("actor_envelope_input_mismatch", "Actor envelope inputHash does not match the executed action input.");
|
|
1894
|
+
}
|
|
1895
|
+
const envelopeResource = actorEnvelope.action.resourceType && actorEnvelope.action.resourceId ? { resourceType: actorEnvelope.action.resourceType, resourceId: actorEnvelope.action.resourceId } : void 0;
|
|
1896
|
+
if (envelopeResource?.resourceType !== options.resource?.resourceType || envelopeResource?.resourceId !== options.resource?.resourceId) {
|
|
1897
|
+
throw new TopoloSdkError("actor_envelope_resource_mismatch", "Actor envelope resource does not match the executed action resource.");
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1612
1900
|
const service = entry.appSlug || entry.appId;
|
|
1613
1901
|
const result = await this.request({
|
|
1614
1902
|
service,
|
|
@@ -1618,6 +1906,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
1618
1906
|
...mapped.query ? { query: mapped.query } : {},
|
|
1619
1907
|
...mapped.body !== void 0 ? { body: mapped.body } : {},
|
|
1620
1908
|
...options.resource ? { resource: options.resource } : {},
|
|
1909
|
+
...resolvedActorEnvelope ? { actorEnvelope: resolvedActorEnvelope } : {},
|
|
1621
1910
|
headers: {
|
|
1622
1911
|
[TOPOLO_ACTION_ID_HEADER]: entry.actionId,
|
|
1623
1912
|
[TOPOLO_ACTION_NAME_HEADER]: entry.name
|
|
@@ -1626,6 +1915,56 @@ var TopoloClient = class _TopoloClient {
|
|
|
1626
1915
|
});
|
|
1627
1916
|
return redactActionResult(result);
|
|
1628
1917
|
}
|
|
1918
|
+
async buildVerifiedAgentActorEnvelope(actionId, input, resource) {
|
|
1919
|
+
if (!this.actorContext) return void 0;
|
|
1920
|
+
const identity = await this.introspect();
|
|
1921
|
+
const principalType = identity.user.principalType;
|
|
1922
|
+
if (principalType !== "agent_employee" && principalType !== "external_agent") return void 0;
|
|
1923
|
+
if (!identity.organization || !identity.user.accountableUserId || !identity.user.principalId) {
|
|
1924
|
+
throw new TopoloSdkError(
|
|
1925
|
+
"incomplete_agent_identity",
|
|
1926
|
+
"Verified agent credentials must resolve an organization, accountable user, and principal id."
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
const performer = principalType === "external_agent" ? {
|
|
1930
|
+
principalType: "external_agent",
|
|
1931
|
+
principalId: identity.user.principalId,
|
|
1932
|
+
installationId: identity.user.installationId ?? void 0,
|
|
1933
|
+
provider: identity.user.provider ?? void 0,
|
|
1934
|
+
model: identity.user.model ?? void 0
|
|
1935
|
+
} : {
|
|
1936
|
+
principalType: "managed_agent",
|
|
1937
|
+
principalId: identity.user.principalId,
|
|
1938
|
+
agentInstanceId: identity.user.agentInstanceId ?? void 0,
|
|
1939
|
+
model: identity.user.model ?? void 0
|
|
1940
|
+
};
|
|
1941
|
+
if (performer.principalType === "external_agent" && (!performer.installationId || !performer.provider) || performer.principalType === "managed_agent" && !performer.agentInstanceId) {
|
|
1942
|
+
throw new TopoloSdkError(
|
|
1943
|
+
"incomplete_agent_identity",
|
|
1944
|
+
"Verified agent credentials are missing the performer identity required for provenance."
|
|
1945
|
+
);
|
|
1946
|
+
}
|
|
1947
|
+
return parseActorEnvelope({
|
|
1948
|
+
schemaVersion: 1,
|
|
1949
|
+
organizationId: identity.organization.id,
|
|
1950
|
+
accountableSubject: { principalType: "human", principalId: identity.user.accountableUserId },
|
|
1951
|
+
performer,
|
|
1952
|
+
delegation: {
|
|
1953
|
+
taskId: this.actorContext.taskId,
|
|
1954
|
+
runId: this.actorContext.runId,
|
|
1955
|
+
lineage: [{ principalType: performer.principalType, principalId: performer.principalId }]
|
|
1956
|
+
},
|
|
1957
|
+
channel: this.actorContext.channel,
|
|
1958
|
+
assurance: { level: "workload_identity", methods: ["client_credentials"] },
|
|
1959
|
+
action: {
|
|
1960
|
+
requestId: generateRequestId(),
|
|
1961
|
+
actionId,
|
|
1962
|
+
...resource ? resource : {},
|
|
1963
|
+
inputHash: await sha256CanonicalValue(input)
|
|
1964
|
+
},
|
|
1965
|
+
issuedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1966
|
+
});
|
|
1967
|
+
}
|
|
1629
1968
|
/**
|
|
1630
1969
|
* Introspect the current credential. Returns the caller's resolved identity,
|
|
1631
1970
|
* organization, and permission set. Used by CLI `whoami` and by MCP to gate
|
|
@@ -1653,7 +1992,18 @@ var TopoloClient = class _TopoloClient {
|
|
|
1653
1992
|
email: user.email,
|
|
1654
1993
|
name: user.name ?? null,
|
|
1655
1994
|
role: user.role ?? (kind === "api_key" ? "service" : "member"),
|
|
1656
|
-
permissions: payload.permissions ?? user.permissions ?? []
|
|
1995
|
+
permissions: payload.permissions ?? user.permissions ?? [],
|
|
1996
|
+
...normalizeAgentPrincipalType(user.principalType) ? {
|
|
1997
|
+
principalId: readOptionalString(user.principalId),
|
|
1998
|
+
principalType: normalizeAgentPrincipalType(user.principalType),
|
|
1999
|
+
accountableUserId: readOptionalString(user.accountableUserId),
|
|
2000
|
+
agentInstanceId: readOptionalString(user.agentInstanceId),
|
|
2001
|
+
installationId: readOptionalString(user.installationId),
|
|
2002
|
+
provider: readOptionalString(user.provider),
|
|
2003
|
+
model: readOptionalString(user.model),
|
|
2004
|
+
serviceScopes: stringArray(user.serviceScopes),
|
|
2005
|
+
policyRef: readOptionalString(user.policyRef)
|
|
2006
|
+
} : {}
|
|
1657
2007
|
},
|
|
1658
2008
|
organization: organization ? {
|
|
1659
2009
|
id: organization.id,
|
|
@@ -1672,26 +2022,29 @@ var TopoloClient = class _TopoloClient {
|
|
|
1672
2022
|
};
|
|
1673
2023
|
function validateActionResource(entry, resource) {
|
|
1674
2024
|
const permissionName = entry.permissionName || entry.requiredPermission.split(".").at(-1) || "";
|
|
1675
|
-
|
|
2025
|
+
const declaredContext = entry.agentContract?.resourceContext;
|
|
2026
|
+
const declaredKind = typeof declaredContext?.kind === "string" ? declaredContext.kind.trim() : "";
|
|
2027
|
+
const expectedType = declaredKind || (permissionName.startsWith("workspace:") ? "workspace" : "");
|
|
2028
|
+
if (!expectedType || declaredContext?.required === false && !permissionName.startsWith("workspace:")) return null;
|
|
1676
2029
|
if (!resource) {
|
|
1677
2030
|
return {
|
|
1678
2031
|
path: "$.resource",
|
|
1679
2032
|
code: "required",
|
|
1680
|
-
message:
|
|
2033
|
+
message: `Select resourceType "${expectedType}" with the application resource catalog before planning or calling this action.`
|
|
1681
2034
|
};
|
|
1682
2035
|
}
|
|
1683
|
-
if (resource.resourceType !==
|
|
2036
|
+
if (resource.resourceType !== expectedType) {
|
|
1684
2037
|
return {
|
|
1685
2038
|
path: "$.resource.resourceType",
|
|
1686
2039
|
code: "const",
|
|
1687
|
-
message:
|
|
2040
|
+
message: `This action requires resourceType "${expectedType}".`
|
|
1688
2041
|
};
|
|
1689
2042
|
}
|
|
1690
2043
|
if (!resource.resourceId.trim()) {
|
|
1691
2044
|
return {
|
|
1692
2045
|
path: "$.resource.resourceId",
|
|
1693
2046
|
code: "required",
|
|
1694
|
-
message:
|
|
2047
|
+
message: `This action requires a ${expectedType} resourceId.`
|
|
1695
2048
|
};
|
|
1696
2049
|
}
|
|
1697
2050
|
return null;
|
|
@@ -1779,12 +2132,21 @@ function redactActionResult(value) {
|
|
|
1779
2132
|
if (!isRecord3(value)) return value;
|
|
1780
2133
|
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
1781
2134
|
key,
|
|
1782
|
-
isSensitiveActionResultKey(key) ? "[REDACTED]" : redactActionResult(item)
|
|
2135
|
+
isSensitiveActionResultKey(key, item) ? "[REDACTED]" : redactActionResult(item)
|
|
1783
2136
|
]));
|
|
1784
2137
|
}
|
|
1785
|
-
function isSensitiveActionResultKey(key) {
|
|
2138
|
+
function isSensitiveActionResultKey(key, value) {
|
|
1786
2139
|
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1787
|
-
|
|
2140
|
+
if (normalized === "capability") return isCredentialShaped(value);
|
|
2141
|
+
return ["authorization", "cookie", "setcookie", "proxyauthorization"].includes(normalized) || /(token|secret|password|privatekey|apikey)$/.test(normalized);
|
|
2142
|
+
}
|
|
2143
|
+
var PLAIN_ENUM_VALUE = /^[a-z][a-z0-9_-]{0,31}$/;
|
|
2144
|
+
function isCredentialShaped(value) {
|
|
2145
|
+
if (typeof value !== "string") return value !== null && value !== void 0 && typeof value !== "boolean" && typeof value !== "number";
|
|
2146
|
+
const trimmed = value.trim();
|
|
2147
|
+
if (!trimmed) return false;
|
|
2148
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)) return true;
|
|
2149
|
+
return !PLAIN_ENUM_VALUE.test(trimmed);
|
|
1788
2150
|
}
|
|
1789
2151
|
function resolveConfiguredServiceUrl(slug, serviceUrls) {
|
|
1790
2152
|
for (const serviceKey of serviceKeyCandidates2(slug)) {
|
|
@@ -2006,6 +2368,9 @@ function normalizeCredentialAuthorizationMode(value, kind) {
|
|
|
2006
2368
|
if (value === "context_rbac" || value === "oauth_scopes" || value === "session_rbac") return value;
|
|
2007
2369
|
return "unknown";
|
|
2008
2370
|
}
|
|
2371
|
+
function normalizeAgentPrincipalType(value) {
|
|
2372
|
+
return value === "agent_employee" || value === "external_agent" ? value : null;
|
|
2373
|
+
}
|
|
2009
2374
|
function describeError(body, fallback) {
|
|
2010
2375
|
if (body && typeof body === "object") {
|
|
2011
2376
|
const maybe = body;
|
|
@@ -2030,10 +2395,10 @@ function extractRequired(body) {
|
|
|
2030
2395
|
if (Array.isArray(maybe.required)) return canonicalTopoloRequired(maybe.required);
|
|
2031
2396
|
for (const nested of [maybe.details, maybe.error]) {
|
|
2032
2397
|
if (!nested || typeof nested !== "object" || Array.isArray(nested)) continue;
|
|
2033
|
-
const
|
|
2034
|
-
if (Array.isArray(
|
|
2035
|
-
if (
|
|
2036
|
-
const required =
|
|
2398
|
+
const record2 = nested;
|
|
2399
|
+
if (Array.isArray(record2.required)) return canonicalTopoloRequired(record2.required);
|
|
2400
|
+
if (record2.details && typeof record2.details === "object" && !Array.isArray(record2.details)) {
|
|
2401
|
+
const required = record2.details.required;
|
|
2037
2402
|
if (Array.isArray(required)) return canonicalTopoloRequired(required);
|
|
2038
2403
|
}
|
|
2039
2404
|
}
|
|
@@ -2063,7 +2428,8 @@ function compactActionCatalogEntry(action) {
|
|
|
2063
2428
|
agentAccess: action.agentAccess ?? (action.requiresConfirmation ? "confirm" : action.readOnly ? "auto" : "confirm"),
|
|
2064
2429
|
requiredPermission: action.requiredPermission,
|
|
2065
2430
|
requiredInput: required,
|
|
2066
|
-
resourceType: action.agentContract?.
|
|
2431
|
+
resourceType: action.agentContract?.resourceContext?.kind ?? (action.permissionName.startsWith("workspace:") ? "workspace" : null),
|
|
2432
|
+
resultResourceType: action.agentContract?.resource?.kind ?? null,
|
|
2067
2433
|
exampleInput: example.value,
|
|
2068
2434
|
exampleInputAvailable: example.available,
|
|
2069
2435
|
docsUrl: action.agentContract?.docsUrl ?? null
|
|
@@ -2107,8 +2473,8 @@ function compactResultValue(value, depth, budget) {
|
|
|
2107
2473
|
return value.length > ACTION_RESULT_MAX_ITEMS ? { count: value.length, items, omittedItems: value.length - ACTION_RESULT_MAX_ITEMS } : items;
|
|
2108
2474
|
}
|
|
2109
2475
|
if (typeof value === "object") {
|
|
2110
|
-
const
|
|
2111
|
-
const allKeys = Object.keys(
|
|
2476
|
+
const record2 = value;
|
|
2477
|
+
const allKeys = Object.keys(record2);
|
|
2112
2478
|
const ranked = allKeys.sort((left, right) => resultKeyPriority(left) - resultKeyPriority(right));
|
|
2113
2479
|
const prioritized = ranked.filter((key) => resultKeyPriority(key) < 2);
|
|
2114
2480
|
const ordinary = ranked.filter((key) => resultKeyPriority(key) === 2);
|
|
@@ -2117,7 +2483,7 @@ function compactResultValue(value, depth, budget) {
|
|
|
2117
2483
|
...prioritized,
|
|
2118
2484
|
...ordinary.slice(0, ordinaryLimit)
|
|
2119
2485
|
].slice(0, ACTION_RESULT_MAX_KEYS);
|
|
2120
|
-
const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(
|
|
2486
|
+
const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(record2[key], depth + 1, budget)]));
|
|
2121
2487
|
if (allKeys.length > keys.length) compact["_omittedKeys"] = allKeys.length - keys.length;
|
|
2122
2488
|
return compact;
|
|
2123
2489
|
}
|
|
@@ -2338,6 +2704,461 @@ var WorkspacesModule = class {
|
|
|
2338
2704
|
return { organizationId: identity.organization.id, appId: service.appId };
|
|
2339
2705
|
}
|
|
2340
2706
|
};
|
|
2707
|
+
var nonEmptyString2 = { type: "string", minLength: 1 };
|
|
2708
|
+
var stringArray3 = { type: "array", items: nonEmptyString2 };
|
|
2709
|
+
var actionBinding = {
|
|
2710
|
+
type: "object",
|
|
2711
|
+
properties: {
|
|
2712
|
+
id: nonEmptyString2,
|
|
2713
|
+
label: nonEmptyString2,
|
|
2714
|
+
actionId: nonEmptyString2,
|
|
2715
|
+
resourceType: nonEmptyString2,
|
|
2716
|
+
resourceId: nonEmptyString2,
|
|
2717
|
+
input: { type: "object" },
|
|
2718
|
+
requiresConfirmation: { type: "boolean" },
|
|
2719
|
+
destructive: { type: "boolean" },
|
|
2720
|
+
effects: stringArray3,
|
|
2721
|
+
verification: stringArray3,
|
|
2722
|
+
recovery: {
|
|
2723
|
+
type: "object",
|
|
2724
|
+
properties: {
|
|
2725
|
+
mode: { enum: ["not_applicable", "retry", "compensating_action"] },
|
|
2726
|
+
actionId: nonEmptyString2,
|
|
2727
|
+
instructions: nonEmptyString2
|
|
2728
|
+
},
|
|
2729
|
+
required: ["mode", "instructions"],
|
|
2730
|
+
additionalProperties: false
|
|
2731
|
+
}
|
|
2732
|
+
},
|
|
2733
|
+
required: [
|
|
2734
|
+
"id",
|
|
2735
|
+
"label",
|
|
2736
|
+
"actionId",
|
|
2737
|
+
"resourceType",
|
|
2738
|
+
"input",
|
|
2739
|
+
"requiresConfirmation",
|
|
2740
|
+
"destructive",
|
|
2741
|
+
"effects",
|
|
2742
|
+
"verification",
|
|
2743
|
+
"recovery"
|
|
2744
|
+
],
|
|
2745
|
+
additionalProperties: false
|
|
2746
|
+
};
|
|
2747
|
+
var dimension = {
|
|
2748
|
+
type: "object",
|
|
2749
|
+
properties: { key: nonEmptyString2, label: nonEmptyString2, value: nonEmptyString2 },
|
|
2750
|
+
required: ["key", "label", "value"],
|
|
2751
|
+
additionalProperties: false
|
|
2752
|
+
};
|
|
2753
|
+
var period = {
|
|
2754
|
+
type: "object",
|
|
2755
|
+
properties: {
|
|
2756
|
+
start: nonEmptyString2,
|
|
2757
|
+
end: nonEmptyString2,
|
|
2758
|
+
timezone: nonEmptyString2
|
|
2759
|
+
},
|
|
2760
|
+
required: ["start", "end", "timezone"],
|
|
2761
|
+
additionalProperties: false
|
|
2762
|
+
};
|
|
2763
|
+
var series = {
|
|
2764
|
+
type: "object",
|
|
2765
|
+
properties: {
|
|
2766
|
+
id: nonEmptyString2,
|
|
2767
|
+
label: nonEmptyString2,
|
|
2768
|
+
unit: nonEmptyString2,
|
|
2769
|
+
points: {
|
|
2770
|
+
type: "array",
|
|
2771
|
+
items: {
|
|
2772
|
+
type: "object",
|
|
2773
|
+
properties: {
|
|
2774
|
+
timestamp: nonEmptyString2,
|
|
2775
|
+
value: { type: "number" },
|
|
2776
|
+
dimensions: { type: "array", items: dimension }
|
|
2777
|
+
},
|
|
2778
|
+
required: ["timestamp", "value", "dimensions"],
|
|
2779
|
+
additionalProperties: false
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
},
|
|
2783
|
+
required: ["id", "label", "unit", "points"],
|
|
2784
|
+
additionalProperties: false
|
|
2785
|
+
};
|
|
2786
|
+
var contribution = {
|
|
2787
|
+
type: "object",
|
|
2788
|
+
properties: {
|
|
2789
|
+
summary: nonEmptyString2,
|
|
2790
|
+
identity: {
|
|
2791
|
+
type: "object",
|
|
2792
|
+
properties: { iconSource: { const: "catalog" } },
|
|
2793
|
+
required: ["iconSource"],
|
|
2794
|
+
additionalProperties: false
|
|
2795
|
+
},
|
|
2796
|
+
workspaceSelector: {
|
|
2797
|
+
type: "object",
|
|
2798
|
+
properties: {
|
|
2799
|
+
mode: { enum: ["none", "optional", "required"] },
|
|
2800
|
+
resourceType: nonEmptyString2,
|
|
2801
|
+
label: nonEmptyString2,
|
|
2802
|
+
supportsMultiple: { type: "boolean" }
|
|
2803
|
+
},
|
|
2804
|
+
required: ["mode", "resourceType", "label", "supportsMultiple"],
|
|
2805
|
+
additionalProperties: false
|
|
2806
|
+
},
|
|
2807
|
+
metricDefinitions: {
|
|
2808
|
+
type: "array",
|
|
2809
|
+
items: {
|
|
2810
|
+
type: "object",
|
|
2811
|
+
properties: {
|
|
2812
|
+
key: nonEmptyString2,
|
|
2813
|
+
label: nonEmptyString2,
|
|
2814
|
+
description: nonEmptyString2,
|
|
2815
|
+
unit: nonEmptyString2,
|
|
2816
|
+
semantic: {
|
|
2817
|
+
enum: ["gauge", "counter", "rate", "duration", "currency", "percentage"]
|
|
2818
|
+
},
|
|
2819
|
+
aggregation: {
|
|
2820
|
+
enum: ["last", "sum", "average", "minimum", "maximum", "count", "distinct_count"]
|
|
2821
|
+
}
|
|
2822
|
+
},
|
|
2823
|
+
required: ["key", "label", "description", "unit", "semantic", "aggregation"],
|
|
2824
|
+
additionalProperties: false
|
|
2825
|
+
}
|
|
2826
|
+
},
|
|
2827
|
+
seriesDefinitions: {
|
|
2828
|
+
type: "array",
|
|
2829
|
+
items: {
|
|
2830
|
+
type: "object",
|
|
2831
|
+
properties: {
|
|
2832
|
+
key: nonEmptyString2,
|
|
2833
|
+
label: nonEmptyString2,
|
|
2834
|
+
metricKey: nonEmptyString2,
|
|
2835
|
+
unit: nonEmptyString2
|
|
2836
|
+
},
|
|
2837
|
+
required: ["key", "label", "metricKey", "unit"],
|
|
2838
|
+
additionalProperties: false
|
|
2839
|
+
}
|
|
2840
|
+
},
|
|
2841
|
+
dimensions: {
|
|
2842
|
+
type: "array",
|
|
2843
|
+
items: {
|
|
2844
|
+
type: "object",
|
|
2845
|
+
properties: {
|
|
2846
|
+
key: nonEmptyString2,
|
|
2847
|
+
label: nonEmptyString2,
|
|
2848
|
+
description: nonEmptyString2,
|
|
2849
|
+
valueType: { enum: ["string", "number", "boolean", "date", "datetime"] }
|
|
2850
|
+
},
|
|
2851
|
+
required: ["key", "label", "description", "valueType"],
|
|
2852
|
+
additionalProperties: false
|
|
2853
|
+
}
|
|
2854
|
+
},
|
|
2855
|
+
lifecycleStages: {
|
|
2856
|
+
type: "array",
|
|
2857
|
+
items: {
|
|
2858
|
+
type: "object",
|
|
2859
|
+
properties: {
|
|
2860
|
+
key: nonEmptyString2,
|
|
2861
|
+
label: nonEmptyString2,
|
|
2862
|
+
order: { type: "number" },
|
|
2863
|
+
terminal: { type: "boolean" }
|
|
2864
|
+
},
|
|
2865
|
+
required: ["key", "label", "order", "terminal"],
|
|
2866
|
+
additionalProperties: false
|
|
2867
|
+
}
|
|
2868
|
+
},
|
|
2869
|
+
events: {
|
|
2870
|
+
type: "array",
|
|
2871
|
+
items: {
|
|
2872
|
+
type: "object",
|
|
2873
|
+
properties: {
|
|
2874
|
+
key: nonEmptyString2,
|
|
2875
|
+
label: nonEmptyString2,
|
|
2876
|
+
description: nonEmptyString2
|
|
2877
|
+
},
|
|
2878
|
+
required: ["key", "label", "description"],
|
|
2879
|
+
additionalProperties: false
|
|
2880
|
+
}
|
|
2881
|
+
},
|
|
2882
|
+
datasets: {
|
|
2883
|
+
type: "array",
|
|
2884
|
+
minItems: 1,
|
|
2885
|
+
items: {
|
|
2886
|
+
type: "object",
|
|
2887
|
+
properties: {
|
|
2888
|
+
id: nonEmptyString2,
|
|
2889
|
+
label: nonEmptyString2,
|
|
2890
|
+
description: nonEmptyString2,
|
|
2891
|
+
grain: nonEmptyString2,
|
|
2892
|
+
metricKeys: stringArray3,
|
|
2893
|
+
seriesKeys: stringArray3,
|
|
2894
|
+
dimensionKeys: stringArray3,
|
|
2895
|
+
eventKeys: stringArray3,
|
|
2896
|
+
actionIds: stringArray3
|
|
2897
|
+
},
|
|
2898
|
+
required: [
|
|
2899
|
+
"id",
|
|
2900
|
+
"label",
|
|
2901
|
+
"description",
|
|
2902
|
+
"grain",
|
|
2903
|
+
"metricKeys",
|
|
2904
|
+
"seriesKeys",
|
|
2905
|
+
"dimensionKeys",
|
|
2906
|
+
"eventKeys",
|
|
2907
|
+
"actionIds"
|
|
2908
|
+
],
|
|
2909
|
+
additionalProperties: false
|
|
2910
|
+
}
|
|
2911
|
+
},
|
|
2912
|
+
compatibleVisualizations: {
|
|
2913
|
+
type: "array",
|
|
2914
|
+
minItems: 1,
|
|
2915
|
+
items: {
|
|
2916
|
+
enum: ["number", "line", "area", "bar", "donut", "table", "funnel", "timeline", "actions"]
|
|
2917
|
+
}
|
|
2918
|
+
},
|
|
2919
|
+
defaultVisualization: {
|
|
2920
|
+
enum: ["number", "line", "area", "bar", "donut", "table", "funnel", "timeline", "actions"]
|
|
2921
|
+
}
|
|
2922
|
+
},
|
|
2923
|
+
required: [
|
|
2924
|
+
"summary",
|
|
2925
|
+
"identity",
|
|
2926
|
+
"workspaceSelector",
|
|
2927
|
+
"metricDefinitions",
|
|
2928
|
+
"seriesDefinitions",
|
|
2929
|
+
"dimensions",
|
|
2930
|
+
"lifecycleStages",
|
|
2931
|
+
"events",
|
|
2932
|
+
"datasets",
|
|
2933
|
+
"compatibleVisualizations",
|
|
2934
|
+
"defaultVisualization"
|
|
2935
|
+
],
|
|
2936
|
+
additionalProperties: false
|
|
2937
|
+
};
|
|
2938
|
+
var widgetItem = {
|
|
2939
|
+
type: "object",
|
|
2940
|
+
properties: {
|
|
2941
|
+
id: nonEmptyString2,
|
|
2942
|
+
version: nonEmptyString2,
|
|
2943
|
+
appId: nonEmptyString2,
|
|
2944
|
+
serviceName: nonEmptyString2,
|
|
2945
|
+
lastUpdated: nonEmptyString2,
|
|
2946
|
+
type: { enum: ["stats", "chart", "activity", "notifications", "actions"] },
|
|
2947
|
+
presentation: {
|
|
2948
|
+
type: "object",
|
|
2949
|
+
properties: {
|
|
2950
|
+
title: nonEmptyString2,
|
|
2951
|
+
description: nonEmptyString2,
|
|
2952
|
+
contexts: {
|
|
2953
|
+
type: "array",
|
|
2954
|
+
minItems: 1,
|
|
2955
|
+
items: { enum: ["personal", "organization", "workspace", "resource"] }
|
|
2956
|
+
},
|
|
2957
|
+
supportedSizes: {
|
|
2958
|
+
type: "array",
|
|
2959
|
+
minItems: 1,
|
|
2960
|
+
items: { enum: ["compact", "medium", "wide", "full"] }
|
|
2961
|
+
},
|
|
2962
|
+
defaultSize: { enum: ["compact", "medium", "wide", "full"] }
|
|
2963
|
+
},
|
|
2964
|
+
required: ["title", "contexts", "supportedSizes", "defaultSize"],
|
|
2965
|
+
additionalProperties: false
|
|
2966
|
+
},
|
|
2967
|
+
resource: {
|
|
2968
|
+
type: "object",
|
|
2969
|
+
properties: {
|
|
2970
|
+
resourceType: nonEmptyString2,
|
|
2971
|
+
resourceId: nonEmptyString2,
|
|
2972
|
+
requiredPermissions: stringArray3
|
|
2973
|
+
},
|
|
2974
|
+
required: ["resourceType", "requiredPermissions"],
|
|
2975
|
+
additionalProperties: false
|
|
2976
|
+
},
|
|
2977
|
+
state: {
|
|
2978
|
+
type: "object",
|
|
2979
|
+
properties: {
|
|
2980
|
+
status: { enum: ["ready", "empty", "unavailable", "stale", "error"] },
|
|
2981
|
+
observedAt: nonEmptyString2,
|
|
2982
|
+
lastSuccessfulAt: nonEmptyString2,
|
|
2983
|
+
code: nonEmptyString2,
|
|
2984
|
+
message: nonEmptyString2
|
|
2985
|
+
},
|
|
2986
|
+
required: ["status", "observedAt"],
|
|
2987
|
+
additionalProperties: false
|
|
2988
|
+
},
|
|
2989
|
+
refresh: {
|
|
2990
|
+
type: "object",
|
|
2991
|
+
properties: {
|
|
2992
|
+
intervalSeconds: { type: "number" },
|
|
2993
|
+
timeoutSeconds: { type: "number" },
|
|
2994
|
+
maxAgeSeconds: { type: "number" },
|
|
2995
|
+
staleWhileRevalidateSeconds: { type: "number" }
|
|
2996
|
+
},
|
|
2997
|
+
required: ["intervalSeconds", "timeoutSeconds", "maxAgeSeconds", "staleWhileRevalidateSeconds"],
|
|
2998
|
+
additionalProperties: false
|
|
2999
|
+
},
|
|
3000
|
+
configuration: {
|
|
3001
|
+
type: "object",
|
|
3002
|
+
properties: {
|
|
3003
|
+
allowMultipleInstances: { type: "boolean" },
|
|
3004
|
+
fields: {
|
|
3005
|
+
type: "array",
|
|
3006
|
+
items: {
|
|
3007
|
+
type: "object",
|
|
3008
|
+
properties: {
|
|
3009
|
+
key: nonEmptyString2,
|
|
3010
|
+
label: nonEmptyString2,
|
|
3011
|
+
type: { enum: ["string", "number", "boolean", "select", "multi-select", "date-range"] },
|
|
3012
|
+
required: { type: "boolean" },
|
|
3013
|
+
options: {
|
|
3014
|
+
type: "array",
|
|
3015
|
+
items: {
|
|
3016
|
+
type: "object",
|
|
3017
|
+
properties: { value: nonEmptyString2, label: nonEmptyString2 },
|
|
3018
|
+
required: ["value", "label"],
|
|
3019
|
+
additionalProperties: false
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
},
|
|
3023
|
+
required: ["key", "label", "type", "required"],
|
|
3024
|
+
additionalProperties: false
|
|
3025
|
+
}
|
|
3026
|
+
},
|
|
3027
|
+
defaults: { type: "object" }
|
|
3028
|
+
},
|
|
3029
|
+
required: ["allowMultipleInstances", "fields", "defaults"],
|
|
3030
|
+
additionalProperties: false
|
|
3031
|
+
},
|
|
3032
|
+
drilldowns: {
|
|
3033
|
+
type: "array",
|
|
3034
|
+
items: {
|
|
3035
|
+
type: "object",
|
|
3036
|
+
properties: { id: nonEmptyString2, label: nonEmptyString2, href: nonEmptyString2 },
|
|
3037
|
+
required: ["id", "label", "href"],
|
|
3038
|
+
additionalProperties: false
|
|
3039
|
+
}
|
|
3040
|
+
},
|
|
3041
|
+
controls: { type: "array", items: actionBinding },
|
|
3042
|
+
localization: {
|
|
3043
|
+
type: "object",
|
|
3044
|
+
properties: {
|
|
3045
|
+
locale: nonEmptyString2,
|
|
3046
|
+
titleKey: nonEmptyString2,
|
|
3047
|
+
descriptionKey: nonEmptyString2,
|
|
3048
|
+
title: nonEmptyString2,
|
|
3049
|
+
description: nonEmptyString2
|
|
3050
|
+
},
|
|
3051
|
+
required: ["locale", "titleKey"],
|
|
3052
|
+
additionalProperties: false
|
|
3053
|
+
},
|
|
3054
|
+
accessibility: {
|
|
3055
|
+
type: "object",
|
|
3056
|
+
properties: { label: nonEmptyString2, description: nonEmptyString2 },
|
|
3057
|
+
required: ["label"],
|
|
3058
|
+
additionalProperties: false
|
|
3059
|
+
},
|
|
3060
|
+
contribution,
|
|
3061
|
+
metrics: {
|
|
3062
|
+
type: "array",
|
|
3063
|
+
items: {
|
|
3064
|
+
type: "object",
|
|
3065
|
+
properties: {
|
|
3066
|
+
key: nonEmptyString2,
|
|
3067
|
+
label: nonEmptyString2,
|
|
3068
|
+
value: { type: "number" },
|
|
3069
|
+
unit: nonEmptyString2,
|
|
3070
|
+
semantic: {
|
|
3071
|
+
enum: ["gauge", "counter", "rate", "duration", "currency", "percentage"]
|
|
3072
|
+
},
|
|
3073
|
+
aggregation: {
|
|
3074
|
+
enum: ["last", "sum", "average", "minimum", "maximum", "count", "distinct_count"]
|
|
3075
|
+
},
|
|
3076
|
+
period,
|
|
3077
|
+
dimensions: { type: "array", items: dimension },
|
|
3078
|
+
series
|
|
3079
|
+
},
|
|
3080
|
+
required: ["key", "label", "value", "unit", "semantic", "aggregation", "period", "dimensions"],
|
|
3081
|
+
additionalProperties: false
|
|
3082
|
+
}
|
|
3083
|
+
},
|
|
3084
|
+
chartType: { enum: ["line", "bar", "area", "pie", "donut"] },
|
|
3085
|
+
series: { type: "array", items: series },
|
|
3086
|
+
activities: { type: "array", items: { type: "object" } },
|
|
3087
|
+
notifications: { type: "array", items: { type: "object" } },
|
|
3088
|
+
unreadCount: { type: "number" },
|
|
3089
|
+
actions: { type: "array", items: actionBinding }
|
|
3090
|
+
},
|
|
3091
|
+
required: [
|
|
3092
|
+
"id",
|
|
3093
|
+
"version",
|
|
3094
|
+
"appId",
|
|
3095
|
+
"serviceName",
|
|
3096
|
+
"lastUpdated",
|
|
3097
|
+
"type",
|
|
3098
|
+
"presentation",
|
|
3099
|
+
"resource",
|
|
3100
|
+
"state",
|
|
3101
|
+
"refresh",
|
|
3102
|
+
"configuration",
|
|
3103
|
+
"drilldowns",
|
|
3104
|
+
"controls",
|
|
3105
|
+
"localization",
|
|
3106
|
+
"accessibility",
|
|
3107
|
+
"contribution"
|
|
3108
|
+
],
|
|
3109
|
+
allOf: [
|
|
3110
|
+
{ if: { properties: { type: { const: "stats" } } }, then: { required: ["metrics"] } },
|
|
3111
|
+
{ if: { properties: { type: { const: "chart" } } }, then: { required: ["chartType", "series"] } },
|
|
3112
|
+
{ if: { properties: { type: { const: "activity" } } }, then: { required: ["activities"] } },
|
|
3113
|
+
{
|
|
3114
|
+
if: { properties: { type: { const: "notifications" } } },
|
|
3115
|
+
then: { required: ["notifications", "unreadCount"] }
|
|
3116
|
+
},
|
|
3117
|
+
{ if: { properties: { type: { const: "actions" } } }, then: { required: ["actions"] } }
|
|
3118
|
+
],
|
|
3119
|
+
additionalProperties: false
|
|
3120
|
+
};
|
|
3121
|
+
var TOPOLO_WIDGET_OUTPUT_SCHEMA = Object.freeze({
|
|
3122
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
3123
|
+
type: "object",
|
|
3124
|
+
properties: {
|
|
3125
|
+
success: { type: "boolean", const: true },
|
|
3126
|
+
contractVersion: { type: "string", const: "3.0.0" },
|
|
3127
|
+
appId: nonEmptyString2,
|
|
3128
|
+
serviceName: nonEmptyString2,
|
|
3129
|
+
generatedAt: nonEmptyString2,
|
|
3130
|
+
widgets: { type: "array", minItems: 1, items: widgetItem },
|
|
3131
|
+
workspace: {
|
|
3132
|
+
anyOf: [
|
|
3133
|
+
{
|
|
3134
|
+
type: "object",
|
|
3135
|
+
properties: {
|
|
3136
|
+
id: { anyOf: [{ type: "string" }, { type: "number" }] },
|
|
3137
|
+
name: nonEmptyString2
|
|
3138
|
+
},
|
|
3139
|
+
required: ["id", "name"],
|
|
3140
|
+
additionalProperties: true
|
|
3141
|
+
},
|
|
3142
|
+
{ type: "null" }
|
|
3143
|
+
]
|
|
3144
|
+
},
|
|
3145
|
+
workspaces: {
|
|
3146
|
+
type: "array",
|
|
3147
|
+
items: {
|
|
3148
|
+
type: "object",
|
|
3149
|
+
properties: {
|
|
3150
|
+
id: { anyOf: [{ type: "string" }, { type: "number" }] },
|
|
3151
|
+
name: nonEmptyString2,
|
|
3152
|
+
isDefault: { type: "boolean" }
|
|
3153
|
+
},
|
|
3154
|
+
required: ["id", "name"],
|
|
3155
|
+
additionalProperties: false
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
},
|
|
3159
|
+
required: ["success", "contractVersion", "appId", "serviceName", "generatedAt", "widgets"],
|
|
3160
|
+
additionalProperties: false
|
|
3161
|
+
});
|
|
2341
3162
|
function createTopolo(options) {
|
|
2342
3163
|
const client = new TopoloClient(options);
|
|
2343
3164
|
return {
|
|
@@ -2348,7 +3169,7 @@ function createTopolo(options) {
|
|
|
2348
3169
|
};
|
|
2349
3170
|
}
|
|
2350
3171
|
|
|
2351
|
-
// node_modules/@topolo/sdk/dist/node/credential-store.js
|
|
3172
|
+
// node_modules/.pnpm/@topolo+sdk@0.17.1/node_modules/@topolo/sdk/dist/node/credential-store.js
|
|
2352
3173
|
import { mkdir, readFile, writeFile, chmod, rm, stat } from "fs/promises";
|
|
2353
3174
|
import { existsSync } from "fs";
|
|
2354
3175
|
import { homedir, platform } from "os";
|
|
@@ -2411,6 +3232,7 @@ var ERROR_CODE_PATTERN2 = /^[a-z][a-z0-9_]{0,63}$/;
|
|
|
2411
3232
|
var TOPOLO_REQUEST_ID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
2412
3233
|
var CLOUDFLARE_RAY_ID_PATTERN2 = /^[0-9a-f]{16}-[A-Z]{3}$/;
|
|
2413
3234
|
var PERMISSION_PATTERN2 = /^[a-z][a-z0-9_-]{0,63}(?:\.[a-z][a-z0-9_-]{0,63})*:(?:[a-z][a-z0-9_-]{0,63}|\*)$/;
|
|
3235
|
+
var PUBLIC_FIELD_PATH_PATTERN2 = /^[$.a-z0-9_[\]-]{1,160}$/i;
|
|
2414
3236
|
var RETRY_AFTER_DATE_PATTERN2 = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/;
|
|
2415
3237
|
var PUBLIC_DETAIL_SOURCES2 = /* @__PURE__ */ new Set([
|
|
2416
3238
|
"api_key_introspection",
|
|
@@ -2470,10 +3292,10 @@ var TopoloAuthError2 = class extends TopoloSdkError2 {
|
|
|
2470
3292
|
};
|
|
2471
3293
|
function extractTopoloServiceErrorCode2(body) {
|
|
2472
3294
|
if (!body || typeof body !== "object" || Array.isArray(body)) return null;
|
|
2473
|
-
const
|
|
2474
|
-
const topLevel = canonicalTopoloErrorCode2(
|
|
3295
|
+
const record2 = body;
|
|
3296
|
+
const topLevel = canonicalTopoloErrorCode2(record2.code);
|
|
2475
3297
|
if (topLevel) return topLevel;
|
|
2476
|
-
const nested =
|
|
3298
|
+
const nested = record2.error;
|
|
2477
3299
|
const nestedString = canonicalTopoloErrorCode2(nested);
|
|
2478
3300
|
if (nestedString) return nestedString;
|
|
2479
3301
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
@@ -2488,15 +3310,19 @@ function serviceErrorCode2(body, fallback) {
|
|
|
2488
3310
|
}
|
|
2489
3311
|
function extractTopoloServiceErrorDetails2(body) {
|
|
2490
3312
|
if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
|
|
2491
|
-
const
|
|
2492
|
-
let candidate =
|
|
2493
|
-
const nested =
|
|
3313
|
+
const record2 = body;
|
|
3314
|
+
let candidate = record2.details;
|
|
3315
|
+
const nested = record2.error;
|
|
2494
3316
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
2495
3317
|
const nestedRecord = nested;
|
|
2496
3318
|
if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
|
|
2497
3319
|
}
|
|
2498
|
-
if (candidate === void 0) candidate =
|
|
2499
|
-
if (
|
|
3320
|
+
if (candidate === void 0) candidate = record2;
|
|
3321
|
+
if (Array.isArray(candidate)) {
|
|
3322
|
+
const paths = canonicalTopoloValidationPaths2(candidate);
|
|
3323
|
+
return paths.length ? { paths } : void 0;
|
|
3324
|
+
}
|
|
3325
|
+
if (!candidate || typeof candidate !== "object") return void 0;
|
|
2500
3326
|
const source = candidate;
|
|
2501
3327
|
const safe = {};
|
|
2502
3328
|
for (const [key, value] of Object.entries(source)) {
|
|
@@ -2533,12 +3359,42 @@ function extractTopoloServiceErrorDetails2(body) {
|
|
|
2533
3359
|
continue;
|
|
2534
3360
|
}
|
|
2535
3361
|
if (["missingFields", "fields", "paths"].includes(key) && Array.isArray(value)) {
|
|
2536
|
-
const paths = value.filter((item) => typeof item === "string" &&
|
|
3362
|
+
const paths = value.filter((item) => typeof item === "string" && PUBLIC_FIELD_PATH_PATTERN2.test(item));
|
|
2537
3363
|
if (paths.length) safe[key] = paths;
|
|
2538
3364
|
}
|
|
2539
3365
|
}
|
|
2540
3366
|
return Object.keys(safe).length ? safe : void 0;
|
|
2541
3367
|
}
|
|
3368
|
+
function canonicalTopoloValidationPaths2(issues) {
|
|
3369
|
+
const paths = [];
|
|
3370
|
+
for (const issue of issues) {
|
|
3371
|
+
if (!issue || typeof issue !== "object" || Array.isArray(issue)) continue;
|
|
3372
|
+
const record2 = issue;
|
|
3373
|
+
const path = canonicalTopoloValidationPath2(record2.field) ?? canonicalTopoloValidationPath2(record2.path);
|
|
3374
|
+
if (path && !paths.includes(path)) paths.push(path);
|
|
3375
|
+
if (paths.length === 32) break;
|
|
3376
|
+
}
|
|
3377
|
+
return paths;
|
|
3378
|
+
}
|
|
3379
|
+
function canonicalTopoloValidationPath2(value) {
|
|
3380
|
+
if (typeof value === "string") {
|
|
3381
|
+
const path2 = value.trim();
|
|
3382
|
+
return PUBLIC_FIELD_PATH_PATTERN2.test(path2) ? path2 : void 0;
|
|
3383
|
+
}
|
|
3384
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > 32) return void 0;
|
|
3385
|
+
const segments = value.map((segment) => {
|
|
3386
|
+
if (typeof segment === "number" && Number.isSafeInteger(segment) && segment >= 0) {
|
|
3387
|
+
return String(segment);
|
|
3388
|
+
}
|
|
3389
|
+
if (typeof segment === "string" && /^[a-z0-9_$-]{1,80}$/i.test(segment)) {
|
|
3390
|
+
return segment;
|
|
3391
|
+
}
|
|
3392
|
+
return null;
|
|
3393
|
+
});
|
|
3394
|
+
if (segments.includes(null)) return void 0;
|
|
3395
|
+
const path = segments.join(".");
|
|
3396
|
+
return PUBLIC_FIELD_PATH_PATTERN2.test(path) ? path : void 0;
|
|
3397
|
+
}
|
|
2542
3398
|
var TopoloHttpError2 = class extends TopoloSdkError2 {
|
|
2543
3399
|
status;
|
|
2544
3400
|
body;
|
|
@@ -3047,7 +3903,7 @@ function summarizeActionCapabilities(service, actions) {
|
|
|
3047
3903
|
mutating: actions.filter((action) => !action.readOnly).length,
|
|
3048
3904
|
destructive: actions.filter((action) => action.destructive).length,
|
|
3049
3905
|
confirmationRequired: actions.filter((action) => action.requiresConfirmation).length,
|
|
3050
|
-
resourceTypes: [...new Set(actions.map((action) => action.agentContract?.
|
|
3906
|
+
resourceTypes: [...new Set(actions.map((action) => action.agentContract?.resourceContext?.kind ?? (action.permissionName.startsWith("workspace:") ? "workspace" : null)).filter(Boolean))].sort()
|
|
3051
3907
|
};
|
|
3052
3908
|
}
|
|
3053
3909
|
function coerceObjectParam(value, name) {
|
|
@@ -3953,6 +4809,7 @@ async function runStdioMcp(dependencies = DEFAULT_DEPENDENCIES2) {
|
|
|
3953
4809
|
const topolo = dependencies.createTopolo({
|
|
3954
4810
|
credential,
|
|
3955
4811
|
environment,
|
|
4812
|
+
actorContext: { channel: "mcp" },
|
|
3956
4813
|
agent: {
|
|
3957
4814
|
clientName: "topolo-mcp",
|
|
3958
4815
|
clientVersion: MCP_VERSION,
|