gesso-framework 0.4.2 → 0.5.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/CHANGELOG.md +106 -0
- package/README.md +2 -0
- package/dist/ChannelProtocol-ByNoHujM.d.ts +247 -0
- package/dist/{FunctionComponent-CgwLKE5d.d.ts → FunctionComponent-fYMdePtH.d.ts} +3 -247
- package/dist/agent/index.d.ts +317 -0
- package/dist/agent/index.js +184 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/app-BvlIO1G9.js +326 -0
- package/dist/app-BvlIO1G9.js.map +1 -0
- package/dist/{index-C9FAI_Kt.d.ts → index-BDM_gzzZ.d.ts} +377 -268
- package/dist/index.d.ts +5 -3
- package/dist/index.js +971 -89
- package/dist/index.js.map +1 -1
- package/dist/jsx/jsx-runtime.d.ts +1 -1
- package/dist/{persisted-CsTPnjkc.js → persisted-pix1fS1D.js} +6 -1
- package/dist/{persisted-CsTPnjkc.js.map → persisted-pix1fS1D.js.map} +1 -1
- package/dist/remote-xxij8zXe.js +600 -0
- package/dist/remote-xxij8zXe.js.map +1 -0
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/ui-U39HjNFA.d.ts +517 -0
- package/dist/webmcp-CJVFvAHe.js +77 -0
- package/dist/webmcp-CJVFvAHe.js.map +1 -0
- package/dist/worker/index.d.ts +4 -2
- package/dist/worker/index.js +1 -1
- package/package.json +12 -4
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
+
import { r as remoteSurface, t as AGENT_PORT } from "./remote-xxij8zXe.js";
|
|
3
|
+
//#region src/agent/webmcp.ts
|
|
4
|
+
var webmcp_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
confirmInWindow: () => confirmInWindow,
|
|
6
|
+
connectWebMcp: () => connectWebMcp,
|
|
7
|
+
pageModelContext: () => pageModelContext,
|
|
8
|
+
registerWebMcpTools: () => registerWebMcpTools
|
|
9
|
+
});
|
|
10
|
+
/** The page's model context, if the browser has one. */
|
|
11
|
+
function pageModelContext() {
|
|
12
|
+
return globalThis.document?.modelContext ?? globalThis.navigator?.modelContext;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Registers every tool a surface offers, and returns what removes them.
|
|
16
|
+
*
|
|
17
|
+
* A tool the browser refuses, a name already taken by something else on
|
|
18
|
+
* the page, is reported on the console and skipped rather than taking
|
|
19
|
+
* the rest down with it. Resolves to a no-op when there is no model
|
|
20
|
+
* context to register with.
|
|
21
|
+
*/
|
|
22
|
+
async function registerWebMcpTools(surface, modelContext = pageModelContext()) {
|
|
23
|
+
if (modelContext === void 0) return () => {};
|
|
24
|
+
const registration = new AbortController();
|
|
25
|
+
for (const tool of await surface.tools()) try {
|
|
26
|
+
await modelContext.registerTool({
|
|
27
|
+
name: tool.name,
|
|
28
|
+
...tool.title === void 0 ? {} : { title: tool.title },
|
|
29
|
+
description: tool.description,
|
|
30
|
+
inputSchema: tool.inputSchema,
|
|
31
|
+
annotations: {
|
|
32
|
+
readOnlyHint: tool.annotations.readOnlyHint,
|
|
33
|
+
consequentialHint: tool.annotations.destructiveHint === true
|
|
34
|
+
},
|
|
35
|
+
execute: async (input) => answerOf(await surface.call(tool.name, input ?? {}))
|
|
36
|
+
}, { signal: registration.signal });
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.warn(`[gesso] WebMCP refused the tool ${tool.name}:`, error);
|
|
39
|
+
}
|
|
40
|
+
return () => registration.abort();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Registers an application's channels once it is mounted.
|
|
44
|
+
*
|
|
45
|
+
* Reaches them the way the development bridge does, through an agent
|
|
46
|
+
* port to the render worker, so every channel the page can reach is
|
|
47
|
+
* offered, wherever it is served.
|
|
48
|
+
*/
|
|
49
|
+
async function connectWebMcp(app, options = {}) {
|
|
50
|
+
const modelContext = options.modelContext ?? pageModelContext();
|
|
51
|
+
if (modelContext === void 0) return () => {};
|
|
52
|
+
const port = app.openRenderPort(AGENT_PORT);
|
|
53
|
+
if (port === void 0) throw new Error("connectWebMcp needs a mounted app: call it after app.mount().");
|
|
54
|
+
const unregister = await registerWebMcpTools(remoteSurface(port, { confirm: options.confirm ?? confirmInWindow }), modelContext);
|
|
55
|
+
return () => {
|
|
56
|
+
unregister();
|
|
57
|
+
port.close();
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** The browser's own dialog, worded for a person who did not ask for anything. */
|
|
61
|
+
function confirmInWindow(request) {
|
|
62
|
+
const lines = [`An AI agent wants to ${request.command} in ${request.channel}.`];
|
|
63
|
+
if (request.description !== void 0) lines.push(request.description);
|
|
64
|
+
if (Object.keys(request.arguments).length > 0) lines.push(JSON.stringify(request.arguments, null, 2));
|
|
65
|
+
if (request.destructive) lines.push("This cannot be undone.");
|
|
66
|
+
return window.confirm(lines.join("\n\n"));
|
|
67
|
+
}
|
|
68
|
+
/** What a call hands back to WebMCP: the view it left, or a rejection that says why. */
|
|
69
|
+
function answerOf(result) {
|
|
70
|
+
const text = result.content.map((part) => part.text).join("\n");
|
|
71
|
+
if (result.isError) throw new Error(text);
|
|
72
|
+
return result.structuredContent ?? text;
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { webmcp_exports as a, registerWebMcpTools as i, connectWebMcp as n, pageModelContext as r, confirmInWindow as t };
|
|
76
|
+
|
|
77
|
+
//# sourceMappingURL=webmcp-CJVFvAHe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webmcp-CJVFvAHe.js","names":[],"sources":["../src/agent/webmcp.ts"],"sourcesContent":["import type { AgentConfirmation, AgentSurfaceLike, AgentToolResult } from './AgentSurface';\nimport { AGENT_PORT, remoteSurface, type AgentConfirm } from './remote';\n\n/**\n * An application's channels, offered to an agent in the browser.\n *\n * WebMCP (https://webmachinelearning.github.io/webmcp/) is a page\n * registering tools with the browser, `document.modelContext.registerTool`,\n * for an agent the browser runs or hosts to call. It is MCP without\n * the server: no port, no process, and the tools live exactly as long\n * as the page does. The channel surface is already a list of tools\n * with JSON Schema inputs and an answer per call, so this registers\n * each one and routes its calls back through the render worker.\n *\n * What the spec gives a tool that a channel does not, and the reverse:\n *\n * - `readOnlyHint` is a channel's view tool; `consequentialHint`, the\n * spec's \"significant, real-world, or non-reversible\", is a command\n * marked `@destructive`. `untrustedContentHint` is never set: a\n * channel's view is the application's own data.\n * - There is no output schema. The result of a call is serialized to\n * JSON for the agent, so a call answers with the view it left.\n * - There is no way to ask the person. A command marked `@confirm`\n * asks through `confirm`, `window.confirm` unless told otherwise.\n * - A failed call rejects, which the spec turns into a failed\n * `executeTool` the agent reads, with the sentence that says why.\n *\n * The API is behind an origin trial in Chrome 149 to 156, and was\n * `navigator.modelContext` until Chrome 150; the old name is read when\n * the new one is missing. Where neither exists, nothing is registered\n * and nothing fails: a page offering tools to a browser that takes\n * none is an ordinary page.\n */\n\n/** The part of `ModelContext` this uses. */\nexport interface ModelContextLike {\n registerTool(\n tool: {\n name: string;\n title?: string;\n description: string;\n inputSchema?: object;\n annotations?: { readOnlyHint?: boolean; consequentialHint?: boolean };\n execute: (input: Record<string, unknown>, options?: { signal?: AbortSignal }) => Promise<unknown>;\n },\n options?: { signal?: AbortSignal }\n ): Promise<void>;\n}\n\nexport interface WebMcpOptions {\n /**\n * Asks the person whether a `@confirm` command may be sent. Defaults to\n * the browser's own `window.confirm`, which an application with its\n * own dialogs will want to replace.\n */\n confirm?: AgentConfirm;\n /** Where to register. Defaults to the page's own `modelContext`. */\n modelContext?: ModelContextLike;\n}\n\n/** The page's model context, if the browser has one. */\nexport function pageModelContext(): ModelContextLike | undefined {\n const fromDocument = (globalThis.document as { modelContext?: ModelContextLike } | undefined)?.modelContext;\n return fromDocument ?? (globalThis.navigator as { modelContext?: ModelContextLike } | undefined)?.modelContext;\n}\n\n/**\n * Registers every tool a surface offers, and returns what removes them.\n *\n * A tool the browser refuses, a name already taken by something else on\n * the page, is reported on the console and skipped rather than taking\n * the rest down with it. Resolves to a no-op when there is no model\n * context to register with.\n */\nexport async function registerWebMcpTools(\n surface: AgentSurfaceLike,\n modelContext: ModelContextLike | undefined = pageModelContext()\n): Promise<() => void> {\n if (modelContext === undefined) {\n return () => {};\n }\n const registration = new AbortController();\n for (const tool of await surface.tools()) {\n try {\n await modelContext.registerTool(\n {\n name: tool.name,\n ...(tool.title === undefined ? {} : { title: tool.title }),\n description: tool.description,\n inputSchema: tool.inputSchema,\n annotations: {\n readOnlyHint: tool.annotations.readOnlyHint,\n consequentialHint: tool.annotations.destructiveHint === true\n },\n execute: async input => answerOf(await surface.call(tool.name, input ?? {}))\n },\n { signal: registration.signal }\n );\n } catch (error) {\n console.warn(`[gesso] WebMCP refused the tool ${tool.name}:`, error);\n }\n }\n return () => registration.abort();\n}\n\n/**\n * Registers an application's channels once it is mounted.\n *\n * Reaches them the way the development bridge does, through an agent\n * port to the render worker, so every channel the page can reach is\n * offered, wherever it is served.\n */\nexport async function connectWebMcp(\n app: { openRenderPort(key: string): MessagePort | undefined },\n options: WebMcpOptions = {}\n): Promise<() => void> {\n const modelContext = options.modelContext ?? pageModelContext();\n if (modelContext === undefined) {\n return () => {};\n }\n const port = app.openRenderPort(AGENT_PORT);\n if (port === undefined) {\n throw new Error('connectWebMcp needs a mounted app: call it after app.mount().');\n }\n const surface = remoteSurface(port, { confirm: options.confirm ?? confirmInWindow });\n const unregister = await registerWebMcpTools(surface, modelContext);\n return () => {\n unregister();\n port.close();\n };\n}\n\n/** The browser's own dialog, worded for a person who did not ask for anything. */\nexport function confirmInWindow(request: AgentConfirmation): boolean {\n const lines = [`An AI agent wants to ${request.command} in ${request.channel}.`];\n if (request.description !== undefined) {\n lines.push(request.description);\n }\n if (Object.keys(request.arguments).length > 0) {\n lines.push(JSON.stringify(request.arguments, null, 2));\n }\n if (request.destructive) {\n lines.push('This cannot be undone.');\n }\n return window.confirm(lines.join('\\n\\n'));\n}\n\n/** What a call hands back to WebMCP: the view it left, or a rejection that says why. */\nfunction answerOf(result: AgentToolResult): unknown {\n const text = result.content.map(part => part.text).join('\\n');\n if (result.isError) {\n throw new Error(text);\n }\n return result.structuredContent ?? text;\n}\n"],"mappings":";;;;;;;;;;AA6DA,SAAgB,mBAAiD;CAE/D,OADsB,WAAW,UAA8D,gBACvE,WAAW,WAA+D;AACpG;;;;;;;;;AAUA,eAAsB,oBACpB,SACA,eAA6C,iBAAiB,GACzC;CACrB,IAAI,iBAAiB,KAAA,GACnB,aAAa,CAAC;CAEhB,MAAM,eAAe,IAAI,gBAAgB;CACzC,KAAK,MAAM,QAAQ,MAAM,QAAQ,MAAM,GACrC,IAAI;EACF,MAAM,aAAa,aACjB;GACE,MAAM,KAAK;GACX,GAAI,KAAK,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM;GACxD,aAAa,KAAK;GAClB,aAAa,KAAK;GAClB,aAAa;IACX,cAAc,KAAK,YAAY;IAC/B,mBAAmB,KAAK,YAAY,oBAAoB;GAC1D;GACA,SAAS,OAAM,UAAS,SAAS,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC;EAC7E,GACA,EAAE,QAAQ,aAAa,OAAO,CAChC;CACF,SAAS,OAAO;EACd,QAAQ,KAAK,mCAAmC,KAAK,KAAK,IAAI,KAAK;CACrE;CAEF,aAAa,aAAa,MAAM;AAClC;;;;;;;;AASA,eAAsB,cACpB,KACA,UAAyB,CAAC,GACL;CACrB,MAAM,eAAe,QAAQ,gBAAgB,iBAAiB;CAC9D,IAAI,iBAAiB,KAAA,GACnB,aAAa,CAAC;CAEhB,MAAM,OAAO,IAAI,eAAe,UAAU;CAC1C,IAAI,SAAS,KAAA,GACX,MAAM,IAAI,MAAM,+DAA+D;CAGjF,MAAM,aAAa,MAAM,oBADT,cAAc,MAAM,EAAE,SAAS,QAAQ,WAAW,gBAAgB,CAC/B,GAAG,YAAY;CAClE,aAAa;EACX,WAAW;EACX,KAAK,MAAM;CACb;AACF;;AAGA,SAAgB,gBAAgB,SAAqC;CACnE,MAAM,QAAQ,CAAC,wBAAwB,QAAQ,QAAQ,MAAM,QAAQ,QAAQ,EAAE;CAC/E,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,MAAM,KAAK,QAAQ,WAAW;CAEhC,IAAI,OAAO,KAAK,QAAQ,SAAS,CAAC,CAAC,SAAS,GAC1C,MAAM,KAAK,KAAK,UAAU,QAAQ,WAAW,MAAM,CAAC,CAAC;CAEvD,IAAI,QAAQ,aACV,MAAM,KAAK,wBAAwB;CAErC,OAAO,OAAO,QAAQ,MAAM,KAAK,MAAM,CAAC;AAC1C;;AAGA,SAAS,SAAS,QAAkC;CAClD,MAAM,OAAO,OAAO,QAAQ,KAAI,SAAQ,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI;CAC5D,IAAI,OAAO,SACT,MAAM,IAAI,MAAM,IAAI;CAEtB,OAAO,OAAO,qBAAqB;AACrC"}
|
package/dist/worker/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { _ as channel, a as isChannelHostMessage, d as ChannelSpec, f as ChannelToken, g as ViewOf, h as CommandsOf, i as isChannelClientMessage, m as CommandMap, n as ChannelHostMessage, p as Command, r as ChannelPort, t as ChannelClientMessage, v as defineChannel, y as viewKeys } from "../ChannelProtocol-ByNoHujM.js";
|
|
2
|
+
import { A as portHandle, C as MessageEndpoint, O as isPortErrorMessage, S as APPLICATION_WORKER, T as PortHost, _ as serve, b as ProvidedChannel, g as ServedChannel, j as servePorts, k as isPortHandshake, v as serveChannels, x as provide, y as ChannelSource } from "../ui-U39HjNFA.js";
|
|
3
|
+
import { C as internalState, S as InternalState, _ as ReadableCell } from "../FunctionComponent-fYMdePtH.js";
|
|
4
|
+
import { $ as StorageAdapter, $r as ResourceOptions, B as PersistedOptions, Dr as requirePlainData, Er as findUnplainPath, G as IndexedDbStorage, H as persisted, J as OpfsFileHandle, Jr as throttled, K as IndexedDbStorageOptions, Pt as ConsoleEntry, Q as MemoryStorage, Qr as Resource, Sr as pickKeys, V as PersistedState, X as OpfsStorageOptions, Xr as Mutation, Y as OpfsStorage, Yr as MutateOptions, Z as OpfsWritable, Zr as mutate, at as storageReadValue, br as structurallyEqual, ct as UndoableOptions, di as ComputedOptions, dt as UndoStackOptions, ei as ResourceState, et as StorageOutcome, fi as ReadSource, ft as UndoTransaction, gi as derive, hi as Equality, ii as select, it as storageReadFailure, lt as undoable, mi as DeriveOptions, ni as resource, nt as classifyStorageError, pi as computed, q as OpfsDirectory, qr as debounced, ri as SelectOptions, rt as storageErrorMessage, ti as ResourceStatus, tt as StorageRead, ui as ComputedCell, ut as UndoStack, xr as pick } from "../index-BDM_gzzZ.js";
|
|
3
5
|
//#region src/worker/captureConsole.d.ts
|
|
4
6
|
/**
|
|
5
7
|
* Forwarding a worker's `console.*`.
|
package/dist/worker/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as structurallyEqual, B as channel, C as captureConsole, G as mutate, H as viewKeys, J as select, K as Resource, M as provide, N as findUnplainPath, P as requirePlainData, R as isChannelClientMessage, U as debounced, V as defineChannel, W as throttled, X as computed, Y as ComputedCell, Z as derive, a as undoable, b as portHandle, c as classifyStorageError, d as storageReadValue, et as InternalState, f as pick, g as APPLICATION_WORKER, h as serveChannels, i as OpfsStorage, j as ProvidedChannel, l as storageErrorMessage, m as serve, n as persisted, o as UndoStack, p as pickKeys, q as resource, r as IndexedDbStorage, s as MemoryStorage, t as PersistedState, tt as internalState, u as storageReadFailure, v as isPortErrorMessage, x as servePorts, y as isPortHandshake, z as isChannelHostMessage } from "../persisted-
|
|
1
|
+
import { $ as structurallyEqual, B as channel, C as captureConsole, G as mutate, H as viewKeys, J as select, K as Resource, M as provide, N as findUnplainPath, P as requirePlainData, R as isChannelClientMessage, U as debounced, V as defineChannel, W as throttled, X as computed, Y as ComputedCell, Z as derive, a as undoable, b as portHandle, c as classifyStorageError, d as storageReadValue, et as InternalState, f as pick, g as APPLICATION_WORKER, h as serveChannels, i as OpfsStorage, j as ProvidedChannel, l as storageErrorMessage, m as serve, n as persisted, o as UndoStack, p as pickKeys, q as resource, r as IndexedDbStorage, s as MemoryStorage, t as PersistedState, tt as internalState, u as storageReadFailure, v as isPortErrorMessage, x as servePorts, y as isPortHandshake, z as isChannelHostMessage } from "../persisted-pix1fS1D.js";
|
|
2
2
|
export { APPLICATION_WORKER, ComputedCell, IndexedDbStorage, InternalState, MemoryStorage, OpfsStorage, PersistedState, ProvidedChannel, Resource, UndoStack, captureConsole, channel, classifyStorageError, computed, debounced, defineChannel, derive, findUnplainPath, internalState, isChannelClientMessage, isChannelHostMessage, isPortErrorMessage, isPortHandshake, mutate, persisted, pick, pickKeys, portHandle, provide, requirePlainData, resource, select, serve, serveChannels, servePorts, storageErrorMessage, storageReadFailure, storageReadValue, structurallyEqual, throttled, undoable, viewKeys };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gesso-framework",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "SwiftUI and Compose, for the web: declarative components, stores and a frame runtime that keeps the whole interface off the main thread.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kevin Baker",
|
|
7
7
|
"homepage": "https://gesso-docs.vercel.app",
|
|
@@ -25,7 +25,11 @@
|
|
|
25
25
|
"web-worker",
|
|
26
26
|
"offscreencanvas",
|
|
27
27
|
"jsx",
|
|
28
|
-
"state-management"
|
|
28
|
+
"state-management",
|
|
29
|
+
"declarative-ui",
|
|
30
|
+
"swiftui",
|
|
31
|
+
"jetpack-compose",
|
|
32
|
+
"native-apps"
|
|
29
33
|
],
|
|
30
34
|
"type": "module",
|
|
31
35
|
"sideEffects": false,
|
|
@@ -45,6 +49,10 @@
|
|
|
45
49
|
"./jsx-dev-runtime": {
|
|
46
50
|
"types": "./dist/jsx/jsx-dev-runtime.d.ts",
|
|
47
51
|
"default": "./dist/jsx/jsx-dev-runtime.js"
|
|
52
|
+
},
|
|
53
|
+
"./agent": {
|
|
54
|
+
"types": "./dist/agent/index.d.ts",
|
|
55
|
+
"default": "./dist/agent/index.js"
|
|
48
56
|
}
|
|
49
57
|
},
|
|
50
58
|
"publishConfig": {
|
|
@@ -57,7 +65,7 @@
|
|
|
57
65
|
"LICENSE"
|
|
58
66
|
],
|
|
59
67
|
"dependencies": {
|
|
60
|
-
"gesso-core": "^0.
|
|
68
|
+
"gesso-core": "^0.5.0"
|
|
61
69
|
},
|
|
62
70
|
"peerDependencies": {
|
|
63
71
|
"rxjs": "^7.8.2"
|