@kya-os/mcp-i-cloudflare 1.8.2 → 1.8.3

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.
@@ -0,0 +1,37 @@
1
+ /**
2
+ * E2E Test Configuration
3
+ *
4
+ * This file contains configuration for end-to-end tests that use real AgentShield API.
5
+ * Set these environment variables before running E2E tests:
6
+ *
7
+ * ```bash
8
+ * export E2E_AGENTSHIELD_API_KEY="sk_test_..."
9
+ * export E2E_AGENTSHIELD_PROJECT_ID="test-project-id"
10
+ * export E2E_AGENTSHIELD_API_URL="https://kya.vouched.id" # Optional, defaults to production
11
+ * ```
12
+ *
13
+ * Or create a `.env.e2e` file in the package root:
14
+ * ```
15
+ * E2E_AGENTSHIELD_API_KEY=sk_test_...
16
+ * E2E_AGENTSHIELD_PROJECT_ID=test-project-id
17
+ * ```
18
+ */
19
+ export interface E2ETestConfig {
20
+ apiKey: string;
21
+ projectId: string;
22
+ apiUrl: string;
23
+ enabled: boolean;
24
+ }
25
+ /**
26
+ * Load E2E test configuration from environment variables
27
+ */
28
+ export declare function loadE2EConfig(): E2ETestConfig | null;
29
+ /**
30
+ * Check if E2E tests should run
31
+ */
32
+ export declare function shouldRunE2ETests(): boolean;
33
+ /**
34
+ * Get E2E test configuration or throw if not configured
35
+ */
36
+ export declare function getE2EConfig(): E2ETestConfig;
37
+ //# sourceMappingURL=test-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-config.d.ts","sourceRoot":"","sources":["../../../src/__tests__/e2e/test-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAWH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,aAAa,GAAG,IAAI,CAyBpD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,aAAa,CAU5C"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * E2E Test Configuration
3
+ *
4
+ * This file contains configuration for end-to-end tests that use real AgentShield API.
5
+ * Set these environment variables before running E2E tests:
6
+ *
7
+ * ```bash
8
+ * export E2E_AGENTSHIELD_API_KEY="sk_test_..."
9
+ * export E2E_AGENTSHIELD_PROJECT_ID="test-project-id"
10
+ * export E2E_AGENTSHIELD_API_URL="https://kya.vouched.id" # Optional, defaults to production
11
+ * ```
12
+ *
13
+ * Or create a `.env.e2e` file in the package root:
14
+ * ```
15
+ * E2E_AGENTSHIELD_API_KEY=sk_test_...
16
+ * E2E_AGENTSHIELD_PROJECT_ID=test-project-id
17
+ * ```
18
+ */
19
+ /**
20
+ * Load E2E test configuration from environment variables
21
+ */
22
+ export function loadE2EConfig() {
23
+ // Access environment variables - works in Node.js (vitest) environment
24
+ const apiKey = typeof process !== "undefined" && process.env
25
+ ? process.env.E2E_AGENTSHIELD_API_KEY
26
+ : undefined;
27
+ const projectId = typeof process !== "undefined" && process.env
28
+ ? process.env.E2E_AGENTSHIELD_PROJECT_ID
29
+ : undefined;
30
+ const apiUrl = typeof process !== "undefined" && process.env
31
+ ? process.env.E2E_AGENTSHIELD_API_URL || "https://kya.vouched.id"
32
+ : "https://kya.vouched.id";
33
+ if (!apiKey || !projectId) {
34
+ return null;
35
+ }
36
+ return {
37
+ apiKey,
38
+ projectId,
39
+ apiUrl,
40
+ enabled: true,
41
+ };
42
+ }
43
+ /**
44
+ * Check if E2E tests should run
45
+ */
46
+ export function shouldRunE2ETests() {
47
+ const config = loadE2EConfig();
48
+ return config !== null && config.enabled;
49
+ }
50
+ /**
51
+ * Get E2E test configuration or throw if not configured
52
+ */
53
+ export function getE2EConfig() {
54
+ const config = loadE2EConfig();
55
+ if (!config) {
56
+ throw new Error("E2E tests require E2E_AGENTSHIELD_API_KEY and E2E_AGENTSHIELD_PROJECT_ID environment variables.\n" +
57
+ "Set them in your environment or create a .env.e2e file.\n" +
58
+ "See packages/mcp-i-cloudflare/src/__tests__/e2e/test-config.ts for details.");
59
+ }
60
+ return config;
61
+ }
62
+ //# sourceMappingURL=test-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-config.js","sourceRoot":"","sources":["../../../src/__tests__/e2e/test-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAkBH;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,uEAAuE;IACvE,MAAM,MAAM,GACV,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG;QAC3C,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB;QACrC,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,SAAS,GACb,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG;QAC3C,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B;QACxC,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,MAAM,GACV,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG;QAC3C,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,wBAAwB;QACjE,CAAC,CAAC,wBAAwB,CAAC;IAE/B,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,MAAM;QACN,SAAS;QACT,MAAM;QACN,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,mGAAmG;YACjG,2DAA2D;YAC3D,6EAA6E,CAChF,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Minimal inline consent UI fallback.
3
+ *
4
+ * Used when @kya-os/consent is not available (optional peer dependency).
5
+ * This is the vanilla HTML/JS/CSS consent form with inline MCP Apps
6
+ * handshake that proves the data pipeline works end-to-end.
7
+ *
8
+ * The full Lit-based UI in @kya-os/consent/mcp-app is preferred when available.
9
+ */
10
+ export declare const CONSENT_FALLBACK_HTML = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <meta name=\"color-scheme\" content=\"light dark\">\n <title>MCPI Consent</title>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: system-ui, -apple-system, sans-serif; padding: 16px; background: transparent; }\n .card { border-radius: 12px; padding: 20px; border: 1px solid rgba(128,128,128,0.2); }\n h2 { font-size: 16px; font-weight: 600; margin-bottom: 8px; }\n p { font-size: 13px; opacity: 0.7; line-height: 1.5; margin-bottom: 6px; }\n .scopes { margin: 10px 0; }\n .scope { display: inline-block; padding: 3px 10px; border-radius: 10px; font-size: 12px; font-weight: 500; margin: 2px 4px 2px 0; background: rgba(46,125,50,0.1); color: #2e7d32; }\n .btn { display: inline-block; padding: 8px 20px; border-radius: 8px; border: none; font-size: 14px; font-weight: 500; cursor: pointer; margin-right: 8px; margin-top: 10px; }\n .btn-approve { background: #2563eb; color: #fff; }\n .btn-approve:disabled { opacity: 0.5; cursor: not-allowed; }\n .btn-deny { background: transparent; border: 1px solid rgba(128,128,128,0.3); }\n .info { font-size: 11px; opacity: 0.5; margin-top: 12px; }\n .fallback { font-size: 12px; margin-top: 8px; }\n .fallback a { color: #2563eb; }\n #loading { font-size: 13px; opacity: 0.6; }\n #consent { display: none; }\n #approved { display: none; font-size: 14px; color: #16a34a; font-weight: 500; }\n .cred-fields { display: none; margin: 12px 0; }\n .cred-fields label { display: block; font-size: 12px; font-weight: 500; margin-bottom: 4px; opacity: 0.8; }\n .cred-fields input[type=\"text\"],\n .cred-fields input[type=\"password\"] { width: 100%; padding: 8px 10px; border-radius: 6px; border: 1px solid rgba(128,128,128,0.3); font-size: 14px; margin-bottom: 10px; background: transparent; color: inherit; }\n .cred-fields input:focus { outline: none; border-color: #2563eb; }\n .pw-wrap { position: relative; }\n .pw-toggle { position: absolute; right: 8px; top: 8px; background: none; border: none; cursor: pointer; font-size: 13px; opacity: 0.5; color: inherit; }\n .terms-row { display: flex; align-items: flex-start; gap: 8px; margin: 10px 0 4px; }\n .terms-row input[type=\"checkbox\"] { margin-top: 2px; }\n .terms-row label { font-size: 12px; opacity: 0.7; cursor: pointer; }\n .auth-error { display: none; font-size: 13px; color: #dc2626; margin: 8px 0; padding: 8px 10px; border-radius: 6px; background: rgba(220,38,38,0.08); }\n </style>\n</head>\n<body>\n <div id=\"loading\">Waiting for consent data&hellip;</div>\n <div id=\"consent\" class=\"card\">\n <h2>Authorization Required</h2>\n <p id=\"tool-desc\"></p>\n <div id=\"scopes-container\" class=\"scopes\"></div>\n <div id=\"cred-fields\" class=\"cred-fields\">\n <label for=\"cred-username\">Username / Email</label>\n <input type=\"text\" id=\"cred-username\" autocomplete=\"username\" placeholder=\"Enter your username or email\">\n <label for=\"cred-password\">Password</label>\n <div class=\"pw-wrap\">\n <input type=\"password\" id=\"cred-password\" autocomplete=\"current-password\" placeholder=\"Enter your password\">\n <button type=\"button\" class=\"pw-toggle\" id=\"pw-toggle\" aria-label=\"Toggle password visibility\">Show</button>\n </div>\n </div>\n <div id=\"auth-error\" class=\"auth-error\"></div>\n <div id=\"terms-row\" class=\"terms-row\" style=\"display:none;\">\n <input type=\"checkbox\" id=\"terms-check\">\n <label for=\"terms-check\">I agree to authorize this tool and accept the terms of service</label>\n </div>\n <p id=\"agent-info\" class=\"info\"></p>\n <div>\n <button class=\"btn btn-approve\" id=\"approve-btn\">Approve</button>\n <button class=\"btn btn-deny\" id=\"deny-btn\">Deny</button>\n </div>\n <div class=\"fallback\" id=\"fallback\"></div>\n </div>\n <div id=\"approved\"></div>\n <script>\n (function() {\n var send = function(msg) { window.parent.postMessage(msg, \"*\"); };\n var consentData = null;\n var authMode = \"consent-only\";\n\n function resizeNotify() {\n send({ jsonrpc: \"2.0\", method: \"ui/notifications/size-changed\", params: {\n width: document.documentElement.scrollWidth,\n height: document.documentElement.scrollHeight\n }});\n }\n\n function showConsent(data) {\n consentData = data;\n authMode = data.authMode || \"consent-only\";\n document.getElementById(\"loading\").style.display = \"none\";\n document.getElementById(\"consent\").style.display = \"block\";\n\n if (authMode === \"credentials\") {\n document.getElementById(\"tool-desc\").textContent =\n \"Tool \\u201c\" + (data.tool || \"unknown\") + \"\\u201d requires authentication.\";\n document.getElementById(\"cred-fields\").style.display = \"block\";\n document.getElementById(\"terms-row\").style.display = \"flex\";\n document.getElementById(\"approve-btn\").textContent = \"Sign In & Authorize\";\n document.getElementById(\"approve-btn\").disabled = true;\n document.getElementById(\"terms-check\").addEventListener(\"change\", function() {\n document.getElementById(\"approve-btn\").disabled = !this.checked;\n });\n } else {\n document.getElementById(\"tool-desc\").textContent =\n \"Tool \\u201c\" + (data.tool || \"unknown\") + \"\\u201d requires your approval.\";\n }\n\n var scopesEl = document.getElementById(\"scopes-container\");\n var scopes = data.scopes || [];\n scopesEl.textContent = \"\";\n scopes.forEach(function(s) {\n var span = document.createElement(\"span\");\n span.className = \"scope\";\n span.textContent = s;\n scopesEl.appendChild(span);\n });\n document.getElementById(\"agent-info\").textContent =\n \"Agent: \" + (data.agentName || data.agentDid || \"unknown\");\n if (data.consentUrl) {\n var fallbackEl = document.getElementById(\"fallback\");\n fallbackEl.textContent = \"\";\n var a = document.createElement(\"a\");\n a.href = data.consentUrl;\n a.target = \"_blank\";\n a.rel = \"noopener\";\n a.textContent = \"Open in browser\";\n fallbackEl.appendChild(a);\n }\n resizeNotify();\n }\n\n document.getElementById(\"pw-toggle\").addEventListener(\"click\", function() {\n var pwInput = document.getElementById(\"cred-password\");\n if (pwInput.type === \"password\") {\n pwInput.type = \"text\";\n this.textContent = \"Hide\";\n } else {\n pwInput.type = \"password\";\n this.textContent = \"Show\";\n }\n });\n\n var pendingRequests = {};\n var nextId = 100;\n\n function handleApprovalResponse(result, error) {\n var statusEl = document.getElementById(\"approved\");\n if (error) {\n if (authMode === \"credentials\") {\n var errEl = document.getElementById(\"auth-error\");\n errEl.textContent = error.message || JSON.stringify(error);\n errEl.style.display = \"block\";\n document.getElementById(\"consent\").style.display = \"block\";\n statusEl.style.display = \"none\";\n document.getElementById(\"approve-btn\").disabled = !document.getElementById(\"terms-check\").checked;\n resizeNotify();\n return;\n }\n statusEl.textContent = \"Approval error: \" + (error.message || JSON.stringify(error));\n statusEl.style.color = \"#dc2626\";\n } else {\n try {\n var text = result && result.content && result.content[0] && result.content[0].text;\n var respData = text ? JSON.parse(text) : {};\n if (respData.success) {\n statusEl.textContent = \"Authorization granted. You can now retry the tool.\";\n statusEl.style.color = \"#22c55e\";\n } else {\n if (authMode === \"credentials\" && (respData.error_code === \"auth_failed\" || respData.error_code === \"validation_error\")) {\n var errEl = document.getElementById(\"auth-error\");\n errEl.textContent = respData.error || \"Authentication failed. Please check your credentials.\";\n errEl.style.display = \"block\";\n document.getElementById(\"consent\").style.display = \"block\";\n statusEl.style.display = \"none\";\n document.getElementById(\"approve-btn\").disabled = !document.getElementById(\"terms-check\").checked;\n resizeNotify();\n return;\n }\n statusEl.textContent = \"Approval error: \" + (respData.error || respData.error_code || \"Unknown\");\n statusEl.style.color = \"#f59e0b\";\n }\n } catch(e) {\n statusEl.textContent = \"Unexpected response\";\n statusEl.style.color = \"#f59e0b\";\n }\n }\n resizeNotify();\n }\n\n document.getElementById(\"approve-btn\").addEventListener(\"click\", function() {\n if (!consentData) return;\n document.getElementById(\"auth-error\").style.display = \"none\";\n var statusEl = document.getElementById(\"approved\");\n document.getElementById(\"consent\").style.display = \"none\";\n statusEl.style.display = \"block\";\n statusEl.textContent = authMode === \"credentials\" ? \"Authenticating...\" : \"Sending approval...\";\n statusEl.style.color = \"\";\n var reqId = nextId++;\n pendingRequests[reqId] = handleApprovalResponse;\n\n if (authMode === \"credentials\") {\n var username = document.getElementById(\"cred-username\").value;\n var password = document.getElementById(\"cred-password\").value;\n if (!username || !password) {\n statusEl.style.display = \"none\";\n document.getElementById(\"consent\").style.display = \"block\";\n var errEl = document.getElementById(\"auth-error\");\n errEl.textContent = \"Please enter both username and password.\";\n errEl.style.display = \"block\";\n resizeNotify();\n return;\n }\n send({\n jsonrpc: \"2.0\", id: reqId, method: \"tools/call\",\n params: {\n name: \"_mcpi_credential_auth\",\n arguments: {\n tool: consentData.tool,\n scopes: consentData.scopes,\n session_id: consentData.sessionId,\n agent_did: consentData.agentDid,\n project_id: consentData.projectId,\n resume_token: consentData.resumeToken,\n username: username,\n password: password,\n provider: consentData.provider || \"credentials\"\n }\n }\n });\n } else {\n send({\n jsonrpc: \"2.0\", id: reqId, method: \"tools/call\",\n params: {\n name: \"_mcpi_approve_consent\",\n arguments: {\n tool: consentData.tool,\n scopes: consentData.scopes,\n session_id: consentData.sessionId,\n agent_did: consentData.agentDid,\n project_id: consentData.projectId,\n resume_token: consentData.resumeToken\n }\n }\n });\n }\n resizeNotify();\n });\n\n document.getElementById(\"deny-btn\").addEventListener(\"click\", function() {\n document.getElementById(\"consent\").style.display = \"none\";\n document.getElementById(\"approved\").style.display = \"block\";\n document.getElementById(\"approved\").textContent = \"Authorization denied.\";\n document.getElementById(\"approved\").style.color = \"#dc2626\";\n resizeNotify();\n });\n\n window.addEventListener(\"message\", function(e) {\n if (e.source !== window.parent) return;\n var msg = e.data;\n if (!msg || msg.jsonrpc !== \"2.0\") return;\n\n if (msg.id === 0 && msg.result) {\n var ctx = msg.result.hostContext || {};\n if (ctx.theme === \"dark\") document.documentElement.style.colorScheme = \"dark\";\n send({ jsonrpc: \"2.0\", method: \"ui/notifications/initialized\" });\n resizeNotify();\n }\n if (msg.id != null && pendingRequests[msg.id]) {\n pendingRequests[msg.id](msg.result, msg.error);\n delete pendingRequests[msg.id];\n }\n if (msg.method === \"ui/notifications/tool-result\" && msg.params) {\n var sc = msg.params.structuredContent;\n if (sc && sc.type === \"consent_required\") showConsent(sc);\n }\n if (msg.method === \"ui/notifications/tool-input\" && msg.params) {\n var args = msg.params.arguments;\n if (args && args.type === \"consent_required\") showConsent(args);\n }\n if (msg.method === \"ping\" && msg.id != null) {\n send({ jsonrpc: \"2.0\", id: msg.id, result: {} });\n }\n if (msg.method === \"ui/resource-teardown\" && msg.id != null) {\n send({ jsonrpc: \"2.0\", id: msg.id, result: {} });\n }\n });\n\n send({\n jsonrpc: \"2.0\", id: 0, method: \"ui/initialize\",\n params: {\n appInfo: { name: \"MCPI Consent\", version: \"1.0.0\" },\n appCapabilities: {},\n protocolVersion: \"2026-01-26\"\n }\n });\n })();\n </script>\n</body>\n</html>";
11
+ //# sourceMappingURL=consent-fallback-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent-fallback-html.d.ts","sourceRoot":"","sources":["../src/consent-fallback-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,eAAO,MAAM,qBAAqB,usbAmS1B,CAAC"}
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Minimal inline consent UI fallback.
3
+ *
4
+ * Used when @kya-os/consent is not available (optional peer dependency).
5
+ * This is the vanilla HTML/JS/CSS consent form with inline MCP Apps
6
+ * handshake that proves the data pipeline works end-to-end.
7
+ *
8
+ * The full Lit-based UI in @kya-os/consent/mcp-app is preferred when available.
9
+ */
10
+ // eslint-disable-next-line @typescript-eslint/naming-convention
11
+ export const CONSENT_FALLBACK_HTML = `<!DOCTYPE html>
12
+ <html lang="en">
13
+ <head>
14
+ <meta charset="utf-8">
15
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
16
+ <meta name="color-scheme" content="light dark">
17
+ <title>MCPI Consent</title>
18
+ <style>
19
+ * { box-sizing: border-box; margin: 0; padding: 0; }
20
+ body { font-family: system-ui, -apple-system, sans-serif; padding: 16px; background: transparent; }
21
+ .card { border-radius: 12px; padding: 20px; border: 1px solid rgba(128,128,128,0.2); }
22
+ h2 { font-size: 16px; font-weight: 600; margin-bottom: 8px; }
23
+ p { font-size: 13px; opacity: 0.7; line-height: 1.5; margin-bottom: 6px; }
24
+ .scopes { margin: 10px 0; }
25
+ .scope { display: inline-block; padding: 3px 10px; border-radius: 10px; font-size: 12px; font-weight: 500; margin: 2px 4px 2px 0; background: rgba(46,125,50,0.1); color: #2e7d32; }
26
+ .btn { display: inline-block; padding: 8px 20px; border-radius: 8px; border: none; font-size: 14px; font-weight: 500; cursor: pointer; margin-right: 8px; margin-top: 10px; }
27
+ .btn-approve { background: #2563eb; color: #fff; }
28
+ .btn-approve:disabled { opacity: 0.5; cursor: not-allowed; }
29
+ .btn-deny { background: transparent; border: 1px solid rgba(128,128,128,0.3); }
30
+ .info { font-size: 11px; opacity: 0.5; margin-top: 12px; }
31
+ .fallback { font-size: 12px; margin-top: 8px; }
32
+ .fallback a { color: #2563eb; }
33
+ #loading { font-size: 13px; opacity: 0.6; }
34
+ #consent { display: none; }
35
+ #approved { display: none; font-size: 14px; color: #16a34a; font-weight: 500; }
36
+ .cred-fields { display: none; margin: 12px 0; }
37
+ .cred-fields label { display: block; font-size: 12px; font-weight: 500; margin-bottom: 4px; opacity: 0.8; }
38
+ .cred-fields input[type="text"],
39
+ .cred-fields input[type="password"] { width: 100%; padding: 8px 10px; border-radius: 6px; border: 1px solid rgba(128,128,128,0.3); font-size: 14px; margin-bottom: 10px; background: transparent; color: inherit; }
40
+ .cred-fields input:focus { outline: none; border-color: #2563eb; }
41
+ .pw-wrap { position: relative; }
42
+ .pw-toggle { position: absolute; right: 8px; top: 8px; background: none; border: none; cursor: pointer; font-size: 13px; opacity: 0.5; color: inherit; }
43
+ .terms-row { display: flex; align-items: flex-start; gap: 8px; margin: 10px 0 4px; }
44
+ .terms-row input[type="checkbox"] { margin-top: 2px; }
45
+ .terms-row label { font-size: 12px; opacity: 0.7; cursor: pointer; }
46
+ .auth-error { display: none; font-size: 13px; color: #dc2626; margin: 8px 0; padding: 8px 10px; border-radius: 6px; background: rgba(220,38,38,0.08); }
47
+ </style>
48
+ </head>
49
+ <body>
50
+ <div id="loading">Waiting for consent data&hellip;</div>
51
+ <div id="consent" class="card">
52
+ <h2>Authorization Required</h2>
53
+ <p id="tool-desc"></p>
54
+ <div id="scopes-container" class="scopes"></div>
55
+ <div id="cred-fields" class="cred-fields">
56
+ <label for="cred-username">Username / Email</label>
57
+ <input type="text" id="cred-username" autocomplete="username" placeholder="Enter your username or email">
58
+ <label for="cred-password">Password</label>
59
+ <div class="pw-wrap">
60
+ <input type="password" id="cred-password" autocomplete="current-password" placeholder="Enter your password">
61
+ <button type="button" class="pw-toggle" id="pw-toggle" aria-label="Toggle password visibility">Show</button>
62
+ </div>
63
+ </div>
64
+ <div id="auth-error" class="auth-error"></div>
65
+ <div id="terms-row" class="terms-row" style="display:none;">
66
+ <input type="checkbox" id="terms-check">
67
+ <label for="terms-check">I agree to authorize this tool and accept the terms of service</label>
68
+ </div>
69
+ <p id="agent-info" class="info"></p>
70
+ <div>
71
+ <button class="btn btn-approve" id="approve-btn">Approve</button>
72
+ <button class="btn btn-deny" id="deny-btn">Deny</button>
73
+ </div>
74
+ <div class="fallback" id="fallback"></div>
75
+ </div>
76
+ <div id="approved"></div>
77
+ <script>
78
+ (function() {
79
+ var send = function(msg) { window.parent.postMessage(msg, "*"); };
80
+ var consentData = null;
81
+ var authMode = "consent-only";
82
+
83
+ function resizeNotify() {
84
+ send({ jsonrpc: "2.0", method: "ui/notifications/size-changed", params: {
85
+ width: document.documentElement.scrollWidth,
86
+ height: document.documentElement.scrollHeight
87
+ }});
88
+ }
89
+
90
+ function showConsent(data) {
91
+ consentData = data;
92
+ authMode = data.authMode || "consent-only";
93
+ document.getElementById("loading").style.display = "none";
94
+ document.getElementById("consent").style.display = "block";
95
+
96
+ if (authMode === "credentials") {
97
+ document.getElementById("tool-desc").textContent =
98
+ "Tool \\u201c" + (data.tool || "unknown") + "\\u201d requires authentication.";
99
+ document.getElementById("cred-fields").style.display = "block";
100
+ document.getElementById("terms-row").style.display = "flex";
101
+ document.getElementById("approve-btn").textContent = "Sign In & Authorize";
102
+ document.getElementById("approve-btn").disabled = true;
103
+ document.getElementById("terms-check").addEventListener("change", function() {
104
+ document.getElementById("approve-btn").disabled = !this.checked;
105
+ });
106
+ } else {
107
+ document.getElementById("tool-desc").textContent =
108
+ "Tool \\u201c" + (data.tool || "unknown") + "\\u201d requires your approval.";
109
+ }
110
+
111
+ var scopesEl = document.getElementById("scopes-container");
112
+ var scopes = data.scopes || [];
113
+ scopesEl.textContent = "";
114
+ scopes.forEach(function(s) {
115
+ var span = document.createElement("span");
116
+ span.className = "scope";
117
+ span.textContent = s;
118
+ scopesEl.appendChild(span);
119
+ });
120
+ document.getElementById("agent-info").textContent =
121
+ "Agent: " + (data.agentName || data.agentDid || "unknown");
122
+ if (data.consentUrl) {
123
+ var fallbackEl = document.getElementById("fallback");
124
+ fallbackEl.textContent = "";
125
+ var a = document.createElement("a");
126
+ a.href = data.consentUrl;
127
+ a.target = "_blank";
128
+ a.rel = "noopener";
129
+ a.textContent = "Open in browser";
130
+ fallbackEl.appendChild(a);
131
+ }
132
+ resizeNotify();
133
+ }
134
+
135
+ document.getElementById("pw-toggle").addEventListener("click", function() {
136
+ var pwInput = document.getElementById("cred-password");
137
+ if (pwInput.type === "password") {
138
+ pwInput.type = "text";
139
+ this.textContent = "Hide";
140
+ } else {
141
+ pwInput.type = "password";
142
+ this.textContent = "Show";
143
+ }
144
+ });
145
+
146
+ var pendingRequests = {};
147
+ var nextId = 100;
148
+
149
+ function handleApprovalResponse(result, error) {
150
+ var statusEl = document.getElementById("approved");
151
+ if (error) {
152
+ if (authMode === "credentials") {
153
+ var errEl = document.getElementById("auth-error");
154
+ errEl.textContent = error.message || JSON.stringify(error);
155
+ errEl.style.display = "block";
156
+ document.getElementById("consent").style.display = "block";
157
+ statusEl.style.display = "none";
158
+ document.getElementById("approve-btn").disabled = !document.getElementById("terms-check").checked;
159
+ resizeNotify();
160
+ return;
161
+ }
162
+ statusEl.textContent = "Approval error: " + (error.message || JSON.stringify(error));
163
+ statusEl.style.color = "#dc2626";
164
+ } else {
165
+ try {
166
+ var text = result && result.content && result.content[0] && result.content[0].text;
167
+ var respData = text ? JSON.parse(text) : {};
168
+ if (respData.success) {
169
+ statusEl.textContent = "Authorization granted. You can now retry the tool.";
170
+ statusEl.style.color = "#22c55e";
171
+ } else {
172
+ if (authMode === "credentials" && (respData.error_code === "auth_failed" || respData.error_code === "validation_error")) {
173
+ var errEl = document.getElementById("auth-error");
174
+ errEl.textContent = respData.error || "Authentication failed. Please check your credentials.";
175
+ errEl.style.display = "block";
176
+ document.getElementById("consent").style.display = "block";
177
+ statusEl.style.display = "none";
178
+ document.getElementById("approve-btn").disabled = !document.getElementById("terms-check").checked;
179
+ resizeNotify();
180
+ return;
181
+ }
182
+ statusEl.textContent = "Approval error: " + (respData.error || respData.error_code || "Unknown");
183
+ statusEl.style.color = "#f59e0b";
184
+ }
185
+ } catch(e) {
186
+ statusEl.textContent = "Unexpected response";
187
+ statusEl.style.color = "#f59e0b";
188
+ }
189
+ }
190
+ resizeNotify();
191
+ }
192
+
193
+ document.getElementById("approve-btn").addEventListener("click", function() {
194
+ if (!consentData) return;
195
+ document.getElementById("auth-error").style.display = "none";
196
+ var statusEl = document.getElementById("approved");
197
+ document.getElementById("consent").style.display = "none";
198
+ statusEl.style.display = "block";
199
+ statusEl.textContent = authMode === "credentials" ? "Authenticating..." : "Sending approval...";
200
+ statusEl.style.color = "";
201
+ var reqId = nextId++;
202
+ pendingRequests[reqId] = handleApprovalResponse;
203
+
204
+ if (authMode === "credentials") {
205
+ var username = document.getElementById("cred-username").value;
206
+ var password = document.getElementById("cred-password").value;
207
+ if (!username || !password) {
208
+ statusEl.style.display = "none";
209
+ document.getElementById("consent").style.display = "block";
210
+ var errEl = document.getElementById("auth-error");
211
+ errEl.textContent = "Please enter both username and password.";
212
+ errEl.style.display = "block";
213
+ resizeNotify();
214
+ return;
215
+ }
216
+ send({
217
+ jsonrpc: "2.0", id: reqId, method: "tools/call",
218
+ params: {
219
+ name: "_mcpi_credential_auth",
220
+ arguments: {
221
+ tool: consentData.tool,
222
+ scopes: consentData.scopes,
223
+ session_id: consentData.sessionId,
224
+ agent_did: consentData.agentDid,
225
+ project_id: consentData.projectId,
226
+ resume_token: consentData.resumeToken,
227
+ username: username,
228
+ password: password,
229
+ provider: consentData.provider || "credentials"
230
+ }
231
+ }
232
+ });
233
+ } else {
234
+ send({
235
+ jsonrpc: "2.0", id: reqId, method: "tools/call",
236
+ params: {
237
+ name: "_mcpi_approve_consent",
238
+ arguments: {
239
+ tool: consentData.tool,
240
+ scopes: consentData.scopes,
241
+ session_id: consentData.sessionId,
242
+ agent_did: consentData.agentDid,
243
+ project_id: consentData.projectId,
244
+ resume_token: consentData.resumeToken
245
+ }
246
+ }
247
+ });
248
+ }
249
+ resizeNotify();
250
+ });
251
+
252
+ document.getElementById("deny-btn").addEventListener("click", function() {
253
+ document.getElementById("consent").style.display = "none";
254
+ document.getElementById("approved").style.display = "block";
255
+ document.getElementById("approved").textContent = "Authorization denied.";
256
+ document.getElementById("approved").style.color = "#dc2626";
257
+ resizeNotify();
258
+ });
259
+
260
+ window.addEventListener("message", function(e) {
261
+ if (e.source !== window.parent) return;
262
+ var msg = e.data;
263
+ if (!msg || msg.jsonrpc !== "2.0") return;
264
+
265
+ if (msg.id === 0 && msg.result) {
266
+ var ctx = msg.result.hostContext || {};
267
+ if (ctx.theme === "dark") document.documentElement.style.colorScheme = "dark";
268
+ send({ jsonrpc: "2.0", method: "ui/notifications/initialized" });
269
+ resizeNotify();
270
+ }
271
+ if (msg.id != null && pendingRequests[msg.id]) {
272
+ pendingRequests[msg.id](msg.result, msg.error);
273
+ delete pendingRequests[msg.id];
274
+ }
275
+ if (msg.method === "ui/notifications/tool-result" && msg.params) {
276
+ var sc = msg.params.structuredContent;
277
+ if (sc && sc.type === "consent_required") showConsent(sc);
278
+ }
279
+ if (msg.method === "ui/notifications/tool-input" && msg.params) {
280
+ var args = msg.params.arguments;
281
+ if (args && args.type === "consent_required") showConsent(args);
282
+ }
283
+ if (msg.method === "ping" && msg.id != null) {
284
+ send({ jsonrpc: "2.0", id: msg.id, result: {} });
285
+ }
286
+ if (msg.method === "ui/resource-teardown" && msg.id != null) {
287
+ send({ jsonrpc: "2.0", id: msg.id, result: {} });
288
+ }
289
+ });
290
+
291
+ send({
292
+ jsonrpc: "2.0", id: 0, method: "ui/initialize",
293
+ params: {
294
+ appInfo: { name: "MCPI Consent", version: "1.0.0" },
295
+ appCapabilities: {},
296
+ protocolVersion: "2026-01-26"
297
+ }
298
+ });
299
+ })();
300
+ </script>
301
+ </body>
302
+ </html>`;
303
+ //# sourceMappingURL=consent-fallback-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent-fallback-html.js","sourceRoot":"","sources":["../src/consent-fallback-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,gEAAgE;AAChE,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAmS7B,CAAC"}
@@ -11,6 +11,26 @@
11
11
  */
