@topolo/mcp 0.11.12 → 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/http.js +893 -695
- package/dist/index.js +806 -36
- 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);
|
|
@@ -167,10 +167,10 @@ var TopoloPermissionError = class extends TopoloSdkError {
|
|
|
167
167
|
};
|
|
168
168
|
function extractTopoloServiceErrorCode(body) {
|
|
169
169
|
if (!body || typeof body !== "object" || Array.isArray(body)) return null;
|
|
170
|
-
const
|
|
171
|
-
const topLevel = canonicalTopoloErrorCode(
|
|
170
|
+
const record2 = body;
|
|
171
|
+
const topLevel = canonicalTopoloErrorCode(record2.code);
|
|
172
172
|
if (topLevel) return topLevel;
|
|
173
|
-
const nested =
|
|
173
|
+
const nested = record2.error;
|
|
174
174
|
const nestedString = canonicalTopoloErrorCode(nested);
|
|
175
175
|
if (nestedString) return nestedString;
|
|
176
176
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
@@ -185,14 +185,14 @@ function serviceErrorCode(body, fallback) {
|
|
|
185
185
|
}
|
|
186
186
|
function extractTopoloServiceErrorDetails(body) {
|
|
187
187
|
if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
|
|
188
|
-
const
|
|
189
|
-
let candidate =
|
|
190
|
-
const nested =
|
|
188
|
+
const record2 = body;
|
|
189
|
+
let candidate = record2.details;
|
|
190
|
+
const nested = record2.error;
|
|
191
191
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
192
192
|
const nestedRecord = nested;
|
|
193
193
|
if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
|
|
194
194
|
}
|
|
195
|
-
if (candidate === void 0) candidate =
|
|
195
|
+
if (candidate === void 0) candidate = record2;
|
|
196
196
|
if (Array.isArray(candidate)) {
|
|
197
197
|
const paths = canonicalTopoloValidationPaths(candidate);
|
|
198
198
|
return paths.length ? { paths } : void 0;
|
|
@@ -244,8 +244,8 @@ function canonicalTopoloValidationPaths(issues) {
|
|
|
244
244
|
const paths = [];
|
|
245
245
|
for (const issue of issues) {
|
|
246
246
|
if (!issue || typeof issue !== "object" || Array.isArray(issue)) continue;
|
|
247
|
-
const
|
|
248
|
-
const path = canonicalTopoloValidationPath(
|
|
247
|
+
const record2 = issue;
|
|
248
|
+
const path = canonicalTopoloValidationPath(record2.field) ?? canonicalTopoloValidationPath(record2.path);
|
|
249
249
|
if (path && !paths.includes(path)) paths.push(path);
|
|
250
250
|
if (paths.length === 32) break;
|
|
251
251
|
}
|
|
@@ -712,6 +712,222 @@ function isMultipleOf(value, divisor) {
|
|
|
712
712
|
const quotient = value / divisor;
|
|
713
713
|
return Math.abs(quotient - Math.round(quotient)) < Number.EPSILON * Math.max(1, Math.abs(quotient)) * 4;
|
|
714
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
|
+
}
|
|
715
931
|
function parseTopoloActionUploadContract(value) {
|
|
716
932
|
if (!isRecord2(value) || value.profile !== "inline-base64" && value.profile !== "url-session") {
|
|
717
933
|
throw new TopoloSdkError("upload_contract_unavailable", "This action does not publish a supported upload contract.");
|
|
@@ -916,6 +1132,7 @@ var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
|
916
1132
|
var TopoloClient = class _TopoloClient {
|
|
917
1133
|
credential;
|
|
918
1134
|
agent;
|
|
1135
|
+
actorContext;
|
|
919
1136
|
serviceUrls;
|
|
920
1137
|
environment;
|
|
921
1138
|
appIds;
|
|
@@ -946,6 +1163,11 @@ var TopoloClient = class _TopoloClient {
|
|
|
946
1163
|
if (!options.agent?.clientName) throw new TopoloAuthError("agent.clientName is required");
|
|
947
1164
|
this.credential = options.credential;
|
|
948
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;
|
|
949
1171
|
this.environment = options.environment;
|
|
950
1172
|
this.serviceUrls = options.environment ? topoloServiceOrigins(options.serviceUrls, options.environment) : options.serviceUrls;
|
|
951
1173
|
this.appIds = options.appIds;
|
|
@@ -999,11 +1221,15 @@ var TopoloClient = class _TopoloClient {
|
|
|
999
1221
|
const platformAppId = resolveConfiguredAppId(resolvedService.serviceKey, this.appIds);
|
|
1000
1222
|
if (platformAppId) headers.set("X-App-ID", platformAppId);
|
|
1001
1223
|
applyAuthHeaders(headers, this.credential);
|
|
1002
|
-
const
|
|
1224
|
+
const actorEnvelope = opts.actorEnvelope === void 0 ? void 0 : parseActorEnvelope(opts.actorEnvelope);
|
|
1225
|
+
const requestId = actorEnvelope?.action.requestId ?? generateRequestId();
|
|
1003
1226
|
applyAuditHeaders(headers, this.agent, requestId);
|
|
1004
1227
|
if (opts.headers) {
|
|
1005
1228
|
for (const [k, v] of Object.entries(opts.headers)) headers.set(k, v);
|
|
1006
1229
|
}
|
|
1230
|
+
if (actorEnvelope) {
|
|
1231
|
+
headers.set(TOPOLO_ACTOR_ENVELOPE_HEADER, encodeActorEnvelopeHeader(actorEnvelope));
|
|
1232
|
+
}
|
|
1007
1233
|
if (opts.resource) {
|
|
1008
1234
|
const resourceType = opts.resource.resourceType.trim();
|
|
1009
1235
|
const resourceId = opts.resource.resourceId.trim();
|
|
@@ -1450,14 +1676,14 @@ var TopoloClient = class _TopoloClient {
|
|
|
1450
1676
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
1451
1677
|
throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is unavailable.");
|
|
1452
1678
|
}
|
|
1453
|
-
const
|
|
1454
|
-
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) {
|
|
1455
1681
|
throw new TopoloSdkError("action_catalog_summary_unavailable", "Action catalog summary is invalid.");
|
|
1456
1682
|
}
|
|
1457
1683
|
return {
|
|
1458
1684
|
algorithm: "sha256-v1",
|
|
1459
|
-
digest:
|
|
1460
|
-
actionCount: Number(
|
|
1685
|
+
digest: record2.digest,
|
|
1686
|
+
actionCount: Number(record2.actionCount)
|
|
1461
1687
|
};
|
|
1462
1688
|
}
|
|
1463
1689
|
/** @deprecated Prefer searchActions() so callers retain the continuation cursor. */
|
|
@@ -1657,6 +1883,20 @@ var TopoloClient = class _TopoloClient {
|
|
|
1657
1883
|
);
|
|
1658
1884
|
}
|
|
1659
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
|
+
}
|
|
1660
1900
|
const service = entry.appSlug || entry.appId;
|
|
1661
1901
|
const result = await this.request({
|
|
1662
1902
|
service,
|
|
@@ -1666,6 +1906,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
1666
1906
|
...mapped.query ? { query: mapped.query } : {},
|
|
1667
1907
|
...mapped.body !== void 0 ? { body: mapped.body } : {},
|
|
1668
1908
|
...options.resource ? { resource: options.resource } : {},
|
|
1909
|
+
...resolvedActorEnvelope ? { actorEnvelope: resolvedActorEnvelope } : {},
|
|
1669
1910
|
headers: {
|
|
1670
1911
|
[TOPOLO_ACTION_ID_HEADER]: entry.actionId,
|
|
1671
1912
|
[TOPOLO_ACTION_NAME_HEADER]: entry.name
|
|
@@ -1674,6 +1915,56 @@ var TopoloClient = class _TopoloClient {
|
|
|
1674
1915
|
});
|
|
1675
1916
|
return redactActionResult(result);
|
|
1676
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
|
+
}
|
|
1677
1968
|
/**
|
|
1678
1969
|
* Introspect the current credential. Returns the caller's resolved identity,
|
|
1679
1970
|
* organization, and permission set. Used by CLI `whoami` and by MCP to gate
|
|
@@ -1701,7 +1992,18 @@ var TopoloClient = class _TopoloClient {
|
|
|
1701
1992
|
email: user.email,
|
|
1702
1993
|
name: user.name ?? null,
|
|
1703
1994
|
role: user.role ?? (kind === "api_key" ? "service" : "member"),
|
|
1704
|
-
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
|
+
} : {}
|
|
1705
2007
|
},
|
|
1706
2008
|
organization: organization ? {
|
|
1707
2009
|
id: organization.id,
|
|
@@ -1830,12 +2132,21 @@ function redactActionResult(value) {
|
|
|
1830
2132
|
if (!isRecord3(value)) return value;
|
|
1831
2133
|
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
1832
2134
|
key,
|
|
1833
|
-
isSensitiveActionResultKey(key) ? "[REDACTED]" : redactActionResult(item)
|
|
2135
|
+
isSensitiveActionResultKey(key, item) ? "[REDACTED]" : redactActionResult(item)
|
|
1834
2136
|
]));
|
|
1835
2137
|
}
|
|
1836
|
-
function isSensitiveActionResultKey(key) {
|
|
2138
|
+
function isSensitiveActionResultKey(key, value) {
|
|
1837
2139
|
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1838
|
-
|
|
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);
|
|
1839
2150
|
}
|
|
1840
2151
|
function resolveConfiguredServiceUrl(slug, serviceUrls) {
|
|
1841
2152
|
for (const serviceKey of serviceKeyCandidates2(slug)) {
|
|
@@ -2057,6 +2368,9 @@ function normalizeCredentialAuthorizationMode(value, kind) {
|
|
|
2057
2368
|
if (value === "context_rbac" || value === "oauth_scopes" || value === "session_rbac") return value;
|
|
2058
2369
|
return "unknown";
|
|
2059
2370
|
}
|
|
2371
|
+
function normalizeAgentPrincipalType(value) {
|
|
2372
|
+
return value === "agent_employee" || value === "external_agent" ? value : null;
|
|
2373
|
+
}
|
|
2060
2374
|
function describeError(body, fallback) {
|
|
2061
2375
|
if (body && typeof body === "object") {
|
|
2062
2376
|
const maybe = body;
|
|
@@ -2081,10 +2395,10 @@ function extractRequired(body) {
|
|
|
2081
2395
|
if (Array.isArray(maybe.required)) return canonicalTopoloRequired(maybe.required);
|
|
2082
2396
|
for (const nested of [maybe.details, maybe.error]) {
|
|
2083
2397
|
if (!nested || typeof nested !== "object" || Array.isArray(nested)) continue;
|
|
2084
|
-
const
|
|
2085
|
-
if (Array.isArray(
|
|
2086
|
-
if (
|
|
2087
|
-
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;
|
|
2088
2402
|
if (Array.isArray(required)) return canonicalTopoloRequired(required);
|
|
2089
2403
|
}
|
|
2090
2404
|
}
|
|
@@ -2159,8 +2473,8 @@ function compactResultValue(value, depth, budget) {
|
|
|
2159
2473
|
return value.length > ACTION_RESULT_MAX_ITEMS ? { count: value.length, items, omittedItems: value.length - ACTION_RESULT_MAX_ITEMS } : items;
|
|
2160
2474
|
}
|
|
2161
2475
|
if (typeof value === "object") {
|
|
2162
|
-
const
|
|
2163
|
-
const allKeys = Object.keys(
|
|
2476
|
+
const record2 = value;
|
|
2477
|
+
const allKeys = Object.keys(record2);
|
|
2164
2478
|
const ranked = allKeys.sort((left, right) => resultKeyPriority(left) - resultKeyPriority(right));
|
|
2165
2479
|
const prioritized = ranked.filter((key) => resultKeyPriority(key) < 2);
|
|
2166
2480
|
const ordinary = ranked.filter((key) => resultKeyPriority(key) === 2);
|
|
@@ -2169,7 +2483,7 @@ function compactResultValue(value, depth, budget) {
|
|
|
2169
2483
|
...prioritized,
|
|
2170
2484
|
...ordinary.slice(0, ordinaryLimit)
|
|
2171
2485
|
].slice(0, ACTION_RESULT_MAX_KEYS);
|
|
2172
|
-
const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(
|
|
2486
|
+
const compact = Object.fromEntries(keys.map((key) => [key, compactResultValue(record2[key], depth + 1, budget)]));
|
|
2173
2487
|
if (allKeys.length > keys.length) compact["_omittedKeys"] = allKeys.length - keys.length;
|
|
2174
2488
|
return compact;
|
|
2175
2489
|
}
|
|
@@ -2390,6 +2704,461 @@ var WorkspacesModule = class {
|
|
|
2390
2704
|
return { organizationId: identity.organization.id, appId: service.appId };
|
|
2391
2705
|
}
|
|
2392
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
|
+
});
|
|
2393
3162
|
function createTopolo(options) {
|
|
2394
3163
|
const client = new TopoloClient(options);
|
|
2395
3164
|
return {
|
|
@@ -2400,7 +3169,7 @@ function createTopolo(options) {
|
|
|
2400
3169
|
};
|
|
2401
3170
|
}
|
|
2402
3171
|
|
|
2403
|
-
// 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
|
|
2404
3173
|
import { mkdir, readFile, writeFile, chmod, rm, stat } from "fs/promises";
|
|
2405
3174
|
import { existsSync } from "fs";
|
|
2406
3175
|
import { homedir, platform } from "os";
|
|
@@ -2523,10 +3292,10 @@ var TopoloAuthError2 = class extends TopoloSdkError2 {
|
|
|
2523
3292
|
};
|
|
2524
3293
|
function extractTopoloServiceErrorCode2(body) {
|
|
2525
3294
|
if (!body || typeof body !== "object" || Array.isArray(body)) return null;
|
|
2526
|
-
const
|
|
2527
|
-
const topLevel = canonicalTopoloErrorCode2(
|
|
3295
|
+
const record2 = body;
|
|
3296
|
+
const topLevel = canonicalTopoloErrorCode2(record2.code);
|
|
2528
3297
|
if (topLevel) return topLevel;
|
|
2529
|
-
const nested =
|
|
3298
|
+
const nested = record2.error;
|
|
2530
3299
|
const nestedString = canonicalTopoloErrorCode2(nested);
|
|
2531
3300
|
if (nestedString) return nestedString;
|
|
2532
3301
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
@@ -2541,14 +3310,14 @@ function serviceErrorCode2(body, fallback) {
|
|
|
2541
3310
|
}
|
|
2542
3311
|
function extractTopoloServiceErrorDetails2(body) {
|
|
2543
3312
|
if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
|
|
2544
|
-
const
|
|
2545
|
-
let candidate =
|
|
2546
|
-
const nested =
|
|
3313
|
+
const record2 = body;
|
|
3314
|
+
let candidate = record2.details;
|
|
3315
|
+
const nested = record2.error;
|
|
2547
3316
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
2548
3317
|
const nestedRecord = nested;
|
|
2549
3318
|
if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
|
|
2550
3319
|
}
|
|
2551
|
-
if (candidate === void 0) candidate =
|
|
3320
|
+
if (candidate === void 0) candidate = record2;
|
|
2552
3321
|
if (Array.isArray(candidate)) {
|
|
2553
3322
|
const paths = canonicalTopoloValidationPaths2(candidate);
|
|
2554
3323
|
return paths.length ? { paths } : void 0;
|
|
@@ -2600,8 +3369,8 @@ function canonicalTopoloValidationPaths2(issues) {
|
|
|
2600
3369
|
const paths = [];
|
|
2601
3370
|
for (const issue of issues) {
|
|
2602
3371
|
if (!issue || typeof issue !== "object" || Array.isArray(issue)) continue;
|
|
2603
|
-
const
|
|
2604
|
-
const path = canonicalTopoloValidationPath2(
|
|
3372
|
+
const record2 = issue;
|
|
3373
|
+
const path = canonicalTopoloValidationPath2(record2.field) ?? canonicalTopoloValidationPath2(record2.path);
|
|
2605
3374
|
if (path && !paths.includes(path)) paths.push(path);
|
|
2606
3375
|
if (paths.length === 32) break;
|
|
2607
3376
|
}
|
|
@@ -4040,6 +4809,7 @@ async function runStdioMcp(dependencies = DEFAULT_DEPENDENCIES2) {
|
|
|
4040
4809
|
const topolo = dependencies.createTopolo({
|
|
4041
4810
|
credential,
|
|
4042
4811
|
environment,
|
|
4812
|
+
actorContext: { channel: "mcp" },
|
|
4043
4813
|
agent: {
|
|
4044
4814
|
clientName: "topolo-mcp",
|
|
4045
4815
|
clientVersion: MCP_VERSION,
|