@humain/terminal 0.0.13 → 0.0.15
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/CHANGELOG.md +9 -0
- package/dist/bundle/chunks/{chunk-V5XRWLQF.js → chunk-QMTWJZBT.js} +252 -40
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +30 -9
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/humain/agent-execution-runtime.d.ts.map +1 -1
- package/dist/humain/agent-execution-runtime.js +3 -1
- package/dist/humain/agent-execution-runtime.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +27 -0
- package/dist/humain/mcp-adapter/vendor/README.md +13 -13
- package/dist/humain/mcp-adapter/vendor/commands.ts +58 -21
- package/dist/humain/mcp-adapter/vendor/config.ts +18 -4
- package/dist/humain/mcp-adapter/vendor/direct-tools.ts +26 -6
- package/dist/humain/mcp-adapter/vendor/dist/config.d.ts +4 -0
- package/dist/humain/mcp-adapter/vendor/dist/config.js +13 -4
- package/dist/humain/mcp-adapter/vendor/dist/config.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/dist/types.d.ts +11 -3
- package/dist/humain/mcp-adapter/vendor/dist/types.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/error-signal.ts +15 -4
- package/dist/humain/mcp-adapter/vendor/errors.ts +141 -0
- package/dist/humain/mcp-adapter/vendor/host-html-template.ts +58 -5
- package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +1017 -160
- package/dist/humain/mcp-adapter/vendor/index.ts +2 -3
- package/dist/humain/mcp-adapter/vendor/init.ts +5 -0
- package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +30 -9
- package/dist/humain/mcp-adapter/vendor/mcp-setup-panel.ts +66 -28
- package/dist/humain/mcp-adapter/vendor/mcp-status.ts +2 -0
- package/dist/humain/mcp-adapter/vendor/package.json +3 -2
- package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +66 -13
- package/dist/humain/mcp-adapter/vendor/sandbox-proxy-template.ts +217 -0
- package/dist/humain/mcp-adapter/vendor/server-manager.ts +337 -6
- package/dist/humain/mcp-adapter/vendor/skills/mcp-scripting/SKILL.md +1 -0
- package/dist/humain/mcp-adapter/vendor/types.ts +18 -3
- package/dist/humain/mcp-adapter/vendor/ui-resource-handler.ts +18 -2
- package/dist/humain/mcp-adapter/vendor/ui-server.ts +179 -54
- package/dist/humain/mcp-adapter/vendor/ui-session.ts +28 -8
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/src/humain/mcp-adapter/UPSTREAM.md +1 -1
- package/src/humain/mcp-adapter/upstream.json +4 -4
- package/src/humain/mcp-adapter/vendor/CHANGELOG.md +27 -0
|
@@ -3,6 +3,8 @@ import type { UiHostContext, UiResourceContent, UiResourceCsp } from "./types.ts
|
|
|
3
3
|
// Use locally bundled AppBridge to avoid CDN Zod bundling issues
|
|
4
4
|
const DEFAULT_APP_BRIDGE_MODULE_URL = "/app-bridge.bundle.js";
|
|
5
5
|
const APP_SANDBOX = "allow-scripts allow-forms allow-modals allow-popups allow-downloads";
|
|
6
|
+
const APP_PROXY_SANDBOX = `${APP_SANDBOX} allow-same-origin`;
|
|
7
|
+
const APP_INNER_SANDBOX = APP_PROXY_SANDBOX;
|
|
6
8
|
|
|
7
9
|
export interface HostHtmlTemplateInput {
|
|
8
10
|
sessionToken: string;
|
|
@@ -16,6 +18,7 @@ export interface HostHtmlTemplateInput {
|
|
|
16
18
|
cacheToolConsent: boolean;
|
|
17
19
|
hostContext?: UiHostContext;
|
|
18
20
|
appBridgeModuleUrl?: string;
|
|
21
|
+
sandboxProxyUrl: string;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
@@ -31,6 +34,9 @@ export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
|
31
34
|
const requireToolConsent = safeInlineJSON(input.requireToolConsent);
|
|
32
35
|
const cacheToolConsent = safeInlineJSON(input.cacheToolConsent);
|
|
33
36
|
const moduleUrl = safeInlineJSON(input.appBridgeModuleUrl ?? DEFAULT_APP_BRIDGE_MODULE_URL);
|
|
37
|
+
const sandboxProxyUrl = safeInlineJSON(input.sandboxProxyUrl);
|
|
38
|
+
const resourceCsp = safeInlineJSON(input.resource.meta.csp);
|
|
39
|
+
const resourcePermissions = safeInlineJSON(input.resource.meta.permissions);
|
|
34
40
|
|
|
35
41
|
return `<!doctype html>
|
|
36
42
|
<html lang="en">
|
|
@@ -112,7 +118,7 @@ export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
|
112
118
|
</div>
|
|
113
119
|
</header>
|
|
114
120
|
<main>
|
|
115
|
-
<iframe id="mcp-app" sandbox="${
|
|
121
|
+
<iframe id="mcp-app" sandbox="${APP_PROXY_SANDBOX}" referrerpolicy="no-referrer"></iframe>
|
|
116
122
|
</main>
|
|
117
123
|
<div class="overlay" id="error-overlay">
|
|
118
124
|
<div class="panel">
|
|
@@ -138,6 +144,10 @@ export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
|
138
144
|
const ALLOW_ATTRIBUTE = ${allowAttribute};
|
|
139
145
|
const REQUIRE_TOOL_CONSENT = ${requireToolConsent};
|
|
140
146
|
const CACHE_TOOL_CONSENT = ${cacheToolConsent};
|
|
147
|
+
const SANDBOX_PROXY_URL = ${sandboxProxyUrl};
|
|
148
|
+
const RESOURCE_CSP = ${resourceCsp};
|
|
149
|
+
const RESOURCE_PERMISSIONS = ${resourcePermissions};
|
|
150
|
+
const INNER_SANDBOX = ${safeInlineJSON(APP_INNER_SANDBOX)};
|
|
141
151
|
const STREAM_CONTEXT_KEY = "pi-mcp-adapter/stream";
|
|
142
152
|
const STREAM_PATCH_METHOD = "notifications/pi-mcp-adapter/ui-result-patch";
|
|
143
153
|
|
|
@@ -148,6 +158,7 @@ export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
|
148
158
|
const errorOverlay = document.getElementById("error-overlay");
|
|
149
159
|
const completionOverlay = document.getElementById("completion-overlay");
|
|
150
160
|
const errorMessage = document.getElementById("error-message");
|
|
161
|
+
const sandboxProxyOrigin = new URL(SANDBOX_PROXY_URL).origin;
|
|
151
162
|
|
|
152
163
|
document.getElementById("server-name").textContent = SERVER_NAME;
|
|
153
164
|
document.getElementById("tool-name").textContent = TOOL_NAME;
|
|
@@ -205,10 +216,41 @@ export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
|
205
216
|
const bridge = new AppBridge(
|
|
206
217
|
null,
|
|
207
218
|
{ name: "pi", version: "1.0.0" },
|
|
208
|
-
{
|
|
219
|
+
{
|
|
220
|
+
serverTools: {},
|
|
221
|
+
openLinks: {},
|
|
222
|
+
logging: {},
|
|
223
|
+
updateModelContext: {},
|
|
224
|
+
message: {},
|
|
225
|
+
sandbox: {
|
|
226
|
+
...(RESOURCE_CSP ? { csp: RESOURCE_CSP } : {}),
|
|
227
|
+
...(RESOURCE_PERMISSIONS ? { permissions: RESOURCE_PERMISSIONS } : {}),
|
|
228
|
+
},
|
|
229
|
+
},
|
|
209
230
|
{ hostContext: HOST_CONTEXT }
|
|
210
231
|
);
|
|
211
232
|
|
|
233
|
+
let sandboxResourceSent = false;
|
|
234
|
+
bridge.onsandboxready = async () => {
|
|
235
|
+
if (sandboxResourceSent) return;
|
|
236
|
+
sandboxResourceSent = true;
|
|
237
|
+
try {
|
|
238
|
+
const response = await fetch("/ui-app?resource=" + encodeURIComponent(UI_RESOURCE_TOKEN), {
|
|
239
|
+
headers: { Accept: "text/html" },
|
|
240
|
+
});
|
|
241
|
+
if (!response.ok) throw new Error("UI resource request failed: HTTP " + response.status);
|
|
242
|
+
const html = await response.text();
|
|
243
|
+
await bridge.sendSandboxResourceReady({
|
|
244
|
+
html,
|
|
245
|
+
sandbox: INNER_SANDBOX,
|
|
246
|
+
...(RESOURCE_CSP ? { csp: RESOURCE_CSP } : {}),
|
|
247
|
+
...(RESOURCE_PERMISSIONS ? { permissions: RESOURCE_PERMISSIONS } : {}),
|
|
248
|
+
});
|
|
249
|
+
} catch (error) {
|
|
250
|
+
showError("Failed to load MCP App resource: " + String(error));
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
212
254
|
bridge.oncalltool = async (params) => {
|
|
213
255
|
if (!consentGranted) {
|
|
214
256
|
const accepted = window.confirm("Allow this UI to call server tools for this session?");
|
|
@@ -240,7 +282,7 @@ export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
|
240
282
|
// Also listen for raw postMessage events with custom types (notify, prompt, intent, etc.)
|
|
241
283
|
// These bypass the AppBridge protocol but are used by some MCP UI implementations
|
|
242
284
|
window.addEventListener("message", async (event) => {
|
|
243
|
-
if (event.source !== iframe.contentWindow) return;
|
|
285
|
+
if (event.source !== iframe.contentWindow || event.origin !== sandboxProxyOrigin) return;
|
|
244
286
|
const data = event.data;
|
|
245
287
|
if (!data || typeof data !== "object") return;
|
|
246
288
|
|
|
@@ -304,6 +346,12 @@ export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
|
304
346
|
}
|
|
305
347
|
|
|
306
348
|
// Connect bridge BEFORE loading iframe to ensure we're listening when the app sends ui/initialize
|
|
349
|
+
const sandboxMessageGuard = (event) => {
|
|
350
|
+
if (event.source === iframe.contentWindow && event.origin !== sandboxProxyOrigin) {
|
|
351
|
+
event.stopImmediatePropagation();
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
window.addEventListener("message", sandboxMessageGuard, true);
|
|
307
355
|
try {
|
|
308
356
|
const transport = new PostMessageTransport(iframe.contentWindow, iframe.contentWindow);
|
|
309
357
|
await bridge.connect(transport);
|
|
@@ -315,7 +363,7 @@ export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
|
315
363
|
const iframeLoaded = new Promise((resolve) => {
|
|
316
364
|
iframe.onload = resolve;
|
|
317
365
|
});
|
|
318
|
-
iframe.src =
|
|
366
|
+
iframe.src = SANDBOX_PROXY_URL;
|
|
319
367
|
await iframeLoaded;
|
|
320
368
|
|
|
321
369
|
const eventSource = new EventSource("/events?session=" + encodeURIComponent(SESSION_TOKEN));
|
|
@@ -340,6 +388,9 @@ export function buildHostHtmlTemplate(input: HostHtmlTemplateInput): string {
|
|
|
340
388
|
showError("Failed to forward cancellation: " + String(error));
|
|
341
389
|
}
|
|
342
390
|
});
|
|
391
|
+
eventSource.addEventListener("resource-updated", () => {
|
|
392
|
+
setStatus("Resource updated on the server. Reopen this UI to load the latest version.");
|
|
393
|
+
});
|
|
343
394
|
eventSource.addEventListener("result-patch", async (event) => {
|
|
344
395
|
try {
|
|
345
396
|
await bridge.notification({
|
|
@@ -443,7 +494,9 @@ function sanitizeCspDomains(domains: unknown): string[] {
|
|
|
443
494
|
}
|
|
444
495
|
|
|
445
496
|
function safeInlineJSON(value: unknown): string {
|
|
446
|
-
|
|
497
|
+
const json = JSON.stringify(value);
|
|
498
|
+
if (json === undefined) return "undefined";
|
|
499
|
+
return json
|
|
447
500
|
.replace(/</g, "\\u003c")
|
|
448
501
|
.replace(/>/g, "\\u003e")
|
|
449
502
|
.replace(/&/g, "\\u0026")
|