12
12
  import type { ConsentPageConfig, OAuthIdentity } from "@kya-os/contracts/consent";
13
13
  import type { CredentialProviderConfig } from "@kya-os/contracts/config";
14
+ import { type ConsentUI, type CredentialsConfig } from "@kya-os/consent";
15
+ /**
16
+ * ConsentPageConfig extended with fields that flow through from AgentShield
17
+ * remote config but are intentionally excluded from the contracts type.
18
+ */
19
+ type RendererPageConfig = ConsentPageConfig & {
20
+ oauthRequired?: boolean;
21
+ oauthUrl?: string;
22
+ credentialProviderType?: string;
23
+ credentialProvider?: string;
24
+ userDid?: string;
25
+ credentialUserEmail?: string;
26
+ credentialProviderUserId?: string;
27
+ oauthProviderType?: string;
28
+ oauthProviderName?: string;
29
+ ui?: ConsentUI;
30
+ credentials?: CredentialsConfig;
31
+ expirationDays?: number;
32
+ agentName?: string;
33
+ };
14
34
  /**
15
35
  * Template-based consent page renderer.
16
36
  *
@@ -38,17 +58,7 @@ export declare class TemplateRenderer {
38
58
  * @param oauthIdentity - Optional OAuth identity from cookie
39
59
  * @returns HTML string
40
60
  */
