@suveren/gateway 0.2.7 → 0.2.8
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/mcp-server/http.mjs +53 -2
- package/package.json +1 -1
package/dist/mcp-server/http.mjs
CHANGED
|
@@ -904,6 +904,54 @@ function buildMandateBrief(opts) {
|
|
|
904
904
|
// src/tools/authorizations.ts
|
|
905
905
|
import { getProfile as getProfile2 } from "@hap/core";
|
|
906
906
|
|
|
907
|
+
// src/lib/receipt-footer.ts
|
|
908
|
+
var AS_BASE = (process.env.SUVEREN_AS_URL ?? "https://www.suveren.ai").replace(/\/$/, "");
|
|
909
|
+
var FOOTER_PROFILES = /* @__PURE__ */ new Set(["email", "calendar", "publish"]);
|
|
910
|
+
var CONTENT_FIELD_CANDIDATES = ["body", "text", "description"];
|
|
911
|
+
var FOOTER_MARKER = "\u2014 Sent by an AI agent via Suveren";
|
|
912
|
+
function shouldAttachFooter() {
|
|
913
|
+
return true;
|
|
914
|
+
}
|
|
915
|
+
function verifyUrl(receiptId) {
|
|
916
|
+
return `${AS_BASE}/r/${receiptId}`;
|
|
917
|
+
}
|
|
918
|
+
function footerText(receiptId) {
|
|
919
|
+
return `
|
|
920
|
+
|
|
921
|
+
${FOOTER_MARKER}. Verify: ${verifyUrl(receiptId)}`;
|
|
922
|
+
}
|
|
923
|
+
function isStringType(t) {
|
|
924
|
+
return t === "string" || Array.isArray(t) && t.includes("string");
|
|
925
|
+
}
|
|
926
|
+
function detectContentField(tool) {
|
|
927
|
+
const schema = tool.inputSchema;
|
|
928
|
+
const props = schema?.properties ?? {};
|
|
929
|
+
for (const candidate of CONTENT_FIELD_CANDIDATES) {
|
|
930
|
+
const prop = props[candidate];
|
|
931
|
+
if (prop && isStringType(prop.type)) return candidate;
|
|
932
|
+
}
|
|
933
|
+
return null;
|
|
934
|
+
}
|
|
935
|
+
function stripFooter(value) {
|
|
936
|
+
const i = value.indexOf(FOOTER_MARKER);
|
|
937
|
+
if (i === -1) return value;
|
|
938
|
+
return value.slice(0, i).replace(/\n+$/, "");
|
|
939
|
+
}
|
|
940
|
+
function appendVerificationFooter(tool, args, receiptId) {
|
|
941
|
+
const profile = tool.gating?.profile;
|
|
942
|
+
if (!profile || !FOOTER_PROFILES.has(profile)) return args;
|
|
943
|
+
if (typeof args.raw === "string" && args.raw.trim().length > 0) {
|
|
944
|
+
console.error(
|
|
945
|
+
`[Suveren MCP] ${tool.namespacedName}: 'raw' message present \u2014 skipping verification footer.`
|
|
946
|
+
);
|
|
947
|
+
return args;
|
|
948
|
+
}
|
|
949
|
+
const field = detectContentField(tool);
|
|
950
|
+
if (!field) return args;
|
|
951
|
+
const current = typeof args[field] === "string" ? args[field] : "";
|
|
952
|
+
return { ...args, [field]: stripFooter(current) + footerText(receiptId) };
|
|
953
|
+
}
|
|
954
|
+
|
|
907
955
|
// src/lib/tool-proxy.ts
|
|
908
956
|
import { readFile } from "fs/promises";
|
|
909
957
|
import { extname } from "path";
|
|
@@ -1064,6 +1112,7 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
|
|
|
1064
1112
|
};
|
|
1065
1113
|
}
|
|
1066
1114
|
}
|
|
1115
|
+
let receiptId;
|
|
1067
1116
|
try {
|
|
1068
1117
|
const actionType = typeof execution.action_type === "string" ? execution.action_type : void 0;
|
|
1069
1118
|
if (!actionType) {
|
|
@@ -1071,7 +1120,7 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
|
|
|
1071
1120
|
`[Suveren MCP] Warning: tool ${tool.namespacedName} has no action_type in staticExecution. Bounds check may be skipped. Fix the integration manifest.`
|
|
1072
1121
|
);
|
|
1073
1122
|
}
|
|
1074
|
-
await state2.spClient.postReceipt({
|
|
1123
|
+
const { receipt } = await state2.spClient.postReceipt({
|
|
1075
1124
|
// v0.5: send the bare content address; the AS reconstructs the
|
|
1076
1125
|
// per-user storage key. Fall back to frameHash only for legacy
|
|
1077
1126
|
// (pre-v0.4) records that predate bounds_hash.
|
|
@@ -1083,6 +1132,7 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
|
|
|
1083
1132
|
amount: typeof execution.amount === "number" ? execution.amount : void 0,
|
|
1084
1133
|
idempotencyKey: randomUUID()
|
|
1085
1134
|
});
|
|
1135
|
+
receiptId = typeof receipt?.id === "string" ? receipt.id : void 0;
|
|
1086
1136
|
} catch (err) {
|
|
1087
1137
|
if (err instanceof SPReceiptError && err.statusCode === 409) {
|
|
1088
1138
|
const spBody = err.body;
|
|
@@ -1160,7 +1210,8 @@ Proposal ID: ${proposal.id}. Use check-pending-commitments to track status.`
|
|
|
1160
1210
|
execution: { ...execution },
|
|
1161
1211
|
timestamp: Math.floor(Date.now() / 1e3)
|
|
1162
1212
|
});
|
|
1163
|
-
|
|
1213
|
+
const outgoingArgs = shouldAttachFooter() && receiptId ? appendVerificationFooter(tool, args, receiptId) : args;
|
|
1214
|
+
return integrationManager2.callTool(tool.integrationId, tool.originalName, outgoingArgs);
|
|
1164
1215
|
}
|
|
1165
1216
|
const reasons = result.errors.map((e) => {
|
|
1166
1217
|
if (e.code === "BOUND_EXCEEDED") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suveren/gateway",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Suveren gateway — local agent gateway built in compliance with the Human Agency Protocol (HAP). Runs the UI, control plane, and MCP server in one Node process.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "server.js",
|