41
- render(config: ConsentPageConfig & {
42
- oauthRequired?: boolean;
43
- oauthUrl?: string;
44
- credentialProviderType?: string;
45
- credentialProvider?: string;
46
- userDid?: string;
47
- credentialUserEmail?: string;
48
- credentialProviderUserId?: string;
49
- oauthProviderType?: string;
50
- oauthProviderName?: string;
51
- }, oauthIdentity?: OAuthIdentity): string;
61
+ render(config: RendererPageConfig, oauthIdentity?: OAuthIdentity): string;
52
62
  /**
53
63
  * Render consent page using Client-Side Rendering (CSR).
54
64
  *
@@ -73,7 +83,7 @@ export declare class TemplateRenderer {
73
83
  * @param authorizationType - Authorization type from tool protection config (default: 'password')
74
84
  * @returns HTML string
75
85
  */
76
- renderCredentialPage(config: ConsentPageConfig, credentialConfig: CredentialProviderConfig, provider: string, csrfToken: string, authorizationType?: string): string;
86
+ renderCredentialPage(config: RendererPageConfig, credentialConfig: CredentialProviderConfig, provider: string, csrfToken: string, authorizationType?: string): string;
77
87
  /**
78
88
  * Render credential login page using CSR (Client-Side Rendering).
79
89
  *
@@ -125,4 +135,5 @@ export declare function createTemplateRenderer(options?: {
125
135
  useCSR?: boolean;
126
136
  bundlePath?: string;
127
137
  }): TemplateRenderer;
138
+ export {};
128
139
  //# sourceMappingURL=template-renderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"template-renderer.d.ts","sourceRoot":"","sources":["../../../src/services/consent-templates/template-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAYH,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACd,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAazE;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;IAK/D;;;;;;;;;OASG;IACH,MAAM,CACJ,MAAM,EAAE,iBAAiB,GAAG;QAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,EACD,aAAa,CAAC,EAAE,aAAa,GAC5B,MAAM;IAoCT;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,SAAS;IAuEjB;;;;;;;;;OASG;IACH,oBAAoB,CAClB,MAAM,EAAE,iBAAiB,EACzB,gBAAgB,EAAE,wBAAwB,EAC1C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,iBAAiB,GAAE,MAAmB,GACrC,MAAM;IA+BT;;;;;;;;;OASG;IACH,OAAO,CAAC,uBAAuB;IAmD/B;;;;;;OAMG;IACH,aAAa,CAAC,OAAO,EAAE;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,GAAG,MAAM;IAIV;;;;;;;OAOG;IACH,iBAAiB,CACf,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,OAAO,GAClB,MAAM;IAsDT;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAqC3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAuC1B;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,gBAAgB,CAEnB"}
1
+ {"version":3,"file":"template-renderer.d.ts","sourceRoot":"","sources":["../../../src/services/consent-templates/template-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAYH,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACd,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AAQzB;;;GAGG;AACH,KAAK,kBAAkB,GAAG,iBAAiB,GAAG;IAC5C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;IAK/D;;;;;;;;;OASG;IACH,MAAM,CACJ,MAAM,EAAE,kBAAkB,EAC1B,aAAa,CAAC,EAAE,aAAa,GAC5B,MAAM;IAoCT;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,SAAS;IAgEjB;;;;;;;;;OASG;IACH,oBAAoB,CAClB,MAAM,EAAE,kBAAkB,EAC1B,gBAAgB,EAAE,wBAAwB,EAC1C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,iBAAiB,GAAE,MAAmB,GACrC,MAAM;IA+BT;;;;;;;;;OASG;IACH,OAAO,CAAC,uBAAuB;IAuD/B;;;;;;OAMG;IACH,aAAa,CAAC,OAAO,EAAE;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,GAAG,MAAM;IAIV;;;;;;;OAOG;IACH,iBAAiB,CACf,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,OAAO,GAClB,MAAM;IAsDT;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA2B3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAqC1B;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,gBAAgB,CAEnB"}
@@ -91,6 +91,8 @@ export class TemplateRenderer {
91
91
  ui: config.ui,
92
92
  // Map credentials config if available
93
93
  credentials: config.credentials,
94
+ // Map expiration days from AgentShield config
95
+ expirationDays: config.expirationDays,
94
96
  // Map other mode configs
95
97
  // CRITICAL: Include providerId for proper OAuth button URL construction
96
98
  oauth: config.oauthRequired
@@ -116,6 +118,7 @@ export class TemplateRenderer {
116
118
  // Set authMode explicitly for OAuth flow
117
119
  // This ensures the mcp-consent component renders the OAuth button
118
120
  authMode: config.oauthRequired ? "oauth" : undefined,
121
+ agentName: config.agentName, // Human-readable agent name for display
119
122
  provider: config.provider, // Pass the OAuth provider name (e.g., 'github')
120
123
  // CRITICAL: Pass pre-built OAuth URL directly to avoid constructing wrong URL
121
124
  // This is the actual OAuth authorization URL (e.g., https://github.com/login/oauth/authorize?...)
@@ -191,6 +194,9 @@ export class TemplateRenderer {
191
194
  terms: config.terms,
192
195
  customFields: config.customFields,
193
196
  ui: config.ui,
197
+ // Pass expiration days so the credential page shows the correct value
198
+ // (parity with renderCSR — otherwise the Lit component falls back to default)
199
+ expirationDays: config.expirationDays,
194
200
  // Include credentials config for the Lit component
195
201
  credentials: {
196
202
  usernameLabel: cpc.usernameLabel || "Username",
@@ -215,6 +221,7 @@ export class TemplateRenderer {
215
221
  pageTitle: consentConfig.ui?.title || "Permission Request",
216
222
  // Force credentials mode
217
223
  authMode: "credentials",
224
+ agentName: config.agentName,
218
225
  provider: provider,
219
226
  // Include CSRF token for form security
220
227
  csrfToken: csrfToken,
@@ -307,7 +314,7 @@ export class TemplateRenderer {
307
314
  provider: config.provider,
308
315
  oauthUrl: config.oauthUrl,
309
316
  oauthRequired: config.oauthRequired,
310
- expirationDays: 30, // Default, could be pulled from config
317
+ expirationDays: config.expirationDays ?? 30,
311
318
  // Pass through credential auth params for 3-screen flow
312
319
  credentialProviderType: config.credentialProviderType,
313
320
  credentialProvider: config.credentialProvider,
@@ -323,8 +330,6 @@ export class TemplateRenderer {
323
330
  * Build ConsentConfigWithMeta from page config's branding/terms/ui.
324
331
  */
325
332
  buildRemoteConfig(config) {
326
- // Cast to any to access optional fields that may come from AgentShield
327
- const extendedConfig = config;
328
333
  const branding = config.branding;
329
334
  return {
330
335
  branding: config.branding
@@ -344,20 +349,20 @@ export class TemplateRenderer {
344
349
  : undefined,
345
350
  customFields: config.customFields,
346
351
  // Map UI config for title, description, button text, etc.
347
- ui: extendedConfig.ui
352
+ ui: config.ui
348
353
  ? {
349
- title: extendedConfig.ui.title,
350
- description: extendedConfig.ui.description,
351
- expirationText: extendedConfig.ui.expirationText,
352
- cancelButtonText: extendedConfig.ui.cancelButtonText,
353
- submitButtonText: extendedConfig.ui.submitButtonText,
354
- permissionsHeader: extendedConfig.ui.permissionsHeader,
354
+ title: config.ui.title,
355
+ description: config.ui.description,
356
+ expirationText: config.ui.expirationText,
357
+ cancelButtonText: config.ui.cancelButtonText,
358
+ submitButtonText: config.ui.submitButtonText,
359
+ permissionsHeader: config.ui.permissionsHeader,
355
360
  }
356
361
  : undefined,
357
362
  // Map credentials config
358
- credentials: extendedConfig.credentials,
363
+ credentials: config.credentials,
359
364
  // Map expiration days
360
- expirationDays: extendedConfig.expirationDays,
365
+ expirationDays: config.expirationDays,
361
366
  };
362
367
  }
363
368
  }